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