1111#include "dir.h"
1212#include "win32/fscache.h"
1313#include "../attr.h"
14+ #include "../string-list.h"
1415
1516#define HCAST (type , handle ) ((type)(intptr_t)handle)
1617
@@ -1538,6 +1539,65 @@ static char *lookup_prog(const char *dir, int dirlen, const char *cmd,
15381539 return NULL ;
15391540}
15401541
1542+ static char * path_lookup (const char * cmd , int exe_only );
1543+
1544+ static char * is_busybox_applet (const char * cmd )
1545+ {
1546+ static struct string_list applets = STRING_LIST_INIT_DUP ;
1547+ static char * busybox_path ;
1548+ static int busybox_path_initialized ;
1549+
1550+ /* Avoid infinite loop */
1551+ if (!strncasecmp (cmd , "busybox" , 7 ) &&
1552+ (!cmd [7 ] || !strcasecmp (cmd + 7 , ".exe" )))
1553+ return NULL ;
1554+
1555+ if (!busybox_path_initialized ) {
1556+ busybox_path = path_lookup ("busybox.exe" , 1 );
1557+ busybox_path_initialized = 1 ;
1558+ }
1559+
1560+ /* Assume that sh is compiled in... */
1561+ if (!busybox_path || !strcasecmp (cmd , "sh" ))
1562+ return xstrdup_or_null (busybox_path );
1563+
1564+ if (!applets .nr ) {
1565+ struct child_process cp = CHILD_PROCESS_INIT ;
1566+ struct strbuf buf = STRBUF_INIT ;
1567+ char * p ;
1568+
1569+ strvec_pushl (& cp .args , busybox_path , "--help" , NULL );
1570+
1571+ if (capture_command (& cp , & buf , 2048 )) {
1572+ string_list_append (& applets , "" );
1573+ return NULL ;
1574+ }
1575+
1576+ /* parse output */
1577+ p = strstr (buf .buf , "Currently defined functions:\n" );
1578+ if (!p ) {
1579+ warning ("Could not parse output of busybox --help" );
1580+ string_list_append (& applets , "" );
1581+ return NULL ;
1582+ }
1583+ p = strchrnul (p , '\n' );
1584+ for (;;) {
1585+ size_t len ;
1586+
1587+ p += strspn (p , "\n\t ," );
1588+ len = strcspn (p , "\n\t ," );
1589+ if (!len )
1590+ break ;
1591+ p [len ] = '\0' ;
1592+ string_list_insert (& applets , p );
1593+ p = p + len + 1 ;
1594+ }
1595+ }
1596+
1597+ return string_list_has_string (& applets , cmd ) ?
1598+ xstrdup (busybox_path ) : NULL ;
1599+ }
1600+
15411601/*
15421602 * Determines the absolute path of cmd using the split path in path.
15431603 * If cmd contains a slash or backslash, no lookup is performed.
@@ -1566,6 +1626,9 @@ static char *path_lookup(const char *cmd, int exe_only)
15661626 path = sep + 1 ;
15671627 }
15681628
1629+ if (!prog && !isexe )
1630+ prog = is_busybox_applet (cmd );
1631+
15691632 return prog ;
15701633}
15711634
@@ -1765,8 +1828,8 @@ static int is_msys2_sh(const char *cmd)
17651828}
17661829
17671830static pid_t mingw_spawnve_fd (const char * cmd , const char * * argv , char * * deltaenv ,
1768- const char * dir ,
1769- int prepend_cmd , int fhin , int fhout , int fherr )
1831+ const char * dir , const char * prepend_cmd ,
1832+ int fhin , int fhout , int fherr )
17701833{
17711834 static int restrict_handle_inheritance = -1 ;
17721835 STARTUPINFOEXW si ;
@@ -1857,9 +1920,9 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaen
18571920 /* concatenate argv, quoting args as we go */
18581921 strbuf_init (& args , 0 );
18591922 if (prepend_cmd ) {
1860- char * quoted = (char * )quote_arg (cmd );
1923+ char * quoted = (char * )quote_arg (prepend_cmd );
18611924 strbuf_addstr (& args , quoted );
1862- if (quoted != cmd )
1925+ if (quoted != prepend_cmd )
18631926 free (quoted );
18641927 }
18651928 for (; * argv ; argv ++ ) {
@@ -2018,7 +2081,8 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaen
20182081 return (pid_t )pi .dwProcessId ;
20192082}
20202083
2021- static pid_t mingw_spawnv (const char * cmd , const char * * argv , int prepend_cmd )
2084+ static pid_t mingw_spawnv (const char * cmd , const char * * argv ,
2085+ const char * prepend_cmd )
20222086{
20232087 return mingw_spawnve_fd (cmd , argv , NULL , NULL , prepend_cmd , 0 , 1 , 2 );
20242088}
@@ -2046,14 +2110,14 @@ pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **deltaenv,
20462110 pid = -1 ;
20472111 }
20482112 else {
2049- pid = mingw_spawnve_fd (iprog , argv , deltaenv , dir , 1 ,
2113+ pid = mingw_spawnve_fd (iprog , argv , deltaenv , dir , interpr ,
20502114 fhin , fhout , fherr );
20512115 free (iprog );
20522116 }
20532117 argv [0 ] = argv0 ;
20542118 }
20552119 else
2056- pid = mingw_spawnve_fd (prog , argv , deltaenv , dir , 0 ,
2120+ pid = mingw_spawnve_fd (prog , argv , deltaenv , dir , NULL ,
20572121 fhin , fhout , fherr );
20582122 free (prog );
20592123 }
@@ -2081,7 +2145,7 @@ static int try_shell_exec(const char *cmd, char *const *argv)
20812145 argv2 [0 ] = (char * )cmd ; /* full path to the script file */
20822146 COPY_ARRAY (& argv2 [1 ], & argv [1 ], argc );
20832147 exec_id = trace2_exec (prog , argv2 );
2084- pid = mingw_spawnv (prog , argv2 , 1 );
2148+ pid = mingw_spawnv (prog , argv2 , interpr );
20852149 if (pid >= 0 ) {
20862150 int status ;
20872151 if (waitpid (pid , & status , 0 ) < 0 )
@@ -2105,7 +2169,7 @@ int mingw_execv(const char *cmd, char *const *argv)
21052169 int exec_id ;
21062170
21072171 exec_id = trace2_exec (cmd , (const char * * )argv );
2108- pid = mingw_spawnv (cmd , (const char * * )argv , 0 );
2172+ pid = mingw_spawnv (cmd , (const char * * )argv , NULL );
21092173 if (pid < 0 ) {
21102174 trace2_exec_result (exec_id , -1 );
21112175 return -1 ;
0 commit comments