]> code.delx.au - pulseaudio/blob - src/pulsecore/core-util.c
fix two thinkos in signal reset/close_all code
[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
44 #ifdef HAVE_STRTOF_L
45 #include <locale.h>
46 #endif
47
48 #ifdef HAVE_SCHED_H
49 #include <sched.h>
50 #endif
51
52 #ifdef HAVE_SYS_RESOURCE_H
53 #include <sys/resource.h>
54 #endif
55
56 #ifdef HAVE_SYS_CAPABILITY_H
57 #include <sys/capability.h>
58 #endif
59
60 #ifdef HAVE_SYS_MMAN_H
61 #include <sys/mman.h>
62 #endif
63
64 #ifdef HAVE_PTHREAD
65 #include <pthread.h>
66 #endif
67
68 #ifdef HAVE_NETDB_H
69 #include <netdb.h>
70 #endif
71
72 #ifdef HAVE_WINDOWS_H
73 #include <windows.h>
74 #endif
75
76 #ifdef HAVE_PWD_H
77 #include <pwd.h>
78 #endif
79
80 #ifdef HAVE_GRP_H
81 #include <grp.h>
82 #endif
83
84 #ifdef HAVE_LIBSAMPLERATE
85 #include <samplerate.h>
86 #endif
87
88 #include <pulse/xmalloc.h>
89 #include <pulse/util.h>
90 #include <pulse/utf8.h>
91
92 #include <pulsecore/core-error.h>
93 #include <pulsecore/winsock.h>
94 #include <pulsecore/log.h>
95 #include <pulsecore/macro.h>
96 #include <pulsecore/thread.h>
97
98 #include "core-util.h"
99
100 /* Not all platforms have this */
101 #ifndef MSG_NOSIGNAL
102 #define MSG_NOSIGNAL 0
103 #endif
104
105 #ifdef OS_IS_WIN32
106
107 #define PULSE_ROOTENV "PULSE_ROOT"
108
109 int pa_set_root(HANDLE handle) {
110 char library_path[MAX_PATH + sizeof(PULSE_ROOTENV) + 1], *sep;
111
112 strcpy(library_path, PULSE_ROOTENV "=");
113
114 if (!GetModuleFileName(handle, library_path + sizeof(PULSE_ROOTENV), MAX_PATH))
115 return 0;
116
117 sep = strrchr(library_path, PA_PATH_SEP_CHAR);
118 if (sep)
119 *sep = '\0';
120
121 if (_putenv(library_path) < 0)
122 return 0;
123
124 return 1;
125 }
126
127 #endif
128
129 /** Make a file descriptor nonblock. Doesn't do any error checking */
130 void pa_make_fd_nonblock(int fd) {
131
132 #ifdef O_NONBLOCK
133 int v;
134 pa_assert(fd >= 0);
135
136 pa_assert_se((v = fcntl(fd, F_GETFL)) >= 0);
137
138 if (!(v & O_NONBLOCK))
139 pa_assert_se(fcntl(fd, F_SETFL, v|O_NONBLOCK) >= 0);
140
141 #elif defined(OS_IS_WIN32)
142 u_long arg = 1;
143 if (ioctlsocket(fd, FIONBIO, &arg) < 0) {
144 pa_assert_se(WSAGetLastError() == WSAENOTSOCK);
145 pa_log_warn("Only sockets can be made non-blocking!");
146 }
147 #else
148 pa_log_warn("Non-blocking I/O not supported.!");
149 #endif
150
151 }
152
153 /* Set the FD_CLOEXEC flag for a fd */
154 void pa_make_fd_cloexec(int fd) {
155
156 #ifdef FD_CLOEXEC
157 int v;
158 pa_assert(fd >= 0);
159
160 pa_assert_se((v = fcntl(fd, F_GETFD, 0)) >= 0);
161
162 if (!(v & FD_CLOEXEC))
163 pa_assert_se(fcntl(fd, F_SETFD, v|FD_CLOEXEC) >= 0);
164 #endif
165
166 }
167
168 /** Creates a directory securely */
169 int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid) {
170 struct stat st;
171 int r;
172
173 pa_assert(dir);
174
175 #ifdef OS_IS_WIN32
176 r = mkdir(dir);
177 #else
178 {
179 mode_t u;
180 u = umask(~m);
181 r = mkdir(dir, m);
182 umask(u);
183 }
184 #endif
185
186 if (r < 0 && errno != EEXIST)
187 return -1;
188
189 #ifdef HAVE_CHOWN
190 if (uid == (uid_t)-1)
191 uid = getuid();
192 if (gid == (gid_t)-1)
193 gid = getgid();
194 (void) chown(dir, uid, gid);
195 #endif
196
197 #ifdef HAVE_CHMOD
198 chmod(dir, m);
199 #endif
200
201 #ifdef HAVE_LSTAT
202 if (lstat(dir, &st) < 0)
203 #else
204 if (stat(dir, &st) < 0)
205 #endif
206 goto fail;
207
208 #ifndef OS_IS_WIN32
209 if (!S_ISDIR(st.st_mode) ||
210 (st.st_uid != uid) ||
211 (st.st_gid != gid) ||
212 ((st.st_mode & 0777) != m)) {
213 errno = EACCES;
214 goto fail;
215 }
216 #else
217 pa_log_warn("Secure directory creation not supported on Win32.");
218 #endif
219
220 return 0;
221
222 fail:
223 rmdir(dir);
224 return -1;
225 }
226
227 /* Return a newly allocated sting containing the parent directory of the specified file */
228 char *pa_parent_dir(const char *fn) {
229 char *slash, *dir = pa_xstrdup(fn);
230
231 if ((slash = (char*) pa_path_get_filename(dir)) == dir) {
232 pa_xfree(dir);
233 return NULL;
234 }
235
236 *(slash-1) = 0;
237 return dir;
238 }
239
240 /* Creates a the parent directory of the specified path securely */
241 int pa_make_secure_parent_dir(const char *fn, mode_t m, uid_t uid, gid_t gid) {
242 int ret = -1;
243 char *dir;
244
245 if (!(dir = pa_parent_dir(fn)))
246 goto finish;
247
248 if (pa_make_secure_dir(dir, m, uid, gid) < 0)
249 goto finish;
250
251 ret = 0;
252
253 finish:
254 pa_xfree(dir);
255 return ret;
256 }
257
258 /** Platform independent read function. Necessary since not all
259 * systems treat all file descriptors equal. If type is
260 * non-NULL it is used to cache the type of the fd. This is
261 * useful for making sure that only a single syscall is executed per
262 * function call. The variable pointed to should be initialized to 0
263 * by the caller. */
264 ssize_t pa_read(int fd, void *buf, size_t count, int *type) {
265
266 #ifdef OS_IS_WIN32
267
268 if (!type || *type == 0) {
269 ssize_t r;
270
271 if ((r = recv(fd, buf, count, 0)) >= 0)
272 return r;
273
274 if (WSAGetLastError() != WSAENOTSOCK) {
275 errno = WSAGetLastError();
276 return r;
277 }
278
279 if (type)
280 *type = 1;
281 }
282
283 #endif
284
285 return read(fd, buf, count);
286 }
287
288 /** Similar to pa_read(), but handles writes */
289 ssize_t pa_write(int fd, const void *buf, size_t count, int *type) {
290
291 if (!type || *type == 0) {
292 ssize_t r;
293
294 if ((r = send(fd, buf, count, MSG_NOSIGNAL)) >= 0)
295 return r;
296
297 #ifdef OS_IS_WIN32
298 if (WSAGetLastError() != WSAENOTSOCK) {
299 errno = WSAGetLastError();
300 return r;
301 }
302 #else
303 if (errno != ENOTSOCK)
304 return r;
305 #endif
306
307 if (type)
308 *type = 1;
309 }
310
311 return write(fd, buf, count);
312 }
313
314 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
315 * unless EOF is reached or an error occured */
316 ssize_t pa_loop_read(int fd, void*data, size_t size, int *type) {
317 ssize_t ret = 0;
318 int _type;
319
320 pa_assert(fd >= 0);
321 pa_assert(data);
322 pa_assert(size);
323
324 if (!type) {
325 _type = 0;
326 type = &_type;
327 }
328
329 while (size > 0) {
330 ssize_t r;
331
332 if ((r = pa_read(fd, data, size, type)) < 0)
333 return r;
334
335 if (r == 0)
336 break;
337
338 ret += r;
339 data = (uint8_t*) data + r;
340 size -= r;
341 }
342
343 return ret;
344 }
345
346 /** Similar to pa_loop_read(), but wraps write() */
347 ssize_t pa_loop_write(int fd, const void*data, size_t size, int *type) {
348 ssize_t ret = 0;
349 int _type;
350
351 pa_assert(fd >= 0);
352 pa_assert(data);
353 pa_assert(size);
354
355 if (!type) {
356 _type = 0;
357 type = &_type;
358 }
359
360 while (size > 0) {
361 ssize_t r;
362
363 if ((r = pa_write(fd, data, size, type)) < 0)
364 return r;
365
366 if (r == 0)
367 break;
368
369 ret += r;
370 data = (const uint8_t*) data + r;
371 size -= r;
372 }
373
374 return ret;
375 }
376
377 /** Platform independent read function. Necessary since not all
378 * systems treat all file descriptors equal. */
379 int pa_close(int fd) {
380
381 #ifdef OS_IS_WIN32
382 int ret;
383
384 if ((ret = closesocket(fd)) == 0)
385 return 0;
386
387 if (WSAGetLastError() != WSAENOTSOCK) {
388 errno = WSAGetLastError();
389 return ret;
390 }
391 #endif
392
393 return close(fd);
394 }
395
396 /* Print a warning messages in case that the given signal is not
397 * blocked or trapped */
398 void pa_check_signal_is_blocked(int sig) {
399 #ifdef HAVE_SIGACTION
400 struct sigaction sa;
401 sigset_t set;
402
403 /* If POSIX threads are supported use thread-aware
404 * pthread_sigmask() function, to check if the signal is
405 * blocked. Otherwise fall back to sigprocmask() */
406
407 #ifdef HAVE_PTHREAD
408 if (pthread_sigmask(SIG_SETMASK, NULL, &set) < 0) {
409 #endif
410 if (sigprocmask(SIG_SETMASK, NULL, &set) < 0) {
411 pa_log("sigprocmask(): %s", pa_cstrerror(errno));
412 return;
413 }
414 #ifdef HAVE_PTHREAD
415 }
416 #endif
417
418 if (sigismember(&set, sig))
419 return;
420
421 /* Check whether the signal is trapped */
422
423 if (sigaction(sig, NULL, &sa) < 0) {
424 pa_log("sigaction(): %s", pa_cstrerror(errno));
425 return;
426 }
427
428 if (sa.sa_handler != SIG_DFL)
429 return;
430
431 pa_log_warn("%s is not trapped. This might cause malfunction!", pa_sig2str(sig));
432 #else /* HAVE_SIGACTION */
433 pa_log_warn("%s might not be trapped. This might cause malfunction!", pa_sig2str(sig));
434 #endif
435 }
436
437 /* The following function is based on an example from the GNU libc
438 * documentation. This function is similar to GNU's asprintf(). */
439 char *pa_sprintf_malloc(const char *format, ...) {
440 int size = 100;
441 char *c = NULL;
442
443 pa_assert(format);
444
445 for(;;) {
446 int r;
447 va_list ap;
448
449 c = pa_xrealloc(c, size);
450
451 va_start(ap, format);
452 r = vsnprintf(c, size, format, ap);
453 va_end(ap);
454
455 c[size-1] = 0;
456
457 if (r > -1 && r < size)
458 return c;
459
460 if (r > -1) /* glibc 2.1 */
461 size = r+1;
462 else /* glibc 2.0 */
463 size *= 2;
464 }
465 }
466
467 /* Same as the previous function, but use a va_list instead of an
468 * ellipsis */
469 char *pa_vsprintf_malloc(const char *format, va_list ap) {
470 int size = 100;
471 char *c = NULL;
472
473 pa_assert(format);
474
475 for(;;) {
476 int r;
477 va_list aq;
478
479 c = pa_xrealloc(c, size);
480
481 va_copy(aq, ap);
482 r = vsnprintf(c, size, format, aq);
483 va_end(aq);
484
485 c[size-1] = 0;
486
487 if (r > -1 && r < size)
488 return c;
489
490 if (r > -1) /* glibc 2.1 */
491 size = r+1;
492 else /* glibc 2.0 */
493 size *= 2;
494 }
495 }
496
497 /* Similar to OpenBSD's strlcpy() function */
498 char *pa_strlcpy(char *b, const char *s, size_t l) {
499 pa_assert(b);
500 pa_assert(s);
501 pa_assert(l > 0);
502
503 strncpy(b, s, l);
504 b[l-1] = 0;
505 return b;
506 }
507
508 /* Make the current thread a realtime thread, and acquire the highest
509 * rtprio we can get that is less or equal the specified parameter. If
510 * the thread is already realtime, don't do anything. */
511 int pa_make_realtime(int rtprio) {
512
513 #ifdef _POSIX_PRIORITY_SCHEDULING
514 struct sched_param sp;
515 int r, policy;
516
517 memset(&sp, 0, sizeof(sp));
518 policy = 0;
519
520 if ((r = pthread_getschedparam(pthread_self(), &policy, &sp)) != 0) {
521 pa_log("pthread_getschedgetparam(): %s", pa_cstrerror(r));
522 return -1;
523 }
524
525 if (policy == SCHED_FIFO && sp.sched_priority >= rtprio) {
526 pa_log_info("Thread already being scheduled with SCHED_FIFO with priority %i.", sp.sched_priority);
527 return 0;
528 }
529
530 sp.sched_priority = rtprio;
531 if ((r = pthread_setschedparam(pthread_self(), SCHED_FIFO, &sp)) != 0) {
532
533 while (sp.sched_priority > 1) {
534 sp.sched_priority --;
535
536 if ((r = pthread_setschedparam(pthread_self(), SCHED_FIFO, &sp)) == 0) {
537 pa_log_info("Successfully enabled SCHED_FIFO scheduling for thread, with priority %i, which is lower than the requested %i.", sp.sched_priority, rtprio);
538 return 0;
539 }
540 }
541
542 pa_log_warn("pthread_setschedparam(): %s", pa_cstrerror(r));
543 return -1;
544 }
545
546 pa_log_info("Successfully enabled SCHED_FIFO scheduling for thread, with priority %i.", sp.sched_priority);
547 return 0;
548 #else
549 return -1;
550 #endif
551 }
552
553 /* This is merely used for giving the user a hint. This is not correct
554 * for anything security related */
555 pa_bool_t pa_can_realtime(void) {
556
557 if (geteuid() == 0)
558 return TRUE;
559
560 #if defined(HAVE_SYS_RESOURCE_H) && defined(RLIMIT_RTPRIO)
561 {
562 struct rlimit rl;
563
564 if (getrlimit(RLIMIT_RTPRIO, &rl) >= 0)
565 if (rl.rlim_cur > 0 || rl.rlim_cur == RLIM_INFINITY)
566 return TRUE;
567 }
568 #endif
569
570 #if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_SYS_NICE)
571 {
572 cap_t cap;
573
574 if ((cap = cap_get_proc())) {
575 cap_flag_value_t flag = CAP_CLEAR;
576
577 if (cap_get_flag(cap, CAP_SYS_NICE, CAP_EFFECTIVE, &flag) >= 0)
578 if (flag == CAP_SET) {
579 cap_free(cap);
580 return TRUE;
581 }
582
583 cap_free(cap);
584 }
585 }
586 #endif
587
588 return FALSE;
589 }
590
591 /* This is merely used for giving the user a hint. This is not correct
592 * for anything security related */
593 pa_bool_t pa_can_high_priority(void) {
594
595 if (geteuid() == 0)
596 return TRUE;
597
598 #if defined(HAVE_SYS_RESOURCE_H) && defined(RLIMIT_RTPRIO)
599 {
600 struct rlimit rl;
601
602 if (getrlimit(RLIMIT_NICE, &rl) >= 0)
603 if (rl.rlim_cur >= 21 || rl.rlim_cur == RLIM_INFINITY)
604 return TRUE;
605 }
606 #endif
607
608 #if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_SYS_NICE)
609 {
610 cap_t cap;
611
612 if ((cap = cap_get_proc())) {
613 cap_flag_value_t flag = CAP_CLEAR;
614
615 if (cap_get_flag(cap, CAP_SYS_NICE, CAP_EFFECTIVE, &flag) >= 0)
616 if (flag == CAP_SET) {
617 cap_free(cap);
618 return TRUE;
619 }
620
621 cap_free(cap);
622 }
623 }
624 #endif
625
626 return FALSE;
627 }
628
629 /* Raise the priority of the current process as much as possible that
630 * is <= the specified nice level..*/
631 int pa_raise_priority(int nice_level) {
632
633 #ifdef HAVE_SYS_RESOURCE_H
634 if (setpriority(PRIO_PROCESS, 0, nice_level) < 0) {
635 int n;
636
637 for (n = nice_level+1; n < 0; n++) {
638
639 if (setpriority(PRIO_PROCESS, 0, n) == 0) {
640 pa_log_info("Successfully acquired nice level %i, which is lower than the requested %i.", n, nice_level);
641 return 0;
642 }
643 }
644
645 pa_log_warn("setpriority(): %s", pa_cstrerror(errno));
646 return -1;
647 }
648
649 pa_log_info("Successfully gained nice level %i.", nice_level);
650 #endif
651
652 #ifdef OS_IS_WIN32
653 if (nice_level < 0) {
654 if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS)) {
655 pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError());
656 return .-1;
657 } else
658 pa_log_info("Successfully gained high priority class.");
659 }
660 #endif
661
662 return 0;
663 }
664
665 /* Reset the priority to normal, inverting the changes made by
666 * pa_raise_priority() and pa_make_realtime()*/
667 void pa_reset_priority(void) {
668 #ifdef HAVE_SYS_RESOURCE_H
669 struct sched_param sp;
670
671 setpriority(PRIO_PROCESS, 0, 0);
672
673 memset(&sp, 0, sizeof(sp));
674 pa_assert_se(pthread_setschedparam(pthread_self(), SCHED_OTHER, &sp) == 0);
675 #endif
676
677 #ifdef OS_IS_WIN32
678 SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
679 #endif
680 }
681
682 /* Try to parse a boolean string value.*/
683 int pa_parse_boolean(const char *v) {
684 pa_assert(v);
685
686 if (!strcmp(v, "1") || v[0] == 'y' || v[0] == 'Y' || v[0] == 't' || v[0] == 'T' || !strcasecmp(v, "on"))
687 return 1;
688 else if (!strcmp(v, "0") || v[0] == 'n' || v[0] == 'N' || v[0] == 'f' || v[0] == 'F' || !strcasecmp(v, "off"))
689 return 0;
690
691 return -1;
692 }
693
694 /* Split the specified string wherever one of the strings in delimiter
695 * occurs. Each time it is called returns a newly allocated string
696 * with pa_xmalloc(). The variable state points to, should be
697 * initiallized to NULL before the first call. */
698 char *pa_split(const char *c, const char *delimiter, const char**state) {
699 const char *current = *state ? *state : c;
700 size_t l;
701
702 if (!*current)
703 return NULL;
704
705 l = strcspn(current, delimiter);
706 *state = current+l;
707
708 if (**state)
709 (*state)++;
710
711 return pa_xstrndup(current, l);
712 }
713
714 /* What is interpreted as whitespace? */
715 #define WHITESPACE " \t\n"
716
717 /* Split a string into words. Otherwise similar to pa_split(). */
718 char *pa_split_spaces(const char *c, const char **state) {
719 const char *current = *state ? *state : c;
720 size_t l;
721
722 if (!*current || *c == 0)
723 return NULL;
724
725 current += strspn(current, WHITESPACE);
726 l = strcspn(current, WHITESPACE);
727
728 *state = current+l;
729
730 return pa_xstrndup(current, l);
731 }
732
733 PA_STATIC_TLS_DECLARE(signame, pa_xfree);
734
735 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
736 const char *pa_sig2str(int sig) {
737 char *t;
738
739 if (sig <= 0)
740 goto fail;
741
742 #ifdef NSIG
743 if (sig >= NSIG)
744 goto fail;
745 #endif
746
747 #ifdef HAVE_SIG2STR
748 {
749 char buf[SIG2STR_MAX];
750
751 if (sig2str(sig, buf) == 0) {
752 pa_xfree(PA_STATIC_TLS_GET(signame));
753 t = pa_sprintf_malloc("SIG%s", buf);
754 PA_STATIC_TLS_SET(signame, t);
755 return t;
756 }
757 }
758 #else
759
760 switch(sig) {
761 #ifdef SIGHUP
762 case SIGHUP: return "SIGHUP";
763 #endif
764 case SIGINT: return "SIGINT";
765 #ifdef SIGQUIT
766 case SIGQUIT: return "SIGQUIT";
767 #endif
768 case SIGILL: return "SIGULL";
769 #ifdef SIGTRAP
770 case SIGTRAP: return "SIGTRAP";
771 #endif
772 case SIGABRT: return "SIGABRT";
773 #ifdef SIGBUS
774 case SIGBUS: return "SIGBUS";
775 #endif
776 case SIGFPE: return "SIGFPE";
777 #ifdef SIGKILL
778 case SIGKILL: return "SIGKILL";
779 #endif
780 #ifdef SIGUSR1
781 case SIGUSR1: return "SIGUSR1";
782 #endif
783 case SIGSEGV: return "SIGSEGV";
784 #ifdef SIGUSR2
785 case SIGUSR2: return "SIGUSR2";
786 #endif
787 #ifdef SIGPIPE
788 case SIGPIPE: return "SIGPIPE";
789 #endif
790 #ifdef SIGALRM
791 case SIGALRM: return "SIGALRM";
792 #endif
793 case SIGTERM: return "SIGTERM";
794 #ifdef SIGSTKFLT
795 case SIGSTKFLT: return "SIGSTKFLT";
796 #endif
797 #ifdef SIGCHLD
798 case SIGCHLD: return "SIGCHLD";
799 #endif
800 #ifdef SIGCONT
801 case SIGCONT: return "SIGCONT";
802 #endif
803 #ifdef SIGSTOP
804 case SIGSTOP: return "SIGSTOP";
805 #endif
806 #ifdef SIGTSTP
807 case SIGTSTP: return "SIGTSTP";
808 #endif
809 #ifdef SIGTTIN
810 case SIGTTIN: return "SIGTTIN";
811 #endif
812 #ifdef SIGTTOU
813 case SIGTTOU: return "SIGTTOU";
814 #endif
815 #ifdef SIGURG
816 case SIGURG: return "SIGURG";
817 #endif
818 #ifdef SIGXCPU
819 case SIGXCPU: return "SIGXCPU";
820 #endif
821 #ifdef SIGXFSZ
822 case SIGXFSZ: return "SIGXFSZ";
823 #endif
824 #ifdef SIGVTALRM
825 case SIGVTALRM: return "SIGVTALRM";
826 #endif
827 #ifdef SIGPROF
828 case SIGPROF: return "SIGPROF";
829 #endif
830 #ifdef SIGWINCH
831 case SIGWINCH: return "SIGWINCH";
832 #endif
833 #ifdef SIGIO
834 case SIGIO: return "SIGIO";
835 #endif
836 #ifdef SIGPWR
837 case SIGPWR: return "SIGPWR";
838 #endif
839 #ifdef SIGSYS
840 case SIGSYS: return "SIGSYS";
841 #endif
842 }
843
844 #ifdef SIGRTMIN
845 if (sig >= SIGRTMIN && sig <= SIGRTMAX) {
846 pa_xfree(PA_STATIC_TLS_GET(signame));
847 t = pa_sprintf_malloc("SIGRTMIN+%i", sig - SIGRTMIN);
848 PA_STATIC_TLS_SET(signame, t);
849 return t;
850 }
851 #endif
852
853 #endif
854
855 fail:
856
857 pa_xfree(PA_STATIC_TLS_GET(signame));
858 t = pa_sprintf_malloc("SIG%i", sig);
859 PA_STATIC_TLS_SET(signame, t);
860 return t;
861 }
862
863 #ifdef HAVE_GRP_H
864
865 /* Check whether the specified GID and the group name match */
866 static int is_group(gid_t gid, const char *name) {
867 struct group group, *result = NULL;
868 long n;
869 void *data;
870 int r = -1;
871
872 #ifdef HAVE_GETGRGID_R
873 #ifdef _SC_GETGR_R_SIZE_MAX
874 n = sysconf(_SC_GETGR_R_SIZE_MAX);
875 #else
876 n = -1;
877 #endif
878 if (n < 0) n = 512;
879 data = pa_xmalloc(n);
880
881 if (getgrgid_r(gid, &group, data, n, &result) < 0 || !result) {
882 pa_log("getgrgid_r(%u): %s", (unsigned)gid, pa_cstrerror(errno));
883 goto finish;
884 }
885
886 r = strcmp(name, result->gr_name) == 0;
887
888 finish:
889 pa_xfree(data);
890 #else
891 /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X) that do not
892 * support getgrgid_r. */
893 if ((result = getgrgid(gid)) == NULL) {
894 pa_log("getgrgid(%u): %s", gid, pa_cstrerror(errno));
895 goto finish;
896 }
897
898 r = strcmp(name, result->gr_name) == 0;
899
900 finish:
901 #endif
902
903 return r;
904 }
905
906 /* Check the current user is member of the specified group */
907 int pa_own_uid_in_group(const char *name, gid_t *gid) {
908 GETGROUPS_T *gids, tgid;
909 int n = sysconf(_SC_NGROUPS_MAX);
910 int r = -1, i;
911
912 pa_assert(n > 0);
913
914 gids = pa_xmalloc(sizeof(GETGROUPS_T)*n);
915
916 if ((n = getgroups(n, gids)) < 0) {
917 pa_log("getgroups(): %s", pa_cstrerror(errno));
918 goto finish;
919 }
920
921 for (i = 0; i < n; i++) {
922 if (is_group(gids[i], name) > 0) {
923 *gid = gids[i];
924 r = 1;
925 goto finish;
926 }
927 }
928
929 if (is_group(tgid = getgid(), name) > 0) {
930 *gid = tgid;
931 r = 1;
932 goto finish;
933 }
934
935 r = 0;
936
937 finish:
938
939 pa_xfree(gids);
940 return r;
941 }
942
943 /* Check whether the specifc user id is a member of the specified group */
944 int pa_uid_in_group(uid_t uid, const char *name) {
945 char *g_buf, *p_buf;
946 long g_n, p_n;
947 struct group grbuf, *gr;
948 char **i;
949 int r = -1;
950
951 g_n = sysconf(_SC_GETGR_R_SIZE_MAX);
952 g_buf = pa_xmalloc(g_n);
953
954 p_n = sysconf(_SC_GETPW_R_SIZE_MAX);
955 p_buf = pa_xmalloc(p_n);
956
957 if (getgrnam_r(name, &grbuf, g_buf, (size_t) g_n, &gr) != 0 || !gr)
958 goto finish;
959
960 r = 0;
961 for (i = gr->gr_mem; *i; i++) {
962 struct passwd pwbuf, *pw;
963
964 if (getpwnam_r(*i, &pwbuf, p_buf, (size_t) p_n, &pw) != 0 || !pw)
965 continue;
966
967 if (pw->pw_uid == uid) {
968 r = 1;
969 break;
970 }
971 }
972
973 finish:
974 pa_xfree(g_buf);
975 pa_xfree(p_buf);
976
977 return r;
978 }
979
980 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
981 gid_t pa_get_gid_of_group(const char *name) {
982 gid_t ret = (gid_t) -1;
983 char *g_buf;
984 long g_n;
985 struct group grbuf, *gr;
986
987 g_n = sysconf(_SC_GETGR_R_SIZE_MAX);
988 g_buf = pa_xmalloc(g_n);
989
990 if (getgrnam_r(name, &grbuf, g_buf, (size_t) g_n, &gr) != 0 || !gr)
991 goto finish;
992
993 ret = gr->gr_gid;
994
995 finish:
996 pa_xfree(g_buf);
997 return ret;
998 }
999
1000 int pa_check_in_group(gid_t g) {
1001 gid_t gids[NGROUPS_MAX];
1002 int r;
1003
1004 if ((r = getgroups(NGROUPS_MAX, gids)) < 0)
1005 return -1;
1006
1007 for (; r > 0; r--)
1008 if (gids[r-1] == g)
1009 return 1;
1010
1011 return 0;
1012 }
1013
1014 #else /* HAVE_GRP_H */
1015
1016 int pa_own_uid_in_group(const char *name, gid_t *gid) {
1017 return -1;
1018
1019 }
1020
1021 int pa_uid_in_group(uid_t uid, const char *name) {
1022 return -1;
1023 }
1024
1025 gid_t pa_get_gid_of_group(const char *name) {
1026 return (gid_t) -1;
1027 }
1028
1029 int pa_check_in_group(gid_t g) {
1030 return -1;
1031 }
1032
1033 #endif
1034
1035 /* Lock or unlock a file entirely.
1036 (advisory on UNIX, mandatory on Windows) */
1037 int pa_lock_fd(int fd, int b) {
1038 #ifdef F_SETLKW
1039 struct flock flock;
1040
1041 /* Try a R/W lock first */
1042
1043 flock.l_type = b ? F_WRLCK : F_UNLCK;
1044 flock.l_whence = SEEK_SET;
1045 flock.l_start = 0;
1046 flock.l_len = 0;
1047
1048 if (fcntl(fd, F_SETLKW, &flock) >= 0)
1049 return 0;
1050
1051 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1052 if (b && errno == EBADF) {
1053 flock.l_type = F_RDLCK;
1054 if (fcntl(fd, F_SETLKW, &flock) >= 0)
1055 return 0;
1056 }
1057
1058 pa_log("%slock: %s", !b? "un" : "", pa_cstrerror(errno));
1059 #endif
1060
1061 #ifdef OS_IS_WIN32
1062 HANDLE h = (HANDLE)_get_osfhandle(fd);
1063
1064 if (b && LockFile(h, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1065 return 0;
1066 if (!b && UnlockFile(h, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1067 return 0;
1068
1069 pa_log("%slock failed: 0x%08X", !b ? "un" : "", GetLastError());
1070 #endif
1071
1072 return -1;
1073 }
1074
1075 /* Remove trailing newlines from a string */
1076 char* pa_strip_nl(char *s) {
1077 pa_assert(s);
1078
1079 s[strcspn(s, "\r\n")] = 0;
1080 return s;
1081 }
1082
1083 /* Create a temporary lock file and lock it. */
1084 int pa_lock_lockfile(const char *fn) {
1085 int fd = -1;
1086 pa_assert(fn);
1087
1088 for (;;) {
1089 struct stat st;
1090
1091 if ((fd = open(fn, O_CREAT|O_RDWR
1092 #ifdef O_NOCTTY
1093 |O_NOCTTY
1094 #endif
1095 #ifdef O_NOFOLLOW
1096 |O_NOFOLLOW
1097 #endif
1098 , S_IRUSR|S_IWUSR)) < 0) {
1099 pa_log_warn("Failed to create lock file '%s': %s", fn, pa_cstrerror(errno));
1100 goto fail;
1101 }
1102
1103 if (pa_lock_fd(fd, 1) < 0) {
1104 pa_log_warn("Failed to lock file '%s'.", fn);
1105 goto fail;
1106 }
1107
1108 if (fstat(fd, &st) < 0) {
1109 pa_log_warn("Failed to fstat() file '%s': %s", fn, pa_cstrerror(errno));
1110 goto fail;
1111 }
1112
1113 /* Check wheter the file has been removed meanwhile. When yes,
1114 * restart this loop, otherwise, we're done */
1115 if (st.st_nlink >= 1)
1116 break;
1117
1118 if (pa_lock_fd(fd, 0) < 0) {
1119 pa_log_warn("Failed to unlock file '%s'.", fn);
1120 goto fail;
1121 }
1122
1123 if (pa_close(fd) < 0) {
1124 pa_log_warn("Failed to close file '%s': %s", fn, pa_cstrerror(errno));
1125 fd = -1;
1126 goto fail;
1127 }
1128
1129 fd = -1;
1130 }
1131
1132 return fd;
1133
1134 fail:
1135
1136 if (fd >= 0)
1137 pa_close(fd);
1138
1139 return -1;
1140 }
1141
1142 /* Unlock a temporary lcok file */
1143 int pa_unlock_lockfile(const char *fn, int fd) {
1144 int r = 0;
1145 pa_assert(fd >= 0);
1146
1147 if (fn) {
1148 if (unlink(fn) < 0) {
1149 pa_log_warn("Unable to remove lock file '%s': %s", fn, pa_cstrerror(errno));
1150 r = -1;
1151 }
1152 }
1153
1154 if (pa_lock_fd(fd, 0) < 0) {
1155 pa_log_warn("Failed to unlock file '%s'.", fn);
1156 r = -1;
1157 }
1158
1159 if (pa_close(fd) < 0) {
1160 pa_log_warn("Failed to close '%s': %s", fn, pa_cstrerror(errno));
1161 r = -1;
1162 }
1163
1164 return r;
1165 }
1166
1167 static char *get_dir(mode_t m, const char *env_name) {
1168 const char *e;
1169 char *d;
1170
1171 if ((e = getenv(env_name)))
1172 d = pa_xstrdup(e);
1173 else {
1174 char h[PATH_MAX];
1175 struct stat st;
1176
1177 if (!pa_get_home_dir(h, sizeof(h))) {
1178 pa_log_error("Failed to get home directory.");
1179 return NULL;
1180 }
1181
1182 if (stat(h, &st) < 0) {
1183 pa_log_error("Failed to stat home directory %s: %s", h, pa_cstrerror(errno));
1184 return NULL;
1185 }
1186
1187 if (st.st_uid != getuid()) {
1188 pa_log_error("Home directory %s not ours.", d);
1189 return NULL;
1190 }
1191
1192 d = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse", h);
1193 }
1194
1195 if (pa_make_secure_dir(d, m, (pid_t) -1, (pid_t) -1) < 0) {
1196 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1197 return NULL;
1198 }
1199
1200 return d;
1201 }
1202
1203 char *pa_get_runtime_dir(void) {
1204 return get_dir(pa_in_system_mode() ? 0755 : 0700, "PULSE_RUNTIME_PATH");
1205 }
1206
1207 char *pa_get_state_dir(void) {
1208 return get_dir(0700, "PULSE_STATE_PATH");
1209 }
1210
1211 /* Try to open a configuration file. If "env" is specified, open the
1212 * value of the specified environment variable. Otherwise look for a
1213 * file "local" in the home directory or a file "global" in global
1214 * file system. If "result" is non-NULL, a pointer to a newly
1215 * allocated buffer containing the used configuration file is
1216 * stored there.*/
1217 FILE *pa_open_config_file(const char *global, const char *local, const char *env, char **result) {
1218 const char *fn;
1219 #ifdef OS_IS_WIN32
1220 char buf[PATH_MAX];
1221
1222 if (!getenv(PULSE_ROOTENV))
1223 pa_set_root(NULL);
1224 #endif
1225
1226 if (env && (fn = getenv(env))) {
1227 FILE *f;
1228
1229 #ifdef OS_IS_WIN32
1230 if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
1231 return NULL;
1232 fn = buf;
1233 #endif
1234
1235 if ((f = fopen(fn, "r"))) {
1236 if (result)
1237 *result = pa_xstrdup(fn);
1238
1239 return f;
1240 }
1241
1242 pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
1243 return NULL;
1244 }
1245
1246 if (local) {
1247 const char *e;
1248 char *lfn;
1249 char h[PATH_MAX];
1250 FILE *f;
1251
1252 if ((e = getenv("PULSE_CONFIG_PATH")))
1253 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
1254 else if (pa_get_home_dir(h, sizeof(h)))
1255 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
1256
1257 #ifdef OS_IS_WIN32
1258 if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) {
1259 pa_xfree(lfn);
1260 return NULL;
1261 }
1262 fn = buf;
1263 #endif
1264
1265 if ((f = fopen(fn, "r"))) {
1266 if (result)
1267 *result = pa_xstrdup(fn);
1268
1269 pa_xfree(lfn);
1270 return f;
1271 }
1272
1273 if (errno != ENOENT) {
1274 pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
1275 pa_xfree(lfn);
1276 return NULL;
1277 }
1278
1279 pa_xfree(lfn);
1280 }
1281
1282 if (global) {
1283 FILE *f;
1284
1285 #ifdef OS_IS_WIN32
1286 if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
1287 return NULL;
1288 global = buf;
1289 #endif
1290
1291 if ((f = fopen(global, "r"))) {
1292
1293 if (result)
1294 *result = pa_xstrdup(global);
1295
1296 return f;
1297 }
1298 } else
1299 errno = ENOENT;
1300
1301 return NULL;
1302 }
1303
1304 char *pa_find_config_file(const char *global, const char *local, const char *env) {
1305 const char *fn;
1306 #ifdef OS_IS_WIN32
1307 char buf[PATH_MAX];
1308
1309 if (!getenv(PULSE_ROOTENV))
1310 pa_set_root(NULL);
1311 #endif
1312
1313 if (env && (fn = getenv(env))) {
1314 #ifdef OS_IS_WIN32
1315 if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
1316 return NULL;
1317 fn = buf;
1318 #endif
1319
1320 if (access(fn, R_OK) == 0)
1321 return pa_xstrdup(fn);
1322
1323 pa_log_warn("Failed to access configuration file '%s': %s", fn, pa_cstrerror(errno));
1324 return NULL;
1325 }
1326
1327 if (local) {
1328 const char *e;
1329 char *lfn;
1330 char h[PATH_MAX];
1331
1332 if ((e = getenv("PULSE_CONFIG_PATH")))
1333 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
1334 else if (pa_get_home_dir(h, sizeof(h)))
1335 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
1336
1337 #ifdef OS_IS_WIN32
1338 if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) {
1339 pa_xfree(lfn);
1340 return NULL;
1341 }
1342 fn = buf;
1343 #endif
1344
1345 if (access(fn, R_OK) == 0) {
1346 char *r = pa_xstrdup(fn);
1347 pa_xfree(lfn);
1348 return r;
1349 }
1350
1351 if (errno != ENOENT) {
1352 pa_log_warn("Failed to access configuration file '%s': %s", fn, pa_cstrerror(errno));
1353 pa_xfree(lfn);
1354 return NULL;
1355 }
1356
1357 pa_xfree(lfn);
1358 }
1359
1360 if (global) {
1361 #ifdef OS_IS_WIN32
1362 if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
1363 return NULL;
1364 global = buf;
1365 #endif
1366
1367 if (access(fn, R_OK) == 0)
1368 return pa_xstrdup(global);
1369 } else
1370 errno = ENOENT;
1371
1372 return NULL;
1373 }
1374
1375 /* Format the specified data as a hexademical string */
1376 char *pa_hexstr(const uint8_t* d, size_t dlength, char *s, size_t slength) {
1377 size_t i = 0, j = 0;
1378 const char hex[] = "0123456789abcdef";
1379
1380 pa_assert(d);
1381 pa_assert(s);
1382 pa_assert(slength > 0);
1383
1384 while (i < dlength && j+3 <= slength) {
1385 s[j++] = hex[*d >> 4];
1386 s[j++] = hex[*d & 0xF];
1387
1388 d++;
1389 i++;
1390 }
1391
1392 s[j < slength ? j : slength] = 0;
1393 return s;
1394 }
1395
1396 /* Convert a hexadecimal digit to a number or -1 if invalid */
1397 static int hexc(char c) {
1398 if (c >= '0' && c <= '9')
1399 return c - '0';
1400
1401 if (c >= 'A' && c <= 'F')
1402 return c - 'A' + 10;
1403
1404 if (c >= 'a' && c <= 'f')
1405 return c - 'a' + 10;
1406
1407 return -1;
1408 }
1409
1410 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1411 size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength) {
1412 size_t j = 0;
1413
1414 pa_assert(p);
1415 pa_assert(d);
1416
1417 while (j < dlength && *p) {
1418 int b;
1419
1420 if ((b = hexc(*(p++))) < 0)
1421 return (size_t) -1;
1422
1423 d[j] = (uint8_t) (b << 4);
1424
1425 if (!*p)
1426 return (size_t) -1;
1427
1428 if ((b = hexc(*(p++))) < 0)
1429 return (size_t) -1;
1430
1431 d[j] |= (uint8_t) b;
1432 j++;
1433 }
1434
1435 return j;
1436 }
1437
1438 /* Returns nonzero when *s starts with *pfx */
1439 pa_bool_t pa_startswith(const char *s, const char *pfx) {
1440 size_t l;
1441
1442 pa_assert(s);
1443 pa_assert(pfx);
1444
1445 l = strlen(pfx);
1446
1447 return strlen(s) >= l && strncmp(s, pfx, l) == 0;
1448 }
1449
1450 /* Returns nonzero when *s ends with *sfx */
1451 pa_bool_t pa_endswith(const char *s, const char *sfx) {
1452 size_t l1, l2;
1453
1454 pa_assert(s);
1455 pa_assert(sfx);
1456
1457 l1 = strlen(s);
1458 l2 = strlen(sfx);
1459
1460 return l1 >= l2 && strcmp(s+l1-l2, sfx) == 0;
1461 }
1462
1463 pa_bool_t pa_is_path_absolute(const char *fn) {
1464 pa_assert(fn);
1465
1466 #ifndef OS_IS_WIN32
1467 return *fn == '/';
1468 #else
1469 return strlen(fn) >= 3 && isalpha(fn[0]) && fn[1] == ':' && fn[2] == '\\';
1470 #endif
1471 }
1472
1473 char *pa_make_path_absolute(const char *p) {
1474 char *r;
1475 char *cwd;
1476
1477 pa_assert(p);
1478
1479 if (pa_is_path_absolute(p))
1480 return pa_xstrdup(p);
1481
1482 if (!(cwd = pa_getcwd()))
1483 return pa_xstrdup(p);
1484
1485 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", cwd, p);
1486 pa_xfree(cwd);
1487 return r;
1488 }
1489
1490 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1491 * if fn is non-null and starts with / return fn
1492 * otherwise append fn to the run time path and return it */
1493 static char *get_path(const char *fn, pa_bool_t rt) {
1494 char *rtp;
1495
1496 if (pa_is_path_absolute(fn))
1497 return pa_xstrdup(fn);
1498
1499 rtp = rt ? pa_get_runtime_dir() : pa_get_state_dir();
1500
1501 if (!rtp)
1502 return NULL;
1503
1504 if (fn) {
1505 char *r;
1506 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", rtp, fn);
1507 pa_xfree(rtp);
1508 return r;
1509 } else
1510 return rtp;
1511 }
1512
1513 char *pa_runtime_path(const char *fn) {
1514 return get_path(fn, 1);
1515 }
1516
1517 char *pa_state_path(const char *fn) {
1518 return get_path(fn, 0);
1519 }
1520
1521 /* Convert the string s to a signed integer in *ret_i */
1522 int pa_atoi(const char *s, int32_t *ret_i) {
1523 char *x = NULL;
1524 long l;
1525
1526 pa_assert(s);
1527 pa_assert(ret_i);
1528
1529 errno = 0;
1530 l = strtol(s, &x, 0);
1531
1532 if (!x || *x || errno != 0)
1533 return -1;
1534
1535 if ((int32_t) l != l)
1536 return -1;
1537
1538 *ret_i = (int32_t) l;
1539
1540 return 0;
1541 }
1542
1543 /* Convert the string s to an unsigned integer in *ret_u */
1544 int pa_atou(const char *s, uint32_t *ret_u) {
1545 char *x = NULL;
1546 unsigned long l;
1547
1548 pa_assert(s);
1549 pa_assert(ret_u);
1550
1551 errno = 0;
1552 l = strtoul(s, &x, 0);
1553
1554 if (!x || *x || errno != 0)
1555 return -1;
1556
1557 if ((uint32_t) l != l)
1558 return -1;
1559
1560 *ret_u = (uint32_t) l;
1561
1562 return 0;
1563 }
1564
1565 #ifdef HAVE_STRTOF_L
1566 static locale_t c_locale = NULL;
1567
1568 static void c_locale_destroy(void) {
1569 freelocale(c_locale);
1570 }
1571 #endif
1572
1573 int pa_atod(const char *s, double *ret_d) {
1574 char *x = NULL;
1575 double f;
1576 int r = 0;
1577
1578 pa_assert(s);
1579 pa_assert(ret_d);
1580
1581 /* This should be locale independent */
1582
1583 #ifdef HAVE_STRTOF_L
1584
1585 PA_ONCE_BEGIN {
1586
1587 if ((c_locale = newlocale(LC_ALL_MASK, "C", NULL)))
1588 atexit(c_locale_destroy);
1589
1590 } PA_ONCE_END;
1591
1592 if (c_locale) {
1593 errno = 0;
1594 f = strtod_l(s, &x, c_locale);
1595 } else
1596 #endif
1597 {
1598 errno = 0;
1599 f = strtod(s, &x);
1600 }
1601
1602 if (!x || *x || errno != 0)
1603 r = -1;
1604 else
1605 *ret_d = f;
1606
1607 return r;
1608 }
1609
1610 /* Same as snprintf, but guarantees NUL-termination on every platform */
1611 int pa_snprintf(char *str, size_t size, const char *format, ...) {
1612 int ret;
1613 va_list ap;
1614
1615 pa_assert(str);
1616 pa_assert(size > 0);
1617 pa_assert(format);
1618
1619 va_start(ap, format);
1620 ret = pa_vsnprintf(str, size, format, ap);
1621 va_end(ap);
1622
1623 return ret;
1624 }
1625
1626 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
1627 int pa_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
1628 int ret;
1629
1630 pa_assert(str);
1631 pa_assert(size > 0);
1632 pa_assert(format);
1633
1634 ret = vsnprintf(str, size, format, ap);
1635
1636 str[size-1] = 0;
1637
1638 if (ret < 0)
1639 ret = strlen(str);
1640
1641 return PA_MIN((int) size-1, ret);
1642 }
1643
1644 /* Truncate the specified string, but guarantee that the string
1645 * returned still validates as UTF8 */
1646 char *pa_truncate_utf8(char *c, size_t l) {
1647 pa_assert(c);
1648 pa_assert(pa_utf8_valid(c));
1649
1650 if (strlen(c) <= l)
1651 return c;
1652
1653 c[l] = 0;
1654
1655 while (l > 0 && !pa_utf8_valid(c))
1656 c[--l] = 0;
1657
1658 return c;
1659 }
1660
1661 char *pa_getcwd(void) {
1662 size_t l = 128;
1663
1664 for (;;) {
1665 char *p = pa_xnew(char, l);
1666 if (getcwd(p, l))
1667 return p;
1668
1669 if (errno != ERANGE)
1670 return NULL;
1671
1672 pa_xfree(p);
1673 l *= 2;
1674 }
1675 }
1676
1677 void *pa_will_need(const void *p, size_t l) {
1678 #ifdef RLIMIT_MEMLOCK
1679 struct rlimit rlim;
1680 #endif
1681 const void *a;
1682 size_t size;
1683 int r;
1684 size_t bs;
1685
1686 pa_assert(p);
1687 pa_assert(l > 0);
1688
1689 a = PA_PAGE_ALIGN_PTR(p);
1690 size = (const uint8_t*) p + l - (const uint8_t*) a;
1691
1692 #ifdef HAVE_POSIX_MADVISE
1693 if ((r = posix_madvise((void*) a, size, POSIX_MADV_WILLNEED)) == 0) {
1694 pa_log_debug("posix_madvise() worked fine!");
1695 return (void*) p;
1696 }
1697 #endif
1698
1699 /* Most likely the memory was not mmap()ed from a file and thus
1700 * madvise() didn't work, so let's misuse mlock() do page this
1701 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
1702 * inviting, the man page of mlock() tells us: "All pages that
1703 * contain a part of the specified address range are guaranteed to
1704 * be resident in RAM when the call returns successfully." */
1705
1706 #ifdef RLIMIT_MEMLOCK
1707 pa_assert_se(getrlimit(RLIMIT_MEMLOCK, &rlim) == 0);
1708
1709 if (rlim.rlim_cur < PA_PAGE_SIZE) {
1710 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));
1711 return (void*) p;
1712 }
1713
1714 bs = PA_PAGE_ALIGN(rlim.rlim_cur);
1715 #else
1716 bs = PA_PAGE_SIZE*4;
1717 #endif
1718
1719 pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r));
1720
1721 #ifdef HAVE_MLOCK
1722 while (size > 0 && bs > 0) {
1723
1724 if (bs > size)
1725 bs = size;
1726
1727 if (mlock(a, bs) < 0) {
1728 bs = PA_PAGE_ALIGN(bs / 2);
1729 continue;
1730 }
1731
1732 pa_assert_se(munlock(a, bs) == 0);
1733
1734 a = (const uint8_t*) a + bs;
1735 size -= bs;
1736 }
1737 #endif
1738
1739 if (bs <= 0)
1740 pa_log_debug("mlock() failed too (or doesn't exist), giving up: %s", pa_cstrerror(errno));
1741 else
1742 pa_log_debug("mlock() worked fine!");
1743
1744 return (void*) p;
1745 }
1746
1747 void pa_close_pipe(int fds[2]) {
1748 pa_assert(fds);
1749
1750 if (fds[0] >= 0)
1751 pa_assert_se(pa_close(fds[0]) == 0);
1752
1753 if (fds[1] >= 0)
1754 pa_assert_se(pa_close(fds[1]) == 0);
1755
1756 fds[0] = fds[1] = -1;
1757 }
1758
1759 char *pa_readlink(const char *p) {
1760 size_t l = 100;
1761
1762 for (;;) {
1763 char *c;
1764 ssize_t n;
1765
1766 c = pa_xnew(char, l);
1767
1768 if ((n = readlink(p, c, l-1)) < 0) {
1769 pa_xfree(c);
1770 return NULL;
1771 }
1772
1773 if ((size_t) n < l-1) {
1774 c[n] = 0;
1775 return c;
1776 }
1777
1778 pa_xfree(c);
1779 l *= 2;
1780 }
1781 }
1782
1783 int pa_close_all(int except_fd, ...) {
1784 va_list ap;
1785 int n = 0, i, r;
1786 int *p;
1787
1788 va_start(ap, except_fd);
1789
1790 if (except_fd >= 0)
1791 for (n = 1; va_arg(ap, int) >= 0; n++)
1792 ;
1793
1794 va_end(ap);
1795
1796 p = pa_xnew(int, n+1);
1797
1798 va_start(ap, except_fd);
1799
1800 i = 0;
1801 if (except_fd >= 0) {
1802 int fd;
1803 p[i++] = except_fd;
1804
1805 while ((fd = va_arg(ap, int)) >= 0)
1806 p[i++] = fd;
1807 }
1808 p[i] = -1;
1809
1810 va_end(ap);
1811
1812 r = pa_close_allv(p);
1813 free(p);
1814
1815 return r;
1816 }
1817
1818 int pa_close_allv(const int except_fds[]) {
1819 struct rlimit rl;
1820 int fd;
1821 int saved_errno;
1822
1823 #ifdef __linux__
1824
1825 DIR *d;
1826
1827 if ((d = opendir("/proc/self/fd"))) {
1828
1829 struct dirent *de;
1830
1831 while ((de = readdir(d))) {
1832 pa_bool_t found;
1833 long l;
1834 char *e = NULL;
1835 int i;
1836
1837 if (de->d_name[0] == '.')
1838 continue;
1839
1840 errno = 0;
1841 l = strtol(de->d_name, &e, 10);
1842 if (errno != 0 || !e || *e) {
1843 closedir(d);
1844 errno = EINVAL;
1845 return -1;
1846 }
1847
1848 fd = (int) l;
1849
1850 if ((long) fd != l) {
1851 closedir(d);
1852 errno = EINVAL;
1853 return -1;
1854 }
1855
1856 if (fd < 3)
1857 continue;
1858
1859 if (fd == dirfd(d))
1860 continue;
1861
1862 found = FALSE;
1863 for (i = 0; except_fds[i] >= 0; i++)
1864 if (except_fds[i] == fd) {
1865 found = TRUE;
1866 break;
1867 }
1868
1869 if (found)
1870 continue;
1871
1872 if (pa_close(fd) < 0) {
1873 saved_errno = errno;
1874 closedir(d);
1875 errno = saved_errno;
1876
1877 return -1;
1878 }
1879 }
1880
1881 closedir(d);
1882 return 0;
1883 }
1884
1885 #endif
1886
1887 if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
1888 return -1;
1889
1890 for (fd = 3; fd < (int) rl.rlim_max; fd++) {
1891 int i;
1892 pa_bool_t found;
1893
1894 found = FALSE;
1895 for (i = 0; except_fds[i] >= 0; i++)
1896 if (except_fds[i] == fd) {
1897 found = TRUE;
1898 break;
1899 }
1900
1901 if (found)
1902 continue;
1903
1904 if (pa_close(fd) < 0 && errno != EBADF)
1905 return -1;
1906 }
1907
1908 return 0;
1909 }
1910
1911 int pa_unblock_sigs(int except, ...) {
1912 va_list ap;
1913 int n = 0, i, r;
1914 int *p;
1915
1916 va_start(ap, except);
1917
1918 if (except >= 1)
1919 for (n = 1; va_arg(ap, int) >= 0; n++)
1920 ;
1921
1922 va_end(ap);
1923
1924 p = pa_xnew(int, n+1);
1925
1926 va_start(ap, except);
1927
1928 i = 0;
1929 if (except >= 1) {
1930 int sig;
1931 p[i++] = except;
1932
1933 while ((sig = va_arg(ap, int)) >= 0)
1934 p[i++] = sig;
1935 }
1936 p[i] = -1;
1937
1938 va_end(ap);
1939
1940 r = pa_unblock_sigsv(p);
1941 pa_xfree(p);
1942
1943 return r;
1944 }
1945
1946 int pa_unblock_sigsv(const int except[]) {
1947 int i;
1948 sigset_t ss;
1949
1950 if (sigemptyset(&ss) < 0)
1951 return -1;
1952
1953 for (i = 0; except[i] > 0; i++)
1954 if (sigaddset(&ss, except[i]) < 0)
1955 return -1;
1956
1957 return sigprocmask(SIG_SETMASK, &ss, NULL);
1958 }
1959
1960 int pa_reset_sigs(int except, ...) {
1961 va_list ap;
1962 int n = 0, i, r;
1963 int *p;
1964
1965 va_start(ap, except);
1966
1967 if (except >= 1)
1968 for (n = 1; va_arg(ap, int) >= 0; n++)
1969 ;
1970
1971 va_end(ap);
1972
1973 p = pa_xnew(int, n+1);
1974
1975 va_start(ap, except);
1976
1977 i = 0;
1978 if (except >= 1) {
1979 int sig;
1980 p[i++] = except;
1981
1982 while ((sig = va_arg(ap, int)) >= 0)
1983 sig = p[i++];
1984 }
1985 p[i] = -1;
1986
1987 va_end(ap);
1988
1989 r = pa_reset_sigsv(p);
1990 pa_xfree(p);
1991
1992 return r;
1993 }
1994
1995 int pa_reset_sigsv(const int except[]) {
1996 int sig;
1997
1998 for (sig = 1; sig < _NSIG; sig++) {
1999 pa_bool_t reset = TRUE;
2000
2001 switch (sig) {
2002 case SIGKILL:
2003 case SIGSTOP:
2004 reset = FALSE;
2005 break;
2006
2007 default: {
2008 int i;
2009
2010 for (i = 0; except[i] > 0; i++) {
2011 if (sig == except[i]) {
2012 reset = FALSE;
2013 break;
2014 }
2015 }
2016 }
2017 }
2018
2019 if (reset) {
2020 struct sigaction sa;
2021
2022 memset(&sa, 0, sizeof(sa));
2023 sa.sa_handler = SIG_DFL;
2024
2025 /* On Linux the first two RT signals are reserved by
2026 * glibc, and sigaction() will return EINVAL for them. */
2027 if ((sigaction(sig, &sa, NULL) < 0))
2028 if (errno != EINVAL)
2029 return -1;
2030 }
2031 }
2032
2033 return 0;
2034 }
2035
2036 void pa_set_env(const char *key, const char *value) {
2037 pa_assert(key);
2038 pa_assert(value);
2039
2040 putenv(pa_sprintf_malloc("%s=%s", key, value));
2041 }
2042
2043 pa_bool_t pa_in_system_mode(void) {
2044 const char *e;
2045
2046 if (!(e = getenv("PULSE_SYSTEM")))
2047 return FALSE;
2048
2049 return !!atoi(e);
2050 }