]> code.delx.au - pulseaudio/blob - src/pulsecore/core-util.c
Get rid of some unused-function compiler warnings
[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 {
1048 if (!errno)
1049 errno = ENOENT;
1050
1051 pa_log("pa_getgrgid_malloc(%u): %s", gid, pa_cstrerror(errno));
1052
1053 goto finish;
1054 }
1055
1056 r = strcmp(name, group->gr_name) == 0;
1057
1058 finish:
1059 pa_getgrgid_free(group);
1060
1061 return r;
1062 }
1063
1064 /* Check the current user is member of the specified group */
1065 int pa_own_uid_in_group(const char *name, gid_t *gid) {
1066 GETGROUPS_T *gids, tgid;
1067 long n = sysconf(_SC_NGROUPS_MAX);
1068 int r = -1, i, k;
1069
1070 pa_assert(n > 0);
1071
1072 gids = pa_xmalloc(sizeof(GETGROUPS_T) * (size_t) n);
1073
1074 if ((n = getgroups((int) n, gids)) < 0) {
1075 pa_log("getgroups(): %s", pa_cstrerror(errno));
1076 goto finish;
1077 }
1078
1079 for (i = 0; i < n; i++) {
1080
1081 if ((k = is_group(gids[i], name)) < 0)
1082 goto finish;
1083 else if (k > 0) {
1084 *gid = gids[i];
1085 r = 1;
1086 goto finish;
1087 }
1088 }
1089
1090 if ((k = is_group(tgid = getgid(), name)) < 0)
1091 goto finish;
1092 else if (k > 0) {
1093 *gid = tgid;
1094 r = 1;
1095 goto finish;
1096 }
1097
1098 r = 0;
1099
1100 finish:
1101
1102 pa_xfree(gids);
1103 return r;
1104 }
1105
1106 /* Check whether the specifc user id is a member of the specified group */
1107 int pa_uid_in_group(uid_t uid, const char *name) {
1108 struct group *group = NULL;
1109 char **i;
1110 int r = -1;
1111
1112 errno = 0;
1113 if (!(group = pa_getgrnam_malloc(name)))
1114 {
1115 if (!errno)
1116 errno = ENOENT;
1117 goto finish;
1118 }
1119
1120 r = 0;
1121 for (i = group->gr_mem; *i; i++) {
1122 struct passwd *pw = NULL;
1123
1124 errno = 0;
1125 if (!(pw = pa_getpwnam_malloc(*i)))
1126 continue;
1127
1128 if (pw->pw_uid == uid)
1129 r = 1;
1130
1131 pa_getpwnam_free(pw);
1132
1133 if (r == 1)
1134 break;
1135 }
1136
1137 finish:
1138 pa_getgrnam_free(group);
1139
1140 return r;
1141 }
1142
1143 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
1144 gid_t pa_get_gid_of_group(const char *name) {
1145 gid_t ret = (gid_t) -1;
1146 struct group *gr = NULL;
1147
1148 errno = 0;
1149 if (!(gr = pa_getgrnam_malloc(name)))
1150 {
1151 if (!errno)
1152 errno = ENOENT;
1153 goto finish;
1154 }
1155
1156 ret = gr->gr_gid;
1157
1158 finish:
1159 pa_getgrnam_free(gr);
1160 return ret;
1161 }
1162
1163 int pa_check_in_group(gid_t g) {
1164 gid_t gids[NGROUPS_MAX];
1165 int r;
1166
1167 if ((r = getgroups(NGROUPS_MAX, gids)) < 0)
1168 return -1;
1169
1170 for (; r > 0; r--)
1171 if (gids[r-1] == g)
1172 return 1;
1173
1174 return 0;
1175 }
1176
1177 #else /* HAVE_GRP_H */
1178
1179 int pa_own_uid_in_group(const char *name, gid_t *gid) {
1180 errno = ENOTSUP;
1181 return -1;
1182
1183 }
1184
1185 int pa_uid_in_group(uid_t uid, const char *name) {
1186 errno = ENOTSUP;
1187 return -1;
1188 }
1189
1190 gid_t pa_get_gid_of_group(const char *name) {
1191 errno = ENOTSUP;
1192 return (gid_t) -1;
1193 }
1194
1195 int pa_check_in_group(gid_t g) {
1196 errno = ENOTSUP;
1197 return -1;
1198 }
1199
1200 #endif
1201
1202 /* Lock or unlock a file entirely.
1203 (advisory on UNIX, mandatory on Windows) */
1204 int pa_lock_fd(int fd, int b) {
1205 #ifdef F_SETLKW
1206 struct flock f_lock;
1207
1208 /* Try a R/W lock first */
1209
1210 f_lock.l_type = (short) (b ? F_WRLCK : F_UNLCK);
1211 f_lock.l_whence = SEEK_SET;
1212 f_lock.l_start = 0;
1213 f_lock.l_len = 0;
1214
1215 if (fcntl(fd, F_SETLKW, &f_lock) >= 0)
1216 return 0;
1217
1218 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1219 if (b && errno == EBADF) {
1220 f_lock.l_type = F_RDLCK;
1221 if (fcntl(fd, F_SETLKW, &f_lock) >= 0)
1222 return 0;
1223 }
1224
1225 pa_log("%slock: %s", !b? "un" : "", pa_cstrerror(errno));
1226 #endif
1227
1228 #ifdef OS_IS_WIN32
1229 HANDLE h = (HANDLE)_get_osfhandle(fd);
1230
1231 if (b && LockFile(h, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1232 return 0;
1233 if (!b && UnlockFile(h, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1234 return 0;
1235
1236 pa_log("%slock failed: 0x%08X", !b ? "un" : "", GetLastError());
1237
1238 /* FIXME: Needs to set errno! */
1239 #endif
1240
1241 return -1;
1242 }
1243
1244 /* Remove trailing newlines from a string */
1245 char* pa_strip_nl(char *s) {
1246 pa_assert(s);
1247
1248 s[strcspn(s, NEWLINE)] = 0;
1249 return s;
1250 }
1251
1252 char *pa_strip(char *s) {
1253 char *e, *l = NULL;
1254
1255 /* Drops trailing whitespace. Modifies the string in
1256 * place. Returns pointer to first non-space character */
1257
1258 s += strspn(s, WHITESPACE);
1259
1260 for (e = s; *e; e++)
1261 if (!strchr(WHITESPACE, *e))
1262 l = e;
1263
1264 if (l)
1265 *(l+1) = 0;
1266 else
1267 *s = 0;
1268
1269 return s;
1270 }
1271
1272 /* Create a temporary lock file and lock it. */
1273 int pa_lock_lockfile(const char *fn) {
1274 int fd;
1275 pa_assert(fn);
1276
1277 for (;;) {
1278 struct stat st;
1279
1280 if ((fd = pa_open_cloexec(fn, O_CREAT|O_RDWR
1281 #ifdef O_NOFOLLOW
1282 |O_NOFOLLOW
1283 #endif
1284 , S_IRUSR|S_IWUSR)) < 0) {
1285 pa_log_warn("Failed to create lock file '%s': %s", fn, pa_cstrerror(errno));
1286 goto fail;
1287 }
1288
1289 if (pa_lock_fd(fd, 1) < 0) {
1290 pa_log_warn("Failed to lock file '%s'.", fn);
1291 goto fail;
1292 }
1293
1294 if (fstat(fd, &st) < 0) {
1295 pa_log_warn("Failed to fstat() file '%s': %s", fn, pa_cstrerror(errno));
1296 goto fail;
1297 }
1298
1299 /* Check whether the file has been removed meanwhile. When yes,
1300 * restart this loop, otherwise, we're done */
1301 if (st.st_nlink >= 1)
1302 break;
1303
1304 if (pa_lock_fd(fd, 0) < 0) {
1305 pa_log_warn("Failed to unlock file '%s'.", fn);
1306 goto fail;
1307 }
1308
1309 if (pa_close(fd) < 0) {
1310 pa_log_warn("Failed to close file '%s': %s", fn, pa_cstrerror(errno));
1311 fd = -1;
1312 goto fail;
1313 }
1314 }
1315
1316 return fd;
1317
1318 fail:
1319
1320 if (fd >= 0) {
1321 int saved_errno = errno;
1322 pa_close(fd);
1323 errno = saved_errno;
1324 }
1325
1326 return -1;
1327 }
1328
1329 /* Unlock a temporary lcok file */
1330 int pa_unlock_lockfile(const char *fn, int fd) {
1331 int r = 0;
1332 pa_assert(fd >= 0);
1333
1334 if (fn) {
1335 if (unlink(fn) < 0) {
1336 pa_log_warn("Unable to remove lock file '%s': %s", fn, pa_cstrerror(errno));
1337 r = -1;
1338 }
1339 }
1340
1341 if (pa_lock_fd(fd, 0) < 0) {
1342 pa_log_warn("Failed to unlock file '%s'.", fn);
1343 r = -1;
1344 }
1345
1346 if (pa_close(fd) < 0) {
1347 pa_log_warn("Failed to close '%s': %s", fn, pa_cstrerror(errno));
1348 r = -1;
1349 }
1350
1351 return r;
1352 }
1353
1354 static char *get_pulse_home(void) {
1355 char *h;
1356 struct stat st;
1357 char *ret = NULL;
1358
1359 if (!(h = pa_get_home_dir_malloc())) {
1360 pa_log_error("Failed to get home directory.");
1361 return NULL;
1362 }
1363
1364 if (stat(h, &st) < 0) {
1365 pa_log_error("Failed to stat home directory %s: %s", h, pa_cstrerror(errno));
1366 goto finish;
1367 }
1368
1369 #ifdef HAVE_GETUID
1370 if (st.st_uid != getuid()) {
1371 pa_log_error("Home directory %s not ours.", h);
1372 errno = EACCES;
1373 goto finish;
1374 }
1375 #endif
1376
1377 ret = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse", h);
1378
1379 finish:
1380 pa_xfree(h);
1381
1382 return ret;
1383 }
1384
1385 char *pa_get_state_dir(void) {
1386 char *d;
1387
1388 /* The state directory shall contain dynamic data that should be
1389 * kept across reboots, and is private to this user */
1390
1391 if (!(d = pa_xstrdup(getenv("PULSE_STATE_PATH"))))
1392 if (!(d = get_pulse_home()))
1393 return NULL;
1394
1395 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1396 * dir then this will break. */
1397
1398 if (pa_make_secure_dir(d, 0700U, (uid_t) -1, (gid_t) -1) < 0) {
1399 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1400 pa_xfree(d);
1401 return NULL;
1402 }
1403
1404 return d;
1405 }
1406
1407 char *pa_get_home_dir_malloc(void) {
1408 char *homedir;
1409 size_t allocated = 128;
1410
1411 for (;;) {
1412 homedir = pa_xmalloc(allocated);
1413
1414 if (!pa_get_home_dir(homedir, allocated)) {
1415 pa_xfree(homedir);
1416 return NULL;
1417 }
1418
1419 if (strlen(homedir) < allocated - 1)
1420 break;
1421
1422 pa_xfree(homedir);
1423 allocated *= 2;
1424 }
1425
1426 return homedir;
1427 }
1428
1429 char *pa_get_binary_name_malloc(void) {
1430 char *t;
1431 size_t allocated = 128;
1432
1433 for (;;) {
1434 t = pa_xmalloc(allocated);
1435
1436 if (!pa_get_binary_name(t, allocated)) {
1437 pa_xfree(t);
1438 return NULL;
1439 }
1440
1441 if (strlen(t) < allocated - 1)
1442 break;
1443
1444 pa_xfree(t);
1445 allocated *= 2;
1446 }
1447
1448 return t;
1449 }
1450
1451 static char* make_random_dir(mode_t m) {
1452 static const char table[] =
1453 "abcdefghijklmnopqrstuvwxyz"
1454 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1455 "0123456789";
1456
1457 char *fn;
1458 size_t pathlen;
1459
1460 fn = pa_sprintf_malloc("%s" PA_PATH_SEP "pulse-XXXXXXXXXXXX", pa_get_temp_dir());
1461 pathlen = strlen(fn);
1462
1463 for (;;) {
1464 size_t i;
1465 int r;
1466 mode_t u;
1467 int saved_errno;
1468
1469 for (i = pathlen - 12; i < pathlen; i++)
1470 fn[i] = table[rand() % (sizeof(table)-1)];
1471
1472 u = umask((~m) & 0777);
1473 #ifndef OS_IS_WIN32
1474 r = mkdir(fn, m);
1475 #else
1476 r = mkdir(fn);
1477 #endif
1478
1479 saved_errno = errno;
1480 umask(u);
1481 errno = saved_errno;
1482
1483 if (r >= 0)
1484 return fn;
1485
1486 if (errno != EEXIST) {
1487 pa_log_error("Failed to create random directory %s: %s", fn, pa_cstrerror(errno));
1488 pa_xfree(fn);
1489 return NULL;
1490 }
1491 }
1492 }
1493
1494 static int make_random_dir_and_link(mode_t m, const char *k) {
1495 char *p;
1496
1497 if (!(p = make_random_dir(m)))
1498 return -1;
1499
1500 #ifdef HAVE_SYMLINK
1501 if (symlink(p, k) < 0) {
1502 int saved_errno = errno;
1503
1504 if (errno != EEXIST)
1505 pa_log_error("Failed to symlink %s to %s: %s", k, p, pa_cstrerror(errno));
1506
1507 rmdir(p);
1508 pa_xfree(p);
1509
1510 errno = saved_errno;
1511 return -1;
1512 }
1513 #else
1514 pa_xfree(p);
1515 return -1;
1516 #endif
1517
1518 pa_xfree(p);
1519 return 0;
1520 }
1521
1522 char *pa_get_runtime_dir(void) {
1523 char *d, *k = NULL, *p = NULL, *t = NULL, *mid;
1524 struct stat st;
1525 mode_t m;
1526
1527 /* The runtime directory shall contain dynamic data that needs NOT
1528 * to be kept accross reboots and is usuallly private to the user,
1529 * except in system mode, where it might be accessible by other
1530 * users, too. Since we need POSIX locking and UNIX sockets in
1531 * this directory, we link it to a random subdir in /tmp, if it
1532 * was not explicitly configured. */
1533
1534 m = pa_in_system_mode() ? 0755U : 0700U;
1535
1536 if ((d = getenv("PULSE_RUNTIME_PATH"))) {
1537
1538 if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0) {
1539 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1540 goto fail;
1541 }
1542
1543 return pa_xstrdup(d);
1544 }
1545
1546 if (!(d = get_pulse_home()))
1547 goto fail;
1548
1549 if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0) {
1550 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1551 pa_xfree(d);
1552 goto fail;
1553 }
1554
1555 if (!(mid = pa_machine_id())) {
1556 pa_xfree(d);
1557 goto fail;
1558 }
1559
1560 k = pa_sprintf_malloc("%s" PA_PATH_SEP "%s-runtime", d, mid);
1561 pa_xfree(d);
1562 pa_xfree(mid);
1563
1564 for (;;) {
1565 /* OK, first let's check if the "runtime" symlink is already
1566 * existant */
1567
1568 if (!(p = pa_readlink(k))) {
1569
1570 if (errno != ENOENT) {
1571 pa_log_error("Failed to stat runtime directory %s: %s", k, pa_cstrerror(errno));
1572 goto fail;
1573 }
1574
1575 #ifdef HAVE_SYMLINK
1576 /* Hmm, so the runtime directory didn't exist yet, so let's
1577 * create one in /tmp and symlink that to it */
1578
1579 if (make_random_dir_and_link(0700, k) < 0) {
1580
1581 /* Mhmm, maybe another process was quicker than us,
1582 * let's check if that was valid */
1583 if (errno == EEXIST)
1584 continue;
1585
1586 goto fail;
1587 }
1588 #else
1589 /* No symlink possible, so let's just create the runtime directly */
1590 if (!mkdir(k))
1591 goto fail;
1592 #endif
1593
1594 return k;
1595 }
1596
1597 /* Make sure that this actually makes sense */
1598 if (!pa_is_path_absolute(p)) {
1599 pa_log_error("Path %s in link %s is not absolute.", p, k);
1600 errno = ENOENT;
1601 goto fail;
1602 }
1603
1604 /* Hmm, so this symlink is still around, make sure nobody fools
1605 * us */
1606
1607 #ifdef HAVE_LSTAT
1608 if (lstat(p, &st) < 0) {
1609
1610 if (errno != ENOENT) {
1611 pa_log_error("Failed to stat runtime directory %s: %s", p, pa_cstrerror(errno));
1612 goto fail;
1613 }
1614
1615 } else {
1616
1617 if (S_ISDIR(st.st_mode) &&
1618 (st.st_uid == getuid()) &&
1619 ((st.st_mode & 0777) == 0700)) {
1620
1621 pa_xfree(p);
1622 return k;
1623 }
1624
1625 pa_log_info("Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory.");
1626 }
1627 #endif
1628
1629 pa_xfree(p);
1630 p = NULL;
1631
1632 /* Hmm, so the link points to some nonexisting or invalid
1633 * dir. Let's replace it by a new link. We first create a
1634 * temporary link and then rename that to allow concurrent
1635 * execution of this function. */
1636
1637 t = pa_sprintf_malloc("%s.tmp", k);
1638
1639 if (make_random_dir_and_link(0700, t) < 0) {
1640
1641 if (errno != EEXIST) {
1642 pa_log_error("Failed to symlink %s: %s", t, pa_cstrerror(errno));
1643 goto fail;
1644 }
1645
1646 pa_xfree(t);
1647 t = NULL;
1648
1649 /* Hmm, someone lese was quicker then us. Let's give
1650 * him some time to finish, and retry. */
1651 pa_msleep(10);
1652 continue;
1653 }
1654
1655 /* OK, we succeeded in creating the temporary symlink, so
1656 * let's rename it */
1657 if (rename(t, k) < 0) {
1658 pa_log_error("Failed to rename %s to %s: %s", t, k, pa_cstrerror(errno));
1659 goto fail;
1660 }
1661
1662 pa_xfree(t);
1663 return k;
1664 }
1665
1666 fail:
1667 pa_xfree(p);
1668 pa_xfree(k);
1669 pa_xfree(t);
1670
1671 return NULL;
1672 }
1673
1674 /* Try to open a configuration file. If "env" is specified, open the
1675 * value of the specified environment variable. Otherwise look for a
1676 * file "local" in the home directory or a file "global" in global
1677 * file system. If "result" is non-NULL, a pointer to a newly
1678 * allocated buffer containing the used configuration file is
1679 * stored there.*/
1680 FILE *pa_open_config_file(const char *global, const char *local, const char *env, char **result) {
1681 const char *fn;
1682 #ifdef OS_IS_WIN32
1683 char buf[PATH_MAX];
1684
1685 if (!getenv(PULSE_ROOTENV))
1686 pa_set_root(NULL);
1687 #endif
1688
1689 if (env && (fn = getenv(env))) {
1690 FILE *f;
1691
1692 #ifdef OS_IS_WIN32
1693 if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
1694 /* FIXME: Needs to set errno! */
1695 return NULL;
1696 fn = buf;
1697 #endif
1698
1699 if ((f = pa_fopen_cloexec(fn, "r"))) {
1700 if (result)
1701 *result = pa_xstrdup(fn);
1702
1703 return f;
1704 }
1705
1706 pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
1707 return NULL;
1708 }
1709
1710 if (local) {
1711 const char *e;
1712 char *lfn;
1713 char *h;
1714 FILE *f;
1715
1716 if ((e = getenv("PULSE_CONFIG_PATH")))
1717 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
1718 else if ((h = pa_get_home_dir_malloc())) {
1719 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
1720 pa_xfree(h);
1721 } else
1722 return NULL;
1723
1724 #ifdef OS_IS_WIN32
1725 if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) {
1726 /* FIXME: Needs to set errno! */
1727 pa_xfree(lfn);
1728 return NULL;
1729 }
1730 fn = buf;
1731 #endif
1732
1733 if ((f = pa_fopen_cloexec(fn, "r"))) {
1734 if (result)
1735 *result = pa_xstrdup(fn);
1736
1737 pa_xfree(lfn);
1738 return f;
1739 }
1740
1741 if (errno != ENOENT) {
1742 pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
1743 pa_xfree(lfn);
1744 return NULL;
1745 }
1746
1747 pa_xfree(lfn);
1748 }
1749
1750 if (global) {
1751 FILE *f;
1752
1753 #ifdef OS_IS_WIN32
1754 if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
1755 /* FIXME: Needs to set errno! */
1756 return NULL;
1757 global = buf;
1758 #endif
1759
1760 if ((f = pa_fopen_cloexec(global, "r"))) {
1761
1762 if (result)
1763 *result = pa_xstrdup(global);
1764
1765 return f;
1766 }
1767 }
1768
1769 errno = ENOENT;
1770 return NULL;
1771 }
1772
1773 char *pa_find_config_file(const char *global, const char *local, const char *env) {
1774 const char *fn;
1775 #ifdef OS_IS_WIN32
1776 char buf[PATH_MAX];
1777
1778 if (!getenv(PULSE_ROOTENV))
1779 pa_set_root(NULL);
1780 #endif
1781
1782 if (env && (fn = getenv(env))) {
1783
1784 #ifdef OS_IS_WIN32
1785 if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
1786 /* FIXME: Needs to set errno! */
1787 return NULL;
1788 fn = buf;
1789 #endif
1790
1791 if (access(fn, R_OK) == 0)
1792 return pa_xstrdup(fn);
1793
1794 pa_log_warn("Failed to access configuration file '%s': %s", fn, pa_cstrerror(errno));
1795 return NULL;
1796 }
1797
1798 if (local) {
1799 const char *e;
1800 char *lfn;
1801 char *h;
1802
1803 if ((e = getenv("PULSE_CONFIG_PATH")))
1804 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
1805 else if ((h = pa_get_home_dir_malloc())) {
1806 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
1807 pa_xfree(h);
1808 } else
1809 return NULL;
1810
1811 #ifdef OS_IS_WIN32
1812 if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) {
1813 /* FIXME: Needs to set errno! */
1814 pa_xfree(lfn);
1815 return NULL;
1816 }
1817 fn = buf;
1818 #endif
1819
1820 if (access(fn, R_OK) == 0) {
1821 char *r = pa_xstrdup(fn);
1822 pa_xfree(lfn);
1823 return r;
1824 }
1825
1826 if (errno != ENOENT) {
1827 pa_log_warn("Failed to access configuration file '%s': %s", fn, pa_cstrerror(errno));
1828 pa_xfree(lfn);
1829 return NULL;
1830 }
1831
1832 pa_xfree(lfn);
1833 }
1834
1835 if (global) {
1836 #ifdef OS_IS_WIN32
1837 if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
1838 /* FIXME: Needs to set errno! */
1839 return NULL;
1840 global = buf;
1841 #endif
1842
1843 if (access(global, R_OK) == 0)
1844 return pa_xstrdup(global);
1845 }
1846
1847 errno = ENOENT;
1848
1849 return NULL;
1850 }
1851
1852 /* Format the specified data as a hexademical string */
1853 char *pa_hexstr(const uint8_t* d, size_t dlength, char *s, size_t slength) {
1854 size_t i = 0, j = 0;
1855 const char hex[] = "0123456789abcdef";
1856
1857 pa_assert(d);
1858 pa_assert(s);
1859 pa_assert(slength > 0);
1860
1861 while (i < dlength && j+3 <= slength) {
1862 s[j++] = hex[*d >> 4];
1863 s[j++] = hex[*d & 0xF];
1864
1865 d++;
1866 i++;
1867 }
1868
1869 s[j < slength ? j : slength] = 0;
1870 return s;
1871 }
1872
1873 /* Convert a hexadecimal digit to a number or -1 if invalid */
1874 static int hexc(char c) {
1875 if (c >= '0' && c <= '9')
1876 return c - '0';
1877
1878 if (c >= 'A' && c <= 'F')
1879 return c - 'A' + 10;
1880
1881 if (c >= 'a' && c <= 'f')
1882 return c - 'a' + 10;
1883
1884 errno = EINVAL;
1885 return -1;
1886 }
1887
1888 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1889 size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength) {
1890 size_t j = 0;
1891
1892 pa_assert(p);
1893 pa_assert(d);
1894
1895 while (j < dlength && *p) {
1896 int b;
1897
1898 if ((b = hexc(*(p++))) < 0)
1899 return (size_t) -1;
1900
1901 d[j] = (uint8_t) (b << 4);
1902
1903 if (!*p)
1904 return (size_t) -1;
1905
1906 if ((b = hexc(*(p++))) < 0)
1907 return (size_t) -1;
1908
1909 d[j] |= (uint8_t) b;
1910 j++;
1911 }
1912
1913 return j;
1914 }
1915
1916 /* Returns nonzero when *s starts with *pfx */
1917 pa_bool_t pa_startswith(const char *s, const char *pfx) {
1918 size_t l;
1919
1920 pa_assert(s);
1921 pa_assert(pfx);
1922
1923 l = strlen(pfx);
1924
1925 return strlen(s) >= l && strncmp(s, pfx, l) == 0;
1926 }
1927
1928 /* Returns nonzero when *s ends with *sfx */
1929 pa_bool_t pa_endswith(const char *s, const char *sfx) {
1930 size_t l1, l2;
1931
1932 pa_assert(s);
1933 pa_assert(sfx);
1934
1935 l1 = strlen(s);
1936 l2 = strlen(sfx);
1937
1938 return l1 >= l2 && strcmp(s+l1-l2, sfx) == 0;
1939 }
1940
1941 pa_bool_t pa_is_path_absolute(const char *fn) {
1942 pa_assert(fn);
1943
1944 #ifndef OS_IS_WIN32
1945 return *fn == '/';
1946 #else
1947 return strlen(fn) >= 3 && isalpha(fn[0]) && fn[1] == ':' && fn[2] == '\\';
1948 #endif
1949 }
1950
1951 char *pa_make_path_absolute(const char *p) {
1952 char *r;
1953 char *cwd;
1954
1955 pa_assert(p);
1956
1957 if (pa_is_path_absolute(p))
1958 return pa_xstrdup(p);
1959
1960 if (!(cwd = pa_getcwd()))
1961 return pa_xstrdup(p);
1962
1963 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", cwd, p);
1964 pa_xfree(cwd);
1965 return r;
1966 }
1967
1968 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1969 * if fn is non-null and starts with / return fn
1970 * otherwise append fn to the run time path and return it */
1971 static char *get_path(const char *fn, pa_bool_t prependmid, pa_bool_t rt) {
1972 char *rtp;
1973
1974 rtp = rt ? pa_get_runtime_dir() : pa_get_state_dir();
1975
1976 if (fn) {
1977 char *r;
1978
1979 if (pa_is_path_absolute(fn))
1980 return pa_xstrdup(fn);
1981
1982 if (!rtp)
1983 return NULL;
1984
1985 if (prependmid) {
1986 char *mid;
1987
1988 if (!(mid = pa_machine_id())) {
1989 pa_xfree(rtp);
1990 return NULL;
1991 }
1992
1993 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s-%s", rtp, mid, fn);
1994 pa_xfree(mid);
1995 } else
1996 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", rtp, fn);
1997
1998 pa_xfree(rtp);
1999 return r;
2000 } else
2001 return rtp;
2002 }
2003
2004 char *pa_runtime_path(const char *fn) {
2005 return get_path(fn, FALSE, TRUE);
2006 }
2007
2008 char *pa_state_path(const char *fn, pa_bool_t appendmid) {
2009 return get_path(fn, appendmid, FALSE);
2010 }
2011
2012 /* Convert the string s to a signed integer in *ret_i */
2013 int pa_atoi(const char *s, int32_t *ret_i) {
2014 char *x = NULL;
2015 long l;
2016
2017 pa_assert(s);
2018 pa_assert(ret_i);
2019
2020 errno = 0;
2021 l = strtol(s, &x, 0);
2022
2023 if (!x || *x || errno) {
2024 if (!errno)
2025 errno = EINVAL;
2026 return -1;
2027 }
2028
2029 if ((int32_t) l != l) {
2030 errno = ERANGE;
2031 return -1;
2032 }
2033
2034 *ret_i = (int32_t) l;
2035
2036 return 0;
2037 }
2038
2039 /* Convert the string s to an unsigned integer in *ret_u */
2040 int pa_atou(const char *s, uint32_t *ret_u) {
2041 char *x = NULL;
2042 unsigned long l;
2043
2044 pa_assert(s);
2045 pa_assert(ret_u);
2046
2047 errno = 0;
2048 l = strtoul(s, &x, 0);
2049
2050 if (!x || *x || errno) {
2051 if (!errno)
2052 errno = EINVAL;
2053 return -1;
2054 }
2055
2056 if ((uint32_t) l != l) {
2057 errno = ERANGE;
2058 return -1;
2059 }
2060
2061 *ret_u = (uint32_t) l;
2062
2063 return 0;
2064 }
2065
2066 #ifdef HAVE_STRTOF_L
2067 static locale_t c_locale = NULL;
2068
2069 static void c_locale_destroy(void) {
2070 freelocale(c_locale);
2071 }
2072 #endif
2073
2074 int pa_atod(const char *s, double *ret_d) {
2075 char *x = NULL;
2076 double f;
2077
2078 pa_assert(s);
2079 pa_assert(ret_d);
2080
2081 /* This should be locale independent */
2082
2083 #ifdef HAVE_STRTOF_L
2084
2085 PA_ONCE_BEGIN {
2086
2087 if ((c_locale = newlocale(LC_ALL_MASK, "C", NULL)))
2088 atexit(c_locale_destroy);
2089
2090 } PA_ONCE_END;
2091
2092 if (c_locale) {
2093 errno = 0;
2094 f = strtod_l(s, &x, c_locale);
2095 } else
2096 #endif
2097 {
2098 errno = 0;
2099 f = strtod(s, &x);
2100 }
2101
2102 if (!x || *x || errno) {
2103 if (!errno)
2104 errno = EINVAL;
2105 return -1;
2106 }
2107
2108 *ret_d = f;
2109
2110 return 0;
2111 }
2112
2113 /* Same as snprintf, but guarantees NUL-termination on every platform */
2114 size_t pa_snprintf(char *str, size_t size, const char *format, ...) {
2115 size_t ret;
2116 va_list ap;
2117
2118 pa_assert(str);
2119 pa_assert(size > 0);
2120 pa_assert(format);
2121
2122 va_start(ap, format);
2123 ret = pa_vsnprintf(str, size, format, ap);
2124 va_end(ap);
2125
2126 return ret;
2127 }
2128
2129 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2130 size_t pa_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
2131 int ret;
2132
2133 pa_assert(str);
2134 pa_assert(size > 0);
2135 pa_assert(format);
2136
2137 ret = vsnprintf(str, size, format, ap);
2138
2139 str[size-1] = 0;
2140
2141 if (ret < 0)
2142 return strlen(str);
2143
2144 if ((size_t) ret > size-1)
2145 return size-1;
2146
2147 return (size_t) ret;
2148 }
2149
2150 /* Truncate the specified string, but guarantee that the string
2151 * returned still validates as UTF8 */
2152 char *pa_truncate_utf8(char *c, size_t l) {
2153 pa_assert(c);
2154 pa_assert(pa_utf8_valid(c));
2155
2156 if (strlen(c) <= l)
2157 return c;
2158
2159 c[l] = 0;
2160
2161 while (l > 0 && !pa_utf8_valid(c))
2162 c[--l] = 0;
2163
2164 return c;
2165 }
2166
2167 char *pa_getcwd(void) {
2168 size_t l = 128;
2169
2170 for (;;) {
2171 char *p = pa_xmalloc(l);
2172 if (getcwd(p, l))
2173 return p;
2174
2175 if (errno != ERANGE)
2176 return NULL;
2177
2178 pa_xfree(p);
2179 l *= 2;
2180 }
2181 }
2182
2183 void *pa_will_need(const void *p, size_t l) {
2184 #ifdef RLIMIT_MEMLOCK
2185 struct rlimit rlim;
2186 #endif
2187 const void *a;
2188 size_t size;
2189 int r;
2190 size_t bs;
2191
2192 pa_assert(p);
2193 pa_assert(l > 0);
2194
2195 a = PA_PAGE_ALIGN_PTR(p);
2196 size = (size_t) ((const uint8_t*) p + l - (const uint8_t*) a);
2197
2198 #ifdef HAVE_POSIX_MADVISE
2199 if ((r = posix_madvise((void*) a, size, POSIX_MADV_WILLNEED)) == 0) {
2200 pa_log_debug("posix_madvise() worked fine!");
2201 return (void*) p;
2202 }
2203 #endif
2204
2205 /* Most likely the memory was not mmap()ed from a file and thus
2206 * madvise() didn't work, so let's misuse mlock() do page this
2207 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2208 * inviting, the man page of mlock() tells us: "All pages that
2209 * contain a part of the specified address range are guaranteed to
2210 * be resident in RAM when the call returns successfully." */
2211
2212 #ifdef RLIMIT_MEMLOCK
2213 pa_assert_se(getrlimit(RLIMIT_MEMLOCK, &rlim) == 0);
2214
2215 if (rlim.rlim_cur < PA_PAGE_SIZE) {
2216 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));
2217 errno = EPERM;
2218 return (void*) p;
2219 }
2220
2221 bs = PA_PAGE_ALIGN((size_t) rlim.rlim_cur);
2222 #else
2223 bs = PA_PAGE_SIZE*4;
2224 #endif
2225
2226 pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r));
2227
2228 #ifdef HAVE_MLOCK
2229 while (size > 0 && bs > 0) {
2230
2231 if (bs > size)
2232 bs = size;
2233
2234 if (mlock(a, bs) < 0) {
2235 bs = PA_PAGE_ALIGN(bs / 2);
2236 continue;
2237 }
2238
2239 pa_assert_se(munlock(a, bs) == 0);
2240
2241 a = (const uint8_t*) a + bs;
2242 size -= bs;
2243 }
2244 #endif
2245
2246 if (bs <= 0)
2247 pa_log_debug("mlock() failed too (or doesn't exist), giving up: %s", pa_cstrerror(errno));
2248 else
2249 pa_log_debug("mlock() worked fine!");
2250
2251 return (void*) p;
2252 }
2253
2254 void pa_close_pipe(int fds[2]) {
2255 pa_assert(fds);
2256
2257 if (fds[0] >= 0)
2258 pa_assert_se(pa_close(fds[0]) == 0);
2259
2260 if (fds[1] >= 0)
2261 pa_assert_se(pa_close(fds[1]) == 0);
2262
2263 fds[0] = fds[1] = -1;
2264 }
2265
2266 char *pa_readlink(const char *p) {
2267 #ifdef HAVE_READLINK
2268 size_t l = 100;
2269
2270 for (;;) {
2271 char *c;
2272 ssize_t n;
2273
2274 c = pa_xmalloc(l);
2275
2276 if ((n = readlink(p, c, l-1)) < 0) {
2277 pa_xfree(c);
2278 return NULL;
2279 }
2280
2281 if ((size_t) n < l-1) {
2282 c[n] = 0;
2283 return c;
2284 }
2285
2286 pa_xfree(c);
2287 l *= 2;
2288 }
2289 #else
2290 return NULL;
2291 #endif
2292 }
2293
2294 int pa_close_all(int except_fd, ...) {
2295 va_list ap;
2296 unsigned n = 0, i;
2297 int r, *p;
2298
2299 va_start(ap, except_fd);
2300
2301 if (except_fd >= 0)
2302 for (n = 1; va_arg(ap, int) >= 0; n++)
2303 ;
2304
2305 va_end(ap);
2306
2307 p = pa_xnew(int, n+1);
2308
2309 va_start(ap, except_fd);
2310
2311 i = 0;
2312 if (except_fd >= 0) {
2313 int fd;
2314 p[i++] = except_fd;
2315
2316 while ((fd = va_arg(ap, int)) >= 0)
2317 p[i++] = fd;
2318 }
2319 p[i] = -1;
2320
2321 va_end(ap);
2322
2323 r = pa_close_allv(p);
2324 pa_xfree(p);
2325
2326 return r;
2327 }
2328
2329 int pa_close_allv(const int except_fds[]) {
2330 #ifndef OS_IS_WIN32
2331 struct rlimit rl;
2332 int maxfd, fd;
2333
2334 #ifdef __linux__
2335 int saved_errno;
2336 DIR *d;
2337
2338 if ((d = opendir("/proc/self/fd"))) {
2339
2340 struct dirent *de;
2341
2342 while ((de = readdir(d))) {
2343 pa_bool_t found;
2344 long l;
2345 char *e = NULL;
2346 int i;
2347
2348 if (de->d_name[0] == '.')
2349 continue;
2350
2351 errno = 0;
2352 l = strtol(de->d_name, &e, 10);
2353 if (errno != 0 || !e || *e) {
2354 closedir(d);
2355 errno = EINVAL;
2356 return -1;
2357 }
2358
2359 fd = (int) l;
2360
2361 if ((long) fd != l) {
2362 closedir(d);
2363 errno = EINVAL;
2364 return -1;
2365 }
2366
2367 if (fd < 3)
2368 continue;
2369
2370 if (fd == dirfd(d))
2371 continue;
2372
2373 found = FALSE;
2374 for (i = 0; except_fds[i] >= 0; i++)
2375 if (except_fds[i] == fd) {
2376 found = TRUE;
2377 break;
2378 }
2379
2380 if (found)
2381 continue;
2382
2383 if (pa_close(fd) < 0) {
2384 saved_errno = errno;
2385 closedir(d);
2386 errno = saved_errno;
2387
2388 return -1;
2389 }
2390 }
2391
2392 closedir(d);
2393 return 0;
2394 }
2395
2396 #endif
2397
2398 if (getrlimit(RLIMIT_NOFILE, &rl) >= 0)
2399 maxfd = (int) rl.rlim_max;
2400 else
2401 maxfd = sysconf(_SC_OPEN_MAX);
2402
2403 for (fd = 3; fd < maxfd; fd++) {
2404 int i;
2405 pa_bool_t found;
2406
2407 found = FALSE;
2408 for (i = 0; except_fds[i] >= 0; i++)
2409 if (except_fds[i] == fd) {
2410 found = TRUE;
2411 break;
2412 }
2413
2414 if (found)
2415 continue;
2416
2417 if (pa_close(fd) < 0 && errno != EBADF)
2418 return -1;
2419 }
2420 #endif /* !OS_IS_WIN32 */
2421
2422 return 0;
2423 }
2424
2425 int pa_unblock_sigs(int except, ...) {
2426 va_list ap;
2427 unsigned n = 0, i;
2428 int r, *p;
2429
2430 va_start(ap, except);
2431
2432 if (except >= 1)
2433 for (n = 1; va_arg(ap, int) >= 0; n++)
2434 ;
2435
2436 va_end(ap);
2437
2438 p = pa_xnew(int, n+1);
2439
2440 va_start(ap, except);
2441
2442 i = 0;
2443 if (except >= 1) {
2444 int sig;
2445 p[i++] = except;
2446
2447 while ((sig = va_arg(ap, int)) >= 0)
2448 p[i++] = sig;
2449 }
2450 p[i] = -1;
2451
2452 va_end(ap);
2453
2454 r = pa_unblock_sigsv(p);
2455 pa_xfree(p);
2456
2457 return r;
2458 }
2459
2460 int pa_unblock_sigsv(const int except[]) {
2461 #ifndef OS_IS_WIN32
2462 int i;
2463 sigset_t ss;
2464
2465 if (sigemptyset(&ss) < 0)
2466 return -1;
2467
2468 for (i = 0; except[i] > 0; i++)
2469 if (sigaddset(&ss, except[i]) < 0)
2470 return -1;
2471
2472 return sigprocmask(SIG_SETMASK, &ss, NULL);
2473 #else
2474 return 0;
2475 #endif
2476 }
2477
2478 int pa_reset_sigs(int except, ...) {
2479 va_list ap;
2480 unsigned n = 0, i;
2481 int *p, r;
2482
2483 va_start(ap, except);
2484
2485 if (except >= 1)
2486 for (n = 1; va_arg(ap, int) >= 0; n++)
2487 ;
2488
2489 va_end(ap);
2490
2491 p = pa_xnew(int, n+1);
2492
2493 va_start(ap, except);
2494
2495 i = 0;
2496 if (except >= 1) {
2497 int sig;
2498 p[i++] = except;
2499
2500 while ((sig = va_arg(ap, int)) >= 0)
2501 p[i++] = sig;
2502 }
2503 p[i] = -1;
2504
2505 va_end(ap);
2506
2507 r = pa_reset_sigsv(p);
2508 pa_xfree(p);
2509
2510 return r;
2511 }
2512
2513 int pa_reset_sigsv(const int except[]) {
2514 #ifndef OS_IS_WIN32
2515 int sig;
2516
2517 for (sig = 1; sig < NSIG; sig++) {
2518 pa_bool_t reset = TRUE;
2519
2520 switch (sig) {
2521 case SIGKILL:
2522 case SIGSTOP:
2523 reset = FALSE;
2524 break;
2525
2526 default: {
2527 int i;
2528
2529 for (i = 0; except[i] > 0; i++) {
2530 if (sig == except[i]) {
2531 reset = FALSE;
2532 break;
2533 }
2534 }
2535 }
2536 }
2537
2538 if (reset) {
2539 struct sigaction sa;
2540
2541 memset(&sa, 0, sizeof(sa));
2542 sa.sa_handler = SIG_DFL;
2543
2544 /* On Linux the first two RT signals are reserved by
2545 * glibc, and sigaction() will return EINVAL for them. */
2546 if ((sigaction(sig, &sa, NULL) < 0))
2547 if (errno != EINVAL)
2548 return -1;
2549 }
2550 }
2551 #endif
2552
2553 return 0;
2554 }
2555
2556 void pa_set_env(const char *key, const char *value) {
2557 pa_assert(key);
2558 pa_assert(value);
2559
2560 /* This is not thread-safe */
2561
2562 #ifdef OS_IS_WIN32
2563 SetEnvironmentVariable(key, value);
2564 #else
2565 setenv(key, value, 1);
2566 #endif
2567 }
2568
2569 void pa_set_env_and_record(const char *key, const char *value) {
2570 pa_assert(key);
2571 pa_assert(value);
2572
2573 /* This is not thread-safe */
2574
2575 pa_set_env(key, value);
2576 recorded_env = pa_strlist_prepend(recorded_env, key);
2577 }
2578
2579 void pa_unset_env_recorded(void) {
2580
2581 /* This is not thread-safe */
2582
2583 for (;;) {
2584 char *s;
2585
2586 recorded_env = pa_strlist_pop(recorded_env, &s);
2587
2588 if (!s)
2589 break;
2590
2591 #ifdef OS_IS_WIN32
2592 SetEnvironmentVariable(s, NULL);
2593 #else
2594 unsetenv(s);
2595 #endif
2596 pa_xfree(s);
2597 }
2598 }
2599
2600 pa_bool_t pa_in_system_mode(void) {
2601 const char *e;
2602
2603 if (!(e = getenv("PULSE_SYSTEM")))
2604 return FALSE;
2605
2606 return !!atoi(e);
2607 }
2608
2609 char *pa_get_user_name_malloc(void) {
2610 ssize_t k;
2611 char *u;
2612
2613 #ifdef _SC_LOGIN_NAME_MAX
2614 k = (ssize_t) sysconf(_SC_LOGIN_NAME_MAX);
2615
2616 if (k <= 0)
2617 #endif
2618 k = 32;
2619
2620 u = pa_xnew(char, k+1);
2621
2622 if (!(pa_get_user_name(u, k))) {
2623 pa_xfree(u);
2624 return NULL;
2625 }
2626
2627 return u;
2628 }
2629
2630 char *pa_get_host_name_malloc(void) {
2631 size_t l;
2632
2633 l = 100;
2634 for (;;) {
2635 char *c;
2636
2637 c = pa_xmalloc(l);
2638
2639 if (!pa_get_host_name(c, l)) {
2640
2641 if (errno != EINVAL && errno != ENAMETOOLONG)
2642 break;
2643
2644 } else if (strlen(c) < l-1) {
2645 char *u;
2646
2647 if (*c == 0) {
2648 pa_xfree(c);
2649 break;
2650 }
2651
2652 u = pa_utf8_filter(c);
2653 pa_xfree(c);
2654 return u;
2655 }
2656
2657 /* Hmm, the hostname is as long the space we offered the
2658 * function, we cannot know if it fully fit in, so let's play
2659 * safe and retry. */
2660
2661 pa_xfree(c);
2662 l *= 2;
2663 }
2664
2665 return NULL;
2666 }
2667
2668 char *pa_machine_id(void) {
2669 FILE *f;
2670 char *h;
2671
2672 /* The returned value is supposed be some kind of ascii identifier
2673 * that is unique and stable across reboots. */
2674
2675 /* First we try the D-Bus UUID, which is the best option we have,
2676 * since it fits perfectly our needs and is not as volatile as the
2677 * hostname which might be set from dhcp. */
2678
2679 if ((f = pa_fopen_cloexec(PA_MACHINE_ID, "r"))) {
2680 char ln[34] = "", *r;
2681
2682 r = fgets(ln, sizeof(ln)-1, f);
2683 fclose(f);
2684
2685 pa_strip_nl(ln);
2686
2687 if (r && ln[0])
2688 return pa_utf8_filter(ln);
2689 }
2690
2691 if ((h = pa_get_host_name_malloc()))
2692 return h;
2693
2694 #ifndef OS_IS_WIN32
2695 /* If no hostname was set we use the POSIX hostid. It's usually
2696 * the IPv4 address. Might not be that stable. */
2697 return pa_sprintf_malloc("%08lx", (unsigned long) gethostid);
2698 #else
2699 return NULL;
2700 #endif
2701 }
2702
2703 char *pa_session_id(void) {
2704 const char *e;
2705
2706 if (!(e = getenv("XDG_SESSION_COOKIE")))
2707 return NULL;
2708
2709 return pa_utf8_filter(e);
2710 }
2711
2712 char *pa_uname_string(void) {
2713 #ifdef HAVE_UNAME
2714 struct utsname u;
2715
2716 pa_assert_se(uname(&u) >= 0);
2717
2718 return pa_sprintf_malloc("%s %s %s %s", u.sysname, u.machine, u.release, u.version);
2719 #endif
2720 #ifdef OS_IS_WIN32
2721 OSVERSIONINFO i;
2722
2723 pa_zero(i);
2724 i.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
2725 pa_assert_se(GetVersionEx(&i));
2726
2727 return pa_sprintf_malloc("Windows %d.%d (%d) %s", i.dwMajorVersion, i.dwMinorVersion, i.dwBuildNumber, i.szCSDVersion);
2728 #endif
2729 }
2730
2731 #ifdef HAVE_VALGRIND_MEMCHECK_H
2732 pa_bool_t pa_in_valgrind(void) {
2733 static int b = 0;
2734
2735 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2736 * here instead of really checking whether we run in valgrind or
2737 * not. */
2738
2739 if (b < 1)
2740 b = getenv("VALGRIND") ? 2 : 1;
2741
2742 return b > 1;
2743 }
2744 #endif
2745
2746 unsigned pa_gcd(unsigned a, unsigned b) {
2747
2748 while (b > 0) {
2749 unsigned t = b;
2750 b = a % b;
2751 a = t;
2752 }
2753
2754 return a;
2755 }
2756
2757 void pa_reduce(unsigned *num, unsigned *den) {
2758
2759 unsigned gcd = pa_gcd(*num, *den);
2760
2761 if (gcd <= 0)
2762 return;
2763
2764 *num /= gcd;
2765 *den /= gcd;
2766
2767 pa_assert(pa_gcd(*num, *den) == 1);
2768 }
2769
2770 unsigned pa_ncpus(void) {
2771 long ncpus;
2772
2773 #ifdef _SC_NPROCESSORS_CONF
2774 ncpus = sysconf(_SC_NPROCESSORS_CONF);
2775 #else
2776 ncpus = 1;
2777 #endif
2778
2779 return ncpus <= 0 ? 1 : (unsigned) ncpus;
2780 }
2781
2782 char *pa_replace(const char*s, const char*a, const char *b) {
2783 pa_strbuf *sb;
2784 size_t an;
2785
2786 pa_assert(s);
2787 pa_assert(a);
2788 pa_assert(b);
2789
2790 an = strlen(a);
2791 sb = pa_strbuf_new();
2792
2793 for (;;) {
2794 const char *p;
2795
2796 if (!(p = strstr(s, a)))
2797 break;
2798
2799 pa_strbuf_putsn(sb, s, p-s);
2800 pa_strbuf_puts(sb, b);
2801 s = p + an;
2802 }
2803
2804 pa_strbuf_puts(sb, s);
2805
2806 return pa_strbuf_tostring_free(sb);
2807 }
2808
2809 char *pa_escape(const char *p, const char *chars) {
2810 const char *s;
2811 const char *c;
2812 pa_strbuf *buf = pa_strbuf_new();
2813
2814 for (s = p; *s; ++s) {
2815 if (*s == '\\')
2816 pa_strbuf_putc(buf, '\\');
2817 else if (chars) {
2818 for (c = chars; *c; ++c) {
2819 if (*s == *c) {
2820 pa_strbuf_putc(buf, '\\');
2821 break;
2822 }
2823 }
2824 }
2825 pa_strbuf_putc(buf, *s);
2826 }
2827
2828 return pa_strbuf_tostring_free(buf);
2829 }
2830
2831 char *pa_unescape(char *p) {
2832 char *s, *d;
2833 pa_bool_t escaped = FALSE;
2834
2835 for (s = p, d = p; *s; s++) {
2836 if (!escaped && *s == '\\') {
2837 escaped = TRUE;
2838 continue;
2839 }
2840
2841 *(d++) = *s;
2842 escaped = FALSE;
2843 }
2844
2845 *d = 0;
2846
2847 return p;
2848 }
2849
2850 char *pa_realpath(const char *path) {
2851 char *t;
2852 pa_assert(path);
2853
2854 /* We want only abolsute paths */
2855 if (path[0] != '/') {
2856 errno = EINVAL;
2857 return NULL;
2858 }
2859
2860 #if defined(__GLIBC__) || defined(__APPLE__)
2861 {
2862 char *r;
2863
2864 if (!(r = realpath(path, NULL)))
2865 return NULL;
2866
2867 /* We copy this here in case our pa_xmalloc() is not
2868 * implemented on top of libc malloc() */
2869 t = pa_xstrdup(r);
2870 pa_xfree(r);
2871 }
2872 #elif defined(PATH_MAX)
2873 {
2874 char *path_buf;
2875 path_buf = pa_xmalloc(PATH_MAX);
2876
2877 #if defined(OS_IS_WIN32)
2878 if (!(t = _fullpath(path_buf, path, _MAX_PATH))) {
2879 pa_xfree(path_buf);
2880 return NULL;
2881 }
2882 #else
2883 if (!(t = realpath(path, path_buf))) {
2884 pa_xfree(path_buf);
2885 return NULL;
2886 }
2887 #endif
2888 }
2889 #else
2890 #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."
2891 #endif
2892
2893 return t;
2894 }
2895
2896 void pa_disable_sigpipe(void) {
2897
2898 #ifdef SIGPIPE
2899 struct sigaction sa;
2900
2901 pa_zero(sa);
2902
2903 if (sigaction(SIGPIPE, NULL, &sa) < 0) {
2904 pa_log("sigaction(): %s", pa_cstrerror(errno));
2905 return;
2906 }
2907
2908 sa.sa_handler = SIG_IGN;
2909
2910 if (sigaction(SIGPIPE, &sa, NULL) < 0) {
2911 pa_log("sigaction(): %s", pa_cstrerror(errno));
2912 return;
2913 }
2914 #endif
2915 }
2916
2917 void pa_xfreev(void**a) {
2918 void **p;
2919
2920 if (!a)
2921 return;
2922
2923 for (p = a; *p; p++)
2924 pa_xfree(*p);
2925
2926 pa_xfree(a);
2927 }
2928
2929 char **pa_split_spaces_strv(const char *s) {
2930 char **t, *e;
2931 unsigned i = 0, n = 8;
2932 const char *state = NULL;
2933
2934 t = pa_xnew(char*, n);
2935 while ((e = pa_split_spaces(s, &state))) {
2936 t[i++] = e;
2937
2938 if (i >= n) {
2939 n *= 2;
2940 t = pa_xrenew(char*, t, n);
2941 }
2942 }
2943
2944 if (i <= 0) {
2945 pa_xfree(t);
2946 return NULL;
2947 }
2948
2949 t[i] = NULL;
2950 return t;
2951 }
2952
2953 char* pa_maybe_prefix_path(const char *path, const char *prefix) {
2954 pa_assert(path);
2955
2956 if (pa_is_path_absolute(path))
2957 return pa_xstrdup(path);
2958
2959 return pa_sprintf_malloc("%s" PA_PATH_SEP "%s", prefix, path);
2960 }
2961
2962 size_t pa_pipe_buf(int fd) {
2963
2964 #ifdef _PC_PIPE_BUF
2965 long n;
2966
2967 if ((n = fpathconf(fd, _PC_PIPE_BUF)) >= 0)
2968 return (size_t) n;
2969 #endif
2970
2971 #ifdef PIPE_BUF
2972 return PIPE_BUF;
2973 #else
2974 return 4096;
2975 #endif
2976 }
2977
2978 void pa_reset_personality(void) {
2979
2980 #ifdef __linux__
2981 if (personality(PER_LINUX) < 0)
2982 pa_log_warn("Uh, personality() failed: %s", pa_cstrerror(errno));
2983 #endif
2984
2985 }
2986
2987 #if defined(__linux__) && !defined(__OPTIMIZE__)
2988
2989 pa_bool_t pa_run_from_build_tree(void) {
2990 char *rp;
2991 pa_bool_t b = FALSE;
2992
2993 /* We abuse __OPTIMIZE__ as a check whether we are a debug build
2994 * or not. */
2995
2996 if ((rp = pa_readlink("/proc/self/exe"))) {
2997 b = pa_startswith(rp, PA_BUILDDIR);
2998 pa_xfree(rp);
2999 }
3000
3001 return b;
3002 }
3003
3004 #endif
3005
3006 const char *pa_get_temp_dir(void) {
3007 const char *t;
3008
3009 if ((t = getenv("TMPDIR")) &&
3010 pa_is_path_absolute(t))
3011 return t;
3012
3013 if ((t = getenv("TMP")) &&
3014 pa_is_path_absolute(t))
3015 return t;
3016
3017 if ((t = getenv("TEMP")) &&
3018 pa_is_path_absolute(t))
3019 return t;
3020
3021 if ((t = getenv("TEMPDIR")) &&
3022 pa_is_path_absolute(t))
3023 return t;
3024
3025 return "/tmp";
3026 }
3027
3028 int pa_open_cloexec(const char *fn, int flags, mode_t mode) {
3029 int fd;
3030
3031 #ifdef O_NOCTTY
3032 flags |= O_NOCTTY;
3033 #endif
3034
3035 #ifdef O_CLOEXEC
3036 if ((fd = open(fn, flags|O_CLOEXEC, mode)) >= 0)
3037 goto finish;
3038
3039 if (errno != EINVAL)
3040 return fd;
3041 #endif
3042
3043 if ((fd = open(fn, flags, mode)) < 0)
3044 return fd;
3045
3046 finish:
3047 /* Some implementations might simply ignore O_CLOEXEC if it is not
3048 * understood, make sure FD_CLOEXEC is enabled anyway */
3049
3050 pa_make_fd_cloexec(fd);
3051 return fd;
3052 }
3053
3054 int pa_socket_cloexec(int domain, int type, int protocol) {
3055 int fd;
3056
3057 #ifdef SOCK_CLOEXEC
3058 if ((fd = socket(domain, type | SOCK_CLOEXEC, protocol)) >= 0)
3059 goto finish;
3060
3061 if (errno != EINVAL)
3062 return fd;
3063 #endif
3064
3065 if ((fd = socket(domain, type, protocol)) < 0)
3066 return fd;
3067
3068 finish:
3069 /* Some implementations might simply ignore SOCK_CLOEXEC if it is
3070 * not understood, make sure FD_CLOEXEC is enabled anyway */
3071
3072 pa_make_fd_cloexec(fd);
3073 return fd;
3074 }
3075
3076 int pa_pipe_cloexec(int pipefd[2]) {
3077 int r;
3078
3079 #ifdef HAVE_PIPE2
3080 if ((r = pipe2(pipefd, O_CLOEXEC)) >= 0)
3081 goto finish;
3082
3083 if (errno != EINVAL && errno != ENOSYS)
3084 return r;
3085
3086 #endif
3087
3088 if ((r = pipe(pipefd)) < 0)
3089 return r;
3090
3091 finish:
3092 pa_make_fd_cloexec(pipefd[0]);
3093 pa_make_fd_cloexec(pipefd[1]);
3094
3095 return 0;
3096 }
3097
3098 int pa_accept_cloexec(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
3099 int fd;
3100
3101 #ifdef HAVE_ACCEPT4
3102 if ((fd = accept4(sockfd, addr, addrlen, SOCK_CLOEXEC)) >= 0)
3103 goto finish;
3104
3105 if (errno != EINVAL && errno != ENOSYS)
3106 return fd;
3107
3108 #endif
3109
3110 if ((fd = accept(sockfd, addr, addrlen)) < 0)
3111 return fd;
3112
3113 finish:
3114 pa_make_fd_cloexec(fd);
3115 return fd;
3116 }
3117
3118 FILE* pa_fopen_cloexec(const char *path, const char *mode) {
3119 FILE *f;
3120 char *m;
3121
3122 m = pa_sprintf_malloc("%se", mode);
3123
3124 errno = 0;
3125 if ((f = fopen(path, m))) {
3126 pa_xfree(m);
3127 goto finish;
3128 }
3129
3130 pa_xfree(m);
3131
3132 if (errno != EINVAL)
3133 return NULL;
3134
3135 if (!(f = fopen(path, mode)))
3136 return NULL;
3137
3138 finish:
3139 pa_make_fd_cloexec(fileno(f));
3140 return f;
3141 }
3142
3143 void pa_nullify_stdfds(void) {
3144
3145 #ifndef OS_IS_WIN32
3146 pa_close(STDIN_FILENO);
3147 pa_close(STDOUT_FILENO);
3148 pa_close(STDERR_FILENO);
3149
3150 pa_assert_se(open("/dev/null", O_RDONLY) == STDIN_FILENO);
3151 pa_assert_se(open("/dev/null", O_WRONLY) == STDOUT_FILENO);
3152 pa_assert_se(open("/dev/null", O_WRONLY) == STDERR_FILENO);
3153 #else
3154 FreeConsole();
3155 #endif
3156
3157 }
3158
3159 char *pa_read_line_from_file(const char *fn) {
3160 FILE *f;
3161 char ln[256] = "", *r;
3162
3163 if (!(f = pa_fopen_cloexec(fn, "r")))
3164 return NULL;
3165
3166 r = fgets(ln, sizeof(ln)-1, f);
3167 fclose(f);
3168
3169 if (!r) {
3170 errno = EIO;
3171 return NULL;
3172 }
3173
3174 pa_strip_nl(ln);
3175 return pa_xstrdup(ln);
3176 }
3177
3178 pa_bool_t pa_running_in_vm(void) {
3179
3180 #if defined(__i386__) || defined(__x86_64__)
3181
3182 /* Both CPUID and DMI are x86 specific interfaces... */
3183
3184 uint32_t eax = 0x40000000;
3185 union {
3186 uint32_t sig32[3];
3187 char text[13];
3188 } sig;
3189
3190 #ifdef __linux__
3191 const char *const dmi_vendors[] = {
3192 "/sys/class/dmi/id/sys_vendor",
3193 "/sys/class/dmi/id/board_vendor",
3194 "/sys/class/dmi/id/bios_vendor"
3195 };
3196
3197 unsigned i;
3198
3199 for (i = 0; i < PA_ELEMENTSOF(dmi_vendors); i++) {
3200 char *s;
3201
3202 if ((s = pa_read_line_from_file(dmi_vendors[i]))) {
3203
3204 if (pa_startswith(s, "QEMU") ||
3205 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3206 pa_startswith(s, "VMware") ||
3207 pa_startswith(s, "VMW") ||
3208 pa_startswith(s, "Microsoft Corporation") ||
3209 pa_startswith(s, "innotek GmbH") ||
3210 pa_startswith(s, "Xen")) {
3211
3212 pa_xfree(s);
3213 return TRUE;
3214 }
3215
3216 pa_xfree(s);
3217 }
3218 }
3219
3220 #endif
3221
3222 /* http://lwn.net/Articles/301888/ */
3223 pa_zero(sig);
3224
3225 __asm__ __volatile__ (
3226 /* ebx/rbx is being used for PIC! */
3227 " push %%"PA_REG_b" \n\t"
3228 " cpuid \n\t"
3229 " mov %%ebx, %1 \n\t"
3230 " pop %%"PA_REG_b" \n\t"
3231
3232 : "=a" (eax), "=r" (sig.sig32[0]), "=c" (sig.sig32[1]), "=d" (sig.sig32[2])
3233 : "0" (eax)
3234 );
3235
3236 if (pa_streq(sig.text, "XenVMMXenVMM") ||
3237 pa_streq(sig.text, "KVMKVMKVM") ||
3238 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3239 pa_streq(sig.text, "VMwareVMware") ||
3240 /* http://msdn.microsoft.com/en-us/library/bb969719.aspx */
3241 pa_streq(sig.text, "Microsoft Hv"))
3242 return TRUE;
3243
3244 #endif
3245
3246 return FALSE;
3247 }