]>
code.delx.au - pulseaudio/blob - src/pulsecore/core-util.c
2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2004 Joe Marcus Clarke
6 Copyright 2006-2007 Pierre Ossman <ossman@cendio.se> for Cendio AB
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.
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.
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
39 #include <sys/types.h>
44 #ifdef HAVE_LANGINFO_H
49 #include <sys/utsname.h>
52 #if defined(HAVE_REGEX_H)
54 #elif defined(HAVE_PCREPOSIX_H)
55 #include <pcreposix.h>
65 #if defined(__linux__) && !defined(SCHED_RESET_ON_FORK)
66 #define SCHED_RESET_ON_FORK 0x40000000
70 #ifdef HAVE_SYS_RESOURCE_H
71 #include <sys/resource.h>
74 #ifdef HAVE_SYS_CAPABILITY_H
75 #include <sys/capability.h>
78 #ifdef HAVE_SYS_MMAN_H
102 #ifdef HAVE_LIBSAMPLERATE
103 #include <samplerate.h>
115 #include <sys/personality.h>
118 #include <pulse/xmalloc.h>
119 #include <pulse/util.h>
120 #include <pulse/utf8.h>
122 #include <pulsecore/core-error.h>
123 #include <pulsecore/socket.h>
124 #include <pulsecore/log.h>
125 #include <pulsecore/macro.h>
126 #include <pulsecore/thread.h>
127 #include <pulsecore/strbuf.h>
128 #include <pulsecore/usergroup.h>
129 #include <pulsecore/strlist.h>
130 #include <pulsecore/cpu-x86.h>
131 #include <pulsecore/pipe.h>
133 #include "core-util.h"
135 /* Not all platforms have this */
137 #define MSG_NOSIGNAL 0
140 #define NEWLINE " \r\n "
141 #define WHITESPACE " \n\r \t "
143 static pa_strlist
* recorded_env
= NULL
;
147 #define PULSE_ROOTENV "PULSE_ROOT"
149 int pa_set_root ( HANDLE handle
) {
150 char library_path
[ MAX_PATH
+ sizeof ( PULSE_ROOTENV
) + 1 ], * sep
;
152 strcpy ( library_path
, PULSE_ROOTENV
"=" );
154 /* FIXME: Needs to set errno */
156 if (! GetModuleFileName ( handle
, library_path
+ sizeof ( PULSE_ROOTENV
), MAX_PATH
))
159 sep
= strrchr ( library_path
, PA_PATH_SEP_CHAR
);
163 if ( _putenv ( library_path
) < 0 )
171 /** Make a file descriptor nonblock. Doesn't do any error checking */
172 void pa_make_fd_nonblock ( int fd
) {
178 pa_assert_se (( v
= fcntl ( fd
, F_GETFL
)) >= 0 );
180 if (!( v
& O_NONBLOCK
))
181 pa_assert_se ( fcntl ( fd
, F_SETFL
, v
| O_NONBLOCK
) >= 0 );
183 #elif defined(OS_IS_WIN32)
185 if ( ioctlsocket ( fd
, FIONBIO
, & arg
) < 0 ) {
186 pa_assert_se ( WSAGetLastError () == WSAENOTSOCK
);
187 pa_log_warn ( "Only sockets can be made non-blocking!" );
190 pa_log_warn ( "Non-blocking I/O not supported.!" );
195 /* Set the FD_CLOEXEC flag for a fd */
196 void pa_make_fd_cloexec ( int fd
) {
202 pa_assert_se (( v
= fcntl ( fd
, F_GETFD
, 0 )) >= 0 );
204 if (!( v
& FD_CLOEXEC
))
205 pa_assert_se ( fcntl ( fd
, F_SETFD
, v
| FD_CLOEXEC
) >= 0 );
210 /** Creates a directory securely */
211 int pa_make_secure_dir ( const char * dir
, mode_t m
, uid_t uid
, gid_t gid
) {
213 int r
, saved_errno
, fd
;
222 u
= umask ((~ m
) & 0777 );
228 if ( r
< 0 && errno
!= EEXIST
)
231 #if defined(HAVE_FSTAT) && !defined(OS_IS_WIN32)
245 if ( fstat ( fd
, & st
) < 0 ) {
246 pa_assert_se ( pa_close ( fd
) >= 0 );
250 if (! S_ISDIR ( st
. st_mode
)) {
251 pa_assert_se ( pa_close ( fd
) >= 0 );
257 if ( uid
== ( uid_t
)- 1 )
259 if ( gid
== ( gid_t
)- 1 )
261 ( void ) fchown ( fd
, uid
, gid
);
265 ( void ) fchmod ( fd
, m
);
268 pa_assert_se ( pa_close ( fd
) >= 0 );
272 if ( lstat ( dir
, & st
) < 0 )
274 if ( stat ( dir
, & st
) < 0 )
279 if (! S_ISDIR ( st
. st_mode
) ||
280 ( st
. st_uid
!= uid
) ||
281 ( st
. st_gid
!= gid
) ||
282 (( st
. st_mode
& 0777 ) != m
)) {
287 pa_log_warn ( "Secure directory creation not supported on Win32." );
300 /* Return a newly allocated sting containing the parent directory of the specified file */
301 char * pa_parent_dir ( const char * fn
) {
302 char * slash
, * dir
= pa_xstrdup ( fn
);
304 if (( slash
= ( char *) pa_path_get_filename ( dir
)) == dir
) {
314 /* Creates a the parent directory of the specified path securely */
315 int pa_make_secure_parent_dir ( const char * fn
, mode_t m
, uid_t uid
, gid_t gid
) {
319 if (!( dir
= pa_parent_dir ( fn
)))
322 if ( pa_make_secure_dir ( dir
, m
, uid
, gid
) < 0 )
332 /** Platform independent read function. Necessary since not all
333 * systems treat all file descriptors equal. If type is
334 * non-NULL it is used to cache the type of the fd. This is
335 * useful for making sure that only a single syscall is executed per
336 * function call. The variable pointed to should be initialized to 0
338 ssize_t
pa_read ( int fd
, void * buf
, size_t count
, int * type
) {
342 if (! type
|| * type
== 0 ) {
345 if (( r
= recv ( fd
, buf
, count
, 0 )) >= 0 )
348 if ( WSAGetLastError () != WSAENOTSOCK
) {
349 errno
= WSAGetLastError ();
362 if (( r
= read ( fd
, buf
, count
)) < 0 )
370 /** Similar to pa_read(), but handles writes */
371 ssize_t
pa_write ( int fd
, const void * buf
, size_t count
, int * type
) {
373 if (! type
|| * type
== 0 ) {
377 if (( r
= send ( fd
, buf
, count
, MSG_NOSIGNAL
)) < 0 ) {
389 if ( WSAGetLastError () != WSAENOTSOCK
) {
390 errno
= WSAGetLastError ();
394 if ( errno
!= ENOTSOCK
)
405 if (( r
= write ( fd
, buf
, count
)) < 0 )
413 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
414 * unless EOF is reached or an error occurred */
415 ssize_t
pa_loop_read ( int fd
, void * data
, size_t size
, int * type
) {
431 if (( r
= pa_read ( fd
, data
, size
, type
)) < 0 )
438 data
= ( uint8_t *) data
+ r
;
445 /** Similar to pa_loop_read(), but wraps write() */
446 ssize_t
pa_loop_write ( int fd
, const void * data
, size_t size
, int * type
) {
462 if (( r
= pa_write ( fd
, data
, size
, type
)) < 0 )
469 data
= ( const uint8_t *) data
+ r
;
476 /** Platform independent read function. Necessary since not all
477 * systems treat all file descriptors equal. */
478 int pa_close ( int fd
) {
483 if (( ret
= closesocket ( fd
)) == 0 )
486 if ( WSAGetLastError () != WSAENOTSOCK
) {
487 errno
= WSAGetLastError ();
495 if (( r
= close ( fd
)) < 0 )
503 /* Print a warning messages in case that the given signal is not
504 * blocked or trapped */
505 void pa_check_signal_is_blocked ( int sig
) {
506 #ifdef HAVE_SIGACTION
510 /* If POSIX threads are supported use thread-aware
511 * pthread_sigmask() function, to check if the signal is
512 * blocked. Otherwise fall back to sigprocmask() */
515 if ( pthread_sigmask ( SIG_SETMASK
, NULL
, & set
) < 0 ) {
517 if ( sigprocmask ( SIG_SETMASK
, NULL
, & set
) < 0 ) {
518 pa_log ( "sigprocmask(): %s" , pa_cstrerror ( errno
));
525 if ( sigismember (& set
, sig
))
528 /* Check whether the signal is trapped */
530 if ( sigaction ( sig
, NULL
, & sa
) < 0 ) {
531 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
535 if ( sa
. sa_handler
!= SIG_DFL
)
538 pa_log_warn ( "%s is not trapped. This might cause malfunction!" , pa_sig2str ( sig
));
539 #else /* HAVE_SIGACTION */
540 pa_log_warn ( "%s might not be trapped. This might cause malfunction!" , pa_sig2str ( sig
));
544 /* The following function is based on an example from the GNU libc
545 * documentation. This function is similar to GNU's asprintf(). */
546 char * pa_sprintf_malloc ( const char * format
, ...) {
556 c
= pa_xrealloc ( c
, size
);
558 va_start ( ap
, format
);
559 r
= vsnprintf ( c
, size
, format
, ap
);
564 if ( r
> - 1 && ( size_t ) r
< size
)
567 if ( r
> - 1 ) /* glibc 2.1 */
574 /* Same as the previous function, but use a va_list instead of an
576 char * pa_vsprintf_malloc ( const char * format
, va_list ap
) {
586 c
= pa_xrealloc ( c
, size
);
589 r
= vsnprintf ( c
, size
, format
, aq
);
594 if ( r
> - 1 && ( size_t ) r
< size
)
597 if ( r
> - 1 ) /* glibc 2.1 */
604 /* Similar to OpenBSD's strlcpy() function */
605 char * pa_strlcpy ( char * b
, const char * s
, size_t l
) {
623 static int set_scheduler ( int rtprio
) {
625 struct sched_param sp
;
631 dbus_error_init (& error
);
635 sp
. sched_priority
= rtprio
;
637 #ifdef SCHED_RESET_ON_FORK
638 if ( pthread_setschedparam ( pthread_self (), SCHED_RR
| SCHED_RESET_ON_FORK
, & sp
) == 0 ) {
639 pa_log_debug ( "SCHED_RR|SCHED_RESET_ON_FORK worked." );
644 if ( pthread_setschedparam ( pthread_self (), SCHED_RR
, & sp
) == 0 ) {
645 pa_log_debug ( "SCHED_RR worked." );
648 #endif /* HAVE_SCHED_H */
651 /* Try to talk to RealtimeKit */
653 if (!( bus
= dbus_bus_get ( DBUS_BUS_SYSTEM
, & error
))) {
654 pa_log ( "Failed to connect to system bus: %s \n " , error
. message
);
655 dbus_error_free (& error
);
660 /* We need to disable exit on disconnect because otherwise
661 * dbus_shutdown will kill us. See
662 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
663 dbus_connection_set_exit_on_disconnect ( bus
, FALSE
);
665 r
= rtkit_make_realtime ( bus
, 0 , rtprio
);
666 dbus_connection_unref ( bus
);
669 pa_log_debug ( "RealtimeKit worked." );
681 /* Make the current thread a realtime thread, and acquire the highest
682 * rtprio we can get that is less or equal the specified parameter. If
683 * the thread is already realtime, don't do anything. */
684 int pa_make_realtime ( int rtprio
) {
686 #ifdef _POSIX_PRIORITY_SCHEDULING
689 if ( set_scheduler ( rtprio
) >= 0 ) {
690 pa_log_info ( "Successfully enabled SCHED_RR scheduling for thread, with priority %i." , rtprio
);
694 for ( p
= rtprio
- 1 ; p
>= 1 ; p
--)
695 if ( set_scheduler ( p
) >= 0 ) {
696 pa_log_info ( "Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i." , p
, rtprio
);
700 pa_log_info ( "Failed to acquire real-time scheduling: %s" , pa_cstrerror ( errno
));
709 static int set_nice ( int nice_level
) {
715 dbus_error_init (& error
);
718 #ifdef HAVE_SYS_RESOURCE_H
719 if ( setpriority ( PRIO_PROCESS
, 0 , nice_level
) >= 0 ) {
720 pa_log_debug ( "setpriority() worked." );
726 /* Try to talk to RealtimeKit */
728 if (!( bus
= dbus_bus_get ( DBUS_BUS_SYSTEM
, & error
))) {
729 pa_log ( "Failed to connect to system bus: %s \n " , error
. message
);
730 dbus_error_free (& error
);
735 /* We need to disable exit on disconnect because otherwise
736 * dbus_shutdown will kill us. See
737 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
738 dbus_connection_set_exit_on_disconnect ( bus
, FALSE
);
740 r
= rtkit_make_high_priority ( bus
, 0 , nice_level
);
741 dbus_connection_unref ( bus
);
744 pa_log_debug ( "RealtimeKit worked." );
754 /* Raise the priority of the current process as much as possible that
755 * is <= the specified nice level..*/
756 int pa_raise_priority ( int nice_level
) {
758 #ifdef HAVE_SYS_RESOURCE_H
761 if ( set_nice ( nice_level
) >= 0 ) {
762 pa_log_info ( "Successfully gained nice level %i." , nice_level
);
766 for ( n
= nice_level
+ 1 ; n
< 0 ; n
++)
767 if ( set_nice ( n
) >= 0 ) {
768 pa_log_info ( "Successfully acquired nice level %i, which is lower than the requested %i." , n
, nice_level
);
772 pa_log_info ( "Failed to acquire high-priority scheduling: %s" , pa_cstrerror ( errno
));
777 if ( nice_level
< 0 ) {
778 if (! SetPriorityClass ( GetCurrentProcess (), HIGH_PRIORITY_CLASS
)) {
779 pa_log_warn ( "SetPriorityClass() failed: 0x%08X" , GetLastError ());
784 pa_log_info ( "Successfully gained high priority class." );
791 /* Reset the priority to normal, inverting the changes made by
792 * pa_raise_priority() and pa_make_realtime()*/
793 void pa_reset_priority ( void ) {
794 #ifdef HAVE_SYS_RESOURCE_H
795 struct sched_param sp
;
797 setpriority ( PRIO_PROCESS
, 0 , 0 );
800 pthread_setschedparam ( pthread_self (), SCHED_OTHER
, & sp
);
804 SetPriorityClass ( GetCurrentProcess (), NORMAL_PRIORITY_CLASS
);
808 int pa_match ( const char * expr
, const char * v
) {
813 if ( regcomp (& re
, expr
, REG_NOSUB
| REG_EXTENDED
) != 0 ) {
818 if (( k
= regexec (& re
, v
, 0 , NULL
, 0 )) == 0 )
820 else if ( k
== REG_NOMATCH
)
833 /* Try to parse a boolean string value.*/
834 int pa_parse_boolean ( const char * v
) {
838 /* First we check language independant */
839 if (! strcmp ( v
, "1" ) || v
[ 0 ] == 'y' || v
[ 0 ] == 'Y' || v
[ 0 ] == 't' || v
[ 0 ] == 'T' || ! strcasecmp ( v
, "on" ))
841 else if (! strcmp ( v
, "0" ) || v
[ 0 ] == 'n' || v
[ 0 ] == 'N' || v
[ 0 ] == 'f' || v
[ 0 ] == 'F' || ! strcasecmp ( v
, "off" ))
844 #ifdef HAVE_LANGINFO_H
845 /* And then we check language dependant */
846 if (( expr
= nl_langinfo ( YESEXPR
)))
848 if ( pa_match ( expr
, v
) > 0 )
851 if (( expr
= nl_langinfo ( NOEXPR
)))
853 if ( pa_match ( expr
, v
) > 0 )
861 /* Split the specified string wherever one of the strings in delimiter
862 * occurs. Each time it is called returns a newly allocated string
863 * with pa_xmalloc(). The variable state points to, should be
864 * initiallized to NULL before the first call. */
865 char * pa_split ( const char * c
, const char * delimiter
, const char ** state
) {
866 const char * current
= * state
? * state
: c
;
872 l
= strcspn ( current
, delimiter
);
878 return pa_xstrndup ( current
, l
);
881 /* Split a string into words. Otherwise similar to pa_split(). */
882 char * pa_split_spaces ( const char * c
, const char ** state
) {
883 const char * current
= * state
? * state
: c
;
886 if (!* current
|| * c
== 0 )
889 current
+= strspn ( current
, WHITESPACE
);
890 l
= strcspn ( current
, WHITESPACE
);
894 return pa_xstrndup ( current
, l
);
897 PA_STATIC_TLS_DECLARE ( signame
, pa_xfree
);
899 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
900 const char * pa_sig2str ( int sig
) {
913 char buf
[ SIG2STR_MAX
];
915 if ( sig2str ( sig
, buf
) == 0 ) {
916 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
917 t
= pa_sprintf_malloc ( "SIG%s" , buf
);
918 PA_STATIC_TLS_SET ( signame
, t
);
926 case SIGHUP
: return "SIGHUP" ;
928 case SIGINT
: return "SIGINT" ;
930 case SIGQUIT
: return "SIGQUIT" ;
932 case SIGILL
: return "SIGULL" ;
934 case SIGTRAP
: return "SIGTRAP" ;
936 case SIGABRT
: return "SIGABRT" ;
938 case SIGBUS
: return "SIGBUS" ;
940 case SIGFPE
: return "SIGFPE" ;
942 case SIGKILL
: return "SIGKILL" ;
945 case SIGUSR1
: return "SIGUSR1" ;
947 case SIGSEGV
: return "SIGSEGV" ;
949 case SIGUSR2
: return "SIGUSR2" ;
952 case SIGPIPE
: return "SIGPIPE" ;
955 case SIGALRM
: return "SIGALRM" ;
957 case SIGTERM
: return "SIGTERM" ;
959 case SIGSTKFLT
: return "SIGSTKFLT" ;
962 case SIGCHLD
: return "SIGCHLD" ;
965 case SIGCONT
: return "SIGCONT" ;
968 case SIGSTOP
: return "SIGSTOP" ;
971 case SIGTSTP
: return "SIGTSTP" ;
974 case SIGTTIN
: return "SIGTTIN" ;
977 case SIGTTOU
: return "SIGTTOU" ;
980 case SIGURG
: return "SIGURG" ;
983 case SIGXCPU
: return "SIGXCPU" ;
986 case SIGXFSZ
: return "SIGXFSZ" ;
989 case SIGVTALRM
: return "SIGVTALRM" ;
992 case SIGPROF
: return "SIGPROF" ;
995 case SIGWINCH
: return "SIGWINCH" ;
998 case SIGIO
: return "SIGIO" ;
1001 case SIGPWR
: return "SIGPWR" ;
1004 case SIGSYS
: return "SIGSYS" ;
1009 if ( sig
>= SIGRTMIN
&& sig
<= SIGRTMAX
) {
1010 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
1011 t
= pa_sprintf_malloc ( "SIGRTMIN+%i" , sig
- SIGRTMIN
);
1012 PA_STATIC_TLS_SET ( signame
, t
);
1021 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
1022 t
= pa_sprintf_malloc ( "SIG%i" , sig
);
1023 PA_STATIC_TLS_SET ( signame
, t
);
1029 /* Check whether the specified GID and the group name match */
1030 static int is_group ( gid_t gid
, const char * name
) {
1031 struct group
* group
= NULL
;
1035 if (!( group
= pa_getgrgid_malloc ( gid
)))
1040 pa_log ( "pa_getgrgid_malloc(%u): %s" , gid
, pa_cstrerror ( errno
));
1045 r
= strcmp ( name
, group
-> gr_name
) == 0 ;
1048 pa_getgrgid_free ( group
);
1053 /* Check the current user is member of the specified group */
1054 int pa_own_uid_in_group ( const char * name
, gid_t
* gid
) {
1055 GETGROUPS_T
* gids
, tgid
;
1056 long n
= sysconf ( _SC_NGROUPS_MAX
);
1061 gids
= pa_xmalloc ( sizeof ( GETGROUPS_T
) * ( size_t ) n
);
1063 if (( n
= getgroups (( int ) n
, gids
)) < 0 ) {
1064 pa_log ( "getgroups(): %s" , pa_cstrerror ( errno
));
1068 for ( i
= 0 ; i
< n
; i
++) {
1070 if (( k
= is_group ( gids
[ i
], name
)) < 0 )
1079 if (( k
= is_group ( tgid
= getgid (), name
)) < 0 )
1095 /* Check whether the specifc user id is a member of the specified group */
1096 int pa_uid_in_group ( uid_t uid
, const char * name
) {
1097 struct group
* group
= NULL
;
1102 if (!( group
= pa_getgrnam_malloc ( name
)))
1110 for ( i
= group
-> gr_mem
; * i
; i
++) {
1111 struct passwd
* pw
= NULL
;
1114 if (!( pw
= pa_getpwnam_malloc (* i
)))
1117 if ( pw
-> pw_uid
== uid
)
1120 pa_getpwnam_free ( pw
);
1127 pa_getgrnam_free ( group
);
1132 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
1133 gid_t
pa_get_gid_of_group ( const char * name
) {
1134 gid_t ret
= ( gid_t
) - 1 ;
1135 struct group
* gr
= NULL
;
1138 if (!( gr
= pa_getgrnam_malloc ( name
)))
1148 pa_getgrnam_free ( gr
);
1152 int pa_check_in_group ( gid_t g
) {
1153 gid_t gids
[ NGROUPS_MAX
];
1156 if (( r
= getgroups ( NGROUPS_MAX
, gids
)) < 0 )
1166 #else /* HAVE_GRP_H */
1168 int pa_own_uid_in_group ( const char * name
, gid_t
* gid
) {
1174 int pa_uid_in_group ( uid_t uid
, const char * name
) {
1179 gid_t
pa_get_gid_of_group ( const char * name
) {
1184 int pa_check_in_group ( gid_t g
) {
1191 /* Lock or unlock a file entirely.
1192 (advisory on UNIX, mandatory on Windows) */
1193 int pa_lock_fd ( int fd
, int b
) {
1195 struct flock f_lock
;
1197 /* Try a R/W lock first */
1199 f_lock
. l_type
= ( short ) ( b
? F_WRLCK
: F_UNLCK
);
1200 f_lock
. l_whence
= SEEK_SET
;
1204 if ( fcntl ( fd
, F_SETLKW
, & f_lock
) >= 0 )
1207 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1208 if ( b
&& errno
== EBADF
) {
1209 f_lock
. l_type
= F_RDLCK
;
1210 if ( fcntl ( fd
, F_SETLKW
, & f_lock
) >= 0 )
1214 pa_log ( "%slock: %s" , ! b
? "un" : "" , pa_cstrerror ( errno
));
1218 HANDLE h
= ( HANDLE
) _get_osfhandle ( fd
);
1220 if ( b
&& LockFile ( h
, 0 , 0 , 0xFFFFFFFF , 0xFFFFFFFF ))
1222 if (! b
&& UnlockFile ( h
, 0 , 0 , 0xFFFFFFFF , 0xFFFFFFFF ))
1225 pa_log ( "%slock failed: 0x%08X" , ! b
? "un" : "" , GetLastError ());
1227 /* FIXME: Needs to set errno! */
1233 /* Remove trailing newlines from a string */
1234 char * pa_strip_nl ( char * s
) {
1237 s
[ strcspn ( s
, NEWLINE
)] = 0 ;
1241 char * pa_strip ( char * s
) {
1244 /* Drops trailing whitespace. Modifies the string in
1245 * place. Returns pointer to first non-space character */
1247 s
+= strspn ( s
, WHITESPACE
);
1249 for ( e
= s
; * e
; e
++)
1250 if (! strchr ( WHITESPACE
, * e
))
1261 /* Create a temporary lock file and lock it. */
1262 int pa_lock_lockfile ( const char * fn
) {
1269 if (( fd
= pa_open_cloexec ( fn
, O_CREAT
| O_RDWR
1273 , S_IRUSR
| S_IWUSR
)) < 0 ) {
1274 pa_log_warn ( "Failed to create lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1278 if ( pa_lock_fd ( fd
, 1 ) < 0 ) {
1279 pa_log_warn ( "Failed to lock file '%s'." , fn
);
1283 if ( fstat ( fd
, & st
) < 0 ) {
1284 pa_log_warn ( "Failed to fstat() file '%s': %s" , fn
, pa_cstrerror ( errno
));
1288 /* Check whether the file has been removed meanwhile. When yes,
1289 * restart this loop, otherwise, we're done */
1290 if ( st
. st_nlink
>= 1 )
1293 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1294 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1298 if ( pa_close ( fd
) < 0 ) {
1299 pa_log_warn ( "Failed to close file '%s': %s" , fn
, pa_cstrerror ( errno
));
1310 int saved_errno
= errno
;
1312 errno
= saved_errno
;
1318 /* Unlock a temporary lcok file */
1319 int pa_unlock_lockfile ( const char * fn
, int fd
) {
1324 if ( unlink ( fn
) < 0 ) {
1325 pa_log_warn ( "Unable to remove lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1330 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1331 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1335 if ( pa_close ( fd
) < 0 ) {
1336 pa_log_warn ( "Failed to close '%s': %s" , fn
, pa_cstrerror ( errno
));
1343 static char * get_pulse_home ( void ) {
1348 if (!( h
= pa_get_home_dir_malloc ())) {
1349 pa_log_error ( "Failed to get home directory." );
1353 if ( stat ( h
, & st
) < 0 ) {
1354 pa_log_error ( "Failed to stat home directory %s: %s" , h
, pa_cstrerror ( errno
));
1359 if ( st
. st_uid
!= getuid ()) {
1360 pa_log_error ( "Home directory %s not ours." , h
);
1366 ret
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" , h
);
1374 char * pa_get_state_dir ( void ) {
1377 /* The state directory shall contain dynamic data that should be
1378 * kept across reboots, and is private to this user */
1380 if (!( d
= pa_xstrdup ( getenv ( "PULSE_STATE_PATH" ))))
1381 if (!( d
= get_pulse_home ()))
1384 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1385 * dir then this will break. */
1387 if ( pa_make_secure_dir ( d
, 0700U , ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1388 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1396 char * pa_get_home_dir_malloc ( void ) {
1398 size_t allocated
= 128 ;
1401 homedir
= pa_xmalloc ( allocated
);
1403 if (! pa_get_home_dir ( homedir
, allocated
)) {
1408 if ( strlen ( homedir
) < allocated
- 1 )
1418 char * pa_get_binary_name_malloc ( void ) {
1420 size_t allocated
= 128 ;
1423 t
= pa_xmalloc ( allocated
);
1425 if (! pa_get_binary_name ( t
, allocated
)) {
1430 if ( strlen ( t
) < allocated
- 1 )
1440 static char * make_random_dir ( mode_t m
) {
1441 static const char table
[] =
1442 "abcdefghijklmnopqrstuvwxyz"
1443 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1449 fn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"pulse-XXXXXXXXXXXX" , pa_get_temp_dir ());
1450 pathlen
= strlen ( fn
);
1458 for ( i
= pathlen
- 12 ; i
< pathlen
; i
++)
1459 fn
[ i
] = table
[ rand () % ( sizeof ( table
)- 1 )];
1461 u
= umask ((~ m
) & 0777 );
1468 saved_errno
= errno
;
1470 errno
= saved_errno
;
1475 if ( errno
!= EEXIST
) {
1476 pa_log_error ( "Failed to create random directory %s: %s" , fn
, pa_cstrerror ( errno
));
1483 static int make_random_dir_and_link ( mode_t m
, const char * k
) {
1486 if (!( p
= make_random_dir ( m
)))
1490 if ( symlink ( p
, k
) < 0 ) {
1491 int saved_errno
= errno
;
1493 if ( errno
!= EEXIST
)
1494 pa_log_error ( "Failed to symlink %s to %s: %s" , k
, p
, pa_cstrerror ( errno
));
1499 errno
= saved_errno
;
1508 char * pa_get_runtime_dir ( void ) {
1509 char * d
, * k
= NULL
, * p
= NULL
, * t
= NULL
, * mid
;
1513 /* The runtime directory shall contain dynamic data that needs NOT
1514 * to be kept accross reboots and is usuallly private to the user,
1515 * except in system mode, where it might be accessible by other
1516 * users, too. Since we need POSIX locking and UNIX sockets in
1517 * this directory, we link it to a random subdir in /tmp, if it
1518 * was not explicitly configured. */
1520 m
= pa_in_system_mode () ? 0755U : 0700U ;
1522 if (( d
= getenv ( "PULSE_RUNTIME_PATH" ))) {
1524 if ( pa_make_secure_dir ( d
, m
, ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1525 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1529 return pa_xstrdup ( d
);
1532 if (!( d
= get_pulse_home ()))
1535 if ( pa_make_secure_dir ( d
, m
, ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1536 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1541 if (!( mid
= pa_machine_id ())) {
1546 k
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s-runtime" , d
, mid
);
1551 /* OK, first let's check if the "runtime" symlink is already
1554 if (!( p
= pa_readlink ( k
))) {
1556 if ( errno
!= ENOENT
) {
1557 pa_log_error ( "Failed to stat runtime directory %s: %s" , k
, pa_cstrerror ( errno
));
1561 /* Hmm, so the runtime directory didn't exist yet, so let's
1562 * create one in /tmp and symlink that to it */
1564 if ( make_random_dir_and_link ( 0700 , k
) < 0 ) {
1566 /* Mhmm, maybe another process was quicker than us,
1567 * let's check if that was valid */
1568 if ( errno
== EEXIST
)
1577 /* Make sure that this actually makes sense */
1578 if (! pa_is_path_absolute ( p
)) {
1579 pa_log_error ( "Path %s in link %s is not absolute." , p
, k
);
1584 /* Hmm, so this symlink is still around, make sure nobody fools
1588 if ( lstat ( p
, & st
) < 0 ) {
1590 if ( errno
!= ENOENT
) {
1591 pa_log_error ( "Failed to stat runtime directory %s: %s" , p
, pa_cstrerror ( errno
));
1597 if ( S_ISDIR ( st
. st_mode
) &&
1598 ( st
. st_uid
== getuid ()) &&
1599 (( st
. st_mode
& 0777 ) == 0700 )) {
1605 pa_log_info ( "Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory." );
1612 /* Hmm, so the link points to some nonexisting or invalid
1613 * dir. Let's replace it by a new link. We first create a
1614 * temporary link and then rename that to allow concurrent
1615 * execution of this function. */
1617 t
= pa_sprintf_malloc ( "%s.tmp" , k
);
1619 if ( make_random_dir_and_link ( 0700 , t
) < 0 ) {
1621 if ( errno
!= EEXIST
) {
1622 pa_log_error ( "Failed to symlink %s: %s" , t
, pa_cstrerror ( errno
));
1629 /* Hmm, someone lese was quicker then us. Let's give
1630 * him some time to finish, and retry. */
1635 /* OK, we succeeded in creating the temporary symlink, so
1636 * let's rename it */
1637 if ( rename ( t
, k
) < 0 ) {
1638 pa_log_error ( "Failed to rename %s to %s: %s" , t
, k
, pa_cstrerror ( errno
));
1654 /* Try to open a configuration file. If "env" is specified, open the
1655 * value of the specified environment variable. Otherwise look for a
1656 * file "local" in the home directory or a file "global" in global
1657 * file system. If "result" is non-NULL, a pointer to a newly
1658 * allocated buffer containing the used configuration file is
1660 FILE * pa_open_config_file ( const char * global
, const char * local
, const char * env
, char ** result
) {
1665 if (! getenv ( PULSE_ROOTENV
))
1669 if ( env
&& ( fn
= getenv ( env
))) {
1673 if (! ExpandEnvironmentStrings ( fn
, buf
, PATH_MAX
))
1674 /* FIXME: Needs to set errno! */
1679 if (( f
= pa_fopen_cloexec ( fn
, "r" ))) {
1681 * result
= pa_xstrdup ( fn
);
1686 pa_log_warn ( "Failed to open configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1696 if (( e
= getenv ( "PULSE_CONFIG_PATH" )))
1697 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , e
, local
);
1698 else if (( h
= pa_get_home_dir_malloc ())) {
1699 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s" , h
, local
);
1705 if (! ExpandEnvironmentStrings ( lfn
, buf
, PATH_MAX
)) {
1706 /* FIXME: Needs to set errno! */
1713 if (( f
= pa_fopen_cloexec ( fn
, "r" ))) {
1715 * result
= pa_xstrdup ( fn
);
1721 if ( errno
!= ENOENT
) {
1722 pa_log_warn ( "Failed to open configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1734 if (! ExpandEnvironmentStrings ( global
, buf
, PATH_MAX
))
1735 /* FIXME: Needs to set errno! */
1740 if (( f
= pa_fopen_cloexec ( global
, "r" ))) {
1743 * result
= pa_xstrdup ( global
);
1753 char * pa_find_config_file ( const char * global
, const char * local
, const char * env
) {
1758 if (! getenv ( PULSE_ROOTENV
))
1762 if ( env
&& ( fn
= getenv ( env
))) {
1765 if (! ExpandEnvironmentStrings ( fn
, buf
, PATH_MAX
))
1766 /* FIXME: Needs to set errno! */
1771 if ( access ( fn
, R_OK
) == 0 )
1772 return pa_xstrdup ( fn
);
1774 pa_log_warn ( "Failed to access configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1783 if (( e
= getenv ( "PULSE_CONFIG_PATH" )))
1784 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , e
, local
);
1785 else if (( h
= pa_get_home_dir_malloc ())) {
1786 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s" , h
, local
);
1792 if (! ExpandEnvironmentStrings ( lfn
, buf
, PATH_MAX
)) {
1793 /* FIXME: Needs to set errno! */
1800 if ( access ( fn
, R_OK
) == 0 ) {
1801 char * r
= pa_xstrdup ( fn
);
1806 if ( errno
!= ENOENT
) {
1807 pa_log_warn ( "Failed to access configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1817 if (! ExpandEnvironmentStrings ( global
, buf
, PATH_MAX
))
1818 /* FIXME: Needs to set errno! */
1823 if ( access ( global
, R_OK
) == 0 )
1824 return pa_xstrdup ( global
);
1832 /* Format the specified data as a hexademical string */
1833 char * pa_hexstr ( const uint8_t * d
, size_t dlength
, char * s
, size_t slength
) {
1834 size_t i
= 0 , j
= 0 ;
1835 const char hex
[] = "0123456789abcdef" ;
1839 pa_assert ( slength
> 0 );
1841 while ( i
< dlength
&& j
+ 3 <= slength
) {
1842 s
[ j
++] = hex
[* d
>> 4 ];
1843 s
[ j
++] = hex
[* d
& 0xF ];
1849 s
[ j
< slength
? j
: slength
] = 0 ;
1853 /* Convert a hexadecimal digit to a number or -1 if invalid */
1854 static int hexc ( char c
) {
1855 if ( c
>= '0' && c
<= '9' )
1858 if ( c
>= 'A' && c
<= 'F' )
1859 return c
- 'A' + 10 ;
1861 if ( c
>= 'a' && c
<= 'f' )
1862 return c
- 'a' + 10 ;
1868 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1869 size_t pa_parsehex ( const char * p
, uint8_t * d
, size_t dlength
) {
1875 while ( j
< dlength
&& * p
) {
1878 if (( b
= hexc (*( p
++))) < 0 )
1881 d
[ j
] = ( uint8_t ) ( b
<< 4 );
1886 if (( b
= hexc (*( p
++))) < 0 )
1889 d
[ j
] |= ( uint8_t ) b
;
1896 /* Returns nonzero when *s starts with *pfx */
1897 pa_bool_t
pa_startswith ( const char * s
, const char * pfx
) {
1905 return strlen ( s
) >= l
&& strncmp ( s
, pfx
, l
) == 0 ;
1908 /* Returns nonzero when *s ends with *sfx */
1909 pa_bool_t
pa_endswith ( const char * s
, const char * sfx
) {
1918 return l1
>= l2
&& strcmp ( s
+ l1
- l2
, sfx
) == 0 ;
1921 pa_bool_t
pa_is_path_absolute ( const char * fn
) {
1927 return strlen ( fn
) >= 3 && isalpha ( fn
[ 0 ]) && fn
[ 1 ] == ':' && fn
[ 2 ] == ' \\ ' ;
1931 char * pa_make_path_absolute ( const char * p
) {
1937 if ( pa_is_path_absolute ( p
))
1938 return pa_xstrdup ( p
);
1940 if (!( cwd
= pa_getcwd ()))
1941 return pa_xstrdup ( p
);
1943 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , cwd
, p
);
1948 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1949 * if fn is non-null and starts with / return fn
1950 * otherwise append fn to the run time path and return it */
1951 static char * get_path ( const char * fn
, pa_bool_t prependmid
, pa_bool_t rt
) {
1954 rtp
= rt
? pa_get_runtime_dir () : pa_get_state_dir ();
1959 if ( pa_is_path_absolute ( fn
))
1960 return pa_xstrdup ( fn
);
1968 if (!( mid
= pa_machine_id ())) {
1973 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s-%s" , rtp
, mid
, fn
);
1976 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , rtp
, fn
);
1984 char * pa_runtime_path ( const char * fn
) {
1985 return get_path ( fn
, FALSE
, TRUE
);
1988 char * pa_state_path ( const char * fn
, pa_bool_t appendmid
) {
1989 return get_path ( fn
, appendmid
, FALSE
);
1992 /* Convert the string s to a signed integer in *ret_i */
1993 int pa_atoi ( const char * s
, int32_t * ret_i
) {
2001 l
= strtol ( s
, & x
, 0 );
2003 if (! x
|| * x
|| errno
) {
2009 if (( int32_t ) l
!= l
) {
2014 * ret_i
= ( int32_t ) l
;
2019 /* Convert the string s to an unsigned integer in *ret_u */
2020 int pa_atou ( const char * s
, uint32_t * ret_u
) {
2028 l
= strtoul ( s
, & x
, 0 );
2030 if (! x
|| * x
|| errno
) {
2036 if (( uint32_t ) l
!= l
) {
2041 * ret_u
= ( uint32_t ) l
;
2046 #ifdef HAVE_STRTOF_L
2047 static locale_t c_locale
= NULL
;
2049 static void c_locale_destroy ( void ) {
2050 freelocale ( c_locale
);
2054 int pa_atod ( const char * s
, double * ret_d
) {
2061 /* This should be locale independent */
2063 #ifdef HAVE_STRTOF_L
2067 if (( c_locale
= newlocale ( LC_ALL_MASK
, "C" , NULL
)))
2068 atexit ( c_locale_destroy
);
2074 f
= strtod_l ( s
, & x
, c_locale
);
2082 if (! x
|| * x
|| errno
) {
2093 /* Same as snprintf, but guarantees NUL-termination on every platform */
2094 size_t pa_snprintf ( char * str
, size_t size
, const char * format
, ...) {
2099 pa_assert ( size
> 0 );
2102 va_start ( ap
, format
);
2103 ret
= pa_vsnprintf ( str
, size
, format
, ap
);
2109 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2110 size_t pa_vsnprintf ( char * str
, size_t size
, const char * format
, va_list ap
) {
2114 pa_assert ( size
> 0 );
2117 ret
= vsnprintf ( str
, size
, format
, ap
);
2124 if (( size_t ) ret
> size
- 1 )
2127 return ( size_t ) ret
;
2130 /* Truncate the specified string, but guarantee that the string
2131 * returned still validates as UTF8 */
2132 char * pa_truncate_utf8 ( char * c
, size_t l
) {
2134 pa_assert ( pa_utf8_valid ( c
));
2141 while ( l
> 0 && ! pa_utf8_valid ( c
))
2147 char * pa_getcwd ( void ) {
2151 char * p
= pa_xmalloc ( l
);
2155 if ( errno
!= ERANGE
)
2163 void * pa_will_need ( const void * p
, size_t l
) {
2164 #ifdef RLIMIT_MEMLOCK
2175 a
= PA_PAGE_ALIGN_PTR ( p
);
2176 size
= ( size_t ) (( const uint8_t *) p
+ l
- ( const uint8_t *) a
);
2178 #ifdef HAVE_POSIX_MADVISE
2179 if (( r
= posix_madvise (( void *) a
, size
, POSIX_MADV_WILLNEED
)) == 0 ) {
2180 pa_log_debug ( "posix_madvise() worked fine!" );
2185 /* Most likely the memory was not mmap()ed from a file and thus
2186 * madvise() didn't work, so let's misuse mlock() do page this
2187 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2188 * inviting, the man page of mlock() tells us: "All pages that
2189 * contain a part of the specified address range are guaranteed to
2190 * be resident in RAM when the call returns successfully." */
2192 #ifdef RLIMIT_MEMLOCK
2193 pa_assert_se ( getrlimit ( RLIMIT_MEMLOCK
, & rlim
) == 0 );
2195 if ( rlim
. rlim_cur
< PA_PAGE_SIZE
) {
2196 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
));
2201 bs
= PA_PAGE_ALIGN (( size_t ) rlim
. rlim_cur
);
2203 bs
= PA_PAGE_SIZE
* 4 ;
2206 pa_log_debug ( "posix_madvise() failed (or doesn't exist), trying mlock(): %s" , pa_cstrerror ( r
));
2209 while ( size
> 0 && bs
> 0 ) {
2214 if ( mlock ( a
, bs
) < 0 ) {
2215 bs
= PA_PAGE_ALIGN ( bs
/ 2 );
2219 pa_assert_se ( munlock ( a
, bs
) == 0 );
2221 a
= ( const uint8_t *) a
+ bs
;
2227 pa_log_debug ( "mlock() failed too (or doesn't exist), giving up: %s" , pa_cstrerror ( errno
));
2229 pa_log_debug ( "mlock() worked fine!" );
2234 void pa_close_pipe ( int fds
[ 2 ]) {
2238 pa_assert_se ( pa_close ( fds
[ 0 ]) == 0 );
2241 pa_assert_se ( pa_close ( fds
[ 1 ]) == 0 );
2243 fds
[ 0 ] = fds
[ 1 ] = - 1 ;
2246 char * pa_readlink ( const char * p
) {
2247 #ifdef HAVE_READLINK
2256 if (( n
= readlink ( p
, c
, l
- 1 )) < 0 ) {
2261 if (( size_t ) n
< l
- 1 ) {
2274 int pa_close_all ( int except_fd
, ...) {
2279 va_start ( ap
, except_fd
);
2282 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2287 p
= pa_xnew ( int , n
+ 1 );
2289 va_start ( ap
, except_fd
);
2292 if ( except_fd
>= 0 ) {
2296 while (( fd
= va_arg ( ap
, int )) >= 0 )
2303 r
= pa_close_allv ( p
);
2309 int pa_close_allv ( const int except_fds
[]) {
2318 if (( d
= opendir ( "/proc/self/fd" ))) {
2322 while (( de
= readdir ( d
))) {
2328 if ( de
-> d_name
[ 0 ] == '.' )
2332 l
= strtol ( de
-> d_name
, & e
, 10 );
2333 if ( errno
!= 0 || ! e
|| * e
) {
2341 if (( long ) fd
!= l
) {
2354 for ( i
= 0 ; except_fds
[ i
] >= 0 ; i
++)
2355 if ( except_fds
[ i
] == fd
) {
2363 if ( pa_close ( fd
) < 0 ) {
2364 saved_errno
= errno
;
2366 errno
= saved_errno
;
2378 if ( getrlimit ( RLIMIT_NOFILE
, & rl
) >= 0 )
2379 maxfd
= ( int ) rl
. rlim_max
;
2381 maxfd
= sysconf ( _SC_OPEN_MAX
);
2383 for ( fd
= 3 ; fd
< maxfd
; fd
++) {
2388 for ( i
= 0 ; except_fds
[ i
] >= 0 ; i
++)
2389 if ( except_fds
[ i
] == fd
) {
2397 if ( pa_close ( fd
) < 0 && errno
!= EBADF
)
2400 #endif /* !OS_IS_WIN32 */
2405 int pa_unblock_sigs ( int except
, ...) {
2410 va_start ( ap
, except
);
2413 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2418 p
= pa_xnew ( int , n
+ 1 );
2420 va_start ( ap
, except
);
2427 while (( sig
= va_arg ( ap
, int )) >= 0 )
2434 r
= pa_unblock_sigsv ( p
);
2440 int pa_unblock_sigsv ( const int except
[]) {
2445 if ( sigemptyset (& ss
) < 0 )
2448 for ( i
= 0 ; except
[ i
] > 0 ; i
++)
2449 if ( sigaddset (& ss
, except
[ i
]) < 0 )
2452 return sigprocmask ( SIG_SETMASK
, & ss
, NULL
);
2458 int pa_reset_sigs ( int except
, ...) {
2463 va_start ( ap
, except
);
2466 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2471 p
= pa_xnew ( int , n
+ 1 );
2473 va_start ( ap
, except
);
2480 while (( sig
= va_arg ( ap
, int )) >= 0 )
2487 r
= pa_reset_sigsv ( p
);
2493 int pa_reset_sigsv ( const int except
[]) {
2497 for ( sig
= 1 ; sig
< NSIG
; sig
++) {
2498 pa_bool_t reset
= TRUE
;
2509 for ( i
= 0 ; except
[ i
] > 0 ; i
++) {
2510 if ( sig
== except
[ i
]) {
2519 struct sigaction sa
;
2521 memset (& sa
, 0 , sizeof ( sa
));
2522 sa
. sa_handler
= SIG_DFL
;
2524 /* On Linux the first two RT signals are reserved by
2525 * glibc, and sigaction() will return EINVAL for them. */
2526 if (( sigaction ( sig
, & sa
, NULL
) < 0 ))
2527 if ( errno
!= EINVAL
)
2536 void pa_set_env ( const char * key
, const char * value
) {
2540 /* This is not thread-safe */
2542 setenv ( key
, value
, 1 );
2545 void pa_set_env_and_record ( const char * key
, const char * value
) {
2549 /* This is not thread-safe */
2551 pa_set_env ( key
, value
);
2552 recorded_env
= pa_strlist_prepend ( recorded_env
, key
);
2555 void pa_unset_env_recorded ( void ) {
2557 /* This is not thread-safe */
2562 recorded_env
= pa_strlist_pop ( recorded_env
, & s
);
2572 pa_bool_t
pa_in_system_mode ( void ) {
2575 if (!( e
= getenv ( "PULSE_SYSTEM" )))
2581 char * pa_get_user_name_malloc ( void ) {
2585 #ifdef _SC_LOGIN_NAME_MAX
2586 k
= ( ssize_t
) sysconf ( _SC_LOGIN_NAME_MAX
);
2592 u
= pa_xnew ( char , k
+ 1 );
2594 if (!( pa_get_user_name ( u
, k
))) {
2602 char * pa_get_host_name_malloc ( void ) {
2611 if (! pa_get_host_name ( c
, l
)) {
2613 if ( errno
!= EINVAL
&& errno
!= ENAMETOOLONG
)
2616 } else if ( strlen ( c
) < l
- 1 ) {
2624 u
= pa_utf8_filter ( c
);
2629 /* Hmm, the hostname is as long the space we offered the
2630 * function, we cannot know if it fully fit in, so let's play
2631 * safe and retry. */
2640 char * pa_machine_id ( void ) {
2644 /* The returned value is supposed be some kind of ascii identifier
2645 * that is unique and stable across reboots. */
2647 /* First we try the D-Bus UUID, which is the best option we have,
2648 * since it fits perfectly our needs and is not as volatile as the
2649 * hostname which might be set from dhcp. */
2651 if (( f
= pa_fopen_cloexec ( PA_MACHINE_ID
, "r" ))) {
2652 char ln
[ 34 ] = "" , * r
;
2654 r
= fgets ( ln
, sizeof ( ln
)- 1 , f
);
2660 return pa_utf8_filter ( ln
);
2663 if (( h
= pa_get_host_name_malloc ()))
2667 /* If no hostname was set we use the POSIX hostid. It's usually
2668 * the IPv4 address. Might not be that stable. */
2669 return pa_sprintf_malloc ( "%08lx" , ( unsigned long ) gethostid
);
2675 char * pa_session_id ( void ) {
2678 if (!( e
= getenv ( "XDG_SESSION_COOKIE" )))
2681 return pa_utf8_filter ( e
);
2684 char * pa_uname_string ( void ) {
2687 pa_assert_se ( uname (& u
) >= 0 );
2689 return pa_sprintf_malloc ( "%s %s %s %s" , u
. sysname
, u
. machine
, u
. release
, u
. version
);
2692 #ifdef HAVE_VALGRIND_MEMCHECK_H
2693 pa_bool_t
pa_in_valgrind ( void ) {
2696 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2697 * here instead of really checking whether we run in valgrind or
2701 b
= getenv ( "VALGRIND" ) ? 2 : 1 ;
2707 unsigned pa_gcd ( unsigned a
, unsigned b
) {
2718 void pa_reduce ( unsigned * num
, unsigned * den
) {
2720 unsigned gcd
= pa_gcd (* num
, * den
);
2728 pa_assert ( pa_gcd (* num
, * den
) == 1 );
2731 unsigned pa_ncpus ( void ) {
2734 #ifdef _SC_NPROCESSORS_CONF
2735 ncpus
= sysconf ( _SC_NPROCESSORS_CONF
);
2740 return ncpus
<= 0 ? 1 : ( unsigned ) ncpus
;
2743 char * pa_replace ( const char * s
, const char * a
, const char * b
) {
2752 sb
= pa_strbuf_new ();
2757 if (!( p
= strstr ( s
, a
)))
2760 pa_strbuf_putsn ( sb
, s
, p
- s
);
2761 pa_strbuf_puts ( sb
, b
);
2765 pa_strbuf_puts ( sb
, s
);
2767 return pa_strbuf_tostring_free ( sb
);
2770 char * pa_escape ( const char * p
, const char * chars
) {
2773 pa_strbuf
* buf
= pa_strbuf_new ();
2775 for ( s
= p
; * s
; ++ s
) {
2777 pa_strbuf_putc ( buf
, ' \\ ' );
2779 for ( c
= chars
; * c
; ++ c
) {
2781 pa_strbuf_putc ( buf
, ' \\ ' );
2786 pa_strbuf_putc ( buf
, * s
);
2789 return pa_strbuf_tostring_free ( buf
);
2792 char * pa_unescape ( char * p
) {
2794 pa_bool_t escaped
= FALSE
;
2796 for ( s
= p
, d
= p
; * s
; s
++) {
2797 if (! escaped
&& * s
== ' \\ ' ) {
2811 char * pa_realpath ( const char * path
) {
2815 /* We want only abolsute paths */
2816 if ( path
[ 0 ] != '/' ) {
2821 #if defined(__GLIBC__) || defined(__APPLE__)
2825 if (!( r
= realpath ( path
, NULL
)))
2828 /* We copy this here in case our pa_xmalloc() is not
2829 * implemented on top of libc malloc() */
2833 #elif defined(PATH_MAX)
2836 path_buf
= pa_xmalloc ( PATH_MAX
);
2838 if (!( t
= realpath ( path
, path_buf
))) {
2844 #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."
2850 void pa_disable_sigpipe ( void ) {
2853 struct sigaction sa
;
2857 if ( sigaction ( SIGPIPE
, NULL
, & sa
) < 0 ) {
2858 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
2862 sa
. sa_handler
= SIG_IGN
;
2864 if ( sigaction ( SIGPIPE
, & sa
, NULL
) < 0 ) {
2865 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
2871 void pa_xfreev ( void ** a
) {
2877 for ( p
= a
; * p
; p
++)
2883 char ** pa_split_spaces_strv ( const char * s
) {
2885 unsigned i
= 0 , n
= 8 ;
2886 const char * state
= NULL
;
2888 t
= pa_xnew ( char *, n
);
2889 while (( e
= pa_split_spaces ( s
, & state
))) {
2894 t
= pa_xrenew ( char *, t
, n
);
2907 char * pa_maybe_prefix_path ( const char * path
, const char * prefix
) {
2910 if ( pa_is_path_absolute ( path
))
2911 return pa_xstrdup ( path
);
2913 return pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , prefix
, path
);
2916 size_t pa_pipe_buf ( int fd
) {
2921 if (( n
= fpathconf ( fd
, _PC_PIPE_BUF
)) >= 0 )
2932 void pa_reset_personality ( void ) {
2935 if ( personality ( PER_LINUX
) < 0 )
2936 pa_log_warn ( "Uh, personality() failed: %s" , pa_cstrerror ( errno
));
2941 #if defined(__linux__) && !defined(__OPTIMIZE__)
2943 pa_bool_t
pa_run_from_build_tree ( void ) {
2945 pa_bool_t b
= FALSE
;
2947 /* We abuse __OPTIMIZE__ as a check whether we are a debug build
2950 if (( rp
= pa_readlink ( "/proc/self/exe" ))) {
2951 b
= pa_startswith ( rp
, PA_BUILDDIR
);
2960 const char * pa_get_temp_dir ( void ) {
2963 if (( t
= getenv ( "TMPDIR" )) &&
2964 pa_is_path_absolute ( t
))
2967 if (( t
= getenv ( "TMP" )) &&
2968 pa_is_path_absolute ( t
))
2971 if (( t
= getenv ( "TEMP" )) &&
2972 pa_is_path_absolute ( t
))
2975 if (( t
= getenv ( "TEMPDIR" )) &&
2976 pa_is_path_absolute ( t
))
2982 int pa_open_cloexec ( const char * fn
, int flags
, mode_t mode
) {
2990 if (( fd
= open ( fn
, flags
| O_CLOEXEC
, mode
)) >= 0 )
2993 if ( errno
!= EINVAL
)
2997 if (( fd
= open ( fn
, flags
, mode
)) < 0 )
3001 /* Some implementations might simply ignore O_CLOEXEC if it is not
3002 * understood, make sure FD_CLOEXEC is enabled anyway */
3004 pa_make_fd_cloexec ( fd
);
3008 int pa_socket_cloexec ( int domain
, int type
, int protocol
) {
3012 if (( fd
= socket ( domain
, type
| SOCK_CLOEXEC
, protocol
)) >= 0 )
3015 if ( errno
!= EINVAL
)
3019 if (( fd
= socket ( domain
, type
, protocol
)) < 0 )
3023 /* Some implementations might simply ignore SOCK_CLOEXEC if it is
3024 * not understood, make sure FD_CLOEXEC is enabled anyway */
3026 pa_make_fd_cloexec ( fd
);
3030 int pa_pipe_cloexec ( int pipefd
[ 2 ]) {
3034 if (( r
= pipe2 ( pipefd
, O_CLOEXEC
)) >= 0 )
3037 if ( errno
!= EINVAL
&& errno
!= ENOSYS
)
3042 if (( r
= pipe ( pipefd
)) < 0 )
3046 pa_make_fd_cloexec ( pipefd
[ 0 ]);
3047 pa_make_fd_cloexec ( pipefd
[ 1 ]);
3052 int pa_accept_cloexec ( int sockfd
, struct sockaddr
* addr
, socklen_t
* addrlen
) {
3056 if (( fd
= accept4 ( sockfd
, addr
, addrlen
, SOCK_CLOEXEC
)) >= 0 )
3059 if ( errno
!= EINVAL
&& errno
!= ENOSYS
)
3064 if (( fd
= accept ( sockfd
, addr
, addrlen
)) < 0 )
3068 pa_make_fd_cloexec ( fd
);
3072 FILE * pa_fopen_cloexec ( const char * path
, const char * mode
) {
3076 m
= pa_sprintf_malloc ( "%se" , mode
);
3079 if (( f
= fopen ( path
, m
))) {
3086 if ( errno
!= EINVAL
)
3089 if (!( f
= fopen ( path
, mode
)))
3093 pa_make_fd_cloexec ( fileno ( f
));
3097 void pa_nullify_stdfds ( void ) {
3100 pa_close ( STDIN_FILENO
);
3101 pa_close ( STDOUT_FILENO
);
3102 pa_close ( STDERR_FILENO
);
3104 pa_assert_se ( open ( "/dev/null" , O_RDONLY
) == STDIN_FILENO
);
3105 pa_assert_se ( open ( "/dev/null" , O_WRONLY
) == STDOUT_FILENO
);
3106 pa_assert_se ( open ( "/dev/null" , O_WRONLY
) == STDERR_FILENO
);
3113 char * pa_read_line_from_file ( const char * fn
) {
3115 char ln
[ 256 ] = "" , * r
;
3117 if (!( f
= pa_fopen_cloexec ( fn
, "r" )))
3120 r
= fgets ( ln
, sizeof ( ln
)- 1 , f
);
3129 return pa_xstrdup ( ln
);
3132 pa_bool_t
pa_running_in_vm ( void ) {
3134 #if defined(__i386__) || defined(__x86_64__)
3136 /* Both CPUID and DMI are x86 specific interfaces... */
3138 uint32_t eax
= 0x40000000 ;
3145 const char * const dmi_vendors
[] = {
3146 "/sys/class/dmi/id/sys_vendor" ,
3147 "/sys/class/dmi/id/board_vendor" ,
3148 "/sys/class/dmi/id/bios_vendor"
3153 for ( i
= 0 ; i
< PA_ELEMENTSOF ( dmi_vendors
); i
++) {
3156 if (( s
= pa_read_line_from_file ( dmi_vendors
[ i
]))) {
3158 if ( pa_startswith ( s
, "QEMU" ) ||
3159 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3160 pa_startswith ( s
, "VMware" ) ||
3161 pa_startswith ( s
, "VMW" ) ||
3162 pa_startswith ( s
, "Microsoft Corporation" ) ||
3163 pa_startswith ( s
, "innotek GmbH" ) ||
3164 pa_startswith ( s
, "Xen" )) {
3176 /* http://lwn.net/Articles/301888/ */
3179 __asm__
__volatile__ (
3180 /* ebx/rbx is being used for PIC! */
3181 " push %%" PA_REG_b
" \n\t "
3183 " mov %%ebx, %1 \n\t "
3184 " pop %%" PA_REG_b
" \n\t "
3186 : "=a" ( eax
), "=r" ( sig
. sig32
[ 0 ]), "=c" ( sig
. sig32
[ 1 ]), "=d" ( sig
. sig32
[ 2 ])
3190 if ( pa_streq ( sig
. text
, "XenVMMXenVMM" ) ||
3191 pa_streq ( sig
. text
, "KVMKVMKVM" ) ||
3192 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3193 pa_streq ( sig
. text
, "VMwareVMware" ) ||
3194 /* http://msdn.microsoft.com/en-us/library/bb969719.aspx */
3195 pa_streq ( sig
. text
, "Microsoft Hv" ))