• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, see <http://www.gnu.org/licenses/>.
19 ***/
20 
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24 
25 #include <errno.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <fcntl.h>
30 #include <sys/stat.h>
31 
32 #ifdef HAVE_SCHED_H
33 #include <sched.h>
34 #endif
35 
36 #include <pulse/xmalloc.h>
37 #include <pulse/timeval.h>
38 #include <pulse/version.h>
39 
40 #include <pulsecore/core-error.h>
41 #include <pulsecore/core-util.h>
42 #include <pulsecore/i18n.h>
43 #include <pulsecore/strbuf.h>
44 #include <pulsecore/conf-parser.h>
45 #include <pulsecore/resampler.h>
46 #include <pulsecore/macro.h>
47 
48 #include "daemon-conf.h"
49 
50 #define DEFAULT_SCRIPT_FILE PA_DEFAULT_CONFIG_DIR PA_PATH_SEP "default.pa"
51 #define DEFAULT_SCRIPT_FILE_USER PA_PATH_SEP "default.pa"
52 #define DEFAULT_SYSTEM_SCRIPT_FILE PA_DEFAULT_CONFIG_DIR PA_PATH_SEP "system.pa"
53 
54 #define DEFAULT_CONFIG_FILE PA_DEFAULT_CONFIG_DIR PA_PATH_SEP "daemon.conf"
55 #define DEFAULT_CONFIG_FILE_USER PA_PATH_SEP "daemon.conf"
56 
57 #define ENV_SCRIPT_FILE "PULSE_SCRIPT"
58 #define ENV_CONFIG_FILE "PULSE_CONFIG"
59 #define ENV_DL_SEARCH_PATH "PULSE_DLPATH"
60 
61 static const pa_daemon_conf default_conf = {
62     .cmd = PA_CMD_DAEMON,
63     .daemonize = false,
64     .fail = true,
65     .high_priority = true,
66     .nice_level = -11,
67     .realtime_scheduling = true,
68     .realtime_priority = 5,  /* Half of JACK's default rtprio */
69     .disallow_module_loading = false,
70     .disallow_exit = false,
71     .flat_volumes = false,
72     .rescue_streams = true,
73     .exit_idle_time = 20,
74     .scache_idle_time = 20,
75     .script_commands = NULL,
76     .dl_search_path = NULL,
77     .load_default_script_file = true,
78     .default_script_file = NULL,
79     .log_target = NULL,
80     .log_level = PA_LOG_NOTICE,
81     .log_backtrace = 0,
82     .log_meta = false,
83     .log_time = false,
84     .resample_method = PA_RESAMPLER_AUTO,
85     .avoid_resampling = false,
86     .disable_remixing = false,
87     .remixing_use_all_sink_channels = true,
88     .remixing_produce_lfe = false,
89     .remixing_consume_lfe = false,
90     .lfe_crossover_freq = 0,
91     .config_file = NULL,
92     .use_pid_file = true,
93     .system_instance = false,
94 #ifdef HAVE_DBUS
95     .local_server_type = PA_SERVER_TYPE_UNSET, /* The actual default is _USER, but we have to detect when the user doesn't specify this option. */
96 #endif
97     .no_cpu_limit = true,
98     .disable_shm = false,
99     .disable_memfd = false,
100     .lock_memory = false,
101     .deferred_volume = true,
102     .default_n_fragments = 4,
103     .default_fragment_size_msec = 25,
104     .deferred_volume_safety_margin_usec = 8000,
105     .deferred_volume_extra_delay_usec = 0,
106     .default_sample_spec = { .format = PA_SAMPLE_S16NE, .rate = 44100, .channels = 2 },
107     .alternate_sample_rate = 48000,
108     .default_channel_map = { .channels = 2, .map = { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT } },
109     .shm_size = 0
110 #ifdef HAVE_SYS_RESOURCE_H
111    ,.rlimit_fsize = { .value = 0, .is_set = false },
112     .rlimit_data = { .value = 0, .is_set = false },
113     .rlimit_stack = { .value = 0, .is_set = false },
114     .rlimit_core = { .value = 0, .is_set = false }
115 #ifdef RLIMIT_RSS
116    ,.rlimit_rss = { .value = 0, .is_set = false }
117 #endif
118 #ifdef RLIMIT_NPROC
119    ,.rlimit_nproc = { .value = 0, .is_set = false }
120 #endif
121 #ifdef RLIMIT_NOFILE
122    ,.rlimit_nofile = { .value = 256, .is_set = true }
123 #endif
124 #ifdef RLIMIT_MEMLOCK
125    ,.rlimit_memlock = { .value = 0, .is_set = false }
126 #endif
127 #ifdef RLIMIT_AS
128    ,.rlimit_as = { .value = 0, .is_set = false }
129 #endif
130 #ifdef RLIMIT_LOCKS
131    ,.rlimit_locks = { .value = 0, .is_set = false }
132 #endif
133 #ifdef RLIMIT_SIGPENDING
134    ,.rlimit_sigpending = { .value = 0, .is_set = false }
135 #endif
136 #ifdef RLIMIT_MSGQUEUE
137    ,.rlimit_msgqueue = { .value = 0, .is_set = false }
138 #endif
139 #ifdef RLIMIT_NICE
140    ,.rlimit_nice = { .value = 31, .is_set = true }     /* nice level of -11 */
141 #endif
142 #ifdef RLIMIT_RTPRIO
143    ,.rlimit_rtprio = { .value = 9, .is_set = true }    /* One below JACK's default for the server */
144 #endif
145 #ifdef RLIMIT_RTTIME
146    ,.rlimit_rttime = { .value = 200*PA_USEC_PER_MSEC, .is_set = true } /* rtkit's limit is 200 ms */
147 #endif
148 #endif
149 };
150 
pa_daemon_conf_new(void)151 pa_daemon_conf *pa_daemon_conf_new(void) {
152     pa_daemon_conf *c;
153 
154     c = pa_xnewdup(pa_daemon_conf, &default_conf, 1);
155 
156 #ifdef OS_IS_WIN32
157     c->dl_search_path = pa_sprintf_malloc("%s" PA_PATH_SEP "lib" PA_PATH_SEP "pulse-%d.%d" PA_PATH_SEP "modules",
158                                           pa_win32_get_toplevel(NULL), PA_MAJOR, PA_MINOR);
159 #else
160 #ifdef HAVE_RUNNING_FROM_BUILD_TREE
161     if (pa_run_from_build_tree()) {
162         pa_log_notice("Detected that we are run from the build tree, fixing search path.");
163 #ifdef MESON_BUILD
164         c->dl_search_path = pa_xstrdup(PA_BUILDDIR PA_PATH_SEP "src" PA_PATH_SEP "modules");
165 #else
166         c->dl_search_path = pa_xstrdup(PA_BUILDDIR);
167 #endif // Endof #ifdef MESON_BUILD
168     } else
169 #endif // Endof #ifdef HAVE_RUNNING_FROM_BUILD_TREE
170         c->dl_search_path = pa_xstrdup(PA_DLSEARCHPATH);
171 #endif // Endof #ifdef OS_IS_WIN32
172 
173     return c;
174 }
175 
pa_daemon_conf_free(pa_daemon_conf * c)176 void pa_daemon_conf_free(pa_daemon_conf *c) {
177     pa_assert(c);
178 
179     pa_xfree(c->script_commands);
180     pa_xfree(c->dl_search_path);
181     pa_xfree(c->default_script_file);
182 
183     if (c->log_target)
184         pa_log_target_free(c->log_target);
185 
186     pa_xfree(c->config_file);
187     pa_xfree(c);
188 }
189 
pa_daemon_conf_set_log_target(pa_daemon_conf * c,const char * string)190 int pa_daemon_conf_set_log_target(pa_daemon_conf *c, const char *string) {
191     pa_log_target *log_target = NULL;
192 
193     pa_assert(c);
194     pa_assert(string);
195 
196     if (!pa_streq(string, "auto")) {
197         log_target = pa_log_parse_target(string);
198 
199         if (!log_target)
200             return -1;
201     }
202 
203     c->log_target = log_target;
204 
205     return 0;
206 }
207 
pa_daemon_conf_set_log_level(pa_daemon_conf * c,const char * string)208 int pa_daemon_conf_set_log_level(pa_daemon_conf *c, const char *string) {
209     uint32_t u;
210     pa_assert(c);
211     pa_assert(string);
212 
213     if (pa_atou(string, &u) >= 0) {
214         if (u >= PA_LOG_LEVEL_MAX)
215             return -1;
216 
217         c->log_level = (pa_log_level_t) u;
218     } else if (pa_startswith(string, "debug"))
219         c->log_level = PA_LOG_DEBUG;
220     else if (pa_startswith(string, "info"))
221         c->log_level = PA_LOG_INFO;
222     else if (pa_startswith(string, "notice"))
223         c->log_level = PA_LOG_NOTICE;
224     else if (pa_startswith(string, "warn"))
225         c->log_level = PA_LOG_WARN;
226     else if (pa_startswith(string, "err"))
227         c->log_level = PA_LOG_ERROR;
228     else
229         return -1;
230 
231     return 0;
232 }
233 
pa_daemon_conf_set_resample_method(pa_daemon_conf * c,const char * string)234 int pa_daemon_conf_set_resample_method(pa_daemon_conf *c, const char *string) {
235     int m;
236     pa_assert(c);
237     pa_assert(string);
238 
239     if ((m = pa_parse_resample_method(string)) < 0)
240         return -1;
241 
242     c->resample_method = m;
243     return 0;
244 }
245 
pa_daemon_conf_set_local_server_type(pa_daemon_conf * c,const char * string)246 int pa_daemon_conf_set_local_server_type(pa_daemon_conf *c, const char *string) {
247     pa_assert(c);
248     pa_assert(string);
249 
250     if (pa_streq(string, "user"))
251         c->local_server_type = PA_SERVER_TYPE_USER;
252     else if (pa_streq(string, "system")) {
253         c->local_server_type = PA_SERVER_TYPE_SYSTEM;
254     } else if (pa_streq(string, "none")) {
255         c->local_server_type = PA_SERVER_TYPE_NONE;
256     } else
257         return -1;
258 
259     return 0;
260 }
261 
parse_log_target(pa_config_parser_state * state)262 static int parse_log_target(pa_config_parser_state *state) {
263     pa_daemon_conf *c;
264 
265     pa_assert(state);
266 
267     c = state->data;
268 
269     if (pa_daemon_conf_set_log_target(c, state->rvalue) < 0) {
270         pa_log(_("[%s:%u] Invalid log target '%s'."), state->filename, state->lineno, state->rvalue);
271         return -1;
272     }
273 
274     return 0;
275 }
276 
parse_log_level(pa_config_parser_state * state)277 static int parse_log_level(pa_config_parser_state *state) {
278     pa_daemon_conf *c;
279 
280     pa_assert(state);
281 
282     c = state->data;
283 
284     if (pa_daemon_conf_set_log_level(c, state->rvalue) < 0) {
285         pa_log(_("[%s:%u] Invalid log level '%s'."), state->filename, state->lineno, state->rvalue);
286         return -1;
287     }
288 
289     return 0;
290 }
291 
parse_resample_method(pa_config_parser_state * state)292 static int parse_resample_method(pa_config_parser_state *state) {
293     pa_daemon_conf *c;
294 
295     pa_assert(state);
296 
297     c = state->data;
298 
299     if (pa_daemon_conf_set_resample_method(c, state->rvalue) < 0) {
300         pa_log(_("[%s:%u] Invalid resample method '%s'."), state->filename, state->lineno, state->rvalue);
301         return -1;
302     }
303 
304     return 0;
305 }
306 
307 #ifdef HAVE_SYS_RESOURCE_H
parse_rlimit(pa_config_parser_state * state)308 static int parse_rlimit(pa_config_parser_state *state) {
309     struct pa_rlimit *r;
310 
311     pa_assert(state);
312 
313     r = state->data;
314 
315     if (state->rvalue[strspn(state->rvalue, "\t ")] == 0) {
316         /* Empty string */
317         r->is_set = 0;
318         r->value = 0;
319     } else {
320         int32_t k;
321         if (pa_atoi(state->rvalue, &k) < 0) {
322             pa_log(_("[%s:%u] Invalid rlimit '%s'."), state->filename, state->lineno, state->rvalue);
323             return -1;
324         }
325         r->is_set = k >= 0;
326         r->value = k >= 0 ? (rlim_t) k : 0;
327     }
328 
329     return 0;
330 }
331 #endif
332 
parse_sample_format(pa_config_parser_state * state)333 static int parse_sample_format(pa_config_parser_state *state) {
334     pa_daemon_conf *c;
335     pa_sample_format_t f;
336 
337     pa_assert(state);
338 
339     c = state->data;
340 
341     if ((f = pa_parse_sample_format(state->rvalue)) < 0) {
342         pa_log(_("[%s:%u] Invalid sample format '%s'."), state->filename, state->lineno, state->rvalue);
343         return -1;
344     }
345 
346     c->default_sample_spec.format = f;
347     return 0;
348 }
349 
parse_sample_rate(pa_config_parser_state * state)350 static int parse_sample_rate(pa_config_parser_state *state) {
351     pa_daemon_conf *c;
352     uint32_t r;
353 
354     pa_assert(state);
355 
356     c = state->data;
357 
358     if (pa_atou(state->rvalue, &r) < 0 || !pa_sample_rate_valid(r)) {
359         pa_log(_("[%s:%u] Invalid sample rate '%s'."), state->filename, state->lineno, state->rvalue);
360         return -1;
361     }
362 
363     c->default_sample_spec.rate = r;
364     return 0;
365 }
366 
parse_alternate_sample_rate(pa_config_parser_state * state)367 static int parse_alternate_sample_rate(pa_config_parser_state *state) {
368     pa_daemon_conf *c;
369     uint32_t r;
370 
371     pa_assert(state);
372 
373     c = state->data;
374 
375     if (pa_atou(state->rvalue, &r) < 0 || !pa_sample_rate_valid(r)) {
376         pa_log(_("[%s:%u] Invalid sample rate '%s'."), state->filename, state->lineno, state->rvalue);
377         return -1;
378     }
379 
380     c->alternate_sample_rate = r;
381     return 0;
382 }
383 
384 struct channel_conf_info {
385     pa_daemon_conf *conf;
386     bool default_sample_spec_set;
387     bool default_channel_map_set;
388 };
389 
parse_sample_channels(pa_config_parser_state * state)390 static int parse_sample_channels(pa_config_parser_state *state) {
391     struct channel_conf_info *i;
392     int32_t n;
393 
394     pa_assert(state);
395 
396     i = state->data;
397 
398     if (pa_atoi(state->rvalue, &n) < 0 || !pa_channels_valid(n)) {
399         pa_log(_("[%s:%u] Invalid sample channels '%s'."), state->filename, state->lineno, state->rvalue);
400         return -1;
401     }
402 
403     i->conf->default_sample_spec.channels = (uint8_t) n;
404     i->default_sample_spec_set = true;
405     return 0;
406 }
407 
parse_channel_map(pa_config_parser_state * state)408 static int parse_channel_map(pa_config_parser_state *state) {
409     struct channel_conf_info *i;
410 
411     pa_assert(state);
412 
413     i = state->data;
414 
415     if (!pa_channel_map_parse(&i->conf->default_channel_map, state->rvalue)) {
416         pa_log(_("[%s:%u] Invalid channel map '%s'."), state->filename, state->lineno, state->rvalue);
417         return -1;
418     }
419 
420     i->default_channel_map_set = true;
421     return 0;
422 }
423 
parse_fragments(pa_config_parser_state * state)424 static int parse_fragments(pa_config_parser_state *state) {
425     pa_daemon_conf *c;
426     int32_t n;
427 
428     pa_assert(state);
429 
430     c = state->data;
431 
432     if (pa_atoi(state->rvalue, &n) < 0 || n < 2) {
433         pa_log(_("[%s:%u] Invalid number of fragments '%s'."), state->filename, state->lineno, state->rvalue);
434         return -1;
435     }
436 
437     c->default_n_fragments = (unsigned) n;
438     return 0;
439 }
440 
parse_fragment_size_msec(pa_config_parser_state * state)441 static int parse_fragment_size_msec(pa_config_parser_state *state) {
442     pa_daemon_conf *c;
443     int32_t n;
444 
445     pa_assert(state);
446 
447     c = state->data;
448 
449     if (pa_atoi(state->rvalue, &n) < 0 || n < 1) {
450         pa_log(_("[%s:%u] Invalid fragment size '%s'."), state->filename, state->lineno, state->rvalue);
451         return -1;
452     }
453 
454     c->default_fragment_size_msec = (unsigned) n;
455     return 0;
456 }
457 
parse_nice_level(pa_config_parser_state * state)458 static int parse_nice_level(pa_config_parser_state *state) {
459     pa_daemon_conf *c;
460     int32_t level;
461 
462     pa_assert(state);
463 
464     c = state->data;
465 
466     if (pa_atoi(state->rvalue, &level) < 0 || level < -20 || level > 19) {
467         pa_log(_("[%s:%u] Invalid nice level '%s'."), state->filename, state->lineno, state->rvalue);
468         return -1;
469     }
470 
471     c->nice_level = (int) level;
472     return 0;
473 }
474 
parse_rtprio(pa_config_parser_state * state)475 static int parse_rtprio(pa_config_parser_state *state) {
476 #if !defined(OS_IS_WIN32) && defined(HAVE_SCHED_H)
477     pa_daemon_conf *c;
478     int32_t rtprio;
479 #endif
480 
481     pa_assert(state);
482 
483 #ifdef OS_IS_WIN32
484     pa_log("[%s:%u] Realtime priority not available on win32.", state->filename, state->lineno);
485 #else
486 # ifdef HAVE_SCHED_H
487     c = state->data;
488 
489     if (pa_atoi(state->rvalue, &rtprio) < 0 || rtprio < sched_get_priority_min(SCHED_FIFO) || rtprio > sched_get_priority_max(SCHED_FIFO)) {
490         pa_log("[%s:%u] Invalid realtime priority '%s'.", state->filename, state->lineno, state->rvalue);
491         return -1;
492     }
493 
494     c->realtime_priority = (int) rtprio;
495 # endif
496 #endif /* OS_IS_WIN32 */
497 
498     return 0;
499 }
500 
parse_disable_lfe_remix(pa_config_parser_state * state)501 static int parse_disable_lfe_remix(pa_config_parser_state *state) {
502     pa_daemon_conf *c;
503     int k;
504 
505     pa_assert(state);
506     c = state->data;
507 
508     if ((k = pa_parse_boolean(state->rvalue)) < 0) {
509         pa_log("[%s:%u] Failed to parse boolean value: %s", state->filename, state->lineno, state->rvalue);
510         return -1;
511     }
512 
513     c->remixing_produce_lfe = c->remixing_consume_lfe = !k;
514 
515     pa_log("[%s:%u] Deprecated option 'disable-lfe-remixing' found.", state->filename, state->lineno);
516     pa_log("[%s:%u] Please migrate to 'remixing-produce-lfe' and 'remixing-consume-lfe', set both to '%s'.",
517            state->filename, state->lineno, pa_yes_no(c->remixing_produce_lfe));
518 
519     return 0;
520 }
521 
parse_enable_lfe_remix(pa_config_parser_state * state)522 static int parse_enable_lfe_remix(pa_config_parser_state *state) {
523     pa_daemon_conf *c;
524     int k;
525 
526     pa_assert(state);
527     c = state->data;
528 
529     if ((k = pa_parse_boolean(state->rvalue)) < 0) {
530         pa_log("[%s:%u] Failed to parse boolean value: %s", state->filename, state->lineno, state->rvalue);
531         return -1;
532     }
533 
534     c->remixing_produce_lfe = c->remixing_consume_lfe = k;
535 
536     pa_log("[%s:%u] Deprecated option 'enable-lfe-remixing' found.", state->filename, state->lineno);
537     pa_log("[%s:%u] Please migrate to 'remixing-produce-lfe' and 'remixing-consume-lfe', set both to '%s'.",
538            state->filename, state->lineno, pa_yes_no(c->remixing_produce_lfe));
539 
540     return 0;
541 }
542 
543 #ifdef HAVE_DBUS
parse_server_type(pa_config_parser_state * state)544 static int parse_server_type(pa_config_parser_state *state) {
545     pa_daemon_conf *c;
546 
547     pa_assert(state);
548 
549     c = state->data;
550 
551     if (pa_daemon_conf_set_local_server_type(c, state->rvalue) < 0) {
552         pa_log(_("[%s:%u] Invalid server type '%s'."), state->filename, state->lineno, state->rvalue);
553         return -1;
554     }
555 
556     return 0;
557 }
558 #endif
559 
pa_daemon_conf_load(pa_daemon_conf * c,const char * filename)560 int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) {
561     int r = -1;
562     FILE *f = NULL;
563     struct channel_conf_info ci;
564     pa_config_item table[] = {
565         { "daemonize",                  pa_config_parse_bool,     &c->daemonize, NULL },
566         { "fail",                       pa_config_parse_bool,     &c->fail, NULL },
567         { "high-priority",              pa_config_parse_bool,     &c->high_priority, NULL },
568         { "realtime-scheduling",        pa_config_parse_bool,     &c->realtime_scheduling, NULL },
569         { "disallow-module-loading",    pa_config_parse_bool,     &c->disallow_module_loading, NULL },
570         { "allow-module-loading",       pa_config_parse_not_bool, &c->disallow_module_loading, NULL },
571         { "disallow-exit",              pa_config_parse_bool,     &c->disallow_exit, NULL },
572         { "allow-exit",                 pa_config_parse_not_bool, &c->disallow_exit, NULL },
573         { "use-pid-file",               pa_config_parse_bool,     &c->use_pid_file, NULL },
574         { "system-instance",            pa_config_parse_bool,     &c->system_instance, NULL },
575 #ifdef HAVE_DBUS
576         { "local-server-type",          parse_server_type,        c, NULL },
577 #endif
578         { "no-cpu-limit",               pa_config_parse_bool,     &c->no_cpu_limit, NULL },
579         { "cpu-limit",                  pa_config_parse_not_bool, &c->no_cpu_limit, NULL },
580         { "disable-shm",                pa_config_parse_bool,     &c->disable_shm, NULL },
581         { "enable-shm",                 pa_config_parse_not_bool, &c->disable_shm, NULL },
582         { "enable-memfd",               pa_config_parse_not_bool, &c->disable_memfd, NULL },
583         { "flat-volumes",               pa_config_parse_bool,     &c->flat_volumes, NULL },
584         { "rescue-streams",             pa_config_parse_bool,     &c->rescue_streams, NULL },
585         { "lock-memory",                pa_config_parse_bool,     &c->lock_memory, NULL },
586         { "enable-deferred-volume",     pa_config_parse_bool,     &c->deferred_volume, NULL },
587         { "exit-idle-time",             pa_config_parse_int,      &c->exit_idle_time, NULL },
588         { "scache-idle-time",           pa_config_parse_int,      &c->scache_idle_time, NULL },
589         { "realtime-priority",          parse_rtprio,             c, NULL },
590         { "dl-search-path",             pa_config_parse_string,   &c->dl_search_path, NULL },
591         { "default-script-file",        pa_config_parse_string,   &c->default_script_file, NULL },
592         { "log-target",                 parse_log_target,         c, NULL },
593         { "log-level",                  parse_log_level,          c, NULL },
594         { "verbose",                    parse_log_level,          c, NULL },
595         { "resample-method",            parse_resample_method,    c, NULL },
596         { "default-sample-format",      parse_sample_format,      c, NULL },
597         { "default-sample-rate",        parse_sample_rate,        c, NULL },
598         { "alternate-sample-rate",      parse_alternate_sample_rate, c, NULL },
599         { "default-sample-channels",    parse_sample_channels,    &ci,  NULL },
600         { "default-channel-map",        parse_channel_map,        &ci,  NULL },
601         { "default-fragments",          parse_fragments,          c, NULL },
602         { "default-fragment-size-msec", parse_fragment_size_msec, c, NULL },
603         { "deferred-volume-safety-margin-usec",
604                                         pa_config_parse_unsigned, &c->deferred_volume_safety_margin_usec, NULL },
605         { "deferred-volume-extra-delay-usec",
606                                         pa_config_parse_int,      &c->deferred_volume_extra_delay_usec, NULL },
607         { "nice-level",                 parse_nice_level,         c, NULL },
608         { "avoid-resampling",           pa_config_parse_bool,     &c->avoid_resampling, NULL },
609         { "disable-remixing",           pa_config_parse_bool,     &c->disable_remixing, NULL },
610         { "enable-remixing",            pa_config_parse_not_bool, &c->disable_remixing, NULL },
611         { "remixing-use-all-sink-channels",
612                                         pa_config_parse_bool,     &c->remixing_use_all_sink_channels, NULL },
613         { "disable-lfe-remixing",       parse_disable_lfe_remix,  c, NULL },
614         { "enable-lfe-remixing",        parse_enable_lfe_remix,   c, NULL },
615         { "remixing-produce-lfe",       pa_config_parse_bool,     &c->remixing_produce_lfe, NULL },
616         { "remixing-consume-lfe",       pa_config_parse_bool,     &c->remixing_consume_lfe, NULL },
617         { "lfe-crossover-freq",         pa_config_parse_unsigned, &c->lfe_crossover_freq, NULL },
618         { "load-default-script-file",   pa_config_parse_bool,     &c->load_default_script_file, NULL },
619         { "shm-size-bytes",             pa_config_parse_size,     &c->shm_size, NULL },
620         { "log-meta",                   pa_config_parse_bool,     &c->log_meta, NULL },
621         { "log-time",                   pa_config_parse_bool,     &c->log_time, NULL },
622         { "log-backtrace",              pa_config_parse_unsigned, &c->log_backtrace, NULL },
623 #ifdef HAVE_SYS_RESOURCE_H
624         { "rlimit-fsize",               parse_rlimit,             &c->rlimit_fsize, NULL },
625         { "rlimit-data",                parse_rlimit,             &c->rlimit_data, NULL },
626         { "rlimit-stack",               parse_rlimit,             &c->rlimit_stack, NULL },
627         { "rlimit-core",                parse_rlimit,             &c->rlimit_core, NULL },
628 #ifdef RLIMIT_RSS
629         { "rlimit-rss",                 parse_rlimit,             &c->rlimit_rss, NULL },
630 #endif
631 #ifdef RLIMIT_NOFILE
632         { "rlimit-nofile",              parse_rlimit,             &c->rlimit_nofile, NULL },
633 #endif
634 #ifdef RLIMIT_AS
635         { "rlimit-as",                  parse_rlimit,             &c->rlimit_as, NULL },
636 #endif
637 #ifdef RLIMIT_NPROC
638         { "rlimit-nproc",               parse_rlimit,             &c->rlimit_nproc, NULL },
639 #endif
640 #ifdef RLIMIT_MEMLOCK
641         { "rlimit-memlock",             parse_rlimit,             &c->rlimit_memlock, NULL },
642 #endif
643 #ifdef RLIMIT_LOCKS
644         { "rlimit-locks",               parse_rlimit,             &c->rlimit_locks, NULL },
645 #endif
646 #ifdef RLIMIT_SIGPENDING
647         { "rlimit-sigpending",          parse_rlimit,             &c->rlimit_sigpending, NULL },
648 #endif
649 #ifdef RLIMIT_MSGQUEUE
650         { "rlimit-msgqueue",            parse_rlimit,             &c->rlimit_msgqueue, NULL },
651 #endif
652 #ifdef RLIMIT_NICE
653         { "rlimit-nice",                parse_rlimit,             &c->rlimit_nice, NULL },
654 #endif
655 #ifdef RLIMIT_RTPRIO
656         { "rlimit-rtprio",              parse_rlimit,             &c->rlimit_rtprio, NULL },
657 #endif
658 #ifdef RLIMIT_RTTIME
659         { "rlimit-rttime",              parse_rlimit,             &c->rlimit_rttime, NULL },
660 #endif
661 #endif
662         { NULL,                         NULL,                     NULL, NULL },
663     };
664 
665     pa_xfree(c->config_file);
666     c->config_file = NULL;
667 
668     f = filename ?
669         pa_fopen_cloexec(c->config_file = pa_xstrdup(filename), "r") :
670         pa_open_config_file(DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_USER, ENV_CONFIG_FILE, &c->config_file);
671 
672     if (!f && errno != ENOENT) {
673         pa_log_warn(_("Failed to open configuration file: %s"), pa_cstrerror(errno));
674         goto finish;
675     }
676 
677     ci.default_channel_map_set = ci.default_sample_spec_set = false;
678     ci.conf = c;
679 
680     r = f ? pa_config_parse(c->config_file, f, table, NULL, true, NULL) : 0;
681 
682     if (r >= 0) {
683 
684         /* Make sure that channel map and sample spec fit together */
685 
686         if (ci.default_sample_spec_set &&
687             ci.default_channel_map_set &&
688             c->default_channel_map.channels != c->default_sample_spec.channels) {
689             pa_log_error(_("The specified default channel map has a different number of channels than the specified default number of channels."));
690             r = -1;
691             goto finish;
692         } else if (ci.default_sample_spec_set)
693             pa_channel_map_init_extend(&c->default_channel_map, c->default_sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
694         else if (ci.default_channel_map_set)
695             c->default_sample_spec.channels = c->default_channel_map.channels;
696     }
697 
698 finish:
699     if (f)
700         fclose(f);
701 
702     return r;
703 }
704 
pa_daemon_conf_env(pa_daemon_conf * c)705 int pa_daemon_conf_env(pa_daemon_conf *c) {
706     char *e;
707     pa_assert(c);
708 
709     if ((e = getenv(ENV_DL_SEARCH_PATH))) {
710         pa_xfree(c->dl_search_path);
711         c->dl_search_path = pa_xstrdup(e);
712     }
713     if ((e = getenv(ENV_SCRIPT_FILE))) {
714         pa_xfree(c->default_script_file);
715         c->default_script_file = pa_xstrdup(e);
716     }
717 
718     return 0;
719 }
720 
pa_daemon_conf_get_default_script_file(pa_daemon_conf * c)721 const char *pa_daemon_conf_get_default_script_file(pa_daemon_conf *c) {
722     pa_assert(c);
723 
724     if (!c->default_script_file) {
725         if (c->system_instance)
726             c->default_script_file = pa_find_config_file(DEFAULT_SYSTEM_SCRIPT_FILE, NULL, ENV_SCRIPT_FILE);
727         else
728             c->default_script_file = pa_find_config_file(DEFAULT_SCRIPT_FILE, DEFAULT_SCRIPT_FILE_USER, ENV_SCRIPT_FILE);
729     }
730 
731     return c->default_script_file;
732 }
733 
pa_daemon_conf_open_default_script_file(pa_daemon_conf * c)734 FILE *pa_daemon_conf_open_default_script_file(pa_daemon_conf *c) {
735     FILE *f;
736     pa_assert(c);
737 
738     if (!c->default_script_file) {
739         if (c->system_instance)
740             f = pa_open_config_file(DEFAULT_SYSTEM_SCRIPT_FILE, NULL, ENV_SCRIPT_FILE, &c->default_script_file);
741         else
742             f = pa_open_config_file(DEFAULT_SCRIPT_FILE, DEFAULT_SCRIPT_FILE_USER, ENV_SCRIPT_FILE, &c->default_script_file);
743     } else
744         f = pa_fopen_cloexec(c->default_script_file, "r");
745 
746     return f;
747 }
748 
pa_daemon_conf_dump(pa_daemon_conf * c)749 char *pa_daemon_conf_dump(pa_daemon_conf *c) {
750     static const char* const log_level_to_string[] = {
751         [PA_LOG_DEBUG] = "debug",
752         [PA_LOG_INFO] = "info",
753         [PA_LOG_NOTICE] = "notice",
754         [PA_LOG_WARN] = "warning",
755         [PA_LOG_ERROR] = "error"
756     };
757 
758 #ifdef HAVE_DBUS
759     static const char* const server_type_to_string[] = {
760         [PA_SERVER_TYPE_UNSET] = "!!UNSET!!",
761         [PA_SERVER_TYPE_USER] = "user",
762         [PA_SERVER_TYPE_SYSTEM] = "system",
763         [PA_SERVER_TYPE_NONE] = "none"
764     };
765 #endif
766 
767     pa_strbuf *s;
768     char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
769     char *log_target = NULL;
770 
771     pa_assert(c);
772 
773     s = pa_strbuf_new();
774 
775     if (c->config_file)
776         pa_strbuf_printf(s, _("### Read from configuration file: %s ###\n"), c->config_file);
777 
778     pa_assert(c->log_level < PA_LOG_LEVEL_MAX);
779 
780     if (c->log_target)
781         log_target = pa_log_target_to_string(c->log_target);
782 
783     pa_strbuf_printf(s, "daemonize = %s\n", pa_yes_no(c->daemonize));
784     pa_strbuf_printf(s, "fail = %s\n", pa_yes_no(c->fail));
785     pa_strbuf_printf(s, "high-priority = %s\n", pa_yes_no(c->high_priority));
786     pa_strbuf_printf(s, "nice-level = %i\n", c->nice_level);
787     pa_strbuf_printf(s, "realtime-scheduling = %s\n", pa_yes_no(c->realtime_scheduling));
788     pa_strbuf_printf(s, "realtime-priority = %i\n", c->realtime_priority);
789     pa_strbuf_printf(s, "allow-module-loading = %s\n", pa_yes_no(!c->disallow_module_loading));
790     pa_strbuf_printf(s, "allow-exit = %s\n", pa_yes_no(!c->disallow_exit));
791     pa_strbuf_printf(s, "use-pid-file = %s\n", pa_yes_no(c->use_pid_file));
792     pa_strbuf_printf(s, "system-instance = %s\n", pa_yes_no(c->system_instance));
793 #ifdef HAVE_DBUS
794     pa_strbuf_printf(s, "local-server-type = %s\n", server_type_to_string[c->local_server_type]);
795 #endif
796     pa_strbuf_printf(s, "cpu-limit = %s\n", pa_yes_no(!c->no_cpu_limit));
797     pa_strbuf_printf(s, "enable-shm = %s\n", pa_yes_no(!c->disable_shm));
798     pa_strbuf_printf(s, "flat-volumes = %s\n", pa_yes_no(c->flat_volumes));
799     pa_strbuf_printf(s, "rescue-streams = %s\n", pa_yes_no(c->rescue_streams));
800     pa_strbuf_printf(s, "lock-memory = %s\n", pa_yes_no(c->lock_memory));
801     pa_strbuf_printf(s, "exit-idle-time = %i\n", c->exit_idle_time);
802     pa_strbuf_printf(s, "scache-idle-time = %i\n", c->scache_idle_time);
803     pa_strbuf_printf(s, "dl-search-path = %s\n", pa_strempty(c->dl_search_path));
804     pa_strbuf_printf(s, "default-script-file = %s\n", pa_strempty(pa_daemon_conf_get_default_script_file(c)));
805     pa_strbuf_printf(s, "load-default-script-file = %s\n", pa_yes_no(c->load_default_script_file));
806     pa_strbuf_printf(s, "log-target = %s\n", pa_strempty(log_target));
807     pa_strbuf_printf(s, "log-level = %s\n", log_level_to_string[c->log_level]);
808     pa_strbuf_printf(s, "resample-method = %s\n", pa_resample_method_to_string(c->resample_method));
809     pa_strbuf_printf(s, "avoid-resampling = %s\n", pa_yes_no(c->avoid_resampling));
810     pa_strbuf_printf(s, "enable-remixing = %s\n", pa_yes_no(!c->disable_remixing));
811     pa_strbuf_printf(s, "remixing-use-all-sink-channels = %s\n", pa_yes_no(c->remixing_use_all_sink_channels));
812     pa_strbuf_printf(s, "remixing-produce-lfe = %s\n", pa_yes_no(c->remixing_produce_lfe));
813     pa_strbuf_printf(s, "remixing-consume-lfe = %s\n", pa_yes_no(c->remixing_consume_lfe));
814     pa_strbuf_printf(s, "lfe-crossover-freq = %u\n", c->lfe_crossover_freq);
815     pa_strbuf_printf(s, "default-sample-format = %s\n", pa_sample_format_to_string(c->default_sample_spec.format));
816     pa_strbuf_printf(s, "default-sample-rate = %u\n", c->default_sample_spec.rate);
817     pa_strbuf_printf(s, "alternate-sample-rate = %u\n", c->alternate_sample_rate);
818     pa_strbuf_printf(s, "default-sample-channels = %u\n", c->default_sample_spec.channels);
819     pa_strbuf_printf(s, "default-channel-map = %s\n", pa_channel_map_snprint(cm, sizeof(cm), &c->default_channel_map));
820     pa_strbuf_printf(s, "default-fragments = %u\n", c->default_n_fragments);
821     pa_strbuf_printf(s, "default-fragment-size-msec = %u\n", c->default_fragment_size_msec);
822     pa_strbuf_printf(s, "enable-deferred-volume = %s\n", pa_yes_no(c->deferred_volume));
823     pa_strbuf_printf(s, "deferred-volume-safety-margin-usec = %u\n", c->deferred_volume_safety_margin_usec);
824     pa_strbuf_printf(s, "deferred-volume-extra-delay-usec = %d\n", c->deferred_volume_extra_delay_usec);
825     pa_strbuf_printf(s, "shm-size-bytes = %lu\n", (unsigned long) c->shm_size);
826     pa_strbuf_printf(s, "log-meta = %s\n", pa_yes_no(c->log_meta));
827     pa_strbuf_printf(s, "log-time = %s\n", pa_yes_no(c->log_time));
828     pa_strbuf_printf(s, "log-backtrace = %u\n", c->log_backtrace);
829 #ifdef HAVE_SYS_RESOURCE_H
830     pa_strbuf_printf(s, "rlimit-fsize = %li\n", c->rlimit_fsize.is_set ? (long int) c->rlimit_fsize.value : -1);
831     pa_strbuf_printf(s, "rlimit-data = %li\n", c->rlimit_data.is_set ? (long int) c->rlimit_data.value : -1);
832     pa_strbuf_printf(s, "rlimit-stack = %li\n", c->rlimit_stack.is_set ? (long int) c->rlimit_stack.value : -1);
833     pa_strbuf_printf(s, "rlimit-core = %li\n", c->rlimit_core.is_set ? (long int) c->rlimit_core.value : -1);
834 #ifdef RLIMIT_RSS
835     pa_strbuf_printf(s, "rlimit-rss = %li\n", c->rlimit_rss.is_set ? (long int) c->rlimit_rss.value : -1);
836 #endif
837 #ifdef RLIMIT_AS
838     pa_strbuf_printf(s, "rlimit-as = %li\n", c->rlimit_as.is_set ? (long int) c->rlimit_as.value : -1);
839 #endif
840 #ifdef RLIMIT_NPROC
841     pa_strbuf_printf(s, "rlimit-nproc = %li\n", c->rlimit_nproc.is_set ? (long int) c->rlimit_nproc.value : -1);
842 #endif
843 #ifdef RLIMIT_NOFILE
844     pa_strbuf_printf(s, "rlimit-nofile = %li\n", c->rlimit_nofile.is_set ? (long int) c->rlimit_nofile.value : -1);
845 #endif
846 #ifdef RLIMIT_MEMLOCK
847     pa_strbuf_printf(s, "rlimit-memlock = %li\n", c->rlimit_memlock.is_set ? (long int) c->rlimit_memlock.value : -1);
848 #endif
849 #ifdef RLIMIT_LOCKS
850     pa_strbuf_printf(s, "rlimit-locks = %li\n", c->rlimit_locks.is_set ? (long int) c->rlimit_locks.value : -1);
851 #endif
852 #ifdef RLIMIT_SIGPENDING
853     pa_strbuf_printf(s, "rlimit-sigpending = %li\n", c->rlimit_sigpending.is_set ? (long int) c->rlimit_sigpending.value : -1);
854 #endif
855 #ifdef RLIMIT_MSGQUEUE
856     pa_strbuf_printf(s, "rlimit-msgqueue = %li\n", c->rlimit_msgqueue.is_set ? (long int) c->rlimit_msgqueue.value : -1);
857 #endif
858 #ifdef RLIMIT_NICE
859     pa_strbuf_printf(s, "rlimit-nice = %li\n", c->rlimit_nice.is_set ? (long int) c->rlimit_nice.value : -1);
860 #endif
861 #ifdef RLIMIT_RTPRIO
862     pa_strbuf_printf(s, "rlimit-rtprio = %li\n", c->rlimit_rtprio.is_set ? (long int) c->rlimit_rtprio.value : -1);
863 #endif
864 #ifdef RLIMIT_RTTIME
865     pa_strbuf_printf(s, "rlimit-rttime = %li\n", c->rlimit_rttime.is_set ? (long int) c->rlimit_rttime.value : -1);
866 #endif
867 #endif
868 
869     pa_xfree(log_target);
870 
871     return pa_strbuf_to_string_free(s);
872 }
873