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