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