aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2020-08-13 14:27:56 +0100
committerRon Yorston <rmy@pobox.com>2020-08-13 14:58:01 +0100
commit41ef232fc522d91f29931ea4ee547432ca8899ee (patch)
treed2acfdc43839b68b569debb4494d5c7fbd8bc66b
parent16e5930a65f3c7c570b8a0dda8daa19ab4792fa2 (diff)
downloadbusybox-w32-41ef232fc522d91f29931ea4ee547432ca8899ee.tar.gz
busybox-w32-41ef232fc522d91f29931ea4ee547432ca8899ee.tar.bz2
busybox-w32-41ef232fc522d91f29931ea4ee547432ca8899ee.zip
win32: use built-in applets for non-existent binaries with Unix-style paths
Shell scripts moved from Unix may contain hard-coded paths to binaries such as /bin/sh. A recent commit made it possible to execute such binaries reliably, but that does require them to be installed. As an alternative solution: if a binary with a standard Unix path prefix can't be found but is available as a built-in applet, run the applet. Add the function unix_path() to detect paths starting with /bin, /usr/bin, /sbin or /usr/sbin. Use this function in: - the 'which' applet - shellexec(), describe_command() and find_command() in ash - mingw_spawn_1() See GitHub issue #195.
-rw-r--r--debianutils/which.c10
-rw-r--r--include/mingw.h1
-rw-r--r--shell/ash.c55
-rw-r--r--win32/mingw.c13
-rw-r--r--win32/process.c15
5 files changed, 83 insertions, 11 deletions
diff --git a/debianutils/which.c b/debianutils/which.c
index c8e99acda..384e2cfec 100644
--- a/debianutils/which.c
+++ b/debianutils/which.c
@@ -71,6 +71,10 @@ int which_main(int argc UNUSED_PARAM, char **argv)
71 if (strchr(*argv, '/')) { 71 if (strchr(*argv, '/')) {
72#else 72#else
73 if (has_path(*argv)) { 73 if (has_path(*argv)) {
74# if ENABLE_FEATURE_SH_STANDALONE
75 const char *name = bb_basename(*argv);
76 int is_unix_path = unix_path(*argv);
77# endif
74 *argv = auto_add_system_drive(*argv); 78 *argv = auto_add_system_drive(*argv);
75 if ((p=auto_win32_extension(*argv)) != NULL) { 79 if ((p=auto_win32_extension(*argv)) != NULL) {
76 missing = 0; 80 missing = 0;
@@ -86,6 +90,12 @@ int which_main(int argc UNUSED_PARAM, char **argv)
86 puts(*argv); 90 puts(*argv);
87#endif 91#endif
88 } 92 }
93#if ENABLE_PLATFORM_MINGW32 && ENABLE_FEATURE_SH_STANDALONE
94 else if (is_unix_path && find_applet_by_name(name) >= 0) {
95 missing = 0;
96 puts(name);
97 }
98#endif
89 } else { 99 } else {
90 char *path; 100 char *path;
91#if !ENABLE_PLATFORM_MINGW32 101#if !ENABLE_PLATFORM_MINGW32
diff --git a/include/mingw.h b/include/mingw.h
index 434f3a474..b34d8772c 100644
--- a/include/mingw.h
+++ b/include/mingw.h
@@ -555,4 +555,5 @@ char *get_drive_cwd(const char *path, char *buffer, int size);
555void fix_path_case(char *path); 555void fix_path_case(char *path);
556void make_sparse(int fd, off_t start, off_t end); 556void make_sparse(int fd, off_t start, off_t end);
557int skip_ansi_emulation(int reset); 557int skip_ansi_emulation(int reset);
558int unix_path(const char *path);
558int has_path(const char *file); 559int has_path(const char *file);
diff --git a/shell/ash.c b/shell/ash.c
index 0a638b1df..2267e841f 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -8754,6 +8754,9 @@ static void shellexec(char *prog, char **argv, const char *path, int idx)
8754#endif 8754#endif
8755 ) { 8755 ) {
8756#if ENABLE_PLATFORM_MINGW32 8756#if ENABLE_PLATFORM_MINGW32
8757# if ENABLE_FEATURE_SH_STANDALONE
8758 char *oldprog = prog;
8759# endif
8757 prog = auto_add_system_drive(prog); 8760 prog = auto_add_system_drive(prog);
8758#endif 8761#endif
8759 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp); 8762 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
@@ -8764,6 +8767,14 @@ static void shellexec(char *prog, char **argv, const char *path, int idx)
8764 */ 8767 */
8765 goto try_PATH; 8768 goto try_PATH;
8766 } 8769 }
8770#if ENABLE_PLATFORM_MINGW32 && ENABLE_FEATURE_SH_STANDALONE
8771 if (oldprog != prog && unix_path(oldprog)) {
8772 if ((applet_no = find_applet_by_name(bb_basename(oldprog))) >= 0)
8773 tryexec(applet_no, bb_basename(oldprog), argv, envp);
8774 else
8775 errno = ENOENT;
8776 }
8777#endif
8767 e = errno; 8778 e = errno;
8768 } else { 8779 } else {
8769 try_PATH: 8780 try_PATH:
@@ -9191,6 +9202,12 @@ describe_command(char *command, const char *path, int describe_command_verbose)
9191 case CMDNORMAL: { 9202 case CMDNORMAL: {
9192 int j = entry.u.index; 9203 int j = entry.u.index;
9193 char *p; 9204 char *p;
9205#if ENABLE_PLATFORM_MINGW32 && ENABLE_FEATURE_SH_STANDALONE
9206 if (j == INT_MIN) {
9207 p = (char *)bb_basename(command);
9208 goto describe;
9209 }
9210#endif
9194 if (j < 0) { 9211 if (j < 0) {
9195#if ENABLE_PLATFORM_MINGW32 9212#if ENABLE_PLATFORM_MINGW32
9196 /* can't use auto_add_system_drive, need space for extension */ 9213 /* can't use auto_add_system_drive, need space for extension */
@@ -9211,6 +9228,7 @@ describe_command(char *command, const char *path, int describe_command_verbose)
9211#if ENABLE_PLATFORM_MINGW32 9228#if ENABLE_PLATFORM_MINGW32
9212 add_win32_extension(p); 9229 add_win32_extension(p);
9213 bs_to_slash(p); 9230 bs_to_slash(p);
9231 IF_FEATURE_SH_STANDALONE(describe:)
9214#endif 9232#endif
9215 if (describe_command_verbose) { 9233 if (describe_command_verbose) {
9216 out1fmt(" is %s", p); 9234 out1fmt(" is %s", p);
@@ -14268,24 +14286,16 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path)
14268 struct builtincmd *bcmd; 14286 struct builtincmd *bcmd;
14269 int len; 14287 int len;
14270 14288
14289#if !ENABLE_PLATFORM_MINGW32
14271 /* If name contains a slash, don't use PATH or hash table */ 14290 /* If name contains a slash, don't use PATH or hash table */
14272#if ENABLE_PLATFORM_MINGW32
14273 if (has_path(name)) {
14274 name = auto_add_system_drive(name);
14275#else
14276 if (strchr(name, '/') != NULL) { 14291 if (strchr(name, '/') != NULL) {
14277#endif
14278 entry->u.index = -1; 14292 entry->u.index = -1;
14279 if (act & DO_ABS) { 14293 if (act & DO_ABS) {
14280#if ENABLE_PLATFORM_MINGW32
14281 if (auto_win32_extension(name) == NULL && stat(name, &statb) < 0) {
14282#else
14283 while (stat(name, &statb) < 0) { 14294 while (stat(name, &statb) < 0) {
14284#ifdef SYSV 14295#ifdef SYSV
14285 if (errno == EINTR) 14296 if (errno == EINTR)
14286 continue; 14297 continue;
14287#endif 14298#endif
14288#endif
14289 entry->cmdtype = CMDUNKNOWN; 14299 entry->cmdtype = CMDUNKNOWN;
14290 return; 14300 return;
14291 } 14301 }
@@ -14293,6 +14303,33 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path)
14293 entry->cmdtype = CMDNORMAL; 14303 entry->cmdtype = CMDNORMAL;
14294 return; 14304 return;
14295 } 14305 }
14306#else /* ENABLE_PLATFORM_MINGW32 */
14307 /* If name contains a slash or drive prefix, don't use PATH or hash table */
14308 if (has_path(name)) {
14309# if ENABLE_FEATURE_SH_STANDALONE
14310 char *oldname = name;
14311# endif
14312 name = auto_add_system_drive(name);
14313 entry->u.index = -1;
14314 if (act & DO_ABS) {
14315 if (auto_win32_extension(name) == NULL && stat(name, &statb) < 0) {
14316# if ENABLE_FEATURE_SH_STANDALONE
14317 int applet_no;
14318 if (unix_path(oldname) &&
14319 (applet_no = find_applet_by_name(bb_basename(oldname))) >= 0) {
14320 entry->cmdtype = CMDNORMAL;
14321 entry->u.index = INT_MIN;
14322 return;
14323 }
14324# endif
14325 entry->cmdtype = CMDUNKNOWN;
14326 return;
14327 }
14328 }
14329 entry->cmdtype = CMDNORMAL;
14330 return;
14331 }
14332#endif /* ENABLE_PLATFORM_MINGW32 */
14296 14333
14297/* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */ 14334/* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
14298 14335
diff --git a/win32/mingw.c b/win32/mingw.c
index e63ffa0ac..4ffc49e9a 100644
--- a/win32/mingw.c
+++ b/win32/mingw.c
@@ -1818,6 +1818,19 @@ void *get_proc_addr(const char *dll, const char *function,
1818 return proc->pfunction; 1818 return proc->pfunction;
1819} 1819}
1820 1820
1821#if ENABLE_FEATURE_SH_STANDALONE || ENABLE_FEATURE_PREFER_APPLETS
1822int unix_path(const char *path)
1823{
1824 int i;
1825 char *p = strdup(path);
1826
1827#define UNIX_PATHS "/bin\0/usr/bin\0/sbin\0/usr/sbin\0"
1828 i = index_in_strings(UNIX_PATHS, dirname(p));
1829 free(p);
1830 return i >= 0;
1831}
1832#endif
1833
1821/* Return true if file is referenced using a path. This means a path 1834/* Return true if file is referenced using a path. This means a path
1822 * look-up isn't required. */ 1835 * look-up isn't required. */
1823int has_path(const char *file) 1836int has_path(const char *file)
diff --git a/win32/process.c b/win32/process.c
index cd164e0ed..a050ec11d 100644
--- a/win32/process.c
+++ b/win32/process.c
@@ -350,6 +350,7 @@ mingw_spawn_1(int mode, const char *cmd, char *const *argv, char *const *envp)
350{ 350{
351 char *prog; 351 char *prog;
352 const char *path; 352 const char *path;
353 intptr_t ret;
353 354
354#if ENABLE_FEATURE_PREFER_APPLETS || ENABLE_FEATURE_SH_STANDALONE 355#if ENABLE_FEATURE_PREFER_APPLETS || ENABLE_FEATURE_SH_STANDALONE
355 if (find_applet_by_name(cmd) >= 0) 356 if (find_applet_by_name(cmd) >= 0)
@@ -357,12 +358,22 @@ mingw_spawn_1(int mode, const char *cmd, char *const *argv, char *const *envp)
357 else 358 else
358#endif 359#endif
359 if (has_path(cmd)) { 360 if (has_path(cmd)) {
361#if ENABLE_FEATURE_PREFER_APPLETS || ENABLE_FEATURE_SH_STANDALONE
362 const char *oldcmd = cmd;
363#endif
360 cmd = auto_add_system_drive(cmd); 364 cmd = auto_add_system_drive(cmd);
361 path = auto_win32_extension(cmd); 365 path = auto_win32_extension(cmd);
362 return mingw_spawn_interpreter(mode, path ? path : cmd, argv, envp, 0); 366 ret = mingw_spawn_interpreter(mode, path ? path : cmd, argv, envp, 0);
367#if ENABLE_FEATURE_PREFER_APPLETS || ENABLE_FEATURE_SH_STANDALONE
368 if (ret == -1 && cmd != oldcmd && unix_path(oldcmd) &&
369 find_applet_by_name(bb_basename(oldcmd))) {
370 return mingw_spawn_applet(mode, argv, envp);
371 }
372#endif
373 return ret;
363 } 374 }
364 else if ((prog=find_first_executable(cmd)) != NULL) { 375 else if ((prog=find_first_executable(cmd)) != NULL) {
365 intptr_t ret = mingw_spawn_interpreter(mode, prog, argv, envp, 0); 376 ret = mingw_spawn_interpreter(mode, prog, argv, envp, 0);
366 free(prog); 377 free(prog);
367 return ret; 378 return ret;
368 } 379 }