]>
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>
55 #ifdef HAVE_SYS_RESOURCE_H
56 #include <sys/resource.h>
59 #ifdef HAVE_SYS_CAPABILITY_H
60 #include <sys/capability.h>
63 #ifdef HAVE_SYS_MMAN_H
87 #ifdef HAVE_LIBSAMPLERATE
88 #include <samplerate.h>
95 #include <pulse/xmalloc.h>
96 #include <pulse/util.h>
97 #include <pulse/utf8.h>
99 #include <pulsecore/core-error.h>
100 #include <pulsecore/winsock.h>
101 #include <pulsecore/log.h>
102 #include <pulsecore/macro.h>
103 #include <pulsecore/thread.h>
104 #include <pulsecore/strbuf.h>
106 #include "core-util.h"
108 /* Not all platforms have this */
110 #define MSG_NOSIGNAL 0
115 #define PULSE_ROOTENV "PULSE_ROOT"
117 int pa_set_root ( HANDLE handle
) {
118 char library_path
[ MAX_PATH
+ sizeof ( PULSE_ROOTENV
) + 1 ], * sep
;
120 strcpy ( library_path
, PULSE_ROOTENV
"=" );
122 /* FIXME: Needs to set errno */
124 if (! GetModuleFileName ( handle
, library_path
+ sizeof ( PULSE_ROOTENV
), MAX_PATH
))
127 sep
= strrchr ( library_path
, PA_PATH_SEP_CHAR
);
131 if ( _putenv ( library_path
) < 0 )
139 /** Make a file descriptor nonblock. Doesn't do any error checking */
140 void pa_make_fd_nonblock ( int fd
) {
146 pa_assert_se (( v
= fcntl ( fd
, F_GETFL
)) >= 0 );
148 if (!( v
& O_NONBLOCK
))
149 pa_assert_se ( fcntl ( fd
, F_SETFL
, v
| O_NONBLOCK
) >= 0 );
151 #elif defined(OS_IS_WIN32)
153 if ( ioctlsocket ( fd
, FIONBIO
, & arg
) < 0 ) {
154 pa_assert_se ( WSAGetLastError () == WSAENOTSOCK
);
155 pa_log_warn ( "Only sockets can be made non-blocking!" );
158 pa_log_warn ( "Non-blocking I/O not supported.!" );
163 /* Set the FD_CLOEXEC flag for a fd */
164 void pa_make_fd_cloexec ( int fd
) {
170 pa_assert_se (( v
= fcntl ( fd
, F_GETFD
, 0 )) >= 0 );
172 if (!( v
& FD_CLOEXEC
))
173 pa_assert_se ( fcntl ( fd
, F_SETFD
, v
| FD_CLOEXEC
) >= 0 );
178 /** Creates a directory securely */
179 int pa_make_secure_dir ( const char * dir
, mode_t m
, uid_t uid
, gid_t gid
) {
190 u
= umask ((~ m
) & 0777 );
196 if ( r
< 0 && errno
!= EEXIST
)
200 if ( uid
== ( uid_t
)- 1 )
202 if ( gid
== ( gid_t
)- 1 )
204 ( void ) chown ( dir
, uid
, gid
);
212 if ( lstat ( dir
, & st
) < 0 )
214 if ( stat ( dir
, & st
) < 0 )
219 if (! S_ISDIR ( st
. st_mode
) ||
220 ( st
. st_uid
!= uid
) ||
221 ( st
. st_gid
!= gid
) ||
222 (( st
. st_mode
& 0777 ) != m
)) {
227 pa_log_warn ( "Secure directory creation not supported on Win32." );
240 /* Return a newly allocated sting containing the parent directory of the specified file */
241 char * pa_parent_dir ( const char * fn
) {
242 char * slash
, * dir
= pa_xstrdup ( fn
);
244 if (( slash
= ( char *) pa_path_get_filename ( dir
)) == dir
) {
254 /* Creates a the parent directory of the specified path securely */
255 int pa_make_secure_parent_dir ( const char * fn
, mode_t m
, uid_t uid
, gid_t gid
) {
259 if (!( dir
= pa_parent_dir ( fn
)))
262 if ( pa_make_secure_dir ( dir
, m
, uid
, gid
) < 0 )
272 /** Platform independent read function. Necessary since not all
273 * systems treat all file descriptors equal. If type is
274 * non-NULL it is used to cache the type of the fd. This is
275 * useful for making sure that only a single syscall is executed per
276 * function call. The variable pointed to should be initialized to 0
278 ssize_t
pa_read ( int fd
, void * buf
, size_t count
, int * type
) {
282 if (! type
|| * type
== 0 ) {
285 if (( r
= recv ( fd
, buf
, count
, 0 )) >= 0 )
288 if ( WSAGetLastError () != WSAENOTSOCK
) {
289 errno
= WSAGetLastError ();
299 return read ( fd
, buf
, count
);
302 /** Similar to pa_read(), but handles writes */
303 ssize_t
pa_write ( int fd
, const void * buf
, size_t count
, int * type
) {
305 if (! type
|| * type
== 0 ) {
308 if (( r
= send ( fd
, buf
, count
, MSG_NOSIGNAL
)) >= 0 )
312 if ( WSAGetLastError () != WSAENOTSOCK
) {
313 errno
= WSAGetLastError ();
317 if ( errno
!= ENOTSOCK
)
325 return write ( fd
, buf
, count
);
328 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
329 * unless EOF is reached or an error occured */
330 ssize_t
pa_loop_read ( int fd
, void * data
, size_t size
, int * type
) {
346 if (( r
= pa_read ( fd
, data
, size
, type
)) < 0 )
353 data
= ( uint8_t *) data
+ r
;
360 /** Similar to pa_loop_read(), but wraps write() */
361 ssize_t
pa_loop_write ( int fd
, const void * data
, size_t size
, int * type
) {
377 if (( r
= pa_write ( fd
, data
, size
, type
)) < 0 )
384 data
= ( const uint8_t *) data
+ r
;
391 /** Platform independent read function. Necessary since not all
392 * systems treat all file descriptors equal. */
393 int pa_close ( int fd
) {
398 if (( ret
= closesocket ( fd
)) == 0 )
401 if ( WSAGetLastError () != WSAENOTSOCK
) {
402 errno
= WSAGetLastError ();
410 if (( r
= close ( fd
)) >= 0 )
418 /* Print a warning messages in case that the given signal is not
419 * blocked or trapped */
420 void pa_check_signal_is_blocked ( int sig
) {
421 #ifdef HAVE_SIGACTION
425 /* If POSIX threads are supported use thread-aware
426 * pthread_sigmask() function, to check if the signal is
427 * blocked. Otherwise fall back to sigprocmask() */
430 if ( pthread_sigmask ( SIG_SETMASK
, NULL
, & set
) < 0 ) {
432 if ( sigprocmask ( SIG_SETMASK
, NULL
, & set
) < 0 ) {
433 pa_log ( "sigprocmask(): %s" , pa_cstrerror ( errno
));
440 if ( sigismember (& set
, sig
))
443 /* Check whether the signal is trapped */
445 if ( sigaction ( sig
, NULL
, & sa
) < 0 ) {
446 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
450 if ( sa
. sa_handler
!= SIG_DFL
)
453 pa_log_warn ( "%s is not trapped. This might cause malfunction!" , pa_sig2str ( sig
));
454 #else /* HAVE_SIGACTION */
455 pa_log_warn ( "%s might not be trapped. This might cause malfunction!" , pa_sig2str ( sig
));
459 /* The following function is based on an example from the GNU libc
460 * documentation. This function is similar to GNU's asprintf(). */
461 char * pa_sprintf_malloc ( const char * format
, ...) {
471 c
= pa_xrealloc ( c
, size
);
473 va_start ( ap
, format
);
474 r
= vsnprintf ( c
, size
, format
, ap
);
479 if ( r
> - 1 && ( size_t ) r
< size
)
482 if ( r
> - 1 ) /* glibc 2.1 */
489 /* Same as the previous function, but use a va_list instead of an
491 char * pa_vsprintf_malloc ( const char * format
, va_list ap
) {
501 c
= pa_xrealloc ( c
, size
);
504 r
= vsnprintf ( c
, size
, format
, aq
);
509 if ( r
> - 1 && ( size_t ) r
< size
)
512 if ( r
> - 1 ) /* glibc 2.1 */
519 /* Similar to OpenBSD's strlcpy() function */
520 char * pa_strlcpy ( char * b
, const char * s
, size_t l
) {
530 /* Make the current thread a realtime thread, and acquire the highest
531 * rtprio we can get that is less or equal the specified parameter. If
532 * the thread is already realtime, don't do anything. */
533 int pa_make_realtime ( int rtprio
) {
535 #ifdef _POSIX_PRIORITY_SCHEDULING
536 struct sched_param sp
;
539 memset (& sp
, 0 , sizeof ( sp
));
542 if (( r
= pthread_getschedparam ( pthread_self (), & policy
, & sp
)) != 0 ) {
543 pa_log ( "pthread_getschedgetparam(): %s" , pa_cstrerror ( r
));
547 if ( policy
== SCHED_FIFO
&& sp
. sched_priority
>= rtprio
) {
548 pa_log_info ( "Thread already being scheduled with SCHED_FIFO with priority %i." , sp
. sched_priority
);
552 sp
. sched_priority
= rtprio
;
553 if (( r
= pthread_setschedparam ( pthread_self (), SCHED_FIFO
, & sp
)) != 0 ) {
555 while ( sp
. sched_priority
> 1 ) {
556 sp
. sched_priority
--;
558 if (( r
= pthread_setschedparam ( pthread_self (), SCHED_FIFO
, & sp
)) == 0 ) {
559 pa_log_info ( "Successfully enabled SCHED_FIFO scheduling for thread, with priority %i, which is lower than the requested %i." , sp
. sched_priority
, rtprio
);
564 pa_log_warn ( "pthread_setschedparam(): %s" , pa_cstrerror ( r
));
568 pa_log_info ( "Successfully enabled SCHED_FIFO scheduling for thread, with priority %i." , sp
. sched_priority
);
577 /* This is merely used for giving the user a hint. This is not correct
578 * for anything security related */
579 pa_bool_t
pa_can_realtime ( void ) {
584 #if defined(HAVE_SYS_RESOURCE_H) && defined(RLIMIT_RTPRIO)
588 if ( getrlimit ( RLIMIT_RTPRIO
, & rl
) >= 0 )
589 if ( rl
. rlim_cur
> 0 || rl
. rlim_cur
== RLIM_INFINITY
)
594 #if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_SYS_NICE)
598 if (( cap
= cap_get_proc ())) {
599 cap_flag_value_t flag
= CAP_CLEAR
;
601 if ( cap_get_flag ( cap
, CAP_SYS_NICE
, CAP_EFFECTIVE
, & flag
) >= 0 )
602 if ( flag
== CAP_SET
) {
615 /* This is merely used for giving the user a hint. This is not correct
616 * for anything security related */
617 pa_bool_t
pa_can_high_priority ( void ) {
622 #if defined(HAVE_SYS_RESOURCE_H) && defined(RLIMIT_RTPRIO)
626 if ( getrlimit ( RLIMIT_NICE
, & rl
) >= 0 )
627 if ( rl
. rlim_cur
>= 21 || rl
. rlim_cur
== RLIM_INFINITY
)
632 #if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_SYS_NICE)
636 if (( cap
= cap_get_proc ())) {
637 cap_flag_value_t flag
= CAP_CLEAR
;
639 if ( cap_get_flag ( cap
, CAP_SYS_NICE
, CAP_EFFECTIVE
, & flag
) >= 0 )
640 if ( flag
== CAP_SET
) {
653 /* Raise the priority of the current process as much as possible that
654 * is <= the specified nice level..*/
655 int pa_raise_priority ( int nice_level
) {
657 #ifdef HAVE_SYS_RESOURCE_H
658 if ( setpriority ( PRIO_PROCESS
, 0 , nice_level
) < 0 ) {
661 for ( n
= nice_level
+ 1 ; n
< 0 ; n
++) {
663 if ( setpriority ( PRIO_PROCESS
, 0 , n
) == 0 ) {
664 pa_log_info ( "Successfully acquired nice level %i, which is lower than the requested %i." , n
, nice_level
);
669 pa_log_warn ( "setpriority(): %s" , pa_cstrerror ( errno
));
673 pa_log_info ( "Successfully gained nice level %i." , nice_level
);
677 if ( nice_level
< 0 ) {
678 if (! SetPriorityClass ( GetCurrentProcess (), HIGH_PRIORITY_CLASS
)) {
679 pa_log_warn ( "SetPriorityClass() failed: 0x%08X" , GetLastError ());
683 pa_log_info ( "Successfully gained high priority class." );
690 /* Reset the priority to normal, inverting the changes made by
691 * pa_raise_priority() and pa_make_realtime()*/
692 void pa_reset_priority ( void ) {
693 #ifdef HAVE_SYS_RESOURCE_H
694 struct sched_param sp
;
696 setpriority ( PRIO_PROCESS
, 0 , 0 );
698 memset (& sp
, 0 , sizeof ( sp
));
699 pa_assert_se ( pthread_setschedparam ( pthread_self (), SCHED_OTHER
, & sp
) == 0 );
703 SetPriorityClass ( GetCurrentProcess (), NORMAL_PRIORITY_CLASS
);
707 int pa_match ( const char * expr
, const char * v
) {
712 if ( regcomp (& re
, expr
, REG_NOSUB
| REG_EXTENDED
) != 0 ) {
717 if (( k
= regexec (& re
, v
, 0 , NULL
, 0 )) == 0 )
719 else if ( k
== REG_NOMATCH
)
732 /* Try to parse a boolean string value.*/
733 int pa_parse_boolean ( const char * v
) {
738 /* First we check language independant */
739 if (! strcmp ( v
, "1" ) || v
[ 0 ] == 'y' || v
[ 0 ] == 'Y' || v
[ 0 ] == 't' || v
[ 0 ] == 'T' || ! strcasecmp ( v
, "on" ))
741 else if (! strcmp ( v
, "0" ) || v
[ 0 ] == 'n' || v
[ 0 ] == 'N' || v
[ 0 ] == 'f' || v
[ 0 ] == 'F' || ! strcasecmp ( v
, "off" ))
744 /* And then we check language dependant */
745 if (( expr
= nl_langinfo ( YESEXPR
)))
747 if (( r
= pa_match ( expr
, v
)) > 0 )
750 if (( expr
= nl_langinfo ( NOEXPR
)))
752 if (( r
= pa_match ( expr
, v
)) > 0 )
759 /* Split the specified string wherever one of the strings in delimiter
760 * occurs. Each time it is called returns a newly allocated string
761 * with pa_xmalloc(). The variable state points to, should be
762 * initiallized to NULL before the first call. */
763 char * pa_split ( const char * c
, const char * delimiter
, const char ** state
) {
764 const char * current
= * state
? * state
: c
;
770 l
= strcspn ( current
, delimiter
);
776 return pa_xstrndup ( current
, l
);
779 /* What is interpreted as whitespace? */
780 #define WHITESPACE " \t\n "
782 /* Split a string into words. Otherwise similar to pa_split(). */
783 char * pa_split_spaces ( const char * c
, const char ** state
) {
784 const char * current
= * state
? * state
: c
;
787 if (!* current
|| * c
== 0 )
790 current
+= strspn ( current
, WHITESPACE
);
791 l
= strcspn ( current
, WHITESPACE
);
795 return pa_xstrndup ( current
, l
);
798 PA_STATIC_TLS_DECLARE ( signame
, pa_xfree
);
800 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
801 const char * pa_sig2str ( int sig
) {
814 char buf
[ SIG2STR_MAX
];
816 if ( sig2str ( sig
, buf
) == 0 ) {
817 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
818 t
= pa_sprintf_malloc ( "SIG%s" , buf
);
819 PA_STATIC_TLS_SET ( signame
, t
);
827 case SIGHUP
: return "SIGHUP" ;
829 case SIGINT
: return "SIGINT" ;
831 case SIGQUIT
: return "SIGQUIT" ;
833 case SIGILL
: return "SIGULL" ;
835 case SIGTRAP
: return "SIGTRAP" ;
837 case SIGABRT
: return "SIGABRT" ;
839 case SIGBUS
: return "SIGBUS" ;
841 case SIGFPE
: return "SIGFPE" ;
843 case SIGKILL
: return "SIGKILL" ;
846 case SIGUSR1
: return "SIGUSR1" ;
848 case SIGSEGV
: return "SIGSEGV" ;
850 case SIGUSR2
: return "SIGUSR2" ;
853 case SIGPIPE
: return "SIGPIPE" ;
856 case SIGALRM
: return "SIGALRM" ;
858 case SIGTERM
: return "SIGTERM" ;
860 case SIGSTKFLT
: return "SIGSTKFLT" ;
863 case SIGCHLD
: return "SIGCHLD" ;
866 case SIGCONT
: return "SIGCONT" ;
869 case SIGSTOP
: return "SIGSTOP" ;
872 case SIGTSTP
: return "SIGTSTP" ;
875 case SIGTTIN
: return "SIGTTIN" ;
878 case SIGTTOU
: return "SIGTTOU" ;
881 case SIGURG
: return "SIGURG" ;
884 case SIGXCPU
: return "SIGXCPU" ;
887 case SIGXFSZ
: return "SIGXFSZ" ;
890 case SIGVTALRM
: return "SIGVTALRM" ;
893 case SIGPROF
: return "SIGPROF" ;
896 case SIGWINCH
: return "SIGWINCH" ;
899 case SIGIO
: return "SIGIO" ;
902 case SIGPWR
: return "SIGPWR" ;
905 case SIGSYS
: return "SIGSYS" ;
910 if ( sig
>= SIGRTMIN
&& sig
<= SIGRTMAX
) {
911 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
912 t
= pa_sprintf_malloc ( "SIGRTMIN+%i" , sig
- SIGRTMIN
);
913 PA_STATIC_TLS_SET ( signame
, t
);
922 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
923 t
= pa_sprintf_malloc ( "SIG%i" , sig
);
924 PA_STATIC_TLS_SET ( signame
, t
);
930 /* Check whether the specified GID and the group name match */
931 static int is_group ( gid_t gid
, const char * name
) {
932 struct group group
, * result
= NULL
;
937 #ifdef HAVE_GETGRGID_R
938 #ifdef _SC_GETGR_R_SIZE_MAX
939 n
= sysconf ( _SC_GETGR_R_SIZE_MAX
);
946 data
= pa_xmalloc (( size_t ) n
);
949 if ( getgrgid_r ( gid
, & group
, data
, ( size_t ) n
, & result
) < 0 || ! result
) {
950 pa_log ( "getgrgid_r(%u): %s" , ( unsigned ) gid
, pa_cstrerror ( errno
));
958 r
= strcmp ( name
, result
-> gr_name
) == 0 ;
963 /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X) that do not
964 * support getgrgid_r. */
967 if (!( result
= getgrgid ( gid
))) {
968 pa_log ( "getgrgid(%u): %s" , gid
, pa_cstrerror ( errno
));
976 r
= strcmp ( name
, result
-> gr_name
) == 0 ;
984 /* Check the current user is member of the specified group */
985 int pa_own_uid_in_group ( const char * name
, gid_t
* gid
) {
986 GETGROUPS_T
* gids
, tgid
;
987 long n
= sysconf ( _SC_NGROUPS_MAX
);
992 gids
= pa_xmalloc ( sizeof ( GETGROUPS_T
) * ( size_t ) n
);
994 if (( n
= getgroups (( int ) n
, gids
)) < 0 ) {
995 pa_log ( "getgroups(): %s" , pa_cstrerror ( errno
));
999 for ( i
= 0 ; i
< n
; i
++) {
1001 if (( k
= is_group ( gids
[ i
], name
)) < 0 )
1010 if (( k
= is_group ( tgid
= getgid (), name
)) < 0 )
1026 /* Check whether the specifc user id is a member of the specified group */
1027 int pa_uid_in_group ( uid_t uid
, const char * name
) {
1028 char * g_buf
, * p_buf
;
1030 struct group grbuf
, * gr
;
1034 #ifdef _SC_GETGR_R_SIZE_MAX
1035 g_n
= sysconf ( _SC_GETGR_R_SIZE_MAX
);
1042 g_buf
= pa_xmalloc (( size_t ) g_n
);
1044 #ifdef _SC_GETPW_R_SIZE_MAX
1045 p_n
= sysconf ( _SC_GETPW_R_SIZE_MAX
);
1052 p_buf
= pa_xmalloc (( size_t ) p_n
);
1055 #ifdef HAVE_GETGRNAM_R
1056 if ( getgrnam_r ( name
, & grbuf
, g_buf
, ( size_t ) g_n
, & gr
) != 0 || ! gr
)
1058 if (!( gr
= getgrnam ( name
)))
1067 for ( i
= gr
-> gr_mem
; * i
; i
++) {
1068 struct passwd pwbuf
, * pw
;
1070 #ifdef HAVE_GETPWNAM_R
1071 if ( getpwnam_r (* i
, & pwbuf
, p_buf
, ( size_t ) p_n
, & pw
) != 0 || ! pw
)
1073 if (!( pw
= getpwnam (* i
)))
1077 if ( pw
-> pw_uid
== uid
) {
1090 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
1091 gid_t
pa_get_gid_of_group ( const char * name
) {
1092 gid_t ret
= ( gid_t
) - 1 ;
1095 struct group grbuf
, * gr
;
1097 #ifdef _SC_GETGR_R_SIZE_MAX
1098 g_n
= sysconf ( _SC_GETGR_R_SIZE_MAX
);
1105 g_buf
= pa_xmalloc (( size_t ) g_n
);
1108 #ifdef HAVE_GETGRNAM_R
1109 if ( getgrnam_r ( name
, & grbuf
, g_buf
, ( size_t ) g_n
, & gr
) != 0 || ! gr
)
1111 if (!( gr
= getgrnam ( name
)))
1126 int pa_check_in_group ( gid_t g
) {
1127 gid_t gids
[ NGROUPS_MAX
];
1130 if (( r
= getgroups ( NGROUPS_MAX
, gids
)) < 0 )
1140 #else /* HAVE_GRP_H */
1142 int pa_own_uid_in_group ( const char * name
, gid_t
* gid
) {
1148 int pa_uid_in_group ( uid_t uid
, const char * name
) {
1153 gid_t
pa_get_gid_of_group ( const char * name
) {
1158 int pa_check_in_group ( gid_t g
) {
1165 /* Lock or unlock a file entirely.
1166 (advisory on UNIX, mandatory on Windows) */
1167 int pa_lock_fd ( int fd
, int b
) {
1171 /* Try a R/W lock first */
1173 flock
. l_type
= ( short ) ( b
? F_WRLCK
: F_UNLCK
);
1174 flock
. l_whence
= SEEK_SET
;
1178 if ( fcntl ( fd
, F_SETLKW
, & flock
) >= 0 )
1181 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1182 if ( b
&& errno
== EBADF
) {
1183 flock
. l_type
= F_RDLCK
;
1184 if ( fcntl ( fd
, F_SETLKW
, & flock
) >= 0 )
1188 pa_log ( "%slock: %s" , ! b
? "un" : "" , pa_cstrerror ( errno
));
1192 HANDLE h
= ( HANDLE
) _get_osfhandle ( fd
);
1194 if ( b
&& LockFile ( h
, 0 , 0 , 0xFFFFFFFF , 0xFFFFFFFF ))
1196 if (! b
&& UnlockFile ( h
, 0 , 0 , 0xFFFFFFFF , 0xFFFFFFFF ))
1199 pa_log ( "%slock failed: 0x%08X" , ! b
? "un" : "" , GetLastError ());
1201 /* FIXME: Needs to set errno! */
1207 /* Remove trailing newlines from a string */
1208 char * pa_strip_nl ( char * s
) {
1211 s
[ strcspn ( s
, " \r\n " )] = 0 ;
1215 /* Create a temporary lock file and lock it. */
1216 int pa_lock_lockfile ( const char * fn
) {
1223 if (( fd
= open ( fn
, O_CREAT
| O_RDWR
1230 , S_IRUSR
| S_IWUSR
)) < 0 ) {
1231 pa_log_warn ( "Failed to create lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1235 if ( pa_lock_fd ( fd
, 1 ) < 0 ) {
1236 pa_log_warn ( "Failed to lock file '%s'." , fn
);
1240 if ( fstat ( fd
, & st
) < 0 ) {
1241 pa_log_warn ( "Failed to fstat() file '%s': %s" , fn
, pa_cstrerror ( errno
));
1245 /* Check wheter the file has been removed meanwhile. When yes,
1246 * restart this loop, otherwise, we're done */
1247 if ( st
. st_nlink
>= 1 )
1250 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1251 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1255 if ( pa_close ( fd
) < 0 ) {
1256 pa_log_warn ( "Failed to close file '%s': %s" , fn
, pa_cstrerror ( errno
));
1269 int saved_errno
= errno
;
1271 errno
= saved_errno
;
1277 /* Unlock a temporary lcok file */
1278 int pa_unlock_lockfile ( const char * fn
, int fd
) {
1283 if ( unlink ( fn
) < 0 ) {
1284 pa_log_warn ( "Unable to remove lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1289 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1290 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1294 if ( pa_close ( fd
) < 0 ) {
1295 pa_log_warn ( "Failed to close '%s': %s" , fn
, pa_cstrerror ( errno
));
1302 static char * get_pulse_home ( void ) {
1306 if (! pa_get_home_dir ( h
, sizeof ( h
))) {
1307 pa_log_error ( "Failed to get home directory." );
1311 if ( stat ( h
, & st
) < 0 ) {
1312 pa_log_error ( "Failed to stat home directory %s: %s" , h
, pa_cstrerror ( errno
));
1316 if ( st
. st_uid
!= getuid ()) {
1317 pa_log_error ( "Home directory %s not ours." , h
);
1322 return pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" , h
);
1325 char * pa_get_state_dir ( void ) {
1328 /* The state directory shall contain dynamic data that should be
1329 * kept across reboots, and is private to this user */
1331 if (!( d
= pa_xstrdup ( getenv ( "PULSE_STATE_PATH" ))))
1332 if (!( d
= get_pulse_home ()))
1335 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1336 * dir then this will break. */
1338 if ( pa_make_secure_dir ( d
, 0700U , ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1339 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1347 static char * make_random_dir ( mode_t m
) {
1348 static const char table
[] =
1349 "abcdefghijklmnopqrstuvwxyz"
1350 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1357 if (!( tmpdir
= getenv ( "TMPDIR" )))
1358 if (!( tmpdir
= getenv ( "TMP" )))
1359 if (!( tmpdir
= getenv ( "TEMP" )))
1360 tmpdir
= getenv ( "TEMPDIR" );
1362 if (! tmpdir
|| ! pa_is_path_absolute ( tmpdir
))
1365 fn
= pa_sprintf_malloc ( "%s/pulse-XXXXXXXXXXXX" , tmpdir
);
1366 pathlen
= strlen ( fn
);
1374 for ( i
= pathlen
- 12 ; i
< pathlen
; i
++)
1375 fn
[ i
] = table
[ rand () % ( sizeof ( table
)- 1 )];
1377 u
= umask ((~ m
) & 0777 );
1380 saved_errno
= errno
;
1382 errno
= saved_errno
;
1387 if ( errno
!= EEXIST
) {
1388 pa_log_error ( "Failed to create random directory %s: %s" , fn
, pa_cstrerror ( errno
));
1395 static int make_random_dir_and_link ( mode_t m
, const char * k
) {
1398 if (!( p
= make_random_dir ( m
)))
1401 if ( symlink ( p
, k
) < 0 ) {
1402 int saved_errno
= errno
;
1404 if ( errno
!= EEXIST
)
1405 pa_log_error ( "Failed to symlink %s to %s: %s" , k
, p
, pa_cstrerror ( errno
));
1410 errno
= saved_errno
;
1418 char * pa_get_runtime_dir ( void ) {
1419 char * d
, * k
= NULL
, * p
= NULL
, * t
= NULL
, * mid
;
1423 /* The runtime directory shall contain dynamic data that needs NOT
1424 * to be kept accross reboots and is usuallly private to the user,
1425 * except in system mode, where it might be accessible by other
1426 * users, too. Since we need POSIX locking and UNIX sockets in
1427 * this directory, we link it to a random subdir in /tmp, if it
1428 * was not explicitly configured. */
1430 m
= pa_in_system_mode () ? 0755U : 0700U ;
1432 if (( d
= getenv ( "PULSE_RUNTIME_PATH" ))) {
1434 if ( pa_make_secure_dir ( d
, m
, ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1435 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1439 return pa_xstrdup ( d
);
1442 if (!( d
= get_pulse_home ()))
1445 if ( pa_make_secure_dir ( d
, m
, ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1446 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1451 if (!( mid
= pa_machine_id ())) {
1456 k
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s:runtime" , d
, mid
);
1461 /* OK, first let's check if the "runtime" symlink is already
1464 if (!( p
= pa_readlink ( k
))) {
1466 if ( errno
!= ENOENT
) {
1467 pa_log_error ( "Failed to stat runtime directory %s: %s" , k
, pa_cstrerror ( errno
));
1471 /* Hmm, so the runtime directory didn't exist yet, so let's
1472 * create one in /tmp and symlink that to it */
1474 if ( make_random_dir_and_link ( 0700 , k
) < 0 ) {
1476 /* Mhmm, maybe another process was quicker than us,
1477 * let's check if that was valid */
1478 if ( errno
== EEXIST
)
1487 /* Make sure that this actually makes sense */
1488 if (! pa_is_path_absolute ( p
)) {
1489 pa_log_error ( "Path %s in link %s is not absolute." , p
, k
);
1494 /* Hmm, so this symlink is still around, make sure nobody fools
1497 if ( lstat ( p
, & st
) < 0 ) {
1499 if ( errno
!= ENOENT
) {
1500 pa_log_error ( "Failed to stat runtime directory %s: %s" , p
, pa_cstrerror ( errno
));
1506 if ( S_ISDIR ( st
. st_mode
) &&
1507 ( st
. st_uid
== getuid ()) &&
1508 (( st
. st_mode
& 0777 ) == 0700 )) {
1514 pa_log_info ( "Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory." );
1520 /* Hmm, so the link points to some nonexisting or invalid
1521 * dir. Let's replace it by a new link. We first create a
1522 * temporary link and then rename that to allow concurrent
1523 * execution of this function. */
1525 t
= pa_sprintf_malloc ( "%s.tmp" , k
);
1527 if ( make_random_dir_and_link ( 0700 , t
) < 0 ) {
1529 if ( errno
!= EEXIST
) {
1530 pa_log_error ( "Failed to symlink %s: %s" , t
, pa_cstrerror ( errno
));
1537 /* Hmm, someone lese was quicker then us. Let's give
1538 * him some time to finish, and retry. */
1543 /* OK, we succeeded in creating the temporary symlink, so
1544 * let's rename it */
1545 if ( rename ( t
, k
) < 0 ) {
1546 pa_log_error ( "Failed to rename %s to %s: %s" , t
, k
, pa_cstrerror ( errno
));
1562 /* Try to open a configuration file. If "env" is specified, open the
1563 * value of the specified environment variable. Otherwise look for a
1564 * file "local" in the home directory or a file "global" in global
1565 * file system. If "result" is non-NULL, a pointer to a newly
1566 * allocated buffer containing the used configuration file is
1568 FILE * pa_open_config_file ( const char * global
, const char * local
, const char * env
, char ** result
) {
1573 if (! getenv ( PULSE_ROOTENV
))
1577 if ( env
&& ( fn
= getenv ( env
))) {
1581 if (! ExpandEnvironmentStrings ( fn
, buf
, PATH_MAX
))
1582 /* FIXME: Needs to set errno! */
1587 if (( f
= fopen ( fn
, "r" ))) {
1589 * result
= pa_xstrdup ( fn
);
1594 pa_log_warn ( "Failed to open configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1604 if (( e
= getenv ( "PULSE_CONFIG_PATH" )))
1605 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , e
, local
);
1606 else if ( pa_get_home_dir ( h
, sizeof ( h
)))
1607 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s" , h
, local
);
1612 if (! ExpandEnvironmentStrings ( lfn
, buf
, PATH_MAX
)) {
1613 /* FIXME: Needs to set errno! */
1620 if (( f
= fopen ( fn
, "r" ))) {
1622 * result
= pa_xstrdup ( fn
);
1628 if ( errno
!= ENOENT
) {
1629 pa_log_warn ( "Failed to open configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1641 if (! ExpandEnvironmentStrings ( global
, buf
, PATH_MAX
))
1642 /* FIXME: Needs to set errno! */
1647 if (( f
= fopen ( global
, "r" ))) {
1650 * result
= pa_xstrdup ( global
);
1660 char * pa_find_config_file ( const char * global
, const char * local
, const char * env
) {
1665 if (! getenv ( PULSE_ROOTENV
))
1669 if ( env
&& ( fn
= getenv ( env
))) {
1672 if (! ExpandEnvironmentStrings ( fn
, buf
, PATH_MAX
))
1673 /* FIXME: Needs to set errno! */
1678 if ( access ( fn
, R_OK
) == 0 )
1679 return pa_xstrdup ( fn
);
1681 pa_log_warn ( "Failed to access 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 ( pa_get_home_dir ( h
, sizeof ( h
)))
1693 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s" , h
, local
);
1698 if (! ExpandEnvironmentStrings ( lfn
, buf
, PATH_MAX
)) {
1699 /* FIXME: Needs to set errno! */
1706 if ( access ( fn
, R_OK
) == 0 ) {
1707 char * r
= pa_xstrdup ( fn
);
1712 if ( errno
!= ENOENT
) {
1713 pa_log_warn ( "Failed to access configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1723 if (! ExpandEnvironmentStrings ( global
, buf
, PATH_MAX
))
1724 /* FIXME: Needs to set errno! */
1729 if ( access ( global
, R_OK
) == 0 )
1730 return pa_xstrdup ( global
);
1738 /* Format the specified data as a hexademical string */
1739 char * pa_hexstr ( const uint8_t * d
, size_t dlength
, char * s
, size_t slength
) {
1740 size_t i
= 0 , j
= 0 ;
1741 const char hex
[] = "0123456789abcdef" ;
1745 pa_assert ( slength
> 0 );
1747 while ( i
< dlength
&& j
+ 3 <= slength
) {
1748 s
[ j
++] = hex
[* d
>> 4 ];
1749 s
[ j
++] = hex
[* d
& 0xF ];
1755 s
[ j
< slength
? j
: slength
] = 0 ;
1759 /* Convert a hexadecimal digit to a number or -1 if invalid */
1760 static int hexc ( char c
) {
1761 if ( c
>= '0' && c
<= '9' )
1764 if ( c
>= 'A' && c
<= 'F' )
1765 return c
- 'A' + 10 ;
1767 if ( c
>= 'a' && c
<= 'f' )
1768 return c
- 'a' + 10 ;
1774 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1775 size_t pa_parsehex ( const char * p
, uint8_t * d
, size_t dlength
) {
1781 while ( j
< dlength
&& * p
) {
1784 if (( b
= hexc (*( p
++))) < 0 )
1787 d
[ j
] = ( uint8_t ) ( b
<< 4 );
1792 if (( b
= hexc (*( p
++))) < 0 )
1795 d
[ j
] |= ( uint8_t ) b
;
1802 /* Returns nonzero when *s starts with *pfx */
1803 pa_bool_t
pa_startswith ( const char * s
, const char * pfx
) {
1811 return strlen ( s
) >= l
&& strncmp ( s
, pfx
, l
) == 0 ;
1814 /* Returns nonzero when *s ends with *sfx */
1815 pa_bool_t
pa_endswith ( const char * s
, const char * sfx
) {
1824 return l1
>= l2
&& strcmp ( s
+ l1
- l2
, sfx
) == 0 ;
1827 pa_bool_t
pa_is_path_absolute ( const char * fn
) {
1833 return strlen ( fn
) >= 3 && isalpha ( fn
[ 0 ]) && fn
[ 1 ] == ':' && fn
[ 2 ] == ' \\ ' ;
1837 char * pa_make_path_absolute ( const char * p
) {
1843 if ( pa_is_path_absolute ( p
))
1844 return pa_xstrdup ( p
);
1846 if (!( cwd
= pa_getcwd ()))
1847 return pa_xstrdup ( p
);
1849 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , cwd
, p
);
1854 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1855 * if fn is non-null and starts with / return fn
1856 * otherwise append fn to the run time path and return it */
1857 static char * get_path ( const char * fn
, pa_bool_t prependmid
, pa_bool_t rt
) {
1860 if ( pa_is_path_absolute ( fn
))
1861 return pa_xstrdup ( fn
);
1863 rtp
= rt
? pa_get_runtime_dir () : pa_get_state_dir ();
1874 if (!( mid
= pa_machine_id ())) {
1879 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s:%s" , rtp
, mid
, fn
);
1882 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , rtp
, fn
);
1890 char * pa_runtime_path ( const char * fn
) {
1891 return get_path ( fn
, FALSE
, TRUE
);
1894 char * pa_state_path ( const char * fn
, pa_bool_t appendmid
) {
1895 return get_path ( fn
, appendmid
, FALSE
);
1898 /* Convert the string s to a signed integer in *ret_i */
1899 int pa_atoi ( const char * s
, int32_t * ret_i
) {
1907 l
= strtol ( s
, & x
, 0 );
1909 if (! x
|| * x
|| errno
) {
1915 if (( int32_t ) l
!= l
) {
1920 * ret_i
= ( int32_t ) l
;
1925 /* Convert the string s to an unsigned integer in *ret_u */
1926 int pa_atou ( const char * s
, uint32_t * ret_u
) {
1934 l
= strtoul ( s
, & x
, 0 );
1936 if (! x
|| * x
|| errno
) {
1942 if (( uint32_t ) l
!= l
) {
1947 * ret_u
= ( uint32_t ) l
;
1952 #ifdef HAVE_STRTOF_L
1953 static locale_t c_locale
= NULL
;
1955 static void c_locale_destroy ( void ) {
1956 freelocale ( c_locale
);
1960 int pa_atod ( const char * s
, double * ret_d
) {
1967 /* This should be locale independent */
1969 #ifdef HAVE_STRTOF_L
1973 if (( c_locale
= newlocale ( LC_ALL_MASK
, "C" , NULL
)))
1974 atexit ( c_locale_destroy
);
1980 f
= strtod_l ( s
, & x
, c_locale
);
1988 if (! x
|| * x
|| errno
) {
1999 /* Same as snprintf, but guarantees NUL-termination on every platform */
2000 size_t pa_snprintf ( char * str
, size_t size
, const char * format
, ...) {
2005 pa_assert ( size
> 0 );
2008 va_start ( ap
, format
);
2009 ret
= pa_vsnprintf ( str
, size
, format
, ap
);
2015 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2016 size_t pa_vsnprintf ( char * str
, size_t size
, const char * format
, va_list ap
) {
2020 pa_assert ( size
> 0 );
2023 ret
= vsnprintf ( str
, size
, format
, ap
);
2030 if (( size_t ) ret
> size
- 1 )
2033 return ( size_t ) ret
;
2036 /* Truncate the specified string, but guarantee that the string
2037 * returned still validates as UTF8 */
2038 char * pa_truncate_utf8 ( char * c
, size_t l
) {
2040 pa_assert ( pa_utf8_valid ( c
));
2047 while ( l
> 0 && ! pa_utf8_valid ( c
))
2053 char * pa_getcwd ( void ) {
2057 char * p
= pa_xmalloc ( l
);
2061 if ( errno
!= ERANGE
)
2069 void * pa_will_need ( const void * p
, size_t l
) {
2070 #ifdef RLIMIT_MEMLOCK
2081 a
= PA_PAGE_ALIGN_PTR ( p
);
2082 size
= ( size_t ) (( const uint8_t *) p
+ l
- ( const uint8_t *) a
);
2084 #ifdef HAVE_POSIX_MADVISE
2085 if (( r
= posix_madvise (( void *) a
, size
, POSIX_MADV_WILLNEED
)) == 0 ) {
2086 pa_log_debug ( "posix_madvise() worked fine!" );
2091 /* Most likely the memory was not mmap()ed from a file and thus
2092 * madvise() didn't work, so let's misuse mlock() do page this
2093 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2094 * inviting, the man page of mlock() tells us: "All pages that
2095 * contain a part of the specified address range are guaranteed to
2096 * be resident in RAM when the call returns successfully." */
2098 #ifdef RLIMIT_MEMLOCK
2099 pa_assert_se ( getrlimit ( RLIMIT_MEMLOCK
, & rlim
) == 0 );
2101 if ( rlim
. rlim_cur
< PA_PAGE_SIZE
) {
2102 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
));
2107 bs
= PA_PAGE_ALIGN (( size_t ) rlim
. rlim_cur
);
2109 bs
= PA_PAGE_SIZE
* 4 ;
2112 pa_log_debug ( "posix_madvise() failed (or doesn't exist), trying mlock(): %s" , pa_cstrerror ( r
));
2115 while ( size
> 0 && bs
> 0 ) {
2120 if ( mlock ( a
, bs
) < 0 ) {
2121 bs
= PA_PAGE_ALIGN ( bs
/ 2 );
2125 pa_assert_se ( munlock ( a
, bs
) == 0 );
2127 a
= ( const uint8_t *) a
+ bs
;
2133 pa_log_debug ( "mlock() failed too (or doesn't exist), giving up: %s" , pa_cstrerror ( errno
));
2135 pa_log_debug ( "mlock() worked fine!" );
2140 void pa_close_pipe ( int fds
[ 2 ]) {
2144 pa_assert_se ( pa_close ( fds
[ 0 ]) == 0 );
2147 pa_assert_se ( pa_close ( fds
[ 1 ]) == 0 );
2149 fds
[ 0 ] = fds
[ 1 ] = - 1 ;
2152 char * pa_readlink ( const char * p
) {
2161 if (( n
= readlink ( p
, c
, l
- 1 )) < 0 ) {
2166 if (( size_t ) n
< l
- 1 ) {
2176 int pa_close_all ( int except_fd
, ...) {
2181 va_start ( ap
, except_fd
);
2184 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2189 p
= pa_xnew ( int , n
+ 1 );
2191 va_start ( ap
, except_fd
);
2194 if ( except_fd
>= 0 ) {
2198 while (( fd
= va_arg ( ap
, int )) >= 0 )
2205 r
= pa_close_allv ( p
);
2211 int pa_close_allv ( const int except_fds
[]) {
2220 if (( d
= opendir ( "/proc/self/fd" ))) {
2224 while (( de
= readdir ( d
))) {
2230 if ( de
-> d_name
[ 0 ] == '.' )
2234 l
= strtol ( de
-> d_name
, & e
, 10 );
2235 if ( errno
!= 0 || ! e
|| * e
) {
2243 if (( long ) fd
!= l
) {
2256 for ( i
= 0 ; except_fds
[ i
] >= 0 ; i
++)
2257 if ( except_fds
[ i
] == fd
) {
2265 if ( pa_close ( fd
) < 0 ) {
2266 saved_errno
= errno
;
2268 errno
= saved_errno
;
2280 if ( getrlimit ( RLIMIT_NOFILE
, & rl
) < 0 )
2283 for ( fd
= 3 ; fd
< ( int ) rl
. rlim_max
; fd
++) {
2288 for ( i
= 0 ; except_fds
[ i
] >= 0 ; i
++)
2289 if ( except_fds
[ i
] == fd
) {
2297 if ( pa_close ( fd
) < 0 && errno
!= EBADF
)
2304 int pa_unblock_sigs ( int except
, ...) {
2309 va_start ( ap
, except
);
2312 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2317 p
= pa_xnew ( int , n
+ 1 );
2319 va_start ( ap
, except
);
2326 while (( sig
= va_arg ( ap
, int )) >= 0 )
2333 r
= pa_unblock_sigsv ( p
);
2339 int pa_unblock_sigsv ( const int except
[]) {
2343 if ( sigemptyset (& ss
) < 0 )
2346 for ( i
= 0 ; except
[ i
] > 0 ; i
++)
2347 if ( sigaddset (& ss
, except
[ i
]) < 0 )
2350 return sigprocmask ( SIG_SETMASK
, & ss
, NULL
);
2353 int pa_reset_sigs ( int except
, ...) {
2358 va_start ( ap
, except
);
2361 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2366 p
= pa_xnew ( int , n
+ 1 );
2368 va_start ( ap
, except
);
2375 while (( sig
= va_arg ( ap
, int )) >= 0 )
2382 r
= pa_reset_sigsv ( p
);
2388 int pa_reset_sigsv ( const int except
[]) {
2391 for ( sig
= 1 ; sig
< NSIG
; sig
++) {
2392 pa_bool_t reset
= TRUE
;
2403 for ( i
= 0 ; except
[ i
] > 0 ; i
++) {
2404 if ( sig
== except
[ i
]) {
2413 struct sigaction sa
;
2415 memset (& sa
, 0 , sizeof ( sa
));
2416 sa
. sa_handler
= SIG_DFL
;
2418 /* On Linux the first two RT signals are reserved by
2419 * glibc, and sigaction() will return EINVAL for them. */
2420 if (( sigaction ( sig
, & sa
, NULL
) < 0 ))
2421 if ( errno
!= EINVAL
)
2429 void pa_set_env ( const char * key
, const char * value
) {
2433 putenv ( pa_sprintf_malloc ( "%s=%s" , key
, value
));
2436 pa_bool_t
pa_in_system_mode ( void ) {
2439 if (!( e
= getenv ( "PULSE_SYSTEM" )))
2445 char * pa_machine_id ( void ) {
2449 /* The returned value is supposed be some kind of ascii identifier
2450 * that is unique and stable across reboots. */
2452 /* First we try the D-Bus UUID, which is the best option we have,
2453 * since it fits perfectly our needs and is not as volatile as the
2454 * hostname which might be set from dhcp. */
2456 if (( f
= fopen ( PA_MACHINE_ID
, "r" ))) {
2457 char ln
[ 34 ] = "" , * r
;
2459 r
= fgets ( ln
, sizeof ( ln
)- 1 , f
);
2465 return pa_xstrdup ( ln
);
2468 /* The we fall back to the host name. It supposed to be somewhat
2469 * unique, at least in a network, but may change. */
2477 if (! pa_get_host_name ( c
, l
)) {
2479 if ( errno
!= EINVAL
&& errno
!= ENAMETOOLONG
)
2482 } else if ( strlen ( c
) < l
- 1 ) {
2492 /* Hmm, the hostname is as long the space we offered the
2493 * function, we cannot know if it fully fit in, so let's play
2494 * safe and retry. */
2500 /* If no hostname was set we use the POSIX hostid. It's usually
2501 * the IPv4 address. Mit not be that stable. */
2502 return pa_sprintf_malloc ( "%08lx" , ( unsigned long ) gethostid
);
2505 char * pa_uname_string ( void ) {
2508 pa_assert_se ( uname (& u
) >= 0 );
2510 return pa_sprintf_malloc ( "%s %s %s %s" , u
. sysname
, u
. machine
, u
. release
, u
. version
);
2513 #ifdef HAVE_VALGRIND_MEMCHECK_H
2514 pa_bool_t
pa_in_valgrind ( void ) {
2517 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2518 * here instead of really checking whether we run in valgrind or
2522 b
= getenv ( "VALGRIND" ) ? 2 : 1 ;
2528 unsigned pa_gcd ( unsigned a
, unsigned b
) {
2539 void pa_reduce ( unsigned * num
, unsigned * den
) {
2541 unsigned gcd
= pa_gcd (* num
, * den
);
2549 pa_assert ( pa_gcd (* num
, * den
) == 1 );
2552 unsigned pa_ncpus ( void ) {
2555 #ifdef _SC_NPROCESSORS_CONF
2556 ncpus
= sysconf ( _SC_NPROCESSORS_CONF
);
2561 return ncpus
<= 0 ? 1 : ( unsigned ) ncpus
;
2564 char * pa_replace ( const char * s
, const char * a
, const char * b
) {
2573 sb
= pa_strbuf_new ();
2578 if (!( p
= strstr ( s
, a
)))
2581 pa_strbuf_putsn ( sb
, s
, p
- s
);
2582 pa_strbuf_puts ( sb
, b
);
2586 pa_strbuf_puts ( sb
, s
);
2588 return pa_strbuf_tostring_free ( sb
);
2591 char * pa_unescape ( char * p
) {
2593 pa_bool_t escaped
= FALSE
;
2595 for ( s
= p
, d
= p
; * s
; s
++) {
2596 if (! escaped
&& * s
== ' \\ ' ) {
2610 char * pa_realpath ( const char * path
) {
2614 /* We want only abolsute paths */
2615 if ( path
[ 0 ] != '/' ) {
2620 #if defined(__GLIBC__) || defined(__APPLE__)
2624 if (!( r
= realpath ( path
, NULL
)))
2627 /* We copy this here in case our pa_xmalloc() is not
2628 * implemented on top of libc malloc() */
2632 #elif defined(PATH_MAX)
2635 path_buf
= pa_xmalloc ( PATH_MAX
);
2637 if (!( t
= realpath ( path
, path_buf
))) {
2643 #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."