daemon: before exec'ing ourselves, make sure nobody plays games with /proc/self/exe
[pulseaudio-mirror.git] / src / daemon / main.c
blob0743967597a8fdd6a1c8b1d3d27130d7971bd8b2
1 /***
2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 2.1 of the License,
10 or (at your option) any later version.
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 USA.
21 ***/
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
27 #include <unistd.h>
28 #include <errno.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <signal.h>
33 #include <stddef.h>
34 #include <ltdl.h>
35 #include <limits.h>
36 #include <fcntl.h>
37 #include <unistd.h>
38 #include <locale.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
42 #include <liboil/liboil.h>
44 #ifdef HAVE_SYS_MMAN_H
45 #include <sys/mman.h>
46 #endif
48 #ifdef HAVE_SYS_IOCTL_H
49 #include <sys/ioctl.h>
50 #endif
52 #ifdef HAVE_PWD_H
53 #include <pwd.h>
54 #endif
55 #ifdef HAVE_GRP_H
56 #include <grp.h>
57 #endif
59 #ifdef HAVE_LIBWRAP
60 #include <syslog.h>
61 #include <tcpd.h>
62 #endif
64 #ifdef HAVE_DBUS
65 #include <dbus/dbus.h>
66 #endif
68 #include <pulse/mainloop.h>
69 #include <pulse/mainloop-signal.h>
70 #include <pulse/timeval.h>
71 #include <pulse/xmalloc.h>
72 #include <pulse/i18n.h>
74 #include <pulsecore/lock-autospawn.h>
75 #include <pulsecore/winsock.h>
76 #include <pulsecore/core-error.h>
77 #include <pulsecore/core-rtclock.h>
78 #include <pulsecore/core.h>
79 #include <pulsecore/memblock.h>
80 #include <pulsecore/module.h>
81 #include <pulsecore/cli-command.h>
82 #include <pulsecore/log.h>
83 #include <pulsecore/core-util.h>
84 #include <pulsecore/sioman.h>
85 #include <pulsecore/cli-text.h>
86 #include <pulsecore/pid.h>
87 #include <pulsecore/namereg.h>
88 #include <pulsecore/random.h>
89 #include <pulsecore/macro.h>
90 #include <pulsecore/mutex.h>
91 #include <pulsecore/thread.h>
92 #include <pulsecore/once.h>
93 #include <pulsecore/shm.h>
94 #include <pulsecore/memtrap.h>
95 #ifdef HAVE_DBUS
96 #include <pulsecore/dbus-shared.h>
97 #endif
99 #include "cmdline.h"
100 #include "cpulimit.h"
101 #include "daemon-conf.h"
102 #include "dumpmodules.h"
103 #include "caps.h"
104 #include "ltdl-bind-now.h"
106 #ifdef HAVE_LIBWRAP
107 /* Only one instance of these variables */
108 int allow_severity = LOG_INFO;
109 int deny_severity = LOG_WARNING;
110 #endif
112 #ifdef HAVE_OSS
113 /* padsp looks for this symbol in the running process and disables
114 * itself if it finds it and it is set to 7 (which is actually a bit
115 * mask). For details see padsp. */
116 int __padsp_disabled__ = 7;
117 #endif
119 #ifdef OS_IS_WIN32
121 static void message_cb(pa_mainloop_api*a, pa_time_event*e, const struct timeval *tv, void *userdata) {
122 MSG msg;
123 struct timeval tvnext;
125 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
126 if (msg.message == WM_QUIT)
127 raise(SIGTERM);
128 else {
129 TranslateMessage(&msg);
130 DispatchMessage(&msg);
134 pa_timeval_add(pa_gettimeofday(&tvnext), 100000);
135 a->rtclock_time_restart(e, &tvnext);
138 #endif
140 static void signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata) {
141 pa_log_info(_("Got signal %s."), pa_sig2str(sig));
143 switch (sig) {
144 #ifdef SIGUSR1
145 case SIGUSR1:
146 pa_module_load(userdata, "module-cli", NULL);
147 break;
148 #endif
150 #ifdef SIGUSR2
151 case SIGUSR2:
152 pa_module_load(userdata, "module-cli-protocol-unix", NULL);
153 break;
154 #endif
156 #ifdef SIGHUP
157 case SIGHUP: {
158 char *c = pa_full_status_string(userdata);
159 pa_log_notice("%s", c);
160 pa_xfree(c);
161 return;
163 #endif
165 case SIGINT:
166 case SIGTERM:
167 default:
168 pa_log_info(_("Exiting."));
169 m->quit(m, 1);
170 break;
174 #if defined(HAVE_PWD_H) && defined(HAVE_GRP_H)
176 static int change_user(void) {
177 struct passwd *pw;
178 struct group * gr;
179 int r;
181 /* This function is called only in system-wide mode. It creates a
182 * runtime dir in /var/run/ with proper UID/GID and drops privs
183 * afterwards. */
185 if (!(pw = getpwnam(PA_SYSTEM_USER))) {
186 pa_log(_("Failed to find user '%s'."), PA_SYSTEM_USER);
187 return -1;
190 if (!(gr = getgrnam(PA_SYSTEM_GROUP))) {
191 pa_log(_("Failed to find group '%s'."), PA_SYSTEM_GROUP);
192 return -1;
195 pa_log_info(_("Found user '%s' (UID %lu) and group '%s' (GID %lu)."),
196 PA_SYSTEM_USER, (unsigned long) pw->pw_uid,
197 PA_SYSTEM_GROUP, (unsigned long) gr->gr_gid);
199 if (pw->pw_gid != gr->gr_gid) {
200 pa_log(_("GID of user '%s' and of group '%s' don't match."), PA_SYSTEM_USER, PA_SYSTEM_GROUP);
201 return -1;
204 if (strcmp(pw->pw_dir, PA_SYSTEM_RUNTIME_PATH) != 0)
205 pa_log_warn(_("Home directory of user '%s' is not '%s', ignoring."), PA_SYSTEM_USER, PA_SYSTEM_RUNTIME_PATH);
207 if (pa_make_secure_dir(PA_SYSTEM_RUNTIME_PATH, 0755, pw->pw_uid, gr->gr_gid) < 0) {
208 pa_log(_("Failed to create '%s': %s"), PA_SYSTEM_RUNTIME_PATH, pa_cstrerror(errno));
209 return -1;
212 if (pa_make_secure_dir(PA_SYSTEM_STATE_PATH, 0700, pw->pw_uid, gr->gr_gid) < 0) {
213 pa_log(_("Failed to create '%s': %s"), PA_SYSTEM_STATE_PATH, pa_cstrerror(errno));
214 return -1;
217 /* We don't create the config dir here, because we don't need to write to it */
219 if (initgroups(PA_SYSTEM_USER, gr->gr_gid) != 0) {
220 pa_log(_("Failed to change group list: %s"), pa_cstrerror(errno));
221 return -1;
224 #if defined(HAVE_SETRESGID)
225 r = setresgid(gr->gr_gid, gr->gr_gid, gr->gr_gid);
226 #elif defined(HAVE_SETEGID)
227 if ((r = setgid(gr->gr_gid)) >= 0)
228 r = setegid(gr->gr_gid);
229 #elif defined(HAVE_SETREGID)
230 r = setregid(gr->gr_gid, gr->gr_gid);
231 #else
232 #error "No API to drop privileges"
233 #endif
235 if (r < 0) {
236 pa_log(_("Failed to change GID: %s"), pa_cstrerror(errno));
237 return -1;
240 #if defined(HAVE_SETRESUID)
241 r = setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid);
242 #elif defined(HAVE_SETEUID)
243 if ((r = setuid(pw->pw_uid)) >= 0)
244 r = seteuid(pw->pw_uid);
245 #elif defined(HAVE_SETREUID)
246 r = setreuid(pw->pw_uid, pw->pw_uid);
247 #else
248 #error "No API to drop privileges"
249 #endif
251 if (r < 0) {
252 pa_log(_("Failed to change UID: %s"), pa_cstrerror(errno));
253 return -1;
256 pa_set_env("USER", PA_SYSTEM_USER);
257 pa_set_env("USERNAME", PA_SYSTEM_USER);
258 pa_set_env("LOGNAME", PA_SYSTEM_USER);
259 pa_set_env("HOME", PA_SYSTEM_RUNTIME_PATH);
261 /* Relevant for pa_runtime_path() */
262 pa_set_env("PULSE_RUNTIME_PATH", PA_SYSTEM_RUNTIME_PATH);
263 pa_set_env("PULSE_CONFIG_PATH", PA_SYSTEM_CONFIG_PATH);
264 pa_set_env("PULSE_STATE_PATH", PA_SYSTEM_STATE_PATH);
266 pa_log_info(_("Successfully dropped root privileges."));
268 return 0;
271 #else /* HAVE_PWD_H && HAVE_GRP_H */
273 static int change_user(void) {
274 pa_log(_("System wide mode unsupported on this platform."));
275 return -1;
278 #endif /* HAVE_PWD_H && HAVE_GRP_H */
280 #ifdef HAVE_SYS_RESOURCE_H
282 static int set_one_rlimit(const pa_rlimit *r, int resource, const char *name) {
283 struct rlimit rl;
284 pa_assert(r);
286 if (!r->is_set)
287 return 0;
289 rl.rlim_cur = rl.rlim_max = r->value;
291 if (setrlimit(resource, &rl) < 0) {
292 pa_log_info(_("setrlimit(%s, (%u, %u)) failed: %s"), name, (unsigned) r->value, (unsigned) r->value, pa_cstrerror(errno));
293 return -1;
296 return 0;
299 static void set_all_rlimits(const pa_daemon_conf *conf) {
300 set_one_rlimit(&conf->rlimit_fsize, RLIMIT_FSIZE, "RLIMIT_FSIZE");
301 set_one_rlimit(&conf->rlimit_data, RLIMIT_DATA, "RLIMIT_DATA");
302 set_one_rlimit(&conf->rlimit_stack, RLIMIT_STACK, "RLIMIT_STACK");
303 set_one_rlimit(&conf->rlimit_core, RLIMIT_CORE, "RLIMIT_CORE");
304 #ifdef RLIMIT_RSS
305 set_one_rlimit(&conf->rlimit_rss, RLIMIT_RSS, "RLIMIT_RSS");
306 #endif
307 #ifdef RLIMIT_NPROC
308 set_one_rlimit(&conf->rlimit_nproc, RLIMIT_NPROC, "RLIMIT_NPROC");
309 #endif
310 #ifdef RLIMIT_NOFILE
311 set_one_rlimit(&conf->rlimit_nofile, RLIMIT_NOFILE, "RLIMIT_NOFILE");
312 #endif
313 #ifdef RLIMIT_MEMLOCK
314 set_one_rlimit(&conf->rlimit_memlock, RLIMIT_MEMLOCK, "RLIMIT_MEMLOCK");
315 #endif
316 #ifdef RLIMIT_AS
317 set_one_rlimit(&conf->rlimit_as, RLIMIT_AS, "RLIMIT_AS");
318 #endif
319 #ifdef RLIMIT_LOCKS
320 set_one_rlimit(&conf->rlimit_locks, RLIMIT_LOCKS, "RLIMIT_LOCKS");
321 #endif
322 #ifdef RLIMIT_SIGPENDING
323 set_one_rlimit(&conf->rlimit_sigpending, RLIMIT_SIGPENDING, "RLIMIT_SIGPENDING");
324 #endif
325 #ifdef RLIMIT_MSGQUEUE
326 set_one_rlimit(&conf->rlimit_msgqueue, RLIMIT_MSGQUEUE, "RLIMIT_MSGQUEUE");
327 #endif
328 #ifdef RLIMIT_NICE
329 set_one_rlimit(&conf->rlimit_nice, RLIMIT_NICE, "RLIMIT_NICE");
330 #endif
331 #ifdef RLIMIT_RTPRIO
332 set_one_rlimit(&conf->rlimit_rtprio, RLIMIT_RTPRIO, "RLIMIT_RTPRIO");
333 #endif
334 #ifdef RLIMIT_RTTIME
335 set_one_rlimit(&conf->rlimit_rttime, RLIMIT_RTTIME, "RLIMIT_RTTIME");
336 #endif
338 #endif
340 #ifdef HAVE_DBUS
341 static pa_dbus_connection *register_dbus(pa_core *c) {
342 DBusError error;
343 pa_dbus_connection *conn;
345 dbus_error_init(&error);
347 if (!(conn = pa_dbus_bus_get(c, pa_in_system_mode() ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &error)) || dbus_error_is_set(&error)) {
348 pa_log_warn("Unable to contact D-Bus: %s: %s", error.name, error.message);
349 goto fail;
352 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) {
353 pa_log_debug("Got org.pulseaudio.Server!");
354 return conn;
357 if (dbus_error_is_set(&error))
358 pa_log_warn("Failed to acquire org.pulseaudio.Server: %s: %s", error.name, error.message);
359 else
360 pa_log_warn("D-Bus name org.pulseaudio.Server already taken. Weird shit!");
362 /* PA cannot be started twice by the same user and hence we can
363 * ignore mostly the case that org.pulseaudio.Server is already
364 * taken. */
366 fail:
368 if (conn)
369 pa_dbus_connection_unref(conn);
371 dbus_error_free(&error);
372 return NULL;
374 #endif
376 int main(int argc, char *argv[]) {
377 pa_core *c = NULL;
378 pa_strbuf *buf = NULL;
379 pa_daemon_conf *conf = NULL;
380 pa_mainloop *mainloop = NULL;
381 char *s;
382 int r = 0, retval = 1, d = 0;
383 pa_bool_t valid_pid_file = FALSE;
384 pa_bool_t ltdl_init = FALSE;
385 int passed_fd = -1;
386 const char *e;
387 #ifdef HAVE_FORK
388 int daemon_pipe[2] = { -1, -1 };
389 #endif
390 #ifdef OS_IS_WIN32
391 pa_time_event *win32_timer;
392 struct timeval win32_tv;
393 #endif
394 int autospawn_fd = -1;
395 pa_bool_t autospawn_locked = FALSE;
396 #ifdef HAVE_DBUS
397 pa_dbus_connection *dbus = NULL;
398 #endif
400 pa_log_set_ident("pulseaudio");
401 pa_log_set_level(PA_LOG_NOTICE);
402 pa_log_set_flags(PA_LOG_COLORS|PA_LOG_PRINT_FILE|PA_LOG_PRINT_LEVEL, PA_LOG_RESET);
404 #if defined(__linux__) && defined(__OPTIMIZE__)
406 Disable lazy relocations to make usage of external libraries
407 more deterministic for our RT threads. We abuse __OPTIMIZE__ as
408 a check whether we are a debug build or not. This all is
409 admittedly a bit snake-oilish.
412 if (!getenv("LD_BIND_NOW")) {
413 char *rp;
415 /* We have to execute ourselves, because the libc caches the
416 * value of $LD_BIND_NOW on initialization. */
418 pa_set_env("LD_BIND_NOW", "1");
420 if ((rp = pa_readlink("/proc/self/exe"))) {
422 if (pa_streq(rp, PA_BINARY))
423 pa_assert_se(execv(rp, argv) == 0);
424 else
425 pa_log_warn("/proc/self/exe does not point to " PA_BINARY ", cannot self execute. Are you playing games?");
427 pa_xfree(rp);
429 } else
430 pa_log_warn("Couldn't read /proc/self/exe, cannot self execute. Running in a chroot()?");
432 #endif
434 if ((e = getenv("PULSE_PASSED_FD"))) {
435 passed_fd = atoi(e);
437 if (passed_fd <= 2)
438 passed_fd = -1;
441 /* We might be autospawned, in which case have no idea in which
442 * context we have been started. Let's cleanup our execution
443 * context as good as possible */
444 pa_drop_root();
445 pa_close_all(passed_fd, -1);
446 pa_reset_sigs(-1);
447 pa_unblock_sigs(-1);
449 setlocale(LC_ALL, "");
450 pa_init_i18n();
452 conf = pa_daemon_conf_new();
454 if (pa_daemon_conf_load(conf, NULL) < 0)
455 goto finish;
457 if (pa_daemon_conf_env(conf) < 0)
458 goto finish;
460 if (pa_cmdline_parse(conf, argc, argv, &d) < 0) {
461 pa_log(_("Failed to parse command line."));
462 goto finish;
465 pa_log_set_level(conf->log_level);
466 pa_log_set_target(conf->auto_log_target ? PA_LOG_STDERR : conf->log_target);
467 if (conf->log_meta)
468 pa_log_set_flags(PA_LOG_PRINT_META, PA_LOG_SET);
469 if (conf->log_time)
470 pa_log_set_flags(PA_LOG_PRINT_TIME, PA_LOG_SET);
471 pa_log_set_show_backtrace(conf->log_backtrace);
473 LTDL_SET_PRELOADED_SYMBOLS();
474 pa_ltdl_init();
475 ltdl_init = TRUE;
477 if (conf->dl_search_path)
478 lt_dlsetsearchpath(conf->dl_search_path);
480 #ifdef OS_IS_WIN32
482 WSADATA data;
483 WSAStartup(MAKEWORD(2, 0), &data);
485 #endif
487 pa_random_seed();
489 switch (conf->cmd) {
490 case PA_CMD_DUMP_MODULES:
491 pa_dump_modules(conf, argc-d, argv+d);
492 retval = 0;
493 goto finish;
495 case PA_CMD_DUMP_CONF: {
496 s = pa_daemon_conf_dump(conf);
497 fputs(s, stdout);
498 pa_xfree(s);
499 retval = 0;
500 goto finish;
503 case PA_CMD_DUMP_RESAMPLE_METHODS: {
504 int i;
506 for (i = 0; i < PA_RESAMPLER_MAX; i++)
507 if (pa_resample_method_supported(i))
508 printf("%s\n", pa_resample_method_to_string(i));
510 retval = 0;
511 goto finish;
514 case PA_CMD_HELP :
515 pa_cmdline_help(argv[0]);
516 retval = 0;
517 goto finish;
519 case PA_CMD_VERSION :
520 printf(PACKAGE_NAME" "PACKAGE_VERSION"\n");
521 retval = 0;
522 goto finish;
524 case PA_CMD_CHECK: {
525 pid_t pid;
527 if (pa_pid_file_check_running(&pid, "pulseaudio") < 0)
528 pa_log_info(_("Daemon not running"));
529 else {
530 pa_log_info(_("Daemon running as PID %u"), pid);
531 retval = 0;
534 goto finish;
537 case PA_CMD_KILL:
539 if (pa_pid_file_kill(SIGINT, NULL, "pulseaudio") < 0)
540 pa_log(_("Failed to kill daemon: %s"), pa_cstrerror(errno));
541 else
542 retval = 0;
544 goto finish;
546 case PA_CMD_CLEANUP_SHM:
548 if (pa_shm_cleanup() >= 0)
549 retval = 0;
551 goto finish;
553 default:
554 pa_assert(conf->cmd == PA_CMD_DAEMON || conf->cmd == PA_CMD_START);
557 if (getuid() == 0 && !conf->system_instance)
558 pa_log_warn(_("This program is not intended to be run as root (unless --system is specified)."));
559 else if (getuid() != 0 && conf->system_instance) {
560 pa_log(_("Root privileges required."));
561 goto finish;
564 if (conf->cmd == PA_CMD_START && conf->system_instance) {
565 pa_log(_("--start not supported for system instances."));
566 goto finish;
569 if (conf->system_instance && !conf->disallow_exit)
570 pa_log_warn(_("Running in system mode, but --disallow-exit not set!"));
572 if (conf->system_instance && !conf->disallow_module_loading)
573 pa_log_warn(_("Running in system mode, but --disallow-module-loading not set!"));
575 if (conf->system_instance && !conf->disable_shm) {
576 pa_log_notice(_("Running in system mode, forcibly disabling SHM mode!"));
577 conf->disable_shm = TRUE;
580 if (conf->system_instance && conf->exit_idle_time >= 0) {
581 pa_log_notice(_("Running in system mode, forcibly disabling exit idle time!"));
582 conf->exit_idle_time = -1;
585 if (conf->cmd == PA_CMD_START) {
586 /* If we shall start PA only when it is not running yet, we
587 * first take the autospawn lock to make things
588 * synchronous. */
590 if ((autospawn_fd = pa_autospawn_lock_init()) < 0) {
591 pa_log("Failed to initialize autospawn lock");
592 goto finish;
595 if ((pa_autospawn_lock_acquire(TRUE) < 0)) {
596 pa_log("Failed to acquire autospawn lock");
597 goto finish;
600 autospawn_locked = TRUE;
603 if (conf->daemonize) {
604 pid_t child;
605 int tty_fd;
607 if (pa_stdio_acquire() < 0) {
608 pa_log(_("Failed to acquire stdio."));
609 goto finish;
612 #ifdef HAVE_FORK
613 if (pipe(daemon_pipe) < 0) {
614 pa_log(_("pipe failed: %s"), pa_cstrerror(errno));
615 goto finish;
618 if ((child = fork()) < 0) {
619 pa_log(_("fork() failed: %s"), pa_cstrerror(errno));
620 goto finish;
623 if (child != 0) {
624 ssize_t n;
625 /* Father */
627 pa_assert_se(pa_close(daemon_pipe[1]) == 0);
628 daemon_pipe[1] = -1;
630 if ((n = pa_loop_read(daemon_pipe[0], &retval, sizeof(retval), NULL)) != sizeof(retval)) {
632 if (n < 0)
633 pa_log(_("read() failed: %s"), pa_cstrerror(errno));
635 retval = 1;
638 if (retval)
639 pa_log(_("Daemon startup failed."));
640 else
641 pa_log_info(_("Daemon startup successful."));
643 goto finish;
646 if (autospawn_fd >= 0) {
647 /* The lock file is unlocked from the parent, so we need
648 * to close it in the child */
650 pa_autospawn_lock_release();
651 pa_autospawn_lock_done(TRUE);
653 autospawn_locked = FALSE;
654 autospawn_fd = -1;
657 pa_assert_se(pa_close(daemon_pipe[0]) == 0);
658 daemon_pipe[0] = -1;
659 #endif
661 if (conf->auto_log_target)
662 pa_log_set_target(PA_LOG_SYSLOG);
664 #ifdef HAVE_SETSID
665 setsid();
666 #endif
667 #ifdef HAVE_SETPGID
668 setpgid(0,0);
669 #endif
671 #ifndef OS_IS_WIN32
672 pa_close(0);
673 pa_close(1);
674 pa_close(2);
676 pa_assert_se(open("/dev/null", O_RDONLY) == 0);
677 pa_assert_se(open("/dev/null", O_WRONLY) == 1);
678 pa_assert_se(open("/dev/null", O_WRONLY) == 2);
679 #else
680 FreeConsole();
681 #endif
683 #ifdef SIGTTOU
684 signal(SIGTTOU, SIG_IGN);
685 #endif
686 #ifdef SIGTTIN
687 signal(SIGTTIN, SIG_IGN);
688 #endif
689 #ifdef SIGTSTP
690 signal(SIGTSTP, SIG_IGN);
691 #endif
693 #ifdef TIOCNOTTY
694 if ((tty_fd = open("/dev/tty", O_RDWR)) >= 0) {
695 ioctl(tty_fd, TIOCNOTTY, (char*) 0);
696 pa_assert_se(pa_close(tty_fd) == 0);
698 #endif
701 pa_set_env("PULSE_INTERNAL", "1");
702 pa_assert_se(chdir("/") == 0);
703 umask(0022);
705 #ifdef HAVE_SYS_RESOURCE_H
706 set_all_rlimits(conf);
707 #endif
708 pa_rtclock_hrtimer_enable();
710 pa_raise_priority(conf->nice_level);
712 if (conf->system_instance)
713 if (change_user() < 0)
714 goto finish;
716 pa_set_env("PULSE_SYSTEM", conf->system_instance ? "1" : "0");
718 pa_log_info(_("This is PulseAudio %s"), PACKAGE_VERSION);
719 pa_log_debug(_("Compilation host: %s"), CANONICAL_HOST);
720 pa_log_debug(_("Compilation CFLAGS: %s"), PA_CFLAGS);
722 s = pa_uname_string();
723 pa_log_debug(_("Running on host: %s"), s);
724 pa_xfree(s);
726 pa_log_debug(_("Found %u CPUs."), pa_ncpus());
728 pa_log_info(_("Page size is %lu bytes"), (unsigned long) PA_PAGE_SIZE);
730 #ifdef HAVE_VALGRIND_MEMCHECK_H
731 pa_log_debug(_("Compiled with Valgrind support: yes"));
732 #else
733 pa_log_debug(_("Compiled with Valgrind support: no"));
734 #endif
736 pa_log_debug(_("Running in valgrind mode: %s"), pa_yes_no(pa_in_valgrind()));
738 #ifdef __OPTIMIZE__
739 pa_log_debug(_("Optimized build: yes"));
740 #else
741 pa_log_debug(_("Optimized build: no"));
742 #endif
744 #ifdef NDEBUG
745 pa_log_debug(_("NDEBUG defined, all asserts disabled."));
746 #elif defined(FASTPATH)
747 pa_log_debug(_("FASTPATH defined, only fast path asserts disabled."));
748 #else
749 pa_log_debug(_("All asserts enabled."));
750 #endif
752 if (!(s = pa_machine_id())) {
753 pa_log(_("Failed to get machine ID"));
754 goto finish;
756 pa_log_info(_("Machine ID is %s."), s);
757 pa_xfree(s);
759 if ((s = pa_session_id())) {
760 pa_log_info(_("Session ID is %s."), s);
761 pa_xfree(s);
764 if (!(s = pa_get_runtime_dir()))
765 goto finish;
766 pa_log_info(_("Using runtime directory %s."), s);
767 pa_xfree(s);
769 if (!(s = pa_get_state_dir()))
770 goto finish;
771 pa_log_info(_("Using state directory %s."), s);
772 pa_xfree(s);
774 pa_log_info(_("Running in system mode: %s"), pa_yes_no(pa_in_system_mode()));
776 if (pa_in_system_mode())
777 pa_log_warn(_("OK, so you are running PA in system mode. Please note that you most likely shouldn't be doing that.\n"
778 "If you do it nonetheless then it's your own fault if things don't work as expected.\n"
779 "Please read http://pulseaudio.org/wiki/WhatIsWrongWithSystemMode for an explanation why system mode is usually a bad idea."));
781 if (conf->use_pid_file) {
782 int z;
784 if ((z = pa_pid_file_create("pulseaudio")) != 0) {
786 if (conf->cmd == PA_CMD_START && z > 0) {
787 /* If we are already running and with are run in
788 * --start mode, then let's return this as success. */
790 retval = 0;
791 goto finish;
794 pa_log(_("pa_pid_file_create() failed."));
795 goto finish;
798 valid_pid_file = TRUE;
801 pa_disable_sigpipe();
803 if (pa_rtclock_hrtimer())
804 pa_log_info(_("Fresh high-resolution timers available! Bon appetit!"));
805 else
806 pa_log_info(_("Dude, your kernel stinks! The chef's recommendation today is Linux with high-resolution timers enabled!"));
808 if (conf->lock_memory) {
809 #ifdef HAVE_SYS_MMAN_H
810 if (mlockall(MCL_FUTURE) < 0)
811 pa_log_warn("mlockall() failed: %s", pa_cstrerror(errno));
812 else
813 pa_log_info("Sucessfully locked process into memory.");
814 #else
815 pa_log_warn("Memory locking requested but not supported on platform.");
816 #endif
819 pa_memtrap_install();
821 pa_assert_se(mainloop = pa_mainloop_new());
823 if (!(c = pa_core_new(pa_mainloop_get_api(mainloop), !conf->disable_shm, conf->shm_size))) {
824 pa_log(_("pa_core_new() failed."));
825 goto finish;
828 c->default_sample_spec = conf->default_sample_spec;
829 c->default_channel_map = conf->default_channel_map;
830 c->default_n_fragments = conf->default_n_fragments;
831 c->default_fragment_size_msec = conf->default_fragment_size_msec;
832 c->exit_idle_time = conf->exit_idle_time;
833 c->scache_idle_time = conf->scache_idle_time;
834 c->resample_method = conf->resample_method;
835 c->realtime_priority = conf->realtime_priority;
836 c->realtime_scheduling = !!conf->realtime_scheduling;
837 c->disable_remixing = !!conf->disable_remixing;
838 c->disable_lfe_remixing = !!conf->disable_lfe_remixing;
839 c->running_as_daemon = !!conf->daemonize;
840 c->disallow_exit = conf->disallow_exit;
841 c->flat_volumes = conf->flat_volumes;
843 pa_assert_se(pa_signal_init(pa_mainloop_get_api(mainloop)) == 0);
844 pa_signal_new(SIGINT, signal_callback, c);
845 pa_signal_new(SIGTERM, signal_callback, c);
846 #ifdef SIGUSR1
847 pa_signal_new(SIGUSR1, signal_callback, c);
848 #endif
849 #ifdef SIGUSR2
850 pa_signal_new(SIGUSR2, signal_callback, c);
851 #endif
852 #ifdef SIGHUP
853 pa_signal_new(SIGHUP, signal_callback, c);
854 #endif
856 #ifdef OS_IS_WIN32
857 win32_timer = pa_mainloop_get_api(mainloop)->rtclock_time_new(pa_mainloop_get_api(mainloop), pa_gettimeofday(&win32_tv), message_cb, NULL);
858 #endif
860 oil_init();
862 if (!conf->no_cpu_limit)
863 pa_assert_se(pa_cpu_limit_init(pa_mainloop_get_api(mainloop)) == 0);
865 buf = pa_strbuf_new();
866 if (conf->load_default_script_file) {
867 FILE *f;
869 if ((f = pa_daemon_conf_open_default_script_file(conf))) {
870 r = pa_cli_command_execute_file_stream(c, f, buf, &conf->fail);
871 fclose(f);
875 if (r >= 0)
876 r = pa_cli_command_execute(c, conf->script_commands, buf, &conf->fail);
878 pa_log_error("%s", s = pa_strbuf_tostring_free(buf));
879 pa_xfree(s);
881 /* We completed the initial module loading, so let's disable it
882 * from now on, if requested */
883 c->disallow_module_loading = !!conf->disallow_module_loading;
885 if (r < 0 && conf->fail) {
886 pa_log(_("Failed to initialize daemon."));
887 goto finish;
890 if (!c->modules || pa_idxset_size(c->modules) == 0) {
891 pa_log(_("Daemon startup without any loaded modules, refusing to work."));
892 goto finish;
895 #ifdef HAVE_FORK
896 if (daemon_pipe[1] >= 0) {
897 int ok = 0;
898 pa_loop_write(daemon_pipe[1], &ok, sizeof(ok), NULL);
899 pa_close(daemon_pipe[1]);
900 daemon_pipe[1] = -1;
902 #endif
904 #ifdef HAVE_DBUS
905 dbus = register_dbus(c);
906 #endif
908 pa_log_info(_("Daemon startup complete."));
910 retval = 0;
911 if (pa_mainloop_run(mainloop, &retval) < 0)
912 goto finish;
914 pa_log_info(_("Daemon shutdown initiated."));
916 finish:
917 #ifdef HAVE_DBUS
918 if (dbus)
919 pa_dbus_connection_unref(dbus);
920 #endif
922 if (autospawn_fd >= 0) {
923 if (autospawn_locked)
924 pa_autospawn_lock_release();
926 pa_autospawn_lock_done(FALSE);
929 #ifdef OS_IS_WIN32
930 if (win32_timer)
931 pa_mainloop_get_api(mainloop)->time_free(win32_timer);
932 #endif
934 if (c) {
935 pa_core_unref(c);
936 pa_log_info(_("Daemon terminated."));
939 if (!conf->no_cpu_limit)
940 pa_cpu_limit_done();
942 pa_signal_done();
944 #ifdef HAVE_FORK
945 if (daemon_pipe[1] >= 0)
946 pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL);
948 pa_close_pipe(daemon_pipe);
949 #endif
951 if (mainloop)
952 pa_mainloop_free(mainloop);
954 if (conf)
955 pa_daemon_conf_free(conf);
957 if (valid_pid_file)
958 pa_pid_file_remove();
960 #ifdef OS_IS_WIN32
961 WSACleanup();
962 #endif
964 if (ltdl_init)
965 pa_ltdl_done();
967 #ifdef HAVE_DBUS
968 dbus_shutdown();
969 #endif
971 return retval;