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