From 834805db9fe525dff26267fb7ba2794cee3ed51a Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Tue, 13 Feb 2018 11:54:43 +0000 Subject: win32: always use safe API calls to manipulate environment It turns out that with the new toolchain safe API calls work on all all platforms. Even the original code from commit fa147bd7e works on Windows XP when built with the new tools. - Remove the unsafe environment manipulation via the environ array - Microsoft's putenv takes a copy of its argument so the string can be freed - Rewrite some routines and add more error checking --- win32/env.c | 126 +++++++++++++----------------------------------------------- 1 file changed, 26 insertions(+), 100 deletions(-) (limited to 'win32') diff --git a/win32/env.c b/win32/env.c index eab3c1708..2837c0720 100644 --- a/win32/env.c +++ b/win32/env.c @@ -1,19 +1,8 @@ #include "libbb.h" -static int lookup_env(char **env, const char *name, size_t nmln) -{ - int i; - - for (i = 0; env[i]; i++) { - if (0 == strncmp(env[i], name, nmln) - && '=' == env[i][nmln]) - /* matches */ - return i; - } - return -1; -} - #undef getenv +#undef putenv + char *mingw_getenv(const char *name) { char *result = getenv(name); @@ -29,69 +18,20 @@ char *mingw_getenv(const char *name) int setenv(const char *name, const char *value, int replace) { int out; - size_t namelen, valuelen; char *envstr; - if (!name || !value) return -1; + if (!name || !*name || strchr(name, '=') || !value) return -1; if (!replace) { - char *oldval = NULL; - oldval = getenv(name); - if (oldval) return 0; + if (getenv(name)) return 0; } - namelen = strlen(name); - valuelen = strlen(value); - envstr = malloc((namelen + valuelen + 2)); - if (!envstr) return -1; - - memcpy(envstr, name, namelen); - envstr[namelen] = '='; - memcpy(envstr + namelen + 1, value, valuelen); - envstr[namelen + valuelen + 1] = 0; - - out = putenv(envstr); - /* putenv(3) makes the argument string part of the environment, - * and changing that string modifies the environment --- which - * means we do not own that storage anymore. Do not free - * envstr. - */ + envstr = xasprintf("%s=%s", name, value); + out = mingw_putenv(envstr); + free(envstr); return out; } -/* - * If name contains '=', then sets the variable, otherwise it unsets it - */ -char **env_setenv(char **env, const char *name) -{ - char *eq = strchrnul(name, '='); - int i = lookup_env(env, name, eq-name); - - if (i < 0) { - if (*eq) { - for (i = 0; env[i]; i++) - ; - env = xrealloc(env, (i+2)*sizeof(*env)); - env[i] = xstrdup(name); - env[i+1] = NULL; - } - } - else { - free(env[i]); - if (*eq) - env[i] = xstrdup(name); - else { - for (; env[i]; i++) - env[i] = env[i+1]; -#if !ENABLE_SAFE_ENV - SetEnvironmentVariable(name, NULL); -#endif - } - } - return env; -} - -#if ENABLE_SAFE_ENV /* * Removing an environment variable with WIN32 putenv requires an argument * like "NAME="; glibc omits the '='. The implementations of unsetenv and @@ -100,28 +40,34 @@ char **env_setenv(char **env, const char *name) * It isn't possible to create an environment variable with an empty value * using WIN32 putenv. */ -#undef putenv -int unsetenv(const char *env) +int unsetenv(const char *name) { - char *name; + char *envstr; int ret; - name = xmalloc(strlen(env)+2); - strcat(strcpy(name, env), "="); - ret = putenv(name); - free(name); + if (!name || !*name || strchr(name, '=') ) { + return -1; + } + + envstr = xmalloc(strlen(name)+2); + strcat(strcpy(envstr, name), "="); + ret = putenv(envstr); + free(envstr); return ret; } int clearenv(void) { - char *name, *s; - - while ( environ && *environ ) { - if ( (s=strchr(*environ, '=')) != NULL ) { - name = xstrndup(*environ, s-*environ+1); - putenv(name); + char *envp, *name, *s; + + while ( environ && (envp=*environ) ) { + if ( (s=strchr(envp, '=')) != NULL ) { + name = xstrndup(envp, s-envp+1); + if ( putenv(name) == -1 ) { + free(name); + return -1; + } free(name); } else { @@ -146,23 +92,3 @@ int mingw_putenv(const char *env) /* can't set empty value */ return 0; } -#else -void unsetenv(const char *env) -{ - env_setenv(environ, env); -} - -int clearenv(void) -{ - char **env = environ; - if (!env) - return 0; - while (*env) { - free(*env); - env++; - } - free(env); - environ = NULL; - return 0; -} -#endif -- cgit v1.2.3-55-g6feb