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