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