ash: eval: Add assignment built-in support again
No binary (build failed)
—
(log yok)
| @@ -8112,7 +8112,7 @@ struct cmdentry { | |
| #define DO_ABS 0x02 /* checks absolute paths */ | |
| #define DO_NOFUNC 0x04 /* don't return shell functions, for command */ | |
| #define DO_ALTPATH 0x08 /* using alternate path */ | |
| - | #define DO_ALTBLTIN 0x20 /* %builtin in alt. path */ |
| + | #define DO_REGBLTIN 0x10 /* regular built-ins and functions only */ |
| static void find_command(char *, struct cmdentry *, int, const char *); | |
| @@ -8718,24 +8718,43 @@ typecmd(int argc UNUSED_PARAM, char **argv) | |
| } | |
| #if ENABLE_ASH_CMDCMD | |
| + | static struct strlist * |
| + | fill_arglist(struct arglist *arglist, union node **argpp) |
| + | { |
| + | struct strlist **lastp = arglist->lastp; |
| + | union node *argp; |
| + | |
| + | while ((argp = *argpp) != NULL) { |
| + | expandarg(argp, arglist, EXP_FULL | EXP_TILDE); |
| + | *argpp = argp->narg.next; |
| + | if (*lastp) |
| + | break; |
| + | } |
| + | |
| + | return *lastp; |
| + | } |
| + | |
| /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */ | |
| - | static char ** |
| - | parse_command_args(char **argv, const char **path) |
| + | static int |
| + | parse_command_args(struct arglist *arglist, union node **argpp, const char **path) |
| { | |
| + | struct strlist *sp = arglist->list; |
| char *cp, c; | |
| for (;;) { | |
| - | cp = *++argv; |
| - | if (!cp) |
| - | return NULL; |
| + | sp = sp->next ? sp->next : fill_arglist(arglist, argpp); |
| + | if (!sp) |
| + | return 0; |
| + | cp = sp->text; |
| if (*cp++ != '-') | |
| break; | |
| c = *cp++; | |
| if (!c) | |
| break; | |
| if (c == '-' && !*cp) { | |
| - | if (!*++argv) |
| - | return NULL; |
| + | if (!sp->next && !fill_arglist(arglist, argpp)) |
| + | return 0; |
| + | sp = sp->next; |
| break; | |
| } | |
| do { | |
| @@ -8745,12 +8764,14 @@ parse_command_args(char **argv, const char **path) | |
| break; | |
| default: | |
| /* run 'typecmd' for other options */ | |
| - | return NULL; |
| + | return 0; |
| } | |
| c = *cp++; | |
| } while (c); | |
| } | |
| - | return argv; |
| + | |
| + | arglist->list = sp; |
| + | return DO_NOFUNC; |
| } | |
| static int FAST_FUNC | |
| @@ -10124,7 +10145,7 @@ static int | |
| evalcommand(union node *cmd, int flags) | |
| { | |
| static const struct builtincmd null_bltin = { | |
| - | "\0\0", bltincmd /* why three NULs? */ |
| + | BUILTIN_REGULAR "", bltincmd |
| }; | |
| struct localvar_list *localvar_stop; | |
| struct parsefile *file_stop; | |
| @@ -10134,12 +10155,14 @@ evalcommand(union node *cmd, int flags) | |
| struct arglist varlist; | |
| char **argv; | |
| int argc; | |
| + | struct strlist *osp; |
| const struct strlist *sp; | |
| struct cmdentry cmdentry; | |
| struct job *jp; | |
| char *lastarg; | |
| const char *path; | |
| int spclbltin; | |
| + | int cmd_flag; |
| int status; | |
| char **nargv; | |
| smallint cmd_is_exec; | |
| @@ -10161,26 +10184,46 @@ evalcommand(union node *cmd, int flags) | |
| arglist.lastp = &arglist.list; | |
| *arglist.lastp = NULL; | |
| + | cmd_flag = 0; |
| + | cmd_is_exec = 0; |
| + | spclbltin = -1; |
| + | path = NULL; |
| + | |
| argc = 0; | |
| - | if (cmd->ncmd.args) { |
| - | struct builtincmd *bcmd; |
| - | smallint pseudovarflag; |
| + | argp = cmd->ncmd.args; |
| + | osp = fill_arglist(&arglist, &argp); |
| + | if (osp) { |
| + | int pseudovarflag = 0; |
| - | bcmd = find_builtin(cmd->ncmd.args->narg.text); |
| - | pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd); |
| + | for (;;) { |
| + | find_command(arglist.list->text, &cmdentry, |
| + | cmd_flag | DO_REGBLTIN, pathval()); |
| - | for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) { |
| - | struct strlist **spp; |
| + | /* implement bltin and command here */ |
| + | if (cmdentry.cmdtype != CMDBUILTIN) |
| + | break; |
| - | spp = arglist.lastp; |
| - | if (pseudovarflag && isassignment(argp->narg.text)) |
| - | expandarg(argp, &arglist, EXP_VARTILDE); |
| - | else |
| - | expandarg(argp, &arglist, EXP_FULL | EXP_TILDE); |
| + | pseudovarflag = IS_BUILTIN_ASSIGN(cmdentry.u.cmd); |
| + | if (spclbltin < 0) { |
| + | spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd); |
| + | } |
| + | cmd_is_exec = cmdentry.u.cmd == EXECCMD; |
| + | if (cmdentry.u.cmd != COMMANDCMD) |
| + | break; |
| - | for (sp = *spp; sp; sp = sp->next) |
| - | argc++; |
| + | cmd_flag = parse_command_args(&arglist, &argp, &path); |
| + | if (!cmd_flag) |
| + | break; |
| } | |
| + | |
| + | for (; argp; argp = argp->narg.next) |
| + | expandarg(argp, &arglist, |
| + | pseudovarflag && |
| + | isassignment(argp->narg.text) ? |
| + | EXP_VARTILDE : EXP_FULL | EXP_TILDE); |
| + | |
| + | for (sp = arglist.list; sp; sp = sp->next) |
| + | argc++; |
| } | |
| /* Reserve one extra spot at the front for shellexec. */ | |
| @@ -10210,23 +10253,13 @@ evalcommand(union node *cmd, int flags) | |
| } | |
| status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2); | |
| - | path = vpath.var_text; |
| for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) { | |
| struct strlist **spp; | |
| - | char *p; |
| spp = varlist.lastp; | |
| expandarg(argp, &varlist, EXP_VARTILDE); | |
| mklocal((*spp)->text); | |
| - | |
| - | /* |
| - | * Modify the command lookup path, if a PATH= assignment |
| - | * is present |
| - | */ |
| - | p = (*spp)->text; |
| - | if (varcmp(p, path) == 0) |
| - | path = p; |
| } | |
| /* Print the command if xflag is set. */ | |
| @@ -10265,46 +10298,16 @@ evalcommand(union node *cmd, int flags) | |
| safe_write(preverrout_fd, "\n", 1); | |
| } | |
| - | cmd_is_exec = 0; |
| - | spclbltin = -1; |
| - | |
| /* Now locate the command. */ | |
| - | if (argc) { |
| - | int cmd_flag = DO_ERR; |
| - | #if ENABLE_ASH_CMDCMD |
| - | const char *oldpath = path + 5; |
| - | #endif |
| - | path += 5; |
| - | for (;;) { |
| - | find_command(argv[0], &cmdentry, cmd_flag, path); |
| - | if (cmdentry.cmdtype == CMDUNKNOWN) { |
| - | flush_stdout_stderr(); |
| - | status = 127; |
| - | goto bail; |
| - | } |
| - | |
| - | /* implement bltin and command here */ |
| - | if (cmdentry.cmdtype != CMDBUILTIN) |
| - | break; |
| - | if (spclbltin < 0) |
| - | spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd); |
| - | if (cmdentry.u.cmd == EXECCMD) |
| - | cmd_is_exec = 1; |
| - | #if ENABLE_ASH_CMDCMD |
| - | if (cmdentry.u.cmd == COMMANDCMD) { |
| - | path = oldpath; |
| - | nargv = parse_command_args(argv, &path); |
| - | if (!nargv) |
| - | break; |
| - | /* It's "command [-p] PROG ARGS" (that is, no -Vv). |
| - | * nargv => "PROG". path is updated if -p. |
| - | */ |
| - | argc -= nargv - argv; |
| - | argv = nargv; |
| - | cmd_flag |= DO_NOFUNC; |
| - | } else |
| - | #endif |
| - | break; |
| + | if (cmdentry.cmdtype != CMDBUILTIN |
| + | || !(IS_BUILTIN_REGULAR(cmdentry.u.cmd)) |
| + | ) { |
| + | find_command(argv[0], &cmdentry, cmd_flag | DO_ERR, |
| + | path ? path : pathval()); |
| + | if (cmdentry.cmdtype == CMDUNKNOWN) { |
| + | status = 127; |
| + | flush_stdout_stderr(); |
| + | goto bail; |
| } | |
| } | |
| @@ -10383,6 +10386,7 @@ evalcommand(union node *cmd, int flags) | |
| /* 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 */ | |
| @@ -13538,11 +13542,8 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) | |
| /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */ | |
| updatetbl = (path == pathval()); | |
| - | if (!updatetbl) { |
| + | if (!updatetbl) |
| act |= DO_ALTPATH; | |
| - | if (strstr(path, "%builtin") != NULL) |
| - | act |= DO_ALTBLTIN; |
| - | } |
| /* If name is in the table, check answer will be ok */ | |
| cmdp = cmdlookup(name, 0); | |
| @@ -13555,16 +13556,19 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) | |
| abort(); | |
| #endif | |
| case CMDNORMAL: | |
| - | bit = DO_ALTPATH; |
| + | bit = DO_ALTPATH | DO_REGBLTIN; |
| break; | |
| case CMDFUNCTION: | |
| bit = DO_NOFUNC; | |
| break; | |
| case CMDBUILTIN: | |
| - | bit = IS_BUILTIN_REGULAR(cmdp->param.cmd) ? 0 : DO_ALTBLTIN; |
| + | bit = IS_BUILTIN_REGULAR(cmdp->param.cmd) ? 0 : DO_REGBLTIN; |
| break; | |
| } | |
| if (act & bit) { | |
| + | if (act & bit & DO_REGBLTIN) |
| + | goto fail; |
| + | |
| updatetbl = 0; | |
| cmdp = NULL; | |
| } else if (cmdp->rehash == 0) | |
| @@ -13577,14 +13581,15 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) | |
| if (bcmd) { | |
| if (IS_BUILTIN_REGULAR(bcmd)) | |
| goto builtin_success; | |
| - | if (act & DO_ALTPATH) { |
| - | if (!(act & DO_ALTBLTIN)) |
| - | goto builtin_success; |
| - | } else if (builtinloc <= 0) { |
| + | if (act & DO_ALTPATH) |
| + | goto builtin_success; |
| + | if (builtinloc <= 0) |
| goto builtin_success; | |
| - | } |
| } | |
| + | if (act & DO_REGBLTIN) |
| + | goto fail; |
| + | |
| #if ENABLE_FEATURE_SH_STANDALONE | |
| { | |
| int applet_no = find_applet_by_name(name); | |
| @@ -13688,6 +13693,7 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) | |
| #endif | |
| ash_msg("%s: %s", name, errmsg(e, "not found")); | |
| } | |
| + | fail: |
| entry->cmdtype = CMDUNKNOWN; | |
| return; | |