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 61static 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 = -1, 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 151pa_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 176void 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 190int 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 208int 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 234int 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 246int 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 262static 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 277static 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 292static 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 308static 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 333static 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 350static 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 367static 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 384struct channel_conf_info { 385 pa_daemon_conf *conf; 386 bool default_sample_spec_set; 387 bool default_channel_map_set; 388}; 389 390static 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 408static 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 424static 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 441static 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 458static 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 475static 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 501static 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 522static 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 544static 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 560int 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 const char *default_config_file = DEFAULT_CONFIG_FILE; 669#ifdef HAVE_RUNNING_FROM_BUILD_TREE 670 if (pa_run_from_build_tree()) { 671 pa_log_notice("Detected that we are run from the build tree, fixing default daemon.conf file path."); 672#ifdef MESON_BUILD 673 default_config_file = PA_BUILDDIR PA_PATH_SEP "src" PA_PATH_SEP "daemon" PA_PATH_SEP "daemon.conf"; 674#else 675 default_config_file = PA_BUILDDIR PA_PATH_SEP "daemon.conf"; 676#endif // Endof #ifdef MESON_BUILD 677 } 678#endif // Endof #ifdef HAVE_RUNNING_FROM_BUILD_TREE 679 680 f = filename ? 681 pa_fopen_cloexec(c->config_file = pa_xstrdup(filename), "r") : 682 pa_open_config_file(default_config_file, DEFAULT_CONFIG_FILE_USER, ENV_CONFIG_FILE, &c->config_file); 683 684 if (!f && errno != ENOENT) { 685 pa_log_warn(_("Failed to open configuration file: %s"), pa_cstrerror(errno)); 686 goto finish; 687 } 688 689 ci.default_channel_map_set = ci.default_sample_spec_set = false; 690 ci.conf = c; 691 692 r = f ? pa_config_parse(c->config_file, f, table, NULL, true, NULL) : 0; 693 694 if (r >= 0) { 695 696 /* Make sure that channel map and sample spec fit together */ 697 698 if (ci.default_sample_spec_set && 699 ci.default_channel_map_set && 700 c->default_channel_map.channels != c->default_sample_spec.channels) { 701 pa_log_error(_("The specified default channel map has a different number of channels than the specified default number of channels.")); 702 r = -1; 703 goto finish; 704 } else if (ci.default_sample_spec_set) 705 pa_channel_map_init_extend(&c->default_channel_map, c->default_sample_spec.channels, PA_CHANNEL_MAP_DEFAULT); 706 else if (ci.default_channel_map_set) 707 c->default_sample_spec.channels = c->default_channel_map.channels; 708 } 709 710finish: 711 if (f) 712 fclose(f); 713 714 return r; 715} 716 717int pa_daemon_conf_env(pa_daemon_conf *c) { 718 char *e; 719 pa_assert(c); 720 721 if ((e = getenv(ENV_DL_SEARCH_PATH))) { 722 pa_xfree(c->dl_search_path); 723 c->dl_search_path = pa_xstrdup(e); 724 } 725 if ((e = getenv(ENV_SCRIPT_FILE))) { 726 pa_xfree(c->default_script_file); 727 c->default_script_file = pa_xstrdup(e); 728 } 729 730 return 0; 731} 732 733const char *pa_daemon_conf_get_default_script_file(pa_daemon_conf *c) { 734 pa_assert(c); 735 736 if (!c->default_script_file) { 737 if (c->system_instance) 738 c->default_script_file = pa_find_config_file(DEFAULT_SYSTEM_SCRIPT_FILE, NULL, ENV_SCRIPT_FILE); 739 else 740 c->default_script_file = pa_find_config_file(DEFAULT_SCRIPT_FILE, DEFAULT_SCRIPT_FILE_USER, ENV_SCRIPT_FILE); 741 } 742 743 return c->default_script_file; 744} 745 746FILE *pa_daemon_conf_open_default_script_file(pa_daemon_conf *c) { 747 FILE *f; 748 pa_assert(c); 749 750 if (!c->default_script_file) { 751 if (c->system_instance) 752 f = pa_open_config_file(DEFAULT_SYSTEM_SCRIPT_FILE, NULL, ENV_SCRIPT_FILE, &c->default_script_file); 753 else 754 f = pa_open_config_file(DEFAULT_SCRIPT_FILE, DEFAULT_SCRIPT_FILE_USER, ENV_SCRIPT_FILE, &c->default_script_file); 755 } else 756 f = pa_fopen_cloexec(c->default_script_file, "r"); 757 758 return f; 759} 760 761char *pa_daemon_conf_dump(pa_daemon_conf *c) { 762 static const char* const log_level_to_string[] = { 763 [PA_LOG_DEBUG] = "debug", 764 [PA_LOG_INFO] = "info", 765 [PA_LOG_NOTICE] = "notice", 766 [PA_LOG_WARN] = "warning", 767 [PA_LOG_ERROR] = "error" 768 }; 769 770#ifdef HAVE_DBUS 771 static const char* const server_type_to_string[] = { 772 [PA_SERVER_TYPE_UNSET] = "!!UNSET!!", 773 [PA_SERVER_TYPE_USER] = "user", 774 [PA_SERVER_TYPE_SYSTEM] = "system", 775 [PA_SERVER_TYPE_NONE] = "none" 776 }; 777#endif 778 779 pa_strbuf *s; 780 char cm[PA_CHANNEL_MAP_SNPRINT_MAX]; 781 char *log_target = NULL; 782 783 pa_assert(c); 784 785 s = pa_strbuf_new(); 786 787 if (c->config_file) 788 pa_strbuf_printf(s, _("### Read from configuration file: %s ###\n"), c->config_file); 789 790 pa_assert(c->log_level < PA_LOG_LEVEL_MAX); 791 792 if (c->log_target) 793 log_target = pa_log_target_to_string(c->log_target); 794 795 pa_strbuf_printf(s, "daemonize = %s\n", pa_yes_no(c->daemonize)); 796 pa_strbuf_printf(s, "fail = %s\n", pa_yes_no(c->fail)); 797 pa_strbuf_printf(s, "high-priority = %s\n", pa_yes_no(c->high_priority)); 798 pa_strbuf_printf(s, "nice-level = %i\n", c->nice_level); 799 pa_strbuf_printf(s, "realtime-scheduling = %s\n", pa_yes_no(c->realtime_scheduling)); 800 pa_strbuf_printf(s, "realtime-priority = %i\n", c->realtime_priority); 801 pa_strbuf_printf(s, "allow-module-loading = %s\n", pa_yes_no(!c->disallow_module_loading)); 802 pa_strbuf_printf(s, "allow-exit = %s\n", pa_yes_no(!c->disallow_exit)); 803 pa_strbuf_printf(s, "use-pid-file = %s\n", pa_yes_no(c->use_pid_file)); 804 pa_strbuf_printf(s, "system-instance = %s\n", pa_yes_no(c->system_instance)); 805#ifdef HAVE_DBUS 806 pa_strbuf_printf(s, "local-server-type = %s\n", server_type_to_string[c->local_server_type]); 807#endif 808 pa_strbuf_printf(s, "cpu-limit = %s\n", pa_yes_no(!c->no_cpu_limit)); 809 pa_strbuf_printf(s, "enable-shm = %s\n", pa_yes_no(!c->disable_shm)); 810 pa_strbuf_printf(s, "flat-volumes = %s\n", pa_yes_no(c->flat_volumes)); 811 pa_strbuf_printf(s, "rescue-streams = %s\n", pa_yes_no(c->rescue_streams)); 812 pa_strbuf_printf(s, "lock-memory = %s\n", pa_yes_no(c->lock_memory)); 813 pa_strbuf_printf(s, "exit-idle-time = %i\n", c->exit_idle_time); 814 pa_strbuf_printf(s, "scache-idle-time = %i\n", c->scache_idle_time); 815 pa_strbuf_printf(s, "dl-search-path = %s\n", pa_strempty(c->dl_search_path)); 816 pa_strbuf_printf(s, "default-script-file = %s\n", pa_strempty(pa_daemon_conf_get_default_script_file(c))); 817 pa_strbuf_printf(s, "load-default-script-file = %s\n", pa_yes_no(c->load_default_script_file)); 818 pa_strbuf_printf(s, "log-target = %s\n", pa_strempty(log_target)); 819 pa_strbuf_printf(s, "log-level = %s\n", log_level_to_string[c->log_level]); 820 pa_strbuf_printf(s, "resample-method = %s\n", pa_resample_method_to_string(c->resample_method)); 821 pa_strbuf_printf(s, "avoid-resampling = %s\n", pa_yes_no(c->avoid_resampling)); 822 pa_strbuf_printf(s, "enable-remixing = %s\n", pa_yes_no(!c->disable_remixing)); 823 pa_strbuf_printf(s, "remixing-use-all-sink-channels = %s\n", pa_yes_no(c->remixing_use_all_sink_channels)); 824 pa_strbuf_printf(s, "remixing-produce-lfe = %s\n", pa_yes_no(c->remixing_produce_lfe)); 825 pa_strbuf_printf(s, "remixing-consume-lfe = %s\n", pa_yes_no(c->remixing_consume_lfe)); 826 pa_strbuf_printf(s, "lfe-crossover-freq = %u\n", c->lfe_crossover_freq); 827 pa_strbuf_printf(s, "default-sample-format = %s\n", pa_sample_format_to_string(c->default_sample_spec.format)); 828 pa_strbuf_printf(s, "default-sample-rate = %u\n", c->default_sample_spec.rate); 829 pa_strbuf_printf(s, "alternate-sample-rate = %u\n", c->alternate_sample_rate); 830 pa_strbuf_printf(s, "default-sample-channels = %u\n", c->default_sample_spec.channels); 831 pa_strbuf_printf(s, "default-channel-map = %s\n", pa_channel_map_snprint(cm, sizeof(cm), &c->default_channel_map)); 832 pa_strbuf_printf(s, "default-fragments = %u\n", c->default_n_fragments); 833 pa_strbuf_printf(s, "default-fragment-size-msec = %u\n", c->default_fragment_size_msec); 834 pa_strbuf_printf(s, "enable-deferred-volume = %s\n", pa_yes_no(c->deferred_volume)); 835 pa_strbuf_printf(s, "deferred-volume-safety-margin-usec = %u\n", c->deferred_volume_safety_margin_usec); 836 pa_strbuf_printf(s, "deferred-volume-extra-delay-usec = %d\n", c->deferred_volume_extra_delay_usec); 837 pa_strbuf_printf(s, "shm-size-bytes = %lu\n", (unsigned long) c->shm_size); 838 pa_strbuf_printf(s, "log-meta = %s\n", pa_yes_no(c->log_meta)); 839 pa_strbuf_printf(s, "log-time = %s\n", pa_yes_no(c->log_time)); 840 pa_strbuf_printf(s, "log-backtrace = %u\n", c->log_backtrace); 841#ifdef HAVE_SYS_RESOURCE_H 842 pa_strbuf_printf(s, "rlimit-fsize = %li\n", c->rlimit_fsize.is_set ? (long int) c->rlimit_fsize.value : -1); 843 pa_strbuf_printf(s, "rlimit-data = %li\n", c->rlimit_data.is_set ? (long int) c->rlimit_data.value : -1); 844 pa_strbuf_printf(s, "rlimit-stack = %li\n", c->rlimit_stack.is_set ? (long int) c->rlimit_stack.value : -1); 845 pa_strbuf_printf(s, "rlimit-core = %li\n", c->rlimit_core.is_set ? (long int) c->rlimit_core.value : -1); 846#ifdef RLIMIT_RSS 847 pa_strbuf_printf(s, "rlimit-rss = %li\n", c->rlimit_rss.is_set ? (long int) c->rlimit_rss.value : -1); 848#endif 849#ifdef RLIMIT_AS 850 pa_strbuf_printf(s, "rlimit-as = %li\n", c->rlimit_as.is_set ? (long int) c->rlimit_as.value : -1); 851#endif 852#ifdef RLIMIT_NPROC 853 pa_strbuf_printf(s, "rlimit-nproc = %li\n", c->rlimit_nproc.is_set ? (long int) c->rlimit_nproc.value : -1); 854#endif 855#ifdef RLIMIT_NOFILE 856 pa_strbuf_printf(s, "rlimit-nofile = %li\n", c->rlimit_nofile.is_set ? (long int) c->rlimit_nofile.value : -1); 857#endif 858#ifdef RLIMIT_MEMLOCK 859 pa_strbuf_printf(s, "rlimit-memlock = %li\n", c->rlimit_memlock.is_set ? (long int) c->rlimit_memlock.value : -1); 860#endif 861#ifdef RLIMIT_LOCKS 862 pa_strbuf_printf(s, "rlimit-locks = %li\n", c->rlimit_locks.is_set ? (long int) c->rlimit_locks.value : -1); 863#endif 864#ifdef RLIMIT_SIGPENDING 865 pa_strbuf_printf(s, "rlimit-sigpending = %li\n", c->rlimit_sigpending.is_set ? (long int) c->rlimit_sigpending.value : -1); 866#endif 867#ifdef RLIMIT_MSGQUEUE 868 pa_strbuf_printf(s, "rlimit-msgqueue = %li\n", c->rlimit_msgqueue.is_set ? (long int) c->rlimit_msgqueue.value : -1); 869#endif 870#ifdef RLIMIT_NICE 871 pa_strbuf_printf(s, "rlimit-nice = %li\n", c->rlimit_nice.is_set ? (long int) c->rlimit_nice.value : -1); 872#endif 873#ifdef RLIMIT_RTPRIO 874 pa_strbuf_printf(s, "rlimit-rtprio = %li\n", c->rlimit_rtprio.is_set ? (long int) c->rlimit_rtprio.value : -1); 875#endif 876#ifdef RLIMIT_RTTIME 877 pa_strbuf_printf(s, "rlimit-rttime = %li\n", c->rlimit_rttime.is_set ? (long int) c->rlimit_rttime.value : -1); 878#endif 879#endif 880 881 pa_xfree(log_target); 882 883 return pa_strbuf_to_string_free(s); 884} 885