From 381341f5f72a46b34126e5c8e6f62f04b702ba47 Mon Sep 17 00:00:00 2001 From: James Morrissey Date: Fri, 16 May 2014 11:36:36 +0100 Subject: [PATCH] Fix environment variable assignment in init The init process allows environment variables to be specified in the rc script globally, via 'export', and for a specific process, via the 'setenv' option. However, the mechanism for assembling the environment simply appended the new variable without checking whether it was already defined, so it was not possible to overwrite an existing entry. This patch fixes that behaviour. Limitations and concerns: The limit of a maximum number of 31 variables is unchanged. Currently, most callers of "add_environment" do not check the return value, but the function now logs the failure rather than failing silently. Change-Id: Ie9a68c37a0f55c5b40e904e695cd35514f67f480 --- init/builtins.c | 5 ++--- init/init.c | 25 ++++++++++++++++++++----- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/init/builtins.c b/init/builtins.c index b32981e35..c474198fc 100644 --- a/init/builtins.c +++ b/init/builtins.c @@ -48,7 +48,7 @@ #include -void add_environment(const char *name, const char *value); +int add_environment(const char *name, const char *value); extern int init_module(void *, unsigned long, const char *); @@ -261,8 +261,7 @@ int do_exec(int nargs, char **args) int do_export(int nargs, char **args) { - add_environment(args[1], args[2]); - return 0; + return add_environment(args[1], args[2]); } int do_hostname(int nargs, char **args) diff --git a/init/init.c b/init/init.c index e4ac1cf2d..74c0308bb 100644 --- a/init/init.c +++ b/init/init.c @@ -96,11 +96,24 @@ static const char *ENV[32]; /* add_environment - add "key=value" to the current environment */ int add_environment(const char *key, const char *val) { - int n; + size_t n; + size_t key_len = strlen(key); - for (n = 0; n < 31; n++) { - if (!ENV[n]) { - size_t len = strlen(key) + strlen(val) + 2; + /* The last environment entry is reserved to terminate the list */ + for (n = 0; n < (ARRAY_SIZE(ENV) - 1); n++) { + + /* Delete any existing entry for this key */ + if (ENV[n] != NULL) { + size_t entry_key_len = strcspn(ENV[n], "="); + if ((entry_key_len == key_len) && (strncmp(ENV[n], key, entry_key_len) == 0)) { + free((char*)ENV[n]); + ENV[n] = NULL; + } + } + + /* Add entry if a free slot is available */ + if (ENV[n] == NULL) { + size_t len = key_len + strlen(val) + 2; char *entry = malloc(len); snprintf(entry, len, "%s=%s", key, val); ENV[n] = entry; @@ -108,7 +121,9 @@ int add_environment(const char *key, const char *val) } } - return 1; + ERROR("No env. room to store: '%s':'%s'\n", key, val); + + return -1; } static void zap_stdio(void)