Get rid of liboil
[profile/ivi/pulseaudio.git] / 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 }