]>
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>
44 #ifdef HAVE_LANGINFO_H
49 #include <sys/utsname.h>
52 #if defined(HAVE_REGEX_H)
54 #elif defined(HAVE_PCREPOSIX_H)
55 #include <pcreposix.h>
65 #if defined(__linux__) && !defined(SCHED_RESET_ON_FORK)
66 #define SCHED_RESET_ON_FORK 0x40000000
70 #ifdef HAVE_SYS_RESOURCE_H
71 #include <sys/resource.h>
74 #ifdef HAVE_SYS_CAPABILITY_H
75 #include <sys/capability.h>
78 #ifdef HAVE_SYS_MMAN_H
102 #ifdef HAVE_LIBSAMPLERATE
103 #include <samplerate.h>
115 #include <sys/personality.h>
118 #include <pulse/xmalloc.h>
119 #include <pulse/util.h>
120 #include <pulse/utf8.h>
122 #include <pulsecore/core-error.h>
123 #include <pulsecore/socket.h>
124 #include <pulsecore/log.h>
125 #include <pulsecore/macro.h>
126 #include <pulsecore/thread.h>
127 #include <pulsecore/strbuf.h>
128 #include <pulsecore/usergroup.h>
129 #include <pulsecore/strlist.h>
130 #include <pulsecore/cpu-x86.h>
132 #include "core-util.h"
134 /* Not all platforms have this */
136 #define MSG_NOSIGNAL 0
139 #define NEWLINE " \r\n "
140 #define WHITESPACE " \n\r \t "
142 static pa_strlist
* recorded_env
= NULL
;
146 #define PULSE_ROOTENV "PULSE_ROOT"
148 int pa_set_root ( HANDLE handle
) {
149 char library_path
[ MAX_PATH
+ sizeof ( PULSE_ROOTENV
) + 1 ], * sep
;
151 strcpy ( library_path
, PULSE_ROOTENV
"=" );
153 /* FIXME: Needs to set errno */
155 if (! GetModuleFileName ( handle
, library_path
+ sizeof ( PULSE_ROOTENV
), MAX_PATH
))
158 sep
= strrchr ( library_path
, PA_PATH_SEP_CHAR
);
162 if ( _putenv ( library_path
) < 0 )
170 /** Make a file descriptor nonblock. Doesn't do any error checking */
171 void pa_make_fd_nonblock ( int fd
) {
177 pa_assert_se (( v
= fcntl ( fd
, F_GETFL
)) >= 0 );
179 if (!( v
& O_NONBLOCK
))
180 pa_assert_se ( fcntl ( fd
, F_SETFL
, v
| O_NONBLOCK
) >= 0 );
182 #elif defined(OS_IS_WIN32)
184 if ( ioctlsocket ( fd
, FIONBIO
, & arg
) < 0 ) {
185 pa_assert_se ( WSAGetLastError () == WSAENOTSOCK
);
186 pa_log_warn ( "Only sockets can be made non-blocking!" );
189 pa_log_warn ( "Non-blocking I/O not supported.!" );
194 /* Set the FD_CLOEXEC flag for a fd */
195 void pa_make_fd_cloexec ( int fd
) {
201 pa_assert_se (( v
= fcntl ( fd
, F_GETFD
, 0 )) >= 0 );
203 if (!( v
& FD_CLOEXEC
))
204 pa_assert_se ( fcntl ( fd
, F_SETFD
, v
| FD_CLOEXEC
) >= 0 );
209 /** Creates a directory securely */
210 int pa_make_secure_dir ( const char * dir
, mode_t m
, uid_t uid
, gid_t gid
) {
212 int r
, saved_errno
, fd
;
221 u
= umask ((~ m
) & 0777 );
227 if ( r
< 0 && errno
!= EEXIST
)
230 #if defined(HAVE_FSTAT) && !defined(OS_IS_WIN32)
244 if ( fstat ( fd
, & st
) < 0 ) {
245 pa_assert_se ( pa_close ( fd
) >= 0 );
249 if (! S_ISDIR ( st
. st_mode
)) {
250 pa_assert_se ( pa_close ( fd
) >= 0 );
256 if ( uid
== ( uid_t
)- 1 )
258 if ( gid
== ( gid_t
)- 1 )
260 ( void ) fchown ( fd
, uid
, gid
);
264 ( void ) fchmod ( fd
, m
);
267 pa_assert_se ( pa_close ( fd
) >= 0 );
271 if ( lstat ( dir
, & st
) < 0 )
273 if ( stat ( dir
, & st
) < 0 )
278 if (! S_ISDIR ( st
. st_mode
) ||
279 ( st
. st_uid
!= uid
) ||
280 ( st
. st_gid
!= gid
) ||
281 (( st
. st_mode
& 0777 ) != m
)) {
286 pa_log_warn ( "Secure directory creation not supported on Win32." );
299 /* Return a newly allocated sting containing the parent directory of the specified file */
300 char * pa_parent_dir ( const char * fn
) {
301 char * slash
, * dir
= pa_xstrdup ( fn
);
303 if (( slash
= ( char *) pa_path_get_filename ( dir
)) == dir
) {
313 /* Creates a the parent directory of the specified path securely */
314 int pa_make_secure_parent_dir ( const char * fn
, mode_t m
, uid_t uid
, gid_t gid
) {
318 if (!( dir
= pa_parent_dir ( fn
)))
321 if ( pa_make_secure_dir ( dir
, m
, uid
, gid
) < 0 )
331 /** Platform independent read function. Necessary since not all
332 * systems treat all file descriptors equal. If type is
333 * non-NULL it is used to cache the type of the fd. This is
334 * useful for making sure that only a single syscall is executed per
335 * function call. The variable pointed to should be initialized to 0
337 ssize_t
pa_read ( int fd
, void * buf
, size_t count
, int * type
) {
341 if (! type
|| * type
== 0 ) {
344 if (( r
= recv ( fd
, buf
, count
, 0 )) >= 0 )
347 if ( WSAGetLastError () != WSAENOTSOCK
) {
348 errno
= WSAGetLastError ();
361 if (( r
= read ( fd
, buf
, count
)) < 0 )
369 /** Similar to pa_read(), but handles writes */
370 ssize_t
pa_write ( int fd
, const void * buf
, size_t count
, int * type
) {
372 if (! type
|| * type
== 0 ) {
376 if (( r
= send ( fd
, buf
, count
, MSG_NOSIGNAL
)) < 0 ) {
388 if ( WSAGetLastError () != WSAENOTSOCK
) {
389 errno
= WSAGetLastError ();
393 if ( errno
!= ENOTSOCK
)
404 if (( r
= write ( fd
, buf
, count
)) < 0 )
412 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
413 * unless EOF is reached or an error occurred */
414 ssize_t
pa_loop_read ( int fd
, void * data
, size_t size
, int * type
) {
430 if (( r
= pa_read ( fd
, data
, size
, type
)) < 0 )
437 data
= ( uint8_t *) data
+ r
;
444 /** Similar to pa_loop_read(), but wraps write() */
445 ssize_t
pa_loop_write ( int fd
, const void * data
, size_t size
, int * type
) {
461 if (( r
= pa_write ( fd
, data
, size
, type
)) < 0 )
468 data
= ( const uint8_t *) data
+ r
;
475 /** Platform independent read function. Necessary since not all
476 * systems treat all file descriptors equal. */
477 int pa_close ( int fd
) {
482 if (( ret
= closesocket ( fd
)) == 0 )
485 if ( WSAGetLastError () != WSAENOTSOCK
) {
486 errno
= WSAGetLastError ();
494 if (( r
= close ( fd
)) < 0 )
502 /* Print a warning messages in case that the given signal is not
503 * blocked or trapped */
504 void pa_check_signal_is_blocked ( int sig
) {
505 #ifdef HAVE_SIGACTION
509 /* If POSIX threads are supported use thread-aware
510 * pthread_sigmask() function, to check if the signal is
511 * blocked. Otherwise fall back to sigprocmask() */
514 if ( pthread_sigmask ( SIG_SETMASK
, NULL
, & set
) < 0 ) {
516 if ( sigprocmask ( SIG_SETMASK
, NULL
, & set
) < 0 ) {
517 pa_log ( "sigprocmask(): %s" , pa_cstrerror ( errno
));
524 if ( sigismember (& set
, sig
))
527 /* Check whether the signal is trapped */
529 if ( sigaction ( sig
, NULL
, & sa
) < 0 ) {
530 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
534 if ( sa
. sa_handler
!= SIG_DFL
)
537 pa_log_warn ( "%s is not trapped. This might cause malfunction!" , pa_sig2str ( sig
));
538 #else /* HAVE_SIGACTION */
539 pa_log_warn ( "%s might not be trapped. This might cause malfunction!" , pa_sig2str ( sig
));
543 /* The following function is based on an example from the GNU libc
544 * documentation. This function is similar to GNU's asprintf(). */
545 char * pa_sprintf_malloc ( const char * format
, ...) {
555 c
= pa_xrealloc ( c
, size
);
557 va_start ( ap
, format
);
558 r
= vsnprintf ( c
, size
, format
, ap
);
563 if ( r
> - 1 && ( size_t ) r
< size
)
566 if ( r
> - 1 ) /* glibc 2.1 */
573 /* Same as the previous function, but use a va_list instead of an
575 char * pa_vsprintf_malloc ( const char * format
, va_list ap
) {
585 c
= pa_xrealloc ( c
, size
);
588 r
= vsnprintf ( c
, size
, format
, aq
);
593 if ( r
> - 1 && ( size_t ) r
< size
)
596 if ( r
> - 1 ) /* glibc 2.1 */
603 /* Similar to OpenBSD's strlcpy() function */
604 char * pa_strlcpy ( char * b
, const char * s
, size_t l
) {
622 static int set_scheduler ( int rtprio
) {
624 struct sched_param sp
;
630 dbus_error_init (& error
);
634 sp
. sched_priority
= rtprio
;
636 #ifdef SCHED_RESET_ON_FORK
637 if ( pthread_setschedparam ( pthread_self (), SCHED_RR
| SCHED_RESET_ON_FORK
, & sp
) == 0 ) {
638 pa_log_debug ( "SCHED_RR|SCHED_RESET_ON_FORK worked." );
643 if ( pthread_setschedparam ( pthread_self (), SCHED_RR
, & sp
) == 0 ) {
644 pa_log_debug ( "SCHED_RR worked." );
647 #endif /* HAVE_SCHED_H */
650 /* Try to talk to RealtimeKit */
652 if (!( bus
= dbus_bus_get ( DBUS_BUS_SYSTEM
, & error
))) {
653 pa_log ( "Failed to connect to system bus: %s \n " , error
. message
);
654 dbus_error_free (& error
);
659 /* We need to disable exit on disconnect because otherwise
660 * dbus_shutdown will kill us. See
661 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
662 dbus_connection_set_exit_on_disconnect ( bus
, FALSE
);
664 r
= rtkit_make_realtime ( bus
, 0 , rtprio
);
665 dbus_connection_unref ( bus
);
668 pa_log_debug ( "RealtimeKit worked." );
680 /* Make the current thread a realtime thread, and acquire the highest
681 * rtprio we can get that is less or equal the specified parameter. If
682 * the thread is already realtime, don't do anything. */
683 int pa_make_realtime ( int rtprio
) {
685 #ifdef _POSIX_PRIORITY_SCHEDULING
688 if ( set_scheduler ( rtprio
) >= 0 ) {
689 pa_log_info ( "Successfully enabled SCHED_RR scheduling for thread, with priority %i." , rtprio
);
693 for ( p
= rtprio
- 1 ; p
>= 1 ; p
--)
694 if ( set_scheduler ( p
) >= 0 ) {
695 pa_log_info ( "Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i." , p
, rtprio
);
699 pa_log_info ( "Failed to acquire real-time scheduling: %s" , pa_cstrerror ( errno
));
708 static int set_nice ( int nice_level
) {
714 dbus_error_init (& error
);
717 #ifdef HAVE_SYS_RESOURCE_H
718 if ( setpriority ( PRIO_PROCESS
, 0 , nice_level
) >= 0 ) {
719 pa_log_debug ( "setpriority() worked." );
725 /* Try to talk to RealtimeKit */
727 if (!( bus
= dbus_bus_get ( DBUS_BUS_SYSTEM
, & error
))) {
728 pa_log ( "Failed to connect to system bus: %s \n " , error
. message
);
729 dbus_error_free (& error
);
734 /* We need to disable exit on disconnect because otherwise
735 * dbus_shutdown will kill us. See
736 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
737 dbus_connection_set_exit_on_disconnect ( bus
, FALSE
);
739 r
= rtkit_make_high_priority ( bus
, 0 , nice_level
);
740 dbus_connection_unref ( bus
);
743 pa_log_debug ( "RealtimeKit worked." );
753 /* Raise the priority of the current process as much as possible that
754 * is <= the specified nice level..*/
755 int pa_raise_priority ( int nice_level
) {
757 #ifdef HAVE_SYS_RESOURCE_H
760 if ( set_nice ( nice_level
) >= 0 ) {
761 pa_log_info ( "Successfully gained nice level %i." , nice_level
);
765 for ( n
= nice_level
+ 1 ; n
< 0 ; n
++)
766 if ( set_nice ( n
) >= 0 ) {
767 pa_log_info ( "Successfully acquired nice level %i, which is lower than the requested %i." , n
, nice_level
);
771 pa_log_info ( "Failed to acquire high-priority scheduling: %s" , pa_cstrerror ( errno
));
776 if ( nice_level
< 0 ) {
777 if (! SetPriorityClass ( GetCurrentProcess (), HIGH_PRIORITY_CLASS
)) {
778 pa_log_warn ( "SetPriorityClass() failed: 0x%08X" , GetLastError ());
783 pa_log_info ( "Successfully gained high priority class." );
790 /* Reset the priority to normal, inverting the changes made by
791 * pa_raise_priority() and pa_make_realtime()*/
792 void pa_reset_priority ( void ) {
793 #ifdef HAVE_SYS_RESOURCE_H
794 struct sched_param sp
;
796 setpriority ( PRIO_PROCESS
, 0 , 0 );
799 pthread_setschedparam ( pthread_self (), SCHED_OTHER
, & sp
);
803 SetPriorityClass ( GetCurrentProcess (), NORMAL_PRIORITY_CLASS
);
807 int pa_match ( const char * expr
, const char * v
) {
812 if ( regcomp (& re
, expr
, REG_NOSUB
| REG_EXTENDED
) != 0 ) {
817 if (( k
= regexec (& re
, v
, 0 , NULL
, 0 )) == 0 )
819 else if ( k
== REG_NOMATCH
)
832 /* Try to parse a boolean string value.*/
833 int pa_parse_boolean ( const char * v
) {
837 /* First we check language independant */
838 if (! strcmp ( v
, "1" ) || v
[ 0 ] == 'y' || v
[ 0 ] == 'Y' || v
[ 0 ] == 't' || v
[ 0 ] == 'T' || ! strcasecmp ( v
, "on" ))
840 else if (! strcmp ( v
, "0" ) || v
[ 0 ] == 'n' || v
[ 0 ] == 'N' || v
[ 0 ] == 'f' || v
[ 0 ] == 'F' || ! strcasecmp ( v
, "off" ))
843 #ifdef HAVE_LANGINFO_H
844 /* And then we check language dependant */
845 if (( expr
= nl_langinfo ( YESEXPR
)))
847 if ( pa_match ( expr
, v
) > 0 )
850 if (( expr
= nl_langinfo ( NOEXPR
)))
852 if ( pa_match ( expr
, v
) > 0 )
860 /* Split the specified string wherever one of the strings in delimiter
861 * occurs. Each time it is called returns a newly allocated string
862 * with pa_xmalloc(). The variable state points to, should be
863 * initiallized to NULL before the first call. */
864 char * pa_split ( const char * c
, const char * delimiter
, const char ** state
) {
865 const char * current
= * state
? * state
: c
;
871 l
= strcspn ( current
, delimiter
);
877 return pa_xstrndup ( current
, l
);
880 /* Split a string into words. Otherwise similar to pa_split(). */
881 char * pa_split_spaces ( const char * c
, const char ** state
) {
882 const char * current
= * state
? * state
: c
;
885 if (!* current
|| * c
== 0 )
888 current
+= strspn ( current
, WHITESPACE
);
889 l
= strcspn ( current
, WHITESPACE
);
893 return pa_xstrndup ( current
, l
);
896 PA_STATIC_TLS_DECLARE ( signame
, pa_xfree
);
898 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
899 const char * pa_sig2str ( int sig
) {
912 char buf
[ SIG2STR_MAX
];
914 if ( sig2str ( sig
, buf
) == 0 ) {
915 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
916 t
= pa_sprintf_malloc ( "SIG%s" , buf
);
917 PA_STATIC_TLS_SET ( signame
, t
);
925 case SIGHUP
: return "SIGHUP" ;
927 case SIGINT
: return "SIGINT" ;
929 case SIGQUIT
: return "SIGQUIT" ;
931 case SIGILL
: return "SIGULL" ;
933 case SIGTRAP
: return "SIGTRAP" ;
935 case SIGABRT
: return "SIGABRT" ;
937 case SIGBUS
: return "SIGBUS" ;
939 case SIGFPE
: return "SIGFPE" ;
941 case SIGKILL
: return "SIGKILL" ;
944 case SIGUSR1
: return "SIGUSR1" ;
946 case SIGSEGV
: return "SIGSEGV" ;
948 case SIGUSR2
: return "SIGUSR2" ;
951 case SIGPIPE
: return "SIGPIPE" ;
954 case SIGALRM
: return "SIGALRM" ;
956 case SIGTERM
: return "SIGTERM" ;
958 case SIGSTKFLT
: return "SIGSTKFLT" ;
961 case SIGCHLD
: return "SIGCHLD" ;
964 case SIGCONT
: return "SIGCONT" ;
967 case SIGSTOP
: return "SIGSTOP" ;
970 case SIGTSTP
: return "SIGTSTP" ;
973 case SIGTTIN
: return "SIGTTIN" ;
976 case SIGTTOU
: return "SIGTTOU" ;
979 case SIGURG
: return "SIGURG" ;
982 case SIGXCPU
: return "SIGXCPU" ;
985 case SIGXFSZ
: return "SIGXFSZ" ;
988 case SIGVTALRM
: return "SIGVTALRM" ;
991 case SIGPROF
: return "SIGPROF" ;
994 case SIGWINCH
: return "SIGWINCH" ;
997 case SIGIO
: return "SIGIO" ;
1000 case SIGPWR
: return "SIGPWR" ;
1003 case SIGSYS
: return "SIGSYS" ;
1008 if ( sig
>= SIGRTMIN
&& sig
<= SIGRTMAX
) {
1009 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
1010 t
= pa_sprintf_malloc ( "SIGRTMIN+%i" , sig
- SIGRTMIN
);
1011 PA_STATIC_TLS_SET ( signame
, t
);
1020 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
1021 t
= pa_sprintf_malloc ( "SIG%i" , sig
);
1022 PA_STATIC_TLS_SET ( signame
, t
);
1028 /* Check whether the specified GID and the group name match */
1029 static int is_group ( gid_t gid
, const char * name
) {
1030 struct group
* group
= NULL
;
1034 if (!( group
= pa_getgrgid_malloc ( gid
)))
1039 pa_log ( "pa_getgrgid_malloc(%u): %s" , gid
, pa_cstrerror ( errno
));
1044 r
= strcmp ( name
, group
-> gr_name
) == 0 ;
1047 pa_getgrgid_free ( group
);
1052 /* Check the current user is member of the specified group */
1053 int pa_own_uid_in_group ( const char * name
, gid_t
* gid
) {
1054 GETGROUPS_T
* gids
, tgid
;
1055 long n
= sysconf ( _SC_NGROUPS_MAX
);
1060 gids
= pa_xmalloc ( sizeof ( GETGROUPS_T
) * ( size_t ) n
);
1062 if (( n
= getgroups (( int ) n
, gids
)) < 0 ) {
1063 pa_log ( "getgroups(): %s" , pa_cstrerror ( errno
));
1067 for ( i
= 0 ; i
< n
; i
++) {
1069 if (( k
= is_group ( gids
[ i
], name
)) < 0 )
1078 if (( k
= is_group ( tgid
= getgid (), name
)) < 0 )
1094 /* Check whether the specifc user id is a member of the specified group */
1095 int pa_uid_in_group ( uid_t uid
, const char * name
) {
1096 struct group
* group
= NULL
;
1101 if (!( group
= pa_getgrnam_malloc ( name
)))
1109 for ( i
= group
-> gr_mem
; * i
; i
++) {
1110 struct passwd
* pw
= NULL
;
1113 if (!( pw
= pa_getpwnam_malloc (* i
)))
1116 if ( pw
-> pw_uid
== uid
)
1119 pa_getpwnam_free ( pw
);
1126 pa_getgrnam_free ( group
);
1131 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
1132 gid_t
pa_get_gid_of_group ( const char * name
) {
1133 gid_t ret
= ( gid_t
) - 1 ;
1134 struct group
* gr
= NULL
;
1137 if (!( gr
= pa_getgrnam_malloc ( name
)))
1147 pa_getgrnam_free ( gr
);
1151 int pa_check_in_group ( gid_t g
) {
1152 gid_t gids
[ NGROUPS_MAX
];
1155 if (( r
= getgroups ( NGROUPS_MAX
, gids
)) < 0 )
1165 #else /* HAVE_GRP_H */
1167 int pa_own_uid_in_group ( const char * name
, gid_t
* gid
) {
1173 int pa_uid_in_group ( uid_t uid
, const char * name
) {
1178 gid_t
pa_get_gid_of_group ( const char * name
) {
1183 int pa_check_in_group ( gid_t g
) {
1190 /* Lock or unlock a file entirely.
1191 (advisory on UNIX, mandatory on Windows) */
1192 int pa_lock_fd ( int fd
, int b
) {
1194 struct flock f_lock
;
1196 /* Try a R/W lock first */
1198 f_lock
. l_type
= ( short ) ( b
? F_WRLCK
: F_UNLCK
);
1199 f_lock
. l_whence
= SEEK_SET
;
1203 if ( fcntl ( fd
, F_SETLKW
, & f_lock
) >= 0 )
1206 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1207 if ( b
&& errno
== EBADF
) {
1208 f_lock
. l_type
= F_RDLCK
;
1209 if ( fcntl ( fd
, F_SETLKW
, & f_lock
) >= 0 )
1213 pa_log ( "%slock: %s" , ! b
? "un" : "" , pa_cstrerror ( errno
));
1217 HANDLE h
= ( HANDLE
) _get_osfhandle ( fd
);
1219 if ( b
&& LockFile ( h
, 0 , 0 , 0xFFFFFFFF , 0xFFFFFFFF ))
1221 if (! b
&& UnlockFile ( h
, 0 , 0 , 0xFFFFFFFF , 0xFFFFFFFF ))
1224 pa_log ( "%slock failed: 0x%08X" , ! b
? "un" : "" , GetLastError ());
1226 /* FIXME: Needs to set errno! */
1232 /* Remove trailing newlines from a string */
1233 char * pa_strip_nl ( char * s
) {
1236 s
[ strcspn ( s
, NEWLINE
)] = 0 ;
1240 char * pa_strip ( char * s
) {
1243 /* Drops trailing whitespace. Modifies the string in
1244 * place. Returns pointer to first non-space character */
1246 s
+= strspn ( s
, WHITESPACE
);
1248 for ( e
= s
; * e
; e
++)
1249 if (! strchr ( WHITESPACE
, * e
))
1260 /* Create a temporary lock file and lock it. */
1261 int pa_lock_lockfile ( const char * fn
) {
1268 if (( fd
= pa_open_cloexec ( fn
, O_CREAT
| O_RDWR
1272 , S_IRUSR
| S_IWUSR
)) < 0 ) {
1273 pa_log_warn ( "Failed to create lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1277 if ( pa_lock_fd ( fd
, 1 ) < 0 ) {
1278 pa_log_warn ( "Failed to lock file '%s'." , fn
);
1282 if ( fstat ( fd
, & st
) < 0 ) {
1283 pa_log_warn ( "Failed to fstat() file '%s': %s" , fn
, pa_cstrerror ( errno
));
1287 /* Check whether the file has been removed meanwhile. When yes,
1288 * restart this loop, otherwise, we're done */
1289 if ( st
. st_nlink
>= 1 )
1292 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1293 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1297 if ( pa_close ( fd
) < 0 ) {
1298 pa_log_warn ( "Failed to close file '%s': %s" , fn
, pa_cstrerror ( errno
));
1309 int saved_errno
= errno
;
1311 errno
= saved_errno
;
1317 /* Unlock a temporary lcok file */
1318 int pa_unlock_lockfile ( const char * fn
, int fd
) {
1323 if ( unlink ( fn
) < 0 ) {
1324 pa_log_warn ( "Unable to remove lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1329 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1330 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1334 if ( pa_close ( fd
) < 0 ) {
1335 pa_log_warn ( "Failed to close '%s': %s" , fn
, pa_cstrerror ( errno
));
1342 static char * get_pulse_home ( void ) {
1347 if (!( h
= pa_get_home_dir_malloc ())) {
1348 pa_log_error ( "Failed to get home directory." );
1352 if ( stat ( h
, & st
) < 0 ) {
1353 pa_log_error ( "Failed to stat home directory %s: %s" , h
, pa_cstrerror ( errno
));
1358 if ( st
. st_uid
!= getuid ()) {
1359 pa_log_error ( "Home directory %s not ours." , h
);
1365 ret
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" , h
);
1373 char * pa_get_state_dir ( void ) {
1376 /* The state directory shall contain dynamic data that should be
1377 * kept across reboots, and is private to this user */
1379 if (!( d
= pa_xstrdup ( getenv ( "PULSE_STATE_PATH" ))))
1380 if (!( d
= get_pulse_home ()))
1383 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1384 * dir then this will break. */
1386 if ( pa_make_secure_dir ( d
, 0700U , ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1387 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1395 char * pa_get_home_dir_malloc ( void ) {
1397 size_t allocated
= 128 ;
1400 homedir
= pa_xmalloc ( allocated
);
1402 if (! pa_get_home_dir ( homedir
, allocated
)) {
1407 if ( strlen ( homedir
) < allocated
- 1 )
1417 char * pa_get_binary_name_malloc ( void ) {
1419 size_t allocated
= 128 ;
1422 t
= pa_xmalloc ( allocated
);
1424 if (! pa_get_binary_name ( t
, allocated
)) {
1429 if ( strlen ( t
) < allocated
- 1 )
1439 static char * make_random_dir ( mode_t m
) {
1440 static const char table
[] =
1441 "abcdefghijklmnopqrstuvwxyz"
1442 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1448 fn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"pulse-XXXXXXXXXXXX" , pa_get_temp_dir ());
1449 pathlen
= strlen ( fn
);
1457 for ( i
= pathlen
- 12 ; i
< pathlen
; i
++)
1458 fn
[ i
] = table
[ rand () % ( sizeof ( table
)- 1 )];
1460 u
= umask ((~ m
) & 0777 );
1467 saved_errno
= errno
;
1469 errno
= saved_errno
;
1474 if ( errno
!= EEXIST
) {
1475 pa_log_error ( "Failed to create random directory %s: %s" , fn
, pa_cstrerror ( errno
));
1482 static int make_random_dir_and_link ( mode_t m
, const char * k
) {
1485 if (!( p
= make_random_dir ( m
)))
1489 if ( symlink ( p
, k
) < 0 ) {
1490 int saved_errno
= errno
;
1492 if ( errno
!= EEXIST
)
1493 pa_log_error ( "Failed to symlink %s to %s: %s" , k
, p
, pa_cstrerror ( errno
));
1498 errno
= saved_errno
;
1507 char * pa_get_runtime_dir ( void ) {
1508 char * d
, * k
= NULL
, * p
= NULL
, * t
= NULL
, * mid
;
1512 /* The runtime directory shall contain dynamic data that needs NOT
1513 * to be kept accross reboots and is usuallly private to the user,
1514 * except in system mode, where it might be accessible by other
1515 * users, too. Since we need POSIX locking and UNIX sockets in
1516 * this directory, we link it to a random subdir in /tmp, if it
1517 * was not explicitly configured. */
1519 m
= pa_in_system_mode () ? 0755U : 0700U ;
1521 if (( d
= getenv ( "PULSE_RUNTIME_PATH" ))) {
1523 if ( pa_make_secure_dir ( d
, m
, ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1524 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1528 return pa_xstrdup ( d
);
1531 if (!( d
= get_pulse_home ()))
1534 if ( pa_make_secure_dir ( d
, m
, ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1535 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1540 if (!( mid
= pa_machine_id ())) {
1545 k
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s-runtime" , d
, mid
);
1550 /* OK, first let's check if the "runtime" symlink is already
1553 if (!( p
= pa_readlink ( k
))) {
1555 if ( errno
!= ENOENT
) {
1556 pa_log_error ( "Failed to stat runtime directory %s: %s" , k
, pa_cstrerror ( errno
));
1560 /* Hmm, so the runtime directory didn't exist yet, so let's
1561 * create one in /tmp and symlink that to it */
1563 if ( make_random_dir_and_link ( 0700 , k
) < 0 ) {
1565 /* Mhmm, maybe another process was quicker than us,
1566 * let's check if that was valid */
1567 if ( errno
== EEXIST
)
1576 /* Make sure that this actually makes sense */
1577 if (! pa_is_path_absolute ( p
)) {
1578 pa_log_error ( "Path %s in link %s is not absolute." , p
, k
);
1583 /* Hmm, so this symlink is still around, make sure nobody fools
1587 if ( lstat ( p
, & st
) < 0 ) {
1589 if ( errno
!= ENOENT
) {
1590 pa_log_error ( "Failed to stat runtime directory %s: %s" , p
, pa_cstrerror ( errno
));
1596 if ( S_ISDIR ( st
. st_mode
) &&
1597 ( st
. st_uid
== getuid ()) &&
1598 (( st
. st_mode
& 0777 ) == 0700 )) {
1604 pa_log_info ( "Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory." );
1611 /* Hmm, so the link points to some nonexisting or invalid
1612 * dir. Let's replace it by a new link. We first create a
1613 * temporary link and then rename that to allow concurrent
1614 * execution of this function. */
1616 t
= pa_sprintf_malloc ( "%s.tmp" , k
);
1618 if ( make_random_dir_and_link ( 0700 , t
) < 0 ) {
1620 if ( errno
!= EEXIST
) {
1621 pa_log_error ( "Failed to symlink %s: %s" , t
, pa_cstrerror ( errno
));
1628 /* Hmm, someone lese was quicker then us. Let's give
1629 * him some time to finish, and retry. */
1634 /* OK, we succeeded in creating the temporary symlink, so
1635 * let's rename it */
1636 if ( rename ( t
, k
) < 0 ) {
1637 pa_log_error ( "Failed to rename %s to %s: %s" , t
, k
, pa_cstrerror ( errno
));
1653 /* Try to open a configuration file. If "env" is specified, open the
1654 * value of the specified environment variable. Otherwise look for a
1655 * file "local" in the home directory or a file "global" in global
1656 * file system. If "result" is non-NULL, a pointer to a newly
1657 * allocated buffer containing the used configuration file is
1659 FILE * pa_open_config_file ( const char * global
, const char * local
, const char * env
, char ** result
) {
1664 if (! getenv ( PULSE_ROOTENV
))
1668 if ( env
&& ( fn
= getenv ( env
))) {
1672 if (! ExpandEnvironmentStrings ( fn
, buf
, PATH_MAX
))
1673 /* FIXME: Needs to set errno! */
1678 if (( f
= pa_fopen_cloexec ( fn
, "r" ))) {
1680 * result
= pa_xstrdup ( fn
);
1685 pa_log_warn ( "Failed to open configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1695 if (( e
= getenv ( "PULSE_CONFIG_PATH" )))
1696 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , e
, local
);
1697 else if (( h
= pa_get_home_dir_malloc ())) {
1698 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s" , h
, local
);
1704 if (! ExpandEnvironmentStrings ( lfn
, buf
, PATH_MAX
)) {
1705 /* FIXME: Needs to set errno! */
1712 if (( f
= pa_fopen_cloexec ( fn
, "r" ))) {
1714 * result
= pa_xstrdup ( fn
);
1720 if ( errno
!= ENOENT
) {
1721 pa_log_warn ( "Failed to open configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1733 if (! ExpandEnvironmentStrings ( global
, buf
, PATH_MAX
))
1734 /* FIXME: Needs to set errno! */
1739 if (( f
= pa_fopen_cloexec ( global
, "r" ))) {
1742 * result
= pa_xstrdup ( global
);
1752 char * pa_find_config_file ( const char * global
, const char * local
, const char * env
) {
1757 if (! getenv ( PULSE_ROOTENV
))
1761 if ( env
&& ( fn
= getenv ( env
))) {
1764 if (! ExpandEnvironmentStrings ( fn
, buf
, PATH_MAX
))
1765 /* FIXME: Needs to set errno! */
1770 if ( access ( fn
, R_OK
) == 0 )
1771 return pa_xstrdup ( fn
);
1773 pa_log_warn ( "Failed to access configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1782 if (( e
= getenv ( "PULSE_CONFIG_PATH" )))
1783 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , e
, local
);
1784 else if (( h
= pa_get_home_dir_malloc ())) {
1785 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s" , h
, local
);
1791 if (! ExpandEnvironmentStrings ( lfn
, buf
, PATH_MAX
)) {
1792 /* FIXME: Needs to set errno! */
1799 if ( access ( fn
, R_OK
) == 0 ) {
1800 char * r
= pa_xstrdup ( fn
);
1805 if ( errno
!= ENOENT
) {
1806 pa_log_warn ( "Failed to access configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1816 if (! ExpandEnvironmentStrings ( global
, buf
, PATH_MAX
))
1817 /* FIXME: Needs to set errno! */
1822 if ( access ( global
, R_OK
) == 0 )
1823 return pa_xstrdup ( global
);
1831 /* Format the specified data as a hexademical string */
1832 char * pa_hexstr ( const uint8_t * d
, size_t dlength
, char * s
, size_t slength
) {
1833 size_t i
= 0 , j
= 0 ;
1834 const char hex
[] = "0123456789abcdef" ;
1838 pa_assert ( slength
> 0 );
1840 while ( i
< dlength
&& j
+ 3 <= slength
) {
1841 s
[ j
++] = hex
[* d
>> 4 ];
1842 s
[ j
++] = hex
[* d
& 0xF ];
1848 s
[ j
< slength
? j
: slength
] = 0 ;
1852 /* Convert a hexadecimal digit to a number or -1 if invalid */
1853 static int hexc ( char c
) {
1854 if ( c
>= '0' && c
<= '9' )
1857 if ( c
>= 'A' && c
<= 'F' )
1858 return c
- 'A' + 10 ;
1860 if ( c
>= 'a' && c
<= 'f' )
1861 return c
- 'a' + 10 ;
1867 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1868 size_t pa_parsehex ( const char * p
, uint8_t * d
, size_t dlength
) {
1874 while ( j
< dlength
&& * p
) {
1877 if (( b
= hexc (*( p
++))) < 0 )
1880 d
[ j
] = ( uint8_t ) ( b
<< 4 );
1885 if (( b
= hexc (*( p
++))) < 0 )
1888 d
[ j
] |= ( uint8_t ) b
;
1895 /* Returns nonzero when *s starts with *pfx */
1896 pa_bool_t
pa_startswith ( const char * s
, const char * pfx
) {
1904 return strlen ( s
) >= l
&& strncmp ( s
, pfx
, l
) == 0 ;
1907 /* Returns nonzero when *s ends with *sfx */
1908 pa_bool_t
pa_endswith ( const char * s
, const char * sfx
) {
1917 return l1
>= l2
&& strcmp ( s
+ l1
- l2
, sfx
) == 0 ;
1920 pa_bool_t
pa_is_path_absolute ( const char * fn
) {
1926 return strlen ( fn
) >= 3 && isalpha ( fn
[ 0 ]) && fn
[ 1 ] == ':' && fn
[ 2 ] == ' \\ ' ;
1930 char * pa_make_path_absolute ( const char * p
) {
1936 if ( pa_is_path_absolute ( p
))
1937 return pa_xstrdup ( p
);
1939 if (!( cwd
= pa_getcwd ()))
1940 return pa_xstrdup ( p
);
1942 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , cwd
, p
);
1947 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1948 * if fn is non-null and starts with / return fn
1949 * otherwise append fn to the run time path and return it */
1950 static char * get_path ( const char * fn
, pa_bool_t prependmid
, pa_bool_t rt
) {
1953 rtp
= rt
? pa_get_runtime_dir () : pa_get_state_dir ();
1958 if ( pa_is_path_absolute ( fn
))
1959 return pa_xstrdup ( fn
);
1967 if (!( mid
= pa_machine_id ())) {
1972 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s-%s" , rtp
, mid
, fn
);
1975 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , rtp
, fn
);
1983 char * pa_runtime_path ( const char * fn
) {
1984 return get_path ( fn
, FALSE
, TRUE
);
1987 char * pa_state_path ( const char * fn
, pa_bool_t appendmid
) {
1988 return get_path ( fn
, appendmid
, FALSE
);
1991 /* Convert the string s to a signed integer in *ret_i */
1992 int pa_atoi ( const char * s
, int32_t * ret_i
) {
2000 l
= strtol ( s
, & x
, 0 );
2002 if (! x
|| * x
|| errno
) {
2008 if (( int32_t ) l
!= l
) {
2013 * ret_i
= ( int32_t ) l
;
2018 /* Convert the string s to an unsigned integer in *ret_u */
2019 int pa_atou ( const char * s
, uint32_t * ret_u
) {
2027 l
= strtoul ( s
, & x
, 0 );
2029 if (! x
|| * x
|| errno
) {
2035 if (( uint32_t ) l
!= l
) {
2040 * ret_u
= ( uint32_t ) l
;
2045 #ifdef HAVE_STRTOF_L
2046 static locale_t c_locale
= NULL
;
2048 static void c_locale_destroy ( void ) {
2049 freelocale ( c_locale
);
2053 int pa_atod ( const char * s
, double * ret_d
) {
2060 /* This should be locale independent */
2062 #ifdef HAVE_STRTOF_L
2066 if (( c_locale
= newlocale ( LC_ALL_MASK
, "C" , NULL
)))
2067 atexit ( c_locale_destroy
);
2073 f
= strtod_l ( s
, & x
, c_locale
);
2081 if (! x
|| * x
|| errno
) {
2092 /* Same as snprintf, but guarantees NUL-termination on every platform */
2093 size_t pa_snprintf ( char * str
, size_t size
, const char * format
, ...) {
2098 pa_assert ( size
> 0 );
2101 va_start ( ap
, format
);
2102 ret
= pa_vsnprintf ( str
, size
, format
, ap
);
2108 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2109 size_t pa_vsnprintf ( char * str
, size_t size
, const char * format
, va_list ap
) {
2113 pa_assert ( size
> 0 );
2116 ret
= vsnprintf ( str
, size
, format
, ap
);
2123 if (( size_t ) ret
> size
- 1 )
2126 return ( size_t ) ret
;
2129 /* Truncate the specified string, but guarantee that the string
2130 * returned still validates as UTF8 */
2131 char * pa_truncate_utf8 ( char * c
, size_t l
) {
2133 pa_assert ( pa_utf8_valid ( c
));
2140 while ( l
> 0 && ! pa_utf8_valid ( c
))
2146 char * pa_getcwd ( void ) {
2150 char * p
= pa_xmalloc ( l
);
2154 if ( errno
!= ERANGE
)
2162 void * pa_will_need ( const void * p
, size_t l
) {
2163 #ifdef RLIMIT_MEMLOCK
2174 a
= PA_PAGE_ALIGN_PTR ( p
);
2175 size
= ( size_t ) (( const uint8_t *) p
+ l
- ( const uint8_t *) a
);
2177 #ifdef HAVE_POSIX_MADVISE
2178 if (( r
= posix_madvise (( void *) a
, size
, POSIX_MADV_WILLNEED
)) == 0 ) {
2179 pa_log_debug ( "posix_madvise() worked fine!" );
2184 /* Most likely the memory was not mmap()ed from a file and thus
2185 * madvise() didn't work, so let's misuse mlock() do page this
2186 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2187 * inviting, the man page of mlock() tells us: "All pages that
2188 * contain a part of the specified address range are guaranteed to
2189 * be resident in RAM when the call returns successfully." */
2191 #ifdef RLIMIT_MEMLOCK
2192 pa_assert_se ( getrlimit ( RLIMIT_MEMLOCK
, & rlim
) == 0 );
2194 if ( rlim
. rlim_cur
< PA_PAGE_SIZE
) {
2195 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
));
2200 bs
= PA_PAGE_ALIGN (( size_t ) rlim
. rlim_cur
);
2202 bs
= PA_PAGE_SIZE
* 4 ;
2205 pa_log_debug ( "posix_madvise() failed (or doesn't exist), trying mlock(): %s" , pa_cstrerror ( r
));
2208 while ( size
> 0 && bs
> 0 ) {
2213 if ( mlock ( a
, bs
) < 0 ) {
2214 bs
= PA_PAGE_ALIGN ( bs
/ 2 );
2218 pa_assert_se ( munlock ( a
, bs
) == 0 );
2220 a
= ( const uint8_t *) a
+ bs
;
2226 pa_log_debug ( "mlock() failed too (or doesn't exist), giving up: %s" , pa_cstrerror ( errno
));
2228 pa_log_debug ( "mlock() worked fine!" );
2233 void pa_close_pipe ( int fds
[ 2 ]) {
2237 pa_assert_se ( pa_close ( fds
[ 0 ]) == 0 );
2240 pa_assert_se ( pa_close ( fds
[ 1 ]) == 0 );
2242 fds
[ 0 ] = fds
[ 1 ] = - 1 ;
2245 char * pa_readlink ( const char * p
) {
2246 #ifdef HAVE_READLINK
2255 if (( n
= readlink ( p
, c
, l
- 1 )) < 0 ) {
2260 if (( size_t ) n
< l
- 1 ) {
2273 int pa_close_all ( int except_fd
, ...) {
2278 va_start ( ap
, except_fd
);
2281 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2286 p
= pa_xnew ( int , n
+ 1 );
2288 va_start ( ap
, except_fd
);
2291 if ( except_fd
>= 0 ) {
2295 while (( fd
= va_arg ( ap
, int )) >= 0 )
2302 r
= pa_close_allv ( p
);
2308 int pa_close_allv ( const int except_fds
[]) {
2317 if (( d
= opendir ( "/proc/self/fd" ))) {
2321 while (( de
= readdir ( d
))) {
2327 if ( de
-> d_name
[ 0 ] == '.' )
2331 l
= strtol ( de
-> d_name
, & e
, 10 );
2332 if ( errno
!= 0 || ! e
|| * e
) {
2340 if (( long ) fd
!= l
) {
2353 for ( i
= 0 ; except_fds
[ i
] >= 0 ; i
++)
2354 if ( except_fds
[ i
] == fd
) {
2362 if ( pa_close ( fd
) < 0 ) {
2363 saved_errno
= errno
;
2365 errno
= saved_errno
;
2377 if ( getrlimit ( RLIMIT_NOFILE
, & rl
) >= 0 )
2378 maxfd
= ( int ) rl
. rlim_max
;
2380 maxfd
= sysconf ( _SC_OPEN_MAX
);
2382 for ( fd
= 3 ; fd
< maxfd
; fd
++) {
2387 for ( i
= 0 ; except_fds
[ i
] >= 0 ; i
++)
2388 if ( except_fds
[ i
] == fd
) {
2396 if ( pa_close ( fd
) < 0 && errno
!= EBADF
)
2399 #endif /* !OS_IS_WIN32 */
2404 int pa_unblock_sigs ( int except
, ...) {
2409 va_start ( ap
, except
);
2412 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2417 p
= pa_xnew ( int , n
+ 1 );
2419 va_start ( ap
, except
);
2426 while (( sig
= va_arg ( ap
, int )) >= 0 )
2433 r
= pa_unblock_sigsv ( p
);
2439 int pa_unblock_sigsv ( const int except
[]) {
2444 if ( sigemptyset (& ss
) < 0 )
2447 for ( i
= 0 ; except
[ i
] > 0 ; i
++)
2448 if ( sigaddset (& ss
, except
[ i
]) < 0 )
2451 return sigprocmask ( SIG_SETMASK
, & ss
, NULL
);
2457 int pa_reset_sigs ( int except
, ...) {
2462 va_start ( ap
, except
);
2465 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2470 p
= pa_xnew ( int , n
+ 1 );
2472 va_start ( ap
, except
);
2479 while (( sig
= va_arg ( ap
, int )) >= 0 )
2486 r
= pa_reset_sigsv ( p
);
2492 int pa_reset_sigsv ( const int except
[]) {
2496 for ( sig
= 1 ; sig
< NSIG
; sig
++) {
2497 pa_bool_t reset
= TRUE
;
2508 for ( i
= 0 ; except
[ i
] > 0 ; i
++) {
2509 if ( sig
== except
[ i
]) {
2518 struct sigaction sa
;
2520 memset (& sa
, 0 , sizeof ( sa
));
2521 sa
. sa_handler
= SIG_DFL
;
2523 /* On Linux the first two RT signals are reserved by
2524 * glibc, and sigaction() will return EINVAL for them. */
2525 if (( sigaction ( sig
, & sa
, NULL
) < 0 ))
2526 if ( errno
!= EINVAL
)
2535 void pa_set_env ( const char * key
, const char * value
) {
2539 /* This is not thread-safe */
2541 setenv ( key
, value
, 1 );
2544 void pa_set_env_and_record ( const char * key
, const char * value
) {
2548 /* This is not thread-safe */
2550 pa_set_env ( key
, value
);
2551 recorded_env
= pa_strlist_prepend ( recorded_env
, key
);
2554 void pa_unset_env_recorded ( void ) {
2556 /* This is not thread-safe */
2561 recorded_env
= pa_strlist_pop ( recorded_env
, & s
);
2571 pa_bool_t
pa_in_system_mode ( void ) {
2574 if (!( e
= getenv ( "PULSE_SYSTEM" )))
2580 char * pa_get_user_name_malloc ( void ) {
2584 #ifdef _SC_LOGIN_NAME_MAX
2585 k
= ( ssize_t
) sysconf ( _SC_LOGIN_NAME_MAX
);
2591 u
= pa_xnew ( char , k
+ 1 );
2593 if (!( pa_get_user_name ( u
, k
))) {
2601 char * pa_get_host_name_malloc ( void ) {
2610 if (! pa_get_host_name ( c
, l
)) {
2612 if ( errno
!= EINVAL
&& errno
!= ENAMETOOLONG
)
2615 } else if ( strlen ( c
) < l
- 1 ) {
2623 u
= pa_utf8_filter ( c
);
2628 /* Hmm, the hostname is as long the space we offered the
2629 * function, we cannot know if it fully fit in, so let's play
2630 * safe and retry. */
2639 char * pa_machine_id ( void ) {
2643 /* The returned value is supposed be some kind of ascii identifier
2644 * that is unique and stable across reboots. */
2646 /* First we try the D-Bus UUID, which is the best option we have,
2647 * since it fits perfectly our needs and is not as volatile as the
2648 * hostname which might be set from dhcp. */
2650 if (( f
= pa_fopen_cloexec ( PA_MACHINE_ID
, "r" ))) {
2651 char ln
[ 34 ] = "" , * r
;
2653 r
= fgets ( ln
, sizeof ( ln
)- 1 , f
);
2659 return pa_utf8_filter ( ln
);
2662 if (( h
= pa_get_host_name_malloc ()))
2666 /* If no hostname was set we use the POSIX hostid. It's usually
2667 * the IPv4 address. Might not be that stable. */
2668 return pa_sprintf_malloc ( "%08lx" , ( unsigned long ) gethostid
);
2674 char * pa_session_id ( void ) {
2677 if (!( e
= getenv ( "XDG_SESSION_COOKIE" )))
2680 return pa_utf8_filter ( e
);
2683 char * pa_uname_string ( void ) {
2686 pa_assert_se ( uname (& u
) >= 0 );
2688 return pa_sprintf_malloc ( "%s %s %s %s" , u
. sysname
, u
. machine
, u
. release
, u
. version
);
2691 #ifdef HAVE_VALGRIND_MEMCHECK_H
2692 pa_bool_t
pa_in_valgrind ( void ) {
2695 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2696 * here instead of really checking whether we run in valgrind or
2700 b
= getenv ( "VALGRIND" ) ? 2 : 1 ;
2706 unsigned pa_gcd ( unsigned a
, unsigned b
) {
2717 void pa_reduce ( unsigned * num
, unsigned * den
) {
2719 unsigned gcd
= pa_gcd (* num
, * den
);
2727 pa_assert ( pa_gcd (* num
, * den
) == 1 );
2730 unsigned pa_ncpus ( void ) {
2733 #ifdef _SC_NPROCESSORS_CONF
2734 ncpus
= sysconf ( _SC_NPROCESSORS_CONF
);
2739 return ncpus
<= 0 ? 1 : ( unsigned ) ncpus
;
2742 char * pa_replace ( const char * s
, const char * a
, const char * b
) {
2751 sb
= pa_strbuf_new ();
2756 if (!( p
= strstr ( s
, a
)))
2759 pa_strbuf_putsn ( sb
, s
, p
- s
);
2760 pa_strbuf_puts ( sb
, b
);
2764 pa_strbuf_puts ( sb
, s
);
2766 return pa_strbuf_tostring_free ( sb
);
2769 char * pa_escape ( const char * p
, const char * chars
) {
2772 pa_strbuf
* buf
= pa_strbuf_new ();
2774 for ( s
= p
; * s
; ++ s
) {
2776 pa_strbuf_putc ( buf
, ' \\ ' );
2778 for ( c
= chars
; * c
; ++ c
) {
2780 pa_strbuf_putc ( buf
, ' \\ ' );
2785 pa_strbuf_putc ( buf
, * s
);
2788 return pa_strbuf_tostring_free ( buf
);
2791 char * pa_unescape ( char * p
) {
2793 pa_bool_t escaped
= FALSE
;
2795 for ( s
= p
, d
= p
; * s
; s
++) {
2796 if (! escaped
&& * s
== ' \\ ' ) {
2810 char * pa_realpath ( const char * path
) {
2814 /* We want only abolsute paths */
2815 if ( path
[ 0 ] != '/' ) {
2820 #if defined(__GLIBC__) || defined(__APPLE__)
2824 if (!( r
= realpath ( path
, NULL
)))
2827 /* We copy this here in case our pa_xmalloc() is not
2828 * implemented on top of libc malloc() */
2832 #elif defined(PATH_MAX)
2835 path_buf
= pa_xmalloc ( PATH_MAX
);
2837 if (!( t
= realpath ( path
, path_buf
))) {
2843 #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."
2849 void pa_disable_sigpipe ( void ) {
2852 struct sigaction sa
;
2856 if ( sigaction ( SIGPIPE
, NULL
, & sa
) < 0 ) {
2857 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
2861 sa
. sa_handler
= SIG_IGN
;
2863 if ( sigaction ( SIGPIPE
, & sa
, NULL
) < 0 ) {
2864 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
2870 void pa_xfreev ( void ** a
) {
2876 for ( p
= a
; * p
; p
++)
2882 char ** pa_split_spaces_strv ( const char * s
) {
2884 unsigned i
= 0 , n
= 8 ;
2885 const char * state
= NULL
;
2887 t
= pa_xnew ( char *, n
);
2888 while (( e
= pa_split_spaces ( s
, & state
))) {
2893 t
= pa_xrenew ( char *, t
, n
);
2906 char * pa_maybe_prefix_path ( const char * path
, const char * prefix
) {
2909 if ( pa_is_path_absolute ( path
))
2910 return pa_xstrdup ( path
);
2912 return pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , prefix
, path
);
2915 size_t pa_pipe_buf ( int fd
) {
2920 if (( n
= fpathconf ( fd
, _PC_PIPE_BUF
)) >= 0 )
2931 void pa_reset_personality ( void ) {
2934 if ( personality ( PER_LINUX
) < 0 )
2935 pa_log_warn ( "Uh, personality() failed: %s" , pa_cstrerror ( errno
));
2940 #if defined(__linux__) && !defined(__OPTIMIZE__)
2942 pa_bool_t
pa_run_from_build_tree ( void ) {
2944 pa_bool_t b
= FALSE
;
2946 /* We abuse __OPTIMIZE__ as a check whether we are a debug build
2949 if (( rp
= pa_readlink ( "/proc/self/exe" ))) {
2950 b
= pa_startswith ( rp
, PA_BUILDDIR
);
2959 const char * pa_get_temp_dir ( void ) {
2962 if (( t
= getenv ( "TMPDIR" )) &&
2963 pa_is_path_absolute ( t
))
2966 if (( t
= getenv ( "TMP" )) &&
2967 pa_is_path_absolute ( t
))
2970 if (( t
= getenv ( "TEMP" )) &&
2971 pa_is_path_absolute ( t
))
2974 if (( t
= getenv ( "TEMPDIR" )) &&
2975 pa_is_path_absolute ( t
))
2981 int pa_open_cloexec ( const char * fn
, int flags
, mode_t mode
) {
2989 if (( fd
= open ( fn
, flags
| O_CLOEXEC
, mode
)) >= 0 )
2992 if ( errno
!= EINVAL
)
2996 if (( fd
= open ( fn
, flags
, mode
)) < 0 )
3000 /* Some implementations might simply ignore O_CLOEXEC if it is not
3001 * understood, make sure FD_CLOEXEC is enabled anyway */
3003 pa_make_fd_cloexec ( fd
);
3007 int pa_socket_cloexec ( int domain
, int type
, int protocol
) {
3011 if (( fd
= socket ( domain
, type
| SOCK_CLOEXEC
, protocol
)) >= 0 )
3014 if ( errno
!= EINVAL
)
3018 if (( fd
= socket ( domain
, type
, protocol
)) < 0 )
3022 /* Some implementations might simply ignore SOCK_CLOEXEC if it is
3023 * not understood, make sure FD_CLOEXEC is enabled anyway */
3025 pa_make_fd_cloexec ( fd
);
3029 int pa_pipe_cloexec ( int pipefd
[ 2 ]) {
3033 if (( r
= pipe2 ( pipefd
, O_CLOEXEC
)) >= 0 )
3036 if ( errno
!= EINVAL
&& errno
!= ENOSYS
)
3041 if (( r
= pipe ( pipefd
)) < 0 )
3045 pa_make_fd_cloexec ( pipefd
[ 0 ]);
3046 pa_make_fd_cloexec ( pipefd
[ 1 ]);
3051 int pa_accept_cloexec ( int sockfd
, struct sockaddr
* addr
, socklen_t
* addrlen
) {
3055 if (( fd
= accept4 ( sockfd
, addr
, addrlen
, SOCK_CLOEXEC
)) >= 0 )
3058 if ( errno
!= EINVAL
&& errno
!= ENOSYS
)
3063 if (( fd
= accept ( sockfd
, addr
, addrlen
)) < 0 )
3067 pa_make_fd_cloexec ( fd
);
3071 FILE * pa_fopen_cloexec ( const char * path
, const char * mode
) {
3075 m
= pa_sprintf_malloc ( "%se" , mode
);
3078 if (( f
= fopen ( path
, m
))) {
3085 if ( errno
!= EINVAL
)
3088 if (!( f
= fopen ( path
, mode
)))
3092 pa_make_fd_cloexec ( fileno ( f
));
3096 void pa_nullify_stdfds ( void ) {
3099 pa_close ( STDIN_FILENO
);
3100 pa_close ( STDOUT_FILENO
);
3101 pa_close ( STDERR_FILENO
);
3103 pa_assert_se ( open ( "/dev/null" , O_RDONLY
) == STDIN_FILENO
);
3104 pa_assert_se ( open ( "/dev/null" , O_WRONLY
) == STDOUT_FILENO
);
3105 pa_assert_se ( open ( "/dev/null" , O_WRONLY
) == STDERR_FILENO
);
3112 char * pa_read_line_from_file ( const char * fn
) {
3114 char ln
[ 256 ] = "" , * r
;
3116 if (!( f
= pa_fopen_cloexec ( fn
, "r" )))
3119 r
= fgets ( ln
, sizeof ( ln
)- 1 , f
);
3128 return pa_xstrdup ( ln
);
3131 pa_bool_t
pa_running_in_vm ( void ) {
3133 #if defined(__i386__) || defined(__x86_64__)
3135 /* Both CPUID and DMI are x86 specific interfaces... */
3137 uint32_t eax
= 0x40000000 ;
3144 const char * const dmi_vendors
[] = {
3145 "/sys/class/dmi/id/sys_vendor" ,
3146 "/sys/class/dmi/id/board_vendor" ,
3147 "/sys/class/dmi/id/bios_vendor"
3152 for ( i
= 0 ; i
< PA_ELEMENTSOF ( dmi_vendors
); i
++) {
3155 if (( s
= pa_read_line_from_file ( dmi_vendors
[ i
]))) {
3157 if ( pa_startswith ( s
, "QEMU" ) ||
3158 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3159 pa_startswith ( s
, "VMware" ) ||
3160 pa_startswith ( s
, "VMW" ) ||
3161 pa_startswith ( s
, "Microsoft Corporation" ) ||
3162 pa_startswith ( s
, "innotek GmbH" ) ||
3163 pa_startswith ( s
, "Xen" )) {
3175 /* http://lwn.net/Articles/301888/ */
3178 __asm__
__volatile__ (
3179 /* ebx/rbx is being used for PIC! */
3180 " push %%" PA_REG_b
" \n\t "
3182 " mov %%ebx, %1 \n\t "
3183 " pop %%" PA_REG_b
" \n\t "
3185 : "=a" ( eax
), "=r" ( sig
. sig32
[ 0 ]), "=c" ( sig
. sig32
[ 1 ]), "=d" ( sig
. sig32
[ 2 ])
3189 if ( pa_streq ( sig
. text
, "XenVMMXenVMM" ) ||
3190 pa_streq ( sig
. text
, "KVMKVMKVM" ) ||
3191 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3192 pa_streq ( sig
. text
, "VMwareVMware" ) ||
3193 /* http://msdn.microsoft.com/en-us/library/bb969719.aspx */
3194 pa_streq ( sig
. text
, "Microsoft Hv" ))