]> code.delx.au - pulseaudio/blob - src/pulsecore/core-util.c
pulsecore: don't leak d in case of error
[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 occured */
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 wheter 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 return 0;
1415 }
1416
1417 char *pa_get_runtime_dir(void) {
1418 char *d, *k = NULL, *p = NULL, *t = NULL, *mid;
1419 struct stat st;
1420 mode_t m;
1421
1422 /* The runtime directory shall contain dynamic data that needs NOT
1423 * to be kept accross reboots and is usuallly private to the user,
1424 * except in system mode, where it might be accessible by other
1425 * users, too. Since we need POSIX locking and UNIX sockets in
1426 * this directory, we link it to a random subdir in /tmp, if it
1427 * was not explicitly configured. */
1428
1429 m = pa_in_system_mode() ? 0755U : 0700U;
1430
1431 if ((d = getenv("PULSE_RUNTIME_PATH"))) {
1432
1433 if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0) {
1434 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1435 goto fail;
1436 }
1437
1438 return pa_xstrdup(d);
1439 }
1440
1441 if (!(d = get_pulse_home()))
1442 goto fail;
1443
1444 if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0) {
1445 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1446 pa_xfree(d);
1447 goto fail;
1448 }
1449
1450 if (!(mid = pa_machine_id())) {
1451 pa_xfree(d);
1452 goto fail;
1453 }
1454
1455 k = pa_sprintf_malloc("%s" PA_PATH_SEP "%s:runtime", d, mid);
1456 pa_xfree(d);
1457 pa_xfree(mid);
1458
1459 for (;;) {
1460 /* OK, first let's check if the "runtime" symlink is already
1461 * existant */
1462
1463 if (!(p = pa_readlink(k))) {
1464
1465 if (errno != ENOENT) {
1466 pa_log_error("Failed to stat runtime directory %s: %s", k, pa_cstrerror(errno));
1467 goto fail;
1468 }
1469
1470 /* Hmm, so the runtime directory didn't exist yet, so let's
1471 * create one in /tmp and symlink that to it */
1472
1473 if (make_random_dir_and_link(0700, k) < 0) {
1474
1475 /* Mhmm, maybe another process was quicker than us,
1476 * let's check if that was valid */
1477 if (errno == EEXIST)
1478 continue;
1479
1480 goto fail;
1481 }
1482
1483 return k;
1484 }
1485
1486 /* Make sure that this actually makes sense */
1487 if (!pa_is_path_absolute(p)) {
1488 pa_log_error("Path %s in link %s is not absolute.", p, k);
1489 errno = ENOENT;
1490 goto fail;
1491 }
1492
1493 /* Hmm, so this symlink is still around, make sure nobody fools
1494 * us */
1495
1496 if (lstat(p, &st) < 0) {
1497
1498 if (errno != ENOENT) {
1499 pa_log_error("Failed to stat runtime directory %s: %s", p, pa_cstrerror(errno));
1500 goto fail;
1501 }
1502
1503 } else {
1504
1505 if (S_ISDIR(st.st_mode) &&
1506 (st.st_uid == getuid()) &&
1507 ((st.st_mode & 0777) == 0700)) {
1508
1509 pa_xfree(p);
1510 return k;
1511 }
1512
1513 pa_log_info("Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory.");
1514 }
1515
1516 pa_xfree(p);
1517 p = NULL;
1518
1519 /* Hmm, so the link points to some nonexisting or invalid
1520 * dir. Let's replace it by a new link. We first create a
1521 * temporary link and then rename that to allow concurrent
1522 * execution of this function. */
1523
1524 t = pa_sprintf_malloc("%s.tmp", k);
1525
1526 if (make_random_dir_and_link(0700, t) < 0) {
1527
1528 if (errno != EEXIST) {
1529 pa_log_error("Failed to symlink %s: %s", t, pa_cstrerror(errno));
1530 goto fail;
1531 }
1532
1533 pa_xfree(t);
1534 t = NULL;
1535
1536 /* Hmm, someone lese was quicker then us. Let's give
1537 * him some time to finish, and retry. */
1538 pa_msleep(10);
1539 continue;
1540 }
1541
1542 /* OK, we succeeded in creating the temporary symlink, so
1543 * let's rename it */
1544 if (rename(t, k) < 0) {
1545 pa_log_error("Failed to rename %s to %s: %s", t, k, pa_cstrerror(errno));
1546 goto fail;
1547 }
1548
1549 pa_xfree(t);
1550 return k;
1551 }
1552
1553 fail:
1554 pa_xfree(p);
1555 pa_xfree(k);
1556 pa_xfree(t);
1557
1558 return NULL;
1559 }
1560
1561 /* Try to open a configuration file. If "env" is specified, open the
1562 * value of the specified environment variable. Otherwise look for a
1563 * file "local" in the home directory or a file "global" in global
1564 * file system. If "result" is non-NULL, a pointer to a newly
1565 * allocated buffer containing the used configuration file is
1566 * stored there.*/
1567 FILE *pa_open_config_file(const char *global, const char *local, const char *env, char **result) {
1568 const char *fn;
1569 #ifdef OS_IS_WIN32
1570 char buf[PATH_MAX];
1571
1572 if (!getenv(PULSE_ROOTENV))
1573 pa_set_root(NULL);
1574 #endif
1575
1576 if (env && (fn = getenv(env))) {
1577 FILE *f;
1578
1579 #ifdef OS_IS_WIN32
1580 if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
1581 /* FIXME: Needs to set errno! */
1582 return NULL;
1583 fn = buf;
1584 #endif
1585
1586 if ((f = fopen(fn, "r"))) {
1587 if (result)
1588 *result = pa_xstrdup(fn);
1589
1590 return f;
1591 }
1592
1593 pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
1594 return NULL;
1595 }
1596
1597 if (local) {
1598 const char *e;
1599 char *lfn;
1600 char h[PATH_MAX];
1601 FILE *f;
1602
1603 if ((e = getenv("PULSE_CONFIG_PATH")))
1604 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
1605 else if (pa_get_home_dir(h, sizeof(h)))
1606 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
1607 else
1608 return NULL;
1609
1610 #ifdef OS_IS_WIN32
1611 if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) {
1612 /* FIXME: Needs to set errno! */
1613 pa_xfree(lfn);
1614 return NULL;
1615 }
1616 fn = buf;
1617 #endif
1618
1619 if ((f = fopen(fn, "r"))) {
1620 if (result)
1621 *result = pa_xstrdup(fn);
1622
1623 pa_xfree(lfn);
1624 return f;
1625 }
1626
1627 if (errno != ENOENT) {
1628 pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
1629 pa_xfree(lfn);
1630 return NULL;
1631 }
1632
1633 pa_xfree(lfn);
1634 }
1635
1636 if (global) {
1637 FILE *f;
1638
1639 #ifdef OS_IS_WIN32
1640 if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
1641 /* FIXME: Needs to set errno! */
1642 return NULL;
1643 global = buf;
1644 #endif
1645
1646 if ((f = fopen(global, "r"))) {
1647
1648 if (result)
1649 *result = pa_xstrdup(global);
1650
1651 return f;
1652 }
1653 }
1654
1655 errno = ENOENT;
1656 return NULL;
1657 }
1658
1659 char *pa_find_config_file(const char *global, const char *local, const char *env) {
1660 const char *fn;
1661 #ifdef OS_IS_WIN32
1662 char buf[PATH_MAX];
1663
1664 if (!getenv(PULSE_ROOTENV))
1665 pa_set_root(NULL);
1666 #endif
1667
1668 if (env && (fn = getenv(env))) {
1669
1670 #ifdef OS_IS_WIN32
1671 if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
1672 /* FIXME: Needs to set errno! */
1673 return NULL;
1674 fn = buf;
1675 #endif
1676
1677 if (access(fn, R_OK) == 0)
1678 return pa_xstrdup(fn);
1679
1680 pa_log_warn("Failed to access configuration file '%s': %s", fn, pa_cstrerror(errno));
1681 return NULL;
1682 }
1683
1684 if (local) {
1685 const char *e;
1686 char *lfn;
1687 char h[PATH_MAX];
1688
1689 if ((e = getenv("PULSE_CONFIG_PATH")))
1690 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
1691 else if (pa_get_home_dir(h, sizeof(h)))
1692 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
1693 else
1694 return NULL;
1695
1696 #ifdef OS_IS_WIN32
1697 if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) {
1698 /* FIXME: Needs to set errno! */
1699 pa_xfree(lfn);
1700 return NULL;
1701 }
1702 fn = buf;
1703 #endif
1704
1705 if (access(fn, R_OK) == 0) {
1706 char *r = pa_xstrdup(fn);
1707 pa_xfree(lfn);
1708 return r;
1709 }
1710
1711 if (errno != ENOENT) {
1712 pa_log_warn("Failed to access configuration file '%s': %s", fn, pa_cstrerror(errno));
1713 pa_xfree(lfn);
1714 return NULL;
1715 }
1716
1717 pa_xfree(lfn);
1718 }
1719
1720 if (global) {
1721 #ifdef OS_IS_WIN32
1722 if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
1723 /* FIXME: Needs to set errno! */
1724 return NULL;
1725 global = buf;
1726 #endif
1727
1728 if (access(global, R_OK) == 0)
1729 return pa_xstrdup(global);
1730 }
1731
1732 errno = ENOENT;
1733
1734 return NULL;
1735 }
1736
1737 /* Format the specified data as a hexademical string */
1738 char *pa_hexstr(const uint8_t* d, size_t dlength, char *s, size_t slength) {
1739 size_t i = 0, j = 0;
1740 const char hex[] = "0123456789abcdef";
1741
1742 pa_assert(d);
1743 pa_assert(s);
1744 pa_assert(slength > 0);
1745
1746 while (i < dlength && j+3 <= slength) {
1747 s[j++] = hex[*d >> 4];
1748 s[j++] = hex[*d & 0xF];
1749
1750 d++;
1751 i++;
1752 }
1753
1754 s[j < slength ? j : slength] = 0;
1755 return s;
1756 }
1757
1758 /* Convert a hexadecimal digit to a number or -1 if invalid */
1759 static int hexc(char c) {
1760 if (c >= '0' && c <= '9')
1761 return c - '0';
1762
1763 if (c >= 'A' && c <= 'F')
1764 return c - 'A' + 10;
1765
1766 if (c >= 'a' && c <= 'f')
1767 return c - 'a' + 10;
1768
1769 errno = EINVAL;
1770 return -1;
1771 }
1772
1773 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1774 size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength) {
1775 size_t j = 0;
1776
1777 pa_assert(p);
1778 pa_assert(d);
1779
1780 while (j < dlength && *p) {
1781 int b;
1782
1783 if ((b = hexc(*(p++))) < 0)
1784 return (size_t) -1;
1785
1786 d[j] = (uint8_t) (b << 4);
1787
1788 if (!*p)
1789 return (size_t) -1;
1790
1791 if ((b = hexc(*(p++))) < 0)
1792 return (size_t) -1;
1793
1794 d[j] |= (uint8_t) b;
1795 j++;
1796 }
1797
1798 return j;
1799 }
1800
1801 /* Returns nonzero when *s starts with *pfx */
1802 pa_bool_t pa_startswith(const char *s, const char *pfx) {
1803 size_t l;
1804
1805 pa_assert(s);
1806 pa_assert(pfx);
1807
1808 l = strlen(pfx);
1809
1810 return strlen(s) >= l && strncmp(s, pfx, l) == 0;
1811 }
1812
1813 /* Returns nonzero when *s ends with *sfx */
1814 pa_bool_t pa_endswith(const char *s, const char *sfx) {
1815 size_t l1, l2;
1816
1817 pa_assert(s);
1818 pa_assert(sfx);
1819
1820 l1 = strlen(s);
1821 l2 = strlen(sfx);
1822
1823 return l1 >= l2 && strcmp(s+l1-l2, sfx) == 0;
1824 }
1825
1826 pa_bool_t pa_is_path_absolute(const char *fn) {
1827 pa_assert(fn);
1828
1829 #ifndef OS_IS_WIN32
1830 return *fn == '/';
1831 #else
1832 return strlen(fn) >= 3 && isalpha(fn[0]) && fn[1] == ':' && fn[2] == '\\';
1833 #endif
1834 }
1835
1836 char *pa_make_path_absolute(const char *p) {
1837 char *r;
1838 char *cwd;
1839
1840 pa_assert(p);
1841
1842 if (pa_is_path_absolute(p))
1843 return pa_xstrdup(p);
1844
1845 if (!(cwd = pa_getcwd()))
1846 return pa_xstrdup(p);
1847
1848 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", cwd, p);
1849 pa_xfree(cwd);
1850 return r;
1851 }
1852
1853 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1854 * if fn is non-null and starts with / return fn
1855 * otherwise append fn to the run time path and return it */
1856 static char *get_path(const char *fn, pa_bool_t prependmid, pa_bool_t rt) {
1857 char *rtp;
1858
1859 if (pa_is_path_absolute(fn))
1860 return pa_xstrdup(fn);
1861
1862 rtp = rt ? pa_get_runtime_dir() : pa_get_state_dir();
1863
1864 if (!rtp)
1865 return NULL;
1866
1867 if (fn) {
1868 char *r;
1869
1870 if (prependmid) {
1871 char *mid;
1872
1873 if (!(mid = pa_machine_id())) {
1874 pa_xfree(rtp);
1875 return NULL;
1876 }
1877
1878 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s:%s", rtp, mid, fn);
1879 pa_xfree(mid);
1880 } else
1881 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", rtp, fn);
1882
1883 pa_xfree(rtp);
1884 return r;
1885 } else
1886 return rtp;
1887 }
1888
1889 char *pa_runtime_path(const char *fn) {
1890 return get_path(fn, FALSE, TRUE);
1891 }
1892
1893 char *pa_state_path(const char *fn, pa_bool_t appendmid) {
1894 return get_path(fn, appendmid, FALSE);
1895 }
1896
1897 /* Convert the string s to a signed integer in *ret_i */
1898 int pa_atoi(const char *s, int32_t *ret_i) {
1899 char *x = NULL;
1900 long l;
1901
1902 pa_assert(s);
1903 pa_assert(ret_i);
1904
1905 errno = 0;
1906 l = strtol(s, &x, 0);
1907
1908 if (!x || *x || errno) {
1909 if (!errno)
1910 errno = EINVAL;
1911 return -1;
1912 }
1913
1914 if ((int32_t) l != l) {
1915 errno = ERANGE;
1916 return -1;
1917 }
1918
1919 *ret_i = (int32_t) l;
1920
1921 return 0;
1922 }
1923
1924 /* Convert the string s to an unsigned integer in *ret_u */
1925 int pa_atou(const char *s, uint32_t *ret_u) {
1926 char *x = NULL;
1927 unsigned long l;
1928
1929 pa_assert(s);
1930 pa_assert(ret_u);
1931
1932 errno = 0;
1933 l = strtoul(s, &x, 0);
1934
1935 if (!x || *x || errno) {
1936 if (!errno)
1937 errno = EINVAL;
1938 return -1;
1939 }
1940
1941 if ((uint32_t) l != l) {
1942 errno = ERANGE;
1943 return -1;
1944 }
1945
1946 *ret_u = (uint32_t) l;
1947
1948 return 0;
1949 }
1950
1951 #ifdef HAVE_STRTOF_L
1952 static locale_t c_locale = NULL;
1953
1954 static void c_locale_destroy(void) {
1955 freelocale(c_locale);
1956 }
1957 #endif
1958
1959 int pa_atod(const char *s, double *ret_d) {
1960 char *x = NULL;
1961 double f;
1962
1963 pa_assert(s);
1964 pa_assert(ret_d);
1965
1966 /* This should be locale independent */
1967
1968 #ifdef HAVE_STRTOF_L
1969
1970 PA_ONCE_BEGIN {
1971
1972 if ((c_locale = newlocale(LC_ALL_MASK, "C", NULL)))
1973 atexit(c_locale_destroy);
1974
1975 } PA_ONCE_END;
1976
1977 if (c_locale) {
1978 errno = 0;
1979 f = strtod_l(s, &x, c_locale);
1980 } else
1981 #endif
1982 {
1983 errno = 0;
1984 f = strtod(s, &x);
1985 }
1986
1987 if (!x || *x || errno) {
1988 if (!errno)
1989 errno = EINVAL;
1990 return -1;
1991 }
1992
1993 *ret_d = f;
1994
1995 return 0;
1996 }
1997
1998 /* Same as snprintf, but guarantees NUL-termination on every platform */
1999 size_t pa_snprintf(char *str, size_t size, const char *format, ...) {
2000 size_t ret;
2001 va_list ap;
2002
2003 pa_assert(str);
2004 pa_assert(size > 0);
2005 pa_assert(format);
2006
2007 va_start(ap, format);
2008 ret = pa_vsnprintf(str, size, format, ap);
2009 va_end(ap);
2010
2011 return ret;
2012 }
2013
2014 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2015 size_t pa_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
2016 int ret;
2017
2018 pa_assert(str);
2019 pa_assert(size > 0);
2020 pa_assert(format);
2021
2022 ret = vsnprintf(str, size, format, ap);
2023
2024 str[size-1] = 0;
2025
2026 if (ret < 0)
2027 return strlen(str);
2028
2029 if ((size_t) ret > size-1)
2030 return size-1;
2031
2032 return (size_t) ret;
2033 }
2034
2035 /* Truncate the specified string, but guarantee that the string
2036 * returned still validates as UTF8 */
2037 char *pa_truncate_utf8(char *c, size_t l) {
2038 pa_assert(c);
2039 pa_assert(pa_utf8_valid(c));
2040
2041 if (strlen(c) <= l)
2042 return c;
2043
2044 c[l] = 0;
2045
2046 while (l > 0 && !pa_utf8_valid(c))
2047 c[--l] = 0;
2048
2049 return c;
2050 }
2051
2052 char *pa_getcwd(void) {
2053 size_t l = 128;
2054
2055 for (;;) {
2056 char *p = pa_xmalloc(l);
2057 if (getcwd(p, l))
2058 return p;
2059
2060 if (errno != ERANGE)
2061 return NULL;
2062
2063 pa_xfree(p);
2064 l *= 2;
2065 }
2066 }
2067
2068 void *pa_will_need(const void *p, size_t l) {
2069 #ifdef RLIMIT_MEMLOCK
2070 struct rlimit rlim;
2071 #endif
2072 const void *a;
2073 size_t size;
2074 int r;
2075 size_t bs;
2076
2077 pa_assert(p);
2078 pa_assert(l > 0);
2079
2080 a = PA_PAGE_ALIGN_PTR(p);
2081 size = (size_t) ((const uint8_t*) p + l - (const uint8_t*) a);
2082
2083 #ifdef HAVE_POSIX_MADVISE
2084 if ((r = posix_madvise((void*) a, size, POSIX_MADV_WILLNEED)) == 0) {
2085 pa_log_debug("posix_madvise() worked fine!");
2086 return (void*) p;
2087 }
2088 #endif
2089
2090 /* Most likely the memory was not mmap()ed from a file and thus
2091 * madvise() didn't work, so let's misuse mlock() do page this
2092 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2093 * inviting, the man page of mlock() tells us: "All pages that
2094 * contain a part of the specified address range are guaranteed to
2095 * be resident in RAM when the call returns successfully." */
2096
2097 #ifdef RLIMIT_MEMLOCK
2098 pa_assert_se(getrlimit(RLIMIT_MEMLOCK, &rlim) == 0);
2099
2100 if (rlim.rlim_cur < PA_PAGE_SIZE) {
2101 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));
2102 errno = EPERM;
2103 return (void*) p;
2104 }
2105
2106 bs = PA_PAGE_ALIGN((size_t) rlim.rlim_cur);
2107 #else
2108 bs = PA_PAGE_SIZE*4;
2109 #endif
2110
2111 pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r));
2112
2113 #ifdef HAVE_MLOCK
2114 while (size > 0 && bs > 0) {
2115
2116 if (bs > size)
2117 bs = size;
2118
2119 if (mlock(a, bs) < 0) {
2120 bs = PA_PAGE_ALIGN(bs / 2);
2121 continue;
2122 }
2123
2124 pa_assert_se(munlock(a, bs) == 0);
2125
2126 a = (const uint8_t*) a + bs;
2127 size -= bs;
2128 }
2129 #endif
2130
2131 if (bs <= 0)
2132 pa_log_debug("mlock() failed too (or doesn't exist), giving up: %s", pa_cstrerror(errno));
2133 else
2134 pa_log_debug("mlock() worked fine!");
2135
2136 return (void*) p;
2137 }
2138
2139 void pa_close_pipe(int fds[2]) {
2140 pa_assert(fds);
2141
2142 if (fds[0] >= 0)
2143 pa_assert_se(pa_close(fds[0]) == 0);
2144
2145 if (fds[1] >= 0)
2146 pa_assert_se(pa_close(fds[1]) == 0);
2147
2148 fds[0] = fds[1] = -1;
2149 }
2150
2151 char *pa_readlink(const char *p) {
2152 size_t l = 100;
2153
2154 for (;;) {
2155 char *c;
2156 ssize_t n;
2157
2158 c = pa_xmalloc(l);
2159
2160 if ((n = readlink(p, c, l-1)) < 0) {
2161 pa_xfree(c);
2162 return NULL;
2163 }
2164
2165 if ((size_t) n < l-1) {
2166 c[n] = 0;
2167 return c;
2168 }
2169
2170 pa_xfree(c);
2171 l *= 2;
2172 }
2173 }
2174
2175 int pa_close_all(int except_fd, ...) {
2176 va_list ap;
2177 unsigned n = 0, i;
2178 int r, *p;
2179
2180 va_start(ap, except_fd);
2181
2182 if (except_fd >= 0)
2183 for (n = 1; va_arg(ap, int) >= 0; n++)
2184 ;
2185
2186 va_end(ap);
2187
2188 p = pa_xnew(int, n+1);
2189
2190 va_start(ap, except_fd);
2191
2192 i = 0;
2193 if (except_fd >= 0) {
2194 int fd;
2195 p[i++] = except_fd;
2196
2197 while ((fd = va_arg(ap, int)) >= 0)
2198 p[i++] = fd;
2199 }
2200 p[i] = -1;
2201
2202 va_end(ap);
2203
2204 r = pa_close_allv(p);
2205 free(p);
2206
2207 return r;
2208 }
2209
2210 int pa_close_allv(const int except_fds[]) {
2211 struct rlimit rl;
2212 int fd;
2213 int saved_errno;
2214
2215 #ifdef __linux__
2216
2217 DIR *d;
2218
2219 if ((d = opendir("/proc/self/fd"))) {
2220
2221 struct dirent *de;
2222
2223 while ((de = readdir(d))) {
2224 pa_bool_t found;
2225 long l;
2226 char *e = NULL;
2227 int i;
2228
2229 if (de->d_name[0] == '.')
2230 continue;
2231
2232 errno = 0;
2233 l = strtol(de->d_name, &e, 10);
2234 if (errno != 0 || !e || *e) {
2235 closedir(d);
2236 errno = EINVAL;
2237 return -1;
2238 }
2239
2240 fd = (int) l;
2241
2242 if ((long) fd != l) {
2243 closedir(d);
2244 errno = EINVAL;
2245 return -1;
2246 }
2247
2248 if (fd < 3)
2249 continue;
2250
2251 if (fd == dirfd(d))
2252 continue;
2253
2254 found = FALSE;
2255 for (i = 0; except_fds[i] >= 0; i++)
2256 if (except_fds[i] == fd) {
2257 found = TRUE;
2258 break;
2259 }
2260
2261 if (found)
2262 continue;
2263
2264 if (pa_close(fd) < 0) {
2265 saved_errno = errno;
2266 closedir(d);
2267 errno = saved_errno;
2268
2269 return -1;
2270 }
2271 }
2272
2273 closedir(d);
2274 return 0;
2275 }
2276
2277 #endif
2278
2279 if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
2280 return -1;
2281
2282 for (fd = 3; fd < (int) rl.rlim_max; fd++) {
2283 int i;
2284 pa_bool_t found;
2285
2286 found = FALSE;
2287 for (i = 0; except_fds[i] >= 0; i++)
2288 if (except_fds[i] == fd) {
2289 found = TRUE;
2290 break;
2291 }
2292
2293 if (found)
2294 continue;
2295
2296 if (pa_close(fd) < 0 && errno != EBADF)
2297 return -1;
2298 }
2299
2300 return 0;
2301 }
2302
2303 int pa_unblock_sigs(int except, ...) {
2304 va_list ap;
2305 unsigned n = 0, i;
2306 int r, *p;
2307
2308 va_start(ap, except);
2309
2310 if (except >= 1)
2311 for (n = 1; va_arg(ap, int) >= 0; n++)
2312 ;
2313
2314 va_end(ap);
2315
2316 p = pa_xnew(int, n+1);
2317
2318 va_start(ap, except);
2319
2320 i = 0;
2321 if (except >= 1) {
2322 int sig;
2323 p[i++] = except;
2324
2325 while ((sig = va_arg(ap, int)) >= 0)
2326 p[i++] = sig;
2327 }
2328 p[i] = -1;
2329
2330 va_end(ap);
2331
2332 r = pa_unblock_sigsv(p);
2333 pa_xfree(p);
2334
2335 return r;
2336 }
2337
2338 int pa_unblock_sigsv(const int except[]) {
2339 int i;
2340 sigset_t ss;
2341
2342 if (sigemptyset(&ss) < 0)
2343 return -1;
2344
2345 for (i = 0; except[i] > 0; i++)
2346 if (sigaddset(&ss, except[i]) < 0)
2347 return -1;
2348
2349 return sigprocmask(SIG_SETMASK, &ss, NULL);
2350 }
2351
2352 int pa_reset_sigs(int except, ...) {
2353 va_list ap;
2354 unsigned n = 0, i;
2355 int *p, r;
2356
2357 va_start(ap, except);
2358
2359 if (except >= 1)
2360 for (n = 1; va_arg(ap, int) >= 0; n++)
2361 ;
2362
2363 va_end(ap);
2364
2365 p = pa_xnew(int, n+1);
2366
2367 va_start(ap, except);
2368
2369 i = 0;
2370 if (except >= 1) {
2371 int sig;
2372 p[i++] = except;
2373
2374 while ((sig = va_arg(ap, int)) >= 0)
2375 sig = p[i++];
2376 }
2377 p[i] = -1;
2378
2379 va_end(ap);
2380
2381 r = pa_reset_sigsv(p);
2382 pa_xfree(p);
2383
2384 return r;
2385 }
2386
2387 int pa_reset_sigsv(const int except[]) {
2388 int sig;
2389
2390 for (sig = 1; sig < NSIG; sig++) {
2391 pa_bool_t reset = TRUE;
2392
2393 switch (sig) {
2394 case SIGKILL:
2395 case SIGSTOP:
2396 reset = FALSE;
2397 break;
2398
2399 default: {
2400 int i;
2401
2402 for (i = 0; except[i] > 0; i++) {
2403 if (sig == except[i]) {
2404 reset = FALSE;
2405 break;
2406 }
2407 }
2408 }
2409 }
2410
2411 if (reset) {
2412 struct sigaction sa;
2413
2414 memset(&sa, 0, sizeof(sa));
2415 sa.sa_handler = SIG_DFL;
2416
2417 /* On Linux the first two RT signals are reserved by
2418 * glibc, and sigaction() will return EINVAL for them. */
2419 if ((sigaction(sig, &sa, NULL) < 0))
2420 if (errno != EINVAL)
2421 return -1;
2422 }
2423 }
2424
2425 return 0;
2426 }
2427
2428 void pa_set_env(const char *key, const char *value) {
2429 pa_assert(key);
2430 pa_assert(value);
2431
2432 putenv(pa_sprintf_malloc("%s=%s", key, value));
2433 }
2434
2435 pa_bool_t pa_in_system_mode(void) {
2436 const char *e;
2437
2438 if (!(e = getenv("PULSE_SYSTEM")))
2439 return FALSE;
2440
2441 return !!atoi(e);
2442 }
2443
2444 char *pa_machine_id(void) {
2445 FILE *f;
2446 size_t l;
2447
2448 /* The returned value is supposed be some kind of ascii identifier
2449 * that is unique and stable across reboots. */
2450
2451 /* First we try the D-Bus UUID, which is the best option we have,
2452 * since it fits perfectly our needs and is not as volatile as the
2453 * hostname which might be set from dhcp. */
2454
2455 if ((f = fopen(PA_MACHINE_ID, "r"))) {
2456 char ln[34] = "", *r;
2457
2458 r = fgets(ln, sizeof(ln)-1, f);
2459 fclose(f);
2460
2461 pa_strip_nl(ln);
2462
2463 if (r && ln[0])
2464 return pa_xstrdup(ln);
2465 }
2466
2467 /* The we fall back to the host name. It supposed to be somewhat
2468 * unique, at least in a network, but may change. */
2469
2470 l = 100;
2471 for (;;) {
2472 char *c;
2473
2474 c = pa_xmalloc(l);
2475
2476 if (!pa_get_host_name(c, l)) {
2477
2478 if (errno != EINVAL && errno != ENAMETOOLONG)
2479 break;
2480
2481 } else if (strlen(c) < l-1) {
2482
2483 if (*c == 0) {
2484 pa_xfree(c);
2485 break;
2486 }
2487
2488 return c;
2489 }
2490
2491 /* Hmm, the hostname is as long the space we offered the
2492 * function, we cannot know if it fully fit in, so let's play
2493 * safe and retry. */
2494
2495 pa_xfree(c);
2496 l *= 2;
2497 }
2498
2499 /* If no hostname was set we use the POSIX hostid. It's usually
2500 * the IPv4 address. Mit not be that stable. */
2501 return pa_sprintf_malloc("%08lx", (unsigned long) gethostid);
2502 }
2503
2504 char *pa_uname_string(void) {
2505 struct utsname u;
2506
2507 pa_assert_se(uname(&u) == 0);
2508
2509 return pa_sprintf_malloc("%s %s %s %s", u.sysname, u.machine, u.release, u.version);
2510 }
2511
2512 #ifdef HAVE_VALGRIND_MEMCHECK_H
2513 pa_bool_t pa_in_valgrind(void) {
2514 static int b = 0;
2515
2516 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2517 * here instead of really checking whether we run in valgrind or
2518 * not. */
2519
2520 if (b < 1)
2521 b = getenv("VALGRIND") ? 2 : 1;
2522
2523 return b > 1;
2524 }
2525 #endif
2526
2527 unsigned pa_gcd(unsigned a, unsigned b) {
2528
2529 while (b > 0) {
2530 unsigned t = b;
2531 b = a % b;
2532 a = t;
2533 }
2534
2535 return a;
2536 }
2537
2538 void pa_reduce(unsigned *num, unsigned *den) {
2539
2540 unsigned gcd = pa_gcd(*num, *den);
2541
2542 if (gcd <= 0)
2543 return;
2544
2545 *num /= gcd;
2546 *den /= gcd;
2547
2548 pa_assert(pa_gcd(*num, *den) == 1);
2549 }
2550
2551 unsigned pa_ncpus(void) {
2552 long ncpus;
2553
2554 #ifdef _SC_NPROCESSORS_CONF
2555 ncpus = sysconf(_SC_NPROCESSORS_CONF);
2556 #else
2557 ncpus = 1;
2558 #endif
2559
2560 return ncpus <= 0 ? 1 : (unsigned) ncpus;
2561 }
2562
2563 char *pa_replace(const char*s, const char*a, const char *b) {
2564 pa_strbuf *sb;
2565 size_t an;
2566
2567 pa_assert(s);
2568 pa_assert(a);
2569 pa_assert(b);
2570
2571 an = strlen(a);
2572 sb = pa_strbuf_new();
2573
2574 for (;;) {
2575 const char *p;
2576
2577 if (!(p = strstr(s, a)))
2578 break;
2579
2580 pa_strbuf_putsn(sb, s, p-s);
2581 pa_strbuf_puts(sb, b);
2582 s = p + an;
2583 }
2584
2585 pa_strbuf_puts(sb, s);
2586
2587 return pa_strbuf_tostring_free(sb);
2588 }
2589
2590 char *pa_unescape(char *p) {
2591 char *s, *d;
2592 pa_bool_t escaped = FALSE;
2593
2594 for (s = p, d = p; *s; s++) {
2595 if (!escaped && *s == '\\') {
2596 escaped = TRUE;
2597 continue;
2598 }
2599
2600 *(d++) = *s;
2601 escaped = FALSE;
2602 }
2603
2604 *d = 0;
2605
2606 return p;
2607 }
2608
2609 char *pa_realpath(const char *path) {
2610 char *r, *t;
2611 pa_assert(path);
2612
2613 /* We want only abolsute paths */
2614 if (path[0] != '/') {
2615 errno = EINVAL;
2616 return NULL;
2617 }
2618
2619 #ifndef __GLIBC__
2620 #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."
2621 #endif
2622
2623 if (!(r = realpath(path, NULL)))
2624 return NULL;
2625
2626 /* We copy this here in case our pa_xmalloc() is not implemented
2627 * on top of libc malloc() */
2628 t = pa_xstrdup(r);
2629 pa_xfree(r);
2630
2631 return t;
2632 }