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 * 4. Neither the name of the University nor the names of its contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#ifndef lint
34#if 0
35static char sccsid[] = "@(#)eval.c	8.9 (Berkeley) 6/8/95";
36#endif
37#endif /* not lint */
38#include <sys/cdefs.h>
39__FBSDID("$FreeBSD$");
40
41#include <paths.h>
42#include <signal.h>
43#include <stdlib.h>
44#include <unistd.h>
45#include <sys/resource.h>
46#include <sys/wait.h> /* For WIFSIGNALED(status) */
47#include <errno.h>
48
49/*
50 * Evaluate a command.
51 */
52
53#include "shell.h"
54#include "nodes.h"
55#include "syntax.h"
56#include "expand.h"
57#include "parser.h"
58#include "jobs.h"
59#include "eval.h"
60#include "builtins.h"
61#include "options.h"
62#include "exec.h"
63#include "redir.h"
64#include "input.h"
65#include "output.h"
66#include "trap.h"
67#include "var.h"
68#include "memalloc.h"
69#include "error.h"
70#include "show.h"
71#include "mystring.h"
72#ifndef NO_HISTORY
73#include "myhistedit.h"
74#endif
75
76
77int evalskip;			/* set if we are skipping commands */
78int skipcount;			/* number of levels to skip */
79static int loopnest;		/* current loop nesting level */
80int funcnest;			/* depth of function calls */
81static int builtin_flags;	/* evalcommand flags for builtins */
82
83
84char *commandname;
85struct arglist *cmdenviron;
86int exitstatus;			/* exit status of last command */
87int oexitstatus;		/* saved exit status */
88
89
90static void evalloop(union node *, int);
91static void evalfor(union node *, int);
92static union node *evalcase(union node *);
93static void evalsubshell(union node *, int);
94static void evalredir(union node *, int);
95static void exphere(union node *, struct arglist *);
96static void expredir(union node *);
97static void evalpipe(union node *);
98static int is_valid_fast_cmdsubst(union node *n);
99static void evalcommand(union node *, int, struct backcmd *);
100static void prehash(union node *);
101
102
103/*
104 * Called to reset things after an exception.
105 */
106
107void
108reseteval(void)
109{
110	evalskip = 0;
111	loopnest = 0;
112}
113
114
115/*
116 * The eval command.
117 */
118
119int
120evalcmd(int argc, char **argv)
121{
122        char *p;
123        char *concat;
124        char **ap;
125
126        if (argc > 1) {
127                p = argv[1];
128                if (argc > 2) {
129                        STARTSTACKSTR(concat);
130                        ap = argv + 2;
131                        for (;;) {
132                                STPUTS(p, concat);
133                                if ((p = *ap++) == NULL)
134                                        break;
135                                STPUTC(' ', concat);
136                        }
137                        STPUTC('\0', concat);
138                        p = grabstackstr(concat);
139                }
140                evalstring(p, builtin_flags);
141        } else
142                exitstatus = 0;
143        return exitstatus;
144}
145
146
147/*
148 * Execute a command or commands contained in a string.
149 */
150
151void
152evalstring(const char *s, int flags)
153{
154	union node *n;
155	struct stackmark smark;
156	int flags_exit;
157	int any;
158
159	flags_exit = flags & EV_EXIT;
160	flags &= ~EV_EXIT;
161	any = 0;
162	setstackmark(&smark);
163	setinputstring(s, 1);
164	while ((n = parsecmd(0)) != NEOF) {
165		if (n != NULL && !nflag) {
166			if (flags_exit && preadateof())
167				evaltree(n, flags | EV_EXIT);
168			else
169				evaltree(n, flags);
170			any = 1;
171			if (evalskip)
172				break;
173		}
174		popstackmark(&smark);
175		setstackmark(&smark);
176	}
177	popfile();
178	popstackmark(&smark);
179	if (!any)
180		exitstatus = 0;
181	if (flags_exit)
182		exraise(EXEXIT);
183}
184
185
186/*
187 * Evaluate a parse tree.  The value is left in the global variable
188 * exitstatus.
189 */
190
191void
192evaltree(union node *n, int flags)
193{
194	int do_etest;
195	union node *next;
196	struct stackmark smark;
197
198	setstackmark(&smark);
199	do_etest = 0;
200	if (n == NULL) {
201		TRACE(("evaltree(NULL) called\n"));
202		exitstatus = 0;
203		goto out;
204	}
205	do {
206		next = NULL;
207#ifndef NO_HISTORY
208		displayhist = 1;	/* show history substitutions done with fc */
209#endif
210		TRACE(("evaltree(%p: %d) called\n", (void *)n, n->type));
211		switch (n->type) {
212		case NSEMI:
213			evaltree(n->nbinary.ch1, flags & ~EV_EXIT);
214			if (evalskip)
215				goto out;
216			next = n->nbinary.ch2;
217			break;
218		case NAND:
219			evaltree(n->nbinary.ch1, EV_TESTED);
220			if (evalskip || exitstatus != 0) {
221				goto out;
222			}
223			next = n->nbinary.ch2;
224			break;
225		case NOR:
226			evaltree(n->nbinary.ch1, EV_TESTED);
227			if (evalskip || exitstatus == 0)
228				goto out;
229			next = n->nbinary.ch2;
230			break;
231		case NREDIR:
232			evalredir(n, flags);
233			break;
234		case NSUBSHELL:
235			evalsubshell(n, flags);
236			do_etest = !(flags & EV_TESTED);
237			break;
238		case NBACKGND:
239			evalsubshell(n, flags);
240			break;
241		case NIF: {
242			evaltree(n->nif.test, EV_TESTED);
243			if (evalskip)
244				goto out;
245			if (exitstatus == 0)
246				next = n->nif.ifpart;
247			else if (n->nif.elsepart)
248				next = n->nif.elsepart;
249			else
250				exitstatus = 0;
251			break;
252		}
253		case NWHILE:
254		case NUNTIL:
255			evalloop(n, flags & ~EV_EXIT);
256			break;
257		case NFOR:
258			evalfor(n, flags & ~EV_EXIT);
259			break;
260		case NCASE:
261			next = evalcase(n);
262			break;
263		case NCLIST:
264			next = n->nclist.body;
265			break;
266		case NCLISTFALLTHRU:
267			if (n->nclist.body) {
268				evaltree(n->nclist.body, flags & ~EV_EXIT);
269				if (evalskip)
270					goto out;
271			}
272			next = n->nclist.next;
273			break;
274		case NDEFUN:
275			defun(n->narg.text, n->narg.next);
276			exitstatus = 0;
277			break;
278		case NNOT:
279			evaltree(n->nnot.com, EV_TESTED);
280			if (evalskip)
281				goto out;
282			exitstatus = !exitstatus;
283			break;
284
285		case NPIPE:
286			evalpipe(n);
287			do_etest = !(flags & EV_TESTED);
288			break;
289		case NCMD:
290			evalcommand(n, flags, (struct backcmd *)NULL);
291			do_etest = !(flags & EV_TESTED);
292			break;
293		default:
294			out1fmt("Node type = %d\n", n->type);
295			flushout(&output);
296			break;
297		}
298		n = next;
299		popstackmark(&smark);
300		setstackmark(&smark);
301	} while (n != NULL);
302out:
303	popstackmark(&smark);
304	if (pendingsig)
305		dotrap();
306	if (eflag && exitstatus != 0 && do_etest)
307		exitshell(exitstatus);
308	if (flags & EV_EXIT)
309		exraise(EXEXIT);
310}
311
312
313static void
314evalloop(union node *n, int flags)
315{
316	int status;
317
318	loopnest++;
319	status = 0;
320	for (;;) {
321		if (!evalskip)
322			evaltree(n->nbinary.ch1, EV_TESTED);
323		if (evalskip) {
324			if (evalskip == SKIPCONT && --skipcount <= 0) {
325				evalskip = 0;
326				continue;
327			}
328			if (evalskip == SKIPBREAK && --skipcount <= 0)
329				evalskip = 0;
330			if (evalskip == SKIPRETURN)
331				status = exitstatus;
332			break;
333		}
334		if (n->type == NWHILE) {
335			if (exitstatus != 0)
336				break;
337		} else {
338			if (exitstatus == 0)
339				break;
340		}
341		evaltree(n->nbinary.ch2, flags);
342		status = exitstatus;
343	}
344	loopnest--;
345	exitstatus = status;
346}
347
348
349
350static void
351evalfor(union node *n, int flags)
352{
353	struct arglist arglist;
354	union node *argp;
355	int i;
356	int status;
357
358	emptyarglist(&arglist);
359	for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
360		oexitstatus = exitstatus;
361		expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
362	}
363
364	loopnest++;
365	status = 0;
366	for (i = 0; i < arglist.count; i++) {
367		setvar(n->nfor.var, arglist.args[i], 0);
368		evaltree(n->nfor.body, flags);
369		status = exitstatus;
370		if (evalskip) {
371			if (evalskip == SKIPCONT && --skipcount <= 0) {
372				evalskip = 0;
373				continue;
374			}
375			if (evalskip == SKIPBREAK && --skipcount <= 0)
376				evalskip = 0;
377			break;
378		}
379	}
380	loopnest--;
381	exitstatus = status;
382}
383
384
385/*
386 * Evaluate a case statement, returning the selected tree.
387 *
388 * The exit status needs care to get right.
389 */
390
391static union node *
392evalcase(union node *n)
393{
394	union node *cp;
395	union node *patp;
396	struct arglist arglist;
397
398	emptyarglist(&arglist);
399	oexitstatus = exitstatus;
400	expandarg(n->ncase.expr, &arglist, EXP_TILDE);
401	for (cp = n->ncase.cases ; cp ; cp = cp->nclist.next) {
402		for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
403			if (casematch(patp, arglist.args[0])) {
404				while (cp->nclist.next &&
405				    cp->type == NCLISTFALLTHRU &&
406				    cp->nclist.body == NULL)
407					cp = cp->nclist.next;
408				if (cp->nclist.next &&
409				    cp->type == NCLISTFALLTHRU)
410					return (cp);
411				if (cp->nclist.body == NULL)
412					exitstatus = 0;
413				return (cp->nclist.body);
414			}
415		}
416	}
417	exitstatus = 0;
418	return (NULL);
419}
420
421
422
423/*
424 * Kick off a subshell to evaluate a tree.
425 */
426
427static void
428evalsubshell(union node *n, int flags)
429{
430	struct job *jp;
431	int backgnd = (n->type == NBACKGND);
432
433	oexitstatus = exitstatus;
434	expredir(n->nredir.redirect);
435	if ((!backgnd && flags & EV_EXIT && !have_traps()) ||
436			forkshell(jp = makejob(n, 1), n, backgnd) == 0) {
437		if (backgnd)
438			flags &=~ EV_TESTED;
439		redirect(n->nredir.redirect, 0);
440		evaltree(n->nredir.n, flags | EV_EXIT);	/* never returns */
441	} else if (! backgnd) {
442		INTOFF;
443		exitstatus = waitforjob(jp, (int *)NULL);
444		INTON;
445	} else
446		exitstatus = 0;
447}
448
449
450/*
451 * Evaluate a redirected compound command.
452 */
453
454static void
455evalredir(union node *n, int flags)
456{
457	struct jmploc jmploc;
458	struct jmploc *savehandler;
459	volatile int in_redirect = 1;
460
461	oexitstatus = exitstatus;
462	expredir(n->nredir.redirect);
463	savehandler = handler;
464	if (setjmp(jmploc.loc)) {
465		int e;
466
467		handler = savehandler;
468		e = exception;
469		popredir();
470		if (e == EXERROR || e == EXEXEC) {
471			if (in_redirect) {
472				exitstatus = 2;
473				return;
474			}
475		}
476		longjmp(handler->loc, 1);
477	} else {
478		INTOFF;
479		handler = &jmploc;
480		redirect(n->nredir.redirect, REDIR_PUSH);
481		in_redirect = 0;
482		INTON;
483		evaltree(n->nredir.n, flags);
484	}
485	INTOFF;
486	handler = savehandler;
487	popredir();
488	INTON;
489}
490
491
492static void
493exphere(union node *redir, struct arglist *fn)
494{
495	struct jmploc jmploc;
496	struct jmploc *savehandler;
497	struct localvar *savelocalvars;
498	int need_longjmp = 0;
499	unsigned char saveoptreset;
500
501	redir->nhere.expdoc = "";
502	savelocalvars = localvars;
503	localvars = NULL;
504	saveoptreset = shellparam.reset;
505	forcelocal++;
506	savehandler = handler;
507	if (setjmp(jmploc.loc))
508		need_longjmp = exception != EXERROR && exception != EXEXEC;
509	else {
510		handler = &jmploc;
511		expandarg(redir->nhere.doc, fn, 0);
512		redir->nhere.expdoc = fn->args[0];
513		INTOFF;
514	}
515	handler = savehandler;
516	forcelocal--;
517	poplocalvars();
518	localvars = savelocalvars;
519	shellparam.reset = saveoptreset;
520	if (need_longjmp)
521		longjmp(handler->loc, 1);
522	INTON;
523}
524
525
526/*
527 * Compute the names of the files in a redirection list.
528 */
529
530static void
531expredir(union node *n)
532{
533	union node *redir;
534
535	for (redir = n ; redir ; redir = redir->nfile.next) {
536		struct arglist fn;
537		emptyarglist(&fn);
538		switch (redir->type) {
539		case NFROM:
540		case NTO:
541		case NFROMTO:
542		case NAPPEND:
543		case NCLOBBER:
544			expandarg(redir->nfile.fname, &fn, EXP_TILDE);
545			redir->nfile.expfname = fn.args[0];
546			break;
547		case NFROMFD:
548		case NTOFD:
549			if (redir->ndup.vname) {
550				expandarg(redir->ndup.vname, &fn, EXP_TILDE);
551				fixredir(redir, fn.args[0], 1);
552			}
553			break;
554		case NXHERE:
555			exphere(redir, &fn);
556			break;
557		}
558	}
559}
560
561
562
563/*
564 * Evaluate a pipeline.  All the processes in the pipeline are children
565 * of the process creating the pipeline.  (This differs from some versions
566 * of the shell, which make the last process in a pipeline the parent
567 * of all the rest.)
568 */
569
570static void
571evalpipe(union node *n)
572{
573	struct job *jp;
574	struct nodelist *lp;
575	int pipelen;
576	int prevfd;
577	int pip[2];
578
579	TRACE(("evalpipe(%p) called\n", (void *)n));
580	pipelen = 0;
581	for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
582		pipelen++;
583	INTOFF;
584	jp = makejob(n, pipelen);
585	prevfd = -1;
586	for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
587		prehash(lp->n);
588		pip[1] = -1;
589		if (lp->next) {
590			if (pipe(pip) < 0) {
591				if (prevfd >= 0)
592					close(prevfd);
593				error("Pipe call failed: %s", strerror(errno));
594			}
595		}
596		if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
597			INTON;
598			if (prevfd > 0) {
599				dup2(prevfd, 0);
600				close(prevfd);
601			}
602			if (pip[1] >= 0) {
603				if (!(prevfd >= 0 && pip[0] == 0))
604					close(pip[0]);
605				if (pip[1] != 1) {
606					dup2(pip[1], 1);
607					close(pip[1]);
608				}
609			}
610			evaltree(lp->n, EV_EXIT);
611		}
612		if (prevfd >= 0)
613			close(prevfd);
614		prevfd = pip[0];
615		if (pip[1] != -1)
616			close(pip[1]);
617	}
618	INTON;
619	if (n->npipe.backgnd == 0) {
620		INTOFF;
621		exitstatus = waitforjob(jp, (int *)NULL);
622		TRACE(("evalpipe:  job done exit status %d\n", exitstatus));
623		INTON;
624	} else
625		exitstatus = 0;
626}
627
628
629
630static int
631is_valid_fast_cmdsubst(union node *n)
632{
633
634	return (n->type == NCMD);
635}
636
637/*
638 * Execute a command inside back quotes.  If it's a builtin command, we
639 * want to save its output in a block obtained from malloc.  Otherwise
640 * we fork off a subprocess and get the output of the command via a pipe.
641 * Should be called with interrupts off.
642 */
643
644void
645evalbackcmd(union node *n, struct backcmd *result)
646{
647	int pip[2];
648	struct job *jp;
649	struct stackmark smark;
650	struct jmploc jmploc;
651	struct jmploc *savehandler;
652	struct localvar *savelocalvars;
653	unsigned char saveoptreset;
654
655	result->fd = -1;
656	result->buf = NULL;
657	result->nleft = 0;
658	result->jp = NULL;
659	if (n == NULL) {
660		exitstatus = 0;
661		return;
662	}
663	setstackmark(&smark);
664	exitstatus = oexitstatus;
665	if (is_valid_fast_cmdsubst(n)) {
666		savelocalvars = localvars;
667		localvars = NULL;
668		saveoptreset = shellparam.reset;
669		forcelocal++;
670		savehandler = handler;
671		if (setjmp(jmploc.loc)) {
672			if (exception == EXERROR || exception == EXEXEC)
673				exitstatus = 2;
674			else if (exception != 0) {
675				handler = savehandler;
676				forcelocal--;
677				poplocalvars();
678				localvars = savelocalvars;
679				shellparam.reset = saveoptreset;
680				longjmp(handler->loc, 1);
681			}
682		} else {
683			handler = &jmploc;
684			evalcommand(n, EV_BACKCMD, result);
685		}
686		handler = savehandler;
687		forcelocal--;
688		poplocalvars();
689		localvars = savelocalvars;
690		shellparam.reset = saveoptreset;
691	} else {
692		if (pipe(pip) < 0)
693			error("Pipe call failed: %s", strerror(errno));
694		jp = makejob(n, 1);
695		if (forkshell(jp, n, FORK_NOJOB) == 0) {
696			FORCEINTON;
697			close(pip[0]);
698			if (pip[1] != 1) {
699				dup2(pip[1], 1);
700				close(pip[1]);
701			}
702			evaltree(n, EV_EXIT);
703		}
704		close(pip[1]);
705		result->fd = pip[0];
706		result->jp = jp;
707	}
708	popstackmark(&smark);
709	TRACE(("evalbackcmd done: fd=%d buf=%p nleft=%d jp=%p\n",
710		result->fd, result->buf, result->nleft, result->jp));
711}
712
713static int
714mustexpandto(const char *argtext, const char *mask)
715{
716	for (;;) {
717		if (*argtext == CTLQUOTEMARK || *argtext == CTLQUOTEEND) {
718			argtext++;
719			continue;
720		}
721		if (*argtext == CTLESC)
722			argtext++;
723		else if (BASESYNTAX[(int)*argtext] == CCTL)
724			return (0);
725		if (*argtext != *mask)
726			return (0);
727		if (*argtext == '\0')
728			return (1);
729		argtext++;
730		mask++;
731	}
732}
733
734static int
735isdeclarationcmd(struct narg *arg)
736{
737	int have_command = 0;
738
739	if (arg == NULL)
740		return (0);
741	while (mustexpandto(arg->text, "command")) {
742		have_command = 1;
743		arg = &arg->next->narg;
744		if (arg == NULL)
745			return (0);
746		/*
747		 * To also allow "command -p" and "command --" as part of
748		 * a declaration command, add code here.
749		 * We do not do this, as ksh does not do it either and it
750		 * is not required by POSIX.
751		 */
752	}
753	return (mustexpandto(arg->text, "export") ||
754	    mustexpandto(arg->text, "readonly") ||
755	    (mustexpandto(arg->text, "local") &&
756		(have_command || !isfunc("local"))));
757}
758
759static void
760xtracecommand(struct arglist *varlist, int argc, char **argv)
761{
762	char sep = 0;
763	const char *text, *p, *ps4;
764	int i;
765
766	ps4 = expandstr(ps4val());
767	out2str(ps4 != NULL ? ps4 : ps4val());
768	for (i = 0; i < varlist->count; i++) {
769		text = varlist->args[i];
770		if (sep != 0)
771			out2c(' ');
772		p = strchr(text, '=');
773		if (p != NULL) {
774			p++;
775			outbin(text, p - text, out2);
776			out2qstr(p);
777		} else
778			out2qstr(text);
779		sep = ' ';
780	}
781	for (i = 0; i < argc; i++) {
782		text = argv[i];
783		if (sep != 0)
784			out2c(' ');
785		out2qstr(text);
786		sep = ' ';
787	}
788	out2c('\n');
789	flushout(&errout);
790}
791
792/*
793 * Check if a builtin can safely be executed in the same process,
794 * even though it should be in a subshell (command substitution).
795 * Note that jobid, jobs, times and trap can show information not
796 * available in a child process; this is deliberate.
797 * The arguments should already have been expanded.
798 */
799static int
800safe_builtin(int idx, int argc, char **argv)
801{
802	if (idx == BLTINCMD || idx == COMMANDCMD || idx == ECHOCMD ||
803	    idx == FALSECMD || idx == JOBIDCMD || idx == JOBSCMD ||
804	    idx == KILLCMD || idx == PRINTFCMD || idx == PWDCMD ||
805	    idx == TESTCMD || idx == TIMESCMD || idx == TRUECMD ||
806	    idx == TYPECMD)
807		return (1);
808	if (idx == EXPORTCMD || idx == TRAPCMD || idx == ULIMITCMD ||
809	    idx == UMASKCMD)
810		return (argc <= 1 || (argc == 2 && argv[1][0] == '-'));
811	if (idx == SETCMD)
812		return (argc <= 1 || (argc == 2 && (argv[1][0] == '-' ||
813		    argv[1][0] == '+') && argv[1][1] == 'o' &&
814		    argv[1][2] == '\0'));
815	return (0);
816}
817
818/*
819 * Execute a simple command.
820 * Note: This may or may not return if (flags & EV_EXIT).
821 */
822
823static void
824evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
825{
826	union node *argp;
827	struct arglist arglist;
828	struct arglist varlist;
829	char **argv;
830	int argc;
831	char **envp;
832	int varflag;
833	int mode;
834	int pip[2];
835	struct cmdentry cmdentry;
836	struct job *jp;
837	struct jmploc jmploc;
838	struct jmploc *savehandler;
839	char *savecmdname;
840	struct shparam saveparam;
841	struct localvar *savelocalvars;
842	struct parsefile *savetopfile;
843	volatile int e;
844	char *lastarg;
845	int realstatus;
846	int do_clearcmdentry;
847	const char *path = pathval();
848	int i;
849
850	/* First expand the arguments. */
851	TRACE(("evalcommand(%p, %d) called\n", (void *)cmd, flags));
852	emptyarglist(&arglist);
853	emptyarglist(&varlist);
854	varflag = 1;
855	jp = NULL;
856	do_clearcmdentry = 0;
857	oexitstatus = exitstatus;
858	exitstatus = 0;
859	/* Add one slot at the beginning for tryexec(). */
860	appendarglist(&arglist, nullstr);
861	for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
862		if (varflag && isassignment(argp->narg.text)) {
863			expandarg(argp, varflag == 1 ? &varlist : &arglist,
864			    EXP_VARTILDE);
865			continue;
866		} else if (varflag == 1)
867			varflag = isdeclarationcmd(&argp->narg) ? 2 : 0;
868		expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
869	}
870	appendarglist(&arglist, nullstr);
871	expredir(cmd->ncmd.redirect);
872	argc = arglist.count - 2;
873	argv = &arglist.args[1];
874
875	argv[argc] = NULL;
876	lastarg = NULL;
877	if (iflag && funcnest == 0 && argc > 0)
878		lastarg = argv[argc - 1];
879
880	/* Print the command if xflag is set. */
881	if (xflag)
882		xtracecommand(&varlist, argc, argv);
883
884	/* Now locate the command. */
885	if (argc == 0) {
886		/* Variable assignment(s) without command */
887		cmdentry.cmdtype = CMDBUILTIN;
888		cmdentry.u.index = BLTINCMD;
889		cmdentry.special = 0;
890	} else {
891		static const char PATH[] = "PATH=";
892		int cmd_flags = 0, bltinonly = 0;
893
894		/*
895		 * Modify the command lookup path, if a PATH= assignment
896		 * is present
897		 */
898		for (i = 0; i < varlist.count; i++)
899			if (strncmp(varlist.args[i], PATH, sizeof(PATH) - 1) == 0) {
900				path = varlist.args[i] + sizeof(PATH) - 1;
901				/*
902				 * On `PATH=... command`, we need to make
903				 * sure that the command isn't using the
904				 * non-updated hash table of the outer PATH
905				 * setting and we need to make sure that
906				 * the hash table isn't filled with items
907				 * from the temporary setting.
908				 *
909				 * It would be better to forbit using and
910				 * updating the table while this command
911				 * runs, by the command finding mechanism
912				 * is heavily integrated with hash handling,
913				 * so we just delete the hash before and after
914				 * the command runs. Partly deleting like
915				 * changepatch() does doesn't seem worth the
916				 * bookinging effort, since most such runs add
917				 * directories in front of the new PATH.
918				 */
919				clearcmdentry();
920				do_clearcmdentry = 1;
921			}
922
923		for (;;) {
924			if (bltinonly) {
925				cmdentry.u.index = find_builtin(*argv, &cmdentry.special);
926				if (cmdentry.u.index < 0) {
927					cmdentry.u.index = BLTINCMD;
928					argv--;
929					argc++;
930					break;
931				}
932			} else
933				find_command(argv[0], &cmdentry, cmd_flags, path);
934			/* implement the bltin and command builtins here */
935			if (cmdentry.cmdtype != CMDBUILTIN)
936				break;
937			if (cmdentry.u.index == BLTINCMD) {
938				if (argc == 1)
939					break;
940				argv++;
941				argc--;
942				bltinonly = 1;
943			} else if (cmdentry.u.index == COMMANDCMD) {
944				if (argc == 1)
945					break;
946				if (!strcmp(argv[1], "-p")) {
947					if (argc == 2)
948						break;
949					if (argv[2][0] == '-') {
950						if (strcmp(argv[2], "--"))
951							break;
952						if (argc == 3)
953							break;
954						argv += 3;
955						argc -= 3;
956					} else {
957						argv += 2;
958						argc -= 2;
959					}
960					path = _PATH_STDPATH;
961					clearcmdentry();
962					do_clearcmdentry = 1;
963				} else if (!strcmp(argv[1], "--")) {
964					if (argc == 2)
965						break;
966					argv += 2;
967					argc -= 2;
968				} else if (argv[1][0] == '-')
969					break;
970				else {
971					argv++;
972					argc--;
973				}
974				cmd_flags |= DO_NOFUNC;
975				bltinonly = 0;
976			} else
977				break;
978		}
979		/*
980		 * Special builtins lose their special properties when
981		 * called via 'command'.
982		 */
983		if (cmd_flags & DO_NOFUNC)
984			cmdentry.special = 0;
985	}
986
987	/* Fork off a child process if necessary. */
988	if (((cmdentry.cmdtype == CMDNORMAL || cmdentry.cmdtype == CMDUNKNOWN)
989	    && ((flags & EV_EXIT) == 0 || have_traps()))
990	 || ((flags & EV_BACKCMD) != 0
991	    && (cmdentry.cmdtype != CMDBUILTIN ||
992		 !safe_builtin(cmdentry.u.index, argc, argv)))) {
993		jp = makejob(cmd, 1);
994		mode = FORK_FG;
995		if (flags & EV_BACKCMD) {
996			mode = FORK_NOJOB;
997			if (pipe(pip) < 0)
998				error("Pipe call failed: %s", strerror(errno));
999		}
1000		if (cmdentry.cmdtype == CMDNORMAL &&
1001		    cmd->ncmd.redirect == NULL &&
1002		    varlist.count == 0 &&
1003		    (mode == FORK_FG || mode == FORK_NOJOB) &&
1004		    !disvforkset() && !iflag && !mflag) {
1005			vforkexecshell(jp, argv, environment(), path,
1006			    cmdentry.u.index, flags & EV_BACKCMD ? pip : NULL);
1007			goto parent;
1008		}
1009		if (forkshell(jp, cmd, mode) != 0)
1010			goto parent;	/* at end of routine */
1011		if (flags & EV_BACKCMD) {
1012			FORCEINTON;
1013			close(pip[0]);
1014			if (pip[1] != 1) {
1015				dup2(pip[1], 1);
1016				close(pip[1]);
1017			}
1018			flags &= ~EV_BACKCMD;
1019		}
1020		flags |= EV_EXIT;
1021	}
1022
1023	/* This is the child process if a fork occurred. */
1024	/* Execute the command. */
1025	if (cmdentry.cmdtype == CMDFUNCTION) {
1026#ifdef DEBUG
1027		trputs("Shell function:  ");  trargs(argv);
1028#endif
1029		saveparam = shellparam;
1030		shellparam.malloc = 0;
1031		shellparam.reset = 1;
1032		shellparam.nparam = argc - 1;
1033		shellparam.p = argv + 1;
1034		shellparam.optp = NULL;
1035		shellparam.optnext = NULL;
1036		INTOFF;
1037		savelocalvars = localvars;
1038		localvars = NULL;
1039		reffunc(cmdentry.u.func);
1040		savehandler = handler;
1041		if (setjmp(jmploc.loc)) {
1042			popredir();
1043			unreffunc(cmdentry.u.func);
1044			poplocalvars();
1045			localvars = savelocalvars;
1046			freeparam(&shellparam);
1047			shellparam = saveparam;
1048			funcnest--;
1049			handler = savehandler;
1050			longjmp(handler->loc, 1);
1051		}
1052		handler = &jmploc;
1053		funcnest++;
1054		redirect(cmd->ncmd.redirect, REDIR_PUSH);
1055		INTON;
1056		for (i = 0; i < varlist.count; i++)
1057			mklocal(varlist.args[i]);
1058		exitstatus = oexitstatus;
1059		evaltree(getfuncnode(cmdentry.u.func),
1060		    flags & (EV_TESTED | EV_EXIT));
1061		INTOFF;
1062		unreffunc(cmdentry.u.func);
1063		poplocalvars();
1064		localvars = savelocalvars;
1065		freeparam(&shellparam);
1066		shellparam = saveparam;
1067		handler = savehandler;
1068		funcnest--;
1069		popredir();
1070		INTON;
1071		if (evalskip == SKIPRETURN) {
1072			evalskip = 0;
1073			skipcount = 0;
1074		}
1075		if (jp)
1076			exitshell(exitstatus);
1077	} else if (cmdentry.cmdtype == CMDBUILTIN) {
1078#ifdef DEBUG
1079		trputs("builtin command:  ");  trargs(argv);
1080#endif
1081		mode = (cmdentry.u.index == EXECCMD)? 0 : REDIR_PUSH;
1082		if (flags == EV_BACKCMD) {
1083			memout.nleft = 0;
1084			memout.nextc = memout.buf;
1085			memout.bufsize = 64;
1086			mode |= REDIR_BACKQ;
1087		}
1088		savecmdname = commandname;
1089		savetopfile = getcurrentfile();
1090		cmdenviron = &varlist;
1091		e = -1;
1092		savehandler = handler;
1093		if (setjmp(jmploc.loc)) {
1094			e = exception;
1095			if (e == EXINT)
1096				exitstatus = SIGINT+128;
1097			else if (e != EXEXIT)
1098				exitstatus = 2;
1099			goto cmddone;
1100		}
1101		handler = &jmploc;
1102		redirect(cmd->ncmd.redirect, mode);
1103		outclearerror(out1);
1104		/*
1105		 * If there is no command word, redirection errors should
1106		 * not be fatal but assignment errors should.
1107		 */
1108		if (argc == 0)
1109			cmdentry.special = 1;
1110		listsetvar(cmdenviron, cmdentry.special ? 0 : VNOSET);
1111		if (argc > 0)
1112			bltinsetlocale();
1113		commandname = argv[0];
1114		argptr = argv + 1;
1115		nextopt_optptr = NULL;		/* initialize nextopt */
1116		builtin_flags = flags;
1117		exitstatus = (*builtinfunc[cmdentry.u.index])(argc, argv);
1118		flushall();
1119		if (outiserror(out1)) {
1120			warning("write error on stdout");
1121			if (exitstatus == 0 || exitstatus == 1)
1122				exitstatus = 2;
1123		}
1124cmddone:
1125		if (argc > 0)
1126			bltinunsetlocale();
1127		cmdenviron = NULL;
1128		out1 = &output;
1129		out2 = &errout;
1130		freestdout();
1131		handler = savehandler;
1132		commandname = savecmdname;
1133		if (jp)
1134			exitshell(exitstatus);
1135		if (flags == EV_BACKCMD) {
1136			backcmd->buf = memout.buf;
1137			backcmd->nleft = memout.nextc - memout.buf;
1138			memout.buf = NULL;
1139		}
1140		if (cmdentry.u.index != EXECCMD)
1141			popredir();
1142		if (e != -1) {
1143			if ((e != EXERROR && e != EXEXEC)
1144			    || cmdentry.special)
1145				exraise(e);
1146			popfilesupto(savetopfile);
1147			if (flags != EV_BACKCMD)
1148				FORCEINTON;
1149		}
1150	} else {
1151#ifdef DEBUG
1152		trputs("normal command:  ");  trargs(argv);
1153#endif
1154		redirect(cmd->ncmd.redirect, 0);
1155		for (i = 0; i < varlist.count; i++)
1156			setvareq(varlist.args[i], VEXPORT|VSTACK);
1157		envp = environment();
1158		shellexec(argv, envp, path, cmdentry.u.index);
1159		/*NOTREACHED*/
1160	}
1161	goto out;
1162
1163parent:	/* parent process gets here (if we forked) */
1164	if (mode == FORK_FG) {	/* argument to fork */
1165		INTOFF;
1166		exitstatus = waitforjob(jp, &realstatus);
1167		INTON;
1168		if (iflag && loopnest > 0 && WIFSIGNALED(realstatus)) {
1169			evalskip = SKIPBREAK;
1170			skipcount = loopnest;
1171		}
1172	} else if (mode == FORK_NOJOB) {
1173		backcmd->fd = pip[0];
1174		close(pip[1]);
1175		backcmd->jp = jp;
1176	}
1177
1178out:
1179	if (lastarg)
1180		setvar("_", lastarg, 0);
1181	if (do_clearcmdentry)
1182		clearcmdentry();
1183}
1184
1185
1186
1187/*
1188 * Search for a command.  This is called before we fork so that the
1189 * location of the command will be available in the parent as well as
1190 * the child.  The check for "goodname" is an overly conservative
1191 * check that the name will not be subject to expansion.
1192 */
1193
1194static void
1195prehash(union node *n)
1196{
1197	struct cmdentry entry;
1198
1199	if (n && n->type == NCMD && n->ncmd.args)
1200		if (goodname(n->ncmd.args->narg.text))
1201			find_command(n->ncmd.args->narg.text, &entry, 0,
1202				     pathval());
1203}
1204
1205
1206
1207/*
1208 * Builtin commands.  Builtin commands whose functions are closely
1209 * tied to evaluation are implemented here.
1210 */
1211
1212/*
1213 * No command given, a bltin command with no arguments, or a bltin command
1214 * with an invalid name.
1215 */
1216
1217int
1218bltincmd(int argc, char **argv)
1219{
1220	if (argc > 1) {
1221		out2fmt_flush("%s: not found\n", argv[1]);
1222		return 127;
1223	}
1224	/*
1225	 * Preserve exitstatus of a previous possible redirection
1226	 * as POSIX mandates
1227	 */
1228	return exitstatus;
1229}
1230
1231
1232/*
1233 * Handle break and continue commands.  Break, continue, and return are
1234 * all handled by setting the evalskip flag.  The evaluation routines
1235 * above all check this flag, and if it is set they start skipping
1236 * commands rather than executing them.  The variable skipcount is
1237 * the number of loops to break/continue, or the number of function
1238 * levels to return.  (The latter is always 1.)  It should probably
1239 * be an error to break out of more loops than exist, but it isn't
1240 * in the standard shell so we don't make it one here.
1241 */
1242
1243int
1244breakcmd(int argc, char **argv)
1245{
1246	long n;
1247	char *end;
1248
1249	if (argc > 1) {
1250		/* Allow arbitrarily large numbers. */
1251		n = strtol(argv[1], &end, 10);
1252		if (!is_digit(argv[1][0]) || *end != '\0')
1253			error("Illegal number: %s", argv[1]);
1254	} else
1255		n = 1;
1256	if (n > loopnest)
1257		n = loopnest;
1258	if (n > 0) {
1259		evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
1260		skipcount = n;
1261	}
1262	return 0;
1263}
1264
1265/*
1266 * The `command' command.
1267 */
1268int
1269commandcmd(int argc __unused, char **argv __unused)
1270{
1271	const char *path;
1272	int ch;
1273	int cmd = -1;
1274
1275	path = bltinlookup("PATH", 1);
1276
1277	while ((ch = nextopt("pvV")) != '\0') {
1278		switch (ch) {
1279		case 'p':
1280			path = _PATH_STDPATH;
1281			break;
1282		case 'v':
1283			cmd = TYPECMD_SMALLV;
1284			break;
1285		case 'V':
1286			cmd = TYPECMD_BIGV;
1287			break;
1288		}
1289	}
1290
1291	if (cmd != -1) {
1292		if (*argptr == NULL || argptr[1] != NULL)
1293			error("wrong number of arguments");
1294		return typecmd_impl(2, argptr - 1, cmd, path);
1295	}
1296	if (*argptr != NULL)
1297		error("commandcmd bad call");
1298
1299	/*
1300	 * Do nothing successfully if no command was specified;
1301	 * ksh also does this.
1302	 */
1303	return 0;
1304}
1305
1306
1307/*
1308 * The return command.
1309 */
1310
1311int
1312returncmd(int argc, char **argv)
1313{
1314	int ret = argc > 1 ? number(argv[1]) : oexitstatus;
1315
1316	evalskip = SKIPRETURN;
1317	skipcount = 1;
1318	return ret;
1319}
1320
1321
1322int
1323falsecmd(int argc __unused, char **argv __unused)
1324{
1325	return 1;
1326}
1327
1328
1329int
1330truecmd(int argc __unused, char **argv __unused)
1331{
1332	return 0;
1333}
1334
1335
1336int
1337execcmd(int argc, char **argv)
1338{
1339	int i;
1340
1341	/*
1342	 * Because we have historically not supported any options,
1343	 * only treat "--" specially.
1344	 */
1345	if (argc > 1 && strcmp(argv[1], "--") == 0)
1346		argc--, argv++;
1347	if (argc > 1) {
1348		iflag = 0;		/* exit on error */
1349		mflag = 0;
1350		optschanged();
1351		for (i = 0; i < cmdenviron->count; i++)
1352			setvareq(cmdenviron->args[i], VEXPORT|VSTACK);
1353		shellexec(argv + 1, environment(), pathval(), 0);
1354
1355	}
1356	return 0;
1357}
1358
1359
1360int
1361timescmd(int argc __unused, char **argv __unused)
1362{
1363	struct rusage ru;
1364	long shumins, shsmins, chumins, chsmins;
1365	double shusecs, shssecs, chusecs, chssecs;
1366
1367	if (getrusage(RUSAGE_SELF, &ru) < 0)
1368		return 1;
1369	shumins = ru.ru_utime.tv_sec / 60;
1370	shusecs = ru.ru_utime.tv_sec % 60 + ru.ru_utime.tv_usec / 1000000.;
1371	shsmins = ru.ru_stime.tv_sec / 60;
1372	shssecs = ru.ru_stime.tv_sec % 60 + ru.ru_stime.tv_usec / 1000000.;
1373	if (getrusage(RUSAGE_CHILDREN, &ru) < 0)
1374		return 1;
1375	chumins = ru.ru_utime.tv_sec / 60;
1376	chusecs = ru.ru_utime.tv_sec % 60 + ru.ru_utime.tv_usec / 1000000.;
1377	chsmins = ru.ru_stime.tv_sec / 60;
1378	chssecs = ru.ru_stime.tv_sec % 60 + ru.ru_stime.tv_usec / 1000000.;
1379	out1fmt("%ldm%.3fs %ldm%.3fs\n%ldm%.3fs %ldm%.3fs\n", shumins,
1380	    shusecs, shsmins, shssecs, chumins, chusecs, chsmins, chssecs);
1381	return 0;
1382}
1383