]>
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 /* Print a warning messages in case that the given signal is not
405 * blocked or trapped */
406 void pa_check_signal_is_blocked ( int sig
) {
407 #ifdef HAVE_SIGACTION
411 /* If POSIX threads are supported use thread-aware
412 * pthread_sigmask() function, to check if the signal is
413 * blocked. Otherwise fall back to sigprocmask() */
416 if ( pthread_sigmask ( SIG_SETMASK
, NULL
, & set
) < 0 ) {
418 if ( sigprocmask ( SIG_SETMASK
, NULL
, & set
) < 0 ) {
419 pa_log ( "sigprocmask(): %s" , pa_cstrerror ( errno
));
426 if ( sigismember (& set
, sig
))
429 /* Check whether the signal is trapped */
431 if ( sigaction ( sig
, NULL
, & sa
) < 0 ) {
432 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
436 if ( sa
. sa_handler
!= SIG_DFL
)
439 pa_log_warn ( "%s is not trapped. This might cause malfunction!" , pa_sig2str ( sig
));
440 #else /* HAVE_SIGACTION */
441 pa_log_warn ( "%s might not be trapped. This might cause malfunction!" , pa_sig2str ( sig
));
445 /* The following function is based on an example from the GNU libc
446 * documentation. This function is similar to GNU's asprintf(). */
447 char * pa_sprintf_malloc ( const char * format
, ...) {
457 c
= pa_xrealloc ( c
, size
);
459 va_start ( ap
, format
);
460 r
= vsnprintf ( c
, size
, format
, ap
);
465 if ( r
> - 1 && ( size_t ) r
< size
)
468 if ( r
> - 1 ) /* glibc 2.1 */
475 /* Same as the previous function, but use a va_list instead of an
477 char * pa_vsprintf_malloc ( const char * format
, va_list ap
) {
487 c
= pa_xrealloc ( c
, size
);
490 r
= vsnprintf ( c
, size
, format
, aq
);
495 if ( r
> - 1 && ( size_t ) r
< size
)
498 if ( r
> - 1 ) /* glibc 2.1 */
505 /* Similar to OpenBSD's strlcpy() function */
506 char * pa_strlcpy ( char * b
, const char * s
, size_t l
) {
516 /* Make the current thread a realtime thread, and acquire the highest
517 * rtprio we can get that is less or equal the specified parameter. If
518 * the thread is already realtime, don't do anything. */
519 int pa_make_realtime ( int rtprio
) {
521 #ifdef _POSIX_PRIORITY_SCHEDULING
522 struct sched_param sp
;
525 memset (& sp
, 0 , sizeof ( sp
));
528 if (( r
= pthread_getschedparam ( pthread_self (), & policy
, & sp
)) != 0 ) {
529 pa_log ( "pthread_getschedgetparam(): %s" , pa_cstrerror ( r
));
533 if ( policy
== SCHED_FIFO
&& sp
. sched_priority
>= rtprio
) {
534 pa_log_info ( "Thread already being scheduled with SCHED_FIFO with priority %i." , sp
. sched_priority
);
538 sp
. sched_priority
= rtprio
;
539 if (( r
= pthread_setschedparam ( pthread_self (), SCHED_FIFO
, & sp
)) != 0 ) {
541 while ( sp
. sched_priority
> 1 ) {
542 sp
. sched_priority
--;
544 if (( r
= pthread_setschedparam ( pthread_self (), SCHED_FIFO
, & sp
)) == 0 ) {
545 pa_log_info ( "Successfully enabled SCHED_FIFO scheduling for thread, with priority %i, which is lower than the requested %i." , sp
. sched_priority
, rtprio
);
550 pa_log_warn ( "pthread_setschedparam(): %s" , pa_cstrerror ( r
));
554 pa_log_info ( "Successfully enabled SCHED_FIFO scheduling for thread, with priority %i." , sp
. sched_priority
);
563 /* This is merely used for giving the user a hint. This is not correct
564 * for anything security related */
565 pa_bool_t
pa_can_realtime ( void ) {
570 #if defined(HAVE_SYS_RESOURCE_H) && defined(RLIMIT_RTPRIO)
574 if ( getrlimit ( RLIMIT_RTPRIO
, & rl
) >= 0 )
575 if ( rl
. rlim_cur
> 0 || rl
. rlim_cur
== RLIM_INFINITY
)
580 #if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_SYS_NICE)
584 if (( cap
= cap_get_proc ())) {
585 cap_flag_value_t flag
= CAP_CLEAR
;
587 if ( cap_get_flag ( cap
, CAP_SYS_NICE
, CAP_EFFECTIVE
, & flag
) >= 0 )
588 if ( flag
== CAP_SET
) {
601 /* This is merely used for giving the user a hint. This is not correct
602 * for anything security related */
603 pa_bool_t
pa_can_high_priority ( void ) {
608 #if defined(HAVE_SYS_RESOURCE_H) && defined(RLIMIT_RTPRIO)
612 if ( getrlimit ( RLIMIT_NICE
, & rl
) >= 0 )
613 if ( rl
. rlim_cur
>= 21 || rl
. rlim_cur
== RLIM_INFINITY
)
618 #if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_SYS_NICE)
622 if (( cap
= cap_get_proc ())) {
623 cap_flag_value_t flag
= CAP_CLEAR
;
625 if ( cap_get_flag ( cap
, CAP_SYS_NICE
, CAP_EFFECTIVE
, & flag
) >= 0 )
626 if ( flag
== CAP_SET
) {
639 /* Raise the priority of the current process as much as possible that
640 * is <= the specified nice level..*/
641 int pa_raise_priority ( int nice_level
) {
643 #ifdef HAVE_SYS_RESOURCE_H
644 if ( setpriority ( PRIO_PROCESS
, 0 , nice_level
) < 0 ) {
647 for ( n
= nice_level
+ 1 ; n
< 0 ; n
++) {
649 if ( setpriority ( PRIO_PROCESS
, 0 , n
) == 0 ) {
650 pa_log_info ( "Successfully acquired nice level %i, which is lower than the requested %i." , n
, nice_level
);
655 pa_log_warn ( "setpriority(): %s" , pa_cstrerror ( errno
));
659 pa_log_info ( "Successfully gained nice level %i." , nice_level
);
663 if ( nice_level
< 0 ) {
664 if (! SetPriorityClass ( GetCurrentProcess (), HIGH_PRIORITY_CLASS
)) {
665 pa_log_warn ( "SetPriorityClass() failed: 0x%08X" , GetLastError ());
669 pa_log_info ( "Successfully gained high priority class." );
676 /* Reset the priority to normal, inverting the changes made by
677 * pa_raise_priority() and pa_make_realtime()*/
678 void pa_reset_priority ( void ) {
679 #ifdef HAVE_SYS_RESOURCE_H
680 struct sched_param sp
;
682 setpriority ( PRIO_PROCESS
, 0 , 0 );
684 memset (& sp
, 0 , sizeof ( sp
));
685 pa_assert_se ( pthread_setschedparam ( pthread_self (), SCHED_OTHER
, & sp
) == 0 );
689 SetPriorityClass ( GetCurrentProcess (), NORMAL_PRIORITY_CLASS
);
693 static int match ( const char * expr
, const char * v
) {
698 if ( regcomp (& re
, expr
, REG_NOSUB
| REG_EXTENDED
) != 0 ) {
703 if (( k
= regexec (& re
, v
, 0 , NULL
, 0 )) == 0 )
705 else if ( k
== REG_NOMATCH
)
718 /* Try to parse a boolean string value.*/
719 int pa_parse_boolean ( const char * v
) {
724 /* First we check language independant */
725 if (! strcmp ( v
, "1" ) || v
[ 0 ] == 'y' || v
[ 0 ] == 'Y' || v
[ 0 ] == 't' || v
[ 0 ] == 'T' || ! strcasecmp ( v
, "on" ))
727 else if (! strcmp ( v
, "0" ) || v
[ 0 ] == 'n' || v
[ 0 ] == 'N' || v
[ 0 ] == 'f' || v
[ 0 ] == 'F' || ! strcasecmp ( v
, "off" ))
730 /* And then we check language dependant */
731 if (( expr
= nl_langinfo ( YESEXPR
)))
733 if (( r
= match ( expr
, v
)) > 0 )
736 if (( expr
= nl_langinfo ( NOEXPR
)))
738 if (( r
= match ( expr
, v
)) > 0 )
745 /* Split the specified string wherever one of the strings in delimiter
746 * occurs. Each time it is called returns a newly allocated string
747 * with pa_xmalloc(). The variable state points to, should be
748 * initiallized to NULL before the first call. */
749 char * pa_split ( const char * c
, const char * delimiter
, const char ** state
) {
750 const char * current
= * state
? * state
: c
;
756 l
= strcspn ( current
, delimiter
);
762 return pa_xstrndup ( current
, l
);
765 /* What is interpreted as whitespace? */
766 #define WHITESPACE " \t\n "
768 /* Split a string into words. Otherwise similar to pa_split(). */
769 char * pa_split_spaces ( const char * c
, const char ** state
) {
770 const char * current
= * state
? * state
: c
;
773 if (!* current
|| * c
== 0 )
776 current
+= strspn ( current
, WHITESPACE
);
777 l
= strcspn ( current
, WHITESPACE
);
781 return pa_xstrndup ( current
, l
);
784 PA_STATIC_TLS_DECLARE ( signame
, pa_xfree
);
786 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
787 const char * pa_sig2str ( int sig
) {
800 char buf
[ SIG2STR_MAX
];
802 if ( sig2str ( sig
, buf
) == 0 ) {
803 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
804 t
= pa_sprintf_malloc ( "SIG%s" , buf
);
805 PA_STATIC_TLS_SET ( signame
, t
);
813 case SIGHUP
: return "SIGHUP" ;
815 case SIGINT
: return "SIGINT" ;
817 case SIGQUIT
: return "SIGQUIT" ;
819 case SIGILL
: return "SIGULL" ;
821 case SIGTRAP
: return "SIGTRAP" ;
823 case SIGABRT
: return "SIGABRT" ;
825 case SIGBUS
: return "SIGBUS" ;
827 case SIGFPE
: return "SIGFPE" ;
829 case SIGKILL
: return "SIGKILL" ;
832 case SIGUSR1
: return "SIGUSR1" ;
834 case SIGSEGV
: return "SIGSEGV" ;
836 case SIGUSR2
: return "SIGUSR2" ;
839 case SIGPIPE
: return "SIGPIPE" ;
842 case SIGALRM
: return "SIGALRM" ;
844 case SIGTERM
: return "SIGTERM" ;
846 case SIGSTKFLT
: return "SIGSTKFLT" ;
849 case SIGCHLD
: return "SIGCHLD" ;
852 case SIGCONT
: return "SIGCONT" ;
855 case SIGSTOP
: return "SIGSTOP" ;
858 case SIGTSTP
: return "SIGTSTP" ;
861 case SIGTTIN
: return "SIGTTIN" ;
864 case SIGTTOU
: return "SIGTTOU" ;
867 case SIGURG
: return "SIGURG" ;
870 case SIGXCPU
: return "SIGXCPU" ;
873 case SIGXFSZ
: return "SIGXFSZ" ;
876 case SIGVTALRM
: return "SIGVTALRM" ;
879 case SIGPROF
: return "SIGPROF" ;
882 case SIGWINCH
: return "SIGWINCH" ;
885 case SIGIO
: return "SIGIO" ;
888 case SIGPWR
: return "SIGPWR" ;
891 case SIGSYS
: return "SIGSYS" ;
896 if ( sig
>= SIGRTMIN
&& sig
<= SIGRTMAX
) {
897 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
898 t
= pa_sprintf_malloc ( "SIGRTMIN+%i" , sig
- SIGRTMIN
);
899 PA_STATIC_TLS_SET ( signame
, t
);
908 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
909 t
= pa_sprintf_malloc ( "SIG%i" , sig
);
910 PA_STATIC_TLS_SET ( signame
, t
);
916 /* Check whether the specified GID and the group name match */
917 static int is_group ( gid_t gid
, const char * name
) {
918 struct group group
, * result
= NULL
;
923 #ifdef HAVE_GETGRGID_R
924 #ifdef _SC_GETGR_R_SIZE_MAX
925 n
= sysconf ( _SC_GETGR_R_SIZE_MAX
);
932 data
= pa_xmalloc (( size_t ) n
);
935 if ( getgrgid_r ( gid
, & group
, data
, ( size_t ) n
, & result
) < 0 || ! result
) {
936 pa_log ( "getgrgid_r(%u): %s" , ( unsigned ) gid
, pa_cstrerror ( errno
));
944 r
= strcmp ( name
, result
-> gr_name
) == 0 ;
949 /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X) that do not
950 * support getgrgid_r. */
953 if (( result
= getgrgid ( gid
)) == NULL
) {
954 pa_log ( "getgrgid(%u): %s" , gid
, pa_cstrerror ( errno
));
962 r
= strcmp ( name
, result
-> gr_name
) == 0 ;
970 /* Check the current user is member of the specified group */
971 int pa_own_uid_in_group ( const char * name
, gid_t
* gid
) {
972 GETGROUPS_T
* gids
, tgid
;
973 long n
= sysconf ( _SC_NGROUPS_MAX
);
978 gids
= pa_xmalloc ( sizeof ( GETGROUPS_T
) * ( size_t ) n
);
980 if (( n
= getgroups (( int ) n
, gids
)) < 0 ) {
981 pa_log ( "getgroups(): %s" , pa_cstrerror ( errno
));
985 for ( i
= 0 ; i
< n
; i
++) {
987 if (( k
= is_group ( gids
[ i
], name
)) < 0 )
996 if (( k
= is_group ( tgid
= getgid (), name
)) < 0 )
1012 /* Check whether the specifc user id is a member of the specified group */
1013 int pa_uid_in_group ( uid_t uid
, const char * name
) {
1014 char * g_buf
, * p_buf
;
1016 struct group grbuf
, * gr
;
1020 g_n
= sysconf ( _SC_GETGR_R_SIZE_MAX
);
1021 g_buf
= pa_xmalloc (( size_t ) g_n
);
1023 p_n
= sysconf ( _SC_GETPW_R_SIZE_MAX
);
1024 p_buf
= pa_xmalloc (( size_t ) p_n
);
1027 if ( getgrnam_r ( name
, & grbuf
, g_buf
, ( size_t ) g_n
, & gr
) != 0 || ! gr
) {
1036 for ( i
= gr
-> gr_mem
; * i
; i
++) {
1037 struct passwd pwbuf
, * pw
;
1040 if ( getpwnam_r (* i
, & pwbuf
, p_buf
, ( size_t ) p_n
, & pw
) != 0 || ! pw
)
1043 if ( pw
-> pw_uid
== uid
) {
1056 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
1057 gid_t
pa_get_gid_of_group ( const char * name
) {
1058 gid_t ret
= ( gid_t
) - 1 ;
1061 struct group grbuf
, * gr
;
1063 g_n
= sysconf ( _SC_GETGR_R_SIZE_MAX
);
1064 g_buf
= pa_xmalloc (( size_t ) g_n
);
1067 if ( getgrnam_r ( name
, & grbuf
, g_buf
, ( size_t ) g_n
, & gr
) != 0 || ! gr
) {
1082 int pa_check_in_group ( gid_t g
) {
1083 gid_t gids
[ NGROUPS_MAX
];
1086 if (( r
= getgroups ( NGROUPS_MAX
, gids
)) < 0 )
1096 #else /* HAVE_GRP_H */
1098 int pa_own_uid_in_group ( const char * name
, gid_t
* gid
) {
1104 int pa_uid_in_group ( uid_t uid
, const char * name
) {
1109 gid_t
pa_get_gid_of_group ( const char * name
) {
1114 int pa_check_in_group ( gid_t g
) {
1121 /* Lock or unlock a file entirely.
1122 (advisory on UNIX, mandatory on Windows) */
1123 int pa_lock_fd ( int fd
, int b
) {
1127 /* Try a R/W lock first */
1129 flock
. l_type
= ( short ) ( b
? F_WRLCK
: F_UNLCK
);
1130 flock
. l_whence
= SEEK_SET
;
1134 if ( fcntl ( fd
, F_SETLKW
, & flock
) >= 0 )
1137 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1138 if ( b
&& errno
== EBADF
) {
1139 flock
. l_type
= F_RDLCK
;
1140 if ( fcntl ( fd
, F_SETLKW
, & flock
) >= 0 )
1144 pa_log ( "%slock: %s" , ! b
? "un" : "" , pa_cstrerror ( errno
));
1148 HANDLE h
= ( HANDLE
) _get_osfhandle ( fd
);
1150 if ( b
&& LockFile ( h
, 0 , 0 , 0xFFFFFFFF , 0xFFFFFFFF ))
1152 if (! b
&& UnlockFile ( h
, 0 , 0 , 0xFFFFFFFF , 0xFFFFFFFF ))
1155 pa_log ( "%slock failed: 0x%08X" , ! b
? "un" : "" , GetLastError ());
1157 /* FIXME: Needs to set errno! */
1163 /* Remove trailing newlines from a string */
1164 char * pa_strip_nl ( char * s
) {
1167 s
[ strcspn ( s
, " \r\n " )] = 0 ;
1171 /* Create a temporary lock file and lock it. */
1172 int pa_lock_lockfile ( const char * fn
) {
1179 if (( fd
= open ( fn
, O_CREAT
| O_RDWR
1186 , S_IRUSR
| S_IWUSR
)) < 0 ) {
1187 pa_log_warn ( "Failed to create lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1191 if ( pa_lock_fd ( fd
, 1 ) < 0 ) {
1192 pa_log_warn ( "Failed to lock file '%s'." , fn
);
1196 if ( fstat ( fd
, & st
) < 0 ) {
1197 pa_log_warn ( "Failed to fstat() file '%s': %s" , fn
, pa_cstrerror ( errno
));
1201 /* Check wheter the file has been removed meanwhile. When yes,
1202 * restart this loop, otherwise, we're done */
1203 if ( st
. st_nlink
>= 1 )
1206 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1207 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1211 if ( pa_close ( fd
) < 0 ) {
1212 pa_log_warn ( "Failed to close file '%s': %s" , fn
, pa_cstrerror ( errno
));
1225 int saved_errno
= errno
;
1227 errno
= saved_errno
;
1233 /* Unlock a temporary lcok file */
1234 int pa_unlock_lockfile ( const char * fn
, int fd
) {
1239 if ( unlink ( fn
) < 0 ) {
1240 pa_log_warn ( "Unable to remove lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1245 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1246 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1250 if ( pa_close ( fd
) < 0 ) {
1251 pa_log_warn ( "Failed to close '%s': %s" , fn
, pa_cstrerror ( errno
));
1258 static char * get_pulse_home ( void ) {
1262 if (! pa_get_home_dir ( h
, sizeof ( h
))) {
1263 pa_log_error ( "Failed to get home directory." );
1267 if ( stat ( h
, & st
) < 0 ) {
1268 pa_log_error ( "Failed to stat home directory %s: %s" , h
, pa_cstrerror ( errno
));
1272 if ( st
. st_uid
!= getuid ()) {
1273 pa_log_error ( "Home directory %s not ours." , h
);
1278 return pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" , h
);
1281 char * pa_get_state_dir ( void ) {
1284 /* The state directory shall contain dynamic data that should be
1285 * kept across reboots, and is private to this user */
1287 if (!( d
= pa_xstrdup ( getenv ( "PULSE_STATE_PATH" ))))
1288 if (!( d
= get_pulse_home ()))
1291 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1292 * dir then this will break. */
1294 if ( pa_make_secure_dir ( d
, 0700U , ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1295 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1303 static char * make_random_dir ( mode_t m
) {
1304 static const char table
[] =
1305 "abcdefghijklmnopqrstuvwxyz"
1306 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1309 char fn
[ 24 ] = "/tmp/pulse-" ;
1311 fn
[ sizeof ( fn
)- 1 ] = 0 ;
1319 for ( i
= 11 ; i
< sizeof ( fn
)- 1 ; i
++)
1320 fn
[ i
] = table
[ rand () % ( sizeof ( table
)- 1 )];
1322 u
= umask ((~ m
) & 0777 );
1324 saved_errno
= errno
;
1328 return pa_xstrdup ( fn
);
1330 errno
= saved_errno
;
1332 if ( errno
!= EEXIST
) {
1333 pa_log_error ( "Failed to create random directory %s: %s" , fn
, pa_cstrerror ( errno
));
1339 static int make_random_dir_and_link ( mode_t m
, const char * k
) {
1342 if (!( p
= make_random_dir ( m
)))
1345 if ( symlink ( p
, k
) < 0 ) {
1346 int saved_errno
= errno
;
1348 if ( errno
!= EEXIST
)
1349 pa_log_error ( "Failed to symlink %s to %s: %s" , k
, p
, pa_cstrerror ( errno
));
1354 errno
= saved_errno
;
1361 char * pa_get_runtime_dir ( void ) {
1362 char * d
, * k
= NULL
, * p
= NULL
, * t
= NULL
, * mid
;
1365 /* The runtime directory shall contain dynamic data that needs NOT
1366 * to be kept accross reboots and is usuallly private to the user,
1367 * except in system mode, where it might be accessible by other
1368 * users, too. Since we need POSIX locking and UNIX sockets in
1369 * this directory, we link it to a random subdir in /tmp, if it
1370 * was not explicitly configured. */
1372 if (( d
= getenv ( "PULSE_RUNTIME_PATH" ))) {
1375 m
= pa_in_system_mode () ? 0755U : 0700U ;
1377 if ( pa_make_secure_dir ( d
, m
, ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1378 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1382 return pa_xstrdup ( d
);
1385 if (!( d
= get_pulse_home ()))
1388 if (!( mid
= pa_machine_id ())) {
1393 k
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s:runtime" , d
, mid
);
1398 /* OK, first let's check if the "runtime" symlink is already
1401 if (!( p
= pa_readlink ( k
))) {
1403 if ( errno
!= ENOENT
) {
1404 pa_log_error ( "Failed to stat runtime directory %s: %s" , k
, pa_cstrerror ( errno
));
1408 /* Hmm, so the runtime directory didn't exist yet, so let's
1409 * create one in /tmp and symlink that to it */
1411 if ( make_random_dir_and_link ( 0700 , k
) < 0 ) {
1413 /* Mhmm, maybe another process was quicker than us,
1414 * let's check if that was valid */
1415 if ( errno
== EEXIST
)
1424 /* Make sure that this actually makes sense */
1425 if (! pa_is_path_absolute ( p
)) {
1426 pa_log_error ( "Path %s in link %s is not absolute." , p
, k
);
1431 /* Hmm, so this symlink is still around, make sure nobody fools
1434 if ( lstat ( p
, & st
) < 0 ) {
1436 if ( errno
!= ENOENT
) {
1437 pa_log_error ( "Failed to stat runtime directory %s: %s" , p
, pa_cstrerror ( errno
));
1443 if ( S_ISDIR ( st
. st_mode
) &&
1444 ( st
. st_uid
== getuid ()) &&
1445 (( st
. st_mode
& 0777 ) == 0700 )) {
1451 pa_log_info ( "Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory." );
1457 /* Hmm, so the link points to some nonexisting or invalid
1458 * dir. Let's replace it by a new link. We first create a
1459 * temporary link and then rename that to allow concurrent
1460 * execution of this function. */
1462 t
= pa_sprintf_malloc ( "%s.tmp" , k
);
1464 if ( make_random_dir_and_link ( 0700 , t
) < 0 ) {
1466 if ( errno
!= EEXIST
) {
1467 pa_log_error ( "Failed to symlink %s: %s" , t
, pa_cstrerror ( errno
));
1474 /* Hmm, someone lese was quicker then us. Let's give
1475 * him some time to finish, and retry. */
1480 /* OK, we succeeded in creating the temporary symlink, so
1481 * let's rename it */
1482 if ( rename ( t
, k
) < 0 ) {
1483 pa_log_error ( "Failed to rename %s to %s: %s" , t
, k
, pa_cstrerror ( errno
));
1499 /* Try to open a configuration file. If "env" is specified, open the
1500 * value of the specified environment variable. Otherwise look for a
1501 * file "local" in the home directory or a file "global" in global
1502 * file system. If "result" is non-NULL, a pointer to a newly
1503 * allocated buffer containing the used configuration file is
1505 FILE * pa_open_config_file ( const char * global
, const char * local
, const char * env
, char ** result
) {
1510 if (! getenv ( PULSE_ROOTENV
))
1514 if ( env
&& ( fn
= getenv ( env
))) {
1518 if (! ExpandEnvironmentStrings ( fn
, buf
, PATH_MAX
))
1519 /* FIXME: Needs to set errno! */
1524 if (( f
= fopen ( fn
, "r" ))) {
1526 * result
= pa_xstrdup ( fn
);
1531 pa_log_warn ( "Failed to open configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1541 if (( e
= getenv ( "PULSE_CONFIG_PATH" )))
1542 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , e
, local
);
1543 else if ( pa_get_home_dir ( h
, sizeof ( h
)))
1544 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s" , h
, local
);
1549 if (! ExpandEnvironmentStrings ( lfn
, buf
, PATH_MAX
)) {
1550 /* FIXME: Needs to set errno! */
1557 if (( f
= fopen ( fn
, "r" ))) {
1559 * result
= pa_xstrdup ( fn
);
1565 if ( errno
!= ENOENT
) {
1566 pa_log_warn ( "Failed to open configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1578 if (! ExpandEnvironmentStrings ( global
, buf
, PATH_MAX
))
1579 /* FIXME: Needs to set errno! */
1584 if (( f
= fopen ( global
, "r" ))) {
1587 * result
= pa_xstrdup ( global
);
1597 char * pa_find_config_file ( const char * global
, const char * local
, const char * env
) {
1602 if (! getenv ( PULSE_ROOTENV
))
1606 if ( env
&& ( fn
= getenv ( env
))) {
1609 if (! ExpandEnvironmentStrings ( fn
, buf
, PATH_MAX
))
1610 /* FIXME: Needs to set errno! */
1615 if ( access ( fn
, R_OK
) == 0 )
1616 return pa_xstrdup ( fn
);
1618 pa_log_warn ( "Failed to access configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1627 if (( e
= getenv ( "PULSE_CONFIG_PATH" )))
1628 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , e
, local
);
1629 else if ( pa_get_home_dir ( h
, sizeof ( h
)))
1630 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s" , h
, local
);
1635 if (! ExpandEnvironmentStrings ( lfn
, buf
, PATH_MAX
)) {
1636 /* FIXME: Needs to set errno! */
1643 if ( access ( fn
, R_OK
) == 0 ) {
1644 char * r
= pa_xstrdup ( fn
);
1649 if ( errno
!= ENOENT
) {
1650 pa_log_warn ( "Failed to access configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1660 if (! ExpandEnvironmentStrings ( global
, buf
, PATH_MAX
))
1661 /* FIXME: Needs to set errno! */
1666 if ( access ( global
, R_OK
) == 0 )
1667 return pa_xstrdup ( global
);
1675 /* Format the specified data as a hexademical string */
1676 char * pa_hexstr ( const uint8_t * d
, size_t dlength
, char * s
, size_t slength
) {
1677 size_t i
= 0 , j
= 0 ;
1678 const char hex
[] = "0123456789abcdef" ;
1682 pa_assert ( slength
> 0 );
1684 while ( i
< dlength
&& j
+ 3 <= slength
) {
1685 s
[ j
++] = hex
[* d
>> 4 ];
1686 s
[ j
++] = hex
[* d
& 0xF ];
1692 s
[ j
< slength
? j
: slength
] = 0 ;
1696 /* Convert a hexadecimal digit to a number or -1 if invalid */
1697 static int hexc ( char c
) {
1698 if ( c
>= '0' && c
<= '9' )
1701 if ( c
>= 'A' && c
<= 'F' )
1702 return c
- 'A' + 10 ;
1704 if ( c
>= 'a' && c
<= 'f' )
1705 return c
- 'a' + 10 ;
1711 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1712 size_t pa_parsehex ( const char * p
, uint8_t * d
, size_t dlength
) {
1718 while ( j
< dlength
&& * p
) {
1721 if (( b
= hexc (*( p
++))) < 0 )
1724 d
[ j
] = ( uint8_t ) ( b
<< 4 );
1729 if (( b
= hexc (*( p
++))) < 0 )
1732 d
[ j
] |= ( uint8_t ) b
;
1739 /* Returns nonzero when *s starts with *pfx */
1740 pa_bool_t
pa_startswith ( const char * s
, const char * pfx
) {
1748 return strlen ( s
) >= l
&& strncmp ( s
, pfx
, l
) == 0 ;
1751 /* Returns nonzero when *s ends with *sfx */
1752 pa_bool_t
pa_endswith ( const char * s
, const char * sfx
) {
1761 return l1
>= l2
&& strcmp ( s
+ l1
- l2
, sfx
) == 0 ;
1764 pa_bool_t
pa_is_path_absolute ( const char * fn
) {
1770 return strlen ( fn
) >= 3 && isalpha ( fn
[ 0 ]) && fn
[ 1 ] == ':' && fn
[ 2 ] == ' \\ ' ;
1774 char * pa_make_path_absolute ( const char * p
) {
1780 if ( pa_is_path_absolute ( p
))
1781 return pa_xstrdup ( p
);
1783 if (!( cwd
= pa_getcwd ()))
1784 return pa_xstrdup ( p
);
1786 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , cwd
, p
);
1791 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1792 * if fn is non-null and starts with / return fn
1793 * otherwise append fn to the run time path and return it */
1794 static char * get_path ( const char * fn
, pa_bool_t prependmid
, pa_bool_t rt
) {
1797 if ( pa_is_path_absolute ( fn
))
1798 return pa_xstrdup ( fn
);
1800 rtp
= rt
? pa_get_runtime_dir () : pa_get_state_dir ();
1811 if (!( mid
= pa_machine_id ())) {
1816 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s:%s" , rtp
, mid
, fn
);
1819 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , rtp
, fn
);
1827 char * pa_runtime_path ( const char * fn
) {
1828 return get_path ( fn
, FALSE
, TRUE
);
1831 char * pa_state_path ( const char * fn
, pa_bool_t appendmid
) {
1832 return get_path ( fn
, appendmid
, FALSE
);
1835 /* Convert the string s to a signed integer in *ret_i */
1836 int pa_atoi ( const char * s
, int32_t * ret_i
) {
1844 l
= strtol ( s
, & x
, 0 );
1846 if (! x
|| * x
|| errno
) {
1852 if (( int32_t ) l
!= l
) {
1857 * ret_i
= ( int32_t ) l
;
1862 /* Convert the string s to an unsigned integer in *ret_u */
1863 int pa_atou ( const char * s
, uint32_t * ret_u
) {
1871 l
= strtoul ( s
, & x
, 0 );
1873 if (! x
|| * x
|| errno
) {
1879 if (( uint32_t ) l
!= l
) {
1884 * ret_u
= ( uint32_t ) l
;
1889 #ifdef HAVE_STRTOF_L
1890 static locale_t c_locale
= NULL
;
1892 static void c_locale_destroy ( void ) {
1893 freelocale ( c_locale
);
1897 int pa_atod ( const char * s
, double * ret_d
) {
1904 /* This should be locale independent */
1906 #ifdef HAVE_STRTOF_L
1910 if (( c_locale
= newlocale ( LC_ALL_MASK
, "C" , NULL
)))
1911 atexit ( c_locale_destroy
);
1917 f
= strtod_l ( s
, & x
, c_locale
);
1925 if (! x
|| * x
|| errno
) {
1936 /* Same as snprintf, but guarantees NUL-termination on every platform */
1937 size_t pa_snprintf ( char * str
, size_t size
, const char * format
, ...) {
1942 pa_assert ( size
> 0 );
1945 va_start ( ap
, format
);
1946 ret
= pa_vsnprintf ( str
, size
, format
, ap
);
1952 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
1953 size_t pa_vsnprintf ( char * str
, size_t size
, const char * format
, va_list ap
) {
1957 pa_assert ( size
> 0 );
1960 ret
= vsnprintf ( str
, size
, format
, ap
);
1967 if (( size_t ) ret
> size
- 1 )
1970 return ( size_t ) ret
;
1973 /* Truncate the specified string, but guarantee that the string
1974 * returned still validates as UTF8 */
1975 char * pa_truncate_utf8 ( char * c
, size_t l
) {
1977 pa_assert ( pa_utf8_valid ( c
));
1984 while ( l
> 0 && ! pa_utf8_valid ( c
))
1990 char * pa_getcwd ( void ) {
1994 char * p
= pa_xmalloc ( l
);
1998 if ( errno
!= ERANGE
)
2006 void * pa_will_need ( const void * p
, size_t l
) {
2007 #ifdef RLIMIT_MEMLOCK
2018 a
= PA_PAGE_ALIGN_PTR ( p
);
2019 size
= ( size_t ) (( const uint8_t *) p
+ l
- ( const uint8_t *) a
);
2021 #ifdef HAVE_POSIX_MADVISE
2022 if (( r
= posix_madvise (( void *) a
, size
, POSIX_MADV_WILLNEED
)) == 0 ) {
2023 pa_log_debug ( "posix_madvise() worked fine!" );
2028 /* Most likely the memory was not mmap()ed from a file and thus
2029 * madvise() didn't work, so let's misuse mlock() do page this
2030 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2031 * inviting, the man page of mlock() tells us: "All pages that
2032 * contain a part of the specified address range are guaranteed to
2033 * be resident in RAM when the call returns successfully." */
2035 #ifdef RLIMIT_MEMLOCK
2036 pa_assert_se ( getrlimit ( RLIMIT_MEMLOCK
, & rlim
) == 0 );
2038 if ( rlim
. rlim_cur
< PA_PAGE_SIZE
) {
2039 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
));
2044 bs
= PA_PAGE_ALIGN ( rlim
. rlim_cur
);
2046 bs
= PA_PAGE_SIZE
* 4 ;
2049 pa_log_debug ( "posix_madvise() failed (or doesn't exist), trying mlock(): %s" , pa_cstrerror ( r
));
2052 while ( size
> 0 && bs
> 0 ) {
2057 if ( mlock ( a
, bs
) < 0 ) {
2058 bs
= PA_PAGE_ALIGN ( bs
/ 2 );
2062 pa_assert_se ( munlock ( a
, bs
) == 0 );
2064 a
= ( const uint8_t *) a
+ bs
;
2070 pa_log_debug ( "mlock() failed too (or doesn't exist), giving up: %s" , pa_cstrerror ( errno
));
2072 pa_log_debug ( "mlock() worked fine!" );
2077 void pa_close_pipe ( int fds
[ 2 ]) {
2081 pa_assert_se ( pa_close ( fds
[ 0 ]) == 0 );
2084 pa_assert_se ( pa_close ( fds
[ 1 ]) == 0 );
2086 fds
[ 0 ] = fds
[ 1 ] = - 1 ;
2089 char * pa_readlink ( const char * p
) {
2098 if (( n
= readlink ( p
, c
, l
- 1 )) < 0 ) {
2103 if (( size_t ) n
< l
- 1 ) {
2113 int pa_close_all ( int except_fd
, ...) {
2118 va_start ( ap
, except_fd
);
2121 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2126 p
= pa_xnew ( int , n
+ 1 );
2128 va_start ( ap
, except_fd
);
2131 if ( except_fd
>= 0 ) {
2135 while (( fd
= va_arg ( ap
, int )) >= 0 )
2142 r
= pa_close_allv ( p
);
2148 int pa_close_allv ( const int except_fds
[]) {
2157 if (( d
= opendir ( "/proc/self/fd" ))) {
2161 while (( de
= readdir ( d
))) {
2167 if ( de
-> d_name
[ 0 ] == '.' )
2171 l
= strtol ( de
-> d_name
, & e
, 10 );
2172 if ( errno
!= 0 || ! e
|| * e
) {
2180 if (( long ) fd
!= l
) {
2193 for ( i
= 0 ; except_fds
[ i
] >= 0 ; i
++)
2194 if ( except_fds
[ i
] == fd
) {
2202 if ( pa_close ( fd
) < 0 ) {
2203 saved_errno
= errno
;
2205 errno
= saved_errno
;
2217 if ( getrlimit ( RLIMIT_NOFILE
, & rl
) < 0 )
2220 for ( fd
= 3 ; fd
< ( int ) rl
. rlim_max
; fd
++) {
2225 for ( i
= 0 ; except_fds
[ i
] >= 0 ; i
++)
2226 if ( except_fds
[ i
] == fd
) {
2234 if ( pa_close ( fd
) < 0 && errno
!= EBADF
)
2241 int pa_unblock_sigs ( int except
, ...) {
2246 va_start ( ap
, except
);
2249 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2254 p
= pa_xnew ( int , n
+ 1 );
2256 va_start ( ap
, except
);
2263 while (( sig
= va_arg ( ap
, int )) >= 0 )
2270 r
= pa_unblock_sigsv ( p
);
2276 int pa_unblock_sigsv ( const int except
[]) {
2280 if ( sigemptyset (& ss
) < 0 )
2283 for ( i
= 0 ; except
[ i
] > 0 ; i
++)
2284 if ( sigaddset (& ss
, except
[ i
]) < 0 )
2287 return sigprocmask ( SIG_SETMASK
, & ss
, NULL
);
2290 int pa_reset_sigs ( int except
, ...) {
2295 va_start ( ap
, except
);
2298 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2303 p
= pa_xnew ( int , n
+ 1 );
2305 va_start ( ap
, except
);
2312 while (( sig
= va_arg ( ap
, int )) >= 0 )
2319 r
= pa_reset_sigsv ( p
);
2325 int pa_reset_sigsv ( const int except
[]) {
2328 for ( sig
= 1 ; sig
< _NSIG
; sig
++) {
2329 pa_bool_t reset
= TRUE
;
2340 for ( i
= 0 ; except
[ i
] > 0 ; i
++) {
2341 if ( sig
== except
[ i
]) {
2350 struct sigaction sa
;
2352 memset (& sa
, 0 , sizeof ( sa
));
2353 sa
. sa_handler
= SIG_DFL
;
2355 /* On Linux the first two RT signals are reserved by
2356 * glibc, and sigaction() will return EINVAL for them. */
2357 if (( sigaction ( sig
, & sa
, NULL
) < 0 ))
2358 if ( errno
!= EINVAL
)
2366 void pa_set_env ( const char * key
, const char * value
) {
2370 putenv ( pa_sprintf_malloc ( "%s=%s" , key
, value
));
2373 pa_bool_t
pa_in_system_mode ( void ) {
2376 if (!( e
= getenv ( "PULSE_SYSTEM" )))
2382 char * pa_machine_id ( void ) {
2386 if (( f
= fopen ( PA_MACHINE_ID
, "r" ))) {
2387 char ln
[ 34 ] = "" , * r
;
2389 r
= fgets ( ln
, sizeof ( ln
)- 1 , f
);
2393 return pa_xstrdup ( pa_strip_nl ( ln
));
2403 if (! pa_get_host_name ( c
, l
)) {
2405 if ( errno
== EINVAL
|| errno
== ENAMETOOLONG
) {
2414 if ( strlen ( c
) < l
- 1 )
2417 /* Hmm, the hostname is as long the space we offered the
2418 * function, we cannot know if it fully fit in, so let's play
2419 * safe and retry. */