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