2626#include "../repository.h"
2727#include "compat/win32/fscache.h"
2828#include "attr.h"
29+ #include "string-list.h"
2930
3031#define HCAST (type , handle ) ((type)(intptr_t)handle)
3132
@@ -1746,6 +1747,65 @@ static char *lookup_prog(const char *dir, int dirlen, const char *cmd,
17461747 return NULL ;
17471748}
17481749
1750+ static char * path_lookup (const char * cmd , int exe_only );
1751+
1752+ static char * is_busybox_applet (const char * cmd )
1753+ {
1754+ static struct string_list applets = STRING_LIST_INIT_DUP ;
1755+ static char * busybox_path ;
1756+ static int busybox_path_initialized ;
1757+
1758+ /* Avoid infinite loop */
1759+ if (!strncasecmp (cmd , "busybox" , 7 ) &&
1760+ (!cmd [7 ] || !strcasecmp (cmd + 7 , ".exe" )))
1761+ return NULL ;
1762+
1763+ if (!busybox_path_initialized ) {
1764+ busybox_path = path_lookup ("busybox.exe" , 1 );
1765+ busybox_path_initialized = 1 ;
1766+ }
1767+
1768+ /* Assume that sh is compiled in... */
1769+ if (!busybox_path || !strcasecmp (cmd , "sh" ))
1770+ return xstrdup_or_null (busybox_path );
1771+
1772+ if (!applets .nr ) {
1773+ struct child_process cp = CHILD_PROCESS_INIT ;
1774+ struct strbuf buf = STRBUF_INIT ;
1775+ char * p ;
1776+
1777+ strvec_pushl (& cp .args , busybox_path , "--help" , NULL );
1778+
1779+ if (capture_command (& cp , & buf , 2048 )) {
1780+ string_list_append (& applets , "" );
1781+ return NULL ;
1782+ }
1783+
1784+ /* parse output */
1785+ p = strstr (buf .buf , "Currently defined functions:\n" );
1786+ if (!p ) {
1787+ warning ("Could not parse output of busybox --help" );
1788+ string_list_append (& applets , "" );
1789+ return NULL ;
1790+ }
1791+ p = strchrnul (p , '\n' );
1792+ for (;;) {
1793+ size_t len ;
1794+
1795+ p += strspn (p , "\n\t ," );
1796+ len = strcspn (p , "\n\t ," );
1797+ if (!len )
1798+ break ;
1799+ p [len ] = '\0' ;
1800+ string_list_insert (& applets , p );
1801+ p = p + len + 1 ;
1802+ }
1803+ }
1804+
1805+ return string_list_has_string (& applets , cmd ) ?
1806+ xstrdup (busybox_path ) : NULL ;
1807+ }
1808+
17491809/*
17501810 * Determines the absolute path of cmd using the split path in path.
17511811 * If cmd contains a slash or backslash, no lookup is performed.
@@ -1774,6 +1834,9 @@ static char *path_lookup(const char *cmd, int exe_only)
17741834 path = sep + 1 ;
17751835 }
17761836
1837+ if (!prog && !isexe )
1838+ prog = is_busybox_applet (cmd );
1839+
17771840 return prog ;
17781841}
17791842
@@ -1977,8 +2040,8 @@ static int is_msys2_sh(const char *cmd)
19772040}
19782041
19792042static pid_t mingw_spawnve_fd (const char * cmd , const char * * argv , char * * deltaenv ,
1980- const char * dir ,
1981- int prepend_cmd , int fhin , int fhout , int fherr )
2043+ const char * dir , const char * prepend_cmd ,
2044+ int fhin , int fhout , int fherr )
19822045{
19832046 static int restrict_handle_inheritance = -1 ;
19842047 STARTUPINFOEXW si ;
@@ -2069,9 +2132,9 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaen
20692132 /* concatenate argv, quoting args as we go */
20702133 strbuf_init (& args , 0 );
20712134 if (prepend_cmd ) {
2072- char * quoted = (char * )quote_arg (cmd );
2135+ char * quoted = (char * )quote_arg (prepend_cmd );
20732136 strbuf_addstr (& args , quoted );
2074- if (quoted != cmd )
2137+ if (quoted != prepend_cmd )
20752138 free (quoted );
20762139 }
20772140 for (; * argv ; argv ++ ) {
@@ -2230,7 +2293,8 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaen
22302293 return (pid_t )pi .dwProcessId ;
22312294}
22322295
2233- static pid_t mingw_spawnv (const char * cmd , const char * * argv , int prepend_cmd )
2296+ static pid_t mingw_spawnv (const char * cmd , const char * * argv ,
2297+ const char * prepend_cmd )
22342298{
22352299 return mingw_spawnve_fd (cmd , argv , NULL , NULL , prepend_cmd , 0 , 1 , 2 );
22362300}
@@ -2258,14 +2322,14 @@ pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **deltaenv,
22582322 pid = -1 ;
22592323 }
22602324 else {
2261- pid = mingw_spawnve_fd (iprog , argv , deltaenv , dir , 1 ,
2325+ pid = mingw_spawnve_fd (iprog , argv , deltaenv , dir , interpr ,
22622326 fhin , fhout , fherr );
22632327 free (iprog );
22642328 }
22652329 argv [0 ] = argv0 ;
22662330 }
22672331 else
2268- pid = mingw_spawnve_fd (prog , argv , deltaenv , dir , 0 ,
2332+ pid = mingw_spawnve_fd (prog , argv , deltaenv , dir , NULL ,
22692333 fhin , fhout , fherr );
22702334 free (prog );
22712335 }
@@ -2290,7 +2354,7 @@ static int try_shell_exec(const char *cmd, char *const *argv)
22902354 argv2 [0 ] = (char * )cmd ; /* full path to the script file */
22912355 COPY_ARRAY (& argv2 [1 ], & argv [1 ], argc );
22922356 exec_id = trace2_exec (prog , (const char * * )argv2 );
2293- pid = mingw_spawnv (prog , (const char * * )argv2 , 1 );
2357+ pid = mingw_spawnv (prog , (const char * * )argv2 , interpr );
22942358 if (pid >= 0 ) {
22952359 int status ;
22962360 if (waitpid (pid , & status , 0 ) < 0 )
@@ -2314,7 +2378,7 @@ int mingw_execv(const char *cmd, char *const *argv)
23142378 int exec_id ;
23152379
23162380 exec_id = trace2_exec (cmd , (const char * * )argv );
2317- pid = mingw_spawnv (cmd , (const char * * )argv , 0 );
2381+ pid = mingw_spawnv (cmd , (const char * * )argv , NULL );
23182382 if (pid < 0 ) {
23192383 trace2_exec_result (exec_id , -1 );
23202384 return -1 ;
0 commit comments