diff options
Diffstat (limited to 'winsup/cygwin/environ.cc')
-rw-r--r-- | winsup/cygwin/environ.cc | 188 |
1 files changed, 118 insertions, 70 deletions
diff --git a/winsup/cygwin/environ.cc b/winsup/cygwin/environ.cc index 8b15c1c08..357af7717 100644 --- a/winsup/cygwin/environ.cc +++ b/winsup/cygwin/environ.cc @@ -195,13 +195,12 @@ getenv (const char *name) return my_findenv (name, &offset); } -extern int __stdcall -envsize (const char * const *in_envp, int debug_print) +static int __stdcall +envsize (const char * const *in_envp) { const char * const *envp; for (envp = in_envp; *envp; envp++) - if (debug_print) - debug_printf ("%s", *envp); + continue; return (1 + envp - in_envp) * sizeof (const char *); } @@ -673,6 +672,8 @@ environ_init (char **envp, int envc) envp_passed_in = 0; else { + envc++; + envc *= sizeof (char *); char **newenv = (char **) malloc (envc); memcpy (newenv, envp, envc); cfree (envp); @@ -749,107 +750,154 @@ env_sort (const void *a, const void *b) return strcmp (*p, *q); } +struct spenv +{ + const char *name; + const char * (cygheap_user::*from_cygheap) (); + char *retrieve (bool, const char * const = NULL, int = 0); +}; + /* Keep this list in upper case and sorted */ -static const NO_COPY char* forced_winenv_vars [] = - { - "SYSTEMDRIVE", - "SYSTEMROOT", - NULL - }; +static NO_COPY spenv spenvs[] = +{ + {"HOMEPATH=", &cygheap_user::env_homepath}, + {"HOMEDRIVE=", &cygheap_user::env_homedrive}, + {"LOGONSERVER=", &cygheap_user::env_logsrv}, + {"SYSTEMDRIVE=", NULL}, + {"SYSTEMROOT=", NULL}, + {"USERPROFILE=", &cygheap_user::env_userprofile}, +}; + +char * +spenv::retrieve (bool no_envblock, const char *const envname, int len) +{ + if (len && !strncasematch (envname, name, len)) + return NULL; + if (from_cygheap) + { + const char *p; + if (!len) + return NULL; /* No need to force these into the + environment */ + + if (no_envblock) + return cstrdup1 (envname); /* Don't really care what it's set to + if we're calling a cygwin program */ + + /* Make a FOO=BAR entry from the value returned by the cygheap_user + method. */ + p = (cygheap->user.*from_cygheap) (); + int namelen = strlen (name); + char *s = (char *) cmalloc (HEAP_1_STR, namelen + strlen (p) + 1); + strcpy (s, name); + (void) strcpy (s + namelen, p); + return s; + } + + if (len) + return cstrdup1 (envname); + + char dum[1]; + int vallen = GetEnvironmentVariable (name, dum, 0); + if (vallen > 0) + { + int namelen = strlen (name); + char *p = (char *) cmalloc (HEAP_1_STR, namelen + ++vallen); + strcpy (p, name); + if (GetEnvironmentVariable (name, p + namelen, vallen)) + return p; + else + cfree (p); + } + + debug_printf ("warning: %s not present in environment", name); + return NULL; +} -#define FORCED_WINENV_SIZE (sizeof (forced_winenv_vars) / sizeof (forced_winenv_vars[0])) +#define SPENVS_SIZE (sizeof (spenvs) / sizeof (spenvs[0])) /* Create a Windows-style environment block, i.e. a typical character buffer filled with null terminated strings, terminated by double null characters. Converts environment variables noted in conv_envvars into win32 form prior to placing them in the string. */ -char * __stdcall -winenv (const char * const *envp, int keep_posix) +char ** __stdcall +build_env (const char * const *envp, char *&envblock, int &envc, + bool no_envblock) { int len, n, tl; const char * const *srcp; - const char **dstp; - bool saw_forced_winenv[FORCED_WINENV_SIZE] = {0}; - char *p; + char **dstp; + bool saw_spenv[SPENVS_SIZE] = {0}; - debug_printf ("envp %p, keep_posix %d", envp, keep_posix); + debug_printf ("envp %p", envp); tl = 0; for (n = 0; envp[n]; n++) continue; - const char *newenvp[n + 1 + FORCED_WINENV_SIZE]; + char **newenv = (char **) cmalloc (HEAP_1_ARGV, sizeof (char *) * (n + SPENVS_SIZE + 1)); - for (srcp = envp, dstp = newenvp; *srcp; srcp++, dstp++) + for (srcp = envp, dstp = newenv; *srcp; srcp++, dstp++) { - len = strcspn (*srcp, "="); - win_env *conv; + len = strcspn (*srcp, "=") + 1; + + for (unsigned i = 0; i < SPENVS_SIZE; i++) + if (!saw_spenv[i] && (*dstp = spenvs[i].retrieve (no_envblock,*srcp, len))) + { + saw_spenv[i] = 1; + goto last; + } - if (keep_posix || !(conv = getwinenv (*srcp, *srcp + len + 1))) - *dstp = *srcp; + win_env *conv; + if (!(conv = getwinenv (*srcp, *srcp + len))) + *dstp = cstrdup1 (*srcp); else - { - p = (char *) alloca (strlen (conv->native) + 1); - strcpy (p, conv->native); - *dstp = p; - } - tl += strlen (*dstp) + 1; + *dstp = cstrdup1 (conv->native); + if ((*dstp)[0] == '!' && isdrive ((*dstp) + 1) && (*dstp)[3] == '=') - { - p = (char *) alloca (strlen (*dstp) + 1); - strcpy (p, *dstp); - *p = '='; - *dstp = p; - } + **dstp = '='; - for (int i = 0; forced_winenv_vars[i]; i++) - if (!saw_forced_winenv[i]) - saw_forced_winenv[i] = strncasematch (forced_winenv_vars[i], *srcp, len); + last: + tl += strlen (*dstp) + 1; } - char dum[1]; - for (int i = 0; forced_winenv_vars[i]; i++) - if (!saw_forced_winenv[i]) + for (unsigned i = 0; i < SPENVS_SIZE; i++) + if (!saw_spenv[i]) { - int vallen = GetEnvironmentVariable (forced_winenv_vars[i], dum, 0); - if (vallen > 0) + *dstp = spenvs[i].retrieve (no_envblock); + if (*dstp) { - int namelen = strlen (forced_winenv_vars[i]) + 1; - p = (char *) alloca (namelen + ++vallen); - strcpy (p, forced_winenv_vars[i]); - strcat (p, "="); - if (!GetEnvironmentVariable (forced_winenv_vars[i], p + namelen, - vallen)) - debug_printf ("warning: %s not present in environment", *srcp); - else - { - *dstp++ = p; - tl += strlen (p) + 1; - } + tl += strlen (*dstp) + 1; + dstp++; } } - *dstp = NULL; /* Terminate */ + envc = dstp - newenv; + *dstp = NULL; /* Terminate */ - int envlen = dstp - newenvp; - debug_printf ("env count %d, bytes %d", envlen, tl); + if (no_envblock) + envblock = NULL; + else + { + debug_printf ("env count %d, bytes %d", envc, tl); - /* Windows programs expect the environment block to be sorted. */ - qsort (newenvp, envlen, sizeof (char *), env_sort); + /* Windows programs expect the environment block to be sorted. */ + qsort (newenv, envc, sizeof (char *), env_sort); - /* Create an environment block suitable for passing to CreateProcess. */ - char *ptr, *envblock; - envblock = (char *) malloc (tl + 2); - for (srcp = newenvp, ptr = envblock; *srcp; srcp++) - { - len = strlen (*srcp); - memcpy (ptr, *srcp, len + 1); - ptr += len + 1; + /* Create an environment block suitable for passing to CreateProcess. */ + char *ptr; + envblock = (char *) malloc (tl + 2); + for (srcp = newenv, ptr = envblock; *srcp; srcp++) + { + len = strlen (*srcp); + memcpy (ptr, *srcp, len + 1); + ptr += len + 1; + } + *ptr = '\0'; /* Two null bytes at the end */ } - *ptr = '\0'; /* Two null bytes at the end */ - return envblock; + return newenv; } /* This idiocy is necessary because the early implementers of cygwin |