From d6201cfc3ac2c16a4a0fc942be31ce753b9770bd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 5 Feb 2009 04:11:26 +0100 Subject: parse ini-style sections properly --- src/daemon/daemon-conf.c | 120 ++++++++++++++++++++++---------------------- src/pulse/client-conf.c | 20 ++++---- src/pulsecore/conf-parser.c | 55 +++++++++++++------- src/pulsecore/conf-parser.h | 15 +++--- 4 files changed, 117 insertions(+), 93 deletions(-) diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index 279fb7ba..7d3b89f0 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -200,7 +200,7 @@ int pa_daemon_conf_set_resample_method(pa_daemon_conf *c, const char *string) { return 0; } -static int parse_log_target(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { +static int parse_log_target(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) { pa_daemon_conf *c = data; pa_assert(filename); @@ -216,7 +216,7 @@ static int parse_log_target(const char *filename, unsigned line, const char *lva return 0; } -static int parse_log_level(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { +static int parse_log_level(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) { pa_daemon_conf *c = data; pa_assert(filename); @@ -232,7 +232,7 @@ static int parse_log_level(const char *filename, unsigned line, const char *lval return 0; } -static int parse_resample_method(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { +static int parse_resample_method(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) { pa_daemon_conf *c = data; pa_assert(filename); @@ -248,7 +248,7 @@ static int parse_resample_method(const char *filename, unsigned line, const char return 0; } -static int parse_rlimit(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { +static int parse_rlimit(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) { #ifdef HAVE_SYS_RESOURCE_H struct pa_rlimit *r = data; @@ -277,7 +277,7 @@ static int parse_rlimit(const char *filename, unsigned line, const char *lvalue, return 0; } -static int parse_sample_format(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { +static int parse_sample_format(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) { pa_daemon_conf *c = data; pa_sample_format_t f; @@ -295,7 +295,7 @@ static int parse_sample_format(const char *filename, unsigned line, const char * return 0; } -static int parse_sample_rate(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { +static int parse_sample_rate(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) { pa_daemon_conf *c = data; uint32_t r; @@ -313,7 +313,7 @@ static int parse_sample_rate(const char *filename, unsigned line, const char *lv return 0; } -static int parse_sample_channels(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { +static int parse_sample_channels(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) { pa_daemon_conf *c = data; int32_t n; @@ -331,7 +331,7 @@ static int parse_sample_channels(const char *filename, unsigned line, const char return 0; } -static int parse_fragments(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { +static int parse_fragments(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) { pa_daemon_conf *c = data; int32_t n; @@ -349,7 +349,7 @@ static int parse_fragments(const char *filename, unsigned line, const char *lval return 0; } -static int parse_fragment_size_msec(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { +static int parse_fragment_size_msec(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) { pa_daemon_conf *c = data; int32_t n; @@ -367,7 +367,7 @@ static int parse_fragment_size_msec(const char *filename, unsigned line, const c return 0; } -static int parse_nice_level(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { +static int parse_nice_level(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) { pa_daemon_conf *c = data; int32_t level; @@ -385,7 +385,7 @@ static int parse_nice_level(const char *filename, unsigned line, const char *lva return 0; } -static int parse_rtprio(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { +static int parse_rtprio(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) { pa_daemon_conf *c = data; int32_t rtprio; @@ -409,77 +409,77 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { unsigned i = 0; pa_config_item table[] = { - { "daemonize", pa_config_parse_bool, NULL }, - { "fail", pa_config_parse_bool, NULL }, - { "high-priority", pa_config_parse_bool, NULL }, - { "realtime-scheduling", pa_config_parse_bool, NULL }, - { "disallow-module-loading", pa_config_parse_bool, NULL }, - { "disallow-exit", pa_config_parse_bool, NULL }, - { "use-pid-file", pa_config_parse_bool, NULL }, - { "system-instance", pa_config_parse_bool, NULL }, - { "no-cpu-limit", pa_config_parse_bool, NULL }, - { "disable-shm", pa_config_parse_bool, NULL }, - { "flat-volumes", pa_config_parse_bool, NULL }, - { "exit-idle-time", pa_config_parse_int, NULL }, - { "scache-idle-time", pa_config_parse_int, NULL }, - { "realtime-priority", parse_rtprio, NULL }, - { "dl-search-path", pa_config_parse_string, NULL }, - { "default-script-file", pa_config_parse_string, NULL }, - { "log-target", parse_log_target, NULL }, - { "log-level", parse_log_level, NULL }, - { "verbose", parse_log_level, NULL }, - { "resample-method", parse_resample_method, NULL }, - { "default-sample-format", parse_sample_format, NULL }, - { "default-sample-rate", parse_sample_rate, NULL }, - { "default-sample-channels", parse_sample_channels, NULL }, - { "default-fragments", parse_fragments, NULL }, - { "default-fragment-size-msec", parse_fragment_size_msec, NULL }, - { "nice-level", parse_nice_level, NULL }, - { "disable-remixing", pa_config_parse_bool, NULL }, - { "disable-lfe-remixing", pa_config_parse_bool, NULL }, - { "load-default-script-file", pa_config_parse_bool, NULL }, - { "shm-size-bytes", pa_config_parse_size, NULL }, - { "log-meta", pa_config_parse_bool, NULL }, - { "log-time", pa_config_parse_bool, NULL }, - { "log-backtrace", pa_config_parse_unsigned, NULL }, + { "daemonize", pa_config_parse_bool, NULL, NULL }, + { "fail", pa_config_parse_bool, NULL, NULL }, + { "high-priority", pa_config_parse_bool, NULL, NULL }, + { "realtime-scheduling", pa_config_parse_bool, NULL, NULL }, + { "disallow-module-loading", pa_config_parse_bool, NULL, NULL }, + { "disallow-exit", pa_config_parse_bool, NULL, NULL }, + { "use-pid-file", pa_config_parse_bool, NULL, NULL }, + { "system-instance", pa_config_parse_bool, NULL, NULL }, + { "no-cpu-limit", pa_config_parse_bool, NULL, NULL }, + { "disable-shm", pa_config_parse_bool, NULL, NULL }, + { "flat-volumes", pa_config_parse_bool, NULL, NULL }, + { "exit-idle-time", pa_config_parse_int, NULL, NULL }, + { "scache-idle-time", pa_config_parse_int, NULL, NULL }, + { "realtime-priority", parse_rtprio, NULL, NULL }, + { "dl-search-path", pa_config_parse_string, NULL, NULL }, + { "default-script-file", pa_config_parse_string, NULL, NULL }, + { "log-target", parse_log_target, NULL, NULL }, + { "log-level", parse_log_level, NULL, NULL }, + { "verbose", parse_log_level, NULL, NULL }, + { "resample-method", parse_resample_method, NULL, NULL }, + { "default-sample-format", parse_sample_format, NULL, NULL }, + { "default-sample-rate", parse_sample_rate, NULL, NULL }, + { "default-sample-channels", parse_sample_channels, NULL, NULL }, + { "default-fragments", parse_fragments, NULL, NULL }, + { "default-fragment-size-msec", parse_fragment_size_msec, NULL, NULL }, + { "nice-level", parse_nice_level, NULL, NULL }, + { "disable-remixing", pa_config_parse_bool, NULL, NULL }, + { "disable-lfe-remixing", pa_config_parse_bool, NULL, NULL }, + { "load-default-script-file", pa_config_parse_bool, NULL, NULL }, + { "shm-size-bytes", pa_config_parse_size, NULL, NULL }, + { "log-meta", pa_config_parse_bool, NULL, NULL }, + { "log-time", pa_config_parse_bool, NULL, NULL }, + { "log-backtrace", pa_config_parse_unsigned, NULL, NULL }, #ifdef HAVE_SYS_RESOURCE_H - { "rlimit-fsize", parse_rlimit, NULL }, - { "rlimit-data", parse_rlimit, NULL }, - { "rlimit-stack", parse_rlimit, NULL }, - { "rlimit-core", parse_rlimit, NULL }, - { "rlimit-rss", parse_rlimit, NULL }, + { "rlimit-fsize", parse_rlimit, NULL, NULL }, + { "rlimit-data", parse_rlimit, NULL, NULL }, + { "rlimit-stack", parse_rlimit, NULL, NULL }, + { "rlimit-core", parse_rlimit, NULL, NULL }, + { "rlimit-rss", parse_rlimit, NULL, NULL }, #ifdef RLIMIT_NOFILE - { "rlimit-nofile", parse_rlimit, NULL }, + { "rlimit-nofile", parse_rlimit, NULL, NULL }, #endif #ifdef RLIMIT_AS - { "rlimit-as", parse_rlimit, NULL }, + { "rlimit-as", parse_rlimit, NULL, NULL }, #endif #ifdef RLIMIT_NPROC - { "rlimit-nproc", parse_rlimit, NULL }, + { "rlimit-nproc", parse_rlimit, NULL, NULL }, #endif #ifdef RLIMIT_MEMLOCK - { "rlimit-memlock", parse_rlimit, NULL }, + { "rlimit-memlock", parse_rlimit, NULL, NULL }, #endif #ifdef RLIMIT_LOCKS - { "rlimit-locks", parse_rlimit, NULL }, + { "rlimit-locks", parse_rlimit, NULL, NULL }, #endif #ifdef RLIMIT_SIGPENDING - { "rlimit-sigpending", parse_rlimit, NULL }, + { "rlimit-sigpending", parse_rlimit, NULL, NULL }, #endif #ifdef RLIMIT_MSGQUEUE - { "rlimit-msgqueue", parse_rlimit, NULL }, + { "rlimit-msgqueue", parse_rlimit, NULL, NULL }, #endif #ifdef RLIMIT_NICE - { "rlimit-nice", parse_rlimit, NULL }, + { "rlimit-nice", parse_rlimit, NULL, NULL }, #endif #ifdef RLIMIT_RTPRIO - { "rlimit-rtprio", parse_rlimit, NULL }, + { "rlimit-rtprio", parse_rlimit, NULL, NULL }, #endif #ifdef RLIMIT_RTTIME - { "rlimit-rttime", parse_rlimit, NULL }, + { "rlimit-rttime", parse_rlimit, NULL, NULL }, #endif #endif - { NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL }, }; table[i++].data = &c->daemonize; diff --git a/src/pulse/client-conf.c b/src/pulse/client-conf.c index 58d64642..71f8443d 100644 --- a/src/pulse/client-conf.c +++ b/src/pulse/client-conf.c @@ -92,16 +92,16 @@ int pa_client_conf_load(pa_client_conf *c, const char *filename) { /* Prepare the configuration parse table */ pa_config_item table[] = { - { "daemon-binary", pa_config_parse_string, NULL }, - { "extra-arguments", pa_config_parse_string, NULL }, - { "default-sink", pa_config_parse_string, NULL }, - { "default-source", pa_config_parse_string, NULL }, - { "default-server", pa_config_parse_string, NULL }, - { "autospawn", pa_config_parse_bool, NULL }, - { "cookie-file", pa_config_parse_string, NULL }, - { "disable-shm", pa_config_parse_bool, NULL }, - { "shm-size-bytes", pa_config_parse_size, NULL }, - { NULL, NULL, NULL }, + { "daemon-binary", pa_config_parse_string, NULL, NULL }, + { "extra-arguments", pa_config_parse_string, NULL, NULL }, + { "default-sink", pa_config_parse_string, NULL, NULL }, + { "default-source", pa_config_parse_string, NULL, NULL }, + { "default-server", pa_config_parse_string, NULL, NULL }, + { "autospawn", pa_config_parse_bool, NULL, NULL }, + { "cookie-file", pa_config_parse_string, NULL, NULL }, + { "disable-shm", pa_config_parse_bool, NULL, NULL }, + { "shm-size-bytes", pa_config_parse_size, NULL, NULL }, + { NULL, NULL, NULL, NULL }, }; table[0].data = &c->daemon_binary; diff --git a/src/pulsecore/conf-parser.c b/src/pulsecore/conf-parser.c index ef6d6bb6..b7ec2b3c 100644 --- a/src/pulsecore/conf-parser.c +++ b/src/pulsecore/conf-parser.c @@ -40,17 +40,19 @@ #define COMMENTS "#;\n" /* Run the user supplied parser for an assignment */ -static int next_assignment(const char *filename, unsigned line, const pa_config_item *t, const char *lvalue, const char *rvalue, void *userdata) { +static int next_assignment(const char *filename, unsigned line, const char *section, const pa_config_item *t, const char *lvalue, const char *rvalue, void *userdata) { pa_assert(filename); pa_assert(t); pa_assert(lvalue); pa_assert(rvalue); for (; t->parse; t++) - if (!strcmp(lvalue, t->lvalue)) - return t->parse(filename, line, lvalue, rvalue, t->data, userdata); + if (!t->lvalue || + (pa_streq(lvalue, t->lvalue) && + ((!section && !t->section) || pa_streq(section, t->section)))) + return t->parse(filename, line, section, lvalue, rvalue, t->data, userdata); - pa_log("[%s:%u] Unknown lvalue '%s'.", filename, line, lvalue); + pa_log("[%s:%u] Unknown lvalue '%s' in section '%s'.", filename, line, lvalue, pa_strnull(section)); return -1; } @@ -83,8 +85,10 @@ static char *strip(char *s) { } /* Parse a variable assignment line */ -static int parse_line(const char *filename, unsigned line, const pa_config_item *t, char *l, void *userdata) { - char *e, *c, *b = l+strspn(l, WHITESPACE); +static int parse_line(const char *filename, unsigned line, char **section, const pa_config_item *t, char *l, void *userdata) { + char *e, *c, *b; + + b = l+strspn(l, WHITESPACE); if ((c = strpbrk(b, COMMENTS))) *c = 0; @@ -92,6 +96,22 @@ static int parse_line(const char *filename, unsigned line, const pa_config_item if (!*b) return 0; + if (*b == '[') { + size_t k; + + k = strlen(b); + pa_assert(k > 0); + + if (b[k-1] != ']') { + pa_log("[%s:%u] Invalid section header.", filename, line); + return -1; + } + + pa_xfree(*section); + *section = pa_xstrndup(b+1, k-2); + return 0; + } + if (!(e = strchr(b, '='))) { pa_log("[%s:%u] Missing '='.", filename, line); return -1; @@ -100,7 +120,7 @@ static int parse_line(const char *filename, unsigned line, const pa_config_item *e = 0; e++; - return next_assignment(filename, line, t, strip(b), strip(e), userdata); + return next_assignment(filename, line, *section, t, strip(b), strip(e), userdata); } /* Go through the file and parse each line */ @@ -108,6 +128,7 @@ int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, void int r = -1; unsigned line = 0; int do_close = !f; + char *section = NULL; pa_assert(filename); pa_assert(t); @@ -118,29 +139,29 @@ int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, void goto finish; } - pa_log_warn("Failed to open configuration file '%s': %s", - filename, pa_cstrerror(errno)); + pa_log_warn("Failed to open configuration file '%s': %s", filename, pa_cstrerror(errno)); goto finish; } while (!feof(f)) { char l[256]; + if (!fgets(l, sizeof(l), f)) { if (feof(f)) break; - pa_log_warn("Failed to read configuration file '%s': %s", - filename, pa_cstrerror(errno)); + pa_log_warn("Failed to read configuration file '%s': %s", filename, pa_cstrerror(errno)); goto finish; } - if (parse_line(filename, ++line, t, l, userdata) < 0) + if (parse_line(filename, ++line, §ion, t, l, userdata) < 0) goto finish; } r = 0; finish: + pa_xfree(section); if (do_close && f) fclose(f); @@ -148,7 +169,7 @@ finish: return r; } -int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { +int pa_config_parse_int(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) { int *i = data; int32_t k; @@ -166,7 +187,7 @@ int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, return 0; } -int pa_config_parse_unsigned(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { +int pa_config_parse_unsigned(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) { unsigned *u = data; uint32_t k; @@ -184,7 +205,7 @@ int pa_config_parse_unsigned(const char *filename, unsigned line, const char *lv return 0; } -int pa_config_parse_size(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { +int pa_config_parse_size(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) { size_t *i = data; uint32_t k; @@ -202,7 +223,7 @@ int pa_config_parse_size(const char *filename, unsigned line, const char *lvalue return 0; } -int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { +int pa_config_parse_bool(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) { int k; pa_bool_t *b = data; @@ -221,7 +242,7 @@ int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue return 0; } -int pa_config_parse_string(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { +int pa_config_parse_string(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) { char **s = data; pa_assert(filename); diff --git a/src/pulsecore/conf-parser.h b/src/pulsecore/conf-parser.h index 48a0fd26..f8f059fe 100644 --- a/src/pulsecore/conf-parser.h +++ b/src/pulsecore/conf-parser.h @@ -27,11 +27,14 @@ /* An abstract parser for simple, line based, shallow configuration * files consisting of variable assignments only. */ +typedef int (*pa_config_parser_cb_t)(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata); + /* Wraps info for parsing a specific configuration variable */ typedef struct pa_config_item { const char *lvalue; /* name of the variable */ - int (*parse)(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata); /* Function that is called to parse the variable's value */ + pa_config_parser_cb_t parse; /* Function that is called to parse the variable's value */ void *data; /* Where to store the variable's data */ + const char *section; } pa_config_item; /* The configuration file parsing routine. Expects a table of @@ -40,10 +43,10 @@ typedef struct pa_config_item { int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, void *userdata); /* Generic parsers for integers, size_t, booleans and strings */ -int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata); -int pa_config_parse_unsigned(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata); -int pa_config_parse_size(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata); -int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata); -int pa_config_parse_string(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata); +int pa_config_parse_int(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata); +int pa_config_parse_unsigned(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata); +int pa_config_parse_size(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata); +int pa_config_parse_bool(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata); +int pa_config_parse_string(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata); #endif -- cgit