]>
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
622 if ( set_scheduler ( rtprio
) >= 0 ) {
623 pa_log_info ( "Successfully enabled SCHED_RR scheduling for thread, with priority %i." , rtprio
);
627 for ( p
= rtprio
- 1 ; p
>= 1 ; p
--)
628 if ( set_scheduler ( p
)) {
629 pa_log_info ( "Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i." , p
, rtprio
);
633 pa_log_info ( "Failed to acquire real-time scheduling: %s" , pa_cstrerror ( errno
));
642 static int set_nice ( int nice_level
) {
648 dbus_error_init (& error
);
651 if ( setpriority ( PRIO_PROCESS
, 0 , nice_level
) >= 0 ) {
652 pa_log_debug ( "setpriority() worked." );
657 /* Try to talk to RealtimeKit */
659 if (!( bus
= dbus_bus_get ( DBUS_BUS_SYSTEM
, & error
))) {
660 pa_log ( "Failed to connect to system bus: %s \n " , error
. message
);
661 dbus_error_free (& error
);
666 r
= rtkit_make_high_priority ( bus
, 0 , nice_level
);
667 dbus_connection_unref ( bus
);
670 pa_log_debug ( "RealtimeKit worked." );
680 /* Raise the priority of the current process as much as possible that
681 * is <= the specified nice level..*/
682 int pa_raise_priority ( int nice_level
) {
684 #ifdef HAVE_SYS_RESOURCE_H
687 if ( set_nice ( nice_level
) >= 0 ) {
688 pa_log_info ( "Successfully gained nice level %i." , nice_level
);
692 for ( n
= nice_level
+ 1 ; n
< 0 ; n
++)
693 if ( set_nice ( n
) > 0 ) {
694 pa_log_info ( "Successfully acquired nice level %i, which is lower than the requested %i." , n
, nice_level
);
698 pa_log_info ( "Failed to acquire high-priority scheduling: %s" , pa_cstrerror ( errno
));
703 if ( nice_level
< 0 ) {
704 if (! SetPriorityClass ( GetCurrentProcess (), HIGH_PRIORITY_CLASS
)) {
705 pa_log_warn ( "SetPriorityClass() failed: 0x%08X" , GetLastError ());
710 pa_log_info ( "Successfully gained high priority class." );
717 /* Reset the priority to normal, inverting the changes made by
718 * pa_raise_priority() and pa_make_realtime()*/
719 void pa_reset_priority ( void ) {
720 #ifdef HAVE_SYS_RESOURCE_H
721 struct sched_param sp
;
723 setpriority ( PRIO_PROCESS
, 0 , 0 );
726 pthread_setschedparam ( pthread_self (), SCHED_OTHER
, & sp
);
730 SetPriorityClass ( GetCurrentProcess (), NORMAL_PRIORITY_CLASS
);
734 int pa_match ( const char * expr
, const char * v
) {
739 if ( regcomp (& re
, expr
, REG_NOSUB
| REG_EXTENDED
) != 0 ) {
744 if (( k
= regexec (& re
, v
, 0 , NULL
, 0 )) == 0 )
746 else if ( k
== REG_NOMATCH
)
759 /* Try to parse a boolean string value.*/
760 int pa_parse_boolean ( const char * v
) {
765 /* First we check language independant */
766 if (! strcmp ( v
, "1" ) || v
[ 0 ] == 'y' || v
[ 0 ] == 'Y' || v
[ 0 ] == 't' || v
[ 0 ] == 'T' || ! strcasecmp ( v
, "on" ))
768 else if (! strcmp ( v
, "0" ) || v
[ 0 ] == 'n' || v
[ 0 ] == 'N' || v
[ 0 ] == 'f' || v
[ 0 ] == 'F' || ! strcasecmp ( v
, "off" ))
771 /* And then we check language dependant */
772 if (( expr
= nl_langinfo ( YESEXPR
)))
774 if (( r
= pa_match ( expr
, v
)) > 0 )
777 if (( expr
= nl_langinfo ( NOEXPR
)))
779 if (( r
= pa_match ( expr
, v
)) > 0 )
786 /* Split the specified string wherever one of the strings in delimiter
787 * occurs. Each time it is called returns a newly allocated string
788 * with pa_xmalloc(). The variable state points to, should be
789 * initiallized to NULL before the first call. */
790 char * pa_split ( const char * c
, const char * delimiter
, const char ** state
) {
791 const char * current
= * state
? * state
: c
;
797 l
= strcspn ( current
, delimiter
);
803 return pa_xstrndup ( current
, l
);
806 /* What is interpreted as whitespace? */
807 #define WHITESPACE " \t\n "
809 /* Split a string into words. Otherwise similar to pa_split(). */
810 char * pa_split_spaces ( const char * c
, const char ** state
) {
811 const char * current
= * state
? * state
: c
;
814 if (!* current
|| * c
== 0 )
817 current
+= strspn ( current
, WHITESPACE
);
818 l
= strcspn ( current
, WHITESPACE
);
822 return pa_xstrndup ( current
, l
);
825 PA_STATIC_TLS_DECLARE ( signame
, pa_xfree
);
827 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
828 const char * pa_sig2str ( int sig
) {
841 char buf
[ SIG2STR_MAX
];
843 if ( sig2str ( sig
, buf
) == 0 ) {
844 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
845 t
= pa_sprintf_malloc ( "SIG%s" , buf
);
846 PA_STATIC_TLS_SET ( signame
, t
);
854 case SIGHUP
: return "SIGHUP" ;
856 case SIGINT
: return "SIGINT" ;
858 case SIGQUIT
: return "SIGQUIT" ;
860 case SIGILL
: return "SIGULL" ;
862 case SIGTRAP
: return "SIGTRAP" ;
864 case SIGABRT
: return "SIGABRT" ;
866 case SIGBUS
: return "SIGBUS" ;
868 case SIGFPE
: return "SIGFPE" ;
870 case SIGKILL
: return "SIGKILL" ;
873 case SIGUSR1
: return "SIGUSR1" ;
875 case SIGSEGV
: return "SIGSEGV" ;
877 case SIGUSR2
: return "SIGUSR2" ;
880 case SIGPIPE
: return "SIGPIPE" ;
883 case SIGALRM
: return "SIGALRM" ;
885 case SIGTERM
: return "SIGTERM" ;
887 case SIGSTKFLT
: return "SIGSTKFLT" ;
890 case SIGCHLD
: return "SIGCHLD" ;
893 case SIGCONT
: return "SIGCONT" ;
896 case SIGSTOP
: return "SIGSTOP" ;
899 case SIGTSTP
: return "SIGTSTP" ;
902 case SIGTTIN
: return "SIGTTIN" ;
905 case SIGTTOU
: return "SIGTTOU" ;
908 case SIGURG
: return "SIGURG" ;
911 case SIGXCPU
: return "SIGXCPU" ;
914 case SIGXFSZ
: return "SIGXFSZ" ;
917 case SIGVTALRM
: return "SIGVTALRM" ;
920 case SIGPROF
: return "SIGPROF" ;
923 case SIGWINCH
: return "SIGWINCH" ;
926 case SIGIO
: return "SIGIO" ;
929 case SIGPWR
: return "SIGPWR" ;
932 case SIGSYS
: return "SIGSYS" ;
937 if ( sig
>= SIGRTMIN
&& sig
<= SIGRTMAX
) {
938 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
939 t
= pa_sprintf_malloc ( "SIGRTMIN+%i" , sig
- SIGRTMIN
);
940 PA_STATIC_TLS_SET ( signame
, t
);
949 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
950 t
= pa_sprintf_malloc ( "SIG%i" , sig
);
951 PA_STATIC_TLS_SET ( signame
, t
);
957 /* Check whether the specified GID and the group name match */
958 static int is_group ( gid_t gid
, const char * name
) {
959 struct group group
, * result
= NULL
;
964 #ifdef HAVE_GETGRGID_R
965 #ifdef _SC_GETGR_R_SIZE_MAX
966 n
= sysconf ( _SC_GETGR_R_SIZE_MAX
);
973 data
= pa_xmalloc (( size_t ) n
);
976 if ( getgrgid_r ( gid
, & group
, data
, ( size_t ) n
, & result
) < 0 || ! result
) {
977 pa_log ( "getgrgid_r(%u): %s" , ( unsigned ) gid
, pa_cstrerror ( errno
));
985 r
= strcmp ( name
, result
-> gr_name
) == 0 ;
990 /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X) that do not
991 * support getgrgid_r. */
994 if (!( result
= getgrgid ( gid
))) {
995 pa_log ( "getgrgid(%u): %s" , gid
, pa_cstrerror ( errno
));
1003 r
= strcmp ( name
, result
-> gr_name
) == 0 ;
1011 /* Check the current user is member of the specified group */
1012 int pa_own_uid_in_group ( const char * name
, gid_t
* gid
) {
1013 GETGROUPS_T
* gids
, tgid
;
1014 long n
= sysconf ( _SC_NGROUPS_MAX
);
1019 gids
= pa_xmalloc ( sizeof ( GETGROUPS_T
) * ( size_t ) n
);
1021 if (( n
= getgroups (( int ) n
, gids
)) < 0 ) {
1022 pa_log ( "getgroups(): %s" , pa_cstrerror ( errno
));
1026 for ( i
= 0 ; i
< n
; i
++) {
1028 if (( k
= is_group ( gids
[ i
], name
)) < 0 )
1037 if (( k
= is_group ( tgid
= getgid (), name
)) < 0 )
1053 /* Check whether the specifc user id is a member of the specified group */
1054 int pa_uid_in_group ( uid_t uid
, const char * name
) {
1055 char * g_buf
, * p_buf
;
1057 struct group grbuf
, * gr
;
1061 #ifdef _SC_GETGR_R_SIZE_MAX
1062 g_n
= sysconf ( _SC_GETGR_R_SIZE_MAX
);
1069 g_buf
= pa_xmalloc (( size_t ) g_n
);
1071 #ifdef _SC_GETPW_R_SIZE_MAX
1072 p_n
= sysconf ( _SC_GETPW_R_SIZE_MAX
);
1079 p_buf
= pa_xmalloc (( size_t ) p_n
);
1082 #ifdef HAVE_GETGRNAM_R
1083 if ( getgrnam_r ( name
, & grbuf
, g_buf
, ( size_t ) g_n
, & gr
) != 0 || ! gr
)
1085 if (!( gr
= getgrnam ( name
)))
1094 for ( i
= gr
-> gr_mem
; * i
; i
++) {
1095 struct passwd pwbuf
, * pw
;
1097 #ifdef HAVE_GETPWNAM_R
1098 if ( getpwnam_r (* i
, & pwbuf
, p_buf
, ( size_t ) p_n
, & pw
) != 0 || ! pw
)
1100 if (!( pw
= getpwnam (* i
)))
1104 if ( pw
-> pw_uid
== uid
) {
1117 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
1118 gid_t
pa_get_gid_of_group ( const char * name
) {
1119 gid_t ret
= ( gid_t
) - 1 ;
1122 struct group grbuf
, * gr
;
1124 #ifdef _SC_GETGR_R_SIZE_MAX
1125 g_n
= sysconf ( _SC_GETGR_R_SIZE_MAX
);
1132 g_buf
= pa_xmalloc (( size_t ) g_n
);
1135 #ifdef HAVE_GETGRNAM_R
1136 if ( getgrnam_r ( name
, & grbuf
, g_buf
, ( size_t ) g_n
, & gr
) != 0 || ! gr
)
1138 if (!( gr
= getgrnam ( name
)))
1153 int pa_check_in_group ( gid_t g
) {
1154 gid_t gids
[ NGROUPS_MAX
];
1157 if (( r
= getgroups ( NGROUPS_MAX
, gids
)) < 0 )
1167 #else /* HAVE_GRP_H */
1169 int pa_own_uid_in_group ( const char * name
, gid_t
* gid
) {
1175 int pa_uid_in_group ( uid_t uid
, const char * name
) {
1180 gid_t
pa_get_gid_of_group ( const char * name
) {
1185 int pa_check_in_group ( gid_t g
) {
1192 /* Lock or unlock a file entirely.
1193 (advisory on UNIX, mandatory on Windows) */
1194 int pa_lock_fd ( int fd
, int b
) {
1198 /* Try a R/W lock first */
1200 flock
. l_type
= ( short ) ( b
? F_WRLCK
: F_UNLCK
);
1201 flock
. l_whence
= SEEK_SET
;
1205 if ( fcntl ( fd
, F_SETLKW
, & flock
) >= 0 )
1208 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1209 if ( b
&& errno
== EBADF
) {
1210 flock
. l_type
= F_RDLCK
;
1211 if ( fcntl ( fd
, F_SETLKW
, & flock
) >= 0 )
1215 pa_log ( "%slock: %s" , ! b
? "un" : "" , pa_cstrerror ( errno
));
1219 HANDLE h
= ( HANDLE
) _get_osfhandle ( fd
);
1221 if ( b
&& LockFile ( h
, 0 , 0 , 0xFFFFFFFF , 0xFFFFFFFF ))
1223 if (! b
&& UnlockFile ( h
, 0 , 0 , 0xFFFFFFFF , 0xFFFFFFFF ))
1226 pa_log ( "%slock failed: 0x%08X" , ! b
? "un" : "" , GetLastError ());
1228 /* FIXME: Needs to set errno! */
1234 /* Remove trailing newlines from a string */
1235 char * pa_strip_nl ( char * s
) {
1238 s
[ strcspn ( s
, " \r\n " )] = 0 ;
1242 /* Create a temporary lock file and lock it. */
1243 int pa_lock_lockfile ( const char * fn
) {
1250 if (( fd
= open ( fn
, O_CREAT
| O_RDWR
1257 , S_IRUSR
| S_IWUSR
)) < 0 ) {
1258 pa_log_warn ( "Failed to create lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1262 if ( pa_lock_fd ( fd
, 1 ) < 0 ) {
1263 pa_log_warn ( "Failed to lock file '%s'." , fn
);
1267 if ( fstat ( fd
, & st
) < 0 ) {
1268 pa_log_warn ( "Failed to fstat() file '%s': %s" , fn
, pa_cstrerror ( errno
));
1272 /* Check whether the file has been removed meanwhile. When yes,
1273 * restart this loop, otherwise, we're done */
1274 if ( st
. st_nlink
>= 1 )
1277 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1278 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1282 if ( pa_close ( fd
) < 0 ) {
1283 pa_log_warn ( "Failed to close file '%s': %s" , fn
, pa_cstrerror ( errno
));
1296 int saved_errno
= errno
;
1298 errno
= saved_errno
;
1304 /* Unlock a temporary lcok file */
1305 int pa_unlock_lockfile ( const char * fn
, int fd
) {
1310 if ( unlink ( fn
) < 0 ) {
1311 pa_log_warn ( "Unable to remove lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1316 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1317 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1321 if ( pa_close ( fd
) < 0 ) {
1322 pa_log_warn ( "Failed to close '%s': %s" , fn
, pa_cstrerror ( errno
));
1329 static char * get_pulse_home ( void ) {
1333 if (! pa_get_home_dir ( h
, sizeof ( h
))) {
1334 pa_log_error ( "Failed to get home directory." );
1338 if ( stat ( h
, & st
) < 0 ) {
1339 pa_log_error ( "Failed to stat home directory %s: %s" , h
, pa_cstrerror ( errno
));
1343 if ( st
. st_uid
!= getuid ()) {
1344 pa_log_error ( "Home directory %s not ours." , h
);
1349 return pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" , h
);
1352 char * pa_get_state_dir ( void ) {
1355 /* The state directory shall contain dynamic data that should be
1356 * kept across reboots, and is private to this user */
1358 if (!( d
= pa_xstrdup ( getenv ( "PULSE_STATE_PATH" ))))
1359 if (!( d
= get_pulse_home ()))
1362 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1363 * dir then this will break. */
1365 if ( pa_make_secure_dir ( d
, 0700U , ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1366 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1374 static char * make_random_dir ( mode_t m
) {
1375 static const char table
[] =
1376 "abcdefghijklmnopqrstuvwxyz"
1377 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1384 if (!( tmpdir
= getenv ( "TMPDIR" )))
1385 if (!( tmpdir
= getenv ( "TMP" )))
1386 if (!( tmpdir
= getenv ( "TEMP" )))
1387 tmpdir
= getenv ( "TEMPDIR" );
1389 if (! tmpdir
|| ! pa_is_path_absolute ( tmpdir
))
1392 fn
= pa_sprintf_malloc ( "%s/pulse-XXXXXXXXXXXX" , tmpdir
);
1393 pathlen
= strlen ( fn
);
1401 for ( i
= pathlen
- 12 ; i
< pathlen
; i
++)
1402 fn
[ i
] = table
[ rand () % ( sizeof ( table
)- 1 )];
1404 u
= umask ((~ m
) & 0777 );
1407 saved_errno
= errno
;
1409 errno
= saved_errno
;
1414 if ( errno
!= EEXIST
) {
1415 pa_log_error ( "Failed to create random directory %s: %s" , fn
, pa_cstrerror ( errno
));
1422 static int make_random_dir_and_link ( mode_t m
, const char * k
) {
1425 if (!( p
= make_random_dir ( m
)))
1428 if ( symlink ( p
, k
) < 0 ) {
1429 int saved_errno
= errno
;
1431 if ( errno
!= EEXIST
)
1432 pa_log_error ( "Failed to symlink %s to %s: %s" , k
, p
, pa_cstrerror ( errno
));
1437 errno
= saved_errno
;
1445 char * pa_get_runtime_dir ( void ) {
1446 char * d
, * k
= NULL
, * p
= NULL
, * t
= NULL
, * mid
;
1450 /* The runtime directory shall contain dynamic data that needs NOT
1451 * to be kept accross reboots and is usuallly private to the user,
1452 * except in system mode, where it might be accessible by other
1453 * users, too. Since we need POSIX locking and UNIX sockets in
1454 * this directory, we link it to a random subdir in /tmp, if it
1455 * was not explicitly configured. */
1457 m
= pa_in_system_mode () ? 0755U : 0700U ;
1459 if (( d
= getenv ( "PULSE_RUNTIME_PATH" ))) {
1461 if ( pa_make_secure_dir ( d
, m
, ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1462 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1466 return pa_xstrdup ( d
);
1469 if (!( d
= get_pulse_home ()))
1472 if ( pa_make_secure_dir ( d
, m
, ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1473 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1478 if (!( mid
= pa_machine_id ())) {
1483 k
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s:runtime" , d
, mid
);
1488 /* OK, first let's check if the "runtime" symlink is already
1491 if (!( p
= pa_readlink ( k
))) {
1493 if ( errno
!= ENOENT
) {
1494 pa_log_error ( "Failed to stat runtime directory %s: %s" , k
, pa_cstrerror ( errno
));
1498 /* Hmm, so the runtime directory didn't exist yet, so let's
1499 * create one in /tmp and symlink that to it */
1501 if ( make_random_dir_and_link ( 0700 , k
) < 0 ) {
1503 /* Mhmm, maybe another process was quicker than us,
1504 * let's check if that was valid */
1505 if ( errno
== EEXIST
)
1514 /* Make sure that this actually makes sense */
1515 if (! pa_is_path_absolute ( p
)) {
1516 pa_log_error ( "Path %s in link %s is not absolute." , p
, k
);
1521 /* Hmm, so this symlink is still around, make sure nobody fools
1524 if ( lstat ( p
, & st
) < 0 ) {
1526 if ( errno
!= ENOENT
) {
1527 pa_log_error ( "Failed to stat runtime directory %s: %s" , p
, pa_cstrerror ( errno
));
1533 if ( S_ISDIR ( st
. st_mode
) &&
1534 ( st
. st_uid
== getuid ()) &&
1535 (( st
. st_mode
& 0777 ) == 0700 )) {
1541 pa_log_info ( "Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory." );
1547 /* Hmm, so the link points to some nonexisting or invalid
1548 * dir. Let's replace it by a new link. We first create a
1549 * temporary link and then rename that to allow concurrent
1550 * execution of this function. */
1552 t
= pa_sprintf_malloc ( "%s.tmp" , k
);
1554 if ( make_random_dir_and_link ( 0700 , t
) < 0 ) {
1556 if ( errno
!= EEXIST
) {
1557 pa_log_error ( "Failed to symlink %s: %s" , t
, pa_cstrerror ( errno
));
1564 /* Hmm, someone lese was quicker then us. Let's give
1565 * him some time to finish, and retry. */
1570 /* OK, we succeeded in creating the temporary symlink, so
1571 * let's rename it */
1572 if ( rename ( t
, k
) < 0 ) {
1573 pa_log_error ( "Failed to rename %s to %s: %s" , t
, k
, pa_cstrerror ( errno
));
1589 /* Try to open a configuration file. If "env" is specified, open the
1590 * value of the specified environment variable. Otherwise look for a
1591 * file "local" in the home directory or a file "global" in global
1592 * file system. If "result" is non-NULL, a pointer to a newly
1593 * allocated buffer containing the used configuration file is
1595 FILE * pa_open_config_file ( const char * global
, const char * local
, const char * env
, char ** result
) {
1600 if (! getenv ( PULSE_ROOTENV
))
1604 if ( env
&& ( fn
= getenv ( env
))) {
1608 if (! ExpandEnvironmentStrings ( fn
, buf
, PATH_MAX
))
1609 /* FIXME: Needs to set errno! */
1614 if (( f
= fopen ( fn
, "r" ))) {
1616 * result
= pa_xstrdup ( fn
);
1621 pa_log_warn ( "Failed to open configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1631 if (( e
= getenv ( "PULSE_CONFIG_PATH" )))
1632 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , e
, local
);
1633 else if ( pa_get_home_dir ( h
, sizeof ( h
)))
1634 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s" , h
, local
);
1639 if (! ExpandEnvironmentStrings ( lfn
, buf
, PATH_MAX
)) {
1640 /* FIXME: Needs to set errno! */
1647 if (( f
= fopen ( fn
, "r" ))) {
1649 * result
= pa_xstrdup ( fn
);
1655 if ( errno
!= ENOENT
) {
1656 pa_log_warn ( "Failed to open configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1668 if (! ExpandEnvironmentStrings ( global
, buf
, PATH_MAX
))
1669 /* FIXME: Needs to set errno! */
1674 if (( f
= fopen ( global
, "r" ))) {
1677 * result
= pa_xstrdup ( global
);
1687 char * pa_find_config_file ( const char * global
, const char * local
, const char * env
) {
1692 if (! getenv ( PULSE_ROOTENV
))
1696 if ( env
&& ( fn
= getenv ( env
))) {
1699 if (! ExpandEnvironmentStrings ( fn
, buf
, PATH_MAX
))
1700 /* FIXME: Needs to set errno! */
1705 if ( access ( fn
, R_OK
) == 0 )
1706 return pa_xstrdup ( fn
);
1708 pa_log_warn ( "Failed to access configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1717 if (( e
= getenv ( "PULSE_CONFIG_PATH" )))
1718 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , e
, local
);
1719 else if ( pa_get_home_dir ( h
, sizeof ( h
)))
1720 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s" , h
, local
);
1725 if (! ExpandEnvironmentStrings ( lfn
, buf
, PATH_MAX
)) {
1726 /* FIXME: Needs to set errno! */
1733 if ( access ( fn
, R_OK
) == 0 ) {
1734 char * r
= pa_xstrdup ( fn
);
1739 if ( errno
!= ENOENT
) {
1740 pa_log_warn ( "Failed to access configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1750 if (! ExpandEnvironmentStrings ( global
, buf
, PATH_MAX
))
1751 /* FIXME: Needs to set errno! */
1756 if ( access ( global
, R_OK
) == 0 )
1757 return pa_xstrdup ( global
);
1765 /* Format the specified data as a hexademical string */
1766 char * pa_hexstr ( const uint8_t * d
, size_t dlength
, char * s
, size_t slength
) {
1767 size_t i
= 0 , j
= 0 ;
1768 const char hex
[] = "0123456789abcdef" ;
1772 pa_assert ( slength
> 0 );
1774 while ( i
< dlength
&& j
+ 3 <= slength
) {
1775 s
[ j
++] = hex
[* d
>> 4 ];
1776 s
[ j
++] = hex
[* d
& 0xF ];
1782 s
[ j
< slength
? j
: slength
] = 0 ;
1786 /* Convert a hexadecimal digit to a number or -1 if invalid */
1787 static int hexc ( char c
) {
1788 if ( c
>= '0' && c
<= '9' )
1791 if ( c
>= 'A' && c
<= 'F' )
1792 return c
- 'A' + 10 ;
1794 if ( c
>= 'a' && c
<= 'f' )
1795 return c
- 'a' + 10 ;
1801 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1802 size_t pa_parsehex ( const char * p
, uint8_t * d
, size_t dlength
) {
1808 while ( j
< dlength
&& * p
) {
1811 if (( b
= hexc (*( p
++))) < 0 )
1814 d
[ j
] = ( uint8_t ) ( b
<< 4 );
1819 if (( b
= hexc (*( p
++))) < 0 )
1822 d
[ j
] |= ( uint8_t ) b
;
1829 /* Returns nonzero when *s starts with *pfx */
1830 pa_bool_t
pa_startswith ( const char * s
, const char * pfx
) {
1838 return strlen ( s
) >= l
&& strncmp ( s
, pfx
, l
) == 0 ;
1841 /* Returns nonzero when *s ends with *sfx */
1842 pa_bool_t
pa_endswith ( const char * s
, const char * sfx
) {
1851 return l1
>= l2
&& strcmp ( s
+ l1
- l2
, sfx
) == 0 ;
1854 pa_bool_t
pa_is_path_absolute ( const char * fn
) {
1860 return strlen ( fn
) >= 3 && isalpha ( fn
[ 0 ]) && fn
[ 1 ] == ':' && fn
[ 2 ] == ' \\ ' ;
1864 char * pa_make_path_absolute ( const char * p
) {
1870 if ( pa_is_path_absolute ( p
))
1871 return pa_xstrdup ( p
);
1873 if (!( cwd
= pa_getcwd ()))
1874 return pa_xstrdup ( p
);
1876 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , cwd
, p
);
1881 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1882 * if fn is non-null and starts with / return fn
1883 * otherwise append fn to the run time path and return it */
1884 static char * get_path ( const char * fn
, pa_bool_t prependmid
, pa_bool_t rt
) {
1887 if ( pa_is_path_absolute ( fn
))
1888 return pa_xstrdup ( fn
);
1890 rtp
= rt
? pa_get_runtime_dir () : pa_get_state_dir ();
1901 if (!( mid
= pa_machine_id ())) {
1906 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s:%s" , rtp
, mid
, fn
);
1909 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , rtp
, fn
);
1917 char * pa_runtime_path ( const char * fn
) {
1918 return get_path ( fn
, FALSE
, TRUE
);
1921 char * pa_state_path ( const char * fn
, pa_bool_t appendmid
) {
1922 return get_path ( fn
, appendmid
, FALSE
);
1925 /* Convert the string s to a signed integer in *ret_i */
1926 int pa_atoi ( const char * s
, int32_t * ret_i
) {
1934 l
= strtol ( s
, & x
, 0 );
1936 if (! x
|| * x
|| errno
) {
1942 if (( int32_t ) l
!= l
) {
1947 * ret_i
= ( int32_t ) l
;
1952 /* Convert the string s to an unsigned integer in *ret_u */
1953 int pa_atou ( const char * s
, uint32_t * ret_u
) {
1961 l
= strtoul ( s
, & x
, 0 );
1963 if (! x
|| * x
|| errno
) {
1969 if (( uint32_t ) l
!= l
) {
1974 * ret_u
= ( uint32_t ) l
;
1979 #ifdef HAVE_STRTOF_L
1980 static locale_t c_locale
= NULL
;
1982 static void c_locale_destroy ( void ) {
1983 freelocale ( c_locale
);
1987 int pa_atod ( const char * s
, double * ret_d
) {
1994 /* This should be locale independent */
1996 #ifdef HAVE_STRTOF_L
2000 if (( c_locale
= newlocale ( LC_ALL_MASK
, "C" , NULL
)))
2001 atexit ( c_locale_destroy
);
2007 f
= strtod_l ( s
, & x
, c_locale
);
2015 if (! x
|| * x
|| errno
) {
2026 /* Same as snprintf, but guarantees NUL-termination on every platform */
2027 size_t pa_snprintf ( char * str
, size_t size
, const char * format
, ...) {
2032 pa_assert ( size
> 0 );
2035 va_start ( ap
, format
);
2036 ret
= pa_vsnprintf ( str
, size
, format
, ap
);
2042 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2043 size_t pa_vsnprintf ( char * str
, size_t size
, const char * format
, va_list ap
) {
2047 pa_assert ( size
> 0 );
2050 ret
= vsnprintf ( str
, size
, format
, ap
);
2057 if (( size_t ) ret
> size
- 1 )
2060 return ( size_t ) ret
;
2063 /* Truncate the specified string, but guarantee that the string
2064 * returned still validates as UTF8 */
2065 char * pa_truncate_utf8 ( char * c
, size_t l
) {
2067 pa_assert ( pa_utf8_valid ( c
));
2074 while ( l
> 0 && ! pa_utf8_valid ( c
))
2080 char * pa_getcwd ( void ) {
2084 char * p
= pa_xmalloc ( l
);
2088 if ( errno
!= ERANGE
)
2096 void * pa_will_need ( const void * p
, size_t l
) {
2097 #ifdef RLIMIT_MEMLOCK
2108 a
= PA_PAGE_ALIGN_PTR ( p
);
2109 size
= ( size_t ) (( const uint8_t *) p
+ l
- ( const uint8_t *) a
);
2111 #ifdef HAVE_POSIX_MADVISE
2112 if (( r
= posix_madvise (( void *) a
, size
, POSIX_MADV_WILLNEED
)) == 0 ) {
2113 pa_log_debug ( "posix_madvise() worked fine!" );
2118 /* Most likely the memory was not mmap()ed from a file and thus
2119 * madvise() didn't work, so let's misuse mlock() do page this
2120 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2121 * inviting, the man page of mlock() tells us: "All pages that
2122 * contain a part of the specified address range are guaranteed to
2123 * be resident in RAM when the call returns successfully." */
2125 #ifdef RLIMIT_MEMLOCK
2126 pa_assert_se ( getrlimit ( RLIMIT_MEMLOCK
, & rlim
) == 0 );
2128 if ( rlim
. rlim_cur
< PA_PAGE_SIZE
) {
2129 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
));
2134 bs
= PA_PAGE_ALIGN (( size_t ) rlim
. rlim_cur
);
2136 bs
= PA_PAGE_SIZE
* 4 ;
2139 pa_log_debug ( "posix_madvise() failed (or doesn't exist), trying mlock(): %s" , pa_cstrerror ( r
));
2142 while ( size
> 0 && bs
> 0 ) {
2147 if ( mlock ( a
, bs
) < 0 ) {
2148 bs
= PA_PAGE_ALIGN ( bs
/ 2 );
2152 pa_assert_se ( munlock ( a
, bs
) == 0 );
2154 a
= ( const uint8_t *) a
+ bs
;
2160 pa_log_debug ( "mlock() failed too (or doesn't exist), giving up: %s" , pa_cstrerror ( errno
));
2162 pa_log_debug ( "mlock() worked fine!" );
2167 void pa_close_pipe ( int fds
[ 2 ]) {
2171 pa_assert_se ( pa_close ( fds
[ 0 ]) == 0 );
2174 pa_assert_se ( pa_close ( fds
[ 1 ]) == 0 );
2176 fds
[ 0 ] = fds
[ 1 ] = - 1 ;
2179 char * pa_readlink ( const char * p
) {
2188 if (( n
= readlink ( p
, c
, l
- 1 )) < 0 ) {
2193 if (( size_t ) n
< l
- 1 ) {
2203 int pa_close_all ( int except_fd
, ...) {
2208 va_start ( ap
, except_fd
);
2211 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2216 p
= pa_xnew ( int , n
+ 1 );
2218 va_start ( ap
, except_fd
);
2221 if ( except_fd
>= 0 ) {
2225 while (( fd
= va_arg ( ap
, int )) >= 0 )
2232 r
= pa_close_allv ( p
);
2238 int pa_close_allv ( const int except_fds
[]) {
2247 if (( d
= opendir ( "/proc/self/fd" ))) {
2251 while (( de
= readdir ( d
))) {
2257 if ( de
-> d_name
[ 0 ] == '.' )
2261 l
= strtol ( de
-> d_name
, & e
, 10 );
2262 if ( errno
!= 0 || ! e
|| * e
) {
2270 if (( long ) fd
!= l
) {
2283 for ( i
= 0 ; except_fds
[ i
] >= 0 ; i
++)
2284 if ( except_fds
[ i
] == fd
) {
2292 if ( pa_close ( fd
) < 0 ) {
2293 saved_errno
= errno
;
2295 errno
= saved_errno
;
2307 if ( getrlimit ( RLIMIT_NOFILE
, & rl
) >= 0 )
2308 maxfd
= ( int ) rl
. rlim_max
;
2310 maxfd
= sysconf ( _SC_OPEN_MAX
);
2312 for ( fd
= 3 ; fd
< maxfd
; fd
++) {
2317 for ( i
= 0 ; except_fds
[ i
] >= 0 ; i
++)
2318 if ( except_fds
[ i
] == fd
) {
2326 if ( pa_close ( fd
) < 0 && errno
!= EBADF
)
2333 int pa_unblock_sigs ( int except
, ...) {
2338 va_start ( ap
, except
);
2341 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2346 p
= pa_xnew ( int , n
+ 1 );
2348 va_start ( ap
, except
);
2355 while (( sig
= va_arg ( ap
, int )) >= 0 )
2362 r
= pa_unblock_sigsv ( p
);
2368 int pa_unblock_sigsv ( const int except
[]) {
2372 if ( sigemptyset (& ss
) < 0 )
2375 for ( i
= 0 ; except
[ i
] > 0 ; i
++)
2376 if ( sigaddset (& ss
, except
[ i
]) < 0 )
2379 return sigprocmask ( SIG_SETMASK
, & ss
, NULL
);
2382 int pa_reset_sigs ( int except
, ...) {
2387 va_start ( ap
, except
);
2390 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2395 p
= pa_xnew ( int , n
+ 1 );
2397 va_start ( ap
, except
);
2404 while (( sig
= va_arg ( ap
, int )) >= 0 )
2411 r
= pa_reset_sigsv ( p
);
2417 int pa_reset_sigsv ( const int except
[]) {
2420 for ( sig
= 1 ; sig
< NSIG
; sig
++) {
2421 pa_bool_t reset
= TRUE
;
2432 for ( i
= 0 ; except
[ i
] > 0 ; i
++) {
2433 if ( sig
== except
[ i
]) {
2442 struct sigaction sa
;
2444 memset (& sa
, 0 , sizeof ( sa
));
2445 sa
. sa_handler
= SIG_DFL
;
2447 /* On Linux the first two RT signals are reserved by
2448 * glibc, and sigaction() will return EINVAL for them. */
2449 if (( sigaction ( sig
, & sa
, NULL
) < 0 ))
2450 if ( errno
!= EINVAL
)
2458 void pa_set_env ( const char * key
, const char * value
) {
2462 putenv ( pa_sprintf_malloc ( "%s=%s" , key
, value
));
2465 pa_bool_t
pa_in_system_mode ( void ) {
2468 if (!( e
= getenv ( "PULSE_SYSTEM" )))
2474 char * pa_get_user_name_malloc ( void ) {
2478 #ifdef _SC_LOGIN_NAME_MAX
2479 k
= ( ssize_t
) sysconf ( _SC_LOGIN_NAME_MAX
);
2485 u
= pa_xnew ( char , k
+ 1 );
2487 if (!( pa_get_user_name ( u
, k
))) {
2495 char * pa_get_host_name_malloc ( void ) {
2504 if (! pa_get_host_name ( c
, l
)) {
2506 if ( errno
!= EINVAL
&& errno
!= ENAMETOOLONG
)
2509 } else if ( strlen ( c
) < l
- 1 ) {
2517 u
= pa_utf8_filter ( c
);
2522 /* Hmm, the hostname is as long the space we offered the
2523 * function, we cannot know if it fully fit in, so let's play
2524 * safe and retry. */
2533 char * pa_machine_id ( void ) {
2537 /* The returned value is supposed be some kind of ascii identifier
2538 * that is unique and stable across reboots. */
2540 /* First we try the D-Bus UUID, which is the best option we have,
2541 * since it fits perfectly our needs and is not as volatile as the
2542 * hostname which might be set from dhcp. */
2544 if (( f
= fopen ( PA_MACHINE_ID
, "r" ))) {
2545 char ln
[ 34 ] = "" , * r
;
2547 r
= fgets ( ln
, sizeof ( ln
)- 1 , f
);
2553 return pa_utf8_filter ( ln
);
2556 if (( h
= pa_get_host_name_malloc ()))
2559 /* If no hostname was set we use the POSIX hostid. It's usually
2560 * the IPv4 address. Might not be that stable. */
2561 return pa_sprintf_malloc ( "%08lx" , ( unsigned long ) gethostid
);
2564 char * pa_session_id ( void ) {
2567 if (!( e
= getenv ( "XDG_SESSION_COOKIE" )))
2570 return pa_utf8_filter ( e
);
2573 char * pa_uname_string ( void ) {
2576 pa_assert_se ( uname (& u
) >= 0 );
2578 return pa_sprintf_malloc ( "%s %s %s %s" , u
. sysname
, u
. machine
, u
. release
, u
. version
);
2581 #ifdef HAVE_VALGRIND_MEMCHECK_H
2582 pa_bool_t
pa_in_valgrind ( void ) {
2585 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2586 * here instead of really checking whether we run in valgrind or
2590 b
= getenv ( "VALGRIND" ) ? 2 : 1 ;
2596 unsigned pa_gcd ( unsigned a
, unsigned b
) {
2607 void pa_reduce ( unsigned * num
, unsigned * den
) {
2609 unsigned gcd
= pa_gcd (* num
, * den
);
2617 pa_assert ( pa_gcd (* num
, * den
) == 1 );
2620 unsigned pa_ncpus ( void ) {
2623 #ifdef _SC_NPROCESSORS_CONF
2624 ncpus
= sysconf ( _SC_NPROCESSORS_CONF
);
2629 return ncpus
<= 0 ? 1 : ( unsigned ) ncpus
;
2632 char * pa_replace ( const char * s
, const char * a
, const char * b
) {
2641 sb
= pa_strbuf_new ();
2646 if (!( p
= strstr ( s
, a
)))
2649 pa_strbuf_putsn ( sb
, s
, p
- s
);
2650 pa_strbuf_puts ( sb
, b
);
2654 pa_strbuf_puts ( sb
, s
);
2656 return pa_strbuf_tostring_free ( sb
);
2659 char * pa_unescape ( char * p
) {
2661 pa_bool_t escaped
= FALSE
;
2663 for ( s
= p
, d
= p
; * s
; s
++) {
2664 if (! escaped
&& * s
== ' \\ ' ) {
2678 char * pa_realpath ( const char * path
) {
2682 /* We want only abolsute paths */
2683 if ( path
[ 0 ] != '/' ) {
2688 #if defined(__GLIBC__) || defined(__APPLE__)
2692 if (!( r
= realpath ( path
, NULL
)))
2695 /* We copy this here in case our pa_xmalloc() is not
2696 * implemented on top of libc malloc() */
2700 #elif defined(PATH_MAX)
2703 path_buf
= pa_xmalloc ( PATH_MAX
);
2705 if (!( t
= realpath ( path
, path_buf
))) {
2711 #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."
2717 void pa_disable_sigpipe ( void ) {
2720 struct sigaction sa
;
2724 if ( sigaction ( SIGPIPE
, NULL
, & sa
) < 0 ) {
2725 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
2729 sa
. sa_handler
= SIG_IGN
;
2731 if ( sigaction ( SIGPIPE
, & sa
, NULL
) < 0 ) {
2732 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
2738 void pa_xfreev ( void ** a
) {
2744 for ( p
= a
; * p
; p
++)
2750 char ** pa_split_spaces_strv ( const char * s
) {
2752 unsigned i
= 0 , n
= 8 ;
2753 const char * state
= NULL
;
2755 t
= pa_xnew ( char *, n
);
2756 while (( e
= pa_split_spaces ( s
, & state
))) {
2761 t
= pa_xrenew ( char *, t
, n
);
2774 char * pa_maybe_prefix_path ( const char * path
, const char * prefix
) {
2777 if ( pa_is_path_absolute ( path
))
2778 return pa_xstrdup ( path
);
2780 return pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , prefix
, path
);