]>
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
978 #ifdef _SC_GETGR_R_SIZE_MAX
979 n
= sysconf ( _SC_GETGR_R_SIZE_MAX
);
986 data
= pa_xmalloc (( size_t ) n
);
989 if ( getgrgid_r ( gid
, & group
, data
, ( size_t ) n
, & result
) < 0 || ! result
) {
990 pa_log ( "getgrgid_r(%u): %s" , ( unsigned ) gid
, pa_cstrerror ( errno
));
998 r
= strcmp ( name
, result
-> gr_name
) == 0 ;
1003 /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X) that do not
1004 * support getgrgid_r. */
1007 if (!( result
= getgrgid ( gid
))) {
1008 pa_log ( "getgrgid(%u): %s" , gid
, pa_cstrerror ( errno
));
1016 r
= strcmp ( name
, result
-> gr_name
) == 0 ;
1024 /* Check the current user is member of the specified group */
1025 int pa_own_uid_in_group ( const char * name
, gid_t
* gid
) {
1026 GETGROUPS_T
* gids
, tgid
;
1027 long n
= sysconf ( _SC_NGROUPS_MAX
);
1032 gids
= pa_xmalloc ( sizeof ( GETGROUPS_T
) * ( size_t ) n
);
1034 if (( n
= getgroups (( int ) n
, gids
)) < 0 ) {
1035 pa_log ( "getgroups(): %s" , pa_cstrerror ( errno
));
1039 for ( i
= 0 ; i
< n
; i
++) {
1041 if (( k
= is_group ( gids
[ i
], name
)) < 0 )
1050 if (( k
= is_group ( tgid
= getgid (), name
)) < 0 )
1066 /* Check whether the specifc user id is a member of the specified group */
1067 int pa_uid_in_group ( uid_t uid
, const char * name
) {
1068 char * g_buf
, * p_buf
;
1070 struct group grbuf
, * gr
;
1074 #ifdef _SC_GETGR_R_SIZE_MAX
1075 g_n
= sysconf ( _SC_GETGR_R_SIZE_MAX
);
1082 g_buf
= pa_xmalloc (( size_t ) g_n
);
1084 #ifdef _SC_GETPW_R_SIZE_MAX
1085 p_n
= sysconf ( _SC_GETPW_R_SIZE_MAX
);
1092 p_buf
= pa_xmalloc (( size_t ) p_n
);
1095 #ifdef HAVE_GETGRNAM_R
1096 if ( getgrnam_r ( name
, & grbuf
, g_buf
, ( size_t ) g_n
, & gr
) != 0 || ! gr
)
1098 if (!( gr
= getgrnam ( name
)))
1107 for ( i
= gr
-> gr_mem
; * i
; i
++) {
1108 struct passwd pwbuf
, * pw
;
1110 #ifdef HAVE_GETPWNAM_R
1111 if ( getpwnam_r (* i
, & pwbuf
, p_buf
, ( size_t ) p_n
, & pw
) != 0 || ! pw
)
1113 if (!( pw
= getpwnam (* i
)))
1117 if ( pw
-> pw_uid
== uid
) {
1130 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
1131 gid_t
pa_get_gid_of_group ( const char * name
) {
1132 gid_t ret
= ( gid_t
) - 1 ;
1135 struct group grbuf
, * gr
;
1137 #ifdef _SC_GETGR_R_SIZE_MAX
1138 g_n
= sysconf ( _SC_GETGR_R_SIZE_MAX
);
1145 g_buf
= pa_xmalloc (( size_t ) g_n
);
1148 #ifdef HAVE_GETGRNAM_R
1149 if ( getgrnam_r ( name
, & grbuf
, g_buf
, ( size_t ) g_n
, & gr
) != 0 || ! gr
)
1151 if (!( gr
= getgrnam ( name
)))
1166 int pa_check_in_group ( gid_t g
) {
1167 gid_t gids
[ NGROUPS_MAX
];
1170 if (( r
= getgroups ( NGROUPS_MAX
, gids
)) < 0 )
1180 #else /* HAVE_GRP_H */
1182 int pa_own_uid_in_group ( const char * name
, gid_t
* gid
) {
1188 int pa_uid_in_group ( uid_t uid
, const char * name
) {
1193 gid_t
pa_get_gid_of_group ( const char * name
) {
1198 int pa_check_in_group ( gid_t g
) {
1205 /* Lock or unlock a file entirely.
1206 (advisory on UNIX, mandatory on Windows) */
1207 int pa_lock_fd ( int fd
, int b
) {
1209 struct flock f_lock
;
1211 /* Try a R/W lock first */
1213 f_lock
. l_type
= ( short ) ( b
? F_WRLCK
: F_UNLCK
);
1214 f_lock
. l_whence
= SEEK_SET
;
1218 if ( fcntl ( fd
, F_SETLKW
, & f_lock
) >= 0 )
1221 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1222 if ( b
&& errno
== EBADF
) {
1223 f_lock
. l_type
= F_RDLCK
;
1224 if ( fcntl ( fd
, F_SETLKW
, & f_lock
) >= 0 )
1228 pa_log ( "%slock: %s" , ! b
? "un" : "" , pa_cstrerror ( errno
));
1232 HANDLE h
= ( HANDLE
) _get_osfhandle ( fd
);
1234 if ( b
&& LockFile ( h
, 0 , 0 , 0xFFFFFFFF , 0xFFFFFFFF ))
1236 if (! b
&& UnlockFile ( h
, 0 , 0 , 0xFFFFFFFF , 0xFFFFFFFF ))
1239 pa_log ( "%slock failed: 0x%08X" , ! b
? "un" : "" , GetLastError ());
1241 /* FIXME: Needs to set errno! */
1247 /* Remove trailing newlines from a string */
1248 char * pa_strip_nl ( char * s
) {
1251 s
[ strcspn ( s
, " \r\n " )] = 0 ;
1255 /* Create a temporary lock file and lock it. */
1256 int pa_lock_lockfile ( const char * fn
) {
1263 if (( fd
= open ( fn
, O_CREAT
| O_RDWR
1270 , S_IRUSR
| S_IWUSR
)) < 0 ) {
1271 pa_log_warn ( "Failed to create lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1275 if ( pa_lock_fd ( fd
, 1 ) < 0 ) {
1276 pa_log_warn ( "Failed to lock file '%s'." , fn
);
1280 if ( fstat ( fd
, & st
) < 0 ) {
1281 pa_log_warn ( "Failed to fstat() file '%s': %s" , fn
, pa_cstrerror ( errno
));
1285 /* Check whether the file has been removed meanwhile. When yes,
1286 * restart this loop, otherwise, we're done */
1287 if ( st
. st_nlink
>= 1 )
1290 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1291 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1295 if ( pa_close ( fd
) < 0 ) {
1296 pa_log_warn ( "Failed to close file '%s': %s" , fn
, pa_cstrerror ( errno
));
1309 int saved_errno
= errno
;
1311 errno
= saved_errno
;
1317 /* Unlock a temporary lcok file */
1318 int pa_unlock_lockfile ( const char * fn
, int fd
) {
1323 if ( unlink ( fn
) < 0 ) {
1324 pa_log_warn ( "Unable to remove lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1329 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1330 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1334 if ( pa_close ( fd
) < 0 ) {
1335 pa_log_warn ( "Failed to close '%s': %s" , fn
, pa_cstrerror ( errno
));
1342 static char * get_pulse_home ( void ) {
1347 if (!( h
= pa_get_home_dir_malloc ())) {
1348 pa_log_error ( "Failed to get home directory." );
1352 if ( stat ( h
, & st
) < 0 ) {
1353 pa_log_error ( "Failed to stat home directory %s: %s" , h
, pa_cstrerror ( errno
));
1357 if ( st
. st_uid
!= getuid ()) {
1358 pa_log_error ( "Home directory %s not ours." , h
);
1363 ret
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" , h
);
1371 char * pa_get_state_dir ( void ) {
1374 /* The state directory shall contain dynamic data that should be
1375 * kept across reboots, and is private to this user */
1377 if (!( d
= pa_xstrdup ( getenv ( "PULSE_STATE_PATH" ))))
1378 if (!( d
= get_pulse_home ()))
1381 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1382 * dir then this will break. */
1384 if ( pa_make_secure_dir ( d
, 0700U , ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1385 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1393 char * pa_get_home_dir_malloc ( void ) {
1395 size_t allocated
= 128 ;
1398 homedir
= pa_xmalloc ( allocated
);
1400 if (! pa_get_home_dir ( homedir
, allocated
)) {
1405 if ( strlen ( homedir
) < allocated
- 1 )
1415 char * pa_get_binary_name_malloc ( void ) {
1417 size_t allocated
= 128 ;
1420 t
= pa_xmalloc ( allocated
);
1422 if (! pa_get_binary_name ( t
, allocated
)) {
1427 if ( strlen ( t
) < allocated
- 1 )
1437 static char * make_random_dir ( mode_t m
) {
1438 static const char table
[] =
1439 "abcdefghijklmnopqrstuvwxyz"
1440 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1447 if (!( tmpdir
= getenv ( "TMPDIR" )))
1448 if (!( tmpdir
= getenv ( "TMP" )))
1449 if (!( tmpdir
= getenv ( "TEMP" )))
1450 tmpdir
= getenv ( "TEMPDIR" );
1452 if (! tmpdir
|| ! pa_is_path_absolute ( tmpdir
))
1455 fn
= pa_sprintf_malloc ( "%s/pulse-XXXXXXXXXXXX" , tmpdir
);
1456 pathlen
= strlen ( fn
);
1464 for ( i
= pathlen
- 12 ; i
< pathlen
; i
++)
1465 fn
[ i
] = table
[ rand () % ( sizeof ( table
)- 1 )];
1467 u
= umask ((~ m
) & 0777 );
1470 saved_errno
= errno
;
1472 errno
= saved_errno
;
1477 if ( errno
!= EEXIST
) {
1478 pa_log_error ( "Failed to create random directory %s: %s" , fn
, pa_cstrerror ( errno
));
1485 static int make_random_dir_and_link ( mode_t m
, const char * k
) {
1488 if (!( p
= make_random_dir ( m
)))
1491 if ( symlink ( p
, k
) < 0 ) {
1492 int saved_errno
= errno
;
1494 if ( errno
!= EEXIST
)
1495 pa_log_error ( "Failed to symlink %s to %s: %s" , k
, p
, pa_cstrerror ( errno
));
1500 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
1587 if ( lstat ( p
, & st
) < 0 ) {
1589 if ( errno
!= ENOENT
) {
1590 pa_log_error ( "Failed to stat runtime directory %s: %s" , p
, pa_cstrerror ( errno
));
1596 if ( S_ISDIR ( st
. st_mode
) &&
1597 ( st
. st_uid
== getuid ()) &&
1598 (( st
. st_mode
& 0777 ) == 0700 )) {
1604 pa_log_info ( "Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory." );
1610 /* Hmm, so the link points to some nonexisting or invalid
1611 * dir. Let's replace it by a new link. We first create a
1612 * temporary link and then rename that to allow concurrent
1613 * execution of this function. */
1615 t
= pa_sprintf_malloc ( "%s.tmp" , k
);
1617 if ( make_random_dir_and_link ( 0700 , t
) < 0 ) {
1619 if ( errno
!= EEXIST
) {
1620 pa_log_error ( "Failed to symlink %s: %s" , t
, pa_cstrerror ( errno
));
1627 /* Hmm, someone lese was quicker then us. Let's give
1628 * him some time to finish, and retry. */
1633 /* OK, we succeeded in creating the temporary symlink, so
1634 * let's rename it */
1635 if ( rename ( t
, k
) < 0 ) {
1636 pa_log_error ( "Failed to rename %s to %s: %s" , t
, k
, pa_cstrerror ( errno
));
1652 /* Try to open a configuration file. If "env" is specified, open the
1653 * value of the specified environment variable. Otherwise look for a
1654 * file "local" in the home directory or a file "global" in global
1655 * file system. If "result" is non-NULL, a pointer to a newly
1656 * allocated buffer containing the used configuration file is
1658 FILE * pa_open_config_file ( const char * global
, const char * local
, const char * env
, char ** result
) {
1663 if (! getenv ( PULSE_ROOTENV
))
1667 if ( env
&& ( fn
= getenv ( env
))) {
1671 if (! ExpandEnvironmentStrings ( fn
, buf
, PATH_MAX
))
1672 /* FIXME: Needs to set errno! */
1677 if (( f
= fopen ( fn
, "r" ))) {
1679 * result
= pa_xstrdup ( fn
);
1684 pa_log_warn ( "Failed to open configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1694 if (( e
= getenv ( "PULSE_CONFIG_PATH" )))
1695 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , e
, local
);
1696 else if (( h
= pa_get_home_dir_malloc ())) {
1697 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s" , h
, local
);
1703 if (! ExpandEnvironmentStrings ( lfn
, buf
, PATH_MAX
)) {
1704 /* FIXME: Needs to set errno! */
1711 if (( f
= fopen ( fn
, "r" ))) {
1713 * result
= pa_xstrdup ( fn
);
1719 if ( errno
!= ENOENT
) {
1720 pa_log_warn ( "Failed to open configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1732 if (! ExpandEnvironmentStrings ( global
, buf
, PATH_MAX
))
1733 /* FIXME: Needs to set errno! */
1738 if (( f
= fopen ( global
, "r" ))) {
1741 * result
= pa_xstrdup ( global
);
1751 char * pa_find_config_file ( const char * global
, const char * local
, const char * env
) {
1756 if (! getenv ( PULSE_ROOTENV
))
1760 if ( env
&& ( fn
= getenv ( env
))) {
1763 if (! ExpandEnvironmentStrings ( fn
, buf
, PATH_MAX
))
1764 /* FIXME: Needs to set errno! */
1769 if ( access ( fn
, R_OK
) == 0 )
1770 return pa_xstrdup ( fn
);
1772 pa_log_warn ( "Failed to access configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1781 if (( e
= getenv ( "PULSE_CONFIG_PATH" )))
1782 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , e
, local
);
1783 else if (( h
= pa_get_home_dir_malloc ())) {
1784 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s" , h
, local
);
1790 if (! ExpandEnvironmentStrings ( lfn
, buf
, PATH_MAX
)) {
1791 /* FIXME: Needs to set errno! */
1798 if ( access ( fn
, R_OK
) == 0 ) {
1799 char * r
= pa_xstrdup ( fn
);
1804 if ( errno
!= ENOENT
) {
1805 pa_log_warn ( "Failed to access configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1815 if (! ExpandEnvironmentStrings ( global
, buf
, PATH_MAX
))
1816 /* FIXME: Needs to set errno! */
1821 if ( access ( global
, R_OK
) == 0 )
1822 return pa_xstrdup ( global
);
1830 /* Format the specified data as a hexademical string */
1831 char * pa_hexstr ( const uint8_t * d
, size_t dlength
, char * s
, size_t slength
) {
1832 size_t i
= 0 , j
= 0 ;
1833 const char hex
[] = "0123456789abcdef" ;
1837 pa_assert ( slength
> 0 );
1839 while ( i
< dlength
&& j
+ 3 <= slength
) {
1840 s
[ j
++] = hex
[* d
>> 4 ];
1841 s
[ j
++] = hex
[* d
& 0xF ];
1847 s
[ j
< slength
? j
: slength
] = 0 ;
1851 /* Convert a hexadecimal digit to a number or -1 if invalid */
1852 static int hexc ( char c
) {
1853 if ( c
>= '0' && c
<= '9' )
1856 if ( c
>= 'A' && c
<= 'F' )
1857 return c
- 'A' + 10 ;
1859 if ( c
>= 'a' && c
<= 'f' )
1860 return c
- 'a' + 10 ;
1866 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1867 size_t pa_parsehex ( const char * p
, uint8_t * d
, size_t dlength
) {
1873 while ( j
< dlength
&& * p
) {
1876 if (( b
= hexc (*( p
++))) < 0 )
1879 d
[ j
] = ( uint8_t ) ( b
<< 4 );
1884 if (( b
= hexc (*( p
++))) < 0 )
1887 d
[ j
] |= ( uint8_t ) b
;
1894 /* Returns nonzero when *s starts with *pfx */
1895 pa_bool_t
pa_startswith ( const char * s
, const char * pfx
) {
1903 return strlen ( s
) >= l
&& strncmp ( s
, pfx
, l
) == 0 ;
1906 /* Returns nonzero when *s ends with *sfx */
1907 pa_bool_t
pa_endswith ( const char * s
, const char * sfx
) {
1916 return l1
>= l2
&& strcmp ( s
+ l1
- l2
, sfx
) == 0 ;
1919 pa_bool_t
pa_is_path_absolute ( const char * fn
) {
1925 return strlen ( fn
) >= 3 && isalpha ( fn
[ 0 ]) && fn
[ 1 ] == ':' && fn
[ 2 ] == ' \\ ' ;
1929 char * pa_make_path_absolute ( const char * p
) {
1935 if ( pa_is_path_absolute ( p
))
1936 return pa_xstrdup ( p
);
1938 if (!( cwd
= pa_getcwd ()))
1939 return pa_xstrdup ( p
);
1941 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , cwd
, p
);
1946 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1947 * if fn is non-null and starts with / return fn
1948 * otherwise append fn to the run time path and return it */
1949 static char * get_path ( const char * fn
, pa_bool_t prependmid
, pa_bool_t rt
) {
1952 if ( pa_is_path_absolute ( fn
))
1953 return pa_xstrdup ( fn
);
1955 rtp
= rt
? pa_get_runtime_dir () : pa_get_state_dir ();
1966 if (!( mid
= pa_machine_id ())) {
1971 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s-%s" , rtp
, mid
, fn
);
1974 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , rtp
, fn
);
1982 char * pa_runtime_path ( const char * fn
) {
1983 return get_path ( fn
, FALSE
, TRUE
);
1986 char * pa_state_path ( const char * fn
, pa_bool_t appendmid
) {
1987 return get_path ( fn
, appendmid
, FALSE
);
1990 /* Convert the string s to a signed integer in *ret_i */
1991 int pa_atoi ( const char * s
, int32_t * ret_i
) {
1999 l
= strtol ( s
, & x
, 0 );
2001 if (! x
|| * x
|| errno
) {
2007 if (( int32_t ) l
!= l
) {
2012 * ret_i
= ( int32_t ) l
;
2017 /* Convert the string s to an unsigned integer in *ret_u */
2018 int pa_atou ( const char * s
, uint32_t * ret_u
) {
2026 l
= strtoul ( s
, & x
, 0 );
2028 if (! x
|| * x
|| errno
) {
2034 if (( uint32_t ) l
!= l
) {
2039 * ret_u
= ( uint32_t ) l
;
2044 #ifdef HAVE_STRTOF_L
2045 static locale_t c_locale
= NULL
;
2047 static void c_locale_destroy ( void ) {
2048 freelocale ( c_locale
);
2052 int pa_atod ( const char * s
, double * ret_d
) {
2059 /* This should be locale independent */
2061 #ifdef HAVE_STRTOF_L
2065 if (( c_locale
= newlocale ( LC_ALL_MASK
, "C" , NULL
)))
2066 atexit ( c_locale_destroy
);
2072 f
= strtod_l ( s
, & x
, c_locale
);
2080 if (! x
|| * x
|| errno
) {
2091 /* Same as snprintf, but guarantees NUL-termination on every platform */
2092 size_t pa_snprintf ( char * str
, size_t size
, const char * format
, ...) {
2097 pa_assert ( size
> 0 );
2100 va_start ( ap
, format
);
2101 ret
= pa_vsnprintf ( str
, size
, format
, ap
);
2107 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2108 size_t pa_vsnprintf ( char * str
, size_t size
, const char * format
, va_list ap
) {
2112 pa_assert ( size
> 0 );
2115 ret
= vsnprintf ( str
, size
, format
, ap
);
2122 if (( size_t ) ret
> size
- 1 )
2125 return ( size_t ) ret
;
2128 /* Truncate the specified string, but guarantee that the string
2129 * returned still validates as UTF8 */
2130 char * pa_truncate_utf8 ( char * c
, size_t l
) {
2132 pa_assert ( pa_utf8_valid ( c
));
2139 while ( l
> 0 && ! pa_utf8_valid ( c
))
2145 char * pa_getcwd ( void ) {
2149 char * p
= pa_xmalloc ( l
);
2153 if ( errno
!= ERANGE
)
2161 void * pa_will_need ( const void * p
, size_t l
) {
2162 #ifdef RLIMIT_MEMLOCK
2173 a
= PA_PAGE_ALIGN_PTR ( p
);
2174 size
= ( size_t ) (( const uint8_t *) p
+ l
- ( const uint8_t *) a
);
2176 #ifdef HAVE_POSIX_MADVISE
2177 if (( r
= posix_madvise (( void *) a
, size
, POSIX_MADV_WILLNEED
)) == 0 ) {
2178 pa_log_debug ( "posix_madvise() worked fine!" );
2183 /* Most likely the memory was not mmap()ed from a file and thus
2184 * madvise() didn't work, so let's misuse mlock() do page this
2185 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2186 * inviting, the man page of mlock() tells us: "All pages that
2187 * contain a part of the specified address range are guaranteed to
2188 * be resident in RAM when the call returns successfully." */
2190 #ifdef RLIMIT_MEMLOCK
2191 pa_assert_se ( getrlimit ( RLIMIT_MEMLOCK
, & rlim
) == 0 );
2193 if ( rlim
. rlim_cur
< PA_PAGE_SIZE
) {
2194 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
));
2199 bs
= PA_PAGE_ALIGN (( size_t ) rlim
. rlim_cur
);
2201 bs
= PA_PAGE_SIZE
* 4 ;
2204 pa_log_debug ( "posix_madvise() failed (or doesn't exist), trying mlock(): %s" , pa_cstrerror ( r
));
2207 while ( size
> 0 && bs
> 0 ) {
2212 if ( mlock ( a
, bs
) < 0 ) {
2213 bs
= PA_PAGE_ALIGN ( bs
/ 2 );
2217 pa_assert_se ( munlock ( a
, bs
) == 0 );
2219 a
= ( const uint8_t *) a
+ bs
;
2225 pa_log_debug ( "mlock() failed too (or doesn't exist), giving up: %s" , pa_cstrerror ( errno
));
2227 pa_log_debug ( "mlock() worked fine!" );
2232 void pa_close_pipe ( int fds
[ 2 ]) {
2236 pa_assert_se ( pa_close ( fds
[ 0 ]) == 0 );
2239 pa_assert_se ( pa_close ( fds
[ 1 ]) == 0 );
2241 fds
[ 0 ] = fds
[ 1 ] = - 1 ;
2244 char * pa_readlink ( const char * p
) {
2253 if (( n
= readlink ( p
, c
, l
- 1 )) < 0 ) {
2258 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
[]) {
2311 if (( d
= opendir ( "/proc/self/fd" ))) {
2315 while (( de
= readdir ( d
))) {
2321 if ( de
-> d_name
[ 0 ] == '.' )
2325 l
= strtol ( de
-> d_name
, & e
, 10 );
2326 if ( errno
!= 0 || ! e
|| * e
) {
2334 if (( long ) fd
!= l
) {
2347 for ( i
= 0 ; except_fds
[ i
] >= 0 ; i
++)
2348 if ( except_fds
[ i
] == fd
) {
2356 if ( pa_close ( fd
) < 0 ) {
2357 saved_errno
= errno
;
2359 errno
= saved_errno
;
2371 if ( getrlimit ( RLIMIT_NOFILE
, & rl
) >= 0 )
2372 maxfd
= ( int ) rl
. rlim_max
;
2374 maxfd
= sysconf ( _SC_OPEN_MAX
);
2376 for ( fd
= 3 ; fd
< maxfd
; fd
++) {
2381 for ( i
= 0 ; except_fds
[ i
] >= 0 ; i
++)
2382 if ( except_fds
[ i
] == fd
) {
2390 if ( pa_close ( fd
) < 0 && errno
!= EBADF
)
2397 int pa_unblock_sigs ( int except
, ...) {
2402 va_start ( ap
, except
);
2405 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2410 p
= pa_xnew ( int , n
+ 1 );
2412 va_start ( ap
, except
);
2419 while (( sig
= va_arg ( ap
, int )) >= 0 )
2426 r
= pa_unblock_sigsv ( p
);
2432 int pa_unblock_sigsv ( const int except
[]) {
2436 if ( sigemptyset (& ss
) < 0 )
2439 for ( i
= 0 ; except
[ i
] > 0 ; i
++)
2440 if ( sigaddset (& ss
, except
[ i
]) < 0 )
2443 return sigprocmask ( SIG_SETMASK
, & ss
, NULL
);
2446 int pa_reset_sigs ( int except
, ...) {
2451 va_start ( ap
, except
);
2454 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2459 p
= pa_xnew ( int , n
+ 1 );
2461 va_start ( ap
, except
);
2468 while (( sig
= va_arg ( ap
, int )) >= 0 )
2475 r
= pa_reset_sigsv ( p
);
2481 int pa_reset_sigsv ( const int except
[]) {
2484 for ( sig
= 1 ; sig
< NSIG
; sig
++) {
2485 pa_bool_t reset
= TRUE
;
2496 for ( i
= 0 ; except
[ i
] > 0 ; i
++) {
2497 if ( sig
== except
[ i
]) {
2506 struct sigaction sa
;
2508 memset (& sa
, 0 , sizeof ( sa
));
2509 sa
. sa_handler
= SIG_DFL
;
2511 /* On Linux the first two RT signals are reserved by
2512 * glibc, and sigaction() will return EINVAL for them. */
2513 if (( sigaction ( sig
, & sa
, NULL
) < 0 ))
2514 if ( errno
!= EINVAL
)
2522 void pa_set_env ( const char * key
, const char * value
) {
2526 putenv ( pa_sprintf_malloc ( "%s=%s" , key
, value
));
2529 pa_bool_t
pa_in_system_mode ( void ) {
2532 if (!( e
= getenv ( "PULSE_SYSTEM" )))
2538 char * pa_get_user_name_malloc ( void ) {
2542 #ifdef _SC_LOGIN_NAME_MAX
2543 k
= ( ssize_t
) sysconf ( _SC_LOGIN_NAME_MAX
);
2549 u
= pa_xnew ( char , k
+ 1 );
2551 if (!( pa_get_user_name ( u
, k
))) {
2559 char * pa_get_host_name_malloc ( void ) {
2568 if (! pa_get_host_name ( c
, l
)) {
2570 if ( errno
!= EINVAL
&& errno
!= ENAMETOOLONG
)
2573 } else if ( strlen ( c
) < l
- 1 ) {
2581 u
= pa_utf8_filter ( c
);
2586 /* Hmm, the hostname is as long the space we offered the
2587 * function, we cannot know if it fully fit in, so let's play
2588 * safe and retry. */
2597 char * pa_machine_id ( void ) {
2601 /* The returned value is supposed be some kind of ascii identifier
2602 * that is unique and stable across reboots. */
2604 /* First we try the D-Bus UUID, which is the best option we have,
2605 * since it fits perfectly our needs and is not as volatile as the
2606 * hostname which might be set from dhcp. */
2608 if (( f
= fopen ( PA_MACHINE_ID
, "r" ))) {
2609 char ln
[ 34 ] = "" , * r
;
2611 r
= fgets ( ln
, sizeof ( ln
)- 1 , f
);
2617 return pa_utf8_filter ( ln
);
2620 if (( h
= pa_get_host_name_malloc ()))
2623 /* If no hostname was set we use the POSIX hostid. It's usually
2624 * the IPv4 address. Might not be that stable. */
2625 return pa_sprintf_malloc ( "%08lx" , ( unsigned long ) gethostid
);
2628 char * pa_session_id ( void ) {
2631 if (!( e
= getenv ( "XDG_SESSION_COOKIE" )))
2634 return pa_utf8_filter ( e
);
2637 char * pa_uname_string ( void ) {
2640 pa_assert_se ( uname (& u
) >= 0 );
2642 return pa_sprintf_malloc ( "%s %s %s %s" , u
. sysname
, u
. machine
, u
. release
, u
. version
);
2645 #ifdef HAVE_VALGRIND_MEMCHECK_H
2646 pa_bool_t
pa_in_valgrind ( void ) {
2649 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2650 * here instead of really checking whether we run in valgrind or
2654 b
= getenv ( "VALGRIND" ) ? 2 : 1 ;
2660 unsigned pa_gcd ( unsigned a
, unsigned b
) {
2671 void pa_reduce ( unsigned * num
, unsigned * den
) {
2673 unsigned gcd
= pa_gcd (* num
, * den
);
2681 pa_assert ( pa_gcd (* num
, * den
) == 1 );
2684 unsigned pa_ncpus ( void ) {
2687 #ifdef _SC_NPROCESSORS_CONF
2688 ncpus
= sysconf ( _SC_NPROCESSORS_CONF
);
2693 return ncpus
<= 0 ? 1 : ( unsigned ) ncpus
;
2696 char * pa_replace ( const char * s
, const char * a
, const char * b
) {
2705 sb
= pa_strbuf_new ();
2710 if (!( p
= strstr ( s
, a
)))
2713 pa_strbuf_putsn ( sb
, s
, p
- s
);
2714 pa_strbuf_puts ( sb
, b
);
2718 pa_strbuf_puts ( sb
, s
);
2720 return pa_strbuf_tostring_free ( sb
);
2723 char * pa_escape ( const char * p
, const char * chars
) {
2726 pa_strbuf
* buf
= pa_strbuf_new ();
2728 for ( s
= p
; * s
; ++ s
) {
2730 pa_strbuf_putc ( buf
, ' \\ ' );
2732 for ( c
= chars
; * c
; ++ c
) {
2734 pa_strbuf_putc ( buf
, ' \\ ' );
2739 pa_strbuf_putc ( buf
, * s
);
2742 return pa_strbuf_tostring_free ( buf
);
2745 char * pa_unescape ( char * p
) {
2747 pa_bool_t escaped
= FALSE
;
2749 for ( s
= p
, d
= p
; * s
; s
++) {
2750 if (! escaped
&& * s
== ' \\ ' ) {
2764 char * pa_realpath ( const char * path
) {
2768 /* We want only abolsute paths */
2769 if ( path
[ 0 ] != '/' ) {
2774 #if defined(__GLIBC__) || defined(__APPLE__)
2778 if (!( r
= realpath ( path
, NULL
)))
2781 /* We copy this here in case our pa_xmalloc() is not
2782 * implemented on top of libc malloc() */
2786 #elif defined(PATH_MAX)
2789 path_buf
= pa_xmalloc ( PATH_MAX
);
2791 if (!( t
= realpath ( path
, path_buf
))) {
2797 #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."
2803 void pa_disable_sigpipe ( void ) {
2806 struct sigaction sa
;
2810 if ( sigaction ( SIGPIPE
, NULL
, & sa
) < 0 ) {
2811 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
2815 sa
. sa_handler
= SIG_IGN
;
2817 if ( sigaction ( SIGPIPE
, & sa
, NULL
) < 0 ) {
2818 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
2824 void pa_xfreev ( void ** a
) {
2830 for ( p
= a
; * p
; p
++)
2836 char ** pa_split_spaces_strv ( const char * s
) {
2838 unsigned i
= 0 , n
= 8 ;
2839 const char * state
= NULL
;
2841 t
= pa_xnew ( char *, n
);
2842 while (( e
= pa_split_spaces ( s
, & state
))) {
2847 t
= pa_xrenew ( char *, t
, n
);
2860 char * pa_maybe_prefix_path ( const char * path
, const char * prefix
) {
2863 if ( pa_is_path_absolute ( path
))
2864 return pa_xstrdup ( path
);
2866 return pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , prefix
, path
);
2869 size_t pa_pipe_buf ( int fd
) {
2874 if (( n
= fpathconf ( fd
, _PC_PIPE_BUF
)) >= 0 )
2885 void pa_reset_personality ( void ) {
2888 if ( personality ( PER_LINUX
) < 0 )
2889 pa_log_warn ( "Uh, personality() failed: %s" , pa_cstrerror ( errno
));