@@ -1155,6 +1155,10 @@ static int do_putenv(char **env, const char *name, int size, int free_old);
11551155static int environ_size = 0 ;
11561156/* allocated size of environ array, in bytes */
11571157static int environ_alloc = 0 ;
1158+ /* used as a indicator when the environment has been changed outside mingw.c */
1159+ static char * * saved_environ ;
1160+
1161+ static void maybe_reinitialize_environ (void );
11581162
11591163/*
11601164 * Create environment block suitable for CreateProcess. Merges current
@@ -1164,21 +1168,24 @@ static wchar_t *make_environment_block(char **deltaenv)
11641168{
11651169 wchar_t * wenvblk = NULL ;
11661170 char * * tmpenv ;
1167- int i = 0 , size = environ_size , wenvsz = 0 , wenvpos = 0 ;
1171+ int i = 0 , size , wenvsz = 0 , wenvpos = 0 ;
1172+
1173+ maybe_reinitialize_environ ();
1174+ size = environ_size ;
11681175
1169- while (deltaenv && deltaenv [i ])
1176+ while (deltaenv && deltaenv [i ] && * deltaenv [ i ] )
11701177 i ++ ;
11711178
11721179 /* copy the environment, leaving space for changes */
11731180 ALLOC_ARRAY (tmpenv , size + i );
11741181 memcpy (tmpenv , environ , size * sizeof (char * ));
11751182
11761183 /* merge supplied environment changes into the temporary environment */
1177- for (i = 0 ; deltaenv && deltaenv [i ]; i ++ )
1184+ for (i = 0 ; deltaenv && deltaenv [i ] && * deltaenv [ i ] ; i ++ )
11781185 size = do_putenv (tmpenv , deltaenv [i ], size , 0 );
11791186
11801187 /* create environment block from temporary environment */
1181- for (i = 0 ; tmpenv [i ]; i ++ ) {
1188+ for (i = 0 ; tmpenv [i ] && * tmpenv [ i ] ; i ++ ) {
11821189 size = 2 * strlen (tmpenv [i ]) + 2 ; /* +2 for final \0 */
11831190 ALLOC_GROW (wenvblk , (wenvpos + size ) * sizeof (wchar_t ), wenvsz );
11841191 wenvpos += xutftowcs (& wenvblk [wenvpos ], tmpenv [i ], size ) + 1 ;
@@ -1259,6 +1266,7 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaen
12591266 HANDLE cons ;
12601267 const char * (* quote_arg )(const char * arg ) =
12611268 is_msys2_sh (* argv ) ? quote_arg_msys2 : quote_arg_msvc ;
1269+ const char * strace_env ;
12621270
12631271 do_unset_environment_variables ();
12641272
@@ -1316,6 +1324,31 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaen
13161324 free (quoted );
13171325 }
13181326
1327+ strace_env = getenv ("GIT_STRACE_COMMANDS" );
1328+ if (strace_env ) {
1329+ char * p = path_lookup ("strace.exe" , 1 );
1330+ if (!p )
1331+ return error ("strace not found!" );
1332+ if (xutftowcs_path (wcmd , p ) < 0 ) {
1333+ free (p );
1334+ return -1 ;
1335+ }
1336+ free (p );
1337+ if (!strcmp ("1" , strace_env ) ||
1338+ !strcasecmp ("yes" , strace_env ) ||
1339+ !strcasecmp ("true" , strace_env ))
1340+ strbuf_insert (& args , 0 , "strace " , 7 );
1341+ else {
1342+ const char * quoted = quote_arg (strace_env );
1343+ struct strbuf buf = STRBUF_INIT ;
1344+ strbuf_addf (& buf , "strace -o %s " , quoted );
1345+ if (quoted != strace_env )
1346+ free ((char * )quoted );
1347+ strbuf_insert (& args , 0 , buf .buf , buf .len );
1348+ strbuf_release (& buf );
1349+ }
1350+ }
1351+
13191352 ALLOC_ARRAY (wargs , st_add (st_mult (2 , args .len ), 1 ));
13201353 xutftowcs (wargs , args .buf , 2 * args .len + 1 );
13211354 strbuf_release (& args );
@@ -1504,6 +1537,41 @@ static int compareenv(const void *v1, const void *v2)
15041537 }
15051538}
15061539
1540+ /*
1541+ * Functions implemented outside Git are able to modify the environment,
1542+ * too. For example, cURL's curl_global_init() function sets the CHARSET
1543+ * environment variable (at least in certain circumstances).
1544+ *
1545+ * Therefore we need to be *really* careful *not* to assume that we have
1546+ * sole control over the environment and reinitialize it when necessary.
1547+ */
1548+ static void maybe_reinitialize_environ (void )
1549+ {
1550+ int i ;
1551+
1552+ if (!saved_environ ) {
1553+ warning ("MinGW environment not initialized yet" );
1554+ return ;
1555+ }
1556+
1557+ if (environ_size <= 0 )
1558+ return ;
1559+
1560+ if (saved_environ != environ )
1561+ /* We have *no* idea how much space was allocated outside */
1562+ environ_alloc = 0 ;
1563+ else if (!environ [environ_size - 1 ])
1564+ return ; /* still consistent */
1565+
1566+ for (i = 0 ; environ [i ] && * environ [i ]; i ++ )
1567+ ; /* continue counting */
1568+ environ [i ] = NULL ;
1569+ environ_size = i + 1 ;
1570+
1571+ /* sort environment for O(log n) getenv / putenv */
1572+ qsort (environ , i , sizeof (char * ), compareenv );
1573+ }
1574+
15071575static int bsearchenv (char * * env , const char * name , size_t size )
15081576{
15091577 unsigned low = 0 , high = size ;
@@ -1527,7 +1595,7 @@ static int bsearchenv(char **env, const char *name, size_t size)
15271595 */
15281596static int do_putenv (char * * env , const char * name , int size , int free_old )
15291597{
1530- int i = bsearchenv (env , name , size - 1 );
1598+ int i = size <= 0 ? -1 : bsearchenv (env , name , size - 1 );
15311599
15321600 /* optionally free removed / replaced entry */
15331601 if (i >= 0 && free_old )
@@ -1552,7 +1620,14 @@ static int do_putenv(char **env, const char *name, int size, int free_old)
15521620char * mingw_getenv (const char * name )
15531621{
15541622 char * value ;
1555- int pos = bsearchenv (environ , name , environ_size - 1 );
1623+ int pos ;
1624+
1625+ if (environ_size <= 0 )
1626+ return NULL ;
1627+
1628+ maybe_reinitialize_environ ();
1629+ pos = bsearchenv (environ , name , environ_size - 1 );
1630+
15561631 if (pos < 0 )
15571632 return NULL ;
15581633 value = strchr (environ [pos ], '=' );
@@ -1561,7 +1636,9 @@ char *mingw_getenv(const char *name)
15611636
15621637int mingw_putenv (const char * namevalue )
15631638{
1639+ maybe_reinitialize_environ ();
15641640 ALLOC_GROW (environ , (environ_size + 1 ) * sizeof (char * ), environ_alloc );
1641+ saved_environ = environ ;
15651642 environ_size = do_putenv (environ , namevalue , environ_size , 1 );
15661643 return 0 ;
15671644}
@@ -2351,6 +2428,33 @@ static void setup_windows_environment(void)
23512428 /* simulate TERM to enable auto-color (see color.c) */
23522429 if (!getenv ("TERM" ))
23532430 setenv ("TERM" , "cygwin" , 1 );
2431+
2432+ /* calculate HOME if not set */
2433+ if (!getenv ("HOME" )) {
2434+ /*
2435+ * try $HOMEDRIVE$HOMEPATH - the home share may be a network
2436+ * location, thus also check if the path exists (i.e. is not
2437+ * disconnected)
2438+ */
2439+ if ((tmp = getenv ("HOMEDRIVE" ))) {
2440+ struct strbuf buf = STRBUF_INIT ;
2441+ strbuf_addstr (& buf , tmp );
2442+ if ((tmp = getenv ("HOMEPATH" ))) {
2443+ strbuf_addstr (& buf , tmp );
2444+ if (is_directory (buf .buf ))
2445+ setenv ("HOME" , buf .buf , 1 );
2446+ else
2447+ tmp = NULL ; /* use $USERPROFILE */
2448+ }
2449+ strbuf_release (& buf );
2450+ }
2451+ /* use $USERPROFILE if the home share is not available */
2452+ if (!tmp && (tmp = getenv ("USERPROFILE" )))
2453+ setenv ("HOME" , tmp , 1 );
2454+ }
2455+
2456+ if (!getenv ("LC_ALL" ) && !getenv ("LC_CTYPE" ) && !getenv ("LANG" ))
2457+ setenv ("LC_CTYPE" , "C" , 1 );
23542458}
23552459
23562460int handle_long_path (wchar_t * path , int len , int max_path , int expand )
@@ -2532,7 +2636,7 @@ void mingw_startup(void)
25322636 */
25332637 environ_size = i + 1 ;
25342638 environ_alloc = alloc_nr (environ_size * sizeof (char * ));
2535- environ = malloc_startup (environ_alloc );
2639+ saved_environ = environ = malloc_startup (environ_alloc );
25362640
25372641 /* allocate buffer (wchar_t encodes to max 3 UTF-8 bytes) */
25382642 maxlen = 3 * maxlen + 1 ;
@@ -2554,6 +2658,17 @@ void mingw_startup(void)
25542658
25552659 unset_environment_variables = xstrdup ("PERL5LIB" );
25562660
2661+ /*
2662+ * Avoid a segmentation fault when cURL tries to set the CHARSET
2663+ * variable and putenv() barfs at our nedmalloc'ed environment.
2664+ */
2665+ if (!getenv ("CHARSET" )) {
2666+ struct strbuf buf = STRBUF_INIT ;
2667+ strbuf_addf (& buf , "cp%u" , GetACP ());
2668+ setenv ("CHARSET" , buf .buf , 1 );
2669+ strbuf_release (& buf );
2670+ }
2671+
25572672 /* initialize critical section for waitpid pinfo_t list */
25582673 InitializeCriticalSection (& pinfo_cs );
25592674
0 commit comments