Allow deriving the current user's home directory via the HOME variable
This patch hails from Git for Windows (where the Cygwin runtime is used in the form of a slightly modified MSYS2 runtime), where it is a well-established technique to let the `$HOME` variable define where the current user's home directory is, falling back to `$HOMEDRIVE$HOMEPATH` and `$USERPROFILE`. The idea is that we want to share user-specific settings between programs, whether they be Cygwin, MSYS2 or not. Unfortunately, we cannot blindly activate the "db_home: windows" setting because in some setups, the user's home directory is set to a hidden directory via an UNC path (\\share\some\hidden\folder$) -- something many programs cannot handle correctly, e.g. `cmd.exe` and other native Windows applications that users want to employ as Git helpers. The established technique is to allow setting the user's home directory via the environment variables mentioned above: `$HOMEDRIVE$HOMEPATH` or `$USERPROFILE`. This has the additional advantage that it is much faster than querying the Windows user database. Of course this scheme needs to be opt-in. For that reason, it needs to be activated explicitly via `db_home: env` in `/etc/nsswitch.conf`. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This commit is contained in:
parent
fc6e89c937
commit
27376c60a9
|
@ -358,7 +358,8 @@ public:
|
|||
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;
|
||||
|
|
|
@ -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,42 @@ fetch_from_path (cyg_ldap *pldap, PUSER_INFO_3 ui, cygpsid &sid, PCWSTR str,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static char *
|
||||
fetch_home_env (void)
|
||||
{
|
||||
/* If `HOME` is set, prefer it */
|
||||
const char *home = getenv ("HOME");
|
||||
if (home)
|
||||
return strdup (home);
|
||||
|
||||
/* If `HOME` is unset, fall back to `HOMEDRIVE``HOMEPATH`
|
||||
(without a directory separator, as `HOMEPATH` starts with one). */
|
||||
const char *home_drive = getenv ("HOMEDRIVE");
|
||||
if (home_drive)
|
||||
{
|
||||
const char *home_path = getenv ("HOMEPATH");
|
||||
if (home_path)
|
||||
{
|
||||
tmp_pathbuf tp;
|
||||
char *p = tp.c_get (), *q;
|
||||
|
||||
// concatenate HOMEDRIVE and HOMEPATH
|
||||
q = stpncpy (p, home_drive, NT_MAX_PATH);
|
||||
strlcpy (q, home_path, NT_MAX_PATH - (q - p));
|
||||
return (char *) cygwin_create_path (CCP_WIN_A_TO_POSIX, p);
|
||||
}
|
||||
}
|
||||
|
||||
/* If neither `HOME` nor `HOMEDRIVE``HOMEPATH` are set, fall back
|
||||
to `USERPROFILE`; In corporate setups, this might point to a
|
||||
disconnected network share, hence this is the last fall back. */
|
||||
home = getenv ("USERPROFILE");
|
||||
if (home)
|
||||
return (char *) cygwin_create_path (CCP_WIN_A_TO_POSIX, home);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *
|
||||
cygheap_pwdgrp::get_home (cyg_ldap *pldap, cygpsid &sid, PCWSTR dom,
|
||||
PCWSTR dnsdomain, PCWSTR name, bool full_qualified)
|
||||
|
@ -980,6 +1018,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 +1054,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 +1077,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 +1142,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 +1224,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 +1252,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)
|
||||
|
|
|
@ -1203,6 +1203,17 @@ schemata are the following:
|
|||
See <xref linkend="ntsec-mapping-nsswitch-desc"></xref>
|
||||
for a more detailed description.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><literal>env</literal></term>
|
||||
<listitem>Derives the home directory of the current user from the
|
||||
environment variable <literal>HOME</literal> (falling back to
|
||||
<literal>HOMEDRIVE\HOMEPATH</literal> and
|
||||
<literal>USERPROFILE</literal>, in that order). This is faster
|
||||
than the <term><literal>windows</literal></term> schema at the
|
||||
expense of determining only the current user's home directory
|
||||
correctly. This schema is skipped for any other account.
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
<para>
|
||||
|
@ -1335,6 +1346,17 @@ of each schema when used with <literal>db_home:</literal>
|
|||
See <xref linkend="ntsec-mapping-nsswitch-desc"></xref>
|
||||
for a detailed description.</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><literal>env</literal></term>
|
||||
<listitem>Derives the home directory of the current user from the
|
||||
environment variable <literal>HOME</literal> (falling back to
|
||||
<literal>HOMEDRIVE\HOMEPATH</literal> and
|
||||
<literal>USERPROFILE</literal>, in that order). This is faster
|
||||
than the <term><literal>windows</literal></term> schema at the
|
||||
expense of determining only the current user's home directory
|
||||
correctly. This schema is skipped for any other account.
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><literal>@ad_attribute</literal></term>
|
||||
<listitem>AD only: The user's home directory is set to the path given
|
||||
|
|
Loading…
Reference in New Issue