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