📄 tclenv.c
字号:
* Interpreters are updated, as is environ. * *---------------------------------------------------------------------- */voidTclUnsetEnv(name) CONST char *name; /* Name of variable to remove. */{ EnvInterp *eiPtr; char *oldValue; int length, index;#ifdef USE_PUTENV char *string;#else char **envPtr;#endif#ifdef MAC_TCL if (environ == NULL) { environSize = TclMacCreateEnv(); }#endif index = FindVariable(name, &length); /* * First make sure that the environment variable exists to avoid * doing needless work and to avoid recursion on the unset. */ if (index == -1) { return; } /* * Remember the old value so we can free it if Tcl created the string. */ oldValue = environ[index]; /* * Update the system environment. This must be done before we * update the interpreters or we will recurse. */#ifdef USE_PUTENV string = ckalloc(length+2); memcpy((VOID *) string, (VOID *) name, (size_t) length); string[length] = '='; string[length+1] = '\0'; putenv(string); ckfree(string);#else for (envPtr = environ+index+1; ; envPtr++) { envPtr[-1] = *envPtr; if (*envPtr == NULL) { break; } }#endif /* * Replace the old value in the cache. */ ReplaceString(oldValue, NULL); /* * Update all of the interpreters. */ for (eiPtr = firstInterpPtr; eiPtr != NULL; eiPtr = eiPtr->nextPtr) { (void) Tcl_UnsetVar2(eiPtr->interp, "env", (char *) name, TCL_GLOBAL_ONLY); }}/* *---------------------------------------------------------------------- * * TclGetEnv -- * * Retrieve the value of an environment variable. * * Results: * Returns a pointer to a static string in the environment, * or NULL if the value was not found. * * Side effects: * None. * *---------------------------------------------------------------------- */char *TclGetEnv(name) CONST char *name; /* Name of variable to find. */{ int length, index;#ifdef MAC_TCL if (environ == NULL) { environSize = TclMacCreateEnv(); }#endif index = FindVariable(name, &length); if ((index != -1) && (*(environ[index]+length) == '=')) { return environ[index]+length+1; } else { return NULL; }}/* *---------------------------------------------------------------------- * * EnvTraceProc -- * * This procedure is invoked whenever an environment variable * is modified or deleted. It propagates the change to the * "environ" array and to any other interpreters for whom * we're managing an "env" array. * * Results: * Always returns NULL to indicate success. * * Side effects: * Environment variable changes get propagated. If the whole * "env" array is deleted, then we stop managing things for * this interpreter (usually this happens because the whole * interpreter is being deleted). * *---------------------------------------------------------------------- */ /* ARGSUSED */static char *EnvTraceProc(clientData, interp, name1, name2, flags) ClientData clientData; /* Not used. */ Tcl_Interp *interp; /* Interpreter whose "env" variable is * being modified. */ char *name1; /* Better be "env". */ char *name2; /* Name of variable being modified, or * NULL if whole array is being deleted. */ int flags; /* Indicates what's happening. */{ /* * First see if the whole "env" variable is being deleted. If * so, just forget about this interpreter. */ if (name2 == NULL) { register EnvInterp *eiPtr, *prevPtr; if ((flags & (TCL_TRACE_UNSETS|TCL_TRACE_DESTROYED)) != (TCL_TRACE_UNSETS|TCL_TRACE_DESTROYED)) { panic("EnvTraceProc called with confusing arguments"); } eiPtr = firstInterpPtr; if (eiPtr->interp == interp) { firstInterpPtr = eiPtr->nextPtr; } else { for (prevPtr = eiPtr, eiPtr = eiPtr->nextPtr; ; prevPtr = eiPtr, eiPtr = eiPtr->nextPtr) { if (eiPtr == NULL) { panic("EnvTraceProc couldn't find interpreter"); } if (eiPtr->interp == interp) { prevPtr->nextPtr = eiPtr->nextPtr; break; } } } ckfree((char *) eiPtr); return NULL; } /* * If a value is being set, call TclSetEnv to do all of the work. */ if (flags & TCL_TRACE_WRITES) { TclSetEnv(name2, Tcl_GetVar2(interp, "env", name2, TCL_GLOBAL_ONLY)); } if (flags & TCL_TRACE_UNSETS) { TclUnsetEnv(name2); } return NULL;}/* *---------------------------------------------------------------------- * * ReplaceString -- * * Replace one string with another in the environment variable * cache. The cache keeps track of all of the environment * variables that Tcl has modified so they can be freed later. * * Results: * None. * * Side effects: * May free the old string. * *---------------------------------------------------------------------- */static voidReplaceString(oldStr, newStr) CONST char *oldStr; /* Old environment string. */ char *newStr; /* New environment string. */{ int i; char **newCache; /* * Check to see if the old value was allocated by Tcl. If so, * it needs to be deallocated to avoid memory leaks. Note that this * algorithm is O(n), not O(1). This will result in n-squared behavior * if lots of environment changes are being made. */ for (i = 0; i < cacheSize; i++) { if ((environCache[i] == oldStr) || (environCache[i] == NULL)) { break; } } if (i < cacheSize) { /* * Replace or delete the old value. */ if (environCache[i]) { ckfree(environCache[i]); } if (newStr) { environCache[i] = newStr; } else { for (; i < cacheSize-1; i++) { environCache[i] = environCache[i+1]; } environCache[cacheSize-1] = NULL; } } else { int allocatedSize = (cacheSize + 5) * sizeof(char *); /* * We need to grow the cache in order to hold the new string. */ newCache = (char **) ckalloc((size_t) allocatedSize); (VOID *) memset(newCache, (int) 0, (size_t) allocatedSize); if (environCache) { memcpy((VOID *) newCache, (VOID *) environCache, (size_t) (cacheSize * sizeof(char*))); ckfree((char *) environCache); } environCache = newCache; environCache[cacheSize] = (char *) newStr; environCache[cacheSize+1] = NULL; cacheSize += 5; }}/* *---------------------------------------------------------------------- * * FindVariable -- * * Locate the entry in environ for a given name. * * Results: * The return value is the index in environ of an entry with the * name "name", or -1 if there is no such entry. The integer at * *lengthPtr is filled in with the length of name (if a matching * entry is found) or the length of the environ array (if no matching * entry is found). * * Side effects: * None. * *---------------------------------------------------------------------- */static intFindVariable(name, lengthPtr) CONST char *name; /* Name of desired environment variable. */ int *lengthPtr; /* Used to return length of name (for * successful searches) or number of non-NULL * entries in environ (for unsuccessful * searches). */{ int i; register CONST char *p1, *p2; for (i = 0, p1 = environ[i]; p1 != NULL; i++, p1 = environ[i]) { for (p2 = name; *p2 == *p1; p1++, p2++) { /* NULL loop body. */ } if ((*p1 == '=') && (*p2 == '\0')) { *lengthPtr = p2-name; return i; } } *lengthPtr = i; return -1;}/* *---------------------------------------------------------------------- * * TclFinalizeEnvironment -- * * This function releases any storage allocated by this module * that isn't still in use by the global environment. Any * strings that are still in the environment will be leaked. * * Results: * None. * * Side effects: * May deallocate storage. * *---------------------------------------------------------------------- */voidTclFinalizeEnvironment(){ /* * For now we just deallocate the cache array and none of the environment * strings. This may leak more memory that strictly necessary, since some * of the strings may no longer be in the environment. However, * determining which ones are ok to delete is n-squared, and is pretty * unlikely, so we don't bother. */ if (environCache) { ckfree((char *) environCache); environCache = NULL; cacheSize = 0;#ifndef USE_PUTENV environSize = 0;#endif }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -