xref: /netbsd-src/bin/sh/eval.c (revision e89934bbf778a6d6d6894877c4da59d0c7835b0f)
1 /*	$NetBSD: eval.c,v 1.130 2017/02/02 19:26:37 christos Exp $	*/
2 
3 /*-
4  * Copyright (c) 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Kenneth Almquist.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 
35 #include <sys/cdefs.h>
36 #ifndef lint
37 #if 0
38 static char sccsid[] = "@(#)eval.c	8.9 (Berkeley) 6/8/95";
39 #else
40 __RCSID("$NetBSD: eval.c,v 1.130 2017/02/02 19:26:37 christos Exp $");
41 #endif
42 #endif /* not lint */
43 
44 #include <stdbool.h>
45 #include <stdlib.h>
46 #include <signal.h>
47 #include <stdio.h>
48 #include <string.h>
49 #include <errno.h>
50 #include <limits.h>
51 #include <unistd.h>
52 #include <sys/fcntl.h>
53 #include <sys/stat.h>
54 #include <sys/times.h>
55 #include <sys/param.h>
56 #include <sys/types.h>
57 #include <sys/wait.h>
58 #include <sys/sysctl.h>
59 
60 /*
61  * Evaluate a command.
62  */
63 
64 #include "shell.h"
65 #include "nodes.h"
66 #include "syntax.h"
67 #include "expand.h"
68 #include "parser.h"
69 #include "jobs.h"
70 #include "eval.h"
71 #include "builtins.h"
72 #include "options.h"
73 #include "exec.h"
74 #include "redir.h"
75 #include "input.h"
76 #include "output.h"
77 #include "trap.h"
78 #include "var.h"
79 #include "memalloc.h"
80 #include "error.h"
81 #include "show.h"
82 #include "mystring.h"
83 #include "main.h"
84 #ifndef SMALL
85 #include "nodenames.h"
86 #include "myhistedit.h"
87 #endif
88 
89 
90 STATIC enum skipstate evalskip;	/* != SKIPNONE if we are skipping commands */
91 STATIC int skipcount;		/* number of levels to skip */
92 STATIC int loopnest;		/* current loop nesting level */
93 STATIC int funcnest;		/* depth of function calls */
94 STATIC int builtin_flags;	/* evalcommand flags for builtins */
95 /*
96  * Base function nesting level inside a dot command.  Set to 0 initially
97  * and to (funcnest + 1) before every dot command to enable
98  *   1) detection of being in a file sourced by a dot command and
99  *   2) counting of function nesting in that file for the implementation
100  *      of the return command.
101  * The value is reset to its previous value after the dot command.
102  */
103 STATIC int dot_funcnest;
104 
105 
106 const char *commandname;
107 struct strlist *cmdenviron;
108 int exitstatus;			/* exit status of last command */
109 int back_exitstatus;		/* exit status of backquoted command */
110 
111 
112 STATIC void evalloop(union node *, int);
113 STATIC void evalfor(union node *, int);
114 STATIC void evalcase(union node *, int);
115 STATIC void evalsubshell(union node *, int);
116 STATIC void expredir(union node *);
117 STATIC void evalpipe(union node *);
118 STATIC void evalcommand(union node *, int, struct backcmd *);
119 STATIC void prehash(union node *);
120 
121 STATIC char *find_dot_file(char *);
122 
123 /*
124  * Called to reset things after an exception.
125  */
126 
127 #ifdef mkinit
128 INCLUDE "eval.h"
129 
130 RESET {
131 	reset_eval();
132 }
133 
134 SHELLPROC {
135 	exitstatus = 0;
136 }
137 #endif
138 
139 void
140 reset_eval(void)
141 {
142 	evalskip = SKIPNONE;
143 	dot_funcnest = 0;
144 	loopnest = 0;
145 	funcnest = 0;
146 }
147 
148 static int
149 sh_pipe(int fds[2])
150 {
151 	int nfd;
152 
153 	if (pipe(fds))
154 		return -1;
155 
156 	if (fds[0] < 3) {
157 		nfd = fcntl(fds[0], F_DUPFD, 3);
158 		if (nfd != -1) {
159 			close(fds[0]);
160 			fds[0] = nfd;
161 		}
162 	}
163 
164 	if (fds[1] < 3) {
165 		nfd = fcntl(fds[1], F_DUPFD, 3);
166 		if (nfd != -1) {
167 			close(fds[1]);
168 			fds[1] = nfd;
169 		}
170 	}
171 	return 0;
172 }
173 
174 
175 /*
176  * The eval commmand.
177  */
178 
179 int
180 evalcmd(int argc, char **argv)
181 {
182         char *p;
183         char *concat;
184         char **ap;
185 
186         if (argc > 1) {
187                 p = argv[1];
188                 if (argc > 2) {
189                         STARTSTACKSTR(concat);
190                         ap = argv + 2;
191                         for (;;) {
192                                 while (*p)
193                                         STPUTC(*p++, concat);
194                                 if ((p = *ap++) == NULL)
195                                         break;
196                                 STPUTC(' ', concat);
197                         }
198                         STPUTC('\0', concat);
199                         p = grabstackstr(concat);
200                 }
201                 evalstring(p, builtin_flags & EV_TESTED);
202         }
203         return exitstatus;
204 }
205 
206 
207 /*
208  * Execute a command or commands contained in a string.
209  */
210 
211 void
212 evalstring(char *s, int flag)
213 {
214 	union node *n;
215 	struct stackmark smark;
216 
217 	setstackmark(&smark);
218 	setinputstring(s, 1);
219 
220 	while ((n = parsecmd(0)) != NEOF) {
221 		TRACE(("evalstring: "); showtree(n));
222 		if (nflag == 0)
223 			evaltree(n, flag | EV_MORE);
224 		popstackmark(&smark);
225 	}
226 	popfile();
227 	popstackmark(&smark);
228 }
229 
230 
231 
232 /*
233  * Evaluate a parse tree.  The value is left in the global variable
234  * exitstatus.
235  */
236 
237 void
238 evaltree(union node *n, int flags)
239 {
240 	bool do_etest;
241 
242 	do_etest = false;
243 	if (n == NULL || nflag) {
244 		TRACE(("evaltree(%s) called\n", n == NULL ? "NULL" : "-n"));
245 		if (nflag == 0)
246 			exitstatus = 0;
247 		goto out;
248 	}
249 #ifndef SMALL
250 	displayhist = 1;	/* show history substitutions done with fc */
251 #endif
252 #ifdef NODETYPENAME
253 	TRACE(("pid %d, evaltree(%p: %s(%d), %#x) called\n",
254 	    getpid(), n, NODETYPENAME(n->type), n->type, flags));
255 #else
256 	TRACE(("pid %d, evaltree(%p: %d, %#x) called\n",
257 	    getpid(), n, n->type, flags));
258 #endif
259 	switch (n->type) {
260 	case NSEMI:
261 		evaltree(n->nbinary.ch1, (flags & EV_TESTED) |
262 		    (n->nbinary.ch2 ? EV_MORE : 0));
263 		if (nflag || evalskip)
264 			goto out;
265 		evaltree(n->nbinary.ch2, flags);
266 		break;
267 	case NAND:
268 		evaltree(n->nbinary.ch1, EV_TESTED | EV_MORE);
269 		if (nflag || evalskip || exitstatus != 0)
270 			goto out;
271 		evaltree(n->nbinary.ch2, flags);
272 		break;
273 	case NOR:
274 		evaltree(n->nbinary.ch1, EV_TESTED | EV_MORE);
275 		if (nflag || evalskip || exitstatus == 0)
276 			goto out;
277 		evaltree(n->nbinary.ch2, flags);
278 		break;
279 	case NREDIR:
280 		expredir(n->nredir.redirect);
281 		redirect(n->nredir.redirect, REDIR_PUSH | REDIR_KEEP);
282 		evaltree(n->nredir.n, flags);
283 		popredir();
284 		break;
285 	case NSUBSHELL:
286 		evalsubshell(n, flags & ~EV_MORE);
287 		do_etest = !(flags & EV_TESTED);
288 		break;
289 	case NBACKGND:
290 		evalsubshell(n, flags & ~EV_MORE);
291 		break;
292 	case NIF: {
293 		evaltree(n->nif.test, EV_TESTED | EV_MORE);
294 		if (nflag || evalskip)
295 			goto out;
296 		if (exitstatus == 0)
297 			evaltree(n->nif.ifpart, flags);
298 		else if (n->nif.elsepart)
299 			evaltree(n->nif.elsepart, flags);
300 		else
301 			exitstatus = 0;
302 		break;
303 	}
304 	case NWHILE:
305 	case NUNTIL:
306 		evalloop(n, flags);
307 		break;
308 	case NFOR:
309 		evalfor(n, flags);
310 		break;
311 	case NCASE:
312 		evalcase(n, flags);
313 		break;
314 	case NDEFUN:
315 		defun(n->narg.text, n->narg.next);
316 		exitstatus = 0;
317 		break;
318 	case NNOT:
319 		evaltree(n->nnot.com, (flags & EV_MORE) | EV_TESTED);
320 		exitstatus = !exitstatus;
321 		break;
322 	case NPIPE:
323 		evalpipe(n);
324 		do_etest = !(flags & EV_TESTED);
325 		break;
326 	case NCMD:
327 		evalcommand(n, flags, NULL);
328 		do_etest = !(flags & EV_TESTED);
329 		break;
330 	default:
331 #ifdef NODETYPENAME
332 		out1fmt("Node type = %d(%s)\n", n->type, NODETYPENAME(n->type));
333 #else
334 		out1fmt("Node type = %d\n", n->type);
335 #endif
336 		flushout(&output);
337 		break;
338 	}
339 out:
340 	if (pendingsigs)
341 		dotrap();
342 	if ((flags & EV_EXIT) != 0 || (eflag && exitstatus != 0 && do_etest))
343 		exitshell(exitstatus);
344 }
345 
346 
347 STATIC void
348 evalloop(union node *n, int flags)
349 {
350 	int status;
351 
352 	loopnest++;
353 	status = 0;
354 
355 #ifdef NODETYPENAME
356 	TRACE(("evalloop %s: ", NODETYPENAME(n->type)));
357 #else
358 	TRACE(("evalloop %s: ", n->type == NWHILE ? "while" : "until"));
359 #endif
360 	TRACE((""); showtree(n->nbinary.ch1));
361 	TRACE(("evalloop    do: "); showtree(n->nbinary.ch2));
362 	TRACE(("evalloop  done\n"));
363 
364 	for (;;) {
365 		evaltree(n->nbinary.ch1, EV_TESTED | EV_MORE);
366 		if (nflag)
367 			break;
368 		if (evalskip) {
369 skipping:	  if (evalskip == SKIPCONT && --skipcount <= 0) {
370 				evalskip = SKIPNONE;
371 				continue;
372 			}
373 			if (evalskip == SKIPBREAK && --skipcount <= 0)
374 				evalskip = SKIPNONE;
375 			break;
376 		}
377 		if (n->type == NWHILE) {
378 			if (exitstatus != 0)
379 				break;
380 		} else {
381 			if (exitstatus == 0)
382 				break;
383 		}
384 		evaltree(n->nbinary.ch2, (flags & EV_TESTED) | EV_MORE);
385 		status = exitstatus;
386 		if (evalskip)
387 			goto skipping;
388 	}
389 	loopnest--;
390 	exitstatus = status;
391 }
392 
393 
394 
395 STATIC void
396 evalfor(union node *n, int flags)
397 {
398 	struct arglist arglist;
399 	union node *argp;
400 	struct strlist *sp;
401 	struct stackmark smark;
402 	int status;
403 
404 	status = nflag ? exitstatus : 0;
405 
406 	setstackmark(&smark);
407 	arglist.lastp = &arglist.list;
408 	for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
409 		expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
410 		if (evalskip)
411 			goto out;
412 	}
413 	*arglist.lastp = NULL;
414 
415 	loopnest++;
416 	for (sp = arglist.list ; sp ; sp = sp->next) {
417 		int f = flags & (EV_TESTED | EV_MORE);
418 
419 		if (sp->next)
420 			f |= EV_MORE;
421 
422 		setvar(n->nfor.var, sp->text, 0);
423 		evaltree(n->nfor.body, f);
424 		status = exitstatus;
425 		if (nflag)
426 			break;
427 		if (evalskip) {
428 			if (evalskip == SKIPCONT && --skipcount <= 0) {
429 				evalskip = SKIPNONE;
430 				continue;
431 			}
432 			if (evalskip == SKIPBREAK && --skipcount <= 0)
433 				evalskip = SKIPNONE;
434 			break;
435 		}
436 	}
437 	loopnest--;
438 	exitstatus = status;
439 out:
440 	popstackmark(&smark);
441 }
442 
443 
444 
445 STATIC void
446 evalcase(union node *n, int flags)
447 {
448 	union node *cp;
449 	union node *patp;
450 	struct arglist arglist;
451 	struct stackmark smark;
452 	int status = 0;
453 
454 	setstackmark(&smark);
455 	arglist.lastp = &arglist.list;
456 	expandarg(n->ncase.expr, &arglist, EXP_TILDE);
457 	for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
458 		for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
459 			if (casematch(patp, arglist.list->text)) {
460 				if (evalskip == 0) {
461 					evaltree(cp->nclist.body, flags);
462 					status = exitstatus;
463 				}
464 				goto out;
465 			}
466 		}
467 	}
468 out:
469 	exitstatus = status;
470 	popstackmark(&smark);
471 }
472 
473 
474 
475 /*
476  * Kick off a subshell to evaluate a tree.
477  */
478 
479 STATIC void
480 evalsubshell(union node *n, int flags)
481 {
482 	struct job *jp;
483 	int backgnd = (n->type == NBACKGND);
484 
485 	expredir(n->nredir.redirect);
486 	INTOFF;
487 	jp = makejob(n, 1);
488 	if (forkshell(jp, n, backgnd ? FORK_BG : FORK_FG) == 0) {
489 		INTON;
490 		if (backgnd)
491 			flags &=~ EV_TESTED;
492 		redirect(n->nredir.redirect, REDIR_KEEP);
493 		/* never returns */
494 		evaltree(n->nredir.n, flags | EV_EXIT);
495 	}
496 	exitstatus = backgnd ? 0 : waitforjob(jp);
497 	INTON;
498 }
499 
500 
501 
502 /*
503  * Compute the names of the files in a redirection list.
504  */
505 
506 STATIC void
507 expredir(union node *n)
508 {
509 	union node *redir;
510 
511 	for (redir = n ; redir ; redir = redir->nfile.next) {
512 		struct arglist fn;
513 
514 		fn.lastp = &fn.list;
515 		switch (redir->type) {
516 		case NFROMTO:
517 		case NFROM:
518 		case NTO:
519 		case NCLOBBER:
520 		case NAPPEND:
521 			expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
522 			redir->nfile.expfname = fn.list->text;
523 			break;
524 		case NFROMFD:
525 		case NTOFD:
526 			if (redir->ndup.vname) {
527 				expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
528 				fixredir(redir, fn.list->text, 1);
529 			}
530 			break;
531 		}
532 	}
533 }
534 
535 
536 
537 /*
538  * Evaluate a pipeline.  All the processes in the pipeline are children
539  * of the process creating the pipeline.  (This differs from some versions
540  * of the shell, which make the last process in a pipeline the parent
541  * of all the rest.)
542  */
543 
544 STATIC void
545 evalpipe(union node *n)
546 {
547 	struct job *jp;
548 	struct nodelist *lp;
549 	int pipelen;
550 	int prevfd;
551 	int pip[2];
552 
553 	TRACE(("evalpipe(0x%lx) called\n", (long)n));
554 	pipelen = 0;
555 	for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
556 		pipelen++;
557 	INTOFF;
558 	jp = makejob(n, pipelen);
559 	prevfd = -1;
560 	for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
561 		prehash(lp->n);
562 		pip[1] = -1;
563 		if (lp->next) {
564 			if (sh_pipe(pip) < 0) {
565 				if (prevfd >= 0)
566 					close(prevfd);
567 				error("Pipe call failed");
568 			}
569 		}
570 		if (forkshell(jp, lp->n, n->npipe.backgnd ? FORK_BG : FORK_FG) == 0) {
571 			INTON;
572 			if (prevfd > 0)
573 				movefd(prevfd, 0);
574 			if (pip[1] >= 0) {
575 				close(pip[0]);
576 				movefd(pip[1], 1);
577 			}
578 			evaltree(lp->n, EV_EXIT);
579 		}
580 		if (prevfd >= 0)
581 			close(prevfd);
582 		prevfd = pip[0];
583 		close(pip[1]);
584 	}
585 	if (n->npipe.backgnd == 0) {
586 		exitstatus = waitforjob(jp);
587 		TRACE(("evalpipe:  job done exit status %d\n", exitstatus));
588 	} else
589 		exitstatus = 0;
590 	INTON;
591 }
592 
593 
594 
595 /*
596  * Execute a command inside back quotes.  If it's a builtin command, we
597  * want to save its output in a block obtained from malloc.  Otherwise
598  * we fork off a subprocess and get the output of the command via a pipe.
599  * Should be called with interrupts off.
600  */
601 
602 void
603 evalbackcmd(union node *n, struct backcmd *result)
604 {
605 	int pip[2];
606 	struct job *jp;
607 	struct stackmark smark;		/* unnecessary */
608 
609 	setstackmark(&smark);
610 	result->fd = -1;
611 	result->buf = NULL;
612 	result->nleft = 0;
613 	result->jp = NULL;
614 	if (nflag || n == NULL) {
615 		goto out;
616 	}
617 #ifdef notyet
618 	/*
619 	 * For now we disable executing builtins in the same
620 	 * context as the shell, because we are not keeping
621 	 * enough state to recover from changes that are
622 	 * supposed only to affect subshells. eg. echo "`cd /`"
623 	 */
624 	if (n->type == NCMD) {
625 		exitstatus = oexitstatus;
626 		evalcommand(n, EV_BACKCMD, result);
627 	} else
628 #endif
629 	{
630 		INTOFF;
631 		if (sh_pipe(pip) < 0)
632 			error("Pipe call failed");
633 		jp = makejob(n, 1);
634 		if (forkshell(jp, n, FORK_NOJOB) == 0) {
635 			FORCEINTON;
636 			close(pip[0]);
637 			movefd(pip[1], 1);
638 			eflag = 0;
639 			evaltree(n, EV_EXIT);
640 			/* NOTREACHED */
641 		}
642 		close(pip[1]);
643 		result->fd = pip[0];
644 		result->jp = jp;
645 		INTON;
646 	}
647 out:
648 	popstackmark(&smark);
649 	TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
650 		result->fd, result->buf, result->nleft, result->jp));
651 }
652 
653 static const char *
654 syspath(void)
655 {
656 	static char *sys_path = NULL;
657 	static int mib[] = {CTL_USER, USER_CS_PATH};
658 	static char def_path[] = "PATH=/usr/bin:/bin:/usr/sbin:/sbin";
659 	size_t len;
660 
661 	if (sys_path == NULL) {
662 		if (sysctl(mib, 2, 0, &len, 0, 0) != -1 &&
663 		    (sys_path = ckmalloc(len + 5)) != NULL &&
664 		    sysctl(mib, 2, sys_path + 5, &len, 0, 0) != -1) {
665 			memcpy(sys_path, "PATH=", 5);
666 		} else {
667 			ckfree(sys_path);
668 			/* something to keep things happy */
669 			sys_path = def_path;
670 		}
671 	}
672 	return sys_path;
673 }
674 
675 static int
676 parse_command_args(int argc, char **argv, int *use_syspath)
677 {
678 	int sv_argc = argc;
679 	char *cp, c;
680 
681 	*use_syspath = 0;
682 
683 	for (;;) {
684 		argv++;
685 		if (--argc == 0)
686 			break;
687 		cp = *argv;
688 		if (*cp++ != '-')
689 			break;
690 		if (*cp == '-' && cp[1] == 0) {
691 			argv++;
692 			argc--;
693 			break;
694 		}
695 		while ((c = *cp++)) {
696 			switch (c) {
697 			case 'p':
698 				*use_syspath = 1;
699 				break;
700 			default:
701 				/* run 'typecmd' for other options */
702 				return 0;
703 			}
704 		}
705 	}
706 	return sv_argc - argc;
707 }
708 
709 int vforked = 0;
710 extern char *trap[];
711 
712 /*
713  * Execute a simple command.
714  */
715 
716 STATIC void
717 evalcommand(union node *cmd, int flgs, struct backcmd *backcmd)
718 {
719 	struct stackmark smark;
720 	union node *argp;
721 	struct arglist arglist;
722 	struct arglist varlist;
723 	volatile int flags = flgs;
724 	char ** volatile argv;
725 	volatile int argc;
726 	char **envp;
727 	int varflag;
728 	struct strlist *sp;
729 	volatile int mode;
730 	int pip[2];
731 	struct cmdentry cmdentry;
732 	struct job * volatile jp;
733 	struct jmploc jmploc;
734 	struct jmploc *volatile savehandler = NULL;
735 	const char *volatile savecmdname;
736 	volatile struct shparam saveparam;
737 	struct localvar *volatile savelocalvars;
738 	volatile int e;
739 	char * volatile lastarg;
740 	const char * volatile path = pathval();
741 	volatile int temp_path;
742 
743 	vforked = 0;
744 	/* First expand the arguments. */
745 	TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
746 	setstackmark(&smark);
747 	back_exitstatus = 0;
748 
749 	arglist.lastp = &arglist.list;
750 	varflag = 1;
751 	/* Expand arguments, ignoring the initial 'name=value' ones */
752 	for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
753 		char *p = argp->narg.text;
754 		if (varflag && is_name(*p)) {
755 			do {
756 				p++;
757 			} while (is_in_name(*p));
758 			if (*p == '=')
759 				continue;
760 		}
761 		expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
762 		varflag = 0;
763 	}
764 	*arglist.lastp = NULL;
765 
766 	expredir(cmd->ncmd.redirect);
767 
768 	/* Now do the initial 'name=value' ones we skipped above */
769 	varlist.lastp = &varlist.list;
770 	for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
771 		char *p = argp->narg.text;
772 		if (!is_name(*p))
773 			break;
774 		do
775 			p++;
776 		while (is_in_name(*p));
777 		if (*p != '=')
778 			break;
779 		expandarg(argp, &varlist, EXP_VARTILDE);
780 	}
781 	*varlist.lastp = NULL;
782 
783 	argc = 0;
784 	for (sp = arglist.list ; sp ; sp = sp->next)
785 		argc++;
786 	argv = stalloc(sizeof (char *) * (argc + 1));
787 
788 	for (sp = arglist.list ; sp ; sp = sp->next) {
789 		TRACE(("evalcommand arg: %s\n", sp->text));
790 		*argv++ = sp->text;
791 	}
792 	*argv = NULL;
793 	lastarg = NULL;
794 	if (iflag && funcnest == 0 && argc > 0)
795 		lastarg = argv[-1];
796 	argv -= argc;
797 
798 	/* Print the command if xflag is set. */
799 	if (xflag) {
800 		char sep = 0;
801 		out2str(ps4val());
802 		for (sp = varlist.list ; sp ; sp = sp->next) {
803 			char *p;
804 
805 			if (sep != 0)
806 				outc(sep, &errout);
807 
808 			/*
809 			 * The "var=" part should not be quoted, regardless
810 			 * of the value, or it would not represent an
811 			 * assignment, but rather a command
812 			 */
813 			p = strchr(sp->text, '=');
814 			if (p != NULL) {
815 				*p = '\0';	/*XXX*/
816 				out2shstr(sp->text);
817 				out2c('=');
818 				*p++ = '=';	/*XXX*/
819 			} else
820 				p = sp->text;
821 			out2shstr(p);
822 			sep = ' ';
823 		}
824 		for (sp = arglist.list ; sp ; sp = sp->next) {
825 			if (sep != 0)
826 				outc(sep, &errout);
827 			out2shstr(sp->text);
828 			sep = ' ';
829 		}
830 		outc('\n', &errout);
831 		flushout(&errout);
832 	}
833 
834 	/* Now locate the command. */
835 	if (argc == 0) {
836 		cmdentry.cmdtype = CMDSPLBLTIN;
837 		cmdentry.u.bltin = bltincmd;
838 	} else {
839 		static const char PATH[] = "PATH=";
840 		int cmd_flags = DO_ERR;
841 
842 		/*
843 		 * Modify the command lookup path, if a PATH= assignment
844 		 * is present
845 		 */
846 		for (sp = varlist.list; sp; sp = sp->next)
847 			if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0)
848 				path = sp->text + sizeof(PATH) - 1;
849 
850 		do {
851 			int argsused, use_syspath;
852 			find_command(argv[0], &cmdentry, cmd_flags, path);
853 			if (cmdentry.cmdtype == CMDUNKNOWN) {
854 				exitstatus = 127;
855 				flushout(&errout);
856 				goto out;
857 			}
858 
859 			/* implement the 'command' builtin here */
860 			if (cmdentry.cmdtype != CMDBUILTIN ||
861 			    cmdentry.u.bltin != bltincmd)
862 				break;
863 			cmd_flags |= DO_NOFUNC;
864 			argsused = parse_command_args(argc, argv, &use_syspath);
865 			if (argsused == 0) {
866 				/* use 'type' builting to display info */
867 				cmdentry.u.bltin = typecmd;
868 				break;
869 			}
870 			argc -= argsused;
871 			argv += argsused;
872 			if (use_syspath)
873 				path = syspath() + 5;
874 		} while (argc != 0);
875 		if (cmdentry.cmdtype == CMDSPLBLTIN && cmd_flags & DO_NOFUNC)
876 			/* posix mandates that 'command <splbltin>' act as if
877 			   <splbltin> was a normal builtin */
878 			cmdentry.cmdtype = CMDBUILTIN;
879 	}
880 
881 	/* Fork off a child process if necessary. */
882 	if (cmd->ncmd.backgnd || (trap[0] && (flags & EV_EXIT) != 0)
883 	 || (cmdentry.cmdtype == CMDNORMAL && (flags & EV_EXIT) == 0)
884 	 || ((flags & EV_BACKCMD) != 0
885 	    && ((cmdentry.cmdtype != CMDBUILTIN && cmdentry.cmdtype != CMDSPLBLTIN)
886 		 || cmdentry.u.bltin == dotcmd
887 		 || cmdentry.u.bltin == evalcmd))) {
888 		INTOFF;
889 		jp = makejob(cmd, 1);
890 		mode = cmd->ncmd.backgnd;
891 		if (mode)
892 			flags &= ~EV_MORE;
893 		if (flags & EV_BACKCMD) {
894 			mode = FORK_NOJOB;
895 			if (sh_pipe(pip) < 0)
896 				error("Pipe call failed");
897 		}
898 #ifdef DO_SHAREDVFORK
899 		/* It is essential that if DO_SHAREDVFORK is defined that the
900 		 * child's address space is actually shared with the parent as
901 		 * we rely on this.
902 		 */
903 		if (usefork == 0 && cmdentry.cmdtype == CMDNORMAL) {
904 			pid_t	pid;
905 			int serrno;
906 
907 			savelocalvars = localvars;
908 			localvars = NULL;
909 			vforked = 1;
910 			switch (pid = vfork()) {
911 			case -1:
912 				serrno = errno;
913 				TRACE(("Vfork failed, errno=%d\n", serrno));
914 				INTON;
915 				error("Cannot vfork (%s)", strerror(serrno));
916 				break;
917 			case 0:
918 				/* Make sure that exceptions only unwind to
919 				 * after the vfork(2)
920 				 */
921 				if (setjmp(jmploc.loc)) {
922 					if (exception == EXSHELLPROC) {
923 						/* We can't progress with the vfork,
924 						 * so, set vforked = 2 so the parent
925 						 * knows, and _exit();
926 						 */
927 						vforked = 2;
928 						_exit(0);
929 					} else {
930 						_exit(exerrno);
931 					}
932 				}
933 				savehandler = handler;
934 				handler = &jmploc;
935 				listmklocal(varlist.list, VEXPORT | VNOFUNC);
936 				forkchild(jp, cmd, mode, vforked);
937 				break;
938 			default:
939 				handler = savehandler;	/* restore from vfork(2) */
940 				poplocalvars();
941 				localvars = savelocalvars;
942 				if (vforked == 2) {
943 					vforked = 0;
944 
945 					(void)waitpid(pid, NULL, 0);
946 					/* We need to progress in a normal fork fashion */
947 					goto normal_fork;
948 				}
949 				vforked = 0;
950 				forkparent(jp, cmd, mode, pid);
951 				goto parent;
952 			}
953 		} else {
954 normal_fork:
955 #endif
956 			if (forkshell(jp, cmd, mode) != 0)
957 				goto parent;	/* at end of routine */
958 			FORCEINTON;
959 #ifdef DO_SHAREDVFORK
960 		}
961 #endif
962 		if (flags & EV_BACKCMD) {
963 			if (!vforked) {
964 				FORCEINTON;
965 			}
966 			close(pip[0]);
967 			movefd(pip[1], 1);
968 		}
969 		flags |= EV_EXIT;
970 	}
971 
972 	/* This is the child process if a fork occurred. */
973 	/* Execute the command. */
974 	switch (cmdentry.cmdtype) {
975 	case CMDFUNCTION:
976 #ifdef DEBUG
977 		trputs("Shell function:  ");  trargs(argv);
978 #endif
979 		redirect(cmd->ncmd.redirect, flags & EV_MORE ? REDIR_PUSH : 0);
980 		saveparam = shellparam;
981 		shellparam.malloc = 0;
982 		shellparam.reset = 1;
983 		shellparam.nparam = argc - 1;
984 		shellparam.p = argv + 1;
985 		shellparam.optnext = NULL;
986 		INTOFF;
987 		savelocalvars = localvars;
988 		localvars = NULL;
989 		INTON;
990 		if (setjmp(jmploc.loc)) {
991 			if (exception == EXSHELLPROC) {
992 				freeparam((volatile struct shparam *)
993 				    &saveparam);
994 			} else {
995 				freeparam(&shellparam);
996 				shellparam = saveparam;
997 			}
998 			poplocalvars();
999 			localvars = savelocalvars;
1000 			handler = savehandler;
1001 			longjmp(handler->loc, 1);
1002 		}
1003 		savehandler = handler;
1004 		handler = &jmploc;
1005 		listmklocal(varlist.list, VEXPORT);
1006 		/* stop shell blowing its stack */
1007 		if (++funcnest > 1000)
1008 			error("too many nested function calls");
1009 		evaltree(cmdentry.u.func, flags & EV_TESTED);
1010 		funcnest--;
1011 		INTOFF;
1012 		poplocalvars();
1013 		localvars = savelocalvars;
1014 		freeparam(&shellparam);
1015 		shellparam = saveparam;
1016 		handler = savehandler;
1017 		if (flags & EV_MORE)
1018 			popredir();
1019 		INTON;
1020 		if (evalskip == SKIPFUNC) {
1021 			evalskip = SKIPNONE;
1022 			skipcount = 0;
1023 		}
1024 		if (flags & EV_EXIT)
1025 			exitshell(exitstatus);
1026 		break;
1027 
1028 	case CMDBUILTIN:
1029 	case CMDSPLBLTIN:
1030 #ifdef DEBUG
1031 		trputs("builtin command:  ");  trargs(argv);
1032 #endif
1033 		mode = (cmdentry.u.bltin == execcmd) ? 0 : REDIR_PUSH;
1034 		if (flags == EV_BACKCMD) {
1035 			memout.nleft = 0;
1036 			memout.nextc = memout.buf;
1037 			memout.bufsize = 64;
1038 			mode |= REDIR_BACKQ;
1039 		}
1040 		e = -1;
1041 		savehandler = handler;
1042 		savecmdname = commandname;
1043 		handler = &jmploc;
1044 		temp_path = 0;
1045 		if (!setjmp(jmploc.loc)) {
1046 			/* We need to ensure the command hash table isn't
1047 			 * corrupted by temporary PATH assignments.
1048 			 * However we must ensure the 'local' command works!
1049 			 */
1050 			if (path != pathval() && (cmdentry.u.bltin == hashcmd ||
1051 			    cmdentry.u.bltin == typecmd)) {
1052 				savelocalvars = localvars;
1053 				localvars = 0;
1054 				temp_path = 1;
1055 				mklocal(path - 5 /* PATH= */, 0);
1056 			}
1057 			redirect(cmd->ncmd.redirect, mode);
1058 
1059 			/* exec is a special builtin, but needs this list... */
1060 			cmdenviron = varlist.list;
1061 			/* we must check 'readonly' flag for all builtins */
1062 			listsetvar(varlist.list,
1063 				cmdentry.cmdtype == CMDSPLBLTIN ? 0 : VNOSET);
1064 			commandname = argv[0];
1065 			/* initialize nextopt */
1066 			argptr = argv + 1;
1067 			optptr = NULL;
1068 			/* and getopt */
1069 			optreset = 1;
1070 			optind = 1;
1071 			builtin_flags = flags;
1072 			exitstatus = cmdentry.u.bltin(argc, argv);
1073 		} else {
1074 			e = exception;
1075 			exitstatus = e == EXINT ? SIGINT + 128 :
1076 					e == EXEXEC ? exerrno : 2;
1077 		}
1078 		handler = savehandler;
1079 		flushall();
1080 		out1 = &output;
1081 		out2 = &errout;
1082 		freestdout();
1083 		if (temp_path) {
1084 			poplocalvars();
1085 			localvars = savelocalvars;
1086 		}
1087 		cmdenviron = NULL;
1088 		if (e != EXSHELLPROC) {
1089 			commandname = savecmdname;
1090 			if (flags & EV_EXIT)
1091 				exitshell(exitstatus);
1092 		}
1093 		if (e != -1) {
1094 			if ((e != EXERROR && e != EXEXEC)
1095 			    || cmdentry.cmdtype == CMDSPLBLTIN)
1096 				exraise(e);
1097 			FORCEINTON;
1098 		}
1099 		if (cmdentry.u.bltin != execcmd)
1100 			popredir();
1101 		if (flags == EV_BACKCMD) {
1102 			backcmd->buf = memout.buf;
1103 			backcmd->nleft = memout.nextc - memout.buf;
1104 			memout.buf = NULL;
1105 		}
1106 		break;
1107 
1108 	default:
1109 #ifdef DEBUG
1110 		trputs("normal command:  ");  trargs(argv);
1111 #endif
1112 		redirect(cmd->ncmd.redirect,
1113 		    (vforked ? REDIR_VFORK : 0) | REDIR_KEEP);
1114 		if (!vforked)
1115 			for (sp = varlist.list ; sp ; sp = sp->next)
1116 				setvareq(sp->text, VEXPORT|VSTACK);
1117 		envp = environment();
1118 		shellexec(argv, envp, path, cmdentry.u.index, vforked);
1119 		break;
1120 	}
1121 	goto out;
1122 
1123 parent:	/* parent process gets here (if we forked) */
1124 	exitstatus = 0;		/* if not altered just below */
1125 	if (mode == FORK_FG) {	/* argument to fork */
1126 		exitstatus = waitforjob(jp);
1127 	} else if (mode == FORK_NOJOB) {
1128 		backcmd->fd = pip[0];
1129 		close(pip[1]);
1130 		backcmd->jp = jp;
1131 	}
1132 	FORCEINTON;
1133 
1134 out:
1135 	if (lastarg)
1136 		/* dsl: I think this is intended to be used to support
1137 		 * '_' in 'vi' command mode during line editing...
1138 		 * However I implemented that within libedit itself.
1139 		 */
1140 		setvar("_", lastarg, 0);
1141 	popstackmark(&smark);
1142 }
1143 
1144 
1145 /*
1146  * Search for a command.  This is called before we fork so that the
1147  * location of the command will be available in the parent as well as
1148  * the child.  The check for "goodname" is an overly conservative
1149  * check that the name will not be subject to expansion.
1150  */
1151 
1152 STATIC void
1153 prehash(union node *n)
1154 {
1155 	struct cmdentry entry;
1156 
1157 	if (n && n->type == NCMD && n->ncmd.args)
1158 		if (goodname(n->ncmd.args->narg.text))
1159 			find_command(n->ncmd.args->narg.text, &entry, 0,
1160 				     pathval());
1161 }
1162 
1163 int
1164 in_function(void)
1165 {
1166 	return funcnest;
1167 }
1168 
1169 enum skipstate
1170 current_skipstate(void)
1171 {
1172 	return evalskip;
1173 }
1174 
1175 void
1176 stop_skipping(void)
1177 {
1178 	evalskip = SKIPNONE;
1179 	skipcount = 0;
1180 }
1181 
1182 /*
1183  * Builtin commands.  Builtin commands whose functions are closely
1184  * tied to evaluation are implemented here.
1185  */
1186 
1187 /*
1188  * No command given.
1189  */
1190 
1191 int
1192 bltincmd(int argc, char **argv)
1193 {
1194 	/*
1195 	 * Preserve exitstatus of a previous possible redirection
1196 	 * as POSIX mandates
1197 	 */
1198 	return back_exitstatus;
1199 }
1200 
1201 
1202 /*
1203  * Handle break and continue commands.  Break, continue, and return are
1204  * all handled by setting the evalskip flag.  The evaluation routines
1205  * above all check this flag, and if it is set they start skipping
1206  * commands rather than executing them.  The variable skipcount is
1207  * the number of loops to break/continue, or the number of function
1208  * levels to return.  (The latter is always 1.)  It should probably
1209  * be an error to break out of more loops than exist, but it isn't
1210  * in the standard shell so we don't make it one here.
1211  */
1212 
1213 int
1214 breakcmd(int argc, char **argv)
1215 {
1216 	int n = argc > 1 ? number(argv[1]) : 1;
1217 
1218 	if (n > loopnest)
1219 		n = loopnest;
1220 	if (n > 0) {
1221 		evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
1222 		skipcount = n;
1223 	}
1224 	return 0;
1225 }
1226 
1227 int
1228 dotcmd(int argc, char **argv)
1229 {
1230 	exitstatus = 0;
1231 
1232 	if (argc >= 2) {		/* That's what SVR2 does */
1233 		char *fullname;
1234 		/*
1235 		 * dot_funcnest needs to be 0 when not in a dotcmd, so it
1236 		 * cannot be restored with (funcnest + 1).
1237 		 */
1238 		int dot_funcnest_old;
1239 		struct stackmark smark;
1240 
1241 		setstackmark(&smark);
1242 		fullname = find_dot_file(argv[1]);
1243 		setinputfile(fullname, 1);
1244 		commandname = fullname;
1245 		dot_funcnest_old = dot_funcnest;
1246 		dot_funcnest = funcnest + 1;
1247 		cmdloop(0);
1248 		dot_funcnest = dot_funcnest_old;
1249 		popfile();
1250 		popstackmark(&smark);
1251 	}
1252 	return exitstatus;
1253 }
1254 
1255 /*
1256  * Take commands from a file.  To be compatible we should do a path
1257  * search for the file, which is necessary to find sub-commands.
1258  */
1259 
1260 STATIC char *
1261 find_dot_file(char *basename)
1262 {
1263 	char *fullname;
1264 	const char *path = pathval();
1265 	struct stat statb;
1266 
1267 	/* don't try this for absolute or relative paths */
1268 	if (strchr(basename, '/')) {
1269 		if (stat(basename, &statb) == 0) {
1270 			if (S_ISDIR(statb.st_mode))
1271 				error("%s: is a directory", basename);
1272 			if (S_ISBLK(statb.st_mode))
1273 				error("%s: is a block device", basename);
1274 			return basename;
1275 		}
1276 	} else while ((fullname = padvance(&path, basename)) != NULL) {
1277 		if ((stat(fullname, &statb) == 0)) {
1278 			/* weird format is to ease future code... */
1279 			if (S_ISDIR(statb.st_mode) || S_ISBLK(statb.st_mode))
1280 				;
1281 #if notyet
1282 			else if (unreadable()) {
1283 				/*
1284 				 * testing this via st_mode is ugly to get
1285 				 * correct (and would ignore ACLs).
1286 				 * better way is just to open the file.
1287 				 * But doing that here would (currently)
1288 				 * mean opening the file twice, which
1289 				 * might not be safe.  So, defer this
1290 				 * test until code is restructures so
1291 				 * we can return a fd.   Then we also
1292 				 * get to fix the mem leak just below...
1293 				 */
1294 			}
1295 #endif
1296 			else {
1297 				/*
1298 				 * Don't bother freeing here, since
1299 				 * it will be freed by the caller.
1300 				 * XXX no it won't - a bug for later.
1301 				 */
1302 				return fullname;
1303 			}
1304 		}
1305 		stunalloc(fullname);
1306 	}
1307 
1308 	/* not found in the PATH */
1309 	error("%s: not found", basename);
1310 	/* NOTREACHED */
1311 }
1312 
1313 
1314 
1315 /*
1316  * The return command.
1317  *
1318  * Quoth the POSIX standard:
1319  *   The return utility shall cause the shell to stop executing the current
1320  *   function or dot script. If the shell is not currently executing
1321  *   a function or dot script, the results are unspecified.
1322  *
1323  * As for the unspecified part, there seems to be no de-facto standard: bash
1324  * ignores the return with a warning, zsh ignores the return in interactive
1325  * mode but seems to liken it to exit in a script.  (checked May 2014)
1326  *
1327  * We choose to silently ignore the return.  Older versions of this shell
1328  * set evalskip to SKIPFILE causing the shell to (indirectly) exit.  This
1329  * had at least the problem of circumventing the check for stopped jobs,
1330  * which would occur for exit or ^D.
1331  */
1332 
1333 int
1334 returncmd(int argc, char **argv)
1335 {
1336 	int ret = argc > 1 ? number(argv[1]) : exitstatus;
1337 
1338 	if ((dot_funcnest == 0 && funcnest)
1339 	    || (dot_funcnest > 0 && funcnest - (dot_funcnest - 1) > 0)) {
1340 		evalskip = SKIPFUNC;
1341 		skipcount = 1;
1342 	} else if (dot_funcnest > 0) {
1343 		evalskip = SKIPFILE;
1344 		skipcount = 1;
1345 	} else {
1346 		/* XXX: should a warning be issued? */
1347 		ret = 0;
1348 	}
1349 
1350 	return ret;
1351 }
1352 
1353 
1354 int
1355 falsecmd(int argc, char **argv)
1356 {
1357 	return 1;
1358 }
1359 
1360 
1361 int
1362 truecmd(int argc, char **argv)
1363 {
1364 	return 0;
1365 }
1366 
1367 
1368 int
1369 execcmd(int argc, char **argv)
1370 {
1371 	if (argc > 1) {
1372 		struct strlist *sp;
1373 
1374 		iflag = 0;		/* exit on error */
1375 		mflag = 0;
1376 		optschanged();
1377 		for (sp = cmdenviron; sp; sp = sp->next)
1378 			setvareq(sp->text, VEXPORT|VSTACK);
1379 		shellexec(argv + 1, environment(), pathval(), 0, 0);
1380 	}
1381 	return 0;
1382 }
1383 
1384 static int
1385 conv_time(clock_t ticks, char *seconds, size_t l)
1386 {
1387 	static clock_t tpm = 0;
1388 	clock_t mins;
1389 	int i;
1390 
1391 	if (!tpm)
1392 		tpm = sysconf(_SC_CLK_TCK) * 60;
1393 
1394 	mins = ticks / tpm;
1395 	snprintf(seconds, l, "%.4f", (ticks - mins * tpm) * 60.0 / tpm );
1396 
1397 	if (seconds[0] == '6' && seconds[1] == '0') {
1398 		/* 59.99995 got rounded up... */
1399 		mins++;
1400 		strlcpy(seconds, "0.0", l);
1401 		return mins;
1402 	}
1403 
1404 	/* suppress trailing zeros */
1405 	i = strlen(seconds) - 1;
1406 	for (; seconds[i] == '0' && seconds[i - 1] != '.'; i--)
1407 		seconds[i] = 0;
1408 	return mins;
1409 }
1410 
1411 int
1412 timescmd(int argc, char **argv)
1413 {
1414 	struct tms tms;
1415 	int u, s, cu, cs;
1416 	char us[8], ss[8], cus[8], css[8];
1417 
1418 	nextopt("");
1419 
1420 	times(&tms);
1421 
1422 	u = conv_time(tms.tms_utime, us, sizeof(us));
1423 	s = conv_time(tms.tms_stime, ss, sizeof(ss));
1424 	cu = conv_time(tms.tms_cutime, cus, sizeof(cus));
1425 	cs = conv_time(tms.tms_cstime, css, sizeof(css));
1426 
1427 	outfmt(out1, "%dm%ss %dm%ss\n%dm%ss %dm%ss\n",
1428 		u, us, s, ss, cu, cus, cs, css);
1429 
1430 	return 0;
1431 }
1432