summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/environ.cc
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/environ.cc')
-rw-r--r--winsup/cygwin/environ.cc188
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