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