From d6271ce9919122e10cbf8d5139881bea17ea41c5 Mon Sep 17 00:00:00 2001 From: Karsten Blees Date: Mon, 6 Apr 2015 20:54:46 +0200 Subject: [PATCH 1/5] git-wrapper: fix HOME initialization git-wrapper fails to initialize HOME correctly if $HOMEDRIVE$HOMEPATH points to a disconnected network drive. Check if the directory exists before using $HOMEDRIVE$HOMEPATH. Signed-off-by: Karsten Blees --- compat/win32/git-wrapper.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/compat/win32/git-wrapper.c b/compat/win32/git-wrapper.c index 714c3d8ef85fd6..6b2d7de4bf029e 100644 --- a/compat/win32/git-wrapper.c +++ b/compat/win32/git-wrapper.c @@ -56,13 +56,29 @@ static void setup_environment(LPWSTR exepath, int full_path) if (!GetEnvironmentVariable(L"PLINK_PROTOCOL", NULL, 0)) SetEnvironmentVariable(L"PLINK_PROTOCOL", L"ssh"); - /* set HOME to %HOMEDRIVE%%HOMEPATH% or %USERPROFILE% + /* + * set HOME to %HOMEDRIVE%%HOMEPATH% or %USERPROFILE% * With roaming profiles: HOMEPATH is the roaming location and * USERPROFILE is the local location */ if (!GetEnvironmentVariable(L"HOME", NULL, 0)) { LPWSTR e = NULL; len = GetEnvironmentVariable(L"HOMEPATH", NULL, 0); + if (len) { + DWORD attr, drvlen = GetEnvironmentVariable(L"HOMEDRIVE", NULL, 0); + e = (LPWSTR)malloc(sizeof(WCHAR) * (drvlen + len)); + drvlen = GetEnvironmentVariable(L"HOMEDRIVE", e, drvlen); + GetEnvironmentVariable(L"HOMEPATH", e + drvlen, len); + /* check if the path exists */ + attr = GetFileAttributesW(e); + if (attr != INVALID_FILE_ATTRIBUTES + && (attr & FILE_ATTRIBUTE_DIRECTORY)) + SetEnvironmentVariable(L"HOME", e); + else + len = 0; /* use USERPROFILE */ + free(e); + } + if (len == 0) { len = GetEnvironmentVariable(L"USERPROFILE", NULL, 0); if (len != 0) { @@ -72,15 +88,6 @@ static void setup_environment(LPWSTR exepath, int full_path) free(e); } } - else { - int n; - len += GetEnvironmentVariable(L"HOMEDRIVE", NULL, 0); - e = (LPWSTR)malloc(sizeof(WCHAR) * (len + 2)); - n = GetEnvironmentVariable(L"HOMEDRIVE", e, len); - GetEnvironmentVariable(L"HOMEPATH", &e[n], len-n); - SetEnvironmentVariable(L"HOME", e); - free(e); - } } /* extend the PATH */ From e678595d67b5f68d6ba50a65b343e874afd3d27f Mon Sep 17 00:00:00 2001 From: Karsten Blees Date: Thu, 2 Apr 2015 19:37:08 +0200 Subject: [PATCH 2/5] mingw: factor out Windows specific environment setup Signed-off-by: Karsten Blees --- compat/mingw.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/compat/mingw.c b/compat/mingw.c index 731fdcbaf21547..174033021dff57 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -2218,6 +2218,22 @@ int handle_long_path(wchar_t *path, int len, int max_path, int expand) } } +static void setup_windows_environment() +{ + /* on Windows it is TMP and TEMP */ + if (!getenv("TMPDIR")) { + const char *tmp = getenv("TMP"); + if (!tmp) + tmp = getenv("TEMP"); + if (tmp) + setenv("TMPDIR", tmp, 1); + } + + /* simulate TERM to enable auto-color (see color.c) */ + if (!getenv("TERM")) + setenv("TERM", "cygwin", 1); +} + /* * Disable MSVCRT command line wildcard expansion (__getmainargs called from * mingw startup code, see init.c in mingw runtime). @@ -2314,19 +2330,7 @@ void mingw_startup() qsort(environ, i, sizeof(char*), compareenv); /* fix Windows specific environment settings */ - - /* on Windows it is TMP and TEMP */ - if (!mingw_getenv("TMPDIR")) { - const char *tmp = mingw_getenv("TMP"); - if (!tmp) - tmp = mingw_getenv("TEMP"); - if (tmp) - setenv("TMPDIR", tmp, 1); - } - - /* simulate TERM to enable auto-color (see color.c) */ - if (!getenv("TERM")) - setenv("TERM", "cygwin", 1); + setup_windows_environment(); /* * Avoid a segmentation fault when cURL tries to set the CHARSET From 0d6d6731a3b2a7efa5e5cfbd3ff9088c366f17e1 Mon Sep 17 00:00:00 2001 From: Karsten Blees Date: Mon, 6 Apr 2015 21:47:07 +0200 Subject: [PATCH 3/5] mingw: move MSys2 specific environment tweaks to setup_windows_environment Lets keep the environment initialization and conversion section as lean as possible and move recently added tweaks to setup_windows_environment(). This fixes the following potential problems: * Prevent duplicate TZ variables if both TZ and MSYS2_TZ are set. * Some of the higher level x* APIs from wrapper.c require a working getenv(), using e.g. xstrdup() during initialization is dangerous. * Slashifying the Windows TMP variable may break native Windows programs, use POSIX TMPDIR instead. * Properly slashify TMPDIR even if it is already set, and also if we only have TEMP, but not TMP. * Reduce complexity from O(n) to O(log n). Signed-off-by: Karsten Blees --- compat/mingw.c | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/compat/mingw.c b/compat/mingw.c index 174033021dff57..216b0fa0c4f916 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -2220,15 +2220,31 @@ int handle_long_path(wchar_t *path, int len, int max_path, int expand) static void setup_windows_environment() { + char *tmp; + /* on Windows it is TMP and TEMP */ if (!getenv("TMPDIR")) { - const char *tmp = getenv("TMP"); - if (!tmp) + if (!(tmp = getenv("TMP"))) tmp = getenv("TEMP"); if (tmp) setenv("TMPDIR", tmp, 1); } + if ((tmp = getenv("TMPDIR"))) { + /* + * Convert all dir separators to forward slashes, + * to help shell commands called from the Git + * executable (by not mistaking the dir separators + * for escape characters). + */ + for (; *tmp; tmp++) + if (*tmp == '\\') + *tmp = '/'; + } + + if (!getenv("TZ") && (tmp = getenv("MSYS2_TZ"))) + setenv("TZ", tmp, 1); + /* simulate TERM to enable auto-color (see color.c) */ if (!getenv("TERM")) setenv("TERM", "cygwin", 1); @@ -2303,26 +2319,8 @@ void mingw_startup() __argv[0] = wcstoutfdup_startup(buffer, _wpgmptr, maxlen); for (i = 1; i < argc; i++) __argv[i] = wcstoutfdup_startup(buffer, wargv[i], maxlen); - for (i = 0; wenv[i]; i++) { + for (i = 0; wenv[i]; i++) environ[i] = wcstoutfdup_startup(buffer, wenv[i], maxlen); - if (!strncasecmp(environ[i], "MSYS2_TZ=", 9)) { - char *to_free = environ[i]; - environ[i] = xstrdup(to_free + 6); - free(to_free); - } - if (!strncasecmp(environ[i], "TMP=", 4)) { - /* - * Convert all dir separators to forward slashes, - * to help shell commands called from the Git - * executable (by not mistaking the dir separators - * for escape characters). - */ - char *p; - for (p = environ[i]; *p; p++) - if (*p == '\\') - *p = '/'; - } - } environ[i] = NULL; free(buffer); From a95753b365a1edcab4723c2d8cebb5c9e19272cf Mon Sep 17 00:00:00 2001 From: Karsten Blees Date: Mon, 6 Apr 2015 21:37:18 +0200 Subject: [PATCH 4/5] mingw: initialize HOME on startup HOME initialization was historically duplicated in many different places, including /etc/profile, launch scripts such as git-bash.vbs and gitk.cmd, and (although slightly broken) in the git-wrapper. Even unrelated projects such as GitExtensions and TortoiseGit need to implement the same logic to be able to call git directly. Initialize HOME in git's own startup code so that we can eventually retire all the duplicate initialization code. Signed-off-by: Karsten Blees --- compat/mingw.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/compat/mingw.c b/compat/mingw.c index 216b0fa0c4f916..41eff1d3350560 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -2248,6 +2248,30 @@ static void setup_windows_environment() /* simulate TERM to enable auto-color (see color.c) */ if (!getenv("TERM")) setenv("TERM", "cygwin", 1); + + /* calculate HOME if not set */ + if (!getenv("HOME")) { + /* + * try $HOMEDRIVE$HOMEPATH - the home share may be a network + * location, thus also check if the path exists (i.e. is not + * disconnected) + */ + if ((tmp = getenv("HOMEDRIVE"))) { + struct strbuf buf = STRBUF_INIT; + strbuf_addstr(&buf, tmp); + if ((tmp = getenv("HOMEPATH"))) { + strbuf_addstr(&buf, tmp); + if (is_directory(buf.buf)) + setenv("HOME", buf.buf, 1); + else + tmp = NULL; /* use $USERPROFILE */ + } + strbuf_release(&buf); + } + /* use $USERPROFILE if the home share is not available */ + if (!tmp && (tmp = getenv("USERPROFILE"))) + setenv("HOME", tmp, 1); + } } /* From d4e943c8e7c1432051a7b7f73fae7c3044727a14 Mon Sep 17 00:00:00 2001 From: Karsten Blees Date: Mon, 6 Apr 2015 21:20:46 +0200 Subject: [PATCH 5/5] git-wrapper: remove redundant TERM initialization Remove redundant TERM initialization from git-wrapper in favor of TERM initialization in git itself. Signed-off-by: Karsten Blees --- compat/win32/git-wrapper.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/compat/win32/git-wrapper.c b/compat/win32/git-wrapper.c index 6b2d7de4bf029e..619070b8c2b20f 100644 --- a/compat/win32/git-wrapper.c +++ b/compat/win32/git-wrapper.c @@ -48,10 +48,6 @@ static void setup_environment(LPWSTR exepath, int full_path) L"MINGW%d", (int) sizeof(void *) * 8); SetEnvironmentVariable(L"MSYSTEM", msystem); - /* if not set, set TERM to cygwin */ - if (!GetEnvironmentVariable(L"TERM", NULL, 0)) - SetEnvironmentVariable(L"TERM", L"cygwin"); - /* if not set, set PLINK_PROTOCOL to ssh */ if (!GetEnvironmentVariable(L"PLINK_PROTOCOL", NULL, 0)) SetEnvironmentVariable(L"PLINK_PROTOCOL", L"ssh");