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