diff options
author | Ron Yorston <rmy@pobox.com> | 2018-02-13 11:54:43 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2018-02-13 11:54:43 +0000 |
commit | 834805db9fe525dff26267fb7ba2794cee3ed51a (patch) | |
tree | 3354ca2d465dce743685d0a4b41936d91a2b4d37 /win32 | |
parent | 5bf7067e61f202f023d70f38d14bb66799a27074 (diff) | |
download | busybox-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.c | 126 |
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 | ||
3 | static 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 | |||
17 | char *mingw_getenv(const char *name) | 6 | char *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) | |||
29 | int setenv(const char *name, const char *value, int replace) | 18 | int 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 | */ | ||
65 | char **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 | 43 | int unsetenv(const char *name) |
104 | int 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 | ||
117 | int clearenv(void) | 60 | int 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 | ||
150 | void unsetenv(const char *env) | ||
151 | { | ||
152 | env_setenv(environ, env); | ||
153 | } | ||
154 | |||
155 | int 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 | ||