Win32: Unicode environment (incoming)

Convert environment from UTF-16 to UTF-8 on startup. No changes to getenv() are necessary, as the MSVCRT version is implemented on top of char **environ. However, putenv / _wputenv from MSVCRT no longer work, for two reasons: 1. they try to keep environ, _wenviron and the Win32 process environment in sync, using the default system encoding instead of UTF-8 to convert between charsets 2. msysgit and MSVCRT use different allocators, memory allocated in git cannot be freed by the CRT and vice versa Implement mingw_putenv using the env_setenv helper function from the environment merge code. Note that in case of memory allocation failure, putenv now dies with error message (due to xrealloc) instead of failing with ENOMEM. As git assumes setenv / putenv to always succeed, this prevents it from continuing with incorrect settings. Signed-off-by: Karsten Blees <blees@dcon.de> Signed-off-by: Stepan Kasal <kasal@ucw.cz> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Karsten Blees committed Jul 17, 2014 at 17:37 UTC b729f98fa50b10cfba7cbf3f37a0ac255e1fbdcd
2 files changed +17
compat/mingw.c
+15
@@ -1260,6 +1260,12 @@ char *mingw_getenv(const char *name)
1260 return result;
1261 }
1262
1263 +int mingw_putenv(const char *namevalue)
1264 +{
1265 + environ = env_setenv(environ, namevalue);
1266 + return 0;
1267 +}
1268 +
1269 /*
1270 * Note, this isn't a complete replacement for getaddrinfo. It assumes
1271 * that service contains a numerical port, or that it is null. It
@@ -2052,6 +2058,11 @@ void mingw_startup()
2058 maxlen = wcslen(_wpgmptr);
2059 for (i = 1; i < argc; i++)
2060 maxlen = max(maxlen, wcslen(wargv[i]));
2061 + for (i = 0; wenv[i]; i++)
2062 + maxlen = max(maxlen, wcslen(wenv[i]));
2063 +
2064 + /* nedmalloc can't free CRT memory, allocate resizable environment list */
2065 + environ = xcalloc(i + 1, sizeof(char*));
2066
2067 /* allocate buffer (wchar_t encodes to max 3 UTF-8 bytes) */
2068 maxlen = 3 * maxlen + 1;
@@ -2064,6 +2075,10 @@ void mingw_startup()
2075 len = xwcstoutf(buffer, wargv[i], maxlen);
2076 __argv[i] = xmemdupz(buffer, len);
2077 }
2078 + for (i = 0; wenv[i]; i++) {
2079 + len = xwcstoutf(buffer, wenv[i], maxlen);
2080 + environ[i] = xmemdupz(buffer, len);
2081 + }
2082 free(buffer);
2083
2084 /* initialize critical section for waitpid pinfo_t list */
compat/mingw.h
+2
@@ -207,6 +207,8 @@ char *mingw_getcwd(char *pointer, int len);
207
208 char *mingw_getenv(const char *name);
209 #define getenv mingw_getenv
210 +int mingw_putenv(const char *namevalue);
211 +#define putenv mingw_putenv
212
213 int mingw_gethostname(char *host, int namelen);
214 #define gethostname mingw_gethostname