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