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