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