tclenv.c
来自「tcl是工具命令语言」· C语言 代码 · 共 781 行 · 第 1/2 页
C
781 行
* 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; } /* * 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((unsigned int) length+2); memcpy((VOID *) string, (VOID *) name, (size_t) length); string[length] = '='; string[length+1] = '\0'; Tcl_UtfToExternalDString(NULL, string, -1, &envString); string = ckrealloc(string, (unsigned) (Tcl_DStringLength(&envString)+1)); strcpy(string, Tcl_DStringValue(&envString)); Tcl_DStringFree(&envString); putenv(string); /* * Watch out for versions of putenv that copy the string (e.g. VC++). * In this case we need to free the string immediately. Otherwise * update the string in the cache. */ if (environ[index] == string) { ReplaceString(oldValue, string); }#else for (envPtr = environ+index+1; ; envPtr++) { envPtr[-1] = *envPtr; if (*envPtr == NULL) { break; } } ReplaceString(oldValue, NULL);#endif Tcl_MutexUnlock(&envMutex);}/* *--------------------------------------------------------------------------- * * TclGetEnv -- * * Retrieve the value of an environment variable. * * Results: * The result is a pointer to a string specifying the value of the * environment variable, or NULL if that environment variable does * not exist. Storage for the result string is allocated in valuePtr; * the caller must call Tcl_DStringFree() when the result is no * longer needed. * * Side effects: * None. * *---------------------------------------------------------------------- */CONST char *TclGetEnv(name, valuePtr) CONST char *name; /* Name of environment variable to find * (UTF-8). */ Tcl_DString *valuePtr; /* Uninitialized or free DString in which * the value of the environment variable is * stored. */{ int length, index; CONST char *result; Tcl_MutexLock(&envMutex); index = TclpFindVariable(name, &length); result = NULL; if (index != -1) { Tcl_DString envStr; result = Tcl_ExternalToUtfDString(NULL, environ[index], -1, &envStr); result += length; if (*result == '=') { result++; Tcl_DStringInit(valuePtr); Tcl_DStringAppend(valuePtr, result, -1); result = Tcl_DStringValue(valuePtr); } else { result = NULL; } Tcl_DStringFree(&envStr); } Tcl_MutexUnlock(&envMutex); return result;}/* *---------------------------------------------------------------------- * * EnvTraceProc -- * * This procedure is invoked whenever an environment variable * is read, modified or deleted. It propagates the change to the global * "environ" 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. */ CONST char *name1; /* Better be "env". */ CONST char *name2; /* Name of variable being modified, or NULL * if whole array is being deleted (UTF-8). */ int flags; /* Indicates what's happening. */{ /* * For array traces, let TclSetupEnv do all the work. */ if (flags & TCL_TRACE_ARRAY) { TclSetupEnv(interp); return NULL; } /* * If name2 is NULL, then return and do nothing. */ if (name2 == NULL) { return NULL; } /* * If a value is being set, call TclSetEnv to do all of the work. */ if (flags & TCL_TRACE_WRITES) { CONST char *value; value = Tcl_GetVar2(interp, "env", name2, TCL_GLOBAL_ONLY); TclSetEnv(name2, value); } /* * If a value is being read, call TclGetEnv to do all of the work. */ if (flags & TCL_TRACE_READS) { Tcl_DString valueString; CONST char *value; value = TclGetEnv(name2, &valueString); if (value == NULL) { return "no such variable"; } Tcl_SetVar2(interp, name1, name2, value, 0); Tcl_DStringFree(&valueString); } /* * For unset traces, let TclUnsetEnv do all the work. */ 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((unsigned) 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] = newStr; environCache[cacheSize+1] = NULL; cacheSize += 5; }}/* *---------------------------------------------------------------------- * * 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 }}#if defined(__CYGWIN__) && defined(__WIN32__)#include <windows.h>/* * When using cygwin, when an environment variable changes, we need to synch * with both the cygwin environment (in case the application C code calls * fork) and the Windows environment (in case the application TCL code calls * exec, which calls the Windows CreateProcess function). */static voidTclCygwinPutenv(str) const char *str;{ char *name, *value; /* Get the name and value, so that we can change the environment variable for Windows. */ name = (char *) alloca (strlen (str) + 1); strcpy (name, str); for (value = name; *value != '=' && *value != '\0'; ++value) ; if (*value == '\0') { /* Can't happen. */ return; } *value = '\0'; ++value; if (*value == '\0') { value = NULL; } /* Set the cygwin environment variable. */#undef putenv if (value == NULL) { unsetenv (name); } else { putenv(str); } /* * Before changing the environment variable in Windows, if this is PATH, * we need to convert the value back to a Windows style path. * * FIXME: The calling program may know it is running under windows, and * may have set the path to a Windows path, or, worse, appended or * prepended a Windows path to PATH. */ if (strcmp (name, "PATH") != 0) { /* If this is Path, eliminate any PATH variable, to prevent any confusion. */ if (strcmp (name, "Path") == 0) { SetEnvironmentVariable ("PATH", (char *) NULL); unsetenv ("PATH"); } SetEnvironmentVariable (name, value); } else { char *buf; /* Eliminate any Path variable, to prevent any confusion. */ SetEnvironmentVariable ("Path", (char *) NULL); unsetenv ("Path"); if (value == NULL) { buf = NULL; } else { int size; size = cygwin_posix_to_win32_path_list_buf_size (value); buf = (char *) alloca (size + 1); cygwin_posix_to_win32_path_list (value, buf); } SetEnvironmentVariable (name, buf); }}#endif /* __CYGWIN__ && __WIN32__ */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?