aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2020-02-19 17:33:44 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2020-02-20 09:36:51 +0100
commit3e729102a86b1fb536f61c6ebcd95321ba98528d (patch)
tree0624e6d0c39f564ad18b4eac3fa1e590eadd7f0b /shell
parent54bef2a8efd21e9992a9d26cf30c5b26cbc0e21a (diff)
downloadbusybox-3e729102a86b1fb536f61c6ebcd95321ba98528d.tar.gz
ash: eval: Replace with listsetvar with mklocal/setvareq
Upstream commit: Date: Sat, 19 May 2018 02:39:55 +0800 eval: Replace with listsetvar with mklocal/setvareq This patch replaces listsetvar with mklocal/setvareq. As we now determine special built-in status prior to variable assignment, we no longer have to do a second pass listsetvar. Instead we will call setvareq directly instead of mklocal when necessary. In order to do this mklocal can now take a flag in order to mark a variable for export. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
-rw-r--r--shell/ash.c63
1 files changed, 28 insertions, 35 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 5570057e9..5bb10e5cb 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -2477,24 +2477,6 @@ unsetvar(const char *s)
}
/*
- * Process a linked list of variable assignments.
- */
-static void
-listsetvar(struct strlist *list_set_var, int flags)
-{
- struct strlist *lp = list_set_var;
-
- if (!lp)
- return;
- INT_OFF;
- do {
- setvareq(lp->text, flags);
- lp = lp->next;
- } while (lp);
- INT_ON;
-}
-
-/*
* Generate a list of variables satisfying the given conditions.
*/
#if !ENABLE_FEATURE_SH_NOFORK
@@ -9810,7 +9792,7 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags)
* (options will be restored on return from the function).
*/
static void
-mklocal(char *name)
+mklocal(char *name, int flags)
{
struct localvar *lvp;
struct var **vpp;
@@ -9847,9 +9829,9 @@ mklocal(char *name)
if (vp == NULL) {
/* variable did not exist yet */
if (eq)
- vp = setvareq(name, VSTRFIXED);
+ vp = setvareq(name, VSTRFIXED | flags);
else
- vp = setvar(name, NULL, VSTRFIXED);
+ vp = setvar(name, NULL, VSTRFIXED | flags);
lvp->flags = VUNSET;
} else {
lvp->text = vp->var_text;
@@ -9859,7 +9841,7 @@ mklocal(char *name)
*/
vp->flags |= VSTRFIXED|VTEXTFIXED;
if (eq)
- setvareq(name, 0);
+ setvareq(name, flags);
else
/* "local VAR" unsets VAR: */
setvar0(name, NULL);
@@ -9885,7 +9867,7 @@ localcmd(int argc UNUSED_PARAM, char **argv)
argv = argptr;
while ((name = *argv++) != NULL) {
- mklocal(name);
+ mklocal(name, 0);
}
return 0;
}
@@ -10166,6 +10148,8 @@ evalcommand(union node *cmd, int flags)
int status;
char **nargv;
smallint cmd_is_exec;
+ int vflags;
+ int vlocal;
errlinno = lineno = cmd->ncmd.linno;
if (funcline)
@@ -10173,7 +10157,6 @@ evalcommand(union node *cmd, int flags)
/* First expand the arguments. */
TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
- localvar_stop = pushlocalvars();
file_stop = g_parsefile;
back_exitstatus = 0;
@@ -10187,6 +10170,8 @@ evalcommand(union node *cmd, int flags)
cmd_flag = 0;
cmd_is_exec = 0;
spclbltin = -1;
+ vflags = 0;
+ vlocal = 0;
path = NULL;
argc = 0;
@@ -10199,6 +10184,8 @@ evalcommand(union node *cmd, int flags)
find_command(arglist.list->text, &cmdentry,
cmd_flag | DO_REGBLTIN, pathval());
+ vlocal++;
+
/* implement bltin and command here */
if (cmdentry.cmdtype != CMDBUILTIN)
break;
@@ -10206,6 +10193,7 @@ evalcommand(union node *cmd, int flags)
pseudovarflag = IS_BUILTIN_ASSIGN(cmdentry.u.cmd);
if (spclbltin < 0) {
spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
+ vlocal = !spclbltin;
}
cmd_is_exec = cmdentry.u.cmd == EXECCMD;
if (cmdentry.u.cmd != COMMANDCMD)
@@ -10224,6 +10212,9 @@ evalcommand(union node *cmd, int flags)
for (sp = arglist.list; sp; sp = sp->next)
argc++;
+
+ if (cmd_is_exec && argc > 1)
+ vflags = VEXPORT;
}
/* Reserve one extra spot at the front for shellexec. */
@@ -10254,6 +10245,7 @@ evalcommand(union node *cmd, int flags)
status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
if (status) {
+ vlocal = 0;
bail:
exitstatus = status;
@@ -10264,13 +10256,20 @@ evalcommand(union node *cmd, int flags)
goto out;
}
+ localvar_stop = NULL;
+ if (vlocal)
+ localvar_stop = pushlocalvars();
+
for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
struct strlist **spp;
spp = varlist.lastp;
expandarg(argp, &varlist, EXP_VARTILDE);
- mklocal((*spp)->text);
+ if (vlocal)
+ mklocal((*spp)->text, VEXPORT);
+ else
+ setvareq((*spp)->text, vflags);
}
/* Print the command if xflag is set. */
@@ -10313,8 +10312,8 @@ evalcommand(union node *cmd, int flags)
if (cmdentry.cmdtype != CMDBUILTIN
|| !(IS_BUILTIN_REGULAR(cmdentry.u.cmd))
) {
- find_command(argv[0], &cmdentry, cmd_flag | DO_ERR,
- path ? path : pathval());
+ path = path ? path : pathval();
+ find_command(argv[0], &cmdentry, cmd_flag | DO_ERR, path);
}
jp = NULL;
@@ -10385,17 +10384,10 @@ evalcommand(union node *cmd, int flags)
FORCE_INT_ON;
/* fall through to exec'ing external program */
}
- listsetvar(varlist.list, VEXPORT|VSTACK);
- path = path ? path : pathval();
shellexec(argv[0], argv, path, cmdentry.u.index);
/* NOTREACHED */
} /* default */
case CMDBUILTIN:
- if (spclbltin > 0 || argc == 0) {
- poplocalvars(1);
- if (cmd_is_exec && argc > 1)
- listsetvar(varlist.list, VEXPORT);
- }
if (evalbltin(cmdentry.u.cmd, argc, argv, flags)
&& !(exception_type == EXERROR && spclbltin <= 0)
) {
@@ -10418,7 +10410,8 @@ evalcommand(union node *cmd, int flags)
popredir(/*drop:*/ cmd_is_exec);
unwindredir(redir_stop);
unwindfiles(file_stop);
- unwindlocalvars(localvar_stop);
+ if (vlocal)
+ unwindlocalvars(localvar_stop);
if (lastarg) {
/* dsl: I think this is intended to be used to support
* '_' in 'vi' command mode during line editing...