diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2018-11-15 12:47:17 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-11-15 12:47:17 +0100 |
commit | cd5a29ce983d0ccfa24b349288146d43b387c885 (patch) | |
tree | 749a8230da2674fb2f7778b70c8e0cadf791f969 /src/basic | |
parent | 042cad5737917e6964ddddba72b8fcc0cb890877 (diff) | |
parent | 483d713e0a39ecfe028ec49b9d9b0e67658ea79f (diff) | |
download | systemd-cd5a29ce983d0ccfa24b349288146d43b387c885.tar.gz systemd-cd5a29ce983d0ccfa24b349288146d43b387c885.tar.bz2 systemd-cd5a29ce983d0ccfa24b349288146d43b387c885.zip |
Merge pull request #10742 from poettering/c-utf8
default to C.UTF-8 locale, and many improvements to env var file parsing/kernel cmdline parsing
Diffstat (limited to 'src/basic')
-rw-r--r-- | src/basic/exec-util.c | 2 | ||||
-rw-r--r-- | src/basic/fileio.c | 46 | ||||
-rw-r--r-- | src/basic/fileio.h | 9 | ||||
-rw-r--r-- | src/basic/locale-util.c | 10 | ||||
-rw-r--r-- | src/basic/locale-util.h | 5 | ||||
-rw-r--r-- | src/basic/os-util.c | 4 | ||||
-rw-r--r-- | src/basic/proc-cmdline.c | 165 | ||||
-rw-r--r-- | src/basic/proc-cmdline.h | 13 | ||||
-rw-r--r-- | src/basic/util.c | 4 |
9 files changed, 169 insertions, 89 deletions
diff --git a/src/basic/exec-util.c b/src/basic/exec-util.c index 031a99afc1..10d774dfcd 100644 --- a/src/basic/exec-util.c +++ b/src/basic/exec-util.c @@ -241,7 +241,7 @@ static int gather_environment_generate(int fd, void *arg) { return -errno; } - r = load_env_file_pairs(f, NULL, NULL, &new); + r = load_env_file_pairs(f, NULL, &new); if (r < 0) return r; diff --git a/src/basic/fileio.c b/src/basic/fileio.c index dc12d0e07f..d3593f196f 100644 --- a/src/basic/fileio.c +++ b/src/basic/fileio.c @@ -367,7 +367,6 @@ int read_full_file(const char *fn, char **contents, size_t *size) { static int parse_env_file_internal( FILE *f, const char *fname, - const char *newline, int (*push) (const char *filename, unsigned line, const char *key, char *value, void *userdata, int *n_pushed), void *userdata, @@ -393,8 +392,6 @@ static int parse_env_file_internal( COMMENT_ESCAPE } state = PRE_KEY; - assert(newline); - if (f) r = read_full_stream(f, &contents, NULL); else @@ -422,7 +419,7 @@ static int parse_env_file_internal( break; case KEY: - if (strchr(newline, c)) { + if (strchr(NEWLINE, c)) { state = PRE_KEY; line++; n_key = 0; @@ -444,7 +441,7 @@ static int parse_env_file_internal( break; case PRE_VALUE: - if (strchr(newline, c)) { + if (strchr(NEWLINE, c)) { state = PRE_KEY; line++; key[n_key] = 0; @@ -482,7 +479,7 @@ static int parse_env_file_internal( break; case VALUE: - if (strchr(newline, c)) { + if (strchr(NEWLINE, c)) { state = PRE_KEY; line++; @@ -527,7 +524,7 @@ static int parse_env_file_internal( case VALUE_ESCAPE: state = VALUE; - if (!strchr(newline, c)) { + if (!strchr(NEWLINE, c)) { /* Escaped newlines we eat up entirely */ if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) return -ENOMEM; @@ -553,7 +550,7 @@ static int parse_env_file_internal( case SINGLE_QUOTE_VALUE_ESCAPE: state = SINGLE_QUOTE_VALUE; - if (!strchr(newline, c)) { + if (!strchr(NEWLINE, c)) { if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) return -ENOMEM; @@ -578,7 +575,7 @@ static int parse_env_file_internal( case DOUBLE_QUOTE_VALUE_ESCAPE: state = DOUBLE_QUOTE_VALUE; - if (!strchr(newline, c)) { + if (!strchr(NEWLINE, c)) { if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) return -ENOMEM; @@ -589,7 +586,7 @@ static int parse_env_file_internal( case COMMENT: if (c == '\\') state = COMMENT_ESCAPE; - else if (strchr(newline, c)) { + else if (strchr(NEWLINE, c)) { state = PRE_KEY; line++; } @@ -698,17 +695,13 @@ static int parse_env_file_push( int parse_env_filev( FILE *f, const char *fname, - const char *newline, va_list ap) { int r, n_pushed = 0; va_list aq; - if (!newline) - newline = NEWLINE; - va_copy(aq, ap); - r = parse_env_file_internal(f, fname, newline, parse_env_file_push, &aq, &n_pushed); + r = parse_env_file_internal(f, fname, parse_env_file_push, &aq, &n_pushed); va_end(aq); if (r < 0) return r; @@ -716,17 +709,16 @@ int parse_env_filev( return n_pushed; } -int parse_env_file( +int parse_env_file_sentinel( FILE *f, const char *fname, - const char *newline, ...) { va_list ap; int r; - va_start(ap, newline); - r = parse_env_filev(f, fname, newline, ap); + va_start(ap, fname); + r = parse_env_filev(f, fname, ap); va_end(ap); return r; @@ -762,14 +754,11 @@ static int load_env_file_push( return 0; } -int load_env_file(FILE *f, const char *fname, const char *newline, char ***rl) { +int load_env_file(FILE *f, const char *fname, char ***rl) { char **m = NULL; int r; - if (!newline) - newline = NEWLINE; - - r = parse_env_file_internal(f, fname, newline, load_env_file_push, &m, NULL); + r = parse_env_file_internal(f, fname, load_env_file_push, &m, NULL); if (r < 0) { strv_free(m); return r; @@ -811,14 +800,11 @@ static int load_env_file_push_pairs( return 0; } -int load_env_file_pairs(FILE *f, const char *fname, const char *newline, char ***rl) { +int load_env_file_pairs(FILE *f, const char *fname, char ***rl) { char **m = NULL; int r; - if (!newline) - newline = NEWLINE; - - r = parse_env_file_internal(f, fname, newline, load_env_file_push_pairs, &m, NULL); + r = parse_env_file_internal(f, fname, load_env_file_push_pairs, &m, NULL); if (r < 0) { strv_free(m); return r; @@ -871,7 +857,7 @@ int merge_env_file( * plus "extended" substitutions, unlike other exported parsing functions. */ - return parse_env_file_internal(f, fname, NEWLINE, merge_env_file_push, env, NULL); + return parse_env_file_internal(f, fname, merge_env_file_push, env, NULL); } static void write_env_var(FILE *f, const char *v) { diff --git a/src/basic/fileio.h b/src/basic/fileio.h index a9e0c2526f..dae115e3bb 100644 --- a/src/basic/fileio.h +++ b/src/basic/fileio.h @@ -44,10 +44,11 @@ int read_full_stream(FILE *f, char **contents, size_t *size); int verify_file(const char *fn, const char *blob, bool accept_extra_nl); -int parse_env_filev(FILE *f, const char *fname, const char *separator, va_list ap); -int parse_env_file(FILE *f, const char *fname, const char *separator, ...) _sentinel_; -int load_env_file(FILE *f, const char *fname, const char *separator, char ***l); -int load_env_file_pairs(FILE *f, const char *fname, const char *separator, char ***l); +int parse_env_filev(FILE *f, const char *fname, va_list ap); +int parse_env_file_sentinel(FILE *f, const char *fname, ...) _sentinel_; +#define parse_env_file(f, fname, ...) parse_env_file_sentinel(f, fname, __VA_ARGS__, NULL) +int load_env_file(FILE *f, const char *fname, char ***l); +int load_env_file_pairs(FILE *f, const char *fname, char ***l); int merge_env_file(char ***env, FILE *f, const char *fname); diff --git a/src/basic/locale-util.c b/src/basic/locale-util.c index 8b89bd0024..9ad51a1972 100644 --- a/src/basic/locale-util.c +++ b/src/basic/locale-util.c @@ -389,6 +389,16 @@ const char *special_glyph(SpecialGlyph code) { return draw_table[is_locale_utf8()][code]; } +void locale_variables_free(char*l[_VARIABLE_LC_MAX]) { + LocaleVariable i; + + if (!l) + return; + + for (i = 0; i < _VARIABLE_LC_MAX; i++) + l[i] = mfree(l[i]); +} + static const char * const locale_variable_table[_VARIABLE_LC_MAX] = { [VARIABLE_LANG] = "LANG", [VARIABLE_LANGUAGE] = "LANGUAGE", diff --git a/src/basic/locale-util.h b/src/basic/locale-util.h index 7762254940..14beece6d8 100644 --- a/src/basic/locale-util.h +++ b/src/basic/locale-util.h @@ -66,3 +66,8 @@ static inline void freelocalep(locale_t *p) { freelocale(*p); } + +void locale_variables_free(char* l[_VARIABLE_LC_MAX]); +static inline void locale_variables_freep(char*(*l)[_VARIABLE_LC_MAX]) { + locale_variables_free(*l); +} diff --git a/src/basic/os-util.c b/src/basic/os-util.c index 207594cef8..82471a45ba 100644 --- a/src/basic/os-util.c +++ b/src/basic/os-util.c @@ -98,7 +98,7 @@ int parse_os_release(const char *root, ...) { return r; va_start(ap, root); - r = parse_env_filev(f, p, NEWLINE, ap); + r = parse_env_filev(f, p, ap); va_end(ap); return r; @@ -113,5 +113,5 @@ int load_os_release_pairs(const char *root, char ***ret) { if (r < 0) return r; - return load_env_file_pairs(f, p, NEWLINE, ret); + return load_env_file_pairs(f, p, ret); } diff --git a/src/basic/proc-cmdline.c b/src/basic/proc-cmdline.c index 205ea08f6d..1670001364 100644 --- a/src/basic/proc-cmdline.c +++ b/src/basic/proc-cmdline.c @@ -39,42 +39,71 @@ int proc_cmdline(char **ret) { return read_one_line_file("/proc/cmdline", ret); } -int proc_cmdline_parse_given(const char *line, proc_cmdline_parse_t parse_item, void *data, unsigned flags) { - const char *p; +static int proc_cmdline_extract_first(const char **p, char **ret_word, ProcCmdlineFlags flags) { + const char *q = *p; int r; - assert(parse_item); - - p = line; for (;;) { _cleanup_free_ char *word = NULL; - char *value, *key, *q; + const char *c; - r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX); + r = extract_first_word(&q, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX); if (r < 0) return r; if (r == 0) break; - key = word; - /* Filter out arguments that are intended only for the initrd */ - q = startswith(word, "rd."); - if (q) { + c = startswith(word, "rd."); + if (c) { if (!in_initrd()) continue; - if (FLAGS_SET(flags, PROC_CMDLINE_STRIP_RD_PREFIX)) - key = q; + if (FLAGS_SET(flags, PROC_CMDLINE_STRIP_RD_PREFIX)) { + r = free_and_strdup(&word, c); + if (r < 0) + return r; + } } else if (FLAGS_SET(flags, PROC_CMDLINE_RD_STRICT) && in_initrd()) continue; /* And optionally filter out arguments that are intended only for the host */ - value = strchr(key, '='); + *p = q; + *ret_word = TAKE_PTR(word); + return 1; + } + + *p = q; + *ret_word = NULL; + return 0; +} + +int proc_cmdline_parse_given(const char *line, proc_cmdline_parse_t parse_item, void *data, ProcCmdlineFlags flags) { + const char *p; + int r; + + assert(parse_item); + + /* The PROC_CMDLINE_VALUE_OPTIONAL flag doesn't really make sense for proc_cmdline_parse(), let's make this + * clear. */ + assert(!FLAGS_SET(flags, PROC_CMDLINE_VALUE_OPTIONAL)); + + p = line; + for (;;) { + _cleanup_free_ char *word = NULL; + char *value; + + r = proc_cmdline_extract_first(&p, &word, flags); + if (r < 0) + return r; + if (r == 0) + break; + + value = strchr(word, '='); if (value) *(value++) = 0; - r = parse_item(key, value, data); + r = parse_item(word, value, data); if (r < 0) return r; } @@ -82,7 +111,7 @@ int proc_cmdline_parse_given(const char *line, proc_cmdline_parse_t parse_item, return 0; } -int proc_cmdline_parse(proc_cmdline_parse_t parse_item, void *data, unsigned flags) { +int proc_cmdline_parse(proc_cmdline_parse_t parse_item, void *data, ProcCmdlineFlags flags) { _cleanup_free_ char *line = NULL; int r; @@ -127,29 +156,29 @@ bool proc_cmdline_key_streq(const char *x, const char *y) { return true; } -int proc_cmdline_get_key(const char *key, unsigned flags, char **value) { +int proc_cmdline_get_key(const char *key, ProcCmdlineFlags flags, char **ret_value) { _cleanup_free_ char *line = NULL, *ret = NULL; bool found = false; const char *p; int r; - /* Looks for a specific key on the kernel command line. Supports two modes: + /* Looks for a specific key on the kernel command line. Supports three modes: * - * a) The "value" parameter is used. In this case a parameter beginning with the "key" string followed by "=" - * is searched, and the value following this is returned in "value". + * a) The "ret_value" parameter is used. In this case a parameter beginning with the "key" string followed by + * "=" is searched for, and the value following it is returned in "ret_value". * - * b) as above, but the PROC_CMDLINE_VALUE_OPTIONAL flag is set. In this case if the key is found as a - * separate word (i.e. not followed by "=" but instead by whitespace or the end of the command line), then - * this is also accepted, and "value" is returned as NULL. + * b) as above, but the PROC_CMDLINE_VALUE_OPTIONAL flag is set. In this case if the key is found as a separate + * word (i.e. not followed by "=" but instead by whitespace or the end of the command line), then this is + * also accepted, and "value" is returned as NULL. * - * c) The "value" parameter is NULL. In this case a search for the exact "key" parameter is performed. + * c) The "ret_value" parameter is NULL. In this case a search for the exact "key" parameter is performed. * * In all three cases, > 0 is returned if the key is found, 0 if not. */ if (isempty(key)) return -EINVAL; - if (FLAGS_SET(flags, PROC_CMDLINE_VALUE_OPTIONAL) && !value) + if (FLAGS_SET(flags, PROC_CMDLINE_VALUE_OPTIONAL) && !ret_value) return -EINVAL; r = proc_cmdline(&line); @@ -159,31 +188,17 @@ int proc_cmdline_get_key(const char *key, unsigned flags, char **value) { p = line; for (;;) { _cleanup_free_ char *word = NULL; - const char *e, *k, *q; - r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX); + r = proc_cmdline_extract_first(&p, &word, flags); if (r < 0) return r; if (r == 0) break; - k = word; - - /* Automatically filter out arguments that are intended only for the initrd, if we are not in the - * initrd. */ - q = startswith(word, "rd."); - if (q) { - if (!in_initrd()) - continue; + if (ret_value) { + const char *e; - if (FLAGS_SET(flags, PROC_CMDLINE_STRIP_RD_PREFIX)) - k = q; - - } else if (FLAGS_SET(flags, PROC_CMDLINE_RD_STRICT) && in_initrd()) - continue; - - if (value) { - e = proc_cmdline_key_startswith(k, key); + e = proc_cmdline_key_startswith(word, key); if (!e) continue; @@ -198,13 +213,15 @@ int proc_cmdline_get_key(const char *key, unsigned flags, char **value) { found = true; } else { - if (streq(k, key)) + if (streq(word, key)) { found = true; + break; /* we found what we were looking for */ + } } } - if (value) - *value = TAKE_PTR(ret); + if (ret_value) + *ret_value = TAKE_PTR(ret); return found; } @@ -234,6 +251,62 @@ int proc_cmdline_get_bool(const char *key, bool *ret) { return 1; } +int proc_cmdline_get_key_many_internal(ProcCmdlineFlags flags, ...) { + _cleanup_free_ char *line = NULL; + const char *p; + va_list ap; + int r, ret = 0; + + /* The PROC_CMDLINE_VALUE_OPTIONAL flag doesn't really make sense for proc_cmdline_get_key_many(), let's make + * this clear. */ + assert(!FLAGS_SET(flags, PROC_CMDLINE_VALUE_OPTIONAL)); + + /* This call may clobber arguments on failure! */ + + r = proc_cmdline(&line); + if (r < 0) + return r; + + p = line; + for (;;) { + _cleanup_free_ char *word = NULL; + + r = proc_cmdline_extract_first(&p, &word, flags); + if (r < 0) + return r; + if (r == 0) + break; + + va_start(ap, flags); + + for (;;) { + char **v; + const char *k, *e; + + k = va_arg(ap, const char*); + if (!k) + break; + + assert_se(v = va_arg(ap, char**)); + + e = proc_cmdline_key_startswith(word, k); + if (e && *e == '=') { + r = free_and_strdup(v, e + 1); + if (r < 0) { + va_end(ap); + return r; + } + + ret++; + } + } + + va_end(ap); + } + + return ret; +} + int shall_restore_state(void) { bool ret; int r; diff --git a/src/basic/proc-cmdline.h b/src/basic/proc-cmdline.h index efa88df0a0..ff04379fbd 100644 --- a/src/basic/proc-cmdline.h +++ b/src/basic/proc-cmdline.h @@ -5,22 +5,25 @@ #include "log.h" -enum { +typedef enum ProcCmdlineFlags { PROC_CMDLINE_STRIP_RD_PREFIX = 1 << 0, PROC_CMDLINE_VALUE_OPTIONAL = 1 << 1, PROC_CMDLINE_RD_STRICT = 1 << 2, -}; +} ProcCmdlineFlags; typedef int (*proc_cmdline_parse_t)(const char *key, const char *value, void *data); int proc_cmdline(char **ret); -int proc_cmdline_parse_given(const char *line, proc_cmdline_parse_t parse_item, void *data, unsigned flags); -int proc_cmdline_parse(const proc_cmdline_parse_t parse, void *userdata, unsigned flags); +int proc_cmdline_parse_given(const char *line, proc_cmdline_parse_t parse_item, void *data, ProcCmdlineFlags flags); +int proc_cmdline_parse(const proc_cmdline_parse_t parse, void *userdata, ProcCmdlineFlags flags); -int proc_cmdline_get_key(const char *parameter, unsigned flags, char **value); +int proc_cmdline_get_key(const char *parameter, ProcCmdlineFlags flags, char **value); int proc_cmdline_get_bool(const char *key, bool *ret); +int proc_cmdline_get_key_many_internal(ProcCmdlineFlags flags, ...); +#define proc_cmdline_get_key_many(flags, ...) proc_cmdline_get_key_many_internal(flags, __VA_ARGS__, NULL) + char *proc_cmdline_key_startswith(const char *s, const char *prefix); bool proc_cmdline_key_streq(const char *x, const char *y); diff --git a/src/basic/util.c b/src/basic/util.c index b6e874c3b8..cd75529cfe 100644 --- a/src/basic/util.c +++ b/src/basic/util.c @@ -248,7 +248,9 @@ int container_get_leader(const char *machine, pid_t *pid) { return -EINVAL; p = strjoina("/run/systemd/machines/", machine); - r = parse_env_file(NULL, p, NEWLINE, "LEADER", &s, "CLASS", &class, NULL); + r = parse_env_file(NULL, p, + "LEADER", &s, + "CLASS", &class); if (r == -ENOENT) return -EHOSTDOWN; if (r < 0) |