From 26ba73098e714459e3294679228a1d54eed14799 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Fri, 6 May 2022 08:26:55 +0100 Subject: win32: search PATH for missing Unix-style executables Commit 41ef232fc5 (win32: use built-in applets for non-existent binaries with Unix-style paths) alters what happens when trying to find an executable. If all of the following apply: - the pathname starts with one of the standard directories for Unix executables (/bin, /usr/bin, /sbin, /usr/sbin); - the file isn't found relative to the system root; - the basename matches an applet then the applet is run. Further extend the procedure so that if the first two conditions are met and either: - the PREFER_APPLETS and SH_STANDALONE features are enabled and the basename *doesn't* match an applet or - the PREFER_APPLETS and SH_STANDALONE features are disabled then PATH is searched for the basename. This affects: - how interpreters and binaries are spawned by mingw_spawn_interpreter() and mingw_spawnvp(); - how 'which' and the shell search for binaries. Special steps need to be taken in the shell to avoid treating shell built-ins and functions as applets. As a consequence of this change: - An executable that isn't an applet, say curl.exe, can be run as /usr/bin/curl so long as it's in a directory in PATH. It doesn't have to be in C:/usr/bin. - If the PREFER_APPLETS and SH_STANDALONE features are disabled binaries can be run using paths referring to standard Unix directories even if they're installed elsewhere in PATH. --- shell/ash.c | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index 97075ed5f..6c1e58d6f 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -8983,6 +8983,7 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, c * have to change the find_command routine as well. * argv[-1] must exist and be writable! See tryexec() for why. */ +static struct builtincmd *find_builtin(const char *name); static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN; static void shellexec(char *prog, char **argv, const char *path, int idx) { @@ -9011,9 +9012,7 @@ static void shellexec(char *prog, char **argv, const char *path, int idx) #endif ) { #if ENABLE_PLATFORM_MINGW32 -# if ENABLE_FEATURE_SH_STANDALONE char *oldprog = prog; -# endif prog = stack_add_system_drive(prog); #endif tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp); @@ -9025,16 +9024,17 @@ static void shellexec(char *prog, char **argv, const char *path, int idx) goto try_PATH; } e = errno; -#if ENABLE_PLATFORM_MINGW32 && ENABLE_FEATURE_SH_STANDALONE - if (unix_path(oldprog)) { +#if ENABLE_PLATFORM_MINGW32 + if (unix_path(oldprog) && !find_builtin(bb_basename(oldprog))) { +# if ENABLE_FEATURE_SH_STANDALONE const char *name = bb_basename(oldprog); if ((applet_no = find_applet_by_name(name)) >= 0) { tryexec(applet_no, name, argv, envp); e = errno; } - else { - e = ENOENT; - } +# endif + argv[0] = (char *)bb_basename(oldprog); + goto try_PATH; } #endif } else { @@ -9481,6 +9481,10 @@ describe_command(char *command, const char *path, int describe_command_verbose) p = command; #endif } else { +#if ENABLE_PLATFORM_MINGW32 + if (unix_path(command)) + command = (char *)bb_basename(command); +#endif do { padvance(&path, command); } while (--j >= 0); @@ -14658,24 +14662,20 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) #else /* ENABLE_PLATFORM_MINGW32 */ /* If name contains a slash or drive prefix, don't use PATH or hash table */ if (has_path(name)) { - fullname = stack_add_system_drive(name); entry->u.index = -1; - if (act & DO_ABS) { - if (!add_win32_extension(fullname) && stat(fullname, &statb) < 0) { -# if ENABLE_FEATURE_SH_STANDALONE - if (unix_path(name) && - find_applet_by_name(bb_basename(name)) >= 0) { - entry->cmdtype = CMDNORMAL; - entry->u.index = INT_MIN; - return; - } -# endif - entry->cmdtype = CMDUNKNOWN; - return; - } - } entry->cmdtype = CMDNORMAL; - return; + fullname = stack_add_system_drive(name); + if (add_win32_extension(fullname) || file_is_executable(fullname)) { + return; + } else if (unix_path(name) && !find_builtin(bb_basename(name))) { + name = (char *)bb_basename(name); + act |= DO_NOFUNC; + } else if (act & DO_ABS) { + entry->cmdtype = CMDUNKNOWN; + return; + } else { + return; + } } #endif /* ENABLE_PLATFORM_MINGW32 */ -- cgit v1.2.3-55-g6feb