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