]>
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>
54 #if defined(__linux__) && !defined(SCHED_RESET_ON_FORK)
55 #define SCHED_RESET_ON_FORK 0x40000000
59 #ifdef HAVE_SYS_RESOURCE_H
60 #include <sys/resource.h>
63 #ifdef HAVE_SYS_CAPABILITY_H
64 #include <sys/capability.h>
67 #ifdef HAVE_SYS_MMAN_H
91 #ifdef HAVE_LIBSAMPLERATE
92 #include <samplerate.h>
103 #include <pulse/xmalloc.h>
104 #include <pulse/util.h>
105 #include <pulse/utf8.h>
107 #include <pulsecore/core-error.h>
108 #include <pulsecore/winsock.h>
109 #include <pulsecore/log.h>
110 #include <pulsecore/macro.h>
111 #include <pulsecore/thread.h>
112 #include <pulsecore/strbuf.h>
114 #include "core-util.h"
116 /* Not all platforms have this */
118 #define MSG_NOSIGNAL 0
123 #define PULSE_ROOTENV "PULSE_ROOT"
125 int pa_set_root ( HANDLE handle
) {
126 char library_path
[ MAX_PATH
+ sizeof ( PULSE_ROOTENV
) + 1 ], * sep
;
128 strcpy ( library_path
, PULSE_ROOTENV
"=" );
130 /* FIXME: Needs to set errno */
132 if (! GetModuleFileName ( handle
, library_path
+ sizeof ( PULSE_ROOTENV
), MAX_PATH
))
135 sep
= strrchr ( library_path
, PA_PATH_SEP_CHAR
);
139 if ( _putenv ( library_path
) < 0 )
147 /** Make a file descriptor nonblock. Doesn't do any error checking */
148 void pa_make_fd_nonblock ( int fd
) {
154 pa_assert_se (( v
= fcntl ( fd
, F_GETFL
)) >= 0 );
156 if (!( v
& O_NONBLOCK
))
157 pa_assert_se ( fcntl ( fd
, F_SETFL
, v
| O_NONBLOCK
) >= 0 );
159 #elif defined(OS_IS_WIN32)
161 if ( ioctlsocket ( fd
, FIONBIO
, & arg
) < 0 ) {
162 pa_assert_se ( WSAGetLastError () == WSAENOTSOCK
);
163 pa_log_warn ( "Only sockets can be made non-blocking!" );
166 pa_log_warn ( "Non-blocking I/O not supported.!" );
171 /* Set the FD_CLOEXEC flag for a fd */
172 void pa_make_fd_cloexec ( int fd
) {
178 pa_assert_se (( v
= fcntl ( fd
, F_GETFD
, 0 )) >= 0 );
180 if (!( v
& FD_CLOEXEC
))
181 pa_assert_se ( fcntl ( fd
, F_SETFD
, v
| FD_CLOEXEC
) >= 0 );
186 /** Creates a directory securely */
187 int pa_make_secure_dir ( const char * dir
, mode_t m
, uid_t uid
, gid_t gid
) {
198 u
= umask ((~ m
) & 0777 );
204 if ( r
< 0 && errno
!= EEXIST
)
208 if ( uid
== ( uid_t
)- 1 )
210 if ( gid
== ( gid_t
)- 1 )
212 ( void ) chown ( dir
, uid
, gid
);
220 if ( lstat ( dir
, & st
) < 0 )
222 if ( stat ( dir
, & st
) < 0 )
227 if (! S_ISDIR ( st
. st_mode
) ||
228 ( st
. st_uid
!= uid
) ||
229 ( st
. st_gid
!= gid
) ||
230 (( st
. st_mode
& 0777 ) != m
)) {
235 pa_log_warn ( "Secure directory creation not supported on Win32." );
248 /* Return a newly allocated sting containing the parent directory of the specified file */
249 char * pa_parent_dir ( const char * fn
) {
250 char * slash
, * dir
= pa_xstrdup ( fn
);
252 if (( slash
= ( char *) pa_path_get_filename ( dir
)) == dir
) {
262 /* Creates a the parent directory of the specified path securely */
263 int pa_make_secure_parent_dir ( const char * fn
, mode_t m
, uid_t uid
, gid_t gid
) {
267 if (!( dir
= pa_parent_dir ( fn
)))
270 if ( pa_make_secure_dir ( dir
, m
, uid
, gid
) < 0 )
280 /** Platform independent read function. Necessary since not all
281 * systems treat all file descriptors equal. If type is
282 * non-NULL it is used to cache the type of the fd. This is
283 * useful for making sure that only a single syscall is executed per
284 * function call. The variable pointed to should be initialized to 0
286 ssize_t
pa_read ( int fd
, void * buf
, size_t count
, int * type
) {
290 if (! type
|| * type
== 0 ) {
293 if (( r
= recv ( fd
, buf
, count
, 0 )) >= 0 )
296 if ( WSAGetLastError () != WSAENOTSOCK
) {
297 errno
= WSAGetLastError ();
310 if (( r
= read ( fd
, buf
, count
)) < 0 )
318 /** Similar to pa_read(), but handles writes */
319 ssize_t
pa_write ( int fd
, const void * buf
, size_t count
, int * type
) {
321 if (! type
|| * type
== 0 ) {
325 if (( r
= send ( fd
, buf
, count
, MSG_NOSIGNAL
)) < 0 ) {
337 if ( WSAGetLastError () != WSAENOTSOCK
) {
338 errno
= WSAGetLastError ();
342 if ( errno
!= ENOTSOCK
)
353 if (( r
= write ( fd
, buf
, count
)) < 0 )
361 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
362 * unless EOF is reached or an error occurred */
363 ssize_t
pa_loop_read ( int fd
, void * data
, size_t size
, int * type
) {
379 if (( r
= pa_read ( fd
, data
, size
, type
)) < 0 )
386 data
= ( uint8_t *) data
+ r
;
393 /** Similar to pa_loop_read(), but wraps write() */
394 ssize_t
pa_loop_write ( int fd
, const void * data
, size_t size
, int * type
) {
410 if (( r
= pa_write ( fd
, data
, size
, type
)) < 0 )
417 data
= ( const uint8_t *) data
+ r
;
424 /** Platform independent read function. Necessary since not all
425 * systems treat all file descriptors equal. */
426 int pa_close ( int fd
) {
431 if (( ret
= closesocket ( fd
)) == 0 )
434 if ( WSAGetLastError () != WSAENOTSOCK
) {
435 errno
= WSAGetLastError ();
443 if (( r
= close ( fd
)) < 0 )
451 /* Print a warning messages in case that the given signal is not
452 * blocked or trapped */
453 void pa_check_signal_is_blocked ( int sig
) {
454 #ifdef HAVE_SIGACTION
458 /* If POSIX threads are supported use thread-aware
459 * pthread_sigmask() function, to check if the signal is
460 * blocked. Otherwise fall back to sigprocmask() */
463 if ( pthread_sigmask ( SIG_SETMASK
, NULL
, & set
) < 0 ) {
465 if ( sigprocmask ( SIG_SETMASK
, NULL
, & set
) < 0 ) {
466 pa_log ( "sigprocmask(): %s" , pa_cstrerror ( errno
));
473 if ( sigismember (& set
, sig
))
476 /* Check whether the signal is trapped */
478 if ( sigaction ( sig
, NULL
, & sa
) < 0 ) {
479 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
483 if ( sa
. sa_handler
!= SIG_DFL
)
486 pa_log_warn ( "%s is not trapped. This might cause malfunction!" , pa_sig2str ( sig
));
487 #else /* HAVE_SIGACTION */
488 pa_log_warn ( "%s might not be trapped. This might cause malfunction!" , pa_sig2str ( sig
));
492 /* The following function is based on an example from the GNU libc
493 * documentation. This function is similar to GNU's asprintf(). */
494 char * pa_sprintf_malloc ( const char * format
, ...) {
504 c
= pa_xrealloc ( c
, size
);
506 va_start ( ap
, format
);
507 r
= vsnprintf ( c
, size
, format
, ap
);
512 if ( r
> - 1 && ( size_t ) r
< size
)
515 if ( r
> - 1 ) /* glibc 2.1 */
522 /* Same as the previous function, but use a va_list instead of an
524 char * pa_vsprintf_malloc ( const char * format
, va_list ap
) {
534 c
= pa_xrealloc ( c
, size
);
537 r
= vsnprintf ( c
, size
, format
, aq
);
542 if ( r
> - 1 && ( size_t ) r
< size
)
545 if ( r
> - 1 ) /* glibc 2.1 */
552 /* Similar to OpenBSD's strlcpy() function */
553 char * pa_strlcpy ( char * b
, const char * s
, size_t l
) {
563 static int set_scheduler ( int rtprio
) {
564 struct sched_param sp
;
570 dbus_error_init (& error
);
574 sp
. sched_priority
= rtprio
;
576 #ifdef SCHED_RESET_ON_FORK
577 if (( r
= pthread_setschedparam ( pthread_self (), SCHED_RR
| SCHED_RESET_ON_FORK
, & sp
)) == 0 ) {
578 pa_log_debug ( "SCHED_RR|SCHED_RESET_ON_FORK worked." );
583 if (( r
= pthread_setschedparam ( pthread_self (), SCHED_RR
, & sp
)) == 0 ) {
584 pa_log_debug ( "SCHED_RR worked." );
589 /* Try to talk to RealtimeKit */
591 if (!( bus
= dbus_bus_get ( DBUS_BUS_SYSTEM
, & error
))) {
592 pa_log ( "Failed to connect to system bus: %s \n " , error
. message
);
593 dbus_error_free (& error
);
598 r
= rtkit_make_realtime ( bus
, 0 , rtprio
);
599 dbus_connection_unref ( bus
);
602 pa_log_debug ( "RealtimeKit worked." );
614 /* Make the current thread a realtime thread, and acquire the highest
615 * rtprio we can get that is less or equal the specified parameter. If
616 * the thread is already realtime, don't do anything. */
617 int pa_make_realtime ( int rtprio
) {
619 #ifdef _POSIX_PRIORITY_SCHEDULING
621 struct sched_param sp
;
627 if (( r
= pthread_getschedparam ( pthread_self (), & policy
, & sp
)) != 0 ) {
628 pa_log ( "pthread_getschedgetparam(): %s" , pa_cstrerror ( r
));
632 #ifdef SCHED_RESET_ON_FORK
633 policy
&= ~ SCHED_RESET_ON_FORK
;
636 if (( policy
== SCHED_FIFO
|| policy
== SCHED_RR
) && sp
. sched_priority
>= rtprio
) {
637 pa_log_info ( "Thread already being scheduled with SCHED_FIFO/SCHED_RR with priority %i." , sp
. sched_priority
);
641 if ( set_scheduler ( rtprio
) >= 0 ) {
642 pa_log_info ( "Successfully enabled SCHED_RR scheduling for thread, with priority %i." , rtprio
);
646 for ( rtprio_try
= rtprio
- 1 ; rtprio_try
>= 1 ; rtprio_try
--) {
647 if ( set_scheduler ( rtprio_try
)) {
648 pa_log_info ( "Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i." , rtprio_try
, rtprio
);
653 pa_log_warn ( "Failed to acquire real-time scheduling: %s" , pa_cstrerror ( r
));
662 /* This is merely used for giving the user a hint. This is not correct
663 * for anything security related */
664 pa_bool_t
pa_can_realtime ( void ) {
669 #if defined(HAVE_SYS_RESOURCE_H) && defined(RLIMIT_RTPRIO)
673 if ( getrlimit ( RLIMIT_RTPRIO
, & rl
) >= 0 )
674 if ( rl
. rlim_cur
> 0 || rl
. rlim_cur
== RLIM_INFINITY
)
679 #if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_SYS_NICE)
683 if (( cap
= cap_get_proc ())) {
684 cap_flag_value_t flag
= CAP_CLEAR
;
686 if ( cap_get_flag ( cap
, CAP_SYS_NICE
, CAP_EFFECTIVE
, & flag
) >= 0 )
687 if ( flag
== CAP_SET
) {
700 /* This is merely used for giving the user a hint. This is not correct
701 * for anything security related */
702 pa_bool_t
pa_can_high_priority ( void ) {
707 #if defined(HAVE_SYS_RESOURCE_H) && defined(RLIMIT_RTPRIO)
711 if ( getrlimit ( RLIMIT_NICE
, & rl
) >= 0 )
712 if ( rl
. rlim_cur
>= 21 || rl
. rlim_cur
== RLIM_INFINITY
)
717 #if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_SYS_NICE)
721 if (( cap
= cap_get_proc ())) {
722 cap_flag_value_t flag
= CAP_CLEAR
;
724 if ( cap_get_flag ( cap
, CAP_SYS_NICE
, CAP_EFFECTIVE
, & flag
) >= 0 )
725 if ( flag
== CAP_SET
) {
738 /* Raise the priority of the current process as much as possible that
739 * is <= the specified nice level..*/
740 int pa_raise_priority ( int nice_level
) {
742 #ifdef HAVE_SYS_RESOURCE_H
743 if ( setpriority ( PRIO_PROCESS
, 0 , nice_level
) < 0 ) {
746 for ( n
= nice_level
+ 1 ; n
< 0 ; n
++) {
748 if ( setpriority ( PRIO_PROCESS
, 0 , n
) == 0 ) {
749 pa_log_info ( "Successfully acquired nice level %i, which is lower than the requested %i." , n
, nice_level
);
754 pa_log_warn ( "setpriority(): %s" , pa_cstrerror ( errno
));
758 pa_log_info ( "Successfully gained nice level %i." , nice_level
);
762 if ( nice_level
< 0 ) {
763 if (! SetPriorityClass ( GetCurrentProcess (), HIGH_PRIORITY_CLASS
)) {
764 pa_log_warn ( "SetPriorityClass() failed: 0x%08X" , GetLastError ());
768 pa_log_info ( "Successfully gained high priority class." );
775 /* Reset the priority to normal, inverting the changes made by
776 * pa_raise_priority() and pa_make_realtime()*/
777 void pa_reset_priority ( void ) {
778 #ifdef HAVE_SYS_RESOURCE_H
779 struct sched_param sp
;
781 setpriority ( PRIO_PROCESS
, 0 , 0 );
783 memset (& sp
, 0 , sizeof ( sp
));
784 pa_assert_se ( pthread_setschedparam ( pthread_self (), SCHED_OTHER
, & sp
) == 0 );
788 SetPriorityClass ( GetCurrentProcess (), NORMAL_PRIORITY_CLASS
);
792 int pa_match ( const char * expr
, const char * v
) {
797 if ( regcomp (& re
, expr
, REG_NOSUB
| REG_EXTENDED
) != 0 ) {
802 if (( k
= regexec (& re
, v
, 0 , NULL
, 0 )) == 0 )
804 else if ( k
== REG_NOMATCH
)
817 /* Try to parse a boolean string value.*/
818 int pa_parse_boolean ( const char * v
) {
823 /* First we check language independant */
824 if (! strcmp ( v
, "1" ) || v
[ 0 ] == 'y' || v
[ 0 ] == 'Y' || v
[ 0 ] == 't' || v
[ 0 ] == 'T' || ! strcasecmp ( v
, "on" ))
826 else if (! strcmp ( v
, "0" ) || v
[ 0 ] == 'n' || v
[ 0 ] == 'N' || v
[ 0 ] == 'f' || v
[ 0 ] == 'F' || ! strcasecmp ( v
, "off" ))
829 /* And then we check language dependant */
830 if (( expr
= nl_langinfo ( YESEXPR
)))
832 if (( r
= pa_match ( expr
, v
)) > 0 )
835 if (( expr
= nl_langinfo ( NOEXPR
)))
837 if (( r
= pa_match ( expr
, v
)) > 0 )
844 /* Split the specified string wherever one of the strings in delimiter
845 * occurs. Each time it is called returns a newly allocated string
846 * with pa_xmalloc(). The variable state points to, should be
847 * initiallized to NULL before the first call. */
848 char * pa_split ( const char * c
, const char * delimiter
, const char ** state
) {
849 const char * current
= * state
? * state
: c
;
855 l
= strcspn ( current
, delimiter
);
861 return pa_xstrndup ( current
, l
);
864 /* What is interpreted as whitespace? */
865 #define WHITESPACE " \t\n "
867 /* Split a string into words. Otherwise similar to pa_split(). */
868 char * pa_split_spaces ( const char * c
, const char ** state
) {
869 const char * current
= * state
? * state
: c
;
872 if (!* current
|| * c
== 0 )
875 current
+= strspn ( current
, WHITESPACE
);
876 l
= strcspn ( current
, WHITESPACE
);
880 return pa_xstrndup ( current
, l
);
883 PA_STATIC_TLS_DECLARE ( signame
, pa_xfree
);
885 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
886 const char * pa_sig2str ( int sig
) {
899 char buf
[ SIG2STR_MAX
];
901 if ( sig2str ( sig
, buf
) == 0 ) {
902 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
903 t
= pa_sprintf_malloc ( "SIG%s" , buf
);
904 PA_STATIC_TLS_SET ( signame
, t
);
912 case SIGHUP
: return "SIGHUP" ;
914 case SIGINT
: return "SIGINT" ;
916 case SIGQUIT
: return "SIGQUIT" ;
918 case SIGILL
: return "SIGULL" ;
920 case SIGTRAP
: return "SIGTRAP" ;
922 case SIGABRT
: return "SIGABRT" ;
924 case SIGBUS
: return "SIGBUS" ;
926 case SIGFPE
: return "SIGFPE" ;
928 case SIGKILL
: return "SIGKILL" ;
931 case SIGUSR1
: return "SIGUSR1" ;
933 case SIGSEGV
: return "SIGSEGV" ;
935 case SIGUSR2
: return "SIGUSR2" ;
938 case SIGPIPE
: return "SIGPIPE" ;
941 case SIGALRM
: return "SIGALRM" ;
943 case SIGTERM
: return "SIGTERM" ;
945 case SIGSTKFLT
: return "SIGSTKFLT" ;
948 case SIGCHLD
: return "SIGCHLD" ;
951 case SIGCONT
: return "SIGCONT" ;
954 case SIGSTOP
: return "SIGSTOP" ;
957 case SIGTSTP
: return "SIGTSTP" ;
960 case SIGTTIN
: return "SIGTTIN" ;
963 case SIGTTOU
: return "SIGTTOU" ;
966 case SIGURG
: return "SIGURG" ;
969 case SIGXCPU
: return "SIGXCPU" ;
972 case SIGXFSZ
: return "SIGXFSZ" ;
975 case SIGVTALRM
: return "SIGVTALRM" ;
978 case SIGPROF
: return "SIGPROF" ;
981 case SIGWINCH
: return "SIGWINCH" ;
984 case SIGIO
: return "SIGIO" ;
987 case SIGPWR
: return "SIGPWR" ;
990 case SIGSYS
: return "SIGSYS" ;
995 if ( sig
>= SIGRTMIN
&& sig
<= SIGRTMAX
) {
996 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
997 t
= pa_sprintf_malloc ( "SIGRTMIN+%i" , sig
- SIGRTMIN
);
998 PA_STATIC_TLS_SET ( signame
, t
);
1007 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
1008 t
= pa_sprintf_malloc ( "SIG%i" , sig
);
1009 PA_STATIC_TLS_SET ( signame
, t
);
1015 /* Check whether the specified GID and the group name match */
1016 static int is_group ( gid_t gid
, const char * name
) {
1017 struct group group
, * result
= NULL
;
1022 #ifdef HAVE_GETGRGID_R
1023 #ifdef _SC_GETGR_R_SIZE_MAX
1024 n
= sysconf ( _SC_GETGR_R_SIZE_MAX
);
1031 data
= pa_xmalloc (( size_t ) n
);
1034 if ( getgrgid_r ( gid
, & group
, data
, ( size_t ) n
, & result
) < 0 || ! result
) {
1035 pa_log ( "getgrgid_r(%u): %s" , ( unsigned ) gid
, pa_cstrerror ( errno
));
1043 r
= strcmp ( name
, result
-> gr_name
) == 0 ;
1048 /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X) that do not
1049 * support getgrgid_r. */
1052 if (!( result
= getgrgid ( gid
))) {
1053 pa_log ( "getgrgid(%u): %s" , gid
, pa_cstrerror ( errno
));
1061 r
= strcmp ( name
, result
-> gr_name
) == 0 ;
1069 /* Check the current user is member of the specified group */
1070 int pa_own_uid_in_group ( const char * name
, gid_t
* gid
) {
1071 GETGROUPS_T
* gids
, tgid
;
1072 long n
= sysconf ( _SC_NGROUPS_MAX
);
1077 gids
= pa_xmalloc ( sizeof ( GETGROUPS_T
) * ( size_t ) n
);
1079 if (( n
= getgroups (( int ) n
, gids
)) < 0 ) {
1080 pa_log ( "getgroups(): %s" , pa_cstrerror ( errno
));
1084 for ( i
= 0 ; i
< n
; i
++) {
1086 if (( k
= is_group ( gids
[ i
], name
)) < 0 )
1095 if (( k
= is_group ( tgid
= getgid (), name
)) < 0 )
1111 /* Check whether the specifc user id is a member of the specified group */
1112 int pa_uid_in_group ( uid_t uid
, const char * name
) {
1113 char * g_buf
, * p_buf
;
1115 struct group grbuf
, * gr
;
1119 #ifdef _SC_GETGR_R_SIZE_MAX
1120 g_n
= sysconf ( _SC_GETGR_R_SIZE_MAX
);
1127 g_buf
= pa_xmalloc (( size_t ) g_n
);
1129 #ifdef _SC_GETPW_R_SIZE_MAX
1130 p_n
= sysconf ( _SC_GETPW_R_SIZE_MAX
);
1137 p_buf
= pa_xmalloc (( size_t ) p_n
);
1140 #ifdef HAVE_GETGRNAM_R
1141 if ( getgrnam_r ( name
, & grbuf
, g_buf
, ( size_t ) g_n
, & gr
) != 0 || ! gr
)
1143 if (!( gr
= getgrnam ( name
)))
1152 for ( i
= gr
-> gr_mem
; * i
; i
++) {
1153 struct passwd pwbuf
, * pw
;
1155 #ifdef HAVE_GETPWNAM_R
1156 if ( getpwnam_r (* i
, & pwbuf
, p_buf
, ( size_t ) p_n
, & pw
) != 0 || ! pw
)
1158 if (!( pw
= getpwnam (* i
)))
1162 if ( pw
-> pw_uid
== uid
) {
1175 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
1176 gid_t
pa_get_gid_of_group ( const char * name
) {
1177 gid_t ret
= ( gid_t
) - 1 ;
1180 struct group grbuf
, * gr
;
1182 #ifdef _SC_GETGR_R_SIZE_MAX
1183 g_n
= sysconf ( _SC_GETGR_R_SIZE_MAX
);
1190 g_buf
= pa_xmalloc (( size_t ) g_n
);
1193 #ifdef HAVE_GETGRNAM_R
1194 if ( getgrnam_r ( name
, & grbuf
, g_buf
, ( size_t ) g_n
, & gr
) != 0 || ! gr
)
1196 if (!( gr
= getgrnam ( name
)))
1211 int pa_check_in_group ( gid_t g
) {
1212 gid_t gids
[ NGROUPS_MAX
];
1215 if (( r
= getgroups ( NGROUPS_MAX
, gids
)) < 0 )
1225 #else /* HAVE_GRP_H */
1227 int pa_own_uid_in_group ( const char * name
, gid_t
* gid
) {
1233 int pa_uid_in_group ( uid_t uid
, const char * name
) {
1238 gid_t
pa_get_gid_of_group ( const char * name
) {
1243 int pa_check_in_group ( gid_t g
) {
1250 /* Lock or unlock a file entirely.
1251 (advisory on UNIX, mandatory on Windows) */
1252 int pa_lock_fd ( int fd
, int b
) {
1256 /* Try a R/W lock first */
1258 flock
. l_type
= ( short ) ( b
? F_WRLCK
: F_UNLCK
);
1259 flock
. l_whence
= SEEK_SET
;
1263 if ( fcntl ( fd
, F_SETLKW
, & flock
) >= 0 )
1266 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1267 if ( b
&& errno
== EBADF
) {
1268 flock
. l_type
= F_RDLCK
;
1269 if ( fcntl ( fd
, F_SETLKW
, & flock
) >= 0 )
1273 pa_log ( "%slock: %s" , ! b
? "un" : "" , pa_cstrerror ( errno
));
1277 HANDLE h
= ( HANDLE
) _get_osfhandle ( fd
);
1279 if ( b
&& LockFile ( h
, 0 , 0 , 0xFFFFFFFF , 0xFFFFFFFF ))
1281 if (! b
&& UnlockFile ( h
, 0 , 0 , 0xFFFFFFFF , 0xFFFFFFFF ))
1284 pa_log ( "%slock failed: 0x%08X" , ! b
? "un" : "" , GetLastError ());
1286 /* FIXME: Needs to set errno! */
1292 /* Remove trailing newlines from a string */
1293 char * pa_strip_nl ( char * s
) {
1296 s
[ strcspn ( s
, " \r\n " )] = 0 ;
1300 /* Create a temporary lock file and lock it. */
1301 int pa_lock_lockfile ( const char * fn
) {
1308 if (( fd
= open ( fn
, O_CREAT
| O_RDWR
1315 , S_IRUSR
| S_IWUSR
)) < 0 ) {
1316 pa_log_warn ( "Failed to create lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1320 if ( pa_lock_fd ( fd
, 1 ) < 0 ) {
1321 pa_log_warn ( "Failed to lock file '%s'." , fn
);
1325 if ( fstat ( fd
, & st
) < 0 ) {
1326 pa_log_warn ( "Failed to fstat() file '%s': %s" , fn
, pa_cstrerror ( errno
));
1330 /* Check whether the file has been removed meanwhile. When yes,
1331 * restart this loop, otherwise, we're done */
1332 if ( st
. st_nlink
>= 1 )
1335 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1336 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1340 if ( pa_close ( fd
) < 0 ) {
1341 pa_log_warn ( "Failed to close file '%s': %s" , fn
, pa_cstrerror ( errno
));
1354 int saved_errno
= errno
;
1356 errno
= saved_errno
;
1362 /* Unlock a temporary lcok file */
1363 int pa_unlock_lockfile ( const char * fn
, int fd
) {
1368 if ( unlink ( fn
) < 0 ) {
1369 pa_log_warn ( "Unable to remove lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1374 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1375 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1379 if ( pa_close ( fd
) < 0 ) {
1380 pa_log_warn ( "Failed to close '%s': %s" , fn
, pa_cstrerror ( errno
));
1387 static char * get_pulse_home ( void ) {
1391 if (! pa_get_home_dir ( h
, sizeof ( h
))) {
1392 pa_log_error ( "Failed to get home directory." );
1396 if ( stat ( h
, & st
) < 0 ) {
1397 pa_log_error ( "Failed to stat home directory %s: %s" , h
, pa_cstrerror ( errno
));
1401 if ( st
. st_uid
!= getuid ()) {
1402 pa_log_error ( "Home directory %s not ours." , h
);
1407 return pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" , h
);
1410 char * pa_get_state_dir ( void ) {
1413 /* The state directory shall contain dynamic data that should be
1414 * kept across reboots, and is private to this user */
1416 if (!( d
= pa_xstrdup ( getenv ( "PULSE_STATE_PATH" ))))
1417 if (!( d
= get_pulse_home ()))
1420 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1421 * dir then this will break. */
1423 if ( pa_make_secure_dir ( d
, 0700U , ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1424 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1432 static char * make_random_dir ( mode_t m
) {
1433 static const char table
[] =
1434 "abcdefghijklmnopqrstuvwxyz"
1435 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1442 if (!( tmpdir
= getenv ( "TMPDIR" )))
1443 if (!( tmpdir
= getenv ( "TMP" )))
1444 if (!( tmpdir
= getenv ( "TEMP" )))
1445 tmpdir
= getenv ( "TEMPDIR" );
1447 if (! tmpdir
|| ! pa_is_path_absolute ( tmpdir
))
1450 fn
= pa_sprintf_malloc ( "%s/pulse-XXXXXXXXXXXX" , tmpdir
);
1451 pathlen
= strlen ( fn
);
1459 for ( i
= pathlen
- 12 ; i
< pathlen
; i
++)
1460 fn
[ i
] = table
[ rand () % ( sizeof ( table
)- 1 )];
1462 u
= umask ((~ m
) & 0777 );
1465 saved_errno
= errno
;
1467 errno
= saved_errno
;
1472 if ( errno
!= EEXIST
) {
1473 pa_log_error ( "Failed to create random directory %s: %s" , fn
, pa_cstrerror ( errno
));
1480 static int make_random_dir_and_link ( mode_t m
, const char * k
) {
1483 if (!( p
= make_random_dir ( m
)))
1486 if ( symlink ( p
, k
) < 0 ) {
1487 int saved_errno
= errno
;
1489 if ( errno
!= EEXIST
)
1490 pa_log_error ( "Failed to symlink %s to %s: %s" , k
, p
, pa_cstrerror ( errno
));
1495 errno
= saved_errno
;
1503 char * pa_get_runtime_dir ( void ) {
1504 char * d
, * k
= NULL
, * p
= NULL
, * t
= NULL
, * mid
;
1508 /* The runtime directory shall contain dynamic data that needs NOT
1509 * to be kept accross reboots and is usuallly private to the user,
1510 * except in system mode, where it might be accessible by other
1511 * users, too. Since we need POSIX locking and UNIX sockets in
1512 * this directory, we link it to a random subdir in /tmp, if it
1513 * was not explicitly configured. */
1515 m
= pa_in_system_mode () ? 0755U : 0700U ;
1517 if (( d
= getenv ( "PULSE_RUNTIME_PATH" ))) {
1519 if ( pa_make_secure_dir ( d
, m
, ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1520 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1524 return pa_xstrdup ( d
);
1527 if (!( d
= get_pulse_home ()))
1530 if ( pa_make_secure_dir ( d
, m
, ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1531 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1536 if (!( mid
= pa_machine_id ())) {
1541 k
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s:runtime" , d
, mid
);
1546 /* OK, first let's check if the "runtime" symlink is already
1549 if (!( p
= pa_readlink ( k
))) {
1551 if ( errno
!= ENOENT
) {
1552 pa_log_error ( "Failed to stat runtime directory %s: %s" , k
, pa_cstrerror ( errno
));
1556 /* Hmm, so the runtime directory didn't exist yet, so let's
1557 * create one in /tmp and symlink that to it */
1559 if ( make_random_dir_and_link ( 0700 , k
) < 0 ) {
1561 /* Mhmm, maybe another process was quicker than us,
1562 * let's check if that was valid */
1563 if ( errno
== EEXIST
)
1572 /* Make sure that this actually makes sense */
1573 if (! pa_is_path_absolute ( p
)) {
1574 pa_log_error ( "Path %s in link %s is not absolute." , p
, k
);
1579 /* Hmm, so this symlink is still around, make sure nobody fools
1582 if ( lstat ( p
, & st
) < 0 ) {
1584 if ( errno
!= ENOENT
) {
1585 pa_log_error ( "Failed to stat runtime directory %s: %s" , p
, pa_cstrerror ( errno
));
1591 if ( S_ISDIR ( st
. st_mode
) &&
1592 ( st
. st_uid
== getuid ()) &&
1593 (( st
. st_mode
& 0777 ) == 0700 )) {
1599 pa_log_info ( "Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory." );
1605 /* Hmm, so the link points to some nonexisting or invalid
1606 * dir. Let's replace it by a new link. We first create a
1607 * temporary link and then rename that to allow concurrent
1608 * execution of this function. */
1610 t
= pa_sprintf_malloc ( "%s.tmp" , k
);
1612 if ( make_random_dir_and_link ( 0700 , t
) < 0 ) {
1614 if ( errno
!= EEXIST
) {
1615 pa_log_error ( "Failed to symlink %s: %s" , t
, pa_cstrerror ( errno
));
1622 /* Hmm, someone lese was quicker then us. Let's give
1623 * him some time to finish, and retry. */
1628 /* OK, we succeeded in creating the temporary symlink, so
1629 * let's rename it */
1630 if ( rename ( t
, k
) < 0 ) {
1631 pa_log_error ( "Failed to rename %s to %s: %s" , t
, k
, pa_cstrerror ( errno
));
1647 /* Try to open a configuration file. If "env" is specified, open the
1648 * value of the specified environment variable. Otherwise look for a
1649 * file "local" in the home directory or a file "global" in global
1650 * file system. If "result" is non-NULL, a pointer to a newly
1651 * allocated buffer containing the used configuration file is
1653 FILE * pa_open_config_file ( const char * global
, const char * local
, const char * env
, char ** result
) {
1658 if (! getenv ( PULSE_ROOTENV
))
1662 if ( env
&& ( fn
= getenv ( env
))) {
1666 if (! ExpandEnvironmentStrings ( fn
, buf
, PATH_MAX
))
1667 /* FIXME: Needs to set errno! */
1672 if (( f
= fopen ( fn
, "r" ))) {
1674 * result
= pa_xstrdup ( fn
);
1679 pa_log_warn ( "Failed to open configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1689 if (( e
= getenv ( "PULSE_CONFIG_PATH" )))
1690 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , e
, local
);
1691 else if ( pa_get_home_dir ( h
, sizeof ( h
)))
1692 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 ( pa_get_home_dir ( h
, sizeof ( h
)))
1778 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s" , h
, local
);
1783 if (! ExpandEnvironmentStrings ( lfn
, buf
, PATH_MAX
)) {
1784 /* FIXME: Needs to set errno! */
1791 if ( access ( fn
, R_OK
) == 0 ) {
1792 char * r
= pa_xstrdup ( fn
);
1797 if ( errno
!= ENOENT
) {
1798 pa_log_warn ( "Failed to access configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1808 if (! ExpandEnvironmentStrings ( global
, buf
, PATH_MAX
))
1809 /* FIXME: Needs to set errno! */
1814 if ( access ( global
, R_OK
) == 0 )
1815 return pa_xstrdup ( global
);
1823 /* Format the specified data as a hexademical string */
1824 char * pa_hexstr ( const uint8_t * d
, size_t dlength
, char * s
, size_t slength
) {
1825 size_t i
= 0 , j
= 0 ;
1826 const char hex
[] = "0123456789abcdef" ;
1830 pa_assert ( slength
> 0 );
1832 while ( i
< dlength
&& j
+ 3 <= slength
) {
1833 s
[ j
++] = hex
[* d
>> 4 ];
1834 s
[ j
++] = hex
[* d
& 0xF ];
1840 s
[ j
< slength
? j
: slength
] = 0 ;
1844 /* Convert a hexadecimal digit to a number or -1 if invalid */
1845 static int hexc ( char c
) {
1846 if ( c
>= '0' && c
<= '9' )
1849 if ( c
>= 'A' && c
<= 'F' )
1850 return c
- 'A' + 10 ;
1852 if ( c
>= 'a' && c
<= 'f' )
1853 return c
- 'a' + 10 ;
1859 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1860 size_t pa_parsehex ( const char * p
, uint8_t * d
, size_t dlength
) {
1866 while ( j
< dlength
&& * p
) {
1869 if (( b
= hexc (*( p
++))) < 0 )
1872 d
[ j
] = ( uint8_t ) ( b
<< 4 );
1877 if (( b
= hexc (*( p
++))) < 0 )
1880 d
[ j
] |= ( uint8_t ) b
;
1887 /* Returns nonzero when *s starts with *pfx */
1888 pa_bool_t
pa_startswith ( const char * s
, const char * pfx
) {
1896 return strlen ( s
) >= l
&& strncmp ( s
, pfx
, l
) == 0 ;
1899 /* Returns nonzero when *s ends with *sfx */
1900 pa_bool_t
pa_endswith ( const char * s
, const char * sfx
) {
1909 return l1
>= l2
&& strcmp ( s
+ l1
- l2
, sfx
) == 0 ;
1912 pa_bool_t
pa_is_path_absolute ( const char * fn
) {
1918 return strlen ( fn
) >= 3 && isalpha ( fn
[ 0 ]) && fn
[ 1 ] == ':' && fn
[ 2 ] == ' \\ ' ;
1922 char * pa_make_path_absolute ( const char * p
) {
1928 if ( pa_is_path_absolute ( p
))
1929 return pa_xstrdup ( p
);
1931 if (!( cwd
= pa_getcwd ()))
1932 return pa_xstrdup ( p
);
1934 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , cwd
, p
);
1939 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1940 * if fn is non-null and starts with / return fn
1941 * otherwise append fn to the run time path and return it */
1942 static char * get_path ( const char * fn
, pa_bool_t prependmid
, pa_bool_t rt
) {
1945 if ( pa_is_path_absolute ( fn
))
1946 return pa_xstrdup ( fn
);
1948 rtp
= rt
? pa_get_runtime_dir () : pa_get_state_dir ();
1959 if (!( mid
= pa_machine_id ())) {
1964 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s:%s" , rtp
, mid
, fn
);
1967 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , rtp
, fn
);
1975 char * pa_runtime_path ( const char * fn
) {
1976 return get_path ( fn
, FALSE
, TRUE
);
1979 char * pa_state_path ( const char * fn
, pa_bool_t appendmid
) {
1980 return get_path ( fn
, appendmid
, FALSE
);
1983 /* Convert the string s to a signed integer in *ret_i */
1984 int pa_atoi ( const char * s
, int32_t * ret_i
) {
1992 l
= strtol ( s
, & x
, 0 );
1994 if (! x
|| * x
|| errno
) {
2000 if (( int32_t ) l
!= l
) {
2005 * ret_i
= ( int32_t ) l
;
2010 /* Convert the string s to an unsigned integer in *ret_u */
2011 int pa_atou ( const char * s
, uint32_t * ret_u
) {
2019 l
= strtoul ( s
, & x
, 0 );
2021 if (! x
|| * x
|| errno
) {
2027 if (( uint32_t ) l
!= l
) {
2032 * ret_u
= ( uint32_t ) l
;
2037 #ifdef HAVE_STRTOF_L
2038 static locale_t c_locale
= NULL
;
2040 static void c_locale_destroy ( void ) {
2041 freelocale ( c_locale
);
2045 int pa_atod ( const char * s
, double * ret_d
) {
2052 /* This should be locale independent */
2054 #ifdef HAVE_STRTOF_L
2058 if (( c_locale
= newlocale ( LC_ALL_MASK
, "C" , NULL
)))
2059 atexit ( c_locale_destroy
);
2065 f
= strtod_l ( s
, & x
, c_locale
);
2073 if (! x
|| * x
|| errno
) {
2084 /* Same as snprintf, but guarantees NUL-termination on every platform */
2085 size_t pa_snprintf ( char * str
, size_t size
, const char * format
, ...) {
2090 pa_assert ( size
> 0 );
2093 va_start ( ap
, format
);
2094 ret
= pa_vsnprintf ( str
, size
, format
, ap
);
2100 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2101 size_t pa_vsnprintf ( char * str
, size_t size
, const char * format
, va_list ap
) {
2105 pa_assert ( size
> 0 );
2108 ret
= vsnprintf ( str
, size
, format
, ap
);
2115 if (( size_t ) ret
> size
- 1 )
2118 return ( size_t ) ret
;
2121 /* Truncate the specified string, but guarantee that the string
2122 * returned still validates as UTF8 */
2123 char * pa_truncate_utf8 ( char * c
, size_t l
) {
2125 pa_assert ( pa_utf8_valid ( c
));
2132 while ( l
> 0 && ! pa_utf8_valid ( c
))
2138 char * pa_getcwd ( void ) {
2142 char * p
= pa_xmalloc ( l
);
2146 if ( errno
!= ERANGE
)
2154 void * pa_will_need ( const void * p
, size_t l
) {
2155 #ifdef RLIMIT_MEMLOCK
2166 a
= PA_PAGE_ALIGN_PTR ( p
);
2167 size
= ( size_t ) (( const uint8_t *) p
+ l
- ( const uint8_t *) a
);
2169 #ifdef HAVE_POSIX_MADVISE
2170 if (( r
= posix_madvise (( void *) a
, size
, POSIX_MADV_WILLNEED
)) == 0 ) {
2171 pa_log_debug ( "posix_madvise() worked fine!" );
2176 /* Most likely the memory was not mmap()ed from a file and thus
2177 * madvise() didn't work, so let's misuse mlock() do page this
2178 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2179 * inviting, the man page of mlock() tells us: "All pages that
2180 * contain a part of the specified address range are guaranteed to
2181 * be resident in RAM when the call returns successfully." */
2183 #ifdef RLIMIT_MEMLOCK
2184 pa_assert_se ( getrlimit ( RLIMIT_MEMLOCK
, & rlim
) == 0 );
2186 if ( rlim
. rlim_cur
< PA_PAGE_SIZE
) {
2187 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
));
2192 bs
= PA_PAGE_ALIGN (( size_t ) rlim
. rlim_cur
);
2194 bs
= PA_PAGE_SIZE
* 4 ;
2197 pa_log_debug ( "posix_madvise() failed (or doesn't exist), trying mlock(): %s" , pa_cstrerror ( r
));
2200 while ( size
> 0 && bs
> 0 ) {
2205 if ( mlock ( a
, bs
) < 0 ) {
2206 bs
= PA_PAGE_ALIGN ( bs
/ 2 );
2210 pa_assert_se ( munlock ( a
, bs
) == 0 );
2212 a
= ( const uint8_t *) a
+ bs
;
2218 pa_log_debug ( "mlock() failed too (or doesn't exist), giving up: %s" , pa_cstrerror ( errno
));
2220 pa_log_debug ( "mlock() worked fine!" );
2225 void pa_close_pipe ( int fds
[ 2 ]) {
2229 pa_assert_se ( pa_close ( fds
[ 0 ]) == 0 );
2232 pa_assert_se ( pa_close ( fds
[ 1 ]) == 0 );
2234 fds
[ 0 ] = fds
[ 1 ] = - 1 ;
2237 char * pa_readlink ( const char * p
) {
2246 if (( n
= readlink ( p
, c
, l
- 1 )) < 0 ) {
2251 if (( size_t ) n
< l
- 1 ) {
2261 int pa_close_all ( int except_fd
, ...) {
2266 va_start ( ap
, except_fd
);
2269 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2274 p
= pa_xnew ( int , n
+ 1 );
2276 va_start ( ap
, except_fd
);
2279 if ( except_fd
>= 0 ) {
2283 while (( fd
= va_arg ( ap
, int )) >= 0 )
2290 r
= pa_close_allv ( p
);
2296 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
);