]> code.delx.au - pulseaudio/blob - src/daemon/main.c
Cleaned up the includes after the restructuring. Indicate which headers are
[pulseaudio] / src / daemon / main.c
1 /* $Id$ */
2
3 /***
4 This file is part of polypaudio.
5
6 polypaudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 2 of the License,
9 or (at your option) any later version.
10
11 polypaudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with polypaudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <unistd.h>
27 #include <errno.h>
28 #include <string.h>
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <signal.h>
32 #include <stddef.h>
33 #include <assert.h>
34 #include <ltdl.h>
35 #include <limits.h>
36 #include <fcntl.h>
37 #include <unistd.h>
38 #include <sys/types.h>
39 #include <liboil/liboil.h>
40
41 #ifdef HAVE_SYS_IOCTL_H
42 #include <sys/ioctl.h>
43 #endif
44
45 #ifdef HAVE_LIBWRAP
46 #include <syslog.h>
47 #include <tcpd.h>
48 #endif
49
50 #include "../polypcore/winsock.h"
51
52 #include <polyp/mainloop.h>
53 #include <polyp/mainloop-signal.h>
54
55 #include <polypcore/core.h>
56 #include <polypcore/memblock.h>
57 #include <polypcore/module.h>
58 #include <polypcore/cli-command.h>
59 #include <polypcore/log.h>
60 #include <polypcore/util.h>
61 #include <polypcore/sioman.h>
62 #include <polypcore/xmalloc.h>
63 #include <polypcore/cli-text.h>
64 #include <polypcore/pid.h>
65 #include <polypcore/namereg.h>
66
67 #include "cmdline.h"
68 #include "cpulimit.h"
69 #include "daemon-conf.h"
70 #include "dumpmodules.h"
71 #include "caps.h"
72
73 #ifdef HAVE_LIBWRAP
74 /* Only one instance of these variables */
75 int allow_severity = LOG_INFO;
76 int deny_severity = LOG_WARNING;
77 #endif
78
79 #ifdef OS_IS_WIN32
80
81 static void message_cb(pa_mainloop_api*a, pa_defer_event *e, void *userdata) {
82 MSG msg;
83
84 while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
85 if (msg.message == WM_QUIT)
86 raise(SIGTERM);
87 else {
88 TranslateMessage(&msg);
89 DispatchMessage(&msg);
90 }
91 }
92 }
93
94 #endif
95
96 static void signal_callback(pa_mainloop_api*m, PA_GCC_UNUSED pa_signal_event *e, int sig, void *userdata) {
97 pa_log_info(__FILE__": Got signal %s.\n", pa_strsignal(sig));
98
99 switch (sig) {
100 #ifdef SIGUSR1
101 case SIGUSR1:
102 pa_module_load(userdata, "module-cli", NULL);
103 break;
104 #endif
105
106 #ifdef SIGUSR2
107 case SIGUSR2:
108 pa_module_load(userdata, "module-cli-protocol-unix", NULL);
109 break;
110 #endif
111
112 #ifdef SIGHUP
113 case SIGHUP: {
114 char *c = pa_full_status_string(userdata);
115 pa_log_notice(c);
116 pa_xfree(c);
117 return;
118 }
119 #endif
120
121 case SIGINT:
122 case SIGTERM:
123 default:
124 pa_log_info(__FILE__": Exiting.\n");
125 m->quit(m, 1);
126 break;
127 }
128 }
129
130 static void close_pipe(int p[2]) {
131 if (p[0] != -1)
132 close(p[0]);
133 if (p[1] != -1)
134 close(p[1]);
135 p[0] = p[1] = -1;
136 }
137
138 int main(int argc, char *argv[]) {
139 pa_core *c;
140 pa_strbuf *buf = NULL;
141 pa_daemon_conf *conf;
142 pa_mainloop *mainloop;
143
144 char *s;
145 int r, retval = 1, d = 0;
146 int daemon_pipe[2] = { -1, -1 };
147 int suid_root;
148 int valid_pid_file = 0;
149
150 #ifdef HAVE_GETUID
151 gid_t gid = (gid_t) -1;
152 #endif
153
154 #ifdef OS_IS_WIN32
155 pa_defer_event *defer;
156 #endif
157
158 pa_limit_caps();
159
160 #ifdef HAVE_GETUID
161 suid_root = getuid() != 0 && geteuid() == 0;
162
163 if (suid_root && (pa_uid_in_group("realtime", &gid) <= 0 || gid >= 1000)) {
164 pa_log_warn(__FILE__": WARNING: called SUID root, but not in group 'realtime'.\n");
165 pa_drop_root();
166 }
167 #else
168 suid_root = 0;
169 #endif
170
171 LTDL_SET_PRELOADED_SYMBOLS();
172
173 r = lt_dlinit();
174 assert(r == 0);
175
176 #ifdef OS_IS_WIN32
177 {
178 WSADATA data;
179 WSAStartup(MAKEWORD(2, 0), &data);
180 }
181 #endif
182
183 pa_log_set_ident("polypaudio");
184
185 conf = pa_daemon_conf_new();
186
187 if (pa_daemon_conf_load(conf, NULL) < 0)
188 goto finish;
189
190 if (pa_daemon_conf_env(conf) < 0)
191 goto finish;
192
193 if (pa_cmdline_parse(conf, argc, argv, &d) < 0) {
194 pa_log(__FILE__": failed to parse command line.\n");
195 goto finish;
196 }
197
198 pa_log_set_maximal_level(conf->log_level);
199 pa_log_set_target(conf->auto_log_target ? PA_LOG_STDERR : conf->log_target, NULL);
200
201 if (conf->high_priority && conf->cmd == PA_CMD_DAEMON)
202 pa_raise_priority();
203
204 pa_drop_caps();
205
206 if (suid_root)
207 pa_drop_root();
208
209 if (conf->dl_search_path)
210 lt_dlsetsearchpath(conf->dl_search_path);
211
212 switch (conf->cmd) {
213 case PA_CMD_DUMP_MODULES:
214 pa_dump_modules(conf, argc-d, argv+d);
215 retval = 0;
216 goto finish;
217
218 case PA_CMD_DUMP_CONF: {
219 s = pa_daemon_conf_dump(conf);
220 fputs(s, stdout);
221 pa_xfree(s);
222 retval = 0;
223 goto finish;
224 }
225
226 case PA_CMD_HELP :
227 pa_cmdline_help(argv[0]);
228 retval = 0;
229 goto finish;
230
231 case PA_CMD_VERSION :
232 printf(PACKAGE_NAME" "PACKAGE_VERSION"\n");
233 retval = 0;
234 goto finish;
235
236 case PA_CMD_CHECK: {
237 pid_t pid;
238
239 if (pa_pid_file_check_running(&pid) < 0) {
240 pa_log_info(__FILE__": daemon not running\n");
241 } else {
242 pa_log_info(__FILE__": daemon running as PID %u\n", pid);
243 retval = 0;
244 }
245
246 goto finish;
247
248 }
249 case PA_CMD_KILL:
250
251 if (pa_pid_file_kill(SIGINT, NULL) < 0)
252 pa_log(__FILE__": failed to kill daemon.\n");
253 else
254 retval = 0;
255
256 goto finish;
257
258 default:
259 assert(conf->cmd == PA_CMD_DAEMON);
260 }
261
262 if (conf->daemonize) {
263 pid_t child;
264 int tty_fd;
265
266 if (pa_stdio_acquire() < 0) {
267 pa_log(__FILE__": failed to acquire stdio.\n");
268 goto finish;
269 }
270
271 #ifdef HAVE_FORK
272 if (pipe(daemon_pipe) < 0) {
273 pa_log(__FILE__": failed to create pipe.\n");
274 goto finish;
275 }
276
277 if ((child = fork()) < 0) {
278 pa_log(__FILE__": fork() failed: %s\n", strerror(errno));
279 goto finish;
280 }
281
282 if (child != 0) {
283 /* Father */
284
285 close(daemon_pipe[1]);
286 daemon_pipe[1] = -1;
287
288 if (pa_loop_read(daemon_pipe[0], &retval, sizeof(retval)) != sizeof(retval)) {
289 pa_log(__FILE__": read() failed: %s\n", strerror(errno));
290 retval = 1;
291 }
292
293 if (retval)
294 pa_log(__FILE__": daemon startup failed.\n");
295 else
296 pa_log_info(__FILE__": daemon startup successful.\n");
297
298 goto finish;
299 }
300
301 close(daemon_pipe[0]);
302 daemon_pipe[0] = -1;
303 #endif
304
305 if (conf->auto_log_target)
306 pa_log_set_target(PA_LOG_SYSLOG, NULL);
307
308 #ifdef HAVE_SETSID
309 setsid();
310 #endif
311 #ifdef HAVE_SETPGID
312 setpgid(0,0);
313 #endif
314
315 #ifndef OS_IS_WIN32
316 close(0);
317 close(1);
318 close(2);
319
320 open("/dev/null", O_RDONLY);
321 open("/dev/null", O_WRONLY);
322 open("/dev/null", O_WRONLY);
323 #else
324 FreeConsole();
325 #endif
326
327 #ifdef SIGTTOU
328 signal(SIGTTOU, SIG_IGN);
329 #endif
330 #ifdef SIGTTIN
331 signal(SIGTTIN, SIG_IGN);
332 #endif
333 #ifdef SIGTSTP
334 signal(SIGTSTP, SIG_IGN);
335 #endif
336
337 #ifdef TIOCNOTTY
338 if ((tty_fd = open("/dev/tty", O_RDWR)) >= 0) {
339 ioctl(tty_fd, TIOCNOTTY, (char*) 0);
340 close(tty_fd);
341 }
342 #endif
343 }
344
345 chdir("/");
346
347 if (conf->use_pid_file) {
348 if (pa_pid_file_create() < 0) {
349 pa_log(__FILE__": pa_pid_file_create() failed.\n");
350 #ifdef HAVE_FORK
351 if (conf->daemonize)
352 pa_loop_write(daemon_pipe[1], &retval, sizeof(retval));
353 #endif
354 goto finish;
355 }
356
357 valid_pid_file = 1;
358 }
359
360 mainloop = pa_mainloop_new();
361 assert(mainloop);
362
363 c = pa_core_new(pa_mainloop_get_api(mainloop));
364 assert(c);
365
366 r = pa_signal_init(pa_mainloop_get_api(mainloop));
367 assert(r == 0);
368 pa_signal_new(SIGINT, signal_callback, c);
369 pa_signal_new(SIGTERM, signal_callback, c);
370 #ifdef SIGPIPE
371 signal(SIGPIPE, SIG_IGN);
372 #endif
373
374 #ifdef OS_IS_WIN32
375 defer = pa_mainloop_get_api(mainloop)->defer_new(pa_mainloop_get_api(mainloop), message_cb, NULL);
376 assert(defer);
377 #endif
378
379 if (conf->daemonize)
380 c->running_as_daemon = 1;
381
382 #ifdef SIGUSR1
383 pa_signal_new(SIGUSR1, signal_callback, c);
384 #endif
385 #ifdef SIGUSR2
386 pa_signal_new(SIGUSR2, signal_callback, c);
387 #endif
388 #ifdef SIGHUP
389 pa_signal_new(SIGHUP, signal_callback, c);
390 #endif
391
392 oil_init();
393
394 r = pa_cpu_limit_init(pa_mainloop_get_api(mainloop));
395 assert(r == 0);
396
397 buf = pa_strbuf_new();
398 assert(buf);
399 if (conf->default_script_file)
400 r = pa_cli_command_execute_file(c, conf->default_script_file, buf, &conf->fail);
401
402 if (r >= 0)
403 r = pa_cli_command_execute(c, conf->script_commands, buf, &conf->fail);
404 pa_log(s = pa_strbuf_tostring_free(buf));
405 pa_xfree(s);
406
407 if (r < 0 && conf->fail) {
408 pa_log(__FILE__": failed to initialize daemon.\n");
409 #ifdef HAVE_FORK
410 if (conf->daemonize)
411 pa_loop_write(daemon_pipe[1], &retval, sizeof(retval));
412 #endif
413 } else if (!c->modules || pa_idxset_size(c->modules) == 0) {
414 pa_log(__FILE__": daemon startup without any loaded modules, refusing to work.\n");
415 #ifdef HAVE_FORK
416 if (conf->daemonize)
417 pa_loop_write(daemon_pipe[1], &retval, sizeof(retval));
418 #endif
419 } else {
420
421 retval = 0;
422 #ifdef HAVE_FORK
423 if (conf->daemonize)
424 pa_loop_write(daemon_pipe[1], &retval, sizeof(retval));
425 #endif
426
427 c->disallow_module_loading = conf->disallow_module_loading;
428 c->exit_idle_time = conf->exit_idle_time;
429 c->module_idle_time = conf->module_idle_time;
430 c->scache_idle_time = conf->scache_idle_time;
431 c->resample_method = conf->resample_method;
432
433 if (c->default_sink_name &&
434 pa_namereg_get(c, c->default_sink_name, PA_NAMEREG_SINK, 1) == NULL) {
435 pa_log_error("%s : Fatal error. Default sink name (%s) does not exist in name register.\n", __FILE__, c->default_sink_name);
436 retval = 1;
437 } else {
438 pa_log_info(__FILE__": Daemon startup complete.\n");
439 if (pa_mainloop_run(mainloop, &retval) < 0)
440 retval = 1;
441 pa_log_info(__FILE__": Daemon shutdown initiated.\n");
442 }
443 }
444
445 #ifdef OS_IS_WIN32
446 pa_mainloop_get_api(mainloop)->defer_free(defer);
447 #endif
448
449 pa_core_free(c);
450
451 pa_cpu_limit_done();
452 pa_signal_done();
453 pa_mainloop_free(mainloop);
454
455 pa_log_info(__FILE__": Daemon terminated.\n");
456
457 finish:
458
459 if (conf)
460 pa_daemon_conf_free(conf);
461
462 if (valid_pid_file)
463 pa_pid_file_remove();
464
465 close_pipe(daemon_pipe);
466
467 #ifdef OS_IS_WIN32
468 WSACleanup();
469 #endif
470
471 lt_dlexit();
472
473 return retval;
474 }