aboutsummaryrefslogtreecommitdiff
path: root/win32/env.c
diff options
context:
space:
mode:
Diffstat (limited to 'win32/env.c')
-rw-r--r--win32/env.c189
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
3char **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
16void free_environ(char **env)
17{
18 int i;
19 for (i = 0; env[i]; i++)
20 free(env[i]);
21 free(env);
22}
23
24static 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
38char *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
50int 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 */
86char **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
125int 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
138int 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
155int 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
171void unsetenv(const char *env)
172{
173 env_setenv(environ, env);
174}
175
176int 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