X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fshared%2Fconf-parser.c;h=158e9efd4cecb260bb15426379fa468e9c8dfe7b;hb=a1948c7bfeb87b54bc7715a44490c01593ee6e23;hp=3d14c58d1386718b49fe2ebc8de2d99571452fe3;hpb=7fd1b19bc9e9f5574f2877936b8ac267c7706947;p=elogind.git diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c index 3d14c58d1..158e9efd4 100644 --- a/src/shared/conf-parser.c +++ b/src/shared/conf-parser.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "conf-parser.h" #include "util.h" @@ -70,7 +71,7 @@ int log_syntax_internal(const char *unit, int level, "ERRNO=%d", error > 0 ? error : EINVAL, "MESSAGE=[%s:%u] %s", config_file, config_line, msg, NULL); - log_info("logged here: '%s': %d", msg, r); + return r; } @@ -155,6 +156,7 @@ static int next_assignment(const char *unit, ConfigItemLookup lookup, void *table, const char *section, + unsigned section_line, const char *lvalue, const char *rvalue, bool relaxed, @@ -177,8 +179,8 @@ static int next_assignment(const char *unit, if (r > 0) { if (func) - return func(unit, filename, line, section, lvalue, ltype, - rvalue, data, userdata); + return func(unit, filename, line, section, section_line, + lvalue, ltype, rvalue, data, userdata); return 0; } @@ -199,7 +201,10 @@ static int parse_line(const char* unit, ConfigItemLookup lookup, void *table, bool relaxed, + bool allow_include, char **section, + unsigned *section_line, + bool *section_ignored, char *l, void *userdata) { @@ -219,13 +224,28 @@ static int parse_line(const char* unit, return 0; if (startswith(l, ".include ")) { - _cleanup_free_ char *fn; + _cleanup_free_ char *fn = NULL; + + /* .includes are a bad idea, we only support them here + * for historical reasons. They create cyclic include + * problems and make it difficult to detect + * configuration file changes with an easy + * stat(). Better approaches, such as .d/ drop-in + * snippets exist. + * + * Support for them should be eventually removed. */ + + if (!allow_include) { + log_syntax(unit, LOG_ERR, filename, line, EBADMSG, + ".include not allowed here. Ignoring."); + return 0; + } fn = file_in_same_dir(filename, strstrip(l+9)); if (!fn) return -ENOMEM; - return config_parse(unit, fn, NULL, sections, lookup, table, relaxed, userdata); + return config_parse(unit, fn, NULL, sections, lookup, table, relaxed, false, userdata); } if (*l == '[') { @@ -247,15 +267,20 @@ static int parse_line(const char* unit, if (sections && !nulstr_contains(sections, n)) { - if (!relaxed) + if (!relaxed && !startswith(n, "X-")) log_syntax(unit, LOG_WARNING, filename, line, EINVAL, "Unknown section '%s'. Ignoring.", n); free(n); + free(*section); *section = NULL; + *section_line = 0; + *section_ignored = true; } else { free(*section); *section = n; + *section_line = line; + *section_ignored = false; } return 0; @@ -263,7 +288,7 @@ static int parse_line(const char* unit, if (sections && !*section) { - if (!relaxed) + if (!relaxed && !*section_ignored) log_syntax(unit, LOG_WARNING, filename, line, EINVAL, "Assignment outside of section. Ignoring."); @@ -285,6 +310,7 @@ static int parse_line(const char* unit, lookup, table, *section, + *section_line, strstrip(l), strstrip(e), relaxed, @@ -299,11 +325,13 @@ int config_parse(const char *unit, ConfigItemLookup lookup, void *table, bool relaxed, + bool allow_include, void *userdata) { - unsigned line = 0; _cleanup_free_ char *section = NULL, *continuation = NULL; _cleanup_fclose_ FILE *ours = NULL; + unsigned line = 0, section_line = 0; + bool section_ignored = false; int r; assert(filename); @@ -312,11 +340,13 @@ int config_parse(const char *unit, if (!f) { f = ours = fopen(filename, "re"); if (!f) { - log_error("Failed to open configuration file '%s': %m", filename); - return -errno; + log_full(errno == ENOENT ? LOG_DEBUG : LOG_ERR, "Failed to open configuration file '%s': %m", filename); + return errno == ENOENT ? 0 : -errno; } } + fd_warn_permissions(filename, fileno(f)); + while (!feof(f)) { char l[LINE_MAX], *p, *c = NULL, *e; bool escaped = false; @@ -370,7 +400,10 @@ int config_parse(const char *unit, lookup, table, relaxed, + allow_include, §ion, + §ion_line, + §ion_ignored, p, userdata); free(c); @@ -387,6 +420,7 @@ int config_parse(const char *unit, const char *filename, \ unsigned line, \ const char *section, \ + unsigned section_line, \ const char *lvalue, \ int ltype, \ const char *rvalue, \ @@ -418,11 +452,11 @@ DEFINE_PARSER(double, double, safe_atod) DEFINE_PARSER(nsec, nsec_t, parse_nsec) DEFINE_PARSER(sec, usec_t, parse_sec) - -int config_parse_bytes_size(const char* unit, +int config_parse_iec_size(const char* unit, const char *filename, unsigned line, const char *section, + unsigned section_line, const char *lvalue, int ltype, const char *rvalue, @@ -438,10 +472,9 @@ int config_parse_bytes_size(const char* unit, assert(rvalue); assert(data); - r = parse_bytes(rvalue, &o); + r = parse_size(rvalue, 1024, &o); if (r < 0 || (off_t) (size_t) o != o) { - log_syntax(unit, LOG_ERR, filename, line, -r, - "Failed to parse byte value, ignoring: %s", rvalue); + log_syntax(unit, LOG_ERR, filename, line, r < 0 ? -r : ERANGE, "Failed to parse size value, ignoring: %s", rvalue); return 0; } @@ -449,11 +482,41 @@ int config_parse_bytes_size(const char* unit, return 0; } +int config_parse_si_size(const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + size_t *sz = data; + off_t o; + int r; -int config_parse_bytes_off(const char* unit, + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = parse_size(rvalue, 1000, &o); + if (r < 0 || (off_t) (size_t) o != o) { + log_syntax(unit, LOG_ERR, filename, line, r < 0 ? -r : ERANGE, "Failed to parse size value, ignoring: %s", rvalue); + return 0; + } + + *sz = (size_t) o; + return 0; +} + +int config_parse_iec_off(const char* unit, const char *filename, unsigned line, const char *section, + unsigned section_line, const char *lvalue, int ltype, const char *rvalue, @@ -470,10 +533,9 @@ int config_parse_bytes_off(const char* unit, assert_cc(sizeof(off_t) == sizeof(uint64_t)); - r = parse_bytes(rvalue, bytes); + r = parse_size(rvalue, 1024, bytes); if (r < 0) - log_syntax(unit, LOG_ERR, filename, line, -r, - "Failed to parse bytes value, ignoring: %s", rvalue); + log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to parse size value, ignoring: %s", rvalue); return 0; } @@ -482,6 +544,7 @@ int config_parse_bool(const char* unit, const char *filename, unsigned line, const char *section, + unsigned section_line, const char *lvalue, int ltype, const char *rvalue, @@ -507,89 +570,57 @@ int config_parse_bool(const char* unit, return 0; } -int config_parse_tristate(const char *unit, - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_string( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { - int k; - int *b = data; + char **s = data, *n; assert(filename); assert(lvalue); assert(rvalue); assert(data); - /* Tristates are like booleans, but can also take the 'default' value, i.e. "-1" */ - - k = parse_boolean(rvalue); - if (k < 0) { - log_syntax(unit, LOG_ERR, filename, line, -k, - "Failed to parse boolean value, ignoring: %s", rvalue); + if (!utf8_is_valid(rvalue)) { + log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue); return 0; } - *b = !!k; - return 0; -} - -int config_parse_string(const char *unit, - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { - - char **s = data; - char *n; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(data); - - n = strdup(rvalue); - if (!n) - return log_oom(); - - if (!utf8_is_valid(n)) { - log_syntax(unit, LOG_ERR, filename, line, EINVAL, - "String is not UTF-8 clean, ignoring assignment: %s", rvalue); - free(n); - return 0; + if (isempty(rvalue)) + n = NULL; + else { + n = strdup(rvalue); + if (!n) + return log_oom(); } free(*s); - if (*n) - *s = n; - else { - free(n); - *s = NULL; - } + *s = n; return 0; } -int config_parse_path(const char *unit, - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_path( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { - char **s = data; - char *n; + char **s = data, *n; assert(filename); assert(lvalue); @@ -597,14 +628,12 @@ int config_parse_path(const char *unit, assert(data); if (!utf8_is_valid(rvalue)) { - log_syntax(unit, LOG_ERR, filename, line, EINVAL, - "Path is not UTF-8 clean, ignoring assignment: %s", rvalue); + log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue); return 0; } if (!path_is_absolute(rvalue)) { - log_syntax(unit, LOG_ERR, filename, line, EINVAL, - "Not an absolute path, ignoring: %s", rvalue); + log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Not an absolute path, ignoring: %s", rvalue); return 0; } @@ -624,6 +653,7 @@ int config_parse_strv(const char *unit, const char *filename, unsigned line, const char *section, + unsigned section_line, const char *lvalue, int ltype, const char *rvalue, @@ -656,73 +686,18 @@ int config_parse_strv(const char *unit, } FOREACH_WORD_QUOTED(w, l, rvalue, state) { - _cleanup_free_ char *n; - - n = cunescape_length(w, l); - if (!n) - return log_oom(); - - if (!utf8_is_valid(n)) { - log_syntax(unit, LOG_ERR, filename, line, EINVAL, - "String is not UTF-8 clean, ignoring: %s", rvalue); - continue; - } - - r = strv_extend(sv, n); - if (r < 0) - return log_oom(); - } - - return 0; -} - -int config_parse_path_strv(const char *unit, - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { - - char*** sv = data, *w, *state; - size_t l; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(data); - - if (isempty(rvalue)) { - /* Empty assignment resets the list */ - strv_free(*sv); - *sv = NULL; - return 0; - } - - FOREACH_WORD_QUOTED(w, l, rvalue, state) { - _cleanup_free_ char *n; + char *n; n = strndup(w, l); if (!n) return log_oom(); if (!utf8_is_valid(n)) { - log_syntax(unit, LOG_ERR, filename, line, EINVAL, - "Path is not UTF-8 clean, ignoring assignment: %s", rvalue); - continue; - } - - if (!path_is_absolute(n)) { - log_syntax(unit, LOG_ERR, filename, line, EINVAL, - "Not an absolute path, ignoring: %s", rvalue); + log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue); continue; } - path_kill_slashes(n); - r = strv_extend(sv, n); + r = strv_consume(sv, n); if (r < 0) return log_oom(); } @@ -734,6 +709,7 @@ int config_parse_mode(const char *unit, const char *filename, unsigned line, const char *section, + unsigned section_line, const char *lvalue, int ltype, const char *rvalue, @@ -767,15 +743,17 @@ int config_parse_mode(const char *unit, return 0; } -int config_parse_facility(const char *unit, - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_log_facility( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { int *o = data, x; @@ -797,15 +775,17 @@ int config_parse_facility(const char *unit, return 0; } -int config_parse_level(const char *unit, - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_log_level( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { int *o = data, x; @@ -825,87 +805,3 @@ int config_parse_level(const char *unit, *o = (*o & LOG_FACMASK) | x; return 0; } - -int config_parse_set_status(const char *unit, - const char *filename, - unsigned line, - const char *section, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { - - char *w; - size_t l; - char *state; - int r; - ExitStatusSet *status_set = data; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(data); - - if (isempty(rvalue)) { - /* Empty assignment resets the list */ - - set_free(status_set->signal); - set_free(status_set->code); - - status_set->signal = status_set->code = NULL; - return 0; - } - - FOREACH_WORD(w, l, rvalue, state) { - int val; - char *temp; - - temp = strndup(w, l); - if (!temp) - return log_oom(); - - r = safe_atoi(temp, &val); - if (r < 0) { - val = signal_from_string_try_harder(temp); - free(temp); - - if (val > 0) { - r = set_ensure_allocated(&status_set->signal, trivial_hash_func, trivial_compare_func); - if (r < 0) - return log_oom(); - - r = set_put(status_set->signal, INT_TO_PTR(val)); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, -r, - "Unable to store: %s", w); - return r; - } - } else { - log_syntax(unit, LOG_ERR, filename, line, -val, - "Failed to parse value, ignoring: %s", w); - return 0; - } - } else { - free(temp); - - if (val < 0 || val > 255) - log_syntax(unit, LOG_ERR, filename, line, ERANGE, - "Value %d is outside range 0-255, ignoring", val); - else { - r = set_ensure_allocated(&status_set->code, trivial_hash_func, trivial_compare_func); - if (r < 0) - return log_oom(); - - r = set_put(status_set->code, INT_TO_PTR(val)); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, -r, - "Unable to store: %s", w); - return r; - } - } - } - } - - return 0; -}