eval.c revision 99110
1/*-
2 * Copyright (c) 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Kenneth Almquist.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 *    must display the following acknowledgement:
18 *	This product includes software developed by the University of
19 *	California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 *    may be used to endorse or promote products derived from this software
22 *    without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#ifndef lint
38#if 0
39static char sccsid[] = "@(#)eval.c	8.9 (Berkeley) 6/8/95";
40#endif
41#endif /* not lint */
42#include <sys/cdefs.h>
43__FBSDID("$FreeBSD: head/bin/sh/eval.c 99110 2002-06-30 05:15:05Z obrien $");
44
45#include <signal.h>
46#include <unistd.h>
47#include <sys/wait.h> /* For WIFSIGNALED(status) */
48#include <errno.h>
49
50/*
51 * Evaluate a command.
52 */
53
54#include "shell.h"
55#include "nodes.h"
56#include "syntax.h"
57#include "expand.h"
58#include "parser.h"
59#include "jobs.h"
60#include "eval.h"
61#include "builtins.h"
62#include "options.h"
63#include "exec.h"
64#include "redir.h"
65#include "input.h"
66#include "output.h"
67#include "trap.h"
68#include "var.h"
69#include "memalloc.h"
70#include "error.h"
71#include "show.h"
72#include "mystring.h"
73#ifndef NO_HISTORY
74#include "myhistedit.h"
75#endif
76
77
78/* flags in argument to evaltree */
79#define EV_EXIT 01		/* exit after evaluating tree */
80#define EV_TESTED 02		/* exit status is checked; ignore -e flag */
81#define EV_BACKCMD 04		/* command executing within back quotes */
82
83MKINIT int evalskip;		/* set if we are skipping commands */
84STATIC int skipcount;		/* number of levels to skip */
85MKINIT int loopnest;		/* current loop nesting level */
86int funcnest;			/* depth of function calls */
87
88
89char *commandname;
90struct strlist *cmdenviron;
91int exitstatus;			/* exit status of last command */
92int oexitstatus;		/* saved exit status */
93
94
95STATIC void evalloop(union node *);
96STATIC void evalfor(union node *);
97STATIC void evalcase(union node *, int);
98STATIC void evalsubshell(union node *, int);
99STATIC void expredir(union node *);
100STATIC void evalpipe(union node *);
101STATIC void evalcommand(union node *, int, struct backcmd *);
102STATIC void prehash(union node *);
103
104
105/*
106 * Called to reset things after an exception.
107 */
108
109#ifdef mkinit
110INCLUDE "eval.h"
111
112RESET {
113	evalskip = 0;
114	loopnest = 0;
115	funcnest = 0;
116}
117
118SHELLPROC {
119	exitstatus = 0;
120}
121#endif
122
123
124
125/*
126 * The eval command.
127 */
128
129int
130evalcmd(int argc, char **argv)
131{
132        char *p;
133        char *concat;
134        char **ap;
135
136        if (argc > 1) {
137                p = argv[1];
138                if (argc > 2) {
139                        STARTSTACKSTR(concat);
140                        ap = argv + 2;
141                        for (;;) {
142                                while (*p)
143                                        STPUTC(*p++, concat);
144                                if ((p = *ap++) == NULL)
145                                        break;
146                                STPUTC(' ', concat);
147                        }
148                        STPUTC('\0', concat);
149                        p = grabstackstr(concat);
150                }
151                evalstring(p);
152        }
153        return exitstatus;
154}
155
156
157/*
158 * Execute a command or commands contained in a string.
159 */
160
161void
162evalstring(char *s)
163{
164	union node *n;
165	struct stackmark smark;
166
167	setstackmark(&smark);
168	setinputstring(s, 1);
169	while ((n = parsecmd(0)) != NEOF) {
170		evaltree(n, 0);
171		popstackmark(&smark);
172	}
173	popfile();
174	popstackmark(&smark);
175}
176
177
178
179/*
180 * Evaluate a parse tree.  The value is left in the global variable
181 * exitstatus.
182 */
183
184void
185evaltree(union node *n, int flags)
186{
187	if (n == NULL) {
188		TRACE(("evaltree(NULL) called\n"));
189		exitstatus = 0;
190		goto out;
191	}
192#ifndef NO_HISTORY
193	displayhist = 1;	/* show history substitutions done with fc */
194#endif
195	TRACE(("evaltree(0x%lx: %d) called\n", (long)n, n->type));
196	switch (n->type) {
197	case NSEMI:
198		evaltree(n->nbinary.ch1, 0);
199		if (evalskip)
200			goto out;
201		evaltree(n->nbinary.ch2, flags);
202		break;
203	case NAND:
204		evaltree(n->nbinary.ch1, EV_TESTED);
205		if (evalskip || exitstatus != 0) {
206			flags |= EV_TESTED;
207			goto out;
208		}
209		evaltree(n->nbinary.ch2, flags);
210		break;
211	case NOR:
212		evaltree(n->nbinary.ch1, EV_TESTED);
213		if (evalskip || exitstatus == 0)
214			goto out;
215		evaltree(n->nbinary.ch2, flags);
216		break;
217	case NREDIR:
218		expredir(n->nredir.redirect);
219		redirect(n->nredir.redirect, REDIR_PUSH);
220		evaltree(n->nredir.n, flags);
221		popredir();
222		break;
223	case NSUBSHELL:
224		evalsubshell(n, flags);
225		break;
226	case NBACKGND:
227		evalsubshell(n, flags);
228		break;
229	case NIF: {
230		evaltree(n->nif.test, EV_TESTED);
231		if (evalskip)
232			goto out;
233		if (exitstatus == 0)
234			evaltree(n->nif.ifpart, flags);
235		else if (n->nif.elsepart)
236			evaltree(n->nif.elsepart, flags);
237		else
238			exitstatus = 0;
239		break;
240	}
241	case NWHILE:
242	case NUNTIL:
243		evalloop(n);
244		break;
245	case NFOR:
246		evalfor(n);
247		/*
248		 * The 'for' command does not set exitstatus, so the value
249		 * now in exitstatus is from the last command executed in
250		 * the 'for' loop.  That exit value had been tested (wrt
251		 * 'sh -e' checking) while processing that command, and
252		 * it should not be re-tested here.
253		 */
254		flags |= EV_TESTED;
255		break;
256	case NCASE:
257		evalcase(n, flags);
258		/*
259		 * The 'case' command does not set exitstatus, so the value
260		 * now in exitstatus is from the last command executed in
261		 * the 'case' block.  That exit value had been tested (wrt
262		 * 'sh -e' checking) while processing that command, and
263		 * it should not be re-tested here.
264		 */
265		flags |= EV_TESTED;
266		break;
267	case NDEFUN:
268		defun(n->narg.text, n->narg.next);
269		exitstatus = 0;
270		break;
271	case NNOT:
272		evaltree(n->nnot.com, EV_TESTED);
273		exitstatus = !exitstatus;
274		break;
275
276	case NPIPE:
277		evalpipe(n);
278		break;
279	case NCMD:
280		evalcommand(n, flags, (struct backcmd *)NULL);
281		break;
282	default:
283		out1fmt("Node type = %d\n", n->type);
284		flushout(&output);
285		break;
286	}
287out:
288	if (pendingsigs)
289		dotrap();
290	/*
291	 * XXX - Like "!(n->type == NSEMI)", more types will probably
292	 * need to be excluded from this test. It's probably better
293	 * to set or unset EV_TESTED in the loop above than to bloat
294	 * the conditional here.
295	 */
296	if ((flags & EV_EXIT) || (eflag && exitstatus
297	    && !(flags & EV_TESTED) && !(n->type == NSEMI)))
298		exitshell(exitstatus);
299}
300
301
302STATIC void
303evalloop(union node *n)
304{
305	int status;
306
307	loopnest++;
308	status = 0;
309	for (;;) {
310		evaltree(n->nbinary.ch1, EV_TESTED);
311		if (evalskip) {
312skipping:	  if (evalskip == SKIPCONT && --skipcount <= 0) {
313				evalskip = 0;
314				continue;
315			}
316			if (evalskip == SKIPBREAK && --skipcount <= 0)
317				evalskip = 0;
318			break;
319		}
320		if (n->type == NWHILE) {
321			if (exitstatus != 0)
322				break;
323		} else {
324			if (exitstatus == 0)
325				break;
326		}
327		evaltree(n->nbinary.ch2, 0);
328		status = exitstatus;
329		if (evalskip)
330			goto skipping;
331	}
332	loopnest--;
333	exitstatus = status;
334}
335
336
337
338STATIC void
339evalfor(union node *n)
340{
341	struct arglist arglist;
342	union node *argp;
343	struct strlist *sp;
344	struct stackmark smark;
345
346	setstackmark(&smark);
347	arglist.lastp = &arglist.list;
348	for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
349		oexitstatus = exitstatus;
350		expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
351		if (evalskip)
352			goto out;
353	}
354	*arglist.lastp = NULL;
355
356	exitstatus = 0;
357	loopnest++;
358	for (sp = arglist.list ; sp ; sp = sp->next) {
359		setvar(n->nfor.var, sp->text, 0);
360		evaltree(n->nfor.body, 0);
361		if (evalskip) {
362			if (evalskip == SKIPCONT && --skipcount <= 0) {
363				evalskip = 0;
364				continue;
365			}
366			if (evalskip == SKIPBREAK && --skipcount <= 0)
367				evalskip = 0;
368			break;
369		}
370	}
371	loopnest--;
372out:
373	popstackmark(&smark);
374}
375
376
377
378STATIC void
379evalcase(union node *n, int flags)
380{
381	union node *cp;
382	union node *patp;
383	struct arglist arglist;
384	struct stackmark smark;
385
386	setstackmark(&smark);
387	arglist.lastp = &arglist.list;
388	oexitstatus = exitstatus;
389	expandarg(n->ncase.expr, &arglist, EXP_TILDE);
390	for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
391		for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
392			if (casematch(patp, arglist.list->text)) {
393				if (evalskip == 0) {
394					evaltree(cp->nclist.body, flags);
395				}
396				goto out;
397			}
398		}
399	}
400out:
401	popstackmark(&smark);
402}
403
404
405
406/*
407 * Kick off a subshell to evaluate a tree.
408 */
409
410STATIC void
411evalsubshell(union node *n, int flags)
412{
413	struct job *jp;
414	int backgnd = (n->type == NBACKGND);
415
416	expredir(n->nredir.redirect);
417	jp = makejob(n, 1);
418	if (forkshell(jp, n, backgnd) == 0) {
419		if (backgnd)
420			flags &=~ EV_TESTED;
421		redirect(n->nredir.redirect, 0);
422		evaltree(n->nredir.n, flags | EV_EXIT);	/* never returns */
423	}
424	if (! backgnd) {
425		INTOFF;
426		exitstatus = waitforjob(jp, (int *)NULL);
427		INTON;
428	}
429}
430
431
432
433/*
434 * Compute the names of the files in a redirection list.
435 */
436
437STATIC void
438expredir(union node *n)
439{
440	union node *redir;
441
442	for (redir = n ; redir ; redir = redir->nfile.next) {
443		struct arglist fn;
444		fn.lastp = &fn.list;
445		oexitstatus = exitstatus;
446		switch (redir->type) {
447		case NFROM:
448		case NTO:
449		case NFROMTO:
450		case NAPPEND:
451		case NCLOBBER:
452			expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
453			redir->nfile.expfname = fn.list->text;
454			break;
455		case NFROMFD:
456		case NTOFD:
457			if (redir->ndup.vname) {
458				expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
459				fixredir(redir, fn.list->text, 1);
460			}
461			break;
462		}
463	}
464}
465
466
467
468/*
469 * Evaluate a pipeline.  All the processes in the pipeline are children
470 * of the process creating the pipeline.  (This differs from some versions
471 * of the shell, which make the last process in a pipeline the parent
472 * of all the rest.)
473 */
474
475STATIC void
476evalpipe(union node *n)
477{
478	struct job *jp;
479	struct nodelist *lp;
480	int pipelen;
481	int prevfd;
482	int pip[2];
483
484	TRACE(("evalpipe(0x%lx) called\n", (long)n));
485	pipelen = 0;
486	for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
487		pipelen++;
488	INTOFF;
489	jp = makejob(n, pipelen);
490	prevfd = -1;
491	for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
492		prehash(lp->n);
493		pip[1] = -1;
494		if (lp->next) {
495			if (pipe(pip) < 0) {
496				close(prevfd);
497				error("Pipe call failed: %s", strerror(errno));
498			}
499		}
500		if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
501			INTON;
502			if (prevfd > 0) {
503				close(0);
504				copyfd(prevfd, 0);
505				close(prevfd);
506			}
507			if (pip[1] >= 0) {
508				if (!(prevfd >= 0 && pip[0] == 0))
509					close(pip[0]);
510				if (pip[1] != 1) {
511					close(1);
512					copyfd(pip[1], 1);
513					close(pip[1]);
514				}
515			}
516			evaltree(lp->n, EV_EXIT);
517		}
518		if (prevfd >= 0)
519			close(prevfd);
520		prevfd = pip[0];
521		close(pip[1]);
522	}
523	INTON;
524	if (n->npipe.backgnd == 0) {
525		INTOFF;
526		exitstatus = waitforjob(jp, (int *)NULL);
527		TRACE(("evalpipe:  job done exit status %d\n", exitstatus));
528		INTON;
529	}
530}
531
532
533
534/*
535 * Execute a command inside back quotes.  If it's a builtin command, we
536 * want to save its output in a block obtained from malloc.  Otherwise
537 * we fork off a subprocess and get the output of the command via a pipe.
538 * Should be called with interrupts off.
539 */
540
541void
542evalbackcmd(union node *n, struct backcmd *result)
543{
544	int pip[2];
545	struct job *jp;
546	struct stackmark smark;		/* unnecessary */
547
548	setstackmark(&smark);
549	result->fd = -1;
550	result->buf = NULL;
551	result->nleft = 0;
552	result->jp = NULL;
553	if (n == NULL) {
554		exitstatus = 0;
555		goto out;
556	}
557	if (n->type == NCMD) {
558		exitstatus = oexitstatus;
559		evalcommand(n, EV_BACKCMD, result);
560	} else {
561		exitstatus = 0;
562		if (pipe(pip) < 0)
563			error("Pipe call failed: %s", strerror(errno));
564		jp = makejob(n, 1);
565		if (forkshell(jp, n, FORK_NOJOB) == 0) {
566			FORCEINTON;
567			close(pip[0]);
568			if (pip[1] != 1) {
569				close(1);
570				copyfd(pip[1], 1);
571				close(pip[1]);
572			}
573			evaltree(n, EV_EXIT);
574		}
575		close(pip[1]);
576		result->fd = pip[0];
577		result->jp = jp;
578	}
579out:
580	popstackmark(&smark);
581	TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
582		result->fd, result->buf, result->nleft, result->jp));
583}
584
585
586
587/*
588 * Execute a simple command.
589 */
590
591STATIC void
592evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
593{
594	struct stackmark smark;
595	union node *argp;
596	struct arglist arglist;
597	struct arglist varlist;
598	char **argv;
599	int argc;
600	char **envp;
601	int varflag;
602	struct strlist *sp;
603	int mode;
604	int pip[2];
605	struct cmdentry cmdentry;
606	struct job *jp;
607	struct jmploc jmploc;
608	struct jmploc *volatile savehandler;
609	char *volatile savecmdname;
610	volatile struct shparam saveparam;
611	struct localvar *volatile savelocalvars;
612	volatile int e;
613	char *lastarg;
614	int realstatus;
615	int do_clearcmdentry;
616#if __GNUC__
617	/* Avoid longjmp clobbering */
618	(void) &argv;
619	(void) &argc;
620	(void) &lastarg;
621	(void) &flags;
622	(void) &do_clearcmdentry;
623#endif
624
625	/* First expand the arguments. */
626	TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
627	setstackmark(&smark);
628	arglist.lastp = &arglist.list;
629	varlist.lastp = &varlist.list;
630	varflag = 1;
631	do_clearcmdentry = 0;
632	oexitstatus = exitstatus;
633	exitstatus = 0;
634	for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
635		char *p = argp->narg.text;
636		if (varflag && is_name(*p)) {
637			do {
638				p++;
639			} while (is_in_name(*p));
640			if (*p == '=') {
641				expandarg(argp, &varlist, EXP_VARTILDE);
642				continue;
643			}
644		}
645		expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
646		varflag = 0;
647	}
648	*arglist.lastp = NULL;
649	*varlist.lastp = NULL;
650	expredir(cmd->ncmd.redirect);
651	argc = 0;
652	for (sp = arglist.list ; sp ; sp = sp->next)
653		argc++;
654	argv = stalloc(sizeof (char *) * (argc + 1));
655
656	for (sp = arglist.list ; sp ; sp = sp->next) {
657		TRACE(("evalcommand arg: %s\n", sp->text));
658		*argv++ = sp->text;
659	}
660	*argv = NULL;
661	lastarg = NULL;
662	if (iflag && funcnest == 0 && argc > 0)
663		lastarg = argv[-1];
664	argv -= argc;
665
666	/* Print the command if xflag is set. */
667	if (xflag) {
668		outc('+', &errout);
669		for (sp = varlist.list ; sp ; sp = sp->next) {
670			outc(' ', &errout);
671			out2str(sp->text);
672		}
673		for (sp = arglist.list ; sp ; sp = sp->next) {
674			outc(' ', &errout);
675			out2str(sp->text);
676		}
677		outc('\n', &errout);
678		flushout(&errout);
679	}
680
681	/* Now locate the command. */
682	if (argc == 0) {
683		cmdentry.cmdtype = CMDBUILTIN;
684		cmdentry.u.index = BLTINCMD;
685	} else {
686		static const char PATH[] = "PATH=";
687		char *path = pathval();
688
689		/*
690		 * Modify the command lookup path, if a PATH= assignment
691		 * is present
692		 */
693		for (sp = varlist.list ; sp ; sp = sp->next)
694			if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0) {
695				path = sp->text + sizeof(PATH) - 1;
696				/*
697				 * On `PATH=... command`, we need to make
698				 * sure that the command isn't using the
699				 * non-updated hash table of the outer PATH
700				 * setting and we need to make sure that
701				 * the hash table isn't filled with items
702				 * from the temporary setting.
703				 *
704				 * It would be better to forbit using and
705				 * updating the table while this command
706				 * runs, by the command finding mechanism
707				 * is heavily integrated with hash handling,
708				 * so we just delete the hash before and after
709				 * the command runs. Partly deleting like
710				 * changepatch() does doesn't seem worth the
711				 * bookinging effort, since most such runs add
712				 * diretories in front of the new PATH.
713				 */
714				clearcmdentry(0);
715				do_clearcmdentry = 1;
716			}
717
718		find_command(argv[0], &cmdentry, 1, path);
719		if (cmdentry.cmdtype == CMDUNKNOWN) {	/* command not found */
720			exitstatus = 127;
721			flushout(&errout);
722			return;
723		}
724		/* implement the bltin builtin here */
725		if (cmdentry.cmdtype == CMDBUILTIN && cmdentry.u.index == BLTINCMD) {
726			for (;;) {
727				argv++;
728				if (--argc == 0)
729					break;
730				if ((cmdentry.u.index = find_builtin(*argv)) < 0) {
731					outfmt(&errout, "%s: not found\n", *argv);
732					exitstatus = 127;
733					flushout(&errout);
734					return;
735				}
736				if (cmdentry.u.index != BLTINCMD)
737					break;
738			}
739		}
740	}
741
742	/* Fork off a child process if necessary. */
743	if (cmd->ncmd.backgnd
744	 || (cmdentry.cmdtype == CMDNORMAL
745	    && ((flags & EV_EXIT) == 0 || Tflag))
746	 || ((flags & EV_BACKCMD) != 0
747	    && (cmdentry.cmdtype != CMDBUILTIN
748		 || cmdentry.u.index == CDCMD
749		 || cmdentry.u.index == DOTCMD
750		 || cmdentry.u.index == EVALCMD))) {
751		jp = makejob(cmd, 1);
752		mode = cmd->ncmd.backgnd;
753		if (flags & EV_BACKCMD) {
754			mode = FORK_NOJOB;
755			if (pipe(pip) < 0)
756				error("Pipe call failed: %s", strerror(errno));
757		}
758		if (forkshell(jp, cmd, mode) != 0)
759			goto parent;	/* at end of routine */
760		if (flags & EV_BACKCMD) {
761			FORCEINTON;
762			close(pip[0]);
763			if (pip[1] != 1) {
764				close(1);
765				copyfd(pip[1], 1);
766				close(pip[1]);
767			}
768		}
769		flags |= EV_EXIT;
770	}
771
772	/* This is the child process if a fork occurred. */
773	/* Execute the command. */
774	if (cmdentry.cmdtype == CMDFUNCTION) {
775#ifdef DEBUG
776		trputs("Shell function:  ");  trargs(argv);
777#endif
778		redirect(cmd->ncmd.redirect, REDIR_PUSH);
779		saveparam = shellparam;
780		shellparam.malloc = 0;
781		shellparam.reset = 1;
782		shellparam.nparam = argc - 1;
783		shellparam.p = argv + 1;
784		shellparam.optnext = NULL;
785		INTOFF;
786		savelocalvars = localvars;
787		localvars = NULL;
788		INTON;
789		if (setjmp(jmploc.loc)) {
790			if (exception == EXSHELLPROC)
791				freeparam((struct shparam *)&saveparam);
792			else {
793				freeparam(&shellparam);
794				shellparam = saveparam;
795			}
796			poplocalvars();
797			localvars = savelocalvars;
798			handler = savehandler;
799			longjmp(handler->loc, 1);
800		}
801		savehandler = handler;
802		handler = &jmploc;
803		for (sp = varlist.list ; sp ; sp = sp->next)
804			mklocal(sp->text);
805		funcnest++;
806		if (flags & EV_TESTED)
807			evaltree(cmdentry.u.func, EV_TESTED);
808		else
809			evaltree(cmdentry.u.func, 0);
810		funcnest--;
811		INTOFF;
812		poplocalvars();
813		localvars = savelocalvars;
814		freeparam(&shellparam);
815		shellparam = saveparam;
816		handler = savehandler;
817		popredir();
818		INTON;
819		if (evalskip == SKIPFUNC) {
820			evalskip = 0;
821			skipcount = 0;
822		}
823		if (flags & EV_EXIT)
824			exitshell(exitstatus);
825	} else if (cmdentry.cmdtype == CMDBUILTIN) {
826#ifdef DEBUG
827		trputs("builtin command:  ");  trargs(argv);
828#endif
829		mode = (cmdentry.u.index == EXECCMD)? 0 : REDIR_PUSH;
830		if (flags == EV_BACKCMD) {
831			memout.nleft = 0;
832			memout.nextc = memout.buf;
833			memout.bufsize = 64;
834			mode |= REDIR_BACKQ;
835		}
836		redirect(cmd->ncmd.redirect, mode);
837		savecmdname = commandname;
838		cmdenviron = varlist.list;
839		e = -1;
840		if (setjmp(jmploc.loc)) {
841			e = exception;
842			exitstatus = (e == EXINT)? SIGINT+128 : 2;
843			goto cmddone;
844		}
845		savehandler = handler;
846		handler = &jmploc;
847		commandname = argv[0];
848		argptr = argv + 1;
849		optptr = NULL;			/* initialize nextopt */
850		exitstatus = (*builtinfunc[cmdentry.u.index])(argc, argv);
851		flushall();
852cmddone:
853		cmdenviron = NULL;
854		out1 = &output;
855		out2 = &errout;
856		freestdout();
857		if (e != EXSHELLPROC) {
858			commandname = savecmdname;
859			if (flags & EV_EXIT) {
860				exitshell(exitstatus);
861			}
862		}
863		handler = savehandler;
864		if (e != -1) {
865			if ((e != EXERROR && e != EXEXEC)
866			   || cmdentry.u.index == BLTINCMD
867			   || cmdentry.u.index == DOTCMD
868			   || cmdentry.u.index == EVALCMD
869#ifndef NO_HISTORY
870			   || cmdentry.u.index == HISTCMD
871#endif
872			   || cmdentry.u.index == EXECCMD)
873				exraise(e);
874			FORCEINTON;
875		}
876		if (cmdentry.u.index != EXECCMD)
877			popredir();
878		if (flags == EV_BACKCMD) {
879			backcmd->buf = memout.buf;
880			backcmd->nleft = memout.nextc - memout.buf;
881			memout.buf = NULL;
882		}
883	} else {
884#ifdef DEBUG
885		trputs("normal command:  ");  trargs(argv);
886#endif
887		clearredir();
888		redirect(cmd->ncmd.redirect, 0);
889		for (sp = varlist.list ; sp ; sp = sp->next)
890			setvareq(sp->text, VEXPORT|VSTACK);
891		envp = environment();
892		shellexec(argv, envp, pathval(), cmdentry.u.index);
893		/*NOTREACHED*/
894	}
895	goto out;
896
897parent:	/* parent process gets here (if we forked) */
898	if (mode == 0) {	/* argument to fork */
899		INTOFF;
900		exitstatus = waitforjob(jp, &realstatus);
901		INTON;
902		if (iflag && loopnest > 0 && WIFSIGNALED(realstatus)) {
903			evalskip = SKIPBREAK;
904			skipcount = loopnest;
905		}
906	} else if (mode == 2) {
907		backcmd->fd = pip[0];
908		close(pip[1]);
909		backcmd->jp = jp;
910	}
911
912out:
913	if (lastarg)
914		setvar("_", lastarg, 0);
915	if (do_clearcmdentry)
916		clearcmdentry(0);
917	popstackmark(&smark);
918}
919
920
921
922/*
923 * Search for a command.  This is called before we fork so that the
924 * location of the command will be available in the parent as well as
925 * the child.  The check for "goodname" is an overly conservative
926 * check that the name will not be subject to expansion.
927 */
928
929STATIC void
930prehash(union node *n)
931{
932	struct cmdentry entry;
933
934	if (n->type == NCMD && n->ncmd.args)
935		if (goodname(n->ncmd.args->narg.text))
936			find_command(n->ncmd.args->narg.text, &entry, 0,
937				     pathval());
938}
939
940
941
942/*
943 * Builtin commands.  Builtin commands whose functions are closely
944 * tied to evaluation are implemented here.
945 */
946
947/*
948 * No command given, or a bltin command with no arguments.  Set the
949 * specified variables.
950 */
951
952int
953bltincmd(int argc __unused, char **argv __unused)
954{
955	listsetvar(cmdenviron);
956	/*
957	 * Preserve exitstatus of a previous possible redirection
958	 * as POSIX mandates
959	 */
960	return exitstatus;
961}
962
963
964/*
965 * Handle break and continue commands.  Break, continue, and return are
966 * all handled by setting the evalskip flag.  The evaluation routines
967 * above all check this flag, and if it is set they start skipping
968 * commands rather than executing them.  The variable skipcount is
969 * the number of loops to break/continue, or the number of function
970 * levels to return.  (The latter is always 1.)  It should probably
971 * be an error to break out of more loops than exist, but it isn't
972 * in the standard shell so we don't make it one here.
973 */
974
975int
976breakcmd(int argc, char **argv)
977{
978	int n = argc > 1 ? number(argv[1]) : 1;
979
980	if (n > loopnest)
981		n = loopnest;
982	if (n > 0) {
983		evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
984		skipcount = n;
985	}
986	return 0;
987}
988
989
990/*
991 * The return command.
992 */
993
994int
995returncmd(int argc, char **argv)
996{
997	int ret = argc > 1 ? number(argv[1]) : oexitstatus;
998
999	if (funcnest) {
1000		evalskip = SKIPFUNC;
1001		skipcount = 1;
1002	} else {
1003		/* skip the rest of the file */
1004		evalskip = SKIPFILE;
1005		skipcount = 1;
1006	}
1007	return ret;
1008}
1009
1010
1011int
1012falsecmd(int argc __unused, char **argv __unused)
1013{
1014	return 1;
1015}
1016
1017
1018int
1019truecmd(int argc __unused, char **argv __unused)
1020{
1021	return 0;
1022}
1023
1024
1025int
1026execcmd(int argc, char **argv)
1027{
1028	if (argc > 1) {
1029		struct strlist *sp;
1030
1031		iflag = 0;		/* exit on error */
1032		mflag = 0;
1033		optschanged();
1034		for (sp = cmdenviron; sp ; sp = sp->next)
1035			setvareq(sp->text, VEXPORT|VSTACK);
1036		shellexec(argv + 1, environment(), pathval(), 0);
1037
1038	}
1039	return 0;
1040}
1041