]> code.delx.au - pulseaudio/blob - src/pulsecore/core-util.c
Merge remote branch 'origin/master-tx'
[pulseaudio] / src / pulsecore / core-util.c
1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2004 Joe Marcus Clarke
6 Copyright 2006-2007 Pierre Ossman <ossman@cendio.se> for Cendio AB
7
8 PulseAudio is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as
10 published by the Free Software Foundation; either version 2.1 of the
11 License, or (at your option) any later version.
12
13 PulseAudio is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public
19 License along with PulseAudio; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 USA.
22 ***/
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <stdarg.h>
29 #include <stdlib.h>
30 #include <signal.h>
31 #include <errno.h>
32 #include <string.h>
33 #include <stdio.h>
34 #include <fcntl.h>
35 #include <unistd.h>
36 #include <limits.h>
37 #include <time.h>
38 #include <ctype.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <sys/time.h>
42 #include <dirent.h>
43 #include <regex.h>
44 #include <langinfo.h>
45 #include <sys/utsname.h>
46 #include <sys/socket.h>
47
48 #ifdef HAVE_STRTOF_L
49 #include <locale.h>
50 #endif
51
52 #ifdef HAVE_SCHED_H
53 #include <sched.h>
54
55 #if defined(__linux__) && !defined(SCHED_RESET_ON_FORK)
56 #define SCHED_RESET_ON_FORK 0x40000000
57 #endif
58 #endif
59
60 #ifdef HAVE_SYS_RESOURCE_H
61 #include <sys/resource.h>
62 #endif
63
64 #ifdef HAVE_SYS_CAPABILITY_H
65 #include <sys/capability.h>
66 #endif
67
68 #ifdef HAVE_SYS_MMAN_H
69 #include <sys/mman.h>
70 #endif
71
72 #ifdef HAVE_PTHREAD
73 #include <pthread.h>
74 #endif
75
76 #ifdef HAVE_NETDB_H
77 #include <netdb.h>
78 #endif
79
80 #ifdef HAVE_WINDOWS_H
81 #include <windows.h>
82 #endif
83
84 #ifdef HAVE_PWD_H
85 #include <pwd.h>
86 #endif
87
88 #ifdef HAVE_GRP_H
89 #include <grp.h>
90 #endif
91
92 #ifdef HAVE_LIBSAMPLERATE
93 #include <samplerate.h>
94 #endif
95
96 #ifdef __APPLE__
97 #include <xlocale.h>
98 #endif
99
100 #ifdef HAVE_DBUS
101 #include "rtkit.h"
102 #endif
103
104 #ifdef __linux__
105 #include <sys/personality.h>
106 #endif
107
108 #include <pulse/xmalloc.h>
109 #include <pulse/util.h>
110 #include <pulse/utf8.h>
111
112 #include <pulsecore/core-error.h>
113 #include <pulsecore/winsock.h>
114 #include <pulsecore/log.h>
115 #include <pulsecore/macro.h>
116 #include <pulsecore/thread.h>
117 #include <pulsecore/strbuf.h>
118 #include <pulsecore/usergroup.h>
119 #include <pulsecore/strlist.h>
120
121 #include "core-util.h"
122
123 /* Not all platforms have this */
124 #ifndef MSG_NOSIGNAL
125 #define MSG_NOSIGNAL 0
126 #endif
127
128 static pa_strlist *recorded_env = NULL;
129
130 #ifdef OS_IS_WIN32
131
132 #define PULSE_ROOTENV "PULSE_ROOT"
133
134 int pa_set_root(HANDLE handle) {
135 char library_path[MAX_PATH + sizeof(PULSE_ROOTENV) + 1], *sep;
136
137 strcpy(library_path, PULSE_ROOTENV "=");
138
139 /* FIXME: Needs to set errno */
140
141 if (!GetModuleFileName(handle, library_path + sizeof(PULSE_ROOTENV), MAX_PATH))
142 return 0;
143
144 sep = strrchr(library_path, PA_PATH_SEP_CHAR);
145 if (sep)
146 *sep = '\0';
147
148 if (_putenv(library_path) < 0)
149 return 0;
150
151 return 1;
152 }
153
154 #endif
155
156 /** Make a file descriptor nonblock. Doesn't do any error checking */
157 void pa_make_fd_nonblock(int fd) {
158
159 #ifdef O_NONBLOCK
160 int v;
161 pa_assert(fd >= 0);
162
163 pa_assert_se((v = fcntl(fd, F_GETFL)) >= 0);
164
165 if (!(v & O_NONBLOCK))
166 pa_assert_se(fcntl(fd, F_SETFL, v|O_NONBLOCK) >= 0);
167
168 #elif defined(OS_IS_WIN32)
169 u_long arg = 1;
170 if (ioctlsocket(fd, FIONBIO, &arg) < 0) {
171 pa_assert_se(WSAGetLastError() == WSAENOTSOCK);
172 pa_log_warn("Only sockets can be made non-blocking!");
173 }
174 #else
175 pa_log_warn("Non-blocking I/O not supported.!");
176 #endif
177
178 }
179
180 /* Set the FD_CLOEXEC flag for a fd */
181 void pa_make_fd_cloexec(int fd) {
182
183 #ifdef FD_CLOEXEC
184 int v;
185 pa_assert(fd >= 0);
186
187 pa_assert_se((v = fcntl(fd, F_GETFD, 0)) >= 0);
188
189 if (!(v & FD_CLOEXEC))
190 pa_assert_se(fcntl(fd, F_SETFD, v|FD_CLOEXEC) >= 0);
191 #endif
192
193 }
194
195 /** Creates a directory securely */
196 int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid) {
197 struct stat st;
198 int r, saved_errno;
199
200 pa_assert(dir);
201
202 #ifdef OS_IS_WIN32
203 r = mkdir(dir);
204 #else
205 {
206 mode_t u;
207 u = umask((~m) & 0777);
208 r = mkdir(dir, m);
209 umask(u);
210 }
211 #endif
212
213 if (r < 0 && errno != EEXIST)
214 return -1;
215
216 #ifdef HAVE_CHOWN
217 if (uid == (uid_t)-1)
218 uid = getuid();
219 if (gid == (gid_t)-1)
220 gid = getgid();
221 (void) chown(dir, uid, gid);
222 #endif
223
224 #ifdef HAVE_CHMOD
225 chmod(dir, m);
226 #endif
227
228 #ifdef HAVE_LSTAT
229 if (lstat(dir, &st) < 0)
230 #else
231 if (stat(dir, &st) < 0)
232 #endif
233 goto fail;
234
235 #ifndef OS_IS_WIN32
236 if (!S_ISDIR(st.st_mode) ||
237 (st.st_uid != uid) ||
238 (st.st_gid != gid) ||
239 ((st.st_mode & 0777) != m)) {
240 errno = EACCES;
241 goto fail;
242 }
243 #else
244 pa_log_warn("Secure directory creation not supported on Win32.");
245 #endif
246
247 return 0;
248
249 fail:
250 saved_errno = errno;
251 rmdir(dir);
252 errno = saved_errno;
253
254 return -1;
255 }
256
257 /* Return a newly allocated sting containing the parent directory of the specified file */
258 char *pa_parent_dir(const char *fn) {
259 char *slash, *dir = pa_xstrdup(fn);
260
261 if ((slash = (char*) pa_path_get_filename(dir)) == dir) {
262 pa_xfree(dir);
263 errno = ENOENT;
264 return NULL;
265 }
266
267 *(slash-1) = 0;
268 return dir;
269 }
270
271 /* Creates a the parent directory of the specified path securely */
272 int pa_make_secure_parent_dir(const char *fn, mode_t m, uid_t uid, gid_t gid) {
273 int ret = -1;
274 char *dir;
275
276 if (!(dir = pa_parent_dir(fn)))
277 goto finish;
278
279 if (pa_make_secure_dir(dir, m, uid, gid) < 0)
280 goto finish;
281
282 ret = 0;
283
284 finish:
285 pa_xfree(dir);
286 return ret;
287 }
288
289 /** Platform independent read function. Necessary since not all
290 * systems treat all file descriptors equal. If type is
291 * non-NULL it is used to cache the type of the fd. This is
292 * useful for making sure that only a single syscall is executed per
293 * function call. The variable pointed to should be initialized to 0
294 * by the caller. */
295 ssize_t pa_read(int fd, void *buf, size_t count, int *type) {
296
297 #ifdef OS_IS_WIN32
298
299 if (!type || *type == 0) {
300 ssize_t r;
301
302 if ((r = recv(fd, buf, count, 0)) >= 0)
303 return r;
304
305 if (WSAGetLastError() != WSAENOTSOCK) {
306 errno = WSAGetLastError();
307 return r;
308 }
309
310 if (type)
311 *type = 1;
312 }
313
314 #endif
315
316 for (;;) {
317 ssize_t r;
318
319 if ((r = read(fd, buf, count)) < 0)
320 if (errno == EINTR)
321 continue;
322
323 return r;
324 }
325 }
326
327 /** Similar to pa_read(), but handles writes */
328 ssize_t pa_write(int fd, const void *buf, size_t count, int *type) {
329
330 if (!type || *type == 0) {
331 ssize_t r;
332
333 for (;;) {
334 if ((r = send(fd, buf, count, MSG_NOSIGNAL)) < 0) {
335
336 if (errno == EINTR)
337 continue;
338
339 break;
340 }
341
342 return r;
343 }
344
345 #ifdef OS_IS_WIN32
346 if (WSAGetLastError() != WSAENOTSOCK) {
347 errno = WSAGetLastError();
348 return r;
349 }
350 #else
351 if (errno != ENOTSOCK)
352 return r;
353 #endif
354
355 if (type)
356 *type = 1;
357 }
358
359 for (;;) {
360 ssize_t r;
361
362 if ((r = write(fd, buf, count)) < 0)
363 if (errno == EINTR)
364 continue;
365
366 return r;
367 }
368 }
369
370 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
371 * unless EOF is reached or an error occurred */
372 ssize_t pa_loop_read(int fd, void*data, size_t size, int *type) {
373 ssize_t ret = 0;
374 int _type;
375
376 pa_assert(fd >= 0);
377 pa_assert(data);
378 pa_assert(size);
379
380 if (!type) {
381 _type = 0;
382 type = &_type;
383 }
384
385 while (size > 0) {
386 ssize_t r;
387
388 if ((r = pa_read(fd, data, size, type)) < 0)
389 return r;
390
391 if (r == 0)
392 break;
393
394 ret += r;
395 data = (uint8_t*) data + r;
396 size -= (size_t) r;
397 }
398
399 return ret;
400 }
401
402 /** Similar to pa_loop_read(), but wraps write() */
403 ssize_t pa_loop_write(int fd, const void*data, size_t size, int *type) {
404 ssize_t ret = 0;
405 int _type;
406
407 pa_assert(fd >= 0);
408 pa_assert(data);
409 pa_assert(size);
410
411 if (!type) {
412 _type = 0;
413 type = &_type;
414 }
415
416 while (size > 0) {
417 ssize_t r;
418
419 if ((r = pa_write(fd, data, size, type)) < 0)
420 return r;
421
422 if (r == 0)
423 break;
424
425 ret += r;
426 data = (const uint8_t*) data + r;
427 size -= (size_t) r;
428 }
429
430 return ret;
431 }
432
433 /** Platform independent read function. Necessary since not all
434 * systems treat all file descriptors equal. */
435 int pa_close(int fd) {
436
437 #ifdef OS_IS_WIN32
438 int ret;
439
440 if ((ret = closesocket(fd)) == 0)
441 return 0;
442
443 if (WSAGetLastError() != WSAENOTSOCK) {
444 errno = WSAGetLastError();
445 return ret;
446 }
447 #endif
448
449 for (;;) {
450 int r;
451
452 if ((r = close(fd)) < 0)
453 if (errno == EINTR)
454 continue;
455
456 return r;
457 }
458 }
459
460 /* Print a warning messages in case that the given signal is not
461 * blocked or trapped */
462 void pa_check_signal_is_blocked(int sig) {
463 #ifdef HAVE_SIGACTION
464 struct sigaction sa;
465 sigset_t set;
466
467 /* If POSIX threads are supported use thread-aware
468 * pthread_sigmask() function, to check if the signal is
469 * blocked. Otherwise fall back to sigprocmask() */
470
471 #ifdef HAVE_PTHREAD
472 if (pthread_sigmask(SIG_SETMASK, NULL, &set) < 0) {
473 #endif
474 if (sigprocmask(SIG_SETMASK, NULL, &set) < 0) {
475 pa_log("sigprocmask(): %s", pa_cstrerror(errno));
476 return;
477 }
478 #ifdef HAVE_PTHREAD
479 }
480 #endif
481
482 if (sigismember(&set, sig))
483 return;
484
485 /* Check whether the signal is trapped */
486
487 if (sigaction(sig, NULL, &sa) < 0) {
488 pa_log("sigaction(): %s", pa_cstrerror(errno));
489 return;
490 }
491
492 if (sa.sa_handler != SIG_DFL)
493 return;
494
495 pa_log_warn("%s is not trapped. This might cause malfunction!", pa_sig2str(sig));
496 #else /* HAVE_SIGACTION */
497 pa_log_warn("%s might not be trapped. This might cause malfunction!", pa_sig2str(sig));
498 #endif
499 }
500
501 /* The following function is based on an example from the GNU libc
502 * documentation. This function is similar to GNU's asprintf(). */
503 char *pa_sprintf_malloc(const char *format, ...) {
504 size_t size = 100;
505 char *c = NULL;
506
507 pa_assert(format);
508
509 for(;;) {
510 int r;
511 va_list ap;
512
513 c = pa_xrealloc(c, size);
514
515 va_start(ap, format);
516 r = vsnprintf(c, size, format, ap);
517 va_end(ap);
518
519 c[size-1] = 0;
520
521 if (r > -1 && (size_t) r < size)
522 return c;
523
524 if (r > -1) /* glibc 2.1 */
525 size = (size_t) r+1;
526 else /* glibc 2.0 */
527 size *= 2;
528 }
529 }
530
531 /* Same as the previous function, but use a va_list instead of an
532 * ellipsis */
533 char *pa_vsprintf_malloc(const char *format, va_list ap) {
534 size_t size = 100;
535 char *c = NULL;
536
537 pa_assert(format);
538
539 for(;;) {
540 int r;
541 va_list aq;
542
543 c = pa_xrealloc(c, size);
544
545 va_copy(aq, ap);
546 r = vsnprintf(c, size, format, aq);
547 va_end(aq);
548
549 c[size-1] = 0;
550
551 if (r > -1 && (size_t) r < size)
552 return c;
553
554 if (r > -1) /* glibc 2.1 */
555 size = (size_t) r+1;
556 else /* glibc 2.0 */
557 size *= 2;
558 }
559 }
560
561 /* Similar to OpenBSD's strlcpy() function */
562 char *pa_strlcpy(char *b, const char *s, size_t l) {
563 size_t k;
564
565 pa_assert(b);
566 pa_assert(s);
567 pa_assert(l > 0);
568
569 k = strlen(s);
570
571 if (k > l-1)
572 k = l-1;
573
574 memcpy(b, s, k);
575 b[k] = 0;
576
577 return b;
578 }
579
580 static int set_scheduler(int rtprio) {
581 struct sched_param sp;
582 int r;
583 #ifdef HAVE_DBUS
584 DBusError error;
585 DBusConnection *bus;
586
587 dbus_error_init(&error);
588 #endif
589
590 pa_zero(sp);
591 sp.sched_priority = rtprio;
592
593 #ifdef SCHED_RESET_ON_FORK
594 if (pthread_setschedparam(pthread_self(), SCHED_RR|SCHED_RESET_ON_FORK, &sp) == 0) {
595 pa_log_debug("SCHED_RR|SCHED_RESET_ON_FORK worked.");
596 return 0;
597 }
598 #endif
599
600 if (pthread_setschedparam(pthread_self(), SCHED_RR, &sp) == 0) {
601 pa_log_debug("SCHED_RR worked.");
602 return 0;
603 }
604
605 #ifdef HAVE_DBUS
606 /* Try to talk to RealtimeKit */
607
608 if (!(bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
609 pa_log("Failed to connect to system bus: %s\n", error.message);
610 dbus_error_free(&error);
611 errno = -EIO;
612 return -1;
613 }
614
615 /* We need to disable exit on disconnect because otherwise
616 * dbus_shutdown will kill us. See
617 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
618 dbus_connection_set_exit_on_disconnect(bus, FALSE);
619
620 r = rtkit_make_realtime(bus, 0, rtprio);
621 dbus_connection_unref(bus);
622
623 if (r >= 0) {
624 pa_log_debug("RealtimeKit worked.");
625 return 0;
626 }
627
628 errno = -r;
629 #else
630 errno = r;
631 #endif
632
633 return -1;
634 }
635
636 /* Make the current thread a realtime thread, and acquire the highest
637 * rtprio we can get that is less or equal the specified parameter. If
638 * the thread is already realtime, don't do anything. */
639 int pa_make_realtime(int rtprio) {
640
641 #ifdef _POSIX_PRIORITY_SCHEDULING
642 int p;
643
644 if (set_scheduler(rtprio) >= 0) {
645 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i.", rtprio);
646 return 0;
647 }
648
649 for (p = rtprio-1; p >= 1; p--)
650 if (set_scheduler(p)) {
651 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i.", p, rtprio);
652 return 0;
653 }
654
655 pa_log_info("Failed to acquire real-time scheduling: %s", pa_cstrerror(errno));
656 return -1;
657 #else
658
659 errno = ENOTSUP;
660 return -1;
661 #endif
662 }
663
664 static int set_nice(int nice_level) {
665 #ifdef HAVE_DBUS
666 DBusError error;
667 DBusConnection *bus;
668 int r;
669
670 dbus_error_init(&error);
671 #endif
672
673 if (setpriority(PRIO_PROCESS, 0, nice_level) >= 0) {
674 pa_log_debug("setpriority() worked.");
675 return 0;
676 }
677
678 #ifdef HAVE_DBUS
679 /* Try to talk to RealtimeKit */
680
681 if (!(bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
682 pa_log("Failed to connect to system bus: %s\n", error.message);
683 dbus_error_free(&error);
684 errno = -EIO;
685 return -1;
686 }
687
688 /* We need to disable exit on disconnect because otherwise
689 * dbus_shutdown will kill us. See
690 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
691 dbus_connection_set_exit_on_disconnect(bus, FALSE);
692
693 r = rtkit_make_high_priority(bus, 0, nice_level);
694 dbus_connection_unref(bus);
695
696 if (r >= 0) {
697 pa_log_debug("RealtimeKit worked.");
698 return 0;
699 }
700
701 errno = -r;
702 #endif
703
704 return -1;
705 }
706
707 /* Raise the priority of the current process as much as possible that
708 * is <= the specified nice level..*/
709 int pa_raise_priority(int nice_level) {
710
711 #ifdef HAVE_SYS_RESOURCE_H
712 int n;
713
714 if (set_nice(nice_level) >= 0) {
715 pa_log_info("Successfully gained nice level %i.", nice_level);
716 return 0;
717 }
718
719 for (n = nice_level+1; n < 0; n++)
720 if (set_nice(n) > 0) {
721 pa_log_info("Successfully acquired nice level %i, which is lower than the requested %i.", n, nice_level);
722 return 0;
723 }
724
725 pa_log_info("Failed to acquire high-priority scheduling: %s", pa_cstrerror(errno));
726 return -1;
727 #endif
728
729 #ifdef OS_IS_WIN32
730 if (nice_level < 0) {
731 if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS)) {
732 pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError());
733 errno = EPERM;
734 return -1;
735 }
736
737 pa_log_info("Successfully gained high priority class.");
738 }
739 #endif
740
741 return 0;
742 }
743
744 /* Reset the priority to normal, inverting the changes made by
745 * pa_raise_priority() and pa_make_realtime()*/
746 void pa_reset_priority(void) {
747 #ifdef HAVE_SYS_RESOURCE_H
748 struct sched_param sp;
749
750 setpriority(PRIO_PROCESS, 0, 0);
751
752 pa_zero(sp);
753 pthread_setschedparam(pthread_self(), SCHED_OTHER, &sp);
754 #endif
755
756 #ifdef OS_IS_WIN32
757 SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
758 #endif
759 }
760
761 int pa_match(const char *expr, const char *v) {
762 int k;
763 regex_t re;
764 int r;
765
766 if (regcomp(&re, expr, REG_NOSUB|REG_EXTENDED) != 0) {
767 errno = EINVAL;
768 return -1;
769 }
770
771 if ((k = regexec(&re, v, 0, NULL, 0)) == 0)
772 r = 1;
773 else if (k == REG_NOMATCH)
774 r = 0;
775 else
776 r = -1;
777
778 regfree(&re);
779
780 if (r < 0)
781 errno = EINVAL;
782
783 return r;
784 }
785
786 /* Try to parse a boolean string value.*/
787 int pa_parse_boolean(const char *v) {
788 const char *expr;
789 pa_assert(v);
790
791 /* First we check language independant */
792 if (!strcmp(v, "1") || v[0] == 'y' || v[0] == 'Y' || v[0] == 't' || v[0] == 'T' || !strcasecmp(v, "on"))
793 return 1;
794 else if (!strcmp(v, "0") || v[0] == 'n' || v[0] == 'N' || v[0] == 'f' || v[0] == 'F' || !strcasecmp(v, "off"))
795 return 0;
796
797 /* And then we check language dependant */
798 if ((expr = nl_langinfo(YESEXPR)))
799 if (expr[0])
800 if (pa_match(expr, v) > 0)
801 return 1;
802
803 if ((expr = nl_langinfo(NOEXPR)))
804 if (expr[0])
805 if (pa_match(expr, v) > 0)
806 return 0;
807
808 errno = EINVAL;
809 return -1;
810 }
811
812 /* Split the specified string wherever one of the strings in delimiter
813 * occurs. Each time it is called returns a newly allocated string
814 * with pa_xmalloc(). The variable state points to, should be
815 * initiallized to NULL before the first call. */
816 char *pa_split(const char *c, const char *delimiter, const char**state) {
817 const char *current = *state ? *state : c;
818 size_t l;
819
820 if (!*current)
821 return NULL;
822
823 l = strcspn(current, delimiter);
824 *state = current+l;
825
826 if (**state)
827 (*state)++;
828
829 return pa_xstrndup(current, l);
830 }
831
832 /* What is interpreted as whitespace? */
833 #define WHITESPACE " \t\n"
834
835 /* Split a string into words. Otherwise similar to pa_split(). */
836 char *pa_split_spaces(const char *c, const char **state) {
837 const char *current = *state ? *state : c;
838 size_t l;
839
840 if (!*current || *c == 0)
841 return NULL;
842
843 current += strspn(current, WHITESPACE);
844 l = strcspn(current, WHITESPACE);
845
846 *state = current+l;
847
848 return pa_xstrndup(current, l);
849 }
850
851 PA_STATIC_TLS_DECLARE(signame, pa_xfree);
852
853 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
854 const char *pa_sig2str(int sig) {
855 char *t;
856
857 if (sig <= 0)
858 goto fail;
859
860 #ifdef NSIG
861 if (sig >= NSIG)
862 goto fail;
863 #endif
864
865 #ifdef HAVE_SIG2STR
866 {
867 char buf[SIG2STR_MAX];
868
869 if (sig2str(sig, buf) == 0) {
870 pa_xfree(PA_STATIC_TLS_GET(signame));
871 t = pa_sprintf_malloc("SIG%s", buf);
872 PA_STATIC_TLS_SET(signame, t);
873 return t;
874 }
875 }
876 #else
877
878 switch(sig) {
879 #ifdef SIGHUP
880 case SIGHUP: return "SIGHUP";
881 #endif
882 case SIGINT: return "SIGINT";
883 #ifdef SIGQUIT
884 case SIGQUIT: return "SIGQUIT";
885 #endif
886 case SIGILL: return "SIGULL";
887 #ifdef SIGTRAP
888 case SIGTRAP: return "SIGTRAP";
889 #endif
890 case SIGABRT: return "SIGABRT";
891 #ifdef SIGBUS
892 case SIGBUS: return "SIGBUS";
893 #endif
894 case SIGFPE: return "SIGFPE";
895 #ifdef SIGKILL
896 case SIGKILL: return "SIGKILL";
897 #endif
898 #ifdef SIGUSR1
899 case SIGUSR1: return "SIGUSR1";
900 #endif
901 case SIGSEGV: return "SIGSEGV";
902 #ifdef SIGUSR2
903 case SIGUSR2: return "SIGUSR2";
904 #endif
905 #ifdef SIGPIPE
906 case SIGPIPE: return "SIGPIPE";
907 #endif
908 #ifdef SIGALRM
909 case SIGALRM: return "SIGALRM";
910 #endif
911 case SIGTERM: return "SIGTERM";
912 #ifdef SIGSTKFLT
913 case SIGSTKFLT: return "SIGSTKFLT";
914 #endif
915 #ifdef SIGCHLD
916 case SIGCHLD: return "SIGCHLD";
917 #endif
918 #ifdef SIGCONT
919 case SIGCONT: return "SIGCONT";
920 #endif
921 #ifdef SIGSTOP
922 case SIGSTOP: return "SIGSTOP";
923 #endif
924 #ifdef SIGTSTP
925 case SIGTSTP: return "SIGTSTP";
926 #endif
927 #ifdef SIGTTIN
928 case SIGTTIN: return "SIGTTIN";
929 #endif
930 #ifdef SIGTTOU
931 case SIGTTOU: return "SIGTTOU";
932 #endif
933 #ifdef SIGURG
934 case SIGURG: return "SIGURG";
935 #endif
936 #ifdef SIGXCPU
937 case SIGXCPU: return "SIGXCPU";
938 #endif
939 #ifdef SIGXFSZ
940 case SIGXFSZ: return "SIGXFSZ";
941 #endif
942 #ifdef SIGVTALRM
943 case SIGVTALRM: return "SIGVTALRM";
944 #endif
945 #ifdef SIGPROF
946 case SIGPROF: return "SIGPROF";
947 #endif
948 #ifdef SIGWINCH
949 case SIGWINCH: return "SIGWINCH";
950 #endif
951 #ifdef SIGIO
952 case SIGIO: return "SIGIO";
953 #endif
954 #ifdef SIGPWR
955 case SIGPWR: return "SIGPWR";
956 #endif
957 #ifdef SIGSYS
958 case SIGSYS: return "SIGSYS";
959 #endif
960 }
961
962 #ifdef SIGRTMIN
963 if (sig >= SIGRTMIN && sig <= SIGRTMAX) {
964 pa_xfree(PA_STATIC_TLS_GET(signame));
965 t = pa_sprintf_malloc("SIGRTMIN+%i", sig - SIGRTMIN);
966 PA_STATIC_TLS_SET(signame, t);
967 return t;
968 }
969 #endif
970
971 #endif
972
973 fail:
974
975 pa_xfree(PA_STATIC_TLS_GET(signame));
976 t = pa_sprintf_malloc("SIG%i", sig);
977 PA_STATIC_TLS_SET(signame, t);
978 return t;
979 }
980
981 #ifdef HAVE_GRP_H
982
983 /* Check whether the specified GID and the group name match */
984 static int is_group(gid_t gid, const char *name) {
985 struct group *group = NULL;
986 int r = -1;
987
988 errno = 0;
989 if (!(group = pa_getgrgid_malloc(gid)))
990 {
991 if (!errno)
992 errno = ENOENT;
993
994 pa_log("pa_getgrgid_malloc(%u): %s", gid, pa_cstrerror(errno));
995
996 goto finish;
997 }
998
999 r = strcmp(name, group->gr_name) == 0;
1000
1001 finish:
1002 pa_getgrgid_free(group);
1003
1004 return r;
1005 }
1006
1007 /* Check the current user is member of the specified group */
1008 int pa_own_uid_in_group(const char *name, gid_t *gid) {
1009 GETGROUPS_T *gids, tgid;
1010 long n = sysconf(_SC_NGROUPS_MAX);
1011 int r = -1, i, k;
1012
1013 pa_assert(n > 0);
1014
1015 gids = pa_xmalloc(sizeof(GETGROUPS_T) * (size_t) n);
1016
1017 if ((n = getgroups((int) n, gids)) < 0) {
1018 pa_log("getgroups(): %s", pa_cstrerror(errno));
1019 goto finish;
1020 }
1021
1022 for (i = 0; i < n; i++) {
1023
1024 if ((k = is_group(gids[i], name)) < 0)
1025 goto finish;
1026 else if (k > 0) {
1027 *gid = gids[i];
1028 r = 1;
1029 goto finish;
1030 }
1031 }
1032
1033 if ((k = is_group(tgid = getgid(), name)) < 0)
1034 goto finish;
1035 else if (k > 0) {
1036 *gid = tgid;
1037 r = 1;
1038 goto finish;
1039 }
1040
1041 r = 0;
1042
1043 finish:
1044
1045 pa_xfree(gids);
1046 return r;
1047 }
1048
1049 /* Check whether the specifc user id is a member of the specified group */
1050 int pa_uid_in_group(uid_t uid, const char *name) {
1051 struct group *group = NULL;
1052 char **i;
1053 int r = -1;
1054
1055 errno = 0;
1056 if (!(group = pa_getgrnam_malloc(name)))
1057 {
1058 if (!errno)
1059 errno = ENOENT;
1060 goto finish;
1061 }
1062
1063 r = 0;
1064 for (i = group->gr_mem; *i; i++) {
1065 struct passwd *pw = NULL;
1066
1067 errno = 0;
1068 if (!(pw = pa_getpwnam_malloc(*i)))
1069 continue;
1070
1071 if (pw->pw_uid == uid)
1072 r = 1;
1073
1074 pa_getpwnam_free(pw);
1075
1076 if (r == 1)
1077 break;
1078 }
1079
1080 finish:
1081 pa_getgrnam_free(group);
1082
1083 return r;
1084 }
1085
1086 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
1087 gid_t pa_get_gid_of_group(const char *name) {
1088 gid_t ret = (gid_t) -1;
1089 struct group *gr = NULL;
1090
1091 errno = 0;
1092 if (!(gr = pa_getgrnam_malloc(name)))
1093 {
1094 if (!errno)
1095 errno = ENOENT;
1096 goto finish;
1097 }
1098
1099 ret = gr->gr_gid;
1100
1101 finish:
1102 pa_getgrnam_free(gr);
1103 return ret;
1104 }
1105
1106 int pa_check_in_group(gid_t g) {
1107 gid_t gids[NGROUPS_MAX];
1108 int r;
1109
1110 if ((r = getgroups(NGROUPS_MAX, gids)) < 0)
1111 return -1;
1112
1113 for (; r > 0; r--)
1114 if (gids[r-1] == g)
1115 return 1;
1116
1117 return 0;
1118 }
1119
1120 #else /* HAVE_GRP_H */
1121
1122 int pa_own_uid_in_group(const char *name, gid_t *gid) {
1123 errno = ENOSUP;
1124 return -1;
1125
1126 }
1127
1128 int pa_uid_in_group(uid_t uid, const char *name) {
1129 errno = ENOSUP;
1130 return -1;
1131 }
1132
1133 gid_t pa_get_gid_of_group(const char *name) {
1134 errno = ENOSUP;
1135 return (gid_t) -1;
1136 }
1137
1138 int pa_check_in_group(gid_t g) {
1139 errno = ENOSUP;
1140 return -1;
1141 }
1142
1143 #endif
1144
1145 /* Lock or unlock a file entirely.
1146 (advisory on UNIX, mandatory on Windows) */
1147 int pa_lock_fd(int fd, int b) {
1148 #ifdef F_SETLKW
1149 struct flock f_lock;
1150
1151 /* Try a R/W lock first */
1152
1153 f_lock.l_type = (short) (b ? F_WRLCK : F_UNLCK);
1154 f_lock.l_whence = SEEK_SET;
1155 f_lock.l_start = 0;
1156 f_lock.l_len = 0;
1157
1158 if (fcntl(fd, F_SETLKW, &f_lock) >= 0)
1159 return 0;
1160
1161 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1162 if (b && errno == EBADF) {
1163 f_lock.l_type = F_RDLCK;
1164 if (fcntl(fd, F_SETLKW, &f_lock) >= 0)
1165 return 0;
1166 }
1167
1168 pa_log("%slock: %s", !b? "un" : "", pa_cstrerror(errno));
1169 #endif
1170
1171 #ifdef OS_IS_WIN32
1172 HANDLE h = (HANDLE)_get_osfhandle(fd);
1173
1174 if (b && LockFile(h, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1175 return 0;
1176 if (!b && UnlockFile(h, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1177 return 0;
1178
1179 pa_log("%slock failed: 0x%08X", !b ? "un" : "", GetLastError());
1180
1181 /* FIXME: Needs to set errno! */
1182 #endif
1183
1184 return -1;
1185 }
1186
1187 /* Remove trailing newlines from a string */
1188 char* pa_strip_nl(char *s) {
1189 pa_assert(s);
1190
1191 s[strcspn(s, "\r\n")] = 0;
1192 return s;
1193 }
1194
1195 /* Create a temporary lock file and lock it. */
1196 int pa_lock_lockfile(const char *fn) {
1197 int fd;
1198 pa_assert(fn);
1199
1200 for (;;) {
1201 struct stat st;
1202
1203 if ((fd = open(fn, O_CREAT|O_RDWR
1204 #ifdef O_NOCTTY
1205 |O_NOCTTY
1206 #endif
1207 #ifdef O_NOFOLLOW
1208 |O_NOFOLLOW
1209 #endif
1210 , S_IRUSR|S_IWUSR)) < 0) {
1211 pa_log_warn("Failed to create lock file '%s': %s", fn, pa_cstrerror(errno));
1212 goto fail;
1213 }
1214
1215 if (pa_lock_fd(fd, 1) < 0) {
1216 pa_log_warn("Failed to lock file '%s'.", fn);
1217 goto fail;
1218 }
1219
1220 if (fstat(fd, &st) < 0) {
1221 pa_log_warn("Failed to fstat() file '%s': %s", fn, pa_cstrerror(errno));
1222 goto fail;
1223 }
1224
1225 /* Check whether the file has been removed meanwhile. When yes,
1226 * restart this loop, otherwise, we're done */
1227 if (st.st_nlink >= 1)
1228 break;
1229
1230 if (pa_lock_fd(fd, 0) < 0) {
1231 pa_log_warn("Failed to unlock file '%s'.", fn);
1232 goto fail;
1233 }
1234
1235 if (pa_close(fd) < 0) {
1236 pa_log_warn("Failed to close file '%s': %s", fn, pa_cstrerror(errno));
1237 fd = -1;
1238 goto fail;
1239 }
1240 }
1241
1242 return fd;
1243
1244 fail:
1245
1246 if (fd >= 0) {
1247 int saved_errno = errno;
1248 pa_close(fd);
1249 errno = saved_errno;
1250 }
1251
1252 return -1;
1253 }
1254
1255 /* Unlock a temporary lcok file */
1256 int pa_unlock_lockfile(const char *fn, int fd) {
1257 int r = 0;
1258 pa_assert(fd >= 0);
1259
1260 if (fn) {
1261 if (unlink(fn) < 0) {
1262 pa_log_warn("Unable to remove lock file '%s': %s", fn, pa_cstrerror(errno));
1263 r = -1;
1264 }
1265 }
1266
1267 if (pa_lock_fd(fd, 0) < 0) {
1268 pa_log_warn("Failed to unlock file '%s'.", fn);
1269 r = -1;
1270 }
1271
1272 if (pa_close(fd) < 0) {
1273 pa_log_warn("Failed to close '%s': %s", fn, pa_cstrerror(errno));
1274 r = -1;
1275 }
1276
1277 return r;
1278 }
1279
1280 static char *get_pulse_home(void) {
1281 char *h;
1282 struct stat st;
1283 char *ret = NULL;
1284
1285 if (!(h = pa_get_home_dir_malloc())) {
1286 pa_log_error("Failed to get home directory.");
1287 return NULL;
1288 }
1289
1290 if (stat(h, &st) < 0) {
1291 pa_log_error("Failed to stat home directory %s: %s", h, pa_cstrerror(errno));
1292 goto finish;
1293 }
1294
1295 if (st.st_uid != getuid()) {
1296 pa_log_error("Home directory %s not ours.", h);
1297 errno = EACCES;
1298 goto finish;
1299 }
1300
1301 ret = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse", h);
1302
1303 finish:
1304 pa_xfree(h);
1305
1306 return ret;
1307 }
1308
1309 char *pa_get_state_dir(void) {
1310 char *d;
1311
1312 /* The state directory shall contain dynamic data that should be
1313 * kept across reboots, and is private to this user */
1314
1315 if (!(d = pa_xstrdup(getenv("PULSE_STATE_PATH"))))
1316 if (!(d = get_pulse_home()))
1317 return NULL;
1318
1319 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1320 * dir then this will break. */
1321
1322 if (pa_make_secure_dir(d, 0700U, (uid_t) -1, (gid_t) -1) < 0) {
1323 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1324 pa_xfree(d);
1325 return NULL;
1326 }
1327
1328 return d;
1329 }
1330
1331 char *pa_get_home_dir_malloc(void) {
1332 char *homedir;
1333 size_t allocated = 128;
1334
1335 for (;;) {
1336 homedir = pa_xmalloc(allocated);
1337
1338 if (!pa_get_home_dir(homedir, allocated)) {
1339 pa_xfree(homedir);
1340 return NULL;
1341 }
1342
1343 if (strlen(homedir) < allocated - 1)
1344 break;
1345
1346 pa_xfree(homedir);
1347 allocated *= 2;
1348 }
1349
1350 return homedir;
1351 }
1352
1353 char *pa_get_binary_name_malloc(void) {
1354 char *t;
1355 size_t allocated = 128;
1356
1357 for (;;) {
1358 t = pa_xmalloc(allocated);
1359
1360 if (!pa_get_binary_name(t, allocated)) {
1361 pa_xfree(t);
1362 return NULL;
1363 }
1364
1365 if (strlen(t) < allocated - 1)
1366 break;
1367
1368 pa_xfree(t);
1369 allocated *= 2;
1370 }
1371
1372 return t;
1373 }
1374
1375 static char* make_random_dir(mode_t m) {
1376 static const char table[] =
1377 "abcdefghijklmnopqrstuvwxyz"
1378 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1379 "0123456789";
1380
1381 const char *tmpdir;
1382 char *fn;
1383 size_t pathlen;
1384
1385 if (!(tmpdir = getenv("TMPDIR")))
1386 if (!(tmpdir = getenv("TMP")))
1387 if (!(tmpdir = getenv("TEMP")))
1388 tmpdir = getenv("TEMPDIR");
1389
1390 if (!tmpdir || !pa_is_path_absolute(tmpdir))
1391 tmpdir = "/tmp";
1392
1393 fn = pa_sprintf_malloc("%s/pulse-XXXXXXXXXXXX", tmpdir);
1394 pathlen = strlen(fn);
1395
1396 for (;;) {
1397 size_t i;
1398 int r;
1399 mode_t u;
1400 int saved_errno;
1401
1402 for (i = pathlen - 12; i < pathlen; i++)
1403 fn[i] = table[rand() % (sizeof(table)-1)];
1404
1405 u = umask((~m) & 0777);
1406 r = mkdir(fn, m);
1407
1408 saved_errno = errno;
1409 umask(u);
1410 errno = saved_errno;
1411
1412 if (r >= 0)
1413 return fn;
1414
1415 if (errno != EEXIST) {
1416 pa_log_error("Failed to create random directory %s: %s", fn, pa_cstrerror(errno));
1417 pa_xfree(fn);
1418 return NULL;
1419 }
1420 }
1421 }
1422
1423 static int make_random_dir_and_link(mode_t m, const char *k) {
1424 char *p;
1425
1426 if (!(p = make_random_dir(m)))
1427 return -1;
1428
1429 if (symlink(p, k) < 0) {
1430 int saved_errno = errno;
1431
1432 if (errno != EEXIST)
1433 pa_log_error("Failed to symlink %s to %s: %s", k, p, pa_cstrerror(errno));
1434
1435 rmdir(p);
1436 pa_xfree(p);
1437
1438 errno = saved_errno;
1439 return -1;
1440 }
1441
1442 pa_xfree(p);
1443 return 0;
1444 }
1445
1446 char *pa_get_runtime_dir(void) {
1447 char *d, *k = NULL, *p = NULL, *t = NULL, *mid;
1448 struct stat st;
1449 mode_t m;
1450
1451 /* The runtime directory shall contain dynamic data that needs NOT
1452 * to be kept accross reboots and is usuallly private to the user,
1453 * except in system mode, where it might be accessible by other
1454 * users, too. Since we need POSIX locking and UNIX sockets in
1455 * this directory, we link it to a random subdir in /tmp, if it
1456 * was not explicitly configured. */
1457
1458 m = pa_in_system_mode() ? 0755U : 0700U;
1459
1460 if ((d = getenv("PULSE_RUNTIME_PATH"))) {
1461
1462 if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0) {
1463 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1464 goto fail;
1465 }
1466
1467 return pa_xstrdup(d);
1468 }
1469
1470 if (!(d = get_pulse_home()))
1471 goto fail;
1472
1473 if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0) {
1474 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1475 pa_xfree(d);
1476 goto fail;
1477 }
1478
1479 if (!(mid = pa_machine_id())) {
1480 pa_xfree(d);
1481 goto fail;
1482 }
1483
1484 k = pa_sprintf_malloc("%s" PA_PATH_SEP "%s-runtime", d, mid);
1485 pa_xfree(d);
1486 pa_xfree(mid);
1487
1488 for (;;) {
1489 /* OK, first let's check if the "runtime" symlink is already
1490 * existant */
1491
1492 if (!(p = pa_readlink(k))) {
1493
1494 if (errno != ENOENT) {
1495 pa_log_error("Failed to stat runtime directory %s: %s", k, pa_cstrerror(errno));
1496 goto fail;
1497 }
1498
1499 /* Hmm, so the runtime directory didn't exist yet, so let's
1500 * create one in /tmp and symlink that to it */
1501
1502 if (make_random_dir_and_link(0700, k) < 0) {
1503
1504 /* Mhmm, maybe another process was quicker than us,
1505 * let's check if that was valid */
1506 if (errno == EEXIST)
1507 continue;
1508
1509 goto fail;
1510 }
1511
1512 return k;
1513 }
1514
1515 /* Make sure that this actually makes sense */
1516 if (!pa_is_path_absolute(p)) {
1517 pa_log_error("Path %s in link %s is not absolute.", p, k);
1518 errno = ENOENT;
1519 goto fail;
1520 }
1521
1522 /* Hmm, so this symlink is still around, make sure nobody fools
1523 * us */
1524
1525 if (lstat(p, &st) < 0) {
1526
1527 if (errno != ENOENT) {
1528 pa_log_error("Failed to stat runtime directory %s: %s", p, pa_cstrerror(errno));
1529 goto fail;
1530 }
1531
1532 } else {
1533
1534 if (S_ISDIR(st.st_mode) &&
1535 (st.st_uid == getuid()) &&
1536 ((st.st_mode & 0777) == 0700)) {
1537
1538 pa_xfree(p);
1539 return k;
1540 }
1541
1542 pa_log_info("Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory.");
1543 }
1544
1545 pa_xfree(p);
1546 p = NULL;
1547
1548 /* Hmm, so the link points to some nonexisting or invalid
1549 * dir. Let's replace it by a new link. We first create a
1550 * temporary link and then rename that to allow concurrent
1551 * execution of this function. */
1552
1553 t = pa_sprintf_malloc("%s.tmp", k);
1554
1555 if (make_random_dir_and_link(0700, t) < 0) {
1556
1557 if (errno != EEXIST) {
1558 pa_log_error("Failed to symlink %s: %s", t, pa_cstrerror(errno));
1559 goto fail;
1560 }
1561
1562 pa_xfree(t);
1563 t = NULL;
1564
1565 /* Hmm, someone lese was quicker then us. Let's give
1566 * him some time to finish, and retry. */
1567 pa_msleep(10);
1568 continue;
1569 }
1570
1571 /* OK, we succeeded in creating the temporary symlink, so
1572 * let's rename it */
1573 if (rename(t, k) < 0) {
1574 pa_log_error("Failed to rename %s to %s: %s", t, k, pa_cstrerror(errno));
1575 goto fail;
1576 }
1577
1578 pa_xfree(t);
1579 return k;
1580 }
1581
1582 fail:
1583 pa_xfree(p);
1584 pa_xfree(k);
1585 pa_xfree(t);
1586
1587 return NULL;
1588 }
1589
1590 /* Try to open a configuration file. If "env" is specified, open the
1591 * value of the specified environment variable. Otherwise look for a
1592 * file "local" in the home directory or a file "global" in global
1593 * file system. If "result" is non-NULL, a pointer to a newly
1594 * allocated buffer containing the used configuration file is
1595 * stored there.*/
1596 FILE *pa_open_config_file(const char *global, const char *local, const char *env, char **result) {
1597 const char *fn;
1598 #ifdef OS_IS_WIN32
1599 char buf[PATH_MAX];
1600
1601 if (!getenv(PULSE_ROOTENV))
1602 pa_set_root(NULL);
1603 #endif
1604
1605 if (env && (fn = getenv(env))) {
1606 FILE *f;
1607
1608 #ifdef OS_IS_WIN32
1609 if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
1610 /* FIXME: Needs to set errno! */
1611 return NULL;
1612 fn = buf;
1613 #endif
1614
1615 if ((f = fopen(fn, "r"))) {
1616 if (result)
1617 *result = pa_xstrdup(fn);
1618
1619 return f;
1620 }
1621
1622 pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
1623 return NULL;
1624 }
1625
1626 if (local) {
1627 const char *e;
1628 char *lfn;
1629 char *h;
1630 FILE *f;
1631
1632 if ((e = getenv("PULSE_CONFIG_PATH")))
1633 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
1634 else if ((h = pa_get_home_dir_malloc())) {
1635 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
1636 pa_xfree(h);
1637 } else
1638 return NULL;
1639
1640 #ifdef OS_IS_WIN32
1641 if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) {
1642 /* FIXME: Needs to set errno! */
1643 pa_xfree(lfn);
1644 return NULL;
1645 }
1646 fn = buf;
1647 #endif
1648
1649 if ((f = fopen(fn, "r"))) {
1650 if (result)
1651 *result = pa_xstrdup(fn);
1652
1653 pa_xfree(lfn);
1654 return f;
1655 }
1656
1657 if (errno != ENOENT) {
1658 pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
1659 pa_xfree(lfn);
1660 return NULL;
1661 }
1662
1663 pa_xfree(lfn);
1664 }
1665
1666 if (global) {
1667 FILE *f;
1668
1669 #ifdef OS_IS_WIN32
1670 if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
1671 /* FIXME: Needs to set errno! */
1672 return NULL;
1673 global = buf;
1674 #endif
1675
1676 if ((f = fopen(global, "r"))) {
1677
1678 if (result)
1679 *result = pa_xstrdup(global);
1680
1681 return f;
1682 }
1683 }
1684
1685 errno = ENOENT;
1686 return NULL;
1687 }
1688
1689 char *pa_find_config_file(const char *global, const char *local, const char *env) {
1690 const char *fn;
1691 #ifdef OS_IS_WIN32
1692 char buf[PATH_MAX];
1693
1694 if (!getenv(PULSE_ROOTENV))
1695 pa_set_root(NULL);
1696 #endif
1697
1698 if (env && (fn = getenv(env))) {
1699
1700 #ifdef OS_IS_WIN32
1701 if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
1702 /* FIXME: Needs to set errno! */
1703 return NULL;
1704 fn = buf;
1705 #endif
1706
1707 if (access(fn, R_OK) == 0)
1708 return pa_xstrdup(fn);
1709
1710 pa_log_warn("Failed to access configuration file '%s': %s", fn, pa_cstrerror(errno));
1711 return NULL;
1712 }
1713
1714 if (local) {
1715 const char *e;
1716 char *lfn;
1717 char *h;
1718
1719 if ((e = getenv("PULSE_CONFIG_PATH")))
1720 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
1721 else if ((h = pa_get_home_dir_malloc())) {
1722 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
1723 pa_xfree(h);
1724 } else
1725 return NULL;
1726
1727 #ifdef OS_IS_WIN32
1728 if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) {
1729 /* FIXME: Needs to set errno! */
1730 pa_xfree(lfn);
1731 return NULL;
1732 }
1733 fn = buf;
1734 #endif
1735
1736 if (access(fn, R_OK) == 0) {
1737 char *r = pa_xstrdup(fn);
1738 pa_xfree(lfn);
1739 return r;
1740 }
1741
1742 if (errno != ENOENT) {
1743 pa_log_warn("Failed to access configuration file '%s': %s", fn, pa_cstrerror(errno));
1744 pa_xfree(lfn);
1745 return NULL;
1746 }
1747
1748 pa_xfree(lfn);
1749 }
1750
1751 if (global) {
1752 #ifdef OS_IS_WIN32
1753 if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
1754 /* FIXME: Needs to set errno! */
1755 return NULL;
1756 global = buf;
1757 #endif
1758
1759 if (access(global, R_OK) == 0)
1760 return pa_xstrdup(global);
1761 }
1762
1763 errno = ENOENT;
1764
1765 return NULL;
1766 }
1767
1768 /* Format the specified data as a hexademical string */
1769 char *pa_hexstr(const uint8_t* d, size_t dlength, char *s, size_t slength) {
1770 size_t i = 0, j = 0;
1771 const char hex[] = "0123456789abcdef";
1772
1773 pa_assert(d);
1774 pa_assert(s);
1775 pa_assert(slength > 0);
1776
1777 while (i < dlength && j+3 <= slength) {
1778 s[j++] = hex[*d >> 4];
1779 s[j++] = hex[*d & 0xF];
1780
1781 d++;
1782 i++;
1783 }
1784
1785 s[j < slength ? j : slength] = 0;
1786 return s;
1787 }
1788
1789 /* Convert a hexadecimal digit to a number or -1 if invalid */
1790 static int hexc(char c) {
1791 if (c >= '0' && c <= '9')
1792 return c - '0';
1793
1794 if (c >= 'A' && c <= 'F')
1795 return c - 'A' + 10;
1796
1797 if (c >= 'a' && c <= 'f')
1798 return c - 'a' + 10;
1799
1800 errno = EINVAL;
1801 return -1;
1802 }
1803
1804 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1805 size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength) {
1806 size_t j = 0;
1807
1808 pa_assert(p);
1809 pa_assert(d);
1810
1811 while (j < dlength && *p) {
1812 int b;
1813
1814 if ((b = hexc(*(p++))) < 0)
1815 return (size_t) -1;
1816
1817 d[j] = (uint8_t) (b << 4);
1818
1819 if (!*p)
1820 return (size_t) -1;
1821
1822 if ((b = hexc(*(p++))) < 0)
1823 return (size_t) -1;
1824
1825 d[j] |= (uint8_t) b;
1826 j++;
1827 }
1828
1829 return j;
1830 }
1831
1832 /* Returns nonzero when *s starts with *pfx */
1833 pa_bool_t pa_startswith(const char *s, const char *pfx) {
1834 size_t l;
1835
1836 pa_assert(s);
1837 pa_assert(pfx);
1838
1839 l = strlen(pfx);
1840
1841 return strlen(s) >= l && strncmp(s, pfx, l) == 0;
1842 }
1843
1844 /* Returns nonzero when *s ends with *sfx */
1845 pa_bool_t pa_endswith(const char *s, const char *sfx) {
1846 size_t l1, l2;
1847
1848 pa_assert(s);
1849 pa_assert(sfx);
1850
1851 l1 = strlen(s);
1852 l2 = strlen(sfx);
1853
1854 return l1 >= l2 && strcmp(s+l1-l2, sfx) == 0;
1855 }
1856
1857 pa_bool_t pa_is_path_absolute(const char *fn) {
1858 pa_assert(fn);
1859
1860 #ifndef OS_IS_WIN32
1861 return *fn == '/';
1862 #else
1863 return strlen(fn) >= 3 && isalpha(fn[0]) && fn[1] == ':' && fn[2] == '\\';
1864 #endif
1865 }
1866
1867 char *pa_make_path_absolute(const char *p) {
1868 char *r;
1869 char *cwd;
1870
1871 pa_assert(p);
1872
1873 if (pa_is_path_absolute(p))
1874 return pa_xstrdup(p);
1875
1876 if (!(cwd = pa_getcwd()))
1877 return pa_xstrdup(p);
1878
1879 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", cwd, p);
1880 pa_xfree(cwd);
1881 return r;
1882 }
1883
1884 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1885 * if fn is non-null and starts with / return fn
1886 * otherwise append fn to the run time path and return it */
1887 static char *get_path(const char *fn, pa_bool_t prependmid, pa_bool_t rt) {
1888 char *rtp;
1889
1890 rtp = rt ? pa_get_runtime_dir() : pa_get_state_dir();
1891
1892 if (fn) {
1893 char *r;
1894
1895 if (pa_is_path_absolute(fn))
1896 return pa_xstrdup(fn);
1897
1898 if (!rtp)
1899 return NULL;
1900
1901 if (prependmid) {
1902 char *mid;
1903
1904 if (!(mid = pa_machine_id())) {
1905 pa_xfree(rtp);
1906 return NULL;
1907 }
1908
1909 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s-%s", rtp, mid, fn);
1910 pa_xfree(mid);
1911 } else
1912 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", rtp, fn);
1913
1914 pa_xfree(rtp);
1915 return r;
1916 } else
1917 return rtp;
1918 }
1919
1920 char *pa_runtime_path(const char *fn) {
1921 return get_path(fn, FALSE, TRUE);
1922 }
1923
1924 char *pa_state_path(const char *fn, pa_bool_t appendmid) {
1925 return get_path(fn, appendmid, FALSE);
1926 }
1927
1928 /* Convert the string s to a signed integer in *ret_i */
1929 int pa_atoi(const char *s, int32_t *ret_i) {
1930 char *x = NULL;
1931 long l;
1932
1933 pa_assert(s);
1934 pa_assert(ret_i);
1935
1936 errno = 0;
1937 l = strtol(s, &x, 0);
1938
1939 if (!x || *x || errno) {
1940 if (!errno)
1941 errno = EINVAL;
1942 return -1;
1943 }
1944
1945 if ((int32_t) l != l) {
1946 errno = ERANGE;
1947 return -1;
1948 }
1949
1950 *ret_i = (int32_t) l;
1951
1952 return 0;
1953 }
1954
1955 /* Convert the string s to an unsigned integer in *ret_u */
1956 int pa_atou(const char *s, uint32_t *ret_u) {
1957 char *x = NULL;
1958 unsigned long l;
1959
1960 pa_assert(s);
1961 pa_assert(ret_u);
1962
1963 errno = 0;
1964 l = strtoul(s, &x, 0);
1965
1966 if (!x || *x || errno) {
1967 if (!errno)
1968 errno = EINVAL;
1969 return -1;
1970 }
1971
1972 if ((uint32_t) l != l) {
1973 errno = ERANGE;
1974 return -1;
1975 }
1976
1977 *ret_u = (uint32_t) l;
1978
1979 return 0;
1980 }
1981
1982 #ifdef HAVE_STRTOF_L
1983 static locale_t c_locale = NULL;
1984
1985 static void c_locale_destroy(void) {
1986 freelocale(c_locale);
1987 }
1988 #endif
1989
1990 int pa_atod(const char *s, double *ret_d) {
1991 char *x = NULL;
1992 double f;
1993
1994 pa_assert(s);
1995 pa_assert(ret_d);
1996
1997 /* This should be locale independent */
1998
1999 #ifdef HAVE_STRTOF_L
2000
2001 PA_ONCE_BEGIN {
2002
2003 if ((c_locale = newlocale(LC_ALL_MASK, "C", NULL)))
2004 atexit(c_locale_destroy);
2005
2006 } PA_ONCE_END;
2007
2008 if (c_locale) {
2009 errno = 0;
2010 f = strtod_l(s, &x, c_locale);
2011 } else
2012 #endif
2013 {
2014 errno = 0;
2015 f = strtod(s, &x);
2016 }
2017
2018 if (!x || *x || errno) {
2019 if (!errno)
2020 errno = EINVAL;
2021 return -1;
2022 }
2023
2024 *ret_d = f;
2025
2026 return 0;
2027 }
2028
2029 /* Same as snprintf, but guarantees NUL-termination on every platform */
2030 size_t pa_snprintf(char *str, size_t size, const char *format, ...) {
2031 size_t ret;
2032 va_list ap;
2033
2034 pa_assert(str);
2035 pa_assert(size > 0);
2036 pa_assert(format);
2037
2038 va_start(ap, format);
2039 ret = pa_vsnprintf(str, size, format, ap);
2040 va_end(ap);
2041
2042 return ret;
2043 }
2044
2045 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2046 size_t pa_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
2047 int ret;
2048
2049 pa_assert(str);
2050 pa_assert(size > 0);
2051 pa_assert(format);
2052
2053 ret = vsnprintf(str, size, format, ap);
2054
2055 str[size-1] = 0;
2056
2057 if (ret < 0)
2058 return strlen(str);
2059
2060 if ((size_t) ret > size-1)
2061 return size-1;
2062
2063 return (size_t) ret;
2064 }
2065
2066 /* Truncate the specified string, but guarantee that the string
2067 * returned still validates as UTF8 */
2068 char *pa_truncate_utf8(char *c, size_t l) {
2069 pa_assert(c);
2070 pa_assert(pa_utf8_valid(c));
2071
2072 if (strlen(c) <= l)
2073 return c;
2074
2075 c[l] = 0;
2076
2077 while (l > 0 && !pa_utf8_valid(c))
2078 c[--l] = 0;
2079
2080 return c;
2081 }
2082
2083 char *pa_getcwd(void) {
2084 size_t l = 128;
2085
2086 for (;;) {
2087 char *p = pa_xmalloc(l);
2088 if (getcwd(p, l))
2089 return p;
2090
2091 if (errno != ERANGE)
2092 return NULL;
2093
2094 pa_xfree(p);
2095 l *= 2;
2096 }
2097 }
2098
2099 void *pa_will_need(const void *p, size_t l) {
2100 #ifdef RLIMIT_MEMLOCK
2101 struct rlimit rlim;
2102 #endif
2103 const void *a;
2104 size_t size;
2105 int r;
2106 size_t bs;
2107
2108 pa_assert(p);
2109 pa_assert(l > 0);
2110
2111 a = PA_PAGE_ALIGN_PTR(p);
2112 size = (size_t) ((const uint8_t*) p + l - (const uint8_t*) a);
2113
2114 #ifdef HAVE_POSIX_MADVISE
2115 if ((r = posix_madvise((void*) a, size, POSIX_MADV_WILLNEED)) == 0) {
2116 pa_log_debug("posix_madvise() worked fine!");
2117 return (void*) p;
2118 }
2119 #endif
2120
2121 /* Most likely the memory was not mmap()ed from a file and thus
2122 * madvise() didn't work, so let's misuse mlock() do page this
2123 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2124 * inviting, the man page of mlock() tells us: "All pages that
2125 * contain a part of the specified address range are guaranteed to
2126 * be resident in RAM when the call returns successfully." */
2127
2128 #ifdef RLIMIT_MEMLOCK
2129 pa_assert_se(getrlimit(RLIMIT_MEMLOCK, &rlim) == 0);
2130
2131 if (rlim.rlim_cur < PA_PAGE_SIZE) {
2132 pa_log_debug("posix_madvise() failed (or doesn't exist), resource limits don't allow mlock(), can't page in data: %s", pa_cstrerror(r));
2133 errno = EPERM;
2134 return (void*) p;
2135 }
2136
2137 bs = PA_PAGE_ALIGN((size_t) rlim.rlim_cur);
2138 #else
2139 bs = PA_PAGE_SIZE*4;
2140 #endif
2141
2142 pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r));
2143
2144 #ifdef HAVE_MLOCK
2145 while (size > 0 && bs > 0) {
2146
2147 if (bs > size)
2148 bs = size;
2149
2150 if (mlock(a, bs) < 0) {
2151 bs = PA_PAGE_ALIGN(bs / 2);
2152 continue;
2153 }
2154
2155 pa_assert_se(munlock(a, bs) == 0);
2156
2157 a = (const uint8_t*) a + bs;
2158 size -= bs;
2159 }
2160 #endif
2161
2162 if (bs <= 0)
2163 pa_log_debug("mlock() failed too (or doesn't exist), giving up: %s", pa_cstrerror(errno));
2164 else
2165 pa_log_debug("mlock() worked fine!");
2166
2167 return (void*) p;
2168 }
2169
2170 void pa_close_pipe(int fds[2]) {
2171 pa_assert(fds);
2172
2173 if (fds[0] >= 0)
2174 pa_assert_se(pa_close(fds[0]) == 0);
2175
2176 if (fds[1] >= 0)
2177 pa_assert_se(pa_close(fds[1]) == 0);
2178
2179 fds[0] = fds[1] = -1;
2180 }
2181
2182 char *pa_readlink(const char *p) {
2183 size_t l = 100;
2184
2185 for (;;) {
2186 char *c;
2187 ssize_t n;
2188
2189 c = pa_xmalloc(l);
2190
2191 if ((n = readlink(p, c, l-1)) < 0) {
2192 pa_xfree(c);
2193 return NULL;
2194 }
2195
2196 if ((size_t) n < l-1) {
2197 c[n] = 0;
2198 return c;
2199 }
2200
2201 pa_xfree(c);
2202 l *= 2;
2203 }
2204 }
2205
2206 int pa_close_all(int except_fd, ...) {
2207 va_list ap;
2208 unsigned n = 0, i;
2209 int r, *p;
2210
2211 va_start(ap, except_fd);
2212
2213 if (except_fd >= 0)
2214 for (n = 1; va_arg(ap, int) >= 0; n++)
2215 ;
2216
2217 va_end(ap);
2218
2219 p = pa_xnew(int, n+1);
2220
2221 va_start(ap, except_fd);
2222
2223 i = 0;
2224 if (except_fd >= 0) {
2225 int fd;
2226 p[i++] = except_fd;
2227
2228 while ((fd = va_arg(ap, int)) >= 0)
2229 p[i++] = fd;
2230 }
2231 p[i] = -1;
2232
2233 va_end(ap);
2234
2235 r = pa_close_allv(p);
2236 pa_xfree(p);
2237
2238 return r;
2239 }
2240
2241 int pa_close_allv(const int except_fds[]) {
2242 struct rlimit rl;
2243 int maxfd, fd;
2244
2245 #ifdef __linux__
2246 int saved_errno;
2247 DIR *d;
2248
2249 if ((d = opendir("/proc/self/fd"))) {
2250
2251 struct dirent *de;
2252
2253 while ((de = readdir(d))) {
2254 pa_bool_t found;
2255 long l;
2256 char *e = NULL;
2257 int i;
2258
2259 if (de->d_name[0] == '.')
2260 continue;
2261
2262 errno = 0;
2263 l = strtol(de->d_name, &e, 10);
2264 if (errno != 0 || !e || *e) {
2265 closedir(d);
2266 errno = EINVAL;
2267 return -1;
2268 }
2269
2270 fd = (int) l;
2271
2272 if ((long) fd != l) {
2273 closedir(d);
2274 errno = EINVAL;
2275 return -1;
2276 }
2277
2278 if (fd < 3)
2279 continue;
2280
2281 if (fd == dirfd(d))
2282 continue;
2283
2284 found = FALSE;
2285 for (i = 0; except_fds[i] >= 0; i++)
2286 if (except_fds[i] == fd) {
2287 found = TRUE;
2288 break;
2289 }
2290
2291 if (found)
2292 continue;
2293
2294 if (pa_close(fd) < 0) {
2295 saved_errno = errno;
2296 closedir(d);
2297 errno = saved_errno;
2298
2299 return -1;
2300 }
2301 }
2302
2303 closedir(d);
2304 return 0;
2305 }
2306
2307 #endif
2308
2309 if (getrlimit(RLIMIT_NOFILE, &rl) >= 0)
2310 maxfd = (int) rl.rlim_max;
2311 else
2312 maxfd = sysconf(_SC_OPEN_MAX);
2313
2314 for (fd = 3; fd < maxfd; fd++) {
2315 int i;
2316 pa_bool_t found;
2317
2318 found = FALSE;
2319 for (i = 0; except_fds[i] >= 0; i++)
2320 if (except_fds[i] == fd) {
2321 found = TRUE;
2322 break;
2323 }
2324
2325 if (found)
2326 continue;
2327
2328 if (pa_close(fd) < 0 && errno != EBADF)
2329 return -1;
2330 }
2331
2332 return 0;
2333 }
2334
2335 int pa_unblock_sigs(int except, ...) {
2336 va_list ap;
2337 unsigned n = 0, i;
2338 int r, *p;
2339
2340 va_start(ap, except);
2341
2342 if (except >= 1)
2343 for (n = 1; va_arg(ap, int) >= 0; n++)
2344 ;
2345
2346 va_end(ap);
2347
2348 p = pa_xnew(int, n+1);
2349
2350 va_start(ap, except);
2351
2352 i = 0;
2353 if (except >= 1) {
2354 int sig;
2355 p[i++] = except;
2356
2357 while ((sig = va_arg(ap, int)) >= 0)
2358 p[i++] = sig;
2359 }
2360 p[i] = -1;
2361
2362 va_end(ap);
2363
2364 r = pa_unblock_sigsv(p);
2365 pa_xfree(p);
2366
2367 return r;
2368 }
2369
2370 int pa_unblock_sigsv(const int except[]) {
2371 int i;
2372 sigset_t ss;
2373
2374 if (sigemptyset(&ss) < 0)
2375 return -1;
2376
2377 for (i = 0; except[i] > 0; i++)
2378 if (sigaddset(&ss, except[i]) < 0)
2379 return -1;
2380
2381 return sigprocmask(SIG_SETMASK, &ss, NULL);
2382 }
2383
2384 int pa_reset_sigs(int except, ...) {
2385 va_list ap;
2386 unsigned n = 0, i;
2387 int *p, r;
2388
2389 va_start(ap, except);
2390
2391 if (except >= 1)
2392 for (n = 1; va_arg(ap, int) >= 0; n++)
2393 ;
2394
2395 va_end(ap);
2396
2397 p = pa_xnew(int, n+1);
2398
2399 va_start(ap, except);
2400
2401 i = 0;
2402 if (except >= 1) {
2403 int sig;
2404 p[i++] = except;
2405
2406 while ((sig = va_arg(ap, int)) >= 0)
2407 p[i++] = sig;
2408 }
2409 p[i] = -1;
2410
2411 va_end(ap);
2412
2413 r = pa_reset_sigsv(p);
2414 pa_xfree(p);
2415
2416 return r;
2417 }
2418
2419 int pa_reset_sigsv(const int except[]) {
2420 int sig;
2421
2422 for (sig = 1; sig < NSIG; sig++) {
2423 pa_bool_t reset = TRUE;
2424
2425 switch (sig) {
2426 case SIGKILL:
2427 case SIGSTOP:
2428 reset = FALSE;
2429 break;
2430
2431 default: {
2432 int i;
2433
2434 for (i = 0; except[i] > 0; i++) {
2435 if (sig == except[i]) {
2436 reset = FALSE;
2437 break;
2438 }
2439 }
2440 }
2441 }
2442
2443 if (reset) {
2444 struct sigaction sa;
2445
2446 memset(&sa, 0, sizeof(sa));
2447 sa.sa_handler = SIG_DFL;
2448
2449 /* On Linux the first two RT signals are reserved by
2450 * glibc, and sigaction() will return EINVAL for them. */
2451 if ((sigaction(sig, &sa, NULL) < 0))
2452 if (errno != EINVAL)
2453 return -1;
2454 }
2455 }
2456
2457 return 0;
2458 }
2459
2460 void pa_set_env(const char *key, const char *value) {
2461 pa_assert(key);
2462 pa_assert(value);
2463
2464 /* This is not thread-safe */
2465
2466 putenv(pa_sprintf_malloc("%s=%s", key, value));
2467 }
2468
2469 void pa_set_env_and_record(const char *key, const char *value) {
2470 pa_assert(key);
2471 pa_assert(value);
2472
2473 /* This is not thread-safe */
2474
2475 pa_set_env(key, value);
2476 recorded_env = pa_strlist_prepend(recorded_env, key);
2477 }
2478
2479 void pa_unset_env_recorded(void) {
2480
2481 /* This is not thread-safe */
2482
2483 for (;;) {
2484 char *s;
2485
2486 recorded_env = pa_strlist_pop(recorded_env, &s);
2487
2488 if (!s)
2489 break;
2490
2491 unsetenv(s);
2492 pa_xfree(s);
2493 }
2494 }
2495
2496 pa_bool_t pa_in_system_mode(void) {
2497 const char *e;
2498
2499 if (!(e = getenv("PULSE_SYSTEM")))
2500 return FALSE;
2501
2502 return !!atoi(e);
2503 }
2504
2505 char *pa_get_user_name_malloc(void) {
2506 ssize_t k;
2507 char *u;
2508
2509 #ifdef _SC_LOGIN_NAME_MAX
2510 k = (ssize_t) sysconf(_SC_LOGIN_NAME_MAX);
2511
2512 if (k <= 0)
2513 #endif
2514 k = 32;
2515
2516 u = pa_xnew(char, k+1);
2517
2518 if (!(pa_get_user_name(u, k))) {
2519 pa_xfree(u);
2520 return NULL;
2521 }
2522
2523 return u;
2524 }
2525
2526 char *pa_get_host_name_malloc(void) {
2527 size_t l;
2528
2529 l = 100;
2530 for (;;) {
2531 char *c;
2532
2533 c = pa_xmalloc(l);
2534
2535 if (!pa_get_host_name(c, l)) {
2536
2537 if (errno != EINVAL && errno != ENAMETOOLONG)
2538 break;
2539
2540 } else if (strlen(c) < l-1) {
2541 char *u;
2542
2543 if (*c == 0) {
2544 pa_xfree(c);
2545 break;
2546 }
2547
2548 u = pa_utf8_filter(c);
2549 pa_xfree(c);
2550 return u;
2551 }
2552
2553 /* Hmm, the hostname is as long the space we offered the
2554 * function, we cannot know if it fully fit in, so let's play
2555 * safe and retry. */
2556
2557 pa_xfree(c);
2558 l *= 2;
2559 }
2560
2561 return NULL;
2562 }
2563
2564 char *pa_machine_id(void) {
2565 FILE *f;
2566 char *h;
2567
2568 /* The returned value is supposed be some kind of ascii identifier
2569 * that is unique and stable across reboots. */
2570
2571 /* First we try the D-Bus UUID, which is the best option we have,
2572 * since it fits perfectly our needs and is not as volatile as the
2573 * hostname which might be set from dhcp. */
2574
2575 if ((f = fopen(PA_MACHINE_ID, "r"))) {
2576 char ln[34] = "", *r;
2577
2578 r = fgets(ln, sizeof(ln)-1, f);
2579 fclose(f);
2580
2581 pa_strip_nl(ln);
2582
2583 if (r && ln[0])
2584 return pa_utf8_filter(ln);
2585 }
2586
2587 if ((h = pa_get_host_name_malloc()))
2588 return h;
2589
2590 /* If no hostname was set we use the POSIX hostid. It's usually
2591 * the IPv4 address. Might not be that stable. */
2592 return pa_sprintf_malloc("%08lx", (unsigned long) gethostid);
2593 }
2594
2595 char *pa_session_id(void) {
2596 const char *e;
2597
2598 if (!(e = getenv("XDG_SESSION_COOKIE")))
2599 return NULL;
2600
2601 return pa_utf8_filter(e);
2602 }
2603
2604 char *pa_uname_string(void) {
2605 struct utsname u;
2606
2607 pa_assert_se(uname(&u) >= 0);
2608
2609 return pa_sprintf_malloc("%s %s %s %s", u.sysname, u.machine, u.release, u.version);
2610 }
2611
2612 #ifdef HAVE_VALGRIND_MEMCHECK_H
2613 pa_bool_t pa_in_valgrind(void) {
2614 static int b = 0;
2615
2616 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2617 * here instead of really checking whether we run in valgrind or
2618 * not. */
2619
2620 if (b < 1)
2621 b = getenv("VALGRIND") ? 2 : 1;
2622
2623 return b > 1;
2624 }
2625 #endif
2626
2627 unsigned pa_gcd(unsigned a, unsigned b) {
2628
2629 while (b > 0) {
2630 unsigned t = b;
2631 b = a % b;
2632 a = t;
2633 }
2634
2635 return a;
2636 }
2637
2638 void pa_reduce(unsigned *num, unsigned *den) {
2639
2640 unsigned gcd = pa_gcd(*num, *den);
2641
2642 if (gcd <= 0)
2643 return;
2644
2645 *num /= gcd;
2646 *den /= gcd;
2647
2648 pa_assert(pa_gcd(*num, *den) == 1);
2649 }
2650
2651 unsigned pa_ncpus(void) {
2652 long ncpus;
2653
2654 #ifdef _SC_NPROCESSORS_CONF
2655 ncpus = sysconf(_SC_NPROCESSORS_CONF);
2656 #else
2657 ncpus = 1;
2658 #endif
2659
2660 return ncpus <= 0 ? 1 : (unsigned) ncpus;
2661 }
2662
2663 char *pa_replace(const char*s, const char*a, const char *b) {
2664 pa_strbuf *sb;
2665 size_t an;
2666
2667 pa_assert(s);
2668 pa_assert(a);
2669 pa_assert(b);
2670
2671 an = strlen(a);
2672 sb = pa_strbuf_new();
2673
2674 for (;;) {
2675 const char *p;
2676
2677 if (!(p = strstr(s, a)))
2678 break;
2679
2680 pa_strbuf_putsn(sb, s, p-s);
2681 pa_strbuf_puts(sb, b);
2682 s = p + an;
2683 }
2684
2685 pa_strbuf_puts(sb, s);
2686
2687 return pa_strbuf_tostring_free(sb);
2688 }
2689
2690 char *pa_unescape(char *p) {
2691 char *s, *d;
2692 pa_bool_t escaped = FALSE;
2693
2694 for (s = p, d = p; *s; s++) {
2695 if (!escaped && *s == '\\') {
2696 escaped = TRUE;
2697 continue;
2698 }
2699
2700 *(d++) = *s;
2701 escaped = FALSE;
2702 }
2703
2704 *d = 0;
2705
2706 return p;
2707 }
2708
2709 char *pa_realpath(const char *path) {
2710 char *t;
2711 pa_assert(path);
2712
2713 /* We want only abolsute paths */
2714 if (path[0] != '/') {
2715 errno = EINVAL;
2716 return NULL;
2717 }
2718
2719 #if defined(__GLIBC__) || defined(__APPLE__)
2720 {
2721 char *r;
2722
2723 if (!(r = realpath(path, NULL)))
2724 return NULL;
2725
2726 /* We copy this here in case our pa_xmalloc() is not
2727 * implemented on top of libc malloc() */
2728 t = pa_xstrdup(r);
2729 pa_xfree(r);
2730 }
2731 #elif defined(PATH_MAX)
2732 {
2733 char *path_buf;
2734 path_buf = pa_xmalloc(PATH_MAX);
2735
2736 if (!(t = realpath(path, path_buf))) {
2737 pa_xfree(path_buf);
2738 return NULL;
2739 }
2740 }
2741 #else
2742 #error "It's not clear whether this system supports realpath(..., NULL) like GNU libc does. If it doesn't we need a private version of realpath() here."
2743 #endif
2744
2745 return t;
2746 }
2747
2748 void pa_disable_sigpipe(void) {
2749
2750 #ifdef SIGPIPE
2751 struct sigaction sa;
2752
2753 pa_zero(sa);
2754
2755 if (sigaction(SIGPIPE, NULL, &sa) < 0) {
2756 pa_log("sigaction(): %s", pa_cstrerror(errno));
2757 return;
2758 }
2759
2760 sa.sa_handler = SIG_IGN;
2761
2762 if (sigaction(SIGPIPE, &sa, NULL) < 0) {
2763 pa_log("sigaction(): %s", pa_cstrerror(errno));
2764 return;
2765 }
2766 #endif
2767 }
2768
2769 void pa_xfreev(void**a) {
2770 void **p;
2771
2772 if (!a)
2773 return;
2774
2775 for (p = a; *p; p++)
2776 pa_xfree(*p);
2777
2778 pa_xfree(a);
2779 }
2780
2781 char **pa_split_spaces_strv(const char *s) {
2782 char **t, *e;
2783 unsigned i = 0, n = 8;
2784 const char *state = NULL;
2785
2786 t = pa_xnew(char*, n);
2787 while ((e = pa_split_spaces(s, &state))) {
2788 t[i++] = e;
2789
2790 if (i >= n) {
2791 n *= 2;
2792 t = pa_xrenew(char*, t, n);
2793 }
2794 }
2795
2796 if (i <= 0) {
2797 pa_xfree(t);
2798 return NULL;
2799 }
2800
2801 t[i] = NULL;
2802 return t;
2803 }
2804
2805 char* pa_maybe_prefix_path(const char *path, const char *prefix) {
2806 pa_assert(path);
2807
2808 if (pa_is_path_absolute(path))
2809 return pa_xstrdup(path);
2810
2811 return pa_sprintf_malloc("%s" PA_PATH_SEP "%s", prefix, path);
2812 }
2813
2814 size_t pa_pipe_buf(int fd) {
2815
2816 #ifdef _PC_PIPE_BUF
2817 long n;
2818
2819 if ((n = fpathconf(fd, _PC_PIPE_BUF)) >= 0)
2820 return (size_t) n;
2821 #endif
2822
2823 #ifdef PIPE_BUF
2824 return PIPE_BUF;
2825 #else
2826 return 4096;
2827 #endif
2828 }
2829
2830 void pa_reset_personality(void) {
2831
2832 #ifdef __linux__
2833 if (personality(PER_LINUX) < 0)
2834 pa_log_warn("Uh, personality() failed: %s", pa_cstrerror(errno));
2835 #endif
2836
2837 }
2838
2839 #if defined(__linux__) && !defined(__OPTIMIZE__)
2840
2841 pa_bool_t pa_run_from_build_tree(void) {
2842 char *rp;
2843 pa_bool_t b = FALSE;
2844
2845 /* We abuse __OPTIMIZE__ as a check whether we are a debug build
2846 * or not. */
2847
2848 if ((rp = pa_readlink("/proc/self/exe"))) {
2849 b = pa_startswith(rp, PA_BUILDDIR);
2850 pa_xfree(rp);
2851 }
2852
2853 return b;
2854 }
2855
2856 #endif