From c5390b667d0d8d7d387707f91795970e078b30b0 Mon Sep 17 00:00:00 2001 From: obarun <eric@obarun.org> Date: Tue, 8 Jun 2021 18:43:37 +1100 Subject: [PATCH] replace ${VAR} syntax by the corresponding value at environment variable declaration --- src/extra-tools/execl-envfile.c | 159 ++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) diff --git a/src/extra-tools/execl-envfile.c b/src/extra-tools/execl-envfile.c index c56d2c4e..3a979357 100644 --- a/src/extra-tools/execl-envfile.c +++ b/src/extra-tools/execl-envfile.c @@ -49,6 +49,142 @@ static inline void info_help (void) log_info(USAGE,"\n",help) ; } +void parse_env_var(stralloc *result, stralloc *modifs, char const *line) ; + +void substitute_env_var(stralloc *result, stralloc *modifs, char const *mkey, char const *key, char const *regex) +{ + stralloc tmp = STRALLOC_ZERO ; + + if (!stralloc_copy(&tmp, result) || + !stralloc_0(&tmp)) + log_die_nomem("stralloc") ; + + if (!sastr_rebuild_in_nline(&tmp) || + !stralloc_0(&tmp)) + log_dieu(LOG_EXIT_SYS,"rebuild line") ; + + char *by = getenv(key) ; + + if (!by) { + + /** check if key and mkey are the same + * variable to avoid a variable calling itself. + * we accept e.g ${PATH}=${PATH} only if PATH + * is set on the environnement */ + if (!strcmp(mkey,key)) + log_die(LOG_EXIT_USER,"recursive call of variable: ",regex) ; + + /** if the key doesn't exist we let + * the variable as it A.K.A. ${VAR} */ + if (!environ_get_val_of_key(&tmp, key)) + return ; + + if (!stralloc_0(&tmp)) + log_die_nomem("stralloc") ; + + by = tmp.s ; + } + + /** recursive call at variable definition. + * parse first the recursive variable*/ + if (str_contain(by,"${") >= 0) { + + char tmp[strlen(key) + 1 + strlen(by) + 1] ; + auto_strings(tmp,key,"=",by) ; + + parse_env_var(result, modifs, tmp) ; + } + + if (!sastr_replace_all(result, regex, by)) + log_dieu(LOG_EXIT_SYS,"replace: ", regex, "by: ", by) ; + + + stralloc_free(&tmp) ; +} + +void parse_env_var(stralloc *result, stralloc *modifs, char const *line) +{ + stralloc subs = STRALLOC_ZERO ; + + size_t spos = 0, pos = 0 ; + + /** be sure to deal with key=value */ + spos = get_sep_before(line,'=','\n') ; + if (spos<= 0) + log_dieu(LOG_EXIT_SYS,"get value from line: ", line) ; + + spos++ ; //remove the = character + + /** master key -- see comment at substitute_env_var */ + char mkey[spos + 1] ; + memcpy(mkey,line,spos - 1) ; + mkey[spos - 1] = 0 ; + + if (!auto_stra(&subs, line + spos)) + log_die_nomem("stralloc") ; + + if (!sastr_split_element_in_nline(&subs) || + !stralloc_0(&subs)) + log_dieu(LOG_EXIT_SYS,"split line") ; + + { + FOREACH_SASTR(&subs, pos) { + + char *line = subs.s + pos ; + size_t len = strlen(line) ; + char key[len + 1] ; + + ssize_t rstart = 0 ; + + /** deal with multiple ${} on the + * same line */ + while (rstart < len) { + + ssize_t r = get_len_until(line + rstart, '$') ; + + if (r == -1) + break ; + + rstart += r ; + + ssize_t start = rstart + 1 ; + + if (line[start] == '{') { + + ssize_t rend = get_len_until(line + start , '}') ; + + if (rend == -1) { + log_warn("unmatched { at line: ", line) ; + return ; + } + + ssize_t end = rend - 1 ; + start++ ; + + memcpy(key, line + start, end) ; + key[end] = 0 ; + + char regex[rend + 3] ; + memcpy(regex,line + rstart, rend + 2) ; + regex[rend + 2] = 0 ; + + substitute_env_var(result, modifs, mkey, key, regex) ; + + rstart += rstart + rend + 2 ; + + } else { + + log_warn("ignoring variable at line: ", line," -- missing {}" ) ; + rstart += rstart + 1 ; + return ; + } + } + } + } + + stralloc_free(&subs) ; +} + int main (int argc, char const *const *argv, char const *const *envp) { int r = 0, unexport = 0, insist = 1 ; @@ -189,6 +325,29 @@ int main (int argc, char const *const *argv, char const *const *envp) stralloc_free(&again) ; + { + stralloc result = STRALLOC_ZERO ; + size_t pos = 0 ; + + if (!stralloc_copy(&result, &modifs) || + !stralloc_0(&result)) + log_die_nomem("stralloc") ; + + FOREACH_SASTR(&modifs, pos) + + parse_env_var(&result, &modifs, modifs.s + pos) ; + + + if (!sastr_split_string_in_nline(&result) || + !stralloc_0(&result)) + log_dieu(LOG_EXIT_SYS,"split string") ; + + if (!stralloc_copy(&modifs, &result)) + log_die_nomem("stralloc") ; + + stralloc_free(&result) ; + } + /** be able to freed the stralloc before existing */ char tmp[modifs.len+1] ; memcpy(tmp,modifs.s,modifs.len) ; -- GitLab