]> code.delx.au - pulseaudio/blob - src/pulsecore/core-util.c
Merge branch 'master' of ssh://rootserver/home/lennart/git/public/pulseaudio
[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
121 #include "core-util.h"
122
123 /* Not all platforms have this */
124 #ifndef MSG_NOSIGNAL
125 #define MSG_NOSIGNAL 0
126 #endif
127
128 static pa_strlist *recorded_env = NULL;
129
130 #ifdef OS_IS_WIN32
131
132 #define PULSE_ROOTENV "PULSE_ROOT"
133
134 int pa_set_root(HANDLE handle) {
135 char library_path[MAX_PATH + sizeof(PULSE_ROOTENV) + 1], *sep;
136
137 strcpy(library_path, PULSE_ROOTENV "=");
138
139 /* FIXME: Needs to set errno */
140
141 if (!GetModuleFileName(handle, library_path + sizeof(PULSE_ROOTENV), MAX_PATH))
142 return 0;
143
144 sep = strrchr(library_path, PA_PATH_SEP_CHAR);
145 if (sep)
146 *sep = '\0';
147
148 if (_putenv(library_path) < 0)
149 return 0;
150
151 return 1;
152 }
153
154 #endif
155
156 /** Make a file descriptor nonblock. Doesn't do any error checking */
157 void pa_make_fd_nonblock(int fd) {
158
159 #ifdef O_NONBLOCK
160 int v;
161 pa_assert(fd >= 0);
162
163 pa_assert_se((v = fcntl(fd, F_GETFL)) >= 0);
164
165 if (!(v & O_NONBLOCK))
166 pa_assert_se(fcntl(fd, F_SETFL, v|O_NONBLOCK) >= 0);
167
168 #elif defined(OS_IS_WIN32)
169 u_long arg = 1;
170 if (ioctlsocket(fd, FIONBIO, &arg) < 0) {
171 pa_assert_se(WSAGetLastError() == WSAENOTSOCK);
172 pa_log_warn("Only sockets can be made non-blocking!");
173 }
174 #else
175 pa_log_warn("Non-blocking I/O not supported.!");
176 #endif
177
178 }
179
180 /* Set the FD_CLOEXEC flag for a fd */
181 void pa_make_fd_cloexec(int fd) {
182
183 #ifdef FD_CLOEXEC
184 int v;
185 pa_assert(fd >= 0);
186
187 pa_assert_se((v = fcntl(fd, F_GETFD, 0)) >= 0);
188
189 if (!(v & FD_CLOEXEC))
190 pa_assert_se(fcntl(fd, F_SETFD, v|FD_CLOEXEC) >= 0);
191 #endif
192
193 }
194
195 /** Creates a directory securely */
196 int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid) {
197 struct stat st;
198 int r, saved_errno;
199
200 pa_assert(dir);
201
202 #ifdef OS_IS_WIN32
203 r = mkdir(dir);
204 #else
205 {
206 mode_t u;
207 u = umask((~m) & 0777);
208 r = mkdir(dir, m);
209 umask(u);
210 }
211 #endif
212
213 if (r < 0 && errno != EEXIST)
214 return -1;
215
216 #ifdef HAVE_CHOWN
217 if (uid == (uid_t)-1)
218 uid = getuid();
219 if (gid == (gid_t)-1)
220 gid = getgid();
221 (void) chown(dir, uid, gid);
222 #endif
223
224 #ifdef HAVE_CHMOD
225 chmod(dir, m);
226 #endif
227
228 #ifdef HAVE_LSTAT
229 if (lstat(dir, &st) < 0)
230 #else
231 if (stat(dir, &st) < 0)
232 #endif
233 goto fail;
234
235 #ifndef OS_IS_WIN32
236 if (!S_ISDIR(st.st_mode) ||
237 (st.st_uid != uid) ||
238 (st.st_gid != gid) ||
239 ((st.st_mode & 0777) != m)) {
240 errno = EACCES;
241 goto fail;
242 }
243 #else
244 pa_log_warn("Secure directory creation not supported on Win32.");
245 #endif
246
247 return 0;
248
249 fail:
250 saved_errno = errno;
251 rmdir(dir);
252 errno = saved_errno;
253
254 return -1;
255 }
256
257 /* Return a newly allocated sting containing the parent directory of the specified file */
258 char *pa_parent_dir(const char *fn) {
259 char *slash, *dir = pa_xstrdup(fn);
260
261 if ((slash = (char*) pa_path_get_filename(dir)) == dir) {
262 pa_xfree(dir);
263 errno = ENOENT;
264 return NULL;
265 }
266
267 *(slash-1) = 0;
268 return dir;
269 }
270
271 /* Creates a the parent directory of the specified path securely */
272 int pa_make_secure_parent_dir(const char *fn, mode_t m, uid_t uid, gid_t gid) {
273 int ret = -1;
274 char *dir;
275
276 if (!(dir = pa_parent_dir(fn)))
277 goto finish;
278
279 if (pa_make_secure_dir(dir, m, uid, gid) < 0)
280 goto finish;
281
282 ret = 0;
283
284 finish:
285 pa_xfree(dir);
286 return ret;
287 }
288
289 /** Platform independent read function. Necessary since not all
290 * systems treat all file descriptors equal. If type is
291 * non-NULL it is used to cache the type of the fd. This is
292 * useful for making sure that only a single syscall is executed per
293 * function call. The variable pointed to should be initialized to 0
294 * by the caller. */
295 ssize_t pa_read(int fd, void *buf, size_t count, int *type) {
296
297 #ifdef OS_IS_WIN32
298
299 if (!type || *type == 0) {
300 ssize_t r;
301
302 if ((r = recv(fd, buf, count, 0)) >= 0)
303 return r;
304
305 if (WSAGetLastError() != WSAENOTSOCK) {
306 errno = WSAGetLastError();
307 return r;
308 }
309
310 if (type)
311 *type = 1;
312 }
313
314 #endif
315
316 for (;;) {
317 ssize_t r;
318
319 if ((r = read(fd, buf, count)) < 0)
320 if (errno == EINTR)
321 continue;
322
323 return r;
324 }
325 }
326
327 /** Similar to pa_read(), but handles writes */
328 ssize_t pa_write(int fd, const void *buf, size_t count, int *type) {
329
330 if (!type || *type == 0) {
331 ssize_t r;
332
333 for (;;) {
334 if ((r = send(fd, buf, count, MSG_NOSIGNAL)) < 0) {
335
336 if (errno == EINTR)
337 continue;
338
339 break;
340 }
341
342 return r;
343 }
344
345 #ifdef OS_IS_WIN32
346 if (WSAGetLastError() != WSAENOTSOCK) {
347 errno = WSAGetLastError();
348 return r;
349 }
350 #else
351 if (errno != ENOTSOCK)
352 return r;
353 #endif
354
355 if (type)
356 *type = 1;
357 }
358
359 for (;;) {
360 ssize_t r;
361
362 if ((r = write(fd, buf, count)) < 0)
363 if (errno == EINTR)
364 continue;
365
366 return r;
367 }
368 }
369
370 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
371 * unless EOF is reached or an error occurred */
372 ssize_t pa_loop_read(int fd, void*data, size_t size, int *type) {
373 ssize_t ret = 0;
374 int _type;
375
376 pa_assert(fd >= 0);
377 pa_assert(data);
378 pa_assert(size);
379
380 if (!type) {
381 _type = 0;
382 type = &_type;
383 }
384
385 while (size > 0) {
386 ssize_t r;
387
388 if ((r = pa_read(fd, data, size, type)) < 0)
389 return r;
390
391 if (r == 0)
392 break;
393
394 ret += r;
395 data = (uint8_t*) data + r;
396 size -= (size_t) r;
397 }
398
399 return ret;
400 }
401
402 /** Similar to pa_loop_read(), but wraps write() */
403 ssize_t pa_loop_write(int fd, const void*data, size_t size, int *type) {
404 ssize_t ret = 0;
405 int _type;
406
407 pa_assert(fd >= 0);
408 pa_assert(data);
409 pa_assert(size);
410
411 if (!type) {
412 _type = 0;
413 type = &_type;
414 }
415
416 while (size > 0) {
417 ssize_t r;
418
419 if ((r = pa_write(fd, data, size, type)) < 0)
420 return r;
421
422 if (r == 0)
423 break;
424
425 ret += r;
426 data = (const uint8_t*) data + r;
427 size -= (size_t) r;
428 }
429
430 return ret;
431 }
432
433 /** Platform independent read function. Necessary since not all
434 * systems treat all file descriptors equal. */
435 int pa_close(int fd) {
436
437 #ifdef OS_IS_WIN32
438 int ret;
439
440 if ((ret = closesocket(fd)) == 0)
441 return 0;
442
443 if (WSAGetLastError() != WSAENOTSOCK) {
444 errno = WSAGetLastError();
445 return ret;
446 }
447 #endif
448
449 for (;;) {
450 int r;
451
452 if ((r = close(fd)) < 0)
453 if (errno == EINTR)
454 continue;
455
456 return r;
457 }
458 }
459
460 /* Print a warning messages in case that the given signal is not
461 * blocked or trapped */
462 void pa_check_signal_is_blocked(int sig) {
463 #ifdef HAVE_SIGACTION
464 struct sigaction sa;
465 sigset_t set;
466
467 /* If POSIX threads are supported use thread-aware
468 * pthread_sigmask() function, to check if the signal is
469 * blocked. Otherwise fall back to sigprocmask() */
470
471 #ifdef HAVE_PTHREAD
472 if (pthread_sigmask(SIG_SETMASK, NULL, &set) < 0) {
473 #endif
474 if (sigprocmask(SIG_SETMASK, NULL, &set) < 0) {
475 pa_log("sigprocmask(): %s", pa_cstrerror(errno));
476 return;
477 }
478 #ifdef HAVE_PTHREAD
479 }
480 #endif
481
482 if (sigismember(&set, sig))
483 return;
484
485 /* Check whether the signal is trapped */
486
487 if (sigaction(sig, NULL, &sa) < 0) {
488 pa_log("sigaction(): %s", pa_cstrerror(errno));
489 return;
490 }
491
492 if (sa.sa_handler != SIG_DFL)
493 return;
494
495 pa_log_warn("%s is not trapped. This might cause malfunction!", pa_sig2str(sig));
496 #else /* HAVE_SIGACTION */
497 pa_log_warn("%s might not be trapped. This might cause malfunction!", pa_sig2str(sig));
498 #endif
499 }
500
501 /* The following function is based on an example from the GNU libc
502 * documentation. This function is similar to GNU's asprintf(). */
503 char *pa_sprintf_malloc(const char *format, ...) {
504 size_t size = 100;
505 char *c = NULL;
506
507 pa_assert(format);
508
509 for(;;) {
510 int r;
511 va_list ap;
512
513 c = pa_xrealloc(c, size);
514
515 va_start(ap, format);
516 r = vsnprintf(c, size, format, ap);
517 va_end(ap);
518
519 c[size-1] = 0;
520
521 if (r > -1 && (size_t) r < size)
522 return c;
523
524 if (r > -1) /* glibc 2.1 */
525 size = (size_t) r+1;
526 else /* glibc 2.0 */
527 size *= 2;
528 }
529 }
530
531 /* Same as the previous function, but use a va_list instead of an
532 * ellipsis */
533 char *pa_vsprintf_malloc(const char *format, va_list ap) {
534 size_t size = 100;
535 char *c = NULL;
536
537 pa_assert(format);
538
539 for(;;) {
540 int r;
541 va_list aq;
542
543 c = pa_xrealloc(c, size);
544
545 va_copy(aq, ap);
546 r = vsnprintf(c, size, format, aq);
547 va_end(aq);
548
549 c[size-1] = 0;
550
551 if (r > -1 && (size_t) r < size)
552 return c;
553
554 if (r > -1) /* glibc 2.1 */
555 size = (size_t) r+1;
556 else /* glibc 2.0 */
557 size *= 2;
558 }
559 }
560
561 /* Similar to OpenBSD's strlcpy() function */
562 char *pa_strlcpy(char *b, const char *s, size_t l) {
563 size_t k;
564
565 pa_assert(b);
566 pa_assert(s);
567 pa_assert(l > 0);
568
569 k = strlen(s);
570
571 if (k > l-1)
572 k = l-1;
573
574 memcpy(b, s, k);
575 b[k] = 0;
576
577 return b;
578 }
579
580 static int set_scheduler(int rtprio) {
581 struct sched_param sp;
582 int r;
583 #ifdef HAVE_DBUS
584 DBusError error;
585 DBusConnection *bus;
586
587 dbus_error_init(&error);
588 #endif
589
590 pa_zero(sp);
591 sp.sched_priority = rtprio;
592
593 #ifdef SCHED_RESET_ON_FORK
594 if ((r = pthread_setschedparam(pthread_self(), SCHED_RR|SCHED_RESET_ON_FORK, &sp)) == 0) {
595 pa_log_debug("SCHED_RR|SCHED_RESET_ON_FORK worked.");
596 return 0;
597 }
598 #endif
599
600 if ((r = pthread_setschedparam(pthread_self(), SCHED_RR, &sp)) == 0) {
601 pa_log_debug("SCHED_RR worked.");
602 return 0;
603 }
604
605 #ifdef HAVE_DBUS
606 /* Try to talk to RealtimeKit */
607
608 if (!(bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
609 pa_log("Failed to connect to system bus: %s\n", error.message);
610 dbus_error_free(&error);
611 errno = -EIO;
612 return -1;
613 }
614
615 /* We need to disable exit on disconnect because otherwise
616 * dbus_shutdown will kill us. See
617 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
618 dbus_connection_set_exit_on_disconnect(bus, FALSE);
619
620 r = rtkit_make_realtime(bus, 0, rtprio);
621 dbus_connection_unref(bus);
622
623 if (r >= 0) {
624 pa_log_debug("RealtimeKit worked.");
625 return 0;
626 }
627
628 errno = -r;
629 #else
630 errno = r;
631 #endif
632
633 return -1;
634 }
635
636 /* Make the current thread a realtime thread, and acquire the highest
637 * rtprio we can get that is less or equal the specified parameter. If
638 * the thread is already realtime, don't do anything. */
639 int pa_make_realtime(int rtprio) {
640
641 #ifdef _POSIX_PRIORITY_SCHEDULING
642 int p;
643
644 if (set_scheduler(rtprio) >= 0) {
645 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i.", rtprio);
646 return 0;
647 }
648
649 for (p = rtprio-1; p >= 1; p--)
650 if (set_scheduler(p)) {
651 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i.", p, rtprio);
652 return 0;
653 }
654
655 pa_log_info("Failed to acquire real-time scheduling: %s", pa_cstrerror(errno));
656 return -1;
657 #else
658
659 errno = ENOTSUP;
660 return -1;
661 #endif
662 }
663
664 static int set_nice(int nice_level) {
665 #ifdef HAVE_DBUS
666 DBusError error;
667 DBusConnection *bus;
668 int r;
669
670 dbus_error_init(&error);
671 #endif
672
673 if (setpriority(PRIO_PROCESS, 0, nice_level) >= 0) {
674 pa_log_debug("setpriority() worked.");
675 return 0;
676 }
677
678 #ifdef HAVE_DBUS
679 /* Try to talk to RealtimeKit */
680
681 if (!(bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
682 pa_log("Failed to connect to system bus: %s\n", error.message);
683 dbus_error_free(&error);
684 errno = -EIO;
685 return -1;
686 }
687
688 /* We need to disable exit on disconnect because otherwise
689 * dbus_shutdown will kill us. See
690 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
691 dbus_connection_set_exit_on_disconnect(bus, FALSE);
692
693 r = rtkit_make_high_priority(bus, 0, nice_level);
694 dbus_connection_unref(bus);
695
696 if (r >= 0) {
697 pa_log_debug("RealtimeKit worked.");
698 return 0;
699 }
700
701 errno = -r;
702 #endif
703
704 return -1;
705 }
706
707 /* Raise the priority of the current process as much as possible that
708 * is <= the specified nice level..*/
709 int pa_raise_priority(int nice_level) {
710
711 #ifdef HAVE_SYS_RESOURCE_H
712 int n;
713
714 if (set_nice(nice_level) >= 0) {
715 pa_log_info("Successfully gained nice level %i.", nice_level);
716 return 0;
717 }
718
719 for (n = nice_level+1; n < 0; n++)
720 if (set_nice(n) > 0) {
721 pa_log_info("Successfully acquired nice level %i, which is lower than the requested %i.", n, nice_level);
722 return 0;
723 }
724
725 pa_log_info("Failed to acquire high-priority scheduling: %s", pa_cstrerror(errno));
726 return -1;
727 #endif
728
729 #ifdef OS_IS_WIN32
730 if (nice_level < 0) {
731 if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS)) {
732 pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError());
733 errno = EPERM;
734 return -1;
735 }
736
737 pa_log_info("Successfully gained high priority class.");
738 }
739 #endif
740
741 return 0;
742 }
743
744 /* Reset the priority to normal, inverting the changes made by
745 * pa_raise_priority() and pa_make_realtime()*/
746 void pa_reset_priority(void) {
747 #ifdef HAVE_SYS_RESOURCE_H
748 struct sched_param sp;
749
750 setpriority(PRIO_PROCESS, 0, 0);
751
752 pa_zero(sp);
753 pthread_setschedparam(pthread_self(), SCHED_OTHER, &sp);
754 #endif
755
756 #ifdef OS_IS_WIN32
757 SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
758 #endif
759 }
760
761 int pa_match(const char *expr, const char *v) {
762 int k;
763 regex_t re;
764 int r;
765
766 if (regcomp(&re, expr, REG_NOSUB|REG_EXTENDED) != 0) {
767 errno = EINVAL;
768 return -1;
769 }
770
771 if ((k = regexec(&re, v, 0, NULL, 0)) == 0)
772 r = 1;
773 else if (k == REG_NOMATCH)
774 r = 0;
775 else
776 r = -1;
777
778 regfree(&re);
779
780 if (r < 0)
781 errno = EINVAL;
782
783 return r;
784 }
785
786 /* Try to parse a boolean string value.*/
787 int pa_parse_boolean(const char *v) {
788 const char *expr;
789 int r;
790 pa_assert(v);
791
792 /* First we check language independant */
793 if (!strcmp(v, "1") || v[0] == 'y' || v[0] == 'Y' || v[0] == 't' || v[0] == 'T' || !strcasecmp(v, "on"))
794 return 1;
795 else if (!strcmp(v, "0") || v[0] == 'n' || v[0] == 'N' || v[0] == 'f' || v[0] == 'F' || !strcasecmp(v, "off"))
796 return 0;
797
798 /* And then we check language dependant */
799 if ((expr = nl_langinfo(YESEXPR)))
800 if (expr[0])
801 if ((r = pa_match(expr, v)) > 0)
802 return 1;
803
804 if ((expr = nl_langinfo(NOEXPR)))
805 if (expr[0])
806 if ((r = pa_match(expr, v)) > 0)
807 return 0;
808
809 errno = EINVAL;
810 return -1;
811 }
812
813 /* Split the specified string wherever one of the strings in delimiter
814 * occurs. Each time it is called returns a newly allocated string
815 * with pa_xmalloc(). The variable state points to, should be
816 * initiallized to NULL before the first call. */
817 char *pa_split(const char *c, const char *delimiter, const char**state) {
818 const char *current = *state ? *state : c;
819 size_t l;
820
821 if (!*current)
822 return NULL;
823
824 l = strcspn(current, delimiter);
825 *state = current+l;
826
827 if (**state)
828 (*state)++;
829
830 return pa_xstrndup(current, l);
831 }
832
833 /* What is interpreted as whitespace? */
834 #define WHITESPACE " \t\n"
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, "\r\n")] = 0;
1193 return s;
1194 }
1195
1196 /* Create a temporary lock file and lock it. */
1197 int pa_lock_lockfile(const char *fn) {
1198 int fd = -1;
1199 pa_assert(fn);
1200
1201 for (;;) {
1202 struct stat st;
1203
1204 if ((fd = open(fn, O_CREAT|O_RDWR
1205 #ifdef O_NOCTTY
1206 |O_NOCTTY
1207 #endif
1208 #ifdef O_NOFOLLOW
1209 |O_NOFOLLOW
1210 #endif
1211 , S_IRUSR|S_IWUSR)) < 0) {
1212 pa_log_warn("Failed to create lock file '%s': %s", fn, pa_cstrerror(errno));
1213 goto fail;
1214 }
1215
1216 if (pa_lock_fd(fd, 1) < 0) {
1217 pa_log_warn("Failed to lock file '%s'.", fn);
1218 goto fail;
1219 }
1220
1221 if (fstat(fd, &st) < 0) {
1222 pa_log_warn("Failed to fstat() file '%s': %s", fn, pa_cstrerror(errno));
1223 goto fail;
1224 }
1225
1226 /* Check whether the file has been removed meanwhile. When yes,
1227 * restart this loop, otherwise, we're done */
1228 if (st.st_nlink >= 1)
1229 break;
1230
1231 if (pa_lock_fd(fd, 0) < 0) {
1232 pa_log_warn("Failed to unlock file '%s'.", fn);
1233 goto fail;
1234 }
1235
1236 if (pa_close(fd) < 0) {
1237 pa_log_warn("Failed to close file '%s': %s", fn, pa_cstrerror(errno));
1238 fd = -1;
1239 goto fail;
1240 }
1241
1242 fd = -1;
1243 }
1244
1245 return fd;
1246
1247 fail:
1248
1249 if (fd >= 0) {
1250 int saved_errno = errno;
1251 pa_close(fd);
1252 errno = saved_errno;
1253 }
1254
1255 return -1;
1256 }
1257
1258 /* Unlock a temporary lcok file */
1259 int pa_unlock_lockfile(const char *fn, int fd) {
1260 int r = 0;
1261 pa_assert(fd >= 0);
1262
1263 if (fn) {
1264 if (unlink(fn) < 0) {
1265 pa_log_warn("Unable to remove lock file '%s': %s", fn, pa_cstrerror(errno));
1266 r = -1;
1267 }
1268 }
1269
1270 if (pa_lock_fd(fd, 0) < 0) {
1271 pa_log_warn("Failed to unlock file '%s'.", fn);
1272 r = -1;
1273 }
1274
1275 if (pa_close(fd) < 0) {
1276 pa_log_warn("Failed to close '%s': %s", fn, pa_cstrerror(errno));
1277 r = -1;
1278 }
1279
1280 return r;
1281 }
1282
1283 static char *get_pulse_home(void) {
1284 char *h;
1285 struct stat st;
1286 char *ret = NULL;
1287
1288 if (!(h = pa_get_home_dir_malloc())) {
1289 pa_log_error("Failed to get home directory.");
1290 return NULL;
1291 }
1292
1293 if (stat(h, &st) < 0) {
1294 pa_log_error("Failed to stat home directory %s: %s", h, pa_cstrerror(errno));
1295 goto finish;
1296 }
1297
1298 if (st.st_uid != getuid()) {
1299 pa_log_error("Home directory %s not ours.", h);
1300 errno = EACCES;
1301 goto finish;
1302 }
1303
1304 ret = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse", h);
1305
1306 finish:
1307 pa_xfree(h);
1308
1309 return ret;
1310 }
1311
1312 char *pa_get_state_dir(void) {
1313 char *d;
1314
1315 /* The state directory shall contain dynamic data that should be
1316 * kept across reboots, and is private to this user */
1317
1318 if (!(d = pa_xstrdup(getenv("PULSE_STATE_PATH"))))
1319 if (!(d = get_pulse_home()))
1320 return NULL;
1321
1322 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1323 * dir then this will break. */
1324
1325 if (pa_make_secure_dir(d, 0700U, (uid_t) -1, (gid_t) -1) < 0) {
1326 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1327 pa_xfree(d);
1328 return NULL;
1329 }
1330
1331 return d;
1332 }
1333
1334 char *pa_get_home_dir_malloc(void) {
1335 char *homedir;
1336 size_t allocated = 128;
1337
1338 for (;;) {
1339 homedir = pa_xmalloc(allocated);
1340
1341 if (!pa_get_home_dir(homedir, allocated)) {
1342 pa_xfree(homedir);
1343 return NULL;
1344 }
1345
1346 if (strlen(homedir) < allocated - 1)
1347 break;
1348
1349 pa_xfree(homedir);
1350 allocated *= 2;
1351 }
1352
1353 return homedir;
1354 }
1355
1356 char *pa_get_binary_name_malloc(void) {
1357 char *t;
1358 size_t allocated = 128;
1359
1360 for (;;) {
1361 t = pa_xmalloc(allocated);
1362
1363 if (!pa_get_binary_name(t, allocated)) {
1364 pa_xfree(t);
1365 return NULL;
1366 }
1367
1368 if (strlen(t) < allocated - 1)
1369 break;
1370
1371 pa_xfree(t);
1372 allocated *= 2;
1373 }
1374
1375 return t;
1376 }
1377
1378 static char* make_random_dir(mode_t m) {
1379 static const char table[] =
1380 "abcdefghijklmnopqrstuvwxyz"
1381 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1382 "0123456789";
1383
1384 const char *tmpdir;
1385 char *fn;
1386 size_t pathlen;
1387
1388 if (!(tmpdir = getenv("TMPDIR")))
1389 if (!(tmpdir = getenv("TMP")))
1390 if (!(tmpdir = getenv("TEMP")))
1391 tmpdir = getenv("TEMPDIR");
1392
1393 if (!tmpdir || !pa_is_path_absolute(tmpdir))
1394 tmpdir = "/tmp";
1395
1396 fn = pa_sprintf_malloc("%s/pulse-XXXXXXXXXXXX", tmpdir);
1397 pathlen = strlen(fn);
1398
1399 for (;;) {
1400 size_t i;
1401 int r;
1402 mode_t u;
1403 int saved_errno;
1404
1405 for (i = pathlen - 12; i < pathlen; i++)
1406 fn[i] = table[rand() % (sizeof(table)-1)];
1407
1408 u = umask((~m) & 0777);
1409 r = mkdir(fn, m);
1410
1411 saved_errno = errno;
1412 umask(u);
1413 errno = saved_errno;
1414
1415 if (r >= 0)
1416 return fn;
1417
1418 if (errno != EEXIST) {
1419 pa_log_error("Failed to create random directory %s: %s", fn, pa_cstrerror(errno));
1420 pa_xfree(fn);
1421 return NULL;
1422 }
1423 }
1424 }
1425
1426 static int make_random_dir_and_link(mode_t m, const char *k) {
1427 char *p;
1428
1429 if (!(p = make_random_dir(m)))
1430 return -1;
1431
1432 if (symlink(p, k) < 0) {
1433 int saved_errno = errno;
1434
1435 if (errno != EEXIST)
1436 pa_log_error("Failed to symlink %s to %s: %s", k, p, pa_cstrerror(errno));
1437
1438 rmdir(p);
1439 pa_xfree(p);
1440
1441 errno = saved_errno;
1442 return -1;
1443 }
1444
1445 pa_xfree(p);
1446 return 0;
1447 }
1448
1449 char *pa_get_runtime_dir(void) {
1450 char *d, *k = NULL, *p = NULL, *t = NULL, *mid;
1451 struct stat st;
1452 mode_t m;
1453
1454 /* The runtime directory shall contain dynamic data that needs NOT
1455 * to be kept accross reboots and is usuallly private to the user,
1456 * except in system mode, where it might be accessible by other
1457 * users, too. Since we need POSIX locking and UNIX sockets in
1458 * this directory, we link it to a random subdir in /tmp, if it
1459 * was not explicitly configured. */
1460
1461 m = pa_in_system_mode() ? 0755U : 0700U;
1462
1463 if ((d = getenv("PULSE_RUNTIME_PATH"))) {
1464
1465 if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0) {
1466 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1467 goto fail;
1468 }
1469
1470 return pa_xstrdup(d);
1471 }
1472
1473 if (!(d = get_pulse_home()))
1474 goto fail;
1475
1476 if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0) {
1477 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1478 pa_xfree(d);
1479 goto fail;
1480 }
1481
1482 if (!(mid = pa_machine_id())) {
1483 pa_xfree(d);
1484 goto fail;
1485 }
1486
1487 k = pa_sprintf_malloc("%s" PA_PATH_SEP "%s-runtime", d, mid);
1488 pa_xfree(d);
1489 pa_xfree(mid);
1490
1491 for (;;) {
1492 /* OK, first let's check if the "runtime" symlink is already
1493 * existant */
1494
1495 if (!(p = pa_readlink(k))) {
1496
1497 if (errno != ENOENT) {
1498 pa_log_error("Failed to stat runtime directory %s: %s", k, pa_cstrerror(errno));
1499 goto fail;
1500 }
1501
1502 /* Hmm, so the runtime directory didn't exist yet, so let's
1503 * create one in /tmp and symlink that to it */
1504
1505 if (make_random_dir_and_link(0700, k) < 0) {
1506
1507 /* Mhmm, maybe another process was quicker than us,
1508 * let's check if that was valid */
1509 if (errno == EEXIST)
1510 continue;
1511
1512 goto fail;
1513 }
1514
1515 return k;
1516 }
1517
1518 /* Make sure that this actually makes sense */
1519 if (!pa_is_path_absolute(p)) {
1520 pa_log_error("Path %s in link %s is not absolute.", p, k);
1521 errno = ENOENT;
1522 goto fail;
1523 }
1524
1525 /* Hmm, so this symlink is still around, make sure nobody fools
1526 * us */
1527
1528 if (lstat(p, &st) < 0) {
1529
1530 if (errno != ENOENT) {
1531 pa_log_error("Failed to stat runtime directory %s: %s", p, pa_cstrerror(errno));
1532 goto fail;
1533 }
1534
1535 } else {
1536
1537 if (S_ISDIR(st.st_mode) &&
1538 (st.st_uid == getuid()) &&
1539 ((st.st_mode & 0777) == 0700)) {
1540
1541 pa_xfree(p);
1542 return k;
1543 }
1544
1545 pa_log_info("Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory.");
1546 }
1547
1548 pa_xfree(p);
1549 p = NULL;
1550
1551 /* Hmm, so the link points to some nonexisting or invalid
1552 * dir. Let's replace it by a new link. We first create a
1553 * temporary link and then rename that to allow concurrent
1554 * execution of this function. */
1555
1556 t = pa_sprintf_malloc("%s.tmp", k);
1557
1558 if (make_random_dir_and_link(0700, t) < 0) {
1559
1560 if (errno != EEXIST) {
1561 pa_log_error("Failed to symlink %s: %s", t, pa_cstrerror(errno));
1562 goto fail;
1563 }
1564
1565 pa_xfree(t);
1566 t = NULL;
1567
1568 /* Hmm, someone lese was quicker then us. Let's give
1569 * him some time to finish, and retry. */
1570 pa_msleep(10);
1571 continue;
1572 }
1573
1574 /* OK, we succeeded in creating the temporary symlink, so
1575 * let's rename it */
1576 if (rename(t, k) < 0) {
1577 pa_log_error("Failed to rename %s to %s: %s", t, k, pa_cstrerror(errno));
1578 goto fail;
1579 }
1580
1581 pa_xfree(t);
1582 return k;
1583 }
1584
1585 fail:
1586 pa_xfree(p);
1587 pa_xfree(k);
1588 pa_xfree(t);
1589
1590 return NULL;
1591 }
1592
1593 /* Try to open a configuration file. If "env" is specified, open the
1594 * value of the specified environment variable. Otherwise look for a
1595 * file "local" in the home directory or a file "global" in global
1596 * file system. If "result" is non-NULL, a pointer to a newly
1597 * allocated buffer containing the used configuration file is
1598 * stored there.*/
1599 FILE *pa_open_config_file(const char *global, const char *local, const char *env, char **result) {
1600 const char *fn;
1601 #ifdef OS_IS_WIN32
1602 char buf[PATH_MAX];
1603
1604 if (!getenv(PULSE_ROOTENV))
1605 pa_set_root(NULL);
1606 #endif
1607
1608 if (env && (fn = getenv(env))) {
1609 FILE *f;
1610
1611 #ifdef OS_IS_WIN32
1612 if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
1613 /* FIXME: Needs to set errno! */
1614 return NULL;
1615 fn = buf;
1616 #endif
1617
1618 if ((f = fopen(fn, "r"))) {
1619 if (result)
1620 *result = pa_xstrdup(fn);
1621
1622 return f;
1623 }
1624
1625 pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
1626 return NULL;
1627 }
1628
1629 if (local) {
1630 const char *e;
1631 char *lfn;
1632 char *h;
1633 FILE *f;
1634
1635 if ((e = getenv("PULSE_CONFIG_PATH")))
1636 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
1637 else if ((h = pa_get_home_dir_malloc())) {
1638 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
1639 pa_xfree(h);
1640 } else
1641 return NULL;
1642
1643 #ifdef OS_IS_WIN32
1644 if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) {
1645 /* FIXME: Needs to set errno! */
1646 pa_xfree(lfn);
1647 return NULL;
1648 }
1649 fn = buf;
1650 #endif
1651
1652 if ((f = fopen(fn, "r"))) {
1653 if (result)
1654 *result = pa_xstrdup(fn);
1655
1656 pa_xfree(lfn);
1657 return f;
1658 }
1659
1660 if (errno != ENOENT) {
1661 pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
1662 pa_xfree(lfn);
1663 return NULL;
1664 }
1665
1666 pa_xfree(lfn);
1667 }
1668
1669 if (global) {
1670 FILE *f;
1671
1672 #ifdef OS_IS_WIN32
1673 if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
1674 /* FIXME: Needs to set errno! */
1675 return NULL;
1676 global = buf;
1677 #endif
1678
1679 if ((f = fopen(global, "r"))) {
1680
1681 if (result)
1682 *result = pa_xstrdup(global);
1683
1684 return f;
1685 }
1686 }
1687
1688 errno = ENOENT;
1689 return NULL;
1690 }
1691
1692 char *pa_find_config_file(const char *global, const char *local, const char *env) {
1693 const char *fn;
1694 #ifdef OS_IS_WIN32
1695 char buf[PATH_MAX];
1696
1697 if (!getenv(PULSE_ROOTENV))
1698 pa_set_root(NULL);
1699 #endif
1700
1701 if (env && (fn = getenv(env))) {
1702
1703 #ifdef OS_IS_WIN32
1704 if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
1705 /* FIXME: Needs to set errno! */
1706 return NULL;
1707 fn = buf;
1708 #endif
1709
1710 if (access(fn, R_OK) == 0)
1711 return pa_xstrdup(fn);
1712
1713 pa_log_warn("Failed to access configuration file '%s': %s", fn, pa_cstrerror(errno));
1714 return NULL;
1715 }
1716
1717 if (local) {
1718 const char *e;
1719 char *lfn;
1720 char *h;
1721
1722 if ((e = getenv("PULSE_CONFIG_PATH")))
1723 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
1724 else if ((h = pa_get_home_dir_malloc())) {
1725 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
1726 pa_xfree(h);
1727 } else
1728 return NULL;
1729
1730 #ifdef OS_IS_WIN32
1731 if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) {
1732 /* FIXME: Needs to set errno! */
1733 pa_xfree(lfn);
1734 return NULL;
1735 }
1736 fn = buf;
1737 #endif
1738
1739 if (access(fn, R_OK) == 0) {
1740 char *r = pa_xstrdup(fn);
1741 pa_xfree(lfn);
1742 return r;
1743 }
1744
1745 if (errno != ENOENT) {
1746 pa_log_warn("Failed to access configuration file '%s': %s", fn, pa_cstrerror(errno));
1747 pa_xfree(lfn);
1748 return NULL;
1749 }
1750
1751 pa_xfree(lfn);
1752 }
1753
1754 if (global) {
1755 #ifdef OS_IS_WIN32
1756 if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
1757 /* FIXME: Needs to set errno! */
1758 return NULL;
1759 global = buf;
1760 #endif
1761
1762 if (access(global, R_OK) == 0)
1763 return pa_xstrdup(global);
1764 }
1765
1766 errno = ENOENT;
1767
1768 return NULL;
1769 }
1770
1771 /* Format the specified data as a hexademical string */
1772 char *pa_hexstr(const uint8_t* d, size_t dlength, char *s, size_t slength) {
1773 size_t i = 0, j = 0;
1774 const char hex[] = "0123456789abcdef";
1775
1776 pa_assert(d);
1777 pa_assert(s);
1778 pa_assert(slength > 0);
1779
1780 while (i < dlength && j+3 <= slength) {
1781 s[j++] = hex[*d >> 4];
1782 s[j++] = hex[*d & 0xF];
1783
1784 d++;
1785 i++;
1786 }
1787
1788 s[j < slength ? j : slength] = 0;
1789 return s;
1790 }
1791
1792 /* Convert a hexadecimal digit to a number or -1 if invalid */
1793 static int hexc(char c) {
1794 if (c >= '0' && c <= '9')
1795 return c - '0';
1796
1797 if (c >= 'A' && c <= 'F')
1798 return c - 'A' + 10;
1799
1800 if (c >= 'a' && c <= 'f')
1801 return c - 'a' + 10;
1802
1803 errno = EINVAL;
1804 return -1;
1805 }
1806
1807 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1808 size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength) {
1809 size_t j = 0;
1810
1811 pa_assert(p);
1812 pa_assert(d);
1813
1814 while (j < dlength && *p) {
1815 int b;
1816
1817 if ((b = hexc(*(p++))) < 0)
1818 return (size_t) -1;
1819
1820 d[j] = (uint8_t) (b << 4);
1821
1822 if (!*p)
1823 return (size_t) -1;
1824
1825 if ((b = hexc(*(p++))) < 0)
1826 return (size_t) -1;
1827
1828 d[j] |= (uint8_t) b;
1829 j++;
1830 }
1831
1832 return j;
1833 }
1834
1835 /* Returns nonzero when *s starts with *pfx */
1836 pa_bool_t pa_startswith(const char *s, const char *pfx) {
1837 size_t l;
1838
1839 pa_assert(s);
1840 pa_assert(pfx);
1841
1842 l = strlen(pfx);
1843
1844 return strlen(s) >= l && strncmp(s, pfx, l) == 0;
1845 }
1846
1847 /* Returns nonzero when *s ends with *sfx */
1848 pa_bool_t pa_endswith(const char *s, const char *sfx) {
1849 size_t l1, l2;
1850
1851 pa_assert(s);
1852 pa_assert(sfx);
1853
1854 l1 = strlen(s);
1855 l2 = strlen(sfx);
1856
1857 return l1 >= l2 && strcmp(s+l1-l2, sfx) == 0;
1858 }
1859
1860 pa_bool_t pa_is_path_absolute(const char *fn) {
1861 pa_assert(fn);
1862
1863 #ifndef OS_IS_WIN32
1864 return *fn == '/';
1865 #else
1866 return strlen(fn) >= 3 && isalpha(fn[0]) && fn[1] == ':' && fn[2] == '\\';
1867 #endif
1868 }
1869
1870 char *pa_make_path_absolute(const char *p) {
1871 char *r;
1872 char *cwd;
1873
1874 pa_assert(p);
1875
1876 if (pa_is_path_absolute(p))
1877 return pa_xstrdup(p);
1878
1879 if (!(cwd = pa_getcwd()))
1880 return pa_xstrdup(p);
1881
1882 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", cwd, p);
1883 pa_xfree(cwd);
1884 return r;
1885 }
1886
1887 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1888 * if fn is non-null and starts with / return fn
1889 * otherwise append fn to the run time path and return it */
1890 static char *get_path(const char *fn, pa_bool_t prependmid, pa_bool_t rt) {
1891 char *rtp;
1892
1893 rtp = rt ? pa_get_runtime_dir() : pa_get_state_dir();
1894
1895 if (fn) {
1896 char *r;
1897
1898 if (pa_is_path_absolute(fn))
1899 return pa_xstrdup(fn);
1900
1901 if (!rtp)
1902 return NULL;
1903
1904 if (prependmid) {
1905 char *mid;
1906
1907 if (!(mid = pa_machine_id())) {
1908 pa_xfree(rtp);
1909 return NULL;
1910 }
1911
1912 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s-%s", rtp, mid, fn);
1913 pa_xfree(mid);
1914 } else
1915 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", rtp, fn);
1916
1917 pa_xfree(rtp);
1918 return r;
1919 } else
1920 return rtp;
1921 }
1922
1923 char *pa_runtime_path(const char *fn) {
1924 return get_path(fn, FALSE, TRUE);
1925 }
1926
1927 char *pa_state_path(const char *fn, pa_bool_t appendmid) {
1928 return get_path(fn, appendmid, FALSE);
1929 }
1930
1931 /* Convert the string s to a signed integer in *ret_i */
1932 int pa_atoi(const char *s, int32_t *ret_i) {
1933 char *x = NULL;
1934 long l;
1935
1936 pa_assert(s);
1937 pa_assert(ret_i);
1938
1939 errno = 0;
1940 l = strtol(s, &x, 0);
1941
1942 if (!x || *x || errno) {
1943 if (!errno)
1944 errno = EINVAL;
1945 return -1;
1946 }
1947
1948 if ((int32_t) l != l) {
1949 errno = ERANGE;
1950 return -1;
1951 }
1952
1953 *ret_i = (int32_t) l;
1954
1955 return 0;
1956 }
1957
1958 /* Convert the string s to an unsigned integer in *ret_u */
1959 int pa_atou(const char *s, uint32_t *ret_u) {
1960 char *x = NULL;
1961 unsigned long l;
1962
1963 pa_assert(s);
1964 pa_assert(ret_u);
1965
1966 errno = 0;
1967 l = strtoul(s, &x, 0);
1968
1969 if (!x || *x || errno) {
1970 if (!errno)
1971 errno = EINVAL;
1972 return -1;
1973 }
1974
1975 if ((uint32_t) l != l) {
1976 errno = ERANGE;
1977 return -1;
1978 }
1979
1980 *ret_u = (uint32_t) l;
1981
1982 return 0;
1983 }
1984
1985 #ifdef HAVE_STRTOF_L
1986 static locale_t c_locale = NULL;
1987
1988 static void c_locale_destroy(void) {
1989 freelocale(c_locale);
1990 }
1991 #endif
1992
1993 int pa_atod(const char *s, double *ret_d) {
1994 char *x = NULL;
1995 double f;
1996
1997 pa_assert(s);
1998 pa_assert(ret_d);
1999
2000 /* This should be locale independent */
2001
2002 #ifdef HAVE_STRTOF_L
2003
2004 PA_ONCE_BEGIN {
2005
2006 if ((c_locale = newlocale(LC_ALL_MASK, "C", NULL)))
2007 atexit(c_locale_destroy);
2008
2009 } PA_ONCE_END;
2010
2011 if (c_locale) {
2012 errno = 0;
2013 f = strtod_l(s, &x, c_locale);
2014 } else
2015 #endif
2016 {
2017 errno = 0;
2018 f = strtod(s, &x);
2019 }
2020
2021 if (!x || *x || errno) {
2022 if (!errno)
2023 errno = EINVAL;
2024 return -1;
2025 }
2026
2027 *ret_d = f;
2028
2029 return 0;
2030 }
2031
2032 /* Same as snprintf, but guarantees NUL-termination on every platform */
2033 size_t pa_snprintf(char *str, size_t size, const char *format, ...) {
2034 size_t ret;
2035 va_list ap;
2036
2037 pa_assert(str);
2038 pa_assert(size > 0);
2039 pa_assert(format);
2040
2041 va_start(ap, format);
2042 ret = pa_vsnprintf(str, size, format, ap);
2043 va_end(ap);
2044
2045 return ret;
2046 }
2047
2048 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2049 size_t pa_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
2050 int ret;
2051
2052 pa_assert(str);
2053 pa_assert(size > 0);
2054 pa_assert(format);
2055
2056 ret = vsnprintf(str, size, format, ap);
2057
2058 str[size-1] = 0;
2059
2060 if (ret < 0)
2061 return strlen(str);
2062
2063 if ((size_t) ret > size-1)
2064 return size-1;
2065
2066 return (size_t) ret;
2067 }
2068
2069 /* Truncate the specified string, but guarantee that the string
2070 * returned still validates as UTF8 */
2071 char *pa_truncate_utf8(char *c, size_t l) {
2072 pa_assert(c);
2073 pa_assert(pa_utf8_valid(c));
2074
2075 if (strlen(c) <= l)
2076 return c;
2077
2078 c[l] = 0;
2079
2080 while (l > 0 && !pa_utf8_valid(c))
2081 c[--l] = 0;
2082
2083 return c;
2084 }
2085
2086 char *pa_getcwd(void) {
2087 size_t l = 128;
2088
2089 for (;;) {
2090 char *p = pa_xmalloc(l);
2091 if (getcwd(p, l))
2092 return p;
2093
2094 if (errno != ERANGE)
2095 return NULL;
2096
2097 pa_xfree(p);
2098 l *= 2;
2099 }
2100 }
2101
2102 void *pa_will_need(const void *p, size_t l) {
2103 #ifdef RLIMIT_MEMLOCK
2104 struct rlimit rlim;
2105 #endif
2106 const void *a;
2107 size_t size;
2108 int r;
2109 size_t bs;
2110
2111 pa_assert(p);
2112 pa_assert(l > 0);
2113
2114 a = PA_PAGE_ALIGN_PTR(p);
2115 size = (size_t) ((const uint8_t*) p + l - (const uint8_t*) a);
2116
2117 #ifdef HAVE_POSIX_MADVISE
2118 if ((r = posix_madvise((void*) a, size, POSIX_MADV_WILLNEED)) == 0) {
2119 pa_log_debug("posix_madvise() worked fine!");
2120 return (void*) p;
2121 }
2122 #endif
2123
2124 /* Most likely the memory was not mmap()ed from a file and thus
2125 * madvise() didn't work, so let's misuse mlock() do page this
2126 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2127 * inviting, the man page of mlock() tells us: "All pages that
2128 * contain a part of the specified address range are guaranteed to
2129 * be resident in RAM when the call returns successfully." */
2130
2131 #ifdef RLIMIT_MEMLOCK
2132 pa_assert_se(getrlimit(RLIMIT_MEMLOCK, &rlim) == 0);
2133
2134 if (rlim.rlim_cur < PA_PAGE_SIZE) {
2135 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));
2136 errno = EPERM;
2137 return (void*) p;
2138 }
2139
2140 bs = PA_PAGE_ALIGN((size_t) rlim.rlim_cur);
2141 #else
2142 bs = PA_PAGE_SIZE*4;
2143 #endif
2144
2145 pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r));
2146
2147 #ifdef HAVE_MLOCK
2148 while (size > 0 && bs > 0) {
2149
2150 if (bs > size)
2151 bs = size;
2152
2153 if (mlock(a, bs) < 0) {
2154 bs = PA_PAGE_ALIGN(bs / 2);
2155 continue;
2156 }
2157
2158 pa_assert_se(munlock(a, bs) == 0);
2159
2160 a = (const uint8_t*) a + bs;
2161 size -= bs;
2162 }
2163 #endif
2164
2165 if (bs <= 0)
2166 pa_log_debug("mlock() failed too (or doesn't exist), giving up: %s", pa_cstrerror(errno));
2167 else
2168 pa_log_debug("mlock() worked fine!");
2169
2170 return (void*) p;
2171 }
2172
2173 void pa_close_pipe(int fds[2]) {
2174 pa_assert(fds);
2175
2176 if (fds[0] >= 0)
2177 pa_assert_se(pa_close(fds[0]) == 0);
2178
2179 if (fds[1] >= 0)
2180 pa_assert_se(pa_close(fds[1]) == 0);
2181
2182 fds[0] = fds[1] = -1;
2183 }
2184
2185 char *pa_readlink(const char *p) {
2186 size_t l = 100;
2187
2188 for (;;) {
2189 char *c;
2190 ssize_t n;
2191
2192 c = pa_xmalloc(l);
2193
2194 if ((n = readlink(p, c, l-1)) < 0) {
2195 pa_xfree(c);
2196 return NULL;
2197 }
2198
2199 if ((size_t) n < l-1) {
2200 c[n] = 0;
2201 return c;
2202 }
2203
2204 pa_xfree(c);
2205 l *= 2;
2206 }
2207 }
2208
2209 int pa_close_all(int except_fd, ...) {
2210 va_list ap;
2211 unsigned n = 0, i;
2212 int r, *p;
2213
2214 va_start(ap, except_fd);
2215
2216 if (except_fd >= 0)
2217 for (n = 1; va_arg(ap, int) >= 0; n++)
2218 ;
2219
2220 va_end(ap);
2221
2222 p = pa_xnew(int, n+1);
2223
2224 va_start(ap, except_fd);
2225
2226 i = 0;
2227 if (except_fd >= 0) {
2228 int fd;
2229 p[i++] = except_fd;
2230
2231 while ((fd = va_arg(ap, int)) >= 0)
2232 p[i++] = fd;
2233 }
2234 p[i] = -1;
2235
2236 va_end(ap);
2237
2238 r = pa_close_allv(p);
2239 pa_xfree(p);
2240
2241 return r;
2242 }
2243
2244 int pa_close_allv(const int except_fds[]) {
2245 struct rlimit rl;
2246 int maxfd, fd;
2247
2248 #ifdef __linux__
2249 int saved_errno;
2250 DIR *d;
2251
2252 if ((d = opendir("/proc/self/fd"))) {
2253
2254 struct dirent *de;
2255
2256 while ((de = readdir(d))) {
2257 pa_bool_t found;
2258 long l;
2259 char *e = NULL;
2260 int i;
2261
2262 if (de->d_name[0] == '.')
2263 continue;
2264
2265 errno = 0;
2266 l = strtol(de->d_name, &e, 10);
2267 if (errno != 0 || !e || *e) {
2268 closedir(d);
2269 errno = EINVAL;
2270 return -1;
2271 }
2272
2273 fd = (int) l;
2274
2275 if ((long) fd != l) {
2276 closedir(d);
2277 errno = EINVAL;
2278 return -1;
2279 }
2280
2281 if (fd < 3)
2282 continue;
2283
2284 if (fd == dirfd(d))
2285 continue;
2286
2287 found = FALSE;
2288 for (i = 0; except_fds[i] >= 0; i++)
2289 if (except_fds[i] == fd) {
2290 found = TRUE;
2291 break;
2292 }
2293
2294 if (found)
2295 continue;
2296
2297 if (pa_close(fd) < 0) {
2298 saved_errno = errno;
2299 closedir(d);
2300 errno = saved_errno;
2301
2302 return -1;
2303 }
2304 }
2305
2306 closedir(d);
2307 return 0;
2308 }
2309
2310 #endif
2311
2312 if (getrlimit(RLIMIT_NOFILE, &rl) >= 0)
2313 maxfd = (int) rl.rlim_max;
2314 else
2315 maxfd = sysconf(_SC_OPEN_MAX);
2316
2317 for (fd = 3; fd < maxfd; fd++) {
2318 int i;
2319 pa_bool_t found;
2320
2321 found = FALSE;
2322 for (i = 0; except_fds[i] >= 0; i++)
2323 if (except_fds[i] == fd) {
2324 found = TRUE;
2325 break;
2326 }
2327
2328 if (found)
2329 continue;
2330
2331 if (pa_close(fd) < 0 && errno != EBADF)
2332 return -1;
2333 }
2334
2335 return 0;
2336 }
2337
2338 int pa_unblock_sigs(int except, ...) {
2339 va_list ap;
2340 unsigned n = 0, i;
2341 int r, *p;
2342
2343 va_start(ap, except);
2344
2345 if (except >= 1)
2346 for (n = 1; va_arg(ap, int) >= 0; n++)
2347 ;
2348
2349 va_end(ap);
2350
2351 p = pa_xnew(int, n+1);
2352
2353 va_start(ap, except);
2354
2355 i = 0;
2356 if (except >= 1) {
2357 int sig;
2358 p[i++] = except;
2359
2360 while ((sig = va_arg(ap, int)) >= 0)
2361 p[i++] = sig;
2362 }
2363 p[i] = -1;
2364
2365 va_end(ap);
2366
2367 r = pa_unblock_sigsv(p);
2368 pa_xfree(p);
2369
2370 return r;
2371 }
2372
2373 int pa_unblock_sigsv(const int except[]) {
2374 int i;
2375 sigset_t ss;
2376
2377 if (sigemptyset(&ss) < 0)
2378 return -1;
2379
2380 for (i = 0; except[i] > 0; i++)
2381 if (sigaddset(&ss, except[i]) < 0)
2382 return -1;
2383
2384 return sigprocmask(SIG_SETMASK, &ss, NULL);
2385 }
2386
2387 int pa_reset_sigs(int except, ...) {
2388 va_list ap;
2389 unsigned n = 0, i;
2390 int *p, r;
2391
2392 va_start(ap, except);
2393
2394 if (except >= 1)
2395 for (n = 1; va_arg(ap, int) >= 0; n++)
2396 ;
2397
2398 va_end(ap);
2399
2400 p = pa_xnew(int, n+1);
2401
2402 va_start(ap, except);
2403
2404 i = 0;
2405 if (except >= 1) {
2406 int sig;
2407 p[i++] = except;
2408
2409 while ((sig = va_arg(ap, int)) >= 0)
2410 sig = p[i++];
2411 }
2412 p[i] = -1;
2413
2414 va_end(ap);
2415
2416 r = pa_reset_sigsv(p);
2417 pa_xfree(p);
2418
2419 return r;
2420 }
2421
2422 int pa_reset_sigsv(const int except[]) {
2423 int sig;
2424
2425 for (sig = 1; sig < NSIG; sig++) {
2426 pa_bool_t reset = TRUE;
2427
2428 switch (sig) {
2429 case SIGKILL:
2430 case SIGSTOP:
2431 reset = FALSE;
2432 break;
2433
2434 default: {
2435 int i;
2436
2437 for (i = 0; except[i] > 0; i++) {
2438 if (sig == except[i]) {
2439 reset = FALSE;
2440 break;
2441 }
2442 }
2443 }
2444 }
2445
2446 if (reset) {
2447 struct sigaction sa;
2448
2449 memset(&sa, 0, sizeof(sa));
2450 sa.sa_handler = SIG_DFL;
2451
2452 /* On Linux the first two RT signals are reserved by
2453 * glibc, and sigaction() will return EINVAL for them. */
2454 if ((sigaction(sig, &sa, NULL) < 0))
2455 if (errno != EINVAL)
2456 return -1;
2457 }
2458 }
2459
2460 return 0;
2461 }
2462
2463 void pa_set_env(const char *key, const char *value) {
2464 pa_assert(key);
2465 pa_assert(value);
2466
2467 /* This is not thread-safe */
2468
2469 putenv(pa_sprintf_malloc("%s=%s", key, value));
2470 }
2471
2472 void pa_set_env_and_record(const char *key, const char *value) {
2473 pa_assert(key);
2474 pa_assert(value);
2475
2476 /* This is not thread-safe */
2477
2478 pa_set_env(key, value);
2479 recorded_env = pa_strlist_prepend(recorded_env, key);
2480 }
2481
2482 void pa_unset_env_recorded(void) {
2483
2484 /* This is not thread-safe */
2485
2486 for (;;) {
2487 char *s;
2488
2489 recorded_env = pa_strlist_pop(recorded_env, &s);
2490
2491 if (!s)
2492 break;
2493
2494 unsetenv(s);
2495 pa_xfree(s);
2496 }
2497 }
2498
2499 pa_bool_t pa_in_system_mode(void) {
2500 const char *e;
2501
2502 if (!(e = getenv("PULSE_SYSTEM")))
2503 return FALSE;
2504
2505 return !!atoi(e);
2506 }
2507
2508 char *pa_get_user_name_malloc(void) {
2509 ssize_t k;
2510 char *u;
2511
2512 #ifdef _SC_LOGIN_NAME_MAX
2513 k = (ssize_t) sysconf(_SC_LOGIN_NAME_MAX);
2514
2515 if (k <= 0)
2516 #endif
2517 k = 32;
2518
2519 u = pa_xnew(char, k+1);
2520
2521 if (!(pa_get_user_name(u, k))) {
2522 pa_xfree(u);
2523 return NULL;
2524 }
2525
2526 return u;
2527 }
2528
2529 char *pa_get_host_name_malloc(void) {
2530 size_t l;
2531
2532 l = 100;
2533 for (;;) {
2534 char *c;
2535
2536 c = pa_xmalloc(l);
2537
2538 if (!pa_get_host_name(c, l)) {
2539
2540 if (errno != EINVAL && errno != ENAMETOOLONG)
2541 break;
2542
2543 } else if (strlen(c) < l-1) {
2544 char *u;
2545
2546 if (*c == 0) {
2547 pa_xfree(c);
2548 break;
2549 }
2550
2551 u = pa_utf8_filter(c);
2552 pa_xfree(c);
2553 return u;
2554 }
2555
2556 /* Hmm, the hostname is as long the space we offered the
2557 * function, we cannot know if it fully fit in, so let's play
2558 * safe and retry. */
2559
2560 pa_xfree(c);
2561 l *= 2;
2562 }
2563
2564 return NULL;
2565 }
2566
2567 char *pa_machine_id(void) {
2568 FILE *f;
2569 char *h;
2570
2571 /* The returned value is supposed be some kind of ascii identifier
2572 * that is unique and stable across reboots. */
2573
2574 /* First we try the D-Bus UUID, which is the best option we have,
2575 * since it fits perfectly our needs and is not as volatile as the
2576 * hostname which might be set from dhcp. */
2577
2578 if ((f = fopen(PA_MACHINE_ID, "r"))) {
2579 char ln[34] = "", *r;
2580
2581 r = fgets(ln, sizeof(ln)-1, f);
2582 fclose(f);
2583
2584 pa_strip_nl(ln);
2585
2586 if (r && ln[0])
2587 return pa_utf8_filter(ln);
2588 }
2589
2590 if ((h = pa_get_host_name_malloc()))
2591 return h;
2592
2593 /* If no hostname was set we use the POSIX hostid. It's usually
2594 * the IPv4 address. Might not be that stable. */
2595 return pa_sprintf_malloc("%08lx", (unsigned long) gethostid);
2596 }
2597
2598 char *pa_session_id(void) {
2599 const char *e;
2600
2601 if (!(e = getenv("XDG_SESSION_COOKIE")))
2602 return NULL;
2603
2604 return pa_utf8_filter(e);
2605 }
2606
2607 char *pa_uname_string(void) {
2608 struct utsname u;
2609
2610 pa_assert_se(uname(&u) >= 0);
2611
2612 return pa_sprintf_malloc("%s %s %s %s", u.sysname, u.machine, u.release, u.version);
2613 }
2614
2615 #ifdef HAVE_VALGRIND_MEMCHECK_H
2616 pa_bool_t pa_in_valgrind(void) {
2617 static int b = 0;
2618
2619 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2620 * here instead of really checking whether we run in valgrind or
2621 * not. */
2622
2623 if (b < 1)
2624 b = getenv("VALGRIND") ? 2 : 1;
2625
2626 return b > 1;
2627 }
2628 #endif
2629
2630 unsigned pa_gcd(unsigned a, unsigned b) {
2631
2632 while (b > 0) {
2633 unsigned t = b;
2634 b = a % b;
2635 a = t;
2636 }
2637
2638 return a;
2639 }
2640
2641 void pa_reduce(unsigned *num, unsigned *den) {
2642
2643 unsigned gcd = pa_gcd(*num, *den);
2644
2645 if (gcd <= 0)
2646 return;
2647
2648 *num /= gcd;
2649 *den /= gcd;
2650
2651 pa_assert(pa_gcd(*num, *den) == 1);
2652 }
2653
2654 unsigned pa_ncpus(void) {
2655 long ncpus;
2656
2657 #ifdef _SC_NPROCESSORS_CONF
2658 ncpus = sysconf(_SC_NPROCESSORS_CONF);
2659 #else
2660 ncpus = 1;
2661 #endif
2662
2663 return ncpus <= 0 ? 1 : (unsigned) ncpus;
2664 }
2665
2666 char *pa_replace(const char*s, const char*a, const char *b) {
2667 pa_strbuf *sb;
2668 size_t an;
2669
2670 pa_assert(s);
2671 pa_assert(a);
2672 pa_assert(b);
2673
2674 an = strlen(a);
2675 sb = pa_strbuf_new();
2676
2677 for (;;) {
2678 const char *p;
2679
2680 if (!(p = strstr(s, a)))
2681 break;
2682
2683 pa_strbuf_putsn(sb, s, p-s);
2684 pa_strbuf_puts(sb, b);
2685 s = p + an;
2686 }
2687
2688 pa_strbuf_puts(sb, s);
2689
2690 return pa_strbuf_tostring_free(sb);
2691 }
2692
2693 char *pa_unescape(char *p) {
2694 char *s, *d;
2695 pa_bool_t escaped = FALSE;
2696
2697 for (s = p, d = p; *s; s++) {
2698 if (!escaped && *s == '\\') {
2699 escaped = TRUE;
2700 continue;
2701 }
2702
2703 *(d++) = *s;
2704 escaped = FALSE;
2705 }
2706
2707 *d = 0;
2708
2709 return p;
2710 }
2711
2712 char *pa_realpath(const char *path) {
2713 char *t;
2714 pa_assert(path);
2715
2716 /* We want only abolsute paths */
2717 if (path[0] != '/') {
2718 errno = EINVAL;
2719 return NULL;
2720 }
2721
2722 #if defined(__GLIBC__) || defined(__APPLE__)
2723 {
2724 char *r;
2725
2726 if (!(r = realpath(path, NULL)))
2727 return NULL;
2728
2729 /* We copy this here in case our pa_xmalloc() is not
2730 * implemented on top of libc malloc() */
2731 t = pa_xstrdup(r);
2732 pa_xfree(r);
2733 }
2734 #elif defined(PATH_MAX)
2735 {
2736 char *path_buf;
2737 path_buf = pa_xmalloc(PATH_MAX);
2738
2739 if (!(t = realpath(path, path_buf))) {
2740 pa_xfree(path_buf);
2741 return NULL;
2742 }
2743 }
2744 #else
2745 #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."
2746 #endif
2747
2748 return t;
2749 }
2750
2751 void pa_disable_sigpipe(void) {
2752
2753 #ifdef SIGPIPE
2754 struct sigaction sa;
2755
2756 pa_zero(sa);
2757
2758 if (sigaction(SIGPIPE, NULL, &sa) < 0) {
2759 pa_log("sigaction(): %s", pa_cstrerror(errno));
2760 return;
2761 }
2762
2763 sa.sa_handler = SIG_IGN;
2764
2765 if (sigaction(SIGPIPE, &sa, NULL) < 0) {
2766 pa_log("sigaction(): %s", pa_cstrerror(errno));
2767 return;
2768 }
2769 #endif
2770 }
2771
2772 void pa_xfreev(void**a) {
2773 void **p;
2774
2775 if (!a)
2776 return;
2777
2778 for (p = a; *p; p++)
2779 pa_xfree(*p);
2780
2781 pa_xfree(a);
2782 }
2783
2784 char **pa_split_spaces_strv(const char *s) {
2785 char **t, *e;
2786 unsigned i = 0, n = 8;
2787 const char *state = NULL;
2788
2789 t = pa_xnew(char*, n);
2790 while ((e = pa_split_spaces(s, &state))) {
2791 t[i++] = e;
2792
2793 if (i >= n) {
2794 n *= 2;
2795 t = pa_xrenew(char*, t, n);
2796 }
2797 }
2798
2799 if (i <= 0) {
2800 pa_xfree(t);
2801 return NULL;
2802 }
2803
2804 t[i] = NULL;
2805 return t;
2806 }
2807
2808 char* pa_maybe_prefix_path(const char *path, const char *prefix) {
2809 pa_assert(path);
2810
2811 if (pa_is_path_absolute(path))
2812 return pa_xstrdup(path);
2813
2814 return pa_sprintf_malloc("%s" PA_PATH_SEP "%s", prefix, path);
2815 }
2816
2817 size_t pa_pipe_buf(int fd) {
2818
2819 #ifdef _PC_PIPE_BUF
2820 long n;
2821
2822 if ((n = fpathconf(fd, _PC_PIPE_BUF)) >= 0)
2823 return (size_t) n;
2824 #endif
2825
2826 #ifdef PIPE_BUF
2827 return PIPE_BUF;
2828 #else
2829 return 4096;
2830 #endif
2831 }
2832
2833 void pa_reset_personality(void) {
2834
2835 #ifdef __linux__
2836 if (personality(PER_LINUX) < 0)
2837 pa_log_warn("Uh, personality() failed: %s", pa_cstrerror(errno));
2838 #endif
2839
2840 }
2841
2842 #if defined(__linux__) && !defined(__OPTIMIZE__)
2843
2844 pa_bool_t pa_run_from_build_tree(void) {
2845 char *rp;
2846 pa_bool_t b = FALSE;
2847
2848 /* We abuse __OPTIMIZE__ as a check whether we are a debug build
2849 * or not. */
2850
2851 if ((rp = pa_readlink("/proc/self/exe"))) {
2852 b = pa_startswith(rp, PA_BUILDDIR);
2853 pa_xfree(rp);
2854 }
2855
2856 return b;
2857 }
2858
2859 #endif