1 /*-
2  * Copyright (c) 1993
3  *	The Regents of the University of California.  All rights reserved.
4  * Copyright (c) 1997-2005
5  *	Herbert Xu <herbert@gondor.apana.org.au>.  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 <stdlib.h>
36 #include <signal.h>
37 #include <unistd.h>
38 #include <sys/types.h>
39 
40 /*
41  * Evaluate a command.
42  */
43 
44 #include "init.h"
45 #include "main.h"
46 #include "shell.h"
47 #include "nodes.h"
48 #include "syntax.h"
49 #include "expand.h"
50 #include "parser.h"
51 #include "jobs.h"
52 #include "eval.h"
53 #include "builtins.h"
54 #include "options.h"
55 #include "exec.h"
56 #include "redir.h"
57 #include "input.h"
58 #include "output.h"
59 #include "trap.h"
60 #include "var.h"
61 #include "memalloc.h"
62 #include "error.h"
63 #include "show.h"
64 #include "mystring.h"
65 #ifndef SMALL
66 #include "myhistedit.h"
67 #endif
68 
69 
70 int evalskip;			/* set if we are skipping commands */
71 STATIC int skipcount;		/* number of levels to skip */
72 MKINIT int loopnest;		/* current loop nesting level */
73 static int funcline;		/* starting line number of current function, or 0 if not in a function */
74 
75 
76 char *commandname;
77 int exitstatus;			/* exit status of last command */
78 int back_exitstatus;		/* exit status of backquoted command */
79 int savestatus = -1;		/* exit status of last command outside traps */
80 
81 
82 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
83 STATIC
84 #endif
85 void evaltreenr(union node *, int) __attribute__ ((__noreturn__));
86 STATIC int evalloop(union node *, int);
87 STATIC int evalfor(union node *, int);
88 STATIC int evalcase(union node *, int);
89 STATIC int evalsubshell(union node *, int);
90 STATIC void expredir(union node *);
91 STATIC int evalpipe(union node *, int);
92 #ifdef notyet
93 STATIC int evalcommand(union node *, int, struct backcmd *);
94 #else
95 STATIC int evalcommand(union node *, int);
96 #endif
97 STATIC int evalbltin(const struct builtincmd *, int, char **, int);
98 STATIC int evalfun(struct funcnode *, int, char **, int);
99 STATIC void prehash(union node *);
100 STATIC int eprintlist(struct output *, struct strlist *, int);
101 STATIC int bltincmd(int, char **);
102 
103 
104 STATIC const struct builtincmd bltin = {
105 	.name = nullstr,
106 	.builtin = bltincmd,
107 	.flags = BUILTIN_REGULAR,
108 };
109 
110 
111 /*
112  * Called to reset things after an exception.
113  */
114 
115 #ifdef mkinit
116 INCLUDE "eval.h"
117 
118 EXITRESET {
119 	if (savestatus >= 0) {
120 		if (exception == EXEXIT || evalskip == SKIPFUNCDEF)
121 			exitstatus = savestatus;
122 		savestatus = -1;
123 	}
124 	evalskip = 0;
125 	loopnest = 0;
126 }
127 #endif
128 
129 
130 
131 /*
132  * The eval commmand.
133  */
134 
evalcmd(int argc,char ** argv,int flags)135 static int evalcmd(int argc, char **argv, int flags)
136 {
137         char *p;
138         char *concat;
139         char **ap;
140 
141         if (argc > 1) {
142                 p = argv[1];
143                 if (argc > 2) {
144                         STARTSTACKSTR(concat);
145                         ap = argv + 2;
146                         for (;;) {
147                         	concat = stputs(p, concat);
148                                 if ((p = *ap++) == NULL)
149                                         break;
150                                 STPUTC(' ', concat);
151                         }
152                         STPUTC('\0', concat);
153                         p = grabstackstr(concat);
154                 }
155                 return evalstring(p, flags & EV_TESTED);
156         }
157         return 0;
158 }
159 
160 
161 /*
162  * Execute a command or commands contained in a string.
163  */
164 
165 int
evalstring(char * s,int flags)166 evalstring(char *s, int flags)
167 {
168 	union node *n;
169 	struct stackmark smark;
170 	int status;
171 
172 	s = sstrdup(s);
173 	setinputstring(s);
174 	setstackmark(&smark);
175 
176 	status = 0;
177 	for (; (n = parsecmd(0)) != NEOF; popstackmark(&smark)) {
178 		int i;
179 
180 		i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
181 		if (n)
182 			status = i;
183 
184 		if (evalskip)
185 			break;
186 	}
187 	popstackmark(&smark);
188 	popfile();
189 	stunalloc(s);
190 
191 	return status;
192 }
193 
194 
195 
196 /*
197  * Evaluate a parse tree.  The value is left in the global variable
198  * exitstatus.
199  */
200 
201 int
evaltree(union node * n,int flags)202 evaltree(union node *n, int flags)
203 {
204 	int checkexit = 0;
205 	int (*evalfn)(union node *, int);
206 	struct stackmark smark;
207 	unsigned isor;
208 	int status = 0;
209 
210 	setstackmark(&smark);
211 
212 	if (n == NULL) {
213 		TRACE(("evaltree(NULL) called\n"));
214 		goto out;
215 	}
216 
217 	dotrap();
218 
219 #ifndef SMALL
220 	displayhist = 1;	/* show history substitutions done with fc */
221 #endif
222 	TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
223 	    getpid(), n, n->type, flags));
224 	switch (n->type) {
225 	default:
226 #ifdef DEBUG
227 		out1fmt("Node type = %d\n", n->type);
228 #ifndef USE_GLIBC_STDIO
229 		flushout(out1);
230 #endif
231 		break;
232 #endif
233 	case NNOT:
234 		status = !evaltree(n->nnot.com, EV_TESTED);
235 		goto setstatus;
236 	case NREDIR:
237 		errlinno = lineno = n->nredir.linno;
238 		if (funcline)
239 			lineno -= funcline - 1;
240 		expredir(n->nredir.redirect);
241 		pushredir(n->nredir.redirect);
242 		status = redirectsafe(n->nredir.redirect, REDIR_PUSH) ?:
243 			 evaltree(n->nredir.n, flags & EV_TESTED);
244 		if (n->nredir.redirect)
245 			popredir(0);
246 		goto setstatus;
247 	case NCMD:
248 		evalfn = evalcommand;
249 checkexit:
250 		checkexit = ~flags & EV_TESTED;
251 		goto calleval;
252 	case NFOR:
253 		evalfn = evalfor;
254 		goto calleval;
255 	case NWHILE:
256 	case NUNTIL:
257 		evalfn = evalloop;
258 		goto calleval;
259 	case NSUBSHELL:
260 	case NBACKGND:
261 		evalfn = evalsubshell;
262 		goto checkexit;
263 	case NPIPE:
264 		evalfn = evalpipe;
265 		goto checkexit;
266 	case NCASE:
267 		evalfn = evalcase;
268 		goto calleval;
269 	case NAND:
270 	case NOR:
271 	case NSEMI:
272 #if NAND + 1 != NOR
273 #error NAND + 1 != NOR
274 #endif
275 #if NOR + 1 != NSEMI
276 #error NOR + 1 != NSEMI
277 #endif
278 		isor = n->type - NAND;
279 		status = evaltree(n->nbinary.ch1,
280 				  (flags | ((isor >> 1) - 1)) & EV_TESTED);
281 		if ((!status) == isor || evalskip)
282 			break;
283 		n = n->nbinary.ch2;
284 evaln:
285 		evalfn = evaltree;
286 calleval:
287 		status = evalfn(n, flags);
288 		goto setstatus;
289 	case NIF:
290 		status = evaltree(n->nif.test, EV_TESTED);
291 		if (evalskip)
292 			break;
293 		if (!status) {
294 			n = n->nif.ifpart;
295 			goto evaln;
296 		} else if (n->nif.elsepart) {
297 			n = n->nif.elsepart;
298 			goto evaln;
299 		}
300 		status = 0;
301 		goto setstatus;
302 	case NDEFUN:
303 		defun(n);
304 setstatus:
305 		exitstatus = status;
306 		break;
307 	}
308 out:
309 	dotrap();
310 
311 	if (eflag && checkexit && status)
312 		goto exexit;
313 
314 	if (flags & EV_EXIT) {
315 exexit:
316 		exraise(EXEND);
317 	}
318 
319 	popstackmark(&smark);
320 
321 	return exitstatus;
322 }
323 
324 
325 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
326 STATIC
327 #endif
328 void evaltreenr(union node *n, int flags)
329 #ifdef HAVE_ATTRIBUTE_ALIAS
330 	__attribute__ ((alias("evaltree")));
331 #else
332 {
333 	evaltree(n, flags);
334 	abort();
335 }
336 #endif
337 
338 
skiploop(void)339 static int skiploop(void)
340 {
341 	int skip = evalskip;
342 
343 	switch (skip) {
344 	case 0:
345 		break;
346 
347 	case SKIPBREAK:
348 	case SKIPCONT:
349 		if (likely(--skipcount <= 0)) {
350 			evalskip = 0;
351 			break;
352 		}
353 
354 		skip = SKIPBREAK;
355 		break;
356 	}
357 
358 	return skip;
359 }
360 
361 
362 STATIC int
evalloop(union node * n,int flags)363 evalloop(union node *n, int flags)
364 {
365 	int skip;
366 	int status;
367 
368 	loopnest++;
369 	status = 0;
370 	flags &= EV_TESTED;
371 	do {
372 		int i;
373 
374 		i = evaltree(n->nbinary.ch1, EV_TESTED);
375 		skip = skiploop();
376 		if (skip == SKIPFUNC)
377 			status = i;
378 		if (skip)
379 			continue;
380 		if (n->type != NWHILE)
381 			i = !i;
382 		if (i != 0)
383 			break;
384 		status = evaltree(n->nbinary.ch2, flags);
385 		skip = skiploop();
386 	} while (!(skip & ~SKIPCONT));
387 	loopnest--;
388 
389 	return status;
390 }
391 
392 
393 
394 STATIC int
evalfor(union node * n,int flags)395 evalfor(union node *n, int flags)
396 {
397 	struct arglist arglist;
398 	union node *argp;
399 	struct strlist *sp;
400 	int status;
401 
402 	errlinno = lineno = n->nfor.linno;
403 	if (funcline)
404 		lineno -= funcline - 1;
405 
406 	arglist.lastp = &arglist.list;
407 	for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
408 		expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
409 	}
410 	*arglist.lastp = NULL;
411 
412 	status = 0;
413 	loopnest++;
414 	flags &= EV_TESTED;
415 	for (sp = arglist.list ; sp ; sp = sp->next) {
416 		setvar(n->nfor.var, sp->text, 0);
417 		status = evaltree(n->nfor.body, flags);
418 		if (skiploop() & ~SKIPCONT)
419 			break;
420 	}
421 	loopnest--;
422 
423 	return status;
424 }
425 
426 
427 
428 STATIC int
evalcase(union node * n,int flags)429 evalcase(union node *n, int flags)
430 {
431 	union node *cp;
432 	union node *patp;
433 	struct arglist arglist;
434 	int status = 0;
435 
436 	errlinno = lineno = n->ncase.linno;
437 	if (funcline)
438 		lineno -= funcline - 1;
439 
440 	arglist.lastp = &arglist.list;
441 	expandarg(n->ncase.expr, &arglist, EXP_TILDE);
442 	for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
443 		for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
444 			if (casematch(patp, arglist.list->text)) {
445 				/* Ensure body is non-empty as otherwise
446 				 * EV_EXIT may prevent us from setting the
447 				 * exit status.
448 				 */
449 				if (evalskip == 0 && cp->nclist.body) {
450 					status = evaltree(cp->nclist.body,
451 							  flags);
452 				}
453 				goto out;
454 			}
455 		}
456 	}
457 out:
458 	return status;
459 }
460 
461 
462 
463 /*
464  * Kick off a subshell to evaluate a tree.
465  */
466 
467 STATIC int
evalsubshell(union node * n,int flags)468 evalsubshell(union node *n, int flags)
469 {
470 	struct job *jp;
471 	int backgnd = (n->type == NBACKGND);
472 	int status;
473 
474 	errlinno = lineno = n->nredir.linno;
475 	if (funcline)
476 		lineno -= funcline - 1;
477 
478 	expredir(n->nredir.redirect);
479 	INTOFF;
480 	if (!backgnd && flags & EV_EXIT && !have_traps()) {
481 		forkreset();
482 		goto nofork;
483 	}
484 	jp = makejob(n, 1);
485 	if (forkshell(jp, n, backgnd) == 0) {
486 		flags |= EV_EXIT;
487 		if (backgnd)
488 			flags &=~ EV_TESTED;
489 nofork:
490 		INTON;
491 		redirect(n->nredir.redirect, 0);
492 		evaltreenr(n->nredir.n, flags);
493 		/* never returns */
494 	}
495 	status = 0;
496 	if (! backgnd)
497 		status = waitforjob(jp);
498 	INTON;
499 	return status;
500 }
501 
502 
503 
504 /*
505  * Compute the names of the files in a redirection list.
506  */
507 
508 STATIC void
expredir(union node * n)509 expredir(union node *n)
510 {
511 	union node *redir;
512 
513 	for (redir = n ; redir ; redir = redir->nfile.next) {
514 		struct arglist fn;
515 		fn.lastp = &fn.list;
516 		switch (redir->type) {
517 		case NFROMTO:
518 		case NFROM:
519 		case NTO:
520 		case NCLOBBER:
521 		case NAPPEND:
522 			expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
523 			redir->nfile.expfname = fn.list->text;
524 			break;
525 		case NFROMFD:
526 		case NTOFD:
527 			if (redir->ndup.vname) {
528 				expandarg(redir->ndup.vname, &fn, EXP_TILDE | EXP_REDIR);
529 				fixredir(redir, fn.list->text, 1);
530 			}
531 			break;
532 		}
533 	}
534 }
535 
536 
537 
538 /*
539  * Evaluate a pipeline.  All the processes in the pipeline are children
540  * of the process creating the pipeline.  (This differs from some versions
541  * of the shell, which make the last process in a pipeline the parent
542  * of all the rest.)
543  */
544 
545 STATIC int
evalpipe(union node * n,int flags)546 evalpipe(union node *n, int flags)
547 {
548 	struct job *jp;
549 	struct nodelist *lp;
550 	int pipelen;
551 	int prevfd;
552 	int pip[2];
553 	int status = 0;
554 
555 	TRACE(("evalpipe(0x%lx) called\n", (long)n));
556 	pipelen = 0;
557 	for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
558 		pipelen++;
559 	flags |= EV_EXIT;
560 	INTOFF;
561 	jp = makejob(n, pipelen);
562 	prevfd = -1;
563 	for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
564 		prehash(lp->n);
565 		pip[1] = -1;
566 		if (lp->next) {
567 			if (pipe(pip) < 0) {
568 				close(prevfd);
569 				sh_error("Pipe call failed");
570 			}
571 		}
572 		if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
573 			INTON;
574 			if (pip[1] >= 0) {
575 				close(pip[0]);
576 			}
577 			if (prevfd > 0) {
578 				dup2(prevfd, 0);
579 				close(prevfd);
580 			}
581 			if (pip[1] > 1) {
582 				dup2(pip[1], 1);
583 				close(pip[1]);
584 			}
585 			evaltreenr(lp->n, flags);
586 			/* never returns */
587 		}
588 		if (prevfd >= 0)
589 			close(prevfd);
590 		prevfd = pip[0];
591 		close(pip[1]);
592 	}
593 	if (n->npipe.backgnd == 0) {
594 		status = waitforjob(jp);
595 		TRACE(("evalpipe:  job done exit status %d\n", status));
596 	}
597 	INTON;
598 
599 	return status;
600 }
601 
602 
603 
604 /*
605  * Execute a command inside back quotes.  If it's a builtin command, we
606  * want to save its output in a block obtained from malloc.  Otherwise
607  * we fork off a subprocess and get the output of the command via a pipe.
608  * Should be called with interrupts off.
609  */
610 
611 void
evalbackcmd(union node * n,struct backcmd * result)612 evalbackcmd(union node *n, struct backcmd *result)
613 {
614 	int pip[2];
615 	struct job *jp;
616 
617 	result->fd = -1;
618 	result->buf = NULL;
619 	result->nleft = 0;
620 	result->jp = NULL;
621 	if (n == NULL) {
622 		goto out;
623 	}
624 
625 	if (pipe(pip) < 0)
626 		sh_error("Pipe call failed");
627 	jp = makejob(n, 1);
628 	if (forkshell(jp, n, FORK_NOJOB) == 0) {
629 		FORCEINTON;
630 		close(pip[0]);
631 		if (pip[1] != 1) {
632 			dup2(pip[1], 1);
633 			close(pip[1]);
634 		}
635 		ifsfree();
636 		evaltreenr(n, EV_EXIT);
637 		/* NOTREACHED */
638 	}
639 	close(pip[1]);
640 	result->fd = pip[0];
641 	result->jp = jp;
642 
643 out:
644 	TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
645 		result->fd, result->buf, result->nleft, result->jp));
646 }
647 
fill_arglist(struct arglist * arglist,union node ** argpp)648 static struct strlist *fill_arglist(struct arglist *arglist,
649 				    union node **argpp)
650 {
651 	struct strlist **lastp = arglist->lastp;
652 	union node *argp;
653 
654 	while ((argp = *argpp)) {
655 		expandarg(argp, arglist, EXP_FULL | EXP_TILDE);
656 		*argpp = argp->narg.next;
657 		if (*lastp)
658 			break;
659 	}
660 
661 	return *lastp;
662 }
663 
parse_command_args(struct arglist * arglist,union node ** argpp,const char ** path)664 static int parse_command_args(struct arglist *arglist, union node **argpp,
665 			      const char **path)
666 {
667 	struct strlist *sp = arglist->list;
668 	char *cp, c;
669 
670 	for (;;) {
671 		sp = unlikely(sp->next) ? sp->next :
672 					  fill_arglist(arglist, argpp);
673 		if (!sp)
674 			return 0;
675 		cp = sp->text;
676 		if (*cp++ != '-')
677 			break;
678 		if (!(c = *cp++))
679 			break;
680 		if (c == '-' && !*cp) {
681 			if (likely(!sp->next) && !fill_arglist(arglist, argpp))
682 				return 0;
683 			sp = sp->next;
684 			break;
685 		}
686 		do {
687 			switch (c) {
688 			case 'p':
689 				*path = defpath;
690 				break;
691 			default:
692 				/* run 'typecmd' for other options */
693 				return 0;
694 			}
695 		} while ((c = *cp++));
696 	}
697 
698 	arglist->list = sp;
699 	return DO_NOFUNC;
700 }
701 
702 /*
703  * Execute a simple command.
704  */
705 
706 STATIC int
707 #ifdef notyet
evalcommand(union node * cmd,int flags,struct backcmd * backcmd)708 evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
709 #else
710 evalcommand(union node *cmd, int flags)
711 #endif
712 {
713 	struct localvar_list *localvar_stop;
714 	struct parsefile *file_stop;
715 	struct redirtab *redir_stop;
716 	union node *argp;
717 	struct arglist arglist;
718 	struct arglist varlist;
719 	char **argv;
720 	int argc;
721 	struct strlist *osp;
722 	struct strlist *sp;
723 #ifdef notyet
724 	int pip[2];
725 #endif
726 	struct cmdentry cmdentry;
727 	struct job *jp;
728 	char *lastarg;
729 	const char *path;
730 	int spclbltin;
731 	int cmd_flag;
732 	int execcmd;
733 	int status;
734 	char **nargv;
735 	int vflags;
736 	int vlocal;
737 
738 	errlinno = lineno = cmd->ncmd.linno;
739 	if (funcline)
740 		lineno -= funcline - 1;
741 
742 	/* First expand the arguments. */
743 	TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
744 	file_stop = parsefile;
745 	back_exitstatus = 0;
746 
747 	cmdentry.cmdtype = CMDBUILTIN;
748 	cmdentry.u.cmd = &bltin;
749 	varlist.lastp = &varlist.list;
750 	*varlist.lastp = NULL;
751 	arglist.lastp = &arglist.list;
752 	*arglist.lastp = NULL;
753 
754 	cmd_flag = 0;
755 	execcmd = 0;
756 	spclbltin = -1;
757 	vflags = 0;
758 	vlocal = 0;
759 	path = NULL;
760 
761 	argc = 0;
762 	argp = cmd->ncmd.args;
763 	if ((osp = fill_arglist(&arglist, &argp))) {
764 		int pseudovarflag = 0;
765 
766 		for (;;) {
767 			find_command(arglist.list->text, &cmdentry,
768 				     cmd_flag | DO_REGBLTIN, pathval());
769 
770 			vlocal++;
771 
772 			/* implement bltin and command here */
773 			if (cmdentry.cmdtype != CMDBUILTIN)
774 				break;
775 
776 			pseudovarflag = cmdentry.u.cmd->flags & BUILTIN_ASSIGN;
777 			if (likely(spclbltin < 0)) {
778 				spclbltin =
779 					cmdentry.u.cmd->flags &
780 					BUILTIN_SPECIAL
781 				;
782 				vlocal = spclbltin ^ BUILTIN_SPECIAL;
783 			}
784 			execcmd = cmdentry.u.cmd == EXECCMD;
785 			if (likely(cmdentry.u.cmd != COMMANDCMD))
786 				break;
787 
788 			cmd_flag = parse_command_args(&arglist, &argp, &path);
789 			if (!cmd_flag)
790 				break;
791 		}
792 
793 		for (; argp; argp = argp->narg.next)
794 			expandarg(argp, &arglist,
795 				  pseudovarflag &&
796 				  isassignment(argp->narg.text) ?
797 				  EXP_VARTILDE : EXP_FULL | EXP_TILDE);
798 
799 		for (sp = arglist.list; sp; sp = sp->next)
800 			argc++;
801 
802 		if (execcmd && argc > 1)
803 			vflags = VEXPORT;
804 	}
805 
806 	localvar_stop = pushlocalvars(vlocal);
807 
808 	/* Reserve one extra spot at the front for shellexec. */
809 	nargv = stalloc(sizeof (char *) * (argc + 2));
810 	argv = ++nargv;
811 	for (sp = arglist.list ; sp ; sp = sp->next) {
812 		TRACE(("evalcommand arg: %s\n", sp->text));
813 		*nargv++ = sp->text;
814 	}
815 	*nargv = NULL;
816 
817 	lastarg = NULL;
818 	if (iflag && funcline == 0 && argc > 0)
819 		lastarg = nargv[-1];
820 
821 	preverrout.fd = 2;
822 	expredir(cmd->ncmd.redirect);
823 	redir_stop = pushredir(cmd->ncmd.redirect);
824 	status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH|REDIR_SAVEFD2);
825 
826 	if (unlikely(status)) {
827 bail:
828 		exitstatus = status;
829 
830 		/* We have a redirection error. */
831 		if (spclbltin > 0)
832 			exraise(EXERROR);
833 
834 		goto out;
835 	}
836 
837 	for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
838 		struct strlist **spp;
839 
840 		spp = varlist.lastp;
841 		expandarg(argp, &varlist, EXP_VARTILDE);
842 
843 		if (vlocal)
844 			mklocal((*spp)->text, VEXPORT);
845 		else
846 			setvareq((*spp)->text, vflags);
847 	}
848 
849 	/* Print the command if xflag is set. */
850 	if (xflag) {
851 		struct output *out;
852 		int sep;
853 
854 		out = &preverrout;
855 		outstr(expandstr(ps4val()), out);
856 		sep = 0;
857 		sep = eprintlist(out, varlist.list, sep);
858 		eprintlist(out, osp, sep);
859 		outcslow('\n', out);
860 #ifdef FLUSHERR
861 		flushout(out);
862 #endif
863 	}
864 
865 	/* Now locate the command. */
866 	if (cmdentry.cmdtype != CMDBUILTIN ||
867 	    !(cmdentry.u.cmd->flags & BUILTIN_REGULAR)) {
868 		path = unlikely(path) ? path : pathval();
869 		find_command(argv[0], &cmdentry, cmd_flag | DO_ERR, path);
870 	}
871 
872 	jp = NULL;
873 
874 	/* Execute the command. */
875 	switch (cmdentry.cmdtype) {
876 	case CMDUNKNOWN:
877 		status = 127;
878 #ifdef FLUSHERR
879 		flushout(&errout);
880 #endif
881 		goto bail;
882 
883 	default:
884 		/* Fork off a child process if necessary. */
885 		if (!(flags & EV_EXIT) || have_traps()) {
886 			INTOFF;
887 			jp = vforkexec(cmd, argv, path, cmdentry.u.index);
888 			break;
889 		}
890 		shellexec(argv, path, cmdentry.u.index);
891 		/* NOTREACHED */
892 
893 	case CMDBUILTIN:
894 		if (evalbltin(cmdentry.u.cmd, argc, argv, flags) &&
895 		    !(exception == EXERROR && spclbltin <= 0)) {
896 raise:
897 			longjmp(handler->loc, 1);
898 		}
899 		break;
900 
901 	case CMDFUNCTION:
902 		if (evalfun(cmdentry.u.func, argc, argv, flags))
903 			goto raise;
904 		break;
905 	}
906 
907 	status = waitforjob(jp);
908 	FORCEINTON;
909 
910 out:
911 	if (cmd->ncmd.redirect)
912 		popredir(execcmd);
913 	unwindredir(redir_stop);
914 	unwindfiles(file_stop);
915 	unwindlocalvars(localvar_stop);
916 	if (lastarg)
917 		/* dsl: I think this is intended to be used to support
918 		 * '_' in 'vi' command mode during line editing...
919 		 * However I implemented that within libedit itself.
920 		 */
921 		setvar("_", lastarg, 0);
922 
923 	return status;
924 }
925 
926 STATIC int
evalbltin(const struct builtincmd * cmd,int argc,char ** argv,int flags)927 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
928 {
929 	char *volatile savecmdname;
930 	struct jmploc *volatile savehandler;
931 	struct jmploc jmploc;
932 	int status;
933 	int i;
934 
935 	savecmdname = commandname;
936 	savehandler = handler;
937 	if ((i = setjmp(jmploc.loc)))
938 		goto cmddone;
939 	handler = &jmploc;
940 	commandname = argv[0];
941 	argptr = argv + 1;
942 	optptr = NULL;			/* initialize nextopt */
943 	if (cmd == EVALCMD)
944 		status = evalcmd(argc, argv, flags);
945 	else
946 		status = (*cmd->builtin)(argc, argv);
947 	flushall();
948 	if (outerr(out1))
949 		sh_warnx("%s: I/O error", commandname);
950 	status |= outerr(out1);
951 	exitstatus = status;
952 cmddone:
953 	freestdout();
954 	commandname = savecmdname;
955 	handler = savehandler;
956 
957 	return i;
958 }
959 
960 STATIC int
evalfun(struct funcnode * func,int argc,char ** argv,int flags)961 evalfun(struct funcnode *func, int argc, char **argv, int flags)
962 {
963 	volatile struct shparam saveparam;
964 	struct jmploc *volatile savehandler;
965 	struct jmploc jmploc;
966 	int e;
967 	int savefuncline;
968 	int saveloopnest;
969 
970 	saveparam = shellparam;
971 	savefuncline = funcline;
972 	saveloopnest = loopnest;
973 	savehandler = handler;
974 	if ((e = setjmp(jmploc.loc))) {
975 		goto funcdone;
976 	}
977 	INTOFF;
978 	handler = &jmploc;
979 	shellparam.malloc = 0;
980 	func->count++;
981 	funcline = func->n.ndefun.linno;
982 	loopnest = 0;
983 	INTON;
984 	shellparam.nparam = argc - 1;
985 	shellparam.p = argv + 1;
986 	shellparam.optind = 1;
987 	shellparam.optoff = -1;
988 	evaltree(func->n.ndefun.body, flags & EV_TESTED);
989 funcdone:
990 	INTOFF;
991 	loopnest = saveloopnest;
992 	funcline = savefuncline;
993 	freefunc(func);
994 	freeparam(&shellparam);
995 	shellparam = saveparam;
996 	handler = savehandler;
997 	INTON;
998 	evalskip &= ~(SKIPFUNC | SKIPFUNCDEF);
999 	return e;
1000 }
1001 
1002 
1003 /*
1004  * Search for a command.  This is called before we fork so that the
1005  * location of the command will be available in the parent as well as
1006  * the child.  The check for "goodname" is an overly conservative
1007  * check that the name will not be subject to expansion.
1008  */
1009 
1010 STATIC void
prehash(union node * n)1011 prehash(union node *n)
1012 {
1013 	struct cmdentry entry;
1014 
1015 	if (n->type == NCMD && n->ncmd.args)
1016 		if (goodname(n->ncmd.args->narg.text))
1017 			find_command(n->ncmd.args->narg.text, &entry, 0,
1018 				     pathval());
1019 }
1020 
1021 
1022 
1023 /*
1024  * Builtin commands.  Builtin commands whose functions are closely
1025  * tied to evaluation are implemented here.
1026  */
1027 
1028 /*
1029  * No command given.
1030  */
1031 
1032 STATIC int
bltincmd(int argc,char ** argv)1033 bltincmd(int argc, char **argv)
1034 {
1035 	/*
1036 	 * Preserve exitstatus of a previous possible redirection
1037 	 * as POSIX mandates
1038 	 */
1039 	return back_exitstatus;
1040 }
1041 
1042 
1043 /*
1044  * Handle break and continue commands.  Break, continue, and return are
1045  * all handled by setting the evalskip flag.  The evaluation routines
1046  * above all check this flag, and if it is set they start skipping
1047  * commands rather than executing them.  The variable skipcount is
1048  * the number of loops to break/continue, or the number of function
1049  * levels to return.  (The latter is always 1.)  It should probably
1050  * be an error to break out of more loops than exist, but it isn't
1051  * in the standard shell so we don't make it one here.
1052  */
1053 
1054 int
breakcmd(int argc,char ** argv)1055 breakcmd(int argc, char **argv)
1056 {
1057 	int n = argc > 1 ? number(argv[1]) : 1;
1058 
1059 	if (n <= 0)
1060 		badnum(argv[1]);
1061 	if (n > loopnest)
1062 		n = loopnest;
1063 	if (n > 0) {
1064 		evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
1065 		skipcount = n;
1066 	}
1067 	return 0;
1068 }
1069 
1070 
1071 /*
1072  * The return command.
1073  */
1074 
1075 int
returncmd(int argc,char ** argv)1076 returncmd(int argc, char **argv)
1077 {
1078 	int skip;
1079 	int status;
1080 
1081 	/*
1082 	 * If called outside a function, do what ksh does;
1083 	 * skip the rest of the file.
1084 	 */
1085 	if (argv[1]) {
1086 		skip = SKIPFUNC;
1087 		status = number(argv[1]);
1088 	} else {
1089 		skip = SKIPFUNCDEF;
1090 		status = exitstatus;
1091 	}
1092 	evalskip = skip;
1093 
1094 	return status;
1095 }
1096 
1097 
1098 int
falsecmd(int argc,char ** argv)1099 falsecmd(int argc, char **argv)
1100 {
1101 	return 1;
1102 }
1103 
1104 
1105 int
truecmd(int argc,char ** argv)1106 truecmd(int argc, char **argv)
1107 {
1108 	return 0;
1109 }
1110 
1111 
1112 int
execcmd(int argc,char ** argv)1113 execcmd(int argc, char **argv)
1114 {
1115 	if (argc > 1) {
1116 		iflag = 0;		/* exit on error */
1117 		mflag = 0;
1118 		optschanged();
1119 		shellexec(argv + 1, pathval(), 0);
1120 	}
1121 	return 0;
1122 }
1123 
1124 
1125 STATIC int
eprintlist(struct output * out,struct strlist * sp,int sep)1126 eprintlist(struct output *out, struct strlist *sp, int sep)
1127 {
1128 	while (sp) {
1129 		const char *p;
1130 
1131 		p = " %s";
1132 		p += (1 - sep);
1133 		sep |= 1;
1134 		outfmt(out, p, sp->text);
1135 		sp = sp->next;
1136 	}
1137 
1138 	return sep;
1139 }
1140