default: esd is obsolete, hence don't load it anymore by default
[pulseaudio-mirror.git] / src / pulsecore / core-util.c
blobf27f87aeab3fbc84b1ff5388ff33abc450d1ca40
1 /***
2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2004 Joe Marcus Clarke
6 Copyright 2006-2007 Pierre Ossman <ossman@cendio.se> for Cendio AB
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.
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.
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 ***/
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
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 <ctype.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <dirent.h>
42 #ifdef HAVE_LANGINFO_H
43 #include <langinfo.h>
44 #endif
46 #ifdef HAVE_UNAME
47 #include <sys/utsname.h>
48 #endif
50 #if defined(HAVE_REGEX_H)
51 #include <regex.h>
52 #elif defined(HAVE_PCREPOSIX_H)
53 #include <pcreposix.h>
54 #endif
56 #ifdef HAVE_STRTOF_L
57 #include <locale.h>
58 #endif
60 #ifdef HAVE_SCHED_H
61 #include <sched.h>
63 #if defined(__linux__) && !defined(SCHED_RESET_ON_FORK)
64 #define SCHED_RESET_ON_FORK 0x40000000
65 #endif
66 #endif
68 #ifdef HAVE_SYS_RESOURCE_H
69 #include <sys/resource.h>
70 #endif
72 #ifdef HAVE_SYS_CAPABILITY_H
73 #include <sys/capability.h>
74 #endif
76 #ifdef HAVE_SYS_MMAN_H
77 #include <sys/mman.h>
78 #endif
80 #ifdef HAVE_PTHREAD
81 #include <pthread.h>
82 #endif
84 #ifdef HAVE_NETDB_H
85 #include <netdb.h>
86 #endif
88 #ifdef HAVE_WINDOWS_H
89 #include <windows.h>
90 #endif
92 #ifndef ENOTSUP
93 #define ENOTSUP 135
94 #endif
96 #ifdef HAVE_PWD_H
97 #include <pwd.h>
98 #endif
100 #ifdef HAVE_GRP_H
101 #include <grp.h>
102 #endif
104 #ifdef HAVE_LIBSAMPLERATE
105 #include <samplerate.h>
106 #endif
108 #ifdef __APPLE__
109 #include <xlocale.h>
110 #include <mach/mach_init.h>
111 #include <mach/thread_act.h>
112 #include <mach/thread_policy.h>
113 #include <sys/sysctl.h>
114 #endif
116 #ifdef HAVE_DBUS
117 #include "rtkit.h"
118 #endif
120 #ifdef __linux__
121 #include <sys/personality.h>
122 #endif
124 #include <pulse/xmalloc.h>
125 #include <pulse/util.h>
126 #include <pulse/utf8.h>
128 #include <pulsecore/core-error.h>
129 #include <pulsecore/socket.h>
130 #include <pulsecore/log.h>
131 #include <pulsecore/macro.h>
132 #include <pulsecore/thread.h>
133 #include <pulsecore/strbuf.h>
134 #include <pulsecore/usergroup.h>
135 #include <pulsecore/strlist.h>
136 #include <pulsecore/cpu-x86.h>
137 #include <pulsecore/pipe.h>
139 #include "core-util.h"
141 /* Not all platforms have this */
142 #ifndef MSG_NOSIGNAL
143 #define MSG_NOSIGNAL 0
144 #endif
146 #define NEWLINE "\r\n"
147 #define WHITESPACE "\n\r \t"
149 static pa_strlist *recorded_env = NULL;
151 #ifdef OS_IS_WIN32
153 /* Returns the directory of the current DLL, with '/bin/' removed if it is the last component */
154 char *pa_win32_get_toplevel(HANDLE handle) {
155 static char *toplevel = NULL;
157 if (!toplevel) {
158 char library_path[MAX_PATH];
159 char *p;
161 if (!GetModuleFileName(handle, library_path, MAX_PATH))
162 return NULL;
164 toplevel = pa_xstrdup(library_path);
166 p = strrchr(toplevel, PA_PATH_SEP_CHAR);
167 if (p)
168 *p = '\0';
170 p = strrchr(toplevel, PA_PATH_SEP_CHAR);
171 if (p && (strcmp(p + 1, "bin") == 0))
172 *p = '\0';
175 return toplevel;
178 #endif
180 /** Make a file descriptor nonblock. Doesn't do any error checking */
181 void pa_make_fd_nonblock(int fd) {
183 #ifdef O_NONBLOCK
184 int v;
185 pa_assert(fd >= 0);
187 pa_assert_se((v = fcntl(fd, F_GETFL)) >= 0);
189 if (!(v & O_NONBLOCK))
190 pa_assert_se(fcntl(fd, F_SETFL, v|O_NONBLOCK) >= 0);
192 #elif defined(OS_IS_WIN32)
193 u_long arg = 1;
194 if (ioctlsocket(fd, FIONBIO, &arg) < 0) {
195 pa_assert_se(WSAGetLastError() == WSAENOTSOCK);
196 pa_log_warn("Only sockets can be made non-blocking!");
198 #else
199 pa_log_warn("Non-blocking I/O not supported.!");
200 #endif
204 /* Set the FD_CLOEXEC flag for a fd */
205 void pa_make_fd_cloexec(int fd) {
207 #ifdef FD_CLOEXEC
208 int v;
209 pa_assert(fd >= 0);
211 pa_assert_se((v = fcntl(fd, F_GETFD, 0)) >= 0);
213 if (!(v & FD_CLOEXEC))
214 pa_assert_se(fcntl(fd, F_SETFD, v|FD_CLOEXEC) >= 0);
215 #endif
219 /** Creates a directory securely */
220 int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid) {
221 struct stat st;
222 int r, saved_errno;
224 pa_assert(dir);
226 #ifdef OS_IS_WIN32
227 r = mkdir(dir);
228 #else
230 mode_t u;
231 u = umask((~m) & 0777);
232 r = mkdir(dir, m);
233 umask(u);
235 #endif
237 if (r < 0 && errno != EEXIST)
238 return -1;
240 #if defined(HAVE_FSTAT) && !defined(OS_IS_WIN32)
242 int fd;
243 if ((fd = open(dir,
244 #ifdef O_CLOEXEC
245 O_CLOEXEC|
246 #endif
247 #ifdef O_NOCTTY
248 O_NOCTTY|
249 #endif
250 #ifdef O_NOFOLLOW
251 O_NOFOLLOW|
252 #endif
253 O_RDONLY)) < 0)
254 goto fail;
256 if (fstat(fd, &st) < 0) {
257 pa_assert_se(pa_close(fd) >= 0);
258 goto fail;
261 if (!S_ISDIR(st.st_mode)) {
262 pa_assert_se(pa_close(fd) >= 0);
263 errno = EEXIST;
264 goto fail;
267 #ifdef HAVE_FCHOWN
268 if (uid == (uid_t) -1)
269 uid = getuid();
270 if (gid == (gid_t) -1)
271 gid = getgid();
272 if (fchown(fd, uid, gid) < 0)
273 goto fail;
274 #endif
276 #ifdef HAVE_FCHMOD
277 (void) fchmod(fd, m);
278 #endif
280 pa_assert_se(pa_close(fd) >= 0);
282 #endif
284 #ifdef HAVE_LSTAT
285 if (lstat(dir, &st) < 0)
286 #else
287 if (stat(dir, &st) < 0)
288 #endif
289 goto fail;
291 #ifndef OS_IS_WIN32
292 if (!S_ISDIR(st.st_mode) ||
293 (st.st_uid != uid) ||
294 (st.st_gid != gid) ||
295 ((st.st_mode & 0777) != m)) {
296 errno = EACCES;
297 goto fail;
299 #else
300 pa_log_warn("Secure directory creation not supported on Win32.");
301 #endif
303 return 0;
305 fail:
306 saved_errno = errno;
307 rmdir(dir);
308 errno = saved_errno;
310 return -1;
313 /* Return a newly allocated sting containing the parent directory of the specified file */
314 char *pa_parent_dir(const char *fn) {
315 char *slash, *dir = pa_xstrdup(fn);
317 if ((slash = (char*) pa_path_get_filename(dir)) == dir) {
318 pa_xfree(dir);
319 errno = ENOENT;
320 return NULL;
323 *(slash-1) = 0;
324 return dir;
327 /* Creates a the parent directory of the specified path securely */
328 int pa_make_secure_parent_dir(const char *fn, mode_t m, uid_t uid, gid_t gid) {
329 int ret = -1;
330 char *dir;
332 if (!(dir = pa_parent_dir(fn)))
333 goto finish;
335 if (pa_make_secure_dir(dir, m, uid, gid) < 0)
336 goto finish;
338 ret = 0;
340 finish:
341 pa_xfree(dir);
342 return ret;
345 /** Platform independent read function. Necessary since not all
346 * systems treat all file descriptors equal. If type is
347 * non-NULL it is used to cache the type of the fd. This is
348 * useful for making sure that only a single syscall is executed per
349 * function call. The variable pointed to should be initialized to 0
350 * by the caller. */
351 ssize_t pa_read(int fd, void *buf, size_t count, int *type) {
353 #ifdef OS_IS_WIN32
355 if (!type || *type == 0) {
356 ssize_t r;
358 if ((r = recv(fd, buf, count, 0)) >= 0)
359 return r;
361 if (WSAGetLastError() != WSAENOTSOCK) {
362 errno = WSAGetLastError();
363 return r;
366 if (type)
367 *type = 1;
370 #endif
372 for (;;) {
373 ssize_t r;
375 if ((r = read(fd, buf, count)) < 0)
376 if (errno == EINTR)
377 continue;
379 return r;
383 /** Similar to pa_read(), but handles writes */
384 ssize_t pa_write(int fd, const void *buf, size_t count, int *type) {
386 if (!type || *type == 0) {
387 ssize_t r;
389 for (;;) {
390 if ((r = send(fd, buf, count, MSG_NOSIGNAL)) < 0) {
392 if (errno == EINTR)
393 continue;
395 break;
398 return r;
401 #ifdef OS_IS_WIN32
402 if (WSAGetLastError() != WSAENOTSOCK) {
403 errno = WSAGetLastError();
404 return r;
406 #else
407 if (errno != ENOTSOCK)
408 return r;
409 #endif
411 if (type)
412 *type = 1;
415 for (;;) {
416 ssize_t r;
418 if ((r = write(fd, buf, count)) < 0)
419 if (errno == EINTR)
420 continue;
422 return r;
426 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
427 * unless EOF is reached or an error occurred */
428 ssize_t pa_loop_read(int fd, void*data, size_t size, int *type) {
429 ssize_t ret = 0;
430 int _type;
432 pa_assert(fd >= 0);
433 pa_assert(data);
434 pa_assert(size);
436 if (!type) {
437 _type = 0;
438 type = &_type;
441 while (size > 0) {
442 ssize_t r;
444 if ((r = pa_read(fd, data, size, type)) < 0)
445 return r;
447 if (r == 0)
448 break;
450 ret += r;
451 data = (uint8_t*) data + r;
452 size -= (size_t) r;
455 return ret;
458 /** Similar to pa_loop_read(), but wraps write() */
459 ssize_t pa_loop_write(int fd, const void*data, size_t size, int *type) {
460 ssize_t ret = 0;
461 int _type;
463 pa_assert(fd >= 0);
464 pa_assert(data);
465 pa_assert(size);
467 if (!type) {
468 _type = 0;
469 type = &_type;
472 while (size > 0) {
473 ssize_t r;
475 if ((r = pa_write(fd, data, size, type)) < 0)
476 return r;
478 if (r == 0)
479 break;
481 ret += r;
482 data = (const uint8_t*) data + r;
483 size -= (size_t) r;
486 return ret;
489 /** Platform independent read function. Necessary since not all
490 * systems treat all file descriptors equal. */
491 int pa_close(int fd) {
493 #ifdef OS_IS_WIN32
494 int ret;
496 if ((ret = closesocket(fd)) == 0)
497 return 0;
499 if (WSAGetLastError() != WSAENOTSOCK) {
500 errno = WSAGetLastError();
501 return ret;
503 #endif
505 for (;;) {
506 int r;
508 if ((r = close(fd)) < 0)
509 if (errno == EINTR)
510 continue;
512 return r;
516 /* Print a warning messages in case that the given signal is not
517 * blocked or trapped */
518 void pa_check_signal_is_blocked(int sig) {
519 #ifdef HAVE_SIGACTION
520 struct sigaction sa;
521 sigset_t set;
523 /* If POSIX threads are supported use thread-aware
524 * pthread_sigmask() function, to check if the signal is
525 * blocked. Otherwise fall back to sigprocmask() */
527 #ifdef HAVE_PTHREAD
528 if (pthread_sigmask(SIG_SETMASK, NULL, &set) < 0) {
529 #endif
530 if (sigprocmask(SIG_SETMASK, NULL, &set) < 0) {
531 pa_log("sigprocmask(): %s", pa_cstrerror(errno));
532 return;
534 #ifdef HAVE_PTHREAD
536 #endif
538 if (sigismember(&set, sig))
539 return;
541 /* Check whether the signal is trapped */
543 if (sigaction(sig, NULL, &sa) < 0) {
544 pa_log("sigaction(): %s", pa_cstrerror(errno));
545 return;
548 if (sa.sa_handler != SIG_DFL)
549 return;
551 pa_log_warn("%s is not trapped. This might cause malfunction!", pa_sig2str(sig));
552 #else /* HAVE_SIGACTION */
553 pa_log_warn("%s might not be trapped. This might cause malfunction!", pa_sig2str(sig));
554 #endif
557 /* The following function is based on an example from the GNU libc
558 * documentation. This function is similar to GNU's asprintf(). */
559 char *pa_sprintf_malloc(const char *format, ...) {
560 size_t size = 100;
561 char *c = NULL;
563 pa_assert(format);
565 for(;;) {
566 int r;
567 va_list ap;
569 c = pa_xrealloc(c, size);
571 va_start(ap, format);
572 r = vsnprintf(c, size, format, ap);
573 va_end(ap);
575 c[size-1] = 0;
577 if (r > -1 && (size_t) r < size)
578 return c;
580 if (r > -1) /* glibc 2.1 */
581 size = (size_t) r+1;
582 else /* glibc 2.0 */
583 size *= 2;
587 /* Same as the previous function, but use a va_list instead of an
588 * ellipsis */
589 char *pa_vsprintf_malloc(const char *format, va_list ap) {
590 size_t size = 100;
591 char *c = NULL;
593 pa_assert(format);
595 for(;;) {
596 int r;
597 va_list aq;
599 c = pa_xrealloc(c, size);
601 va_copy(aq, ap);
602 r = vsnprintf(c, size, format, aq);
603 va_end(aq);
605 c[size-1] = 0;
607 if (r > -1 && (size_t) r < size)
608 return c;
610 if (r > -1) /* glibc 2.1 */
611 size = (size_t) r+1;
612 else /* glibc 2.0 */
613 size *= 2;
617 /* Similar to OpenBSD's strlcpy() function */
618 char *pa_strlcpy(char *b, const char *s, size_t l) {
619 size_t k;
621 pa_assert(b);
622 pa_assert(s);
623 pa_assert(l > 0);
625 k = strlen(s);
627 if (k > l-1)
628 k = l-1;
630 memcpy(b, s, k);
631 b[k] = 0;
633 return b;
636 #ifdef _POSIX_PRIORITY_SCHEDULING
637 static int set_scheduler(int rtprio) {
638 #ifdef HAVE_SCHED_H
639 struct sched_param sp;
640 #ifdef HAVE_DBUS
641 int r;
642 DBusError error;
643 DBusConnection *bus;
645 dbus_error_init(&error);
646 #endif
648 pa_zero(sp);
649 sp.sched_priority = rtprio;
651 #ifdef SCHED_RESET_ON_FORK
652 if (pthread_setschedparam(pthread_self(), SCHED_RR|SCHED_RESET_ON_FORK, &sp) == 0) {
653 pa_log_debug("SCHED_RR|SCHED_RESET_ON_FORK worked.");
654 return 0;
656 #endif
658 if (pthread_setschedparam(pthread_self(), SCHED_RR, &sp) == 0) {
659 pa_log_debug("SCHED_RR worked.");
660 return 0;
662 #endif /* HAVE_SCHED_H */
664 #ifdef HAVE_DBUS
665 /* Try to talk to RealtimeKit */
667 if (!(bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error))) {
668 pa_log("Failed to connect to system bus: %s\n", error.message);
669 dbus_error_free(&error);
670 errno = -EIO;
671 return -1;
674 /* We need to disable exit on disconnect because otherwise
675 * dbus_shutdown will kill us. See
676 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
677 dbus_connection_set_exit_on_disconnect(bus, FALSE);
679 r = rtkit_make_realtime(bus, 0, rtprio);
680 dbus_connection_close(bus);
681 dbus_connection_unref(bus);
683 if (r >= 0) {
684 pa_log_debug("RealtimeKit worked.");
685 return 0;
688 errno = -r;
689 #else
690 errno = 0;
691 #endif
693 return -1;
695 #endif
697 /* Make the current thread a realtime thread, and acquire the highest
698 * rtprio we can get that is less or equal the specified parameter. If
699 * the thread is already realtime, don't do anything. */
700 int pa_make_realtime(int rtprio) {
702 #if defined(OS_IS_DARWIN)
703 struct thread_time_constraint_policy ttcpolicy;
704 uint64_t freq = 0;
705 size_t size = sizeof(freq);
706 int ret;
708 ret = sysctlbyname("hw.cpufrequency", &freq, &size, NULL, 0);
709 if (ret < 0) {
710 pa_log_info("Unable to read CPU frequency, acquisition of real-time scheduling failed.");
711 return -1;
714 pa_log_debug("sysctl for hw.cpufrequency: %llu", freq);
716 /* See http://developer.apple.com/library/mac/#documentation/Darwin/Conceptual/KernelProgramming/scheduler/scheduler.html */
717 ttcpolicy.period = freq / 160;
718 ttcpolicy.computation = freq / 3300;
719 ttcpolicy.constraint = freq / 2200;
720 ttcpolicy.preemptible = 1;
722 ret = thread_policy_set(mach_thread_self(),
723 THREAD_TIME_CONSTRAINT_POLICY,
724 (thread_policy_t) &ttcpolicy,
725 THREAD_TIME_CONSTRAINT_POLICY_COUNT);
726 if (ret) {
727 pa_log_info("Unable to set real-time thread priority (%08x).", ret);
728 return -1;
731 pa_log_info("Successfully acquired real-time thread priority.");
732 return 0;
734 #elif defined(_POSIX_PRIORITY_SCHEDULING)
735 int p;
737 if (set_scheduler(rtprio) >= 0) {
738 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i.", rtprio);
739 return 0;
742 for (p = rtprio-1; p >= 1; p--)
743 if (set_scheduler(p) >= 0) {
744 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i.", p, rtprio);
745 return 0;
747 #elif defined(OS_IS_WIN32)
748 /* Windows only allows realtime scheduling to be set on a per process basis.
749 * Therefore, instead of making the thread realtime, just give it the highest non-realtime priority. */
750 if (SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL)) {
751 pa_log_info("Successfully enabled THREAD_PRIORITY_TIME_CRITICAL scheduling for thread.");
752 return 0;
755 pa_log_warn("SetThreadPriority() failed: 0x%08X", GetLastError());
756 errno = EPERM;
757 #else
758 errno = ENOTSUP;
759 #endif
760 pa_log_info("Failed to acquire real-time scheduling: %s", pa_cstrerror(errno));
761 return -1;
764 #ifdef HAVE_SYS_RESOURCE_H
765 static int set_nice(int nice_level) {
766 #ifdef HAVE_DBUS
767 DBusError error;
768 DBusConnection *bus;
769 int r;
771 dbus_error_init(&error);
772 #endif
774 #ifdef HAVE_SYS_RESOURCE_H
775 if (setpriority(PRIO_PROCESS, 0, nice_level) >= 0) {
776 pa_log_debug("setpriority() worked.");
777 return 0;
779 #endif
781 #ifdef HAVE_DBUS
782 /* Try to talk to RealtimeKit */
784 if (!(bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
785 pa_log("Failed to connect to system bus: %s\n", error.message);
786 dbus_error_free(&error);
787 errno = -EIO;
788 return -1;
791 /* We need to disable exit on disconnect because otherwise
792 * dbus_shutdown will kill us. See
793 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
794 dbus_connection_set_exit_on_disconnect(bus, FALSE);
796 r = rtkit_make_high_priority(bus, 0, nice_level);
797 dbus_connection_unref(bus);
799 if (r >= 0) {
800 pa_log_debug("RealtimeKit worked.");
801 return 0;
804 errno = -r;
805 #endif
807 return -1;
809 #endif
811 /* Raise the priority of the current process as much as possible that
812 * is <= the specified nice level..*/
813 int pa_raise_priority(int nice_level) {
815 #ifdef HAVE_SYS_RESOURCE_H
816 int n;
818 if (set_nice(nice_level) >= 0) {
819 pa_log_info("Successfully gained nice level %i.", nice_level);
820 return 0;
823 for (n = nice_level+1; n < 0; n++)
824 if (set_nice(n) >= 0) {
825 pa_log_info("Successfully acquired nice level %i, which is lower than the requested %i.", n, nice_level);
826 return 0;
829 pa_log_info("Failed to acquire high-priority scheduling: %s", pa_cstrerror(errno));
830 return -1;
831 #endif
833 #ifdef OS_IS_WIN32
834 if (nice_level < 0) {
835 if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS)) {
836 pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError());
837 errno = EPERM;
838 return -1;
841 pa_log_info("Successfully gained high priority class.");
843 #endif
845 return 0;
848 /* Reset the priority to normal, inverting the changes made by
849 * pa_raise_priority() and pa_make_realtime()*/
850 void pa_reset_priority(void) {
851 #ifdef HAVE_SYS_RESOURCE_H
852 struct sched_param sp;
854 setpriority(PRIO_PROCESS, 0, 0);
856 pa_zero(sp);
857 pthread_setschedparam(pthread_self(), SCHED_OTHER, &sp);
858 #endif
860 #ifdef OS_IS_WIN32
861 SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
862 #endif
865 int pa_match(const char *expr, const char *v) {
866 int k;
867 regex_t re;
868 int r;
870 if (regcomp(&re, expr, REG_NOSUB|REG_EXTENDED) != 0) {
871 errno = EINVAL;
872 return -1;
875 if ((k = regexec(&re, v, 0, NULL, 0)) == 0)
876 r = 1;
877 else if (k == REG_NOMATCH)
878 r = 0;
879 else
880 r = -1;
882 regfree(&re);
884 if (r < 0)
885 errno = EINVAL;
887 return r;
890 /* Try to parse a boolean string value.*/
891 int pa_parse_boolean(const char *v) {
892 pa_assert(v);
894 /* First we check language independant */
895 if (!strcmp(v, "1") || v[0] == 'y' || v[0] == 'Y' || v[0] == 't' || v[0] == 'T' || !strcasecmp(v, "on"))
896 return 1;
897 else if (!strcmp(v, "0") || v[0] == 'n' || v[0] == 'N' || v[0] == 'f' || v[0] == 'F' || !strcasecmp(v, "off"))
898 return 0;
900 #ifdef HAVE_LANGINFO_H
902 const char *expr;
903 /* And then we check language dependant */
904 if ((expr = nl_langinfo(YESEXPR)))
905 if (expr[0])
906 if (pa_match(expr, v) > 0)
907 return 1;
909 if ((expr = nl_langinfo(NOEXPR)))
910 if (expr[0])
911 if (pa_match(expr, v) > 0)
912 return 0;
914 #endif
916 errno = EINVAL;
917 return -1;
920 /* Split the specified string wherever one of the strings in delimiter
921 * occurs. Each time it is called returns a newly allocated string
922 * with pa_xmalloc(). The variable state points to, should be
923 * initiallized to NULL before the first call. */
924 char *pa_split(const char *c, const char *delimiter, const char**state) {
925 const char *current = *state ? *state : c;
926 size_t l;
928 if (!*current)
929 return NULL;
931 l = strcspn(current, delimiter);
932 *state = current+l;
934 if (**state)
935 (*state)++;
937 return pa_xstrndup(current, l);
940 /* Split a string into words. Otherwise similar to pa_split(). */
941 char *pa_split_spaces(const char *c, const char **state) {
942 const char *current = *state ? *state : c;
943 size_t l;
945 if (!*current || *c == 0)
946 return NULL;
948 current += strspn(current, WHITESPACE);
949 l = strcspn(current, WHITESPACE);
951 *state = current+l;
953 return pa_xstrndup(current, l);
956 PA_STATIC_TLS_DECLARE(signame, pa_xfree);
958 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
959 const char *pa_sig2str(int sig) {
960 char *t;
962 if (sig <= 0)
963 goto fail;
965 #ifdef NSIG
966 if (sig >= NSIG)
967 goto fail;
968 #endif
970 #ifdef HAVE_SIG2STR
972 char buf[SIG2STR_MAX];
974 if (sig2str(sig, buf) == 0) {
975 pa_xfree(PA_STATIC_TLS_GET(signame));
976 t = pa_sprintf_malloc("SIG%s", buf);
977 PA_STATIC_TLS_SET(signame, t);
978 return t;
981 #else
983 switch (sig) {
984 #ifdef SIGHUP
985 case SIGHUP: return "SIGHUP";
986 #endif
987 case SIGINT: return "SIGINT";
988 #ifdef SIGQUIT
989 case SIGQUIT: return "SIGQUIT";
990 #endif
991 case SIGILL: return "SIGULL";
992 #ifdef SIGTRAP
993 case SIGTRAP: return "SIGTRAP";
994 #endif
995 case SIGABRT: return "SIGABRT";
996 #ifdef SIGBUS
997 case SIGBUS: return "SIGBUS";
998 #endif
999 case SIGFPE: return "SIGFPE";
1000 #ifdef SIGKILL
1001 case SIGKILL: return "SIGKILL";
1002 #endif
1003 #ifdef SIGUSR1
1004 case SIGUSR1: return "SIGUSR1";
1005 #endif
1006 case SIGSEGV: return "SIGSEGV";
1007 #ifdef SIGUSR2
1008 case SIGUSR2: return "SIGUSR2";
1009 #endif
1010 #ifdef SIGPIPE
1011 case SIGPIPE: return "SIGPIPE";
1012 #endif
1013 #ifdef SIGALRM
1014 case SIGALRM: return "SIGALRM";
1015 #endif
1016 case SIGTERM: return "SIGTERM";
1017 #ifdef SIGSTKFLT
1018 case SIGSTKFLT: return "SIGSTKFLT";
1019 #endif
1020 #ifdef SIGCHLD
1021 case SIGCHLD: return "SIGCHLD";
1022 #endif
1023 #ifdef SIGCONT
1024 case SIGCONT: return "SIGCONT";
1025 #endif
1026 #ifdef SIGSTOP
1027 case SIGSTOP: return "SIGSTOP";
1028 #endif
1029 #ifdef SIGTSTP
1030 case SIGTSTP: return "SIGTSTP";
1031 #endif
1032 #ifdef SIGTTIN
1033 case SIGTTIN: return "SIGTTIN";
1034 #endif
1035 #ifdef SIGTTOU
1036 case SIGTTOU: return "SIGTTOU";
1037 #endif
1038 #ifdef SIGURG
1039 case SIGURG: return "SIGURG";
1040 #endif
1041 #ifdef SIGXCPU
1042 case SIGXCPU: return "SIGXCPU";
1043 #endif
1044 #ifdef SIGXFSZ
1045 case SIGXFSZ: return "SIGXFSZ";
1046 #endif
1047 #ifdef SIGVTALRM
1048 case SIGVTALRM: return "SIGVTALRM";
1049 #endif
1050 #ifdef SIGPROF
1051 case SIGPROF: return "SIGPROF";
1052 #endif
1053 #ifdef SIGWINCH
1054 case SIGWINCH: return "SIGWINCH";
1055 #endif
1056 #ifdef SIGIO
1057 case SIGIO: return "SIGIO";
1058 #endif
1059 #ifdef SIGPWR
1060 case SIGPWR: return "SIGPWR";
1061 #endif
1062 #ifdef SIGSYS
1063 case SIGSYS: return "SIGSYS";
1064 #endif
1067 #ifdef SIGRTMIN
1068 if (sig >= SIGRTMIN && sig <= SIGRTMAX) {
1069 pa_xfree(PA_STATIC_TLS_GET(signame));
1070 t = pa_sprintf_malloc("SIGRTMIN+%i", sig - SIGRTMIN);
1071 PA_STATIC_TLS_SET(signame, t);
1072 return t;
1074 #endif
1076 #endif
1078 fail:
1080 pa_xfree(PA_STATIC_TLS_GET(signame));
1081 t = pa_sprintf_malloc("SIG%i", sig);
1082 PA_STATIC_TLS_SET(signame, t);
1083 return t;
1086 #ifdef HAVE_GRP_H
1088 /* Check whether the specified GID and the group name match */
1089 static int is_group(gid_t gid, const char *name) {
1090 struct group *group = NULL;
1091 int r = -1;
1093 errno = 0;
1094 if (!(group = pa_getgrgid_malloc(gid))) {
1095 if (!errno)
1096 errno = ENOENT;
1098 pa_log("pa_getgrgid_malloc(%u): %s", gid, pa_cstrerror(errno));
1100 goto finish;
1103 r = strcmp(name, group->gr_name) == 0;
1105 finish:
1106 pa_getgrgid_free(group);
1108 return r;
1111 /* Check the current user is member of the specified group */
1112 int pa_own_uid_in_group(const char *name, gid_t *gid) {
1113 GETGROUPS_T *gids, tgid;
1114 long n = sysconf(_SC_NGROUPS_MAX);
1115 int r = -1, i, k;
1117 pa_assert(n > 0);
1119 gids = pa_xmalloc(sizeof(GETGROUPS_T) * (size_t) n);
1121 if ((n = getgroups((int) n, gids)) < 0) {
1122 pa_log("getgroups(): %s", pa_cstrerror(errno));
1123 goto finish;
1126 for (i = 0; i < n; i++) {
1128 if ((k = is_group(gids[i], name)) < 0)
1129 goto finish;
1130 else if (k > 0) {
1131 *gid = gids[i];
1132 r = 1;
1133 goto finish;
1137 if ((k = is_group(tgid = getgid(), name)) < 0)
1138 goto finish;
1139 else if (k > 0) {
1140 *gid = tgid;
1141 r = 1;
1142 goto finish;
1145 r = 0;
1147 finish:
1149 pa_xfree(gids);
1150 return r;
1153 /* Check whether the specifc user id is a member of the specified group */
1154 int pa_uid_in_group(uid_t uid, const char *name) {
1155 struct group *group = NULL;
1156 char **i;
1157 int r = -1;
1159 errno = 0;
1160 if (!(group = pa_getgrnam_malloc(name))) {
1161 if (!errno)
1162 errno = ENOENT;
1163 goto finish;
1166 r = 0;
1167 for (i = group->gr_mem; *i; i++) {
1168 struct passwd *pw = NULL;
1170 errno = 0;
1171 if (!(pw = pa_getpwnam_malloc(*i)))
1172 continue;
1174 if (pw->pw_uid == uid)
1175 r = 1;
1177 pa_getpwnam_free(pw);
1179 if (r == 1)
1180 break;
1183 finish:
1184 pa_getgrnam_free(group);
1186 return r;
1189 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
1190 gid_t pa_get_gid_of_group(const char *name) {
1191 gid_t ret = (gid_t) -1;
1192 struct group *gr = NULL;
1194 errno = 0;
1195 if (!(gr = pa_getgrnam_malloc(name))) {
1196 if (!errno)
1197 errno = ENOENT;
1198 goto finish;
1201 ret = gr->gr_gid;
1203 finish:
1204 pa_getgrnam_free(gr);
1205 return ret;
1208 int pa_check_in_group(gid_t g) {
1209 gid_t gids[NGROUPS_MAX];
1210 int r;
1212 if ((r = getgroups(NGROUPS_MAX, gids)) < 0)
1213 return -1;
1215 for (; r > 0; r--)
1216 if (gids[r-1] == g)
1217 return 1;
1219 return 0;
1222 #else /* HAVE_GRP_H */
1224 int pa_own_uid_in_group(const char *name, gid_t *gid) {
1225 errno = ENOTSUP;
1226 return -1;
1230 int pa_uid_in_group(uid_t uid, const char *name) {
1231 errno = ENOTSUP;
1232 return -1;
1235 gid_t pa_get_gid_of_group(const char *name) {
1236 errno = ENOTSUP;
1237 return (gid_t) -1;
1240 int pa_check_in_group(gid_t g) {
1241 errno = ENOTSUP;
1242 return -1;
1245 #endif
1247 /* Lock or unlock a file entirely.
1248 (advisory on UNIX, mandatory on Windows) */
1249 int pa_lock_fd(int fd, int b) {
1250 #ifdef F_SETLKW
1251 struct flock f_lock;
1253 /* Try a R/W lock first */
1255 f_lock.l_type = (short) (b ? F_WRLCK : F_UNLCK);
1256 f_lock.l_whence = SEEK_SET;
1257 f_lock.l_start = 0;
1258 f_lock.l_len = 0;
1260 if (fcntl(fd, F_SETLKW, &f_lock) >= 0)
1261 return 0;
1263 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1264 if (b && errno == EBADF) {
1265 f_lock.l_type = F_RDLCK;
1266 if (fcntl(fd, F_SETLKW, &f_lock) >= 0)
1267 return 0;
1270 pa_log("%slock: %s", !b ? "un" : "", pa_cstrerror(errno));
1271 #endif
1273 #ifdef OS_IS_WIN32
1274 HANDLE h = (HANDLE) _get_osfhandle(fd);
1276 if (b && LockFile(h, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1277 return 0;
1278 if (!b && UnlockFile(h, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1279 return 0;
1281 pa_log("%slock failed: 0x%08X", !b ? "un" : "", GetLastError());
1283 /* FIXME: Needs to set errno! */
1284 #endif
1286 return -1;
1289 /* Remove trailing newlines from a string */
1290 char* pa_strip_nl(char *s) {
1291 pa_assert(s);
1293 s[strcspn(s, NEWLINE)] = 0;
1294 return s;
1297 char *pa_strip(char *s) {
1298 char *e, *l = NULL;
1300 /* Drops trailing whitespace. Modifies the string in
1301 * place. Returns pointer to first non-space character */
1303 s += strspn(s, WHITESPACE);
1305 for (e = s; *e; e++)
1306 if (!strchr(WHITESPACE, *e))
1307 l = e;
1309 if (l)
1310 *(l+1) = 0;
1311 else
1312 *s = 0;
1314 return s;
1317 /* Create a temporary lock file and lock it. */
1318 int pa_lock_lockfile(const char *fn) {
1319 int fd;
1320 pa_assert(fn);
1322 for (;;) {
1323 struct stat st;
1325 if ((fd = pa_open_cloexec(fn, O_CREAT|O_RDWR
1326 #ifdef O_NOFOLLOW
1327 |O_NOFOLLOW
1328 #endif
1329 , S_IRUSR|S_IWUSR)) < 0) {
1330 pa_log_warn("Failed to create lock file '%s': %s", fn, pa_cstrerror(errno));
1331 goto fail;
1334 if (pa_lock_fd(fd, 1) < 0) {
1335 pa_log_warn("Failed to lock file '%s'.", fn);
1336 goto fail;
1339 if (fstat(fd, &st) < 0) {
1340 pa_log_warn("Failed to fstat() file '%s': %s", fn, pa_cstrerror(errno));
1341 goto fail;
1344 /* Check whether the file has been removed meanwhile. When yes,
1345 * restart this loop, otherwise, we're done */
1346 if (st.st_nlink >= 1)
1347 break;
1349 if (pa_lock_fd(fd, 0) < 0) {
1350 pa_log_warn("Failed to unlock file '%s'.", fn);
1351 goto fail;
1354 if (pa_close(fd) < 0) {
1355 pa_log_warn("Failed to close file '%s': %s", fn, pa_cstrerror(errno));
1356 fd = -1;
1357 goto fail;
1361 return fd;
1363 fail:
1365 if (fd >= 0) {
1366 int saved_errno = errno;
1367 pa_close(fd);
1368 errno = saved_errno;
1371 return -1;
1374 /* Unlock a temporary lcok file */
1375 int pa_unlock_lockfile(const char *fn, int fd) {
1376 int r = 0;
1377 pa_assert(fd >= 0);
1379 if (fn) {
1380 if (unlink(fn) < 0) {
1381 pa_log_warn("Unable to remove lock file '%s': %s", fn, pa_cstrerror(errno));
1382 r = -1;
1386 if (pa_lock_fd(fd, 0) < 0) {
1387 pa_log_warn("Failed to unlock file '%s'.", fn);
1388 r = -1;
1391 if (pa_close(fd) < 0) {
1392 pa_log_warn("Failed to close '%s': %s", fn, pa_cstrerror(errno));
1393 r = -1;
1396 return r;
1399 static char *get_pulse_home(void) {
1400 char *h;
1401 struct stat st;
1402 char *ret = NULL;
1404 if (!(h = pa_get_home_dir_malloc())) {
1405 pa_log_error("Failed to get home directory.");
1406 return NULL;
1409 if (stat(h, &st) < 0) {
1410 pa_log_error("Failed to stat home directory %s: %s", h, pa_cstrerror(errno));
1411 goto finish;
1414 #ifdef HAVE_GETUID
1415 if (st.st_uid != getuid()) {
1416 pa_log_error("Home directory %s not ours.", h);
1417 errno = EACCES;
1418 goto finish;
1420 #endif
1422 ret = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse", h);
1424 finish:
1425 pa_xfree(h);
1427 return ret;
1430 char *pa_get_state_dir(void) {
1431 char *d;
1433 /* The state directory shall contain dynamic data that should be
1434 * kept across reboots, and is private to this user */
1436 if (!(d = pa_xstrdup(getenv("PULSE_STATE_PATH"))))
1437 if (!(d = get_pulse_home()))
1438 return NULL;
1440 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1441 * dir then this will break. */
1443 if (pa_make_secure_dir(d, 0700U, (uid_t) -1, (gid_t) -1) < 0) {
1444 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1445 pa_xfree(d);
1446 return NULL;
1449 return d;
1452 char *pa_get_home_dir_malloc(void) {
1453 char *homedir;
1454 size_t allocated = 128;
1456 for (;;) {
1457 homedir = pa_xmalloc(allocated);
1459 if (!pa_get_home_dir(homedir, allocated)) {
1460 pa_xfree(homedir);
1461 return NULL;
1464 if (strlen(homedir) < allocated - 1)
1465 break;
1467 pa_xfree(homedir);
1468 allocated *= 2;
1471 return homedir;
1474 char *pa_get_binary_name_malloc(void) {
1475 char *t;
1476 size_t allocated = 128;
1478 for (;;) {
1479 t = pa_xmalloc(allocated);
1481 if (!pa_get_binary_name(t, allocated)) {
1482 pa_xfree(t);
1483 return NULL;
1486 if (strlen(t) < allocated - 1)
1487 break;
1489 pa_xfree(t);
1490 allocated *= 2;
1493 return t;
1496 static char* make_random_dir(mode_t m) {
1497 static const char table[] =
1498 "abcdefghijklmnopqrstuvwxyz"
1499 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1500 "0123456789";
1502 char *fn;
1503 size_t pathlen;
1505 fn = pa_sprintf_malloc("%s" PA_PATH_SEP "pulse-XXXXXXXXXXXX", pa_get_temp_dir());
1506 pathlen = strlen(fn);
1508 for (;;) {
1509 size_t i;
1510 int r;
1511 mode_t u;
1512 int saved_errno;
1514 for (i = pathlen - 12; i < pathlen; i++)
1515 fn[i] = table[rand() % (sizeof(table)-1)];
1517 u = umask((~m) & 0777);
1518 #ifndef OS_IS_WIN32
1519 r = mkdir(fn, m);
1520 #else
1521 r = mkdir(fn);
1522 #endif
1524 saved_errno = errno;
1525 umask(u);
1526 errno = saved_errno;
1528 if (r >= 0)
1529 return fn;
1531 if (errno != EEXIST) {
1532 pa_log_error("Failed to create random directory %s: %s", fn, pa_cstrerror(errno));
1533 pa_xfree(fn);
1534 return NULL;
1539 static int make_random_dir_and_link(mode_t m, const char *k) {
1540 char *p;
1542 if (!(p = make_random_dir(m)))
1543 return -1;
1545 #ifdef HAVE_SYMLINK
1546 if (symlink(p, k) < 0) {
1547 int saved_errno = errno;
1549 if (errno != EEXIST)
1550 pa_log_error("Failed to symlink %s to %s: %s", k, p, pa_cstrerror(errno));
1552 rmdir(p);
1553 pa_xfree(p);
1555 errno = saved_errno;
1556 return -1;
1558 #else
1559 pa_xfree(p);
1560 return -1;
1561 #endif
1563 pa_xfree(p);
1564 return 0;
1567 char *pa_get_runtime_dir(void) {
1568 char *d, *k = NULL, *p = NULL, *t = NULL, *mid;
1569 mode_t m;
1571 /* The runtime directory shall contain dynamic data that needs NOT
1572 * to be kept accross reboots and is usuallly private to the user,
1573 * except in system mode, where it might be accessible by other
1574 * users, too. Since we need POSIX locking and UNIX sockets in
1575 * this directory, we link it to a random subdir in /tmp, if it
1576 * was not explicitly configured. */
1578 m = pa_in_system_mode() ? 0755U : 0700U;
1580 if ((d = getenv("PULSE_RUNTIME_PATH"))) {
1582 if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0) {
1583 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1584 goto fail;
1587 return pa_xstrdup(d);
1590 if (!(d = get_pulse_home()))
1591 goto fail;
1593 if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0) {
1594 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1595 pa_xfree(d);
1596 goto fail;
1599 if (!(mid = pa_machine_id())) {
1600 pa_xfree(d);
1601 goto fail;
1604 k = pa_sprintf_malloc("%s" PA_PATH_SEP "%s-runtime", d, mid);
1605 pa_xfree(d);
1606 pa_xfree(mid);
1608 for (;;) {
1609 /* OK, first let's check if the "runtime" symlink is already
1610 * existant */
1612 if (!(p = pa_readlink(k))) {
1614 if (errno != ENOENT) {
1615 pa_log_error("Failed to stat runtime directory %s: %s", k, pa_cstrerror(errno));
1616 goto fail;
1619 #ifdef HAVE_SYMLINK
1620 /* Hmm, so the runtime directory didn't exist yet, so let's
1621 * create one in /tmp and symlink that to it */
1623 if (make_random_dir_and_link(0700, k) < 0) {
1625 /* Mhmm, maybe another process was quicker than us,
1626 * let's check if that was valid */
1627 if (errno == EEXIST)
1628 continue;
1630 goto fail;
1632 #else
1633 /* No symlink possible, so let's just create the runtime directly */
1634 if (!mkdir(k))
1635 goto fail;
1636 #endif
1638 return k;
1641 /* Make sure that this actually makes sense */
1642 if (!pa_is_path_absolute(p)) {
1643 pa_log_error("Path %s in link %s is not absolute.", p, k);
1644 errno = ENOENT;
1645 goto fail;
1648 /* Hmm, so this symlink is still around, make sure nobody fools us */
1649 #ifdef HAVE_LSTAT
1651 struct stat st;
1652 if (lstat(p, &st) < 0) {
1654 if (errno != ENOENT) {
1655 pa_log_error("Failed to stat runtime directory %s: %s", p, pa_cstrerror(errno));
1656 goto fail;
1659 } else {
1661 if (S_ISDIR(st.st_mode) &&
1662 (st.st_uid == getuid()) &&
1663 ((st.st_mode & 0777) == 0700)) {
1665 pa_xfree(p);
1666 return k;
1669 pa_log_info("Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory.");
1672 #endif
1674 pa_xfree(p);
1675 p = NULL;
1677 /* Hmm, so the link points to some nonexisting or invalid
1678 * dir. Let's replace it by a new link. We first create a
1679 * temporary link and then rename that to allow concurrent
1680 * execution of this function. */
1682 t = pa_sprintf_malloc("%s.tmp", k);
1684 if (make_random_dir_and_link(0700, t) < 0) {
1686 if (errno != EEXIST) {
1687 pa_log_error("Failed to symlink %s: %s", t, pa_cstrerror(errno));
1688 goto fail;
1691 pa_xfree(t);
1692 t = NULL;
1694 /* Hmm, someone lese was quicker then us. Let's give
1695 * him some time to finish, and retry. */
1696 pa_msleep(10);
1697 continue;
1700 /* OK, we succeeded in creating the temporary symlink, so
1701 * let's rename it */
1702 if (rename(t, k) < 0) {
1703 pa_log_error("Failed to rename %s to %s: %s", t, k, pa_cstrerror(errno));
1704 goto fail;
1707 pa_xfree(t);
1708 return k;
1711 fail:
1712 pa_xfree(p);
1713 pa_xfree(k);
1714 pa_xfree(t);
1716 return NULL;
1719 /* Try to open a configuration file. If "env" is specified, open the
1720 * value of the specified environment variable. Otherwise look for a
1721 * file "local" in the home directory or a file "global" in global
1722 * file system. If "result" is non-NULL, a pointer to a newly
1723 * allocated buffer containing the used configuration file is
1724 * stored there.*/
1725 FILE *pa_open_config_file(const char *global, const char *local, const char *env, char **result) {
1726 const char *fn;
1727 FILE *f;
1729 if (env && (fn = getenv(env))) {
1730 if ((f = pa_fopen_cloexec(fn, "r"))) {
1731 if (result)
1732 *result = pa_xstrdup(fn);
1734 return f;
1737 pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
1738 return NULL;
1741 if (local) {
1742 const char *e;
1743 char *lfn;
1744 char *h;
1746 if ((e = getenv("PULSE_CONFIG_PATH")))
1747 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
1748 else if ((h = pa_get_home_dir_malloc())) {
1749 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
1750 pa_xfree(h);
1751 } else
1752 return NULL;
1754 if ((f = pa_fopen_cloexec(fn, "r"))) {
1755 if (result)
1756 *result = pa_xstrdup(fn);
1758 pa_xfree(lfn);
1759 return f;
1762 if (errno != ENOENT) {
1763 pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
1764 pa_xfree(lfn);
1765 return NULL;
1768 pa_xfree(lfn);
1771 if (global) {
1772 char *gfn;
1774 #ifdef OS_IS_WIN32
1775 if (strncmp(global, PA_DEFAULT_CONFIG_DIR, strlen(PA_DEFAULT_CONFIG_DIR)) == 0)
1776 gfn = pa_sprintf_malloc("%s" PA_PATH_SEP "etc" PA_PATH_SEP "pulse%s",
1777 pa_win32_get_toplevel(NULL),
1778 global + strlen(PA_DEFAULT_CONFIG_DIR));
1779 else
1780 #endif
1781 gfn = pa_xstrdup(global);
1783 if ((f = pa_fopen_cloexec(gfn, "r"))) {
1784 if (result)
1785 *result = gfn;
1786 else
1787 pa_xfree(gfn);
1789 return f;
1791 pa_xfree(gfn);
1794 errno = ENOENT;
1795 return NULL;
1798 char *pa_find_config_file(const char *global, const char *local, const char *env) {
1799 const char *fn;
1801 if (env && (fn = getenv(env))) {
1802 if (access(fn, R_OK) == 0)
1803 return pa_xstrdup(fn);
1805 pa_log_warn("Failed to access configuration file '%s': %s", fn, pa_cstrerror(errno));
1806 return NULL;
1809 if (local) {
1810 const char *e;
1811 char *lfn;
1812 char *h;
1814 if ((e = getenv("PULSE_CONFIG_PATH")))
1815 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
1816 else if ((h = pa_get_home_dir_malloc())) {
1817 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
1818 pa_xfree(h);
1819 } else
1820 return NULL;
1822 if (access(fn, R_OK) == 0) {
1823 char *r = pa_xstrdup(fn);
1824 pa_xfree(lfn);
1825 return r;
1828 if (errno != ENOENT) {
1829 pa_log_warn("Failed to access configuration file '%s': %s", fn, pa_cstrerror(errno));
1830 pa_xfree(lfn);
1831 return NULL;
1834 pa_xfree(lfn);
1837 if (global) {
1838 char *gfn;
1840 #ifdef OS_IS_WIN32
1841 if (strncmp(global, PA_DEFAULT_CONFIG_DIR, strlen(PA_DEFAULT_CONFIG_DIR)) == 0)
1842 gfn = pa_sprintf_malloc("%s" PA_PATH_SEP "etc" PA_PATH_SEP "pulse%s",
1843 pa_win32_get_toplevel(NULL),
1844 global + strlen(PA_DEFAULT_CONFIG_DIR));
1845 else
1846 #endif
1847 gfn = pa_xstrdup(global);
1849 if (access(gfn, R_OK) == 0)
1850 return gfn;
1851 pa_xfree(gfn);
1854 errno = ENOENT;
1856 return NULL;
1859 /* Format the specified data as a hexademical string */
1860 char *pa_hexstr(const uint8_t* d, size_t dlength, char *s, size_t slength) {
1861 size_t i = 0, j = 0;
1862 const char hex[] = "0123456789abcdef";
1864 pa_assert(d);
1865 pa_assert(s);
1866 pa_assert(slength > 0);
1868 while (j+2 < slength && i < dlength) {
1869 s[j++] = hex[*d >> 4];
1870 s[j++] = hex[*d & 0xF];
1872 d++;
1873 i++;
1876 s[j < slength ? j : slength] = 0;
1877 return s;
1880 /* Convert a hexadecimal digit to a number or -1 if invalid */
1881 static int hexc(char c) {
1882 if (c >= '0' && c <= '9')
1883 return c - '0';
1885 if (c >= 'A' && c <= 'F')
1886 return c - 'A' + 10;
1888 if (c >= 'a' && c <= 'f')
1889 return c - 'a' + 10;
1891 errno = EINVAL;
1892 return -1;
1895 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1896 size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength) {
1897 size_t j = 0;
1899 pa_assert(p);
1900 pa_assert(d);
1902 while (j < dlength && *p) {
1903 int b;
1905 if ((b = hexc(*(p++))) < 0)
1906 return (size_t) -1;
1908 d[j] = (uint8_t) (b << 4);
1910 if (!*p)
1911 return (size_t) -1;
1913 if ((b = hexc(*(p++))) < 0)
1914 return (size_t) -1;
1916 d[j] |= (uint8_t) b;
1917 j++;
1920 return j;
1923 /* Returns nonzero when *s starts with *pfx */
1924 pa_bool_t pa_startswith(const char *s, const char *pfx) {
1925 size_t l;
1927 pa_assert(s);
1928 pa_assert(pfx);
1930 l = strlen(pfx);
1932 return strlen(s) >= l && strncmp(s, pfx, l) == 0;
1935 /* Returns nonzero when *s ends with *sfx */
1936 pa_bool_t pa_endswith(const char *s, const char *sfx) {
1937 size_t l1, l2;
1939 pa_assert(s);
1940 pa_assert(sfx);
1942 l1 = strlen(s);
1943 l2 = strlen(sfx);
1945 return l1 >= l2 && strcmp(s+l1-l2, sfx) == 0;
1948 pa_bool_t pa_is_path_absolute(const char *fn) {
1949 pa_assert(fn);
1951 #ifndef OS_IS_WIN32
1952 return *fn == '/';
1953 #else
1954 return strlen(fn) >= 3 && isalpha(fn[0]) && fn[1] == ':' && fn[2] == '\\';
1955 #endif
1958 char *pa_make_path_absolute(const char *p) {
1959 char *r;
1960 char *cwd;
1962 pa_assert(p);
1964 if (pa_is_path_absolute(p))
1965 return pa_xstrdup(p);
1967 if (!(cwd = pa_getcwd()))
1968 return pa_xstrdup(p);
1970 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", cwd, p);
1971 pa_xfree(cwd);
1972 return r;
1975 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1976 * if fn is non-null and starts with / return fn
1977 * otherwise append fn to the run time path and return it */
1978 static char *get_path(const char *fn, pa_bool_t prependmid, pa_bool_t rt) {
1979 char *rtp;
1981 rtp = rt ? pa_get_runtime_dir() : pa_get_state_dir();
1983 if (fn) {
1984 char *r;
1986 if (pa_is_path_absolute(fn))
1987 return pa_xstrdup(fn);
1989 if (!rtp)
1990 return NULL;
1992 if (prependmid) {
1993 char *mid;
1995 if (!(mid = pa_machine_id())) {
1996 pa_xfree(rtp);
1997 return NULL;
2000 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s-%s", rtp, mid, fn);
2001 pa_xfree(mid);
2002 } else
2003 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", rtp, fn);
2005 pa_xfree(rtp);
2006 return r;
2007 } else
2008 return rtp;
2011 char *pa_runtime_path(const char *fn) {
2012 return get_path(fn, FALSE, TRUE);
2015 char *pa_state_path(const char *fn, pa_bool_t appendmid) {
2016 return get_path(fn, appendmid, FALSE);
2019 /* Convert the string s to a signed integer in *ret_i */
2020 int pa_atoi(const char *s, int32_t *ret_i) {
2021 long l;
2023 pa_assert(s);
2024 pa_assert(ret_i);
2026 if (pa_atol(s, &l) < 0)
2027 return -1;
2029 if ((int32_t) l != l) {
2030 errno = ERANGE;
2031 return -1;
2034 *ret_i = (int32_t) l;
2036 return 0;
2039 /* Convert the string s to an unsigned integer in *ret_u */
2040 int pa_atou(const char *s, uint32_t *ret_u) {
2041 char *x = NULL;
2042 unsigned long l;
2044 pa_assert(s);
2045 pa_assert(ret_u);
2047 errno = 0;
2048 l = strtoul(s, &x, 0);
2050 if (!x || *x || errno) {
2051 if (!errno)
2052 errno = EINVAL;
2053 return -1;
2056 if ((uint32_t) l != l) {
2057 errno = ERANGE;
2058 return -1;
2061 *ret_u = (uint32_t) l;
2063 return 0;
2066 /* Convert the string s to a signed long integer in *ret_l. */
2067 int pa_atol(const char *s, long *ret_l) {
2068 char *x = NULL;
2069 long l;
2071 pa_assert(s);
2072 pa_assert(ret_l);
2074 errno = 0;
2075 l = strtol(s, &x, 0);
2077 if (!x || *x || errno) {
2078 if (!errno)
2079 errno = EINVAL;
2080 return -1;
2083 *ret_l = l;
2085 return 0;
2088 #ifdef HAVE_STRTOF_L
2089 static locale_t c_locale = NULL;
2091 static void c_locale_destroy(void) {
2092 freelocale(c_locale);
2094 #endif
2096 int pa_atod(const char *s, double *ret_d) {
2097 char *x = NULL;
2098 double f;
2100 pa_assert(s);
2101 pa_assert(ret_d);
2103 /* This should be locale independent */
2105 #ifdef HAVE_STRTOF_L
2107 PA_ONCE_BEGIN {
2109 if ((c_locale = newlocale(LC_ALL_MASK, "C", NULL)))
2110 atexit(c_locale_destroy);
2112 } PA_ONCE_END;
2114 if (c_locale) {
2115 errno = 0;
2116 f = strtod_l(s, &x, c_locale);
2117 } else
2118 #endif
2120 errno = 0;
2121 f = strtod(s, &x);
2124 if (!x || *x || errno) {
2125 if (!errno)
2126 errno = EINVAL;
2127 return -1;
2130 *ret_d = f;
2132 return 0;
2135 /* Same as snprintf, but guarantees NUL-termination on every platform */
2136 size_t pa_snprintf(char *str, size_t size, const char *format, ...) {
2137 size_t ret;
2138 va_list ap;
2140 pa_assert(str);
2141 pa_assert(size > 0);
2142 pa_assert(format);
2144 va_start(ap, format);
2145 ret = pa_vsnprintf(str, size, format, ap);
2146 va_end(ap);
2148 return ret;
2151 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2152 size_t pa_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
2153 int ret;
2155 pa_assert(str);
2156 pa_assert(size > 0);
2157 pa_assert(format);
2159 ret = vsnprintf(str, size, format, ap);
2161 str[size-1] = 0;
2163 if (ret < 0)
2164 return strlen(str);
2166 if ((size_t) ret > size-1)
2167 return size-1;
2169 return (size_t) ret;
2172 /* Truncate the specified string, but guarantee that the string
2173 * returned still validates as UTF8 */
2174 char *pa_truncate_utf8(char *c, size_t l) {
2175 pa_assert(c);
2176 pa_assert(pa_utf8_valid(c));
2178 if (strlen(c) <= l)
2179 return c;
2181 c[l] = 0;
2183 while (l > 0 && !pa_utf8_valid(c))
2184 c[--l] = 0;
2186 return c;
2189 char *pa_getcwd(void) {
2190 size_t l = 128;
2192 for (;;) {
2193 char *p = pa_xmalloc(l);
2194 if (getcwd(p, l))
2195 return p;
2197 if (errno != ERANGE)
2198 return NULL;
2200 pa_xfree(p);
2201 l *= 2;
2205 void *pa_will_need(const void *p, size_t l) {
2206 #ifdef RLIMIT_MEMLOCK
2207 struct rlimit rlim;
2208 #endif
2209 const void *a;
2210 size_t size;
2211 int r = ENOTSUP;
2212 size_t bs;
2214 pa_assert(p);
2215 pa_assert(l > 0);
2217 a = PA_PAGE_ALIGN_PTR(p);
2218 size = (size_t) ((const uint8_t*) p + l - (const uint8_t*) a);
2220 #ifdef HAVE_POSIX_MADVISE
2221 if ((r = posix_madvise((void*) a, size, POSIX_MADV_WILLNEED)) == 0) {
2222 pa_log_debug("posix_madvise() worked fine!");
2223 return (void*) p;
2225 #endif
2227 /* Most likely the memory was not mmap()ed from a file and thus
2228 * madvise() didn't work, so let's misuse mlock() do page this
2229 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2230 * inviting, the man page of mlock() tells us: "All pages that
2231 * contain a part of the specified address range are guaranteed to
2232 * be resident in RAM when the call returns successfully." */
2234 #ifdef RLIMIT_MEMLOCK
2235 pa_assert_se(getrlimit(RLIMIT_MEMLOCK, &rlim) == 0);
2237 if (rlim.rlim_cur < PA_PAGE_SIZE) {
2238 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));
2239 errno = EPERM;
2240 return (void*) p;
2243 bs = PA_PAGE_ALIGN((size_t) rlim.rlim_cur);
2244 #else
2245 bs = PA_PAGE_SIZE*4;
2246 #endif
2248 pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r));
2250 #ifdef HAVE_MLOCK
2251 while (size > 0 && bs > 0) {
2253 if (bs > size)
2254 bs = size;
2256 if (mlock(a, bs) < 0) {
2257 bs = PA_PAGE_ALIGN(bs / 2);
2258 continue;
2261 pa_assert_se(munlock(a, bs) == 0);
2263 a = (const uint8_t*) a + bs;
2264 size -= bs;
2266 #endif
2268 if (bs <= 0)
2269 pa_log_debug("mlock() failed too (or doesn't exist), giving up: %s", pa_cstrerror(errno));
2270 else
2271 pa_log_debug("mlock() worked fine!");
2273 return (void*) p;
2276 void pa_close_pipe(int fds[2]) {
2277 pa_assert(fds);
2279 if (fds[0] >= 0)
2280 pa_assert_se(pa_close(fds[0]) == 0);
2282 if (fds[1] >= 0)
2283 pa_assert_se(pa_close(fds[1]) == 0);
2285 fds[0] = fds[1] = -1;
2288 char *pa_readlink(const char *p) {
2289 #ifdef HAVE_READLINK
2290 size_t l = 100;
2292 for (;;) {
2293 char *c;
2294 ssize_t n;
2296 c = pa_xmalloc(l);
2298 if ((n = readlink(p, c, l-1)) < 0) {
2299 pa_xfree(c);
2300 return NULL;
2303 if ((size_t) n < l-1) {
2304 c[n] = 0;
2305 return c;
2308 pa_xfree(c);
2309 l *= 2;
2311 #else
2312 return NULL;
2313 #endif
2316 int pa_close_all(int except_fd, ...) {
2317 va_list ap;
2318 unsigned n = 0, i;
2319 int r, *p;
2321 va_start(ap, except_fd);
2323 if (except_fd >= 0)
2324 for (n = 1; va_arg(ap, int) >= 0; n++)
2327 va_end(ap);
2329 p = pa_xnew(int, n+1);
2331 va_start(ap, except_fd);
2333 i = 0;
2334 if (except_fd >= 0) {
2335 int fd;
2336 p[i++] = except_fd;
2338 while ((fd = va_arg(ap, int)) >= 0)
2339 p[i++] = fd;
2341 p[i] = -1;
2343 va_end(ap);
2345 r = pa_close_allv(p);
2346 pa_xfree(p);
2348 return r;
2351 int pa_close_allv(const int except_fds[]) {
2352 #ifndef OS_IS_WIN32
2353 struct rlimit rl;
2354 int maxfd, fd;
2356 #ifdef __linux__
2357 int saved_errno;
2358 DIR *d;
2360 if ((d = opendir("/proc/self/fd"))) {
2362 struct dirent *de;
2364 while ((de = readdir(d))) {
2365 pa_bool_t found;
2366 long l;
2367 char *e = NULL;
2368 int i;
2370 if (de->d_name[0] == '.')
2371 continue;
2373 errno = 0;
2374 l = strtol(de->d_name, &e, 10);
2375 if (errno != 0 || !e || *e) {
2376 closedir(d);
2377 errno = EINVAL;
2378 return -1;
2381 fd = (int) l;
2383 if ((long) fd != l) {
2384 closedir(d);
2385 errno = EINVAL;
2386 return -1;
2389 if (fd < 3)
2390 continue;
2392 if (fd == dirfd(d))
2393 continue;
2395 found = FALSE;
2396 for (i = 0; except_fds[i] >= 0; i++)
2397 if (except_fds[i] == fd) {
2398 found = TRUE;
2399 break;
2402 if (found)
2403 continue;
2405 if (pa_close(fd) < 0) {
2406 saved_errno = errno;
2407 closedir(d);
2408 errno = saved_errno;
2410 return -1;
2414 closedir(d);
2415 return 0;
2418 #endif
2420 if (getrlimit(RLIMIT_NOFILE, &rl) >= 0)
2421 maxfd = (int) rl.rlim_max;
2422 else
2423 maxfd = sysconf(_SC_OPEN_MAX);
2425 for (fd = 3; fd < maxfd; fd++) {
2426 int i;
2427 pa_bool_t found;
2429 found = FALSE;
2430 for (i = 0; except_fds[i] >= 0; i++)
2431 if (except_fds[i] == fd) {
2432 found = TRUE;
2433 break;
2436 if (found)
2437 continue;
2439 if (pa_close(fd) < 0 && errno != EBADF)
2440 return -1;
2442 #endif /* !OS_IS_WIN32 */
2444 return 0;
2447 int pa_unblock_sigs(int except, ...) {
2448 va_list ap;
2449 unsigned n = 0, i;
2450 int r, *p;
2452 va_start(ap, except);
2454 if (except >= 1)
2455 for (n = 1; va_arg(ap, int) >= 0; n++)
2458 va_end(ap);
2460 p = pa_xnew(int, n+1);
2462 va_start(ap, except);
2464 i = 0;
2465 if (except >= 1) {
2466 int sig;
2467 p[i++] = except;
2469 while ((sig = va_arg(ap, int)) >= 0)
2470 p[i++] = sig;
2472 p[i] = -1;
2474 va_end(ap);
2476 r = pa_unblock_sigsv(p);
2477 pa_xfree(p);
2479 return r;
2482 int pa_unblock_sigsv(const int except[]) {
2483 #ifndef OS_IS_WIN32
2484 int i;
2485 sigset_t ss;
2487 if (sigemptyset(&ss) < 0)
2488 return -1;
2490 for (i = 0; except[i] > 0; i++)
2491 if (sigaddset(&ss, except[i]) < 0)
2492 return -1;
2494 return sigprocmask(SIG_SETMASK, &ss, NULL);
2495 #else
2496 return 0;
2497 #endif
2500 int pa_reset_sigs(int except, ...) {
2501 va_list ap;
2502 unsigned n = 0, i;
2503 int *p, r;
2505 va_start(ap, except);
2507 if (except >= 1)
2508 for (n = 1; va_arg(ap, int) >= 0; n++)
2511 va_end(ap);
2513 p = pa_xnew(int, n+1);
2515 va_start(ap, except);
2517 i = 0;
2518 if (except >= 1) {
2519 int sig;
2520 p[i++] = except;
2522 while ((sig = va_arg(ap, int)) >= 0)
2523 p[i++] = sig;
2525 p[i] = -1;
2527 va_end(ap);
2529 r = pa_reset_sigsv(p);
2530 pa_xfree(p);
2532 return r;
2535 int pa_reset_sigsv(const int except[]) {
2536 #ifndef OS_IS_WIN32
2537 int sig;
2539 for (sig = 1; sig < NSIG; sig++) {
2540 pa_bool_t reset = TRUE;
2542 switch (sig) {
2543 case SIGKILL:
2544 case SIGSTOP:
2545 reset = FALSE;
2546 break;
2548 default: {
2549 int i;
2551 for (i = 0; except[i] > 0; i++) {
2552 if (sig == except[i]) {
2553 reset = FALSE;
2554 break;
2560 if (reset) {
2561 struct sigaction sa;
2563 memset(&sa, 0, sizeof(sa));
2564 sa.sa_handler = SIG_DFL;
2566 /* On Linux the first two RT signals are reserved by
2567 * glibc, and sigaction() will return EINVAL for them. */
2568 if ((sigaction(sig, &sa, NULL) < 0))
2569 if (errno != EINVAL)
2570 return -1;
2573 #endif
2575 return 0;
2578 void pa_set_env(const char *key, const char *value) {
2579 pa_assert(key);
2580 pa_assert(value);
2582 /* This is not thread-safe */
2584 #ifdef OS_IS_WIN32
2585 SetEnvironmentVariable(key, value);
2586 #else
2587 setenv(key, value, 1);
2588 #endif
2591 void pa_set_env_and_record(const char *key, const char *value) {
2592 pa_assert(key);
2593 pa_assert(value);
2595 /* This is not thread-safe */
2597 pa_set_env(key, value);
2598 recorded_env = pa_strlist_prepend(recorded_env, key);
2601 void pa_unset_env_recorded(void) {
2603 /* This is not thread-safe */
2605 for (;;) {
2606 char *s;
2608 recorded_env = pa_strlist_pop(recorded_env, &s);
2610 if (!s)
2611 break;
2613 #ifdef OS_IS_WIN32
2614 SetEnvironmentVariable(s, NULL);
2615 #else
2616 unsetenv(s);
2617 #endif
2618 pa_xfree(s);
2622 pa_bool_t pa_in_system_mode(void) {
2623 const char *e;
2625 if (!(e = getenv("PULSE_SYSTEM")))
2626 return FALSE;
2628 return !!atoi(e);
2631 char *pa_get_user_name_malloc(void) {
2632 ssize_t k;
2633 char *u;
2635 #ifdef _SC_LOGIN_NAME_MAX
2636 k = (ssize_t) sysconf(_SC_LOGIN_NAME_MAX);
2638 if (k <= 0)
2639 #endif
2640 k = 32;
2642 u = pa_xnew(char, k+1);
2644 if (!(pa_get_user_name(u, k))) {
2645 pa_xfree(u);
2646 return NULL;
2649 return u;
2652 char *pa_get_host_name_malloc(void) {
2653 size_t l;
2655 l = 100;
2656 for (;;) {
2657 char *c;
2659 c = pa_xmalloc(l);
2661 if (!pa_get_host_name(c, l)) {
2663 if (errno != EINVAL && errno != ENAMETOOLONG)
2664 break;
2666 } else if (strlen(c) < l-1) {
2667 char *u;
2669 if (*c == 0) {
2670 pa_xfree(c);
2671 break;
2674 u = pa_utf8_filter(c);
2675 pa_xfree(c);
2676 return u;
2679 /* Hmm, the hostname is as long the space we offered the
2680 * function, we cannot know if it fully fit in, so let's play
2681 * safe and retry. */
2683 pa_xfree(c);
2684 l *= 2;
2687 return NULL;
2690 char *pa_machine_id(void) {
2691 FILE *f;
2692 char *h;
2694 /* The returned value is supposed be some kind of ascii identifier
2695 * that is unique and stable across reboots. */
2697 /* First we try the D-Bus UUID, which is the best option we have,
2698 * since it fits perfectly our needs and is not as volatile as the
2699 * hostname which might be set from dhcp. */
2701 if ((f = pa_fopen_cloexec(PA_MACHINE_ID, "r"))) {
2702 char ln[34] = "", *r;
2704 r = fgets(ln, sizeof(ln)-1, f);
2705 fclose(f);
2707 pa_strip_nl(ln);
2709 if (r && ln[0])
2710 return pa_utf8_filter(ln);
2713 if ((h = pa_get_host_name_malloc()))
2714 return h;
2716 #ifndef OS_IS_WIN32
2717 /* If no hostname was set we use the POSIX hostid. It's usually
2718 * the IPv4 address. Might not be that stable. */
2719 return pa_sprintf_malloc("%08lx", (unsigned long) gethostid);
2720 #else
2721 return NULL;
2722 #endif
2725 char *pa_session_id(void) {
2726 const char *e;
2728 if (!(e = getenv("XDG_SESSION_COOKIE")))
2729 return NULL;
2731 return pa_utf8_filter(e);
2734 char *pa_uname_string(void) {
2735 #ifdef HAVE_UNAME
2736 struct utsname u;
2738 pa_assert_se(uname(&u) >= 0);
2740 return pa_sprintf_malloc("%s %s %s %s", u.sysname, u.machine, u.release, u.version);
2741 #endif
2742 #ifdef OS_IS_WIN32
2743 OSVERSIONINFO i;
2745 pa_zero(i);
2746 i.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
2747 pa_assert_se(GetVersionEx(&i));
2749 return pa_sprintf_malloc("Windows %d.%d (%d) %s", i.dwMajorVersion, i.dwMinorVersion, i.dwBuildNumber, i.szCSDVersion);
2750 #endif
2753 #ifdef HAVE_VALGRIND_MEMCHECK_H
2754 pa_bool_t pa_in_valgrind(void) {
2755 static int b = 0;
2757 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2758 * here instead of really checking whether we run in valgrind or
2759 * not. */
2761 if (b < 1)
2762 b = getenv("VALGRIND") ? 2 : 1;
2764 return b > 1;
2766 #endif
2768 unsigned pa_gcd(unsigned a, unsigned b) {
2770 while (b > 0) {
2771 unsigned t = b;
2772 b = a % b;
2773 a = t;
2776 return a;
2779 void pa_reduce(unsigned *num, unsigned *den) {
2781 unsigned gcd = pa_gcd(*num, *den);
2783 if (gcd <= 0)
2784 return;
2786 *num /= gcd;
2787 *den /= gcd;
2789 pa_assert(pa_gcd(*num, *den) == 1);
2792 unsigned pa_ncpus(void) {
2793 long ncpus;
2795 #ifdef _SC_NPROCESSORS_CONF
2796 ncpus = sysconf(_SC_NPROCESSORS_CONF);
2797 #else
2798 ncpus = 1;
2799 #endif
2801 return ncpus <= 0 ? 1 : (unsigned) ncpus;
2804 char *pa_replace(const char*s, const char*a, const char *b) {
2805 pa_strbuf *sb;
2806 size_t an;
2808 pa_assert(s);
2809 pa_assert(a);
2810 pa_assert(b);
2812 an = strlen(a);
2813 sb = pa_strbuf_new();
2815 for (;;) {
2816 const char *p;
2818 if (!(p = strstr(s, a)))
2819 break;
2821 pa_strbuf_putsn(sb, s, p-s);
2822 pa_strbuf_puts(sb, b);
2823 s = p + an;
2826 pa_strbuf_puts(sb, s);
2828 return pa_strbuf_tostring_free(sb);
2831 char *pa_escape(const char *p, const char *chars) {
2832 const char *s;
2833 const char *c;
2834 pa_strbuf *buf = pa_strbuf_new();
2836 for (s = p; *s; ++s) {
2837 if (*s == '\\')
2838 pa_strbuf_putc(buf, '\\');
2839 else if (chars) {
2840 for (c = chars; *c; ++c) {
2841 if (*s == *c) {
2842 pa_strbuf_putc(buf, '\\');
2843 break;
2847 pa_strbuf_putc(buf, *s);
2850 return pa_strbuf_tostring_free(buf);
2853 char *pa_unescape(char *p) {
2854 char *s, *d;
2855 pa_bool_t escaped = FALSE;
2857 for (s = p, d = p; *s; s++) {
2858 if (!escaped && *s == '\\') {
2859 escaped = TRUE;
2860 continue;
2863 *(d++) = *s;
2864 escaped = FALSE;
2867 *d = 0;
2869 return p;
2872 char *pa_realpath(const char *path) {
2873 char *t;
2874 pa_assert(path);
2876 /* We want only abolsute paths */
2877 if (path[0] != '/') {
2878 errno = EINVAL;
2879 return NULL;
2882 #if defined(__GLIBC__) || defined(__APPLE__)
2884 char *r;
2886 if (!(r = realpath(path, NULL)))
2887 return NULL;
2889 /* We copy this here in case our pa_xmalloc() is not
2890 * implemented on top of libc malloc() */
2891 t = pa_xstrdup(r);
2892 pa_xfree(r);
2894 #elif defined(PATH_MAX)
2896 char *path_buf;
2897 path_buf = pa_xmalloc(PATH_MAX);
2899 #if defined(OS_IS_WIN32)
2900 if (!(t = _fullpath(path_buf, path, _MAX_PATH))) {
2901 pa_xfree(path_buf);
2902 return NULL;
2904 #else
2905 if (!(t = realpath(path, path_buf))) {
2906 pa_xfree(path_buf);
2907 return NULL;
2909 #endif
2911 #else
2912 #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."
2913 #endif
2915 return t;
2918 void pa_disable_sigpipe(void) {
2920 #ifdef SIGPIPE
2921 struct sigaction sa;
2923 pa_zero(sa);
2925 if (sigaction(SIGPIPE, NULL, &sa) < 0) {
2926 pa_log("sigaction(): %s", pa_cstrerror(errno));
2927 return;
2930 sa.sa_handler = SIG_IGN;
2932 if (sigaction(SIGPIPE, &sa, NULL) < 0) {
2933 pa_log("sigaction(): %s", pa_cstrerror(errno));
2934 return;
2936 #endif
2939 void pa_xfreev(void**a) {
2940 void **p;
2942 if (!a)
2943 return;
2945 for (p = a; *p; p++)
2946 pa_xfree(*p);
2948 pa_xfree(a);
2951 char **pa_split_spaces_strv(const char *s) {
2952 char **t, *e;
2953 unsigned i = 0, n = 8;
2954 const char *state = NULL;
2956 t = pa_xnew(char*, n);
2957 while ((e = pa_split_spaces(s, &state))) {
2958 t[i++] = e;
2960 if (i >= n) {
2961 n *= 2;
2962 t = pa_xrenew(char*, t, n);
2966 if (i <= 0) {
2967 pa_xfree(t);
2968 return NULL;
2971 t[i] = NULL;
2972 return t;
2975 char* pa_maybe_prefix_path(const char *path, const char *prefix) {
2976 pa_assert(path);
2978 if (pa_is_path_absolute(path))
2979 return pa_xstrdup(path);
2981 return pa_sprintf_malloc("%s" PA_PATH_SEP "%s", prefix, path);
2984 size_t pa_pipe_buf(int fd) {
2986 #ifdef _PC_PIPE_BUF
2987 long n;
2989 if ((n = fpathconf(fd, _PC_PIPE_BUF)) >= 0)
2990 return (size_t) n;
2991 #endif
2993 #ifdef PIPE_BUF
2994 return PIPE_BUF;
2995 #else
2996 return 4096;
2997 #endif
3000 void pa_reset_personality(void) {
3002 #ifdef __linux__
3003 if (personality(PER_LINUX) < 0)
3004 pa_log_warn("Uh, personality() failed: %s", pa_cstrerror(errno));
3005 #endif
3009 #if defined(__linux__) && !defined(__OPTIMIZE__)
3011 pa_bool_t pa_run_from_build_tree(void) {
3012 char *rp;
3013 pa_bool_t b = FALSE;
3015 if ((rp = pa_readlink("/proc/self/exe"))) {
3016 b = pa_startswith(rp, PA_BUILDDIR);
3017 pa_xfree(rp);
3020 return b;
3023 #endif
3025 const char *pa_get_temp_dir(void) {
3026 const char *t;
3028 if ((t = getenv("TMPDIR")) &&
3029 pa_is_path_absolute(t))
3030 return t;
3032 if ((t = getenv("TMP")) &&
3033 pa_is_path_absolute(t))
3034 return t;
3036 if ((t = getenv("TEMP")) &&
3037 pa_is_path_absolute(t))
3038 return t;
3040 if ((t = getenv("TEMPDIR")) &&
3041 pa_is_path_absolute(t))
3042 return t;
3044 return "/tmp";
3047 int pa_open_cloexec(const char *fn, int flags, mode_t mode) {
3048 int fd;
3050 #ifdef O_NOCTTY
3051 flags |= O_NOCTTY;
3052 #endif
3054 #ifdef O_CLOEXEC
3055 if ((fd = open(fn, flags|O_CLOEXEC, mode)) >= 0)
3056 goto finish;
3058 if (errno != EINVAL)
3059 return fd;
3060 #endif
3062 if ((fd = open(fn, flags, mode)) < 0)
3063 return fd;
3065 finish:
3066 /* Some implementations might simply ignore O_CLOEXEC if it is not
3067 * understood, make sure FD_CLOEXEC is enabled anyway */
3069 pa_make_fd_cloexec(fd);
3070 return fd;
3073 int pa_socket_cloexec(int domain, int type, int protocol) {
3074 int fd;
3076 #ifdef SOCK_CLOEXEC
3077 if ((fd = socket(domain, type | SOCK_CLOEXEC, protocol)) >= 0)
3078 goto finish;
3080 if (errno != EINVAL)
3081 return fd;
3082 #endif
3084 if ((fd = socket(domain, type, protocol)) < 0)
3085 return fd;
3087 finish:
3088 /* Some implementations might simply ignore SOCK_CLOEXEC if it is
3089 * not understood, make sure FD_CLOEXEC is enabled anyway */
3091 pa_make_fd_cloexec(fd);
3092 return fd;
3095 int pa_pipe_cloexec(int pipefd[2]) {
3096 int r;
3098 #ifdef HAVE_PIPE2
3099 if ((r = pipe2(pipefd, O_CLOEXEC)) >= 0)
3100 goto finish;
3102 if (errno != EINVAL && errno != ENOSYS)
3103 return r;
3105 #endif
3107 if ((r = pipe(pipefd)) < 0)
3108 return r;
3110 finish:
3111 pa_make_fd_cloexec(pipefd[0]);
3112 pa_make_fd_cloexec(pipefd[1]);
3114 return 0;
3117 int pa_accept_cloexec(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
3118 int fd;
3120 #ifdef HAVE_ACCEPT4
3121 if ((fd = accept4(sockfd, addr, addrlen, SOCK_CLOEXEC)) >= 0)
3122 goto finish;
3124 if (errno != EINVAL && errno != ENOSYS)
3125 return fd;
3127 #endif
3129 if ((fd = accept(sockfd, addr, addrlen)) < 0)
3130 return fd;
3132 finish:
3133 pa_make_fd_cloexec(fd);
3134 return fd;
3137 FILE* pa_fopen_cloexec(const char *path, const char *mode) {
3138 FILE *f;
3139 char *m;
3141 m = pa_sprintf_malloc("%se", mode);
3143 errno = 0;
3144 if ((f = fopen(path, m))) {
3145 pa_xfree(m);
3146 goto finish;
3149 pa_xfree(m);
3151 if (errno != EINVAL)
3152 return NULL;
3154 if (!(f = fopen(path, mode)))
3155 return NULL;
3157 finish:
3158 pa_make_fd_cloexec(fileno(f));
3159 return f;
3162 void pa_nullify_stdfds(void) {
3164 #ifndef OS_IS_WIN32
3165 pa_close(STDIN_FILENO);
3166 pa_close(STDOUT_FILENO);
3167 pa_close(STDERR_FILENO);
3169 pa_assert_se(open("/dev/null", O_RDONLY) == STDIN_FILENO);
3170 pa_assert_se(open("/dev/null", O_WRONLY) == STDOUT_FILENO);
3171 pa_assert_se(open("/dev/null", O_WRONLY) == STDERR_FILENO);
3172 #else
3173 FreeConsole();
3174 #endif
3178 char *pa_read_line_from_file(const char *fn) {
3179 FILE *f;
3180 char ln[256] = "", *r;
3182 if (!(f = pa_fopen_cloexec(fn, "r")))
3183 return NULL;
3185 r = fgets(ln, sizeof(ln)-1, f);
3186 fclose(f);
3188 if (!r) {
3189 errno = EIO;
3190 return NULL;
3193 pa_strip_nl(ln);
3194 return pa_xstrdup(ln);
3197 pa_bool_t pa_running_in_vm(void) {
3199 #if defined(__i386__) || defined(__x86_64__)
3201 /* Both CPUID and DMI are x86 specific interfaces... */
3203 uint32_t eax = 0x40000000;
3204 union {
3205 uint32_t sig32[3];
3206 char text[13];
3207 } sig;
3209 #ifdef __linux__
3210 const char *const dmi_vendors[] = {
3211 "/sys/class/dmi/id/sys_vendor",
3212 "/sys/class/dmi/id/board_vendor",
3213 "/sys/class/dmi/id/bios_vendor"
3216 unsigned i;
3218 for (i = 0; i < PA_ELEMENTSOF(dmi_vendors); i++) {
3219 char *s;
3221 if ((s = pa_read_line_from_file(dmi_vendors[i]))) {
3223 if (pa_startswith(s, "QEMU") ||
3224 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3225 pa_startswith(s, "VMware") ||
3226 pa_startswith(s, "VMW") ||
3227 pa_startswith(s, "Microsoft Corporation") ||
3228 pa_startswith(s, "innotek GmbH") ||
3229 pa_startswith(s, "Xen")) {
3231 pa_xfree(s);
3232 return TRUE;
3235 pa_xfree(s);
3239 #endif
3241 /* http://lwn.net/Articles/301888/ */
3242 pa_zero(sig);
3244 __asm__ __volatile__ (
3245 /* ebx/rbx is being used for PIC! */
3246 " push %%"PA_REG_b" \n\t"
3247 " cpuid \n\t"
3248 " mov %%ebx, %1 \n\t"
3249 " pop %%"PA_REG_b" \n\t"
3251 : "=a" (eax), "=r" (sig.sig32[0]), "=c" (sig.sig32[1]), "=d" (sig.sig32[2])
3252 : "0" (eax)
3255 if (pa_streq(sig.text, "XenVMMXenVMM") ||
3256 pa_streq(sig.text, "KVMKVMKVM") ||
3257 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3258 pa_streq(sig.text, "VMwareVMware") ||
3259 /* http://msdn.microsoft.com/en-us/library/bb969719.aspx */
3260 pa_streq(sig.text, "Microsoft Hv"))
3261 return TRUE;
3263 #endif
3265 return FALSE;