1 /*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20 */
21
22 #if defined(__clang_analyzer__) && !defined(SDL_DISABLE_ANALYZE_MACROS)
23 #define SDL_DISABLE_ANALYZE_MACROS 1
24 #endif
25
26 #include "../SDL_internal.h"
27
28 #if defined(__WIN32__)
29 #include "../core/windows/SDL_windows.h"
30 #endif
31
32 #include "SDL_stdinc.h"
33
34 #if defined(__WIN32__) && (!defined(HAVE_SETENV) || !defined(HAVE_GETENV))
35 /* Note this isn't thread-safe! */
36 static char *SDL_envmem = NULL; /* Ugh, memory leak */
37 static size_t SDL_envmemlen = 0;
38 #endif
39
40 /* Put a variable into the environment */
41 /* Note: Name may not contain a '=' character. (Reference: http://www.unix.com/man-page/Linux/3/setenv/) */
42 #if defined(HAVE_SETENV)
43 int
SDL_setenv(const char * name,const char * value,int overwrite)44 SDL_setenv(const char *name, const char *value, int overwrite)
45 {
46 /* Input validation */
47 if (!name || SDL_strlen(name) == 0 || SDL_strchr(name, '=') != NULL || !value) {
48 return (-1);
49 }
50
51 return setenv(name, value, overwrite);
52 }
53 #elif defined(__WIN32__)
54 int
SDL_setenv(const char * name,const char * value,int overwrite)55 SDL_setenv(const char *name, const char *value, int overwrite)
56 {
57 /* Input validation */
58 if (!name || SDL_strlen(name) == 0 || SDL_strchr(name, '=') != NULL || !value) {
59 return (-1);
60 }
61
62 if (!overwrite) {
63 char ch = 0;
64 const size_t len = GetEnvironmentVariableA(name, &ch, sizeof (ch));
65 if (len > 0) {
66 return 0; /* asked not to overwrite existing value. */
67 }
68 }
69 if (!SetEnvironmentVariableA(name, *value ? value : NULL)) {
70 return -1;
71 }
72 return 0;
73 }
74 /* We have a real environment table, but no real setenv? Fake it w/ putenv. */
75 #elif (defined(HAVE_GETENV) && defined(HAVE_PUTENV) && !defined(HAVE_SETENV))
76 int
SDL_setenv(const char * name,const char * value,int overwrite)77 SDL_setenv(const char *name, const char *value, int overwrite)
78 {
79 size_t len;
80 char *new_variable;
81
82 /* Input validation */
83 if (!name || SDL_strlen(name) == 0 || SDL_strchr(name, '=') != NULL || !value) {
84 return (-1);
85 }
86
87 if (getenv(name) != NULL) {
88 if (overwrite) {
89 unsetenv(name);
90 } else {
91 return 0; /* leave the existing one there. */
92 }
93 }
94
95 /* This leaks. Sorry. Get a better OS so we don't have to do this. */
96 len = SDL_strlen(name) + SDL_strlen(value) + 2;
97 new_variable = (char *) SDL_malloc(len);
98 if (!new_variable) {
99 return (-1);
100 }
101
102 SDL_snprintf(new_variable, len, "%s=%s", name, value);
103 return putenv(new_variable);
104 }
105 #else /* roll our own */
106 static char **SDL_env = (char **) 0;
107 int
SDL_setenv(const char * name,const char * value,int overwrite)108 SDL_setenv(const char *name, const char *value, int overwrite)
109 {
110 int added;
111 int len, i;
112 char **new_env;
113 char *new_variable;
114
115 /* Input validation */
116 if (!name || SDL_strlen(name) == 0 || SDL_strchr(name, '=') != NULL || !value) {
117 return (-1);
118 }
119
120 /* See if it already exists */
121 if (!overwrite && SDL_getenv(name)) {
122 return 0;
123 }
124
125 /* Allocate memory for the variable */
126 len = SDL_strlen(name) + SDL_strlen(value) + 2;
127 new_variable = (char *) SDL_malloc(len);
128 if (!new_variable) {
129 return (-1);
130 }
131
132 SDL_snprintf(new_variable, len, "%s=%s", name, value);
133 value = new_variable + SDL_strlen(name) + 1;
134 name = new_variable;
135
136 /* Actually put it into the environment */
137 added = 0;
138 i = 0;
139 if (SDL_env) {
140 /* Check to see if it's already there... */
141 len = (value - name);
142 for (; SDL_env[i]; ++i) {
143 if (SDL_strncmp(SDL_env[i], name, len) == 0) {
144 break;
145 }
146 }
147 /* If we found it, just replace the entry */
148 if (SDL_env[i]) {
149 SDL_free(SDL_env[i]);
150 SDL_env[i] = new_variable;
151 added = 1;
152 }
153 }
154
155 /* Didn't find it in the environment, expand and add */
156 if (!added) {
157 new_env = SDL_realloc(SDL_env, (i + 2) * sizeof(char *));
158 if (new_env) {
159 SDL_env = new_env;
160 SDL_env[i++] = new_variable;
161 SDL_env[i++] = (char *) 0;
162 added = 1;
163 } else {
164 SDL_free(new_variable);
165 }
166 }
167 return (added ? 0 : -1);
168 }
169 #endif
170
171 /* Retrieve a variable named "name" from the environment */
172 #if defined(HAVE_GETENV)
173 char *
SDL_getenv(const char * name)174 SDL_getenv(const char *name)
175 {
176 /* Input validation */
177 if (!name || SDL_strlen(name)==0) {
178 return NULL;
179 }
180
181 return getenv(name);
182 }
183 #elif defined(__WIN32__)
184 char *
SDL_getenv(const char * name)185 SDL_getenv(const char *name)
186 {
187 size_t bufferlen;
188
189 /* Input validation */
190 if (!name || SDL_strlen(name)==0) {
191 return NULL;
192 }
193
194 bufferlen =
195 GetEnvironmentVariableA(name, SDL_envmem, (DWORD) SDL_envmemlen);
196 if (bufferlen == 0) {
197 return NULL;
198 }
199 if (bufferlen > SDL_envmemlen) {
200 char *newmem = (char *) SDL_realloc(SDL_envmem, bufferlen);
201 if (newmem == NULL) {
202 return NULL;
203 }
204 SDL_envmem = newmem;
205 SDL_envmemlen = bufferlen;
206 GetEnvironmentVariableA(name, SDL_envmem, (DWORD) SDL_envmemlen);
207 }
208 return SDL_envmem;
209 }
210 #else
211 char *
SDL_getenv(const char * name)212 SDL_getenv(const char *name)
213 {
214 int len, i;
215 char *value;
216
217 /* Input validation */
218 if (!name || SDL_strlen(name)==0) {
219 return NULL;
220 }
221
222 value = (char *) 0;
223 if (SDL_env) {
224 len = SDL_strlen(name);
225 for (i = 0; SDL_env[i] && !value; ++i) {
226 if ((SDL_strncmp(SDL_env[i], name, len) == 0) &&
227 (SDL_env[i][len] == '=')) {
228 value = &SDL_env[i][len + 1];
229 }
230 }
231 }
232 return value;
233 }
234 #endif
235
236
237 #ifdef TEST_MAIN
238 #include <stdio.h>
239
240 int
main(int argc,char * argv[])241 main(int argc, char *argv[])
242 {
243 char *value;
244
245 printf("Checking for non-existent variable... ");
246 fflush(stdout);
247 if (!SDL_getenv("EXISTS")) {
248 printf("okay\n");
249 } else {
250 printf("failed\n");
251 }
252 printf("Setting FIRST=VALUE1 in the environment... ");
253 fflush(stdout);
254 if (SDL_setenv("FIRST", "VALUE1", 0) == 0) {
255 printf("okay\n");
256 } else {
257 printf("failed\n");
258 }
259 printf("Getting FIRST from the environment... ");
260 fflush(stdout);
261 value = SDL_getenv("FIRST");
262 if (value && (SDL_strcmp(value, "VALUE1") == 0)) {
263 printf("okay\n");
264 } else {
265 printf("failed\n");
266 }
267 printf("Setting SECOND=VALUE2 in the environment... ");
268 fflush(stdout);
269 if (SDL_setenv("SECOND", "VALUE2", 0) == 0) {
270 printf("okay\n");
271 } else {
272 printf("failed\n");
273 }
274 printf("Getting SECOND from the environment... ");
275 fflush(stdout);
276 value = SDL_getenv("SECOND");
277 if (value && (SDL_strcmp(value, "VALUE2") == 0)) {
278 printf("okay\n");
279 } else {
280 printf("failed\n");
281 }
282 printf("Setting FIRST=NOVALUE in the environment... ");
283 fflush(stdout);
284 if (SDL_setenv("FIRST", "NOVALUE", 1) == 0) {
285 printf("okay\n");
286 } else {
287 printf("failed\n");
288 }
289 printf("Getting FIRST from the environment... ");
290 fflush(stdout);
291 value = SDL_getenv("FIRST");
292 if (value && (SDL_strcmp(value, "NOVALUE") == 0)) {
293 printf("okay\n");
294 } else {
295 printf("failed\n");
296 }
297 printf("Checking for non-existent variable... ");
298 fflush(stdout);
299 if (!SDL_getenv("EXISTS")) {
300 printf("okay\n");
301 } else {
302 printf("failed\n");
303 }
304 return (0);
305 }
306 #endif /* TEST_MAIN */
307
308 /* vi: set ts=4 sw=4 expandtab: */
309