2004-07-16 19:56:36 +00:00
/***
2006-06-19 21:53:48 +00:00
This file is part of PulseAudio .
2007-01-04 13:43:45 +00:00
2007-02-13 15:35:19 +00:00
Copyright 2004 - 2006 Lennart Poettering
Copyright 2006 Pierre Ossman < ossman @ cendio . se > for Cendio AB
2006-06-19 21:53:48 +00:00
PulseAudio is free software ; you can redistribute it and / or modify
2004-11-14 14:58:54 +00:00
it under the terms of the GNU Lesser General Public License as published
2009-03-03 20:23:02 +00:00
by the Free Software Foundation ; either version 2.1 of the License ,
2004-07-16 19:56:36 +00:00
or ( at your option ) any later version .
2007-01-04 13:43:45 +00:00
2006-06-19 21:53:48 +00:00
PulseAudio is distributed in the hope that it will be useful , but
2004-07-16 19:56:36 +00:00
WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
General Public License for more details .
2007-01-04 13:43:45 +00:00
2004-11-14 14:58:54 +00:00
You should have received a copy of the GNU Lesser General Public License
2006-06-19 21:53:48 +00:00
along with PulseAudio ; if not , write to the Free Software
2004-07-16 19:56:36 +00:00
Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307
USA .
* * */
2004-07-16 19:16:42 +00:00
# ifdef HAVE_CONFIG_H
# include <config.h>
# endif
2004-07-15 19:00:42 +00:00
# include <unistd.h>
# include <errno.h>
# include <string.h>
2004-07-14 21:52:41 +00:00
# include <stdlib.h>
2004-06-11 21:30:16 +00:00
# include <stdio.h>
# include <signal.h>
2004-06-08 23:54:24 +00:00
# include <stddef.h>
2004-06-11 00:33:43 +00:00
# include <ltdl.h>
2004-11-20 23:48:18 +00:00
# include <limits.h>
2004-12-14 14:09:00 +00:00
# include <fcntl.h>
2006-01-10 17:51:06 +00:00
# include <unistd.h>
2006-05-18 10:36:36 +00:00
# include <locale.h>
2006-01-10 17:51:06 +00:00
# include <sys/types.h>
2006-07-19 17:44:19 +00:00
2006-01-27 16:25:31 +00:00
# include <liboil/liboil.h>
2006-01-10 17:51:06 +00:00
# ifdef HAVE_SYS_IOCTL_H
2004-12-14 14:20:52 +00:00
# include <sys/ioctl.h>
2006-01-10 17:51:06 +00:00
# endif
2004-06-08 23:54:24 +00:00
2006-07-20 13:16:23 +00:00
# ifdef HAVE_PWD_H
# include <pwd.h>
# endif
# ifdef HAVE_GRP_H
# include <grp.h>
# endif
2004-09-29 20:13:05 +00:00
# ifdef HAVE_LIBWRAP
# include <syslog.h>
# include <tcpd.h>
# endif
2007-10-28 19:13:50 +00:00
# ifdef HAVE_DBUS
# include <dbus/dbus.h>
# endif
2006-06-19 21:53:48 +00:00
# include <pulse/mainloop.h>
# include <pulse/mainloop-signal.h>
2006-07-20 00:28:18 +00:00
# include <pulse/timeval.h>
2006-06-19 21:53:48 +00:00
# include <pulse/xmalloc.h>
2008-08-06 18:54:13 +02:00
# include <pulse/i18n.h>
2006-06-19 21:53:48 +00:00
2008-09-08 17:22:27 +03:00
# include <pulsecore/lock-autospawn.h>
2007-10-28 19:13:50 +00:00
# include <pulsecore/winsock.h>
2006-06-19 21:53:48 +00:00
# include <pulsecore/core-error.h>
# include <pulsecore/core.h>
# include <pulsecore/memblock.h>
# include <pulsecore/module.h>
# include <pulsecore/cli-command.h>
# include <pulsecore/log.h>
# include <pulsecore/core-util.h>
# include <pulsecore/sioman.h>
# include <pulsecore/cli-text.h>
# include <pulsecore/pid.h>
# include <pulsecore/namereg.h>
# include <pulsecore/random.h>
2007-10-28 19:13:50 +00:00
# include <pulsecore/rtsig.h>
# include <pulsecore/rtclock.h>
# include <pulsecore/macro.h>
# include <pulsecore/mutex.h>
# include <pulsecore/thread.h>
# include <pulsecore/once.h>
# include <pulsecore/shm.h>
2009-03-20 18:39:30 +02:00
# ifdef HAVE_DBUS
# include <pulsecore/dbus-shared.h>
# endif
2006-02-17 12:10:58 +00:00
# include "cmdline.h"
2004-09-03 20:14:23 +00:00
# include "cpulimit.h"
2004-09-17 20:06:17 +00:00
# include "daemon-conf.h"
2004-09-13 23:28:30 +00:00
# include "dumpmodules.h"
2004-09-23 15:47:11 +00:00
# include "caps.h"
2007-10-28 19:13:50 +00:00
# include "ltdl-bind-now.h"
2007-11-21 01:30:40 +00:00
# include "polkit.h"
2004-06-08 23:54:24 +00:00
2004-09-29 20:13:05 +00:00
# ifdef HAVE_LIBWRAP
/* Only one instance of these variables */
int allow_severity = LOG_INFO ;
int deny_severity = LOG_WARNING ;
# endif
2006-05-26 17:59:39 +00:00
# ifdef HAVE_OSS
/* padsp looks for this symbol in the running process and disables
* itself if it finds it and it is set to 7 ( which is actually a bit
* mask ) . For details see padsp . */
int __padsp_disabled__ = 7 ;
# endif
2006-01-10 17:51:06 +00:00
# ifdef OS_IS_WIN32
2008-08-09 16:20:29 +02:00
static void message_cb ( pa_mainloop_api * a , pa_time_event * e , const struct timeval * tv , void * userdata ) {
2006-01-10 17:51:06 +00:00
MSG msg ;
2006-04-19 11:53:24 +00:00
struct timeval tvnext ;
2006-01-10 17:51:06 +00:00
2008-05-15 23:34:41 +00:00
while ( PeekMessage ( & msg , NULL , 0 , 0 , PM_REMOVE ) ) {
2006-01-10 17:51:06 +00:00
if ( msg . message = = WM_QUIT )
raise ( SIGTERM ) ;
else {
TranslateMessage ( & msg ) ;
DispatchMessage ( & msg ) ;
}
}
2006-04-19 11:53:24 +00:00
pa_timeval_add ( pa_gettimeofday ( & tvnext ) , 100000 ) ;
a - > time_restart ( e , & tvnext ) ;
2006-01-10 17:51:06 +00:00
}
# endif
2008-08-09 16:20:29 +02:00
static void signal_callback ( pa_mainloop_api * m , pa_signal_event * e , int sig , void * userdata ) {
2008-08-06 18:54:13 +02:00
pa_log_info ( _ ( " Got signal %s. " ) , pa_sig2str ( sig ) ) ;
2004-09-03 20:14:23 +00:00
switch ( sig ) {
2006-01-10 17:51:06 +00:00
# ifdef SIGUSR1
2004-09-03 20:14:23 +00:00
case SIGUSR1 :
pa_module_load ( userdata , " module-cli " , NULL ) ;
2005-01-12 18:51:38 +00:00
break ;
2006-01-10 17:51:06 +00:00
# endif
2007-01-04 13:43:45 +00:00
2006-01-10 17:51:06 +00:00
# ifdef SIGUSR2
2004-09-03 20:14:23 +00:00
case SIGUSR2 :
pa_module_load ( userdata , " module-cli-protocol-unix " , NULL ) ;
2005-01-12 18:51:38 +00:00
break ;
2006-01-10 17:51:06 +00:00
# endif
2004-09-26 17:02:26 +00:00
2006-01-10 17:51:06 +00:00
# ifdef SIGHUP
2004-09-26 17:02:26 +00:00
case SIGHUP : {
2005-01-12 18:51:38 +00:00
char * c = pa_full_status_string ( userdata ) ;
2006-02-23 02:27:19 +00:00
pa_log_notice ( " %s " , c ) ;
2005-01-12 18:51:38 +00:00
pa_xfree ( c ) ;
2004-09-26 17:02:26 +00:00
return ;
}
2006-01-10 17:51:06 +00:00
# endif
2004-09-26 17:02:26 +00:00
2004-09-03 20:14:23 +00:00
case SIGINT :
case SIGTERM :
default :
2008-08-06 18:54:13 +02:00
pa_log_info ( _ ( " Exiting. " ) ) ;
2004-09-03 20:14:23 +00:00
m - > quit ( m , 1 ) ;
2005-01-12 18:51:38 +00:00
break ;
2004-09-03 20:14:23 +00:00
}
2004-06-11 21:30:16 +00:00
}
2006-07-20 13:16:23 +00:00
# if defined(HAVE_PWD_H) && defined(HAVE_GRP_H)
2006-07-19 17:44:19 +00:00
static int change_user ( void ) {
struct passwd * pw ;
struct group * gr ;
int r ;
2006-07-19 23:16:02 +00:00
/* This function is called only in system-wide mode. It creates a
* runtime dir in / var / run / with proper UID / GID and drops privs
* afterwards . */
2007-01-04 13:43:45 +00:00
2006-07-19 17:44:19 +00:00
if ( ! ( pw = getpwnam ( PA_SYSTEM_USER ) ) ) {
2008-08-06 18:54:13 +02:00
pa_log ( _ ( " Failed to find user '%s'. " ) , PA_SYSTEM_USER ) ;
2006-07-19 17:44:19 +00:00
return - 1 ;
}
if ( ! ( gr = getgrnam ( PA_SYSTEM_GROUP ) ) ) {
2008-08-06 18:54:13 +02:00
pa_log ( _ ( " Failed to find group '%s'. " ) , PA_SYSTEM_GROUP ) ;
2006-07-19 17:44:19 +00:00
return - 1 ;
}
2008-08-06 18:54:13 +02:00
pa_log_info ( _ ( " Found user '%s' (UID %lu) and group '%s' (GID %lu). " ) ,
2006-07-19 17:44:19 +00:00
PA_SYSTEM_USER , ( unsigned long ) pw - > pw_uid ,
PA_SYSTEM_GROUP , ( unsigned long ) gr - > gr_gid ) ;
if ( pw - > pw_gid ! = gr - > gr_gid ) {
2008-08-06 18:54:13 +02:00
pa_log ( _ ( " GID of user '%s' and of group '%s' don't match. " ) , PA_SYSTEM_USER , PA_SYSTEM_GROUP ) ;
2006-07-19 17:44:19 +00:00
return - 1 ;
}
if ( strcmp ( pw - > pw_dir , PA_SYSTEM_RUNTIME_PATH ) ! = 0 )
2008-08-06 18:54:13 +02:00
pa_log_warn ( _ ( " Home directory of user '%s' is not '%s', ignoring. " ) , PA_SYSTEM_USER , PA_SYSTEM_RUNTIME_PATH ) ;
2006-07-19 17:44:19 +00:00
if ( pa_make_secure_dir ( PA_SYSTEM_RUNTIME_PATH , 0755 , pw - > pw_uid , gr - > gr_gid ) < 0 ) {
2008-08-06 18:54:13 +02:00
pa_log ( _ ( " Failed to create '%s': %s " ) , PA_SYSTEM_RUNTIME_PATH , pa_cstrerror ( errno ) ) ;
2006-07-19 17:44:19 +00:00
return - 1 ;
}
2007-01-04 13:43:45 +00:00
2008-05-21 22:50:58 +00:00
if ( pa_make_secure_dir ( PA_SYSTEM_STATE_PATH , 0700 , pw - > pw_uid , gr - > gr_gid ) < 0 ) {
2008-08-06 18:54:13 +02:00
pa_log ( _ ( " Failed to create '%s': %s " ) , PA_SYSTEM_STATE_PATH , pa_cstrerror ( errno ) ) ;
2008-05-21 22:50:58 +00:00
return - 1 ;
}
/* We don't create the config dir here, because we don't need to write to it */
2006-07-19 17:44:19 +00:00
if ( initgroups ( PA_SYSTEM_USER , gr - > gr_gid ) ! = 0 ) {
2008-08-06 18:54:13 +02:00
pa_log ( _ ( " Failed to change group list: %s " ) , pa_cstrerror ( errno ) ) ;
2006-07-19 17:44:19 +00:00
return - 1 ;
}
# if defined(HAVE_SETRESGID)
r = setresgid ( gr - > gr_gid , gr - > gr_gid , gr - > gr_gid ) ;
# elif defined(HAVE_SETEGID)
if ( ( r = setgid ( gr - > gr_gid ) ) > = 0 )
r = setegid ( gr - > gr_gid ) ;
# elif defined(HAVE_SETREGID)
r = setregid ( gr - > gr_gid , gr - > gr_gid ) ;
# else
2008-10-19 22:25:58 +02:00
# error "No API to drop privileges"
2006-07-19 17:44:19 +00:00
# endif
if ( r < 0 ) {
2008-08-06 18:54:13 +02:00
pa_log ( _ ( " Failed to change GID: %s " ) , pa_cstrerror ( errno ) ) ;
2006-07-19 17:44:19 +00:00
return - 1 ;
}
# if defined(HAVE_SETRESUID)
r = setresuid ( pw - > pw_uid , pw - > pw_uid , pw - > pw_uid ) ;
# elif defined(HAVE_SETEUID)
if ( ( r = setuid ( pw - > pw_uid ) ) > = 0 )
r = seteuid ( pw - > pw_uid ) ;
# elif defined(HAVE_SETREUID)
r = setreuid ( pw - > pw_uid , pw - > pw_uid ) ;
# else
2008-10-19 22:25:58 +02:00
# error "No API to drop privileges"
2006-07-19 17:44:19 +00:00
# endif
if ( r < 0 ) {
2008-08-06 18:54:13 +02:00
pa_log ( _ ( " Failed to change UID: %s " ) , pa_cstrerror ( errno ) ) ;
2006-07-19 17:44:19 +00:00
return - 1 ;
}
2008-05-15 23:34:41 +00:00
pa_set_env ( " USER " , PA_SYSTEM_USER ) ;
pa_set_env ( " USERNAME " , PA_SYSTEM_USER ) ;
pa_set_env ( " LOGNAME " , PA_SYSTEM_USER ) ;
pa_set_env ( " HOME " , PA_SYSTEM_RUNTIME_PATH ) ;
2006-07-19 17:44:19 +00:00
/* Relevant for pa_runtime_path() */
2008-05-15 23:34:41 +00:00
pa_set_env ( " PULSE_RUNTIME_PATH " , PA_SYSTEM_RUNTIME_PATH ) ;
2008-05-21 22:50:58 +00:00
pa_set_env ( " PULSE_CONFIG_PATH " , PA_SYSTEM_CONFIG_PATH ) ;
pa_set_env ( " PULSE_STATE_PATH " , PA_SYSTEM_STATE_PATH ) ;
2006-07-19 17:44:19 +00:00
2008-08-06 18:54:13 +02:00
pa_log_info ( _ ( " Successfully dropped root privileges. " ) ) ;
2006-07-19 17:44:19 +00:00
return 0 ;
}
2006-07-20 13:16:23 +00:00
# else /* HAVE_PWD_H && HAVE_GRP_H */
static int change_user ( void ) {
2008-08-06 18:54:13 +02:00
pa_log ( _ ( " System wide mode unsupported on this platform. " ) ) ;
2006-07-20 13:16:23 +00:00
return - 1 ;
}
# endif /* HAVE_PWD_H && HAVE_GRP_H */
2006-07-20 01:25:37 +00:00
# ifdef HAVE_SYS_RESOURCE_H
2007-11-21 01:30:40 +00:00
static int set_one_rlimit ( const pa_rlimit * r , int resource , const char * name ) {
2006-07-20 01:25:37 +00:00
struct rlimit rl ;
2007-10-28 19:13:50 +00:00
pa_assert ( r ) ;
2006-07-20 01:25:37 +00:00
if ( ! r - > is_set )
2007-11-21 01:30:40 +00:00
return 0 ;
2006-07-20 01:25:37 +00:00
rl . rlim_cur = rl . rlim_max = r - > value ;
2007-11-21 01:30:40 +00:00
if ( setrlimit ( resource , & rl ) < 0 ) {
2008-08-06 18:54:13 +02:00
pa_log_info ( _ ( " setrlimit(%s, (%u, %u)) failed: %s " ) , name , ( unsigned ) r - > value , ( unsigned ) r - > value , pa_cstrerror ( errno ) ) ;
2007-11-21 01:30:40 +00:00
return - 1 ;
}
return 0 ;
2006-07-20 01:25:37 +00:00
}
static void set_all_rlimits ( const pa_daemon_conf * conf ) {
set_one_rlimit ( & conf - > rlimit_fsize , RLIMIT_FSIZE , " RLIMIT_FSIZE " ) ;
2008-05-15 23:34:41 +00:00
set_one_rlimit ( & conf - > rlimit_data , RLIMIT_DATA , " RLIMIT_DATA " ) ;
2006-07-20 01:25:37 +00:00
set_one_rlimit ( & conf - > rlimit_stack , RLIMIT_STACK , " RLIMIT_STACK " ) ;
2008-05-15 23:34:41 +00:00
set_one_rlimit ( & conf - > rlimit_core , RLIMIT_CORE , " RLIMIT_CORE " ) ;
2009-02-26 16:48:58 +11:00
# ifdef RLIMIT_RSS
2008-05-15 23:34:41 +00:00
set_one_rlimit ( & conf - > rlimit_rss , RLIMIT_RSS , " RLIMIT_RSS " ) ;
2009-02-26 16:48:58 +11:00
# endif
2006-07-20 01:25:37 +00:00
# ifdef RLIMIT_NPROC
set_one_rlimit ( & conf - > rlimit_nproc , RLIMIT_NPROC , " RLIMIT_NPROC " ) ;
# endif
2009-01-27 00:48:53 +01:00
# ifdef RLIMIT_NOFILE
2008-05-15 23:34:41 +00:00
set_one_rlimit ( & conf - > rlimit_nofile , RLIMIT_NOFILE , " RLIMIT_NOFILE " ) ;
2009-01-27 00:48:53 +01:00
# endif
2006-07-20 01:25:37 +00:00
# ifdef RLIMIT_MEMLOCK
set_one_rlimit ( & conf - > rlimit_memlock , RLIMIT_MEMLOCK , " RLIMIT_MEMLOCK " ) ;
2008-05-15 23:34:41 +00:00
# endif
2009-01-22 01:39:54 +01:00
# ifdef RLIMIT_AS
2008-05-15 23:34:41 +00:00
set_one_rlimit ( & conf - > rlimit_as , RLIMIT_AS , " RLIMIT_AS " ) ;
2009-01-22 01:39:54 +01:00
# endif
2008-05-15 23:34:41 +00:00
# ifdef RLIMIT_LOCKS
set_one_rlimit ( & conf - > rlimit_locks , RLIMIT_LOCKS , " RLIMIT_LOCKS " ) ;
# endif
# ifdef RLIMIT_SIGPENDING
set_one_rlimit ( & conf - > rlimit_sigpending , RLIMIT_SIGPENDING , " RLIMIT_SIGPENDING " ) ;
# endif
# ifdef RLIMIT_MSGQUEUE
set_one_rlimit ( & conf - > rlimit_msgqueue , RLIMIT_MSGQUEUE , " RLIMIT_MSGQUEUE " ) ;
2006-07-20 01:25:37 +00:00
# endif
2007-11-01 00:34:43 +00:00
# ifdef RLIMIT_NICE
set_one_rlimit ( & conf - > rlimit_nice , RLIMIT_NICE , " RLIMIT_NICE " ) ;
# endif
# ifdef RLIMIT_RTPRIO
set_one_rlimit ( & conf - > rlimit_rtprio , RLIMIT_RTPRIO , " RLIMIT_RTPRIO " ) ;
# endif
2008-05-15 23:34:41 +00:00
# ifdef RLIMIT_RTTIME
set_one_rlimit ( & conf - > rlimit_rttime , RLIMIT_RTTIME , " RLIMIT_RTTIME " ) ;
# endif
2006-07-20 01:25:37 +00:00
}
# endif
2009-03-20 18:39:30 +02:00
# ifdef HAVE_DBUS
static void register_org_pulseaudio ( pa_core * c )
{
DBusError error ;
pa_dbus_connection * conn ;
dbus_error_init ( & error ) ;
if ( ! ( conn = pa_dbus_bus_get ( c , pa_in_system_mode ( ) ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION , & error ) ) | | dbus_error_is_set ( & error ) ) {
pa_log_warn ( " Unable to contact DBUS: %s: %s " , error . name , error . message ) ;
goto finish_dbus ;
}
2009-03-30 21:07:23 +02:00
if ( dbus_bus_request_name ( pa_dbus_connection_get ( conn ) , " org.pulseaudio.Server " , DBUS_NAME_FLAG_DO_NOT_QUEUE , & error ) = = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER )
pa_log_debug ( " Got org.pulseaudio.Server! " ) ;
2009-03-20 18:39:30 +02:00
else if ( dbus_error_is_set ( & error ) )
2009-03-30 21:07:23 +02:00
pa_log_warn ( " Unable to get org.pulseaudio.Server: %s: %s " , error . name , error . message ) ;
2009-03-20 18:39:30 +02:00
finish_dbus :
if ( conn )
pa_dbus_connection_unref ( conn ) ;
dbus_error_free ( & error ) ;
}
# endif
2004-06-08 23:54:24 +00:00
int main ( int argc , char * argv [ ] ) {
2006-08-19 01:20:13 +00:00
pa_core * c = NULL ;
2006-01-11 01:17:39 +00:00
pa_strbuf * buf = NULL ;
2006-08-19 01:20:13 +00:00
pa_daemon_conf * conf = NULL ;
pa_mainloop * mainloop = NULL ;
2007-01-04 13:43:45 +00:00
char * s ;
2007-10-28 19:13:50 +00:00
int r = 0 , retval = 1 , d = 0 ;
2007-11-21 01:30:40 +00:00
pa_bool_t suid_root , real_root ;
2008-05-15 23:34:41 +00:00
pa_bool_t valid_pid_file = FALSE ;
2006-01-10 17:51:06 +00:00
gid_t gid = ( gid_t ) - 1 ;
2008-02-15 18:03:11 +00:00
pa_bool_t ltdl_init = FALSE ;
2008-05-15 23:34:41 +00:00
int passed_fd = - 1 ;
const char * e ;
# ifdef HAVE_FORK
int daemon_pipe [ 2 ] = { - 1 , - 1 } ;
# endif
2006-01-10 17:51:06 +00:00
# ifdef OS_IS_WIN32
2008-05-15 23:34:41 +00:00
pa_time_event * win32_timer ;
struct timeval win32_tv ;
2006-01-10 17:51:06 +00:00
# endif
2008-08-09 03:49:42 +02:00
int autospawn_fd = - 1 ;
pa_bool_t autospawn_locked = FALSE ;
2006-01-10 17:51:06 +00:00
2008-08-29 21:43:50 +02:00
pa_log_set_ident ( " pulseaudio " ) ;
2009-02-21 22:45:56 +01:00
pa_log_set_level ( PA_LOG_INFO ) ;
pa_log_set_flags ( PA_LOG_COLORS | PA_LOG_PRINT_FILE | PA_LOG_PRINT_LEVEL , PA_LOG_RESET ) ;
2008-08-29 21:43:50 +02:00
2007-10-28 19:13:50 +00:00
# if defined(__linux__) && defined(__OPTIMIZE__)
/*
Disable lazy relocations to make usage of external libraries
more deterministic for our RT threads . We abuse __OPTIMIZE__ as
a check whether we are a debug build or not .
*/
if ( ! getenv ( " LD_BIND_NOW " ) ) {
2007-10-29 15:33:07 +00:00
char * rp ;
2007-10-28 19:13:50 +00:00
/* We have to execute ourselves, because the libc caches the
* value of $ LD_BIND_NOW on initialization . */
2007-10-29 15:33:07 +00:00
2008-05-15 23:34:41 +00:00
pa_set_env ( " LD_BIND_NOW " , " 1 " ) ;
2009-02-18 21:45:06 +01:00
if ( ( rp = pa_readlink ( " /proc/self/exe " ) ) )
pa_assert_se ( execv ( rp , argv ) = = 0 ) ;
else
pa_log_warn ( " Couldn't read /proc/self/exe, cannot self execute. Running in a chroot()? " ) ;
2007-10-28 19:13:50 +00:00
}
# endif
2006-01-10 17:51:06 +00:00
# ifdef HAVE_GETUID
2006-07-20 13:24:04 +00:00
real_root = getuid ( ) = = 0 ;
suid_root = ! real_root & & geteuid ( ) = = 0 ;
2007-05-25 20:35:30 +00:00
# else
2007-11-21 01:30:40 +00:00
real_root = FALSE ;
suid_root = FALSE ;
2007-05-25 20:35:30 +00:00
# endif
2008-06-22 01:48:46 +02:00
if ( ! real_root ) {
2007-10-28 19:13:50 +00:00
/* Drop all capabilities except CAP_SYS_NICE */
pa_limit_caps ( ) ;
2008-10-19 22:25:58 +02:00
/* Drop privileges, but keep CAP_SYS_NICE */
2007-10-28 19:13:50 +00:00
pa_drop_root ( ) ;
/* After dropping root, the effective set is reset, hence,
* let ' s raise it again */
pa_limit_caps ( ) ;
/* When capabilities are not supported we will not be able to
2009-04-01 12:35:44 +02:00
* acquire RT sched anymore . But yes , that ' s the way it is . It
2007-10-28 19:13:50 +00:00
* is just too risky tun let PA run as root all the time . */
2007-05-25 20:35:30 +00:00
}
2008-05-15 23:34:41 +00:00
if ( ( e = getenv ( " PULSE_PASSED_FD " ) ) ) {
passed_fd = atoi ( e ) ;
if ( passed_fd < = 2 )
passed_fd = - 1 ;
}
pa_close_all ( passed_fd , - 1 ) ;
pa_reset_sigs ( - 1 ) ;
pa_unblock_sigs ( - 1 ) ;
2007-11-21 01:30:40 +00:00
/* At this point, we are a normal user, possibly with CAP_NICE if
* we were started SUID . If we are started as normal root , than we
* still are normal root . */
2007-01-04 13:43:45 +00:00
2007-11-21 01:30:40 +00:00
setlocale ( LC_ALL , " " ) ;
2008-08-06 18:54:13 +02:00
pa_init_i18n ( ) ;
2004-09-17 20:06:17 +00:00
conf = pa_daemon_conf_new ( ) ;
2007-01-04 13:43:45 +00:00
2004-09-17 20:06:17 +00:00
if ( pa_daemon_conf_load ( conf , NULL ) < 0 )
2004-09-13 23:28:30 +00:00
goto finish ;
2004-12-11 00:10:41 +00:00
2004-09-17 20:06:17 +00:00
if ( pa_daemon_conf_env ( conf ) < 0 )
goto finish ;
2004-12-11 00:10:41 +00:00
2004-09-13 23:28:30 +00:00
if ( pa_cmdline_parse ( conf , argc , argv , & d ) < 0 ) {
2008-08-06 18:54:13 +02:00
pa_log ( _ ( " Failed to parse command line. " ) ) ;
2004-07-15 19:00:42 +00:00
goto finish ;
2004-07-12 21:28:11 +00:00
}
2004-12-11 00:10:41 +00:00
2009-02-21 22:45:56 +01:00
pa_log_set_level ( conf - > log_level ) ;
pa_log_set_target ( conf - > auto_log_target ? PA_LOG_STDERR : conf - > log_target ) ;
if ( conf - > log_meta )
pa_log_set_flags ( PA_LOG_PRINT_META , PA_LOG_SET ) ;
if ( conf - > log_time )
pa_log_set_flags ( PA_LOG_PRINT_TIME , PA_LOG_SET ) ;
2008-10-21 19:15:41 +02:00
pa_log_set_show_backtrace ( conf - > log_backtrace ) ;
2004-09-13 23:28:30 +00:00
2008-06-22 01:48:46 +02:00
pa_log_debug ( " Started as real root: %s, suid root: %s " , pa_yes_no ( real_root ) , pa_yes_no ( suid_root ) ) ;
2008-05-15 23:34:41 +00:00
2008-06-22 01:48:46 +02:00
if ( ! real_root & & pa_have_caps ( ) ) {
2008-12-18 01:25:54 +01:00
# ifdef HAVE_SYS_RESOURCE_H
struct rlimit rl ;
# endif
2008-06-22 01:48:46 +02:00
pa_bool_t allow_high_priority = FALSE , allow_realtime = FALSE ;
2007-11-21 01:30:40 +00:00
2008-06-22 01:48:46 +02:00
/* Let's better not enable high prio or RT by default */
2007-11-21 01:30:40 +00:00
2008-06-22 01:48:46 +02:00
if ( conf - > high_priority & & ! allow_high_priority ) {
2008-05-15 23:34:41 +00:00
if ( pa_own_uid_in_group ( PA_REALTIME_GROUP , & gid ) > 0 ) {
2008-08-06 18:54:13 +02:00
pa_log_info ( _ ( " We're in the group '%s', allowing high-priority scheduling. " ) , PA_REALTIME_GROUP ) ;
2008-06-22 01:48:46 +02:00
allow_high_priority = TRUE ;
2008-05-15 23:34:41 +00:00
}
2008-06-22 01:48:46 +02:00
}
if ( conf - > realtime_scheduling & & ! allow_realtime ) {
if ( pa_own_uid_in_group ( PA_REALTIME_GROUP , & gid ) > 0 ) {
2008-08-06 18:54:13 +02:00
pa_log_info ( _ ( " We're in the group '%s', allowing real-time scheduling. " ) , PA_REALTIME_GROUP ) ;
2008-06-22 01:48:46 +02:00
allow_realtime = TRUE ;
}
}
2008-05-15 23:34:41 +00:00
2007-11-21 01:30:40 +00:00
# ifdef HAVE_POLKIT
2008-05-15 23:34:41 +00:00
if ( conf - > high_priority & & ! allow_high_priority ) {
2007-11-21 01:30:40 +00:00
if ( pa_polkit_check ( " org.pulseaudio.acquire-high-priority " ) > 0 ) {
2008-08-06 18:54:13 +02:00
pa_log_info ( _ ( " PolicyKit grants us acquire-high-priority privilege. " ) ) ;
2007-11-21 01:30:40 +00:00
allow_high_priority = TRUE ;
} else
2008-08-06 18:54:13 +02:00
pa_log_info ( _ ( " PolicyKit refuses acquire-high-priority privilege. " ) ) ;
2007-11-21 01:30:40 +00:00
}
2008-05-15 23:34:41 +00:00
if ( conf - > realtime_scheduling & & ! allow_realtime ) {
2007-11-21 01:30:40 +00:00
if ( pa_polkit_check ( " org.pulseaudio.acquire-real-time " ) > 0 ) {
2008-08-06 18:54:13 +02:00
pa_log_info ( _ ( " PolicyKit grants us acquire-real-time privilege. " ) ) ;
2007-11-21 01:30:40 +00:00
allow_realtime = TRUE ;
} else
2008-08-06 18:54:13 +02:00
pa_log_info ( _ ( " PolicyKit refuses acquire-real-time privilege. " ) ) ;
2007-11-21 01:30:40 +00:00
}
# endif
if ( ! allow_high_priority & & ! allow_realtime ) {
/* OK, there's no further need to keep CAP_NICE. Hence
* let ' s give it up early */
pa_drop_caps ( ) ;
}
2008-12-18 01:25:54 +01:00
# ifdef RLIMIT_RTPRIO
if ( getrlimit ( RLIMIT_RTPRIO , & rl ) > = 0 )
if ( rl . rlim_cur > 0 ) {
pa_log_info ( " RLIMIT_RTPRIO is set to %u, allowing real-time scheduling. " , ( unsigned ) rl . rlim_cur ) ;
allow_realtime = TRUE ;
}
# endif
# ifdef RLIMIT_NICE
if ( getrlimit ( RLIMIT_NICE , & rl ) > = 0 )
if ( rl . rlim_cur > 20 ) {
pa_log_info ( " RLIMIT_NICE is set to %u, allowing high-priority scheduling. " , ( unsigned ) rl . rlim_cur ) ;
allow_high_priority = TRUE ;
}
# endif
if ( ( conf - > high_priority & & ! allow_high_priority ) | |
( conf - > realtime_scheduling & & ! allow_realtime ) )
2009-04-03 17:49:05 +02:00
pa_log_info ( _ ( " Called SUID root and real-time and/or high-priority scheduling was requested in the configuration. However, we lack the necessary privileges: \n "
2009-02-21 17:01:01 +01:00
" We are not in group '%s', PolicyKit refuse to grant us the requested privileges and we have no increase RLIMIT_NICE/RLIMIT_RTPRIO resource limits. \n "
" For enabling real-time/high-priority scheduling please acquire the appropriate PolicyKit privileges, or become a member of '%s', or increase the RLIMIT_NICE/RLIMIT_RTPRIO resource limits for this user. " ) ,
PA_REALTIME_GROUP , PA_REALTIME_GROUP ) ;
2008-12-18 01:25:54 +01:00
if ( ! allow_realtime )
conf - > realtime_scheduling = FALSE ;
if ( ! allow_high_priority )
conf - > high_priority = FALSE ;
2007-11-21 01:30:40 +00:00
}
2008-05-15 23:34:41 +00:00
# ifdef HAVE_SYS_RESOURCE_H
/* Reset resource limits. If we are run as root (for system mode)
* this might end up increasing the limits , which is intended
* behaviour . For all other cases , i . e . started as normal user , or
* SUID root at this point we should have no CAP_SYS_RESOURCE and
* increasing the limits thus should fail . Which is , too , intended
* behaviour */
2007-11-21 01:30:40 +00:00
2008-05-15 23:34:41 +00:00
set_all_rlimits ( conf ) ;
# endif
2008-12-18 01:25:54 +01:00
if ( conf - > high_priority & & ! pa_can_high_priority ( ) ) {
2009-04-03 17:49:05 +02:00
pa_log_info ( _ ( " High-priority scheduling enabled in configuration but not allowed by policy. " ) ) ;
2008-12-18 01:25:54 +01:00
conf - > high_priority = FALSE ;
}
2007-11-21 01:30:40 +00:00
2008-06-11 17:38:50 +00:00
if ( conf - > high_priority & & ( conf - > cmd = = PA_CMD_DAEMON | | conf - > cmd = = PA_CMD_START ) )
2007-11-01 02:58:26 +00:00
pa_raise_priority ( conf - > nice_level ) ;
2004-09-23 22:42:49 +00:00
2008-12-18 01:25:54 +01:00
pa_log_debug ( " Can realtime: %s, can high-priority: %s " , pa_yes_no ( pa_can_realtime ( ) ) , pa_yes_no ( pa_can_high_priority ( ) ) ) ;
2008-07-22 21:13:46 +02:00
if ( ! real_root & & pa_have_caps ( ) ) {
2007-11-21 01:30:40 +00:00
pa_bool_t drop ;
2008-06-11 17:38:50 +00:00
drop = ( conf - > cmd ! = PA_CMD_DAEMON & & conf - > cmd ! = PA_CMD_START ) | | ! conf - > realtime_scheduling ;
2007-11-21 01:30:40 +00:00
# ifdef RLIMIT_RTPRIO
if ( ! drop ) {
2008-05-15 23:34:41 +00:00
struct rlimit rl ;
2007-11-21 01:30:40 +00:00
/* At this point we still have CAP_NICE if we were loaded
* SUID root . If possible let ' s acquire RLIMIT_RTPRIO
* instead and give CAP_NICE up . */
2008-05-15 23:34:41 +00:00
if ( getrlimit ( RLIMIT_RTPRIO , & rl ) > = 0 ) {
2007-11-21 01:30:40 +00:00
2008-05-15 23:34:41 +00:00
if ( rl . rlim_cur > = 9 )
drop = TRUE ;
else {
rl . rlim_max = rl . rlim_cur = 9 ;
if ( setrlimit ( RLIMIT_RTPRIO , & rl ) > = 0 ) {
2008-08-06 18:54:13 +02:00
pa_log_info ( _ ( " Successfully increased RLIMIT_RTPRIO " ) ) ;
2008-05-15 23:34:41 +00:00
drop = TRUE ;
} else
2008-08-06 18:54:13 +02:00
pa_log_warn ( _ ( " RLIMIT_RTPRIO failed: %s " ) , pa_cstrerror ( errno ) ) ;
2008-05-15 23:34:41 +00:00
}
}
2007-11-21 01:30:40 +00:00
}
# endif
if ( drop ) {
2008-08-06 18:54:13 +02:00
pa_log_info ( _ ( " Giving up CAP_NICE " ) ) ;
2007-11-21 01:30:40 +00:00
pa_drop_caps ( ) ;
2008-05-15 23:34:41 +00:00
suid_root = FALSE ;
2007-11-21 01:30:40 +00:00
}
2007-05-25 20:35:30 +00:00
}
2006-07-20 01:25:37 +00:00
2008-12-18 01:25:54 +01:00
if ( conf - > realtime_scheduling & & ! pa_can_realtime ( ) ) {
2009-04-03 17:49:05 +02:00
pa_log_info ( _ ( " Real-time scheduling enabled in configuration but not allowed by policy. " ) ) ;
2008-12-18 01:25:54 +01:00
conf - > realtime_scheduling = FALSE ;
}
2008-05-15 23:34:41 +00:00
2008-06-22 01:48:46 +02:00
pa_log_debug ( " Can realtime: %s, can high-priority: %s " , pa_yes_no ( pa_can_realtime ( ) ) , pa_yes_no ( pa_can_high_priority ( ) ) ) ;
2007-11-21 01:30:40 +00:00
LTDL_SET_PRELOADED_SYMBOLS ( ) ;
pa_ltdl_init ( ) ;
2008-02-15 18:03:11 +00:00
ltdl_init = TRUE ;
2007-11-21 01:30:40 +00:00
2004-09-13 23:28:30 +00:00
if ( conf - > dl_search_path )
lt_dlsetsearchpath ( conf - > dl_search_path ) ;
2007-11-21 01:30:40 +00:00
# ifdef OS_IS_WIN32
{
WSADATA data ;
WSAStartup ( MAKEWORD ( 2 , 0 ) , & data ) ;
}
# endif
pa_random_seed ( ) ;
2004-09-14 17:52:11 +00:00
switch ( conf - > cmd ) {
case PA_CMD_DUMP_MODULES :
pa_dump_modules ( conf , argc - d , argv + d ) ;
retval = 0 ;
goto finish ;
2004-09-05 00:03:16 +00:00
2004-09-14 17:52:11 +00:00
case PA_CMD_DUMP_CONF : {
2006-01-11 01:17:39 +00:00
s = pa_daemon_conf_dump ( conf ) ;
2004-09-14 17:52:11 +00:00
fputs ( s , stdout ) ;
pa_xfree ( s ) ;
retval = 0 ;
goto finish ;
}
2004-07-15 19:00:42 +00:00
2007-10-28 19:13:50 +00:00
case PA_CMD_DUMP_RESAMPLE_METHODS : {
int i ;
for ( i = 0 ; i < PA_RESAMPLER_MAX ; i + + )
if ( pa_resample_method_supported ( i ) )
printf ( " %s \n " , pa_resample_method_to_string ( i ) ) ;
2008-12-16 18:17:21 +01:00
retval = 0 ;
2007-10-28 19:13:50 +00:00
goto finish ;
}
2004-09-14 17:52:11 +00:00
case PA_CMD_HELP :
pa_cmdline_help ( argv [ 0 ] ) ;
retval = 0 ;
goto finish ;
2004-09-01 00:23:51 +00:00
2004-09-14 17:52:11 +00:00
case PA_CMD_VERSION :
printf ( PACKAGE_NAME " " PACKAGE_VERSION " \n " ) ;
retval = 0 ;
goto finish ;
2004-11-20 23:48:18 +00:00
case PA_CMD_CHECK : {
pid_t pid ;
2007-11-21 01:30:40 +00:00
if ( pa_pid_file_check_running ( & pid , " pulseaudio " ) < 0 )
2008-08-06 18:54:13 +02:00
pa_log_info ( _ ( " Daemon not running " ) ) ;
2007-11-21 01:30:40 +00:00
else {
2008-08-06 18:54:13 +02:00
pa_log_info ( _ ( " Daemon running as PID %u " ) , pid ) ;
2004-11-20 23:48:18 +00:00
retval = 0 ;
}
goto finish ;
}
case PA_CMD_KILL :
2007-11-21 01:30:40 +00:00
if ( pa_pid_file_kill ( SIGINT , NULL , " pulseaudio " ) < 0 )
2008-08-09 03:47:59 +02:00
pa_log ( _ ( " Failed to kill daemon: %s " ) , pa_cstrerror ( errno ) ) ;
2004-11-20 23:48:18 +00:00
else
retval = 0 ;
2007-01-04 13:43:45 +00:00
2004-11-20 23:48:18 +00:00
goto finish ;
2007-01-04 13:43:45 +00:00
2007-10-28 19:13:50 +00:00
case PA_CMD_CLEANUP_SHM :
if ( pa_shm_cleanup ( ) > = 0 )
retval = 0 ;
goto finish ;
2004-09-14 17:52:11 +00:00
default :
2008-06-11 17:38:50 +00:00
pa_assert ( conf - > cmd = = PA_CMD_DAEMON | | conf - > cmd = = PA_CMD_START ) ;
2004-09-14 17:52:11 +00:00
}
2004-09-01 00:23:51 +00:00
2007-11-21 01:30:40 +00:00
if ( real_root & & ! conf - > system_instance )
2008-08-06 18:54:13 +02:00
pa_log_warn ( _ ( " This program is not intended to be run as root (unless --system is specified). " ) ) ;
2007-11-21 01:30:40 +00:00
else if ( ! real_root & & conf - > system_instance ) {
2008-10-19 22:25:58 +02:00
pa_log ( _ ( " Root privileges required. " ) ) ;
2006-07-19 17:44:19 +00:00
goto finish ;
}
2008-07-30 20:36:34 +02:00
if ( conf - > cmd = = PA_CMD_START & & conf - > system_instance ) {
2008-08-06 18:54:13 +02:00
pa_log ( _ ( " --start not supported for system instances. " ) ) ;
2008-07-30 20:36:34 +02:00
goto finish ;
}
2008-08-06 19:56:15 +02:00
if ( conf - > system_instance & & ! conf - > disallow_exit )
pa_log_warn ( _ ( " Running in system mode, but --disallow-exit not set! " ) ) ;
if ( conf - > system_instance & & ! conf - > disallow_module_loading )
pa_log_warn ( _ ( " Running in system mode, but --disallow-module-loading not set! " ) ) ;
if ( conf - > system_instance & & ! conf - > disable_shm ) {
pa_log_notice ( _ ( " Running in system mode, forcibly disabling SHM mode! " ) ) ;
conf - > disable_shm = TRUE ;
}
2008-10-07 02:00:07 +02:00
if ( conf - > system_instance & & conf - > exit_idle_time > = 0 ) {
2008-08-06 19:56:15 +02:00
pa_log_notice ( _ ( " Running in system mode, forcibly disabling exit idle time! " ) ) ;
2008-10-07 02:00:07 +02:00
conf - > exit_idle_time = - 1 ;
2008-08-06 19:56:15 +02:00
}
2008-06-11 17:38:50 +00:00
if ( conf - > cmd = = PA_CMD_START ) {
/* If we shall start PA only when it is not running yet, we
* first take the autospawn lock to make things
* synchronous . */
2008-08-09 03:49:42 +02:00
if ( ( autospawn_fd = pa_autospawn_lock_init ( ) ) < 0 ) {
pa_log ( " Failed to initialize autospawn lock " ) ;
goto finish ;
}
if ( ( pa_autospawn_lock_acquire ( TRUE ) < 0 ) ) {
pa_log ( " Failed to acquire autospawn lock " ) ;
goto finish ;
}
autospawn_locked = TRUE ;
2008-06-11 17:38:50 +00:00
}
2004-09-13 23:28:30 +00:00
if ( conf - > daemonize ) {
2004-07-15 19:00:42 +00:00
pid_t child ;
2004-12-14 14:20:52 +00:00
int tty_fd ;
2004-07-15 19:00:42 +00:00
if ( pa_stdio_acquire ( ) < 0 ) {
2008-08-06 18:54:13 +02:00
pa_log ( _ ( " Failed to acquire stdio. " ) ) ;
2004-07-15 19:00:42 +00:00
goto finish ;
}
2006-01-10 17:51:06 +00:00
# ifdef HAVE_FORK
2004-07-15 19:00:42 +00:00
if ( pipe ( daemon_pipe ) < 0 ) {
2008-08-06 18:54:13 +02:00
pa_log ( _ ( " pipe failed: %s " ) , pa_cstrerror ( errno ) ) ;
2004-07-15 19:00:42 +00:00
goto finish ;
}
2007-01-04 13:43:45 +00:00
2004-07-15 19:00:42 +00:00
if ( ( child = fork ( ) ) < 0 ) {
2008-08-06 18:54:13 +02:00
pa_log ( _ ( " fork() failed: %s " ) , pa_cstrerror ( errno ) ) ;
2004-07-15 19:00:42 +00:00
goto finish ;
}
if ( child ! = 0 ) {
2008-05-15 23:34:41 +00:00
ssize_t n ;
2004-07-15 19:00:42 +00:00
/* Father */
2007-10-28 19:13:50 +00:00
pa_assert_se ( pa_close ( daemon_pipe [ 1 ] ) = = 0 ) ;
2004-07-15 19:00:42 +00:00
daemon_pipe [ 1 ] = - 1 ;
2008-05-15 23:34:41 +00:00
if ( ( n = pa_loop_read ( daemon_pipe [ 0 ] , & retval , sizeof ( retval ) , NULL ) ) ! = sizeof ( retval ) ) {
if ( n < 0 )
2008-08-06 18:54:13 +02:00
pa_log ( _ ( " read() failed: %s " ) , pa_cstrerror ( errno ) ) ;
2008-05-15 23:34:41 +00:00
2004-07-15 19:00:42 +00:00
retval = 1 ;
}
2004-12-11 00:10:41 +00:00
if ( retval )
2008-08-06 18:54:13 +02:00
pa_log ( _ ( " Daemon startup failed. " ) ) ;
2004-12-11 00:10:41 +00:00
else
2008-08-06 18:54:13 +02:00
pa_log_info ( _ ( " Daemon startup successful. " ) ) ;
2007-01-04 13:43:45 +00:00
2004-07-15 19:00:42 +00:00
goto finish ;
}
2008-08-09 03:49:42 +02:00
if ( autospawn_fd > = 0 ) {
2008-06-11 17:38:50 +00:00
/* The lock file is unlocked from the parent, so we need
* to close it in the child */
2008-08-09 03:49:42 +02:00
pa_autospawn_lock_release ( ) ;
pa_autospawn_lock_done ( TRUE ) ;
autospawn_locked = FALSE ;
autospawn_fd = - 1 ;
2008-06-11 17:38:50 +00:00
}
2007-10-28 19:13:50 +00:00
pa_assert_se ( pa_close ( daemon_pipe [ 0 ] ) = = 0 ) ;
2004-07-15 19:00:42 +00:00
daemon_pipe [ 0 ] = - 1 ;
2006-01-10 17:51:06 +00:00
# endif
2004-09-05 00:03:16 +00:00
2004-09-13 23:28:30 +00:00
if ( conf - > auto_log_target )
2009-02-21 22:45:56 +01:00
pa_log_set_target ( PA_LOG_SYSLOG ) ;
2004-09-05 00:03:16 +00:00
2006-01-10 17:51:06 +00:00
# ifdef HAVE_SETSID
2004-07-15 19:00:42 +00:00
setsid ( ) ;
2006-01-10 17:51:06 +00:00
# endif
# ifdef HAVE_SETPGID
2004-09-23 15:57:15 +00:00
setpgid ( 0 , 0 ) ;
2006-01-10 17:51:06 +00:00
# endif
# ifndef OS_IS_WIN32
2007-10-28 19:13:50 +00:00
pa_close ( 0 ) ;
pa_close ( 1 ) ;
pa_close ( 2 ) ;
2004-12-14 14:09:00 +00:00
2008-05-15 23:34:41 +00:00
pa_assert_se ( open ( " /dev/null " , O_RDONLY ) = = 0 ) ;
pa_assert_se ( open ( " /dev/null " , O_WRONLY ) = = 1 ) ;
pa_assert_se ( open ( " /dev/null " , O_WRONLY ) = = 2 ) ;
2006-01-10 17:51:06 +00:00
# else
FreeConsole ( ) ;
# endif
# ifdef SIGTTOU
2004-12-14 14:20:52 +00:00
signal ( SIGTTOU , SIG_IGN ) ;
2006-01-10 17:51:06 +00:00
# endif
# ifdef SIGTTIN
2004-12-14 14:20:52 +00:00
signal ( SIGTTIN , SIG_IGN ) ;
2006-01-10 17:51:06 +00:00
# endif
# ifdef SIGTSTP
2004-12-14 14:20:52 +00:00
signal ( SIGTSTP , SIG_IGN ) ;
2006-01-10 17:51:06 +00:00
# endif
2007-01-04 13:43:45 +00:00
2006-01-10 17:51:06 +00:00
# ifdef TIOCNOTTY
2004-12-14 14:20:52 +00:00
if ( ( tty_fd = open ( " /dev/tty " , O_RDWR ) ) > = 0 ) {
ioctl ( tty_fd , TIOCNOTTY , ( char * ) 0 ) ;
2007-10-28 19:13:50 +00:00
pa_assert_se ( pa_close ( tty_fd ) = = 0 ) ;
2004-12-14 14:20:52 +00:00
}
2006-01-10 17:51:06 +00:00
# endif
2004-07-12 21:28:11 +00:00
}
2004-07-17 15:00:31 +00:00
2008-05-15 23:34:41 +00:00
pa_set_env ( " PULSE_INTERNAL " , " 1 " ) ;
2007-10-28 19:13:50 +00:00
pa_assert_se ( chdir ( " / " ) = = 0 ) ;
2006-07-19 17:44:19 +00:00
umask ( 0022 ) ;
2007-01-04 13:43:45 +00:00
2008-05-15 23:34:41 +00:00
if ( conf - > system_instance )
2006-07-19 17:44:19 +00:00
if ( change_user ( ) < 0 )
goto finish ;
2008-05-15 23:34:41 +00:00
2008-05-21 22:50:58 +00:00
pa_set_env ( " PULSE_SYSTEM " , conf - > system_instance ? " 1 " : " 0 " ) ;
2008-08-06 18:54:13 +02:00
pa_log_info ( _ ( " This is PulseAudio %s " ) , PACKAGE_VERSION ) ;
2008-09-05 15:42:39 +03:00
pa_log_debug ( _ ( " Compilation host: %s " ) , CANONICAL_HOST ) ;
2008-08-29 20:08:55 +02:00
pa_log_debug ( _ ( " Compilation CFLAGS: %s " ) , PA_CFLAGS ) ;
2008-09-01 02:38:32 +02:00
2008-09-05 15:42:39 +03:00
s = pa_uname_string ( ) ;
pa_log_debug ( _ ( " Running on host: %s " ) , s ) ;
pa_xfree ( s ) ;
2009-01-22 02:16:53 +01:00
pa_log_debug ( _ ( " Found %u CPUs. " ) , pa_ncpus ( ) ) ;
2008-09-05 15:42:39 +03:00
pa_log_info ( _ ( " Page size is %lu bytes " ) , ( unsigned long ) PA_PAGE_SIZE ) ;
2008-09-01 02:38:32 +02:00
# ifdef HAVE_VALGRIND_MEMCHECK_H
pa_log_debug ( _ ( " Compiled with Valgrind support: yes " ) ) ;
# else
pa_log_debug ( _ ( " Compiled with Valgrind support: no " ) ) ;
# endif
2008-10-04 00:13:29 +02:00
pa_log_debug ( _ ( " Running in valgrind mode: %s " ) , pa_yes_no ( pa_in_valgrind ( ) ) ) ;
2008-09-01 02:38:32 +02:00
# ifdef __OPTIMIZE__
pa_log_debug ( _ ( " Optimized build: yes " ) ) ;
# else
pa_log_debug ( _ ( " Optimized build: no " ) ) ;
# endif
2009-03-20 13:29:42 +01:00
# ifdef NDEBUG
pa_log_debug ( _ ( " NDEBUG defined, all asserts disabled. " ) ) ;
# elif defined(FASTPATH)
pa_log_debug ( _ ( " FASTPATH defined, only fast path asserts disabled. " ) ) ;
# else
pa_log_debug ( _ ( " All asserts enabled. " ) ) ;
# endif
2008-08-07 02:23:45 +02:00
if ( ! ( s = pa_machine_id ( ) ) ) {
pa_log ( _ ( " Failed to get machine ID " ) ) ;
goto finish ;
}
pa_log_info ( _ ( " Machine ID is %s. " ) , s ) ;
pa_xfree ( s ) ;
2008-05-21 22:50:58 +00:00
if ( ! ( s = pa_get_runtime_dir ( ) ) )
goto finish ;
2008-08-06 18:54:13 +02:00
pa_log_info ( _ ( " Using runtime directory %s. " ) , s ) ;
2008-05-15 23:34:41 +00:00
pa_xfree ( s ) ;
2008-08-07 02:23:45 +02:00
2008-05-21 22:50:58 +00:00
if ( ! ( s = pa_get_state_dir ( ) ) )
2008-08-07 02:23:45 +02:00
goto finish ;
pa_log_info ( _ ( " Using state directory %s. " ) , s ) ;
2008-05-21 22:50:58 +00:00
pa_xfree ( s ) ;
2008-08-06 18:54:13 +02:00
pa_log_info ( _ ( " Running in system mode: %s " ) , pa_yes_no ( pa_in_system_mode ( ) ) ) ;
2007-01-04 13:43:45 +00:00
2004-11-20 23:48:18 +00:00
if ( conf - > use_pid_file ) {
2008-06-11 17:38:50 +00:00
int z ;
if ( ( z = pa_pid_file_create ( " pulseaudio " ) ) ! = 0 ) {
if ( conf - > cmd = = PA_CMD_START & & z > 0 ) {
/* If we are already running and with are run in
* - - start mode , then let ' s return this as success . */
retval = 0 ;
goto finish ;
}
2008-08-06 18:54:13 +02:00
pa_log ( _ ( " pa_pid_file_create() failed. " ) ) ;
2004-11-20 23:48:18 +00:00
goto finish ;
2004-12-15 01:17:04 +00:00
}
2004-11-20 23:48:18 +00:00
2008-05-15 23:34:41 +00:00
valid_pid_file = TRUE ;
2004-11-20 23:48:18 +00:00
}
2006-02-20 23:58:51 +00:00
# ifdef SIGPIPE
signal ( SIGPIPE , SIG_IGN ) ;
# endif
2006-07-19 17:44:19 +00:00
2007-10-28 19:13:50 +00:00
if ( pa_rtclock_hrtimer ( ) )
2008-08-06 18:54:13 +02:00
pa_log_info ( _ ( " Fresh high-resolution timers available! Bon appetit! " ) ) ;
2007-10-28 19:13:50 +00:00
else
2008-08-06 18:54:13 +02:00
pa_log_info ( _ ( " Dude, your kernel stinks! The chef's recommendation today is Linux with high-resolution timers enabled! " ) ) ;
2007-10-28 19:13:50 +00:00
2009-01-16 19:57:58 +01:00
pa_rtclock_hrtimer_enable ( ) ;
2007-10-28 19:13:50 +00:00
# ifdef SIGRTMIN
/* Valgrind uses SIGRTMAX. To easy debugging we don't use it here */
pa_rtsig_configure ( SIGRTMIN , SIGRTMAX - 1 ) ;
# endif
pa_assert_se ( mainloop = pa_mainloop_new ( ) ) ;
2004-06-08 23:54:24 +00:00
2008-10-01 01:14:36 +02:00
if ( ! ( c = pa_core_new ( pa_mainloop_get_api ( mainloop ) , ! conf - > disable_shm , conf - > shm_size ) ) ) {
2008-08-06 18:54:13 +02:00
pa_log ( _ ( " pa_core_new() failed. " ) ) ;
2006-08-19 01:20:13 +00:00
goto finish ;
2006-08-22 12:46:05 +00:00
}
2006-08-19 01:20:13 +00:00
2007-10-28 19:13:50 +00:00
c - > default_sample_spec = conf - > default_sample_spec ;
2009-02-21 16:32:42 +01:00
c - > default_channel_map = conf - > default_channel_map ;
2007-10-28 19:13:50 +00:00
c - > default_n_fragments = conf - > default_n_fragments ;
c - > default_fragment_size_msec = conf - > default_fragment_size_msec ;
c - > exit_idle_time = conf - > exit_idle_time ;
c - > scache_idle_time = conf - > scache_idle_time ;
c - > resample_method = conf - > resample_method ;
2007-11-01 02:58:26 +00:00
c - > realtime_priority = conf - > realtime_priority ;
c - > realtime_scheduling = ! ! conf - > realtime_scheduling ;
2007-11-21 01:30:40 +00:00
c - > disable_remixing = ! ! conf - > disable_remixing ;
2008-09-05 16:04:42 +03:00
c - > disable_lfe_remixing = ! ! conf - > disable_lfe_remixing ;
2008-05-15 23:34:41 +00:00
c - > running_as_daemon = ! ! conf - > daemonize ;
2008-08-06 19:39:12 +02:00
c - > disallow_exit = conf - > disallow_exit ;
2009-01-27 04:39:07 +01:00
c - > flat_volumes = conf - > flat_volumes ;
2007-10-28 19:13:50 +00:00
pa_assert_se ( pa_signal_init ( pa_mainloop_get_api ( mainloop ) ) = = 0 ) ;
2004-09-03 20:14:23 +00:00
pa_signal_new ( SIGINT , signal_callback , c ) ;
pa_signal_new ( SIGTERM , signal_callback , c ) ;
2006-01-10 17:51:06 +00:00
# ifdef SIGUSR1
2004-09-03 20:14:23 +00:00
pa_signal_new ( SIGUSR1 , signal_callback , c ) ;
2006-01-10 17:51:06 +00:00
# endif
# ifdef SIGUSR2
2004-09-03 20:14:23 +00:00
pa_signal_new ( SIGUSR2 , signal_callback , c ) ;
2006-01-10 17:51:06 +00:00
# endif
# ifdef SIGHUP
2004-09-26 17:02:26 +00:00
pa_signal_new ( SIGHUP , signal_callback , c ) ;
2006-01-10 17:51:06 +00:00
# endif
2007-01-04 13:43:45 +00:00
2006-02-20 23:58:51 +00:00
# ifdef OS_IS_WIN32
2008-05-15 23:34:41 +00:00
win32_timer = pa_mainloop_get_api ( mainloop ) - > time_new ( pa_mainloop_get_api ( mainloop ) , pa_gettimeofday ( & win32_tv ) , message_cb , NULL ) ;
2006-02-20 23:58:51 +00:00
# endif
2006-01-27 16:25:31 +00:00
oil_init ( ) ;
2006-07-25 20:51:15 +00:00
2007-10-28 19:13:50 +00:00
if ( ! conf - > no_cpu_limit )
pa_assert_se ( pa_cpu_limit_init ( pa_mainloop_get_api ( mainloop ) ) = = 0 ) ;
2007-01-04 13:43:45 +00:00
2004-07-14 21:52:41 +00:00
buf = pa_strbuf_new ( ) ;
2008-05-15 23:34:41 +00:00
if ( conf - > load_default_script_file ) {
FILE * f ;
if ( ( f = pa_daemon_conf_open_default_script_file ( conf ) ) ) {
r = pa_cli_command_execute_file_stream ( c , f , buf , & conf - > fail ) ;
fclose ( f ) ;
}
}
2004-09-14 23:08:39 +00:00
if ( r > = 0 )
2004-12-11 00:10:41 +00:00
r = pa_cli_command_execute ( c , conf - > script_commands , buf , & conf - > fail ) ;
2008-05-15 23:34:41 +00:00
2006-02-23 02:27:19 +00:00
pa_log_error ( " %s " , s = pa_strbuf_tostring_free ( buf ) ) ;
2004-08-04 16:39:30 +00:00
pa_xfree ( s ) ;
2007-01-04 13:43:45 +00:00
2007-11-01 11:23:45 +00:00
/* We completed the initial module loading, so let's disable it
* from now on , if requested */
c - > disallow_module_loading = ! ! conf - > disallow_module_loading ;
2004-09-13 23:28:30 +00:00
if ( r < 0 & & conf - > fail ) {
2008-08-06 18:54:13 +02:00
pa_log ( _ ( " Failed to initialize daemon. " ) ) ;
2008-05-15 23:34:41 +00:00
goto finish ;
}
2004-11-20 23:48:18 +00:00
2008-05-15 23:34:41 +00:00
if ( ! c - > modules | | pa_idxset_size ( c - > modules ) = = 0 ) {
2008-08-06 18:54:13 +02:00
pa_log ( _ ( " Daemon startup without any loaded modules, refusing to work. " ) ) ;
2008-05-15 23:34:41 +00:00
goto finish ;
}
2006-01-10 17:51:06 +00:00
# ifdef HAVE_FORK
2008-06-11 17:38:50 +00:00
if ( daemon_pipe [ 1 ] > = 0 ) {
2008-05-15 23:34:41 +00:00
int ok = 0 ;
pa_loop_write ( daemon_pipe [ 1 ] , & ok , sizeof ( ok ) , NULL ) ;
2008-06-11 17:38:50 +00:00
pa_close ( daemon_pipe [ 1 ] ) ;
daemon_pipe [ 1 ] = - 1 ;
2008-05-15 23:34:41 +00:00
}
2006-01-10 17:51:06 +00:00
# endif
2004-09-03 22:44:55 +00:00
2009-03-20 18:39:30 +02:00
# ifdef HAVE_DBUS
register_org_pulseaudio ( c ) ;
# endif
2008-08-06 18:54:13 +02:00
pa_log_info ( _ ( " Daemon startup complete. " ) ) ;
2008-05-15 23:34:41 +00:00
retval = 0 ;
if ( pa_mainloop_run ( mainloop , & retval ) < 0 )
goto finish ;
2008-08-06 18:54:13 +02:00
pa_log_info ( _ ( " Daemon shutdown initiated. " ) ) ;
2008-05-15 23:34:41 +00:00
finish :
2006-01-10 17:51:06 +00:00
2008-08-09 03:49:42 +02:00
if ( autospawn_fd > = 0 ) {
if ( autospawn_locked )
pa_autospawn_lock_release ( ) ;
pa_autospawn_lock_done ( FALSE ) ;
}
2008-06-11 17:38:50 +00:00
2006-01-10 17:51:06 +00:00
# ifdef OS_IS_WIN32
2008-05-15 23:34:41 +00:00
if ( win32_timer )
pa_mainloop_get_api ( mainloop ) - > time_free ( win32_timer ) ;
2006-01-10 17:51:06 +00:00
# endif
2008-05-15 23:34:41 +00:00
if ( c ) {
pa_core_unref ( c ) ;
2008-08-06 18:54:13 +02:00
pa_log_info ( _ ( " Daemon terminated. " ) ) ;
2008-05-15 23:34:41 +00:00
}
2004-06-23 23:17:30 +00:00
2006-07-25 20:51:15 +00:00
if ( ! conf - > no_cpu_limit )
pa_cpu_limit_done ( ) ;
2007-01-04 13:43:45 +00:00
2004-06-23 23:17:30 +00:00
pa_signal_done ( ) ;
2007-01-04 13:43:45 +00:00
2008-05-15 23:34:41 +00:00
# ifdef HAVE_FORK
2008-06-11 17:38:50 +00:00
if ( daemon_pipe [ 1 ] > = 0 )
pa_loop_write ( daemon_pipe [ 1 ] , & retval , sizeof ( retval ) , NULL ) ;
2008-05-15 23:34:41 +00:00
pa_close_pipe ( daemon_pipe ) ;
# endif
2004-07-15 19:00:42 +00:00
2006-08-19 01:20:13 +00:00
if ( mainloop )
pa_mainloop_free ( mainloop ) ;
2004-09-13 23:28:30 +00:00
if ( conf )
2004-09-17 20:06:17 +00:00
pa_daemon_conf_free ( conf ) ;
2004-07-15 19:00:42 +00:00
2004-11-20 23:48:18 +00:00
if ( valid_pid_file )
pa_pid_file_remove ( ) ;
2007-01-04 13:43:45 +00:00
2006-01-10 17:51:06 +00:00
# ifdef OS_IS_WIN32
WSACleanup ( ) ;
# endif
2008-02-15 18:03:11 +00:00
if ( ltdl_init )
pa_ltdl_done ( ) ;
2007-10-28 19:13:50 +00:00
# ifdef HAVE_DBUS
dbus_shutdown ( ) ;
# endif
2007-01-04 13:43:45 +00:00
2004-06-23 23:17:30 +00:00
return retval ;
2004-06-08 23:54:24 +00:00
}