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