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