X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fconf-parser.c;h=1cabc0d789b2d9ef17f9689490e81fb498f2e006;hp=6994211b1095ace6e014320b46971ae1d2a4b6c2;hb=1e001f52d20a4685c9e8cf3cfa690021ca05c9e7;hpb=e99e38bbdcca3fe5956823bdb3d38544ccf93221 diff --git a/src/conf-parser.c b/src/conf-parser.c index 6994211b1..1cabc0d78 100644 --- a/src/conf-parser.c +++ b/src/conf-parser.c @@ -32,7 +32,6 @@ #include "log.h" #define COMMENTS "#;\n" -#define LINE_MAX 4096 /* Run the user supplied parser for an assignment */ static int next_assignment( @@ -40,6 +39,7 @@ static int next_assignment( unsigned line, const char *section, const ConfigItem *t, + bool relaxed, const char *lvalue, const char *rvalue, void *userdata) { @@ -49,7 +49,7 @@ static int next_assignment( assert(lvalue); assert(rvalue); - for (; t->parse; t++) { + for (; t->parse || t->lvalue; t++) { if (t->lvalue && !streq(lvalue, t->lvalue)) continue; @@ -60,18 +60,21 @@ static int next_assignment( if (t->section && !streq(section, t->section)) continue; + if (!t->parse) + return 0; + return t->parse(filename, line, section, lvalue, rvalue, t->data, userdata); } /* Warn about unknown non-extension fields. */ - if (!startswith(lvalue, "X-")) + if (!relaxed && !startswith(lvalue, "X-")) log_info("[%s:%u] Unknown lvalue '%s' in section '%s'. Ignoring.", filename, line, lvalue, strna(section)); return 0; } /* Parse a variable assignment line */ -static int parse_line(const char *filename, unsigned line, char **section, const char* const * sections, const ConfigItem *t, char *l, void *userdata) { +static int parse_line(const char *filename, unsigned line, char **section, const char* const * sections, const ConfigItem *t, bool relaxed, char *l, void *userdata) { char *e; l = strstrip(l); @@ -89,7 +92,7 @@ static int parse_line(const char *filename, unsigned line, char **section, const if (!(fn = file_in_same_dir(filename, strstrip(l+9)))) return -ENOMEM; - r = config_parse(fn, NULL, sections, t, userdata); + r = config_parse(fn, NULL, sections, t, relaxed, userdata); free(fn); return r; @@ -110,11 +113,8 @@ static int parse_line(const char *filename, unsigned line, char **section, const if (!(n = strndup(l+1, k-2))) return -ENOMEM; - if (sections && !strv_contains((char**) sections, n)) { - log_error("[%s:%u] Unknown section '%s'.", filename, line, n); - free(n); - return -EBADMSG; - } + if (!relaxed && sections && !strv_contains((char**) sections, n)) + log_info("[%s:%u] Unknown section '%s'. Ignoring.", filename, line, n); free(*section); *section = n; @@ -122,6 +122,9 @@ static int parse_line(const char *filename, unsigned line, char **section, const return 0; } + if (sections && !strv_contains((char**) sections, *section)) + return 0; + if (!(e = strchr(l, '='))) { log_error("[%s:%u] Missing '='.", filename, line); return -EBADMSG; @@ -130,15 +133,16 @@ static int parse_line(const char *filename, unsigned line, char **section, const *e = 0; e++; - return next_assignment(filename, line, *section, t, strstrip(l), strstrip(e), userdata); + return next_assignment(filename, line, *section, t, relaxed, strstrip(l), strstrip(e), userdata); } /* Go through the file and parse each line */ -int config_parse(const char *filename, FILE *f, const char* const * sections, const ConfigItem *t, void *userdata) { +int config_parse(const char *filename, FILE *f, const char* const * sections, const ConfigItem *t, bool relaxed, void *userdata) { unsigned line = 0; char *section = NULL; int r; bool ours = false; + char *continuation = NULL; assert(filename); assert(t); @@ -154,7 +158,8 @@ int config_parse(const char *filename, FILE *f, const char* const * sections, co } while (!feof(f)) { - char l[LINE_MAX]; + char l[LINE_MAX], *p, *c = NULL, *e; + bool escaped = false; if (!fgets(l, sizeof(l), f)) { if (feof(f)) @@ -165,7 +170,44 @@ int config_parse(const char *filename, FILE *f, const char* const * sections, co goto finish; } - if ((r = parse_line(filename, ++line, §ion, sections, t, l, userdata)) < 0) + truncate_nl(l); + + if (continuation) { + if (!(c = strappend(continuation, l))) { + r = -ENOMEM; + goto finish; + } + + free(continuation); + continuation = NULL; + p = c; + } else + p = l; + + for (e = p; *e; e++) { + if (escaped) + escaped = false; + else if (*e == '\\') + escaped = true; + } + + if (escaped) { + *(e-1) = ' '; + + if (c) + continuation = c; + else if (!(continuation = strdup(l))) { + r = -ENOMEM; + goto finish; + } + + continue; + } + + r = parse_line(filename, ++line, §ion, sections, t, relaxed, p, userdata); + free(c); + + if (r < 0) goto finish; } @@ -173,6 +215,7 @@ int config_parse(const char *filename, FILE *f, const char* const * sections, co finish: free(section); + free(continuation); if (f && ours) fclose(f); @@ -337,6 +380,8 @@ int config_parse_path( if (!(n = strdup(rvalue))) return -ENOMEM; + path_kill_slashes(n); + free(*s); *s = n; @@ -378,7 +423,7 @@ int config_parse_strv( k = 0; FOREACH_WORD_QUOTED(w, l, rvalue, state) - if (!(n[k++] = strndup(w, l))) + if (!(n[k++] = cunescape_length(w, l))) goto fail; n[k] = NULL; @@ -430,7 +475,7 @@ int config_parse_path_strv( n[k] = (*sv)[k]; FOREACH_WORD_QUOTED(w, l, rvalue, state) { - if (!(n[k] = strndup(w, l))) { + if (!(n[k] = cunescape_length(w, l))) { r = -ENOMEM; goto fail; } @@ -441,6 +486,8 @@ int config_parse_path_strv( goto fail; } + path_kill_slashes(n[k]); + k++; }