Windows: teach getenv to do a case-sensitive search

getenv() on Windows looks up environment variables in a case-insensitive manner. Even though all documentations claim that the environment is case-insensitive, it is possible for applications to pass an environment to child processes that has variables that differ only in case. Bash on Windows does this, for example, and sh-i18n--envsubst depends on this behavior. With this patch environment variables are first looked up in a case-sensitive manner; only if this finds nothing, the system's getenv() is used as a fallback. Signed-off-by: Johannes Sixt <j6t@kdbg.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Johannes Sixt committed Jun 6, 2011 at 09:08 UTC df599e9612788b728ce43a03159b85f1fe624d6a
1 file changed +20 -3
compat/mingw.c
+20 -3
@@ -1116,14 +1116,31 @@ char **make_augmented_environ(const char *const *vars)
1116 }
1117
1118 #undef getenv
1119 +
1120 +/*
1121 + * The system's getenv looks up the name in a case-insensitive manner.
1122 + * This version tries a case-sensitive lookup and falls back to
1123 + * case-insensitive if nothing was found. This is necessary because,
1124 + * as a prominent example, CMD sets 'Path', but not 'PATH'.
1125 + * Warning: not thread-safe.
1126 + */
1127 +static char *getenv_cs(const char *name)
1128 +{
1129 + size_t len = strlen(name);
1130 + int i = lookup_env(environ, name, len);
1131 + if (i >= 0)
1132 + return environ[i] + len + 1; /* skip past name and '=' */
1133 + return getenv(name);
1134 +}
1135 +
1136 char *mingw_getenv(const char *name)
1137 {
1121 - char *result = getenv(name);
1138 + char *result = getenv_cs(name);
1139 if (!result && !strcmp(name, "TMPDIR")) {
1140 /* on Windows it is TMP and TEMP */
1124 - result = getenv("TMP");
1141 + result = getenv_cs("TMP");
1142 if (!result)
1126 - result = getenv("TEMP");
1143 + result = getenv_cs("TEMP");
1144 }
1145 return result;
1146 }