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