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