diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 9be9d1674..0152f4691 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,29 @@ +2002-06-28 Christopher Faylor + + * cygheap.h (cygheap_user): Reorg to accommodate environment caching. + (cygheap_user::logsrv): New method. + (cygheap_user::winname): Ditto. + (cygheap_user::domain): Ditto. + (cygheap_user::test_uid): Ditto. + * cygheap.cc (cygheap_user::set_name): Reflect name "pwinname" name + change. + * environ.cc (getwinenveq): New function. + (spenv::from_cygheap): Change arguments. + (spenv::retrieve): Ditto for call. Use getwinenveq to retrieve info + from environment. Always return value from cygwin environment, if it + exists. + * environ.h (getwinenveq): Declare. + * uinfo.cc (cygheap_user::ontherange): Use logsrv() rather than + env_logsrv(). + (cygheap_user::test_uid): Define new method. + (cygheap_user::env_logsrv): Accept environment arguments. Use test_uid + to find info. + (cygheap_user::env_domain): Ditto. + (cygheap_user::env_userprofile): Ditto. + (cygheap_user::env_homepath): Ditto. + (cygheap_user::env_homedrive): Ditto. + (cygheap_user::env_name): Ditto. + 2002-06-27 Christopher Faylor * cygheap.cc (cfree_and_set): New function. diff --git a/winsup/cygwin/cygheap.cc b/winsup/cygwin/cygheap.cc index 2cf7e2068..f74a97a57 100644 --- a/winsup/cygwin/cygheap.cc +++ b/winsup/cygwin/cygheap.cc @@ -465,7 +465,7 @@ cygheap_user::set_name (const char *new_name) cfree_and_set (homepath); cfree_and_set (plogsrv); cfree_and_set (pdomain); - cfree_and_set (winname); + cfree_and_set (pwinname); } BOOL diff --git a/winsup/cygwin/cygheap.h b/winsup/cygwin/cygheap.h index e2fcaec31..63585d91a 100644 --- a/winsup/cygwin/cygheap.h +++ b/winsup/cygwin/cygheap.h @@ -93,6 +93,7 @@ enum homebodies }; struct passwd; + class cygheap_user { /* Extendend user information. @@ -103,7 +104,7 @@ class cygheap_user char *pdomain; /* Logon domain of the user */ char *homedrive; /* User's home drive */ char *homepath; /* User's home path */ - char *winname; /* User's name as far as Windows knows it */ + char *pwinname; /* User's name as far as Windows knows it */ char *puserprof; /* User profile */ PSID psid; /* buffer for user's SID */ PSID orig_psid; /* Remains intact even after impersonation */ @@ -134,13 +135,25 @@ public: void set_name (const char *new_name); const char *name () const { return pname; } - const char *env_logsrv (); - const char *env_homepath (); - const char *env_homedrive (); - const char *env_userprofile (); - const char *env_domain (); - const char *env_name (); + const char *env_logsrv (const char *, size_t); + const char *env_homepath (const char *, size_t); + const char *env_homedrive (const char *, size_t); + const char *env_userprofile (const char *, size_t); + const char *env_domain (const char *, size_t); + const char *env_name (const char *, size_t); + const char *logsrv () + { + return env_logsrv ("LOGONSERVER=", sizeof ("LOGONSERVER=") - 1); + } + const char *winname () + { + return env_name ("USERNAME=", sizeof ("USERNAME=") - 1); + } + const char *domain () + { + return env_domain ("USERDOMAIN=", sizeof ("USERDOMAIN=") - 1); + } BOOL set_sid (PSID new_sid); BOOL set_orig_sid (); PSID sid () const { return psid; } @@ -150,6 +163,8 @@ public: { return impersonated && token != INVALID_HANDLE_VALUE; } + const char *cygheap_user::test_uid (char *&, const char *, size_t) + __attribute__ ((regparm (3))); }; /* cwd cache stuff. */ diff --git a/winsup/cygwin/environ.cc b/winsup/cygwin/environ.cc index 052398a7f..ae7268fdf 100644 --- a/winsup/cygwin/environ.cc +++ b/winsup/cygwin/environ.cc @@ -750,11 +750,43 @@ env_sort (const void *a, const void *b) return strcmp (*p, *q); } +char * __stdcall +getwinenveq (const char *name, size_t namelen, int x) +{ + char dum[1]; + char name0[namelen - 1]; + memcpy (name0, name, namelen - 1); + name0[namelen - 1] = '\0'; + int totlen = GetEnvironmentVariable (name0, dum, 0); + if (totlen > 0) + { + totlen++; + if (x == HEAP_1_STR) + totlen += namelen; + else + namelen = 0; + char *p = (char *) cmalloc ((cygheap_types) x, totlen); + if (namelen) + strcpy (p, name); + if (GetEnvironmentVariable (name0, p + namelen, totlen)) + { + debug_printf ("using value from GetEnvironmentVariable for '%s'", + name0); + return p; + } + else + cfree (p); + } + + debug_printf ("warning: %s not present in environment", name); + return NULL; +} + struct spenv { const char *name; size_t namelen; - const char * (cygheap_user::*from_cygheap) (); + const char * (cygheap_user::*from_cygheap) (const char *, size_t); char *retrieve (bool, const char * const = NULL) __attribute__ ((regparm (3))); }; @@ -785,28 +817,15 @@ spenv::retrieve (bool no_envblock, const char *const envname) if (from_cygheap) { const char *p; - if (cygheap->user.issetuid ()) - debug_printf ("calculating for setuid"); - else + if (envname) { - debug_printf ("calculating for non-setuid"); - if (!envname) - { - debug_printf ("not adding %s to windows environment", name); - return NULL; /* No need to force these into the - environment */ - } - - if (no_envblock) - { - debug_printf ("duping existing value for '%s'", name); - return cstrdup1 (envname);/* Don't really care what it's set to + 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 */ - } } /* Calculate (potentially) value for given environment variable. */ - p = (cygheap->user.*from_cygheap) (); + p = (cygheap->user.*from_cygheap) (name, namelen); if (!p || (no_envblock && !envname)) return env_dontadd; char *s = (char *) cmalloc (HEAP_1_STR, namelen + strlen (p) + 1); @@ -819,24 +838,7 @@ spenv::retrieve (bool no_envblock, const char *const envname) if (envname) return cstrdup1 (envname); - char dum[1]; - int vallen = GetEnvironmentVariable (name, dum, 0); - if (vallen > 0) - { - char *p = (char *) cmalloc (HEAP_1_STR, namelen + ++vallen); - strcpy (p, name); - if (GetEnvironmentVariable (name, p + namelen, vallen)) - { - debug_printf ("using value from GetEnvironmentVariable for '%s'", - envname); - return p; - } - else - cfree (p); - } - - debug_printf ("warning: %s not present in environment", name); - return NULL; + return getwinenveq (name, namelen, HEAP_1_STR); } #define SPENVS_SIZE (sizeof (spenvs) / sizeof (spenvs[0])) diff --git a/winsup/cygwin/environ.h b/winsup/cygwin/environ.h index ebccc53dd..1a616b214 100644 --- a/winsup/cygwin/environ.h +++ b/winsup/cygwin/environ.h @@ -35,6 +35,8 @@ struct win_env win_env * __stdcall getwinenv (const char *name, const char *posix = NULL) __attribute__ ((regparm (3))); +char * __stdcall getwinenveq (const char *name, size_t len, int) + __attribute__ ((regparm (3))); void __stdcall update_envptrs (); extern char **__cygwin_environ, ***main_environ; diff --git a/winsup/cygwin/uinfo.cc b/winsup/cygwin/uinfo.cc index effcd5908..5326ce475 100644 --- a/winsup/cygwin/uinfo.cc +++ b/winsup/cygwin/uinfo.cc @@ -28,6 +28,7 @@ details. */ #include "cygheap.h" #include "registry.h" #include "child_info.h" +#include "environ.h" void internal_getlogin (cygheap_user &user) @@ -199,6 +200,7 @@ cygheap_user::ontherange (homebodies what, struct passwd *pw) char *newhomepath = NULL; + debug_printf ("what %d, pw %p", what, pw); if (what == CH_HOME) { char *p; @@ -232,7 +234,7 @@ cygheap_user::ontherange (homebodies what, struct passwd *pw) } } - if (homepath == NULL && newhomepath == NULL) + if (what != CH_HOME && homepath == NULL && newhomepath == NULL) { if (!pw) pw = getpwnam (name ()); @@ -241,12 +243,12 @@ cygheap_user::ontherange (homebodies what, struct passwd *pw) else { homepath_env_buf[0] = homepath_env_buf[1] = '\0'; - if (env_logsrv ()) + if (logsrv ()) { WCHAR wlogsrv[INTERNET_MAX_HOST_NAME_LENGTH + 3]; - sys_mbstowcs (wlogsrv, env_logsrv (), + sys_mbstowcs (wlogsrv, logsrv (), sizeof (wlogsrv) / sizeof(*wlogsrv)); - sys_mbstowcs (wuser, env_name (), sizeof (wuser) / sizeof (*wuser)); + sys_mbstowcs (wuser, winname (), sizeof (wuser) / sizeof (*wuser)); if (!(ret = NetUserGetInfo (wlogsrv, wuser, 3,(LPBYTE *)&ui))) { char *p; @@ -302,25 +304,35 @@ cygheap_user::ontherange (homebodies what, struct passwd *pw) } const char * -cygheap_user::env_logsrv () +cygheap_user::test_uid (char *&what, const char *name, size_t namelen) { - if (plogsrv) + if (what) + return what; + if (orig_uid == myself->uid) + what = getwinenveq (name, namelen, HEAP_STR) ?: almost_null; + return what; +} + +const char * +cygheap_user::env_logsrv (const char *name, size_t namelen) +{ + if (test_uid (plogsrv, name, namelen)) return plogsrv; - if (!env_domain () || strcasematch (env_name (), "SYSTEM")) + if (!domain () || strcasematch (winname (), "SYSTEM")) return NULL; char logsrv[INTERNET_MAX_HOST_NAME_LENGTH + 3]; cfree_and_set (plogsrv, almost_null); - if (get_logon_server (env_domain (), logsrv, NULL)) + if (get_logon_server (domain (), logsrv, NULL)) plogsrv = cstrdup (logsrv); return plogsrv; } const char * -cygheap_user::env_domain () +cygheap_user::env_domain (const char *name, size_t namelen) { - if (pdomain) + if (test_uid (pdomain, name, namelen)) return pdomain; char username[UNLEN + 1]; @@ -329,26 +341,29 @@ cygheap_user::env_domain () DWORD dlen = sizeof (userdomain); SID_NAME_USE use; - cfree_and_set (winname, almost_null); + cfree_and_set (pwinname, almost_null); cfree_and_set (pdomain, almost_null); if (!LookupAccountSid (NULL, sid (), username, &ulen, userdomain, &dlen, &use)) __seterrno (); else { - winname = cstrdup (username); + pwinname = cstrdup (username); pdomain = cstrdup (userdomain); } return pdomain; } const char * -cygheap_user::env_userprofile () +cygheap_user::env_userprofile (const char *name, size_t namelen) { + if (test_uid (puserprof, name, namelen)) + return puserprof; + char userprofile_env_buf[MAX_PATH + 1]; cfree_and_set (puserprof, almost_null); /* FIXME: Should this just be setting a puserprofile like everything else? */ - if (!strcasematch (env_name (), "SYSTEM") + if (!strcasematch (winname (), "SYSTEM") && get_registry_hive_path (sid (), userprofile_env_buf)) puserprof = cstrdup (userprofile_env_buf); @@ -356,20 +371,21 @@ cygheap_user::env_userprofile () } const char * -cygheap_user::env_homepath () +cygheap_user::env_homepath (const char *name, size_t namelen) { return ontherange (CH_HOMEPATH); } const char * -cygheap_user::env_homedrive () +cygheap_user::env_homedrive (const char *name, size_t namelen) { return ontherange (CH_HOMEDRIVE); } const char * -cygheap_user::env_name () +cygheap_user::env_name (const char *name, size_t namelen) { - (void) env_domain (); - return winname; + if (!test_uid (pwinname, name, namelen)) + (void) domain (); + return pwinname; }