From: Karel Zak Date: Tue, 27 Aug 2024 11:07:56 +0000 (+0200) Subject: env: save parsed variables into ul_env_list X-Git-Tag: v2.42-start~214^2~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=aa789c1efcd28223308d010c830bc7f22c52927b;p=thirdparty%2Futil-linux.git env: save parsed variables into ul_env_list The struct ul_env_list is currently only used to store the value of env when sanitizing environ[]. It would be beneficial to also use the functions related to ul_env_list for other purposes. In order to do this, it is important to keep the NAME and VALUE components separate. * Accept non-terminated name and value for env_list_add(). * Add env_list_add_from_string() to add item to the list from a "name=value" string. * Add env_list_add_variable() to add item to the list using separate "name" and "value" strings. * Update __sanitize_env() to use env_list_add_from_string(). * Modify the test to use "abc" as the value instead of copying the variable name (with '=') to the value. Signed-off-by: Karel Zak --- diff --git a/include/env.h b/include/env.h index 9b2991950..5e9198c88 100644 --- a/include/env.h +++ b/include/env.h @@ -13,6 +13,10 @@ struct ul_env_list; extern void sanitize_env(void); extern void __sanitize_env(struct ul_env_list **org); +extern struct ul_env_list *env_list_add_variable(struct ul_env_list *ls, + const char *name, const char *value); + + extern int env_list_setenv(struct ul_env_list *ls); extern void env_list_free(struct ul_env_list *ls); extern struct ul_env_list *env_from_fd(int pid); diff --git a/lib/env.c b/lib/env.c index 2bdfe5697..bab8822b0 100644 --- a/lib/env.c +++ b/lib/env.c @@ -52,36 +52,74 @@ static char * const noslash[] = { struct ul_env_list { - char *env; + char *name; + char *value; + struct ul_env_list *next; }; /* - * Saves @name env.variable to @ls, returns pointer to the new head of the list. + * Saves to the list and returns a pointer to the new head of the list. */ -static struct ul_env_list *env_list_add(struct ul_env_list *ls0, const char *str) +static struct ul_env_list *env_list_add( struct ul_env_list *ls0, + const char *name, size_t namesz, + const char *value, size_t valsz) { struct ul_env_list *ls; - char *p; - size_t sz = 0; - if (!str || !*str) + ls = calloc(1, sizeof(struct ul_env_list) + namesz + valsz + 2); + if (!ls) return ls0; - sz = strlen(str) + 1; - p = malloc(sizeof(struct ul_env_list) + sz); - if (!p) - return ls0; + ls->name = ((char *) ls) + sizeof(struct ul_env_list); + ls->value = ls->name + namesz + 1; - ls = (struct ul_env_list *) p; - p += sizeof(struct ul_env_list); - memcpy(p, str, sz); - ls->env = p; + memcpy(ls->name, name, namesz); + memcpy(ls->value, value, valsz); ls->next = ls0; return ls; } + +/* + * Saves the @str (with the name=value string) to the @ls and returns a pointer + * to the new head of the list. + */ +static struct ul_env_list *env_list_add_from_string(struct ul_env_list *ls, + const char *str) +{ + size_t namesz = 0, valsz = 0; + const char *val; + + if (!str || !*str) + return ls; + + val = strchr(str, '='); + if (!val) + return NULL; + namesz = val - str; + + val++; + valsz = strlen(val); + + return env_list_add(ls, str, namesz, val, valsz); +} + +/* + * Saves the @name and @value to @ls0 and returns a pointer to the new head of + * the list. + */ +struct ul_env_list *env_list_add_variable( + struct ul_env_list *ls, + const char *name, const char *value) +{ + if (!name || !*name) + return ls; + + return env_list_add(ls, name, strlen(name), value, value ? strlen(value) : 0); +} + /* * Use env_from_fd() to read environment from @fd. * @@ -99,7 +137,7 @@ struct ul_env_list *env_from_fd(int fd) p = buf; while (rc > 0) { - ls = env_list_add(ls, p); + ls = env_list_add_from_string(ls, p); p += strlen(p) + 1; rc -= strlen(p) + 1; } @@ -110,22 +148,14 @@ struct ul_env_list *env_from_fd(int fd) /* * Use setenv() for all stuff in @ls. - * - * It would be possible to use putenv(), but we want to keep @ls free()-able. */ int env_list_setenv(struct ul_env_list *ls) { int rc = 0; while (ls && rc == 0) { - if (ls->env) { - char *val = strchr(ls->env, '='); - if (!val) - continue; - *val = '\0'; - rc = setenv(ls->env, val + 1, 0); - *val = '='; - } + if (ls->name && ls->value) + rc = setenv(ls->name, ls->value, 0); ls = ls->next; } return rc; @@ -158,7 +188,7 @@ void __sanitize_env(struct ul_env_list **org) for (bad = forbid; *bad; bad++) { if (strncmp(*cur, *bad, strlen(*bad)) == 0) { if (org) - *org = env_list_add(*org, *cur); + *org = env_list_add_from_string(*org, *cur); last = remove_entry(envp, cur - envp, last); cur--; break; @@ -173,7 +203,7 @@ void __sanitize_env(struct ul_env_list **org) if (!strchr(*cur, '/')) continue; /* OK */ if (org) - *org = env_list_add(*org, *cur); + *org = env_list_add_from_string(*org, *cur); last = remove_entry(envp, cur - envp, last); cur--; break; @@ -217,12 +247,13 @@ int main(void) int retval = EXIT_SUCCESS; struct ul_env_list *removed = NULL; + /* define env. */ for (bad = forbid; *bad; bad++) { strcpy(copy, *bad); p = strchr(copy, '='); if (p) *p = '\0'; - setenv(copy, copy, 1); + setenv(copy, "abc", 1); } /* removed */