env.c 12 KB

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