From: Ronny Chevalier Date: Fri, 10 Apr 2015 22:25:43 +0000 (+0200) Subject: shared: move replace_env* from util to env-util X-Git-Tag: v226.4~1^2~479 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=99a720797c7779625c23de456c85ed0b3056bca6 shared: move replace_env* from util to env-util --- diff --git a/src/shared/env-util.c b/src/shared/env-util.c index 00c2cdd8c..ac7bbdc71 100644 --- a/src/shared/env-util.c +++ b/src/shared/env-util.c @@ -448,3 +448,147 @@ char **strv_env_clean_with_callback(char **e, void (*invalid_callback)(const cha return e; } + +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; +} diff --git a/src/shared/env-util.h b/src/shared/env-util.h index 9de362171..803aa61ca 100644 --- a/src/shared/env-util.h +++ b/src/shared/env-util.h @@ -29,6 +29,9 @@ bool env_name_is_valid(const char *e); bool env_value_is_valid(const char *e); bool env_assignment_is_valid(const char *e); +char *replace_env(const char *format, char **env); +char **replace_env_argv(char **argv, char **env); + bool strv_env_is_valid(char **e); #define strv_env_clean(l) strv_env_clean_with_callback(l, NULL, NULL) char **strv_env_clean_with_callback(char **l, void (*invalid_callback)(const char *p, void *userdata), void *userdata); diff --git a/src/shared/util.c b/src/shared/util.c index e71231cea..03edafb95 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -2083,150 +2083,6 @@ cpu_set_t* cpu_set_malloc(unsigned *ncpus) { } } -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; -} - int files_same(const char *filea, const char *fileb) { struct stat a, b; diff --git a/src/shared/util.h b/src/shared/util.h index dae9fde1d..5b2a08389 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -221,9 +221,6 @@ const char* split(const char **state, size_t *l, const char *separator, bool quo char *strappend(const char *s, const char *suffix); char *strnappend(const char *s, const char *suffix, size_t length); -char *replace_env(const char *format, char **env); -char **replace_env_argv(char **argv, char **env); - int readlinkat_malloc(int fd, const char *p, char **ret); int readlink_malloc(const char *p, char **r); int readlink_value(const char *p, char **ret);