Skip to content

Commit ad711d9

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 <johannes.schindelin@gmx.de>
1 parent 76cdfb2 commit ad711d9

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
@@ -403,7 +403,8 @@ class cygheap_pwdgrp
403403
NSS_SCHEME_UNIX,
404404
NSS_SCHEME_DESC,
405405
NSS_SCHEME_PATH,
406-
NSS_SCHEME_FREEATTR
406+
NSS_SCHEME_FREEATTR,
407+
NSS_SCHEME_ENV
407408
};
408409
struct nss_scheme_t {
409410
nss_scheme_method method;

winsup/cygwin/uinfo.cc

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,8 @@ cygheap_pwdgrp::nss_init_line (const char *line)
794794
scheme[idx].method = NSS_SCHEME_UNIX;
795795
else if (NSS_CMP ("desc"))
796796
scheme[idx].method = NSS_SCHEME_DESC;
797+
else if (NSS_CMP ("env"))
798+
scheme[idx].method = NSS_SCHEME_ENV;
797799
else if (NSS_NCMP ("/"))
798800
{
799801
const char *e = c + strcspn (c, " \t");
@@ -982,6 +984,40 @@ fetch_from_path (cyg_ldap *pldap, PUSER_INFO_3 ui, cygpsid &sid, PCWSTR str,
982984
return ret;
983985
}
984986

987+
static size_t
988+
fetch_env(LPCWSTR key, char *buf, size_t size)
989+
{
990+
WCHAR wbuf[32767];
991+
DWORD max = sizeof wbuf / sizeof *wbuf;
992+
DWORD len = GetEnvironmentVariableW (key, wbuf, max);
993+
994+
if (!len || len >= max)
995+
return 0;
996+
997+
len = sys_wcstombs (buf, size, wbuf, len);
998+
return len && len < size ? len : 0;
999+
}
1000+
1001+
static char *
1002+
fetch_home_env (void)
1003+
{
1004+
char home[32767];
1005+
size_t max = sizeof home / sizeof *home, len;
1006+
1007+
if (fetch_env (L"HOME", home, max)
1008+
|| ((len = fetch_env (L"HOMEDRIVE", home, max))
1009+
&& fetch_env (L"HOMEPATH", home + len, max - len))
1010+
|| fetch_env (L"USERPROFILE", home, max))
1011+
{
1012+
tmp_pathbuf tp;
1013+
cygwin_conv_path (CCP_WIN_A_TO_POSIX | CCP_ABSOLUTE,
1014+
home, tp.c_get(), NT_MAX_PATH);
1015+
return strdup(tp.c_get());
1016+
}
1017+
1018+
return NULL;
1019+
}
1020+
9851021
char *
9861022
cygheap_pwdgrp::get_home (cyg_ldap *pldap, cygpsid &sid, PCWSTR dom,
9871023
PCWSTR dnsdomain, PCWSTR name, bool full_qualified)
@@ -1041,6 +1077,10 @@ cygheap_pwdgrp::get_home (cyg_ldap *pldap, cygpsid &sid, PCWSTR dom,
10411077
}
10421078
}
10431079
break;
1080+
case NSS_SCHEME_ENV:
1081+
if (RtlEqualSid (sid, cygheap->user.sid ()))
1082+
home = fetch_home_env ();
1083+
break;
10441084
}
10451085
}
10461086
return home;
@@ -1073,6 +1113,10 @@ cygheap_pwdgrp::get_home (PUSER_INFO_3 ui, cygpsid &sid, PCWSTR dom,
10731113
home = fetch_from_path (NULL, ui, sid, home_scheme[idx].attrib,
10741114
dom, NULL, name, full_qualified);
10751115
break;
1116+
case NSS_SCHEME_ENV:
1117+
if (RtlEqualSid (sid, cygheap->user.sid ()))
1118+
home = fetch_home_env ();
1119+
break;
10761120
}
10771121
}
10781122
return home;
@@ -1092,6 +1136,7 @@ cygheap_pwdgrp::get_shell (cyg_ldap *pldap, cygpsid &sid, PCWSTR dom,
10921136
case NSS_SCHEME_FALLBACK:
10931137
return NULL;
10941138
case NSS_SCHEME_WINDOWS:
1139+
case NSS_SCHEME_ENV:
10951140
break;
10961141
case NSS_SCHEME_CYGWIN:
10971142
if (pldap->fetch_ad_account (sid, false, dnsdomain))
@@ -1156,6 +1201,7 @@ cygheap_pwdgrp::get_shell (PUSER_INFO_3 ui, cygpsid &sid, PCWSTR dom,
11561201
case NSS_SCHEME_CYGWIN:
11571202
case NSS_SCHEME_UNIX:
11581203
case NSS_SCHEME_FREEATTR:
1204+
case NSS_SCHEME_ENV:
11591205
break;
11601206
case NSS_SCHEME_DESC:
11611207
if (ui)
@@ -1237,6 +1283,8 @@ cygheap_pwdgrp::get_gecos (cyg_ldap *pldap, cygpsid &sid, PCWSTR dom,
12371283
sys_wcstombs_alloc (&gecos, HEAP_NOTHEAP, val);
12381284
}
12391285
break;
1286+
case NSS_SCHEME_ENV:
1287+
break;
12401288
}
12411289
}
12421290
if (gecos)
@@ -1263,6 +1311,7 @@ cygheap_pwdgrp::get_gecos (PUSER_INFO_3 ui, cygpsid &sid, PCWSTR dom,
12631311
case NSS_SCHEME_CYGWIN:
12641312
case NSS_SCHEME_UNIX:
12651313
case NSS_SCHEME_FREEATTR:
1314+
case NSS_SCHEME_ENV:
12661315
break;
12671316
case NSS_SCHEME_DESC:
12681317
if (ui)

0 commit comments

Comments
 (0)