diff options
Diffstat (limited to 'src/util.c')
-rw-r--r-- | src/util.c | 112 |
1 files changed, 109 insertions, 3 deletions
diff --git a/src/util.c b/src/util.c index a01229e659..cdfc9e0158 100644 --- a/src/util.c +++ b/src/util.c @@ -613,15 +613,23 @@ int get_process_cmdline(pid_t pid, size_t max_length, char **line) { return 0; } -char *strappend(const char *s, const char *suffix) { - size_t a, b; +char *strnappend(const char *s, const char *suffix, size_t b) { + size_t a; char *r; + if (!s && !suffix) + return strdup(""); + + if (!s) + return strndup(suffix, b); + + if (!suffix) + return strdup(s); + assert(s); assert(suffix); a = strlen(s); - b = strlen(suffix); if (!(r = new(char, a+b+1))) return NULL; @@ -633,6 +641,10 @@ char *strappend(const char *s, const char *suffix) { return r; } +char *strappend(const char *s, const char *suffix) { + return strnappend(s, suffix, suffix ? strlen(suffix) : 0); +} + int readlink_malloc(const char *p, char **r) { size_t l = 100; @@ -2692,6 +2704,100 @@ void status_welcome(void) { #endif } +char *replace_env(const char *format, char **env) { + enum { + WORD, + DOLLAR, + 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 = DOLLAR; + break; + + case DOLLAR: + if (*e == '(') { + if (!(k = strnappend(r, word, e-word-1))) + goto fail; + + free(r); + r = k; + + word = e-1; + state = VARIABLE; + + } else if (*e == '$') { + if (!(k = strnappend(r, word, e-word))) + goto fail; + + free(r); + r = k; + + word = e+1; + state = WORD; + } else + state = WORD; + break; + + case VARIABLE: + if (*e == ')') { + char *t; + + if ((t = strv_env_get_with_length(env, word+2, e-word-2))) { + if (!(k = strappend(r, t))) + goto fail; + + free(r); + r = k; + + word = e+1; + } + + state = WORD; + } + break; + } + } + + if (!(k = strnappend(r, word, e-word))) + goto fail; + + free(r); + return k; + +fail: + free(r); + return NULL; +} + +char **replace_env_argv(char **argv, char **env) { + char **r, **i; + unsigned k; + + if (!(r = new(char*, strv_length(argv)+1))) + return NULL; + + STRV_FOREACH(i, argv) { + if (!(r[k++] = replace_env(*i, env))) { + strv_free(r); + return NULL; + } + } + + r[k] = NULL; + return r; +} + static const char *const ioprio_class_table[] = { [IOPRIO_CLASS_NONE] = "none", [IOPRIO_CLASS_RT] = "realtime", |