diff options
Diffstat (limited to 'win32/env.c')
-rw-r--r-- | win32/env.c | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/win32/env.c b/win32/env.c new file mode 100644 index 000000000..48b86c555 --- /dev/null +++ b/win32/env.c | |||
@@ -0,0 +1,189 @@ | |||
1 | #include "libbb.h" | ||
2 | |||
3 | char **copy_environ(const char *const *envp) | ||
4 | { | ||
5 | char **env; | ||
6 | int i = 0; | ||
7 | while (envp[i]) | ||
8 | i++; | ||
9 | env = xmalloc((i+1)*sizeof(*env)); | ||
10 | for (i = 0; envp[i]; i++) | ||
11 | env[i] = xstrdup(envp[i]); | ||
12 | env[i] = NULL; | ||
13 | return env; | ||
14 | } | ||
15 | |||
16 | void free_environ(char **env) | ||
17 | { | ||
18 | int i; | ||
19 | for (i = 0; env[i]; i++) | ||
20 | free(env[i]); | ||
21 | free(env); | ||
22 | } | ||
23 | |||
24 | static int lookup_env(char **env, const char *name, size_t nmln) | ||
25 | { | ||
26 | int i; | ||
27 | |||
28 | for (i = 0; env[i]; i++) { | ||
29 | if (0 == strncmp(env[i], name, nmln) | ||
30 | && '=' == env[i][nmln]) | ||
31 | /* matches */ | ||
32 | return i; | ||
33 | } | ||
34 | return -1; | ||
35 | } | ||
36 | |||
37 | #undef getenv | ||
38 | char *mingw_getenv(const char *name) | ||
39 | { | ||
40 | char *result = getenv(name); | ||
41 | if (!result && !strcmp(name, "TMPDIR")) { | ||
42 | /* on Windows it is TMP and TEMP */ | ||
43 | result = getenv("TMP"); | ||
44 | if (!result) | ||
45 | result = getenv("TEMP"); | ||
46 | } | ||
47 | return result; | ||
48 | } | ||
49 | |||
50 | int setenv(const char *name, const char *value, int replace) | ||
51 | { | ||
52 | int out; | ||
53 | size_t namelen, valuelen; | ||
54 | char *envstr; | ||
55 | |||
56 | if (!name || !value) return -1; | ||
57 | if (!replace) { | ||
58 | char *oldval = NULL; | ||
59 | oldval = getenv(name); | ||
60 | if (oldval) return 0; | ||
61 | } | ||
62 | |||
63 | namelen = strlen(name); | ||
64 | valuelen = strlen(value); | ||
65 | envstr = malloc((namelen + valuelen + 2)); | ||
66 | if (!envstr) return -1; | ||
67 | |||
68 | memcpy(envstr, name, namelen); | ||
69 | envstr[namelen] = '='; | ||
70 | memcpy(envstr + namelen + 1, value, valuelen); | ||
71 | envstr[namelen + valuelen + 1] = 0; | ||
72 | |||
73 | out = putenv(envstr); | ||
74 | /* putenv(3) makes the argument string part of the environment, | ||
75 | * and changing that string modifies the environment --- which | ||
76 | * means we do not own that storage anymore. Do not free | ||
77 | * envstr. | ||
78 | */ | ||
79 | |||
80 | return out; | ||
81 | } | ||
82 | |||
83 | /* | ||
84 | * If name contains '=', then sets the variable, otherwise it unsets it | ||
85 | */ | ||
86 | char **env_setenv(char **env, const char *name) | ||
87 | { | ||
88 | char *eq = strchrnul(name, '='); | ||
89 | int i = lookup_env(env, name, eq-name); | ||
90 | |||
91 | if (i < 0) { | ||
92 | if (*eq) { | ||
93 | for (i = 0; env[i]; i++) | ||
94 | ; | ||
95 | env = xrealloc(env, (i+2)*sizeof(*env)); | ||
96 | env[i] = xstrdup(name); | ||
97 | env[i+1] = NULL; | ||
98 | } | ||
99 | } | ||
100 | else { | ||
101 | free(env[i]); | ||
102 | if (*eq) | ||
103 | env[i] = xstrdup(name); | ||
104 | else { | ||
105 | for (; env[i]; i++) | ||
106 | env[i] = env[i+1]; | ||
107 | #if !ENABLE_SAFE_ENV | ||
108 | SetEnvironmentVariable(name, NULL); | ||
109 | #endif | ||
110 | } | ||
111 | } | ||
112 | return env; | ||
113 | } | ||
114 | |||
115 | #if ENABLE_SAFE_ENV | ||
116 | /* | ||
117 | * Removing an environment variable with WIN32 putenv requires an argument | ||
118 | * like "NAME="; glibc omits the '='. The implementations of unsetenv and | ||
119 | * clearenv allow for this. | ||
120 | * | ||
121 | * It isn't possible to create an environment variable with an empty value | ||
122 | * using WIN32 putenv. | ||
123 | */ | ||
124 | #undef putenv | ||
125 | int unsetenv(const char *env) | ||
126 | { | ||
127 | char *name; | ||
128 | int ret; | ||
129 | |||
130 | name = xmalloc(strlen(env)+2); | ||
131 | strcat(strcpy(name, env), "="); | ||
132 | ret = putenv(name); | ||
133 | free(name); | ||
134 | |||
135 | return ret; | ||
136 | } | ||
137 | |||
138 | int clearenv(void) | ||
139 | { | ||
140 | char *name, *s; | ||
141 | |||
142 | while ( environ && *environ ) { | ||
143 | if ( (s=strchr(*environ, '=')) != NULL ) { | ||
144 | name = xstrndup(*environ, s-*environ+1); | ||
145 | putenv(name); | ||
146 | free(name); | ||
147 | } | ||
148 | else { | ||
149 | return -1; | ||
150 | } | ||
151 | } | ||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | int mingw_putenv(const char *env) | ||
156 | { | ||
157 | char *s; | ||
158 | |||
159 | if ( (s=strchr(env, '=')) == NULL ) { | ||
160 | return unsetenv(env); | ||
161 | } | ||
162 | |||
163 | if ( s[1] != '\0' ) { | ||
164 | return putenv(env); | ||
165 | } | ||
166 | |||
167 | /* can't set empty value */ | ||
168 | return 0; | ||
169 | } | ||
170 | #else | ||
171 | void unsetenv(const char *env) | ||
172 | { | ||
173 | env_setenv(environ, env); | ||
174 | } | ||
175 | |||
176 | int clearenv(void) | ||
177 | { | ||
178 | char **env = environ; | ||
179 | if (!env) | ||
180 | return 0; | ||
181 | while (*env) { | ||
182 | free(*env); | ||
183 | env++; | ||
184 | } | ||
185 | free(env); | ||
186 | environ = NULL; | ||
187 | return 0; | ||
188 | } | ||
189 | #endif | ||