-/* SPDX-License-Identifier: LGPL-2.1+ */
-
-#include <stdio_ext.h>
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "alloc-util.h"
#include "env-file.h"
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;
+ size_t key_alloc = 0, n_key = 0, value_alloc = 0, n_value = 0, last_value_whitespace = SIZE_MAX, last_key_whitespace = SIZE_MAX;
_cleanup_free_ char *contents = NULL, *key = NULL, *value = NULL;
unsigned line = 1;
char *p;
VALUE,
VALUE_ESCAPE,
SINGLE_QUOTE_VALUE,
- SINGLE_QUOTE_VALUE_ESCAPE,
DOUBLE_QUOTE_VALUE,
DOUBLE_QUOTE_VALUE_ESCAPE,
COMMENT,
state = COMMENT;
else if (!strchr(WHITESPACE, c)) {
state = KEY;
- last_key_whitespace = (size_t) -1;
+ last_key_whitespace = SIZE_MAX;
if (!GREEDY_REALLOC(key, key_alloc, n_key+2))
return -ENOMEM;
n_key = 0;
} else if (c == '=') {
state = PRE_VALUE;
- last_value_whitespace = (size_t) -1;
+ last_value_whitespace = SIZE_MAX;
} else {
if (!strchr(WHITESPACE, c))
- last_key_whitespace = (size_t) -1;
- else if (last_key_whitespace == (size_t) -1)
+ last_key_whitespace = SIZE_MAX;
+ else if (last_key_whitespace == SIZE_MAX)
last_key_whitespace = n_key;
if (!GREEDY_REALLOC(key, key_alloc, n_key+2))
value[n_value] = 0;
/* strip trailing whitespace from key */
- if (last_key_whitespace != (size_t) -1)
+ if (last_key_whitespace != SIZE_MAX)
key[last_key_whitespace] = 0;
r = push(fname, line, key, value, userdata, n_pushed);
} else if (c == '\'')
state = SINGLE_QUOTE_VALUE;
- else if (c == '\"')
+ else if (c == '"')
state = DOUBLE_QUOTE_VALUE;
else if (c == '\\')
state = VALUE_ESCAPE;
value[n_value] = 0;
/* Chomp off trailing whitespace from value */
- if (last_value_whitespace != (size_t) -1)
+ if (last_value_whitespace != SIZE_MAX)
value[last_value_whitespace] = 0;
/* strip trailing whitespace from key */
- if (last_key_whitespace != (size_t) -1)
+ if (last_key_whitespace != SIZE_MAX)
key[last_key_whitespace] = 0;
r = push(fname, line, key, value, userdata, n_pushed);
} else if (c == '\\') {
state = VALUE_ESCAPE;
- last_value_whitespace = (size_t) -1;
+ last_value_whitespace = SIZE_MAX;
} else {
if (!strchr(WHITESPACE, c))
- last_value_whitespace = (size_t) -1;
- else if (last_value_whitespace == (size_t) -1)
+ last_value_whitespace = SIZE_MAX;
+ else if (last_value_whitespace == SIZE_MAX)
last_value_whitespace = n_value;
if (!GREEDY_REALLOC(value, value_alloc, n_value+2))
case SINGLE_QUOTE_VALUE:
if (c == '\'')
state = PRE_VALUE;
- else if (c == '\\')
- state = SINGLE_QUOTE_VALUE_ESCAPE;
else {
if (!GREEDY_REALLOC(value, value_alloc, n_value+2))
return -ENOMEM;
break;
- case SINGLE_QUOTE_VALUE_ESCAPE:
- state = SINGLE_QUOTE_VALUE;
-
- if (!strchr(NEWLINE, c)) {
- if (!GREEDY_REALLOC(value, value_alloc, n_value+2))
- return -ENOMEM;
-
- value[n_value++] = c;
- }
- break;
-
case DOUBLE_QUOTE_VALUE:
- if (c == '\"')
+ if (c == '"')
state = PRE_VALUE;
else if (c == '\\')
state = DOUBLE_QUOTE_VALUE_ESCAPE;
case DOUBLE_QUOTE_VALUE_ESCAPE:
state = DOUBLE_QUOTE_VALUE;
- if (!strchr(NEWLINE, c)) {
+ 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:
VALUE,
VALUE_ESCAPE,
SINGLE_QUOTE_VALUE,
- SINGLE_QUOTE_VALUE_ESCAPE,
DOUBLE_QUOTE_VALUE,
DOUBLE_QUOTE_VALUE_ESCAPE)) {
value[n_value] = 0;
if (state == VALUE)
- if (last_value_whitespace != (size_t) -1)
+ if (last_value_whitespace != SIZE_MAX)
value[last_value_whitespace] = 0;
/* strip trailing whitespace from key */
- if (last_key_whitespace != (size_t) -1)
+ if (last_key_whitespace != SIZE_MAX)
key[last_key_whitespace] = 0;
r = push(fname, line, key, value, userdata, n_pushed);
if (!p)
return -ENOMEM;
- r = strv_env_replace(m, p);
- if (r < 0) {
- free(p);
+ r = strv_env_replace_consume(m, p);
+ if (r < 0)
return r;
- }
if (n_pushed)
(*n_pushed)++;
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);
}
fwrite_unlocked(v, 1, p-v, f);
if (string_has_cc(p, NULL) || chars_intersect(p, WHITESPACE SHELL_NEED_QUOTES)) {
- fputc_unlocked('\"', f);
+ fputc_unlocked('"', f);
for (; *p; p++) {
if (strchr(SHELL_NEED_ESCAPE, *p))
fputc_unlocked(*p, f);
}
- fputc_unlocked('\"', f);
+ fputc_unlocked('"', f);
} else
fputs_unlocked(p, f);
if (r < 0)
return r;
- (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
(void) fchmod_umask(fileno(f), 0644);
STRV_FOREACH(i, l)
r = -errno;
}
- unlink(p);
+ (void) unlink(p);
return r;
}