]> code.delx.au - pulseaudio/blob - src/daemon/daemon-conf.c
Don't set RLIMIT_MEMBLOCK to 0 on startup. Retain 4 pages
[pulseaudio] / src / daemon / daemon-conf.c
1 /* $Id$ */
2
3 /***
4 This file is part of PulseAudio.
5
6 Copyright 2004-2006 Lennart Poettering
7 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
8
9 PulseAudio is free software; you can redistribute it and/or modify
10 it under the terms of the GNU Lesser General Public License as published
11 by the Free Software Foundation; either version 2 of the License,
12 or (at your option) any later version.
13
14 PulseAudio is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public License
20 along with PulseAudio; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22 USA.
23 ***/
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include <errno.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <unistd.h>
33
34 #include <pulse/xmalloc.h>
35
36 #include <pulsecore/core-error.h>
37 #include <pulsecore/core-util.h>
38 #include <pulsecore/strbuf.h>
39 #include <pulsecore/conf-parser.h>
40 #include <pulsecore/resampler.h>
41 #include <pulsecore/macro.h>
42
43 #include "daemon-conf.h"
44
45 #ifndef OS_IS_WIN32
46 # define PATH_SEP "/"
47 #else
48 # define PATH_SEP "\\"
49 #endif
50
51 #define DEFAULT_SCRIPT_FILE PA_DEFAULT_CONFIG_DIR PATH_SEP "default.pa"
52 #define DEFAULT_SCRIPT_FILE_USER PATH_SEP "default.pa"
53 #define DEFAULT_CONFIG_FILE PA_DEFAULT_CONFIG_DIR PATH_SEP "daemon.conf"
54 #define DEFAULT_CONFIG_FILE_USER PATH_SEP "daemon.conf"
55
56 #define ENV_SCRIPT_FILE "PULSE_SCRIPT"
57 #define ENV_CONFIG_FILE "PULSE_CONFIG"
58 #define ENV_DL_SEARCH_PATH "PULSE_DLPATH"
59
60 static const pa_daemon_conf default_conf = {
61 .cmd = PA_CMD_DAEMON,
62 .daemonize = 0,
63 .fail = 1,
64 .high_priority = 0,
65 .disallow_module_loading = 0,
66 .exit_idle_time = -1,
67 .module_idle_time = 20,
68 .scache_idle_time = 20,
69 .auto_log_target = 1,
70 .script_commands = NULL,
71 .dl_search_path = NULL,
72 .default_script_file = NULL,
73 .log_target = PA_LOG_SYSLOG,
74 .log_level = PA_LOG_NOTICE,
75 .resample_method = PA_RESAMPLER_AUTO,
76 .config_file = NULL,
77 .use_pid_file = 1,
78 .system_instance = 0,
79 .no_cpu_limit = 0,
80 .disable_shm = 0,
81 .default_n_fragments = 4,
82 .default_fragment_size_msec = 25,
83 .default_sample_spec = { .format = PA_SAMPLE_S16NE, .rate = 44100, .channels = 2 }
84 #ifdef HAVE_SYS_RESOURCE_H
85 , .rlimit_as = { .value = 0, .is_set = 0 },
86 .rlimit_core = { .value = 0, .is_set = 0 },
87 .rlimit_data = { .value = 0, .is_set = 0 },
88 .rlimit_fsize = { .value = 0, .is_set = 0 },
89 .rlimit_nofile = { .value = 256, .is_set = 1 },
90 .rlimit_stack = { .value = 0, .is_set = 0 }
91 #ifdef RLIMIT_NPROC
92 , .rlimit_nproc = { .value = 0, .is_set = 0 }
93 #endif
94 #ifdef RLIMIT_MEMLOCK
95 , .rlimit_memlock = { .value = 16384, .is_set = 1 }
96 #endif
97 #endif
98 };
99
100 pa_daemon_conf* pa_daemon_conf_new(void) {
101 FILE *f;
102 pa_daemon_conf *c = pa_xnewdup(pa_daemon_conf, &default_conf, 1);
103
104 if ((f = pa_open_config_file(DEFAULT_SCRIPT_FILE, DEFAULT_SCRIPT_FILE_USER, ENV_SCRIPT_FILE, &c->default_script_file, "r")))
105 fclose(f);
106
107 c->dl_search_path = pa_xstrdup(PA_DLSEARCHPATH);
108 return c;
109 }
110
111 void pa_daemon_conf_free(pa_daemon_conf *c) {
112 pa_assert(c);
113 pa_xfree(c->script_commands);
114 pa_xfree(c->dl_search_path);
115 pa_xfree(c->default_script_file);
116 pa_xfree(c->config_file);
117 pa_xfree(c);
118 }
119
120 int pa_daemon_conf_set_log_target(pa_daemon_conf *c, const char *string) {
121 pa_assert(c);
122 pa_assert(string);
123
124 if (!strcmp(string, "auto"))
125 c->auto_log_target = 1;
126 else if (!strcmp(string, "syslog")) {
127 c->auto_log_target = 0;
128 c->log_target = PA_LOG_SYSLOG;
129 } else if (!strcmp(string, "stderr")) {
130 c->auto_log_target = 0;
131 c->log_target = PA_LOG_STDERR;
132 } else
133 return -1;
134
135 return 0;
136 }
137
138 int pa_daemon_conf_set_log_level(pa_daemon_conf *c, const char *string) {
139 uint32_t u;
140 pa_assert(c);
141 pa_assert(string);
142
143 if (pa_atou(string, &u) >= 0) {
144 if (u >= PA_LOG_LEVEL_MAX)
145 return -1;
146
147 c->log_level = (pa_log_level_t) u;
148 } else if (pa_startswith(string, "debug"))
149 c->log_level = PA_LOG_DEBUG;
150 else if (pa_startswith(string, "info"))
151 c->log_level = PA_LOG_INFO;
152 else if (pa_startswith(string, "notice"))
153 c->log_level = PA_LOG_NOTICE;
154 else if (pa_startswith(string, "warn"))
155 c->log_level = PA_LOG_WARN;
156 else if (pa_startswith(string, "err"))
157 c->log_level = PA_LOG_ERROR;
158 else
159 return -1;
160
161 return 0;
162 }
163
164 int pa_daemon_conf_set_resample_method(pa_daemon_conf *c, const char *string) {
165 int m;
166 pa_assert(c);
167 pa_assert(string);
168
169 if ((m = pa_parse_resample_method(string)) < 0)
170 return -1;
171
172 c->resample_method = m;
173 return 0;
174 }
175
176 static int parse_log_target(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
177 pa_daemon_conf *c = data;
178
179 pa_assert(filename);
180 pa_assert(lvalue);
181 pa_assert(rvalue);
182 pa_assert(data);
183
184 if (pa_daemon_conf_set_log_target(c, rvalue) < 0) {
185 pa_log("[%s:%u] Invalid log target '%s'.", filename, line, rvalue);
186 return -1;
187 }
188
189 return 0;
190 }
191
192 static int parse_log_level(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
193 pa_daemon_conf *c = data;
194
195 pa_assert(filename);
196 pa_assert(lvalue);
197 pa_assert(rvalue);
198 pa_assert(data);
199
200 if (pa_daemon_conf_set_log_level(c, rvalue) < 0) {
201 pa_log("[%s:%u] Invalid log level '%s'.", filename, line, rvalue);
202 return -1;
203 }
204
205 return 0;
206 }
207
208 static int parse_resample_method(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
209 pa_daemon_conf *c = data;
210
211 pa_assert(filename);
212 pa_assert(lvalue);
213 pa_assert(rvalue);
214 pa_assert(data);
215
216 if (pa_daemon_conf_set_resample_method(c, rvalue) < 0) {
217 pa_log("[%s:%u] Invalid resample method '%s'.", filename, line, rvalue);
218 return -1;
219 }
220
221 return 0;
222 }
223
224 static int parse_rlimit(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
225 #ifdef HAVE_SYS_RESOURCE_H
226 struct pa_rlimit *r = data;
227
228 pa_assert(filename);
229 pa_assert(lvalue);
230 pa_assert(rvalue);
231 pa_assert(r);
232
233 if (rvalue[strspn(rvalue, "\t ")] == 0) {
234 /* Empty string */
235 r->is_set = 0;
236 r->value = 0;
237 } else {
238 int32_t k;
239 if (pa_atoi(rvalue, &k) < 0) {
240 pa_log("[%s:%u] Invalid rlimit '%s'.", filename, line, rvalue);
241 return -1;
242 }
243 r->is_set = k >= 0;
244 r->value = k >= 0 ? (rlim_t) k : 0;
245 }
246 #else
247 pa_log_warn("[%s:%u] rlimit not supported on this platform.", filename, line);
248 #endif
249
250 return 0;
251 }
252
253 static int parse_sample_format(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
254 pa_daemon_conf *c = data;
255 pa_sample_format_t f;
256
257 pa_assert(filename);
258 pa_assert(lvalue);
259 pa_assert(rvalue);
260 pa_assert(data);
261
262 if ((f = pa_parse_sample_format(rvalue)) < 0) {
263 pa_log("[%s:%u] Invalid sample format '%s'.", filename, line, rvalue);
264 return -1;
265 }
266
267 c->default_sample_spec.format = f;
268 return 0;
269 }
270
271 static int parse_sample_rate(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
272 pa_daemon_conf *c = data;
273 int32_t r;
274
275 pa_assert(filename);
276 pa_assert(lvalue);
277 pa_assert(rvalue);
278 pa_assert(data);
279
280 if (pa_atoi(rvalue, &r) < 0 || r > PA_RATE_MAX || r <= 0) {
281 pa_log("[%s:%u] Invalid sample rate '%s'.", filename, line, rvalue);
282 return -1;
283 }
284
285 c->default_sample_spec.rate = r;
286 return 0;
287 }
288
289 static int parse_sample_channels(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
290 pa_daemon_conf *c = data;
291 int32_t n;
292
293 pa_assert(filename);
294 pa_assert(lvalue);
295 pa_assert(rvalue);
296 pa_assert(data);
297
298 if (pa_atoi(rvalue, &n) < 0 || n > PA_CHANNELS_MAX || n <= 0) {
299 pa_log("[%s:%u] Invalid sample channels '%s'.", filename, line, rvalue);
300 return -1;
301 }
302
303 c->default_sample_spec.channels = (uint8_t) n;
304 return 0;
305 }
306
307 static int parse_fragments(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
308 pa_daemon_conf *c = data;
309 int32_t n;
310
311 pa_assert(filename);
312 pa_assert(lvalue);
313 pa_assert(rvalue);
314 pa_assert(data);
315
316 if (pa_atoi(rvalue, &n) < 0 || n < 2) {
317 pa_log("[%s:%u] Invalid number of fragments '%s'.", filename, line, rvalue);
318 return -1;
319 }
320
321 c->default_n_fragments = (unsigned) n;
322 return 0;
323 }
324
325 static int parse_fragment_size_msec(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
326 pa_daemon_conf *c = data;
327 int32_t n;
328
329 pa_assert(filename);
330 pa_assert(lvalue);
331 pa_assert(rvalue);
332 pa_assert(data);
333
334 if (pa_atoi(rvalue, &n) < 0 || n < 1) {
335 pa_log("[%s:%u] Invalid fragment size '%s'.", filename, line, rvalue);
336 return -1;
337 }
338
339 c->default_fragment_size_msec = (unsigned) n;
340 return 0;
341 }
342
343 int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) {
344 int r = -1;
345 FILE *f = NULL;
346
347 pa_config_item table[] = {
348 { "daemonize", pa_config_parse_bool, NULL },
349 { "fail", pa_config_parse_bool, NULL },
350 { "high-priority", pa_config_parse_bool, NULL },
351 { "disallow-module-loading", pa_config_parse_bool, NULL },
352 { "exit-idle-time", pa_config_parse_int, NULL },
353 { "module-idle-time", pa_config_parse_int, NULL },
354 { "scache-idle-time", pa_config_parse_int, NULL },
355 { "dl-search-path", pa_config_parse_string, NULL },
356 { "default-script-file", pa_config_parse_string, NULL },
357 { "log-target", parse_log_target, NULL },
358 { "log-level", parse_log_level, NULL },
359 { "verbose", parse_log_level, NULL },
360 { "resample-method", parse_resample_method, NULL },
361 { "use-pid-file", pa_config_parse_bool, NULL },
362 { "system-instance", pa_config_parse_bool, NULL },
363 { "no-cpu-limit", pa_config_parse_bool, NULL },
364 { "disable-shm", pa_config_parse_bool, NULL },
365 { "default-sample-format", parse_sample_format, NULL },
366 { "default-sample-rate", parse_sample_rate, NULL },
367 { "default-sample-channels", parse_sample_channels, NULL },
368 { "default-fragments", parse_fragments, NULL },
369 { "default-fragment-size-msec", parse_fragment_size_msec, NULL },
370 #ifdef HAVE_SYS_RESOURCE_H
371 { "rlimit-as", parse_rlimit, NULL },
372 { "rlimit-core", parse_rlimit, NULL },
373 { "rlimit-data", parse_rlimit, NULL },
374 { "rlimit-fsize", parse_rlimit, NULL },
375 { "rlimit-nofile", parse_rlimit, NULL },
376 { "rlimit-stack", parse_rlimit, NULL },
377 #ifdef RLIMIT_NPROC
378 { "rlimit-nproc", parse_rlimit, NULL },
379 #endif
380 #ifdef RLIMIT_MEMLOCK
381 { "rlimit-memlock", parse_rlimit, NULL },
382 #endif
383 #endif
384 { NULL, NULL, NULL },
385 };
386
387 table[0].data = &c->daemonize;
388 table[1].data = &c->fail;
389 table[2].data = &c->high_priority;
390 table[3].data = &c->disallow_module_loading;
391 table[4].data = &c->exit_idle_time;
392 table[5].data = &c->module_idle_time;
393 table[6].data = &c->scache_idle_time;
394 table[7].data = &c->dl_search_path;
395 table[8].data = &c->default_script_file;
396 table[9].data = c;
397 table[10].data = c;
398 table[11].data = c;
399 table[12].data = c;
400 table[13].data = &c->use_pid_file;
401 table[14].data = &c->system_instance;
402 table[15].data = &c->no_cpu_limit;
403 table[16].data = &c->disable_shm;
404 table[17].data = c;
405 table[18].data = c;
406 table[19].data = c;
407 table[20].data = c;
408 table[21].data = c;
409 #ifdef HAVE_SYS_RESOURCE_H
410 table[22].data = &c->rlimit_as;
411 table[23].data = &c->rlimit_core;
412 table[24].data = &c->rlimit_data;
413 table[25].data = &c->rlimit_fsize;
414 table[26].data = &c->rlimit_nofile;
415 table[27].data = &c->rlimit_stack;
416 #ifdef RLIMIT_NPROC
417 table[28].data = &c->rlimit_nproc;
418 #endif
419 #ifdef RLIMIT_MEMLOCK
420 #ifndef RLIMIT_NPROC
421 #error "Houston, we have a numbering problem!"
422 #endif
423 table[29].data = &c->rlimit_memlock;
424 #endif
425 #endif
426
427 pa_xfree(c->config_file);
428 c->config_file = NULL;
429
430 f = filename ?
431 fopen(c->config_file = pa_xstrdup(filename), "r") :
432 pa_open_config_file(DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_USER, ENV_CONFIG_FILE, &c->config_file, "r");
433
434 if (!f && errno != ENOENT) {
435 pa_log("WARNING: failed to open configuration file '%s': %s", c->config_file, pa_cstrerror(errno));
436 goto finish;
437 }
438
439 r = f ? pa_config_parse(c->config_file, f, table, NULL) : 0;
440
441 finish:
442 if (f)
443 fclose(f);
444
445 return r;
446 }
447
448 int pa_daemon_conf_env(pa_daemon_conf *c) {
449 char *e;
450
451 if ((e = getenv(ENV_DL_SEARCH_PATH))) {
452 pa_xfree(c->dl_search_path);
453 c->dl_search_path = pa_xstrdup(e);
454 }
455 if ((e = getenv(ENV_SCRIPT_FILE))) {
456 pa_xfree(c->default_script_file);
457 c->default_script_file = pa_xstrdup(e);
458 }
459
460 return 0;
461 }
462
463 static const char* const log_level_to_string[] = {
464 [PA_LOG_DEBUG] = "debug",
465 [PA_LOG_INFO] = "info",
466 [PA_LOG_NOTICE] = "notice",
467 [PA_LOG_WARN] = "warning",
468 [PA_LOG_ERROR] = "error"
469 };
470
471 char *pa_daemon_conf_dump(pa_daemon_conf *c) {
472 pa_strbuf *s;
473
474 pa_assert(c);
475
476 s = pa_strbuf_new();
477
478 if (c->config_file)
479 pa_strbuf_printf(s, "### Read from configuration file: %s ###\n", c->config_file);
480
481 pa_assert(c->log_level <= PA_LOG_LEVEL_MAX);
482
483 pa_strbuf_printf(s, "daemonize = %i\n", !!c->daemonize);
484 pa_strbuf_printf(s, "fail = %i\n", !!c->fail);
485 pa_strbuf_printf(s, "high-priority = %i\n", !!c->high_priority);
486 pa_strbuf_printf(s, "disallow-module-loading = %i\n", !!c->disallow_module_loading);
487 pa_strbuf_printf(s, "exit-idle-time = %i\n", c->exit_idle_time);
488 pa_strbuf_printf(s, "module-idle-time = %i\n", c->module_idle_time);
489 pa_strbuf_printf(s, "scache-idle-time = %i\n", c->scache_idle_time);
490 pa_strbuf_printf(s, "dl-search-path = %s\n", c->dl_search_path ? c->dl_search_path : "");
491 pa_strbuf_printf(s, "default-script-file = %s\n", c->default_script_file);
492 pa_strbuf_printf(s, "log-target = %s\n", c->auto_log_target ? "auto" : (c->log_target == PA_LOG_SYSLOG ? "syslog" : "stderr"));
493 pa_strbuf_printf(s, "log-level = %s\n", log_level_to_string[c->log_level]);
494 pa_strbuf_printf(s, "resample-method = %s\n", pa_resample_method_to_string(c->resample_method));
495 pa_strbuf_printf(s, "use-pid-file = %i\n", c->use_pid_file);
496 pa_strbuf_printf(s, "system-instance = %i\n", !!c->system_instance);
497 pa_strbuf_printf(s, "no-cpu-limit = %i\n", !!c->no_cpu_limit);
498 pa_strbuf_printf(s, "disable-shm = %i\n", !!c->disable_shm);
499 pa_strbuf_printf(s, "default-sample-format = %s\n", pa_sample_format_to_string(c->default_sample_spec.format));
500 pa_strbuf_printf(s, "default-sample-rate = %u\n", c->default_sample_spec.rate);
501 pa_strbuf_printf(s, "default-sample-channels = %u\n", c->default_sample_spec.channels);
502 pa_strbuf_printf(s, "default-fragments = %u\n", c->default_n_fragments);
503 pa_strbuf_printf(s, "default-fragment-size-msec = %u\n", c->default_fragment_size_msec);
504 #ifdef HAVE_SYS_RESOURCE_H
505 pa_strbuf_printf(s, "rlimit-as = %li\n", c->rlimit_as.is_set ? (long int) c->rlimit_as.value : -1);
506 pa_strbuf_printf(s, "rlimit-core = %li\n", c->rlimit_core.is_set ? (long int) c->rlimit_core.value : -1);
507 pa_strbuf_printf(s, "rlimit-data = %li\n", c->rlimit_data.is_set ? (long int) c->rlimit_data.value : -1);
508 pa_strbuf_printf(s, "rlimit-fsize = %li\n", c->rlimit_fsize.is_set ? (long int) c->rlimit_fsize.value : -1);
509 pa_strbuf_printf(s, "rlimit-nofile = %li\n", c->rlimit_nofile.is_set ? (long int) c->rlimit_nofile.value : -1);
510 pa_strbuf_printf(s, "rlimit-stack = %li\n", c->rlimit_stack.is_set ? (long int) c->rlimit_stack.value : -1);
511 #ifdef RLIMIT_NPROC
512 pa_strbuf_printf(s, "rlimit-nproc = %li\n", c->rlimit_nproc.is_set ? (long int) c->rlimit_nproc.value : -1);
513 #endif
514 #ifdef RLIMIT_MEMLOCK
515 pa_strbuf_printf(s, "rlimit-memlock = %li\n", c->rlimit_memlock.is_set ? (long int) c->rlimit_memlock.value : -1);
516 #endif
517 #endif
518
519 return pa_strbuf_tostring_free(s);
520 }