summaryrefslogtreecommitdiff
path: root/src/basic/env-util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/basic/env-util.c')
-rw-r--r--src/basic/env-util.c67
1 files changed, 64 insertions, 3 deletions
diff --git a/src/basic/env-util.c b/src/basic/env-util.c
index 1b955ff1d5..2ca64c3301 100644
--- a/src/basic/env-util.c
+++ b/src/basic/env-util.c
@@ -525,12 +525,16 @@ char *replace_env_n(const char *format, size_t n, char **env, unsigned flags) {
CURLY,
VARIABLE,
VARIABLE_RAW,
+ TEST,
+ DEFAULT_VALUE,
+ ALTERNATE_VALUE,
} state = WORD;
- const char *e, *word = format;
+ const char *e, *word = format, *test_value;
char *k;
_cleanup_free_ char *r = NULL;
- size_t i;
+ size_t i, len;
+ int nest = 0;
assert(format);
@@ -554,7 +558,7 @@ char *replace_env_n(const char *format, size_t n, char **env, unsigned flags) {
word = e-1;
state = VARIABLE;
-
+ nest++;
} else if (*e == '$') {
k = strnappend(r, word, e-word);
if (!k)
@@ -596,6 +600,63 @@ char *replace_env_n(const char *format, size_t n, char **env, unsigned flags) {
word = e+1;
state = WORD;
+ } else if (*e == ':') {
+ if (!(flags & REPLACE_ENV_ALLOW_EXTENDED))
+ /* Treat this as unsupported syntax, i.e. do no replacement */
+ state = WORD;
+ else {
+ len = e-word-2;
+ state = TEST;
+ }
+ }
+ break;
+
+ case TEST:
+ if (*e == '-')
+ state = DEFAULT_VALUE;
+ else if (*e == '+')
+ state = ALTERNATE_VALUE;
+ else {
+ state = WORD;
+ break;
+ }
+
+ test_value = e+1;
+ break;
+
+ case DEFAULT_VALUE: /* fall through */
+ case ALTERNATE_VALUE:
+ assert(flags & REPLACE_ENV_ALLOW_EXTENDED);
+
+ if (*e == '{') {
+ nest++;
+ break;
+ }
+
+ if (*e != '}')
+ break;
+
+ nest--;
+ if (nest == 0) { // || !strchr(e+1, '}')) {
+ const char *t;
+ _cleanup_free_ char *v = NULL;
+
+ t = strv_env_get_n(env, word+2, len, flags);
+
+ if (t && state == ALTERNATE_VALUE)
+ t = v = replace_env_n(test_value, e-test_value, env, flags);
+ else if (!t && state == DEFAULT_VALUE)
+ t = v = replace_env_n(test_value, e-test_value, env, flags);
+
+ k = strappend(r, t);
+ if (!k)
+ return NULL;
+
+ free(r);
+ r = k;
+
+ word = e+1;
+ state = WORD;
}
break;