aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2018-02-28 17:00:43 +0000
committerRon Yorston <rmy@pobox.com>2018-02-28 17:00:43 +0000
commit92dbd3c0932abbfb6814554603abd38e3eb9d953 (patch)
tree11ec318924d65796538a776422ab130d81b56752
parentb0a565de930df8dc4fd8f00cbfe3a585391cb05a (diff)
downloadbusybox-w32-92dbd3c0932abbfb6814554603abd38e3eb9d953.tar.gz
busybox-w32-92dbd3c0932abbfb6814554603abd38e3eb9d953.tar.bz2
busybox-w32-92dbd3c0932abbfb6814554603abd38e3eb9d953.zip
ash: changes to command resolution, execution and display
ash separates searching for commands from running them. Searching is performed in find_command(). The result of the search is stored in a hash table but not as the full path: the path is reconstructed in shellexec() by combining the directory and command name. In Windows the command name is insufficient, as the executable name may also include an extension. To resolve this we must ensure that extensions are processed in the same order in find_command, shellexec and any other places where command names are resolved into file names. The order used matches that of spawnve: .com, .exe, .bat, .cmd. Finally the bare filename with no additional extension The order has been made consistent: - in find_command for absolute paths and the Windows-specific path search; - in tryexec (which is called by shellexec) where an additional test that the file is executable has been added; - in the type and hash built-ins where the output has been modified to include the extension. Additionally, the code in tryexec to handle ENOEXEC errors from execve has been excluded. The rationale for the exec functions in POSIX [1] suggests the requirement to retry is a workaround for the lack of '#!' support on some platforms. [1] http://pubs.opengroup.org/onlinepubs/009695399/functions/exec.html
-rw-r--r--shell/ash.c78
1 files changed, 55 insertions, 23 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 7dec5dfc7..fa71bd84d 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -8318,6 +8318,10 @@ static int builtinloc = -1; /* index in path of %builtin, or -1 */
8318static void 8318static void
8319tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, char **envp) 8319tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, char **envp)
8320{ 8320{
8321#if ENABLE_PLATFORM_MINGW32
8322 char *new_cmd;
8323#endif
8324
8321#if ENABLE_FEATURE_SH_STANDALONE 8325#if ENABLE_FEATURE_SH_STANDALONE
8322 if (applet_no >= 0) { 8326 if (applet_no >= 0) {
8323 if (APPLET_IS_NOEXEC(applet_no)) { 8327 if (APPLET_IS_NOEXEC(applet_no)) {
@@ -8334,6 +8338,16 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, c
8334 } 8338 }
8335#endif 8339#endif
8336 8340
8341#if ENABLE_PLATFORM_MINGW32
8342 /* ensure we have a path to a real, executable file */
8343 if (!(new_cmd=add_win32_extension(cmd)) && !file_is_executable(cmd)) {
8344 errno = EACCES;
8345 return;
8346 }
8347 execve(new_cmd ? new_cmd : cmd, argv, envp);
8348 free(new_cmd);
8349 /* skip POSIX-mandated retry on ENOEXEC */
8350#else
8337 repeat: 8351 repeat:
8338#ifdef SYSV 8352#ifdef SYSV
8339 do { 8353 do {
@@ -8368,6 +8382,7 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, c
8368 argv[0] = (char*) "ash"; 8382 argv[0] = (char*) "ash";
8369 goto repeat; 8383 goto repeat;
8370 } 8384 }
8385#endif
8371} 8386}
8372 8387
8373/* 8388/*
@@ -8437,6 +8452,9 @@ printentry(struct tblentry *cmdp)
8437 int idx; 8452 int idx;
8438 const char *path; 8453 const char *path;
8439 char *name; 8454 char *name;
8455#if ENABLE_PLATFORM_MINGW32
8456 char *n;
8457#endif
8440 8458
8441 idx = cmdp->param.index; 8459 idx = cmdp->param.index;
8442 path = pathval(); 8460 path = pathval();
@@ -8444,7 +8462,14 @@ printentry(struct tblentry *cmdp)
8444 name = path_advance(&path, cmdp->cmdname); 8462 name = path_advance(&path, cmdp->cmdname);
8445 stunalloc(name); 8463 stunalloc(name);
8446 } while (--idx >= 0); 8464 } while (--idx >= 0);
8465#if ENABLE_PLATFORM_MINGW32
8466 if ((n=add_win32_extension(name)) != NULL)
8467 name = n;
8468#endif
8447 out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr)); 8469 out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
8470#if ENABLE_PLATFORM_MINGW32
8471 free(n);
8472#endif
8448} 8473}
8449 8474
8450/* 8475/*
@@ -8832,6 +8857,9 @@ describe_command(char *command, const char *path, int describe_command_verbose)
8832 case CMDNORMAL: { 8857 case CMDNORMAL: {
8833 int j = entry.u.index; 8858 int j = entry.u.index;
8834 char *p; 8859 char *p;
8860#if ENABLE_PLATFORM_MINGW32
8861 char *q;
8862#endif
8835 if (j < 0) { 8863 if (j < 0) {
8836 p = command; 8864 p = command;
8837 } else { 8865 } else {
@@ -8840,11 +8868,18 @@ describe_command(char *command, const char *path, int describe_command_verbose)
8840 stunalloc(p); 8868 stunalloc(p);
8841 } while (--j >= 0); 8869 } while (--j >= 0);
8842 } 8870 }
8871#if ENABLE_PLATFORM_MINGW32
8872 if ((q=add_win32_extension(p)) != NULL)
8873 p = q;
8874#endif
8843 if (describe_command_verbose) { 8875 if (describe_command_verbose) {
8844 out1fmt(" is %s", p); 8876 out1fmt(" is %s", p);
8845 } else { 8877 } else {
8846 out1str(p); 8878 out1str(p);
8847 } 8879 }
8880#if ENABLE_PLATFORM_MINGW32
8881 free(q);
8882#endif
8848 break; 8883 break;
8849 } 8884 }
8850 8885
@@ -13647,16 +13682,21 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path)
13647 int e; 13682 int e;
13648 int updatetbl; 13683 int updatetbl;
13649 struct builtincmd *bcmd; 13684 struct builtincmd *bcmd;
13685#if ENABLE_PLATFORM_MINGW32
13686 extern const char win_suffix[4][4];
13687 int i, len;
13688#endif
13650 13689
13651 /* If name contains a slash, don't use PATH or hash table */ 13690 /* If name contains a slash, don't use PATH or hash table */
13652 if (strchr(name, '/') || (ENABLE_PLATFORM_MINGW32 && strchr(name, '\\'))) { 13691 if (strchr(name, '/') || (ENABLE_PLATFORM_MINGW32 && strchr(name, '\\'))) {
13653 entry->u.index = -1; 13692 entry->u.index = -1;
13654 if (act & DO_ABS) { 13693 if (act & DO_ABS) {
13655 while (stat(name, &statb) < 0
13656#if ENABLE_PLATFORM_MINGW32 13694#if ENABLE_PLATFORM_MINGW32
13657 && (fullname=add_win32_extension(name)) == NULL 13695 while ((fullname=add_win32_extension(name)) == NULL ||
13696 stat(name, &statb) < 0 ) {
13697#else
13698 while (stat(name, &statb) < 0) {
13658#endif 13699#endif
13659 ) {
13660#ifdef SYSV 13700#ifdef SYSV
13661 if (errno == EINTR) 13701 if (errno == EINTR)
13662 continue; 13702 continue;
@@ -13770,34 +13810,26 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path)
13770 goto success; 13810 goto success;
13771 } 13811 }
13772#if ENABLE_PLATFORM_MINGW32 13812#if ENABLE_PLATFORM_MINGW32
13773 if (has_exe_suffix(fullname)) { 13813 /* first try appending suffixes (unless there's one already) */
13774 if (stat(fullname, &statb) < 0) { 13814 i = 4;
13775 if (errno != ENOENT && errno != ENOTDIR) 13815 len = strlen(fullname);
13776 e = errno; 13816 if (!has_exe_suffix_or_dot(fullname)) {
13777 goto loop;
13778 }
13779 }
13780 else {
13781 extern const char win_suffix[4][4];
13782 int i, len;
13783
13784 /* path_advance() has reserved space for suffix */ 13817 /* path_advance() has reserved space for suffix */
13785 len = strlen(fullname);
13786 fullname[len] = '.'; 13818 fullname[len] = '.';
13787 for (i=0; i<4; ++i) { 13819 for (i=0; i<4; ++i) {
13788 memcpy(fullname+len+1, win_suffix[i], 4); 13820 memcpy(fullname+len+1, win_suffix[i], 4);
13789 if (stat(fullname, &statb) == 0) 13821 if (stat(fullname, &statb) == 0)
13790 break; 13822 break;
13791 } 13823 }
13792 fullname[len] = '\0'; 13824 }
13793 13825
13794 if (i == 4) { 13826 if (i == 4) {
13795 /* suffix didn't work, try without */ 13827 /* adding a suffix failed (or wasn't tried), try original */
13796 if (stat(fullname, &statb) < 0) { 13828 fullname[len] = '\0';
13797 if (errno != ENOENT && errno != ENOTDIR) 13829 if (stat(fullname, &statb) < 0) {
13798 e = errno; 13830 if (errno != ENOENT && errno != ENOTDIR)
13799 goto loop; 13831 e = errno;
13800 } 13832 goto loop;
13801 } 13833 }
13802 } 13834 }
13803#else 13835#else