SDL  2.0
SDL_getenv.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2018 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 #if defined(__ANDROID__)
33 #include "../core/android/SDL_android.h"
34 #endif
35 
36 #include "SDL_stdinc.h"
37 
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;
42 #endif
43 
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)
47 int
48 SDL_setenv(const char *name, const char *value, int overwrite)
49 {
50  /* Input validation */
51  if (!name || SDL_strlen(name) == 0 || SDL_strchr(name, '=') != NULL || !value) {
52  return (-1);
53  }
54 
55  return setenv(name, value, overwrite);
56 }
57 #elif defined(__WIN32__)
58 int
59 SDL_setenv(const char *name, const char *value, int overwrite)
60 {
61  /* Input validation */
62  if (!name || SDL_strlen(name) == 0 || SDL_strchr(name, '=') != NULL || !value) {
63  return (-1);
64  }
65 
66  if (!overwrite) {
67  if (GetEnvironmentVariableA(name, NULL, 0) > 0) {
68  return 0; /* asked not to overwrite existing value. */
69  }
70  }
71  if (!SetEnvironmentVariableA(name, *value ? value : NULL)) {
72  return -1;
73  }
74  return 0;
75 }
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))
78 int
79 SDL_setenv(const char *name, const char *value, int overwrite)
80 {
81  size_t len;
82  char *new_variable;
83 
84  /* Input validation */
85  if (!name || SDL_strlen(name) == 0 || SDL_strchr(name, '=') != NULL || !value) {
86  return (-1);
87  }
88 
89  if (getenv(name) != NULL) {
90  if (overwrite) {
91  unsetenv(name);
92  } else {
93  return 0; /* leave the existing one there. */
94  }
95  }
96 
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);
100  if (!new_variable) {
101  return (-1);
102  }
103 
104  SDL_snprintf(new_variable, len, "%s=%s", name, value);
105  return putenv(new_variable);
106 }
107 #else /* roll our own */
108 static char **SDL_env = (char **) 0;
109 int
110 SDL_setenv(const char *name, const char *value, int overwrite)
111 {
112  int added;
113  int len, i;
114  char **new_env;
115  char *new_variable;
116 
117  /* Input validation */
118  if (!name || SDL_strlen(name) == 0 || SDL_strchr(name, '=') != NULL || !value) {
119  return (-1);
120  }
121 
122  /* See if it already exists */
123  if (!overwrite && SDL_getenv(name)) {
124  return 0;
125  }
126 
127  /* Allocate memory for the variable */
128  len = SDL_strlen(name) + SDL_strlen(value) + 2;
129  new_variable = (char *) SDL_malloc(len);
130  if (!new_variable) {
131  return (-1);
132  }
133 
134  SDL_snprintf(new_variable, len, "%s=%s", name, value);
135  value = new_variable + SDL_strlen(name) + 1;
136  name = new_variable;
137 
138  /* Actually put it into the environment */
139  added = 0;
140  i = 0;
141  if (SDL_env) {
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) {
146  break;
147  }
148  }
149  /* If we found it, just replace the entry */
150  if (SDL_env[i]) {
151  SDL_free(SDL_env[i]);
152  SDL_env[i] = new_variable;
153  added = 1;
154  }
155  }
156 
157  /* Didn't find it in the environment, expand and add */
158  if (!added) {
159  new_env = SDL_realloc(SDL_env, (i + 2) * sizeof(char *));
160  if (new_env) {
161  SDL_env = new_env;
162  SDL_env[i++] = new_variable;
163  SDL_env[i++] = (char *) 0;
164  added = 1;
165  } else {
166  SDL_free(new_variable);
167  }
168  }
169  return (added ? 0 : -1);
170 }
171 #endif
172 
173 /* Retrieve a variable named "name" from the environment */
174 #if defined(HAVE_GETENV)
175 char *
176 SDL_getenv(const char *name)
177 {
178 #if defined(__ANDROID__)
179  /* Make sure variables from the application manifest are available */
181 #endif
182 
183  /* Input validation */
184  if (!name || !*name) {
185  return NULL;
186  }
187 
188  return getenv(name);
189 }
190 #elif defined(__WIN32__)
191 char *
192 SDL_getenv(const char *name)
193 {
194  size_t bufferlen;
195 
196  /* Input validation */
197  if (!name || SDL_strlen(name)==0) {
198  return NULL;
199  }
200 
201  bufferlen =
202  GetEnvironmentVariableA(name, SDL_envmem, (DWORD) SDL_envmemlen);
203  if (bufferlen == 0) {
204  return NULL;
205  }
206  if (bufferlen > SDL_envmemlen) {
207  char *newmem = (char *) SDL_realloc(SDL_envmem, bufferlen);
208  if (newmem == NULL) {
209  return NULL;
210  }
211  SDL_envmem = newmem;
212  SDL_envmemlen = bufferlen;
213  GetEnvironmentVariableA(name, SDL_envmem, (DWORD) SDL_envmemlen);
214  }
215  return SDL_envmem;
216 }
217 #else
218 char *
219 SDL_getenv(const char *name)
220 {
221  int len, i;
222  char *value;
223 
224  /* Input validation */
225  if (!name || SDL_strlen(name)==0) {
226  return NULL;
227  }
228 
229  value = (char *) 0;
230  if (SDL_env) {
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];
236  }
237  }
238  }
239  return value;
240 }
241 #endif
242 
243 
244 #ifdef TEST_MAIN
245 #include <stdio.h>
246 
247 int
248 main(int argc, char *argv[])
249 {
250  char *value;
251 
252  printf("Checking for non-existent variable... ");
253  fflush(stdout);
254  if (!SDL_getenv("EXISTS")) {
255  printf("okay\n");
256  } else {
257  printf("failed\n");
258  }
259  printf("Setting FIRST=VALUE1 in the environment... ");
260  fflush(stdout);
261  if (SDL_setenv("FIRST", "VALUE1", 0) == 0) {
262  printf("okay\n");
263  } else {
264  printf("failed\n");
265  }
266  printf("Getting FIRST from the environment... ");
267  fflush(stdout);
268  value = SDL_getenv("FIRST");
269  if (value && (SDL_strcmp(value, "VALUE1") == 0)) {
270  printf("okay\n");
271  } else {
272  printf("failed\n");
273  }
274  printf("Setting SECOND=VALUE2 in the environment... ");
275  fflush(stdout);
276  if (SDL_setenv("SECOND", "VALUE2", 0) == 0) {
277  printf("okay\n");
278  } else {
279  printf("failed\n");
280  }
281  printf("Getting SECOND from the environment... ");
282  fflush(stdout);
283  value = SDL_getenv("SECOND");
284  if (value && (SDL_strcmp(value, "VALUE2") == 0)) {
285  printf("okay\n");
286  } else {
287  printf("failed\n");
288  }
289  printf("Setting FIRST=NOVALUE in the environment... ");
290  fflush(stdout);
291  if (SDL_setenv("FIRST", "NOVALUE", 1) == 0) {
292  printf("okay\n");
293  } else {
294  printf("failed\n");
295  }
296  printf("Getting FIRST from the environment... ");
297  fflush(stdout);
298  value = SDL_getenv("FIRST");
299  if (value && (SDL_strcmp(value, "NOVALUE") == 0)) {
300  printf("okay\n");
301  } else {
302  printf("failed\n");
303  }
304  printf("Checking for non-existent variable... ");
305  fflush(stdout);
306  if (!SDL_getenv("EXISTS")) {
307  printf("okay\n");
308  } else {
309  printf("failed\n");
310  }
311  return (0);
312 }
313 #endif /* TEST_MAIN */
314 
315 /* vi: set ts=4 sw=4 expandtab: */
char * SDL_getenv(const char *name)
Definition: SDL_getenv.c:219
#define SDL_realloc
#define SDL_strncmp
static char ** SDL_env
Definition: SDL_getenv.c:108
GLenum GLsizei len
GLuint const GLchar * name
#define SDL_strchr
#define SDL_free
int SDL_setenv(const char *name, const char *value, int overwrite)
Definition: SDL_getenv.c:110
GLsizei const GLfloat * value
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
#define NULL
Definition: begin_code.h:164
void Android_JNI_GetManifestEnvironmentVariables(void)
#define SDL_strlen
#define SDL_snprintf
#define SDL_malloc
#define main
Definition: SDL_main.h:111
#define SDL_strcmp