Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

314 lines
9.4 KiB

  1. /***
  2. *putenv.c - put an environment variable into the environment
  3. *
  4. * Copyright (c) 1985-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * defines _putenv() - adds a new variable to environment; does not
  8. * change global environment, only the process' environment.
  9. *
  10. *Revision History:
  11. * 08-08-84 RN initial version
  12. * 02-23-88 SKS check for environment containing only the NULL string
  13. * 05-31-88 PHG Merged DLL and normal versions
  14. * 07-14-88 JCR Much simplified since (1) __setenvp always uses heap, and
  15. * (2) envp array and env strings are in seperate heap blocks
  16. * 07-03-89 PHG Now "option=" string removes string from environment
  17. * 08-17-89 GJF Removed _NEAR_, _LOAD_DS and fixed indents.
  18. * 09-14-89 KRS Don't give error if 'option' not defined in "option=".
  19. * 11-20-89 GJF Added const to arg type. Also, fixed copyright.
  20. * 03-15-90 GJF Made the calling type _CALLTYPE1, added #include
  21. * <cruntime.h> and removed #include <register.h>.
  22. * 04-05-90 GJF Made findenv() _CALLTYPE4.
  23. * 04-26-90 JCR Bug fix if environ is NULL (stubbed out _setenvp)
  24. * 07-25-90 SBM Removed redundant include (stdio.h)
  25. * 10-04-90 GJF New-style function declarators.
  26. * 01-21-91 GJF ANSI naming.
  27. * 02-06-91 SRW Added _WIN32_ conditional for SetEnvironmentVariable
  28. * 02-18-91 SRW Changed _WIN32_ conditional for SetEnvironmentVariable
  29. * to be in addition to old logic instead of replacement
  30. * 04-23-92 GJF Made findenv insensitive to the case of name for Win32.
  31. * Also added support for 'current drive' environment
  32. * strings in Win32.
  33. * 04-29-92 GJF Repackaged so that _putenv_lk could be easily added for
  34. * for Win32.
  35. * 05-05-92 DJM POSIX not supported.
  36. * 04-06-93 SKS Replace _CRTAPI* with __cdecl
  37. * 06-05-92 PLM Added _MAC_
  38. * 11-24-93 CFW Rip out Cruiser, disallow "=C:=C:\foo" format putenvs.
  39. * 11-29-93 CFW Wide char enable, convert between wide and narrow
  40. * types. Mucho code moved to setenv.c
  41. * 12-07-93 CFW Change _TCHAR to _TSCHAR.
  42. * 01-15-94 CFW Use _tcsnicoll for global match.
  43. * 09-06-94 CFW Replace MTHREAD with _MT.
  44. * 01-10-95 CFW Debug CRT allocs.
  45. * 02-14-95 CFW Debug CRT allocs for Mac version.
  46. * 02-16-95 JWM Spliced _WIN32 & Mac versions.
  47. * 06-01-95 CFW Copy environment string before passing to _crt[w]setenv.
  48. * 07-09-97 GJF Added a check that the environment initialization has
  49. * been executed. Also, cleaned up the format a bit and
  50. * got rid of obsolete _CALLTYPE* macros.
  51. * 03-03-98 RKP Added 64 bit support.
  52. * 03-05-98 GJF Exception-safe locking.
  53. * 08-28-98 GJF Use CP_ACP instead of CP_OEMCP.
  54. * 05-17-99 PML Remove all Macintosh support.
  55. * 05-25-99 GJF Free up buffers allocated to hold env string when there
  56. * there is a failure.
  57. *
  58. *******************************************************************************/
  59. #ifndef _POSIX_
  60. #include <windows.h>
  61. #include <cruntime.h>
  62. #include <internal.h>
  63. #include <mtdll.h>
  64. #include <stdlib.h>
  65. #include <string.h>
  66. #include <tchar.h>
  67. #include <dbgint.h>
  68. #ifndef CRTDLL
  69. /*
  70. * Flag checked by getenv() and _putenv() to determine if the environment has
  71. * been initialized.
  72. */
  73. extern int __env_initialized;
  74. #endif
  75. /***
  76. *int _putenv(option) - add/replace/remove variable in environment
  77. *
  78. *Purpose:
  79. * option should be of the form "option=value". If a string with the
  80. * given option part already exists, it is replaced with the given
  81. * string; otherwise the given string is added to the environment.
  82. * If the string is of the form "option=", then the string is
  83. * removed from the environment, if it exists. If the string has
  84. * no equals sign, error is returned.
  85. *
  86. *Entry:
  87. * char *option - option string to set in the environment list.
  88. * should be of the form "option=value".
  89. *
  90. *Exit:
  91. * returns 0 if OK, -1 if fails.
  92. *
  93. *Exceptions:
  94. *
  95. *Warning:
  96. * This code will not work if variables are removed from the
  97. * environment by deleting them from environ[]. Use _putenv("option=")
  98. * to remove a variable.
  99. *
  100. *******************************************************************************/
  101. #ifdef _MT
  102. #ifdef WPRFLAG
  103. int __cdecl _wputenv (
  104. #else
  105. int __cdecl _putenv (
  106. #endif
  107. const _TSCHAR *option
  108. )
  109. {
  110. int retval;
  111. _mlock( _ENV_LOCK );
  112. __try {
  113. #ifdef WPRFLAG
  114. retval = _wputenv_lk(option);
  115. #else
  116. retval = _putenv_lk(option);
  117. #endif
  118. }
  119. __finally {
  120. _munlock( _ENV_LOCK );
  121. }
  122. return retval;
  123. }
  124. #ifdef WPRFLAG
  125. int __cdecl _wputenv_lk (
  126. #else
  127. int __cdecl _putenv_lk (
  128. #endif
  129. const _TSCHAR *option
  130. )
  131. #else /* ndef _MT */
  132. #ifdef WPRFLAG
  133. int __cdecl _wputenv (
  134. #else
  135. int __cdecl _putenv (
  136. #endif
  137. const _TSCHAR *option
  138. )
  139. #endif /* _MT */
  140. {
  141. int size;
  142. _TSCHAR * newoption;
  143. #ifndef CRTDLL
  144. /*
  145. * Make sure the environment is initialized.
  146. */
  147. if ( !__env_initialized )
  148. return -1;
  149. #endif /* CRTDLL */
  150. /*
  151. * At startup, we obtain the 'native' flavor of environment strings
  152. * from the OS. So a "main" program has _environ and a "wmain" has
  153. * _wenviron loaded at startup. Only when the user gets or puts the
  154. * 'other' flavor do we convert it.
  155. */
  156. /* copy the new environent string */
  157. if ( (newoption = (_TSCHAR *)_malloc_crt((_tcslen(option)+1) *
  158. sizeof(_TSCHAR))) == NULL )
  159. return -1;
  160. _tcscpy(newoption, option);
  161. #ifdef WPRFLAG
  162. if ( __crtwsetenv(newoption, 1) != 0 )
  163. {
  164. _free_crt(newoption);
  165. return -1;
  166. }
  167. /* If other environment type exists, set it */
  168. if (_environ)
  169. {
  170. char *mboption;
  171. /* find out how much space is needed */
  172. if ( (size = WideCharToMultiByte(CP_ACP, 0, option, -1, NULL,
  173. 0, NULL, NULL)) == 0 )
  174. return -1;
  175. /* allocate space for variable */
  176. if ((mboption = (char *) _malloc_crt(size * sizeof(char))) == NULL)
  177. return -1;
  178. /* convert it */
  179. if ( WideCharToMultiByte(CP_ACP, 0, option, -1, mboption, size,
  180. NULL, NULL) == 0 )
  181. {
  182. _free_crt(mboption);
  183. return -1;
  184. }
  185. /* set it - this is not primary call, so set primary == 0 */
  186. if ( __crtsetenv(mboption, 0) != 0 )
  187. {
  188. _free_crt(mboption);
  189. return -1;
  190. }
  191. }
  192. #else
  193. /* Set requested environment type, primary call */
  194. if ( __crtsetenv(newoption, 1) != 0 )
  195. {
  196. _free_crt(newoption);
  197. return -1;
  198. }
  199. /* If other environment type exists, set it */
  200. if (_wenviron)
  201. {
  202. wchar_t *woption;
  203. /* find out how much space is needed */
  204. if ( (size = MultiByteToWideChar(CP_ACP, 0, option, -1, NULL, 0))
  205. == 0 )
  206. return -1;
  207. /* allocate space for variable */
  208. if ( (woption = (wchar_t *) _malloc_crt(size * sizeof(wchar_t)))
  209. == NULL )
  210. return -1;
  211. /* convert it */
  212. if ( MultiByteToWideChar(CP_ACP, 0, option, -1, woption, size)
  213. == 0 )
  214. {
  215. _free_crt(woption);
  216. return -1;
  217. }
  218. /* set it - this is not primary call, so set primary == 0 */
  219. if ( __crtwsetenv(woption, 0) != 0 )
  220. {
  221. _free_crt(woption);
  222. return -1;
  223. }
  224. }
  225. #endif
  226. return 0;
  227. }
  228. /***
  229. *int findenv(name, len) - [STATIC]
  230. *
  231. *Purpose:
  232. * Scan for the given string within the environment
  233. *
  234. *Entry:
  235. *
  236. *Exit:
  237. * Returns the offset in "environ[]" of the given variable
  238. * Returns the negative of the length of environ[] if not found.
  239. * Returns 0 if the environment is empty.
  240. *
  241. * [NOTE: That a 0 return can mean that the environment is empty
  242. * or that the string was found as the first entry in the array.]
  243. *
  244. *Exceptions:
  245. *
  246. *******************************************************************************/
  247. #ifdef WPRFLAG
  248. static int __cdecl wfindenv (
  249. #else
  250. static int __cdecl findenv (
  251. #endif
  252. const _TSCHAR *name,
  253. int len
  254. )
  255. {
  256. _TSCHAR **env;
  257. for ( env = _tenviron ; *env != NULL ; env++ ) {
  258. /*
  259. * See if first len characters match, up to case
  260. */
  261. if ( _tcsnicoll(name, *env, len) == 0 )
  262. /*
  263. * the next character of the environment string must
  264. * be an '=' or a '\0'
  265. */
  266. if ( (*env)[len] == _T('=') || (*env)[len] == _T('\0') )
  267. return(int)(env - _tenviron);
  268. //
  269. // We cannot break here since findenv must report the total number of strings.
  270. // else
  271. // break;
  272. }
  273. return(-(int)(env - _tenviron));
  274. }
  275. #endif /* _POSIX_ */