aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2022-05-01 10:20:16 +0100
committerRon Yorston <rmy@pobox.com>2022-05-01 11:03:10 +0100
commit6d87be4d760ceda18d354c6d4c523a9adf50c04b (patch)
treeca286c74b3d0689591ce7bee6a9b98af93e15e21
parentae61e126ee8e8200e87f285d9c410eb377505578 (diff)
downloadbusybox-w32-6d87be4d760ceda18d354c6d4c523a9adf50c04b.tar.gz
busybox-w32-6d87be4d760ceda18d354c6d4c523a9adf50c04b.tar.bz2
busybox-w32-6d87be4d760ceda18d354c6d4c523a9adf50c04b.zip
which,ash: changes to which/command/type
Change how 'which' detects if it was run from a standalone shell: the shell passes the undocumented '-s' option. This is stricter and more reliable than the previous method of checking the name of the binary. Add a function to determine the binary associated with a given applet name. This makes it possible for 'which' and 'command -v' to list the correct binary even for applets other than 'busybox'. For example, when the binary is called 'sh.exe' 'which sh' will report its path. In standalone shell mode 'command -V' and 'type' now report "xxx is a builtin applet" rather than "xxx is xxx", which is true but not very illuminating. (GitHub issue #248)
-rw-r--r--debianutils/which.c50
-rw-r--r--include/mingw.h1
-rw-r--r--shell/ash.c18
-rw-r--r--win32/mingw.c21
4 files changed, 67 insertions, 23 deletions
diff --git a/debianutils/which.c b/debianutils/which.c
index 815ac71da..d00b92e0b 100644
--- a/debianutils/which.c
+++ b/debianutils/which.c
@@ -12,7 +12,12 @@
12//config: which is used to find programs in your PATH and 12//config: which is used to find programs in your PATH and
13//config: print out their pathnames. 13//config: print out their pathnames.
14 14
15//applet:IF_WHICH(APPLET_NOFORK(which, which, BB_DIR_USR_BIN, BB_SUID_DROP, which)) 15// NOTE: For WIN32 this applet is NOEXEC as alloc_system_drive() and
16// find_executable() both allocate memory. And find_executable()
17// calls alloc_system_drive().
18
19//applet:IF_PLATFORM_MINGW32(IF_WHICH(APPLET_NOEXEC(which, which, BB_DIR_USR_BIN, BB_SUID_DROP, which)))
20//applet:IF_PLATFORM_POSIX(IF_WHICH(APPLET_NOFORK(which, which, BB_DIR_USR_BIN, BB_SUID_DROP, which)))
16 21
17//kbuild:lib-$(CONFIG_WHICH) += which.o 22//kbuild:lib-$(CONFIG_WHICH) += which.o
18 23
@@ -28,6 +33,13 @@
28 33
29#include "libbb.h" 34#include "libbb.h"
30 35
36#if ENABLE_PLATFORM_MINGW32 && ENABLE_FEATURE_SH_STANDALONE
37enum {
38 OPT_a = (1 << 0),
39 OPT_s = (1 << 1)
40};
41#endif
42
31int which_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 43int which_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
32int which_main(int argc UNUSED_PARAM, char **argv) 44int which_main(int argc UNUSED_PARAM, char **argv)
33{ 45{
@@ -36,9 +48,7 @@ int which_main(int argc UNUSED_PARAM, char **argv)
36 /* This sizeof(): bb_default_root_path is shorter than BB_PATH_ROOT_PATH */ 48 /* This sizeof(): bb_default_root_path is shorter than BB_PATH_ROOT_PATH */
37 char buf[sizeof(BB_PATH_ROOT_PATH)]; 49 char buf[sizeof(BB_PATH_ROOT_PATH)];
38#if ENABLE_PLATFORM_MINGW32 && ENABLE_FEATURE_SH_STANDALONE 50#if ENABLE_PLATFORM_MINGW32 && ENABLE_FEATURE_SH_STANDALONE
39 /* If we were run as 'which.exe' skip standalone shell behaviour */ 51 int sh_standalone;
40 int sh_standalone =
41 is_suffixed_with_case(bb_busybox_exec_path, "which.exe") == NULL;
42#endif 52#endif
43 53
44 env_path = getenv("PATH"); 54 env_path = getenv("PATH");
@@ -46,28 +56,25 @@ int which_main(int argc UNUSED_PARAM, char **argv)
46 /* env_path must be writable, and must not alloc, so... */ 56 /* env_path must be writable, and must not alloc, so... */
47 env_path = strcpy(buf, bb_default_root_path); 57 env_path = strcpy(buf, bb_default_root_path);
48 58
59#if ENABLE_PLATFORM_MINGW32 && ENABLE_FEATURE_SH_STANDALONE
60 /* '-s' option indicates we were run from a standalone shell */
61 getopt32(argv, "^" "as" "\0" "-1"/*at least one arg*/);
62 sh_standalone = option_mask32 & OPT_s;
63 option_mask32 &= ~OPT_s;
64#else
49 getopt32(argv, "^" "a" "\0" "-1"/*at least one arg*/); 65 getopt32(argv, "^" "a" "\0" "-1"/*at least one arg*/);
66#endif
50 argv += optind; 67 argv += optind;
51 68
52 do { 69 do {
53 int missing = 1; 70 int missing = 1;
54 71
55#if ENABLE_PLATFORM_MINGW32 && ENABLE_FEATURE_SH_STANDALONE 72#if ENABLE_PLATFORM_MINGW32 && ENABLE_FEATURE_SH_STANDALONE
56 if (sh_standalone) { 73 if (sh_standalone && find_applet_by_name(*argv) >= 0) {
57 if (strcmp(*argv, "busybox") == 0 && 74 missing = 0;
58 is_prefixed_with_case(bb_basename(bb_busybox_exec_path), 75 puts(applet_to_exe(*argv));
59 "busybox")) { 76 if (!option_mask32) /* -a not set */
60 missing = 0; 77 break;
61 puts(bb_busybox_exec_path);
62 if (!option_mask32) /* -a not set */
63 break;
64 }
65 else if (find_applet_by_name(*argv) >= 0) {
66 missing = 0;
67 puts(*argv);
68 if (!option_mask32) /* -a not set */
69 break;
70 }
71 } 78 }
72#endif 79#endif
73 80
@@ -87,15 +94,16 @@ int which_main(int argc UNUSED_PARAM, char **argv)
87 puts(bs_to_slash(path)); 94 puts(bs_to_slash(path));
88 } 95 }
89# if ENABLE_FEATURE_SH_STANDALONE 96# if ENABLE_FEATURE_SH_STANDALONE
90 else if (sh_standalone) { 97 else if (sh_standalone && unix_path(*argv)) {
91 const char *name = bb_basename(*argv); 98 const char *name = bb_basename(*argv);
92 99
93 if (unix_path(*argv) && find_applet_by_name(name) >= 0) { 100 if (find_applet_by_name(name) >= 0) {
94 missing = 0; 101 missing = 0;
95 puts(name); 102 puts(name);
96 } 103 }
97 } 104 }
98# endif 105# endif
106 free(path);
99#endif 107#endif
100 } else { 108 } else {
101 char *path; 109 char *path;
diff --git a/include/mingw.h b/include/mingw.h
index 8a9610898..5e01b874e 100644
--- a/include/mingw.h
+++ b/include/mingw.h
@@ -584,3 +584,4 @@ int unix_path(const char *path);
584int has_path(const char *file); 584int has_path(const char *file);
585int is_relative_path(const char *path); 585int is_relative_path(const char *path);
586char *get_last_slash(const char *path); 586char *get_last_slash(const char *path);
587const char *applet_to_exe(const char *name);
diff --git a/shell/ash.c b/shell/ash.c
index afb865146..97075ed5f 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -8904,6 +8904,16 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, c
8904 (fs && fs->fpid == FS_SHELLEXEC)) { 8904 (fs && fs->fpid == FS_SHELLEXEC)) {
8905 /* mingw-w64's getopt() uses __argv[0] as the program name */ 8905 /* mingw-w64's getopt() uses __argv[0] as the program name */
8906 __argv[0] = (char *)cmd; 8906 __argv[0] = (char *)cmd;
8907 /* 'which' wants to know if it was invoked from a standalone
8908 * shell. Use the spare element of argv to add a flag, but
8909 * not if the first argument is '--help', that's a special
8910 * case. */
8911 if (strcmp(argv[0], "which") == 0 &&
8912 (argv[1] == NULL || strcmp(argv[1], "--help") != 0)) {
8913 --argv;
8914 argv[0] = argv[1];
8915 argv[1] = (char *)"-s";
8916 }
8907# else 8917# else
8908 if (APPLET_IS_NOEXEC(applet_no)) { 8918 if (APPLET_IS_NOEXEC(applet_no)) {
8909# endif 8919# endif
@@ -9456,7 +9466,12 @@ describe_command(char *command, const char *path, int describe_command_verbose)
9456#if ENABLE_PLATFORM_MINGW32 && ENABLE_FEATURE_SH_STANDALONE 9466#if ENABLE_PLATFORM_MINGW32 && ENABLE_FEATURE_SH_STANDALONE
9457 if (j < -1) { 9467 if (j < -1) {
9458 p = (char *)bb_basename(command); 9468 p = (char *)bb_basename(command);
9459 goto describe; 9469 if (describe_command_verbose) {
9470 out1fmt(" is a builtin applet");
9471 } else {
9472 out1str(applet_to_exe(p));
9473 }
9474 break;
9460 } 9475 }
9461#endif 9476#endif
9462 if (j < 0) { 9477 if (j < 0) {
@@ -9474,7 +9489,6 @@ describe_command(char *command, const char *path, int describe_command_verbose)
9474#if ENABLE_PLATFORM_MINGW32 9489#if ENABLE_PLATFORM_MINGW32
9475 add_win32_extension(p); 9490 add_win32_extension(p);
9476 bs_to_slash(p); 9491 bs_to_slash(p);
9477 IF_FEATURE_SH_STANDALONE(describe:)
9478#endif 9492#endif
9479 if (describe_command_verbose) { 9493 if (describe_command_verbose) {
9480 out1fmt(" is %s", p); 9494 out1fmt(" is %s", p);
diff --git a/win32/mingw.c b/win32/mingw.c
index 063a0c546..0fa2a1b8f 100644
--- a/win32/mingw.c
+++ b/win32/mingw.c
@@ -2130,3 +2130,24 @@ int is_relative_path(const char *path)
2130{ 2130{
2131 return !is_dir_sep(path[0]) && !has_dos_drive_prefix(path); 2131 return !is_dir_sep(path[0]) && !has_dos_drive_prefix(path);
2132} 2132}
2133
2134#if ENABLE_FEATURE_SH_STANDALONE
2135/*
2136 * In standalone shell mode it's possible there's no binary file
2137 * corresponding to an applet name. There's one case where it's
2138 * easy to determine the corresponding binary: if the applet name
2139 * matches the file name from bb_busybox_exec_path (with appropriate
2140 * allowance for 'busybox*.exe').
2141 */
2142const char *applet_to_exe(const char *name)
2143{
2144 const char *exefile = bb_basename(bb_busybox_exec_path);
2145 const char *exesuff = is_prefixed_with_case(exefile, name);
2146
2147 if (exesuff && (strcmp(name, "busybox") == 0 ||
2148 strcasecmp(exesuff, ".exe") == 0)) {
2149 return bb_busybox_exec_path;
2150 }
2151 return name;
2152}
2153#endif