From 47dc3dec0ab30187d3502e0c66ed78396aa14672 Mon Sep 17 00:00:00 2001 From: Christopher Faylor Date: Wed, 30 Mar 2005 15:54:28 +0000 Subject: [PATCH] * environ.h (win_env::immediate): Declare new field. (win_env::operator = ): Declare new operator. (win_env::reset): Declare new function. (win_env::~win_env): Declare new destructor. (getwinenv): Add optional third argument to declaration. * environ.cc (conv_envvars): Accommodate immediate field. (win_env::operator =): Define new operator. (win_env::~win_env): Define new destructor. (win_env::add_cache): Add value to environment immediately if "immediate" is set. (getwinenv): Accept optional third argument which will be used to store "cached" values to avoid overwriting real cache. (spenv::force): Declare new field. (spenvs): Accommodate force field. Add "PATH=" with force set to true. (spenv::retrieve): Avoid duping anything if we're not building an envblock. (build_env): Ditto. Use size of potentially constructed new environment block to determine if we need to create an environment block. Pass getwinenv temporary storage to avoid inappropriately overwriting the environment cache. --- winsup/cygwin/ChangeLog | 23 +++++++++ winsup/cygwin/environ.cc | 105 ++++++++++++++++++++++++++++----------- winsup/cygwin/environ.h | 6 ++- 3 files changed, 103 insertions(+), 31 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index aa28ca4dc..21331b37c 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,26 @@ +2005-03-30 Christopher Faylor + + * environ.h (win_env::immediate): Declare new field. + (win_env::operator = ): Declare new operator. + (win_env::reset): Declare new function. + (win_env::~win_env): Declare new destructor. + (getwinenv): Add optional third argument to declaration. + * environ.cc (conv_envvars): Accommodate immediate field. + (win_env::operator =): Define new operator. + (win_env::~win_env): Define new destructor. + (win_env::add_cache): Add value to environment immediately if + "immediate" is set. + (getwinenv): Accept optional third argument which will be used to store + "cached" values to avoid overwriting real cache. + (spenv::force): Declare new field. + (spenvs): Accommodate force field. Add "PATH=" with force set to true. + (spenv::retrieve): Avoid duping anything if we're not building an + envblock. + (build_env): Ditto. Use size of potentially constructed new + environment block to determine if we need to create an environment + block. Pass getwinenv temporary storage to avoid inappropriately + overwriting the environment cache. + 2005-03-29 Eric Blake * include/limits.h (NAME_MAX): New define. diff --git a/winsup/cygwin/environ.cc b/winsup/cygwin/environ.cc index 6bb3ae971..db8c6d171 100644 --- a/winsup/cygwin/environ.cc +++ b/winsup/cygwin/environ.cc @@ -59,22 +59,43 @@ static win_env conv_envvars[] = {NL ("PATH="), NULL, NULL, cygwin_win32_to_posix_path_list, cygwin_posix_to_win32_path_list, cygwin_win32_to_posix_path_list_buf_size, - cygwin_posix_to_win32_path_list_buf_size}, + cygwin_posix_to_win32_path_list_buf_size, true}, {NL ("HOME="), NULL, NULL, cygwin_conv_to_full_posix_path, - cygwin_conv_to_full_win32_path, return_MAX_PATH, return_MAX_PATH}, + cygwin_conv_to_full_win32_path, return_MAX_PATH, return_MAX_PATH, false}, {NL ("LD_LIBRARY_PATH="), NULL, NULL, cygwin_conv_to_full_posix_path, - cygwin_conv_to_full_win32_path, return_MAX_PATH, return_MAX_PATH}, + cygwin_conv_to_full_win32_path, return_MAX_PATH, return_MAX_PATH, true}, {NL ("TMPDIR="), NULL, NULL, cygwin_conv_to_full_posix_path, - cygwin_conv_to_full_win32_path, return_MAX_PATH, return_MAX_PATH}, + cygwin_conv_to_full_win32_path, return_MAX_PATH, return_MAX_PATH, false}, {NL ("TMP="), NULL, NULL, cygwin_conv_to_full_posix_path, - cygwin_conv_to_full_win32_path, return_MAX_PATH, return_MAX_PATH}, + cygwin_conv_to_full_win32_path, return_MAX_PATH, return_MAX_PATH, false}, {NL ("TEMP="), NULL, NULL, cygwin_conv_to_full_posix_path, - cygwin_conv_to_full_win32_path, return_MAX_PATH, return_MAX_PATH}, + cygwin_conv_to_full_win32_path, return_MAX_PATH, return_MAX_PATH, false}, {NULL, 0, NULL, NULL, NULL, NULL, 0, 0} }; static unsigned char conv_start_chars[256] = {0}; +struct win_env& +win_env::operator = (struct win_env& x) +{ + name = x.name; + namelen = x.namelen; + toposix = x.toposix; + towin32 = x.towin32; + posix_len = x.posix_len; + win32_len = x.win32_len; + immediate = false; + return *this; +} + +win_env::~win_env () +{ + if (posix) + free (posix); + if (native) + free (native); +} + void win_env::add_cache (const char *in_posix, const char *in_native) { @@ -94,6 +115,14 @@ win_env::add_cache (const char *in_posix, const char *in_native) towin32 (in_posix, native + namelen); } MALLOC_CHECK; + if (immediate) + { + char s[namelen]; + size_t n = namelen - 1; + memcpy (s, name, n); + s[n] = '\0'; + SetEnvironmentVariable (s, native + namelen); + } debug_printf ("posix %s", posix); debug_printf ("native %s", native); } @@ -104,7 +133,7 @@ win_env::add_cache (const char *in_posix, const char *in_native) known posix value for the environment variable. Returns a pointer to the appropriate conversion structure. */ win_env * __stdcall -getwinenv (const char *env, const char *in_posix) +getwinenv (const char *env, const char *in_posix, win_env *temp) { if (!conv_start_chars[(unsigned char)*env]) return NULL; @@ -112,13 +141,20 @@ getwinenv (const char *env, const char *in_posix) for (int i = 0; conv_envvars[i].name != NULL; i++) if (strncmp (env, conv_envvars[i].name, conv_envvars[i].namelen) == 0) { - win_env * const we = conv_envvars + i; + win_env *we = conv_envvars + i; const char *val; if (!cur_environ () || !(val = in_posix ?: getenv (we->name))) debug_printf ("can't set native for %s since no environ yet", we->name); else if (!envcache || !we->posix || strcmp (val, we->posix) != 0) - we->add_cache (val); + { + if (temp) + { + *temp = *we; + we = temp; + } + we->add_cache (val); + } return we; } return NULL; @@ -825,6 +861,7 @@ struct spenv const char *name; size_t namelen; bool add_always; /* If true, always add to env if missing */ + bool force; /* if true, retrieve value from cache */ const char * (cygheap_user::*from_cygheap) (const char *, size_t); char *retrieve (bool, const char * const = NULL) @@ -836,20 +873,21 @@ struct spenv /* Keep this list in upper case and sorted */ static NO_COPY spenv spenvs[] = { - {NL ("HOMEDRIVE="), false, &cygheap_user::env_homedrive}, - {NL ("HOMEPATH="), false, &cygheap_user::env_homepath}, - {NL ("LOGONSERVER="), false, &cygheap_user::env_logsrv}, - {NL ("SYSTEMDRIVE="), false, NULL}, - {NL ("SYSTEMROOT="), true, &cygheap_user::env_systemroot}, - {NL ("USERDOMAIN="), false, &cygheap_user::env_domain}, - {NL ("USERNAME="), false, &cygheap_user::env_name}, - {NL ("USERPROFILE="), false, &cygheap_user::env_userprofile}, + {NL ("HOMEDRIVE="), false, false, &cygheap_user::env_homedrive}, + {NL ("HOMEPATH="), false, false, &cygheap_user::env_homepath}, + {NL ("LOGONSERVER="), false, false, &cygheap_user::env_logsrv}, + {NL ("PATH="), false, true, NULL}, + {NL ("SYSTEMDRIVE="), false, false, NULL}, + {NL ("SYSTEMROOT="), true, false, &cygheap_user::env_systemroot}, + {NL ("USERDOMAIN="), false, false, &cygheap_user::env_domain}, + {NL ("USERNAME="), false, false, &cygheap_user::env_name}, + {NL ("USERPROFILE="), false, false, &cygheap_user::env_userprofile} }; char * -spenv::retrieve (bool no_envblock, const char *const envname) +spenv::retrieve (bool no_envblock, const char *const env) { - if (envname && !strncasematch (envname, name, namelen)) + if (env && !strncasematch (env, name, namelen)) return NULL; debug_printf ("no_envblock %d", no_envblock); @@ -857,16 +895,16 @@ spenv::retrieve (bool no_envblock, const char *const envname) if (from_cygheap) { const char *p; - if (envname && !cygheap->user.issetuid ()) + if (env && !cygheap->user.issetuid ()) { debug_printf ("duping existing value for '%s'", name); - return cstrdup1 (envname); /* Don't really care what it's set to - if we're calling a cygwin program */ + /* Don't really care what it's set to if we're calling a cygwin program */ + return (no_envblock && !force) ? env_dontadd : cstrdup1 (env); } /* Calculate (potentially) value for given environment variable. */ p = (cygheap->user.*from_cygheap) (name, namelen); - if (!p || (no_envblock && !envname) || (p == env_dontadd)) + if (!p || (p == env_dontadd) || (!force && (no_envblock && !env))) return env_dontadd; char *s = (char *) cmalloc (HEAP_1_STR, namelen + strlen (p) + 1); strcpy (s, name); @@ -875,8 +913,10 @@ spenv::retrieve (bool no_envblock, const char *const envname) return s; } - if (envname) - return cstrdup1 (envname); + if (!force && no_envblock) + return env_dontadd; + if (env) + return cstrdup1 (env); return getwinenveq (name, namelen, HEAP_1_STR); } @@ -916,11 +956,13 @@ build_env (const char * const *envp, char *&envblock, int &envc, if (!saw_spenv[i] && (*dstp = spenvs[i].retrieve (no_envblock, *srcp))) { saw_spenv[i] = 1; - if (*dstp == env_dontadd) - goto next1; - goto next0; + if (*dstp != env_dontadd) + goto next0; + goto next1; } + if (no_envblock) + goto next1; /* Add entry to new environment */ *dstp = cstrdup1 (*srcp); @@ -950,11 +992,13 @@ build_env (const char * const *envp, char *&envblock, int &envc, assert ((size_t) envc <= (n + SPENVS_SIZE)); *dstp = NULL; /* Terminate */ - if (no_envblock) + if (!envc) envblock = NULL; else { debug_printf ("env count %d, bytes %d", envc, tl); + win_env temp; + temp.reset (); /* Windows programs expect the environment block to be sorted. */ qsort (newenv, envc, sizeof (char *), env_sort); @@ -978,7 +1022,7 @@ build_env (const char * const *envp, char *&envblock, int &envc, continue; /* See if this entry requires posix->win32 conversion. */ - conv = getwinenv (*srcp, *srcp + len); + conv = getwinenv (*srcp, *srcp + len, &temp); if (conv) p = conv->native; /* Use win32 path */ else @@ -1017,6 +1061,7 @@ build_env (const char * const *envp, char *&envblock, int &envc, of buffer */ } + debug_printf ("envp %p, envc %d", newenv, envc); return newenv; } diff --git a/winsup/cygwin/environ.h b/winsup/cygwin/environ.h index f6a1797ad..b953148b4 100644 --- a/winsup/cygwin/environ.h +++ b/winsup/cygwin/environ.h @@ -27,13 +27,17 @@ struct win_env int (*towin32) (const char *, char *); int (*posix_len) (const char *); int (*win32_len) (const char *); + bool immediate; void add_cache (const char *in_posix, const char *in_native = NULL) __attribute__ ((regparm (3))); const char * get_native () const {return native ? native + namelen : NULL;} const char * get_posix () const {return posix ? posix : NULL;} + struct win_env& operator = (struct win_env& x); + void reset () {native = posix = NULL;} + ~win_env (); }; -win_env * __stdcall getwinenv (const char *name, const char *posix = NULL) +win_env * __stdcall getwinenv (const char *name, const char *posix = NULL, win_env * = NULL) __attribute__ ((regparm (3))); char * __stdcall getwinenveq (const char *name, size_t len, int) __attribute__ ((regparm (3)));