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