X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/41d407f18705b7ded760f12134cda8821a0aa168..6a43fdd10a599893bc0d342b248c8996f0efa90f:/usr/src/bin/sh/eval.c diff --git a/usr/src/bin/sh/eval.c b/usr/src/bin/sh/eval.c index 0a2512b584..e4d81d6696 100644 --- a/usr/src/bin/sh/eval.c +++ b/usr/src/bin/sh/eval.c @@ -1,43 +1,20 @@ /*- - * Copyright (c) 1991 The Regents of the University of California. - * All rights reserved. + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * %sccs.include.redist.c% */ #ifndef lint -static char sccsid[] = "@(#)eval.c 5.4 (Berkeley) 4/16/92"; +static char sccsid[] = "@(#)eval.c 8.8 (Berkeley) %G%"; #endif /* not lint */ +#include +#include + /* * Evaluate a command. */ @@ -59,9 +36,11 @@ static char sccsid[] = "@(#)eval.c 5.4 (Berkeley) 4/16/92"; #include "var.h" #include "memalloc.h" #include "error.h" +#include "show.h" #include "mystring.h" +#ifndef NO_HISTORY #include "myhistedit.h" -#include +#endif /* flags in argument to evaltree */ @@ -84,28 +63,17 @@ int funcnest; /* depth of function calls */ char *commandname; struct strlist *cmdenviron; int exitstatus; /* exit status of last command */ +int oexitstatus; /* saved exit status */ -#ifdef __STDC__ -STATIC void evalloop(union node *); -STATIC void evalfor(union node *); -STATIC void evalcase(union node *, int); -STATIC void evalsubshell(union node *, int); -STATIC void expredir(union node *); -STATIC void evalpipe(union node *); -STATIC void evalcommand(union node *, int, struct backcmd *); -STATIC void prehash(union node *); -#else -STATIC void evalloop(); -STATIC void evalfor(); -STATIC void evalcase(); -STATIC void evalsubshell(); -STATIC void expredir(); -STATIC void evalpipe(); -STATIC void evalcommand(); -STATIC void prehash(); -#endif - +STATIC void evalloop __P((union node *)); +STATIC void evalfor __P((union node *)); +STATIC void evalcase __P((union node *, int)); +STATIC void evalsubshell __P((union node *, int)); +STATIC void expredir __P((union node *)); +STATIC void evalpipe __P((union node *)); +STATIC void evalcommand __P((union node *, int, struct backcmd *)); +STATIC void prehash __P((union node *)); /* @@ -132,7 +100,9 @@ SHELLPROC { * The eval commmand. */ +int evalcmd(argc, argv) + int argc; char **argv; { char *p; @@ -191,14 +161,17 @@ evalstring(s) void evaltree(n, flags) union node *n; - { + int flags; +{ if (n == NULL) { TRACE(("evaltree(NULL) called\n")); exitstatus = 0; goto out; } +#ifndef NO_HISTORY displayhist = 1; /* show history substitutions done with fc */ - TRACE(("evaltree(0x%x: %d) called\n", (int)n, n->type)); +#endif + TRACE(("evaltree(0x%lx: %d) called\n", (long)n, n->type)); switch (n->type) { case NSEMI: evaltree(n->nbinary.ch1, 0); @@ -231,19 +204,17 @@ evaltree(n, flags) evalsubshell(n, flags); break; case NIF: { - int status = 0; + int status; evaltree(n->nif.test, EV_TESTED); + status = exitstatus; + exitstatus = 0; if (evalskip) goto out; - if (exitstatus == 0) { + if (status == 0) evaltree(n->nif.ifpart, flags); - status = exitstatus; - } else if (n->nif.elsepart) { + else if (n->nif.elsepart) evaltree(n->nif.elsepart, flags); - status = exitstatus; - } - exitstatus = status; break; } case NWHILE: @@ -287,7 +258,7 @@ out: STATIC void evalloop(n) union node *n; - { +{ int status; loopnest++; @@ -323,8 +294,8 @@ skipping: if (evalskip == SKIPCONT && --skipcount <= 0) { STATIC void evalfor(n) - union node *n; - { + union node *n; +{ struct arglist arglist; union node *argp; struct strlist *sp; @@ -333,6 +304,7 @@ evalfor(n) setstackmark(&smark); arglist.lastp = &arglist.list; for (argp = n->nfor.args ; argp ; argp = argp->narg.next) { + oexitstatus = exitstatus; expandarg(argp, &arglist, EXP_FULL | EXP_TILDE); if (evalskip) goto out; @@ -364,7 +336,8 @@ out: STATIC void evalcase(n, flags) union node *n; - { + int flags; +{ union node *cp; union node *patp; struct arglist arglist; @@ -372,6 +345,7 @@ evalcase(n, flags) setstackmark(&smark); arglist.lastp = &arglist.list; + oexitstatus = exitstatus; expandarg(n->ncase.expr, &arglist, EXP_TILDE); for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) { for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) { @@ -396,7 +370,8 @@ out: STATIC void evalsubshell(n, flags) union node *n; - { + int flags; +{ struct job *jp; int backgnd = (n->type == NBACKGND); @@ -424,17 +399,27 @@ evalsubshell(n, flags) STATIC void expredir(n) union node *n; - { +{ register union node *redir; for (redir = n ; redir ; redir = redir->nfile.next) { - if (redir->type == NFROM - || redir->type == NTO - || redir->type == NAPPEND) { - struct arglist fn; - fn.lastp = &fn.list; + struct arglist fn; + fn.lastp = &fn.list; + oexitstatus = exitstatus; + switch (redir->type) { + case NFROM: + case NTO: + case NAPPEND: expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR); redir->nfile.expfname = fn.list->text; + break; + case NFROMFD: + case NTOFD: + if (redir->ndup.vname) { + expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE); + fixredir(redir, fn.list->text, 1); + } + break; } } } @@ -451,14 +436,14 @@ expredir(n) STATIC void evalpipe(n) union node *n; - { +{ struct job *jp; struct nodelist *lp; int pipelen; int prevfd; int pip[2]; - TRACE(("evalpipe(0x%x) called\n", (int)n)); + TRACE(("evalpipe(0x%lx) called\n", (long)n)); pipelen = 0; for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) pipelen++; @@ -518,7 +503,7 @@ void evalbackcmd(n, result) union node *n; struct backcmd *result; - { +{ int pip[2]; struct job *jp; struct stackmark smark; /* unnecessary */ @@ -528,12 +513,15 @@ evalbackcmd(n, result) result->buf = NULL; result->nleft = 0; result->jp = NULL; - exitstatus = 0; - if (n == NULL) + if (n == NULL) { + exitstatus = 0; goto out; + } if (n->type == NCMD) { + exitstatus = oexitstatus; evalcommand(n, EV_BACKCMD, result); } else { + exitstatus = 0; if (pipe(pip) < 0) error("Pipe call failed"); jp = makejob(n, 1); @@ -566,8 +554,9 @@ out: STATIC void evalcommand(cmd, flags, backcmd) union node *cmd; + int flags; struct backcmd *backcmd; - { +{ struct stackmark smark; union node *argp; struct arglist arglist; @@ -577,7 +566,6 @@ evalcommand(cmd, flags, backcmd) char **envp; int varflag; struct strlist *sp; - register char *p; int mode; int pip[2]; struct cmdentry cmdentry; @@ -589,15 +577,24 @@ evalcommand(cmd, flags, backcmd) struct localvar *volatile savelocalvars; volatile int e; char *lastarg; +#if __GNUC__ + /* Avoid longjmp clobbering */ + (void) &argv; + (void) &argc; + (void) &lastarg; + (void) &flags; +#endif /* First expand the arguments. */ - TRACE(("evalcommand(0x%x, %d) called\n", (int)cmd, flags)); + TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags)); setstackmark(&smark); arglist.lastp = &arglist.list; varlist.lastp = &varlist.list; varflag = 1; + oexitstatus = exitstatus; + exitstatus = 0; for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) { - p = argp->narg.text; + char *p = argp->narg.text; if (varflag && is_name(*p)) { do { p++; @@ -650,7 +647,7 @@ evalcommand(cmd, flags, backcmd) } else { find_command(argv[0], &cmdentry, 1); if (cmdentry.cmdtype == CMDUNKNOWN) { /* command not found */ - exitstatus = 2; + exitstatus = 1; flushout(&errout); return; } @@ -662,7 +659,7 @@ evalcommand(cmd, flags, backcmd) break; if ((cmdentry.u.index = find_builtin(*argv)) < 0) { outfmt(&errout, "%s: not found\n", *argv); - exitstatus = 2; + exitstatus = 1; flushout(&errout); return; } @@ -674,11 +671,11 @@ evalcommand(cmd, flags, backcmd) /* Fork off a child process if necessary. */ if (cmd->ncmd.backgnd - || cmdentry.cmdtype == CMDNORMAL && (flags & EV_EXIT) == 0 - || (flags & EV_BACKCMD) != 0 + || (cmdentry.cmdtype == CMDNORMAL && (flags & EV_EXIT) == 0) + || ((flags & EV_BACKCMD) != 0 && (cmdentry.cmdtype != CMDBUILTIN || cmdentry.u.index == DOTCMD - || cmdentry.u.index == EVALCMD)) { + || cmdentry.u.index == EVALCMD))) { jp = makejob(cmd, 1); mode = cmd->ncmd.backgnd; if (flags & EV_BACKCMD) { @@ -787,7 +784,9 @@ cmddone: if (e != EXERROR || cmdentry.u.index == BLTINCMD || cmdentry.u.index == DOTCMD || cmdentry.u.index == EVALCMD +#ifndef NO_HISTORY || cmdentry.u.index == HISTCMD +#endif || cmdentry.u.index == EXECCMD) exraise(e); FORCEINTON; @@ -803,16 +802,10 @@ cmddone: trputs("normal command: "); trargs(argv); clearredir(); redirect(cmd->ncmd.redirect, 0); - if (varlist.list) { - p = stalloc(strlen(pathval()) + 1); - scopy(pathval(), p); - } else { - p = pathval(); - } for (sp = varlist.list ; sp ; sp = sp->next) setvareq(sp->text, VEXPORT|VSTACK); envp = environment(); - shellexec(argv, envp, p, cmdentry.u.index); + shellexec(argv, envp, pathval(), cmdentry.u.index); /*NOTREACHED*/ } goto out; @@ -846,11 +839,12 @@ out: STATIC void prehash(n) union node *n; - { +{ struct cmdentry entry; - if (n->type == NCMD && goodname(n->ncmd.args->narg.text)) - find_command(n->ncmd.args->narg.text, &entry, 0); + if (n->type == NCMD && n->ncmd.args) + if (goodname(n->ncmd.args->narg.text)) + find_command(n->ncmd.args->narg.text, &entry, 0); } @@ -865,8 +859,16 @@ prehash(n) * specified variables. */ -bltincmd(argc, argv) char **argv; { +int +bltincmd(argc, argv) + int argc; + char **argv; +{ listsetvar(cmdenviron); + /* + * Preserve exitstatus of a previous possible redirection + * as POSIX mandates + */ return exitstatus; } @@ -882,7 +884,11 @@ bltincmd(argc, argv) char **argv; { * in the standard shell so we don't make it one here. */ -breakcmd(argc, argv) char **argv; { +int +breakcmd(argc, argv) + int argc; + char **argv; +{ int n; n = 1; @@ -902,7 +908,11 @@ breakcmd(argc, argv) char **argv; { * The return command. */ -returncmd(argc, argv) char **argv; { +int +returncmd(argc, argv) + int argc; + char **argv; +{ int ret; ret = exitstatus; @@ -916,16 +926,37 @@ returncmd(argc, argv) char **argv; { } -truecmd(argc, argv) char **argv; { +int +falsecmd(argc, argv) + int argc; + char **argv; +{ + return 1; +} + + +int +truecmd(argc, argv) + int argc; + char **argv; +{ return 0; } -execcmd(argc, argv) char **argv; { +int +execcmd(argc, argv) + int argc; + char **argv; +{ if (argc > 1) { + struct strlist *sp; + iflag = 0; /* exit on error */ mflag = 0; optschanged(); + for (sp = cmdenviron; sp ; sp = sp->next) + setvareq(sp->text, VEXPORT|VSTACK); shellexec(argv + 1, environment(), pathval(), 0); }