Skip to content

Commit 0f56cdd

Browse files
committed
Allow overriding the home directory via the HOME variable
In Git for Windows, it is a well-established technique to use the `$HOME` variable to define where the current user's home directory is, falling back to `$HOMEDRIVE$HOMEPATH` and `$USERPROFILE`. This strategy is particular important when Cygwin, or command-line programs depending on the HOME variable, cannot cope with the Windows' idea of the user's home directory e.g. when it is set to a hidden directory via an UNC path (\\share\some\hidden\folder$). Of course this strategy needs to be opt-in. For that reason, this strategy is activated via the `env` keyword in the `db_home` line in `/etc/nsswitch.conf`. Signed-off-by: Johannes Schindelin <[email protected]>
1 parent d50e35a commit 0f56cdd

File tree

2 files changed

+51
-1
lines changed

2 files changed

+51
-1
lines changed

winsup/cygwin/cygheap.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,8 @@ class cygheap_pwdgrp
408408
NSS_SCHEME_UNIX,
409409
NSS_SCHEME_DESC,
410410
NSS_SCHEME_PATH,
411-
NSS_SCHEME_FREEATTR
411+
NSS_SCHEME_FREEATTR,
412+
NSS_SCHEME_ENV
412413
};
413414
struct nss_scheme_t {
414415
nss_scheme_method method;

winsup/cygwin/uinfo.cc

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -808,6 +808,8 @@ cygheap_pwdgrp::nss_init_line (const char *line)
808808
scheme[idx].method = NSS_SCHEME_UNIX;
809809
else if (NSS_CMP ("desc"))
810810
scheme[idx].method = NSS_SCHEME_DESC;
811+
else if (NSS_CMP ("env"))
812+
scheme[idx].method = NSS_SCHEME_ENV;
811813
else if (NSS_NCMP ("/"))
812814
{
813815
const char *e = c + strcspn (c, " \t");
@@ -998,6 +1000,40 @@ fetch_from_path (cyg_ldap *pldap, PUSER_INFO_3 ui, cygpsid &sid, PCWSTR str,
9981000
return ret;
9991001
}
10001002

1003+
static size_t
1004+
fetch_env(LPCWSTR key, char *buf, size_t size)
1005+
{
1006+
WCHAR wbuf[32767];
1007+
DWORD max = sizeof wbuf / sizeof *wbuf;
1008+
DWORD len = GetEnvironmentVariableW (key, wbuf, max);
1009+
1010+
if (!len || len >= max)
1011+
return 0;
1012+
1013+
len = sys_wcstombs (buf, size, wbuf, len);
1014+
return len && len < size ? len : 0;
1015+
}
1016+
1017+
static char *
1018+
fetch_home_env (void)
1019+
{
1020+
char home[32767];
1021+
size_t max = sizeof home / sizeof *home, len;
1022+
1023+
if (fetch_env (L"HOME", home, max)
1024+
|| ((len = fetch_env (L"HOMEDRIVE", home, max))
1025+
&& fetch_env (L"HOMEPATH", home + len, max - len))
1026+
|| fetch_env (L"USERPROFILE", home, max))
1027+
{
1028+
tmp_pathbuf tp;
1029+
cygwin_conv_path (CCP_WIN_A_TO_POSIX | CCP_ABSOLUTE,
1030+
home, tp.c_get(), NT_MAX_PATH);
1031+
return strdup(tp.c_get());
1032+
}
1033+
1034+
return NULL;
1035+
}
1036+
10011037
char *
10021038
cygheap_pwdgrp::get_home (cyg_ldap *pldap, cygpsid &sid, PCWSTR dom,
10031039
PCWSTR dnsdomain, PCWSTR name, bool full_qualified)
@@ -1057,6 +1093,10 @@ cygheap_pwdgrp::get_home (cyg_ldap *pldap, cygpsid &sid, PCWSTR dom,
10571093
}
10581094
}
10591095
break;
1096+
case NSS_SCHEME_ENV:
1097+
if (RtlEqualSid (sid, cygheap->user.sid ()))
1098+
home = fetch_home_env ();
1099+
break;
10601100
}
10611101
}
10621102
return home;
@@ -1089,6 +1129,10 @@ cygheap_pwdgrp::get_home (PUSER_INFO_3 ui, cygpsid &sid, PCWSTR dom,
10891129
home = fetch_from_path (NULL, ui, sid, home_scheme[idx].attrib,
10901130
dom, NULL, name, full_qualified);
10911131
break;
1132+
case NSS_SCHEME_ENV:
1133+
if (RtlEqualSid (sid, cygheap->user.sid ()))
1134+
home = fetch_home_env ();
1135+
break;
10921136
}
10931137
}
10941138
return home;
@@ -1108,6 +1152,7 @@ cygheap_pwdgrp::get_shell (cyg_ldap *pldap, cygpsid &sid, PCWSTR dom,
11081152
case NSS_SCHEME_FALLBACK:
11091153
return NULL;
11101154
case NSS_SCHEME_WINDOWS:
1155+
case NSS_SCHEME_ENV:
11111156
break;
11121157
case NSS_SCHEME_CYGWIN:
11131158
if (pldap->fetch_ad_account (sid, false, dnsdomain))
@@ -1172,6 +1217,7 @@ cygheap_pwdgrp::get_shell (PUSER_INFO_3 ui, cygpsid &sid, PCWSTR dom,
11721217
case NSS_SCHEME_CYGWIN:
11731218
case NSS_SCHEME_UNIX:
11741219
case NSS_SCHEME_FREEATTR:
1220+
case NSS_SCHEME_ENV:
11751221
break;
11761222
case NSS_SCHEME_DESC:
11771223
if (ui)
@@ -1253,6 +1299,8 @@ cygheap_pwdgrp::get_gecos (cyg_ldap *pldap, cygpsid &sid, PCWSTR dom,
12531299
sys_wcstombs_alloc (&gecos, HEAP_NOTHEAP, val);
12541300
}
12551301
break;
1302+
case NSS_SCHEME_ENV:
1303+
break;
12561304
}
12571305
}
12581306
if (gecos)
@@ -1279,6 +1327,7 @@ cygheap_pwdgrp::get_gecos (PUSER_INFO_3 ui, cygpsid &sid, PCWSTR dom,
12791327
case NSS_SCHEME_CYGWIN:
12801328
case NSS_SCHEME_UNIX:
12811329
case NSS_SCHEME_FREEATTR:
1330+
case NSS_SCHEME_ENV:
12821331
break;
12831332
case NSS_SCHEME_DESC:
12841333
if (ui)

0 commit comments

Comments
 (0)