• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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