Attachment "979640-env-hobbs.patch" to
ticket [979640ffff]
added by
hobbs
2005-10-05 15:04:07.
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 <[email protected]>
+
+ * 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 <[email protected]>
* 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.