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