1/*
2    SDL - Simple DirectMedia Layer
3    Copyright (C) 1997-2006 Sam Lantinga
4
5    This library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    This library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with this library; if not, write to the Free Software
17    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
19    Sam Lantinga
20    slouken@libsdl.org
21*/
22#include "SDL_config.h"
23
24#include "SDL_stdinc.h"
25
26#ifndef HAVE_GETENV
27
28#if defined(__WIN32__) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__)
29
30#define WIN32_LEAN_AND_MEAN
31#include <windows.h>
32
33/* Note this isn't thread-safe! */
34
35static char *SDL_envmem = NULL;	/* Ugh, memory leak */
36static size_t SDL_envmemlen = 0;
37
38/* Put a variable of the form "name=value" into the environment */
39int SDL_putenv(const char *variable)
40{
41	size_t bufferlen;
42	char *value;
43	const char *sep;
44
45	sep = SDL_strchr(variable, '=');
46	if ( sep == NULL ) {
47		return -1;
48	}
49	bufferlen = SDL_strlen(variable)+1;
50	if ( bufferlen > SDL_envmemlen ) {
51		char *newmem = (char *)SDL_realloc(SDL_envmem, bufferlen);
52		if ( newmem == NULL ) {
53			return -1;
54		}
55		SDL_envmem = newmem;
56		SDL_envmemlen = bufferlen;
57	}
58	SDL_strlcpy(SDL_envmem, variable, bufferlen);
59	value = SDL_envmem + (sep - variable);
60	*value++ = '\0';
61	if ( !SetEnvironmentVariable(SDL_envmem, *value ? value : NULL) ) {
62		return -1;
63	}
64	return 0;
65}
66
67/* Retrieve a variable named "name" from the environment */
68char *SDL_getenv(const char *name)
69{
70	size_t bufferlen;
71
72	bufferlen = GetEnvironmentVariable(name, SDL_envmem, (DWORD)SDL_envmemlen);
73	if ( bufferlen == 0 ) {
74		return NULL;
75	}
76	if ( bufferlen > SDL_envmemlen ) {
77		char *newmem = (char *)SDL_realloc(SDL_envmem, bufferlen);
78		if ( newmem == NULL ) {
79			return NULL;
80		}
81		SDL_envmem = newmem;
82		SDL_envmemlen = bufferlen;
83		GetEnvironmentVariable(name, SDL_envmem, (DWORD)SDL_envmemlen);
84	}
85	return SDL_envmem;
86}
87
88#else /* roll our own */
89
90static char **SDL_env = (char **)0;
91
92/* Put a variable of the form "name=value" into the environment */
93int SDL_putenv(const char *variable)
94{
95	const char *name, *value;
96	int added;
97	int len, i;
98	char **new_env;
99	char *new_variable;
100
101	/* A little error checking */
102	if ( ! variable ) {
103		return(-1);
104	}
105	name = variable;
106	for ( value=variable; *value && (*value != '='); ++value ) {
107		/* Keep looking for '=' */ ;
108	}
109	if ( *value ) {
110		++value;
111	} else {
112		return(-1);
113	}
114
115	/* Allocate memory for the variable */
116	new_variable = SDL_strdup(variable);
117	if ( ! new_variable ) {
118		return(-1);
119	}
120
121	/* Actually put it into the environment */
122	added = 0;
123	i = 0;
124	if ( SDL_env ) {
125		/* Check to see if it's already there... */
126		len = (value - name);
127		for ( ; SDL_env[i]; ++i ) {
128			if ( SDL_strncmp(SDL_env[i], name, len) == 0 ) {
129				break;
130			}
131		}
132		/* If we found it, just replace the entry */
133		if ( SDL_env[i] ) {
134			SDL_free(SDL_env[i]);
135			SDL_env[i] = new_variable;
136			added = 1;
137		}
138	}
139
140	/* Didn't find it in the environment, expand and add */
141	if ( ! added ) {
142		new_env = SDL_realloc(SDL_env, (i+2)*sizeof(char *));
143		if ( new_env ) {
144			SDL_env = new_env;
145			SDL_env[i++] = new_variable;
146			SDL_env[i++] = (char *)0;
147			added = 1;
148		} else {
149			SDL_free(new_variable);
150		}
151	}
152	return (added ? 0 : -1);
153}
154
155/* Retrieve a variable named "name" from the environment */
156char *SDL_getenv(const char *name)
157{
158	int len, i;
159	char *value;
160
161	value = (char *)0;
162	if ( SDL_env ) {
163		len = SDL_strlen(name);
164		for ( i=0; SDL_env[i] && !value; ++i ) {
165			if ( (SDL_strncmp(SDL_env[i], name, len) == 0) &&
166			     (SDL_env[i][len] == '=') ) {
167				value = &SDL_env[i][len+1];
168			}
169		}
170	}
171	return value;
172}
173
174#endif /* __WIN32__ */
175
176#endif /* !HAVE_GETENV */
177
178#ifdef TEST_MAIN
179#include <stdio.h>
180
181int main(int argc, char *argv[])
182{
183	char *value;
184
185	printf("Checking for non-existent variable... ");
186	fflush(stdout);
187	if ( ! SDL_getenv("EXISTS") ) {
188		printf("okay\n");
189	} else {
190		printf("failed\n");
191	}
192	printf("Setting FIRST=VALUE1 in the environment... ");
193	fflush(stdout);
194	if ( SDL_putenv("FIRST=VALUE1") == 0 ) {
195		printf("okay\n");
196	} else {
197		printf("failed\n");
198	}
199	printf("Getting FIRST from the environment... ");
200	fflush(stdout);
201	value = SDL_getenv("FIRST");
202	if ( value && (SDL_strcmp(value, "VALUE1") == 0) ) {
203		printf("okay\n");
204	} else {
205		printf("failed\n");
206	}
207	printf("Setting SECOND=VALUE2 in the environment... ");
208	fflush(stdout);
209	if ( SDL_putenv("SECOND=VALUE2") == 0 ) {
210		printf("okay\n");
211	} else {
212		printf("failed\n");
213	}
214	printf("Getting SECOND from the environment... ");
215	fflush(stdout);
216	value = SDL_getenv("SECOND");
217	if ( value && (SDL_strcmp(value, "VALUE2") == 0) ) {
218		printf("okay\n");
219	} else {
220		printf("failed\n");
221	}
222	printf("Setting FIRST=NOVALUE in the environment... ");
223	fflush(stdout);
224	if ( SDL_putenv("FIRST=NOVALUE") == 0 ) {
225		printf("okay\n");
226	} else {
227		printf("failed\n");
228	}
229	printf("Getting FIRST from the environment... ");
230	fflush(stdout);
231	value = SDL_getenv("FIRST");
232	if ( value && (SDL_strcmp(value, "NOVALUE") == 0) ) {
233		printf("okay\n");
234	} else {
235		printf("failed\n");
236	}
237	printf("Checking for non-existent variable... ");
238	fflush(stdout);
239	if ( ! SDL_getenv("EXISTS") ) {
240		printf("okay\n");
241	} else {
242		printf("failed\n");
243	}
244	return(0);
245}
246#endif /* TEST_MAIN */
247
248