diff options
| author | Michael Biebl <biebl@debian.org> | 2021-10-01 23:05:04 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2021-10-01 23:05:04 +0200 |
| commit | e74c568b07b50b97873fb4ee1d776dedefbd54d6 (patch) | |
| tree | 3469f17ea9af91f7ff169b890633bda68b0cf76e /shared/systemd/src/basic/env-file.c | |
| parent | bfe522304da217296e2a61040f58e35ec5d6f3f2 (diff) | |
New upstream version 1.32.12 upstream/1.32.12
Diffstat (limited to 'shared/systemd/src/basic/env-file.c')
| -rw-r--r-- | shared/systemd/src/basic/env-file.c | 571 |
1 files changed, 0 insertions, 571 deletions
diff --git a/shared/systemd/src/basic/env-file.c b/shared/systemd/src/basic/env-file.c deleted file mode 100644 index 568b742f..00000000 --- a/shared/systemd/src/basic/env-file.c +++ /dev/null @@ -1,571 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -#include "nm-sd-adapt-shared.h" - -#include "alloc-util.h" -#include "env-file.h" -#include "env-util.h" -#include "escape.h" -#include "fd-util.h" -#include "fileio.h" -#include "fs-util.h" -#include "string-util.h" -#include "strv.h" -#include "tmpfile-util.h" -#include "utf8.h" - -static int parse_env_file_internal( - FILE *f, - const char *fname, - int (*push) (const char *filename, unsigned line, - const char *key, char *value, void *userdata, int *n_pushed), - void *userdata, - int *n_pushed) { - - size_t key_alloc = 0, n_key = 0, value_alloc = 0, n_value = 0, last_value_whitespace = (size_t) -1, last_key_whitespace = (size_t) -1; - _cleanup_free_ char *contents = NULL, *key = NULL, *value = NULL; - unsigned line = 1; - char *p; - int r; - - enum { - PRE_KEY, - KEY, - PRE_VALUE, - VALUE, - VALUE_ESCAPE, - SINGLE_QUOTE_VALUE, - DOUBLE_QUOTE_VALUE, - DOUBLE_QUOTE_VALUE_ESCAPE, - COMMENT, - COMMENT_ESCAPE - } state = PRE_KEY; - - if (f) - r = read_full_stream(f, &contents, NULL); - else - r = read_full_file(fname, &contents, NULL); - if (r < 0) - return r; - - for (p = contents; *p; p++) { - char c = *p; - - switch (state) { - - case PRE_KEY: - if (strchr(COMMENTS, c)) - state = COMMENT; - else if (!strchr(WHITESPACE, c)) { - state = KEY; - last_key_whitespace = (size_t) -1; - - if (!GREEDY_REALLOC(key, key_alloc, n_key+2)) - return -ENOMEM; - - key[n_key++] = c; - } - break; - - case KEY: - if (strchr(NEWLINE, c)) { - state = PRE_KEY; - line++; - n_key = 0; - } else if (c == '=') { - state = PRE_VALUE; - last_value_whitespace = (size_t) -1; - } else { - if (!strchr(WHITESPACE, c)) - last_key_whitespace = (size_t) -1; - else if (last_key_whitespace == (size_t) -1) - last_key_whitespace = n_key; - - if (!GREEDY_REALLOC(key, key_alloc, n_key+2)) - return -ENOMEM; - - key[n_key++] = c; - } - - break; - - case PRE_VALUE: - if (strchr(NEWLINE, c)) { - state = PRE_KEY; - line++; - key[n_key] = 0; - - if (value) - value[n_value] = 0; - - /* strip trailing whitespace from key */ - if (last_key_whitespace != (size_t) -1) - key[last_key_whitespace] = 0; - - r = push(fname, line, key, value, userdata, n_pushed); - if (r < 0) - return r; - - n_key = 0; - value = NULL; - value_alloc = n_value = 0; - - } else if (c == '\'') - state = SINGLE_QUOTE_VALUE; - else if (c == '"') - state = DOUBLE_QUOTE_VALUE; - else if (c == '\\') - state = VALUE_ESCAPE; - else if (!strchr(WHITESPACE, c)) { - state = VALUE; - - if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) - return -ENOMEM; - - value[n_value++] = c; - } - - break; - - case VALUE: - if (strchr(NEWLINE, c)) { - state = PRE_KEY; - line++; - - key[n_key] = 0; - - if (value) - value[n_value] = 0; - - /* Chomp off trailing whitespace from value */ - if (last_value_whitespace != (size_t) -1) - value[last_value_whitespace] = 0; - - /* strip trailing whitespace from key */ - if (last_key_whitespace != (size_t) -1) - key[last_key_whitespace] = 0; - - r = push(fname, line, key, value, userdata, n_pushed); - if (r < 0) - return r; - - n_key = 0; - value = NULL; - value_alloc = n_value = 0; - - } else if (c == '\\') { - state = VALUE_ESCAPE; - last_value_whitespace = (size_t) -1; - } else { - if (!strchr(WHITESPACE, c)) - last_value_whitespace = (size_t) -1; - else if (last_value_whitespace == (size_t) -1) - last_value_whitespace = n_value; - - if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) - return -ENOMEM; - - value[n_value++] = c; - } - - break; - - case VALUE_ESCAPE: - state = VALUE; - - if (!strchr(NEWLINE, c)) { - /* Escaped newlines we eat up entirely */ - if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) - return -ENOMEM; - - value[n_value++] = c; - } - break; - - case SINGLE_QUOTE_VALUE: - if (c == '\'') - state = PRE_VALUE; - else { - if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) - return -ENOMEM; - - value[n_value++] = c; - } - - break; - - case DOUBLE_QUOTE_VALUE: - if (c == '"') - state = PRE_VALUE; - else if (c == '\\') - state = DOUBLE_QUOTE_VALUE_ESCAPE; - else { - if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) - return -ENOMEM; - - value[n_value++] = c; - } - - break; - - case DOUBLE_QUOTE_VALUE_ESCAPE: - state = DOUBLE_QUOTE_VALUE; - - if (strchr(SHELL_NEED_ESCAPE, c)) { - /* If this is a char that needs escaping, just unescape it. */ - if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) - return -ENOMEM; - value[n_value++] = c; - } else if (c != '\n') { - /* If other char than what needs escaping, keep the "\" in place, like the - * real shell does. */ - if (!GREEDY_REALLOC(value, value_alloc, n_value+3)) - return -ENOMEM; - value[n_value++] = '\\'; - value[n_value++] = c; - } - - /* Escaped newlines (aka "continuation lines") are eaten up entirely */ - break; - - case COMMENT: - if (c == '\\') - state = COMMENT_ESCAPE; - else if (strchr(NEWLINE, c)) { - state = PRE_KEY; - line++; - } - break; - - case COMMENT_ESCAPE: - state = COMMENT; - break; - } - } - - if (IN_SET(state, - PRE_VALUE, - VALUE, - VALUE_ESCAPE, - SINGLE_QUOTE_VALUE, - DOUBLE_QUOTE_VALUE, - DOUBLE_QUOTE_VALUE_ESCAPE)) { - - key[n_key] = 0; - - if (value) - value[n_value] = 0; - - if (state == VALUE) - if (last_value_whitespace != (size_t) -1) - value[last_value_whitespace] = 0; - - /* strip trailing whitespace from key */ - if (last_key_whitespace != (size_t) -1) - key[last_key_whitespace] = 0; - - r = push(fname, line, key, value, userdata, n_pushed); - if (r < 0) - return r; - - value = NULL; - } - - return 0; -} - -static int check_utf8ness_and_warn( - const char *filename, unsigned line, - const char *key, char *value) { - - if (!utf8_is_valid(key)) { - _cleanup_free_ char *p = NULL; - - p = utf8_escape_invalid(key); - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "%s:%u: invalid UTF-8 in key '%s', ignoring.", - strna(filename), line, p); - } - - if (value && !utf8_is_valid(value)) { - _cleanup_free_ char *p = NULL; - - p = utf8_escape_invalid(value); - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "%s:%u: invalid UTF-8 value for key %s: '%s', ignoring.", - strna(filename), line, key, p); - } - - return 0; -} - -static int parse_env_file_push( - const char *filename, unsigned line, - const char *key, char *value, - void *userdata, - int *n_pushed) { - - const char *k; - va_list aq, *ap = userdata; - int r; - - r = check_utf8ness_and_warn(filename, line, key, value); - if (r < 0) - return r; - - va_copy(aq, *ap); - - while ((k = va_arg(aq, const char *))) { - char **v; - - v = va_arg(aq, char **); - - if (streq(key, k)) { - va_end(aq); - free(*v); - *v = value; - - if (n_pushed) - (*n_pushed)++; - - return 1; - } - } - - va_end(aq); - free(value); - - return 0; -} - -int parse_env_filev( - FILE *f, - const char *fname, - va_list ap) { - - int r, n_pushed = 0; - va_list aq; - - va_copy(aq, ap); - r = parse_env_file_internal(f, fname, parse_env_file_push, &aq, &n_pushed); - va_end(aq); - if (r < 0) - return r; - - return n_pushed; -} - -int parse_env_file_sentinel( - FILE *f, - const char *fname, - ...) { - - va_list ap; - int r; - - va_start(ap, fname); - r = parse_env_filev(f, fname, ap); - va_end(ap); - - return r; -} - -#if 0 /* NM_IGNORED */ -static int load_env_file_push( - const char *filename, unsigned line, - const char *key, char *value, - void *userdata, - int *n_pushed) { - char ***m = userdata; - char *p; - int r; - - r = check_utf8ness_and_warn(filename, line, key, value); - if (r < 0) - return r; - - p = strjoin(key, "=", value); - if (!p) - return -ENOMEM; - - r = strv_env_replace(m, p); - if (r < 0) { - free(p); - return r; - } - - if (n_pushed) - (*n_pushed)++; - - free(value); - return 0; -} - -int load_env_file(FILE *f, const char *fname, char ***rl) { - char **m = NULL; - int r; - - r = parse_env_file_internal(f, fname, load_env_file_push, &m, NULL); - if (r < 0) { - strv_free(m); - return r; - } - - *rl = m; - return 0; -} - -static int load_env_file_push_pairs( - const char *filename, unsigned line, - const char *key, char *value, - void *userdata, - int *n_pushed) { - char ***m = userdata; - int r; - - r = check_utf8ness_and_warn(filename, line, key, value); - if (r < 0) - return r; - - r = strv_extend(m, key); - if (r < 0) - return -ENOMEM; - - if (!value) { - r = strv_extend(m, ""); - if (r < 0) - return -ENOMEM; - } else { - r = strv_push(m, value); - if (r < 0) - return r; - } - - if (n_pushed) - (*n_pushed)++; - - return 0; -} - -int load_env_file_pairs(FILE *f, const char *fname, char ***rl) { - char **m = NULL; - int r; - - r = parse_env_file_internal(f, fname, load_env_file_push_pairs, &m, NULL); - if (r < 0) { - strv_free(m); - return r; - } - - *rl = m; - return 0; -} - -static int merge_env_file_push( - const char *filename, unsigned line, - const char *key, char *value, - void *userdata, - int *n_pushed) { - - char ***env = userdata; - char *expanded_value; - - assert(env); - - if (!value) { - log_error("%s:%u: invalid syntax (around \"%s\"), ignoring.", strna(filename), line, key); - return 0; - } - - if (!env_name_is_valid(key)) { - log_error("%s:%u: invalid variable name \"%s\", ignoring.", strna(filename), line, key); - free(value); - return 0; - } - - expanded_value = replace_env(value, *env, - REPLACE_ENV_USE_ENVIRONMENT| - REPLACE_ENV_ALLOW_BRACELESS| - REPLACE_ENV_ALLOW_EXTENDED); - if (!expanded_value) - return -ENOMEM; - - free_and_replace(value, expanded_value); - - log_debug("%s:%u: setting %s=%s", filename, line, key, value); - - return load_env_file_push(filename, line, key, value, env, n_pushed); -} - -int merge_env_file( - char ***env, - FILE *f, - const char *fname) { - - /* NOTE: this function supports braceful and braceless variable expansions, - * plus "extended" substitutions, unlike other exported parsing functions. - */ - - return parse_env_file_internal(f, fname, merge_env_file_push, env, NULL); -} - -static void write_env_var(FILE *f, const char *v) { - const char *p; - - p = strchr(v, '='); - if (!p) { - /* Fallback */ - fputs_unlocked(v, f); - fputc_unlocked('\n', f); - return; - } - - p++; - fwrite_unlocked(v, 1, p-v, f); - - if (string_has_cc(p, NULL) || chars_intersect(p, WHITESPACE SHELL_NEED_QUOTES)) { - fputc_unlocked('"', f); - - for (; *p; p++) { - if (strchr(SHELL_NEED_ESCAPE, *p)) - fputc_unlocked('\\', f); - - fputc_unlocked(*p, f); - } - - fputc_unlocked('"', f); - } else - fputs_unlocked(p, f); - - fputc_unlocked('\n', f); -} - -int write_env_file(const char *fname, char **l) { - _cleanup_fclose_ FILE *f = NULL; - _cleanup_free_ char *p = NULL; - char **i; - int r; - - assert(fname); - - r = fopen_temporary(fname, &f, &p); - if (r < 0) - return r; - - (void) fchmod_umask(fileno(f), 0644); - - STRV_FOREACH(i, l) - write_env_var(f, *i); - - r = fflush_and_check(f); - if (r >= 0) { - if (rename(p, fname) >= 0) - return 0; - - r = -errno; - } - - (void) unlink(p); - return r; -} -#endif /* NM_IGNORED */ |