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