211 lines
5.1 KiB
C
211 lines
5.1 KiB
C
/***
|
|
*putenv.c - put an environment variable into the environment
|
|
*
|
|
* Copyright (c) 1985-1990, 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
|
|
* 09-14-89 KRS Don't give error if 'option' not defined in "option=".
|
|
* 09-25-89 GJF Fixed copyright, indents. Build with -G[w|W] for Win
|
|
* 3.0 libs.
|
|
* 10-24-89 GJF Added const attribute to type of option.
|
|
* 03-29-90 JCR Bug fix if environ is NULL (stubbed out _setenvp)
|
|
*
|
|
*******************************************************************************/
|
|
|
|
#include "nmake.h"
|
|
#include "nmmsg.h"
|
|
#include "proto.h"
|
|
#include "globals.h"
|
|
#include "grammar.h"
|
|
|
|
#include <register.h>
|
|
#include <internal.h>
|
|
#include <os2dll.h>
|
|
|
|
static int _NEAR_ findenv(const char *name, int len);
|
|
|
|
/***
|
|
*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.
|
|
*
|
|
*******************************************************************************/
|
|
|
|
//Modified to be near and name changed to PutEnv() -Sundeep-
|
|
int _LOAD_DS _NEAR_ PutEnv (option)
|
|
REG3 const char *option;
|
|
{
|
|
#ifdef FLAT
|
|
return (_putenv(option));
|
|
#else
|
|
REG1 char **env;
|
|
REG4 const char *equal;
|
|
REG2 int ix;
|
|
int remove; /* 1 means remove string from environment */
|
|
|
|
if (!option)
|
|
return(-1);
|
|
|
|
_mlock( _ENV_LOCK );
|
|
|
|
/* find the equal sign to delimit the name being searched for.
|
|
* If no equal sign, then return error
|
|
*/
|
|
|
|
for (equal = option; *equal != '='; equal++)
|
|
if (*equal == '\0')
|
|
goto unlock_error;
|
|
|
|
/* see if removing or adding */
|
|
remove = (equal[1] == '\0');
|
|
|
|
#ifdef _WINDOWS
|
|
/* see if environ array exists (too late to change C6) */
|
|
if (environ == NULL) {
|
|
if (remove)
|
|
goto unlock_good;
|
|
else {
|
|
/* get an array and init it to NULL */
|
|
if ( (environ = malloc(sizeof(void *))) == NULL)
|
|
goto unlock_error;
|
|
*environ = NULL;
|
|
}
|
|
}
|
|
#endif
|
|
/* init env pointer */
|
|
|
|
env = environ;
|
|
|
|
/* See if the string is already in the environment */
|
|
|
|
ix = findenv(option, equal - option);
|
|
|
|
if ((ix >= 0) && (*env != NULL)) {
|
|
/* String is already in the environment -- overwrite/remove it.
|
|
*/
|
|
if (remove) {
|
|
/* removing -- move all the later strings up */
|
|
for ( ; env[ix] != NULL; ++ix) {
|
|
env[ix] = env[ix+1];
|
|
}
|
|
|
|
/* shrink the environment memory block
|
|
(ix now has number of strings, including NULL) --
|
|
this realloc probably can't fail, since we're
|
|
shrinking a mem block, but we're careful anyway. */
|
|
if (env = (char **) realloc(env, ix * sizeof(char *)))
|
|
environ = env;
|
|
}
|
|
else {
|
|
//Add this free call -Sundeep-
|
|
free(env[ix]);
|
|
/* replace the option */
|
|
env[ix] = (char *) option;
|
|
}
|
|
}
|
|
else {
|
|
/* String is NOT in the environment */
|
|
if (!remove) { /* can't remove something that's not there */
|
|
|
|
/* Grow vector table by one */
|
|
if (ix < 0)
|
|
ix = -ix; /* ix = length of environ table */
|
|
|
|
if (!(env = (char **)realloc(env, sizeof(char *) *
|
|
(ix + 2))))
|
|
goto unlock_error;
|
|
|
|
env[ix] = (char *)option;
|
|
env[ix + 1] = NULL;
|
|
environ = env;
|
|
}
|
|
}
|
|
|
|
#ifdef _WINDOWS
|
|
unlock_good:
|
|
#endif
|
|
_munlock( _ENV_LOCK );
|
|
return(0);
|
|
|
|
unlock_error:
|
|
_munlock( _ENV_LOCK );
|
|
return -1;
|
|
#endif
|
|
}
|
|
|
|
|
|
#ifndef FLAT
|
|
|
|
/***
|
|
*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:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
static int _NEAR_ findenv(const char *name, int len)
|
|
{
|
|
REG4 char **env = environ;
|
|
REG2 const char *nm;
|
|
REG1 char *envname;
|
|
REG3 int l;
|
|
|
|
while (envname = *env) {
|
|
nm = name;
|
|
l = len;
|
|
while (l && *envname++ == *nm++)
|
|
l--;
|
|
|
|
if (l == 0 && ( *envname == '=' || !*envname ) )
|
|
return(env - environ);
|
|
env++;
|
|
}
|
|
return(-(env - environ));
|
|
}
|
|
|
|
#endif
|