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