]> code.delx.au - pulseaudio/commitdiff
parse ini-style sections properly
authorLennart Poettering <lennart@poettering.net>
Thu, 5 Feb 2009 03:11:26 +0000 (04:11 +0100)
committerLennart Poettering <lennart@poettering.net>
Thu, 5 Feb 2009 03:11:26 +0000 (04:11 +0100)
src/daemon/daemon-conf.c
src/pulse/client-conf.c
src/pulsecore/conf-parser.c
src/pulsecore/conf-parser.h

index 279fb7ba6c1e12618f73de3af8c186bed722f9bf..7d3b89f0160478de6e831933dac4f6b8afb5eee0 100644 (file)
@@ -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;
index 58d64642adfb5c3dc6945d4dfbe709b376cfaa13..71f8443d6dad5dfb7dc48d467684e00f2f44b97a 100644 (file)
@@ -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;
index ef6d6bb653311dd4e75df18fa40e6cba726beb06..b7ec2b3c7138df246af5f347e089bde2ce0f0337 100644 (file)
 #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, &section, 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);
index 48a0fd2694697b302f3343e489ceef836ca08b5e..f8f059fef43ca885de9c7db4e9e60222729f3d9d 100644 (file)
 /* 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