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