]>
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>
54 #ifdef HAVE_SYS_RESOURCE_H
55 #include <sys/resource.h>
58 #ifdef HAVE_SYS_CAPABILITY_H
59 #include <sys/capability.h>
62 #ifdef HAVE_SYS_MMAN_H
86 #ifdef HAVE_LIBSAMPLERATE
87 #include <samplerate.h>
90 #include <pulse/xmalloc.h>
91 #include <pulse/util.h>
92 #include <pulse/utf8.h>
94 #include <pulsecore/core-error.h>
95 #include <pulsecore/winsock.h>
96 #include <pulsecore/log.h>
97 #include <pulsecore/macro.h>
98 #include <pulsecore/thread.h>
100 #include "core-util.h"
102 /* Not all platforms have this */
104 #define MSG_NOSIGNAL 0
109 #define PULSE_ROOTENV "PULSE_ROOT"
111 int pa_set_root ( HANDLE handle
) {
112 char library_path
[ MAX_PATH
+ sizeof ( PULSE_ROOTENV
) + 1 ], * sep
;
114 strcpy ( library_path
, PULSE_ROOTENV
"=" );
116 /* FIXME: Needs to set errno */
118 if (! GetModuleFileName ( handle
, library_path
+ sizeof ( PULSE_ROOTENV
), MAX_PATH
))
121 sep
= strrchr ( library_path
, PA_PATH_SEP_CHAR
);
125 if ( _putenv ( library_path
) < 0 )
133 /** Make a file descriptor nonblock. Doesn't do any error checking */
134 void pa_make_fd_nonblock ( int fd
) {
140 pa_assert_se (( v
= fcntl ( fd
, F_GETFL
)) >= 0 );
142 if (!( v
& O_NONBLOCK
))
143 pa_assert_se ( fcntl ( fd
, F_SETFL
, v
| O_NONBLOCK
) >= 0 );
145 #elif defined(OS_IS_WIN32)
147 if ( ioctlsocket ( fd
, FIONBIO
, & arg
) < 0 ) {
148 pa_assert_se ( WSAGetLastError () == WSAENOTSOCK
);
149 pa_log_warn ( "Only sockets can be made non-blocking!" );
152 pa_log_warn ( "Non-blocking I/O not supported.!" );
157 /* Set the FD_CLOEXEC flag for a fd */
158 void pa_make_fd_cloexec ( int fd
) {
164 pa_assert_se (( v
= fcntl ( fd
, F_GETFD
, 0 )) >= 0 );
166 if (!( v
& FD_CLOEXEC
))
167 pa_assert_se ( fcntl ( fd
, F_SETFD
, v
| FD_CLOEXEC
) >= 0 );
172 /** Creates a directory securely */
173 int pa_make_secure_dir ( const char * dir
, mode_t m
, uid_t uid
, gid_t gid
) {
184 u
= umask ((~ m
) & 0777 );
190 if ( r
< 0 && errno
!= EEXIST
)
194 if ( uid
== ( uid_t
)- 1 )
196 if ( gid
== ( gid_t
)- 1 )
198 ( void ) chown ( dir
, uid
, gid
);
206 if ( lstat ( dir
, & st
) < 0 )
208 if ( stat ( dir
, & st
) < 0 )
213 if (! S_ISDIR ( st
. st_mode
) ||
214 ( st
. st_uid
!= uid
) ||
215 ( st
. st_gid
!= gid
) ||
216 (( st
. st_mode
& 0777 ) != m
)) {
221 pa_log_warn ( "Secure directory creation not supported on Win32." );
234 /* Return a newly allocated sting containing the parent directory of the specified file */
235 char * pa_parent_dir ( const char * fn
) {
236 char * slash
, * dir
= pa_xstrdup ( fn
);
238 if (( slash
= ( char *) pa_path_get_filename ( dir
)) == dir
) {
248 /* Creates a the parent directory of the specified path securely */
249 int pa_make_secure_parent_dir ( const char * fn
, mode_t m
, uid_t uid
, gid_t gid
) {
253 if (!( dir
= pa_parent_dir ( fn
)))
256 if ( pa_make_secure_dir ( dir
, m
, uid
, gid
) < 0 )
266 /** Platform independent read function. Necessary since not all
267 * systems treat all file descriptors equal. If type is
268 * non-NULL it is used to cache the type of the fd. This is
269 * useful for making sure that only a single syscall is executed per
270 * function call. The variable pointed to should be initialized to 0
272 ssize_t
pa_read ( int fd
, void * buf
, size_t count
, int * type
) {
276 if (! type
|| * type
== 0 ) {
279 if (( r
= recv ( fd
, buf
, count
, 0 )) >= 0 )
282 if ( WSAGetLastError () != WSAENOTSOCK
) {
283 errno
= WSAGetLastError ();
293 return read ( fd
, buf
, count
);
296 /** Similar to pa_read(), but handles writes */
297 ssize_t
pa_write ( int fd
, const void * buf
, size_t count
, int * type
) {
299 if (! type
|| * type
== 0 ) {
302 if (( r
= send ( fd
, buf
, count
, MSG_NOSIGNAL
)) >= 0 )
306 if ( WSAGetLastError () != WSAENOTSOCK
) {
307 errno
= WSAGetLastError ();
311 if ( errno
!= ENOTSOCK
)
319 return write ( fd
, buf
, count
);
322 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
323 * unless EOF is reached or an error occured */
324 ssize_t
pa_loop_read ( int fd
, void * data
, size_t size
, int * type
) {
340 if (( r
= pa_read ( fd
, data
, size
, type
)) < 0 )
347 data
= ( uint8_t *) data
+ r
;
354 /** Similar to pa_loop_read(), but wraps write() */
355 ssize_t
pa_loop_write ( int fd
, const void * data
, size_t size
, int * type
) {
371 if (( r
= pa_write ( fd
, data
, size
, type
)) < 0 )
378 data
= ( const uint8_t *) data
+ r
;
385 /** Platform independent read function. Necessary since not all
386 * systems treat all file descriptors equal. */
387 int pa_close ( int fd
) {
392 if (( ret
= closesocket ( fd
)) == 0 )
395 if ( WSAGetLastError () != WSAENOTSOCK
) {
396 errno
= WSAGetLastError ();
404 if (( r
= close ( fd
)) >= 0 )
412 /* Print a warning messages in case that the given signal is not
413 * blocked or trapped */
414 void pa_check_signal_is_blocked ( int sig
) {
415 #ifdef HAVE_SIGACTION
419 /* If POSIX threads are supported use thread-aware
420 * pthread_sigmask() function, to check if the signal is
421 * blocked. Otherwise fall back to sigprocmask() */
424 if ( pthread_sigmask ( SIG_SETMASK
, NULL
, & set
) < 0 ) {
426 if ( sigprocmask ( SIG_SETMASK
, NULL
, & set
) < 0 ) {
427 pa_log ( "sigprocmask(): %s" , pa_cstrerror ( errno
));
434 if ( sigismember (& set
, sig
))
437 /* Check whether the signal is trapped */
439 if ( sigaction ( sig
, NULL
, & sa
) < 0 ) {
440 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
444 if ( sa
. sa_handler
!= SIG_DFL
)
447 pa_log_warn ( "%s is not trapped. This might cause malfunction!" , pa_sig2str ( sig
));
448 #else /* HAVE_SIGACTION */
449 pa_log_warn ( "%s might not be trapped. This might cause malfunction!" , pa_sig2str ( sig
));
453 /* The following function is based on an example from the GNU libc
454 * documentation. This function is similar to GNU's asprintf(). */
455 char * pa_sprintf_malloc ( const char * format
, ...) {
465 c
= pa_xrealloc ( c
, size
);
467 va_start ( ap
, format
);
468 r
= vsnprintf ( c
, size
, format
, ap
);
473 if ( r
> - 1 && ( size_t ) r
< size
)
476 if ( r
> - 1 ) /* glibc 2.1 */
483 /* Same as the previous function, but use a va_list instead of an
485 char * pa_vsprintf_malloc ( const char * format
, va_list ap
) {
495 c
= pa_xrealloc ( c
, size
);
498 r
= vsnprintf ( c
, size
, format
, aq
);
503 if ( r
> - 1 && ( size_t ) r
< size
)
506 if ( r
> - 1 ) /* glibc 2.1 */
513 /* Similar to OpenBSD's strlcpy() function */
514 char * pa_strlcpy ( char * b
, const char * s
, size_t l
) {
524 /* Make the current thread a realtime thread, and acquire the highest
525 * rtprio we can get that is less or equal the specified parameter. If
526 * the thread is already realtime, don't do anything. */
527 int pa_make_realtime ( int rtprio
) {
529 #ifdef _POSIX_PRIORITY_SCHEDULING
530 struct sched_param sp
;
533 memset (& sp
, 0 , sizeof ( sp
));
536 if (( r
= pthread_getschedparam ( pthread_self (), & policy
, & sp
)) != 0 ) {
537 pa_log ( "pthread_getschedgetparam(): %s" , pa_cstrerror ( r
));
541 if ( policy
== SCHED_FIFO
&& sp
. sched_priority
>= rtprio
) {
542 pa_log_info ( "Thread already being scheduled with SCHED_FIFO with priority %i." , sp
. sched_priority
);
546 sp
. sched_priority
= rtprio
;
547 if (( r
= pthread_setschedparam ( pthread_self (), SCHED_FIFO
, & sp
)) != 0 ) {
549 while ( sp
. sched_priority
> 1 ) {
550 sp
. sched_priority
--;
552 if (( r
= pthread_setschedparam ( pthread_self (), SCHED_FIFO
, & sp
)) == 0 ) {
553 pa_log_info ( "Successfully enabled SCHED_FIFO scheduling for thread, with priority %i, which is lower than the requested %i." , sp
. sched_priority
, rtprio
);
558 pa_log_warn ( "pthread_setschedparam(): %s" , pa_cstrerror ( r
));
562 pa_log_info ( "Successfully enabled SCHED_FIFO scheduling for thread, with priority %i." , sp
. sched_priority
);
571 /* This is merely used for giving the user a hint. This is not correct
572 * for anything security related */
573 pa_bool_t
pa_can_realtime ( void ) {
578 #if defined(HAVE_SYS_RESOURCE_H) && defined(RLIMIT_RTPRIO)
582 if ( getrlimit ( RLIMIT_RTPRIO
, & rl
) >= 0 )
583 if ( rl
. rlim_cur
> 0 || rl
. rlim_cur
== RLIM_INFINITY
)
588 #if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_SYS_NICE)
592 if (( cap
= cap_get_proc ())) {
593 cap_flag_value_t flag
= CAP_CLEAR
;
595 if ( cap_get_flag ( cap
, CAP_SYS_NICE
, CAP_EFFECTIVE
, & flag
) >= 0 )
596 if ( flag
== CAP_SET
) {
609 /* This is merely used for giving the user a hint. This is not correct
610 * for anything security related */
611 pa_bool_t
pa_can_high_priority ( void ) {
616 #if defined(HAVE_SYS_RESOURCE_H) && defined(RLIMIT_RTPRIO)
620 if ( getrlimit ( RLIMIT_NICE
, & rl
) >= 0 )
621 if ( rl
. rlim_cur
>= 21 || rl
. rlim_cur
== RLIM_INFINITY
)
626 #if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_SYS_NICE)
630 if (( cap
= cap_get_proc ())) {
631 cap_flag_value_t flag
= CAP_CLEAR
;
633 if ( cap_get_flag ( cap
, CAP_SYS_NICE
, CAP_EFFECTIVE
, & flag
) >= 0 )
634 if ( flag
== CAP_SET
) {
647 /* Raise the priority of the current process as much as possible that
648 * is <= the specified nice level..*/
649 int pa_raise_priority ( int nice_level
) {
651 #ifdef HAVE_SYS_RESOURCE_H
652 if ( setpriority ( PRIO_PROCESS
, 0 , nice_level
) < 0 ) {
655 for ( n
= nice_level
+ 1 ; n
< 0 ; n
++) {
657 if ( setpriority ( PRIO_PROCESS
, 0 , n
) == 0 ) {
658 pa_log_info ( "Successfully acquired nice level %i, which is lower than the requested %i." , n
, nice_level
);
663 pa_log_warn ( "setpriority(): %s" , pa_cstrerror ( errno
));
667 pa_log_info ( "Successfully gained nice level %i." , nice_level
);
671 if ( nice_level
< 0 ) {
672 if (! SetPriorityClass ( GetCurrentProcess (), HIGH_PRIORITY_CLASS
)) {
673 pa_log_warn ( "SetPriorityClass() failed: 0x%08X" , GetLastError ());
677 pa_log_info ( "Successfully gained high priority class." );
684 /* Reset the priority to normal, inverting the changes made by
685 * pa_raise_priority() and pa_make_realtime()*/
686 void pa_reset_priority ( void ) {
687 #ifdef HAVE_SYS_RESOURCE_H
688 struct sched_param sp
;
690 setpriority ( PRIO_PROCESS
, 0 , 0 );
692 memset (& sp
, 0 , sizeof ( sp
));
693 pa_assert_se ( pthread_setschedparam ( pthread_self (), SCHED_OTHER
, & sp
) == 0 );
697 SetPriorityClass ( GetCurrentProcess (), NORMAL_PRIORITY_CLASS
);
701 static int match ( const char * expr
, const char * v
) {
706 if ( regcomp (& re
, expr
, REG_NOSUB
| REG_EXTENDED
) != 0 ) {
711 if (( k
= regexec (& re
, v
, 0 , NULL
, 0 )) == 0 )
713 else if ( k
== REG_NOMATCH
)
726 /* Try to parse a boolean string value.*/
727 int pa_parse_boolean ( const char * v
) {
732 /* First we check language independant */
733 if (! strcmp ( v
, "1" ) || v
[ 0 ] == 'y' || v
[ 0 ] == 'Y' || v
[ 0 ] == 't' || v
[ 0 ] == 'T' || ! strcasecmp ( v
, "on" ))
735 else if (! strcmp ( v
, "0" ) || v
[ 0 ] == 'n' || v
[ 0 ] == 'N' || v
[ 0 ] == 'f' || v
[ 0 ] == 'F' || ! strcasecmp ( v
, "off" ))
738 /* And then we check language dependant */
739 if (( expr
= nl_langinfo ( YESEXPR
)))
741 if (( r
= match ( expr
, v
)) > 0 )
744 if (( expr
= nl_langinfo ( NOEXPR
)))
746 if (( r
= match ( expr
, v
)) > 0 )
753 /* Split the specified string wherever one of the strings in delimiter
754 * occurs. Each time it is called returns a newly allocated string
755 * with pa_xmalloc(). The variable state points to, should be
756 * initiallized to NULL before the first call. */
757 char * pa_split ( const char * c
, const char * delimiter
, const char ** state
) {
758 const char * current
= * state
? * state
: c
;
764 l
= strcspn ( current
, delimiter
);
770 return pa_xstrndup ( current
, l
);
773 /* What is interpreted as whitespace? */
774 #define WHITESPACE " \t\n "
776 /* Split a string into words. Otherwise similar to pa_split(). */
777 char * pa_split_spaces ( const char * c
, const char ** state
) {
778 const char * current
= * state
? * state
: c
;
781 if (!* current
|| * c
== 0 )
784 current
+= strspn ( current
, WHITESPACE
);
785 l
= strcspn ( current
, WHITESPACE
);
789 return pa_xstrndup ( current
, l
);
792 PA_STATIC_TLS_DECLARE ( signame
, pa_xfree
);
794 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
795 const char * pa_sig2str ( int sig
) {
808 char buf
[ SIG2STR_MAX
];
810 if ( sig2str ( sig
, buf
) == 0 ) {
811 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
812 t
= pa_sprintf_malloc ( "SIG%s" , buf
);
813 PA_STATIC_TLS_SET ( signame
, t
);
821 case SIGHUP
: return "SIGHUP" ;
823 case SIGINT
: return "SIGINT" ;
825 case SIGQUIT
: return "SIGQUIT" ;
827 case SIGILL
: return "SIGULL" ;
829 case SIGTRAP
: return "SIGTRAP" ;
831 case SIGABRT
: return "SIGABRT" ;
833 case SIGBUS
: return "SIGBUS" ;
835 case SIGFPE
: return "SIGFPE" ;
837 case SIGKILL
: return "SIGKILL" ;
840 case SIGUSR1
: return "SIGUSR1" ;
842 case SIGSEGV
: return "SIGSEGV" ;
844 case SIGUSR2
: return "SIGUSR2" ;
847 case SIGPIPE
: return "SIGPIPE" ;
850 case SIGALRM
: return "SIGALRM" ;
852 case SIGTERM
: return "SIGTERM" ;
854 case SIGSTKFLT
: return "SIGSTKFLT" ;
857 case SIGCHLD
: return "SIGCHLD" ;
860 case SIGCONT
: return "SIGCONT" ;
863 case SIGSTOP
: return "SIGSTOP" ;
866 case SIGTSTP
: return "SIGTSTP" ;
869 case SIGTTIN
: return "SIGTTIN" ;
872 case SIGTTOU
: return "SIGTTOU" ;
875 case SIGURG
: return "SIGURG" ;
878 case SIGXCPU
: return "SIGXCPU" ;
881 case SIGXFSZ
: return "SIGXFSZ" ;
884 case SIGVTALRM
: return "SIGVTALRM" ;
887 case SIGPROF
: return "SIGPROF" ;
890 case SIGWINCH
: return "SIGWINCH" ;
893 case SIGIO
: return "SIGIO" ;
896 case SIGPWR
: return "SIGPWR" ;
899 case SIGSYS
: return "SIGSYS" ;
904 if ( sig
>= SIGRTMIN
&& sig
<= SIGRTMAX
) {
905 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
906 t
= pa_sprintf_malloc ( "SIGRTMIN+%i" , sig
- SIGRTMIN
);
907 PA_STATIC_TLS_SET ( signame
, t
);
916 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
917 t
= pa_sprintf_malloc ( "SIG%i" , sig
);
918 PA_STATIC_TLS_SET ( signame
, t
);
924 /* Check whether the specified GID and the group name match */
925 static int is_group ( gid_t gid
, const char * name
) {
926 struct group group
, * result
= NULL
;
931 #ifdef HAVE_GETGRGID_R
932 #ifdef _SC_GETGR_R_SIZE_MAX
933 n
= sysconf ( _SC_GETGR_R_SIZE_MAX
);
940 data
= pa_xmalloc (( size_t ) n
);
943 if ( getgrgid_r ( gid
, & group
, data
, ( size_t ) n
, & result
) < 0 || ! result
) {
944 pa_log ( "getgrgid_r(%u): %s" , ( unsigned ) gid
, pa_cstrerror ( errno
));
952 r
= strcmp ( name
, result
-> gr_name
) == 0 ;
957 /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X) that do not
958 * support getgrgid_r. */
961 if (( result
= getgrgid ( gid
)) == NULL
) {
962 pa_log ( "getgrgid(%u): %s" , gid
, pa_cstrerror ( errno
));
970 r
= strcmp ( name
, result
-> gr_name
) == 0 ;
978 /* Check the current user is member of the specified group */
979 int pa_own_uid_in_group ( const char * name
, gid_t
* gid
) {
980 GETGROUPS_T
* gids
, tgid
;
981 long n
= sysconf ( _SC_NGROUPS_MAX
);
986 gids
= pa_xmalloc ( sizeof ( GETGROUPS_T
) * ( size_t ) n
);
988 if (( n
= getgroups (( int ) n
, gids
)) < 0 ) {
989 pa_log ( "getgroups(): %s" , pa_cstrerror ( errno
));
993 for ( i
= 0 ; i
< n
; i
++) {
995 if (( k
= is_group ( gids
[ i
], name
)) < 0 )
1004 if (( k
= is_group ( tgid
= getgid (), name
)) < 0 )
1020 /* Check whether the specifc user id is a member of the specified group */
1021 int pa_uid_in_group ( uid_t uid
, const char * name
) {
1022 char * g_buf
, * p_buf
;
1024 struct group grbuf
, * gr
;
1028 g_n
= sysconf ( _SC_GETGR_R_SIZE_MAX
);
1029 g_buf
= pa_xmalloc (( size_t ) g_n
);
1031 p_n
= sysconf ( _SC_GETPW_R_SIZE_MAX
);
1032 p_buf
= pa_xmalloc (( size_t ) p_n
);
1035 if ( getgrnam_r ( name
, & grbuf
, g_buf
, ( size_t ) g_n
, & gr
) != 0 || ! gr
) {
1044 for ( i
= gr
-> gr_mem
; * i
; i
++) {
1045 struct passwd pwbuf
, * pw
;
1048 if ( getpwnam_r (* i
, & pwbuf
, p_buf
, ( size_t ) p_n
, & pw
) != 0 || ! pw
)
1051 if ( pw
-> pw_uid
== uid
) {
1064 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
1065 gid_t
pa_get_gid_of_group ( const char * name
) {
1066 gid_t ret
= ( gid_t
) - 1 ;
1069 struct group grbuf
, * gr
;
1071 g_n
= sysconf ( _SC_GETGR_R_SIZE_MAX
);
1072 g_buf
= pa_xmalloc (( size_t ) g_n
);
1075 if ( getgrnam_r ( name
, & grbuf
, g_buf
, ( size_t ) g_n
, & gr
) != 0 || ! gr
) {
1090 int pa_check_in_group ( gid_t g
) {
1091 gid_t gids
[ NGROUPS_MAX
];
1094 if (( r
= getgroups ( NGROUPS_MAX
, gids
)) < 0 )
1104 #else /* HAVE_GRP_H */
1106 int pa_own_uid_in_group ( const char * name
, gid_t
* gid
) {
1112 int pa_uid_in_group ( uid_t uid
, const char * name
) {
1117 gid_t
pa_get_gid_of_group ( const char * name
) {
1122 int pa_check_in_group ( gid_t g
) {
1129 /* Lock or unlock a file entirely.
1130 (advisory on UNIX, mandatory on Windows) */
1131 int pa_lock_fd ( int fd
, int b
) {
1135 /* Try a R/W lock first */
1137 flock
. l_type
= ( short ) ( b
? F_WRLCK
: F_UNLCK
);
1138 flock
. l_whence
= SEEK_SET
;
1142 if ( fcntl ( fd
, F_SETLKW
, & flock
) >= 0 )
1145 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1146 if ( b
&& errno
== EBADF
) {
1147 flock
. l_type
= F_RDLCK
;
1148 if ( fcntl ( fd
, F_SETLKW
, & flock
) >= 0 )
1152 pa_log ( "%slock: %s" , ! b
? "un" : "" , pa_cstrerror ( errno
));
1156 HANDLE h
= ( HANDLE
) _get_osfhandle ( fd
);
1158 if ( b
&& LockFile ( h
, 0 , 0 , 0xFFFFFFFF , 0xFFFFFFFF ))
1160 if (! b
&& UnlockFile ( h
, 0 , 0 , 0xFFFFFFFF , 0xFFFFFFFF ))
1163 pa_log ( "%slock failed: 0x%08X" , ! b
? "un" : "" , GetLastError ());
1165 /* FIXME: Needs to set errno! */
1171 /* Remove trailing newlines from a string */
1172 char * pa_strip_nl ( char * s
) {
1175 s
[ strcspn ( s
, " \r\n " )] = 0 ;
1179 /* Create a temporary lock file and lock it. */
1180 int pa_lock_lockfile ( const char * fn
) {
1187 if (( fd
= open ( fn
, O_CREAT
| O_RDWR
1194 , S_IRUSR
| S_IWUSR
)) < 0 ) {
1195 pa_log_warn ( "Failed to create lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1199 if ( pa_lock_fd ( fd
, 1 ) < 0 ) {
1200 pa_log_warn ( "Failed to lock file '%s'." , fn
);
1204 if ( fstat ( fd
, & st
) < 0 ) {
1205 pa_log_warn ( "Failed to fstat() file '%s': %s" , fn
, pa_cstrerror ( errno
));
1209 /* Check wheter the file has been removed meanwhile. When yes,
1210 * restart this loop, otherwise, we're done */
1211 if ( st
. st_nlink
>= 1 )
1214 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1215 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1219 if ( pa_close ( fd
) < 0 ) {
1220 pa_log_warn ( "Failed to close file '%s': %s" , fn
, pa_cstrerror ( errno
));
1233 int saved_errno
= errno
;
1235 errno
= saved_errno
;
1241 /* Unlock a temporary lcok file */
1242 int pa_unlock_lockfile ( const char * fn
, int fd
) {
1247 if ( unlink ( fn
) < 0 ) {
1248 pa_log_warn ( "Unable to remove lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1253 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1254 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1258 if ( pa_close ( fd
) < 0 ) {
1259 pa_log_warn ( "Failed to close '%s': %s" , fn
, pa_cstrerror ( errno
));
1266 static char * get_pulse_home ( void ) {
1270 if (! pa_get_home_dir ( h
, sizeof ( h
))) {
1271 pa_log_error ( "Failed to get home directory." );
1275 if ( stat ( h
, & st
) < 0 ) {
1276 pa_log_error ( "Failed to stat home directory %s: %s" , h
, pa_cstrerror ( errno
));
1280 if ( st
. st_uid
!= getuid ()) {
1281 pa_log_error ( "Home directory %s not ours." , h
);
1286 return pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" , h
);
1289 char * pa_get_state_dir ( void ) {
1292 /* The state directory shall contain dynamic data that should be
1293 * kept across reboots, and is private to this user */
1295 if (!( d
= pa_xstrdup ( getenv ( "PULSE_STATE_PATH" ))))
1296 if (!( d
= get_pulse_home ()))
1299 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1300 * dir then this will break. */
1302 if ( pa_make_secure_dir ( d
, 0700U , ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1303 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1311 static char * make_random_dir ( mode_t m
) {
1312 static const char table
[] =
1313 "abcdefghijklmnopqrstuvwxyz"
1314 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1317 char fn
[ 24 ] = "/tmp/pulse-" ;
1319 fn
[ sizeof ( fn
)- 1 ] = 0 ;
1327 for ( i
= 11 ; i
< sizeof ( fn
)- 1 ; i
++)
1328 fn
[ i
] = table
[ rand () % ( sizeof ( table
)- 1 )];
1330 u
= umask ((~ m
) & 0777 );
1332 saved_errno
= errno
;
1336 return pa_xstrdup ( fn
);
1338 errno
= saved_errno
;
1340 if ( errno
!= EEXIST
) {
1341 pa_log_error ( "Failed to create random directory %s: %s" , fn
, pa_cstrerror ( errno
));
1347 static int make_random_dir_and_link ( mode_t m
, const char * k
) {
1350 if (!( p
= make_random_dir ( m
)))
1353 if ( symlink ( p
, k
) < 0 ) {
1354 int saved_errno
= errno
;
1356 if ( errno
!= EEXIST
)
1357 pa_log_error ( "Failed to symlink %s to %s: %s" , k
, p
, pa_cstrerror ( errno
));
1362 errno
= saved_errno
;
1369 char * pa_get_runtime_dir ( void ) {
1370 char * d
, * k
= NULL
, * p
= NULL
, * t
= NULL
, * mid
;
1373 /* The runtime directory shall contain dynamic data that needs NOT
1374 * to be kept accross reboots and is usuallly private to the user,
1375 * except in system mode, where it might be accessible by other
1376 * users, too. Since we need POSIX locking and UNIX sockets in
1377 * this directory, we link it to a random subdir in /tmp, if it
1378 * was not explicitly configured. */
1380 if (( d
= getenv ( "PULSE_RUNTIME_PATH" ))) {
1383 m
= pa_in_system_mode () ? 0755U : 0700U ;
1385 if ( pa_make_secure_dir ( d
, m
, ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1386 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1390 return pa_xstrdup ( d
);
1393 if (!( d
= get_pulse_home ()))
1396 if (!( mid
= pa_machine_id ())) {
1401 k
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s:runtime" , d
, mid
);
1406 /* OK, first let's check if the "runtime" symlink is already
1409 if (!( p
= pa_readlink ( k
))) {
1411 if ( errno
!= ENOENT
) {
1412 pa_log_error ( "Failed to stat runtime directory %s: %s" , k
, pa_cstrerror ( errno
));
1416 /* Hmm, so the runtime directory didn't exist yet, so let's
1417 * create one in /tmp and symlink that to it */
1419 if ( make_random_dir_and_link ( 0700 , k
) < 0 ) {
1421 /* Mhmm, maybe another process was quicker than us,
1422 * let's check if that was valid */
1423 if ( errno
== EEXIST
)
1432 /* Make sure that this actually makes sense */
1433 if (! pa_is_path_absolute ( p
)) {
1434 pa_log_error ( "Path %s in link %s is not absolute." , p
, k
);
1439 /* Hmm, so this symlink is still around, make sure nobody fools
1442 if ( lstat ( p
, & st
) < 0 ) {
1444 if ( errno
!= ENOENT
) {
1445 pa_log_error ( "Failed to stat runtime directory %s: %s" , p
, pa_cstrerror ( errno
));
1451 if ( S_ISDIR ( st
. st_mode
) &&
1452 ( st
. st_uid
== getuid ()) &&
1453 (( st
. st_mode
& 0777 ) == 0700 )) {
1459 pa_log_info ( "Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory." );
1465 /* Hmm, so the link points to some nonexisting or invalid
1466 * dir. Let's replace it by a new link. We first create a
1467 * temporary link and then rename that to allow concurrent
1468 * execution of this function. */
1470 t
= pa_sprintf_malloc ( "%s.tmp" , k
);
1472 if ( make_random_dir_and_link ( 0700 , t
) < 0 ) {
1474 if ( errno
!= EEXIST
) {
1475 pa_log_error ( "Failed to symlink %s: %s" , t
, pa_cstrerror ( errno
));
1482 /* Hmm, someone lese was quicker then us. Let's give
1483 * him some time to finish, and retry. */
1488 /* OK, we succeeded in creating the temporary symlink, so
1489 * let's rename it */
1490 if ( rename ( t
, k
) < 0 ) {
1491 pa_log_error ( "Failed to rename %s to %s: %s" , t
, k
, pa_cstrerror ( errno
));
1507 /* Try to open a configuration file. If "env" is specified, open the
1508 * value of the specified environment variable. Otherwise look for a
1509 * file "local" in the home directory or a file "global" in global
1510 * file system. If "result" is non-NULL, a pointer to a newly
1511 * allocated buffer containing the used configuration file is
1513 FILE * pa_open_config_file ( const char * global
, const char * local
, const char * env
, char ** result
) {
1518 if (! getenv ( PULSE_ROOTENV
))
1522 if ( env
&& ( fn
= getenv ( env
))) {
1526 if (! ExpandEnvironmentStrings ( fn
, buf
, PATH_MAX
))
1527 /* FIXME: Needs to set errno! */
1532 if (( f
= fopen ( fn
, "r" ))) {
1534 * result
= pa_xstrdup ( fn
);
1539 pa_log_warn ( "Failed to open configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1549 if (( e
= getenv ( "PULSE_CONFIG_PATH" )))
1550 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , e
, local
);
1551 else if ( pa_get_home_dir ( h
, sizeof ( h
)))
1552 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s" , h
, local
);
1557 if (! ExpandEnvironmentStrings ( lfn
, buf
, PATH_MAX
)) {
1558 /* FIXME: Needs to set errno! */
1565 if (( f
= fopen ( fn
, "r" ))) {
1567 * result
= pa_xstrdup ( fn
);
1573 if ( errno
!= ENOENT
) {
1574 pa_log_warn ( "Failed to open configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1586 if (! ExpandEnvironmentStrings ( global
, buf
, PATH_MAX
))
1587 /* FIXME: Needs to set errno! */
1592 if (( f
= fopen ( global
, "r" ))) {
1595 * result
= pa_xstrdup ( global
);
1605 char * pa_find_config_file ( const char * global
, const char * local
, const char * env
) {
1610 if (! getenv ( PULSE_ROOTENV
))
1614 if ( env
&& ( fn
= getenv ( env
))) {
1617 if (! ExpandEnvironmentStrings ( fn
, buf
, PATH_MAX
))
1618 /* FIXME: Needs to set errno! */
1623 if ( access ( fn
, R_OK
) == 0 )
1624 return pa_xstrdup ( fn
);
1626 pa_log_warn ( "Failed to access configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1635 if (( e
= getenv ( "PULSE_CONFIG_PATH" )))
1636 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , e
, local
);
1637 else if ( pa_get_home_dir ( h
, sizeof ( h
)))
1638 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s" , h
, local
);
1643 if (! ExpandEnvironmentStrings ( lfn
, buf
, PATH_MAX
)) {
1644 /* FIXME: Needs to set errno! */
1651 if ( access ( fn
, R_OK
) == 0 ) {
1652 char * r
= pa_xstrdup ( fn
);
1657 if ( errno
!= ENOENT
) {
1658 pa_log_warn ( "Failed to access configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1668 if (! ExpandEnvironmentStrings ( global
, buf
, PATH_MAX
))
1669 /* FIXME: Needs to set errno! */
1674 if ( access ( global
, R_OK
) == 0 )
1675 return pa_xstrdup ( global
);
1683 /* Format the specified data as a hexademical string */
1684 char * pa_hexstr ( const uint8_t * d
, size_t dlength
, char * s
, size_t slength
) {
1685 size_t i
= 0 , j
= 0 ;
1686 const char hex
[] = "0123456789abcdef" ;
1690 pa_assert ( slength
> 0 );
1692 while ( i
< dlength
&& j
+ 3 <= slength
) {
1693 s
[ j
++] = hex
[* d
>> 4 ];
1694 s
[ j
++] = hex
[* d
& 0xF ];
1700 s
[ j
< slength
? j
: slength
] = 0 ;
1704 /* Convert a hexadecimal digit to a number or -1 if invalid */
1705 static int hexc ( char c
) {
1706 if ( c
>= '0' && c
<= '9' )
1709 if ( c
>= 'A' && c
<= 'F' )
1710 return c
- 'A' + 10 ;
1712 if ( c
>= 'a' && c
<= 'f' )
1713 return c
- 'a' + 10 ;
1719 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1720 size_t pa_parsehex ( const char * p
, uint8_t * d
, size_t dlength
) {
1726 while ( j
< dlength
&& * p
) {
1729 if (( b
= hexc (*( p
++))) < 0 )
1732 d
[ j
] = ( uint8_t ) ( b
<< 4 );
1737 if (( b
= hexc (*( p
++))) < 0 )
1740 d
[ j
] |= ( uint8_t ) b
;
1747 /* Returns nonzero when *s starts with *pfx */
1748 pa_bool_t
pa_startswith ( const char * s
, const char * pfx
) {
1756 return strlen ( s
) >= l
&& strncmp ( s
, pfx
, l
) == 0 ;
1759 /* Returns nonzero when *s ends with *sfx */
1760 pa_bool_t
pa_endswith ( const char * s
, const char * sfx
) {
1769 return l1
>= l2
&& strcmp ( s
+ l1
- l2
, sfx
) == 0 ;
1772 pa_bool_t
pa_is_path_absolute ( const char * fn
) {
1778 return strlen ( fn
) >= 3 && isalpha ( fn
[ 0 ]) && fn
[ 1 ] == ':' && fn
[ 2 ] == ' \\ ' ;
1782 char * pa_make_path_absolute ( const char * p
) {
1788 if ( pa_is_path_absolute ( p
))
1789 return pa_xstrdup ( p
);
1791 if (!( cwd
= pa_getcwd ()))
1792 return pa_xstrdup ( p
);
1794 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , cwd
, p
);
1799 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1800 * if fn is non-null and starts with / return fn
1801 * otherwise append fn to the run time path and return it */
1802 static char * get_path ( const char * fn
, pa_bool_t prependmid
, pa_bool_t rt
) {
1805 if ( pa_is_path_absolute ( fn
))
1806 return pa_xstrdup ( fn
);
1808 rtp
= rt
? pa_get_runtime_dir () : pa_get_state_dir ();
1819 if (!( mid
= pa_machine_id ())) {
1824 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s:%s" , rtp
, mid
, fn
);
1827 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , rtp
, fn
);
1835 char * pa_runtime_path ( const char * fn
) {
1836 return get_path ( fn
, FALSE
, TRUE
);
1839 char * pa_state_path ( const char * fn
, pa_bool_t appendmid
) {
1840 return get_path ( fn
, appendmid
, FALSE
);
1843 /* Convert the string s to a signed integer in *ret_i */
1844 int pa_atoi ( const char * s
, int32_t * ret_i
) {
1852 l
= strtol ( s
, & x
, 0 );
1854 if (! x
|| * x
|| errno
) {
1860 if (( int32_t ) l
!= l
) {
1865 * ret_i
= ( int32_t ) l
;
1870 /* Convert the string s to an unsigned integer in *ret_u */
1871 int pa_atou ( const char * s
, uint32_t * ret_u
) {
1879 l
= strtoul ( s
, & x
, 0 );
1881 if (! x
|| * x
|| errno
) {
1887 if (( uint32_t ) l
!= l
) {
1892 * ret_u
= ( uint32_t ) l
;
1897 #ifdef HAVE_STRTOF_L
1898 static locale_t c_locale
= NULL
;
1900 static void c_locale_destroy ( void ) {
1901 freelocale ( c_locale
);
1905 int pa_atod ( const char * s
, double * ret_d
) {
1912 /* This should be locale independent */
1914 #ifdef HAVE_STRTOF_L
1918 if (( c_locale
= newlocale ( LC_ALL_MASK
, "C" , NULL
)))
1919 atexit ( c_locale_destroy
);
1925 f
= strtod_l ( s
, & x
, c_locale
);
1933 if (! x
|| * x
|| errno
) {
1944 /* Same as snprintf, but guarantees NUL-termination on every platform */
1945 size_t pa_snprintf ( char * str
, size_t size
, const char * format
, ...) {
1950 pa_assert ( size
> 0 );
1953 va_start ( ap
, format
);
1954 ret
= pa_vsnprintf ( str
, size
, format
, ap
);
1960 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
1961 size_t pa_vsnprintf ( char * str
, size_t size
, const char * format
, va_list ap
) {
1965 pa_assert ( size
> 0 );
1968 ret
= vsnprintf ( str
, size
, format
, ap
);
1975 if (( size_t ) ret
> size
- 1 )
1978 return ( size_t ) ret
;
1981 /* Truncate the specified string, but guarantee that the string
1982 * returned still validates as UTF8 */
1983 char * pa_truncate_utf8 ( char * c
, size_t l
) {
1985 pa_assert ( pa_utf8_valid ( c
));
1992 while ( l
> 0 && ! pa_utf8_valid ( c
))
1998 char * pa_getcwd ( void ) {
2002 char * p
= pa_xmalloc ( l
);
2006 if ( errno
!= ERANGE
)
2014 void * pa_will_need ( const void * p
, size_t l
) {
2015 #ifdef RLIMIT_MEMLOCK
2026 a
= PA_PAGE_ALIGN_PTR ( p
);
2027 size
= ( size_t ) (( const uint8_t *) p
+ l
- ( const uint8_t *) a
);
2029 #ifdef HAVE_POSIX_MADVISE
2030 if (( r
= posix_madvise (( void *) a
, size
, POSIX_MADV_WILLNEED
)) == 0 ) {
2031 pa_log_debug ( "posix_madvise() worked fine!" );
2036 /* Most likely the memory was not mmap()ed from a file and thus
2037 * madvise() didn't work, so let's misuse mlock() do page this
2038 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2039 * inviting, the man page of mlock() tells us: "All pages that
2040 * contain a part of the specified address range are guaranteed to
2041 * be resident in RAM when the call returns successfully." */
2043 #ifdef RLIMIT_MEMLOCK
2044 pa_assert_se ( getrlimit ( RLIMIT_MEMLOCK
, & rlim
) == 0 );
2046 if ( rlim
. rlim_cur
< PA_PAGE_SIZE
) {
2047 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
));
2052 bs
= PA_PAGE_ALIGN (( size_t ) rlim
. rlim_cur
);
2054 bs
= PA_PAGE_SIZE
* 4 ;
2057 pa_log_debug ( "posix_madvise() failed (or doesn't exist), trying mlock(): %s" , pa_cstrerror ( r
));
2060 while ( size
> 0 && bs
> 0 ) {
2065 if ( mlock ( a
, bs
) < 0 ) {
2066 bs
= PA_PAGE_ALIGN ( bs
/ 2 );
2070 pa_assert_se ( munlock ( a
, bs
) == 0 );
2072 a
= ( const uint8_t *) a
+ bs
;
2078 pa_log_debug ( "mlock() failed too (or doesn't exist), giving up: %s" , pa_cstrerror ( errno
));
2080 pa_log_debug ( "mlock() worked fine!" );
2085 void pa_close_pipe ( int fds
[ 2 ]) {
2089 pa_assert_se ( pa_close ( fds
[ 0 ]) == 0 );
2092 pa_assert_se ( pa_close ( fds
[ 1 ]) == 0 );
2094 fds
[ 0 ] = fds
[ 1 ] = - 1 ;
2097 char * pa_readlink ( const char * p
) {
2106 if (( n
= readlink ( p
, c
, l
- 1 )) < 0 ) {
2111 if (( size_t ) n
< l
- 1 ) {
2121 int pa_close_all ( int except_fd
, ...) {
2126 va_start ( ap
, except_fd
);
2129 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2134 p
= pa_xnew ( int , n
+ 1 );
2136 va_start ( ap
, except_fd
);
2139 if ( except_fd
>= 0 ) {
2143 while (( fd
= va_arg ( ap
, int )) >= 0 )
2150 r
= pa_close_allv ( p
);
2156 int pa_close_allv ( const int except_fds
[]) {
2165 if (( d
= opendir ( "/proc/self/fd" ))) {
2169 while (( de
= readdir ( d
))) {
2175 if ( de
-> d_name
[ 0 ] == '.' )
2179 l
= strtol ( de
-> d_name
, & e
, 10 );
2180 if ( errno
!= 0 || ! e
|| * e
) {
2188 if (( long ) fd
!= l
) {
2201 for ( i
= 0 ; except_fds
[ i
] >= 0 ; i
++)
2202 if ( except_fds
[ i
] == fd
) {
2210 if ( pa_close ( fd
) < 0 ) {
2211 saved_errno
= errno
;
2213 errno
= saved_errno
;
2225 if ( getrlimit ( RLIMIT_NOFILE
, & rl
) < 0 )
2228 for ( fd
= 3 ; fd
< ( int ) rl
. rlim_max
; fd
++) {
2233 for ( i
= 0 ; except_fds
[ i
] >= 0 ; i
++)
2234 if ( except_fds
[ i
] == fd
) {
2242 if ( pa_close ( fd
) < 0 && errno
!= EBADF
)
2249 int pa_unblock_sigs ( int except
, ...) {
2254 va_start ( ap
, except
);
2257 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2262 p
= pa_xnew ( int , n
+ 1 );
2264 va_start ( ap
, except
);
2271 while (( sig
= va_arg ( ap
, int )) >= 0 )
2278 r
= pa_unblock_sigsv ( p
);
2284 int pa_unblock_sigsv ( const int except
[]) {
2288 if ( sigemptyset (& ss
) < 0 )
2291 for ( i
= 0 ; except
[ i
] > 0 ; i
++)
2292 if ( sigaddset (& ss
, except
[ i
]) < 0 )
2295 return sigprocmask ( SIG_SETMASK
, & ss
, NULL
);
2298 int pa_reset_sigs ( int except
, ...) {
2303 va_start ( ap
, except
);
2306 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2311 p
= pa_xnew ( int , n
+ 1 );
2313 va_start ( ap
, except
);
2320 while (( sig
= va_arg ( ap
, int )) >= 0 )
2327 r
= pa_reset_sigsv ( p
);
2333 int pa_reset_sigsv ( const int except
[]) {
2336 for ( sig
= 1 ; sig
< _NSIG
; sig
++) {
2337 pa_bool_t reset
= TRUE
;
2348 for ( i
= 0 ; except
[ i
] > 0 ; i
++) {
2349 if ( sig
== except
[ i
]) {
2358 struct sigaction sa
;
2360 memset (& sa
, 0 , sizeof ( sa
));
2361 sa
. sa_handler
= SIG_DFL
;
2363 /* On Linux the first two RT signals are reserved by
2364 * glibc, and sigaction() will return EINVAL for them. */
2365 if (( sigaction ( sig
, & sa
, NULL
) < 0 ))
2366 if ( errno
!= EINVAL
)
2374 void pa_set_env ( const char * key
, const char * value
) {
2378 putenv ( pa_sprintf_malloc ( "%s=%s" , key
, value
));
2381 pa_bool_t
pa_in_system_mode ( void ) {
2384 if (!( e
= getenv ( "PULSE_SYSTEM" )))
2390 char * pa_machine_id ( void ) {
2394 /* The returned value is supposed be some kind of ascii identifier
2395 * that is unique and stable across reboots. */
2397 /* First we try the D-Bus UUID, which is the best option we have,
2398 * since it fits perfectly our needs and is not as volatile as the
2399 * hostname which might be set from dhcp. */
2401 if (( f
= fopen ( PA_MACHINE_ID
, "r" ))) {
2402 char ln
[ 34 ] = "" , * r
;
2404 r
= fgets ( ln
, sizeof ( ln
)- 1 , f
);
2410 return pa_xstrdup ( ln
);
2413 /* The we fall back to the host name. It supposed to be somewhat
2414 * unique, at least in a network, but may change. */
2422 if (! pa_get_host_name ( c
, l
)) {
2424 if ( errno
!= EINVAL
&& errno
!= ENAMETOOLONG
)
2427 } else if ( strlen ( c
) < l
- 1 ) {
2437 /* Hmm, the hostname is as long the space we offered the
2438 * function, we cannot know if it fully fit in, so let's play
2439 * safe and retry. */
2445 /* If no hostname was set we use the POSIX hostid. It's usually
2446 * the IPv4 address. Mit not be that stable. */
2447 return pa_sprintf_malloc ( "%08lx" , ( unsigned long ) gethostid
);