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) continue;
52 switch (opt->option)
53 {
54 case 'd': /* debug */
55 debug = 1;
56 break;
57 case 'v': /* verbose */
58 verbose = 1;
59 break;
60 case 's': /* secure / set[ug]id */
61 /*
62 ** To test PR_GetEnvSecure, make this executable (or a
63 ** copy of it) setuid / setgid / otherwise inherently
64 ** privileged (e.g., file capabilities) and run it
65 ** with this flag.
66 */
67 secure = 1;
68 break;
69 default:
70 break;
71 }
72 }
73 PL_DestroyOptState(opt);
74 } /* end block "Get command line options" */
75
76 #if 0
77 {
78 /*
79 ** This uses Windows native environment manipulation
80 ** as an experiment. Note the separation of namespace!
81 */
82 BOOL rv;
83 DWORD size;
84 rv = SetEnvironmentVariable( ENVNAME, ENVVALUE );
85 if ( rv == 0 ) {
86 if (debug) printf("env: Shit! SetEnvironmentVariable() failed\n");
87 failedAlready = PR_TRUE;
88 }
89 if (verbose) printf("env: SetEnvironmentVariable() worked\n");
90
91 size = GetEnvironmentVariable( ENVNAME, envBuf, ENVBUFSIZE );
92 if ( size == 0 ) {
93 if (debug) printf("env: Shit! GetEnvironmentVariable() failed. Found: %s\n", envBuf );
94 failedAlready = PR_TRUE;
95 }
96 if (verbose) printf("env: GetEnvironmentVariable() worked. Found: %s\n", envBuf);
97
98 value = PR_GetEnv( ENVNAME );
99 if ( (NULL == value ) || (strcmp( value, ENVVALUE))) {
100 if (debug) printf( "env: PR_GetEnv() failed retrieving WinNative. Found: %s\n", value);
101 failedAlready = PR_TRUE;
102 }
103 if (verbose) printf("env: PR_GetEnv() worked. Found: %s\n", value);
104 }
105 #endif
106
107 /* set an environment variable, read it back */
108 envBuf = NewBuffer( ENVBUFSIZE );
109 sprintf( envBuf, ENVNAME "=" ENVVALUE );
110 rc = PR_SetEnv( envBuf );
111 if ( PR_FAILURE == rc ) {
112 if (debug) printf( "env: PR_SetEnv() failed setting\n");
113 failedAlready = PR_TRUE;
114 } else {
115 if (verbose) printf("env: PR_SetEnv() worked.\n");
116 }
117
118 value = PR_GetEnv( ENVNAME );
119 if ( (NULL == value ) || (strcmp( value, ENVVALUE))) {
120 if (debug) printf( "env: PR_GetEnv() Failed after setting\n" );
121 failedAlready = PR_TRUE;
122 } else {
123 if (verbose) printf("env: PR_GetEnv() worked after setting it. Found: %s\n", value );
124 }
125
126 if ( secure ) {
127 /*
128 ** In this case we've been run with elevated privileges, so
129 ** test that PR_GetEnvSecure *doesn't* find that env var.
130 */
131 value = PR_GetEnvSecure( ENVNAME );
132 if ( NULL != value ) {
133 if (debug) printf( "env: PR_GetEnvSecure() failed; expected NULL, found \"%s\"\n", value );
134 failedAlready = PR_TRUE;
135 } else {
136 if (verbose) printf("env: PR_GetEnvSecure() worked\n" );
137 }
138 } else {
139 /*
140 ** In this case the program is being run normally, so do the
141 ** same check for PR_GetEnvSecure as for PR_GetEnv.
142 */
143 value = PR_GetEnvSecure( ENVNAME );
144 if ( (NULL == value ) || (strcmp( value, ENVVALUE))) {
145 if (debug) printf( "env: PR_GetEnvSecure() Failed after setting\n" );
146 failedAlready = PR_TRUE;
147 } else {
148 if (verbose) printf("env: PR_GetEnvSecure() worked after setting it. Found: %s\n", value );
149 }
150 }
151
152 /* ---------------------------------------------------------------------- */
153 /* check that PR_DuplicateEnvironment() agrees with PR_GetEnv() */
154 {
155 #if defined(XP_UNIX) && (!defined(DARWIN) || defined(HAVE_CRT_EXTERNS_H))
156 static const PRBool expect_failure = PR_FALSE;
157 #else
158 static const PRBool expect_failure = PR_TRUE;
159 #endif
160 char **i, **dupenv = PR_DuplicateEnvironment();
161
162
163 if ( NULL == dupenv ) {
164 if (expect_failure) {
165 if (verbose) printf("env: PR_DuplicateEnvironment failed, "
166 "as expected on this platform.\n");
167 } else {
168 if (debug) printf("env: PR_DuplicateEnvironment() failed.\n");
169 failedAlready = PR_TRUE;
170 }
171 } else {
172 unsigned found = 0;
173
174 if (expect_failure) {
175 if (debug) printf("env: PR_DuplicateEnvironment() succeeded, "
176 "but failure is expected on this platform.\n");
177 failedAlready = PR_TRUE;
178 } else {
179 if (verbose) printf("env: PR_DuplicateEnvironment() succeeded.\n");
180 }
181 for (i = dupenv; *i; i++) {
182 char *equals = strchr(*i, '=');
183
184 if ( equals == NULL ) {
185 if (debug) printf("env: PR_DuplicateEnvironment() returned a string"
186 " with no '=': %s\n", *i);
187 failedAlready = PR_TRUE;
188 } else {
189 /* We own this string, so we can temporarily alter it */
190 /* *i is the null-terminated name; equals + 1 is the value */
191 *equals = '\0';
192
193 if ( strcmp(*i, ENVNAME) == 0) {
194 found++;
195 if (verbose) printf("env: PR_DuplicateEnvironment() found " ENVNAME
196 " (%u so far).\n", found);
197 }
198
199 /* Multiple values for the same name can't happen, according to POSIX. */
200 value = PR_GetEnv(*i);
201 if ( value == NULL ) {
202 if (debug) printf("env: PR_DuplicateEnvironment() returned a name"
203 " which PR_GetEnv() failed to find: %s\n", *i);
204 failedAlready = PR_TRUE;
205 } else if ( strcmp(equals + 1, value) != 0) {
206 if (debug) printf("env: PR_DuplicateEnvironment() returned the wrong"
207 " value for %s: expected %s; found %s\n",
208 *i, value, equals + 1);
209 failedAlready = PR_TRUE;
210 } else {
211 if (verbose) printf("env: PR_DuplicateEnvironment() agreed with"
212 " PR_GetEnv() about %s\n", *i);
213 }
214 }
215 PR_Free(*i);
216 }
217 PR_Free(dupenv);
218
219 if (found != 1) {
220 if (debug) printf("env: PR_DuplicateEnvironment() found %u entries for " ENVNAME
221 " (expected 1)\n", found);
222 failedAlready = PR_TRUE;
223 } else {
224 if (verbose) printf("env: PR_DuplicateEnvironment() found 1 entry for " ENVNAME "\n");
225 }
226 }
227 }
228
229 /* ---------------------------------------------------------------------- */
230 /* un-set the variable, using RAW name... should not work */
231 envBuf = NewBuffer( ENVBUFSIZE );
232 sprintf( envBuf, ENVNAME );
233 rc = PR_SetEnv( envBuf );
234 if ( PR_FAILURE == rc ) {
235 if (verbose) printf( "env: PR_SetEnv() not un-set using RAW name. Good!\n");
236 } else {
237 if (debug) printf("env: PR_SetEnv() un-set using RAW name. Bad!\n" );
238 failedAlready = PR_TRUE;
239 }
240
241 value = PR_GetEnv( ENVNAME );
242 if ( NULL == value ) {
243 if (debug) printf("env: PR_GetEnv() after un-set using RAW name. Bad!\n" );
244 failedAlready = PR_TRUE;
245 } else {
246 if (verbose) printf( "env: PR_GetEnv() after RAW un-set found: %s\n", value );
247 }
248
249 /* ---------------------------------------------------------------------- */
250 /* set it again ... */
251 envBuf = NewBuffer( ENVBUFSIZE );
252 sprintf( envBuf, ENVNAME "=" ENVVALUE );
253 rc = PR_SetEnv( envBuf );
254 if ( PR_FAILURE == rc ) {
255 if (debug) printf( "env: PR_SetEnv() failed setting the second time.\n");
256 failedAlready = PR_TRUE;
257 } else {
258 if (verbose) printf("env: PR_SetEnv() worked.\n");
259 }
260
261 /* un-set the variable using the form name= */
262 envBuf = NewBuffer( ENVBUFSIZE );
263 sprintf( envBuf, ENVNAME "=" );
264 rc = PR_SetEnv( envBuf );
265 if ( PR_FAILURE == rc ) {
266 if (debug) printf( "env: PR_SetEnv() failed un-setting using name=\n");
267 failedAlready = PR_TRUE;
268 } else {
269 if (verbose) printf("env: PR_SetEnv() un-set using name= worked\n" );
270 }
271
272 value = PR_GetEnv( ENVNAME );
273 if (( NULL == value ) || ( 0x00 == *value )) {
274 if (verbose) printf("env: PR_GetEnv() after un-set using name= worked\n" );
275 } else {
276 if (debug) printf( "env: PR_GetEnv() after un-set using name=. Found: %s\n", value );
277 failedAlready = PR_TRUE;
278 }
279 /* ---------------------------------------------------------------------- */
280 /* un-set the variable using the form name= */
281 envBuf = NewBuffer( ENVBUFSIZE );
282 sprintf( envBuf, ENVNAME "999=" );
283 rc = PR_SetEnv( envBuf );
284 if ( PR_FAILURE == rc ) {
285 if (debug) printf( "env: PR_SetEnv() failed un-setting using name=\n");
286 failedAlready = PR_TRUE;
287 } else {
288 if (verbose) printf("env: PR_SetEnv() un-set using name= worked\n" );
289 }
290
291 value = PR_GetEnv( ENVNAME "999" );
292 if (( NULL == value ) || ( 0x00 == *value )) {
293 if (verbose) printf("env: PR_GetEnv() after un-set using name= worked\n" );
294 } else {
295 if (debug) printf( "env: PR_GetEnv() after un-set using name=. Found: %s\n", value );
296 failedAlready = PR_TRUE;
297 }
298
299 /* ---------------------------------------------------------------------- */
300 if (debug || verbose) printf("\n%s\n", (failedAlready)? "FAILED" : "PASSED" );
301 return( (failedAlready)? 1 : 0 );
302 } /* main() */
303
304 /* env.c */
305