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