diff options
-rw-r--r-- | ChangeLog | 11 | ||||
-rw-r--r-- | generic/tclEnv.c | 45 | ||||
-rw-r--r-- | win/tclWinPort.h | 5 |
3 files changed, 46 insertions, 15 deletions
@@ -1,3 +1,14 @@ +2005-10-05 Jeff Hobbs <jeffh@ActiveState.com> + + * win/tclWinPort.h: define USE_PUTENV_FOR_UNSET 1 + * generic/tclEnv.c (TclSetEnv, TclUnsetEnv): add + USE_PUTENV_FOR_UNSET to existing USE_PUTENV define to account for + various systems that have putenv(), but can't unset env vars with + it. Note difference between Windows and Linux for actually + unsetting the env var (use of '='). + Correct the resizing of the environ array. We assume that we are + in full ownership, but that's not correct.[Bug 979640] + 2005-10-04 Jeff Hobbs <jeffh@ActiveState.com> * win/tclWinSerial.c (SerialSetOptionProc): free argv [Bug 1067708] diff --git a/generic/tclEnv.c b/generic/tclEnv.c index 1e171ff..947d397 100644 --- a/generic/tclEnv.c +++ b/generic/tclEnv.c @@ -12,7 +12,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclEnv.c,v 1.20.2.1 2003/05/14 17:17:46 hobbs Exp $ + * RCS: @(#) $Id: tclEnv.c,v 1.20.2.2 2005/10/05 08:02:20 hobbs Exp $ */ #include "tclInt.h" @@ -26,6 +26,11 @@ static char **environCache = NULL; * strings that Tcl has allocated. */ #ifndef USE_PUTENV +static char **ourEnviron = NULL;/* Cache of the array that we allocate. + * We need to track this in case another + * subsystem swaps around the environ array + * like we do. + */ static int environSize = 0; /* Non-zero means that the environ array was * malloced and has this many total entries * allocated to it (not all may be in use at @@ -191,17 +196,22 @@ TclSetEnv(name, value) if (index == -1) { #ifndef USE_PUTENV - if ((length + 2) > environSize) { + /* + * We need to handle the case where the environment may be changed + * outside our control. environSize is only valid if the current + * environment is the one we allocated. [Bug 979640] + */ + if ((ourEnviron != environ) || ((length + 2) > environSize)) { char **newEnviron; newEnviron = (char **) ckalloc((unsigned) ((length + 5) * sizeof(char *))); memcpy((VOID *) newEnviron, (VOID *) environ, length*sizeof(char *)); - if (environSize != 0) { - ckfree((char *) environ); + if ((environSize != 0) && (ourEnviron != NULL)) { + ckfree((char *) ourEnviron); } - environ = newEnviron; + environ = ourEnviron = newEnviron; environSize = length + 5; #if defined(__APPLE__) && defined(__DYNAMIC__) { @@ -237,7 +247,6 @@ TclSetEnv(name, value) oldValue = environ[index]; nameLength = length; } - /* * Create a new entry. Build a complete UTF string that contains @@ -378,7 +387,7 @@ TclUnsetEnv(name) char *oldValue; int length; int index; -#ifdef USE_PUTENV +#ifdef USE_PUTENV_FOR_UNSET Tcl_DString envString; char *string; #else @@ -392,7 +401,7 @@ TclUnsetEnv(name) * First make sure that the environment variable exists to avoid * doing needless work and to avoid recursion on the unset. */ - + if (index == -1) { Tcl_MutexUnlock(&envMutex); return; @@ -408,12 +417,22 @@ TclUnsetEnv(name) * update the interpreters or we will recurse. */ -#ifdef USE_PUTENV +#ifdef USE_PUTENV_FOR_UNSET + /* + * For those platforms that support putenv to unset, Linux indicates + * that no = should be included, and Windows requires it. + */ +#ifdef WIN32 string = ckalloc((unsigned int) length+2); memcpy((VOID *) string, (VOID *) name, (size_t) length); string[length] = '='; string[length+1] = '\0'; - +#else + string = ckalloc((unsigned int) length+1); + memcpy((VOID *) string, (VOID *) name, (size_t) length); + string[length] = '\0'; +#endif + Tcl_UtfToExternalDString(NULL, string, -1, &envString); string = ckrealloc(string, (unsigned) (Tcl_DStringLength(&envString)+1)); strcpy(string, Tcl_DStringValue(&envString)); @@ -633,7 +652,7 @@ ReplaceString(oldStr, newStr) if (environCache[i]) { ckfree(environCache[i]); } - + if (newStr) { environCache[i] = newStr; } else { @@ -642,7 +661,7 @@ ReplaceString(oldStr, newStr) } environCache[cacheSize-1] = NULL; } - } else { + } else { int allocatedSize = (cacheSize + 5) * sizeof(char *); /* @@ -651,7 +670,7 @@ ReplaceString(oldStr, newStr) newCache = (char **) ckalloc((unsigned) allocatedSize); (VOID *) memset(newCache, (int) 0, (size_t) allocatedSize); - + if (environCache) { memcpy((VOID *) newCache, (VOID *) environCache, (size_t) (cacheSize * sizeof(char*))); diff --git a/win/tclWinPort.h b/win/tclWinPort.h index c553ea6..47545ba 100644 --- a/win/tclWinPort.h +++ b/win/tclWinPort.h @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclWinPort.h,v 1.36 2002/11/27 18:13:38 davygrvy Exp $ + * RCS: @(#) $Id: tclWinPort.h,v 1.36.2.1 2005/10/05 08:02:20 hobbs Exp $ */ #ifndef _TCLWINPORT @@ -423,7 +423,8 @@ * the C level environment in synch with the system level environment. */ -#define USE_PUTENV 1 +#define USE_PUTENV 1 +#define USE_PUTENV_FOR_UNSET 1 /* * Msvcrt's putenv() copies the string rather than takes ownership of it. |