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