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