aboutsummaryrefslogtreecommitdiff
path: root/winsup/cygwin
diff options
context:
space:
mode:
authorChristopher Faylor <me@cgf.cx>2002-06-12 05:13:54 +0000
committerChristopher Faylor <me@cgf.cx>2002-06-12 05:13:54 +0000
commitda086d020cc3fd5c0a374ca753dfb0bc62a3cda0 (patch)
tree66bfacfed261a4c61efbf482a93606fac66b96f2 /winsup/cygwin
parent09c95bb14fd314b0529e1183c26d72dba386832a (diff)
downloadnewlib-da086d020cc3fd5c0a374ca753dfb0bc62a3cda0.zip
newlib-da086d020cc3fd5c0a374ca753dfb0bc62a3cda0.tar.gz
newlib-da086d020cc3fd5c0a374ca753dfb0bc62a3cda0.tar.bz2
* cygheap.cc (cygheap_user::set_name): Set homedrive and homepath to NULL on
user name change. (cygheap_user::set_logsrv): Allocate enough space for leading \\ so that we can put this in the environment, if needed. * cygheap.h (homebodies): New enum. (cygheap_user::homedrive): New field. (cygheap_user::homepath): Ditto. (cygheap_user::env_logsrv): New method. (cygheap_user::env_homepath): New method. (cygheap_user::env_homedrive): New method. (cygheap_user::env_userprofile): New method. (cygheap_user::ontherange): New method. * environ.cc (envsize): Eliminate debugging argument. (environ_init): Assume that envc counts number of elments not total size. (spenv): New class. (spenvs): New array, renamed from forced_winenv_vars, using spenv. (spenv::retrieve): New method. (build_env): Rename from 'winenv' -- one stop shopping for building new environment blocks for both windows and "unix". * environ.h (build_env: Declare. (winenv): Delete declaration. (envsize): Ditto. * spawn.cc (spawn_guts): Use build_env to build windows and cygwin environment blocks. * uinfo.cc (internal_getlogin): Eliminate environment manipulation. Default to info from GetUserName if it exists. Move HOMEPATH and HOMEDRIVE stuff elsewhere. Move HOME setting elsewhere. Only set HOME environment variable in processes that are not parented by a cygwin process. (cygheap_user::ontherange): Define new method. (cygheap_user::env_logsrv): Ditto. (cygheap_user::env_homepath): Ditto. (cygheap_user::env_homedrive): Ditto. (cygheap_user::env_userprofile): Ditto.
Diffstat (limited to 'winsup/cygwin')
-rw-r--r--winsup/cygwin/ChangeLog38
-rw-r--r--winsup/cygwin/cygheap.cc10
-rw-r--r--winsup/cygwin/cygheap.h16
-rw-r--r--winsup/cygwin/environ.cc188
-rw-r--r--winsup/cygwin/environ.h15
-rw-r--r--winsup/cygwin/spawn.cc19
-rw-r--r--winsup/cygwin/uinfo.cc237
7 files changed, 344 insertions, 179 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index ae54ce6..a8d26e3 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,41 @@
+2002-06-12 Christopher Faylor <cgf@redhat.com>
+
+ * cygheap.cc (cygheap_user::set_name): Set homedrive and homepath to
+ NULL on user name change.
+ (cygheap_user::set_logsrv): Allocate enough space for leading \\ so
+ that we can put this in the environment, if needed.
+ * cygheap.h (homebodies): New enum.
+ (cygheap_user::homedrive): New field.
+ (cygheap_user::homepath): Ditto.
+ (cygheap_user::env_logsrv): New method.
+ (cygheap_user::env_homepath): New method.
+ (cygheap_user::env_homedrive): New method.
+ (cygheap_user::env_userprofile): New method.
+ (cygheap_user::ontherange): New method.
+ * environ.cc (envsize): Eliminate debugging argument.
+ (environ_init): Assume that envc counts number of elments not total
+ size.
+ (spenv): New class.
+ (spenvs): New array, renamed from forced_winenv_vars, using spenv.
+ (spenv::retrieve): New method.
+ (build_env): Rename from 'winenv' -- one stop shopping for building new
+ environment blocks for both windows and "unix".
+ * environ.h (build_env: Declare.
+ (winenv): Delete declaration.
+ (envsize): Ditto.
+ * spawn.cc (spawn_guts): Use build_env to build windows and cygwin
+ environment blocks.
+ * uinfo.cc (internal_getlogin): Eliminate environment manipulation.
+ Default to info from GetUserName if it exists. Move HOMEPATH and
+ HOMEDRIVE stuff elsewhere. Move HOME setting elsewhere. Only set HOME
+ environment variable in processes that are not parented by a cygwin
+ process.
+ (cygheap_user::ontherange): Define new method.
+ (cygheap_user::env_logsrv): Ditto.
+ (cygheap_user::env_homepath): Ditto.
+ (cygheap_user::env_homedrive): Ditto.
+ (cygheap_user::env_userprofile): Ditto.
+
2002-06-11 Christopher Faylor <cgf@redhat.com>
* spawn.cc (spawn_guts): More hToken removal cleanup.
diff --git a/winsup/cygwin/cygheap.cc b/winsup/cygwin/cygheap.cc
index d6ce676..bd6ae3c 100644
--- a/winsup/cygwin/cygheap.cc
+++ b/winsup/cygwin/cygheap.cc
@@ -443,6 +443,8 @@ cygheap_user::set_name (const char *new_name)
if (pname)
cfree (pname);
pname = cstrdup (new_name ? new_name : "");
+ homedrive = NULL;
+ homepath = NULL;
}
void
@@ -450,7 +452,13 @@ cygheap_user::set_logsrv (const char *new_logsrv)
{
if (plogsrv)
cfree (plogsrv);
- plogsrv = (new_logsrv && *new_logsrv) ? cstrdup (new_logsrv) : NULL;
+ if (!new_logsrv || !*new_logsrv)
+ plogsrv = NULL;
+ else
+ {
+ plogsrv = (char *) cmalloc (HEAP_STR, strlen (new_logsrv) + 3) + 2;
+ strcpy (plogsrv, new_logsrv);
+ }
}
void
diff --git a/winsup/cygwin/cygheap.h b/winsup/cygwin/cygheap.h
index f4ef144..e4fbe5f 100644
--- a/winsup/cygwin/cygheap.h
+++ b/winsup/cygwin/cygheap.h
@@ -85,6 +85,14 @@ public:
const char *native_path () const { return m->native_path; }
};
+enum homebodies
+{
+ CH_HOMEDRIVE,
+ CH_HOMEPATH,
+ CH_HOME
+};
+
+struct passwd;
class cygheap_user
{
/* Extendend user information.
@@ -93,6 +101,8 @@ class cygheap_user
char *pname; /* user's name */
char *plogsrv; /* Logon server, may be FQDN */
char *pdomain; /* Logon domain of the user */
+ char *homedrive; /* User's home drive */
+ char *homepath; /* User's home path */
PSID psid; /* buffer for user's SID */
PSID orig_psid; /* Remains intact even after impersonation */
public:
@@ -116,6 +126,11 @@ public:
void set_logsrv (const char *new_logsrv);
const char *logsrv () const { return plogsrv; }
+ const char *env_logsrv ();
+ const char *env_homepath ();
+ const char *env_homedrive ();
+ const char *env_userprofile ();
+
void set_domain (const char *new_domain);
const char *domain () const { return pdomain; }
@@ -130,6 +145,7 @@ public:
set_domain (user.domain ());
set_sid (user.sid ());
}
+ const char *ontherange (homebodies what, struct passwd * = NULL);
};
/* cwd cache stuff. */
diff --git a/winsup/cygwin/environ.cc b/winsup/cygwin/environ.cc
index 8b15c1c..357af77 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
diff --git a/winsup/cygwin/environ.h b/winsup/cygwin/environ.h
index 86f70f6..3f372b1 100644
--- a/winsup/cygwin/environ.h
+++ b/winsup/cygwin/environ.h
@@ -1,6 +1,6 @@
/* environ.h: Declarations for environ manipulation
- Copyright 2000 Red Hat, Inc.
+ Copyright 2000, 2001, 2002 Red Hat, Inc.
This file is part of Cygwin.
@@ -12,11 +12,10 @@ details. */
void environ_init (char **, int);
/* The structure below is used to control conversion to/from posix-style
- * file specs. Currently, only PATH and HOME are converted, but PATH
- * needs to use a "convert path list" function while HOME needs a simple
- * "convert to posix/win32". For the simple case, where a calculated length
- * is required, just return MAX_PATH. *FIXME*
- */
+ file specs. Currently, only PATH and HOME are converted, but PATH
+ needs to use a "convert path list" function while HOME needs a simple
+ "convert to posix/win32". For the simple case, where a calculated length
+ is required, just return MAX_PATH. *FIXME* */
struct win_env
{
const char *name;
@@ -35,7 +34,7 @@ struct win_env
win_env * __stdcall getwinenv (const char *name, const char *posix = NULL);
void __stdcall update_envptrs ();
-char * __stdcall winenv (const char * const *, int);
extern char **__cygwin_environ, ***main_environ;
extern "C" char __stdcall **cur_environ ();
-int __stdcall envsize (const char * const *, int debug_print = 0);
+char ** __stdcall build_env (const char * const *envp, char *&envblock,
+ int &envc, bool need_envblock);
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index 12e82a6..e5d9bfe 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -562,18 +562,14 @@ spawn_guts (const char * prog_arg, const char *const *argv,
MALLOC_CHECK;
}
+ char *envblock;
newargv.all_calloced ();
ciresrv.moreinfo->argc = newargv.argc;
ciresrv.moreinfo->argv = newargv;
-
- ciresrv.moreinfo->envc = envsize (envp, 1);
- ciresrv.moreinfo->envp = (char **) cmalloc (HEAP_1_ARGV, ciresrv.moreinfo->envc);
ciresrv.hexec_proc = hexec_proc;
- char **c;
- const char * const *e;
- for (c = ciresrv.moreinfo->envp, e = envp; *e;)
- *c++ = cstrdup1 (*e++);
- *c = NULL;
+ ciresrv.moreinfo->envp = build_env (envp, envblock, ciresrv.moreinfo->envc,
+ real_path.iscygexec ());
+
if (mode != _P_OVERLAY ||
!DuplicateHandle (hMainProc, myself.shared_handle (), hMainProc,
&ciresrv.moreinfo->myself_pinfo, 0,
@@ -605,13 +601,6 @@ spawn_guts (const char * prog_arg, const char *const *argv,
flags |= CREATE_SUSPENDED;
- /* Build windows style environment list */
- char *envblock;
- if (real_path.iscygexec ())
- envblock = NULL;
- else
- envblock = winenv (envp, 0);
-
const char *runpath = null_app_name ? NULL : (const char *) real_path;
syscall_printf ("null_app_name %d (%s, %.132s)", null_app_name, runpath, one_line.buf);
diff --git a/winsup/cygwin/uinfo.cc b/winsup/cygwin/uinfo.cc
index 20171c4..9bb0b69 100644
--- a/winsup/cygwin/uinfo.cc
+++ b/winsup/cygwin/uinfo.cc
@@ -37,7 +37,7 @@ internal_getlogin (cygheap_user &user)
struct passwd *pw = NULL;
if (!GetUserName (username, &username_len))
- user.set_name ("unknown");
+ user.set_name (NULL);
else
user.set_name (username);
debug_printf ("GetUserName() = %s", user.name ());
@@ -50,7 +50,7 @@ internal_getlogin (cygheap_user &user)
user.set_logsrv (NULL);
/* First trying to get logon info from environment */
- if ((env = getenv ("USERNAME")) != NULL)
+ if (!*user.name () && (env = getenv ("USERNAME")) != NULL)
user.set_name (env);
if ((env = getenv ("USERDOMAIN")) != NULL)
user.set_domain (env);
@@ -73,58 +73,10 @@ internal_getlogin (cygheap_user &user)
}
if (!user.logsrv () && user.domain() &&
get_logon_server(user.domain(), buf, NULL))
- {
- user.set_logsrv (buf + 2);
- setenv ("LOGONSERVER", buf, 1);
- }
+ user.set_logsrv (buf + 2);
debug_printf ("Domain: %s, Logon Server: %s, Windows Username: %s",
user.domain (), user.logsrv (), user.name ());
- /* NetUserGetInfo() can be slow in NT domain environment, thus we
- * only obtain HOMEDRIVE and HOMEPATH if they are not already set
- * in the environment. */
- if (!getenv ("HOMEPATH") || !getenv ("HOMEDRIVE"))
- {
- LPUSER_INFO_3 ui = NULL;
- WCHAR wuser[UNLEN + 1];
-
- sys_mbstowcs (wuser, user.name (), sizeof (wuser) / sizeof (*wuser));
- if ((ret = NetUserGetInfo (NULL, wuser, 3, (LPBYTE *)&ui)))
- {
- if (user.logsrv ())
- {
- WCHAR wlogsrv[INTERNET_MAX_HOST_NAME_LENGTH + 3];
- strcat (strcpy (buf, "\\\\"), user.logsrv ());
-
- sys_mbstowcs (wlogsrv, buf,
- sizeof (wlogsrv) / sizeof(*wlogsrv));
- ret = NetUserGetInfo (wlogsrv, wuser, 3,(LPBYTE *)&ui);
- }
- }
- if (!ret)
- {
- sys_wcstombs (buf, ui->usri3_home_dir, MAX_PATH);
- if (!buf[0])
- {
- sys_wcstombs (buf, ui->usri3_home_dir_drive, MAX_PATH);
- if (buf[0])
- strcat (buf, "\\");
- else
- {
- env = getenv ("SYSTEMDRIVE");
- if (env && *env)
- strcat (strcpy (buf, env), "\\");
- else
- GetSystemDirectoryA (buf, MAX_PATH);
- }
- }
- setenv ("HOMEPATH", buf + 2, 1);
- buf[2] = '\0';
- setenv ("HOMEDRIVE", buf, 1);
- }
- if (ui)
- NetApiBufferFree (ui);
- }
HANDLE ptok = user.token; /* Which is INVALID_HANDLE_VALUE if no
impersonation took place. */
@@ -181,21 +133,13 @@ internal_getlogin (cygheap_user &user)
gsid = NO_SID;
break;
}
- if (!strcasematch (user.name (), "SYSTEM")
- && user.domain () && user.logsrv ())
- {
- if (get_registry_hive_path (user.sid (), buf))
- setenv ("USERPROFILE", buf, 1);
- else
- unsetenv ("USERPROFILE");
- }
}
/* If this process is started from a non Cygwin process,
set token owner to the same value as token user and
primary group to the group which is set as primary group
in /etc/passwd. */
- if (ptok != INVALID_HANDLE_VALUE && myself->ppid == 1)
+ if (ptok != INVALID_HANDLE_VALUE && !myself->ppid_handle)
{
if (!SetTokenInformation (ptok, TokenOwner, &tu, sizeof tu))
debug_printf ("SetTokenInformation(TokenOwner): %E");
@@ -213,26 +157,11 @@ internal_getlogin (cygheap_user &user)
debug_printf ("Cygwins Username: %s", user.name ());
if (!pw)
- pw = getpwnam(user.name ());
- if (!getenv ("HOME"))
- {
- const char *homedrive, *homepath;
- if (pw && pw->pw_dir && *pw->pw_dir)
- {
- setenv ("HOME", pw->pw_dir, 1);
- debug_printf ("Set HOME (from /etc/passwd) to %s", pw->pw_dir);
- }
- else if ((homedrive = getenv ("HOMEDRIVE"))
- && (homepath = getenv ("HOMEPATH")))
- {
- char home[MAX_PATH];
- strcpy (buf, homedrive);
- strcat (buf, homepath);
- cygwin_conv_to_full_posix_path (buf, home);
- setenv ("HOME", home, 1);
- debug_printf ("Set HOME (from HOMEDRIVE/HOMEPATH) to %s", home);
- }
- }
+ pw = getpwnam (user.name ());
+
+ if (!myself->ppid_handle)
+ (void) cygheap->user.ontherange (CH_HOME, pw);
+
return pw;
}
@@ -336,13 +265,151 @@ getegid (void)
extern "C" char *
cuserid (char *src)
{
- if (src)
+ if (!src)
+ return getlogin ();
+
+ strcpy (src, getlogin ());
+ return src;
+}
+
+const char *
+cygheap_user::ontherange (homebodies what, struct passwd *pw)
+{
+ static char buf[MAX_PATH + 1];
+ static char homedrive_buf[3];
+ LPUSER_INFO_3 ui = NULL;
+ WCHAR wuser[UNLEN + 1];
+ NET_API_STATUS ret;
+
+ if (what == CH_HOME)
+ {
+ char *p;
+ if ((p = getenv ("HOMEDRIVE")))
+ {
+ memcpy (homedrive_buf, p, 2);
+ homedrive = homedrive_buf;
+ }
+ if ((p = getenv ("HOMEPATH")))
+ {
+ strcpy (buf, p);
+ homepath = buf;
+ }
+ if ((p = getenv ("HOME")))
+ debug_printf ("HOME is already in the environment %s", p);
+ else
+ {
+ if (!pw)
+ pw = getpwnam (name ());
+ if (pw && pw->pw_dir && *pw->pw_dir)
+ {
+ setenv ("HOME", pw->pw_dir, 1);
+ debug_printf ("Set HOME (from /etc/passwd) to %s", pw->pw_dir);
+ }
+ else if (homedrive && homepath)
+ {
+ char home[MAX_PATH];
+ strcpy (buf, homedrive);
+ strcat (buf, homepath);
+ cygwin_conv_to_full_posix_path (buf, home);
+ setenv ("HOME", home, 1);
+ debug_printf ("Set HOME (from HOMEDRIVE/HOMEPATH) to %s", home);
+ }
+ }
+ }
+
+ if (homedrive == NULL)
{
- strcpy (src, getlogin ());
- return src;
+ if (!pw)
+ pw = getpwnam (name ());
+ if (pw && pw->pw_dir && *pw->pw_dir)
+ cygwin_conv_to_full_win32_path (pw->pw_dir, buf);
+ else
+ {
+ sys_mbstowcs (wuser, name (), sizeof (wuser) / sizeof (*wuser));
+ if ((ret = NetUserGetInfo (NULL, wuser, 3, (LPBYTE *)&ui)))
+ {
+ if (logsrv ())
+ {
+ WCHAR wlogsrv[INTERNET_MAX_HOST_NAME_LENGTH + 3];
+ strcat (strcpy (buf, "\\\\"), logsrv ());
+ sys_mbstowcs (wlogsrv, buf, sizeof (wlogsrv) / sizeof(*wlogsrv));
+ ret = NetUserGetInfo (wlogsrv, wuser, 3,(LPBYTE *)&ui);
+ }
+ }
+ if (!ret)
+ {
+ char *p;
+ sys_wcstombs (buf, ui->usri3_home_dir, MAX_PATH);
+ if (!buf[0])
+ {
+ sys_wcstombs (buf, ui->usri3_home_dir_drive, MAX_PATH);
+ if (buf[0])
+ strcat (buf, "\\");
+ else if (!GetSystemDirectory (buf, MAX_PATH))
+ strcpy (buf, "c:\\");
+ else if ((p = strchr (buf, '\\')))
+ p[1] = '\0';
+ }
+ }
+ if (ui)
+ NetApiBufferFree (ui);
+ }
+
+ if (buf[1] != ':')
+ {
+ homedrive_buf[0] = homedrive_buf[1] = '\0';
+ homepath = buf;
+ }
+ else
+ {
+ homedrive_buf[0] = buf[0];
+ homedrive_buf[1] = buf[1];
+ homepath = buf + 2;
+ }
+ homedrive = homedrive_buf;
}
- else
+
+ switch (what)
{
- return getlogin ();
+ case CH_HOMEDRIVE:
+ return homedrive;
+ case CH_HOMEPATH:
+ return homepath;
+ default:
+ return homepath;
}
}
+
+const char *
+cygheap_user::env_logsrv ()
+{
+ char *p = plogsrv - 2;
+
+ *p = p[1] = '\\';
+ return p;
+}
+
+const char *
+cygheap_user::env_userprofile ()
+{
+ static char buf[512]; /* FIXME: This shouldn't be static. */
+ if (strcasematch (name (), "SYSTEM") || !domain () || !logsrv ())
+ return NULL;
+
+ if (get_registry_hive_path (sid (), buf))
+ return buf;
+ else
+ return NULL;
+}
+
+const char *
+cygheap_user::env_homepath ()
+{
+ return ontherange (CH_HOMEPATH);
+}
+
+const char *
+cygheap_user::env_homedrive ()
+{
+ return ontherange (CH_HOMEDRIVE);
+}