[VAR] Do not poplocalvars prematurely on regular utilities
[dash.git] / src / eval.c
blob337667fadca7619c7dfbccff3254c2bcc9955d25
1 /*-
2 * Copyright (c) 1993
3 * The Regents of the University of California. All rights reserved.
4 * Copyright (c) 1997-2005
5 * Herbert Xu <herbert@gondor.apana.org.au>. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
8 * Kenneth Almquist.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
35 #include <stdlib.h>
36 #include <signal.h>
37 #include <unistd.h>
38 #include <sys/types.h>
41 * Evaluate a command.
44 #include "shell.h"
45 #include "nodes.h"
46 #include "syntax.h"
47 #include "expand.h"
48 #include "parser.h"
49 #include "jobs.h"
50 #include "eval.h"
51 #include "builtins.h"
52 #include "options.h"
53 #include "exec.h"
54 #include "redir.h"
55 #include "input.h"
56 #include "output.h"
57 #include "trap.h"
58 #include "var.h"
59 #include "memalloc.h"
60 #include "error.h"
61 #include "show.h"
62 #include "mystring.h"
63 #ifndef SMALL
64 #include "myhistedit.h"
65 #endif
68 /* flags in argument to evaltree */
69 #define EV_EXIT 01 /* exit after evaluating tree */
70 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
71 #define EV_BACKCMD 04 /* command executing within back quotes */
73 int evalskip; /* set if we are skipping commands */
74 STATIC int skipcount; /* number of levels to skip */
75 MKINIT int loopnest; /* current loop nesting level */
76 static int funcnest; /* depth of function calls */
79 char *commandname;
80 int exitstatus; /* exit status of last command */
81 int back_exitstatus; /* exit status of backquoted command */
84 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
85 STATIC
86 #endif
87 void evaltreenr(union node *, int) __attribute__ ((__noreturn__));
88 STATIC void evalloop(union node *, int);
89 STATIC void evalfor(union node *, int);
90 STATIC void evalcase(union node *, int);
91 STATIC void evalsubshell(union node *, int);
92 STATIC void expredir(union node *);
93 STATIC void evalpipe(union node *, int);
94 #ifdef notyet
95 STATIC void evalcommand(union node *, int, struct backcmd *);
96 #else
97 STATIC void evalcommand(union node *, int);
98 #endif
99 STATIC int evalbltin(const struct builtincmd *, int, char **, int);
100 STATIC int evalfun(struct funcnode *, int, char **, int);
101 STATIC void prehash(union node *);
102 STATIC int eprintlist(struct output *, struct strlist *, int);
103 STATIC int bltincmd(int, char **);
106 STATIC const struct builtincmd bltin = {
107 name: nullstr,
108 builtin: bltincmd
113 * Called to reset things after an exception.
116 #ifdef mkinit
117 INCLUDE "eval.h"
119 RESET {
120 evalskip = 0;
121 loopnest = 0;
123 #endif
128 * The eval commmand.
131 static int evalcmd(int argc, char **argv, int flags)
133 char *p;
134 char *concat;
135 char **ap;
137 if (argc > 1) {
138 p = argv[1];
139 if (argc > 2) {
140 STARTSTACKSTR(concat);
141 ap = argv + 2;
142 for (;;) {
143 concat = stputs(p, concat);
144 if ((p = *ap++) == NULL)
145 break;
146 STPUTC(' ', concat);
148 STPUTC('\0', concat);
149 p = grabstackstr(concat);
151 return evalstring(p, flags & EV_TESTED);
153 return 0;
158 * Execute a command or commands contained in a string.
162 evalstring(char *s, int flags)
164 union node *n;
165 struct stackmark smark;
166 int status;
168 setinputstring(s);
169 setstackmark(&smark);
171 status = 0;
172 while ((n = parsecmd(0)) != NEOF) {
173 evaltree(n, flags);
174 status = exitstatus;
175 popstackmark(&smark);
176 if (evalskip)
177 break;
179 popfile();
181 return status;
187 * Evaluate a parse tree. The value is left in the global variable
188 * exitstatus.
191 void
192 evaltree(union node *n, int flags)
194 int checkexit = 0;
195 void (*evalfn)(union node *, int);
196 unsigned isor;
197 int status;
198 if (n == NULL) {
199 TRACE(("evaltree(NULL) called\n"));
200 goto out;
202 #ifndef SMALL
203 displayhist = 1; /* show history substitutions done with fc */
204 #endif
205 TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
206 getpid(), n, n->type, flags));
207 switch (n->type) {
208 default:
209 #ifdef DEBUG
210 out1fmt("Node type = %d\n", n->type);
211 #ifndef USE_GLIBC_STDIO
212 flushout(out1);
213 #endif
214 break;
215 #endif
216 case NNOT:
217 evaltree(n->nnot.com, EV_TESTED);
218 status = !exitstatus;
219 goto setstatus;
220 case NREDIR:
221 expredir(n->nredir.redirect);
222 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
223 if (!status) {
224 evaltree(n->nredir.n, flags & EV_TESTED);
225 status = exitstatus;
227 popredir(0);
228 goto setstatus;
229 case NCMD:
230 #ifdef notyet
231 if (eflag && !(flags & EV_TESTED))
232 checkexit = ~0;
233 evalcommand(n, flags, (struct backcmd *)NULL);
234 break;
235 #else
236 evalfn = evalcommand;
237 checkexit:
238 if (eflag && !(flags & EV_TESTED))
239 checkexit = ~0;
240 goto calleval;
241 #endif
242 case NFOR:
243 evalfn = evalfor;
244 goto calleval;
245 case NWHILE:
246 case NUNTIL:
247 evalfn = evalloop;
248 goto calleval;
249 case NSUBSHELL:
250 case NBACKGND:
251 evalfn = evalsubshell;
252 goto calleval;
253 case NPIPE:
254 evalfn = evalpipe;
255 #ifdef notyet
256 if (eflag && !(flags & EV_TESTED))
257 checkexit = ~0;
258 goto calleval;
259 #else
260 goto checkexit;
261 #endif
262 case NCASE:
263 evalfn = evalcase;
264 goto calleval;
265 case NAND:
266 case NOR:
267 case NSEMI:
268 #if NAND + 1 != NOR
269 #error NAND + 1 != NOR
270 #endif
271 #if NOR + 1 != NSEMI
272 #error NOR + 1 != NSEMI
273 #endif
274 isor = n->type - NAND;
275 evaltree(
276 n->nbinary.ch1,
277 (flags | ((isor >> 1) - 1)) & EV_TESTED
279 if (!exitstatus == isor)
280 break;
281 if (!evalskip) {
282 n = n->nbinary.ch2;
283 evaln:
284 evalfn = evaltree;
285 calleval:
286 evalfn(n, flags);
287 break;
289 break;
290 case NIF:
291 evaltree(n->nif.test, EV_TESTED);
292 if (evalskip)
293 break;
294 if (exitstatus == 0) {
295 n = n->nif.ifpart;
296 goto evaln;
297 } else if (n->nif.elsepart) {
298 n = n->nif.elsepart;
299 goto evaln;
301 goto success;
302 case NDEFUN:
303 defun(n->narg.text, n->narg.next);
304 success:
305 status = 0;
306 setstatus:
307 exitstatus = status;
308 break;
310 out:
311 if ((checkexit & exitstatus) ||
312 (pendingsigs && dotrap()) ||
313 (flags & EV_EXIT))
314 exraise(EXEXIT);
318 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
319 STATIC
320 #endif
321 void evaltreenr(union node *n, int flags)
322 #ifdef HAVE_ATTRIBUTE_ALIAS
323 __attribute__ ((alias("evaltree")));
324 #else
326 evaltree(n, flags);
327 abort();
329 #endif
332 STATIC void
333 evalloop(union node *n, int flags)
335 int status;
337 loopnest++;
338 status = 0;
339 flags &= EV_TESTED;
340 for (;;) {
341 int i;
343 evaltree(n->nbinary.ch1, EV_TESTED);
344 if (evalskip) {
345 skipping: if (evalskip == SKIPCONT && --skipcount <= 0) {
346 evalskip = 0;
347 continue;
349 if (evalskip == SKIPBREAK && --skipcount <= 0)
350 evalskip = 0;
351 break;
353 i = exitstatus;
354 if (n->type != NWHILE)
355 i = !i;
356 if (i != 0)
357 break;
358 evaltree(n->nbinary.ch2, flags);
359 status = exitstatus;
360 if (evalskip)
361 goto skipping;
363 loopnest--;
364 exitstatus = status;
369 STATIC void
370 evalfor(union node *n, int flags)
372 struct arglist arglist;
373 union node *argp;
374 struct strlist *sp;
375 struct stackmark smark;
377 setstackmark(&smark);
378 arglist.lastp = &arglist.list;
379 for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
380 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
381 /* XXX */
382 if (evalskip)
383 goto out;
385 *arglist.lastp = NULL;
387 exitstatus = 0;
388 loopnest++;
389 flags &= EV_TESTED;
390 for (sp = arglist.list ; sp ; sp = sp->next) {
391 setvar(n->nfor.var, sp->text, 0);
392 evaltree(n->nfor.body, flags);
393 if (evalskip) {
394 if (evalskip == SKIPCONT && --skipcount <= 0) {
395 evalskip = 0;
396 continue;
398 if (evalskip == SKIPBREAK && --skipcount <= 0)
399 evalskip = 0;
400 break;
403 loopnest--;
404 out:
405 popstackmark(&smark);
410 STATIC void
411 evalcase(union node *n, int flags)
413 union node *cp;
414 union node *patp;
415 struct arglist arglist;
416 struct stackmark smark;
418 setstackmark(&smark);
419 arglist.lastp = &arglist.list;
420 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
421 exitstatus = 0;
422 for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
423 for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
424 if (casematch(patp, arglist.list->text)) {
425 if (evalskip == 0) {
426 evaltree(cp->nclist.body, flags);
428 goto out;
432 out:
433 popstackmark(&smark);
439 * Kick off a subshell to evaluate a tree.
442 STATIC void
443 evalsubshell(union node *n, int flags)
445 struct job *jp;
446 int backgnd = (n->type == NBACKGND);
447 int status;
449 expredir(n->nredir.redirect);
450 if (!backgnd && flags & EV_EXIT && !trap[0])
451 goto nofork;
452 INTOFF;
453 jp = makejob(n, 1);
454 if (forkshell(jp, n, backgnd) == 0) {
455 INTON;
456 flags |= EV_EXIT;
457 if (backgnd)
458 flags &=~ EV_TESTED;
459 nofork:
460 redirect(n->nredir.redirect, 0);
461 evaltreenr(n->nredir.n, flags);
462 /* never returns */
464 status = 0;
465 if (! backgnd)
466 status = waitforjob(jp);
467 exitstatus = status;
468 INTON;
474 * Compute the names of the files in a redirection list.
477 STATIC void
478 expredir(union node *n)
480 union node *redir;
482 for (redir = n ; redir ; redir = redir->nfile.next) {
483 struct arglist fn;
484 fn.lastp = &fn.list;
485 switch (redir->type) {
486 case NFROMTO:
487 case NFROM:
488 case NTO:
489 case NCLOBBER:
490 case NAPPEND:
491 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
492 redir->nfile.expfname = fn.list->text;
493 break;
494 case NFROMFD:
495 case NTOFD:
496 if (redir->ndup.vname) {
497 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
498 fixredir(redir, fn.list->text, 1);
500 break;
508 * Evaluate a pipeline. All the processes in the pipeline are children
509 * of the process creating the pipeline. (This differs from some versions
510 * of the shell, which make the last process in a pipeline the parent
511 * of all the rest.)
514 STATIC void
515 evalpipe(union node *n, int flags)
517 struct job *jp;
518 struct nodelist *lp;
519 int pipelen;
520 int prevfd;
521 int pip[2];
523 TRACE(("evalpipe(0x%lx) called\n", (long)n));
524 pipelen = 0;
525 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
526 pipelen++;
527 flags |= EV_EXIT;
528 INTOFF;
529 jp = makejob(n, pipelen);
530 prevfd = -1;
531 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
532 prehash(lp->n);
533 pip[1] = -1;
534 if (lp->next) {
535 if (pipe(pip) < 0) {
536 close(prevfd);
537 sh_error("Pipe call failed");
540 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
541 INTON;
542 if (pip[1] >= 0) {
543 close(pip[0]);
545 if (prevfd > 0) {
546 dup2(prevfd, 0);
547 close(prevfd);
549 if (pip[1] > 1) {
550 dup2(pip[1], 1);
551 close(pip[1]);
553 evaltreenr(lp->n, flags);
554 /* never returns */
556 if (prevfd >= 0)
557 close(prevfd);
558 prevfd = pip[0];
559 close(pip[1]);
561 if (n->npipe.backgnd == 0) {
562 exitstatus = waitforjob(jp);
563 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
565 INTON;
571 * Execute a command inside back quotes. If it's a builtin command, we
572 * want to save its output in a block obtained from malloc. Otherwise
573 * we fork off a subprocess and get the output of the command via a pipe.
574 * Should be called with interrupts off.
577 void
578 evalbackcmd(union node *n, struct backcmd *result)
580 result->fd = -1;
581 result->buf = NULL;
582 result->nleft = 0;
583 result->jp = NULL;
584 if (n == NULL) {
585 goto out;
588 #ifdef notyet
590 * For now we disable executing builtins in the same
591 * context as the shell, because we are not keeping
592 * enough state to recover from changes that are
593 * supposed only to affect subshells. eg. echo "`cd /`"
595 if (n->type == NCMD) {
596 struct ifsregion saveifs;
597 struct ifsregion *savelastp;
598 struct nodelist *saveargbackq;
600 saveifs = ifsfirst;
601 savelastp = ifslastp;
602 saveargbackq = argbackq;
604 exitstatus = oexitstatus;
605 evalcommand(n, EV_BACKCMD, result);
607 ifsfirst = saveifs;
608 ifslastp = savelastp;
609 argbackq = saveargbackq;
610 } else
611 #endif
613 int pip[2];
614 struct job *jp;
616 if (pipe(pip) < 0)
617 sh_error("Pipe call failed");
618 jp = makejob(n, 1);
619 if (forkshell(jp, n, FORK_NOJOB) == 0) {
620 FORCEINTON;
621 close(pip[0]);
622 if (pip[1] != 1) {
623 dup2(pip[1], 1);
624 close(pip[1]);
626 eflag = 0;
627 evaltreenr(n, EV_EXIT);
628 /* NOTREACHED */
630 close(pip[1]);
631 result->fd = pip[0];
632 result->jp = jp;
634 out:
635 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
636 result->fd, result->buf, result->nleft, result->jp));
639 static char **
640 parse_command_args(char **argv, const char **path)
642 char *cp, c;
644 for (;;) {
645 cp = *++argv;
646 if (!cp)
647 return 0;
648 if (*cp++ != '-')
649 break;
650 if (!(c = *cp++))
651 break;
652 if (c == '-' && !*cp) {
653 if (!*++argv)
654 return 0;
655 break;
657 do {
658 switch (c) {
659 case 'p':
660 *path = defpath;
661 break;
662 default:
663 /* run 'typecmd' for other options */
664 return 0;
666 } while ((c = *cp++));
668 return argv;
674 * Execute a simple command.
677 STATIC void
678 #ifdef notyet
679 evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
680 #else
681 evalcommand(union node *cmd, int flags)
682 #endif
684 struct localvar_list *localvar_stop;
685 struct stackmark smark;
686 union node *argp;
687 struct arglist arglist;
688 struct arglist varlist;
689 char **argv;
690 int argc;
691 struct strlist *sp;
692 #ifdef notyet
693 int pip[2];
694 #endif
695 struct cmdentry cmdentry;
696 struct job *jp;
697 char *lastarg;
698 const char *path;
699 int spclbltin;
700 int execcmd;
701 int status;
702 char **nargv;
704 /* First expand the arguments. */
705 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
706 setstackmark(&smark);
707 localvar_stop = pushlocalvars();
708 back_exitstatus = 0;
710 cmdentry.cmdtype = CMDBUILTIN;
711 cmdentry.u.cmd = &bltin;
712 varlist.lastp = &varlist.list;
713 *varlist.lastp = NULL;
714 arglist.lastp = &arglist.list;
715 *arglist.lastp = NULL;
717 argc = 0;
718 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
719 struct strlist **spp;
721 spp = arglist.lastp;
722 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
723 for (sp = *spp; sp; sp = sp->next)
724 argc++;
727 /* Reserve one extra spot at the front for shellexec. */
728 nargv = stalloc(sizeof (char *) * (argc + 2));
729 argv = ++nargv;
730 for (sp = arglist.list ; sp ; sp = sp->next) {
731 TRACE(("evalcommand arg: %s\n", sp->text));
732 *nargv++ = sp->text;
734 *nargv = NULL;
736 lastarg = NULL;
737 if (iflag && funcnest == 0 && argc > 0)
738 lastarg = nargv[-1];
740 preverrout.fd = 2;
741 expredir(cmd->ncmd.redirect);
742 status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH|REDIR_SAVEFD2);
744 path = vpath.text;
745 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
746 struct strlist **spp;
747 char *p;
749 spp = varlist.lastp;
750 expandarg(argp, &varlist, EXP_VARTILDE);
752 mklocal((*spp)->text);
755 * Modify the command lookup path, if a PATH= assignment
756 * is present
758 p = (*spp)->text;
759 if (varequal(p, path))
760 path = p;
763 /* Print the command if xflag is set. */
764 if (xflag) {
765 struct output *out;
766 int sep;
768 out = &preverrout;
769 outstr(expandstr(ps4val()), out);
770 sep = 0;
771 sep = eprintlist(out, varlist.list, sep);
772 eprintlist(out, arglist.list, sep);
773 outcslow('\n', out);
774 #ifdef FLUSHERR
775 flushout(out);
776 #endif
779 execcmd = 0;
780 spclbltin = -1;
782 /* Now locate the command. */
783 if (argc) {
784 const char *oldpath;
785 int cmd_flag = DO_ERR;
787 path += 5;
788 oldpath = path;
789 for (;;) {
790 find_command(argv[0], &cmdentry, cmd_flag, path);
791 if (cmdentry.cmdtype == CMDUNKNOWN) {
792 status = 127;
793 #ifdef FLUSHERR
794 flushout(&errout);
795 #endif
796 goto bail;
799 /* implement bltin and command here */
800 if (cmdentry.cmdtype != CMDBUILTIN)
801 break;
802 if (spclbltin < 0)
803 spclbltin =
804 cmdentry.u.cmd->flags &
805 BUILTIN_SPECIAL
807 if (cmdentry.u.cmd == EXECCMD)
808 execcmd++;
809 if (cmdentry.u.cmd != COMMANDCMD)
810 break;
812 path = oldpath;
813 nargv = parse_command_args(argv, &path);
814 if (!nargv)
815 break;
816 argc -= nargv - argv;
817 argv = nargv;
818 cmd_flag |= DO_NOFUNC;
822 if (status) {
823 /* We have a redirection error. */
824 if (spclbltin > 0)
825 exraise(EXERROR);
826 bail:
827 exitstatus = status;
828 goto out;
831 /* Execute the command. */
832 switch (cmdentry.cmdtype) {
833 default:
834 /* Fork off a child process if necessary. */
835 if (!(flags & EV_EXIT) || trap[0]) {
836 INTOFF;
837 jp = makejob(cmd, 1);
838 if (forkshell(jp, cmd, FORK_FG) != 0) {
839 exitstatus = waitforjob(jp);
840 INTON;
841 break;
843 FORCEINTON;
845 listsetvar(varlist.list, VEXPORT|VSTACK);
846 shellexec(argv, path, cmdentry.u.index);
847 /* NOTREACHED */
849 case CMDBUILTIN:
850 if (spclbltin > 0 || argc == 0) {
851 poplocalvars(1);
852 if (execcmd && argc > 1)
853 listsetvar(varlist.list, VEXPORT);
855 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
856 int status;
857 int i;
859 i = exception;
860 if (i == EXEXIT)
861 goto raise;
863 status = (i == EXINT) ? SIGINT + 128 : 2;
864 exitstatus = status;
866 if (i == EXINT || spclbltin > 0) {
867 raise:
868 longjmp(handler->loc, 1);
870 FORCEINTON;
872 break;
874 case CMDFUNCTION:
875 poplocalvars(1);
876 if (evalfun(cmdentry.u.func, argc, argv, flags))
877 goto raise;
878 break;
881 out:
882 popredir(execcmd);
883 unwindlocalvars(localvar_stop);
884 if (lastarg)
885 /* dsl: I think this is intended to be used to support
886 * '_' in 'vi' command mode during line editing...
887 * However I implemented that within libedit itself.
889 setvar("_", lastarg, 0);
890 popstackmark(&smark);
893 STATIC int
894 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
896 char *volatile savecmdname;
897 struct jmploc *volatile savehandler;
898 struct jmploc jmploc;
899 int status;
900 int i;
902 savecmdname = commandname;
903 if ((i = setjmp(jmploc.loc)))
904 goto cmddone;
905 savehandler = handler;
906 handler = &jmploc;
907 commandname = argv[0];
908 argptr = argv + 1;
909 optptr = NULL; /* initialize nextopt */
910 if (cmd == EVALCMD)
911 status = evalcmd(argc, argv, flags);
912 else
913 status = (*cmd->builtin)(argc, argv);
914 flushall();
915 status |= outerr(out1);
916 exitstatus = status;
917 cmddone:
918 freestdout();
919 commandname = savecmdname;
920 handler = savehandler;
922 return i;
925 STATIC int
926 evalfun(struct funcnode *func, int argc, char **argv, int flags)
928 volatile struct shparam saveparam;
929 struct jmploc *volatile savehandler;
930 struct jmploc jmploc;
931 int e;
933 saveparam = shellparam;
934 if ((e = setjmp(jmploc.loc))) {
935 goto funcdone;
937 INTOFF;
938 savehandler = handler;
939 handler = &jmploc;
940 shellparam.malloc = 0;
941 func->count++;
942 funcnest++;
943 INTON;
944 shellparam.nparam = argc - 1;
945 shellparam.p = argv + 1;
946 shellparam.optind = 1;
947 shellparam.optoff = -1;
948 pushlocalvars();
949 evaltree(&func->n, flags & EV_TESTED);
950 poplocalvars(0);
951 funcdone:
952 INTOFF;
953 funcnest--;
954 freefunc(func);
955 freeparam(&shellparam);
956 shellparam = saveparam;
957 handler = savehandler;
958 INTON;
959 evalskip &= ~SKIPFUNC;
960 return e;
965 * Search for a command. This is called before we fork so that the
966 * location of the command will be available in the parent as well as
967 * the child. The check for "goodname" is an overly conservative
968 * check that the name will not be subject to expansion.
971 STATIC void
972 prehash(union node *n)
974 struct cmdentry entry;
976 if (n->type == NCMD && n->ncmd.args)
977 if (goodname(n->ncmd.args->narg.text))
978 find_command(n->ncmd.args->narg.text, &entry, 0,
979 pathval());
985 * Builtin commands. Builtin commands whose functions are closely
986 * tied to evaluation are implemented here.
990 * No command given.
993 STATIC int
994 bltincmd(int argc, char **argv)
997 * Preserve exitstatus of a previous possible redirection
998 * as POSIX mandates
1000 return back_exitstatus;
1005 * Handle break and continue commands. Break, continue, and return are
1006 * all handled by setting the evalskip flag. The evaluation routines
1007 * above all check this flag, and if it is set they start skipping
1008 * commands rather than executing them. The variable skipcount is
1009 * the number of loops to break/continue, or the number of function
1010 * levels to return. (The latter is always 1.) It should probably
1011 * be an error to break out of more loops than exist, but it isn't
1012 * in the standard shell so we don't make it one here.
1016 breakcmd(int argc, char **argv)
1018 int n = argc > 1 ? number(argv[1]) : 1;
1020 if (n <= 0)
1021 badnum(argv[1]);
1022 if (n > loopnest)
1023 n = loopnest;
1024 if (n > 0) {
1025 evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
1026 skipcount = n;
1028 return 0;
1033 * The return command.
1037 returncmd(int argc, char **argv)
1040 * If called outside a function, do what ksh does;
1041 * skip the rest of the file.
1043 evalskip = funcnest ? SKIPFUNC : SKIPFILE;
1044 return argv[1] ? number(argv[1]) : exitstatus;
1049 falsecmd(int argc, char **argv)
1051 return 1;
1056 truecmd(int argc, char **argv)
1058 return 0;
1063 execcmd(int argc, char **argv)
1065 if (argc > 1) {
1066 iflag = 0; /* exit on error */
1067 mflag = 0;
1068 optschanged();
1069 shellexec(argv + 1, pathval(), 0);
1071 return 0;
1075 STATIC int
1076 eprintlist(struct output *out, struct strlist *sp, int sep)
1078 while (sp) {
1079 const char *p;
1081 p = " %s" + (1 - sep);
1082 sep |= 1;
1083 outfmt(out, p, sp->text);
1084 sp = sp->next;
1087 return sep;