Index: ChangeLog
===================================================================
RCS file: /cvsroot/tcl/tcl/ChangeLog,v
retrieving revision 1.1453.2.522
diff -u -r1.1453.2.522 ChangeLog
--- ChangeLog	5 Oct 2005 06:33:51 -0000	1.1453.2.522
+++ ChangeLog	5 Oct 2005 08:01:54 -0000
@@ -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]
Index: generic/tclEnv.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclEnv.c,v
retrieving revision 1.20.2.1
diff -u -r1.20.2.1 tclEnv.c
--- generic/tclEnv.c	14 May 2003 17:17:46 -0000	1.20.2.1
+++ generic/tclEnv.c	5 Oct 2005 08:01:54 -0000
@@ -26,6 +26,11 @@
 				 * 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 @@
 
     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 @@
 	oldValue = environ[index];
 	nameLength = length;
     }
-	
 
     /*
      * Create a new entry.  Build a complete UTF string that contains
@@ -378,7 +387,7 @@
     char *oldValue;
     int length;
     int index;
-#ifdef USE_PUTENV
+#ifdef USE_PUTENV_FOR_UNSET
     Tcl_DString envString;
     char *string;
 #else
@@ -392,7 +401,7 @@
      * 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 @@
      * 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 @@
 	if (environCache[i]) {
 	    ckfree(environCache[i]);
 	}
-	    
+
 	if (newStr) {
 	    environCache[i] = newStr;
 	} else {
@@ -642,7 +661,7 @@
 	    }
 	    environCache[cacheSize-1] = NULL;
 	}
-    } else {	
+    } else {
         int allocatedSize = (cacheSize + 5) * sizeof(char *);
 
 	/*
@@ -651,7 +670,7 @@
 
 	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*)));
Index: win/tclWinPort.h
===================================================================
RCS file: /cvsroot/tcl/tcl/win/tclWinPort.h,v
retrieving revision 1.36
diff -u -r1.36 tclWinPort.h
--- win/tclWinPort.h	27 Nov 2002 18:13:38 -0000	1.36
+++ win/tclWinPort.h	5 Oct 2005 08:01:54 -0000
@@ -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.
