diff --git a/winsup/cygwin/local_includes/cygheap.h b/winsup/cygwin/local_includes/cygheap.h index 347cbf448d..f5aecba37a 100644 --- a/winsup/cygwin/local_includes/cygheap.h +++ b/winsup/cygwin/local_includes/cygheap.h @@ -406,7 +406,8 @@ class cygheap_pwdgrp NSS_SCHEME_UNIX, NSS_SCHEME_DESC, NSS_SCHEME_PATH, - NSS_SCHEME_FREEATTR + NSS_SCHEME_FREEATTR, + NSS_SCHEME_ENV }; struct nss_scheme_t { nss_scheme_method method; diff --git a/winsup/cygwin/uinfo.cc b/winsup/cygwin/uinfo.cc index 9bbcf1c17f..f569858671 100644 --- a/winsup/cygwin/uinfo.cc +++ b/winsup/cygwin/uinfo.cc @@ -733,6 +733,8 @@ cygheap_pwdgrp::nss_init_line (const char *line) scheme[idx].method = NSS_SCHEME_UNIX; else if (NSS_CMP ("desc")) scheme[idx].method = NSS_SCHEME_DESC; + else if (NSS_CMP ("env")) + scheme[idx].method = NSS_SCHEME_ENV; else if (NSS_NCMP ("/")) { const char *e = c + strcspn (c, " \t"); @@ -921,6 +923,40 @@ fetch_from_path (cyg_ldap *pldap, PUSER_INFO_3 ui, cygpsid &sid, PCWSTR str, return ret; } +static size_t +fetch_env(LPCWSTR key, char *buf, size_t size) +{ + WCHAR wbuf[32767]; + DWORD max = sizeof wbuf / sizeof *wbuf; + DWORD len = GetEnvironmentVariableW (key, wbuf, max); + + if (!len || len >= max) + return 0; + + len = sys_wcstombs (buf, size, wbuf, len); + return len && len < size ? len : 0; +} + +static char * +fetch_home_env (void) +{ + char home[32767]; + size_t max = sizeof home / sizeof *home, len; + + if (fetch_env (L"HOME", home, max) + || ((len = fetch_env (L"HOMEDRIVE", home, max)) + && fetch_env (L"HOMEPATH", home + len, max - len)) + || fetch_env (L"USERPROFILE", home, max)) + { + tmp_pathbuf tp; + cygwin_conv_path (CCP_WIN_A_TO_POSIX | CCP_ABSOLUTE, + home, tp.c_get(), NT_MAX_PATH); + return strdup(tp.c_get()); + } + + return NULL; +} + char * cygheap_pwdgrp::get_home (cyg_ldap *pldap, cygpsid &sid, PCWSTR dom, PCWSTR dnsdomain, PCWSTR name, bool full_qualified) @@ -980,6 +1016,10 @@ cygheap_pwdgrp::get_home (cyg_ldap *pldap, cygpsid &sid, PCWSTR dom, } } break; + case NSS_SCHEME_ENV: + if (RtlEqualSid (sid, cygheap->user.sid ())) + home = fetch_home_env (); + break; } } return home; @@ -1012,6 +1052,10 @@ cygheap_pwdgrp::get_home (PUSER_INFO_3 ui, cygpsid &sid, PCWSTR dom, home = fetch_from_path (NULL, ui, sid, home_scheme[idx].attrib, dom, NULL, name, full_qualified); break; + case NSS_SCHEME_ENV: + if (RtlEqualSid (sid, cygheap->user.sid ())) + home = fetch_home_env (); + break; } } return home; @@ -1031,6 +1075,7 @@ cygheap_pwdgrp::get_shell (cyg_ldap *pldap, cygpsid &sid, PCWSTR dom, case NSS_SCHEME_FALLBACK: return NULL; case NSS_SCHEME_WINDOWS: + case NSS_SCHEME_ENV: break; case NSS_SCHEME_CYGWIN: if (pldap->fetch_ad_account (sid, false, dnsdomain)) @@ -1095,6 +1140,7 @@ cygheap_pwdgrp::get_shell (PUSER_INFO_3 ui, cygpsid &sid, PCWSTR dom, case NSS_SCHEME_CYGWIN: case NSS_SCHEME_UNIX: case NSS_SCHEME_FREEATTR: + case NSS_SCHEME_ENV: break; case NSS_SCHEME_DESC: if (ui) @@ -1176,6 +1222,8 @@ cygheap_pwdgrp::get_gecos (cyg_ldap *pldap, cygpsid &sid, PCWSTR dom, sys_wcstombs_alloc (&gecos, HEAP_NOTHEAP, val); } break; + case NSS_SCHEME_ENV: + break; } } if (gecos) @@ -1202,6 +1250,7 @@ cygheap_pwdgrp::get_gecos (PUSER_INFO_3 ui, cygpsid &sid, PCWSTR dom, case NSS_SCHEME_CYGWIN: case NSS_SCHEME_UNIX: case NSS_SCHEME_FREEATTR: + case NSS_SCHEME_ENV: break; case NSS_SCHEME_DESC: if (ui)