]>
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>
45 #ifdef HAVE_LANGINFO_H
50 #include <sys/utsname.h>
60 #if defined(__linux__) && !defined(SCHED_RESET_ON_FORK)
61 #define SCHED_RESET_ON_FORK 0x40000000
65 #ifdef HAVE_SYS_RESOURCE_H
66 #include <sys/resource.h>
69 #ifdef HAVE_SYS_CAPABILITY_H
70 #include <sys/capability.h>
73 #ifdef HAVE_SYS_MMAN_H
97 #ifdef HAVE_LIBSAMPLERATE
98 #include <samplerate.h>
110 #include <sys/personality.h>
113 #include <pulse/xmalloc.h>
114 #include <pulse/util.h>
115 #include <pulse/utf8.h>
117 #include <pulsecore/core-error.h>
118 #include <pulsecore/socket.h>
119 #include <pulsecore/log.h>
120 #include <pulsecore/macro.h>
121 #include <pulsecore/thread.h>
122 #include <pulsecore/strbuf.h>
123 #include <pulsecore/usergroup.h>
124 #include <pulsecore/strlist.h>
125 #include <pulsecore/cpu-x86.h>
127 #include "core-util.h"
129 /* Not all platforms have this */
131 #define MSG_NOSIGNAL 0
134 #define NEWLINE " \r\n "
135 #define WHITESPACE " \n\r \t "
137 static pa_strlist
* recorded_env
= NULL
;
141 #define PULSE_ROOTENV "PULSE_ROOT"
143 int pa_set_root ( HANDLE handle
) {
144 char library_path
[ MAX_PATH
+ sizeof ( PULSE_ROOTENV
) + 1 ], * sep
;
146 strcpy ( library_path
, PULSE_ROOTENV
"=" );
148 /* FIXME: Needs to set errno */
150 if (! GetModuleFileName ( handle
, library_path
+ sizeof ( PULSE_ROOTENV
), MAX_PATH
))
153 sep
= strrchr ( library_path
, PA_PATH_SEP_CHAR
);
157 if ( _putenv ( library_path
) < 0 )
165 /** Make a file descriptor nonblock. Doesn't do any error checking */
166 void pa_make_fd_nonblock ( int fd
) {
172 pa_assert_se (( v
= fcntl ( fd
, F_GETFL
)) >= 0 );
174 if (!( v
& O_NONBLOCK
))
175 pa_assert_se ( fcntl ( fd
, F_SETFL
, v
| O_NONBLOCK
) >= 0 );
177 #elif defined(OS_IS_WIN32)
179 if ( ioctlsocket ( fd
, FIONBIO
, & arg
) < 0 ) {
180 pa_assert_se ( WSAGetLastError () == WSAENOTSOCK
);
181 pa_log_warn ( "Only sockets can be made non-blocking!" );
184 pa_log_warn ( "Non-blocking I/O not supported.!" );
189 /* Set the FD_CLOEXEC flag for a fd */
190 void pa_make_fd_cloexec ( int fd
) {
196 pa_assert_se (( v
= fcntl ( fd
, F_GETFD
, 0 )) >= 0 );
198 if (!( v
& FD_CLOEXEC
))
199 pa_assert_se ( fcntl ( fd
, F_SETFD
, v
| FD_CLOEXEC
) >= 0 );
204 /** Creates a directory securely */
205 int pa_make_secure_dir ( const char * dir
, mode_t m
, uid_t uid
, gid_t gid
) {
207 int r
, saved_errno
, fd
;
216 u
= umask ((~ m
) & 0777 );
222 if ( r
< 0 && errno
!= EEXIST
)
225 #if defined(HAVE_FSTAT) && !defined(OS_IS_WIN32)
239 if ( fstat ( fd
, & st
) < 0 ) {
240 pa_assert_se ( pa_close ( fd
) >= 0 );
244 if (! S_ISDIR ( st
. st_mode
)) {
245 pa_assert_se ( pa_close ( fd
) >= 0 );
251 if ( uid
== ( uid_t
)- 1 )
253 if ( gid
== ( gid_t
)- 1 )
255 ( void ) fchown ( fd
, uid
, gid
);
259 ( void ) fchmod ( fd
, m
);
262 pa_assert_se ( pa_close ( fd
) >= 0 );
266 if ( lstat ( dir
, & st
) < 0 )
268 if ( stat ( dir
, & st
) < 0 )
273 if (! S_ISDIR ( st
. st_mode
) ||
274 ( st
. st_uid
!= uid
) ||
275 ( st
. st_gid
!= gid
) ||
276 (( st
. st_mode
& 0777 ) != m
)) {
281 pa_log_warn ( "Secure directory creation not supported on Win32." );
294 /* Return a newly allocated sting containing the parent directory of the specified file */
295 char * pa_parent_dir ( const char * fn
) {
296 char * slash
, * dir
= pa_xstrdup ( fn
);
298 if (( slash
= ( char *) pa_path_get_filename ( dir
)) == dir
) {
308 /* Creates a the parent directory of the specified path securely */
309 int pa_make_secure_parent_dir ( const char * fn
, mode_t m
, uid_t uid
, gid_t gid
) {
313 if (!( dir
= pa_parent_dir ( fn
)))
316 if ( pa_make_secure_dir ( dir
, m
, uid
, gid
) < 0 )
326 /** Platform independent read function. Necessary since not all
327 * systems treat all file descriptors equal. If type is
328 * non-NULL it is used to cache the type of the fd. This is
329 * useful for making sure that only a single syscall is executed per
330 * function call. The variable pointed to should be initialized to 0
332 ssize_t
pa_read ( int fd
, void * buf
, size_t count
, int * type
) {
336 if (! type
|| * type
== 0 ) {
339 if (( r
= recv ( fd
, buf
, count
, 0 )) >= 0 )
342 if ( WSAGetLastError () != WSAENOTSOCK
) {
343 errno
= WSAGetLastError ();
356 if (( r
= read ( fd
, buf
, count
)) < 0 )
364 /** Similar to pa_read(), but handles writes */
365 ssize_t
pa_write ( int fd
, const void * buf
, size_t count
, int * type
) {
367 if (! type
|| * type
== 0 ) {
371 if (( r
= send ( fd
, buf
, count
, MSG_NOSIGNAL
)) < 0 ) {
383 if ( WSAGetLastError () != WSAENOTSOCK
) {
384 errno
= WSAGetLastError ();
388 if ( errno
!= ENOTSOCK
)
399 if (( r
= write ( fd
, buf
, count
)) < 0 )
407 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
408 * unless EOF is reached or an error occurred */
409 ssize_t
pa_loop_read ( int fd
, void * data
, size_t size
, int * type
) {
425 if (( r
= pa_read ( fd
, data
, size
, type
)) < 0 )
432 data
= ( uint8_t *) data
+ r
;
439 /** Similar to pa_loop_read(), but wraps write() */
440 ssize_t
pa_loop_write ( int fd
, const void * data
, size_t size
, int * type
) {
456 if (( r
= pa_write ( fd
, data
, size
, type
)) < 0 )
463 data
= ( const uint8_t *) data
+ r
;
470 /** Platform independent read function. Necessary since not all
471 * systems treat all file descriptors equal. */
472 int pa_close ( int fd
) {
477 if (( ret
= closesocket ( fd
)) == 0 )
480 if ( WSAGetLastError () != WSAENOTSOCK
) {
481 errno
= WSAGetLastError ();
489 if (( r
= close ( fd
)) < 0 )
497 /* Print a warning messages in case that the given signal is not
498 * blocked or trapped */
499 void pa_check_signal_is_blocked ( int sig
) {
500 #ifdef HAVE_SIGACTION
504 /* If POSIX threads are supported use thread-aware
505 * pthread_sigmask() function, to check if the signal is
506 * blocked. Otherwise fall back to sigprocmask() */
509 if ( pthread_sigmask ( SIG_SETMASK
, NULL
, & set
) < 0 ) {
511 if ( sigprocmask ( SIG_SETMASK
, NULL
, & set
) < 0 ) {
512 pa_log ( "sigprocmask(): %s" , pa_cstrerror ( errno
));
519 if ( sigismember (& set
, sig
))
522 /* Check whether the signal is trapped */
524 if ( sigaction ( sig
, NULL
, & sa
) < 0 ) {
525 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
529 if ( sa
. sa_handler
!= SIG_DFL
)
532 pa_log_warn ( "%s is not trapped. This might cause malfunction!" , pa_sig2str ( sig
));
533 #else /* HAVE_SIGACTION */
534 pa_log_warn ( "%s might not be trapped. This might cause malfunction!" , pa_sig2str ( sig
));
538 /* The following function is based on an example from the GNU libc
539 * documentation. This function is similar to GNU's asprintf(). */
540 char * pa_sprintf_malloc ( const char * format
, ...) {
550 c
= pa_xrealloc ( c
, size
);
552 va_start ( ap
, format
);
553 r
= vsnprintf ( c
, size
, format
, ap
);
558 if ( r
> - 1 && ( size_t ) r
< size
)
561 if ( r
> - 1 ) /* glibc 2.1 */
568 /* Same as the previous function, but use a va_list instead of an
570 char * pa_vsprintf_malloc ( const char * format
, va_list ap
) {
580 c
= pa_xrealloc ( c
, size
);
583 r
= vsnprintf ( c
, size
, format
, aq
);
588 if ( r
> - 1 && ( size_t ) r
< size
)
591 if ( r
> - 1 ) /* glibc 2.1 */
598 /* Similar to OpenBSD's strlcpy() function */
599 char * pa_strlcpy ( char * b
, const char * s
, size_t l
) {
617 static int set_scheduler ( int rtprio
) {
619 struct sched_param sp
;
625 dbus_error_init (& error
);
629 sp
. sched_priority
= rtprio
;
631 #ifdef SCHED_RESET_ON_FORK
632 if ( pthread_setschedparam ( pthread_self (), SCHED_RR
| SCHED_RESET_ON_FORK
, & sp
) == 0 ) {
633 pa_log_debug ( "SCHED_RR|SCHED_RESET_ON_FORK worked." );
638 if ( pthread_setschedparam ( pthread_self (), SCHED_RR
, & sp
) == 0 ) {
639 pa_log_debug ( "SCHED_RR worked." );
642 #endif /* HAVE_SCHED_H */
645 /* Try to talk to RealtimeKit */
647 if (!( bus
= dbus_bus_get ( DBUS_BUS_SYSTEM
, & error
))) {
648 pa_log ( "Failed to connect to system bus: %s \n " , error
. message
);
649 dbus_error_free (& error
);
654 /* We need to disable exit on disconnect because otherwise
655 * dbus_shutdown will kill us. See
656 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
657 dbus_connection_set_exit_on_disconnect ( bus
, FALSE
);
659 r
= rtkit_make_realtime ( bus
, 0 , rtprio
);
660 dbus_connection_unref ( bus
);
663 pa_log_debug ( "RealtimeKit worked." );
675 /* Make the current thread a realtime thread, and acquire the highest
676 * rtprio we can get that is less or equal the specified parameter. If
677 * the thread is already realtime, don't do anything. */
678 int pa_make_realtime ( int rtprio
) {
680 #ifdef _POSIX_PRIORITY_SCHEDULING
683 if ( set_scheduler ( rtprio
) >= 0 ) {
684 pa_log_info ( "Successfully enabled SCHED_RR scheduling for thread, with priority %i." , rtprio
);
688 for ( p
= rtprio
- 1 ; p
>= 1 ; p
--)
689 if ( set_scheduler ( p
) >= 0 ) {
690 pa_log_info ( "Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i." , p
, rtprio
);
694 pa_log_info ( "Failed to acquire real-time scheduling: %s" , pa_cstrerror ( errno
));
703 static int set_nice ( int nice_level
) {
709 dbus_error_init (& error
);
712 #ifdef HAVE_SYS_RESOURCE_H
713 if ( setpriority ( PRIO_PROCESS
, 0 , nice_level
) >= 0 ) {
714 pa_log_debug ( "setpriority() worked." );
720 /* Try to talk to RealtimeKit */
722 if (!( bus
= dbus_bus_get ( DBUS_BUS_SYSTEM
, & error
))) {
723 pa_log ( "Failed to connect to system bus: %s \n " , error
. message
);
724 dbus_error_free (& error
);
729 /* We need to disable exit on disconnect because otherwise
730 * dbus_shutdown will kill us. See
731 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
732 dbus_connection_set_exit_on_disconnect ( bus
, FALSE
);
734 r
= rtkit_make_high_priority ( bus
, 0 , nice_level
);
735 dbus_connection_unref ( bus
);
738 pa_log_debug ( "RealtimeKit worked." );
748 /* Raise the priority of the current process as much as possible that
749 * is <= the specified nice level..*/
750 int pa_raise_priority ( int nice_level
) {
752 #ifdef HAVE_SYS_RESOURCE_H
755 if ( set_nice ( nice_level
) >= 0 ) {
756 pa_log_info ( "Successfully gained nice level %i." , nice_level
);
760 for ( n
= nice_level
+ 1 ; n
< 0 ; n
++)
761 if ( set_nice ( n
) >= 0 ) {
762 pa_log_info ( "Successfully acquired nice level %i, which is lower than the requested %i." , n
, nice_level
);
766 pa_log_info ( "Failed to acquire high-priority scheduling: %s" , pa_cstrerror ( errno
));
771 if ( nice_level
< 0 ) {
772 if (! SetPriorityClass ( GetCurrentProcess (), HIGH_PRIORITY_CLASS
)) {
773 pa_log_warn ( "SetPriorityClass() failed: 0x%08X" , GetLastError ());
778 pa_log_info ( "Successfully gained high priority class." );
785 /* Reset the priority to normal, inverting the changes made by
786 * pa_raise_priority() and pa_make_realtime()*/
787 void pa_reset_priority ( void ) {
788 #ifdef HAVE_SYS_RESOURCE_H
789 struct sched_param sp
;
791 setpriority ( PRIO_PROCESS
, 0 , 0 );
794 pthread_setschedparam ( pthread_self (), SCHED_OTHER
, & sp
);
798 SetPriorityClass ( GetCurrentProcess (), NORMAL_PRIORITY_CLASS
);
802 int pa_match ( const char * expr
, const char * v
) {
807 if ( regcomp (& re
, expr
, REG_NOSUB
| REG_EXTENDED
) != 0 ) {
812 if (( k
= regexec (& re
, v
, 0 , NULL
, 0 )) == 0 )
814 else if ( k
== REG_NOMATCH
)
827 /* Try to parse a boolean string value.*/
828 int pa_parse_boolean ( const char * v
) {
832 /* First we check language independant */
833 if (! strcmp ( v
, "1" ) || v
[ 0 ] == 'y' || v
[ 0 ] == 'Y' || v
[ 0 ] == 't' || v
[ 0 ] == 'T' || ! strcasecmp ( v
, "on" ))
835 else if (! strcmp ( v
, "0" ) || v
[ 0 ] == 'n' || v
[ 0 ] == 'N' || v
[ 0 ] == 'f' || v
[ 0 ] == 'F' || ! strcasecmp ( v
, "off" ))
838 #ifdef HAVE_LANGINFO_H
839 /* And then we check language dependant */
840 if (( expr
= nl_langinfo ( YESEXPR
)))
842 if ( pa_match ( expr
, v
) > 0 )
845 if (( expr
= nl_langinfo ( NOEXPR
)))
847 if ( pa_match ( expr
, v
) > 0 )
855 /* Split the specified string wherever one of the strings in delimiter
856 * occurs. Each time it is called returns a newly allocated string
857 * with pa_xmalloc(). The variable state points to, should be
858 * initiallized to NULL before the first call. */
859 char * pa_split ( const char * c
, const char * delimiter
, const char ** state
) {
860 const char * current
= * state
? * state
: c
;
866 l
= strcspn ( current
, delimiter
);
872 return pa_xstrndup ( current
, l
);
875 /* Split a string into words. Otherwise similar to pa_split(). */
876 char * pa_split_spaces ( const char * c
, const char ** state
) {
877 const char * current
= * state
? * state
: c
;
880 if (!* current
|| * c
== 0 )
883 current
+= strspn ( current
, WHITESPACE
);
884 l
= strcspn ( current
, WHITESPACE
);
888 return pa_xstrndup ( current
, l
);
891 PA_STATIC_TLS_DECLARE ( signame
, pa_xfree
);
893 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
894 const char * pa_sig2str ( int sig
) {
907 char buf
[ SIG2STR_MAX
];
909 if ( sig2str ( sig
, buf
) == 0 ) {
910 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
911 t
= pa_sprintf_malloc ( "SIG%s" , buf
);
912 PA_STATIC_TLS_SET ( signame
, t
);
920 case SIGHUP
: return "SIGHUP" ;
922 case SIGINT
: return "SIGINT" ;
924 case SIGQUIT
: return "SIGQUIT" ;
926 case SIGILL
: return "SIGULL" ;
928 case SIGTRAP
: return "SIGTRAP" ;
930 case SIGABRT
: return "SIGABRT" ;
932 case SIGBUS
: return "SIGBUS" ;
934 case SIGFPE
: return "SIGFPE" ;
936 case SIGKILL
: return "SIGKILL" ;
939 case SIGUSR1
: return "SIGUSR1" ;
941 case SIGSEGV
: return "SIGSEGV" ;
943 case SIGUSR2
: return "SIGUSR2" ;
946 case SIGPIPE
: return "SIGPIPE" ;
949 case SIGALRM
: return "SIGALRM" ;
951 case SIGTERM
: return "SIGTERM" ;
953 case SIGSTKFLT
: return "SIGSTKFLT" ;
956 case SIGCHLD
: return "SIGCHLD" ;
959 case SIGCONT
: return "SIGCONT" ;
962 case SIGSTOP
: return "SIGSTOP" ;
965 case SIGTSTP
: return "SIGTSTP" ;
968 case SIGTTIN
: return "SIGTTIN" ;
971 case SIGTTOU
: return "SIGTTOU" ;
974 case SIGURG
: return "SIGURG" ;
977 case SIGXCPU
: return "SIGXCPU" ;
980 case SIGXFSZ
: return "SIGXFSZ" ;
983 case SIGVTALRM
: return "SIGVTALRM" ;
986 case SIGPROF
: return "SIGPROF" ;
989 case SIGWINCH
: return "SIGWINCH" ;
992 case SIGIO
: return "SIGIO" ;
995 case SIGPWR
: return "SIGPWR" ;
998 case SIGSYS
: return "SIGSYS" ;
1003 if ( sig
>= SIGRTMIN
&& sig
<= SIGRTMAX
) {
1004 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
1005 t
= pa_sprintf_malloc ( "SIGRTMIN+%i" , sig
- SIGRTMIN
);
1006 PA_STATIC_TLS_SET ( signame
, t
);
1015 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
1016 t
= pa_sprintf_malloc ( "SIG%i" , sig
);
1017 PA_STATIC_TLS_SET ( signame
, t
);
1023 /* Check whether the specified GID and the group name match */
1024 static int is_group ( gid_t gid
, const char * name
) {
1025 struct group
* group
= NULL
;
1029 if (!( group
= pa_getgrgid_malloc ( gid
)))
1034 pa_log ( "pa_getgrgid_malloc(%u): %s" , gid
, pa_cstrerror ( errno
));
1039 r
= strcmp ( name
, group
-> gr_name
) == 0 ;
1042 pa_getgrgid_free ( group
);
1047 /* Check the current user is member of the specified group */
1048 int pa_own_uid_in_group ( const char * name
, gid_t
* gid
) {
1049 GETGROUPS_T
* gids
, tgid
;
1050 long n
= sysconf ( _SC_NGROUPS_MAX
);
1055 gids
= pa_xmalloc ( sizeof ( GETGROUPS_T
) * ( size_t ) n
);
1057 if (( n
= getgroups (( int ) n
, gids
)) < 0 ) {
1058 pa_log ( "getgroups(): %s" , pa_cstrerror ( errno
));
1062 for ( i
= 0 ; i
< n
; i
++) {
1064 if (( k
= is_group ( gids
[ i
], name
)) < 0 )
1073 if (( k
= is_group ( tgid
= getgid (), name
)) < 0 )
1089 /* Check whether the specifc user id is a member of the specified group */
1090 int pa_uid_in_group ( uid_t uid
, const char * name
) {
1091 struct group
* group
= NULL
;
1096 if (!( group
= pa_getgrnam_malloc ( name
)))
1104 for ( i
= group
-> gr_mem
; * i
; i
++) {
1105 struct passwd
* pw
= NULL
;
1108 if (!( pw
= pa_getpwnam_malloc (* i
)))
1111 if ( pw
-> pw_uid
== uid
)
1114 pa_getpwnam_free ( pw
);
1121 pa_getgrnam_free ( group
);
1126 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
1127 gid_t
pa_get_gid_of_group ( const char * name
) {
1128 gid_t ret
= ( gid_t
) - 1 ;
1129 struct group
* gr
= NULL
;
1132 if (!( gr
= pa_getgrnam_malloc ( name
)))
1142 pa_getgrnam_free ( gr
);
1146 int pa_check_in_group ( gid_t g
) {
1147 gid_t gids
[ NGROUPS_MAX
];
1150 if (( r
= getgroups ( NGROUPS_MAX
, gids
)) < 0 )
1160 #else /* HAVE_GRP_H */
1162 int pa_own_uid_in_group ( const char * name
, gid_t
* gid
) {
1168 int pa_uid_in_group ( uid_t uid
, const char * name
) {
1173 gid_t
pa_get_gid_of_group ( const char * name
) {
1178 int pa_check_in_group ( gid_t g
) {
1185 /* Lock or unlock a file entirely.
1186 (advisory on UNIX, mandatory on Windows) */
1187 int pa_lock_fd ( int fd
, int b
) {
1189 struct flock f_lock
;
1191 /* Try a R/W lock first */
1193 f_lock
. l_type
= ( short ) ( b
? F_WRLCK
: F_UNLCK
);
1194 f_lock
. l_whence
= SEEK_SET
;
1198 if ( fcntl ( fd
, F_SETLKW
, & f_lock
) >= 0 )
1201 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1202 if ( b
&& errno
== EBADF
) {
1203 f_lock
. l_type
= F_RDLCK
;
1204 if ( fcntl ( fd
, F_SETLKW
, & f_lock
) >= 0 )
1208 pa_log ( "%slock: %s" , ! b
? "un" : "" , pa_cstrerror ( errno
));
1212 HANDLE h
= ( HANDLE
) _get_osfhandle ( fd
);
1214 if ( b
&& LockFile ( h
, 0 , 0 , 0xFFFFFFFF , 0xFFFFFFFF ))
1216 if (! b
&& UnlockFile ( h
, 0 , 0 , 0xFFFFFFFF , 0xFFFFFFFF ))
1219 pa_log ( "%slock failed: 0x%08X" , ! b
? "un" : "" , GetLastError ());
1221 /* FIXME: Needs to set errno! */
1227 /* Remove trailing newlines from a string */
1228 char * pa_strip_nl ( char * s
) {
1231 s
[ strcspn ( s
, NEWLINE
)] = 0 ;
1235 char * pa_strip ( char * s
) {
1238 /* Drops trailing whitespace. Modifies the string in
1239 * place. Returns pointer to first non-space character */
1241 s
+= strspn ( s
, WHITESPACE
);
1243 for ( e
= s
; * e
; e
++)
1244 if (! strchr ( WHITESPACE
, * e
))
1255 /* Create a temporary lock file and lock it. */
1256 int pa_lock_lockfile ( const char * fn
) {
1263 if (( fd
= pa_open_cloexec ( fn
, O_CREAT
| O_RDWR
1267 , S_IRUSR
| S_IWUSR
)) < 0 ) {
1268 pa_log_warn ( "Failed to create lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1272 if ( pa_lock_fd ( fd
, 1 ) < 0 ) {
1273 pa_log_warn ( "Failed to lock file '%s'." , fn
);
1277 if ( fstat ( fd
, & st
) < 0 ) {
1278 pa_log_warn ( "Failed to fstat() file '%s': %s" , fn
, pa_cstrerror ( errno
));
1282 /* Check whether the file has been removed meanwhile. When yes,
1283 * restart this loop, otherwise, we're done */
1284 if ( st
. st_nlink
>= 1 )
1287 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1288 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1292 if ( pa_close ( fd
) < 0 ) {
1293 pa_log_warn ( "Failed to close file '%s': %s" , fn
, pa_cstrerror ( errno
));
1304 int saved_errno
= errno
;
1306 errno
= saved_errno
;
1312 /* Unlock a temporary lcok file */
1313 int pa_unlock_lockfile ( const char * fn
, int fd
) {
1318 if ( unlink ( fn
) < 0 ) {
1319 pa_log_warn ( "Unable to remove lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1324 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1325 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1329 if ( pa_close ( fd
) < 0 ) {
1330 pa_log_warn ( "Failed to close '%s': %s" , fn
, pa_cstrerror ( errno
));
1337 static char * get_pulse_home ( void ) {
1342 if (!( h
= pa_get_home_dir_malloc ())) {
1343 pa_log_error ( "Failed to get home directory." );
1347 if ( stat ( h
, & st
) < 0 ) {
1348 pa_log_error ( "Failed to stat home directory %s: %s" , h
, pa_cstrerror ( errno
));
1353 if ( st
. st_uid
!= getuid ()) {
1354 pa_log_error ( "Home directory %s not ours." , h
);
1360 ret
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" , h
);
1368 char * pa_get_state_dir ( void ) {
1371 /* The state directory shall contain dynamic data that should be
1372 * kept across reboots, and is private to this user */
1374 if (!( d
= pa_xstrdup ( getenv ( "PULSE_STATE_PATH" ))))
1375 if (!( d
= get_pulse_home ()))
1378 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1379 * dir then this will break. */
1381 if ( pa_make_secure_dir ( d
, 0700U , ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1382 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1390 char * pa_get_home_dir_malloc ( void ) {
1392 size_t allocated
= 128 ;
1395 homedir
= pa_xmalloc ( allocated
);
1397 if (! pa_get_home_dir ( homedir
, allocated
)) {
1402 if ( strlen ( homedir
) < allocated
- 1 )
1412 char * pa_get_binary_name_malloc ( void ) {
1414 size_t allocated
= 128 ;
1417 t
= pa_xmalloc ( allocated
);
1419 if (! pa_get_binary_name ( t
, allocated
)) {
1424 if ( strlen ( t
) < allocated
- 1 )
1434 static char * make_random_dir ( mode_t m
) {
1435 static const char table
[] =
1436 "abcdefghijklmnopqrstuvwxyz"
1437 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1443 fn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"pulse-XXXXXXXXXXXX" , pa_get_temp_dir ());
1444 pathlen
= strlen ( fn
);
1452 for ( i
= pathlen
- 12 ; i
< pathlen
; i
++)
1453 fn
[ i
] = table
[ rand () % ( sizeof ( table
)- 1 )];
1455 u
= umask ((~ m
) & 0777 );
1462 saved_errno
= errno
;
1464 errno
= saved_errno
;
1469 if ( errno
!= EEXIST
) {
1470 pa_log_error ( "Failed to create random directory %s: %s" , fn
, pa_cstrerror ( errno
));
1477 static int make_random_dir_and_link ( mode_t m
, const char * k
) {
1480 if (!( p
= make_random_dir ( m
)))
1484 if ( symlink ( p
, k
) < 0 ) {
1485 int saved_errno
= errno
;
1487 if ( errno
!= EEXIST
)
1488 pa_log_error ( "Failed to symlink %s to %s: %s" , k
, p
, pa_cstrerror ( errno
));
1493 errno
= saved_errno
;
1502 char * pa_get_runtime_dir ( void ) {
1503 char * d
, * k
= NULL
, * p
= NULL
, * t
= NULL
, * mid
;
1507 /* The runtime directory shall contain dynamic data that needs NOT
1508 * to be kept accross reboots and is usuallly private to the user,
1509 * except in system mode, where it might be accessible by other
1510 * users, too. Since we need POSIX locking and UNIX sockets in
1511 * this directory, we link it to a random subdir in /tmp, if it
1512 * was not explicitly configured. */
1514 m
= pa_in_system_mode () ? 0755U : 0700U ;
1516 if (( d
= getenv ( "PULSE_RUNTIME_PATH" ))) {
1518 if ( pa_make_secure_dir ( d
, m
, ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1519 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1523 return pa_xstrdup ( d
);
1526 if (!( d
= get_pulse_home ()))
1529 if ( pa_make_secure_dir ( d
, m
, ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1530 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1535 if (!( mid
= pa_machine_id ())) {
1540 k
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s-runtime" , d
, mid
);
1545 /* OK, first let's check if the "runtime" symlink is already
1548 if (!( p
= pa_readlink ( k
))) {
1550 if ( errno
!= ENOENT
) {
1551 pa_log_error ( "Failed to stat runtime directory %s: %s" , k
, pa_cstrerror ( errno
));
1555 /* Hmm, so the runtime directory didn't exist yet, so let's
1556 * create one in /tmp and symlink that to it */
1558 if ( make_random_dir_and_link ( 0700 , k
) < 0 ) {
1560 /* Mhmm, maybe another process was quicker than us,
1561 * let's check if that was valid */
1562 if ( errno
== EEXIST
)
1571 /* Make sure that this actually makes sense */
1572 if (! pa_is_path_absolute ( p
)) {
1573 pa_log_error ( "Path %s in link %s is not absolute." , p
, k
);
1578 /* Hmm, so this symlink is still around, make sure nobody fools
1582 if ( lstat ( p
, & st
) < 0 ) {
1584 if ( errno
!= ENOENT
) {
1585 pa_log_error ( "Failed to stat runtime directory %s: %s" , p
, pa_cstrerror ( errno
));
1591 if ( S_ISDIR ( st
. st_mode
) &&
1592 ( st
. st_uid
== getuid ()) &&
1593 (( st
. st_mode
& 0777 ) == 0700 )) {
1599 pa_log_info ( "Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory." );
1606 /* Hmm, so the link points to some nonexisting or invalid
1607 * dir. Let's replace it by a new link. We first create a
1608 * temporary link and then rename that to allow concurrent
1609 * execution of this function. */
1611 t
= pa_sprintf_malloc ( "%s.tmp" , k
);
1613 if ( make_random_dir_and_link ( 0700 , t
) < 0 ) {
1615 if ( errno
!= EEXIST
) {
1616 pa_log_error ( "Failed to symlink %s: %s" , t
, pa_cstrerror ( errno
));
1623 /* Hmm, someone lese was quicker then us. Let's give
1624 * him some time to finish, and retry. */
1629 /* OK, we succeeded in creating the temporary symlink, so
1630 * let's rename it */
1631 if ( rename ( t
, k
) < 0 ) {
1632 pa_log_error ( "Failed to rename %s to %s: %s" , t
, k
, pa_cstrerror ( errno
));
1648 /* Try to open a configuration file. If "env" is specified, open the
1649 * value of the specified environment variable. Otherwise look for a
1650 * file "local" in the home directory or a file "global" in global
1651 * file system. If "result" is non-NULL, a pointer to a newly
1652 * allocated buffer containing the used configuration file is
1654 FILE * pa_open_config_file ( const char * global
, const char * local
, const char * env
, char ** result
) {
1659 if (! getenv ( PULSE_ROOTENV
))
1663 if ( env
&& ( fn
= getenv ( env
))) {
1667 if (! ExpandEnvironmentStrings ( fn
, buf
, PATH_MAX
))
1668 /* FIXME: Needs to set errno! */
1673 if (( f
= pa_fopen_cloexec ( fn
, "r" ))) {
1675 * result
= pa_xstrdup ( fn
);
1680 pa_log_warn ( "Failed to open configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1690 if (( e
= getenv ( "PULSE_CONFIG_PATH" )))
1691 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , e
, local
);
1692 else if (( h
= pa_get_home_dir_malloc ())) {
1693 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s" , h
, local
);
1699 if (! ExpandEnvironmentStrings ( lfn
, buf
, PATH_MAX
)) {
1700 /* FIXME: Needs to set errno! */
1707 if (( f
= pa_fopen_cloexec ( fn
, "r" ))) {
1709 * result
= pa_xstrdup ( fn
);
1715 if ( errno
!= ENOENT
) {
1716 pa_log_warn ( "Failed to open configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1728 if (! ExpandEnvironmentStrings ( global
, buf
, PATH_MAX
))
1729 /* FIXME: Needs to set errno! */
1734 if (( f
= pa_fopen_cloexec ( global
, "r" ))) {
1737 * result
= pa_xstrdup ( global
);
1747 char * pa_find_config_file ( const char * global
, const char * local
, const char * env
) {
1752 if (! getenv ( PULSE_ROOTENV
))
1756 if ( env
&& ( fn
= getenv ( env
))) {
1759 if (! ExpandEnvironmentStrings ( fn
, buf
, PATH_MAX
))
1760 /* FIXME: Needs to set errno! */
1765 if ( access ( fn
, R_OK
) == 0 )
1766 return pa_xstrdup ( fn
);
1768 pa_log_warn ( "Failed to access configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1777 if (( e
= getenv ( "PULSE_CONFIG_PATH" )))
1778 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , e
, local
);
1779 else if (( h
= pa_get_home_dir_malloc ())) {
1780 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s" , h
, local
);
1786 if (! ExpandEnvironmentStrings ( lfn
, buf
, PATH_MAX
)) {
1787 /* FIXME: Needs to set errno! */
1794 if ( access ( fn
, R_OK
) == 0 ) {
1795 char * r
= pa_xstrdup ( fn
);
1800 if ( errno
!= ENOENT
) {
1801 pa_log_warn ( "Failed to access configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1811 if (! ExpandEnvironmentStrings ( global
, buf
, PATH_MAX
))
1812 /* FIXME: Needs to set errno! */
1817 if ( access ( global
, R_OK
) == 0 )
1818 return pa_xstrdup ( global
);
1826 /* Format the specified data as a hexademical string */
1827 char * pa_hexstr ( const uint8_t * d
, size_t dlength
, char * s
, size_t slength
) {
1828 size_t i
= 0 , j
= 0 ;
1829 const char hex
[] = "0123456789abcdef" ;
1833 pa_assert ( slength
> 0 );
1835 while ( i
< dlength
&& j
+ 3 <= slength
) {
1836 s
[ j
++] = hex
[* d
>> 4 ];
1837 s
[ j
++] = hex
[* d
& 0xF ];
1843 s
[ j
< slength
? j
: slength
] = 0 ;
1847 /* Convert a hexadecimal digit to a number or -1 if invalid */
1848 static int hexc ( char c
) {
1849 if ( c
>= '0' && c
<= '9' )
1852 if ( c
>= 'A' && c
<= 'F' )
1853 return c
- 'A' + 10 ;
1855 if ( c
>= 'a' && c
<= 'f' )
1856 return c
- 'a' + 10 ;
1862 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1863 size_t pa_parsehex ( const char * p
, uint8_t * d
, size_t dlength
) {
1869 while ( j
< dlength
&& * p
) {
1872 if (( b
= hexc (*( p
++))) < 0 )
1875 d
[ j
] = ( uint8_t ) ( b
<< 4 );
1880 if (( b
= hexc (*( p
++))) < 0 )
1883 d
[ j
] |= ( uint8_t ) b
;
1890 /* Returns nonzero when *s starts with *pfx */
1891 pa_bool_t
pa_startswith ( const char * s
, const char * pfx
) {
1899 return strlen ( s
) >= l
&& strncmp ( s
, pfx
, l
) == 0 ;
1902 /* Returns nonzero when *s ends with *sfx */
1903 pa_bool_t
pa_endswith ( const char * s
, const char * sfx
) {
1912 return l1
>= l2
&& strcmp ( s
+ l1
- l2
, sfx
) == 0 ;
1915 pa_bool_t
pa_is_path_absolute ( const char * fn
) {
1921 return strlen ( fn
) >= 3 && isalpha ( fn
[ 0 ]) && fn
[ 1 ] == ':' && fn
[ 2 ] == ' \\ ' ;
1925 char * pa_make_path_absolute ( const char * p
) {
1931 if ( pa_is_path_absolute ( p
))
1932 return pa_xstrdup ( p
);
1934 if (!( cwd
= pa_getcwd ()))
1935 return pa_xstrdup ( p
);
1937 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , cwd
, p
);
1942 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1943 * if fn is non-null and starts with / return fn
1944 * otherwise append fn to the run time path and return it */
1945 static char * get_path ( const char * fn
, pa_bool_t prependmid
, pa_bool_t rt
) {
1948 rtp
= rt
? pa_get_runtime_dir () : pa_get_state_dir ();
1953 if ( pa_is_path_absolute ( fn
))
1954 return pa_xstrdup ( fn
);
1962 if (!( mid
= pa_machine_id ())) {
1967 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s-%s" , rtp
, mid
, fn
);
1970 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , rtp
, fn
);
1978 char * pa_runtime_path ( const char * fn
) {
1979 return get_path ( fn
, FALSE
, TRUE
);
1982 char * pa_state_path ( const char * fn
, pa_bool_t appendmid
) {
1983 return get_path ( fn
, appendmid
, FALSE
);
1986 /* Convert the string s to a signed integer in *ret_i */
1987 int pa_atoi ( const char * s
, int32_t * ret_i
) {
1995 l
= strtol ( s
, & x
, 0 );
1997 if (! x
|| * x
|| errno
) {
2003 if (( int32_t ) l
!= l
) {
2008 * ret_i
= ( int32_t ) l
;
2013 /* Convert the string s to an unsigned integer in *ret_u */
2014 int pa_atou ( const char * s
, uint32_t * ret_u
) {
2022 l
= strtoul ( s
, & x
, 0 );
2024 if (! x
|| * x
|| errno
) {
2030 if (( uint32_t ) l
!= l
) {
2035 * ret_u
= ( uint32_t ) l
;
2040 #ifdef HAVE_STRTOF_L
2041 static locale_t c_locale
= NULL
;
2043 static void c_locale_destroy ( void ) {
2044 freelocale ( c_locale
);
2048 int pa_atod ( const char * s
, double * ret_d
) {
2055 /* This should be locale independent */
2057 #ifdef HAVE_STRTOF_L
2061 if (( c_locale
= newlocale ( LC_ALL_MASK
, "C" , NULL
)))
2062 atexit ( c_locale_destroy
);
2068 f
= strtod_l ( s
, & x
, c_locale
);
2076 if (! x
|| * x
|| errno
) {
2087 /* Same as snprintf, but guarantees NUL-termination on every platform */
2088 size_t pa_snprintf ( char * str
, size_t size
, const char * format
, ...) {
2093 pa_assert ( size
> 0 );
2096 va_start ( ap
, format
);
2097 ret
= pa_vsnprintf ( str
, size
, format
, ap
);
2103 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2104 size_t pa_vsnprintf ( char * str
, size_t size
, const char * format
, va_list ap
) {
2108 pa_assert ( size
> 0 );
2111 ret
= vsnprintf ( str
, size
, format
, ap
);
2118 if (( size_t ) ret
> size
- 1 )
2121 return ( size_t ) ret
;
2124 /* Truncate the specified string, but guarantee that the string
2125 * returned still validates as UTF8 */
2126 char * pa_truncate_utf8 ( char * c
, size_t l
) {
2128 pa_assert ( pa_utf8_valid ( c
));
2135 while ( l
> 0 && ! pa_utf8_valid ( c
))
2141 char * pa_getcwd ( void ) {
2145 char * p
= pa_xmalloc ( l
);
2149 if ( errno
!= ERANGE
)
2157 void * pa_will_need ( const void * p
, size_t l
) {
2158 #ifdef RLIMIT_MEMLOCK
2169 a
= PA_PAGE_ALIGN_PTR ( p
);
2170 size
= ( size_t ) (( const uint8_t *) p
+ l
- ( const uint8_t *) a
);
2172 #ifdef HAVE_POSIX_MADVISE
2173 if (( r
= posix_madvise (( void *) a
, size
, POSIX_MADV_WILLNEED
)) == 0 ) {
2174 pa_log_debug ( "posix_madvise() worked fine!" );
2179 /* Most likely the memory was not mmap()ed from a file and thus
2180 * madvise() didn't work, so let's misuse mlock() do page this
2181 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2182 * inviting, the man page of mlock() tells us: "All pages that
2183 * contain a part of the specified address range are guaranteed to
2184 * be resident in RAM when the call returns successfully." */
2186 #ifdef RLIMIT_MEMLOCK
2187 pa_assert_se ( getrlimit ( RLIMIT_MEMLOCK
, & rlim
) == 0 );
2189 if ( rlim
. rlim_cur
< PA_PAGE_SIZE
) {
2190 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
));
2195 bs
= PA_PAGE_ALIGN (( size_t ) rlim
. rlim_cur
);
2197 bs
= PA_PAGE_SIZE
* 4 ;
2200 pa_log_debug ( "posix_madvise() failed (or doesn't exist), trying mlock(): %s" , pa_cstrerror ( r
));
2203 while ( size
> 0 && bs
> 0 ) {
2208 if ( mlock ( a
, bs
) < 0 ) {
2209 bs
= PA_PAGE_ALIGN ( bs
/ 2 );
2213 pa_assert_se ( munlock ( a
, bs
) == 0 );
2215 a
= ( const uint8_t *) a
+ bs
;
2221 pa_log_debug ( "mlock() failed too (or doesn't exist), giving up: %s" , pa_cstrerror ( errno
));
2223 pa_log_debug ( "mlock() worked fine!" );
2228 void pa_close_pipe ( int fds
[ 2 ]) {
2232 pa_assert_se ( pa_close ( fds
[ 0 ]) == 0 );
2235 pa_assert_se ( pa_close ( fds
[ 1 ]) == 0 );
2237 fds
[ 0 ] = fds
[ 1 ] = - 1 ;
2240 char * pa_readlink ( const char * p
) {
2241 #ifdef HAVE_READLINK
2250 if (( n
= readlink ( p
, c
, l
- 1 )) < 0 ) {
2255 if (( size_t ) n
< l
- 1 ) {
2268 int pa_close_all ( int except_fd
, ...) {
2273 va_start ( ap
, except_fd
);
2276 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2281 p
= pa_xnew ( int , n
+ 1 );
2283 va_start ( ap
, except_fd
);
2286 if ( except_fd
>= 0 ) {
2290 while (( fd
= va_arg ( ap
, int )) >= 0 )
2297 r
= pa_close_allv ( p
);
2303 int pa_close_allv ( const int except_fds
[]) {
2312 if (( d
= opendir ( "/proc/self/fd" ))) {
2316 while (( de
= readdir ( d
))) {
2322 if ( de
-> d_name
[ 0 ] == '.' )
2326 l
= strtol ( de
-> d_name
, & e
, 10 );
2327 if ( errno
!= 0 || ! e
|| * e
) {
2335 if (( long ) fd
!= l
) {
2348 for ( i
= 0 ; except_fds
[ i
] >= 0 ; i
++)
2349 if ( except_fds
[ i
] == fd
) {
2357 if ( pa_close ( fd
) < 0 ) {
2358 saved_errno
= errno
;
2360 errno
= saved_errno
;
2372 if ( getrlimit ( RLIMIT_NOFILE
, & rl
) >= 0 )
2373 maxfd
= ( int ) rl
. rlim_max
;
2375 maxfd
= sysconf ( _SC_OPEN_MAX
);
2377 for ( fd
= 3 ; fd
< maxfd
; fd
++) {
2382 for ( i
= 0 ; except_fds
[ i
] >= 0 ; i
++)
2383 if ( except_fds
[ i
] == fd
) {
2391 if ( pa_close ( fd
) < 0 && errno
!= EBADF
)
2394 #endif /* !OS_IS_WIN32 */
2399 int pa_unblock_sigs ( int except
, ...) {
2404 va_start ( ap
, except
);
2407 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2412 p
= pa_xnew ( int , n
+ 1 );
2414 va_start ( ap
, except
);
2421 while (( sig
= va_arg ( ap
, int )) >= 0 )
2428 r
= pa_unblock_sigsv ( p
);
2434 int pa_unblock_sigsv ( const int except
[]) {
2439 if ( sigemptyset (& ss
) < 0 )
2442 for ( i
= 0 ; except
[ i
] > 0 ; i
++)
2443 if ( sigaddset (& ss
, except
[ i
]) < 0 )
2446 return sigprocmask ( SIG_SETMASK
, & ss
, NULL
);
2452 int pa_reset_sigs ( int except
, ...) {
2457 va_start ( ap
, except
);
2460 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2465 p
= pa_xnew ( int , n
+ 1 );
2467 va_start ( ap
, except
);
2474 while (( sig
= va_arg ( ap
, int )) >= 0 )
2481 r
= pa_reset_sigsv ( p
);
2487 int pa_reset_sigsv ( const int except
[]) {
2491 for ( sig
= 1 ; sig
< NSIG
; sig
++) {
2492 pa_bool_t reset
= TRUE
;
2503 for ( i
= 0 ; except
[ i
] > 0 ; i
++) {
2504 if ( sig
== except
[ i
]) {
2513 struct sigaction sa
;
2515 memset (& sa
, 0 , sizeof ( sa
));
2516 sa
. sa_handler
= SIG_DFL
;
2518 /* On Linux the first two RT signals are reserved by
2519 * glibc, and sigaction() will return EINVAL for them. */
2520 if (( sigaction ( sig
, & sa
, NULL
) < 0 ))
2521 if ( errno
!= EINVAL
)
2530 void pa_set_env ( const char * key
, const char * value
) {
2534 /* This is not thread-safe */
2536 setenv ( key
, value
, 1 );
2539 void pa_set_env_and_record ( const char * key
, const char * value
) {
2543 /* This is not thread-safe */
2545 pa_set_env ( key
, value
);
2546 recorded_env
= pa_strlist_prepend ( recorded_env
, key
);
2549 void pa_unset_env_recorded ( void ) {
2551 /* This is not thread-safe */
2556 recorded_env
= pa_strlist_pop ( recorded_env
, & s
);
2566 pa_bool_t
pa_in_system_mode ( void ) {
2569 if (!( e
= getenv ( "PULSE_SYSTEM" )))
2575 char * pa_get_user_name_malloc ( void ) {
2579 #ifdef _SC_LOGIN_NAME_MAX
2580 k
= ( ssize_t
) sysconf ( _SC_LOGIN_NAME_MAX
);
2586 u
= pa_xnew ( char , k
+ 1 );
2588 if (!( pa_get_user_name ( u
, k
))) {
2596 char * pa_get_host_name_malloc ( void ) {
2605 if (! pa_get_host_name ( c
, l
)) {
2607 if ( errno
!= EINVAL
&& errno
!= ENAMETOOLONG
)
2610 } else if ( strlen ( c
) < l
- 1 ) {
2618 u
= pa_utf8_filter ( c
);
2623 /* Hmm, the hostname is as long the space we offered the
2624 * function, we cannot know if it fully fit in, so let's play
2625 * safe and retry. */
2634 char * pa_machine_id ( void ) {
2638 /* The returned value is supposed be some kind of ascii identifier
2639 * that is unique and stable across reboots. */
2641 /* First we try the D-Bus UUID, which is the best option we have,
2642 * since it fits perfectly our needs and is not as volatile as the
2643 * hostname which might be set from dhcp. */
2645 if (( f
= pa_fopen_cloexec ( PA_MACHINE_ID
, "r" ))) {
2646 char ln
[ 34 ] = "" , * r
;
2648 r
= fgets ( ln
, sizeof ( ln
)- 1 , f
);
2654 return pa_utf8_filter ( ln
);
2657 if (( h
= pa_get_host_name_malloc ()))
2661 /* If no hostname was set we use the POSIX hostid. It's usually
2662 * the IPv4 address. Might not be that stable. */
2663 return pa_sprintf_malloc ( "%08lx" , ( unsigned long ) gethostid
);
2669 char * pa_session_id ( void ) {
2672 if (!( e
= getenv ( "XDG_SESSION_COOKIE" )))
2675 return pa_utf8_filter ( e
);
2678 char * pa_uname_string ( void ) {
2681 pa_assert_se ( uname (& u
) >= 0 );
2683 return pa_sprintf_malloc ( "%s %s %s %s" , u
. sysname
, u
. machine
, u
. release
, u
. version
);
2686 #ifdef HAVE_VALGRIND_MEMCHECK_H
2687 pa_bool_t
pa_in_valgrind ( void ) {
2690 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2691 * here instead of really checking whether we run in valgrind or
2695 b
= getenv ( "VALGRIND" ) ? 2 : 1 ;
2701 unsigned pa_gcd ( unsigned a
, unsigned b
) {
2712 void pa_reduce ( unsigned * num
, unsigned * den
) {
2714 unsigned gcd
= pa_gcd (* num
, * den
);
2722 pa_assert ( pa_gcd (* num
, * den
) == 1 );
2725 unsigned pa_ncpus ( void ) {
2728 #ifdef _SC_NPROCESSORS_CONF
2729 ncpus
= sysconf ( _SC_NPROCESSORS_CONF
);
2734 return ncpus
<= 0 ? 1 : ( unsigned ) ncpus
;
2737 char * pa_replace ( const char * s
, const char * a
, const char * b
) {
2746 sb
= pa_strbuf_new ();
2751 if (!( p
= strstr ( s
, a
)))
2754 pa_strbuf_putsn ( sb
, s
, p
- s
);
2755 pa_strbuf_puts ( sb
, b
);
2759 pa_strbuf_puts ( sb
, s
);
2761 return pa_strbuf_tostring_free ( sb
);
2764 char * pa_escape ( const char * p
, const char * chars
) {
2767 pa_strbuf
* buf
= pa_strbuf_new ();
2769 for ( s
= p
; * s
; ++ s
) {
2771 pa_strbuf_putc ( buf
, ' \\ ' );
2773 for ( c
= chars
; * c
; ++ c
) {
2775 pa_strbuf_putc ( buf
, ' \\ ' );
2780 pa_strbuf_putc ( buf
, * s
);
2783 return pa_strbuf_tostring_free ( buf
);
2786 char * pa_unescape ( char * p
) {
2788 pa_bool_t escaped
= FALSE
;
2790 for ( s
= p
, d
= p
; * s
; s
++) {
2791 if (! escaped
&& * s
== ' \\ ' ) {
2805 char * pa_realpath ( const char * path
) {
2809 /* We want only abolsute paths */
2810 if ( path
[ 0 ] != '/' ) {
2815 #if defined(__GLIBC__) || defined(__APPLE__)
2819 if (!( r
= realpath ( path
, NULL
)))
2822 /* We copy this here in case our pa_xmalloc() is not
2823 * implemented on top of libc malloc() */
2827 #elif defined(PATH_MAX)
2830 path_buf
= pa_xmalloc ( PATH_MAX
);
2832 if (!( t
= realpath ( path
, path_buf
))) {
2838 #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."
2844 void pa_disable_sigpipe ( void ) {
2847 struct sigaction sa
;
2851 if ( sigaction ( SIGPIPE
, NULL
, & sa
) < 0 ) {
2852 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
2856 sa
. sa_handler
= SIG_IGN
;
2858 if ( sigaction ( SIGPIPE
, & sa
, NULL
) < 0 ) {
2859 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
2865 void pa_xfreev ( void ** a
) {
2871 for ( p
= a
; * p
; p
++)
2877 char ** pa_split_spaces_strv ( const char * s
) {
2879 unsigned i
= 0 , n
= 8 ;
2880 const char * state
= NULL
;
2882 t
= pa_xnew ( char *, n
);
2883 while (( e
= pa_split_spaces ( s
, & state
))) {
2888 t
= pa_xrenew ( char *, t
, n
);
2901 char * pa_maybe_prefix_path ( const char * path
, const char * prefix
) {
2904 if ( pa_is_path_absolute ( path
))
2905 return pa_xstrdup ( path
);
2907 return pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , prefix
, path
);
2910 size_t pa_pipe_buf ( int fd
) {
2915 if (( n
= fpathconf ( fd
, _PC_PIPE_BUF
)) >= 0 )
2926 void pa_reset_personality ( void ) {
2929 if ( personality ( PER_LINUX
) < 0 )
2930 pa_log_warn ( "Uh, personality() failed: %s" , pa_cstrerror ( errno
));
2935 #if defined(__linux__) && !defined(__OPTIMIZE__)
2937 pa_bool_t
pa_run_from_build_tree ( void ) {
2939 pa_bool_t b
= FALSE
;
2941 /* We abuse __OPTIMIZE__ as a check whether we are a debug build
2944 if (( rp
= pa_readlink ( "/proc/self/exe" ))) {
2945 b
= pa_startswith ( rp
, PA_BUILDDIR
);
2954 const char * pa_get_temp_dir ( void ) {
2957 if (( t
= getenv ( "TMPDIR" )) &&
2958 pa_is_path_absolute ( t
))
2961 if (( t
= getenv ( "TMP" )) &&
2962 pa_is_path_absolute ( t
))
2965 if (( t
= getenv ( "TEMP" )) &&
2966 pa_is_path_absolute ( t
))
2969 if (( t
= getenv ( "TEMPDIR" )) &&
2970 pa_is_path_absolute ( t
))
2976 int pa_open_cloexec ( const char * fn
, int flags
, mode_t mode
) {
2984 if (( fd
= open ( fn
, flags
| O_CLOEXEC
, mode
)) >= 0 )
2987 if ( errno
!= EINVAL
)
2991 if (( fd
= open ( fn
, flags
, mode
)) < 0 )
2995 /* Some implementations might simply ignore O_CLOEXEC if it is not
2996 * understood, make sure FD_CLOEXEC is enabled anyway */
2998 pa_make_fd_cloexec ( fd
);
3002 int pa_socket_cloexec ( int domain
, int type
, int protocol
) {
3006 if (( fd
= socket ( domain
, type
| SOCK_CLOEXEC
, protocol
)) >= 0 )
3009 if ( errno
!= EINVAL
)
3013 if (( fd
= socket ( domain
, type
, protocol
)) < 0 )
3017 /* Some implementations might simply ignore SOCK_CLOEXEC if it is
3018 * not understood, make sure FD_CLOEXEC is enabled anyway */
3020 pa_make_fd_cloexec ( fd
);
3024 int pa_pipe_cloexec ( int pipefd
[ 2 ]) {
3028 if (( r
= pipe2 ( pipefd
, O_CLOEXEC
)) >= 0 )
3031 if ( errno
!= EINVAL
&& errno
!= ENOSYS
)
3036 if (( r
= pipe ( pipefd
)) < 0 )
3040 pa_make_fd_cloexec ( pipefd
[ 0 ]);
3041 pa_make_fd_cloexec ( pipefd
[ 1 ]);
3046 int pa_accept_cloexec ( int sockfd
, struct sockaddr
* addr
, socklen_t
* addrlen
) {
3050 if (( fd
= accept4 ( sockfd
, addr
, addrlen
, SOCK_CLOEXEC
)) >= 0 )
3053 if ( errno
!= EINVAL
&& errno
!= ENOSYS
)
3058 if (( fd
= accept ( sockfd
, addr
, addrlen
)) < 0 )
3062 pa_make_fd_cloexec ( fd
);
3066 FILE * pa_fopen_cloexec ( const char * path
, const char * mode
) {
3070 m
= pa_sprintf_malloc ( "%se" , mode
);
3073 if (( f
= fopen ( path
, m
))) {
3080 if ( errno
!= EINVAL
)
3083 if (!( f
= fopen ( path
, mode
)))
3087 pa_make_fd_cloexec ( fileno ( f
));
3091 void pa_nullify_stdfds ( void ) {
3094 pa_close ( STDIN_FILENO
);
3095 pa_close ( STDOUT_FILENO
);
3096 pa_close ( STDERR_FILENO
);
3098 pa_assert_se ( open ( "/dev/null" , O_RDONLY
) == STDIN_FILENO
);
3099 pa_assert_se ( open ( "/dev/null" , O_WRONLY
) == STDOUT_FILENO
);
3100 pa_assert_se ( open ( "/dev/null" , O_WRONLY
) == STDERR_FILENO
);
3107 char * pa_read_line_from_file ( const char * fn
) {
3109 char ln
[ 256 ] = "" , * r
;
3111 if (!( f
= pa_fopen_cloexec ( fn
, "r" )))
3114 r
= fgets ( ln
, sizeof ( ln
)- 1 , f
);
3123 return pa_xstrdup ( ln
);
3126 pa_bool_t
pa_running_in_vm ( void ) {
3128 #if defined(__i386__) || defined(__x86_64__)
3130 /* Both CPUID and DMI are x86 specific interfaces... */
3132 uint32_t eax
= 0x40000000 ;
3139 const char * const dmi_vendors
[] = {
3140 "/sys/class/dmi/id/sys_vendor" ,
3141 "/sys/class/dmi/id/board_vendor" ,
3142 "/sys/class/dmi/id/bios_vendor"
3147 for ( i
= 0 ; i
< PA_ELEMENTSOF ( dmi_vendors
); i
++) {
3150 if (( s
= pa_read_line_from_file ( dmi_vendors
[ i
]))) {
3152 if ( pa_startswith ( s
, "QEMU" ) ||
3153 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3154 pa_startswith ( s
, "VMware" ) ||
3155 pa_startswith ( s
, "VMW" ) ||
3156 pa_startswith ( s
, "Microsoft Corporation" ) ||
3157 pa_startswith ( s
, "innotek GmbH" ) ||
3158 pa_startswith ( s
, "Xen" )) {
3170 /* http://lwn.net/Articles/301888/ */
3173 __asm__
__volatile__ (
3174 /* ebx/rbx is being used for PIC! */
3175 " push %%" PA_REG_b
" \n\t "
3177 " mov %%ebx, %1 \n\t "
3178 " pop %%" PA_REG_b
" \n\t "
3180 : "=a" ( eax
), "=r" ( sig
. sig32
[ 0 ]), "=c" ( sig
. sig32
[ 1 ]), "=d" ( sig
. sig32
[ 2 ])
3184 if ( pa_streq ( sig
. text
, "XenVMMXenVMM" ) ||
3185 pa_streq ( sig
. text
, "KVMKVMKVM" ) ||
3186 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3187 pa_streq ( sig
. text
, "VMwareVMware" ) ||
3188 /* http://msdn.microsoft.com/en-us/library/bb969719.aspx */
3189 pa_streq ( sig
. text
, "Microsoft Hv" ))