aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2018-12-15 15:01:53 +0000
committerRon Yorston <rmy@pobox.com>2018-12-15 15:39:28 +0000
commit65189dacb44708743313c81ec1ccaff87a68be8d (patch)
treeb1330575c61bce5adc7d5be815490ac7cb431852
parenta236242374daf911a01e998fabb1cc1268b2be7b (diff)
downloadbusybox-w32-65189dacb44708743313c81ec1ccaff87a68be8d.tar.gz
busybox-w32-65189dacb44708743313c81ec1ccaff87a68be8d.tar.bz2
busybox-w32-65189dacb44708743313c81ec1ccaff87a68be8d.zip
ash: fix local PATH assignments
The previous commit included code to use PATH values assigned to local variables: PATH=/new/path:$PATH new_binary It didn't work in the case when no fork was needed, for example: (PATH=/new/path:$PATH new_binary) because the call to listsetvar() freed the PATH value that was passed to shellexec(). The forking case only worked because the spawn_forkshell() mechanism in busybox-w32 didn't allow the PATH value to be freed. Rewrite the code so it works whether or not a fork is needed. The code would also work on POSIX systems. A cleaner solution could be extracted from dash commit cbb71a8 'eval: Add assignment built-in support again' but neither that nor the current patch are suitable for submission to upstream BusyBox. This one is preferred because it requires fewer changes from upstream.
-rw-r--r--shell/ash.c27
1 files changed, 20 insertions, 7 deletions
diff --git a/shell/ash.c b/shell/ash.c
index a659fd703..5195a8557 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -10531,6 +10531,9 @@ evalcommand(union node *cmd, int flags)
10531 int status; 10531 int status;
10532 char **nargv; 10532 char **nargv;
10533 smallint cmd_is_exec; 10533 smallint cmd_is_exec;
10534#if ENABLE_PLATFORM_MINGW32
10535 int cmdpath;
10536#endif
10534 10537
10535 errlinno = lineno = cmd->ncmd.linno; 10538 errlinno = lineno = cmd->ncmd.linno;
10536 if (funcline) 10539 if (funcline)
@@ -10599,6 +10602,7 @@ evalcommand(union node *cmd, int flags)
10599 } 10602 }
10600 status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2); 10603 status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
10601 10604
10605#if !ENABLE_PLATFORM_MINGW32
10602 path = vpath.var_text; 10606 path = vpath.var_text;
10603 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) { 10607 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
10604 struct strlist **spp; 10608 struct strlist **spp;
@@ -10615,14 +10619,17 @@ evalcommand(union node *cmd, int flags)
10615 */ 10619 */
10616 p = (*spp)->text; 10620 p = (*spp)->text;
10617 if (varcmp(p, path) == 0) 10621 if (varcmp(p, path) == 0)
10618#if !ENABLE_PLATFORM_MINGW32
10619 path = p; 10622 path = p;
10623 }
10620#else 10624#else
10621 /* fix_pathvar may have modified the value of the local 10625 /* Set path after any local PATH= has been processed. */
10622 * variable so we look it up again */ 10626 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
10623 path = vpath.var_text; 10627 struct strlist **spp = varlist.lastp;
10624#endif 10628 expandarg(argp, &varlist, EXP_VARTILDE);
10629 mklocal((*spp)->text);
10625 } 10630 }
10631 path = vpath.var_text;
10632#endif
10626 10633
10627 /* Print the command if xflag is set. */ 10634 /* Print the command if xflag is set. */
10628 if (xflag) { 10635 if (xflag) {
@@ -10780,7 +10787,13 @@ evalcommand(union node *cmd, int flags)
10780 TRACE(("forked child exited with %d\n", status)); 10787 TRACE(("forked child exited with %d\n", status));
10781 break; 10788 break;
10782 } 10789 }
10783 /* goes through to shellexec() */ 10790 /* If we're running 'command -p' we need to use the value stored
10791 * in path by parse_command_args(). If PATH is a local variable
10792 * listsetvar() will free the value currently in path so we need
10793 * to fetch the updated version. */
10794 cmdpath = (path != pathval());
10795 listsetvar(varlist.list, VEXPORT|VSTACK);
10796 shellexec(argv[0], argv, cmdpath ? path : pathval(), cmdentry.u.index);
10784#else 10797#else
10785 if (!(flags & EV_EXIT) || may_have_traps) { 10798 if (!(flags & EV_EXIT) || may_have_traps) {
10786 /* No, forking off a child is necessary */ 10799 /* No, forking off a child is necessary */
@@ -10798,9 +10811,9 @@ evalcommand(union node *cmd, int flags)
10798 FORCE_INT_ON; 10811 FORCE_INT_ON;
10799 /* fall through to exec'ing external program */ 10812 /* fall through to exec'ing external program */
10800 } 10813 }
10801#endif
10802 listsetvar(varlist.list, VEXPORT|VSTACK); 10814 listsetvar(varlist.list, VEXPORT|VSTACK);
10803 shellexec(argv[0], argv, path, cmdentry.u.index); 10815 shellexec(argv[0], argv, path, cmdentry.u.index);
10816#endif
10804 /* NOTREACHED */ 10817 /* NOTREACHED */
10805 } /* default */ 10818 } /* default */
10806 case CMDBUILTIN: 10819 case CMDBUILTIN: