315 lines
9.4 KiB
C
315 lines
9.4 KiB
C
|
/***
|
||
|
*putenv.c - put an environment variable into the environment
|
||
|
*
|
||
|
* Copyright (c) 1985-2001, Microsoft Corporation. All rights reserved.
|
||
|
*
|
||
|
*Purpose:
|
||
|
* defines _putenv() - adds a new variable to environment; does not
|
||
|
* change global environment, only the process' environment.
|
||
|
*
|
||
|
*Revision History:
|
||
|
* 08-08-84 RN initial version
|
||
|
* 02-23-88 SKS check for environment containing only the NULL string
|
||
|
* 05-31-88 PHG Merged DLL and normal versions
|
||
|
* 07-14-88 JCR Much simplified since (1) __setenvp always uses heap, and
|
||
|
* (2) envp array and env strings are in seperate heap blocks
|
||
|
* 07-03-89 PHG Now "option=" string removes string from environment
|
||
|
* 08-17-89 GJF Removed _NEAR_, _LOAD_DS and fixed indents.
|
||
|
* 09-14-89 KRS Don't give error if 'option' not defined in "option=".
|
||
|
* 11-20-89 GJF Added const to arg type. Also, fixed copyright.
|
||
|
* 03-15-90 GJF Made the calling type _CALLTYPE1, added #include
|
||
|
* <cruntime.h> and removed #include <register.h>.
|
||
|
* 04-05-90 GJF Made findenv() _CALLTYPE4.
|
||
|
* 04-26-90 JCR Bug fix if environ is NULL (stubbed out _setenvp)
|
||
|
* 07-25-90 SBM Removed redundant include (stdio.h)
|
||
|
* 10-04-90 GJF New-style function declarators.
|
||
|
* 01-21-91 GJF ANSI naming.
|
||
|
* 02-06-91 SRW Added _WIN32_ conditional for SetEnvironmentVariable
|
||
|
* 02-18-91 SRW Changed _WIN32_ conditional for SetEnvironmentVariable
|
||
|
* to be in addition to old logic instead of replacement
|
||
|
* 04-23-92 GJF Made findenv insensitive to the case of name for Win32.
|
||
|
* Also added support for 'current drive' environment
|
||
|
* strings in Win32.
|
||
|
* 04-29-92 GJF Repackaged so that _putenv_lk could be easily added for
|
||
|
* for Win32.
|
||
|
* 05-05-92 DJM POSIX not supported.
|
||
|
* 04-06-93 SKS Replace _CRTAPI* with __cdecl
|
||
|
* 06-05-92 PLM Added _MAC_
|
||
|
* 11-24-93 CFW Rip out Cruiser, disallow "=C:=C:\foo" format putenvs.
|
||
|
* 11-29-93 CFW Wide char enable, convert between wide and narrow
|
||
|
* types. Mucho code moved to setenv.c
|
||
|
* 12-07-93 CFW Change _TCHAR to _TSCHAR.
|
||
|
* 01-15-94 CFW Use _tcsnicoll for global match.
|
||
|
* 09-06-94 CFW Replace MTHREAD with _MT.
|
||
|
* 01-10-95 CFW Debug CRT allocs.
|
||
|
* 02-14-95 CFW Debug CRT allocs for Mac version.
|
||
|
* 02-16-95 JWM Spliced _WIN32 & Mac versions.
|
||
|
* 06-01-95 CFW Copy environment string before passing to _crt[w]setenv.
|
||
|
* 07-09-97 GJF Added a check that the environment initialization has
|
||
|
* been executed. Also, cleaned up the format a bit and
|
||
|
* got rid of obsolete _CALLTYPE* macros.
|
||
|
* 03-03-98 RKP Added 64 bit support.
|
||
|
* 03-05-98 GJF Exception-safe locking.
|
||
|
* 08-28-98 GJF Use CP_ACP instead of CP_OEMCP.
|
||
|
* 05-17-99 PML Remove all Macintosh support.
|
||
|
* 05-25-99 GJF Free up buffers allocated to hold env string when there
|
||
|
* there is a failure.
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
#ifndef _POSIX_
|
||
|
|
||
|
#include <windows.h>
|
||
|
#include <cruntime.h>
|
||
|
#include <internal.h>
|
||
|
#include <mtdll.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <tchar.h>
|
||
|
#include <dbgint.h>
|
||
|
|
||
|
#ifndef CRTDLL
|
||
|
|
||
|
/*
|
||
|
* Flag checked by getenv() and _putenv() to determine if the environment has
|
||
|
* been initialized.
|
||
|
*/
|
||
|
extern int __env_initialized;
|
||
|
|
||
|
#endif
|
||
|
|
||
|
/***
|
||
|
*int _putenv(option) - add/replace/remove variable in environment
|
||
|
*
|
||
|
*Purpose:
|
||
|
* option should be of the form "option=value". If a string with the
|
||
|
* given option part already exists, it is replaced with the given
|
||
|
* string; otherwise the given string is added to the environment.
|
||
|
* If the string is of the form "option=", then the string is
|
||
|
* removed from the environment, if it exists. If the string has
|
||
|
* no equals sign, error is returned.
|
||
|
*
|
||
|
*Entry:
|
||
|
* char *option - option string to set in the environment list.
|
||
|
* should be of the form "option=value".
|
||
|
*
|
||
|
*Exit:
|
||
|
* returns 0 if OK, -1 if fails.
|
||
|
*
|
||
|
*Exceptions:
|
||
|
*
|
||
|
*Warning:
|
||
|
* This code will not work if variables are removed from the
|
||
|
* environment by deleting them from environ[]. Use _putenv("option=")
|
||
|
* to remove a variable.
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
#ifdef _MT
|
||
|
|
||
|
#ifdef WPRFLAG
|
||
|
int __cdecl _wputenv (
|
||
|
#else
|
||
|
int __cdecl _putenv (
|
||
|
#endif
|
||
|
const _TSCHAR *option
|
||
|
)
|
||
|
{
|
||
|
int retval;
|
||
|
|
||
|
_mlock( _ENV_LOCK );
|
||
|
|
||
|
__try {
|
||
|
#ifdef WPRFLAG
|
||
|
retval = _wputenv_lk(option);
|
||
|
#else
|
||
|
retval = _putenv_lk(option);
|
||
|
#endif
|
||
|
}
|
||
|
__finally {
|
||
|
_munlock( _ENV_LOCK );
|
||
|
}
|
||
|
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
#ifdef WPRFLAG
|
||
|
int __cdecl _wputenv_lk (
|
||
|
#else
|
||
|
int __cdecl _putenv_lk (
|
||
|
#endif
|
||
|
const _TSCHAR *option
|
||
|
)
|
||
|
|
||
|
#else /* ndef _MT */
|
||
|
|
||
|
#ifdef WPRFLAG
|
||
|
int __cdecl _wputenv (
|
||
|
#else
|
||
|
int __cdecl _putenv (
|
||
|
#endif
|
||
|
const _TSCHAR *option
|
||
|
)
|
||
|
|
||
|
#endif /* _MT */
|
||
|
|
||
|
{
|
||
|
int size;
|
||
|
_TSCHAR * newoption;
|
||
|
|
||
|
#ifndef CRTDLL
|
||
|
/*
|
||
|
* Make sure the environment is initialized.
|
||
|
*/
|
||
|
if ( !__env_initialized )
|
||
|
return -1;
|
||
|
#endif /* CRTDLL */
|
||
|
|
||
|
/*
|
||
|
* At startup, we obtain the 'native' flavor of environment strings
|
||
|
* from the OS. So a "main" program has _environ and a "wmain" has
|
||
|
* _wenviron loaded at startup. Only when the user gets or puts the
|
||
|
* 'other' flavor do we convert it.
|
||
|
*/
|
||
|
|
||
|
/* copy the new environent string */
|
||
|
if ( (newoption = (_TSCHAR *)_malloc_crt((_tcslen(option)+1) *
|
||
|
sizeof(_TSCHAR))) == NULL )
|
||
|
return -1;
|
||
|
|
||
|
_tcscpy(newoption, option);
|
||
|
|
||
|
#ifdef WPRFLAG
|
||
|
if ( __crtwsetenv(newoption, 1) != 0 )
|
||
|
{
|
||
|
_free_crt(newoption);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/* If other environment type exists, set it */
|
||
|
if (_environ)
|
||
|
{
|
||
|
char *mboption;
|
||
|
|
||
|
/* find out how much space is needed */
|
||
|
if ( (size = WideCharToMultiByte(CP_ACP, 0, option, -1, NULL,
|
||
|
0, NULL, NULL)) == 0 )
|
||
|
return -1;
|
||
|
|
||
|
/* allocate space for variable */
|
||
|
if ((mboption = (char *) _malloc_crt(size * sizeof(char))) == NULL)
|
||
|
return -1;
|
||
|
|
||
|
/* convert it */
|
||
|
if ( WideCharToMultiByte(CP_ACP, 0, option, -1, mboption, size,
|
||
|
NULL, NULL) == 0 )
|
||
|
{
|
||
|
_free_crt(mboption);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/* set it - this is not primary call, so set primary == 0 */
|
||
|
if ( __crtsetenv(mboption, 0) != 0 )
|
||
|
{
|
||
|
_free_crt(mboption);
|
||
|
return -1;
|
||
|
}
|
||
|
}
|
||
|
#else
|
||
|
/* Set requested environment type, primary call */
|
||
|
if ( __crtsetenv(newoption, 1) != 0 )
|
||
|
{
|
||
|
_free_crt(newoption);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/* If other environment type exists, set it */
|
||
|
if (_wenviron)
|
||
|
{
|
||
|
wchar_t *woption;
|
||
|
|
||
|
/* find out how much space is needed */
|
||
|
if ( (size = MultiByteToWideChar(CP_ACP, 0, option, -1, NULL, 0))
|
||
|
== 0 )
|
||
|
return -1;
|
||
|
|
||
|
/* allocate space for variable */
|
||
|
if ( (woption = (wchar_t *) _malloc_crt(size * sizeof(wchar_t)))
|
||
|
== NULL )
|
||
|
return -1;
|
||
|
|
||
|
/* convert it */
|
||
|
if ( MultiByteToWideChar(CP_ACP, 0, option, -1, woption, size)
|
||
|
== 0 )
|
||
|
{
|
||
|
_free_crt(woption);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/* set it - this is not primary call, so set primary == 0 */
|
||
|
if ( __crtwsetenv(woption, 0) != 0 )
|
||
|
{
|
||
|
_free_crt(woption);
|
||
|
return -1;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/***
|
||
|
*int findenv(name, len) - [STATIC]
|
||
|
*
|
||
|
*Purpose:
|
||
|
* Scan for the given string within the environment
|
||
|
*
|
||
|
*Entry:
|
||
|
*
|
||
|
*Exit:
|
||
|
* Returns the offset in "environ[]" of the given variable
|
||
|
* Returns the negative of the length of environ[] if not found.
|
||
|
* Returns 0 if the environment is empty.
|
||
|
*
|
||
|
* [NOTE: That a 0 return can mean that the environment is empty
|
||
|
* or that the string was found as the first entry in the array.]
|
||
|
*
|
||
|
*Exceptions:
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
#ifdef WPRFLAG
|
||
|
static int __cdecl wfindenv (
|
||
|
#else
|
||
|
static int __cdecl findenv (
|
||
|
#endif
|
||
|
const _TSCHAR *name,
|
||
|
int len
|
||
|
)
|
||
|
{
|
||
|
_TSCHAR **env;
|
||
|
|
||
|
for ( env = _tenviron ; *env != NULL ; env++ ) {
|
||
|
/*
|
||
|
* See if first len characters match, up to case
|
||
|
*/
|
||
|
if ( _tcsnicoll(name, *env, len) == 0 )
|
||
|
/*
|
||
|
* the next character of the environment string must
|
||
|
* be an '=' or a '\0'
|
||
|
*/
|
||
|
if ( (*env)[len] == _T('=') || (*env)[len] == _T('\0') )
|
||
|
return(int)(env - _tenviron);
|
||
|
//
|
||
|
// We cannot break here since findenv must report the total number of strings.
|
||
|
// else
|
||
|
// break;
|
||
|
}
|
||
|
|
||
|
return(-(int)(env - _tenviron));
|
||
|
}
|
||
|
|
||
|
#endif /* _POSIX_ */
|