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