eval.c revision 90111
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
41static const char rcsid[] =
42  "$FreeBSD: head/bin/sh/eval.c 90111 2002-02-02 06:50:57Z imp $";
43#endif /* not lint */
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			expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
452			redir->nfile.expfname = fn.list->text;
453			break;
454		case NFROMFD:
455		case NTOFD:
456			if (redir->ndup.vname) {
457				expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
458				fixredir(redir, fn.list->text, 1);
459			}
460			break;
461		}
462	}
463}
464
465
466
467/*
468 * Evaluate a pipeline.  All the processes in the pipeline are children
469 * of the process creating the pipeline.  (This differs from some versions
470 * of the shell, which make the last process in a pipeline the parent
471 * of all the rest.)
472 */
473
474STATIC void
475evalpipe(union node *n)
476{
477	struct job *jp;
478	struct nodelist *lp;
479	int pipelen;
480	int prevfd;
481	int pip[2];
482
483	TRACE(("evalpipe(0x%lx) called\n", (long)n));
484	pipelen = 0;
485	for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
486		pipelen++;
487	INTOFF;
488	jp = makejob(n, pipelen);
489	prevfd = -1;
490	for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
491		prehash(lp->n);
492		pip[1] = -1;
493		if (lp->next) {
494			if (pipe(pip) < 0) {
495				close(prevfd);
496				error("Pipe call failed: %s", strerror(errno));
497			}
498		}
499		if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
500			INTON;
501			if (prevfd > 0) {
502				close(0);
503				copyfd(prevfd, 0);
504				close(prevfd);
505			}
506			if (pip[1] >= 0) {
507				if (!(prevfd >= 0 && pip[0] == 0))
508					close(pip[0]);
509				if (pip[1] != 1) {
510					close(1);
511					copyfd(pip[1], 1);
512					close(pip[1]);
513				}
514			}
515			evaltree(lp->n, EV_EXIT);
516		}
517		if (prevfd >= 0)
518			close(prevfd);
519		prevfd = pip[0];
520		close(pip[1]);
521	}
522	INTON;
523	if (n->npipe.backgnd == 0) {
524		INTOFF;
525		exitstatus = waitforjob(jp, (int *)NULL);
526		TRACE(("evalpipe:  job done exit status %d\n", exitstatus));
527		INTON;
528	}
529}
530
531
532
533/*
534 * Execute a command inside back quotes.  If it's a builtin command, we
535 * want to save its output in a block obtained from malloc.  Otherwise
536 * we fork off a subprocess and get the output of the command via a pipe.
537 * Should be called with interrupts off.
538 */
539
540void
541evalbackcmd(union node *n, struct backcmd *result)
542{
543	int pip[2];
544	struct job *jp;
545	struct stackmark smark;		/* unnecessary */
546
547	setstackmark(&smark);
548	result->fd = -1;
549	result->buf = NULL;
550	result->nleft = 0;
551	result->jp = NULL;
552	if (n == NULL) {
553		exitstatus = 0;
554		goto out;
555	}
556	if (n->type == NCMD) {
557		exitstatus = oexitstatus;
558		evalcommand(n, EV_BACKCMD, result);
559	} else {
560		exitstatus = 0;
561		if (pipe(pip) < 0)
562			error("Pipe call failed: %s", strerror(errno));
563		jp = makejob(n, 1);
564		if (forkshell(jp, n, FORK_NOJOB) == 0) {
565			FORCEINTON;
566			close(pip[0]);
567			if (pip[1] != 1) {
568				close(1);
569				copyfd(pip[1], 1);
570				close(pip[1]);
571			}
572			evaltree(n, EV_EXIT);
573		}
574		close(pip[1]);
575		result->fd = pip[0];
576		result->jp = jp;
577	}
578out:
579	popstackmark(&smark);
580	TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
581		result->fd, result->buf, result->nleft, result->jp));
582}
583
584
585
586/*
587 * Execute a simple command.
588 */
589
590STATIC void
591evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
592{
593	struct stackmark smark;
594	union node *argp;
595	struct arglist arglist;
596	struct arglist varlist;
597	char **argv;
598	int argc;
599	char **envp;
600	int varflag;
601	struct strlist *sp;
602	int mode;
603	int pip[2];
604	struct cmdentry cmdentry;
605	struct job *jp;
606	struct jmploc jmploc;
607	struct jmploc *volatile savehandler;
608	char *volatile savecmdname;
609	volatile struct shparam saveparam;
610	struct localvar *volatile savelocalvars;
611	volatile int e;
612	char *lastarg;
613	int realstatus;
614	int do_clearcmdentry;
615#if __GNUC__
616	/* Avoid longjmp clobbering */
617	(void) &argv;
618	(void) &argc;
619	(void) &lastarg;
620	(void) &flags;
621	(void) &do_clearcmdentry;
622#endif
623
624	/* First expand the arguments. */
625	TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
626	setstackmark(&smark);
627	arglist.lastp = &arglist.list;
628	varlist.lastp = &varlist.list;
629	varflag = 1;
630	do_clearcmdentry = 0;
631	oexitstatus = exitstatus;
632	exitstatus = 0;
633	for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
634		char *p = argp->narg.text;
635		if (varflag && is_name(*p)) {
636			do {
637				p++;
638			} while (is_in_name(*p));
639			if (*p == '=') {
640				expandarg(argp, &varlist, EXP_VARTILDE);
641				continue;
642			}
643		}
644		expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
645		varflag = 0;
646	}
647	*arglist.lastp = NULL;
648	*varlist.lastp = NULL;
649	expredir(cmd->ncmd.redirect);
650	argc = 0;
651	for (sp = arglist.list ; sp ; sp = sp->next)
652		argc++;
653	argv = stalloc(sizeof (char *) * (argc + 1));
654
655	for (sp = arglist.list ; sp ; sp = sp->next) {
656		TRACE(("evalcommand arg: %s\n", sp->text));
657		*argv++ = sp->text;
658	}
659	*argv = NULL;
660	lastarg = NULL;
661	if (iflag && funcnest == 0 && argc > 0)
662		lastarg = argv[-1];
663	argv -= argc;
664
665	/* Print the command if xflag is set. */
666	if (xflag) {
667		outc('+', &errout);
668		for (sp = varlist.list ; sp ; sp = sp->next) {
669			outc(' ', &errout);
670			out2str(sp->text);
671		}
672		for (sp = arglist.list ; sp ; sp = sp->next) {
673			outc(' ', &errout);
674			out2str(sp->text);
675		}
676		outc('\n', &errout);
677		flushout(&errout);
678	}
679
680	/* Now locate the command. */
681	if (argc == 0) {
682		cmdentry.cmdtype = CMDBUILTIN;
683		cmdentry.u.index = BLTINCMD;
684	} else {
685		static const char PATH[] = "PATH=";
686		char *path = pathval();
687
688		/*
689		 * Modify the command lookup path, if a PATH= assignment
690		 * is present
691		 */
692		for (sp = varlist.list ; sp ; sp = sp->next)
693			if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0) {
694				path = sp->text + sizeof(PATH) - 1;
695				/*
696				 * On `PATH=... command`, we need to make
697				 * sure that the command isn't using the
698				 * non-updated hash table of the outer PATH
699				 * setting and we need to make sure that
700				 * the hash table isn't filled with items
701				 * from the temporary setting.
702				 *
703				 * It would be better to forbit using and
704				 * updating the table while this command
705				 * runs, by the command finding mechanism
706				 * is heavily integrated with hash handling,
707				 * so we just delete the hash before and after
708				 * the command runs. Partly deleting like
709				 * changepatch() does doesn't seem worth the
710				 * bookinging effort, since most such runs add
711				 * diretories in front of the new PATH.
712				 */
713				clearcmdentry(0);
714				do_clearcmdentry = 1;
715			}
716
717		find_command(argv[0], &cmdentry, 1, path);
718		if (cmdentry.cmdtype == CMDUNKNOWN) {	/* command not found */
719			exitstatus = 127;
720			flushout(&errout);
721			return;
722		}
723		/* implement the bltin builtin here */
724		if (cmdentry.cmdtype == CMDBUILTIN && cmdentry.u.index == BLTINCMD) {
725			for (;;) {
726				argv++;
727				if (--argc == 0)
728					break;
729				if ((cmdentry.u.index = find_builtin(*argv)) < 0) {
730					outfmt(&errout, "%s: not found\n", *argv);
731					exitstatus = 127;
732					flushout(&errout);
733					return;
734				}
735				if (cmdentry.u.index != BLTINCMD)
736					break;
737			}
738		}
739	}
740
741	/* Fork off a child process if necessary. */
742	if (cmd->ncmd.backgnd
743	 || (cmdentry.cmdtype == CMDNORMAL
744	    && ((flags & EV_EXIT) == 0 || Tflag))
745	 || ((flags & EV_BACKCMD) != 0
746	    && (cmdentry.cmdtype != CMDBUILTIN
747		 || cmdentry.u.index == CDCMD
748		 || cmdentry.u.index == DOTCMD
749		 || cmdentry.u.index == EVALCMD))) {
750		jp = makejob(cmd, 1);
751		mode = cmd->ncmd.backgnd;
752		if (flags & EV_BACKCMD) {
753			mode = FORK_NOJOB;
754			if (pipe(pip) < 0)
755				error("Pipe call failed: %s", strerror(errno));
756		}
757		if (forkshell(jp, cmd, mode) != 0)
758			goto parent;	/* at end of routine */
759		if (flags & EV_BACKCMD) {
760			FORCEINTON;
761			close(pip[0]);
762			if (pip[1] != 1) {
763				close(1);
764				copyfd(pip[1], 1);
765				close(pip[1]);
766			}
767		}
768		flags |= EV_EXIT;
769	}
770
771	/* This is the child process if a fork occurred. */
772	/* Execute the command. */
773	if (cmdentry.cmdtype == CMDFUNCTION) {
774#ifdef DEBUG
775		trputs("Shell function:  ");  trargs(argv);
776#endif
777		redirect(cmd->ncmd.redirect, REDIR_PUSH);
778		saveparam = shellparam;
779		shellparam.malloc = 0;
780		shellparam.reset = 1;
781		shellparam.nparam = argc - 1;
782		shellparam.p = argv + 1;
783		shellparam.optnext = NULL;
784		INTOFF;
785		savelocalvars = localvars;
786		localvars = NULL;
787		INTON;
788		if (setjmp(jmploc.loc)) {
789			if (exception == EXSHELLPROC)
790				freeparam((struct shparam *)&saveparam);
791			else {
792				freeparam(&shellparam);
793				shellparam = saveparam;
794			}
795			poplocalvars();
796			localvars = savelocalvars;
797			handler = savehandler;
798			longjmp(handler->loc, 1);
799		}
800		savehandler = handler;
801		handler = &jmploc;
802		for (sp = varlist.list ; sp ; sp = sp->next)
803			mklocal(sp->text);
804		funcnest++;
805		if (flags & EV_TESTED)
806			evaltree(cmdentry.u.func, EV_TESTED);
807		else
808			evaltree(cmdentry.u.func, 0);
809		funcnest--;
810		INTOFF;
811		poplocalvars();
812		localvars = savelocalvars;
813		freeparam(&shellparam);
814		shellparam = saveparam;
815		handler = savehandler;
816		popredir();
817		INTON;
818		if (evalskip == SKIPFUNC) {
819			evalskip = 0;
820			skipcount = 0;
821		}
822		if (flags & EV_EXIT)
823			exitshell(exitstatus);
824	} else if (cmdentry.cmdtype == CMDBUILTIN) {
825#ifdef DEBUG
826		trputs("builtin command:  ");  trargs(argv);
827#endif
828		mode = (cmdentry.u.index == EXECCMD)? 0 : REDIR_PUSH;
829		if (flags == EV_BACKCMD) {
830			memout.nleft = 0;
831			memout.nextc = memout.buf;
832			memout.bufsize = 64;
833			mode |= REDIR_BACKQ;
834		}
835		redirect(cmd->ncmd.redirect, mode);
836		savecmdname = commandname;
837		cmdenviron = varlist.list;
838		e = -1;
839		if (setjmp(jmploc.loc)) {
840			e = exception;
841			exitstatus = (e == EXINT)? SIGINT+128 : 2;
842			goto cmddone;
843		}
844		savehandler = handler;
845		handler = &jmploc;
846		commandname = argv[0];
847		argptr = argv + 1;
848		optptr = NULL;			/* initialize nextopt */
849		exitstatus = (*builtinfunc[cmdentry.u.index])(argc, argv);
850		flushall();
851cmddone:
852		cmdenviron = NULL;
853		out1 = &output;
854		out2 = &errout;
855		freestdout();
856		if (e != EXSHELLPROC) {
857			commandname = savecmdname;
858			if (flags & EV_EXIT) {
859				exitshell(exitstatus);
860			}
861		}
862		handler = savehandler;
863		if (e != -1) {
864			if ((e != EXERROR && e != EXEXEC)
865			   || cmdentry.u.index == BLTINCMD
866			   || cmdentry.u.index == DOTCMD
867			   || cmdentry.u.index == EVALCMD
868#ifndef NO_HISTORY
869			   || cmdentry.u.index == HISTCMD
870#endif
871			   || cmdentry.u.index == EXECCMD)
872				exraise(e);
873			FORCEINTON;
874		}
875		if (cmdentry.u.index != EXECCMD)
876			popredir();
877		if (flags == EV_BACKCMD) {
878			backcmd->buf = memout.buf;
879			backcmd->nleft = memout.nextc - memout.buf;
880			memout.buf = NULL;
881		}
882	} else {
883#ifdef DEBUG
884		trputs("normal command:  ");  trargs(argv);
885#endif
886		clearredir();
887		redirect(cmd->ncmd.redirect, 0);
888		for (sp = varlist.list ; sp ; sp = sp->next)
889			setvareq(sp->text, VEXPORT|VSTACK);
890		envp = environment();
891		shellexec(argv, envp, pathval(), cmdentry.u.index);
892		/*NOTREACHED*/
893	}
894	goto out;
895
896parent:	/* parent process gets here (if we forked) */
897	if (mode == 0) {	/* argument to fork */
898		INTOFF;
899		exitstatus = waitforjob(jp, &realstatus);
900		INTON;
901		if (iflag && loopnest > 0 && WIFSIGNALED(realstatus)) {
902			evalskip = SKIPBREAK;
903			skipcount = loopnest;
904		}
905	} else if (mode == 2) {
906		backcmd->fd = pip[0];
907		close(pip[1]);
908		backcmd->jp = jp;
909	}
910
911out:
912	if (lastarg)
913		setvar("_", lastarg, 0);
914	if (do_clearcmdentry)
915		clearcmdentry(0);
916	popstackmark(&smark);
917}
918
919
920
921/*
922 * Search for a command.  This is called before we fork so that the
923 * location of the command will be available in the parent as well as
924 * the child.  The check for "goodname" is an overly conservative
925 * check that the name will not be subject to expansion.
926 */
927
928STATIC void
929prehash(union node *n)
930{
931	struct cmdentry entry;
932
933	if (n->type == NCMD && n->ncmd.args)
934		if (goodname(n->ncmd.args->narg.text))
935			find_command(n->ncmd.args->narg.text, &entry, 0,
936				     pathval());
937}
938
939
940
941/*
942 * Builtin commands.  Builtin commands whose functions are closely
943 * tied to evaluation are implemented here.
944 */
945
946/*
947 * No command given, or a bltin command with no arguments.  Set the
948 * specified variables.
949 */
950
951int
952bltincmd(int argc __unused, char **argv __unused)
953{
954	listsetvar(cmdenviron);
955	/*
956	 * Preserve exitstatus of a previous possible redirection
957	 * as POSIX mandates
958	 */
959	return exitstatus;
960}
961
962
963/*
964 * Handle break and continue commands.  Break, continue, and return are
965 * all handled by setting the evalskip flag.  The evaluation routines
966 * above all check this flag, and if it is set they start skipping
967 * commands rather than executing them.  The variable skipcount is
968 * the number of loops to break/continue, or the number of function
969 * levels to return.  (The latter is always 1.)  It should probably
970 * be an error to break out of more loops than exist, but it isn't
971 * in the standard shell so we don't make it one here.
972 */
973
974int
975breakcmd(int argc, char **argv)
976{
977	int n = argc > 1 ? number(argv[1]) : 1;
978
979	if (n > loopnest)
980		n = loopnest;
981	if (n > 0) {
982		evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
983		skipcount = n;
984	}
985	return 0;
986}
987
988
989/*
990 * The return command.
991 */
992
993int
994returncmd(int argc, char **argv)
995{
996	int ret = argc > 1 ? number(argv[1]) : oexitstatus;
997
998	if (funcnest) {
999		evalskip = SKIPFUNC;
1000		skipcount = 1;
1001	} else {
1002		/* skip the rest of the file */
1003		evalskip = SKIPFILE;
1004		skipcount = 1;
1005	}
1006	return ret;
1007}
1008
1009
1010int
1011falsecmd(int argc __unused, char **argv __unused)
1012{
1013	return 1;
1014}
1015
1016
1017int
1018truecmd(int argc __unused, char **argv __unused)
1019{
1020	return 0;
1021}
1022
1023
1024int
1025execcmd(int argc, char **argv)
1026{
1027	if (argc > 1) {
1028		struct strlist *sp;
1029
1030		iflag = 0;		/* exit on error */
1031		mflag = 0;
1032		optschanged();
1033		for (sp = cmdenviron; sp ; sp = sp->next)
1034			setvareq(sp->text, VEXPORT|VSTACK);
1035		shellexec(argv + 1, environment(), pathval(), 0);
1036
1037	}
1038	return 0;
1039}
1040