X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fshared%2Fenv-util.c;h=ac7bbdc7110c3f85d5149392c1058fb2894f1478;hp=fbdc73dd2c6459f324d487ba8826d00f8ced4cf4;hb=86e97d599f8b1ca379dce64fadac9b8f6b002ac5;hpb=79008bddf679a5e0900369950eb346c9fa687107 diff --git a/src/shared/env-util.c b/src/shared/env-util.c index fbdc73dd2..ac7bbdc71 100644 --- a/src/shared/env-util.c +++ b/src/shared/env-util.c @@ -20,7 +20,6 @@ ***/ #include -#include #include #include "strv.h" @@ -28,7 +27,6 @@ #include "util.h" #include "env-util.h" #include "def.h" -#include "unit.h" #define VALID_CHARS_ENV_NAME \ DIGITS LETTERS \ @@ -415,7 +413,7 @@ char *strv_env_get(char **l, const char *name) { return strv_env_get_n(l, name, strlen(name)); } -char **strv_env_clean_log(char **e, const char *unit_id, const char *message) { +char **strv_env_clean_with_callback(char **e, void (*invalid_callback)(const char *p, void *userdata), void *userdata) { char **p, **q; int k = 0; @@ -424,8 +422,8 @@ char **strv_env_clean_log(char **e, const char *unit_id, const char *message) { bool duplicate = false; if (!env_assignment_is_valid(*p)) { - if (message) - log_unit_error(unit_id, "Ignoring invalid environment '%s': %s", *p, message); + if (invalid_callback) + invalid_callback(*p, userdata); free(*p); continue; } @@ -451,6 +449,146 @@ char **strv_env_clean_log(char **e, const char *unit_id, const char *message) { return e; } -char **strv_env_clean(char **e) { - return strv_env_clean_log(e, NULL, NULL); +char *replace_env(const char *format, char **env) { + enum { + WORD, + CURLY, + VARIABLE + } state = WORD; + + const char *e, *word = format; + char *r = NULL, *k; + + assert(format); + + for (e = format; *e; e ++) { + + switch (state) { + + case WORD: + if (*e == '$') + state = CURLY; + break; + + case CURLY: + if (*e == '{') { + k = strnappend(r, word, e-word-1); + if (!k) + goto fail; + + free(r); + r = k; + + word = e-1; + state = VARIABLE; + + } else if (*e == '$') { + k = strnappend(r, word, e-word); + if (!k) + goto fail; + + free(r); + r = k; + + word = e+1; + state = WORD; + } else + state = WORD; + break; + + case VARIABLE: + if (*e == '}') { + const char *t; + + t = strempty(strv_env_get_n(env, word+2, e-word-2)); + + k = strappend(r, t); + if (!k) + goto fail; + + free(r); + r = k; + + word = e+1; + state = WORD; + } + break; + } + } + + k = strnappend(r, word, e-word); + if (!k) + goto fail; + + free(r); + return k; + +fail: + free(r); + return NULL; +} + +char **replace_env_argv(char **argv, char **env) { + char **ret, **i; + unsigned k = 0, l = 0; + + l = strv_length(argv); + + ret = new(char*, l+1); + if (!ret) + return NULL; + + STRV_FOREACH(i, argv) { + + /* If $FOO appears as single word, replace it by the split up variable */ + if ((*i)[0] == '$' && (*i)[1] != '{') { + char *e; + char **w, **m = NULL; + unsigned q; + + e = strv_env_get(env, *i+1); + if (e) { + int r; + + r = strv_split_quoted(&m, e, UNQUOTE_RELAX); + if (r < 0) { + ret[k] = NULL; + strv_free(ret); + return NULL; + } + } else + m = NULL; + + q = strv_length(m); + l = l + q - 1; + + w = realloc(ret, sizeof(char*) * (l+1)); + if (!w) { + ret[k] = NULL; + strv_free(ret); + strv_free(m); + return NULL; + } + + ret = w; + if (m) { + memcpy(ret + k, m, q * sizeof(char*)); + free(m); + } + + k += q; + continue; + } + + /* If ${FOO} appears as part of a word, replace it by the variable as-is */ + ret[k] = replace_env(*i, env); + if (!ret[k]) { + strv_free(ret); + return NULL; + } + k++; + } + + ret[k] = NULL; + return ret; }