]>
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 #include <sys/utsname.h>
46 #include <sys/socket.h>
55 #if defined(__linux__) && !defined(SCHED_RESET_ON_FORK)
56 #define SCHED_RESET_ON_FORK 0x40000000
60 #ifdef HAVE_SYS_RESOURCE_H
61 #include <sys/resource.h>
64 #ifdef HAVE_SYS_CAPABILITY_H
65 #include <sys/capability.h>
68 #ifdef HAVE_SYS_MMAN_H
92 #ifdef HAVE_LIBSAMPLERATE
93 #include <samplerate.h>
105 #include <sys/personality.h>
108 #include <pulse/xmalloc.h>
109 #include <pulse/util.h>
110 #include <pulse/utf8.h>
112 #include <pulsecore/core-error.h>
113 #include <pulsecore/winsock.h>
114 #include <pulsecore/log.h>
115 #include <pulsecore/macro.h>
116 #include <pulsecore/thread.h>
117 #include <pulsecore/strbuf.h>
119 #include "core-util.h"
121 /* Not all platforms have this */
123 #define MSG_NOSIGNAL 0
128 #define PULSE_ROOTENV "PULSE_ROOT"
130 int pa_set_root ( HANDLE handle
) {
131 char library_path
[ MAX_PATH
+ sizeof ( PULSE_ROOTENV
) + 1 ], * sep
;
133 strcpy ( library_path
, PULSE_ROOTENV
"=" );
135 /* FIXME: Needs to set errno */
137 if (! GetModuleFileName ( handle
, library_path
+ sizeof ( PULSE_ROOTENV
), MAX_PATH
))
140 sep
= strrchr ( library_path
, PA_PATH_SEP_CHAR
);
144 if ( _putenv ( library_path
) < 0 )
152 /** Make a file descriptor nonblock. Doesn't do any error checking */
153 void pa_make_fd_nonblock ( int fd
) {
159 pa_assert_se (( v
= fcntl ( fd
, F_GETFL
)) >= 0 );
161 if (!( v
& O_NONBLOCK
))
162 pa_assert_se ( fcntl ( fd
, F_SETFL
, v
| O_NONBLOCK
) >= 0 );
164 #elif defined(OS_IS_WIN32)
166 if ( ioctlsocket ( fd
, FIONBIO
, & arg
) < 0 ) {
167 pa_assert_se ( WSAGetLastError () == WSAENOTSOCK
);
168 pa_log_warn ( "Only sockets can be made non-blocking!" );
171 pa_log_warn ( "Non-blocking I/O not supported.!" );
176 /* Set the FD_CLOEXEC flag for a fd */
177 void pa_make_fd_cloexec ( int fd
) {
183 pa_assert_se (( v
= fcntl ( fd
, F_GETFD
, 0 )) >= 0 );
185 if (!( v
& FD_CLOEXEC
))
186 pa_assert_se ( fcntl ( fd
, F_SETFD
, v
| FD_CLOEXEC
) >= 0 );
191 /** Creates a directory securely */
192 int pa_make_secure_dir ( const char * dir
, mode_t m
, uid_t uid
, gid_t gid
) {
203 u
= umask ((~ m
) & 0777 );
209 if ( r
< 0 && errno
!= EEXIST
)
213 if ( uid
== ( uid_t
)- 1 )
215 if ( gid
== ( gid_t
)- 1 )
217 ( void ) chown ( dir
, uid
, gid
);
225 if ( lstat ( dir
, & st
) < 0 )
227 if ( stat ( dir
, & st
) < 0 )
232 if (! S_ISDIR ( st
. st_mode
) ||
233 ( st
. st_uid
!= uid
) ||
234 ( st
. st_gid
!= gid
) ||
235 (( st
. st_mode
& 0777 ) != m
)) {
240 pa_log_warn ( "Secure directory creation not supported on Win32." );
253 /* Return a newly allocated sting containing the parent directory of the specified file */
254 char * pa_parent_dir ( const char * fn
) {
255 char * slash
, * dir
= pa_xstrdup ( fn
);
257 if (( slash
= ( char *) pa_path_get_filename ( dir
)) == dir
) {
267 /* Creates a the parent directory of the specified path securely */
268 int pa_make_secure_parent_dir ( const char * fn
, mode_t m
, uid_t uid
, gid_t gid
) {
272 if (!( dir
= pa_parent_dir ( fn
)))
275 if ( pa_make_secure_dir ( dir
, m
, uid
, gid
) < 0 )
285 /** Platform independent read function. Necessary since not all
286 * systems treat all file descriptors equal. If type is
287 * non-NULL it is used to cache the type of the fd. This is
288 * useful for making sure that only a single syscall is executed per
289 * function call. The variable pointed to should be initialized to 0
291 ssize_t
pa_read ( int fd
, void * buf
, size_t count
, int * type
) {
295 if (! type
|| * type
== 0 ) {
298 if (( r
= recv ( fd
, buf
, count
, 0 )) >= 0 )
301 if ( WSAGetLastError () != WSAENOTSOCK
) {
302 errno
= WSAGetLastError ();
315 if (( r
= read ( fd
, buf
, count
)) < 0 )
323 /** Similar to pa_read(), but handles writes */
324 ssize_t
pa_write ( int fd
, const void * buf
, size_t count
, int * type
) {
326 if (! type
|| * type
== 0 ) {
330 if (( r
= send ( fd
, buf
, count
, MSG_NOSIGNAL
)) < 0 ) {
342 if ( WSAGetLastError () != WSAENOTSOCK
) {
343 errno
= WSAGetLastError ();
347 if ( errno
!= ENOTSOCK
)
358 if (( r
= write ( fd
, buf
, count
)) < 0 )
366 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
367 * unless EOF is reached or an error occurred */
368 ssize_t
pa_loop_read ( int fd
, void * data
, size_t size
, int * type
) {
384 if (( r
= pa_read ( fd
, data
, size
, type
)) < 0 )
391 data
= ( uint8_t *) data
+ r
;
398 /** Similar to pa_loop_read(), but wraps write() */
399 ssize_t
pa_loop_write ( int fd
, const void * data
, size_t size
, int * type
) {
415 if (( r
= pa_write ( fd
, data
, size
, type
)) < 0 )
422 data
= ( const uint8_t *) data
+ r
;
429 /** Platform independent read function. Necessary since not all
430 * systems treat all file descriptors equal. */
431 int pa_close ( int fd
) {
436 if (( ret
= closesocket ( fd
)) == 0 )
439 if ( WSAGetLastError () != WSAENOTSOCK
) {
440 errno
= WSAGetLastError ();
448 if (( r
= close ( fd
)) < 0 )
456 /* Print a warning messages in case that the given signal is not
457 * blocked or trapped */
458 void pa_check_signal_is_blocked ( int sig
) {
459 #ifdef HAVE_SIGACTION
463 /* If POSIX threads are supported use thread-aware
464 * pthread_sigmask() function, to check if the signal is
465 * blocked. Otherwise fall back to sigprocmask() */
468 if ( pthread_sigmask ( SIG_SETMASK
, NULL
, & set
) < 0 ) {
470 if ( sigprocmask ( SIG_SETMASK
, NULL
, & set
) < 0 ) {
471 pa_log ( "sigprocmask(): %s" , pa_cstrerror ( errno
));
478 if ( sigismember (& set
, sig
))
481 /* Check whether the signal is trapped */
483 if ( sigaction ( sig
, NULL
, & sa
) < 0 ) {
484 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
488 if ( sa
. sa_handler
!= SIG_DFL
)
491 pa_log_warn ( "%s is not trapped. This might cause malfunction!" , pa_sig2str ( sig
));
492 #else /* HAVE_SIGACTION */
493 pa_log_warn ( "%s might not be trapped. This might cause malfunction!" , pa_sig2str ( sig
));
497 /* The following function is based on an example from the GNU libc
498 * documentation. This function is similar to GNU's asprintf(). */
499 char * pa_sprintf_malloc ( const char * format
, ...) {
509 c
= pa_xrealloc ( c
, size
);
511 va_start ( ap
, format
);
512 r
= vsnprintf ( c
, size
, format
, ap
);
517 if ( r
> - 1 && ( size_t ) r
< size
)
520 if ( r
> - 1 ) /* glibc 2.1 */
527 /* Same as the previous function, but use a va_list instead of an
529 char * pa_vsprintf_malloc ( const char * format
, va_list ap
) {
539 c
= pa_xrealloc ( c
, size
);
542 r
= vsnprintf ( c
, size
, format
, aq
);
547 if ( r
> - 1 && ( size_t ) r
< size
)
550 if ( r
> - 1 ) /* glibc 2.1 */
557 /* Similar to OpenBSD's strlcpy() function */
558 char * pa_strlcpy ( char * b
, const char * s
, size_t l
) {
576 static int set_scheduler ( int rtprio
) {
577 struct sched_param sp
;
583 dbus_error_init (& error
);
587 sp
. sched_priority
= rtprio
;
589 #ifdef SCHED_RESET_ON_FORK
590 if (( r
= pthread_setschedparam ( pthread_self (), SCHED_RR
| SCHED_RESET_ON_FORK
, & sp
)) == 0 ) {
591 pa_log_debug ( "SCHED_RR|SCHED_RESET_ON_FORK worked." );
596 if (( r
= pthread_setschedparam ( pthread_self (), SCHED_RR
, & sp
)) == 0 ) {
597 pa_log_debug ( "SCHED_RR worked." );
602 /* Try to talk to RealtimeKit */
604 if (!( bus
= dbus_bus_get ( DBUS_BUS_SYSTEM
, & error
))) {
605 pa_log ( "Failed to connect to system bus: %s \n " , error
. message
);
606 dbus_error_free (& error
);
611 r
= rtkit_make_realtime ( bus
, 0 , rtprio
);
612 dbus_connection_unref ( bus
);
615 pa_log_debug ( "RealtimeKit worked." );
627 /* Make the current thread a realtime thread, and acquire the highest
628 * rtprio we can get that is less or equal the specified parameter. If
629 * the thread is already realtime, don't do anything. */
630 int pa_make_realtime ( int rtprio
) {
632 #ifdef _POSIX_PRIORITY_SCHEDULING
635 if ( set_scheduler ( rtprio
) >= 0 ) {
636 pa_log_info ( "Successfully enabled SCHED_RR scheduling for thread, with priority %i." , rtprio
);
640 for ( p
= rtprio
- 1 ; p
>= 1 ; p
--)
641 if ( set_scheduler ( p
)) {
642 pa_log_info ( "Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i." , p
, rtprio
);
646 pa_log_info ( "Failed to acquire real-time scheduling: %s" , pa_cstrerror ( errno
));
655 static int set_nice ( int nice_level
) {
661 dbus_error_init (& error
);
664 if ( setpriority ( PRIO_PROCESS
, 0 , nice_level
) >= 0 ) {
665 pa_log_debug ( "setpriority() worked." );
670 /* Try to talk to RealtimeKit */
672 if (!( bus
= dbus_bus_get ( DBUS_BUS_SYSTEM
, & error
))) {
673 pa_log ( "Failed to connect to system bus: %s \n " , error
. message
);
674 dbus_error_free (& error
);
679 r
= rtkit_make_high_priority ( bus
, 0 , nice_level
);
680 dbus_connection_unref ( bus
);
683 pa_log_debug ( "RealtimeKit worked." );
693 /* Raise the priority of the current process as much as possible that
694 * is <= the specified nice level..*/
695 int pa_raise_priority ( int nice_level
) {
697 #ifdef HAVE_SYS_RESOURCE_H
700 if ( set_nice ( nice_level
) >= 0 ) {
701 pa_log_info ( "Successfully gained nice level %i." , nice_level
);
705 for ( n
= nice_level
+ 1 ; n
< 0 ; n
++)
706 if ( set_nice ( n
) > 0 ) {
707 pa_log_info ( "Successfully acquired nice level %i, which is lower than the requested %i." , n
, nice_level
);
711 pa_log_info ( "Failed to acquire high-priority scheduling: %s" , pa_cstrerror ( errno
));
716 if ( nice_level
< 0 ) {
717 if (! SetPriorityClass ( GetCurrentProcess (), HIGH_PRIORITY_CLASS
)) {
718 pa_log_warn ( "SetPriorityClass() failed: 0x%08X" , GetLastError ());
723 pa_log_info ( "Successfully gained high priority class." );
730 /* Reset the priority to normal, inverting the changes made by
731 * pa_raise_priority() and pa_make_realtime()*/
732 void pa_reset_priority ( void ) {
733 #ifdef HAVE_SYS_RESOURCE_H
734 struct sched_param sp
;
736 setpriority ( PRIO_PROCESS
, 0 , 0 );
739 pthread_setschedparam ( pthread_self (), SCHED_OTHER
, & sp
);
743 SetPriorityClass ( GetCurrentProcess (), NORMAL_PRIORITY_CLASS
);
747 int pa_match ( const char * expr
, const char * v
) {
752 if ( regcomp (& re
, expr
, REG_NOSUB
| REG_EXTENDED
) != 0 ) {
757 if (( k
= regexec (& re
, v
, 0 , NULL
, 0 )) == 0 )
759 else if ( k
== REG_NOMATCH
)
772 /* Try to parse a boolean string value.*/
773 int pa_parse_boolean ( const char * v
) {
778 /* First we check language independant */
779 if (! strcmp ( v
, "1" ) || v
[ 0 ] == 'y' || v
[ 0 ] == 'Y' || v
[ 0 ] == 't' || v
[ 0 ] == 'T' || ! strcasecmp ( v
, "on" ))
781 else if (! strcmp ( v
, "0" ) || v
[ 0 ] == 'n' || v
[ 0 ] == 'N' || v
[ 0 ] == 'f' || v
[ 0 ] == 'F' || ! strcasecmp ( v
, "off" ))
784 /* And then we check language dependant */
785 if (( expr
= nl_langinfo ( YESEXPR
)))
787 if (( r
= pa_match ( expr
, v
)) > 0 )
790 if (( expr
= nl_langinfo ( NOEXPR
)))
792 if (( r
= pa_match ( expr
, v
)) > 0 )
799 /* Split the specified string wherever one of the strings in delimiter
800 * occurs. Each time it is called returns a newly allocated string
801 * with pa_xmalloc(). The variable state points to, should be
802 * initiallized to NULL before the first call. */
803 char * pa_split ( const char * c
, const char * delimiter
, const char ** state
) {
804 const char * current
= * state
? * state
: c
;
810 l
= strcspn ( current
, delimiter
);
816 return pa_xstrndup ( current
, l
);
819 /* What is interpreted as whitespace? */
820 #define WHITESPACE " \t\n "
822 /* Split a string into words. Otherwise similar to pa_split(). */
823 char * pa_split_spaces ( const char * c
, const char ** state
) {
824 const char * current
= * state
? * state
: c
;
827 if (!* current
|| * c
== 0 )
830 current
+= strspn ( current
, WHITESPACE
);
831 l
= strcspn ( current
, WHITESPACE
);
835 return pa_xstrndup ( current
, l
);
838 PA_STATIC_TLS_DECLARE ( signame
, pa_xfree
);
840 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
841 const char * pa_sig2str ( int sig
) {
854 char buf
[ SIG2STR_MAX
];
856 if ( sig2str ( sig
, buf
) == 0 ) {
857 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
858 t
= pa_sprintf_malloc ( "SIG%s" , buf
);
859 PA_STATIC_TLS_SET ( signame
, t
);
867 case SIGHUP
: return "SIGHUP" ;
869 case SIGINT
: return "SIGINT" ;
871 case SIGQUIT
: return "SIGQUIT" ;
873 case SIGILL
: return "SIGULL" ;
875 case SIGTRAP
: return "SIGTRAP" ;
877 case SIGABRT
: return "SIGABRT" ;
879 case SIGBUS
: return "SIGBUS" ;
881 case SIGFPE
: return "SIGFPE" ;
883 case SIGKILL
: return "SIGKILL" ;
886 case SIGUSR1
: return "SIGUSR1" ;
888 case SIGSEGV
: return "SIGSEGV" ;
890 case SIGUSR2
: return "SIGUSR2" ;
893 case SIGPIPE
: return "SIGPIPE" ;
896 case SIGALRM
: return "SIGALRM" ;
898 case SIGTERM
: return "SIGTERM" ;
900 case SIGSTKFLT
: return "SIGSTKFLT" ;
903 case SIGCHLD
: return "SIGCHLD" ;
906 case SIGCONT
: return "SIGCONT" ;
909 case SIGSTOP
: return "SIGSTOP" ;
912 case SIGTSTP
: return "SIGTSTP" ;
915 case SIGTTIN
: return "SIGTTIN" ;
918 case SIGTTOU
: return "SIGTTOU" ;
921 case SIGURG
: return "SIGURG" ;
924 case SIGXCPU
: return "SIGXCPU" ;
927 case SIGXFSZ
: return "SIGXFSZ" ;
930 case SIGVTALRM
: return "SIGVTALRM" ;
933 case SIGPROF
: return "SIGPROF" ;
936 case SIGWINCH
: return "SIGWINCH" ;
939 case SIGIO
: return "SIGIO" ;
942 case SIGPWR
: return "SIGPWR" ;
945 case SIGSYS
: return "SIGSYS" ;
950 if ( sig
>= SIGRTMIN
&& sig
<= SIGRTMAX
) {
951 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
952 t
= pa_sprintf_malloc ( "SIGRTMIN+%i" , sig
- SIGRTMIN
);
953 PA_STATIC_TLS_SET ( signame
, t
);
962 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
963 t
= pa_sprintf_malloc ( "SIG%i" , sig
);
964 PA_STATIC_TLS_SET ( signame
, t
);
970 /* Check whether the specified GID and the group name match */
971 static int is_group ( gid_t gid
, const char * name
) {
972 struct group group
, * result
= NULL
;
977 #ifdef HAVE_GETGRGID_R
979 #ifdef _SC_GETGR_R_SIZE_MAX
980 n
= sysconf ( _SC_GETGR_R_SIZE_MAX
);
987 data
= pa_xmalloc (( size_t ) n
);
989 if (( errno
= getgrgid_r ( gid
, & group
, data
, ( size_t ) n
, & result
)) || ! result
)
992 if (!( result
= getgrgid ( gid
)))
998 pa_log ( "getgrgid(%u): %s" , gid
, pa_cstrerror ( errno
));
1003 r
= strcmp ( name
, result
-> gr_name
) == 0 ;
1012 /* Check the current user is member of the specified group */
1013 int pa_own_uid_in_group ( const char * name
, gid_t
* gid
) {
1014 GETGROUPS_T
* gids
, tgid
;
1015 long n
= sysconf ( _SC_NGROUPS_MAX
);
1020 gids
= pa_xmalloc ( sizeof ( GETGROUPS_T
) * ( size_t ) n
);
1022 if (( n
= getgroups (( int ) n
, gids
)) < 0 ) {
1023 pa_log ( "getgroups(): %s" , pa_cstrerror ( errno
));
1027 for ( i
= 0 ; i
< n
; i
++) {
1029 if (( k
= is_group ( gids
[ i
], name
)) < 0 )
1038 if (( k
= is_group ( tgid
= getgid (), name
)) < 0 )
1054 /* Check whether the specifc user id is a member of the specified group */
1055 int pa_uid_in_group ( uid_t uid
, const char * name
) {
1056 char * g_buf
= NULL
, * p_buf
= NULL
;
1058 struct group grbuf
, * gr
= NULL
;
1062 #ifdef HAVE_GETGRNAM_R
1064 #ifdef _SC_GETGR_R_SIZE_MAX
1065 g_n
= sysconf ( _SC_GETGR_R_SIZE_MAX
);
1072 g_buf
= pa_xmalloc (( size_t ) g_n
);
1074 if (( errno
= getgrnam_r ( name
, & grbuf
, g_buf
, ( size_t ) g_n
, & gr
)) != 0 || ! gr
)
1077 if (!( gr
= getgrnam ( name
)))
1085 #ifdef HAVE_GETPWNAM_R
1087 #ifdef _SC_GETPW_R_SIZE_MAX
1088 p_n
= sysconf ( _SC_GETPW_R_SIZE_MAX
);
1095 p_buf
= pa_xmalloc (( size_t ) p_n
);
1099 for ( i
= gr
-> gr_mem
; * i
; i
++) {
1100 struct passwd pwbuf
, * pw
= NULL
;
1102 #ifdef HAVE_GETPWNAM_R
1103 if (( errno
= getpwnam_r (* i
, & pwbuf
, p_buf
, ( size_t ) p_n
, & pw
)) != 0 || ! pw
)
1106 if (!( pw
= getpwnam (* i
)))
1110 if ( pw
-> pw_uid
== uid
) {
1123 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
1124 gid_t
pa_get_gid_of_group ( const char * name
) {
1125 gid_t ret
= ( gid_t
) - 1 ;
1128 struct group grbuf
, * gr
= NULL
;
1130 #ifdef HAVE_GETGRNAM_R
1132 #ifdef _SC_GETGR_R_SIZE_MAX
1133 g_n
= sysconf ( _SC_GETGR_R_SIZE_MAX
);
1140 g_buf
= pa_xmalloc (( size_t ) g_n
);
1142 if (( errno
= getgrnam_r ( name
, & grbuf
, g_buf
, ( size_t ) g_n
, & gr
)) != 0 || ! gr
)
1145 if (!( gr
= getgrnam ( name
)))
1160 int pa_check_in_group ( gid_t g
) {
1161 gid_t gids
[ NGROUPS_MAX
];
1164 if (( r
= getgroups ( NGROUPS_MAX
, gids
)) < 0 )
1174 #else /* HAVE_GRP_H */
1176 int pa_own_uid_in_group ( const char * name
, gid_t
* gid
) {
1182 int pa_uid_in_group ( uid_t uid
, const char * name
) {
1187 gid_t
pa_get_gid_of_group ( const char * name
) {
1192 int pa_check_in_group ( gid_t g
) {
1199 /* Lock or unlock a file entirely.
1200 (advisory on UNIX, mandatory on Windows) */
1201 int pa_lock_fd ( int fd
, int b
) {
1203 struct flock f_lock
;
1205 /* Try a R/W lock first */
1207 f_lock
. l_type
= ( short ) ( b
? F_WRLCK
: F_UNLCK
);
1208 f_lock
. l_whence
= SEEK_SET
;
1212 if ( fcntl ( fd
, F_SETLKW
, & f_lock
) >= 0 )
1215 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1216 if ( b
&& errno
== EBADF
) {
1217 f_lock
. l_type
= F_RDLCK
;
1218 if ( fcntl ( fd
, F_SETLKW
, & f_lock
) >= 0 )
1222 pa_log ( "%slock: %s" , ! b
? "un" : "" , pa_cstrerror ( errno
));
1226 HANDLE h
= ( HANDLE
) _get_osfhandle ( fd
);
1228 if ( b
&& LockFile ( h
, 0 , 0 , 0xFFFFFFFF , 0xFFFFFFFF ))
1230 if (! b
&& UnlockFile ( h
, 0 , 0 , 0xFFFFFFFF , 0xFFFFFFFF ))
1233 pa_log ( "%slock failed: 0x%08X" , ! b
? "un" : "" , GetLastError ());
1235 /* FIXME: Needs to set errno! */
1241 /* Remove trailing newlines from a string */
1242 char * pa_strip_nl ( char * s
) {
1245 s
[ strcspn ( s
, " \r\n " )] = 0 ;
1249 /* Create a temporary lock file and lock it. */
1250 int pa_lock_lockfile ( const char * fn
) {
1257 if (( fd
= open ( fn
, O_CREAT
| O_RDWR
1264 , S_IRUSR
| S_IWUSR
)) < 0 ) {
1265 pa_log_warn ( "Failed to create lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1269 if ( pa_lock_fd ( fd
, 1 ) < 0 ) {
1270 pa_log_warn ( "Failed to lock file '%s'." , fn
);
1274 if ( fstat ( fd
, & st
) < 0 ) {
1275 pa_log_warn ( "Failed to fstat() file '%s': %s" , fn
, pa_cstrerror ( errno
));
1279 /* Check whether the file has been removed meanwhile. When yes,
1280 * restart this loop, otherwise, we're done */
1281 if ( st
. st_nlink
>= 1 )
1284 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1285 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1289 if ( pa_close ( fd
) < 0 ) {
1290 pa_log_warn ( "Failed to close file '%s': %s" , fn
, pa_cstrerror ( errno
));
1303 int saved_errno
= errno
;
1305 errno
= saved_errno
;
1311 /* Unlock a temporary lcok file */
1312 int pa_unlock_lockfile ( const char * fn
, int fd
) {
1317 if ( unlink ( fn
) < 0 ) {
1318 pa_log_warn ( "Unable to remove lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1323 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1324 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1328 if ( pa_close ( fd
) < 0 ) {
1329 pa_log_warn ( "Failed to close '%s': %s" , fn
, pa_cstrerror ( errno
));
1336 static char * get_pulse_home ( void ) {
1341 if (!( h
= pa_get_home_dir_malloc ())) {
1342 pa_log_error ( "Failed to get home directory." );
1346 if ( stat ( h
, & st
) < 0 ) {
1347 pa_log_error ( "Failed to stat home directory %s: %s" , h
, pa_cstrerror ( errno
));
1351 if ( st
. st_uid
!= getuid ()) {
1352 pa_log_error ( "Home directory %s not ours." , h
);
1357 ret
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" , h
);
1365 char * pa_get_state_dir ( void ) {
1368 /* The state directory shall contain dynamic data that should be
1369 * kept across reboots, and is private to this user */
1371 if (!( d
= pa_xstrdup ( getenv ( "PULSE_STATE_PATH" ))))
1372 if (!( d
= get_pulse_home ()))
1375 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1376 * dir then this will break. */
1378 if ( pa_make_secure_dir ( d
, 0700U , ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1379 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1387 char * pa_get_home_dir_malloc ( void ) {
1389 size_t allocated
= 128 ;
1392 homedir
= pa_xmalloc ( allocated
);
1394 if (! pa_get_home_dir ( homedir
, allocated
)) {
1399 if ( strlen ( homedir
) < allocated
- 1 )
1409 char * pa_get_binary_name_malloc ( void ) {
1411 size_t allocated
= 128 ;
1414 t
= pa_xmalloc ( allocated
);
1416 if (! pa_get_binary_name ( t
, allocated
)) {
1421 if ( strlen ( t
) < allocated
- 1 )
1431 static char * make_random_dir ( mode_t m
) {
1432 static const char table
[] =
1433 "abcdefghijklmnopqrstuvwxyz"
1434 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1441 if (!( tmpdir
= getenv ( "TMPDIR" )))
1442 if (!( tmpdir
= getenv ( "TMP" )))
1443 if (!( tmpdir
= getenv ( "TEMP" )))
1444 tmpdir
= getenv ( "TEMPDIR" );
1446 if (! tmpdir
|| ! pa_is_path_absolute ( tmpdir
))
1449 fn
= pa_sprintf_malloc ( "%s/pulse-XXXXXXXXXXXX" , tmpdir
);
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 );
1464 saved_errno
= errno
;
1466 errno
= saved_errno
;
1471 if ( errno
!= EEXIST
) {
1472 pa_log_error ( "Failed to create random directory %s: %s" , fn
, pa_cstrerror ( errno
));
1479 static int make_random_dir_and_link ( mode_t m
, const char * k
) {
1482 if (!( p
= make_random_dir ( m
)))
1485 if ( symlink ( p
, k
) < 0 ) {
1486 int saved_errno
= errno
;
1488 if ( errno
!= EEXIST
)
1489 pa_log_error ( "Failed to symlink %s to %s: %s" , k
, p
, pa_cstrerror ( errno
));
1494 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
1581 if ( lstat ( p
, & st
) < 0 ) {
1583 if ( errno
!= ENOENT
) {
1584 pa_log_error ( "Failed to stat runtime directory %s: %s" , p
, pa_cstrerror ( errno
));
1590 if ( S_ISDIR ( st
. st_mode
) &&
1591 ( st
. st_uid
== getuid ()) &&
1592 (( st
. st_mode
& 0777 ) == 0700 )) {
1598 pa_log_info ( "Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory." );
1604 /* Hmm, so the link points to some nonexisting or invalid
1605 * dir. Let's replace it by a new link. We first create a
1606 * temporary link and then rename that to allow concurrent
1607 * execution of this function. */
1609 t
= pa_sprintf_malloc ( "%s.tmp" , k
);
1611 if ( make_random_dir_and_link ( 0700 , t
) < 0 ) {
1613 if ( errno
!= EEXIST
) {
1614 pa_log_error ( "Failed to symlink %s: %s" , t
, pa_cstrerror ( errno
));
1621 /* Hmm, someone lese was quicker then us. Let's give
1622 * him some time to finish, and retry. */
1627 /* OK, we succeeded in creating the temporary symlink, so
1628 * let's rename it */
1629 if ( rename ( t
, k
) < 0 ) {
1630 pa_log_error ( "Failed to rename %s to %s: %s" , t
, k
, pa_cstrerror ( errno
));
1646 /* Try to open a configuration file. If "env" is specified, open the
1647 * value of the specified environment variable. Otherwise look for a
1648 * file "local" in the home directory or a file "global" in global
1649 * file system. If "result" is non-NULL, a pointer to a newly
1650 * allocated buffer containing the used configuration file is
1652 FILE * pa_open_config_file ( const char * global
, const char * local
, const char * env
, char ** result
) {
1657 if (! getenv ( PULSE_ROOTENV
))
1661 if ( env
&& ( fn
= getenv ( env
))) {
1665 if (! ExpandEnvironmentStrings ( fn
, buf
, PATH_MAX
))
1666 /* FIXME: Needs to set errno! */
1671 if (( f
= fopen ( fn
, "r" ))) {
1673 * result
= pa_xstrdup ( fn
);
1678 pa_log_warn ( "Failed to open configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1688 if (( e
= getenv ( "PULSE_CONFIG_PATH" )))
1689 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , e
, local
);
1690 else if (( h
= pa_get_home_dir_malloc ())) {
1691 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s" , h
, local
);
1697 if (! ExpandEnvironmentStrings ( lfn
, buf
, PATH_MAX
)) {
1698 /* FIXME: Needs to set errno! */
1705 if (( f
= fopen ( fn
, "r" ))) {
1707 * result
= pa_xstrdup ( fn
);
1713 if ( errno
!= ENOENT
) {
1714 pa_log_warn ( "Failed to open configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1726 if (! ExpandEnvironmentStrings ( global
, buf
, PATH_MAX
))
1727 /* FIXME: Needs to set errno! */
1732 if (( f
= fopen ( global
, "r" ))) {
1735 * result
= pa_xstrdup ( global
);
1745 char * pa_find_config_file ( const char * global
, const char * local
, const char * env
) {
1750 if (! getenv ( PULSE_ROOTENV
))
1754 if ( env
&& ( fn
= getenv ( env
))) {
1757 if (! ExpandEnvironmentStrings ( fn
, buf
, PATH_MAX
))
1758 /* FIXME: Needs to set errno! */
1763 if ( access ( fn
, R_OK
) == 0 )
1764 return pa_xstrdup ( fn
);
1766 pa_log_warn ( "Failed to access configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1775 if (( e
= getenv ( "PULSE_CONFIG_PATH" )))
1776 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , e
, local
);
1777 else if (( h
= pa_get_home_dir_malloc ())) {
1778 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s" , h
, local
);
1784 if (! ExpandEnvironmentStrings ( lfn
, buf
, PATH_MAX
)) {
1785 /* FIXME: Needs to set errno! */
1792 if ( access ( fn
, R_OK
) == 0 ) {
1793 char * r
= pa_xstrdup ( fn
);
1798 if ( errno
!= ENOENT
) {
1799 pa_log_warn ( "Failed to access configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1809 if (! ExpandEnvironmentStrings ( global
, buf
, PATH_MAX
))
1810 /* FIXME: Needs to set errno! */
1815 if ( access ( global
, R_OK
) == 0 )
1816 return pa_xstrdup ( global
);
1824 /* Format the specified data as a hexademical string */
1825 char * pa_hexstr ( const uint8_t * d
, size_t dlength
, char * s
, size_t slength
) {
1826 size_t i
= 0 , j
= 0 ;
1827 const char hex
[] = "0123456789abcdef" ;
1831 pa_assert ( slength
> 0 );
1833 while ( i
< dlength
&& j
+ 3 <= slength
) {
1834 s
[ j
++] = hex
[* d
>> 4 ];
1835 s
[ j
++] = hex
[* d
& 0xF ];
1841 s
[ j
< slength
? j
: slength
] = 0 ;
1845 /* Convert a hexadecimal digit to a number or -1 if invalid */
1846 static int hexc ( char c
) {
1847 if ( c
>= '0' && c
<= '9' )
1850 if ( c
>= 'A' && c
<= 'F' )
1851 return c
- 'A' + 10 ;
1853 if ( c
>= 'a' && c
<= 'f' )
1854 return c
- 'a' + 10 ;
1860 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1861 size_t pa_parsehex ( const char * p
, uint8_t * d
, size_t dlength
) {
1867 while ( j
< dlength
&& * p
) {
1870 if (( b
= hexc (*( p
++))) < 0 )
1873 d
[ j
] = ( uint8_t ) ( b
<< 4 );
1878 if (( b
= hexc (*( p
++))) < 0 )
1881 d
[ j
] |= ( uint8_t ) b
;
1888 /* Returns nonzero when *s starts with *pfx */
1889 pa_bool_t
pa_startswith ( const char * s
, const char * pfx
) {
1897 return strlen ( s
) >= l
&& strncmp ( s
, pfx
, l
) == 0 ;
1900 /* Returns nonzero when *s ends with *sfx */
1901 pa_bool_t
pa_endswith ( const char * s
, const char * sfx
) {
1910 return l1
>= l2
&& strcmp ( s
+ l1
- l2
, sfx
) == 0 ;
1913 pa_bool_t
pa_is_path_absolute ( const char * fn
) {
1919 return strlen ( fn
) >= 3 && isalpha ( fn
[ 0 ]) && fn
[ 1 ] == ':' && fn
[ 2 ] == ' \\ ' ;
1923 char * pa_make_path_absolute ( const char * p
) {
1929 if ( pa_is_path_absolute ( p
))
1930 return pa_xstrdup ( p
);
1932 if (!( cwd
= pa_getcwd ()))
1933 return pa_xstrdup ( p
);
1935 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , cwd
, p
);
1940 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1941 * if fn is non-null and starts with / return fn
1942 * otherwise append fn to the run time path and return it */
1943 static char * get_path ( const char * fn
, pa_bool_t prependmid
, pa_bool_t rt
) {
1946 if ( pa_is_path_absolute ( fn
))
1947 return pa_xstrdup ( fn
);
1949 rtp
= rt
? pa_get_runtime_dir () : pa_get_state_dir ();
1960 if (!( mid
= pa_machine_id ())) {
1965 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s-%s" , rtp
, mid
, fn
);
1968 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , rtp
, fn
);
1976 char * pa_runtime_path ( const char * fn
) {
1977 return get_path ( fn
, FALSE
, TRUE
);
1980 char * pa_state_path ( const char * fn
, pa_bool_t appendmid
) {
1981 return get_path ( fn
, appendmid
, FALSE
);
1984 /* Convert the string s to a signed integer in *ret_i */
1985 int pa_atoi ( const char * s
, int32_t * ret_i
) {
1993 l
= strtol ( s
, & x
, 0 );
1995 if (! x
|| * x
|| errno
) {
2001 if (( int32_t ) l
!= l
) {
2006 * ret_i
= ( int32_t ) l
;
2011 /* Convert the string s to an unsigned integer in *ret_u */
2012 int pa_atou ( const char * s
, uint32_t * ret_u
) {
2020 l
= strtoul ( s
, & x
, 0 );
2022 if (! x
|| * x
|| errno
) {
2028 if (( uint32_t ) l
!= l
) {
2033 * ret_u
= ( uint32_t ) l
;
2038 #ifdef HAVE_STRTOF_L
2039 static locale_t c_locale
= NULL
;
2041 static void c_locale_destroy ( void ) {
2042 freelocale ( c_locale
);
2046 int pa_atod ( const char * s
, double * ret_d
) {
2053 /* This should be locale independent */
2055 #ifdef HAVE_STRTOF_L
2059 if (( c_locale
= newlocale ( LC_ALL_MASK
, "C" , NULL
)))
2060 atexit ( c_locale_destroy
);
2066 f
= strtod_l ( s
, & x
, c_locale
);
2074 if (! x
|| * x
|| errno
) {
2085 /* Same as snprintf, but guarantees NUL-termination on every platform */
2086 size_t pa_snprintf ( char * str
, size_t size
, const char * format
, ...) {
2091 pa_assert ( size
> 0 );
2094 va_start ( ap
, format
);
2095 ret
= pa_vsnprintf ( str
, size
, format
, ap
);
2101 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2102 size_t pa_vsnprintf ( char * str
, size_t size
, const char * format
, va_list ap
) {
2106 pa_assert ( size
> 0 );
2109 ret
= vsnprintf ( str
, size
, format
, ap
);
2116 if (( size_t ) ret
> size
- 1 )
2119 return ( size_t ) ret
;
2122 /* Truncate the specified string, but guarantee that the string
2123 * returned still validates as UTF8 */
2124 char * pa_truncate_utf8 ( char * c
, size_t l
) {
2126 pa_assert ( pa_utf8_valid ( c
));
2133 while ( l
> 0 && ! pa_utf8_valid ( c
))
2139 char * pa_getcwd ( void ) {
2143 char * p
= pa_xmalloc ( l
);
2147 if ( errno
!= ERANGE
)
2155 void * pa_will_need ( const void * p
, size_t l
) {
2156 #ifdef RLIMIT_MEMLOCK
2167 a
= PA_PAGE_ALIGN_PTR ( p
);
2168 size
= ( size_t ) (( const uint8_t *) p
+ l
- ( const uint8_t *) a
);
2170 #ifdef HAVE_POSIX_MADVISE
2171 if (( r
= posix_madvise (( void *) a
, size
, POSIX_MADV_WILLNEED
)) == 0 ) {
2172 pa_log_debug ( "posix_madvise() worked fine!" );
2177 /* Most likely the memory was not mmap()ed from a file and thus
2178 * madvise() didn't work, so let's misuse mlock() do page this
2179 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2180 * inviting, the man page of mlock() tells us: "All pages that
2181 * contain a part of the specified address range are guaranteed to
2182 * be resident in RAM when the call returns successfully." */
2184 #ifdef RLIMIT_MEMLOCK
2185 pa_assert_se ( getrlimit ( RLIMIT_MEMLOCK
, & rlim
) == 0 );
2187 if ( rlim
. rlim_cur
< PA_PAGE_SIZE
) {
2188 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
));
2193 bs
= PA_PAGE_ALIGN (( size_t ) rlim
. rlim_cur
);
2195 bs
= PA_PAGE_SIZE
* 4 ;
2198 pa_log_debug ( "posix_madvise() failed (or doesn't exist), trying mlock(): %s" , pa_cstrerror ( r
));
2201 while ( size
> 0 && bs
> 0 ) {
2206 if ( mlock ( a
, bs
) < 0 ) {
2207 bs
= PA_PAGE_ALIGN ( bs
/ 2 );
2211 pa_assert_se ( munlock ( a
, bs
) == 0 );
2213 a
= ( const uint8_t *) a
+ bs
;
2219 pa_log_debug ( "mlock() failed too (or doesn't exist), giving up: %s" , pa_cstrerror ( errno
));
2221 pa_log_debug ( "mlock() worked fine!" );
2226 void pa_close_pipe ( int fds
[ 2 ]) {
2230 pa_assert_se ( pa_close ( fds
[ 0 ]) == 0 );
2233 pa_assert_se ( pa_close ( fds
[ 1 ]) == 0 );
2235 fds
[ 0 ] = fds
[ 1 ] = - 1 ;
2238 char * pa_readlink ( const char * p
) {
2247 if (( n
= readlink ( p
, c
, l
- 1 )) < 0 ) {
2252 if (( size_t ) n
< l
- 1 ) {
2262 int pa_close_all ( int except_fd
, ...) {
2267 va_start ( ap
, except_fd
);
2270 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2275 p
= pa_xnew ( int , n
+ 1 );
2277 va_start ( ap
, except_fd
);
2280 if ( except_fd
>= 0 ) {
2284 while (( fd
= va_arg ( ap
, int )) >= 0 )
2291 r
= pa_close_allv ( p
);
2297 int pa_close_allv ( const int except_fds
[]) {
2305 if (( d
= opendir ( "/proc/self/fd" ))) {
2309 while (( de
= readdir ( d
))) {
2315 if ( de
-> d_name
[ 0 ] == '.' )
2319 l
= strtol ( de
-> d_name
, & e
, 10 );
2320 if ( errno
!= 0 || ! e
|| * e
) {
2328 if (( long ) fd
!= l
) {
2341 for ( i
= 0 ; except_fds
[ i
] >= 0 ; i
++)
2342 if ( except_fds
[ i
] == fd
) {
2350 if ( pa_close ( fd
) < 0 ) {
2351 saved_errno
= errno
;
2353 errno
= saved_errno
;
2365 if ( getrlimit ( RLIMIT_NOFILE
, & rl
) >= 0 )
2366 maxfd
= ( int ) rl
. rlim_max
;
2368 maxfd
= sysconf ( _SC_OPEN_MAX
);
2370 for ( fd
= 3 ; fd
< maxfd
; fd
++) {
2375 for ( i
= 0 ; except_fds
[ i
] >= 0 ; i
++)
2376 if ( except_fds
[ i
] == fd
) {
2384 if ( pa_close ( fd
) < 0 && errno
!= EBADF
)
2391 int pa_unblock_sigs ( int except
, ...) {
2396 va_start ( ap
, except
);
2399 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2404 p
= pa_xnew ( int , n
+ 1 );
2406 va_start ( ap
, except
);
2413 while (( sig
= va_arg ( ap
, int )) >= 0 )
2420 r
= pa_unblock_sigsv ( p
);
2426 int pa_unblock_sigsv ( const int except
[]) {
2430 if ( sigemptyset (& ss
) < 0 )
2433 for ( i
= 0 ; except
[ i
] > 0 ; i
++)
2434 if ( sigaddset (& ss
, except
[ i
]) < 0 )
2437 return sigprocmask ( SIG_SETMASK
, & ss
, NULL
);
2440 int pa_reset_sigs ( int except
, ...) {
2445 va_start ( ap
, except
);
2448 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2453 p
= pa_xnew ( int , n
+ 1 );
2455 va_start ( ap
, except
);
2462 while (( sig
= va_arg ( ap
, int )) >= 0 )
2469 r
= pa_reset_sigsv ( p
);
2475 int pa_reset_sigsv ( const int except
[]) {
2478 for ( sig
= 1 ; sig
< NSIG
; sig
++) {
2479 pa_bool_t reset
= TRUE
;
2490 for ( i
= 0 ; except
[ i
] > 0 ; i
++) {
2491 if ( sig
== except
[ i
]) {
2500 struct sigaction sa
;
2502 memset (& sa
, 0 , sizeof ( sa
));
2503 sa
. sa_handler
= SIG_DFL
;
2505 /* On Linux the first two RT signals are reserved by
2506 * glibc, and sigaction() will return EINVAL for them. */
2507 if (( sigaction ( sig
, & sa
, NULL
) < 0 ))
2508 if ( errno
!= EINVAL
)
2516 void pa_set_env ( const char * key
, const char * value
) {
2520 putenv ( pa_sprintf_malloc ( "%s=%s" , key
, value
));
2523 pa_bool_t
pa_in_system_mode ( void ) {
2526 if (!( e
= getenv ( "PULSE_SYSTEM" )))
2532 char * pa_get_user_name_malloc ( void ) {
2536 #ifdef _SC_LOGIN_NAME_MAX
2537 k
= ( ssize_t
) sysconf ( _SC_LOGIN_NAME_MAX
);
2543 u
= pa_xnew ( char , k
+ 1 );
2545 if (!( pa_get_user_name ( u
, k
))) {
2553 char * pa_get_host_name_malloc ( void ) {
2562 if (! pa_get_host_name ( c
, l
)) {
2564 if ( errno
!= EINVAL
&& errno
!= ENAMETOOLONG
)
2567 } else if ( strlen ( c
) < l
- 1 ) {
2575 u
= pa_utf8_filter ( c
);
2580 /* Hmm, the hostname is as long the space we offered the
2581 * function, we cannot know if it fully fit in, so let's play
2582 * safe and retry. */
2591 char * pa_machine_id ( void ) {
2595 /* The returned value is supposed be some kind of ascii identifier
2596 * that is unique and stable across reboots. */
2598 /* First we try the D-Bus UUID, which is the best option we have,
2599 * since it fits perfectly our needs and is not as volatile as the
2600 * hostname which might be set from dhcp. */
2602 if (( f
= fopen ( PA_MACHINE_ID
, "r" ))) {
2603 char ln
[ 34 ] = "" , * r
;
2605 r
= fgets ( ln
, sizeof ( ln
)- 1 , f
);
2611 return pa_utf8_filter ( ln
);
2614 if (( h
= pa_get_host_name_malloc ()))
2617 /* If no hostname was set we use the POSIX hostid. It's usually
2618 * the IPv4 address. Might not be that stable. */
2619 return pa_sprintf_malloc ( "%08lx" , ( unsigned long ) gethostid
);
2622 char * pa_session_id ( void ) {
2625 if (!( e
= getenv ( "XDG_SESSION_COOKIE" )))
2628 return pa_utf8_filter ( e
);
2631 char * pa_uname_string ( void ) {
2634 pa_assert_se ( uname (& u
) >= 0 );
2636 return pa_sprintf_malloc ( "%s %s %s %s" , u
. sysname
, u
. machine
, u
. release
, u
. version
);
2639 #ifdef HAVE_VALGRIND_MEMCHECK_H
2640 pa_bool_t
pa_in_valgrind ( void ) {
2643 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2644 * here instead of really checking whether we run in valgrind or
2648 b
= getenv ( "VALGRIND" ) ? 2 : 1 ;
2654 unsigned pa_gcd ( unsigned a
, unsigned b
) {
2665 void pa_reduce ( unsigned * num
, unsigned * den
) {
2667 unsigned gcd
= pa_gcd (* num
, * den
);
2675 pa_assert ( pa_gcd (* num
, * den
) == 1 );
2678 unsigned pa_ncpus ( void ) {
2681 #ifdef _SC_NPROCESSORS_CONF
2682 ncpus
= sysconf ( _SC_NPROCESSORS_CONF
);
2687 return ncpus
<= 0 ? 1 : ( unsigned ) ncpus
;
2690 char * pa_replace ( const char * s
, const char * a
, const char * b
) {
2699 sb
= pa_strbuf_new ();
2704 if (!( p
= strstr ( s
, a
)))
2707 pa_strbuf_putsn ( sb
, s
, p
- s
);
2708 pa_strbuf_puts ( sb
, b
);
2712 pa_strbuf_puts ( sb
, s
);
2714 return pa_strbuf_tostring_free ( sb
);
2717 char * pa_unescape ( char * p
) {
2719 pa_bool_t escaped
= FALSE
;
2721 for ( s
= p
, d
= p
; * s
; s
++) {
2722 if (! escaped
&& * s
== ' \\ ' ) {
2736 char * pa_realpath ( const char * path
) {
2740 /* We want only abolsute paths */
2741 if ( path
[ 0 ] != '/' ) {
2746 #if defined(__GLIBC__) || defined(__APPLE__)
2750 if (!( r
= realpath ( path
, NULL
)))
2753 /* We copy this here in case our pa_xmalloc() is not
2754 * implemented on top of libc malloc() */
2758 #elif defined(PATH_MAX)
2761 path_buf
= pa_xmalloc ( PATH_MAX
);
2763 if (!( t
= realpath ( path
, path_buf
))) {
2769 #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."
2775 void pa_disable_sigpipe ( void ) {
2778 struct sigaction sa
;
2782 if ( sigaction ( SIGPIPE
, NULL
, & sa
) < 0 ) {
2783 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
2787 sa
. sa_handler
= SIG_IGN
;
2789 if ( sigaction ( SIGPIPE
, & sa
, NULL
) < 0 ) {
2790 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
2796 void pa_xfreev ( void ** a
) {
2802 for ( p
= a
; * p
; p
++)
2808 char ** pa_split_spaces_strv ( const char * s
) {
2810 unsigned i
= 0 , n
= 8 ;
2811 const char * state
= NULL
;
2813 t
= pa_xnew ( char *, n
);
2814 while (( e
= pa_split_spaces ( s
, & state
))) {
2819 t
= pa_xrenew ( char *, t
, n
);
2832 char * pa_maybe_prefix_path ( const char * path
, const char * prefix
) {
2835 if ( pa_is_path_absolute ( path
))
2836 return pa_xstrdup ( path
);
2838 return pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , prefix
, path
);
2841 size_t pa_pipe_buf ( int fd
) {
2846 if (( n
= fpathconf ( fd
, _PC_PIPE_BUF
)) >= 0 )
2857 void pa_reset_personality ( void ) {
2860 if ( personality ( PER_LINUX
) < 0 )
2861 pa_log_warn ( "Uh, personality() failed: %s" , pa_cstrerror ( errno
));
2866 #if defined(__linux__) && !defined(__OPTIMIZE__)
2868 pa_bool_t
pa_run_from_build_tree ( void ) {
2870 pa_bool_t b
= FALSE
;
2872 /* We abuse __OPTIMIZE__ as a check whether we are a debug build
2875 if (( rp
= pa_readlink ( "/proc/self/exe" ))) {
2876 b
= pa_startswith ( rp
, PA_BUILDDIR
);