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