]> code.delx.au - pulseaudio/blob - src/pulsecore/core-util.c
core-util: add api for setting env vars and record them so that we can undo them...
[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 ((r = 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 ((r = 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 r = rtkit_make_realtime(bus, 0, rtprio);
616 dbus_connection_unref(bus);
617
618 if (r >= 0) {
619 pa_log_debug("RealtimeKit worked.");
620 return 0;
621 }
622
623 errno = -r;
624 #else
625 errno = r;
626 #endif
627
628 return -1;
629 }
630
631 /* Make the current thread a realtime thread, and acquire the highest
632 * rtprio we can get that is less or equal the specified parameter. If
633 * the thread is already realtime, don't do anything. */
634 int pa_make_realtime(int rtprio) {
635
636 #ifdef _POSIX_PRIORITY_SCHEDULING
637 int p;
638
639 if (set_scheduler(rtprio) >= 0) {
640 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i.", rtprio);
641 return 0;
642 }
643
644 for (p = rtprio-1; p >= 1; p--)
645 if (set_scheduler(p)) {
646 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i.", p, rtprio);
647 return 0;
648 }
649
650 pa_log_info("Failed to acquire real-time scheduling: %s", pa_cstrerror(errno));
651 return -1;
652 #else
653
654 errno = ENOTSUP;
655 return -1;
656 #endif
657 }
658
659 static int set_nice(int nice_level) {
660 #ifdef HAVE_DBUS
661 DBusError error;
662 DBusConnection *bus;
663 int r;
664
665 dbus_error_init(&error);
666 #endif
667
668 if (setpriority(PRIO_PROCESS, 0, nice_level) >= 0) {
669 pa_log_debug("setpriority() worked.");
670 return 0;
671 }
672
673 #ifdef HAVE_DBUS
674 /* Try to talk to RealtimeKit */
675
676 if (!(bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
677 pa_log("Failed to connect to system bus: %s\n", error.message);
678 dbus_error_free(&error);
679 errno = -EIO;
680 return -1;
681 }
682
683 r = rtkit_make_high_priority(bus, 0, nice_level);
684 dbus_connection_unref(bus);
685
686 if (r >= 0) {
687 pa_log_debug("RealtimeKit worked.");
688 return 0;
689 }
690
691 errno = -r;
692 #endif
693
694 return -1;
695 }
696
697 /* Raise the priority of the current process as much as possible that
698 * is <= the specified nice level..*/
699 int pa_raise_priority(int nice_level) {
700
701 #ifdef HAVE_SYS_RESOURCE_H
702 int n;
703
704 if (set_nice(nice_level) >= 0) {
705 pa_log_info("Successfully gained nice level %i.", nice_level);
706 return 0;
707 }
708
709 for (n = nice_level+1; n < 0; n++)
710 if (set_nice(n) > 0) {
711 pa_log_info("Successfully acquired nice level %i, which is lower than the requested %i.", n, nice_level);
712 return 0;
713 }
714
715 pa_log_info("Failed to acquire high-priority scheduling: %s", pa_cstrerror(errno));
716 return -1;
717 #endif
718
719 #ifdef OS_IS_WIN32
720 if (nice_level < 0) {
721 if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS)) {
722 pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError());
723 errno = EPERM;
724 return -1;
725 }
726
727 pa_log_info("Successfully gained high priority class.");
728 }
729 #endif
730
731 return 0;
732 }
733
734 /* Reset the priority to normal, inverting the changes made by
735 * pa_raise_priority() and pa_make_realtime()*/
736 void pa_reset_priority(void) {
737 #ifdef HAVE_SYS_RESOURCE_H
738 struct sched_param sp;
739
740 setpriority(PRIO_PROCESS, 0, 0);
741
742 pa_zero(sp);
743 pthread_setschedparam(pthread_self(), SCHED_OTHER, &sp);
744 #endif
745
746 #ifdef OS_IS_WIN32
747 SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
748 #endif
749 }
750
751 int pa_match(const char *expr, const char *v) {
752 int k;
753 regex_t re;
754 int r;
755
756 if (regcomp(&re, expr, REG_NOSUB|REG_EXTENDED) != 0) {
757 errno = EINVAL;
758 return -1;
759 }
760
761 if ((k = regexec(&re, v, 0, NULL, 0)) == 0)
762 r = 1;
763 else if (k == REG_NOMATCH)
764 r = 0;
765 else
766 r = -1;
767
768 regfree(&re);
769
770 if (r < 0)
771 errno = EINVAL;
772
773 return r;
774 }
775
776 /* Try to parse a boolean string value.*/
777 int pa_parse_boolean(const char *v) {
778 const char *expr;
779 int r;
780 pa_assert(v);
781
782 /* First we check language independant */
783 if (!strcmp(v, "1") || v[0] == 'y' || v[0] == 'Y' || v[0] == 't' || v[0] == 'T' || !strcasecmp(v, "on"))
784 return 1;
785 else if (!strcmp(v, "0") || v[0] == 'n' || v[0] == 'N' || v[0] == 'f' || v[0] == 'F' || !strcasecmp(v, "off"))
786 return 0;
787
788 /* And then we check language dependant */
789 if ((expr = nl_langinfo(YESEXPR)))
790 if (expr[0])
791 if ((r = pa_match(expr, v)) > 0)
792 return 1;
793
794 if ((expr = nl_langinfo(NOEXPR)))
795 if (expr[0])
796 if ((r = pa_match(expr, v)) > 0)
797 return 0;
798
799 errno = EINVAL;
800 return -1;
801 }
802
803 /* Split the specified string wherever one of the strings in delimiter
804 * occurs. Each time it is called returns a newly allocated string
805 * with pa_xmalloc(). The variable state points to, should be
806 * initiallized to NULL before the first call. */
807 char *pa_split(const char *c, const char *delimiter, const char**state) {
808 const char *current = *state ? *state : c;
809 size_t l;
810
811 if (!*current)
812 return NULL;
813
814 l = strcspn(current, delimiter);
815 *state = current+l;
816
817 if (**state)
818 (*state)++;
819
820 return pa_xstrndup(current, l);
821 }
822
823 /* What is interpreted as whitespace? */
824 #define WHITESPACE " \t\n"
825
826 /* Split a string into words. Otherwise similar to pa_split(). */
827 char *pa_split_spaces(const char *c, const char **state) {
828 const char *current = *state ? *state : c;
829 size_t l;
830
831 if (!*current || *c == 0)
832 return NULL;
833
834 current += strspn(current, WHITESPACE);
835 l = strcspn(current, WHITESPACE);
836
837 *state = current+l;
838
839 return pa_xstrndup(current, l);
840 }
841
842 PA_STATIC_TLS_DECLARE(signame, pa_xfree);
843
844 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
845 const char *pa_sig2str(int sig) {
846 char *t;
847
848 if (sig <= 0)
849 goto fail;
850
851 #ifdef NSIG
852 if (sig >= NSIG)
853 goto fail;
854 #endif
855
856 #ifdef HAVE_SIG2STR
857 {
858 char buf[SIG2STR_MAX];
859
860 if (sig2str(sig, buf) == 0) {
861 pa_xfree(PA_STATIC_TLS_GET(signame));
862 t = pa_sprintf_malloc("SIG%s", buf);
863 PA_STATIC_TLS_SET(signame, t);
864 return t;
865 }
866 }
867 #else
868
869 switch(sig) {
870 #ifdef SIGHUP
871 case SIGHUP: return "SIGHUP";
872 #endif
873 case SIGINT: return "SIGINT";
874 #ifdef SIGQUIT
875 case SIGQUIT: return "SIGQUIT";
876 #endif
877 case SIGILL: return "SIGULL";
878 #ifdef SIGTRAP
879 case SIGTRAP: return "SIGTRAP";
880 #endif
881 case SIGABRT: return "SIGABRT";
882 #ifdef SIGBUS
883 case SIGBUS: return "SIGBUS";
884 #endif
885 case SIGFPE: return "SIGFPE";
886 #ifdef SIGKILL
887 case SIGKILL: return "SIGKILL";
888 #endif
889 #ifdef SIGUSR1
890 case SIGUSR1: return "SIGUSR1";
891 #endif
892 case SIGSEGV: return "SIGSEGV";
893 #ifdef SIGUSR2
894 case SIGUSR2: return "SIGUSR2";
895 #endif
896 #ifdef SIGPIPE
897 case SIGPIPE: return "SIGPIPE";
898 #endif
899 #ifdef SIGALRM
900 case SIGALRM: return "SIGALRM";
901 #endif
902 case SIGTERM: return "SIGTERM";
903 #ifdef SIGSTKFLT
904 case SIGSTKFLT: return "SIGSTKFLT";
905 #endif
906 #ifdef SIGCHLD
907 case SIGCHLD: return "SIGCHLD";
908 #endif
909 #ifdef SIGCONT
910 case SIGCONT: return "SIGCONT";
911 #endif
912 #ifdef SIGSTOP
913 case SIGSTOP: return "SIGSTOP";
914 #endif
915 #ifdef SIGTSTP
916 case SIGTSTP: return "SIGTSTP";
917 #endif
918 #ifdef SIGTTIN
919 case SIGTTIN: return "SIGTTIN";
920 #endif
921 #ifdef SIGTTOU
922 case SIGTTOU: return "SIGTTOU";
923 #endif
924 #ifdef SIGURG
925 case SIGURG: return "SIGURG";
926 #endif
927 #ifdef SIGXCPU
928 case SIGXCPU: return "SIGXCPU";
929 #endif
930 #ifdef SIGXFSZ
931 case SIGXFSZ: return "SIGXFSZ";
932 #endif
933 #ifdef SIGVTALRM
934 case SIGVTALRM: return "SIGVTALRM";
935 #endif
936 #ifdef SIGPROF
937 case SIGPROF: return "SIGPROF";
938 #endif
939 #ifdef SIGWINCH
940 case SIGWINCH: return "SIGWINCH";
941 #endif
942 #ifdef SIGIO
943 case SIGIO: return "SIGIO";
944 #endif
945 #ifdef SIGPWR
946 case SIGPWR: return "SIGPWR";
947 #endif
948 #ifdef SIGSYS
949 case SIGSYS: return "SIGSYS";
950 #endif
951 }
952
953 #ifdef SIGRTMIN
954 if (sig >= SIGRTMIN && sig <= SIGRTMAX) {
955 pa_xfree(PA_STATIC_TLS_GET(signame));
956 t = pa_sprintf_malloc("SIGRTMIN+%i", sig - SIGRTMIN);
957 PA_STATIC_TLS_SET(signame, t);
958 return t;
959 }
960 #endif
961
962 #endif
963
964 fail:
965
966 pa_xfree(PA_STATIC_TLS_GET(signame));
967 t = pa_sprintf_malloc("SIG%i", sig);
968 PA_STATIC_TLS_SET(signame, t);
969 return t;
970 }
971
972 #ifdef HAVE_GRP_H
973
974 /* Check whether the specified GID and the group name match */
975 static int is_group(gid_t gid, const char *name) {
976 struct group *group = NULL;
977 int r = -1;
978
979 errno = 0;
980 if (!(group = pa_getgrgid_malloc(gid)))
981 {
982 if (!errno)
983 errno = ENOENT;
984
985 pa_log("pa_getgrgid_malloc(%u): %s", gid, pa_cstrerror(errno));
986
987 goto finish;
988 }
989
990 r = strcmp(name, group->gr_name) == 0;
991
992 finish:
993 pa_getgrgid_free(group);
994
995 return r;
996 }
997
998 /* Check the current user is member of the specified group */
999 int pa_own_uid_in_group(const char *name, gid_t *gid) {
1000 GETGROUPS_T *gids, tgid;
1001 long n = sysconf(_SC_NGROUPS_MAX);
1002 int r = -1, i, k;
1003
1004 pa_assert(n > 0);
1005
1006 gids = pa_xmalloc(sizeof(GETGROUPS_T) * (size_t) n);
1007
1008 if ((n = getgroups((int) n, gids)) < 0) {
1009 pa_log("getgroups(): %s", pa_cstrerror(errno));
1010 goto finish;
1011 }
1012
1013 for (i = 0; i < n; i++) {
1014
1015 if ((k = is_group(gids[i], name)) < 0)
1016 goto finish;
1017 else if (k > 0) {
1018 *gid = gids[i];
1019 r = 1;
1020 goto finish;
1021 }
1022 }
1023
1024 if ((k = is_group(tgid = getgid(), name)) < 0)
1025 goto finish;
1026 else if (k > 0) {
1027 *gid = tgid;
1028 r = 1;
1029 goto finish;
1030 }
1031
1032 r = 0;
1033
1034 finish:
1035
1036 pa_xfree(gids);
1037 return r;
1038 }
1039
1040 /* Check whether the specifc user id is a member of the specified group */
1041 int pa_uid_in_group(uid_t uid, const char *name) {
1042 struct group *group = NULL;
1043 char **i;
1044 int r = -1;
1045
1046 errno = 0;
1047 if (!(group = pa_getgrnam_malloc(name)))
1048 {
1049 if (!errno)
1050 errno = ENOENT;
1051 goto finish;
1052 }
1053
1054 r = 0;
1055 for (i = group->gr_mem; *i; i++) {
1056 struct passwd *pw = NULL;
1057
1058 errno = 0;
1059 if (!(pw = pa_getpwnam_malloc(*i)))
1060 continue;
1061
1062 if (pw->pw_uid == uid)
1063 r = 1;
1064
1065 pa_getpwnam_free(pw);
1066
1067 if (r == 1)
1068 break;
1069 }
1070
1071 finish:
1072 pa_getgrnam_free(group);
1073
1074 return r;
1075 }
1076
1077 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
1078 gid_t pa_get_gid_of_group(const char *name) {
1079 gid_t ret = (gid_t) -1;
1080 struct group *gr = NULL;
1081
1082 errno = 0;
1083 if (!(gr = pa_getgrnam_malloc(name)))
1084 {
1085 if (!errno)
1086 errno = ENOENT;
1087 goto finish;
1088 }
1089
1090 ret = gr->gr_gid;
1091
1092 finish:
1093 pa_getgrnam_free(gr);
1094 return ret;
1095 }
1096
1097 int pa_check_in_group(gid_t g) {
1098 gid_t gids[NGROUPS_MAX];
1099 int r;
1100
1101 if ((r = getgroups(NGROUPS_MAX, gids)) < 0)
1102 return -1;
1103
1104 for (; r > 0; r--)
1105 if (gids[r-1] == g)
1106 return 1;
1107
1108 return 0;
1109 }
1110
1111 #else /* HAVE_GRP_H */
1112
1113 int pa_own_uid_in_group(const char *name, gid_t *gid) {
1114 errno = ENOSUP;
1115 return -1;
1116
1117 }
1118
1119 int pa_uid_in_group(uid_t uid, const char *name) {
1120 errno = ENOSUP;
1121 return -1;
1122 }
1123
1124 gid_t pa_get_gid_of_group(const char *name) {
1125 errno = ENOSUP;
1126 return (gid_t) -1;
1127 }
1128
1129 int pa_check_in_group(gid_t g) {
1130 errno = ENOSUP;
1131 return -1;
1132 }
1133
1134 #endif
1135
1136 /* Lock or unlock a file entirely.
1137 (advisory on UNIX, mandatory on Windows) */
1138 int pa_lock_fd(int fd, int b) {
1139 #ifdef F_SETLKW
1140 struct flock f_lock;
1141
1142 /* Try a R/W lock first */
1143
1144 f_lock.l_type = (short) (b ? F_WRLCK : F_UNLCK);
1145 f_lock.l_whence = SEEK_SET;
1146 f_lock.l_start = 0;
1147 f_lock.l_len = 0;
1148
1149 if (fcntl(fd, F_SETLKW, &f_lock) >= 0)
1150 return 0;
1151
1152 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1153 if (b && errno == EBADF) {
1154 f_lock.l_type = F_RDLCK;
1155 if (fcntl(fd, F_SETLKW, &f_lock) >= 0)
1156 return 0;
1157 }
1158
1159 pa_log("%slock: %s", !b? "un" : "", pa_cstrerror(errno));
1160 #endif
1161
1162 #ifdef OS_IS_WIN32
1163 HANDLE h = (HANDLE)_get_osfhandle(fd);
1164
1165 if (b && LockFile(h, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1166 return 0;
1167 if (!b && UnlockFile(h, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1168 return 0;
1169
1170 pa_log("%slock failed: 0x%08X", !b ? "un" : "", GetLastError());
1171
1172 /* FIXME: Needs to set errno! */
1173 #endif
1174
1175 return -1;
1176 }
1177
1178 /* Remove trailing newlines from a string */
1179 char* pa_strip_nl(char *s) {
1180 pa_assert(s);
1181
1182 s[strcspn(s, "\r\n")] = 0;
1183 return s;
1184 }
1185
1186 /* Create a temporary lock file and lock it. */
1187 int pa_lock_lockfile(const char *fn) {
1188 int fd = -1;
1189 pa_assert(fn);
1190
1191 for (;;) {
1192 struct stat st;
1193
1194 if ((fd = open(fn, O_CREAT|O_RDWR
1195 #ifdef O_NOCTTY
1196 |O_NOCTTY
1197 #endif
1198 #ifdef O_NOFOLLOW
1199 |O_NOFOLLOW
1200 #endif
1201 , S_IRUSR|S_IWUSR)) < 0) {
1202 pa_log_warn("Failed to create lock file '%s': %s", fn, pa_cstrerror(errno));
1203 goto fail;
1204 }
1205
1206 if (pa_lock_fd(fd, 1) < 0) {
1207 pa_log_warn("Failed to lock file '%s'.", fn);
1208 goto fail;
1209 }
1210
1211 if (fstat(fd, &st) < 0) {
1212 pa_log_warn("Failed to fstat() file '%s': %s", fn, pa_cstrerror(errno));
1213 goto fail;
1214 }
1215
1216 /* Check whether the file has been removed meanwhile. When yes,
1217 * restart this loop, otherwise, we're done */
1218 if (st.st_nlink >= 1)
1219 break;
1220
1221 if (pa_lock_fd(fd, 0) < 0) {
1222 pa_log_warn("Failed to unlock file '%s'.", fn);
1223 goto fail;
1224 }
1225
1226 if (pa_close(fd) < 0) {
1227 pa_log_warn("Failed to close file '%s': %s", fn, pa_cstrerror(errno));
1228 fd = -1;
1229 goto fail;
1230 }
1231
1232 fd = -1;
1233 }
1234
1235 return fd;
1236
1237 fail:
1238
1239 if (fd >= 0) {
1240 int saved_errno = errno;
1241 pa_close(fd);
1242 errno = saved_errno;
1243 }
1244
1245 return -1;
1246 }
1247
1248 /* Unlock a temporary lcok file */
1249 int pa_unlock_lockfile(const char *fn, int fd) {
1250 int r = 0;
1251 pa_assert(fd >= 0);
1252
1253 if (fn) {
1254 if (unlink(fn) < 0) {
1255 pa_log_warn("Unable to remove lock file '%s': %s", fn, pa_cstrerror(errno));
1256 r = -1;
1257 }
1258 }
1259
1260 if (pa_lock_fd(fd, 0) < 0) {
1261 pa_log_warn("Failed to unlock file '%s'.", fn);
1262 r = -1;
1263 }
1264
1265 if (pa_close(fd) < 0) {
1266 pa_log_warn("Failed to close '%s': %s", fn, pa_cstrerror(errno));
1267 r = -1;
1268 }
1269
1270 return r;
1271 }
1272
1273 static char *get_pulse_home(void) {
1274 char *h;
1275 struct stat st;
1276 char *ret = NULL;
1277
1278 if (!(h = pa_get_home_dir_malloc())) {
1279 pa_log_error("Failed to get home directory.");
1280 return NULL;
1281 }
1282
1283 if (stat(h, &st) < 0) {
1284 pa_log_error("Failed to stat home directory %s: %s", h, pa_cstrerror(errno));
1285 goto finish;
1286 }
1287
1288 if (st.st_uid != getuid()) {
1289 pa_log_error("Home directory %s not ours.", h);
1290 errno = EACCES;
1291 goto finish;
1292 }
1293
1294 ret = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse", h);
1295
1296 finish:
1297 pa_xfree(h);
1298
1299 return ret;
1300 }
1301
1302 char *pa_get_state_dir(void) {
1303 char *d;
1304
1305 /* The state directory shall contain dynamic data that should be
1306 * kept across reboots, and is private to this user */
1307
1308 if (!(d = pa_xstrdup(getenv("PULSE_STATE_PATH"))))
1309 if (!(d = get_pulse_home()))
1310 return NULL;
1311
1312 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1313 * dir then this will break. */
1314
1315 if (pa_make_secure_dir(d, 0700U, (uid_t) -1, (gid_t) -1) < 0) {
1316 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1317 pa_xfree(d);
1318 return NULL;
1319 }
1320
1321 return d;
1322 }
1323
1324 char *pa_get_home_dir_malloc(void) {
1325 char *homedir;
1326 size_t allocated = 128;
1327
1328 for (;;) {
1329 homedir = pa_xmalloc(allocated);
1330
1331 if (!pa_get_home_dir(homedir, allocated)) {
1332 pa_xfree(homedir);
1333 return NULL;
1334 }
1335
1336 if (strlen(homedir) < allocated - 1)
1337 break;
1338
1339 pa_xfree(homedir);
1340 allocated *= 2;
1341 }
1342
1343 return homedir;
1344 }
1345
1346 char *pa_get_binary_name_malloc(void) {
1347 char *t;
1348 size_t allocated = 128;
1349
1350 for (;;) {
1351 t = pa_xmalloc(allocated);
1352
1353 if (!pa_get_binary_name(t, allocated)) {
1354 pa_xfree(t);
1355 return NULL;
1356 }
1357
1358 if (strlen(t) < allocated - 1)
1359 break;
1360
1361 pa_xfree(t);
1362 allocated *= 2;
1363 }
1364
1365 return t;
1366 }
1367
1368 static char* make_random_dir(mode_t m) {
1369 static const char table[] =
1370 "abcdefghijklmnopqrstuvwxyz"
1371 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1372 "0123456789";
1373
1374 const char *tmpdir;
1375 char *fn;
1376 size_t pathlen;
1377
1378 if (!(tmpdir = getenv("TMPDIR")))
1379 if (!(tmpdir = getenv("TMP")))
1380 if (!(tmpdir = getenv("TEMP")))
1381 tmpdir = getenv("TEMPDIR");
1382
1383 if (!tmpdir || !pa_is_path_absolute(tmpdir))
1384 tmpdir = "/tmp";
1385
1386 fn = pa_sprintf_malloc("%s/pulse-XXXXXXXXXXXX", tmpdir);
1387 pathlen = strlen(fn);
1388
1389 for (;;) {
1390 size_t i;
1391 int r;
1392 mode_t u;
1393 int saved_errno;
1394
1395 for (i = pathlen - 12; i < pathlen; i++)
1396 fn[i] = table[rand() % (sizeof(table)-1)];
1397
1398 u = umask((~m) & 0777);
1399 r = mkdir(fn, m);
1400
1401 saved_errno = errno;
1402 umask(u);
1403 errno = saved_errno;
1404
1405 if (r >= 0)
1406 return fn;
1407
1408 if (errno != EEXIST) {
1409 pa_log_error("Failed to create random directory %s: %s", fn, pa_cstrerror(errno));
1410 pa_xfree(fn);
1411 return NULL;
1412 }
1413 }
1414 }
1415
1416 static int make_random_dir_and_link(mode_t m, const char *k) {
1417 char *p;
1418
1419 if (!(p = make_random_dir(m)))
1420 return -1;
1421
1422 if (symlink(p, k) < 0) {
1423 int saved_errno = errno;
1424
1425 if (errno != EEXIST)
1426 pa_log_error("Failed to symlink %s to %s: %s", k, p, pa_cstrerror(errno));
1427
1428 rmdir(p);
1429 pa_xfree(p);
1430
1431 errno = saved_errno;
1432 return -1;
1433 }
1434
1435 pa_xfree(p);
1436 return 0;
1437 }
1438
1439 char *pa_get_runtime_dir(void) {
1440 char *d, *k = NULL, *p = NULL, *t = NULL, *mid;
1441 struct stat st;
1442 mode_t m;
1443
1444 /* The runtime directory shall contain dynamic data that needs NOT
1445 * to be kept accross reboots and is usuallly private to the user,
1446 * except in system mode, where it might be accessible by other
1447 * users, too. Since we need POSIX locking and UNIX sockets in
1448 * this directory, we link it to a random subdir in /tmp, if it
1449 * was not explicitly configured. */
1450
1451 m = pa_in_system_mode() ? 0755U : 0700U;
1452
1453 if ((d = getenv("PULSE_RUNTIME_PATH"))) {
1454
1455 if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0) {
1456 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1457 goto fail;
1458 }
1459
1460 return pa_xstrdup(d);
1461 }
1462
1463 if (!(d = get_pulse_home()))
1464 goto fail;
1465
1466 if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0) {
1467 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1468 pa_xfree(d);
1469 goto fail;
1470 }
1471
1472 if (!(mid = pa_machine_id())) {
1473 pa_xfree(d);
1474 goto fail;
1475 }
1476
1477 k = pa_sprintf_malloc("%s" PA_PATH_SEP "%s-runtime", d, mid);
1478 pa_xfree(d);
1479 pa_xfree(mid);
1480
1481 for (;;) {
1482 /* OK, first let's check if the "runtime" symlink is already
1483 * existant */
1484
1485 if (!(p = pa_readlink(k))) {
1486
1487 if (errno != ENOENT) {
1488 pa_log_error("Failed to stat runtime directory %s: %s", k, pa_cstrerror(errno));
1489 goto fail;
1490 }
1491
1492 /* Hmm, so the runtime directory didn't exist yet, so let's
1493 * create one in /tmp and symlink that to it */
1494
1495 if (make_random_dir_and_link(0700, k) < 0) {
1496
1497 /* Mhmm, maybe another process was quicker than us,
1498 * let's check if that was valid */
1499 if (errno == EEXIST)
1500 continue;
1501
1502 goto fail;
1503 }
1504
1505 return k;
1506 }
1507
1508 /* Make sure that this actually makes sense */
1509 if (!pa_is_path_absolute(p)) {
1510 pa_log_error("Path %s in link %s is not absolute.", p, k);
1511 errno = ENOENT;
1512 goto fail;
1513 }
1514
1515 /* Hmm, so this symlink is still around, make sure nobody fools
1516 * us */
1517
1518 if (lstat(p, &st) < 0) {
1519
1520 if (errno != ENOENT) {
1521 pa_log_error("Failed to stat runtime directory %s: %s", p, pa_cstrerror(errno));
1522 goto fail;
1523 }
1524
1525 } else {
1526
1527 if (S_ISDIR(st.st_mode) &&
1528 (st.st_uid == getuid()) &&
1529 ((st.st_mode & 0777) == 0700)) {
1530
1531 pa_xfree(p);
1532 return k;
1533 }
1534
1535 pa_log_info("Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory.");
1536 }
1537
1538 pa_xfree(p);
1539 p = NULL;
1540
1541 /* Hmm, so the link points to some nonexisting or invalid
1542 * dir. Let's replace it by a new link. We first create a
1543 * temporary link and then rename that to allow concurrent
1544 * execution of this function. */
1545
1546 t = pa_sprintf_malloc("%s.tmp", k);
1547
1548 if (make_random_dir_and_link(0700, t) < 0) {
1549
1550 if (errno != EEXIST) {
1551 pa_log_error("Failed to symlink %s: %s", t, pa_cstrerror(errno));
1552 goto fail;
1553 }
1554
1555 pa_xfree(t);
1556 t = NULL;
1557
1558 /* Hmm, someone lese was quicker then us. Let's give
1559 * him some time to finish, and retry. */
1560 pa_msleep(10);
1561 continue;
1562 }
1563
1564 /* OK, we succeeded in creating the temporary symlink, so
1565 * let's rename it */
1566 if (rename(t, k) < 0) {
1567 pa_log_error("Failed to rename %s to %s: %s", t, k, pa_cstrerror(errno));
1568 goto fail;
1569 }
1570
1571 pa_xfree(t);
1572 return k;
1573 }
1574
1575 fail:
1576 pa_xfree(p);
1577 pa_xfree(k);
1578 pa_xfree(t);
1579
1580 return NULL;
1581 }
1582
1583 /* Try to open a configuration file. If "env" is specified, open the
1584 * value of the specified environment variable. Otherwise look for a
1585 * file "local" in the home directory or a file "global" in global
1586 * file system. If "result" is non-NULL, a pointer to a newly
1587 * allocated buffer containing the used configuration file is
1588 * stored there.*/
1589 FILE *pa_open_config_file(const char *global, const char *local, const char *env, char **result) {
1590 const char *fn;
1591 #ifdef OS_IS_WIN32
1592 char buf[PATH_MAX];
1593
1594 if (!getenv(PULSE_ROOTENV))
1595 pa_set_root(NULL);
1596 #endif
1597
1598 if (env && (fn = getenv(env))) {
1599 FILE *f;
1600
1601 #ifdef OS_IS_WIN32
1602 if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
1603 /* FIXME: Needs to set errno! */
1604 return NULL;
1605 fn = buf;
1606 #endif
1607
1608 if ((f = fopen(fn, "r"))) {
1609 if (result)
1610 *result = pa_xstrdup(fn);
1611
1612 return f;
1613 }
1614
1615 pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
1616 return NULL;
1617 }
1618
1619 if (local) {
1620 const char *e;
1621 char *lfn;
1622 char *h;
1623 FILE *f;
1624
1625 if ((e = getenv("PULSE_CONFIG_PATH")))
1626 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
1627 else if ((h = pa_get_home_dir_malloc())) {
1628 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
1629 pa_xfree(h);
1630 } else
1631 return NULL;
1632
1633 #ifdef OS_IS_WIN32
1634 if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) {
1635 /* FIXME: Needs to set errno! */
1636 pa_xfree(lfn);
1637 return NULL;
1638 }
1639 fn = buf;
1640 #endif
1641
1642 if ((f = fopen(fn, "r"))) {
1643 if (result)
1644 *result = pa_xstrdup(fn);
1645
1646 pa_xfree(lfn);
1647 return f;
1648 }
1649
1650 if (errno != ENOENT) {
1651 pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
1652 pa_xfree(lfn);
1653 return NULL;
1654 }
1655
1656 pa_xfree(lfn);
1657 }
1658
1659 if (global) {
1660 FILE *f;
1661
1662 #ifdef OS_IS_WIN32
1663 if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
1664 /* FIXME: Needs to set errno! */
1665 return NULL;
1666 global = buf;
1667 #endif
1668
1669 if ((f = fopen(global, "r"))) {
1670
1671 if (result)
1672 *result = pa_xstrdup(global);
1673
1674 return f;
1675 }
1676 }
1677
1678 errno = ENOENT;
1679 return NULL;
1680 }
1681
1682 char *pa_find_config_file(const char *global, const char *local, const char *env) {
1683 const char *fn;
1684 #ifdef OS_IS_WIN32
1685 char buf[PATH_MAX];
1686
1687 if (!getenv(PULSE_ROOTENV))
1688 pa_set_root(NULL);
1689 #endif
1690
1691 if (env && (fn = getenv(env))) {
1692
1693 #ifdef OS_IS_WIN32
1694 if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
1695 /* FIXME: Needs to set errno! */
1696 return NULL;
1697 fn = buf;
1698 #endif
1699
1700 if (access(fn, R_OK) == 0)
1701 return pa_xstrdup(fn);
1702
1703 pa_log_warn("Failed to access configuration file '%s': %s", fn, pa_cstrerror(errno));
1704 return NULL;
1705 }
1706
1707 if (local) {
1708 const char *e;
1709 char *lfn;
1710 char *h;
1711
1712 if ((e = getenv("PULSE_CONFIG_PATH")))
1713 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
1714 else if ((h = pa_get_home_dir_malloc())) {
1715 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
1716 pa_xfree(h);
1717 } else
1718 return NULL;
1719
1720 #ifdef OS_IS_WIN32
1721 if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) {
1722 /* FIXME: Needs to set errno! */
1723 pa_xfree(lfn);
1724 return NULL;
1725 }
1726 fn = buf;
1727 #endif
1728
1729 if (access(fn, R_OK) == 0) {
1730 char *r = pa_xstrdup(fn);
1731 pa_xfree(lfn);
1732 return r;
1733 }
1734
1735 if (errno != ENOENT) {
1736 pa_log_warn("Failed to access configuration file '%s': %s", fn, pa_cstrerror(errno));
1737 pa_xfree(lfn);
1738 return NULL;
1739 }
1740
1741 pa_xfree(lfn);
1742 }
1743
1744 if (global) {
1745 #ifdef OS_IS_WIN32
1746 if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
1747 /* FIXME: Needs to set errno! */
1748 return NULL;
1749 global = buf;
1750 #endif
1751
1752 if (access(global, R_OK) == 0)
1753 return pa_xstrdup(global);
1754 }
1755
1756 errno = ENOENT;
1757
1758 return NULL;
1759 }
1760
1761 /* Format the specified data as a hexademical string */
1762 char *pa_hexstr(const uint8_t* d, size_t dlength, char *s, size_t slength) {
1763 size_t i = 0, j = 0;
1764 const char hex[] = "0123456789abcdef";
1765
1766 pa_assert(d);
1767 pa_assert(s);
1768 pa_assert(slength > 0);
1769
1770 while (i < dlength && j+3 <= slength) {
1771 s[j++] = hex[*d >> 4];
1772 s[j++] = hex[*d & 0xF];
1773
1774 d++;
1775 i++;
1776 }
1777
1778 s[j < slength ? j : slength] = 0;
1779 return s;
1780 }
1781
1782 /* Convert a hexadecimal digit to a number or -1 if invalid */
1783 static int hexc(char c) {
1784 if (c >= '0' && c <= '9')
1785 return c - '0';
1786
1787 if (c >= 'A' && c <= 'F')
1788 return c - 'A' + 10;
1789
1790 if (c >= 'a' && c <= 'f')
1791 return c - 'a' + 10;
1792
1793 errno = EINVAL;
1794 return -1;
1795 }
1796
1797 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1798 size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength) {
1799 size_t j = 0;
1800
1801 pa_assert(p);
1802 pa_assert(d);
1803
1804 while (j < dlength && *p) {
1805 int b;
1806
1807 if ((b = hexc(*(p++))) < 0)
1808 return (size_t) -1;
1809
1810 d[j] = (uint8_t) (b << 4);
1811
1812 if (!*p)
1813 return (size_t) -1;
1814
1815 if ((b = hexc(*(p++))) < 0)
1816 return (size_t) -1;
1817
1818 d[j] |= (uint8_t) b;
1819 j++;
1820 }
1821
1822 return j;
1823 }
1824
1825 /* Returns nonzero when *s starts with *pfx */
1826 pa_bool_t pa_startswith(const char *s, const char *pfx) {
1827 size_t l;
1828
1829 pa_assert(s);
1830 pa_assert(pfx);
1831
1832 l = strlen(pfx);
1833
1834 return strlen(s) >= l && strncmp(s, pfx, l) == 0;
1835 }
1836
1837 /* Returns nonzero when *s ends with *sfx */
1838 pa_bool_t pa_endswith(const char *s, const char *sfx) {
1839 size_t l1, l2;
1840
1841 pa_assert(s);
1842 pa_assert(sfx);
1843
1844 l1 = strlen(s);
1845 l2 = strlen(sfx);
1846
1847 return l1 >= l2 && strcmp(s+l1-l2, sfx) == 0;
1848 }
1849
1850 pa_bool_t pa_is_path_absolute(const char *fn) {
1851 pa_assert(fn);
1852
1853 #ifndef OS_IS_WIN32
1854 return *fn == '/';
1855 #else
1856 return strlen(fn) >= 3 && isalpha(fn[0]) && fn[1] == ':' && fn[2] == '\\';
1857 #endif
1858 }
1859
1860 char *pa_make_path_absolute(const char *p) {
1861 char *r;
1862 char *cwd;
1863
1864 pa_assert(p);
1865
1866 if (pa_is_path_absolute(p))
1867 return pa_xstrdup(p);
1868
1869 if (!(cwd = pa_getcwd()))
1870 return pa_xstrdup(p);
1871
1872 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", cwd, p);
1873 pa_xfree(cwd);
1874 return r;
1875 }
1876
1877 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1878 * if fn is non-null and starts with / return fn
1879 * otherwise append fn to the run time path and return it */
1880 static char *get_path(const char *fn, pa_bool_t prependmid, pa_bool_t rt) {
1881 char *rtp;
1882
1883 rtp = rt ? pa_get_runtime_dir() : pa_get_state_dir();
1884
1885 if (fn) {
1886 char *r;
1887
1888 if (pa_is_path_absolute(fn))
1889 return pa_xstrdup(fn);
1890
1891 if (!rtp)
1892 return NULL;
1893
1894 if (prependmid) {
1895 char *mid;
1896
1897 if (!(mid = pa_machine_id())) {
1898 pa_xfree(rtp);
1899 return NULL;
1900 }
1901
1902 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s-%s", rtp, mid, fn);
1903 pa_xfree(mid);
1904 } else
1905 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", rtp, fn);
1906
1907 pa_xfree(rtp);
1908 return r;
1909 } else
1910 return rtp;
1911 }
1912
1913 char *pa_runtime_path(const char *fn) {
1914 return get_path(fn, FALSE, TRUE);
1915 }
1916
1917 char *pa_state_path(const char *fn, pa_bool_t appendmid) {
1918 return get_path(fn, appendmid, FALSE);
1919 }
1920
1921 /* Convert the string s to a signed integer in *ret_i */
1922 int pa_atoi(const char *s, int32_t *ret_i) {
1923 char *x = NULL;
1924 long l;
1925
1926 pa_assert(s);
1927 pa_assert(ret_i);
1928
1929 errno = 0;
1930 l = strtol(s, &x, 0);
1931
1932 if (!x || *x || errno) {
1933 if (!errno)
1934 errno = EINVAL;
1935 return -1;
1936 }
1937
1938 if ((int32_t) l != l) {
1939 errno = ERANGE;
1940 return -1;
1941 }
1942
1943 *ret_i = (int32_t) l;
1944
1945 return 0;
1946 }
1947
1948 /* Convert the string s to an unsigned integer in *ret_u */
1949 int pa_atou(const char *s, uint32_t *ret_u) {
1950 char *x = NULL;
1951 unsigned long l;
1952
1953 pa_assert(s);
1954 pa_assert(ret_u);
1955
1956 errno = 0;
1957 l = strtoul(s, &x, 0);
1958
1959 if (!x || *x || errno) {
1960 if (!errno)
1961 errno = EINVAL;
1962 return -1;
1963 }
1964
1965 if ((uint32_t) l != l) {
1966 errno = ERANGE;
1967 return -1;
1968 }
1969
1970 *ret_u = (uint32_t) l;
1971
1972 return 0;
1973 }
1974
1975 #ifdef HAVE_STRTOF_L
1976 static locale_t c_locale = NULL;
1977
1978 static void c_locale_destroy(void) {
1979 freelocale(c_locale);
1980 }
1981 #endif
1982
1983 int pa_atod(const char *s, double *ret_d) {
1984 char *x = NULL;
1985 double f;
1986
1987 pa_assert(s);
1988 pa_assert(ret_d);
1989
1990 /* This should be locale independent */
1991
1992 #ifdef HAVE_STRTOF_L
1993
1994 PA_ONCE_BEGIN {
1995
1996 if ((c_locale = newlocale(LC_ALL_MASK, "C", NULL)))
1997 atexit(c_locale_destroy);
1998
1999 } PA_ONCE_END;
2000
2001 if (c_locale) {
2002 errno = 0;
2003 f = strtod_l(s, &x, c_locale);
2004 } else
2005 #endif
2006 {
2007 errno = 0;
2008 f = strtod(s, &x);
2009 }
2010
2011 if (!x || *x || errno) {
2012 if (!errno)
2013 errno = EINVAL;
2014 return -1;
2015 }
2016
2017 *ret_d = f;
2018
2019 return 0;
2020 }
2021
2022 /* Same as snprintf, but guarantees NUL-termination on every platform */
2023 size_t pa_snprintf(char *str, size_t size, const char *format, ...) {
2024 size_t ret;
2025 va_list ap;
2026
2027 pa_assert(str);
2028 pa_assert(size > 0);
2029 pa_assert(format);
2030
2031 va_start(ap, format);
2032 ret = pa_vsnprintf(str, size, format, ap);
2033 va_end(ap);
2034
2035 return ret;
2036 }
2037
2038 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2039 size_t pa_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
2040 int ret;
2041
2042 pa_assert(str);
2043 pa_assert(size > 0);
2044 pa_assert(format);
2045
2046 ret = vsnprintf(str, size, format, ap);
2047
2048 str[size-1] = 0;
2049
2050 if (ret < 0)
2051 return strlen(str);
2052
2053 if ((size_t) ret > size-1)
2054 return size-1;
2055
2056 return (size_t) ret;
2057 }
2058
2059 /* Truncate the specified string, but guarantee that the string
2060 * returned still validates as UTF8 */
2061 char *pa_truncate_utf8(char *c, size_t l) {
2062 pa_assert(c);
2063 pa_assert(pa_utf8_valid(c));
2064
2065 if (strlen(c) <= l)
2066 return c;
2067
2068 c[l] = 0;
2069
2070 while (l > 0 && !pa_utf8_valid(c))
2071 c[--l] = 0;
2072
2073 return c;
2074 }
2075
2076 char *pa_getcwd(void) {
2077 size_t l = 128;
2078
2079 for (;;) {
2080 char *p = pa_xmalloc(l);
2081 if (getcwd(p, l))
2082 return p;
2083
2084 if (errno != ERANGE)
2085 return NULL;
2086
2087 pa_xfree(p);
2088 l *= 2;
2089 }
2090 }
2091
2092 void *pa_will_need(const void *p, size_t l) {
2093 #ifdef RLIMIT_MEMLOCK
2094 struct rlimit rlim;
2095 #endif
2096 const void *a;
2097 size_t size;
2098 int r;
2099 size_t bs;
2100
2101 pa_assert(p);
2102 pa_assert(l > 0);
2103
2104 a = PA_PAGE_ALIGN_PTR(p);
2105 size = (size_t) ((const uint8_t*) p + l - (const uint8_t*) a);
2106
2107 #ifdef HAVE_POSIX_MADVISE
2108 if ((r = posix_madvise((void*) a, size, POSIX_MADV_WILLNEED)) == 0) {
2109 pa_log_debug("posix_madvise() worked fine!");
2110 return (void*) p;
2111 }
2112 #endif
2113
2114 /* Most likely the memory was not mmap()ed from a file and thus
2115 * madvise() didn't work, so let's misuse mlock() do page this
2116 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2117 * inviting, the man page of mlock() tells us: "All pages that
2118 * contain a part of the specified address range are guaranteed to
2119 * be resident in RAM when the call returns successfully." */
2120
2121 #ifdef RLIMIT_MEMLOCK
2122 pa_assert_se(getrlimit(RLIMIT_MEMLOCK, &rlim) == 0);
2123
2124 if (rlim.rlim_cur < PA_PAGE_SIZE) {
2125 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));
2126 errno = EPERM;
2127 return (void*) p;
2128 }
2129
2130 bs = PA_PAGE_ALIGN((size_t) rlim.rlim_cur);
2131 #else
2132 bs = PA_PAGE_SIZE*4;
2133 #endif
2134
2135 pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r));
2136
2137 #ifdef HAVE_MLOCK
2138 while (size > 0 && bs > 0) {
2139
2140 if (bs > size)
2141 bs = size;
2142
2143 if (mlock(a, bs) < 0) {
2144 bs = PA_PAGE_ALIGN(bs / 2);
2145 continue;
2146 }
2147
2148 pa_assert_se(munlock(a, bs) == 0);
2149
2150 a = (const uint8_t*) a + bs;
2151 size -= bs;
2152 }
2153 #endif
2154
2155 if (bs <= 0)
2156 pa_log_debug("mlock() failed too (or doesn't exist), giving up: %s", pa_cstrerror(errno));
2157 else
2158 pa_log_debug("mlock() worked fine!");
2159
2160 return (void*) p;
2161 }
2162
2163 void pa_close_pipe(int fds[2]) {
2164 pa_assert(fds);
2165
2166 if (fds[0] >= 0)
2167 pa_assert_se(pa_close(fds[0]) == 0);
2168
2169 if (fds[1] >= 0)
2170 pa_assert_se(pa_close(fds[1]) == 0);
2171
2172 fds[0] = fds[1] = -1;
2173 }
2174
2175 char *pa_readlink(const char *p) {
2176 size_t l = 100;
2177
2178 for (;;) {
2179 char *c;
2180 ssize_t n;
2181
2182 c = pa_xmalloc(l);
2183
2184 if ((n = readlink(p, c, l-1)) < 0) {
2185 pa_xfree(c);
2186 return NULL;
2187 }
2188
2189 if ((size_t) n < l-1) {
2190 c[n] = 0;
2191 return c;
2192 }
2193
2194 pa_xfree(c);
2195 l *= 2;
2196 }
2197 }
2198
2199 int pa_close_all(int except_fd, ...) {
2200 va_list ap;
2201 unsigned n = 0, i;
2202 int r, *p;
2203
2204 va_start(ap, except_fd);
2205
2206 if (except_fd >= 0)
2207 for (n = 1; va_arg(ap, int) >= 0; n++)
2208 ;
2209
2210 va_end(ap);
2211
2212 p = pa_xnew(int, n+1);
2213
2214 va_start(ap, except_fd);
2215
2216 i = 0;
2217 if (except_fd >= 0) {
2218 int fd;
2219 p[i++] = except_fd;
2220
2221 while ((fd = va_arg(ap, int)) >= 0)
2222 p[i++] = fd;
2223 }
2224 p[i] = -1;
2225
2226 va_end(ap);
2227
2228 r = pa_close_allv(p);
2229 pa_xfree(p);
2230
2231 return r;
2232 }
2233
2234 int pa_close_allv(const int except_fds[]) {
2235 struct rlimit rl;
2236 int maxfd, fd;
2237
2238 #ifdef __linux__
2239 int saved_errno;
2240 DIR *d;
2241
2242 if ((d = opendir("/proc/self/fd"))) {
2243
2244 struct dirent *de;
2245
2246 while ((de = readdir(d))) {
2247 pa_bool_t found;
2248 long l;
2249 char *e = NULL;
2250 int i;
2251
2252 if (de->d_name[0] == '.')
2253 continue;
2254
2255 errno = 0;
2256 l = strtol(de->d_name, &e, 10);
2257 if (errno != 0 || !e || *e) {
2258 closedir(d);
2259 errno = EINVAL;
2260 return -1;
2261 }
2262
2263 fd = (int) l;
2264
2265 if ((long) fd != l) {
2266 closedir(d);
2267 errno = EINVAL;
2268 return -1;
2269 }
2270
2271 if (fd < 3)
2272 continue;
2273
2274 if (fd == dirfd(d))
2275 continue;
2276
2277 found = FALSE;
2278 for (i = 0; except_fds[i] >= 0; i++)
2279 if (except_fds[i] == fd) {
2280 found = TRUE;
2281 break;
2282 }
2283
2284 if (found)
2285 continue;
2286
2287 if (pa_close(fd) < 0) {
2288 saved_errno = errno;
2289 closedir(d);
2290 errno = saved_errno;
2291
2292 return -1;
2293 }
2294 }
2295
2296 closedir(d);
2297 return 0;
2298 }
2299
2300 #endif
2301
2302 if (getrlimit(RLIMIT_NOFILE, &rl) >= 0)
2303 maxfd = (int) rl.rlim_max;
2304 else
2305 maxfd = sysconf(_SC_OPEN_MAX);
2306
2307 for (fd = 3; fd < maxfd; fd++) {
2308 int i;
2309 pa_bool_t found;
2310
2311 found = FALSE;
2312 for (i = 0; except_fds[i] >= 0; i++)
2313 if (except_fds[i] == fd) {
2314 found = TRUE;
2315 break;
2316 }
2317
2318 if (found)
2319 continue;
2320
2321 if (pa_close(fd) < 0 && errno != EBADF)
2322 return -1;
2323 }
2324
2325 return 0;
2326 }
2327
2328 int pa_unblock_sigs(int except, ...) {
2329 va_list ap;
2330 unsigned n = 0, i;
2331 int r, *p;
2332
2333 va_start(ap, except);
2334
2335 if (except >= 1)
2336 for (n = 1; va_arg(ap, int) >= 0; n++)
2337 ;
2338
2339 va_end(ap);
2340
2341 p = pa_xnew(int, n+1);
2342
2343 va_start(ap, except);
2344
2345 i = 0;
2346 if (except >= 1) {
2347 int sig;
2348 p[i++] = except;
2349
2350 while ((sig = va_arg(ap, int)) >= 0)
2351 p[i++] = sig;
2352 }
2353 p[i] = -1;
2354
2355 va_end(ap);
2356
2357 r = pa_unblock_sigsv(p);
2358 pa_xfree(p);
2359
2360 return r;
2361 }
2362
2363 int pa_unblock_sigsv(const int except[]) {
2364 int i;
2365 sigset_t ss;
2366
2367 if (sigemptyset(&ss) < 0)
2368 return -1;
2369
2370 for (i = 0; except[i] > 0; i++)
2371 if (sigaddset(&ss, except[i]) < 0)
2372 return -1;
2373
2374 return sigprocmask(SIG_SETMASK, &ss, NULL);
2375 }
2376
2377 int pa_reset_sigs(int except, ...) {
2378 va_list ap;
2379 unsigned n = 0, i;
2380 int *p, r;
2381
2382 va_start(ap, except);
2383
2384 if (except >= 1)
2385 for (n = 1; va_arg(ap, int) >= 0; n++)
2386 ;
2387
2388 va_end(ap);
2389
2390 p = pa_xnew(int, n+1);
2391
2392 va_start(ap, except);
2393
2394 i = 0;
2395 if (except >= 1) {
2396 int sig;
2397 p[i++] = except;
2398
2399 while ((sig = va_arg(ap, int)) >= 0)
2400 sig = p[i++];
2401 }
2402 p[i] = -1;
2403
2404 va_end(ap);
2405
2406 r = pa_reset_sigsv(p);
2407 pa_xfree(p);
2408
2409 return r;
2410 }
2411
2412 int pa_reset_sigsv(const int except[]) {
2413 int sig;
2414
2415 for (sig = 1; sig < NSIG; sig++) {
2416 pa_bool_t reset = TRUE;
2417
2418 switch (sig) {
2419 case SIGKILL:
2420 case SIGSTOP:
2421 reset = FALSE;
2422 break;
2423
2424 default: {
2425 int i;
2426
2427 for (i = 0; except[i] > 0; i++) {
2428 if (sig == except[i]) {
2429 reset = FALSE;
2430 break;
2431 }
2432 }
2433 }
2434 }
2435
2436 if (reset) {
2437 struct sigaction sa;
2438
2439 memset(&sa, 0, sizeof(sa));
2440 sa.sa_handler = SIG_DFL;
2441
2442 /* On Linux the first two RT signals are reserved by
2443 * glibc, and sigaction() will return EINVAL for them. */
2444 if ((sigaction(sig, &sa, NULL) < 0))
2445 if (errno != EINVAL)
2446 return -1;
2447 }
2448 }
2449
2450 return 0;
2451 }
2452
2453 void pa_set_env(const char *key, const char *value) {
2454 pa_assert(key);
2455 pa_assert(value);
2456
2457 /* This is not thread-safe */
2458
2459 putenv(pa_sprintf_malloc("%s=%s", key, value));
2460 }
2461
2462 void pa_set_env_and_record(const char *key, const char *value) {
2463 pa_assert(key);
2464 pa_assert(value);
2465
2466 /* This is not thread-safe */
2467
2468 pa_set_env(key, value);
2469 recorded_env = pa_strlist_prepend(recorded_env, key);
2470 }
2471
2472 void pa_unset_env_recorded(void) {
2473
2474 /* This is not thread-safe */
2475
2476 for (;;) {
2477 char *s = NULL;
2478
2479 if (!(recorded_env = pa_strlist_pop(recorded_env, &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_unescape(char *p) {
2682 char *s, *d;
2683 pa_bool_t escaped = FALSE;
2684
2685 for (s = p, d = p; *s; s++) {
2686 if (!escaped && *s == '\\') {
2687 escaped = TRUE;
2688 continue;
2689 }
2690
2691 *(d++) = *s;
2692 escaped = FALSE;
2693 }
2694
2695 *d = 0;
2696
2697 return p;
2698 }
2699
2700 char *pa_realpath(const char *path) {
2701 char *t;
2702 pa_assert(path);
2703
2704 /* We want only abolsute paths */
2705 if (path[0] != '/') {
2706 errno = EINVAL;
2707 return NULL;
2708 }
2709
2710 #if defined(__GLIBC__) || defined(__APPLE__)
2711 {
2712 char *r;
2713
2714 if (!(r = realpath(path, NULL)))
2715 return NULL;
2716
2717 /* We copy this here in case our pa_xmalloc() is not
2718 * implemented on top of libc malloc() */
2719 t = pa_xstrdup(r);
2720 pa_xfree(r);
2721 }
2722 #elif defined(PATH_MAX)
2723 {
2724 char *path_buf;
2725 path_buf = pa_xmalloc(PATH_MAX);
2726
2727 if (!(t = realpath(path, path_buf))) {
2728 pa_xfree(path_buf);
2729 return NULL;
2730 }
2731 }
2732 #else
2733 #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."
2734 #endif
2735
2736 return t;
2737 }
2738
2739 void pa_disable_sigpipe(void) {
2740
2741 #ifdef SIGPIPE
2742 struct sigaction sa;
2743
2744 pa_zero(sa);
2745
2746 if (sigaction(SIGPIPE, NULL, &sa) < 0) {
2747 pa_log("sigaction(): %s", pa_cstrerror(errno));
2748 return;
2749 }
2750
2751 sa.sa_handler = SIG_IGN;
2752
2753 if (sigaction(SIGPIPE, &sa, NULL) < 0) {
2754 pa_log("sigaction(): %s", pa_cstrerror(errno));
2755 return;
2756 }
2757 #endif
2758 }
2759
2760 void pa_xfreev(void**a) {
2761 void **p;
2762
2763 if (!a)
2764 return;
2765
2766 for (p = a; *p; p++)
2767 pa_xfree(*p);
2768
2769 pa_xfree(a);
2770 }
2771
2772 char **pa_split_spaces_strv(const char *s) {
2773 char **t, *e;
2774 unsigned i = 0, n = 8;
2775 const char *state = NULL;
2776
2777 t = pa_xnew(char*, n);
2778 while ((e = pa_split_spaces(s, &state))) {
2779 t[i++] = e;
2780
2781 if (i >= n) {
2782 n *= 2;
2783 t = pa_xrenew(char*, t, n);
2784 }
2785 }
2786
2787 if (i <= 0) {
2788 pa_xfree(t);
2789 return NULL;
2790 }
2791
2792 t[i] = NULL;
2793 return t;
2794 }
2795
2796 char* pa_maybe_prefix_path(const char *path, const char *prefix) {
2797 pa_assert(path);
2798
2799 if (pa_is_path_absolute(path))
2800 return pa_xstrdup(path);
2801
2802 return pa_sprintf_malloc("%s" PA_PATH_SEP "%s", prefix, path);
2803 }
2804
2805 size_t pa_pipe_buf(int fd) {
2806
2807 #ifdef _PC_PIPE_BUF
2808 long n;
2809
2810 if ((n = fpathconf(fd, _PC_PIPE_BUF)) >= 0)
2811 return (size_t) n;
2812 #endif
2813
2814 #ifdef PIPE_BUF
2815 return PIPE_BUF;
2816 #else
2817 return 4096;
2818 #endif
2819 }
2820
2821 void pa_reset_personality(void) {
2822
2823 #ifdef __linux__
2824 if (personality(PER_LINUX) < 0)
2825 pa_log_warn("Uh, personality() failed: %s", pa_cstrerror(errno));
2826 #endif
2827
2828 }
2829
2830 #if defined(__linux__) && !defined(__OPTIMIZE__)
2831
2832 pa_bool_t pa_run_from_build_tree(void) {
2833 char *rp;
2834 pa_bool_t b = FALSE;
2835
2836 /* We abuse __OPTIMIZE__ as a check whether we are a debug build
2837 * or not. */
2838
2839 if ((rp = pa_readlink("/proc/self/exe"))) {
2840 b = pa_startswith(rp, PA_BUILDDIR);
2841 pa_xfree(rp);
2842 }
2843
2844 return b;
2845 }
2846
2847 #endif