]> code.delx.au - pulseaudio/blob - src/pulsecore/core-util.c
core-util: make sure to enable FD_CLOEXEC unconditionally to cope with kernels that...
[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 = pa_open_cloexec(fn, O_CREAT|O_RDWR
1204 #ifdef O_NOFOLLOW
1205 |O_NOFOLLOW
1206 #endif
1207 , S_IRUSR|S_IWUSR)) < 0) {
1208 pa_log_warn("Failed to create lock file '%s': %s", fn, pa_cstrerror(errno));
1209 goto fail;
1210 }
1211
1212 if (pa_lock_fd(fd, 1) < 0) {
1213 pa_log_warn("Failed to lock file '%s'.", fn);
1214 goto fail;
1215 }
1216
1217 if (fstat(fd, &st) < 0) {
1218 pa_log_warn("Failed to fstat() file '%s': %s", fn, pa_cstrerror(errno));
1219 goto fail;
1220 }
1221
1222 /* Check whether the file has been removed meanwhile. When yes,
1223 * restart this loop, otherwise, we're done */
1224 if (st.st_nlink >= 1)
1225 break;
1226
1227 if (pa_lock_fd(fd, 0) < 0) {
1228 pa_log_warn("Failed to unlock file '%s'.", fn);
1229 goto fail;
1230 }
1231
1232 if (pa_close(fd) < 0) {
1233 pa_log_warn("Failed to close file '%s': %s", fn, pa_cstrerror(errno));
1234 fd = -1;
1235 goto fail;
1236 }
1237 }
1238
1239 return fd;
1240
1241 fail:
1242
1243 if (fd >= 0) {
1244 int saved_errno = errno;
1245 pa_close(fd);
1246 errno = saved_errno;
1247 }
1248
1249 return -1;
1250 }
1251
1252 /* Unlock a temporary lcok file */
1253 int pa_unlock_lockfile(const char *fn, int fd) {
1254 int r = 0;
1255 pa_assert(fd >= 0);
1256
1257 if (fn) {
1258 if (unlink(fn) < 0) {
1259 pa_log_warn("Unable to remove lock file '%s': %s", fn, pa_cstrerror(errno));
1260 r = -1;
1261 }
1262 }
1263
1264 if (pa_lock_fd(fd, 0) < 0) {
1265 pa_log_warn("Failed to unlock file '%s'.", fn);
1266 r = -1;
1267 }
1268
1269 if (pa_close(fd) < 0) {
1270 pa_log_warn("Failed to close '%s': %s", fn, pa_cstrerror(errno));
1271 r = -1;
1272 }
1273
1274 return r;
1275 }
1276
1277 static char *get_pulse_home(void) {
1278 char *h;
1279 struct stat st;
1280 char *ret = NULL;
1281
1282 if (!(h = pa_get_home_dir_malloc())) {
1283 pa_log_error("Failed to get home directory.");
1284 return NULL;
1285 }
1286
1287 if (stat(h, &st) < 0) {
1288 pa_log_error("Failed to stat home directory %s: %s", h, pa_cstrerror(errno));
1289 goto finish;
1290 }
1291
1292 if (st.st_uid != getuid()) {
1293 pa_log_error("Home directory %s not ours.", h);
1294 errno = EACCES;
1295 goto finish;
1296 }
1297
1298 ret = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse", h);
1299
1300 finish:
1301 pa_xfree(h);
1302
1303 return ret;
1304 }
1305
1306 char *pa_get_state_dir(void) {
1307 char *d;
1308
1309 /* The state directory shall contain dynamic data that should be
1310 * kept across reboots, and is private to this user */
1311
1312 if (!(d = pa_xstrdup(getenv("PULSE_STATE_PATH"))))
1313 if (!(d = get_pulse_home()))
1314 return NULL;
1315
1316 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1317 * dir then this will break. */
1318
1319 if (pa_make_secure_dir(d, 0700U, (uid_t) -1, (gid_t) -1) < 0) {
1320 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1321 pa_xfree(d);
1322 return NULL;
1323 }
1324
1325 return d;
1326 }
1327
1328 char *pa_get_home_dir_malloc(void) {
1329 char *homedir;
1330 size_t allocated = 128;
1331
1332 for (;;) {
1333 homedir = pa_xmalloc(allocated);
1334
1335 if (!pa_get_home_dir(homedir, allocated)) {
1336 pa_xfree(homedir);
1337 return NULL;
1338 }
1339
1340 if (strlen(homedir) < allocated - 1)
1341 break;
1342
1343 pa_xfree(homedir);
1344 allocated *= 2;
1345 }
1346
1347 return homedir;
1348 }
1349
1350 char *pa_get_binary_name_malloc(void) {
1351 char *t;
1352 size_t allocated = 128;
1353
1354 for (;;) {
1355 t = pa_xmalloc(allocated);
1356
1357 if (!pa_get_binary_name(t, allocated)) {
1358 pa_xfree(t);
1359 return NULL;
1360 }
1361
1362 if (strlen(t) < allocated - 1)
1363 break;
1364
1365 pa_xfree(t);
1366 allocated *= 2;
1367 }
1368
1369 return t;
1370 }
1371
1372 static char* make_random_dir(mode_t m) {
1373 static const char table[] =
1374 "abcdefghijklmnopqrstuvwxyz"
1375 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1376 "0123456789";
1377
1378 char *fn;
1379 size_t pathlen;
1380
1381 fn = pa_sprintf_malloc("%s" PA_PATH_SEP "pulse-XXXXXXXXXXXX", pa_get_temp_dir());
1382 pathlen = strlen(fn);
1383
1384 for (;;) {
1385 size_t i;
1386 int r;
1387 mode_t u;
1388 int saved_errno;
1389
1390 for (i = pathlen - 12; i < pathlen; i++)
1391 fn[i] = table[rand() % (sizeof(table)-1)];
1392
1393 u = umask((~m) & 0777);
1394 r = mkdir(fn, m);
1395
1396 saved_errno = errno;
1397 umask(u);
1398 errno = saved_errno;
1399
1400 if (r >= 0)
1401 return fn;
1402
1403 if (errno != EEXIST) {
1404 pa_log_error("Failed to create random directory %s: %s", fn, pa_cstrerror(errno));
1405 pa_xfree(fn);
1406 return NULL;
1407 }
1408 }
1409 }
1410
1411 static int make_random_dir_and_link(mode_t m, const char *k) {
1412 char *p;
1413
1414 if (!(p = make_random_dir(m)))
1415 return -1;
1416
1417 if (symlink(p, k) < 0) {
1418 int saved_errno = errno;
1419
1420 if (errno != EEXIST)
1421 pa_log_error("Failed to symlink %s to %s: %s", k, p, pa_cstrerror(errno));
1422
1423 rmdir(p);
1424 pa_xfree(p);
1425
1426 errno = saved_errno;
1427 return -1;
1428 }
1429
1430 pa_xfree(p);
1431 return 0;
1432 }
1433
1434 char *pa_get_runtime_dir(void) {
1435 char *d, *k = NULL, *p = NULL, *t = NULL, *mid;
1436 struct stat st;
1437 mode_t m;
1438
1439 /* The runtime directory shall contain dynamic data that needs NOT
1440 * to be kept accross reboots and is usuallly private to the user,
1441 * except in system mode, where it might be accessible by other
1442 * users, too. Since we need POSIX locking and UNIX sockets in
1443 * this directory, we link it to a random subdir in /tmp, if it
1444 * was not explicitly configured. */
1445
1446 m = pa_in_system_mode() ? 0755U : 0700U;
1447
1448 if ((d = getenv("PULSE_RUNTIME_PATH"))) {
1449
1450 if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0) {
1451 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1452 goto fail;
1453 }
1454
1455 return pa_xstrdup(d);
1456 }
1457
1458 if (!(d = get_pulse_home()))
1459 goto fail;
1460
1461 if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0) {
1462 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1463 pa_xfree(d);
1464 goto fail;
1465 }
1466
1467 if (!(mid = pa_machine_id())) {
1468 pa_xfree(d);
1469 goto fail;
1470 }
1471
1472 k = pa_sprintf_malloc("%s" PA_PATH_SEP "%s-runtime", d, mid);
1473 pa_xfree(d);
1474 pa_xfree(mid);
1475
1476 for (;;) {
1477 /* OK, first let's check if the "runtime" symlink is already
1478 * existant */
1479
1480 if (!(p = pa_readlink(k))) {
1481
1482 if (errno != ENOENT) {
1483 pa_log_error("Failed to stat runtime directory %s: %s", k, pa_cstrerror(errno));
1484 goto fail;
1485 }
1486
1487 /* Hmm, so the runtime directory didn't exist yet, so let's
1488 * create one in /tmp and symlink that to it */
1489
1490 if (make_random_dir_and_link(0700, k) < 0) {
1491
1492 /* Mhmm, maybe another process was quicker than us,
1493 * let's check if that was valid */
1494 if (errno == EEXIST)
1495 continue;
1496
1497 goto fail;
1498 }
1499
1500 return k;
1501 }
1502
1503 /* Make sure that this actually makes sense */
1504 if (!pa_is_path_absolute(p)) {
1505 pa_log_error("Path %s in link %s is not absolute.", p, k);
1506 errno = ENOENT;
1507 goto fail;
1508 }
1509
1510 /* Hmm, so this symlink is still around, make sure nobody fools
1511 * us */
1512
1513 if (lstat(p, &st) < 0) {
1514
1515 if (errno != ENOENT) {
1516 pa_log_error("Failed to stat runtime directory %s: %s", p, pa_cstrerror(errno));
1517 goto fail;
1518 }
1519
1520 } else {
1521
1522 if (S_ISDIR(st.st_mode) &&
1523 (st.st_uid == getuid()) &&
1524 ((st.st_mode & 0777) == 0700)) {
1525
1526 pa_xfree(p);
1527 return k;
1528 }
1529
1530 pa_log_info("Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory.");
1531 }
1532
1533 pa_xfree(p);
1534 p = NULL;
1535
1536 /* Hmm, so the link points to some nonexisting or invalid
1537 * dir. Let's replace it by a new link. We first create a
1538 * temporary link and then rename that to allow concurrent
1539 * execution of this function. */
1540
1541 t = pa_sprintf_malloc("%s.tmp", k);
1542
1543 if (make_random_dir_and_link(0700, t) < 0) {
1544
1545 if (errno != EEXIST) {
1546 pa_log_error("Failed to symlink %s: %s", t, pa_cstrerror(errno));
1547 goto fail;
1548 }
1549
1550 pa_xfree(t);
1551 t = NULL;
1552
1553 /* Hmm, someone lese was quicker then us. Let's give
1554 * him some time to finish, and retry. */
1555 pa_msleep(10);
1556 continue;
1557 }
1558
1559 /* OK, we succeeded in creating the temporary symlink, so
1560 * let's rename it */
1561 if (rename(t, k) < 0) {
1562 pa_log_error("Failed to rename %s to %s: %s", t, k, pa_cstrerror(errno));
1563 goto fail;
1564 }
1565
1566 pa_xfree(t);
1567 return k;
1568 }
1569
1570 fail:
1571 pa_xfree(p);
1572 pa_xfree(k);
1573 pa_xfree(t);
1574
1575 return NULL;
1576 }
1577
1578 /* Try to open a configuration file. If "env" is specified, open the
1579 * value of the specified environment variable. Otherwise look for a
1580 * file "local" in the home directory or a file "global" in global
1581 * file system. If "result" is non-NULL, a pointer to a newly
1582 * allocated buffer containing the used configuration file is
1583 * stored there.*/
1584 FILE *pa_open_config_file(const char *global, const char *local, const char *env, char **result) {
1585 const char *fn;
1586 #ifdef OS_IS_WIN32
1587 char buf[PATH_MAX];
1588
1589 if (!getenv(PULSE_ROOTENV))
1590 pa_set_root(NULL);
1591 #endif
1592
1593 if (env && (fn = getenv(env))) {
1594 FILE *f;
1595
1596 #ifdef OS_IS_WIN32
1597 if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
1598 /* FIXME: Needs to set errno! */
1599 return NULL;
1600 fn = buf;
1601 #endif
1602
1603 if ((f = fopen(fn, "r"))) {
1604 if (result)
1605 *result = pa_xstrdup(fn);
1606
1607 return f;
1608 }
1609
1610 pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
1611 return NULL;
1612 }
1613
1614 if (local) {
1615 const char *e;
1616 char *lfn;
1617 char *h;
1618 FILE *f;
1619
1620 if ((e = getenv("PULSE_CONFIG_PATH")))
1621 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
1622 else if ((h = pa_get_home_dir_malloc())) {
1623 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
1624 pa_xfree(h);
1625 } else
1626 return NULL;
1627
1628 #ifdef OS_IS_WIN32
1629 if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) {
1630 /* FIXME: Needs to set errno! */
1631 pa_xfree(lfn);
1632 return NULL;
1633 }
1634 fn = buf;
1635 #endif
1636
1637 if ((f = fopen(fn, "r"))) {
1638 if (result)
1639 *result = pa_xstrdup(fn);
1640
1641 pa_xfree(lfn);
1642 return f;
1643 }
1644
1645 if (errno != ENOENT) {
1646 pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
1647 pa_xfree(lfn);
1648 return NULL;
1649 }
1650
1651 pa_xfree(lfn);
1652 }
1653
1654 if (global) {
1655 FILE *f;
1656
1657 #ifdef OS_IS_WIN32
1658 if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
1659 /* FIXME: Needs to set errno! */
1660 return NULL;
1661 global = buf;
1662 #endif
1663
1664 if ((f = fopen(global, "r"))) {
1665
1666 if (result)
1667 *result = pa_xstrdup(global);
1668
1669 return f;
1670 }
1671 }
1672
1673 errno = ENOENT;
1674 return NULL;
1675 }
1676
1677 char *pa_find_config_file(const char *global, const char *local, const char *env) {
1678 const char *fn;
1679 #ifdef OS_IS_WIN32
1680 char buf[PATH_MAX];
1681
1682 if (!getenv(PULSE_ROOTENV))
1683 pa_set_root(NULL);
1684 #endif
1685
1686 if (env && (fn = getenv(env))) {
1687
1688 #ifdef OS_IS_WIN32
1689 if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
1690 /* FIXME: Needs to set errno! */
1691 return NULL;
1692 fn = buf;
1693 #endif
1694
1695 if (access(fn, R_OK) == 0)
1696 return pa_xstrdup(fn);
1697
1698 pa_log_warn("Failed to access configuration file '%s': %s", fn, pa_cstrerror(errno));
1699 return NULL;
1700 }
1701
1702 if (local) {
1703 const char *e;
1704 char *lfn;
1705 char *h;
1706
1707 if ((e = getenv("PULSE_CONFIG_PATH")))
1708 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
1709 else if ((h = pa_get_home_dir_malloc())) {
1710 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
1711 pa_xfree(h);
1712 } else
1713 return NULL;
1714
1715 #ifdef OS_IS_WIN32
1716 if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) {
1717 /* FIXME: Needs to set errno! */
1718 pa_xfree(lfn);
1719 return NULL;
1720 }
1721 fn = buf;
1722 #endif
1723
1724 if (access(fn, R_OK) == 0) {
1725 char *r = pa_xstrdup(fn);
1726 pa_xfree(lfn);
1727 return r;
1728 }
1729
1730 if (errno != ENOENT) {
1731 pa_log_warn("Failed to access configuration file '%s': %s", fn, pa_cstrerror(errno));
1732 pa_xfree(lfn);
1733 return NULL;
1734 }
1735
1736 pa_xfree(lfn);
1737 }
1738
1739 if (global) {
1740 #ifdef OS_IS_WIN32
1741 if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
1742 /* FIXME: Needs to set errno! */
1743 return NULL;
1744 global = buf;
1745 #endif
1746
1747 if (access(global, R_OK) == 0)
1748 return pa_xstrdup(global);
1749 }
1750
1751 errno = ENOENT;
1752
1753 return NULL;
1754 }
1755
1756 /* Format the specified data as a hexademical string */
1757 char *pa_hexstr(const uint8_t* d, size_t dlength, char *s, size_t slength) {
1758 size_t i = 0, j = 0;
1759 const char hex[] = "0123456789abcdef";
1760
1761 pa_assert(d);
1762 pa_assert(s);
1763 pa_assert(slength > 0);
1764
1765 while (i < dlength && j+3 <= slength) {
1766 s[j++] = hex[*d >> 4];
1767 s[j++] = hex[*d & 0xF];
1768
1769 d++;
1770 i++;
1771 }
1772
1773 s[j < slength ? j : slength] = 0;
1774 return s;
1775 }
1776
1777 /* Convert a hexadecimal digit to a number or -1 if invalid */
1778 static int hexc(char c) {
1779 if (c >= '0' && c <= '9')
1780 return c - '0';
1781
1782 if (c >= 'A' && c <= 'F')
1783 return c - 'A' + 10;
1784
1785 if (c >= 'a' && c <= 'f')
1786 return c - 'a' + 10;
1787
1788 errno = EINVAL;
1789 return -1;
1790 }
1791
1792 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1793 size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength) {
1794 size_t j = 0;
1795
1796 pa_assert(p);
1797 pa_assert(d);
1798
1799 while (j < dlength && *p) {
1800 int b;
1801
1802 if ((b = hexc(*(p++))) < 0)
1803 return (size_t) -1;
1804
1805 d[j] = (uint8_t) (b << 4);
1806
1807 if (!*p)
1808 return (size_t) -1;
1809
1810 if ((b = hexc(*(p++))) < 0)
1811 return (size_t) -1;
1812
1813 d[j] |= (uint8_t) b;
1814 j++;
1815 }
1816
1817 return j;
1818 }
1819
1820 /* Returns nonzero when *s starts with *pfx */
1821 pa_bool_t pa_startswith(const char *s, const char *pfx) {
1822 size_t l;
1823
1824 pa_assert(s);
1825 pa_assert(pfx);
1826
1827 l = strlen(pfx);
1828
1829 return strlen(s) >= l && strncmp(s, pfx, l) == 0;
1830 }
1831
1832 /* Returns nonzero when *s ends with *sfx */
1833 pa_bool_t pa_endswith(const char *s, const char *sfx) {
1834 size_t l1, l2;
1835
1836 pa_assert(s);
1837 pa_assert(sfx);
1838
1839 l1 = strlen(s);
1840 l2 = strlen(sfx);
1841
1842 return l1 >= l2 && strcmp(s+l1-l2, sfx) == 0;
1843 }
1844
1845 pa_bool_t pa_is_path_absolute(const char *fn) {
1846 pa_assert(fn);
1847
1848 #ifndef OS_IS_WIN32
1849 return *fn == '/';
1850 #else
1851 return strlen(fn) >= 3 && isalpha(fn[0]) && fn[1] == ':' && fn[2] == '\\';
1852 #endif
1853 }
1854
1855 char *pa_make_path_absolute(const char *p) {
1856 char *r;
1857 char *cwd;
1858
1859 pa_assert(p);
1860
1861 if (pa_is_path_absolute(p))
1862 return pa_xstrdup(p);
1863
1864 if (!(cwd = pa_getcwd()))
1865 return pa_xstrdup(p);
1866
1867 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", cwd, p);
1868 pa_xfree(cwd);
1869 return r;
1870 }
1871
1872 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1873 * if fn is non-null and starts with / return fn
1874 * otherwise append fn to the run time path and return it */
1875 static char *get_path(const char *fn, pa_bool_t prependmid, pa_bool_t rt) {
1876 char *rtp;
1877
1878 rtp = rt ? pa_get_runtime_dir() : pa_get_state_dir();
1879
1880 if (fn) {
1881 char *r;
1882
1883 if (pa_is_path_absolute(fn))
1884 return pa_xstrdup(fn);
1885
1886 if (!rtp)
1887 return NULL;
1888
1889 if (prependmid) {
1890 char *mid;
1891
1892 if (!(mid = pa_machine_id())) {
1893 pa_xfree(rtp);
1894 return NULL;
1895 }
1896
1897 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s-%s", rtp, mid, fn);
1898 pa_xfree(mid);
1899 } else
1900 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", rtp, fn);
1901
1902 pa_xfree(rtp);
1903 return r;
1904 } else
1905 return rtp;
1906 }
1907
1908 char *pa_runtime_path(const char *fn) {
1909 return get_path(fn, FALSE, TRUE);
1910 }
1911
1912 char *pa_state_path(const char *fn, pa_bool_t appendmid) {
1913 return get_path(fn, appendmid, FALSE);
1914 }
1915
1916 /* Convert the string s to a signed integer in *ret_i */
1917 int pa_atoi(const char *s, int32_t *ret_i) {
1918 char *x = NULL;
1919 long l;
1920
1921 pa_assert(s);
1922 pa_assert(ret_i);
1923
1924 errno = 0;
1925 l = strtol(s, &x, 0);
1926
1927 if (!x || *x || errno) {
1928 if (!errno)
1929 errno = EINVAL;
1930 return -1;
1931 }
1932
1933 if ((int32_t) l != l) {
1934 errno = ERANGE;
1935 return -1;
1936 }
1937
1938 *ret_i = (int32_t) l;
1939
1940 return 0;
1941 }
1942
1943 /* Convert the string s to an unsigned integer in *ret_u */
1944 int pa_atou(const char *s, uint32_t *ret_u) {
1945 char *x = NULL;
1946 unsigned long l;
1947
1948 pa_assert(s);
1949 pa_assert(ret_u);
1950
1951 errno = 0;
1952 l = strtoul(s, &x, 0);
1953
1954 if (!x || *x || errno) {
1955 if (!errno)
1956 errno = EINVAL;
1957 return -1;
1958 }
1959
1960 if ((uint32_t) l != l) {
1961 errno = ERANGE;
1962 return -1;
1963 }
1964
1965 *ret_u = (uint32_t) l;
1966
1967 return 0;
1968 }
1969
1970 #ifdef HAVE_STRTOF_L
1971 static locale_t c_locale = NULL;
1972
1973 static void c_locale_destroy(void) {
1974 freelocale(c_locale);
1975 }
1976 #endif
1977
1978 int pa_atod(const char *s, double *ret_d) {
1979 char *x = NULL;
1980 double f;
1981
1982 pa_assert(s);
1983 pa_assert(ret_d);
1984
1985 /* This should be locale independent */
1986
1987 #ifdef HAVE_STRTOF_L
1988
1989 PA_ONCE_BEGIN {
1990
1991 if ((c_locale = newlocale(LC_ALL_MASK, "C", NULL)))
1992 atexit(c_locale_destroy);
1993
1994 } PA_ONCE_END;
1995
1996 if (c_locale) {
1997 errno = 0;
1998 f = strtod_l(s, &x, c_locale);
1999 } else
2000 #endif
2001 {
2002 errno = 0;
2003 f = strtod(s, &x);
2004 }
2005
2006 if (!x || *x || errno) {
2007 if (!errno)
2008 errno = EINVAL;
2009 return -1;
2010 }
2011
2012 *ret_d = f;
2013
2014 return 0;
2015 }
2016
2017 /* Same as snprintf, but guarantees NUL-termination on every platform */
2018 size_t pa_snprintf(char *str, size_t size, const char *format, ...) {
2019 size_t ret;
2020 va_list ap;
2021
2022 pa_assert(str);
2023 pa_assert(size > 0);
2024 pa_assert(format);
2025
2026 va_start(ap, format);
2027 ret = pa_vsnprintf(str, size, format, ap);
2028 va_end(ap);
2029
2030 return ret;
2031 }
2032
2033 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2034 size_t pa_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
2035 int ret;
2036
2037 pa_assert(str);
2038 pa_assert(size > 0);
2039 pa_assert(format);
2040
2041 ret = vsnprintf(str, size, format, ap);
2042
2043 str[size-1] = 0;
2044
2045 if (ret < 0)
2046 return strlen(str);
2047
2048 if ((size_t) ret > size-1)
2049 return size-1;
2050
2051 return (size_t) ret;
2052 }
2053
2054 /* Truncate the specified string, but guarantee that the string
2055 * returned still validates as UTF8 */
2056 char *pa_truncate_utf8(char *c, size_t l) {
2057 pa_assert(c);
2058 pa_assert(pa_utf8_valid(c));
2059
2060 if (strlen(c) <= l)
2061 return c;
2062
2063 c[l] = 0;
2064
2065 while (l > 0 && !pa_utf8_valid(c))
2066 c[--l] = 0;
2067
2068 return c;
2069 }
2070
2071 char *pa_getcwd(void) {
2072 size_t l = 128;
2073
2074 for (;;) {
2075 char *p = pa_xmalloc(l);
2076 if (getcwd(p, l))
2077 return p;
2078
2079 if (errno != ERANGE)
2080 return NULL;
2081
2082 pa_xfree(p);
2083 l *= 2;
2084 }
2085 }
2086
2087 void *pa_will_need(const void *p, size_t l) {
2088 #ifdef RLIMIT_MEMLOCK
2089 struct rlimit rlim;
2090 #endif
2091 const void *a;
2092 size_t size;
2093 int r;
2094 size_t bs;
2095
2096 pa_assert(p);
2097 pa_assert(l > 0);
2098
2099 a = PA_PAGE_ALIGN_PTR(p);
2100 size = (size_t) ((const uint8_t*) p + l - (const uint8_t*) a);
2101
2102 #ifdef HAVE_POSIX_MADVISE
2103 if ((r = posix_madvise((void*) a, size, POSIX_MADV_WILLNEED)) == 0) {
2104 pa_log_debug("posix_madvise() worked fine!");
2105 return (void*) p;
2106 }
2107 #endif
2108
2109 /* Most likely the memory was not mmap()ed from a file and thus
2110 * madvise() didn't work, so let's misuse mlock() do page this
2111 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2112 * inviting, the man page of mlock() tells us: "All pages that
2113 * contain a part of the specified address range are guaranteed to
2114 * be resident in RAM when the call returns successfully." */
2115
2116 #ifdef RLIMIT_MEMLOCK
2117 pa_assert_se(getrlimit(RLIMIT_MEMLOCK, &rlim) == 0);
2118
2119 if (rlim.rlim_cur < PA_PAGE_SIZE) {
2120 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));
2121 errno = EPERM;
2122 return (void*) p;
2123 }
2124
2125 bs = PA_PAGE_ALIGN((size_t) rlim.rlim_cur);
2126 #else
2127 bs = PA_PAGE_SIZE*4;
2128 #endif
2129
2130 pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r));
2131
2132 #ifdef HAVE_MLOCK
2133 while (size > 0 && bs > 0) {
2134
2135 if (bs > size)
2136 bs = size;
2137
2138 if (mlock(a, bs) < 0) {
2139 bs = PA_PAGE_ALIGN(bs / 2);
2140 continue;
2141 }
2142
2143 pa_assert_se(munlock(a, bs) == 0);
2144
2145 a = (const uint8_t*) a + bs;
2146 size -= bs;
2147 }
2148 #endif
2149
2150 if (bs <= 0)
2151 pa_log_debug("mlock() failed too (or doesn't exist), giving up: %s", pa_cstrerror(errno));
2152 else
2153 pa_log_debug("mlock() worked fine!");
2154
2155 return (void*) p;
2156 }
2157
2158 void pa_close_pipe(int fds[2]) {
2159 pa_assert(fds);
2160
2161 if (fds[0] >= 0)
2162 pa_assert_se(pa_close(fds[0]) == 0);
2163
2164 if (fds[1] >= 0)
2165 pa_assert_se(pa_close(fds[1]) == 0);
2166
2167 fds[0] = fds[1] = -1;
2168 }
2169
2170 char *pa_readlink(const char *p) {
2171 size_t l = 100;
2172
2173 for (;;) {
2174 char *c;
2175 ssize_t n;
2176
2177 c = pa_xmalloc(l);
2178
2179 if ((n = readlink(p, c, l-1)) < 0) {
2180 pa_xfree(c);
2181 return NULL;
2182 }
2183
2184 if ((size_t) n < l-1) {
2185 c[n] = 0;
2186 return c;
2187 }
2188
2189 pa_xfree(c);
2190 l *= 2;
2191 }
2192 }
2193
2194 int pa_close_all(int except_fd, ...) {
2195 va_list ap;
2196 unsigned n = 0, i;
2197 int r, *p;
2198
2199 va_start(ap, except_fd);
2200
2201 if (except_fd >= 0)
2202 for (n = 1; va_arg(ap, int) >= 0; n++)
2203 ;
2204
2205 va_end(ap);
2206
2207 p = pa_xnew(int, n+1);
2208
2209 va_start(ap, except_fd);
2210
2211 i = 0;
2212 if (except_fd >= 0) {
2213 int fd;
2214 p[i++] = except_fd;
2215
2216 while ((fd = va_arg(ap, int)) >= 0)
2217 p[i++] = fd;
2218 }
2219 p[i] = -1;
2220
2221 va_end(ap);
2222
2223 r = pa_close_allv(p);
2224 pa_xfree(p);
2225
2226 return r;
2227 }
2228
2229 int pa_close_allv(const int except_fds[]) {
2230 struct rlimit rl;
2231 int maxfd, fd;
2232
2233 #ifdef __linux__
2234 int saved_errno;
2235 DIR *d;
2236
2237 if ((d = opendir("/proc/self/fd"))) {
2238
2239 struct dirent *de;
2240
2241 while ((de = readdir(d))) {
2242 pa_bool_t found;
2243 long l;
2244 char *e = NULL;
2245 int i;
2246
2247 if (de->d_name[0] == '.')
2248 continue;
2249
2250 errno = 0;
2251 l = strtol(de->d_name, &e, 10);
2252 if (errno != 0 || !e || *e) {
2253 closedir(d);
2254 errno = EINVAL;
2255 return -1;
2256 }
2257
2258 fd = (int) l;
2259
2260 if ((long) fd != l) {
2261 closedir(d);
2262 errno = EINVAL;
2263 return -1;
2264 }
2265
2266 if (fd < 3)
2267 continue;
2268
2269 if (fd == dirfd(d))
2270 continue;
2271
2272 found = FALSE;
2273 for (i = 0; except_fds[i] >= 0; i++)
2274 if (except_fds[i] == fd) {
2275 found = TRUE;
2276 break;
2277 }
2278
2279 if (found)
2280 continue;
2281
2282 if (pa_close(fd) < 0) {
2283 saved_errno = errno;
2284 closedir(d);
2285 errno = saved_errno;
2286
2287 return -1;
2288 }
2289 }
2290
2291 closedir(d);
2292 return 0;
2293 }
2294
2295 #endif
2296
2297 if (getrlimit(RLIMIT_NOFILE, &rl) >= 0)
2298 maxfd = (int) rl.rlim_max;
2299 else
2300 maxfd = sysconf(_SC_OPEN_MAX);
2301
2302 for (fd = 3; fd < maxfd; fd++) {
2303 int i;
2304 pa_bool_t found;
2305
2306 found = FALSE;
2307 for (i = 0; except_fds[i] >= 0; i++)
2308 if (except_fds[i] == fd) {
2309 found = TRUE;
2310 break;
2311 }
2312
2313 if (found)
2314 continue;
2315
2316 if (pa_close(fd) < 0 && errno != EBADF)
2317 return -1;
2318 }
2319
2320 return 0;
2321 }
2322
2323 int pa_unblock_sigs(int except, ...) {
2324 va_list ap;
2325 unsigned n = 0, i;
2326 int r, *p;
2327
2328 va_start(ap, except);
2329
2330 if (except >= 1)
2331 for (n = 1; va_arg(ap, int) >= 0; n++)
2332 ;
2333
2334 va_end(ap);
2335
2336 p = pa_xnew(int, n+1);
2337
2338 va_start(ap, except);
2339
2340 i = 0;
2341 if (except >= 1) {
2342 int sig;
2343 p[i++] = except;
2344
2345 while ((sig = va_arg(ap, int)) >= 0)
2346 p[i++] = sig;
2347 }
2348 p[i] = -1;
2349
2350 va_end(ap);
2351
2352 r = pa_unblock_sigsv(p);
2353 pa_xfree(p);
2354
2355 return r;
2356 }
2357
2358 int pa_unblock_sigsv(const int except[]) {
2359 int i;
2360 sigset_t ss;
2361
2362 if (sigemptyset(&ss) < 0)
2363 return -1;
2364
2365 for (i = 0; except[i] > 0; i++)
2366 if (sigaddset(&ss, except[i]) < 0)
2367 return -1;
2368
2369 return sigprocmask(SIG_SETMASK, &ss, NULL);
2370 }
2371
2372 int pa_reset_sigs(int except, ...) {
2373 va_list ap;
2374 unsigned n = 0, i;
2375 int *p, r;
2376
2377 va_start(ap, except);
2378
2379 if (except >= 1)
2380 for (n = 1; va_arg(ap, int) >= 0; n++)
2381 ;
2382
2383 va_end(ap);
2384
2385 p = pa_xnew(int, n+1);
2386
2387 va_start(ap, except);
2388
2389 i = 0;
2390 if (except >= 1) {
2391 int sig;
2392 p[i++] = except;
2393
2394 while ((sig = va_arg(ap, int)) >= 0)
2395 p[i++] = sig;
2396 }
2397 p[i] = -1;
2398
2399 va_end(ap);
2400
2401 r = pa_reset_sigsv(p);
2402 pa_xfree(p);
2403
2404 return r;
2405 }
2406
2407 int pa_reset_sigsv(const int except[]) {
2408 int sig;
2409
2410 for (sig = 1; sig < NSIG; sig++) {
2411 pa_bool_t reset = TRUE;
2412
2413 switch (sig) {
2414 case SIGKILL:
2415 case SIGSTOP:
2416 reset = FALSE;
2417 break;
2418
2419 default: {
2420 int i;
2421
2422 for (i = 0; except[i] > 0; i++) {
2423 if (sig == except[i]) {
2424 reset = FALSE;
2425 break;
2426 }
2427 }
2428 }
2429 }
2430
2431 if (reset) {
2432 struct sigaction sa;
2433
2434 memset(&sa, 0, sizeof(sa));
2435 sa.sa_handler = SIG_DFL;
2436
2437 /* On Linux the first two RT signals are reserved by
2438 * glibc, and sigaction() will return EINVAL for them. */
2439 if ((sigaction(sig, &sa, NULL) < 0))
2440 if (errno != EINVAL)
2441 return -1;
2442 }
2443 }
2444
2445 return 0;
2446 }
2447
2448 void pa_set_env(const char *key, const char *value) {
2449 pa_assert(key);
2450 pa_assert(value);
2451
2452 /* This is not thread-safe */
2453
2454 putenv(pa_sprintf_malloc("%s=%s", key, value));
2455 }
2456
2457 void pa_set_env_and_record(const char *key, const char *value) {
2458 pa_assert(key);
2459 pa_assert(value);
2460
2461 /* This is not thread-safe */
2462
2463 pa_set_env(key, value);
2464 recorded_env = pa_strlist_prepend(recorded_env, key);
2465 }
2466
2467 void pa_unset_env_recorded(void) {
2468
2469 /* This is not thread-safe */
2470
2471 for (;;) {
2472 char *s;
2473
2474 recorded_env = pa_strlist_pop(recorded_env, &s);
2475
2476 if (!s)
2477 break;
2478
2479 unsetenv(s);
2480 pa_xfree(s);
2481 }
2482 }
2483
2484 pa_bool_t pa_in_system_mode(void) {
2485 const char *e;
2486
2487 if (!(e = getenv("PULSE_SYSTEM")))
2488 return FALSE;
2489
2490 return !!atoi(e);
2491 }
2492
2493 char *pa_get_user_name_malloc(void) {
2494 ssize_t k;
2495 char *u;
2496
2497 #ifdef _SC_LOGIN_NAME_MAX
2498 k = (ssize_t) sysconf(_SC_LOGIN_NAME_MAX);
2499
2500 if (k <= 0)
2501 #endif
2502 k = 32;
2503
2504 u = pa_xnew(char, k+1);
2505
2506 if (!(pa_get_user_name(u, k))) {
2507 pa_xfree(u);
2508 return NULL;
2509 }
2510
2511 return u;
2512 }
2513
2514 char *pa_get_host_name_malloc(void) {
2515 size_t l;
2516
2517 l = 100;
2518 for (;;) {
2519 char *c;
2520
2521 c = pa_xmalloc(l);
2522
2523 if (!pa_get_host_name(c, l)) {
2524
2525 if (errno != EINVAL && errno != ENAMETOOLONG)
2526 break;
2527
2528 } else if (strlen(c) < l-1) {
2529 char *u;
2530
2531 if (*c == 0) {
2532 pa_xfree(c);
2533 break;
2534 }
2535
2536 u = pa_utf8_filter(c);
2537 pa_xfree(c);
2538 return u;
2539 }
2540
2541 /* Hmm, the hostname is as long the space we offered the
2542 * function, we cannot know if it fully fit in, so let's play
2543 * safe and retry. */
2544
2545 pa_xfree(c);
2546 l *= 2;
2547 }
2548
2549 return NULL;
2550 }
2551
2552 char *pa_machine_id(void) {
2553 FILE *f;
2554 char *h;
2555
2556 /* The returned value is supposed be some kind of ascii identifier
2557 * that is unique and stable across reboots. */
2558
2559 /* First we try the D-Bus UUID, which is the best option we have,
2560 * since it fits perfectly our needs and is not as volatile as the
2561 * hostname which might be set from dhcp. */
2562
2563 if ((f = fopen(PA_MACHINE_ID, "r"))) {
2564 char ln[34] = "", *r;
2565
2566 r = fgets(ln, sizeof(ln)-1, f);
2567 fclose(f);
2568
2569 pa_strip_nl(ln);
2570
2571 if (r && ln[0])
2572 return pa_utf8_filter(ln);
2573 }
2574
2575 if ((h = pa_get_host_name_malloc()))
2576 return h;
2577
2578 /* If no hostname was set we use the POSIX hostid. It's usually
2579 * the IPv4 address. Might not be that stable. */
2580 return pa_sprintf_malloc("%08lx", (unsigned long) gethostid);
2581 }
2582
2583 char *pa_session_id(void) {
2584 const char *e;
2585
2586 if (!(e = getenv("XDG_SESSION_COOKIE")))
2587 return NULL;
2588
2589 return pa_utf8_filter(e);
2590 }
2591
2592 char *pa_uname_string(void) {
2593 struct utsname u;
2594
2595 pa_assert_se(uname(&u) >= 0);
2596
2597 return pa_sprintf_malloc("%s %s %s %s", u.sysname, u.machine, u.release, u.version);
2598 }
2599
2600 #ifdef HAVE_VALGRIND_MEMCHECK_H
2601 pa_bool_t pa_in_valgrind(void) {
2602 static int b = 0;
2603
2604 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2605 * here instead of really checking whether we run in valgrind or
2606 * not. */
2607
2608 if (b < 1)
2609 b = getenv("VALGRIND") ? 2 : 1;
2610
2611 return b > 1;
2612 }
2613 #endif
2614
2615 unsigned pa_gcd(unsigned a, unsigned b) {
2616
2617 while (b > 0) {
2618 unsigned t = b;
2619 b = a % b;
2620 a = t;
2621 }
2622
2623 return a;
2624 }
2625
2626 void pa_reduce(unsigned *num, unsigned *den) {
2627
2628 unsigned gcd = pa_gcd(*num, *den);
2629
2630 if (gcd <= 0)
2631 return;
2632
2633 *num /= gcd;
2634 *den /= gcd;
2635
2636 pa_assert(pa_gcd(*num, *den) == 1);
2637 }
2638
2639 unsigned pa_ncpus(void) {
2640 long ncpus;
2641
2642 #ifdef _SC_NPROCESSORS_CONF
2643 ncpus = sysconf(_SC_NPROCESSORS_CONF);
2644 #else
2645 ncpus = 1;
2646 #endif
2647
2648 return ncpus <= 0 ? 1 : (unsigned) ncpus;
2649 }
2650
2651 char *pa_replace(const char*s, const char*a, const char *b) {
2652 pa_strbuf *sb;
2653 size_t an;
2654
2655 pa_assert(s);
2656 pa_assert(a);
2657 pa_assert(b);
2658
2659 an = strlen(a);
2660 sb = pa_strbuf_new();
2661
2662 for (;;) {
2663 const char *p;
2664
2665 if (!(p = strstr(s, a)))
2666 break;
2667
2668 pa_strbuf_putsn(sb, s, p-s);
2669 pa_strbuf_puts(sb, b);
2670 s = p + an;
2671 }
2672
2673 pa_strbuf_puts(sb, s);
2674
2675 return pa_strbuf_tostring_free(sb);
2676 }
2677
2678 char *pa_escape(const char *p, const char *chars) {
2679 const char *s;
2680 const char *c;
2681 pa_strbuf *buf = pa_strbuf_new();
2682
2683 for (s = p; *s; ++s) {
2684 if (*s == '\\')
2685 pa_strbuf_putc(buf, '\\');
2686 else if (chars) {
2687 for (c = chars; *c; ++c) {
2688 if (*s == *c) {
2689 pa_strbuf_putc(buf, '\\');
2690 break;
2691 }
2692 }
2693 }
2694 pa_strbuf_putc(buf, *s);
2695 }
2696
2697 return pa_strbuf_tostring_free(buf);
2698 }
2699
2700 char *pa_unescape(char *p) {
2701 char *s, *d;
2702 pa_bool_t escaped = FALSE;
2703
2704 for (s = p, d = p; *s; s++) {
2705 if (!escaped && *s == '\\') {
2706 escaped = TRUE;
2707 continue;
2708 }
2709
2710 *(d++) = *s;
2711 escaped = FALSE;
2712 }
2713
2714 *d = 0;
2715
2716 return p;
2717 }
2718
2719 char *pa_realpath(const char *path) {
2720 char *t;
2721 pa_assert(path);
2722
2723 /* We want only abolsute paths */
2724 if (path[0] != '/') {
2725 errno = EINVAL;
2726 return NULL;
2727 }
2728
2729 #if defined(__GLIBC__) || defined(__APPLE__)
2730 {
2731 char *r;
2732
2733 if (!(r = realpath(path, NULL)))
2734 return NULL;
2735
2736 /* We copy this here in case our pa_xmalloc() is not
2737 * implemented on top of libc malloc() */
2738 t = pa_xstrdup(r);
2739 pa_xfree(r);
2740 }
2741 #elif defined(PATH_MAX)
2742 {
2743 char *path_buf;
2744 path_buf = pa_xmalloc(PATH_MAX);
2745
2746 if (!(t = realpath(path, path_buf))) {
2747 pa_xfree(path_buf);
2748 return NULL;
2749 }
2750 }
2751 #else
2752 #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."
2753 #endif
2754
2755 return t;
2756 }
2757
2758 void pa_disable_sigpipe(void) {
2759
2760 #ifdef SIGPIPE
2761 struct sigaction sa;
2762
2763 pa_zero(sa);
2764
2765 if (sigaction(SIGPIPE, NULL, &sa) < 0) {
2766 pa_log("sigaction(): %s", pa_cstrerror(errno));
2767 return;
2768 }
2769
2770 sa.sa_handler = SIG_IGN;
2771
2772 if (sigaction(SIGPIPE, &sa, NULL) < 0) {
2773 pa_log("sigaction(): %s", pa_cstrerror(errno));
2774 return;
2775 }
2776 #endif
2777 }
2778
2779 void pa_xfreev(void**a) {
2780 void **p;
2781
2782 if (!a)
2783 return;
2784
2785 for (p = a; *p; p++)
2786 pa_xfree(*p);
2787
2788 pa_xfree(a);
2789 }
2790
2791 char **pa_split_spaces_strv(const char *s) {
2792 char **t, *e;
2793 unsigned i = 0, n = 8;
2794 const char *state = NULL;
2795
2796 t = pa_xnew(char*, n);
2797 while ((e = pa_split_spaces(s, &state))) {
2798 t[i++] = e;
2799
2800 if (i >= n) {
2801 n *= 2;
2802 t = pa_xrenew(char*, t, n);
2803 }
2804 }
2805
2806 if (i <= 0) {
2807 pa_xfree(t);
2808 return NULL;
2809 }
2810
2811 t[i] = NULL;
2812 return t;
2813 }
2814
2815 char* pa_maybe_prefix_path(const char *path, const char *prefix) {
2816 pa_assert(path);
2817
2818 if (pa_is_path_absolute(path))
2819 return pa_xstrdup(path);
2820
2821 return pa_sprintf_malloc("%s" PA_PATH_SEP "%s", prefix, path);
2822 }
2823
2824 size_t pa_pipe_buf(int fd) {
2825
2826 #ifdef _PC_PIPE_BUF
2827 long n;
2828
2829 if ((n = fpathconf(fd, _PC_PIPE_BUF)) >= 0)
2830 return (size_t) n;
2831 #endif
2832
2833 #ifdef PIPE_BUF
2834 return PIPE_BUF;
2835 #else
2836 return 4096;
2837 #endif
2838 }
2839
2840 void pa_reset_personality(void) {
2841
2842 #ifdef __linux__
2843 if (personality(PER_LINUX) < 0)
2844 pa_log_warn("Uh, personality() failed: %s", pa_cstrerror(errno));
2845 #endif
2846
2847 }
2848
2849 #if defined(__linux__) && !defined(__OPTIMIZE__)
2850
2851 pa_bool_t pa_run_from_build_tree(void) {
2852 char *rp;
2853 pa_bool_t b = FALSE;
2854
2855 /* We abuse __OPTIMIZE__ as a check whether we are a debug build
2856 * or not. */
2857
2858 if ((rp = pa_readlink("/proc/self/exe"))) {
2859 b = pa_startswith(rp, PA_BUILDDIR);
2860 pa_xfree(rp);
2861 }
2862
2863 return b;
2864 }
2865
2866 #endif
2867
2868 const char *pa_get_temp_dir(void) {
2869 const char *t;
2870
2871 if ((t = getenv("TMPDIR")) &&
2872 pa_is_path_absolute(t))
2873 return t;
2874
2875 if ((t = getenv("TMP")) &&
2876 pa_is_path_absolute(t))
2877 return t;
2878
2879 if ((t = getenv("TEMP")) &&
2880 pa_is_path_absolute(t))
2881 return t;
2882
2883 if ((t = getenv("TEMPDIR")) &&
2884 pa_is_path_absolute(t))
2885 return t;
2886
2887 return "/tmp";
2888 }
2889
2890 int pa_open_cloexec(const char *fn, int flags, mode_t mode) {
2891 int fd;
2892
2893 #ifdef O_NOCTTY
2894 flags |= O_NOCTTY;
2895 #endif
2896
2897 #ifdef O_CLOEXEC
2898 if ((fd = open(fn, flags|O_CLOEXEC, mode)) >= 0)
2899 goto finish;
2900
2901 if (errno != EINVAL)
2902 return fd;
2903 #endif
2904
2905 if ((fd = open(fn, flags, mode)) < 0)
2906 return fd;
2907
2908 finish:
2909 /* Some implementations might simply ignore O_CLOEXEC if it is not
2910 * understood, make sure FD_CLOEXEC is enabled anyway */
2911
2912 pa_make_fd_cloexec(fd);
2913 return fd;
2914 }
2915
2916 int pa_socket_cloexec(int domain, int type, int protocol) {
2917 int fd;
2918
2919 #ifdef SOCK_CLOEXEC
2920 if ((fd = socket(domain, type | SOCK_CLOEXEC, protocol)) >= 0)
2921 goto finish;
2922
2923 if (errno != EINVAL)
2924 return fd;
2925 #endif
2926
2927 if ((fd = socket(domain, type, protocol)) < 0)
2928 return fd;
2929
2930 finish:
2931 /* Some implementations might simply ignore SOCK_CLOEXEC if it is
2932 * not understood, make sure FD_CLOEXEC is enabled anyway */
2933
2934 pa_make_fd_cloexec(fd);
2935 return fd;
2936 }
2937
2938 int pa_pipe_cloexec(int pipefd[2]) {
2939 int r;
2940
2941 #ifdef HAVE_PIPE2
2942 if ((r = pipe2(pipefd, O_CLOEXEC)) >= 0)
2943 goto finish;
2944
2945 if (errno != EINVAL && errno != ENOSYS)
2946 return r;
2947 #endif
2948
2949 if ((r = pipe(pipefd)) < 0)
2950 return r;
2951
2952 finish:
2953 pa_make_fd_cloexec(pipefd[0]);
2954 pa_make_fd_cloexec(pipefd[1]);
2955
2956 return 0;
2957 }
2958
2959 int pa_accept_cloexec(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
2960 int fd;
2961
2962 #ifdef HAVE_ACCEPT4
2963 if ((fd = accept4(sockfd, addr, addrlen, SOCK_CLOEXEC)) >= 0)
2964 return fd;
2965
2966 if (errno != EINVAL && errno != ENOSYS)
2967 return fd;
2968 #endif
2969
2970 if ((fd = accept(sockfd, addr, addrlen)) < 0)
2971 return fd;
2972
2973 pa_make_fd_cloexec(fd);
2974
2975 return 0;
2976 }