* environ.cc (build_env): Correctly fill out windows environment block with

win32 paths rather than posix paths.
This commit is contained in:
Christopher Faylor 2002-06-13 01:28:51 +00:00
parent b89a2aac33
commit 12a2ef4462
2 changed files with 64 additions and 29 deletions

View File

@ -1,3 +1,8 @@
2002-06-12 Christopher Faylor <cgf@redhat.com>
* environ.cc (build_env): Correctly fill out windows environment block
with win32 paths rather than posix paths.
2002-06-12 Christopher Faylor <cgf@redhat.com> 2002-06-12 Christopher Faylor <cgf@redhat.com>
* cygheap.cc (cygheap_user::set_name): Set homedrive and homepath to * cygheap.cc (cygheap_user::set_name): Set homedrive and homepath to

View File

@ -12,6 +12,7 @@ details. */
#include <stdlib.h> #include <stdlib.h>
#include <stddef.h> #include <stddef.h>
#include <ctype.h> #include <ctype.h>
#include <assert.h>
#include <sys/cygwin.h> #include <sys/cygwin.h>
#include <cygwin/version.h> #include <cygwin/version.h>
#include "pinfo.h" #include "pinfo.h"
@ -96,10 +97,9 @@ win_env::add_cache (const char *in_posix, const char *in_native)
/* Check for a "special" environment variable name. *env is the pointer /* Check for a "special" environment variable name. *env is the pointer
* to the beginning of the environment variable name. n is the length to the beginning of the environment variable name. *in_posix is any
* of the name including a mandatory '='. Returns a pointer to the known posix value for the environment variable. Returns a pointer to
* appropriate conversion structure. the appropriate conversion structure. */
*/
win_env * __stdcall win_env * __stdcall
getwinenv (const char *env, const char *in_posix) getwinenv (const char *env, const char *in_posix)
{ {
@ -824,50 +824,52 @@ char ** __stdcall
build_env (const char * const *envp, char *&envblock, int &envc, build_env (const char * const *envp, char *&envblock, int &envc,
bool no_envblock) bool no_envblock)
{ {
int len, n, tl; int len, n;
const char * const *srcp; const char * const *srcp;
char **dstp; char **dstp;
bool saw_spenv[SPENVS_SIZE] = {0}; bool saw_spenv[SPENVS_SIZE] = {0};
debug_printf ("envp %p", envp); debug_printf ("envp %p", envp);
tl = 0; /* How many elements? */
for (n = 0; envp[n]; n++) for (n = 0; envp[n]; n++)
continue; continue;
char **newenv = (char **) cmalloc (HEAP_1_ARGV, sizeof (char *) * (n + SPENVS_SIZE + 1)); /* Allocate a new "argv-style" environ list with room for extra stuff. */
char **newenv = (char **) cmalloc (HEAP_1_ARGV, sizeof (char *) *
(n + SPENVS_SIZE + 1));
int tl = 0;
/* Iterate over input list, generating a new environment list and refreshing
"special" entries, if necessary. */
for (srcp = envp, dstp = newenv; *srcp; srcp++, dstp++) for (srcp = envp, dstp = newenv; *srcp; srcp++, dstp++)
{ {
len = strcspn (*srcp, "=") + 1; len = strcspn (*srcp, "=") + 1;
/* Look for entries that require special attention */
for (unsigned i = 0; i < SPENVS_SIZE; i++) for (unsigned i = 0; i < SPENVS_SIZE; i++)
if (!saw_spenv[i] && (*dstp = spenvs[i].retrieve (no_envblock,*srcp, len))) if (!saw_spenv[i]
&& (*dstp = spenvs[i].retrieve (no_envblock, *srcp, len)))
{ {
saw_spenv[i] = 1; saw_spenv[i] = 1;
goto last; goto next;
} }
win_env *conv;
if (!(conv = getwinenv (*srcp, *srcp + len)))
*dstp = cstrdup1 (*srcp); *dstp = cstrdup1 (*srcp);
else
*dstp = cstrdup1 (conv->native);
if ((*dstp)[0] == '!' && isdrive ((*dstp) + 1) && (*dstp)[3] == '=') next:
**dstp = '='; if (!no_envblock)
last:
tl += strlen (*dstp) + 1; tl += strlen (*dstp) + 1;
} }
/* Fill in any required-but-missing environment variables. */
for (unsigned i = 0; i < SPENVS_SIZE; i++) for (unsigned i = 0; i < SPENVS_SIZE; i++)
if (!saw_spenv[i]) if (!saw_spenv[i])
{ {
*dstp = spenvs[i].retrieve (no_envblock); *dstp = spenvs[i].retrieve (no_envblock);
if (*dstp) if (*dstp)
{ {
if (!no_envblock)
tl += strlen (*dstp) + 1; tl += strlen (*dstp) + 1;
dstp++; dstp++;
} }
@ -886,15 +888,43 @@ build_env (const char * const *envp, char *&envblock, int &envc,
qsort (newenv, envc, sizeof (char *), env_sort); qsort (newenv, envc, sizeof (char *), env_sort);
/* Create an environment block suitable for passing to CreateProcess. */ /* Create an environment block suitable for passing to CreateProcess. */
char *ptr; char *s;
envblock = (char *) malloc (tl + 2); envblock = (char *) malloc (2 + tl);
for (srcp = newenv, ptr = envblock; *srcp; srcp++) int new_tl = 0;
for (srcp = newenv, s = envblock; *srcp; srcp++)
{ {
len = strlen (*srcp); const char *p;
memcpy (ptr, *srcp, len + 1); win_env *conv;
ptr += len + 1; len = strcspn (*srcp, "=") + 1;
/* See if this entry requires posix->win32 conversion. */
conv = getwinenv (*srcp, *srcp + len);
if (conv)
p = conv->native; /* Use win32 path */
else
p = *srcp; /* Don't worry about it */
len = strlen (p);
new_tl += len + 1; /* Keep running total of block length so far */
/* See if we need to increase the size of the block. */
if (new_tl > tl)
envblock = (char *) realloc (envblock, 2 + (tl += len + 100));
memcpy (s, p, len + 1);
/* See if environment variable is "special" in a Windows sense.
Under NT, the current directories for visited drives are stored
as =C:=\bar. Cygwin converts the '=' to '!' for hopefully obvious
reasons. We need to convert it back when building the envblock */
if (s[0] == '!' && (isdrive (s + 1) || (s[1] == ':' && s[2] == ':'))
&& s[3] == '=')
*s = '=';
s += len + 1;
} }
*ptr = '\0'; /* Two null bytes at the end */ *s = '\0'; /* Two null bytes at the end */
assert ((s - envblock) <= tl); /* Detect if we somehow ran over end
of buffer */
} }
return newenv; return newenv;