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