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