xref: /csrg-svn/bin/sh/eval.c (revision 47112)
1*47112Sbostic /*-
2*47112Sbostic  * Copyright (c) 1991 The Regents of the University of California.
3*47112Sbostic  * All rights reserved.
4*47112Sbostic  *
5*47112Sbostic  * This code is derived from software contributed to Berkeley by
6*47112Sbostic  * Kenneth Almquist.
7*47112Sbostic  *
8*47112Sbostic  * %sccs.include.redist.c%
9*47112Sbostic  */
10*47112Sbostic 
11*47112Sbostic #ifndef lint
12*47112Sbostic static char sccsid[] = "@(#)eval.c	5.1 (Berkeley) 03/07/91";
13*47112Sbostic #endif /* not lint */
14*47112Sbostic 
15*47112Sbostic /*
16*47112Sbostic  * Evaluate a command.
17*47112Sbostic  */
18*47112Sbostic 
19*47112Sbostic #include "shell.h"
20*47112Sbostic #include "nodes.h"
21*47112Sbostic #include "syntax.h"
22*47112Sbostic #include "expand.h"
23*47112Sbostic #include "parser.h"
24*47112Sbostic #include "jobs.h"
25*47112Sbostic #include "eval.h"
26*47112Sbostic #include "builtins.h"
27*47112Sbostic #include "options.h"
28*47112Sbostic #include "exec.h"
29*47112Sbostic #include "redir.h"
30*47112Sbostic #include "input.h"
31*47112Sbostic #include "output.h"
32*47112Sbostic #include "trap.h"
33*47112Sbostic #include "var.h"
34*47112Sbostic #include "memalloc.h"
35*47112Sbostic #include "error.h"
36*47112Sbostic #include "mystring.h"
37*47112Sbostic #include <signal.h>
38*47112Sbostic 
39*47112Sbostic 
40*47112Sbostic /* flags in argument to evaltree */
41*47112Sbostic #define EV_EXIT 01		/* exit after evaluating tree */
42*47112Sbostic #define EV_TESTED 02		/* exit status is checked; ignore -e flag */
43*47112Sbostic #define EV_BACKCMD 04		/* command executing within back quotes */
44*47112Sbostic 
45*47112Sbostic 
46*47112Sbostic /* reasons for skipping commands (see comment on breakcmd routine) */
47*47112Sbostic #define SKIPBREAK 1
48*47112Sbostic #define SKIPCONT 2
49*47112Sbostic #define SKIPFUNC 3
50*47112Sbostic 
51*47112Sbostic MKINIT int evalskip;		/* set if we are skipping commands */
52*47112Sbostic STATIC int skipcount;		/* number of levels to skip */
53*47112Sbostic MKINIT int loopnest;		/* current loop nesting level */
54*47112Sbostic int funcnest;			/* depth of function calls */
55*47112Sbostic 
56*47112Sbostic 
57*47112Sbostic char *commandname;
58*47112Sbostic struct strlist *cmdenviron;
59*47112Sbostic int exitstatus;			/* exit status of last command */
60*47112Sbostic 
61*47112Sbostic 
62*47112Sbostic #ifdef __STDC__
63*47112Sbostic STATIC void evalloop(union node *);
64*47112Sbostic STATIC void evalfor(union node *);
65*47112Sbostic STATIC void evalcase(union node *, int);
66*47112Sbostic STATIC void evalsubshell(union node *, int);
67*47112Sbostic STATIC void expredir(union node *);
68*47112Sbostic STATIC void evalpipe(union node *);
69*47112Sbostic STATIC void evalcommand(union node *, int, struct backcmd *);
70*47112Sbostic STATIC void prehash(union node *);
71*47112Sbostic #else
72*47112Sbostic STATIC void evalloop();
73*47112Sbostic STATIC void evalfor();
74*47112Sbostic STATIC void evalcase();
75*47112Sbostic STATIC void evalsubshell();
76*47112Sbostic STATIC void expredir();
77*47112Sbostic STATIC void evalpipe();
78*47112Sbostic STATIC void evalcommand();
79*47112Sbostic STATIC void prehash();
80*47112Sbostic #endif
81*47112Sbostic 
82*47112Sbostic 
83*47112Sbostic 
84*47112Sbostic /*
85*47112Sbostic  * Called to reset things after an exception.
86*47112Sbostic  */
87*47112Sbostic 
88*47112Sbostic #ifdef mkinit
89*47112Sbostic INCLUDE "eval.h"
90*47112Sbostic 
91*47112Sbostic RESET {
92*47112Sbostic 	evalskip = 0;
93*47112Sbostic 	loopnest = 0;
94*47112Sbostic 	funcnest = 0;
95*47112Sbostic }
96*47112Sbostic 
97*47112Sbostic SHELLPROC {
98*47112Sbostic 	exitstatus = 0;
99*47112Sbostic }
100*47112Sbostic #endif
101*47112Sbostic 
102*47112Sbostic 
103*47112Sbostic 
104*47112Sbostic /*
105*47112Sbostic  * The eval builtin.  Do you want clean, straight-forward semantics for
106*47112Sbostic  * your eval command?  If so, read on....
107*47112Sbostic  */
108*47112Sbostic 
109*47112Sbostic #ifdef ELIGANT
110*47112Sbostic evalcmd(argc, argv)  char **argv; {
111*47112Sbostic 	char **ap;
112*47112Sbostic 
113*47112Sbostic 	for (ap = argv + 1 ; *ap ; ap++) {
114*47112Sbostic 		evalstring(*ap);
115*47112Sbostic 	}
116*47112Sbostic 	return exitstatus;
117*47112Sbostic }
118*47112Sbostic #else
119*47112Sbostic 
120*47112Sbostic /*
121*47112Sbostic  * If, on the other hand, you prefer downright bogus semantics in the
122*47112Sbostic  * name of compatibility, here it is...
123*47112Sbostic  */
124*47112Sbostic 
125*47112Sbostic evalcmd(argc, argv)  char **argv; {
126*47112Sbostic 	char **ap;
127*47112Sbostic 	char *p, *q;
128*47112Sbostic 
129*47112Sbostic 	if (argc <= 1) {
130*47112Sbostic 		p = nullstr;
131*47112Sbostic 	} else if (argc == 2) {
132*47112Sbostic 		p = argv[1];
133*47112Sbostic 	} else {
134*47112Sbostic 		STARTSTACKSTR(p);
135*47112Sbostic 		ap = argv + 1;
136*47112Sbostic 		for (;;) {
137*47112Sbostic 			q = *ap++;
138*47112Sbostic 			while (*q) {
139*47112Sbostic 				STPUTC(*q++, p);
140*47112Sbostic 			}
141*47112Sbostic 			if (*ap == NULL)
142*47112Sbostic 				break;
143*47112Sbostic 			STPUTC(' ', p);
144*47112Sbostic 		}
145*47112Sbostic 		STPUTC('\0', p);
146*47112Sbostic 		p = grabstackstr(p);
147*47112Sbostic 	}
148*47112Sbostic 	evalstring(p);
149*47112Sbostic 	return exitstatus;
150*47112Sbostic }
151*47112Sbostic #endif
152*47112Sbostic 
153*47112Sbostic 
154*47112Sbostic 
155*47112Sbostic /*
156*47112Sbostic  * Execute a command or commands contained in a string.
157*47112Sbostic  */
158*47112Sbostic 
159*47112Sbostic void
160*47112Sbostic evalstring(s)
161*47112Sbostic 	char *s;
162*47112Sbostic 	{
163*47112Sbostic 	union node *n;
164*47112Sbostic 	struct stackmark smark;
165*47112Sbostic 
166*47112Sbostic 	setstackmark(&smark);
167*47112Sbostic 	setinputstring(s, 1);
168*47112Sbostic 	while ((n = parsecmd(0)) != NEOF) {
169*47112Sbostic 		evaltree(n, 0);
170*47112Sbostic 		popstackmark(&smark);
171*47112Sbostic 	}
172*47112Sbostic 	popfile();
173*47112Sbostic 	popstackmark(&smark);
174*47112Sbostic }
175*47112Sbostic 
176*47112Sbostic 
177*47112Sbostic 
178*47112Sbostic /*
179*47112Sbostic  * Evaluate a parse tree.  The value is left in the global variable
180*47112Sbostic  * exitstatus.
181*47112Sbostic  */
182*47112Sbostic 
183*47112Sbostic void
184*47112Sbostic evaltree(n, flags)
185*47112Sbostic 	union node *n;
186*47112Sbostic 	{
187*47112Sbostic 	if (n == NULL) {
188*47112Sbostic 		TRACE(("evaltree(NULL) called\n"));
189*47112Sbostic 		return;
190*47112Sbostic 	}
191*47112Sbostic 	TRACE(("evaltree(0x%x: %d) called\n", (int)n, n->type));
192*47112Sbostic 	switch (n->type) {
193*47112Sbostic 	case NSEMI:
194*47112Sbostic 		evaltree(n->nbinary.ch1, 0);
195*47112Sbostic 		if (evalskip)
196*47112Sbostic 			goto out;
197*47112Sbostic 		evaltree(n->nbinary.ch2, flags);
198*47112Sbostic 		break;
199*47112Sbostic 	case NAND:
200*47112Sbostic 		evaltree(n->nbinary.ch1, EV_TESTED);
201*47112Sbostic 		if (evalskip || exitstatus != 0)
202*47112Sbostic 			goto out;
203*47112Sbostic 		evaltree(n->nbinary.ch2, flags);
204*47112Sbostic 		break;
205*47112Sbostic 	case NOR:
206*47112Sbostic 		evaltree(n->nbinary.ch1, EV_TESTED);
207*47112Sbostic 		if (evalskip || exitstatus == 0)
208*47112Sbostic 			goto out;
209*47112Sbostic 		evaltree(n->nbinary.ch2, flags);
210*47112Sbostic 		break;
211*47112Sbostic 	case NREDIR:
212*47112Sbostic 		expredir(n->nredir.redirect);
213*47112Sbostic 		redirect(n->nredir.redirect, REDIR_PUSH);
214*47112Sbostic 		evaltree(n->nredir.n, flags);
215*47112Sbostic 		popredir();
216*47112Sbostic 		break;
217*47112Sbostic 	case NSUBSHELL:
218*47112Sbostic 		evalsubshell(n, flags);
219*47112Sbostic 		break;
220*47112Sbostic 	case NBACKGND:
221*47112Sbostic 		evalsubshell(n, flags);
222*47112Sbostic 		break;
223*47112Sbostic 	case NIF:
224*47112Sbostic 		evaltree(n->nif.test, EV_TESTED);
225*47112Sbostic 		if (evalskip)
226*47112Sbostic 			goto out;
227*47112Sbostic 		if (exitstatus == 0) {
228*47112Sbostic 			evaltree(n->nif.ifpart, flags);
229*47112Sbostic 		} else if (n->nif.elsepart) {
230*47112Sbostic 			evaltree(n->nif.elsepart, flags);
231*47112Sbostic 		}
232*47112Sbostic 		break;
233*47112Sbostic 	case NWHILE:
234*47112Sbostic 	case NUNTIL:
235*47112Sbostic 		evalloop(n);
236*47112Sbostic 		break;
237*47112Sbostic 	case NFOR:
238*47112Sbostic 		evalfor(n);
239*47112Sbostic 		break;
240*47112Sbostic 	case NCASE:
241*47112Sbostic 		evalcase(n, flags);
242*47112Sbostic 		break;
243*47112Sbostic 	case NDEFUN:
244*47112Sbostic 		defun(n->narg.text, n->narg.next);
245*47112Sbostic 		exitstatus = 0;
246*47112Sbostic 		break;
247*47112Sbostic 	case NPIPE:
248*47112Sbostic 		evalpipe(n);
249*47112Sbostic 		break;
250*47112Sbostic 	case NCMD:
251*47112Sbostic 		evalcommand(n, flags, (struct backcmd *)NULL);
252*47112Sbostic 		break;
253*47112Sbostic 	default:
254*47112Sbostic 		out1fmt("Node type = %d\n", n->type);
255*47112Sbostic 		flushout(&output);
256*47112Sbostic 		break;
257*47112Sbostic 	}
258*47112Sbostic out:
259*47112Sbostic 	if (pendingsigs)
260*47112Sbostic 		dotrap();
261*47112Sbostic 	if ((flags & EV_EXIT) || (eflag && exitstatus && !(flags & EV_TESTED)))
262*47112Sbostic 		exitshell(exitstatus);
263*47112Sbostic }
264*47112Sbostic 
265*47112Sbostic 
266*47112Sbostic STATIC void
267*47112Sbostic evalloop(n)
268*47112Sbostic 	union node *n;
269*47112Sbostic 	{
270*47112Sbostic 	int status;
271*47112Sbostic 
272*47112Sbostic 	loopnest++;
273*47112Sbostic 	status = 0;
274*47112Sbostic 	for (;;) {
275*47112Sbostic 		evaltree(n->nbinary.ch1, EV_TESTED);
276*47112Sbostic 		if (evalskip) {
277*47112Sbostic skipping:	  if (evalskip == SKIPCONT && --skipcount <= 0) {
278*47112Sbostic 				evalskip = 0;
279*47112Sbostic 				continue;
280*47112Sbostic 			}
281*47112Sbostic 			if (evalskip == SKIPBREAK && --skipcount <= 0)
282*47112Sbostic 				evalskip = 0;
283*47112Sbostic 			break;
284*47112Sbostic 		}
285*47112Sbostic 		if (n->type == NWHILE) {
286*47112Sbostic 			if (exitstatus != 0)
287*47112Sbostic 				break;
288*47112Sbostic 		} else {
289*47112Sbostic 			if (exitstatus == 0)
290*47112Sbostic 				break;
291*47112Sbostic 		}
292*47112Sbostic 		evaltree(n->nbinary.ch2, 0);
293*47112Sbostic 		status = exitstatus;
294*47112Sbostic 		if (evalskip)
295*47112Sbostic 			goto skipping;
296*47112Sbostic 	}
297*47112Sbostic 	loopnest--;
298*47112Sbostic 	exitstatus = status;
299*47112Sbostic }
300*47112Sbostic 
301*47112Sbostic 
302*47112Sbostic 
303*47112Sbostic STATIC void
304*47112Sbostic evalfor(n)
305*47112Sbostic 	union node *n;
306*47112Sbostic 	{
307*47112Sbostic 	struct arglist arglist;
308*47112Sbostic 	union node *argp;
309*47112Sbostic 	struct strlist *sp;
310*47112Sbostic 	struct stackmark smark;
311*47112Sbostic 
312*47112Sbostic 	setstackmark(&smark);
313*47112Sbostic 	arglist.lastp = &arglist.list;
314*47112Sbostic 	for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
315*47112Sbostic 		expandarg(argp, &arglist, 1);
316*47112Sbostic 		if (evalskip)
317*47112Sbostic 			goto out;
318*47112Sbostic 	}
319*47112Sbostic 	*arglist.lastp = NULL;
320*47112Sbostic 
321*47112Sbostic 	exitstatus = 0;
322*47112Sbostic 	loopnest++;
323*47112Sbostic 	for (sp = arglist.list ; sp ; sp = sp->next) {
324*47112Sbostic 		setvar(n->nfor.var, sp->text, 0);
325*47112Sbostic 		evaltree(n->nfor.body, 0);
326*47112Sbostic 		if (evalskip) {
327*47112Sbostic 			if (evalskip == SKIPCONT && --skipcount <= 0) {
328*47112Sbostic 				evalskip = 0;
329*47112Sbostic 				continue;
330*47112Sbostic 			}
331*47112Sbostic 			if (evalskip == SKIPBREAK && --skipcount <= 0)
332*47112Sbostic 				evalskip = 0;
333*47112Sbostic 			break;
334*47112Sbostic 		}
335*47112Sbostic 	}
336*47112Sbostic 	loopnest--;
337*47112Sbostic out:
338*47112Sbostic 	popstackmark(&smark);
339*47112Sbostic }
340*47112Sbostic 
341*47112Sbostic 
342*47112Sbostic 
343*47112Sbostic STATIC void
344*47112Sbostic evalcase(n, flags)
345*47112Sbostic 	union node *n;
346*47112Sbostic 	{
347*47112Sbostic 	union node *cp;
348*47112Sbostic 	union node *patp;
349*47112Sbostic 	struct arglist arglist;
350*47112Sbostic 	struct stackmark smark;
351*47112Sbostic 
352*47112Sbostic 	setstackmark(&smark);
353*47112Sbostic 	arglist.lastp = &arglist.list;
354*47112Sbostic 	expandarg(n->ncase.expr, &arglist, 0);
355*47112Sbostic 	for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
356*47112Sbostic 		for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
357*47112Sbostic 			if (casematch(patp, arglist.list->text)) {
358*47112Sbostic 				if (evalskip == 0) {
359*47112Sbostic 					evaltree(cp->nclist.body, flags);
360*47112Sbostic 				}
361*47112Sbostic 				goto out;
362*47112Sbostic 			}
363*47112Sbostic 		}
364*47112Sbostic 	}
365*47112Sbostic out:
366*47112Sbostic 	popstackmark(&smark);
367*47112Sbostic }
368*47112Sbostic 
369*47112Sbostic 
370*47112Sbostic 
371*47112Sbostic /*
372*47112Sbostic  * Kick off a subshell to evaluate a tree.
373*47112Sbostic  */
374*47112Sbostic 
375*47112Sbostic STATIC void
376*47112Sbostic evalsubshell(n, flags)
377*47112Sbostic 	union node *n;
378*47112Sbostic 	{
379*47112Sbostic 	struct job *jp;
380*47112Sbostic 	int backgnd = (n->type == NBACKGND);
381*47112Sbostic 
382*47112Sbostic 	expredir(n->nredir.redirect);
383*47112Sbostic 	jp = makejob(n, 1);
384*47112Sbostic 	if (forkshell(jp, n, backgnd) == 0) {
385*47112Sbostic 		if (backgnd)
386*47112Sbostic 			flags &=~ EV_TESTED;
387*47112Sbostic 		redirect(n->nredir.redirect, 0);
388*47112Sbostic 		evaltree(n->nredir.n, flags | EV_EXIT);	/* never returns */
389*47112Sbostic 	}
390*47112Sbostic 	if (! backgnd) {
391*47112Sbostic 		INTOFF;
392*47112Sbostic 		exitstatus = waitforjob(jp);
393*47112Sbostic 		INTON;
394*47112Sbostic 	}
395*47112Sbostic }
396*47112Sbostic 
397*47112Sbostic 
398*47112Sbostic 
399*47112Sbostic /*
400*47112Sbostic  * Compute the names of the files in a redirection list.
401*47112Sbostic  */
402*47112Sbostic 
403*47112Sbostic STATIC void
404*47112Sbostic expredir(n)
405*47112Sbostic 	union node *n;
406*47112Sbostic 	{
407*47112Sbostic 	register union node *redir;
408*47112Sbostic 
409*47112Sbostic 	for (redir = n ; redir ; redir = redir->nfile.next) {
410*47112Sbostic 		if (redir->type == NFROM
411*47112Sbostic 		 || redir->type == NTO
412*47112Sbostic 		 || redir->type == NAPPEND) {
413*47112Sbostic 			struct arglist fn;
414*47112Sbostic 			fn.lastp = &fn.list;
415*47112Sbostic 			expandarg(redir->nfile.fname, &fn, 0);
416*47112Sbostic 			redir->nfile.expfname = fn.list->text;
417*47112Sbostic 		}
418*47112Sbostic 	}
419*47112Sbostic }
420*47112Sbostic 
421*47112Sbostic 
422*47112Sbostic 
423*47112Sbostic /*
424*47112Sbostic  * Evaluate a pipeline.  All the processes in the pipeline are children
425*47112Sbostic  * of the process creating the pipeline.  (This differs from some versions
426*47112Sbostic  * of the shell, which make the last process in a pipeline the parent
427*47112Sbostic  * of all the rest.)
428*47112Sbostic  */
429*47112Sbostic 
430*47112Sbostic STATIC void
431*47112Sbostic evalpipe(n)
432*47112Sbostic 	union node *n;
433*47112Sbostic 	{
434*47112Sbostic 	struct job *jp;
435*47112Sbostic 	struct nodelist *lp;
436*47112Sbostic 	int pipelen;
437*47112Sbostic 	int prevfd;
438*47112Sbostic 	int pip[2];
439*47112Sbostic 
440*47112Sbostic 	TRACE(("evalpipe(0x%x) called\n", (int)n));
441*47112Sbostic 	pipelen = 0;
442*47112Sbostic 	for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
443*47112Sbostic 		pipelen++;
444*47112Sbostic 	INTOFF;
445*47112Sbostic 	jp = makejob(n, pipelen);
446*47112Sbostic 	prevfd = -1;
447*47112Sbostic 	for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
448*47112Sbostic 		prehash(lp->n);
449*47112Sbostic 		pip[1] = -1;
450*47112Sbostic 		if (lp->next) {
451*47112Sbostic 			if (pipe(pip) < 0) {
452*47112Sbostic 				close(prevfd);
453*47112Sbostic 				error("Pipe call failed");
454*47112Sbostic 			}
455*47112Sbostic 		}
456*47112Sbostic 		if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
457*47112Sbostic 			INTON;
458*47112Sbostic 			if (prevfd > 0) {
459*47112Sbostic 				close(0);
460*47112Sbostic 				copyfd(prevfd, 0);
461*47112Sbostic 				close(prevfd);
462*47112Sbostic 			}
463*47112Sbostic 			if (pip[1] >= 0) {
464*47112Sbostic 				close(pip[0]);
465*47112Sbostic 				if (pip[1] != 1) {
466*47112Sbostic 					close(1);
467*47112Sbostic 					copyfd(pip[1], 1);
468*47112Sbostic 					close(pip[1]);
469*47112Sbostic 				}
470*47112Sbostic 			}
471*47112Sbostic 			evaltree(lp->n, EV_EXIT);
472*47112Sbostic 		}
473*47112Sbostic 		if (prevfd >= 0)
474*47112Sbostic 			close(prevfd);
475*47112Sbostic 		prevfd = pip[0];
476*47112Sbostic 		close(pip[1]);
477*47112Sbostic 	}
478*47112Sbostic 	INTON;
479*47112Sbostic 	if (n->npipe.backgnd == 0) {
480*47112Sbostic 		INTOFF;
481*47112Sbostic 		exitstatus = waitforjob(jp);
482*47112Sbostic 		TRACE(("evalpipe:  job done exit status %d\n", exitstatus));
483*47112Sbostic 		INTON;
484*47112Sbostic 	}
485*47112Sbostic }
486*47112Sbostic 
487*47112Sbostic 
488*47112Sbostic 
489*47112Sbostic /*
490*47112Sbostic  * Execute a command inside back quotes.  If it's a builtin command, we
491*47112Sbostic  * want to save its output in a block obtained from malloc.  Otherwise
492*47112Sbostic  * we fork off a subprocess and get the output of the command via a pipe.
493*47112Sbostic  * Should be called with interrupts off.
494*47112Sbostic  */
495*47112Sbostic 
496*47112Sbostic void
497*47112Sbostic evalbackcmd(n, result)
498*47112Sbostic 	union node *n;
499*47112Sbostic 	struct backcmd *result;
500*47112Sbostic 	{
501*47112Sbostic 	int pip[2];
502*47112Sbostic 	struct job *jp;
503*47112Sbostic 	struct stackmark smark;		/* unnecessary */
504*47112Sbostic 
505*47112Sbostic 	setstackmark(&smark);
506*47112Sbostic 	result->fd = -1;
507*47112Sbostic 	result->buf = NULL;
508*47112Sbostic 	result->nleft = 0;
509*47112Sbostic 	result->jp = NULL;
510*47112Sbostic 	if (n->type == NCMD) {
511*47112Sbostic 		evalcommand(n, EV_BACKCMD, result);
512*47112Sbostic 	} else {
513*47112Sbostic 		if (pipe(pip) < 0)
514*47112Sbostic 			error("Pipe call failed");
515*47112Sbostic 		jp = makejob(n, 1);
516*47112Sbostic 		if (forkshell(jp, n, FORK_NOJOB) == 0) {
517*47112Sbostic 			FORCEINTON;
518*47112Sbostic 			close(pip[0]);
519*47112Sbostic 			if (pip[1] != 1) {
520*47112Sbostic 				close(1);
521*47112Sbostic 				copyfd(pip[1], 1);
522*47112Sbostic 				close(pip[1]);
523*47112Sbostic 			}
524*47112Sbostic 			evaltree(n, EV_EXIT);
525*47112Sbostic 		}
526*47112Sbostic 		close(pip[1]);
527*47112Sbostic 		result->fd = pip[0];
528*47112Sbostic 		result->jp = jp;
529*47112Sbostic 	}
530*47112Sbostic 	popstackmark(&smark);
531*47112Sbostic 	TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
532*47112Sbostic 		result->fd, result->buf, result->nleft, result->jp));
533*47112Sbostic }
534*47112Sbostic 
535*47112Sbostic 
536*47112Sbostic 
537*47112Sbostic /*
538*47112Sbostic  * Execute a simple command.
539*47112Sbostic  */
540*47112Sbostic 
541*47112Sbostic STATIC void
542*47112Sbostic evalcommand(cmd, flags, backcmd)
543*47112Sbostic 	union node *cmd;
544*47112Sbostic 	struct backcmd *backcmd;
545*47112Sbostic 	{
546*47112Sbostic 	struct stackmark smark;
547*47112Sbostic 	union node *argp;
548*47112Sbostic 	struct arglist arglist;
549*47112Sbostic 	struct arglist varlist;
550*47112Sbostic 	char **argv;
551*47112Sbostic 	int argc;
552*47112Sbostic 	char **envp;
553*47112Sbostic 	int varflag;
554*47112Sbostic 	struct strlist *sp;
555*47112Sbostic 	register char *p;
556*47112Sbostic 	int mode;
557*47112Sbostic 	int pip[2];
558*47112Sbostic 	struct cmdentry cmdentry;
559*47112Sbostic 	struct job *jp;
560*47112Sbostic 	struct jmploc jmploc;
561*47112Sbostic 	struct jmploc *volatile savehandler;
562*47112Sbostic 	char *volatile savecmdname;
563*47112Sbostic 	volatile struct shparam saveparam;
564*47112Sbostic 	struct localvar *volatile savelocalvars;
565*47112Sbostic 	volatile int e;
566*47112Sbostic 	char *lastarg;
567*47112Sbostic 
568*47112Sbostic 	/* First expand the arguments. */
569*47112Sbostic 	TRACE(("evalcommand(0x%x, %d) called\n", (int)cmd, flags));
570*47112Sbostic 	setstackmark(&smark);
571*47112Sbostic 	arglist.lastp = &arglist.list;
572*47112Sbostic 	varlist.lastp = &varlist.list;
573*47112Sbostic 	varflag = 1;
574*47112Sbostic 	for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
575*47112Sbostic 		p = argp->narg.text;
576*47112Sbostic 		if (varflag && is_name(*p)) {
577*47112Sbostic 			do {
578*47112Sbostic 				p++;
579*47112Sbostic 			} while (is_in_name(*p));
580*47112Sbostic 			if (*p == '=') {
581*47112Sbostic 				expandarg(argp, &varlist, 0);
582*47112Sbostic 				continue;
583*47112Sbostic 			}
584*47112Sbostic 		}
585*47112Sbostic 		expandarg(argp, &arglist, 1);
586*47112Sbostic 		varflag = 0;
587*47112Sbostic 	}
588*47112Sbostic 	*arglist.lastp = NULL;
589*47112Sbostic 	*varlist.lastp = NULL;
590*47112Sbostic 	expredir(cmd->ncmd.redirect);
591*47112Sbostic 	argc = 0;
592*47112Sbostic 	for (sp = arglist.list ; sp ; sp = sp->next)
593*47112Sbostic 		argc++;
594*47112Sbostic 	argv = stalloc(sizeof (char *) * (argc + 1));
595*47112Sbostic 	for (sp = arglist.list ; sp ; sp = sp->next)
596*47112Sbostic 		*argv++ = sp->text;
597*47112Sbostic 	*argv = NULL;
598*47112Sbostic 	lastarg = NULL;
599*47112Sbostic 	if (iflag && funcnest == 0 && argc > 0)
600*47112Sbostic 		lastarg = argv[-1];
601*47112Sbostic 	argv -= argc;
602*47112Sbostic 
603*47112Sbostic 	/* Print the command if xflag is set. */
604*47112Sbostic 	if (xflag) {
605*47112Sbostic 		outc('+', &errout);
606*47112Sbostic 		for (sp = varlist.list ; sp ; sp = sp->next) {
607*47112Sbostic 			outc(' ', &errout);
608*47112Sbostic 			out2str(sp->text);
609*47112Sbostic 		}
610*47112Sbostic 		for (sp = arglist.list ; sp ; sp = sp->next) {
611*47112Sbostic 			outc(' ', &errout);
612*47112Sbostic 			out2str(sp->text);
613*47112Sbostic 		}
614*47112Sbostic 		outc('\n', &errout);
615*47112Sbostic 		flushout(&errout);
616*47112Sbostic 	}
617*47112Sbostic 
618*47112Sbostic 	/* Now locate the command. */
619*47112Sbostic 	if (argc == 0) {
620*47112Sbostic 		cmdentry.cmdtype = CMDBUILTIN;
621*47112Sbostic 		cmdentry.u.index = BLTINCMD;
622*47112Sbostic 	} else {
623*47112Sbostic 		find_command(argv[0], &cmdentry, 1);
624*47112Sbostic 		if (cmdentry.cmdtype == CMDUNKNOWN) {	/* command not found */
625*47112Sbostic 			exitstatus = 2;
626*47112Sbostic 			flushout(&errout);
627*47112Sbostic 			return;
628*47112Sbostic 		}
629*47112Sbostic 		/* implement the bltin builtin here */
630*47112Sbostic 		if (cmdentry.cmdtype == CMDBUILTIN && cmdentry.u.index == BLTINCMD) {
631*47112Sbostic 			for (;;) {
632*47112Sbostic 				argv++;
633*47112Sbostic 				if (--argc == 0)
634*47112Sbostic 					break;
635*47112Sbostic 				if ((cmdentry.u.index = find_builtin(*argv)) < 0) {
636*47112Sbostic 					outfmt(&errout, "%s: not found\n", *argv);
637*47112Sbostic 					exitstatus = 2;
638*47112Sbostic 					flushout(&errout);
639*47112Sbostic 					return;
640*47112Sbostic 				}
641*47112Sbostic 				if (cmdentry.u.index != BLTINCMD)
642*47112Sbostic 					break;
643*47112Sbostic 			}
644*47112Sbostic 		}
645*47112Sbostic 	}
646*47112Sbostic 
647*47112Sbostic 	/* Fork off a child process if necessary. */
648*47112Sbostic 	if (cmd->ncmd.backgnd
649*47112Sbostic 	 || cmdentry.cmdtype == CMDNORMAL && (flags & EV_EXIT) == 0
650*47112Sbostic 	 || (flags & EV_BACKCMD) != 0
651*47112Sbostic 	    && (cmdentry.cmdtype != CMDBUILTIN
652*47112Sbostic 		 || cmdentry.u.index == DOTCMD
653*47112Sbostic 		 || cmdentry.u.index == EVALCMD)) {
654*47112Sbostic 		jp = makejob(cmd, 1);
655*47112Sbostic 		mode = cmd->ncmd.backgnd;
656*47112Sbostic 		if (flags & EV_BACKCMD) {
657*47112Sbostic 			mode = FORK_NOJOB;
658*47112Sbostic 			if (pipe(pip) < 0)
659*47112Sbostic 				error("Pipe call failed");
660*47112Sbostic 		}
661*47112Sbostic 		if (forkshell(jp, cmd, mode) != 0)
662*47112Sbostic 			goto parent;	/* at end of routine */
663*47112Sbostic 		if (flags & EV_BACKCMD) {
664*47112Sbostic 			FORCEINTON;
665*47112Sbostic 			close(pip[0]);
666*47112Sbostic 			if (pip[1] != 1) {
667*47112Sbostic 				close(1);
668*47112Sbostic 				copyfd(pip[1], 1);
669*47112Sbostic 				close(pip[1]);
670*47112Sbostic 			}
671*47112Sbostic 		}
672*47112Sbostic 		flags |= EV_EXIT;
673*47112Sbostic 	}
674*47112Sbostic 
675*47112Sbostic 	/* This is the child process if a fork occurred. */
676*47112Sbostic 	/* Execute the command. */
677*47112Sbostic 	if (cmdentry.cmdtype == CMDFUNCTION) {
678*47112Sbostic 		trputs("Shell function:  ");  trargs(argv);
679*47112Sbostic 		redirect(cmd->ncmd.redirect, REDIR_PUSH);
680*47112Sbostic 		saveparam = shellparam;
681*47112Sbostic 		shellparam.malloc = 0;
682*47112Sbostic 		shellparam.nparam = argc - 1;
683*47112Sbostic 		shellparam.p = argv + 1;
684*47112Sbostic 		shellparam.optnext = NULL;
685*47112Sbostic 		INTOFF;
686*47112Sbostic 		savelocalvars = localvars;
687*47112Sbostic 		localvars = NULL;
688*47112Sbostic 		INTON;
689*47112Sbostic 		if (setjmp(jmploc.loc)) {
690*47112Sbostic 			if (exception == EXSHELLPROC)
691*47112Sbostic 				freeparam((struct shparam *)&saveparam);
692*47112Sbostic 			else {
693*47112Sbostic 				freeparam(&shellparam);
694*47112Sbostic 				shellparam = saveparam;
695*47112Sbostic 			}
696*47112Sbostic 			poplocalvars();
697*47112Sbostic 			localvars = savelocalvars;
698*47112Sbostic 			handler = savehandler;
699*47112Sbostic 			longjmp(handler->loc, 1);
700*47112Sbostic 		}
701*47112Sbostic 		savehandler = handler;
702*47112Sbostic 		handler = &jmploc;
703*47112Sbostic 		for (sp = varlist.list ; sp ; sp = sp->next)
704*47112Sbostic 			mklocal(sp->text);
705*47112Sbostic 		funcnest++;
706*47112Sbostic 		evaltree(cmdentry.u.func, 0);
707*47112Sbostic 		funcnest--;
708*47112Sbostic 		INTOFF;
709*47112Sbostic 		poplocalvars();
710*47112Sbostic 		localvars = savelocalvars;
711*47112Sbostic 		freeparam(&shellparam);
712*47112Sbostic 		shellparam = saveparam;
713*47112Sbostic 		handler = savehandler;
714*47112Sbostic 		popredir();
715*47112Sbostic 		INTON;
716*47112Sbostic 		if (evalskip == SKIPFUNC) {
717*47112Sbostic 			evalskip = 0;
718*47112Sbostic 			skipcount = 0;
719*47112Sbostic 		}
720*47112Sbostic 		if (flags & EV_EXIT)
721*47112Sbostic 			exitshell(exitstatus);
722*47112Sbostic 	} else if (cmdentry.cmdtype == CMDBUILTIN) {
723*47112Sbostic 		trputs("builtin command:  ");  trargs(argv);
724*47112Sbostic 		mode = (cmdentry.u.index == EXECCMD)? 0 : REDIR_PUSH;
725*47112Sbostic 		if (flags == EV_BACKCMD) {
726*47112Sbostic 			memout.nleft = 0;
727*47112Sbostic 			memout.nextc = memout.buf;
728*47112Sbostic 			memout.bufsize = 64;
729*47112Sbostic 			mode |= REDIR_BACKQ;
730*47112Sbostic 		}
731*47112Sbostic 		redirect(cmd->ncmd.redirect, mode);
732*47112Sbostic 		savecmdname = commandname;
733*47112Sbostic 		cmdenviron = varlist.list;
734*47112Sbostic 		e = -1;
735*47112Sbostic 		if (setjmp(jmploc.loc)) {
736*47112Sbostic 			e = exception;
737*47112Sbostic 			exitstatus = (e == EXINT)? SIGINT+128 : 2;
738*47112Sbostic 			goto cmddone;
739*47112Sbostic 		}
740*47112Sbostic 		savehandler = handler;
741*47112Sbostic 		handler = &jmploc;
742*47112Sbostic 		commandname = argv[0];
743*47112Sbostic 		argptr = argv + 1;
744*47112Sbostic 		optptr = NULL;			/* initialize nextopt */
745*47112Sbostic 		exitstatus = (*builtinfunc[cmdentry.u.index])(argc, argv);
746*47112Sbostic 		flushall();
747*47112Sbostic cmddone:
748*47112Sbostic 		out1 = &output;
749*47112Sbostic 		out2 = &errout;
750*47112Sbostic 		freestdout();
751*47112Sbostic 		if (e != EXSHELLPROC) {
752*47112Sbostic 			commandname = savecmdname;
753*47112Sbostic 			if (flags & EV_EXIT) {
754*47112Sbostic 				exitshell(exitstatus);
755*47112Sbostic 			}
756*47112Sbostic 		}
757*47112Sbostic 		handler = savehandler;
758*47112Sbostic 		if (e != -1) {
759*47112Sbostic 			if (e != EXERROR || cmdentry.u.index == BLTINCMD
760*47112Sbostic 					       || cmdentry.u.index == DOTCMD
761*47112Sbostic 					       || cmdentry.u.index == EVALCMD
762*47112Sbostic 					       || cmdentry.u.index == EXECCMD)
763*47112Sbostic 				exraise(e);
764*47112Sbostic 			FORCEINTON;
765*47112Sbostic 		}
766*47112Sbostic 		if (cmdentry.u.index != EXECCMD)
767*47112Sbostic 			popredir();
768*47112Sbostic 		if (flags == EV_BACKCMD) {
769*47112Sbostic 			backcmd->buf = memout.buf;
770*47112Sbostic 			backcmd->nleft = memout.nextc - memout.buf;
771*47112Sbostic 			memout.buf = NULL;
772*47112Sbostic 		}
773*47112Sbostic 	} else {
774*47112Sbostic 		trputs("normal command:  ");  trargs(argv);
775*47112Sbostic 		clearredir();
776*47112Sbostic 		redirect(cmd->ncmd.redirect, 0);
777*47112Sbostic 		if (varlist.list) {
778*47112Sbostic 			p = stalloc(strlen(pathval()) + 1);
779*47112Sbostic 			scopy(pathval(), p);
780*47112Sbostic 		} else {
781*47112Sbostic 			p = pathval();
782*47112Sbostic 		}
783*47112Sbostic 		for (sp = varlist.list ; sp ; sp = sp->next)
784*47112Sbostic 			setvareq(sp->text, VEXPORT|VSTACK);
785*47112Sbostic 		envp = environment();
786*47112Sbostic 		shellexec(argv, envp, p, cmdentry.u.index);
787*47112Sbostic 		/*NOTREACHED*/
788*47112Sbostic 	}
789*47112Sbostic 	goto out;
790*47112Sbostic 
791*47112Sbostic parent:	/* parent process gets here (if we forked) */
792*47112Sbostic 	if (mode == 0) {	/* argument to fork */
793*47112Sbostic 		INTOFF;
794*47112Sbostic 		exitstatus = waitforjob(jp);
795*47112Sbostic 		INTON;
796*47112Sbostic 	} else if (mode == 2) {
797*47112Sbostic 		backcmd->fd = pip[0];
798*47112Sbostic 		close(pip[1]);
799*47112Sbostic 		backcmd->jp = jp;
800*47112Sbostic 	}
801*47112Sbostic 
802*47112Sbostic out:
803*47112Sbostic 	if (lastarg)
804*47112Sbostic 		setvar("_", lastarg, 0);
805*47112Sbostic 	popstackmark(&smark);
806*47112Sbostic }
807*47112Sbostic 
808*47112Sbostic 
809*47112Sbostic 
810*47112Sbostic /*
811*47112Sbostic  * Search for a command.  This is called before we fork so that the
812*47112Sbostic  * location of the command will be available in the parent as well as
813*47112Sbostic  * the child.  The check for "goodname" is an overly conservative
814*47112Sbostic  * check that the name will not be subject to expansion.
815*47112Sbostic  */
816*47112Sbostic 
817*47112Sbostic STATIC void
818*47112Sbostic prehash(n)
819*47112Sbostic 	union node *n;
820*47112Sbostic 	{
821*47112Sbostic 	struct cmdentry entry;
822*47112Sbostic 
823*47112Sbostic 	if (n->type == NCMD && goodname(n->ncmd.args->narg.text))
824*47112Sbostic 		find_command(n->ncmd.args->narg.text, &entry, 0);
825*47112Sbostic }
826*47112Sbostic 
827*47112Sbostic 
828*47112Sbostic 
829*47112Sbostic /*
830*47112Sbostic  * Builtin commands.  Builtin commands whose functions are closely
831*47112Sbostic  * tied to evaluation are implemented here.
832*47112Sbostic  */
833*47112Sbostic 
834*47112Sbostic /*
835*47112Sbostic  * No command given, or a bltin command with no arguments.  Set the
836*47112Sbostic  * specified variables.
837*47112Sbostic  */
838*47112Sbostic 
839*47112Sbostic bltincmd(argc, argv)  char **argv; {
840*47112Sbostic 	listsetvar(cmdenviron);
841*47112Sbostic 	return exitstatus;
842*47112Sbostic }
843*47112Sbostic 
844*47112Sbostic 
845*47112Sbostic /*
846*47112Sbostic  * Handle break and continue commands.  Break, continue, and return are
847*47112Sbostic  * all handled by setting the evalskip flag.  The evaluation routines
848*47112Sbostic  * above all check this flag, and if it is set they start skipping
849*47112Sbostic  * commands rather than executing them.  The variable skipcount is
850*47112Sbostic  * the number of loops to break/continue, or the number of function
851*47112Sbostic  * levels to return.  (The latter is always 1.)  It should probably
852*47112Sbostic  * be an error to break out of more loops than exist, but it isn't
853*47112Sbostic  * in the standard shell so we don't make it one here.
854*47112Sbostic  */
855*47112Sbostic 
856*47112Sbostic breakcmd(argc, argv)  char **argv; {
857*47112Sbostic 	int n;
858*47112Sbostic 
859*47112Sbostic 	n = 1;
860*47112Sbostic 	if (argc > 1)
861*47112Sbostic 		n = number(argv[1]);
862*47112Sbostic 	if (n > loopnest)
863*47112Sbostic 		n = loopnest;
864*47112Sbostic 	if (n > 0) {
865*47112Sbostic 		evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
866*47112Sbostic 		skipcount = n;
867*47112Sbostic 	}
868*47112Sbostic 	return 0;
869*47112Sbostic }
870*47112Sbostic 
871*47112Sbostic 
872*47112Sbostic /*
873*47112Sbostic  * The return command.
874*47112Sbostic  */
875*47112Sbostic 
876*47112Sbostic returncmd(argc, argv)  char **argv; {
877*47112Sbostic 	int ret;
878*47112Sbostic 
879*47112Sbostic 	ret = exitstatus;
880*47112Sbostic 	if (argc > 1)
881*47112Sbostic 		ret = number(argv[1]);
882*47112Sbostic 	if (funcnest) {
883*47112Sbostic 		evalskip = SKIPFUNC;
884*47112Sbostic 		skipcount = 1;
885*47112Sbostic 	}
886*47112Sbostic 	return ret;
887*47112Sbostic }
888*47112Sbostic 
889*47112Sbostic 
890*47112Sbostic truecmd(argc, argv)  char **argv; {
891*47112Sbostic 	return 0;
892*47112Sbostic }
893*47112Sbostic 
894*47112Sbostic 
895*47112Sbostic execcmd(argc, argv)  char **argv; {
896*47112Sbostic 	if (argc > 1) {
897*47112Sbostic 		iflag = 0;		/* exit on error */
898*47112Sbostic 		setinteractive(0);
899*47112Sbostic #if JOBS
900*47112Sbostic 		jflag = 0;
901*47112Sbostic 		setjobctl(0);
902*47112Sbostic #endif
903*47112Sbostic 		shellexec(argv + 1, environment(), pathval(), 0);
904*47112Sbostic 
905*47112Sbostic 	}
906*47112Sbostic 	return 0;
907*47112Sbostic }
908