aboutsummaryrefslogtreecommitdiff
path: root/win32
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2018-02-13 11:54:43 +0000
committerRon Yorston <rmy@pobox.com>2018-02-13 11:54:43 +0000
commit834805db9fe525dff26267fb7ba2794cee3ed51a (patch)
tree3354ca2d465dce743685d0a4b41936d91a2b4d37 /win32
parent5bf7067e61f202f023d70f38d14bb66799a27074 (diff)
downloadbusybox-w32-834805db9fe525dff26267fb7ba2794cee3ed51a.tar.gz
busybox-w32-834805db9fe525dff26267fb7ba2794cee3ed51a.tar.bz2
busybox-w32-834805db9fe525dff26267fb7ba2794cee3ed51a.zip
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
Diffstat (limited to 'win32')
-rw-r--r--win32/env.c126
1 files changed, 26 insertions, 100 deletions
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 @@
1#include "libbb.h" 1#include "libbb.h"
2 2
3static int lookup_env(char **env, const char *name, size_t nmln)
4{
5 int i;
6
7 for (i = 0; env[i]; i++) {
8 if (0 == strncmp(env[i], name, nmln)
9 && '=' == env[i][nmln])
10 /* matches */
11 return i;
12 }
13 return -1;
14}
15
16#undef getenv 3#undef getenv
4#undef putenv
5
17char *mingw_getenv(const char *name) 6char *mingw_getenv(const char *name)
18{ 7{
19 char *result = getenv(name); 8 char *result = getenv(name);
@@ -29,70 +18,21 @@ char *mingw_getenv(const char *name)
29int setenv(const char *name, const char *value, int replace) 18int setenv(const char *name, const char *value, int replace)
30{ 19{
31 int out; 20 int out;
32 size_t namelen, valuelen;
33 char *envstr; 21 char *envstr;
34 22
35 if (!name || !value) return -1; 23 if (!name || !*name || strchr(name, '=') || !value) return -1;
36 if (!replace) { 24 if (!replace) {
37 char *oldval = NULL; 25 if (getenv(name)) return 0;
38 oldval = getenv(name);
39 if (oldval) return 0;
40 } 26 }
41 27
42 namelen = strlen(name); 28 envstr = xasprintf("%s=%s", name, value);
43 valuelen = strlen(value); 29 out = mingw_putenv(envstr);
44 envstr = malloc((namelen + valuelen + 2)); 30 free(envstr);
45 if (!envstr) return -1;
46
47 memcpy(envstr, name, namelen);
48 envstr[namelen] = '=';
49 memcpy(envstr + namelen + 1, value, valuelen);
50 envstr[namelen + valuelen + 1] = 0;
51
52 out = putenv(envstr);
53 /* putenv(3) makes the argument string part of the environment,
54 * and changing that string modifies the environment --- which
55 * means we do not own that storage anymore. Do not free
56 * envstr.
57 */
58 31
59 return out; 32 return out;
60} 33}
61 34
62/* 35/*
63 * If name contains '=', then sets the variable, otherwise it unsets it
64 */
65char **env_setenv(char **env, const char *name)
66{
67 char *eq = strchrnul(name, '=');
68 int i = lookup_env(env, name, eq-name);
69
70 if (i < 0) {
71 if (*eq) {
72 for (i = 0; env[i]; i++)
73 ;
74 env = xrealloc(env, (i+2)*sizeof(*env));
75 env[i] = xstrdup(name);
76 env[i+1] = NULL;
77 }
78 }
79 else {
80 free(env[i]);
81 if (*eq)
82 env[i] = xstrdup(name);
83 else {
84 for (; env[i]; i++)
85 env[i] = env[i+1];
86#if !ENABLE_SAFE_ENV
87 SetEnvironmentVariable(name, NULL);
88#endif
89 }
90 }
91 return env;
92}
93
94#if ENABLE_SAFE_ENV
95/*
96 * Removing an environment variable with WIN32 putenv requires an argument 36 * Removing an environment variable with WIN32 putenv requires an argument
97 * like "NAME="; glibc omits the '='. The implementations of unsetenv and 37 * like "NAME="; glibc omits the '='. The implementations of unsetenv and
98 * clearenv allow for this. 38 * clearenv allow for this.
@@ -100,28 +40,34 @@ char **env_setenv(char **env, const char *name)
100 * It isn't possible to create an environment variable with an empty value 40 * It isn't possible to create an environment variable with an empty value
101 * using WIN32 putenv. 41 * using WIN32 putenv.
102 */ 42 */
103#undef putenv 43int unsetenv(const char *name)
104int unsetenv(const char *env)
105{ 44{
106 char *name; 45 char *envstr;
107 int ret; 46 int ret;
108 47
109 name = xmalloc(strlen(env)+2); 48 if (!name || !*name || strchr(name, '=') ) {
110 strcat(strcpy(name, env), "="); 49 return -1;
111 ret = putenv(name); 50 }
112 free(name); 51
52 envstr = xmalloc(strlen(name)+2);
53 strcat(strcpy(envstr, name), "=");
54 ret = putenv(envstr);
55 free(envstr);
113 56
114 return ret; 57 return ret;
115} 58}
116 59
117int clearenv(void) 60int clearenv(void)
118{ 61{
119 char *name, *s; 62 char *envp, *name, *s;
120 63
121 while ( environ && *environ ) { 64 while ( environ && (envp=*environ) ) {
122 if ( (s=strchr(*environ, '=')) != NULL ) { 65 if ( (s=strchr(envp, '=')) != NULL ) {
123 name = xstrndup(*environ, s-*environ+1); 66 name = xstrndup(envp, s-envp+1);
124 putenv(name); 67 if ( putenv(name) == -1 ) {
68 free(name);
69 return -1;
70 }
125 free(name); 71 free(name);
126 } 72 }
127 else { 73 else {
@@ -146,23 +92,3 @@ int mingw_putenv(const char *env)
146 /* can't set empty value */ 92 /* can't set empty value */
147 return 0; 93 return 0;
148} 94}
149#else
150void unsetenv(const char *env)
151{
152 env_setenv(environ, env);
153}
154
155int clearenv(void)
156{
157 char **env = environ;
158 if (!env)
159 return 0;
160 while (*env) {
161 free(*env);
162 env++;
163 }
164 free(env);
165 environ = NULL;
166 return 0;
167}
168#endif