1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 /*
7 ** File: env.c
8 ** Description: Testing environment variable operations
9 **
10 */
11 #include "prenv.h"
12 #include "prmem.h"
13 #include "plgetopt.h"
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18
19 PRIntn debug = 0;
20 PRIntn verbose = 0;
21 PRIntn secure = 0;
22 PRBool failedAlready = PR_FALSE;
23
24 #define ENVNAME "NSPR_ENVIRONMENT_TEST_VARIABLE"
25 #define ENVVALUE "The expected result"
26 #define ENVBUFSIZE 256
27
28 char *envBuf; /* buffer pointer. We leak memory here on purpose! */
29
NewBuffer(size_t size)30 static char * NewBuffer( size_t size )
31 {
32 char *buf = malloc( size );
33 if ( NULL == buf ) {
34 printf("env: NewBuffer() failed\n");
35 exit(1);
36 }
37 return(buf);
38 } /* end NewBuffer() */
39
main(int argc,char ** argv)40 int main(int argc, char **argv)
41 {
42 char *value;
43 PRStatus rc;
44
45 { /* Get command line options */
46 PLOptStatus os;
47 PLOptState *opt = PL_CreateOptState(argc, argv, "vds");
48
49 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
50 {
51 if (PL_OPT_BAD == os) {
52 continue;
53 }
54 switch (opt->option)
55 {
56 case 'd': /* debug */
57 debug = 1;
58 break;
59 case 'v': /* verbose */
60 verbose = 1;
61 break;
62 case 's': /* secure / set[ug]id */
63 /*
64 ** To test PR_GetEnvSecure, make this executable (or a
65 ** copy of it) setuid / setgid / otherwise inherently
66 ** privileged (e.g., file capabilities) and run it
67 ** with this flag.
68 */
69 secure = 1;
70 break;
71 default:
72 break;
73 }
74 }
75 PL_DestroyOptState(opt);
76 } /* end block "Get command line options" */
77
78 #if 0
79 {
80 /*
81 ** This uses Windows native environment manipulation
82 ** as an experiment. Note the separation of namespace!
83 */
84 BOOL rv;
85 DWORD size;
86 rv = SetEnvironmentVariable( ENVNAME, ENVVALUE );
87 if ( rv == 0 ) {
88 if (debug) {
89 printf("env: Shit! SetEnvironmentVariable() failed\n");
90 }
91 failedAlready = PR_TRUE;
92 }
93 if (verbose) {
94 printf("env: SetEnvironmentVariable() worked\n");
95 }
96
97 size = GetEnvironmentVariable( ENVNAME, envBuf, ENVBUFSIZE );
98 if ( size == 0 ) {
99 if (debug) {
100 printf("env: Shit! GetEnvironmentVariable() failed. Found: %s\n", envBuf );
101 }
102 failedAlready = PR_TRUE;
103 }
104 if (verbose) {
105 printf("env: GetEnvironmentVariable() worked. Found: %s\n", envBuf);
106 }
107
108 value = PR_GetEnv( ENVNAME );
109 if ( (NULL == value ) || (strcmp( value, ENVVALUE))) {
110 if (debug) {
111 printf( "env: PR_GetEnv() failed retrieving WinNative. Found: %s\n", value);
112 }
113 failedAlready = PR_TRUE;
114 }
115 if (verbose) {
116 printf("env: PR_GetEnv() worked. Found: %s\n", value);
117 }
118 }
119 #endif
120
121 /* set an environment variable, read it back */
122 envBuf = NewBuffer( ENVBUFSIZE );
123 sprintf( envBuf, ENVNAME "=" ENVVALUE );
124 rc = PR_SetEnv( envBuf );
125 if ( PR_FAILURE == rc ) {
126 if (debug) {
127 printf( "env: PR_SetEnv() failed setting\n");
128 }
129 failedAlready = PR_TRUE;
130 } else {
131 if (verbose) {
132 printf("env: PR_SetEnv() worked.\n");
133 }
134 }
135
136 value = PR_GetEnv( ENVNAME );
137 if ( (NULL == value ) || (strcmp( value, ENVVALUE))) {
138 if (debug) {
139 printf( "env: PR_GetEnv() Failed after setting\n" );
140 }
141 failedAlready = PR_TRUE;
142 } else {
143 if (verbose) {
144 printf("env: PR_GetEnv() worked after setting it. Found: %s\n", value );
145 }
146 }
147
148 if ( secure ) {
149 /*
150 ** In this case we've been run with elevated privileges, so
151 ** test that PR_GetEnvSecure *doesn't* find that env var.
152 */
153 value = PR_GetEnvSecure( ENVNAME );
154 if ( NULL != value ) {
155 if (debug) {
156 printf( "env: PR_GetEnvSecure() failed; expected NULL, found \"%s\"\n", value );
157 }
158 failedAlready = PR_TRUE;
159 } else {
160 if (verbose) {
161 printf("env: PR_GetEnvSecure() worked\n" );
162 }
163 }
164 } else {
165 /*
166 ** In this case the program is being run normally, so do the
167 ** same check for PR_GetEnvSecure as for PR_GetEnv.
168 */
169 value = PR_GetEnvSecure( ENVNAME );
170 if ( (NULL == value ) || (strcmp( value, ENVVALUE))) {
171 if (debug) {
172 printf( "env: PR_GetEnvSecure() Failed after setting\n" );
173 }
174 failedAlready = PR_TRUE;
175 } else {
176 if (verbose) {
177 printf("env: PR_GetEnvSecure() worked after setting it. Found: %s\n", value );
178 }
179 }
180 }
181
182 /* ---------------------------------------------------------------------- */
183 /* check that PR_DuplicateEnvironment() agrees with PR_GetEnv() */
184 {
185 #if defined(XP_UNIX) && (!defined(DARWIN) || defined(HAVE_CRT_EXTERNS_H))
186 static const PRBool expect_failure = PR_FALSE;
187 #else
188 static const PRBool expect_failure = PR_TRUE;
189 #endif
190 char **i, **dupenv = PR_DuplicateEnvironment();
191
192
193 if ( NULL == dupenv ) {
194 if (expect_failure) {
195 if (verbose) printf("env: PR_DuplicateEnvironment failed, "
196 "as expected on this platform.\n");
197 } else {
198 if (debug) {
199 printf("env: PR_DuplicateEnvironment() failed.\n");
200 }
201 failedAlready = PR_TRUE;
202 }
203 } else {
204 unsigned found = 0;
205
206 if (expect_failure) {
207 if (debug) printf("env: PR_DuplicateEnvironment() succeeded, "
208 "but failure is expected on this platform.\n");
209 failedAlready = PR_TRUE;
210 } else {
211 if (verbose) {
212 printf("env: PR_DuplicateEnvironment() succeeded.\n");
213 }
214 }
215 for (i = dupenv; *i; i++) {
216 char *equals = strchr(*i, '=');
217
218 if ( equals == NULL ) {
219 if (debug) printf("env: PR_DuplicateEnvironment() returned a string"
220 " with no '=': %s\n", *i);
221 failedAlready = PR_TRUE;
222 } else {
223 /* We own this string, so we can temporarily alter it */
224 /* *i is the null-terminated name; equals + 1 is the value */
225 *equals = '\0';
226
227 if ( strcmp(*i, ENVNAME) == 0) {
228 found++;
229 if (verbose) printf("env: PR_DuplicateEnvironment() found " ENVNAME
230 " (%u so far).\n", found);
231 }
232
233 /* Multiple values for the same name can't happen, according to POSIX. */
234 value = PR_GetEnv(*i);
235 if ( value == NULL ) {
236 if (debug) printf("env: PR_DuplicateEnvironment() returned a name"
237 " which PR_GetEnv() failed to find: %s\n", *i);
238 failedAlready = PR_TRUE;
239 } else if ( strcmp(equals + 1, value) != 0) {
240 if (debug) printf("env: PR_DuplicateEnvironment() returned the wrong"
241 " value for %s: expected %s; found %s\n",
242 *i, value, equals + 1);
243 failedAlready = PR_TRUE;
244 } else {
245 if (verbose) printf("env: PR_DuplicateEnvironment() agreed with"
246 " PR_GetEnv() about %s\n", *i);
247 }
248 }
249 PR_Free(*i);
250 }
251 PR_Free(dupenv);
252
253 if (found != 1) {
254 if (debug) printf("env: PR_DuplicateEnvironment() found %u entries for " ENVNAME
255 " (expected 1)\n", found);
256 failedAlready = PR_TRUE;
257 } else {
258 if (verbose) {
259 printf("env: PR_DuplicateEnvironment() found 1 entry for " ENVNAME "\n");
260 }
261 }
262 }
263 }
264
265 /* ---------------------------------------------------------------------- */
266 /* un-set the variable, using RAW name... should not work */
267 envBuf = NewBuffer( ENVBUFSIZE );
268 sprintf( envBuf, ENVNAME );
269 rc = PR_SetEnv( envBuf );
270 if ( PR_FAILURE == rc ) {
271 if (verbose) {
272 printf( "env: PR_SetEnv() not un-set using RAW name. Good!\n");
273 }
274 } else {
275 if (debug) {
276 printf("env: PR_SetEnv() un-set using RAW name. Bad!\n" );
277 }
278 failedAlready = PR_TRUE;
279 }
280
281 value = PR_GetEnv( ENVNAME );
282 if ( NULL == value ) {
283 if (debug) {
284 printf("env: PR_GetEnv() after un-set using RAW name. Bad!\n" );
285 }
286 failedAlready = PR_TRUE;
287 } else {
288 if (verbose) {
289 printf( "env: PR_GetEnv() after RAW un-set found: %s\n", value );
290 }
291 }
292
293 /* ---------------------------------------------------------------------- */
294 /* set it again ... */
295 envBuf = NewBuffer( ENVBUFSIZE );
296 sprintf( envBuf, ENVNAME "=" ENVVALUE );
297 rc = PR_SetEnv( envBuf );
298 if ( PR_FAILURE == rc ) {
299 if (debug) {
300 printf( "env: PR_SetEnv() failed setting the second time.\n");
301 }
302 failedAlready = PR_TRUE;
303 } else {
304 if (verbose) {
305 printf("env: PR_SetEnv() worked.\n");
306 }
307 }
308
309 /* un-set the variable using the form name= */
310 envBuf = NewBuffer( ENVBUFSIZE );
311 sprintf( envBuf, ENVNAME "=" );
312 rc = PR_SetEnv( envBuf );
313 if ( PR_FAILURE == rc ) {
314 if (debug) {
315 printf( "env: PR_SetEnv() failed un-setting using name=\n");
316 }
317 failedAlready = PR_TRUE;
318 } else {
319 if (verbose) {
320 printf("env: PR_SetEnv() un-set using name= worked\n" );
321 }
322 }
323
324 value = PR_GetEnv( ENVNAME );
325 if (( NULL == value ) || ( 0x00 == *value )) {
326 if (verbose) {
327 printf("env: PR_GetEnv() after un-set using name= worked\n" );
328 }
329 } else {
330 if (debug) {
331 printf( "env: PR_GetEnv() after un-set using name=. Found: %s\n", value );
332 }
333 failedAlready = PR_TRUE;
334 }
335 /* ---------------------------------------------------------------------- */
336 /* un-set the variable using the form name= */
337 envBuf = NewBuffer( ENVBUFSIZE );
338 sprintf( envBuf, ENVNAME "999=" );
339 rc = PR_SetEnv( envBuf );
340 if ( PR_FAILURE == rc ) {
341 if (debug) {
342 printf( "env: PR_SetEnv() failed un-setting using name=\n");
343 }
344 failedAlready = PR_TRUE;
345 } else {
346 if (verbose) {
347 printf("env: PR_SetEnv() un-set using name= worked\n" );
348 }
349 }
350
351 value = PR_GetEnv( ENVNAME "999" );
352 if (( NULL == value ) || ( 0x00 == *value )) {
353 if (verbose) {
354 printf("env: PR_GetEnv() after un-set using name= worked\n" );
355 }
356 } else {
357 if (debug) {
358 printf( "env: PR_GetEnv() after un-set using name=. Found: %s\n", value );
359 }
360 failedAlready = PR_TRUE;
361 }
362
363 /* ---------------------------------------------------------------------- */
364 if (debug || verbose) {
365 printf("\n%s\n", (failedAlready)? "FAILED" : "PASSED" );
366 }
367 return( (failedAlready)? 1 : 0 );
368 } /* main() */
369
370 /* env.c */
371