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