]> code.delx.au - pulseaudio/blob - src/daemon/main.c
Get rid of liboil
[pulseaudio] / src / daemon / main.c
1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6
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.
11
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.
16
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 ***/
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
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>
41
42 #ifdef HAVE_SYS_MMAN_H
43 #include <sys/mman.h>
44 #endif
45
46 #ifdef HAVE_SYS_IOCTL_H
47 #include <sys/ioctl.h>
48 #endif
49
50 #ifdef HAVE_PWD_H
51 #include <pwd.h>
52 #endif
53 #ifdef HAVE_GRP_H
54 #include <grp.h>
55 #endif
56
57 #ifdef HAVE_LIBWRAP
58 #include <syslog.h>
59 #include <tcpd.h>
60 #endif
61
62 #ifdef HAVE_DBUS
63 #include <dbus/dbus.h>
64 #endif
65
66 #include <pulse/mainloop.h>
67 #include <pulse/mainloop-signal.h>
68 #include <pulse/timeval.h>
69 #include <pulse/xmalloc.h>
70 #include <pulse/i18n.h>
71
72 #include <pulsecore/lock-autospawn.h>
73 #include <pulsecore/winsock.h>
74 #include <pulsecore/core-error.h>
75 #include <pulsecore/core-rtclock.h>
76 #include <pulsecore/core.h>
77 #include <pulsecore/memblock.h>
78 #include <pulsecore/module.h>
79 #include <pulsecore/cli-command.h>
80 #include <pulsecore/log.h>
81 #include <pulsecore/core-util.h>
82 #include <pulsecore/sioman.h>
83 #include <pulsecore/cli-text.h>
84 #include <pulsecore/pid.h>
85 #include <pulsecore/namereg.h>
86 #include <pulsecore/random.h>
87 #include <pulsecore/macro.h>
88 #include <pulsecore/mutex.h>
89 #include <pulsecore/thread.h>
90 #include <pulsecore/once.h>
91 #include <pulsecore/shm.h>
92 #include <pulsecore/memtrap.h>
93 #ifdef HAVE_DBUS
94 #include <pulsecore/dbus-shared.h>
95 #endif
96 #include <pulsecore/cpu-x86.h>
97
98 #include "cmdline.h"
99 #include "cpulimit.h"
100 #include "daemon-conf.h"
101 #include "dumpmodules.h"
102 #include "caps.h"
103 #include "ltdl-bind-now.h"
104
105 #ifdef HAVE_LIBWRAP
106 /* Only one instance of these variables */
107 int allow_severity = LOG_INFO;
108 int deny_severity = LOG_WARNING;
109 #endif
110
111 #ifdef HAVE_OSS_WRAPPER
112 /* padsp looks for this symbol in the running process and disables
113 * itself if it finds it and it is set to 7 (which is actually a bit
114 * mask). For details see padsp. */
115 int __padsp_disabled__ = 7;
116 #endif
117
118 #ifdef OS_IS_WIN32
119
120 static void message_cb(pa_mainloop_api*a, pa_time_event*e, const struct timeval *tv, void *userdata) {
121 MSG msg;
122 struct timeval tvnext;
123
124 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
125 if (msg.message == WM_QUIT)
126 raise(SIGTERM);
127 else {
128 TranslateMessage(&msg);
129 DispatchMessage(&msg);
130 }
131 }
132
133 pa_timeval_add(pa_gettimeofday(&tvnext), 100000);
134 a->rtclock_time_restart(e, &tvnext);
135 }
136
137 #endif
138
139 static void signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata) {
140 pa_log_info(_("Got signal %s."), pa_sig2str(sig));
141
142 switch (sig) {
143 #ifdef SIGUSR1
144 case SIGUSR1:
145 pa_module_load(userdata, "module-cli", NULL);
146 break;
147 #endif
148
149 #ifdef SIGUSR2
150 case SIGUSR2:
151 pa_module_load(userdata, "module-cli-protocol-unix", NULL);
152 break;
153 #endif
154
155 #ifdef SIGHUP
156 case SIGHUP: {
157 char *c = pa_full_status_string(userdata);
158 pa_log_notice("%s", c);
159 pa_xfree(c);
160 return;
161 }
162 #endif
163
164 case SIGINT:
165 case SIGTERM:
166 default:
167 pa_log_info(_("Exiting."));
168 m->quit(m, 1);
169 break;
170 }
171 }
172
173 #if defined(HAVE_PWD_H) && defined(HAVE_GRP_H)
174
175 static int change_user(void) {
176 struct passwd *pw;
177 struct group * gr;
178 int r;
179
180 /* This function is called only in system-wide mode. It creates a
181 * runtime dir in /var/run/ with proper UID/GID and drops privs
182 * afterwards. */
183
184 if (!(pw = getpwnam(PA_SYSTEM_USER))) {
185 pa_log(_("Failed to find user '%s'."), PA_SYSTEM_USER);
186 return -1;
187 }
188
189 if (!(gr = getgrnam(PA_SYSTEM_GROUP))) {
190 pa_log(_("Failed to find group '%s'."), PA_SYSTEM_GROUP);
191 return -1;
192 }
193
194 pa_log_info(_("Found user '%s' (UID %lu) and group '%s' (GID %lu)."),
195 PA_SYSTEM_USER, (unsigned long) pw->pw_uid,
196 PA_SYSTEM_GROUP, (unsigned long) gr->gr_gid);
197
198 if (pw->pw_gid != gr->gr_gid) {
199 pa_log(_("GID of user '%s' and of group '%s' don't match."), PA_SYSTEM_USER, PA_SYSTEM_GROUP);
200 return -1;
201 }
202
203 if (strcmp(pw->pw_dir, PA_SYSTEM_RUNTIME_PATH) != 0)
204 pa_log_warn(_("Home directory of user '%s' is not '%s', ignoring."), PA_SYSTEM_USER, PA_SYSTEM_RUNTIME_PATH);
205
206 if (pa_make_secure_dir(PA_SYSTEM_RUNTIME_PATH, 0755, pw->pw_uid, gr->gr_gid) < 0) {
207 pa_log(_("Failed to create '%s': %s"), PA_SYSTEM_RUNTIME_PATH, pa_cstrerror(errno));
208 return -1;
209 }
210
211 if (pa_make_secure_dir(PA_SYSTEM_STATE_PATH, 0700, pw->pw_uid, gr->gr_gid) < 0) {
212 pa_log(_("Failed to create '%s': %s"), PA_SYSTEM_STATE_PATH, pa_cstrerror(errno));
213 return -1;
214 }
215
216 /* We don't create the config dir here, because we don't need to write to it */
217
218 if (initgroups(PA_SYSTEM_USER, gr->gr_gid) != 0) {
219 pa_log(_("Failed to change group list: %s"), pa_cstrerror(errno));
220 return -1;
221 }
222
223 #if defined(HAVE_SETRESGID)
224 r = setresgid(gr->gr_gid, gr->gr_gid, gr->gr_gid);
225 #elif defined(HAVE_SETEGID)
226 if ((r = setgid(gr->gr_gid)) >= 0)
227 r = setegid(gr->gr_gid);
228 #elif defined(HAVE_SETREGID)
229 r = setregid(gr->gr_gid, gr->gr_gid);
230 #else
231 #error "No API to drop privileges"
232 #endif
233
234 if (r < 0) {
235 pa_log(_("Failed to change GID: %s"), pa_cstrerror(errno));
236 return -1;
237 }
238
239 #if defined(HAVE_SETRESUID)
240 r = setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid);
241 #elif defined(HAVE_SETEUID)
242 if ((r = setuid(pw->pw_uid)) >= 0)
243 r = seteuid(pw->pw_uid);
244 #elif defined(HAVE_SETREUID)
245 r = setreuid(pw->pw_uid, pw->pw_uid);
246 #else
247 #error "No API to drop privileges"
248 #endif
249
250 if (r < 0) {
251 pa_log(_("Failed to change UID: %s"), pa_cstrerror(errno));
252 return -1;
253 }
254
255 pa_set_env("USER", PA_SYSTEM_USER);
256 pa_set_env("USERNAME", PA_SYSTEM_USER);
257 pa_set_env("LOGNAME", PA_SYSTEM_USER);
258 pa_set_env("HOME", PA_SYSTEM_RUNTIME_PATH);
259
260 /* Relevant for pa_runtime_path() */
261 pa_set_env("PULSE_RUNTIME_PATH", PA_SYSTEM_RUNTIME_PATH);
262 pa_set_env("PULSE_CONFIG_PATH", PA_SYSTEM_CONFIG_PATH);
263 pa_set_env("PULSE_STATE_PATH", PA_SYSTEM_STATE_PATH);
264
265 pa_log_info(_("Successfully dropped root privileges."));
266
267 return 0;
268 }
269
270 #else /* HAVE_PWD_H && HAVE_GRP_H */
271
272 static int change_user(void) {
273 pa_log(_("System wide mode unsupported on this platform."));
274 return -1;
275 }
276
277 #endif /* HAVE_PWD_H && HAVE_GRP_H */
278
279 #ifdef HAVE_SYS_RESOURCE_H
280
281 static int set_one_rlimit(const pa_rlimit *r, int resource, const char *name) {
282 struct rlimit rl;
283 pa_assert(r);
284
285 if (!r->is_set)
286 return 0;
287
288 rl.rlim_cur = rl.rlim_max = r->value;
289
290 if (setrlimit(resource, &rl) < 0) {
291 pa_log_info(_("setrlimit(%s, (%u, %u)) failed: %s"), name, (unsigned) r->value, (unsigned) r->value, pa_cstrerror(errno));
292 return -1;
293 }
294
295 return 0;
296 }
297
298 static void set_all_rlimits(const pa_daemon_conf *conf) {
299 set_one_rlimit(&conf->rlimit_fsize, RLIMIT_FSIZE, "RLIMIT_FSIZE");
300 set_one_rlimit(&conf->rlimit_data, RLIMIT_DATA, "RLIMIT_DATA");
301 set_one_rlimit(&conf->rlimit_stack, RLIMIT_STACK, "RLIMIT_STACK");
302 set_one_rlimit(&conf->rlimit_core, RLIMIT_CORE, "RLIMIT_CORE");
303 #ifdef RLIMIT_RSS
304 set_one_rlimit(&conf->rlimit_rss, RLIMIT_RSS, "RLIMIT_RSS");
305 #endif
306 #ifdef RLIMIT_NPROC
307 set_one_rlimit(&conf->rlimit_nproc, RLIMIT_NPROC, "RLIMIT_NPROC");
308 #endif
309 #ifdef RLIMIT_NOFILE
310 set_one_rlimit(&conf->rlimit_nofile, RLIMIT_NOFILE, "RLIMIT_NOFILE");
311 #endif
312 #ifdef RLIMIT_MEMLOCK
313 set_one_rlimit(&conf->rlimit_memlock, RLIMIT_MEMLOCK, "RLIMIT_MEMLOCK");
314 #endif
315 #ifdef RLIMIT_AS
316 set_one_rlimit(&conf->rlimit_as, RLIMIT_AS, "RLIMIT_AS");
317 #endif
318 #ifdef RLIMIT_LOCKS
319 set_one_rlimit(&conf->rlimit_locks, RLIMIT_LOCKS, "RLIMIT_LOCKS");
320 #endif
321 #ifdef RLIMIT_SIGPENDING
322 set_one_rlimit(&conf->rlimit_sigpending, RLIMIT_SIGPENDING, "RLIMIT_SIGPENDING");
323 #endif
324 #ifdef RLIMIT_MSGQUEUE
325 set_one_rlimit(&conf->rlimit_msgqueue, RLIMIT_MSGQUEUE, "RLIMIT_MSGQUEUE");
326 #endif
327 #ifdef RLIMIT_NICE
328 set_one_rlimit(&conf->rlimit_nice, RLIMIT_NICE, "RLIMIT_NICE");
329 #endif
330 #ifdef RLIMIT_RTPRIO
331 set_one_rlimit(&conf->rlimit_rtprio, RLIMIT_RTPRIO, "RLIMIT_RTPRIO");
332 #endif
333 #ifdef RLIMIT_RTTIME
334 set_one_rlimit(&conf->rlimit_rttime, RLIMIT_RTTIME, "RLIMIT_RTTIME");
335 #endif
336 }
337 #endif
338
339 #ifdef HAVE_DBUS
340 static pa_dbus_connection *register_dbus(pa_core *c) {
341 DBusError error;
342 pa_dbus_connection *conn;
343
344 dbus_error_init(&error);
345
346 if (!(conn = pa_dbus_bus_get(c, pa_in_system_mode() ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &error)) || dbus_error_is_set(&error)) {
347 pa_log_warn("Unable to contact D-Bus: %s: %s", error.name, error.message);
348 goto fail;
349 }
350
351 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) {
352 pa_log_debug("Got org.pulseaudio.Server!");
353 return conn;
354 }
355
356 if (dbus_error_is_set(&error))
357 pa_log_warn("Failed to acquire org.pulseaudio.Server: %s: %s", error.name, error.message);
358 else
359 pa_log_warn("D-Bus name org.pulseaudio.Server already taken. Weird shit!");
360
361 /* PA cannot be started twice by the same user and hence we can
362 * ignore mostly the case that org.pulseaudio.Server is already
363 * taken. */
364
365 fail:
366
367 if (conn)
368 pa_dbus_connection_unref(conn);
369
370 dbus_error_free(&error);
371 return NULL;
372 }
373 #endif
374
375 int main(int argc, char *argv[]) {
376 pa_core *c = NULL;
377 pa_strbuf *buf = NULL;
378 pa_daemon_conf *conf = NULL;
379 pa_mainloop *mainloop = NULL;
380 char *s;
381 int r = 0, retval = 1, d = 0;
382 pa_bool_t valid_pid_file = FALSE;
383 pa_bool_t ltdl_init = FALSE;
384 int passed_fd = -1;
385 const char *e;
386 #ifdef HAVE_FORK
387 int daemon_pipe[2] = { -1, -1 };
388 #endif
389 #ifdef OS_IS_WIN32
390 pa_time_event *win32_timer;
391 struct timeval win32_tv;
392 #endif
393 int autospawn_fd = -1;
394 pa_bool_t autospawn_locked = FALSE;
395 #ifdef HAVE_DBUS
396 pa_dbus_connection *dbus = NULL;
397 #endif
398
399 pa_log_set_ident("pulseaudio");
400 pa_log_set_level(PA_LOG_NOTICE);
401 pa_log_set_flags(PA_LOG_COLORS|PA_LOG_PRINT_FILE|PA_LOG_PRINT_LEVEL, PA_LOG_RESET);
402
403 #if defined(__linux__) && defined(__OPTIMIZE__)
404 /*
405 Disable lazy relocations to make usage of external libraries
406 more deterministic for our RT threads. We abuse __OPTIMIZE__ as
407 a check whether we are a debug build or not. This all is
408 admittedly a bit snake-oilish.
409 */
410
411 if (!getenv("LD_BIND_NOW")) {
412 char *rp;
413
414 /* We have to execute ourselves, because the libc caches the
415 * value of $LD_BIND_NOW on initialization. */
416
417 pa_set_env("LD_BIND_NOW", "1");
418
419 if ((rp = pa_readlink("/proc/self/exe"))) {
420
421 if (pa_streq(rp, PA_BINARY))
422 pa_assert_se(execv(rp, argv) == 0);
423 else
424 pa_log_warn("/proc/self/exe does not point to " PA_BINARY ", cannot self execute. Are you playing games?");
425
426 pa_xfree(rp);
427
428 } else
429 pa_log_warn("Couldn't read /proc/self/exe, cannot self execute. Running in a chroot()?");
430 }
431 #endif
432
433 if ((e = getenv("PULSE_PASSED_FD"))) {
434 passed_fd = atoi(e);
435
436 if (passed_fd <= 2)
437 passed_fd = -1;
438 }
439
440 /* We might be autospawned, in which case have no idea in which
441 * context we have been started. Let's cleanup our execution
442 * context as good as possible */
443
444 pa_reset_personality();
445 pa_drop_root();
446 pa_close_all(passed_fd, -1);
447 pa_reset_sigs(-1);
448 pa_unblock_sigs(-1);
449 pa_reset_priority();
450
451 setlocale(LC_ALL, "");
452 pa_init_i18n();
453
454 conf = pa_daemon_conf_new();
455
456 if (pa_daemon_conf_load(conf, NULL) < 0)
457 goto finish;
458
459 if (pa_daemon_conf_env(conf) < 0)
460 goto finish;
461
462 if (pa_cmdline_parse(conf, argc, argv, &d) < 0) {
463 pa_log(_("Failed to parse command line."));
464 goto finish;
465 }
466
467 pa_log_set_level(conf->log_level);
468 pa_log_set_target(conf->auto_log_target ? PA_LOG_STDERR : conf->log_target);
469 if (conf->log_meta)
470 pa_log_set_flags(PA_LOG_PRINT_META, PA_LOG_SET);
471 if (conf->log_time)
472 pa_log_set_flags(PA_LOG_PRINT_TIME, PA_LOG_SET);
473 pa_log_set_show_backtrace(conf->log_backtrace);
474
475 LTDL_SET_PRELOADED_SYMBOLS();
476 pa_ltdl_init();
477 ltdl_init = TRUE;
478
479 if (conf->dl_search_path)
480 lt_dlsetsearchpath(conf->dl_search_path);
481
482 #ifdef OS_IS_WIN32
483 {
484 WSADATA data;
485 WSAStartup(MAKEWORD(2, 0), &data);
486 }
487 #endif
488
489 pa_random_seed();
490
491 switch (conf->cmd) {
492 case PA_CMD_DUMP_MODULES:
493 pa_dump_modules(conf, argc-d, argv+d);
494 retval = 0;
495 goto finish;
496
497 case PA_CMD_DUMP_CONF: {
498 s = pa_daemon_conf_dump(conf);
499 fputs(s, stdout);
500 pa_xfree(s);
501 retval = 0;
502 goto finish;
503 }
504
505 case PA_CMD_DUMP_RESAMPLE_METHODS: {
506 int i;
507
508 for (i = 0; i < PA_RESAMPLER_MAX; i++)
509 if (pa_resample_method_supported(i))
510 printf("%s\n", pa_resample_method_to_string(i));
511
512 retval = 0;
513 goto finish;
514 }
515
516 case PA_CMD_HELP :
517 pa_cmdline_help(argv[0]);
518 retval = 0;
519 goto finish;
520
521 case PA_CMD_VERSION :
522 printf(PACKAGE_NAME" "PACKAGE_VERSION"\n");
523 retval = 0;
524 goto finish;
525
526 case PA_CMD_CHECK: {
527 pid_t pid;
528
529 if (pa_pid_file_check_running(&pid, "pulseaudio") < 0)
530 pa_log_info(_("Daemon not running"));
531 else {
532 pa_log_info(_("Daemon running as PID %u"), pid);
533 retval = 0;
534 }
535
536 goto finish;
537
538 }
539 case PA_CMD_KILL:
540
541 if (pa_pid_file_kill(SIGINT, NULL, "pulseaudio") < 0)
542 pa_log(_("Failed to kill daemon: %s"), pa_cstrerror(errno));
543 else
544 retval = 0;
545
546 goto finish;
547
548 case PA_CMD_CLEANUP_SHM:
549
550 if (pa_shm_cleanup() >= 0)
551 retval = 0;
552
553 goto finish;
554
555 default:
556 pa_assert(conf->cmd == PA_CMD_DAEMON || conf->cmd == PA_CMD_START);
557 }
558
559 if (getuid() == 0 && !conf->system_instance)
560 pa_log_warn(_("This program is not intended to be run as root (unless --system is specified)."));
561 else if (getuid() != 0 && conf->system_instance) {
562 pa_log(_("Root privileges required."));
563 goto finish;
564 }
565
566 if (conf->cmd == PA_CMD_START && conf->system_instance) {
567 pa_log(_("--start not supported for system instances."));
568 goto finish;
569 }
570
571 if (conf->system_instance && !conf->disallow_exit)
572 pa_log_warn(_("Running in system mode, but --disallow-exit not set!"));
573
574 if (conf->system_instance && !conf->disallow_module_loading)
575 pa_log_warn(_("Running in system mode, but --disallow-module-loading not set!"));
576
577 if (conf->system_instance && !conf->disable_shm) {
578 pa_log_notice(_("Running in system mode, forcibly disabling SHM mode!"));
579 conf->disable_shm = TRUE;
580 }
581
582 if (conf->system_instance && conf->exit_idle_time >= 0) {
583 pa_log_notice(_("Running in system mode, forcibly disabling exit idle time!"));
584 conf->exit_idle_time = -1;
585 }
586
587 if (conf->cmd == PA_CMD_START) {
588 /* If we shall start PA only when it is not running yet, we
589 * first take the autospawn lock to make things
590 * synchronous. */
591
592 if ((autospawn_fd = pa_autospawn_lock_init()) < 0) {
593 pa_log("Failed to initialize autospawn lock");
594 goto finish;
595 }
596
597 if ((pa_autospawn_lock_acquire(TRUE) < 0)) {
598 pa_log("Failed to acquire autospawn lock");
599 goto finish;
600 }
601
602 autospawn_locked = TRUE;
603 }
604
605 if (conf->daemonize) {
606 pid_t child;
607 int tty_fd;
608
609 if (pa_stdio_acquire() < 0) {
610 pa_log(_("Failed to acquire stdio."));
611 goto finish;
612 }
613
614 #ifdef HAVE_FORK
615 if (pipe(daemon_pipe) < 0) {
616 pa_log(_("pipe failed: %s"), pa_cstrerror(errno));
617 goto finish;
618 }
619
620 if ((child = fork()) < 0) {
621 pa_log(_("fork() failed: %s"), pa_cstrerror(errno));
622 goto finish;
623 }
624
625 if (child != 0) {
626 ssize_t n;
627 /* Father */
628
629 pa_assert_se(pa_close(daemon_pipe[1]) == 0);
630 daemon_pipe[1] = -1;
631
632 if ((n = pa_loop_read(daemon_pipe[0], &retval, sizeof(retval), NULL)) != sizeof(retval)) {
633
634 if (n < 0)
635 pa_log(_("read() failed: %s"), pa_cstrerror(errno));
636
637 retval = 1;
638 }
639
640 if (retval)
641 pa_log(_("Daemon startup failed."));
642 else
643 pa_log_info(_("Daemon startup successful."));
644
645 goto finish;
646 }
647
648 if (autospawn_fd >= 0) {
649 /* The lock file is unlocked from the parent, so we need
650 * to close it in the child */
651
652 pa_autospawn_lock_release();
653 pa_autospawn_lock_done(TRUE);
654
655 autospawn_locked = FALSE;
656 autospawn_fd = -1;
657 }
658
659 pa_assert_se(pa_close(daemon_pipe[0]) == 0);
660 daemon_pipe[0] = -1;
661 #endif
662
663 if (conf->auto_log_target)
664 pa_log_set_target(PA_LOG_SYSLOG);
665
666 #ifdef HAVE_SETSID
667 setsid();
668 #endif
669 #ifdef HAVE_SETPGID
670 setpgid(0,0);
671 #endif
672
673 #ifndef OS_IS_WIN32
674 pa_close(0);
675 pa_close(1);
676 pa_close(2);
677
678 pa_assert_se(open("/dev/null", O_RDONLY) == 0);
679 pa_assert_se(open("/dev/null", O_WRONLY) == 1);
680 pa_assert_se(open("/dev/null", O_WRONLY) == 2);
681 #else
682 FreeConsole();
683 #endif
684
685 #ifdef SIGTTOU
686 signal(SIGTTOU, SIG_IGN);
687 #endif
688 #ifdef SIGTTIN
689 signal(SIGTTIN, SIG_IGN);
690 #endif
691 #ifdef SIGTSTP
692 signal(SIGTSTP, SIG_IGN);
693 #endif
694
695 #ifdef TIOCNOTTY
696 if ((tty_fd = open("/dev/tty", O_RDWR)) >= 0) {
697 ioctl(tty_fd, TIOCNOTTY, (char*) 0);
698 pa_assert_se(pa_close(tty_fd) == 0);
699 }
700 #endif
701 }
702
703 pa_set_env("PULSE_INTERNAL", "1");
704 pa_assert_se(chdir("/") == 0);
705 umask(0022);
706
707 #ifdef HAVE_SYS_RESOURCE_H
708 set_all_rlimits(conf);
709 #endif
710 pa_rtclock_hrtimer_enable();
711
712 pa_raise_priority(conf->nice_level);
713
714 if (conf->system_instance)
715 if (change_user() < 0)
716 goto finish;
717
718 pa_set_env("PULSE_SYSTEM", conf->system_instance ? "1" : "0");
719
720 pa_log_info(_("This is PulseAudio %s"), PACKAGE_VERSION);
721 pa_log_debug(_("Compilation host: %s"), CANONICAL_HOST);
722 pa_log_debug(_("Compilation CFLAGS: %s"), PA_CFLAGS);
723
724 s = pa_uname_string();
725 pa_log_debug(_("Running on host: %s"), s);
726 pa_xfree(s);
727
728 pa_log_debug(_("Found %u CPUs."), pa_ncpus());
729
730 pa_log_info(_("Page size is %lu bytes"), (unsigned long) PA_PAGE_SIZE);
731
732 #ifdef HAVE_VALGRIND_MEMCHECK_H
733 pa_log_debug(_("Compiled with Valgrind support: yes"));
734 #else
735 pa_log_debug(_("Compiled with Valgrind support: no"));
736 #endif
737
738 pa_log_debug(_("Running in valgrind mode: %s"), pa_yes_no(pa_in_valgrind()));
739
740 #ifdef __OPTIMIZE__
741 pa_log_debug(_("Optimized build: yes"));
742 #else
743 pa_log_debug(_("Optimized build: no"));
744 #endif
745
746 #ifdef NDEBUG
747 pa_log_debug(_("NDEBUG defined, all asserts disabled."));
748 #elif defined(FASTPATH)
749 pa_log_debug(_("FASTPATH defined, only fast path asserts disabled."));
750 #else
751 pa_log_debug(_("All asserts enabled."));
752 #endif
753
754 if (!(s = pa_machine_id())) {
755 pa_log(_("Failed to get machine ID"));
756 goto finish;
757 }
758 pa_log_info(_("Machine ID is %s."), s);
759 pa_xfree(s);
760
761 if ((s = pa_session_id())) {
762 pa_log_info(_("Session ID is %s."), s);
763 pa_xfree(s);
764 }
765
766 if (!(s = pa_get_runtime_dir()))
767 goto finish;
768 pa_log_info(_("Using runtime directory %s."), s);
769 pa_xfree(s);
770
771 if (!(s = pa_get_state_dir()))
772 goto finish;
773 pa_log_info(_("Using state directory %s."), s);
774 pa_xfree(s);
775
776 pa_log_info(_("Running in system mode: %s"), pa_yes_no(pa_in_system_mode()));
777
778 if (pa_in_system_mode())
779 pa_log_warn(_("OK, so you are running PA in system mode. Please note that you most likely shouldn't be doing that.\n"
780 "If you do it nonetheless then it's your own fault if things don't work as expected.\n"
781 "Please read http://pulseaudio.org/wiki/WhatIsWrongWithSystemMode for an explanation why system mode is usually a bad idea."));
782
783 if (conf->use_pid_file) {
784 int z;
785
786 if ((z = pa_pid_file_create("pulseaudio")) != 0) {
787
788 if (conf->cmd == PA_CMD_START && z > 0) {
789 /* If we are already running and with are run in
790 * --start mode, then let's return this as success. */
791
792 retval = 0;
793 goto finish;
794 }
795
796 pa_log(_("pa_pid_file_create() failed."));
797 goto finish;
798 }
799
800 valid_pid_file = TRUE;
801 }
802
803 pa_disable_sigpipe();
804
805 if (pa_rtclock_hrtimer())
806 pa_log_info(_("Fresh high-resolution timers available! Bon appetit!"));
807 else
808 pa_log_info(_("Dude, your kernel stinks! The chef's recommendation today is Linux with high-resolution timers enabled!"));
809
810 if (conf->lock_memory) {
811 #ifdef HAVE_SYS_MMAN_H
812 if (mlockall(MCL_FUTURE) < 0)
813 pa_log_warn("mlockall() failed: %s", pa_cstrerror(errno));
814 else
815 pa_log_info("Sucessfully locked process into memory.");
816 #else
817 pa_log_warn("Memory locking requested but not supported on platform.");
818 #endif
819 }
820
821 pa_memtrap_install();
822
823 pa_cpu_init_x86();
824
825 pa_assert_se(mainloop = pa_mainloop_new());
826
827 if (!(c = pa_core_new(pa_mainloop_get_api(mainloop), !conf->disable_shm, conf->shm_size))) {
828 pa_log(_("pa_core_new() failed."));
829 goto finish;
830 }
831
832 c->default_sample_spec = conf->default_sample_spec;
833 c->default_channel_map = conf->default_channel_map;
834 c->default_n_fragments = conf->default_n_fragments;
835 c->default_fragment_size_msec = conf->default_fragment_size_msec;
836 c->exit_idle_time = conf->exit_idle_time;
837 c->scache_idle_time = conf->scache_idle_time;
838 c->resample_method = conf->resample_method;
839 c->realtime_priority = conf->realtime_priority;
840 c->realtime_scheduling = !!conf->realtime_scheduling;
841 c->disable_remixing = !!conf->disable_remixing;
842 c->disable_lfe_remixing = !!conf->disable_lfe_remixing;
843 c->running_as_daemon = !!conf->daemonize;
844 c->disallow_exit = conf->disallow_exit;
845 c->flat_volumes = conf->flat_volumes;
846
847 pa_assert_se(pa_signal_init(pa_mainloop_get_api(mainloop)) == 0);
848 pa_signal_new(SIGINT, signal_callback, c);
849 pa_signal_new(SIGTERM, signal_callback, c);
850 #ifdef SIGUSR1
851 pa_signal_new(SIGUSR1, signal_callback, c);
852 #endif
853 #ifdef SIGUSR2
854 pa_signal_new(SIGUSR2, signal_callback, c);
855 #endif
856 #ifdef SIGHUP
857 pa_signal_new(SIGHUP, signal_callback, c);
858 #endif
859
860 #ifdef OS_IS_WIN32
861 win32_timer = pa_mainloop_get_api(mainloop)->rtclock_time_new(pa_mainloop_get_api(mainloop), pa_gettimeofday(&win32_tv), message_cb, NULL);
862 #endif
863
864 if (!conf->no_cpu_limit)
865 pa_assert_se(pa_cpu_limit_init(pa_mainloop_get_api(mainloop)) == 0);
866
867 buf = pa_strbuf_new();
868 if (conf->load_default_script_file) {
869 FILE *f;
870
871 if ((f = pa_daemon_conf_open_default_script_file(conf))) {
872 r = pa_cli_command_execute_file_stream(c, f, buf, &conf->fail);
873 fclose(f);
874 }
875 }
876
877 if (r >= 0)
878 r = pa_cli_command_execute(c, conf->script_commands, buf, &conf->fail);
879
880 pa_log_error("%s", s = pa_strbuf_tostring_free(buf));
881 pa_xfree(s);
882
883 /* We completed the initial module loading, so let's disable it
884 * from now on, if requested */
885 c->disallow_module_loading = !!conf->disallow_module_loading;
886
887 if (r < 0 && conf->fail) {
888 pa_log(_("Failed to initialize daemon."));
889 goto finish;
890 }
891
892 if (!c->modules || pa_idxset_size(c->modules) == 0) {
893 pa_log(_("Daemon startup without any loaded modules, refusing to work."));
894 goto finish;
895 }
896
897 #ifdef HAVE_FORK
898 if (daemon_pipe[1] >= 0) {
899 int ok = 0;
900 pa_loop_write(daemon_pipe[1], &ok, sizeof(ok), NULL);
901 pa_close(daemon_pipe[1]);
902 daemon_pipe[1] = -1;
903 }
904 #endif
905
906 #ifdef HAVE_DBUS
907 dbus = register_dbus(c);
908 #endif
909
910 pa_log_info(_("Daemon startup complete."));
911
912 retval = 0;
913 if (pa_mainloop_run(mainloop, &retval) < 0)
914 goto finish;
915
916 pa_log_info(_("Daemon shutdown initiated."));
917
918 finish:
919 #ifdef HAVE_DBUS
920 if (dbus)
921 pa_dbus_connection_unref(dbus);
922 #endif
923
924 if (autospawn_fd >= 0) {
925 if (autospawn_locked)
926 pa_autospawn_lock_release();
927
928 pa_autospawn_lock_done(FALSE);
929 }
930
931 #ifdef OS_IS_WIN32
932 if (win32_timer)
933 pa_mainloop_get_api(mainloop)->time_free(win32_timer);
934 #endif
935
936 if (c) {
937 pa_core_unref(c);
938 pa_log_info(_("Daemon terminated."));
939 }
940
941 if (!conf->no_cpu_limit)
942 pa_cpu_limit_done();
943
944 pa_signal_done();
945
946 #ifdef HAVE_FORK
947 if (daemon_pipe[1] >= 0)
948 pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL);
949
950 pa_close_pipe(daemon_pipe);
951 #endif
952
953 if (mainloop)
954 pa_mainloop_free(mainloop);
955
956 if (conf)
957 pa_daemon_conf_free(conf);
958
959 if (valid_pid_file)
960 pa_pid_file_remove();
961
962 #ifdef OS_IS_WIN32
963 WSACleanup();
964 #endif
965
966 if (ltdl_init)
967 pa_ltdl_done();
968
969 #ifdef HAVE_DBUS
970 dbus_shutdown();
971 #endif
972
973 return retval;
974 }