diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2020-02-19 17:33:44 +0100 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2020-02-20 09:36:51 +0100 |
| commit | 3e729102a86b1fb536f61c6ebcd95321ba98528d (patch) | |
| tree | 0624e6d0c39f564ad18b4eac3fa1e590eadd7f0b /shell | |
| parent | 54bef2a8efd21e9992a9d26cf30c5b26cbc0e21a (diff) | |
| download | busybox-w32-3e729102a86b1fb536f61c6ebcd95321ba98528d.tar.gz busybox-w32-3e729102a86b1fb536f61c6ebcd95321ba98528d.tar.bz2 busybox-w32-3e729102a86b1fb536f61c6ebcd95321ba98528d.zip | |
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.c | 63 |
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) | |||
| 2477 | } | 2477 | } |
| 2478 | 2478 | ||
| 2479 | /* | 2479 | /* |
| 2480 | * Process a linked list of variable assignments. | ||
| 2481 | */ | ||
| 2482 | static void | ||
| 2483 | listsetvar(struct strlist *list_set_var, int flags) | ||
| 2484 | { | ||
| 2485 | struct strlist *lp = list_set_var; | ||
| 2486 | |||
| 2487 | if (!lp) | ||
| 2488 | return; | ||
| 2489 | INT_OFF; | ||
| 2490 | do { | ||
| 2491 | setvareq(lp->text, flags); | ||
| 2492 | lp = lp->next; | ||
| 2493 | } while (lp); | ||
| 2494 | INT_ON; | ||
| 2495 | } | ||
| 2496 | |||
| 2497 | /* | ||
| 2498 | * Generate a list of variables satisfying the given conditions. | 2480 | * Generate a list of variables satisfying the given conditions. |
| 2499 | */ | 2481 | */ |
| 2500 | #if !ENABLE_FEATURE_SH_NOFORK | 2482 | #if !ENABLE_FEATURE_SH_NOFORK |
| @@ -9810,7 +9792,7 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags) | |||
| 9810 | * (options will be restored on return from the function). | 9792 | * (options will be restored on return from the function). |
| 9811 | */ | 9793 | */ |
| 9812 | static void | 9794 | static void |
| 9813 | mklocal(char *name) | 9795 | mklocal(char *name, int flags) |
| 9814 | { | 9796 | { |
| 9815 | struct localvar *lvp; | 9797 | struct localvar *lvp; |
| 9816 | struct var **vpp; | 9798 | struct var **vpp; |
| @@ -9847,9 +9829,9 @@ mklocal(char *name) | |||
| 9847 | if (vp == NULL) { | 9829 | if (vp == NULL) { |
| 9848 | /* variable did not exist yet */ | 9830 | /* variable did not exist yet */ |
| 9849 | if (eq) | 9831 | if (eq) |
| 9850 | vp = setvareq(name, VSTRFIXED); | 9832 | vp = setvareq(name, VSTRFIXED | flags); |
| 9851 | else | 9833 | else |
| 9852 | vp = setvar(name, NULL, VSTRFIXED); | 9834 | vp = setvar(name, NULL, VSTRFIXED | flags); |
| 9853 | lvp->flags = VUNSET; | 9835 | lvp->flags = VUNSET; |
| 9854 | } else { | 9836 | } else { |
| 9855 | lvp->text = vp->var_text; | 9837 | lvp->text = vp->var_text; |
| @@ -9859,7 +9841,7 @@ mklocal(char *name) | |||
| 9859 | */ | 9841 | */ |
| 9860 | vp->flags |= VSTRFIXED|VTEXTFIXED; | 9842 | vp->flags |= VSTRFIXED|VTEXTFIXED; |
| 9861 | if (eq) | 9843 | if (eq) |
| 9862 | setvareq(name, 0); | 9844 | setvareq(name, flags); |
| 9863 | else | 9845 | else |
| 9864 | /* "local VAR" unsets VAR: */ | 9846 | /* "local VAR" unsets VAR: */ |
| 9865 | setvar0(name, NULL); | 9847 | setvar0(name, NULL); |
| @@ -9885,7 +9867,7 @@ localcmd(int argc UNUSED_PARAM, char **argv) | |||
| 9885 | 9867 | ||
| 9886 | argv = argptr; | 9868 | argv = argptr; |
| 9887 | while ((name = *argv++) != NULL) { | 9869 | while ((name = *argv++) != NULL) { |
| 9888 | mklocal(name); | 9870 | mklocal(name, 0); |
| 9889 | } | 9871 | } |
| 9890 | return 0; | 9872 | return 0; |
| 9891 | } | 9873 | } |
| @@ -10166,6 +10148,8 @@ evalcommand(union node *cmd, int flags) | |||
| 10166 | int status; | 10148 | int status; |
| 10167 | char **nargv; | 10149 | char **nargv; |
| 10168 | smallint cmd_is_exec; | 10150 | smallint cmd_is_exec; |
| 10151 | int vflags; | ||
| 10152 | int vlocal; | ||
| 10169 | 10153 | ||
| 10170 | errlinno = lineno = cmd->ncmd.linno; | 10154 | errlinno = lineno = cmd->ncmd.linno; |
| 10171 | if (funcline) | 10155 | if (funcline) |
| @@ -10173,7 +10157,6 @@ evalcommand(union node *cmd, int flags) | |||
| 10173 | 10157 | ||
| 10174 | /* First expand the arguments. */ | 10158 | /* First expand the arguments. */ |
| 10175 | TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags)); | 10159 | TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags)); |
| 10176 | localvar_stop = pushlocalvars(); | ||
| 10177 | file_stop = g_parsefile; | 10160 | file_stop = g_parsefile; |
| 10178 | back_exitstatus = 0; | 10161 | back_exitstatus = 0; |
| 10179 | 10162 | ||
| @@ -10187,6 +10170,8 @@ evalcommand(union node *cmd, int flags) | |||
| 10187 | cmd_flag = 0; | 10170 | cmd_flag = 0; |
| 10188 | cmd_is_exec = 0; | 10171 | cmd_is_exec = 0; |
| 10189 | spclbltin = -1; | 10172 | spclbltin = -1; |
| 10173 | vflags = 0; | ||
| 10174 | vlocal = 0; | ||
| 10190 | path = NULL; | 10175 | path = NULL; |
| 10191 | 10176 | ||
| 10192 | argc = 0; | 10177 | argc = 0; |
| @@ -10199,6 +10184,8 @@ evalcommand(union node *cmd, int flags) | |||
| 10199 | find_command(arglist.list->text, &cmdentry, | 10184 | find_command(arglist.list->text, &cmdentry, |
| 10200 | cmd_flag | DO_REGBLTIN, pathval()); | 10185 | cmd_flag | DO_REGBLTIN, pathval()); |
| 10201 | 10186 | ||
| 10187 | vlocal++; | ||
| 10188 | |||
| 10202 | /* implement bltin and command here */ | 10189 | /* implement bltin and command here */ |
| 10203 | if (cmdentry.cmdtype != CMDBUILTIN) | 10190 | if (cmdentry.cmdtype != CMDBUILTIN) |
| 10204 | break; | 10191 | break; |
| @@ -10206,6 +10193,7 @@ evalcommand(union node *cmd, int flags) | |||
| 10206 | pseudovarflag = IS_BUILTIN_ASSIGN(cmdentry.u.cmd); | 10193 | pseudovarflag = IS_BUILTIN_ASSIGN(cmdentry.u.cmd); |
| 10207 | if (spclbltin < 0) { | 10194 | if (spclbltin < 0) { |
| 10208 | spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd); | 10195 | spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd); |
| 10196 | vlocal = !spclbltin; | ||
| 10209 | } | 10197 | } |
| 10210 | cmd_is_exec = cmdentry.u.cmd == EXECCMD; | 10198 | cmd_is_exec = cmdentry.u.cmd == EXECCMD; |
| 10211 | if (cmdentry.u.cmd != COMMANDCMD) | 10199 | if (cmdentry.u.cmd != COMMANDCMD) |
| @@ -10224,6 +10212,9 @@ evalcommand(union node *cmd, int flags) | |||
| 10224 | 10212 | ||
| 10225 | for (sp = arglist.list; sp; sp = sp->next) | 10213 | for (sp = arglist.list; sp; sp = sp->next) |
| 10226 | argc++; | 10214 | argc++; |
| 10215 | |||
| 10216 | if (cmd_is_exec && argc > 1) | ||
| 10217 | vflags = VEXPORT; | ||
| 10227 | } | 10218 | } |
| 10228 | 10219 | ||
| 10229 | /* Reserve one extra spot at the front for shellexec. */ | 10220 | /* Reserve one extra spot at the front for shellexec. */ |
| @@ -10254,6 +10245,7 @@ evalcommand(union node *cmd, int flags) | |||
| 10254 | status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2); | 10245 | status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2); |
| 10255 | 10246 | ||
| 10256 | if (status) { | 10247 | if (status) { |
| 10248 | vlocal = 0; | ||
| 10257 | bail: | 10249 | bail: |
| 10258 | exitstatus = status; | 10250 | exitstatus = status; |
| 10259 | 10251 | ||
| @@ -10264,13 +10256,20 @@ evalcommand(union node *cmd, int flags) | |||
| 10264 | goto out; | 10256 | goto out; |
| 10265 | } | 10257 | } |
| 10266 | 10258 | ||
| 10259 | localvar_stop = NULL; | ||
| 10260 | if (vlocal) | ||
| 10261 | localvar_stop = pushlocalvars(); | ||
| 10262 | |||
| 10267 | for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) { | 10263 | for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) { |
| 10268 | struct strlist **spp; | 10264 | struct strlist **spp; |
| 10269 | 10265 | ||
| 10270 | spp = varlist.lastp; | 10266 | spp = varlist.lastp; |
| 10271 | expandarg(argp, &varlist, EXP_VARTILDE); | 10267 | expandarg(argp, &varlist, EXP_VARTILDE); |
| 10272 | 10268 | ||
| 10273 | mklocal((*spp)->text); | 10269 | if (vlocal) |
| 10270 | mklocal((*spp)->text, VEXPORT); | ||
| 10271 | else | ||
| 10272 | setvareq((*spp)->text, vflags); | ||
| 10274 | } | 10273 | } |
| 10275 | 10274 | ||
| 10276 | /* Print the command if xflag is set. */ | 10275 | /* Print the command if xflag is set. */ |
| @@ -10313,8 +10312,8 @@ evalcommand(union node *cmd, int flags) | |||
| 10313 | if (cmdentry.cmdtype != CMDBUILTIN | 10312 | if (cmdentry.cmdtype != CMDBUILTIN |
| 10314 | || !(IS_BUILTIN_REGULAR(cmdentry.u.cmd)) | 10313 | || !(IS_BUILTIN_REGULAR(cmdentry.u.cmd)) |
| 10315 | ) { | 10314 | ) { |
| 10316 | find_command(argv[0], &cmdentry, cmd_flag | DO_ERR, | 10315 | path = path ? path : pathval(); |
| 10317 | path ? path : pathval()); | 10316 | find_command(argv[0], &cmdentry, cmd_flag | DO_ERR, path); |
| 10318 | } | 10317 | } |
| 10319 | 10318 | ||
| 10320 | jp = NULL; | 10319 | jp = NULL; |
| @@ -10385,17 +10384,10 @@ evalcommand(union node *cmd, int flags) | |||
| 10385 | FORCE_INT_ON; | 10384 | FORCE_INT_ON; |
| 10386 | /* fall through to exec'ing external program */ | 10385 | /* fall through to exec'ing external program */ |
| 10387 | } | 10386 | } |
| 10388 | listsetvar(varlist.list, VEXPORT|VSTACK); | ||
| 10389 | path = path ? path : pathval(); | ||
| 10390 | shellexec(argv[0], argv, path, cmdentry.u.index); | 10387 | shellexec(argv[0], argv, path, cmdentry.u.index); |
| 10391 | /* NOTREACHED */ | 10388 | /* NOTREACHED */ |
| 10392 | } /* default */ | 10389 | } /* default */ |
| 10393 | case CMDBUILTIN: | 10390 | case CMDBUILTIN: |
| 10394 | if (spclbltin > 0 || argc == 0) { | ||
| 10395 | poplocalvars(1); | ||
| 10396 | if (cmd_is_exec && argc > 1) | ||
| 10397 | listsetvar(varlist.list, VEXPORT); | ||
| 10398 | } | ||
| 10399 | if (evalbltin(cmdentry.u.cmd, argc, argv, flags) | 10391 | if (evalbltin(cmdentry.u.cmd, argc, argv, flags) |
| 10400 | && !(exception_type == EXERROR && spclbltin <= 0) | 10392 | && !(exception_type == EXERROR && spclbltin <= 0) |
| 10401 | ) { | 10393 | ) { |
| @@ -10418,7 +10410,8 @@ evalcommand(union node *cmd, int flags) | |||
| 10418 | popredir(/*drop:*/ cmd_is_exec); | 10410 | popredir(/*drop:*/ cmd_is_exec); |
| 10419 | unwindredir(redir_stop); | 10411 | unwindredir(redir_stop); |
| 10420 | unwindfiles(file_stop); | 10412 | unwindfiles(file_stop); |
| 10421 | unwindlocalvars(localvar_stop); | 10413 | if (vlocal) |
| 10414 | unwindlocalvars(localvar_stop); | ||
| 10422 | if (lastarg) { | 10415 | if (lastarg) { |
| 10423 | /* dsl: I think this is intended to be used to support | 10416 | /* dsl: I think this is intended to be used to support |
| 10424 | * '_' in 'vi' command mode during line editing... | 10417 | * '_' in 'vi' command mode during line editing... |
