2 Simple DirectMedia Layer
3 Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
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.
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:
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.
22 #if defined(__clang_analyzer__) && !defined(SDL_DISABLE_ANALYZE_MACROS)
23 #define SDL_DISABLE_ANALYZE_MACROS 1
26 #include "../SDL_internal.h"
28 #if defined(__WIN32__)
29 #include "../core/windows/SDL_windows.h"
32 #if defined(__ANDROID__)
33 #include "../core/android/SDL_android.h"
36 #include "SDL_stdinc.h"
38 #if defined(__WIN32__) && (!defined(HAVE_SETENV) || !defined(HAVE_GETENV))
39 /* Note this isn't thread-safe! */
40 static char *SDL_envmem = NULL; /* Ugh, memory leak */
41 static size_t SDL_envmemlen = 0;
44 /* Put a variable into the environment */
45 /* Note: Name may not contain a '=' character. (Reference: http://www.unix.com/man-page/Linux/3/setenv/) */
46 #if defined(HAVE_SETENV)
48 SDL_setenv(const char *name, const char *value, int overwrite)
50 /* Input validation */
51 if (!name || SDL_strlen(name) == 0 || SDL_strchr(name, '=') != NULL || !value) {
55 return setenv(name, value, overwrite);
57 #elif defined(__WIN32__)
59 SDL_setenv(const char *name, const char *value, int overwrite)
61 /* Input validation */
62 if (!name || SDL_strlen(name) == 0 || SDL_strchr(name, '=') != NULL || !value) {
67 if (GetEnvironmentVariableA(name, NULL, 0) > 0) {
68 return 0; /* asked not to overwrite existing value. */
71 if (!SetEnvironmentVariableA(name, *value ? value : NULL)) {
76 /* We have a real environment table, but no real setenv? Fake it w/ putenv. */
77 #elif (defined(HAVE_GETENV) && defined(HAVE_PUTENV) && !defined(HAVE_SETENV))
79 SDL_setenv(const char *name, const char *value, int overwrite)
84 /* Input validation */
85 if (!name || SDL_strlen(name) == 0 || SDL_strchr(name, '=') != NULL || !value) {
89 if (getenv(name) != NULL) {
93 return 0; /* leave the existing one there. */
97 /* This leaks. Sorry. Get a better OS so we don't have to do this. */
98 len = SDL_strlen(name) + SDL_strlen(value) + 2;
99 new_variable = (char *) SDL_malloc(len);
104 SDL_snprintf(new_variable, len, "%s=%s", name, value);
105 return putenv(new_variable);
107 #else /* roll our own */
108 static char **SDL_env = (char **) 0;
110 SDL_setenv(const char *name, const char *value, int overwrite)
117 /* Input validation */
118 if (!name || SDL_strlen(name) == 0 || SDL_strchr(name, '=') != NULL || !value) {
122 /* See if it already exists */
123 if (!overwrite && SDL_getenv(name)) {
127 /* Allocate memory for the variable */
128 len = SDL_strlen(name) + SDL_strlen(value) + 2;
129 new_variable = (char *) SDL_malloc(len);
134 SDL_snprintf(new_variable, len, "%s=%s", name, value);
135 value = new_variable + SDL_strlen(name) + 1;
138 /* Actually put it into the environment */
142 /* Check to see if it's already there... */
143 len = (value - name);
144 for (; SDL_env[i]; ++i) {
145 if (SDL_strncmp(SDL_env[i], name, len) == 0) {
149 /* If we found it, just replace the entry */
151 SDL_free(SDL_env[i]);
152 SDL_env[i] = new_variable;
157 /* Didn't find it in the environment, expand and add */
159 new_env = SDL_realloc(SDL_env, (i + 2) * sizeof(char *));
162 SDL_env[i++] = new_variable;
163 SDL_env[i++] = (char *) 0;
166 SDL_free(new_variable);
169 return (added ? 0 : -1);
173 /* Retrieve a variable named "name" from the environment */
174 #if defined(HAVE_GETENV)
176 SDL_getenv(const char *name)
178 #if defined(__ANDROID__)
179 /* Make sure variables from the application manifest are available */
180 Android_JNI_GetManifestEnvironmentVariables();
183 /* Input validation */
184 if (!name || !*name) {
190 #elif defined(__WIN32__)
192 SDL_getenv(const char *name)
196 /* Input validation */
197 if (!name || SDL_strlen(name)==0) {
202 GetEnvironmentVariableA(name, SDL_envmem, (DWORD) SDL_envmemlen);
203 if (bufferlen == 0) {
206 if (bufferlen > SDL_envmemlen) {
207 char *newmem = (char *) SDL_realloc(SDL_envmem, bufferlen);
208 if (newmem == NULL) {
212 SDL_envmemlen = bufferlen;
213 GetEnvironmentVariableA(name, SDL_envmem, (DWORD) SDL_envmemlen);
219 SDL_getenv(const char *name)
224 /* Input validation */
225 if (!name || SDL_strlen(name)==0) {
231 len = SDL_strlen(name);
232 for (i = 0; SDL_env[i] && !value; ++i) {
233 if ((SDL_strncmp(SDL_env[i], name, len) == 0) &&
234 (SDL_env[i][len] == '=')) {
235 value = &SDL_env[i][len + 1];
248 main(int argc, char *argv[])
252 printf("Checking for non-existent variable... ");
254 if (!SDL_getenv("EXISTS")) {
259 printf("Setting FIRST=VALUE1 in the environment... ");
261 if (SDL_setenv("FIRST", "VALUE1", 0) == 0) {
266 printf("Getting FIRST from the environment... ");
268 value = SDL_getenv("FIRST");
269 if (value && (SDL_strcmp(value, "VALUE1") == 0)) {
274 printf("Setting SECOND=VALUE2 in the environment... ");
276 if (SDL_setenv("SECOND", "VALUE2", 0) == 0) {
281 printf("Getting SECOND from the environment... ");
283 value = SDL_getenv("SECOND");
284 if (value && (SDL_strcmp(value, "VALUE2") == 0)) {
289 printf("Setting FIRST=NOVALUE in the environment... ");
291 if (SDL_setenv("FIRST", "NOVALUE", 1) == 0) {
296 printf("Getting FIRST from the environment... ");
298 value = SDL_getenv("FIRST");
299 if (value && (SDL_strcmp(value, "NOVALUE") == 0)) {
304 printf("Checking for non-existent variable... ");
306 if (!SDL_getenv("EXISTS")) {
313 #endif /* TEST_MAIN */
315 /* vi: set ts=4 sw=4 expandtab: */