]>
code.delx.au - pulseaudio/blob - src/pulsecore/core-util.c
d4baf6977be97cfd11f5c6e0959bdacc5bd7be38
2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2004 Joe Marcus Clarke
6 Copyright 2006-2007 Pierre Ossman <ossman@cendio.se> for Cendio AB
8 PulseAudio is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as
10 published by the Free Software Foundation; either version 2.1 of the
11 License, or (at your option) any later version.
13 PulseAudio is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with PulseAudio; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
39 #include <sys/types.h>
45 #include <sys/utsname.h>
46 #include <sys/socket.h>
55 #if defined(__linux__) && !defined(SCHED_RESET_ON_FORK)
56 #define SCHED_RESET_ON_FORK 0x40000000
60 #ifdef HAVE_SYS_RESOURCE_H
61 #include <sys/resource.h>
64 #ifdef HAVE_SYS_CAPABILITY_H
65 #include <sys/capability.h>
68 #ifdef HAVE_SYS_MMAN_H
92 #ifdef HAVE_LIBSAMPLERATE
93 #include <samplerate.h>
104 #include <pulse/xmalloc.h>
105 #include <pulse/util.h>
106 #include <pulse/utf8.h>
108 #include <pulsecore/core-error.h>
109 #include <pulsecore/winsock.h>
110 #include <pulsecore/log.h>
111 #include <pulsecore/macro.h>
112 #include <pulsecore/thread.h>
113 #include <pulsecore/strbuf.h>
115 #include "core-util.h"
117 /* Not all platforms have this */
119 #define MSG_NOSIGNAL 0
124 #define PULSE_ROOTENV "PULSE_ROOT"
126 int pa_set_root ( HANDLE handle
) {
127 char library_path
[ MAX_PATH
+ sizeof ( PULSE_ROOTENV
) + 1 ], * sep
;
129 strcpy ( library_path
, PULSE_ROOTENV
"=" );
131 /* FIXME: Needs to set errno */
133 if (! GetModuleFileName ( handle
, library_path
+ sizeof ( PULSE_ROOTENV
), MAX_PATH
))
136 sep
= strrchr ( library_path
, PA_PATH_SEP_CHAR
);
140 if ( _putenv ( library_path
) < 0 )
148 /** Make a file descriptor nonblock. Doesn't do any error checking */
149 void pa_make_fd_nonblock ( int fd
) {
155 pa_assert_se (( v
= fcntl ( fd
, F_GETFL
)) >= 0 );
157 if (!( v
& O_NONBLOCK
))
158 pa_assert_se ( fcntl ( fd
, F_SETFL
, v
| O_NONBLOCK
) >= 0 );
160 #elif defined(OS_IS_WIN32)
162 if ( ioctlsocket ( fd
, FIONBIO
, & arg
) < 0 ) {
163 pa_assert_se ( WSAGetLastError () == WSAENOTSOCK
);
164 pa_log_warn ( "Only sockets can be made non-blocking!" );
167 pa_log_warn ( "Non-blocking I/O not supported.!" );
172 /* Set the FD_CLOEXEC flag for a fd */
173 void pa_make_fd_cloexec ( int fd
) {
179 pa_assert_se (( v
= fcntl ( fd
, F_GETFD
, 0 )) >= 0 );
181 if (!( v
& FD_CLOEXEC
))
182 pa_assert_se ( fcntl ( fd
, F_SETFD
, v
| FD_CLOEXEC
) >= 0 );
187 /** Creates a directory securely */
188 int pa_make_secure_dir ( const char * dir
, mode_t m
, uid_t uid
, gid_t gid
) {
199 u
= umask ((~ m
) & 0777 );
205 if ( r
< 0 && errno
!= EEXIST
)
209 if ( uid
== ( uid_t
)- 1 )
211 if ( gid
== ( gid_t
)- 1 )
213 ( void ) chown ( dir
, uid
, gid
);
221 if ( lstat ( dir
, & st
) < 0 )
223 if ( stat ( dir
, & st
) < 0 )
228 if (! S_ISDIR ( st
. st_mode
) ||
229 ( st
. st_uid
!= uid
) ||
230 ( st
. st_gid
!= gid
) ||
231 (( st
. st_mode
& 0777 ) != m
)) {
236 pa_log_warn ( "Secure directory creation not supported on Win32." );
249 /* Return a newly allocated sting containing the parent directory of the specified file */
250 char * pa_parent_dir ( const char * fn
) {
251 char * slash
, * dir
= pa_xstrdup ( fn
);
253 if (( slash
= ( char *) pa_path_get_filename ( dir
)) == dir
) {
263 /* Creates a the parent directory of the specified path securely */
264 int pa_make_secure_parent_dir ( const char * fn
, mode_t m
, uid_t uid
, gid_t gid
) {
268 if (!( dir
= pa_parent_dir ( fn
)))
271 if ( pa_make_secure_dir ( dir
, m
, uid
, gid
) < 0 )
281 /** Platform independent read function. Necessary since not all
282 * systems treat all file descriptors equal. If type is
283 * non-NULL it is used to cache the type of the fd. This is
284 * useful for making sure that only a single syscall is executed per
285 * function call. The variable pointed to should be initialized to 0
287 ssize_t
pa_read ( int fd
, void * buf
, size_t count
, int * type
) {
291 if (! type
|| * type
== 0 ) {
294 if (( r
= recv ( fd
, buf
, count
, 0 )) >= 0 )
297 if ( WSAGetLastError () != WSAENOTSOCK
) {
298 errno
= WSAGetLastError ();
311 if (( r
= read ( fd
, buf
, count
)) < 0 )
319 /** Similar to pa_read(), but handles writes */
320 ssize_t
pa_write ( int fd
, const void * buf
, size_t count
, int * type
) {
322 if (! type
|| * type
== 0 ) {
326 if (( r
= send ( fd
, buf
, count
, MSG_NOSIGNAL
)) < 0 ) {
338 if ( WSAGetLastError () != WSAENOTSOCK
) {
339 errno
= WSAGetLastError ();
343 if ( errno
!= ENOTSOCK
)
354 if (( r
= write ( fd
, buf
, count
)) < 0 )
362 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
363 * unless EOF is reached or an error occurred */
364 ssize_t
pa_loop_read ( int fd
, void * data
, size_t size
, int * type
) {
380 if (( r
= pa_read ( fd
, data
, size
, type
)) < 0 )
387 data
= ( uint8_t *) data
+ r
;
394 /** Similar to pa_loop_read(), but wraps write() */
395 ssize_t
pa_loop_write ( int fd
, const void * data
, size_t size
, int * type
) {
411 if (( r
= pa_write ( fd
, data
, size
, type
)) < 0 )
418 data
= ( const uint8_t *) data
+ r
;
425 /** Platform independent read function. Necessary since not all
426 * systems treat all file descriptors equal. */
427 int pa_close ( int fd
) {
432 if (( ret
= closesocket ( fd
)) == 0 )
435 if ( WSAGetLastError () != WSAENOTSOCK
) {
436 errno
= WSAGetLastError ();
444 if (( r
= close ( fd
)) < 0 )
452 /* Print a warning messages in case that the given signal is not
453 * blocked or trapped */
454 void pa_check_signal_is_blocked ( int sig
) {
455 #ifdef HAVE_SIGACTION
459 /* If POSIX threads are supported use thread-aware
460 * pthread_sigmask() function, to check if the signal is
461 * blocked. Otherwise fall back to sigprocmask() */
464 if ( pthread_sigmask ( SIG_SETMASK
, NULL
, & set
) < 0 ) {
466 if ( sigprocmask ( SIG_SETMASK
, NULL
, & set
) < 0 ) {
467 pa_log ( "sigprocmask(): %s" , pa_cstrerror ( errno
));
474 if ( sigismember (& set
, sig
))
477 /* Check whether the signal is trapped */
479 if ( sigaction ( sig
, NULL
, & sa
) < 0 ) {
480 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
484 if ( sa
. sa_handler
!= SIG_DFL
)
487 pa_log_warn ( "%s is not trapped. This might cause malfunction!" , pa_sig2str ( sig
));
488 #else /* HAVE_SIGACTION */
489 pa_log_warn ( "%s might not be trapped. This might cause malfunction!" , pa_sig2str ( sig
));
493 /* The following function is based on an example from the GNU libc
494 * documentation. This function is similar to GNU's asprintf(). */
495 char * pa_sprintf_malloc ( const char * format
, ...) {
505 c
= pa_xrealloc ( c
, size
);
507 va_start ( ap
, format
);
508 r
= vsnprintf ( c
, size
, format
, ap
);
513 if ( r
> - 1 && ( size_t ) r
< size
)
516 if ( r
> - 1 ) /* glibc 2.1 */
523 /* Same as the previous function, but use a va_list instead of an
525 char * pa_vsprintf_malloc ( const char * format
, va_list ap
) {
535 c
= pa_xrealloc ( c
, size
);
538 r
= vsnprintf ( c
, size
, format
, aq
);
543 if ( r
> - 1 && ( size_t ) r
< size
)
546 if ( r
> - 1 ) /* glibc 2.1 */
553 /* Similar to OpenBSD's strlcpy() function */
554 char * pa_strlcpy ( char * b
, const char * s
, size_t l
) {
572 static int set_scheduler ( int rtprio
) {
573 struct sched_param sp
;
579 dbus_error_init (& error
);
583 sp
. sched_priority
= rtprio
;
585 #ifdef SCHED_RESET_ON_FORK
586 if (( r
= pthread_setschedparam ( pthread_self (), SCHED_RR
| SCHED_RESET_ON_FORK
, & sp
)) == 0 ) {
587 pa_log_debug ( "SCHED_RR|SCHED_RESET_ON_FORK worked." );
592 if (( r
= pthread_setschedparam ( pthread_self (), SCHED_RR
, & sp
)) == 0 ) {
593 pa_log_debug ( "SCHED_RR worked." );
598 /* Try to talk to RealtimeKit */
600 if (!( bus
= dbus_bus_get ( DBUS_BUS_SYSTEM
, & error
))) {
601 pa_log ( "Failed to connect to system bus: %s \n " , error
. message
);
602 dbus_error_free (& error
);
607 r
= rtkit_make_realtime ( bus
, 0 , rtprio
);
608 dbus_connection_unref ( bus
);
611 pa_log_debug ( "RealtimeKit worked." );
623 /* Make the current thread a realtime thread, and acquire the highest
624 * rtprio we can get that is less or equal the specified parameter. If
625 * the thread is already realtime, don't do anything. */
626 int pa_make_realtime ( int rtprio
) {
628 #ifdef _POSIX_PRIORITY_SCHEDULING
631 if ( set_scheduler ( rtprio
) >= 0 ) {
632 pa_log_info ( "Successfully enabled SCHED_RR scheduling for thread, with priority %i." , rtprio
);
636 for ( p
= rtprio
- 1 ; p
>= 1 ; p
--)
637 if ( set_scheduler ( p
)) {
638 pa_log_info ( "Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i." , p
, rtprio
);
642 pa_log_info ( "Failed to acquire real-time scheduling: %s" , pa_cstrerror ( errno
));
651 static int set_nice ( int nice_level
) {
657 dbus_error_init (& error
);
660 if ( setpriority ( PRIO_PROCESS
, 0 , nice_level
) >= 0 ) {
661 pa_log_debug ( "setpriority() worked." );
666 /* Try to talk to RealtimeKit */
668 if (!( bus
= dbus_bus_get ( DBUS_BUS_SYSTEM
, & error
))) {
669 pa_log ( "Failed to connect to system bus: %s \n " , error
. message
);
670 dbus_error_free (& error
);
675 r
= rtkit_make_high_priority ( bus
, 0 , nice_level
);
676 dbus_connection_unref ( bus
);
679 pa_log_debug ( "RealtimeKit worked." );
689 /* Raise the priority of the current process as much as possible that
690 * is <= the specified nice level..*/
691 int pa_raise_priority ( int nice_level
) {
693 #ifdef HAVE_SYS_RESOURCE_H
696 if ( set_nice ( nice_level
) >= 0 ) {
697 pa_log_info ( "Successfully gained nice level %i." , nice_level
);
701 for ( n
= nice_level
+ 1 ; n
< 0 ; n
++)
702 if ( set_nice ( n
) > 0 ) {
703 pa_log_info ( "Successfully acquired nice level %i, which is lower than the requested %i." , n
, nice_level
);
707 pa_log_info ( "Failed to acquire high-priority scheduling: %s" , pa_cstrerror ( errno
));
712 if ( nice_level
< 0 ) {
713 if (! SetPriorityClass ( GetCurrentProcess (), HIGH_PRIORITY_CLASS
)) {
714 pa_log_warn ( "SetPriorityClass() failed: 0x%08X" , GetLastError ());
719 pa_log_info ( "Successfully gained high priority class." );
726 /* Reset the priority to normal, inverting the changes made by
727 * pa_raise_priority() and pa_make_realtime()*/
728 void pa_reset_priority ( void ) {
729 #ifdef HAVE_SYS_RESOURCE_H
730 struct sched_param sp
;
732 setpriority ( PRIO_PROCESS
, 0 , 0 );
735 pthread_setschedparam ( pthread_self (), SCHED_OTHER
, & sp
);
739 SetPriorityClass ( GetCurrentProcess (), NORMAL_PRIORITY_CLASS
);
743 int pa_match ( const char * expr
, const char * v
) {
748 if ( regcomp (& re
, expr
, REG_NOSUB
| REG_EXTENDED
) != 0 ) {
753 if (( k
= regexec (& re
, v
, 0 , NULL
, 0 )) == 0 )
755 else if ( k
== REG_NOMATCH
)
768 /* Try to parse a boolean string value.*/
769 int pa_parse_boolean ( const char * v
) {
774 /* First we check language independant */
775 if (! strcmp ( v
, "1" ) || v
[ 0 ] == 'y' || v
[ 0 ] == 'Y' || v
[ 0 ] == 't' || v
[ 0 ] == 'T' || ! strcasecmp ( v
, "on" ))
777 else if (! strcmp ( v
, "0" ) || v
[ 0 ] == 'n' || v
[ 0 ] == 'N' || v
[ 0 ] == 'f' || v
[ 0 ] == 'F' || ! strcasecmp ( v
, "off" ))
780 /* And then we check language dependant */
781 if (( expr
= nl_langinfo ( YESEXPR
)))
783 if (( r
= pa_match ( expr
, v
)) > 0 )
786 if (( expr
= nl_langinfo ( NOEXPR
)))
788 if (( r
= pa_match ( expr
, v
)) > 0 )
795 /* Split the specified string wherever one of the strings in delimiter
796 * occurs. Each time it is called returns a newly allocated string
797 * with pa_xmalloc(). The variable state points to, should be
798 * initiallized to NULL before the first call. */
799 char * pa_split ( const char * c
, const char * delimiter
, const char ** state
) {
800 const char * current
= * state
? * state
: c
;
806 l
= strcspn ( current
, delimiter
);
812 return pa_xstrndup ( current
, l
);
815 /* What is interpreted as whitespace? */
816 #define WHITESPACE " \t\n "
818 /* Split a string into words. Otherwise similar to pa_split(). */
819 char * pa_split_spaces ( const char * c
, const char ** state
) {
820 const char * current
= * state
? * state
: c
;
823 if (!* current
|| * c
== 0 )
826 current
+= strspn ( current
, WHITESPACE
);
827 l
= strcspn ( current
, WHITESPACE
);
831 return pa_xstrndup ( current
, l
);
834 PA_STATIC_TLS_DECLARE ( signame
, pa_xfree
);
836 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
837 const char * pa_sig2str ( int sig
) {
850 char buf
[ SIG2STR_MAX
];
852 if ( sig2str ( sig
, buf
) == 0 ) {
853 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
854 t
= pa_sprintf_malloc ( "SIG%s" , buf
);
855 PA_STATIC_TLS_SET ( signame
, t
);
863 case SIGHUP
: return "SIGHUP" ;
865 case SIGINT
: return "SIGINT" ;
867 case SIGQUIT
: return "SIGQUIT" ;
869 case SIGILL
: return "SIGULL" ;
871 case SIGTRAP
: return "SIGTRAP" ;
873 case SIGABRT
: return "SIGABRT" ;
875 case SIGBUS
: return "SIGBUS" ;
877 case SIGFPE
: return "SIGFPE" ;
879 case SIGKILL
: return "SIGKILL" ;
882 case SIGUSR1
: return "SIGUSR1" ;
884 case SIGSEGV
: return "SIGSEGV" ;
886 case SIGUSR2
: return "SIGUSR2" ;
889 case SIGPIPE
: return "SIGPIPE" ;
892 case SIGALRM
: return "SIGALRM" ;
894 case SIGTERM
: return "SIGTERM" ;
896 case SIGSTKFLT
: return "SIGSTKFLT" ;
899 case SIGCHLD
: return "SIGCHLD" ;
902 case SIGCONT
: return "SIGCONT" ;
905 case SIGSTOP
: return "SIGSTOP" ;
908 case SIGTSTP
: return "SIGTSTP" ;
911 case SIGTTIN
: return "SIGTTIN" ;
914 case SIGTTOU
: return "SIGTTOU" ;
917 case SIGURG
: return "SIGURG" ;
920 case SIGXCPU
: return "SIGXCPU" ;
923 case SIGXFSZ
: return "SIGXFSZ" ;
926 case SIGVTALRM
: return "SIGVTALRM" ;
929 case SIGPROF
: return "SIGPROF" ;
932 case SIGWINCH
: return "SIGWINCH" ;
935 case SIGIO
: return "SIGIO" ;
938 case SIGPWR
: return "SIGPWR" ;
941 case SIGSYS
: return "SIGSYS" ;
946 if ( sig
>= SIGRTMIN
&& sig
<= SIGRTMAX
) {
947 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
948 t
= pa_sprintf_malloc ( "SIGRTMIN+%i" , sig
- SIGRTMIN
);
949 PA_STATIC_TLS_SET ( signame
, t
);
958 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
959 t
= pa_sprintf_malloc ( "SIG%i" , sig
);
960 PA_STATIC_TLS_SET ( signame
, t
);
966 /* Check whether the specified GID and the group name match */
967 static int is_group ( gid_t gid
, const char * name
) {
968 struct group group
, * result
= NULL
;
973 #ifdef HAVE_GETGRGID_R
974 #ifdef _SC_GETGR_R_SIZE_MAX
975 n
= sysconf ( _SC_GETGR_R_SIZE_MAX
);
982 data
= pa_xmalloc (( size_t ) n
);
985 if ( getgrgid_r ( gid
, & group
, data
, ( size_t ) n
, & result
) < 0 || ! result
) {
986 pa_log ( "getgrgid_r(%u): %s" , ( unsigned ) gid
, pa_cstrerror ( errno
));
994 r
= strcmp ( name
, result
-> gr_name
) == 0 ;
999 /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X) that do not
1000 * support getgrgid_r. */
1003 if (!( result
= getgrgid ( gid
))) {
1004 pa_log ( "getgrgid(%u): %s" , gid
, pa_cstrerror ( errno
));
1012 r
= strcmp ( name
, result
-> gr_name
) == 0 ;
1020 /* Check the current user is member of the specified group */
1021 int pa_own_uid_in_group ( const char * name
, gid_t
* gid
) {
1022 GETGROUPS_T
* gids
, tgid
;
1023 long n
= sysconf ( _SC_NGROUPS_MAX
);
1028 gids
= pa_xmalloc ( sizeof ( GETGROUPS_T
) * ( size_t ) n
);
1030 if (( n
= getgroups (( int ) n
, gids
)) < 0 ) {
1031 pa_log ( "getgroups(): %s" , pa_cstrerror ( errno
));
1035 for ( i
= 0 ; i
< n
; i
++) {
1037 if (( k
= is_group ( gids
[ i
], name
)) < 0 )
1046 if (( k
= is_group ( tgid
= getgid (), name
)) < 0 )
1062 /* Check whether the specifc user id is a member of the specified group */
1063 int pa_uid_in_group ( uid_t uid
, const char * name
) {
1064 char * g_buf
, * p_buf
;
1066 struct group grbuf
, * gr
;
1070 #ifdef _SC_GETGR_R_SIZE_MAX
1071 g_n
= sysconf ( _SC_GETGR_R_SIZE_MAX
);
1078 g_buf
= pa_xmalloc (( size_t ) g_n
);
1080 #ifdef _SC_GETPW_R_SIZE_MAX
1081 p_n
= sysconf ( _SC_GETPW_R_SIZE_MAX
);
1088 p_buf
= pa_xmalloc (( size_t ) p_n
);
1091 #ifdef HAVE_GETGRNAM_R
1092 if ( getgrnam_r ( name
, & grbuf
, g_buf
, ( size_t ) g_n
, & gr
) != 0 || ! gr
)
1094 if (!( gr
= getgrnam ( name
)))
1103 for ( i
= gr
-> gr_mem
; * i
; i
++) {
1104 struct passwd pwbuf
, * pw
;
1106 #ifdef HAVE_GETPWNAM_R
1107 if ( getpwnam_r (* i
, & pwbuf
, p_buf
, ( size_t ) p_n
, & pw
) != 0 || ! pw
)
1109 if (!( pw
= getpwnam (* i
)))
1113 if ( pw
-> pw_uid
== uid
) {
1126 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
1127 gid_t
pa_get_gid_of_group ( const char * name
) {
1128 gid_t ret
= ( gid_t
) - 1 ;
1131 struct group grbuf
, * gr
;
1133 #ifdef _SC_GETGR_R_SIZE_MAX
1134 g_n
= sysconf ( _SC_GETGR_R_SIZE_MAX
);
1141 g_buf
= pa_xmalloc (( size_t ) g_n
);
1144 #ifdef HAVE_GETGRNAM_R
1145 if ( getgrnam_r ( name
, & grbuf
, g_buf
, ( size_t ) g_n
, & gr
) != 0 || ! gr
)
1147 if (!( gr
= getgrnam ( name
)))
1162 int pa_check_in_group ( gid_t g
) {
1163 gid_t gids
[ NGROUPS_MAX
];
1166 if (( r
= getgroups ( NGROUPS_MAX
, gids
)) < 0 )
1176 #else /* HAVE_GRP_H */
1178 int pa_own_uid_in_group ( const char * name
, gid_t
* gid
) {
1184 int pa_uid_in_group ( uid_t uid
, const char * name
) {
1189 gid_t
pa_get_gid_of_group ( const char * name
) {
1194 int pa_check_in_group ( gid_t g
) {
1201 /* Lock or unlock a file entirely.
1202 (advisory on UNIX, mandatory on Windows) */
1203 int pa_lock_fd ( int fd
, int b
) {
1205 struct flock f_lock
;
1207 /* Try a R/W lock first */
1209 f_lock
. l_type
= ( short ) ( b
? F_WRLCK
: F_UNLCK
);
1210 f_lock
. l_whence
= SEEK_SET
;
1214 if ( fcntl ( fd
, F_SETLKW
, & f_lock
) >= 0 )
1217 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1218 if ( b
&& errno
== EBADF
) {
1219 f_lock
. l_type
= F_RDLCK
;
1220 if ( fcntl ( fd
, F_SETLKW
, & f_lock
) >= 0 )
1224 pa_log ( "%slock: %s" , ! b
? "un" : "" , pa_cstrerror ( errno
));
1228 HANDLE h
= ( HANDLE
) _get_osfhandle ( fd
);
1230 if ( b
&& LockFile ( h
, 0 , 0 , 0xFFFFFFFF , 0xFFFFFFFF ))
1232 if (! b
&& UnlockFile ( h
, 0 , 0 , 0xFFFFFFFF , 0xFFFFFFFF ))
1235 pa_log ( "%slock failed: 0x%08X" , ! b
? "un" : "" , GetLastError ());
1237 /* FIXME: Needs to set errno! */
1243 /* Remove trailing newlines from a string */
1244 char * pa_strip_nl ( char * s
) {
1247 s
[ strcspn ( s
, " \r\n " )] = 0 ;
1251 /* Create a temporary lock file and lock it. */
1252 int pa_lock_lockfile ( const char * fn
) {
1259 if (( fd
= open ( fn
, O_CREAT
| O_RDWR
1266 , S_IRUSR
| S_IWUSR
)) < 0 ) {
1267 pa_log_warn ( "Failed to create lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1271 if ( pa_lock_fd ( fd
, 1 ) < 0 ) {
1272 pa_log_warn ( "Failed to lock file '%s'." , fn
);
1276 if ( fstat ( fd
, & st
) < 0 ) {
1277 pa_log_warn ( "Failed to fstat() file '%s': %s" , fn
, pa_cstrerror ( errno
));
1281 /* Check whether the file has been removed meanwhile. When yes,
1282 * restart this loop, otherwise, we're done */
1283 if ( st
. st_nlink
>= 1 )
1286 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1287 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1291 if ( pa_close ( fd
) < 0 ) {
1292 pa_log_warn ( "Failed to close file '%s': %s" , fn
, pa_cstrerror ( errno
));
1305 int saved_errno
= errno
;
1307 errno
= saved_errno
;
1313 /* Unlock a temporary lcok file */
1314 int pa_unlock_lockfile ( const char * fn
, int fd
) {
1319 if ( unlink ( fn
) < 0 ) {
1320 pa_log_warn ( "Unable to remove lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1325 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1326 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1330 if ( pa_close ( fd
) < 0 ) {
1331 pa_log_warn ( "Failed to close '%s': %s" , fn
, pa_cstrerror ( errno
));
1338 static char * get_pulse_home ( void ) {
1343 if (!( h
= pa_get_home_dir_malloc ())) {
1344 pa_log_error ( "Failed to get home directory." );
1348 if ( stat ( h
, & st
) < 0 ) {
1349 pa_log_error ( "Failed to stat home directory %s: %s" , h
, pa_cstrerror ( errno
));
1353 if ( st
. st_uid
!= getuid ()) {
1354 pa_log_error ( "Home directory %s not ours." , h
);
1359 ret
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" , h
);
1367 char * pa_get_state_dir ( void ) {
1370 /* The state directory shall contain dynamic data that should be
1371 * kept across reboots, and is private to this user */
1373 if (!( d
= pa_xstrdup ( getenv ( "PULSE_STATE_PATH" ))))
1374 if (!( d
= get_pulse_home ()))
1377 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1378 * dir then this will break. */
1380 if ( pa_make_secure_dir ( d
, 0700U , ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1381 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1389 char * pa_get_home_dir_malloc ( void ) {
1391 size_t allocated
= 128 ;
1394 homedir
= pa_xmalloc ( allocated
);
1396 if (! pa_get_home_dir ( homedir
, allocated
)) {
1401 if ( strlen ( homedir
) < allocated
- 1 )
1411 char * pa_get_binary_name_malloc ( void ) {
1413 size_t allocated
= 128 ;
1416 t
= pa_xmalloc ( allocated
);
1418 if (! pa_get_binary_name ( t
, allocated
)) {
1423 if ( strlen ( t
) < allocated
- 1 )
1433 static char * make_random_dir ( mode_t m
) {
1434 static const char table
[] =
1435 "abcdefghijklmnopqrstuvwxyz"
1436 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1443 if (!( tmpdir
= getenv ( "TMPDIR" )))
1444 if (!( tmpdir
= getenv ( "TMP" )))
1445 if (!( tmpdir
= getenv ( "TEMP" )))
1446 tmpdir
= getenv ( "TEMPDIR" );
1448 if (! tmpdir
|| ! pa_is_path_absolute ( tmpdir
))
1451 fn
= pa_sprintf_malloc ( "%s/pulse-XXXXXXXXXXXX" , tmpdir
);
1452 pathlen
= strlen ( fn
);
1460 for ( i
= pathlen
- 12 ; i
< pathlen
; i
++)
1461 fn
[ i
] = table
[ rand () % ( sizeof ( table
)- 1 )];
1463 u
= umask ((~ m
) & 0777 );
1466 saved_errno
= errno
;
1468 errno
= saved_errno
;
1473 if ( errno
!= EEXIST
) {
1474 pa_log_error ( "Failed to create random directory %s: %s" , fn
, pa_cstrerror ( errno
));
1481 static int make_random_dir_and_link ( mode_t m
, const char * k
) {
1484 if (!( p
= make_random_dir ( m
)))
1487 if ( symlink ( p
, k
) < 0 ) {
1488 int saved_errno
= errno
;
1490 if ( errno
!= EEXIST
)
1491 pa_log_error ( "Failed to symlink %s to %s: %s" , k
, p
, pa_cstrerror ( errno
));
1496 errno
= saved_errno
;
1504 char * pa_get_runtime_dir ( void ) {
1505 char * d
, * k
= NULL
, * p
= NULL
, * t
= NULL
, * mid
;
1509 /* The runtime directory shall contain dynamic data that needs NOT
1510 * to be kept accross reboots and is usuallly private to the user,
1511 * except in system mode, where it might be accessible by other
1512 * users, too. Since we need POSIX locking and UNIX sockets in
1513 * this directory, we link it to a random subdir in /tmp, if it
1514 * was not explicitly configured. */
1516 m
= pa_in_system_mode () ? 0755U : 0700U ;
1518 if (( d
= getenv ( "PULSE_RUNTIME_PATH" ))) {
1520 if ( pa_make_secure_dir ( d
, m
, ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1521 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1525 return pa_xstrdup ( d
);
1528 if (!( d
= get_pulse_home ()))
1531 if ( pa_make_secure_dir ( d
, m
, ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1532 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1537 if (!( mid
= pa_machine_id ())) {
1542 k
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s-runtime" , d
, mid
);
1547 /* OK, first let's check if the "runtime" symlink is already
1550 if (!( p
= pa_readlink ( k
))) {
1552 if ( errno
!= ENOENT
) {
1553 pa_log_error ( "Failed to stat runtime directory %s: %s" , k
, pa_cstrerror ( errno
));
1557 /* Hmm, so the runtime directory didn't exist yet, so let's
1558 * create one in /tmp and symlink that to it */
1560 if ( make_random_dir_and_link ( 0700 , k
) < 0 ) {
1562 /* Mhmm, maybe another process was quicker than us,
1563 * let's check if that was valid */
1564 if ( errno
== EEXIST
)
1573 /* Make sure that this actually makes sense */
1574 if (! pa_is_path_absolute ( p
)) {
1575 pa_log_error ( "Path %s in link %s is not absolute." , p
, k
);
1580 /* Hmm, so this symlink is still around, make sure nobody fools
1583 if ( lstat ( p
, & st
) < 0 ) {
1585 if ( errno
!= ENOENT
) {
1586 pa_log_error ( "Failed to stat runtime directory %s: %s" , p
, pa_cstrerror ( errno
));
1592 if ( S_ISDIR ( st
. st_mode
) &&
1593 ( st
. st_uid
== getuid ()) &&
1594 (( st
. st_mode
& 0777 ) == 0700 )) {
1600 pa_log_info ( "Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory." );
1606 /* Hmm, so the link points to some nonexisting or invalid
1607 * dir. Let's replace it by a new link. We first create a
1608 * temporary link and then rename that to allow concurrent
1609 * execution of this function. */
1611 t
= pa_sprintf_malloc ( "%s.tmp" , k
);
1613 if ( make_random_dir_and_link ( 0700 , t
) < 0 ) {
1615 if ( errno
!= EEXIST
) {
1616 pa_log_error ( "Failed to symlink %s: %s" , t
, pa_cstrerror ( errno
));
1623 /* Hmm, someone lese was quicker then us. Let's give
1624 * him some time to finish, and retry. */
1629 /* OK, we succeeded in creating the temporary symlink, so
1630 * let's rename it */
1631 if ( rename ( t
, k
) < 0 ) {
1632 pa_log_error ( "Failed to rename %s to %s: %s" , t
, k
, pa_cstrerror ( errno
));
1648 /* Try to open a configuration file. If "env" is specified, open the
1649 * value of the specified environment variable. Otherwise look for a
1650 * file "local" in the home directory or a file "global" in global
1651 * file system. If "result" is non-NULL, a pointer to a newly
1652 * allocated buffer containing the used configuration file is
1654 FILE * pa_open_config_file ( const char * global
, const char * local
, const char * env
, char ** result
) {
1659 if (! getenv ( PULSE_ROOTENV
))
1663 if ( env
&& ( fn
= getenv ( env
))) {
1667 if (! ExpandEnvironmentStrings ( fn
, buf
, PATH_MAX
))
1668 /* FIXME: Needs to set errno! */
1673 if (( f
= fopen ( fn
, "r" ))) {
1675 * result
= pa_xstrdup ( fn
);
1680 pa_log_warn ( "Failed to open configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1690 if (( e
= getenv ( "PULSE_CONFIG_PATH" )))
1691 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , e
, local
);
1692 else if (( h
= pa_get_home_dir_malloc ())) {
1693 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s" , h
, local
);
1699 if (! ExpandEnvironmentStrings ( lfn
, buf
, PATH_MAX
)) {
1700 /* FIXME: Needs to set errno! */
1707 if (( f
= fopen ( fn
, "r" ))) {
1709 * result
= pa_xstrdup ( fn
);
1715 if ( errno
!= ENOENT
) {
1716 pa_log_warn ( "Failed to open configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1728 if (! ExpandEnvironmentStrings ( global
, buf
, PATH_MAX
))
1729 /* FIXME: Needs to set errno! */
1734 if (( f
= fopen ( global
, "r" ))) {
1737 * result
= pa_xstrdup ( global
);
1747 char * pa_find_config_file ( const char * global
, const char * local
, const char * env
) {
1752 if (! getenv ( PULSE_ROOTENV
))
1756 if ( env
&& ( fn
= getenv ( env
))) {
1759 if (! ExpandEnvironmentStrings ( fn
, buf
, PATH_MAX
))
1760 /* FIXME: Needs to set errno! */
1765 if ( access ( fn
, R_OK
) == 0 )
1766 return pa_xstrdup ( fn
);
1768 pa_log_warn ( "Failed to access configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1777 if (( e
= getenv ( "PULSE_CONFIG_PATH" )))
1778 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , e
, local
);
1779 else if (( h
= pa_get_home_dir_malloc ())) {
1780 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s" , h
, local
);
1786 if (! ExpandEnvironmentStrings ( lfn
, buf
, PATH_MAX
)) {
1787 /* FIXME: Needs to set errno! */
1794 if ( access ( fn
, R_OK
) == 0 ) {
1795 char * r
= pa_xstrdup ( fn
);
1800 if ( errno
!= ENOENT
) {
1801 pa_log_warn ( "Failed to access configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1811 if (! ExpandEnvironmentStrings ( global
, buf
, PATH_MAX
))
1812 /* FIXME: Needs to set errno! */
1817 if ( access ( global
, R_OK
) == 0 )
1818 return pa_xstrdup ( global
);
1826 /* Format the specified data as a hexademical string */
1827 char * pa_hexstr ( const uint8_t * d
, size_t dlength
, char * s
, size_t slength
) {
1828 size_t i
= 0 , j
= 0 ;
1829 const char hex
[] = "0123456789abcdef" ;
1833 pa_assert ( slength
> 0 );
1835 while ( i
< dlength
&& j
+ 3 <= slength
) {
1836 s
[ j
++] = hex
[* d
>> 4 ];
1837 s
[ j
++] = hex
[* d
& 0xF ];
1843 s
[ j
< slength
? j
: slength
] = 0 ;
1847 /* Convert a hexadecimal digit to a number or -1 if invalid */
1848 static int hexc ( char c
) {
1849 if ( c
>= '0' && c
<= '9' )
1852 if ( c
>= 'A' && c
<= 'F' )
1853 return c
- 'A' + 10 ;
1855 if ( c
>= 'a' && c
<= 'f' )
1856 return c
- 'a' + 10 ;
1862 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1863 size_t pa_parsehex ( const char * p
, uint8_t * d
, size_t dlength
) {
1869 while ( j
< dlength
&& * p
) {
1872 if (( b
= hexc (*( p
++))) < 0 )
1875 d
[ j
] = ( uint8_t ) ( b
<< 4 );
1880 if (( b
= hexc (*( p
++))) < 0 )
1883 d
[ j
] |= ( uint8_t ) b
;
1890 /* Returns nonzero when *s starts with *pfx */
1891 pa_bool_t
pa_startswith ( const char * s
, const char * pfx
) {
1899 return strlen ( s
) >= l
&& strncmp ( s
, pfx
, l
) == 0 ;
1902 /* Returns nonzero when *s ends with *sfx */
1903 pa_bool_t
pa_endswith ( const char * s
, const char * sfx
) {
1912 return l1
>= l2
&& strcmp ( s
+ l1
- l2
, sfx
) == 0 ;
1915 pa_bool_t
pa_is_path_absolute ( const char * fn
) {
1921 return strlen ( fn
) >= 3 && isalpha ( fn
[ 0 ]) && fn
[ 1 ] == ':' && fn
[ 2 ] == ' \\ ' ;
1925 char * pa_make_path_absolute ( const char * p
) {
1931 if ( pa_is_path_absolute ( p
))
1932 return pa_xstrdup ( p
);
1934 if (!( cwd
= pa_getcwd ()))
1935 return pa_xstrdup ( p
);
1937 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , cwd
, p
);
1942 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1943 * if fn is non-null and starts with / return fn
1944 * otherwise append fn to the run time path and return it */
1945 static char * get_path ( const char * fn
, pa_bool_t prependmid
, pa_bool_t rt
) {
1948 if ( pa_is_path_absolute ( fn
))
1949 return pa_xstrdup ( fn
);
1951 rtp
= rt
? pa_get_runtime_dir () : pa_get_state_dir ();
1962 if (!( mid
= pa_machine_id ())) {
1967 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s-%s" , rtp
, mid
, fn
);
1970 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , rtp
, fn
);
1978 char * pa_runtime_path ( const char * fn
) {
1979 return get_path ( fn
, FALSE
, TRUE
);
1982 char * pa_state_path ( const char * fn
, pa_bool_t appendmid
) {
1983 return get_path ( fn
, appendmid
, FALSE
);
1986 /* Convert the string s to a signed integer in *ret_i */
1987 int pa_atoi ( const char * s
, int32_t * ret_i
) {
1995 l
= strtol ( s
, & x
, 0 );
1997 if (! x
|| * x
|| errno
) {
2003 if (( int32_t ) l
!= l
) {
2008 * ret_i
= ( int32_t ) l
;
2013 /* Convert the string s to an unsigned integer in *ret_u */
2014 int pa_atou ( const char * s
, uint32_t * ret_u
) {
2022 l
= strtoul ( s
, & x
, 0 );
2024 if (! x
|| * x
|| errno
) {
2030 if (( uint32_t ) l
!= l
) {
2035 * ret_u
= ( uint32_t ) l
;
2040 #ifdef HAVE_STRTOF_L
2041 static locale_t c_locale
= NULL
;
2043 static void c_locale_destroy ( void ) {
2044 freelocale ( c_locale
);
2048 int pa_atod ( const char * s
, double * ret_d
) {
2055 /* This should be locale independent */
2057 #ifdef HAVE_STRTOF_L
2061 if (( c_locale
= newlocale ( LC_ALL_MASK
, "C" , NULL
)))
2062 atexit ( c_locale_destroy
);
2068 f
= strtod_l ( s
, & x
, c_locale
);
2076 if (! x
|| * x
|| errno
) {
2087 /* Same as snprintf, but guarantees NUL-termination on every platform */
2088 size_t pa_snprintf ( char * str
, size_t size
, const char * format
, ...) {
2093 pa_assert ( size
> 0 );
2096 va_start ( ap
, format
);
2097 ret
= pa_vsnprintf ( str
, size
, format
, ap
);
2103 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2104 size_t pa_vsnprintf ( char * str
, size_t size
, const char * format
, va_list ap
) {
2108 pa_assert ( size
> 0 );
2111 ret
= vsnprintf ( str
, size
, format
, ap
);
2118 if (( size_t ) ret
> size
- 1 )
2121 return ( size_t ) ret
;
2124 /* Truncate the specified string, but guarantee that the string
2125 * returned still validates as UTF8 */
2126 char * pa_truncate_utf8 ( char * c
, size_t l
) {
2128 pa_assert ( pa_utf8_valid ( c
));
2135 while ( l
> 0 && ! pa_utf8_valid ( c
))
2141 char * pa_getcwd ( void ) {
2145 char * p
= pa_xmalloc ( l
);
2149 if ( errno
!= ERANGE
)
2157 void * pa_will_need ( const void * p
, size_t l
) {
2158 #ifdef RLIMIT_MEMLOCK
2169 a
= PA_PAGE_ALIGN_PTR ( p
);
2170 size
= ( size_t ) (( const uint8_t *) p
+ l
- ( const uint8_t *) a
);
2172 #ifdef HAVE_POSIX_MADVISE
2173 if (( r
= posix_madvise (( void *) a
, size
, POSIX_MADV_WILLNEED
)) == 0 ) {
2174 pa_log_debug ( "posix_madvise() worked fine!" );
2179 /* Most likely the memory was not mmap()ed from a file and thus
2180 * madvise() didn't work, so let's misuse mlock() do page this
2181 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2182 * inviting, the man page of mlock() tells us: "All pages that
2183 * contain a part of the specified address range are guaranteed to
2184 * be resident in RAM when the call returns successfully." */
2186 #ifdef RLIMIT_MEMLOCK
2187 pa_assert_se ( getrlimit ( RLIMIT_MEMLOCK
, & rlim
) == 0 );
2189 if ( rlim
. rlim_cur
< PA_PAGE_SIZE
) {
2190 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
));
2195 bs
= PA_PAGE_ALIGN (( size_t ) rlim
. rlim_cur
);
2197 bs
= PA_PAGE_SIZE
* 4 ;
2200 pa_log_debug ( "posix_madvise() failed (or doesn't exist), trying mlock(): %s" , pa_cstrerror ( r
));
2203 while ( size
> 0 && bs
> 0 ) {
2208 if ( mlock ( a
, bs
) < 0 ) {
2209 bs
= PA_PAGE_ALIGN ( bs
/ 2 );
2213 pa_assert_se ( munlock ( a
, bs
) == 0 );
2215 a
= ( const uint8_t *) a
+ bs
;
2221 pa_log_debug ( "mlock() failed too (or doesn't exist), giving up: %s" , pa_cstrerror ( errno
));
2223 pa_log_debug ( "mlock() worked fine!" );
2228 void pa_close_pipe ( int fds
[ 2 ]) {
2232 pa_assert_se ( pa_close ( fds
[ 0 ]) == 0 );
2235 pa_assert_se ( pa_close ( fds
[ 1 ]) == 0 );
2237 fds
[ 0 ] = fds
[ 1 ] = - 1 ;
2240 char * pa_readlink ( const char * p
) {
2249 if (( n
= readlink ( p
, c
, l
- 1 )) < 0 ) {
2254 if (( size_t ) n
< l
- 1 ) {
2264 int pa_close_all ( int except_fd
, ...) {
2269 va_start ( ap
, except_fd
);
2272 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2277 p
= pa_xnew ( int , n
+ 1 );
2279 va_start ( ap
, except_fd
);
2282 if ( except_fd
>= 0 ) {
2286 while (( fd
= va_arg ( ap
, int )) >= 0 )
2293 r
= pa_close_allv ( p
);
2299 int pa_close_allv ( const int except_fds
[]) {
2307 if (( d
= opendir ( "/proc/self/fd" ))) {
2311 while (( de
= readdir ( d
))) {
2317 if ( de
-> d_name
[ 0 ] == '.' )
2321 l
= strtol ( de
-> d_name
, & e
, 10 );
2322 if ( errno
!= 0 || ! e
|| * e
) {
2330 if (( long ) fd
!= l
) {
2343 for ( i
= 0 ; except_fds
[ i
] >= 0 ; i
++)
2344 if ( except_fds
[ i
] == fd
) {
2352 if ( pa_close ( fd
) < 0 ) {
2353 saved_errno
= errno
;
2355 errno
= saved_errno
;
2367 if ( getrlimit ( RLIMIT_NOFILE
, & rl
) >= 0 )
2368 maxfd
= ( int ) rl
. rlim_max
;
2370 maxfd
= sysconf ( _SC_OPEN_MAX
);
2372 for ( fd
= 3 ; fd
< maxfd
; fd
++) {
2377 for ( i
= 0 ; except_fds
[ i
] >= 0 ; i
++)
2378 if ( except_fds
[ i
] == fd
) {
2386 if ( pa_close ( fd
) < 0 && errno
!= EBADF
)
2393 int pa_unblock_sigs ( int except
, ...) {
2398 va_start ( ap
, except
);
2401 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2406 p
= pa_xnew ( int , n
+ 1 );
2408 va_start ( ap
, except
);
2415 while (( sig
= va_arg ( ap
, int )) >= 0 )
2422 r
= pa_unblock_sigsv ( p
);
2428 int pa_unblock_sigsv ( const int except
[]) {
2432 if ( sigemptyset (& ss
) < 0 )
2435 for ( i
= 0 ; except
[ i
] > 0 ; i
++)
2436 if ( sigaddset (& ss
, except
[ i
]) < 0 )
2439 return sigprocmask ( SIG_SETMASK
, & ss
, NULL
);
2442 int pa_reset_sigs ( int except
, ...) {
2447 va_start ( ap
, except
);
2450 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2455 p
= pa_xnew ( int , n
+ 1 );
2457 va_start ( ap
, except
);
2464 while (( sig
= va_arg ( ap
, int )) >= 0 )
2471 r
= pa_reset_sigsv ( p
);
2477 int pa_reset_sigsv ( const int except
[]) {
2480 for ( sig
= 1 ; sig
< NSIG
; sig
++) {
2481 pa_bool_t reset
= TRUE
;
2492 for ( i
= 0 ; except
[ i
] > 0 ; i
++) {
2493 if ( sig
== except
[ i
]) {
2502 struct sigaction sa
;
2504 memset (& sa
, 0 , sizeof ( sa
));
2505 sa
. sa_handler
= SIG_DFL
;
2507 /* On Linux the first two RT signals are reserved by
2508 * glibc, and sigaction() will return EINVAL for them. */
2509 if (( sigaction ( sig
, & sa
, NULL
) < 0 ))
2510 if ( errno
!= EINVAL
)
2518 void pa_set_env ( const char * key
, const char * value
) {
2522 putenv ( pa_sprintf_malloc ( "%s=%s" , key
, value
));
2525 pa_bool_t
pa_in_system_mode ( void ) {
2528 if (!( e
= getenv ( "PULSE_SYSTEM" )))
2534 char * pa_get_user_name_malloc ( void ) {
2538 #ifdef _SC_LOGIN_NAME_MAX
2539 k
= ( ssize_t
) sysconf ( _SC_LOGIN_NAME_MAX
);
2545 u
= pa_xnew ( char , k
+ 1 );
2547 if (!( pa_get_user_name ( u
, k
))) {
2555 char * pa_get_host_name_malloc ( void ) {
2564 if (! pa_get_host_name ( c
, l
)) {
2566 if ( errno
!= EINVAL
&& errno
!= ENAMETOOLONG
)
2569 } else if ( strlen ( c
) < l
- 1 ) {
2577 u
= pa_utf8_filter ( c
);
2582 /* Hmm, the hostname is as long the space we offered the
2583 * function, we cannot know if it fully fit in, so let's play
2584 * safe and retry. */
2593 char * pa_machine_id ( void ) {
2597 /* The returned value is supposed be some kind of ascii identifier
2598 * that is unique and stable across reboots. */
2600 /* First we try the D-Bus UUID, which is the best option we have,
2601 * since it fits perfectly our needs and is not as volatile as the
2602 * hostname which might be set from dhcp. */
2604 if (( f
= fopen ( PA_MACHINE_ID
, "r" ))) {
2605 char ln
[ 34 ] = "" , * r
;
2607 r
= fgets ( ln
, sizeof ( ln
)- 1 , f
);
2613 return pa_utf8_filter ( ln
);
2616 if (( h
= pa_get_host_name_malloc ()))
2619 /* If no hostname was set we use the POSIX hostid. It's usually
2620 * the IPv4 address. Might not be that stable. */
2621 return pa_sprintf_malloc ( "%08lx" , ( unsigned long ) gethostid
);
2624 char * pa_session_id ( void ) {
2627 if (!( e
= getenv ( "XDG_SESSION_COOKIE" )))
2630 return pa_utf8_filter ( e
);
2633 char * pa_uname_string ( void ) {
2636 pa_assert_se ( uname (& u
) >= 0 );
2638 return pa_sprintf_malloc ( "%s %s %s %s" , u
. sysname
, u
. machine
, u
. release
, u
. version
);
2641 #ifdef HAVE_VALGRIND_MEMCHECK_H
2642 pa_bool_t
pa_in_valgrind ( void ) {
2645 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2646 * here instead of really checking whether we run in valgrind or
2650 b
= getenv ( "VALGRIND" ) ? 2 : 1 ;
2656 unsigned pa_gcd ( unsigned a
, unsigned b
) {
2667 void pa_reduce ( unsigned * num
, unsigned * den
) {
2669 unsigned gcd
= pa_gcd (* num
, * den
);
2677 pa_assert ( pa_gcd (* num
, * den
) == 1 );
2680 unsigned pa_ncpus ( void ) {
2683 #ifdef _SC_NPROCESSORS_CONF
2684 ncpus
= sysconf ( _SC_NPROCESSORS_CONF
);
2689 return ncpus
<= 0 ? 1 : ( unsigned ) ncpus
;
2692 char * pa_replace ( const char * s
, const char * a
, const char * b
) {
2701 sb
= pa_strbuf_new ();
2706 if (!( p
= strstr ( s
, a
)))
2709 pa_strbuf_putsn ( sb
, s
, p
- s
);
2710 pa_strbuf_puts ( sb
, b
);
2714 pa_strbuf_puts ( sb
, s
);
2716 return pa_strbuf_tostring_free ( sb
);
2719 char * pa_unescape ( char * p
) {
2721 pa_bool_t escaped
= FALSE
;
2723 for ( s
= p
, d
= p
; * s
; s
++) {
2724 if (! escaped
&& * s
== ' \\ ' ) {
2738 char * pa_realpath ( const char * path
) {
2742 /* We want only abolsute paths */
2743 if ( path
[ 0 ] != '/' ) {
2748 #if defined(__GLIBC__) || defined(__APPLE__)
2752 if (!( r
= realpath ( path
, NULL
)))
2755 /* We copy this here in case our pa_xmalloc() is not
2756 * implemented on top of libc malloc() */
2760 #elif defined(PATH_MAX)
2763 path_buf
= pa_xmalloc ( PATH_MAX
);
2765 if (!( t
= realpath ( path
, path_buf
))) {
2771 #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."
2777 void pa_disable_sigpipe ( void ) {
2780 struct sigaction sa
;
2784 if ( sigaction ( SIGPIPE
, NULL
, & sa
) < 0 ) {
2785 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
2789 sa
. sa_handler
= SIG_IGN
;
2791 if ( sigaction ( SIGPIPE
, & sa
, NULL
) < 0 ) {
2792 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
2798 void pa_xfreev ( void ** a
) {
2804 for ( p
= a
; * p
; p
++)
2810 char ** pa_split_spaces_strv ( const char * s
) {
2812 unsigned i
= 0 , n
= 8 ;
2813 const char * state
= NULL
;
2815 t
= pa_xnew ( char *, n
);
2816 while (( e
= pa_split_spaces ( s
, & state
))) {
2821 t
= pa_xrenew ( char *, t
, n
);
2834 char * pa_maybe_prefix_path ( const char * path
, const char * prefix
) {
2837 if ( pa_is_path_absolute ( path
))
2838 return pa_xstrdup ( path
);
2840 return pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , prefix
, path
);
2843 size_t pa_pipe_buf ( int fd
) {
2848 if (( n
= fpathconf ( fd
, _PC_PIPE_BUF
)) >= 0 )