Home | History | Annotate | Line # | Download | only in sh
eval.c revision 1.1
      1  1.1  cgd /*-
      2  1.1  cgd  * Copyright (c) 1991 The Regents of the University of California.
      3  1.1  cgd  * All rights reserved.
      4  1.1  cgd  *
      5  1.1  cgd  * This code is derived from software contributed to Berkeley by
      6  1.1  cgd  * Kenneth Almquist.
      7  1.1  cgd  *
      8  1.1  cgd  * Redistribution and use in source and binary forms, with or without
      9  1.1  cgd  * modification, are permitted provided that the following conditions
     10  1.1  cgd  * are met:
     11  1.1  cgd  * 1. Redistributions of source code must retain the above copyright
     12  1.1  cgd  *    notice, this list of conditions and the following disclaimer.
     13  1.1  cgd  * 2. Redistributions in binary form must reproduce the above copyright
     14  1.1  cgd  *    notice, this list of conditions and the following disclaimer in the
     15  1.1  cgd  *    documentation and/or other materials provided with the distribution.
     16  1.1  cgd  * 3. All advertising materials mentioning features or use of this software
     17  1.1  cgd  *    must display the following acknowledgement:
     18  1.1  cgd  *	This product includes software developed by the University of
     19  1.1  cgd  *	California, Berkeley and its contributors.
     20  1.1  cgd  * 4. Neither the name of the University nor the names of its contributors
     21  1.1  cgd  *    may be used to endorse or promote products derived from this software
     22  1.1  cgd  *    without specific prior written permission.
     23  1.1  cgd  *
     24  1.1  cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     25  1.1  cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     26  1.1  cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     27  1.1  cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     28  1.1  cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     29  1.1  cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     30  1.1  cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     31  1.1  cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     32  1.1  cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     33  1.1  cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     34  1.1  cgd  * SUCH DAMAGE.
     35  1.1  cgd  */
     36  1.1  cgd 
     37  1.1  cgd #ifndef lint
     38  1.1  cgd static char sccsid[] = "@(#)eval.c	5.3 (Berkeley) 4/12/91";
     39  1.1  cgd #endif /* not lint */
     40  1.1  cgd 
     41  1.1  cgd /*
     42  1.1  cgd  * Evaluate a command.
     43  1.1  cgd  */
     44  1.1  cgd 
     45  1.1  cgd #include "shell.h"
     46  1.1  cgd #include "nodes.h"
     47  1.1  cgd #include "syntax.h"
     48  1.1  cgd #include "expand.h"
     49  1.1  cgd #include "parser.h"
     50  1.1  cgd #include "jobs.h"
     51  1.1  cgd #include "eval.h"
     52  1.1  cgd #include "builtins.h"
     53  1.1  cgd #include "options.h"
     54  1.1  cgd #include "exec.h"
     55  1.1  cgd #include "redir.h"
     56  1.1  cgd #include "input.h"
     57  1.1  cgd #include "output.h"
     58  1.1  cgd #include "trap.h"
     59  1.1  cgd #include "var.h"
     60  1.1  cgd #include "memalloc.h"
     61  1.1  cgd #include "error.h"
     62  1.1  cgd #include "mystring.h"
     63  1.1  cgd #include <signal.h>
     64  1.1  cgd 
     65  1.1  cgd 
     66  1.1  cgd /* flags in argument to evaltree */
     67  1.1  cgd #define EV_EXIT 01		/* exit after evaluating tree */
     68  1.1  cgd #define EV_TESTED 02		/* exit status is checked; ignore -e flag */
     69  1.1  cgd #define EV_BACKCMD 04		/* command executing within back quotes */
     70  1.1  cgd 
     71  1.1  cgd 
     72  1.1  cgd /* reasons for skipping commands (see comment on breakcmd routine) */
     73  1.1  cgd #define SKIPBREAK 1
     74  1.1  cgd #define SKIPCONT 2
     75  1.1  cgd #define SKIPFUNC 3
     76  1.1  cgd 
     77  1.1  cgd MKINIT int evalskip;		/* set if we are skipping commands */
     78  1.1  cgd STATIC int skipcount;		/* number of levels to skip */
     79  1.1  cgd MKINIT int loopnest;		/* current loop nesting level */
     80  1.1  cgd int funcnest;			/* depth of function calls */
     81  1.1  cgd 
     82  1.1  cgd 
     83  1.1  cgd char *commandname;
     84  1.1  cgd struct strlist *cmdenviron;
     85  1.1  cgd int exitstatus;			/* exit status of last command */
     86  1.1  cgd 
     87  1.1  cgd 
     88  1.1  cgd #ifdef __STDC__
     89  1.1  cgd STATIC void evalloop(union node *);
     90  1.1  cgd STATIC void evalfor(union node *);
     91  1.1  cgd STATIC void evalcase(union node *, int);
     92  1.1  cgd STATIC void evalsubshell(union node *, int);
     93  1.1  cgd STATIC void expredir(union node *);
     94  1.1  cgd STATIC void evalpipe(union node *);
     95  1.1  cgd STATIC void evalcommand(union node *, int, struct backcmd *);
     96  1.1  cgd STATIC void prehash(union node *);
     97  1.1  cgd #else
     98  1.1  cgd STATIC void evalloop();
     99  1.1  cgd STATIC void evalfor();
    100  1.1  cgd STATIC void evalcase();
    101  1.1  cgd STATIC void evalsubshell();
    102  1.1  cgd STATIC void expredir();
    103  1.1  cgd STATIC void evalpipe();
    104  1.1  cgd STATIC void evalcommand();
    105  1.1  cgd STATIC void prehash();
    106  1.1  cgd #endif
    107  1.1  cgd 
    108  1.1  cgd 
    109  1.1  cgd 
    110  1.1  cgd /*
    111  1.1  cgd  * Called to reset things after an exception.
    112  1.1  cgd  */
    113  1.1  cgd 
    114  1.1  cgd #ifdef mkinit
    115  1.1  cgd INCLUDE "eval.h"
    116  1.1  cgd 
    117  1.1  cgd RESET {
    118  1.1  cgd 	evalskip = 0;
    119  1.1  cgd 	loopnest = 0;
    120  1.1  cgd 	funcnest = 0;
    121  1.1  cgd }
    122  1.1  cgd 
    123  1.1  cgd SHELLPROC {
    124  1.1  cgd 	exitstatus = 0;
    125  1.1  cgd }
    126  1.1  cgd #endif
    127  1.1  cgd 
    128  1.1  cgd 
    129  1.1  cgd 
    130  1.1  cgd /*
    131  1.1  cgd  * The eval commmand.
    132  1.1  cgd  */
    133  1.1  cgd 
    134  1.1  cgd evalcmd(argc, argv)
    135  1.1  cgd 	char **argv;
    136  1.1  cgd {
    137  1.1  cgd         char *p;
    138  1.1  cgd         char *concat;
    139  1.1  cgd         char **ap;
    140  1.1  cgd 
    141  1.1  cgd         if (argc > 1) {
    142  1.1  cgd                 p = argv[1];
    143  1.1  cgd                 if (argc > 2) {
    144  1.1  cgd                         STARTSTACKSTR(concat);
    145  1.1  cgd                         ap = argv + 2;
    146  1.1  cgd                         for (;;) {
    147  1.1  cgd                                 while (*p)
    148  1.1  cgd                                         STPUTC(*p++, concat);
    149  1.1  cgd                                 if ((p = *ap++) == NULL)
    150  1.1  cgd                                         break;
    151  1.1  cgd                                 STPUTC(' ', concat);
    152  1.1  cgd                         }
    153  1.1  cgd                         STPUTC('\0', concat);
    154  1.1  cgd                         p = grabstackstr(concat);
    155  1.1  cgd                 }
    156  1.1  cgd                 evalstring(p);
    157  1.1  cgd         }
    158  1.1  cgd         return exitstatus;
    159  1.1  cgd }
    160  1.1  cgd 
    161  1.1  cgd 
    162  1.1  cgd /*
    163  1.1  cgd  * Execute a command or commands contained in a string.
    164  1.1  cgd  */
    165  1.1  cgd 
    166  1.1  cgd void
    167  1.1  cgd evalstring(s)
    168  1.1  cgd 	char *s;
    169  1.1  cgd 	{
    170  1.1  cgd 	union node *n;
    171  1.1  cgd 	struct stackmark smark;
    172  1.1  cgd 
    173  1.1  cgd 	setstackmark(&smark);
    174  1.1  cgd 	setinputstring(s, 1);
    175  1.1  cgd 	while ((n = parsecmd(0)) != NEOF) {
    176  1.1  cgd 		evaltree(n, 0);
    177  1.1  cgd 		popstackmark(&smark);
    178  1.1  cgd 	}
    179  1.1  cgd 	popfile();
    180  1.1  cgd 	popstackmark(&smark);
    181  1.1  cgd }
    182  1.1  cgd 
    183  1.1  cgd 
    184  1.1  cgd 
    185  1.1  cgd /*
    186  1.1  cgd  * Evaluate a parse tree.  The value is left in the global variable
    187  1.1  cgd  * exitstatus.
    188  1.1  cgd  */
    189  1.1  cgd 
    190  1.1  cgd void
    191  1.1  cgd evaltree(n, flags)
    192  1.1  cgd 	union node *n;
    193  1.1  cgd 	{
    194  1.1  cgd 	if (n == NULL) {
    195  1.1  cgd 		TRACE(("evaltree(NULL) called\n"));
    196  1.1  cgd 		return;
    197  1.1  cgd 	}
    198  1.1  cgd 	TRACE(("evaltree(0x%x: %d) called\n", (int)n, n->type));
    199  1.1  cgd 	switch (n->type) {
    200  1.1  cgd 	case NSEMI:
    201  1.1  cgd 		evaltree(n->nbinary.ch1, 0);
    202  1.1  cgd 		if (evalskip)
    203  1.1  cgd 			goto out;
    204  1.1  cgd 		evaltree(n->nbinary.ch2, flags);
    205  1.1  cgd 		break;
    206  1.1  cgd 	case NAND:
    207  1.1  cgd 		evaltree(n->nbinary.ch1, EV_TESTED);
    208  1.1  cgd 		if (evalskip || exitstatus != 0)
    209  1.1  cgd 			goto out;
    210  1.1  cgd 		evaltree(n->nbinary.ch2, flags);
    211  1.1  cgd 		break;
    212  1.1  cgd 	case NOR:
    213  1.1  cgd 		evaltree(n->nbinary.ch1, EV_TESTED);
    214  1.1  cgd 		if (evalskip || exitstatus == 0)
    215  1.1  cgd 			goto out;
    216  1.1  cgd 		evaltree(n->nbinary.ch2, flags);
    217  1.1  cgd 		break;
    218  1.1  cgd 	case NREDIR:
    219  1.1  cgd 		expredir(n->nredir.redirect);
    220  1.1  cgd 		redirect(n->nredir.redirect, REDIR_PUSH);
    221  1.1  cgd 		evaltree(n->nredir.n, flags);
    222  1.1  cgd 		popredir();
    223  1.1  cgd 		break;
    224  1.1  cgd 	case NSUBSHELL:
    225  1.1  cgd 		evalsubshell(n, flags);
    226  1.1  cgd 		break;
    227  1.1  cgd 	case NBACKGND:
    228  1.1  cgd 		evalsubshell(n, flags);
    229  1.1  cgd 		break;
    230  1.1  cgd 	case NIF: {
    231  1.1  cgd 		int status = 0;
    232  1.1  cgd 
    233  1.1  cgd 		evaltree(n->nif.test, EV_TESTED);
    234  1.1  cgd 		if (evalskip)
    235  1.1  cgd 			goto out;
    236  1.1  cgd 		if (exitstatus == 0) {
    237  1.1  cgd 			evaltree(n->nif.ifpart, flags);
    238  1.1  cgd 			status = exitstatus;
    239  1.1  cgd 		} else if (n->nif.elsepart) {
    240  1.1  cgd 			evaltree(n->nif.elsepart, flags);
    241  1.1  cgd 			status = exitstatus;
    242  1.1  cgd 		}
    243  1.1  cgd 		exitstatus = status;
    244  1.1  cgd 		break;
    245  1.1  cgd 	}
    246  1.1  cgd 	case NWHILE:
    247  1.1  cgd 	case NUNTIL:
    248  1.1  cgd 		evalloop(n);
    249  1.1  cgd 		break;
    250  1.1  cgd 	case NFOR:
    251  1.1  cgd 		evalfor(n);
    252  1.1  cgd 		break;
    253  1.1  cgd 	case NCASE:
    254  1.1  cgd 		evalcase(n, flags);
    255  1.1  cgd 		break;
    256  1.1  cgd 	case NDEFUN:
    257  1.1  cgd 		defun(n->narg.text, n->narg.next);
    258  1.1  cgd 		exitstatus = 0;
    259  1.1  cgd 		break;
    260  1.1  cgd 	case NPIPE:
    261  1.1  cgd 		evalpipe(n);
    262  1.1  cgd 		break;
    263  1.1  cgd 	case NCMD:
    264  1.1  cgd 		evalcommand(n, flags, (struct backcmd *)NULL);
    265  1.1  cgd 		break;
    266  1.1  cgd 	default:
    267  1.1  cgd 		out1fmt("Node type = %d\n", n->type);
    268  1.1  cgd 		flushout(&output);
    269  1.1  cgd 		break;
    270  1.1  cgd 	}
    271  1.1  cgd out:
    272  1.1  cgd 	if (pendingsigs)
    273  1.1  cgd 		dotrap();
    274  1.1  cgd 	if ((flags & EV_EXIT) || (eflag && exitstatus && !(flags & EV_TESTED)))
    275  1.1  cgd 		exitshell(exitstatus);
    276  1.1  cgd }
    277  1.1  cgd 
    278  1.1  cgd 
    279  1.1  cgd STATIC void
    280  1.1  cgd evalloop(n)
    281  1.1  cgd 	union node *n;
    282  1.1  cgd 	{
    283  1.1  cgd 	int status;
    284  1.1  cgd 
    285  1.1  cgd 	loopnest++;
    286  1.1  cgd 	status = 0;
    287  1.1  cgd 	for (;;) {
    288  1.1  cgd 		evaltree(n->nbinary.ch1, EV_TESTED);
    289  1.1  cgd 		if (evalskip) {
    290  1.1  cgd skipping:	  if (evalskip == SKIPCONT && --skipcount <= 0) {
    291  1.1  cgd 				evalskip = 0;
    292  1.1  cgd 				continue;
    293  1.1  cgd 			}
    294  1.1  cgd 			if (evalskip == SKIPBREAK && --skipcount <= 0)
    295  1.1  cgd 				evalskip = 0;
    296  1.1  cgd 			break;
    297  1.1  cgd 		}
    298  1.1  cgd 		if (n->type == NWHILE) {
    299  1.1  cgd 			if (exitstatus != 0)
    300  1.1  cgd 				break;
    301  1.1  cgd 		} else {
    302  1.1  cgd 			if (exitstatus == 0)
    303  1.1  cgd 				break;
    304  1.1  cgd 		}
    305  1.1  cgd 		evaltree(n->nbinary.ch2, 0);
    306  1.1  cgd 		status = exitstatus;
    307  1.1  cgd 		if (evalskip)
    308  1.1  cgd 			goto skipping;
    309  1.1  cgd 	}
    310  1.1  cgd 	loopnest--;
    311  1.1  cgd 	exitstatus = status;
    312  1.1  cgd }
    313  1.1  cgd 
    314  1.1  cgd 
    315  1.1  cgd 
    316  1.1  cgd STATIC void
    317  1.1  cgd evalfor(n)
    318  1.1  cgd 	union node *n;
    319  1.1  cgd 	{
    320  1.1  cgd 	struct arglist arglist;
    321  1.1  cgd 	union node *argp;
    322  1.1  cgd 	struct strlist *sp;
    323  1.1  cgd 	struct stackmark smark;
    324  1.1  cgd 
    325  1.1  cgd 	setstackmark(&smark);
    326  1.1  cgd 	arglist.lastp = &arglist.list;
    327  1.1  cgd 	for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
    328  1.1  cgd 		expandarg(argp, &arglist, 1);
    329  1.1  cgd 		if (evalskip)
    330  1.1  cgd 			goto out;
    331  1.1  cgd 	}
    332  1.1  cgd 	*arglist.lastp = NULL;
    333  1.1  cgd 
    334  1.1  cgd 	exitstatus = 0;
    335  1.1  cgd 	loopnest++;
    336  1.1  cgd 	for (sp = arglist.list ; sp ; sp = sp->next) {
    337  1.1  cgd 		setvar(n->nfor.var, sp->text, 0);
    338  1.1  cgd 		evaltree(n->nfor.body, 0);
    339  1.1  cgd 		if (evalskip) {
    340  1.1  cgd 			if (evalskip == SKIPCONT && --skipcount <= 0) {
    341  1.1  cgd 				evalskip = 0;
    342  1.1  cgd 				continue;
    343  1.1  cgd 			}
    344  1.1  cgd 			if (evalskip == SKIPBREAK && --skipcount <= 0)
    345  1.1  cgd 				evalskip = 0;
    346  1.1  cgd 			break;
    347  1.1  cgd 		}
    348  1.1  cgd 	}
    349  1.1  cgd 	loopnest--;
    350  1.1  cgd out:
    351  1.1  cgd 	popstackmark(&smark);
    352  1.1  cgd }
    353  1.1  cgd 
    354  1.1  cgd 
    355  1.1  cgd 
    356  1.1  cgd STATIC void
    357  1.1  cgd evalcase(n, flags)
    358  1.1  cgd 	union node *n;
    359  1.1  cgd 	{
    360  1.1  cgd 	union node *cp;
    361  1.1  cgd 	union node *patp;
    362  1.1  cgd 	struct arglist arglist;
    363  1.1  cgd 	struct stackmark smark;
    364  1.1  cgd 
    365  1.1  cgd 	setstackmark(&smark);
    366  1.1  cgd 	arglist.lastp = &arglist.list;
    367  1.1  cgd 	expandarg(n->ncase.expr, &arglist, 0);
    368  1.1  cgd 	for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
    369  1.1  cgd 		for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
    370  1.1  cgd 			if (casematch(patp, arglist.list->text)) {
    371  1.1  cgd 				if (evalskip == 0) {
    372  1.1  cgd 					evaltree(cp->nclist.body, flags);
    373  1.1  cgd 				}
    374  1.1  cgd 				goto out;
    375  1.1  cgd 			}
    376  1.1  cgd 		}
    377  1.1  cgd 	}
    378  1.1  cgd out:
    379  1.1  cgd 	popstackmark(&smark);
    380  1.1  cgd }
    381  1.1  cgd 
    382  1.1  cgd 
    383  1.1  cgd 
    384  1.1  cgd /*
    385  1.1  cgd  * Kick off a subshell to evaluate a tree.
    386  1.1  cgd  */
    387  1.1  cgd 
    388  1.1  cgd STATIC void
    389  1.1  cgd evalsubshell(n, flags)
    390  1.1  cgd 	union node *n;
    391  1.1  cgd 	{
    392  1.1  cgd 	struct job *jp;
    393  1.1  cgd 	int backgnd = (n->type == NBACKGND);
    394  1.1  cgd 
    395  1.1  cgd 	expredir(n->nredir.redirect);
    396  1.1  cgd 	jp = makejob(n, 1);
    397  1.1  cgd 	if (forkshell(jp, n, backgnd) == 0) {
    398  1.1  cgd 		if (backgnd)
    399  1.1  cgd 			flags &=~ EV_TESTED;
    400  1.1  cgd 		redirect(n->nredir.redirect, 0);
    401  1.1  cgd 		evaltree(n->nredir.n, flags | EV_EXIT);	/* never returns */
    402  1.1  cgd 	}
    403  1.1  cgd 	if (! backgnd) {
    404  1.1  cgd 		INTOFF;
    405  1.1  cgd 		exitstatus = waitforjob(jp);
    406  1.1  cgd 		INTON;
    407  1.1  cgd 	}
    408  1.1  cgd }
    409  1.1  cgd 
    410  1.1  cgd 
    411  1.1  cgd 
    412  1.1  cgd /*
    413  1.1  cgd  * Compute the names of the files in a redirection list.
    414  1.1  cgd  */
    415  1.1  cgd 
    416  1.1  cgd STATIC void
    417  1.1  cgd expredir(n)
    418  1.1  cgd 	union node *n;
    419  1.1  cgd 	{
    420  1.1  cgd 	register union node *redir;
    421  1.1  cgd 
    422  1.1  cgd 	for (redir = n ; redir ; redir = redir->nfile.next) {
    423  1.1  cgd 		if (redir->type == NFROM
    424  1.1  cgd 		 || redir->type == NTO
    425  1.1  cgd 		 || redir->type == NAPPEND) {
    426  1.1  cgd 			struct arglist fn;
    427  1.1  cgd 			fn.lastp = &fn.list;
    428  1.1  cgd 			expandarg(redir->nfile.fname, &fn, 0);
    429  1.1  cgd 			redir->nfile.expfname = fn.list->text;
    430  1.1  cgd 		}
    431  1.1  cgd 	}
    432  1.1  cgd }
    433  1.1  cgd 
    434  1.1  cgd 
    435  1.1  cgd 
    436  1.1  cgd /*
    437  1.1  cgd  * Evaluate a pipeline.  All the processes in the pipeline are children
    438  1.1  cgd  * of the process creating the pipeline.  (This differs from some versions
    439  1.1  cgd  * of the shell, which make the last process in a pipeline the parent
    440  1.1  cgd  * of all the rest.)
    441  1.1  cgd  */
    442  1.1  cgd 
    443  1.1  cgd STATIC void
    444  1.1  cgd evalpipe(n)
    445  1.1  cgd 	union node *n;
    446  1.1  cgd 	{
    447  1.1  cgd 	struct job *jp;
    448  1.1  cgd 	struct nodelist *lp;
    449  1.1  cgd 	int pipelen;
    450  1.1  cgd 	int prevfd;
    451  1.1  cgd 	int pip[2];
    452  1.1  cgd 
    453  1.1  cgd 	TRACE(("evalpipe(0x%x) called\n", (int)n));
    454  1.1  cgd 	pipelen = 0;
    455  1.1  cgd 	for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
    456  1.1  cgd 		pipelen++;
    457  1.1  cgd 	INTOFF;
    458  1.1  cgd 	jp = makejob(n, pipelen);
    459  1.1  cgd 	prevfd = -1;
    460  1.1  cgd 	for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
    461  1.1  cgd 		prehash(lp->n);
    462  1.1  cgd 		pip[1] = -1;
    463  1.1  cgd 		if (lp->next) {
    464  1.1  cgd 			if (pipe(pip) < 0) {
    465  1.1  cgd 				close(prevfd);
    466  1.1  cgd 				error("Pipe call failed");
    467  1.1  cgd 			}
    468  1.1  cgd 		}
    469  1.1  cgd 		if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
    470  1.1  cgd 			INTON;
    471  1.1  cgd 			if (prevfd > 0) {
    472  1.1  cgd 				close(0);
    473  1.1  cgd 				copyfd(prevfd, 0);
    474  1.1  cgd 				close(prevfd);
    475  1.1  cgd 			}
    476  1.1  cgd 			if (pip[1] >= 0) {
    477  1.1  cgd 				close(pip[0]);
    478  1.1  cgd 				if (pip[1] != 1) {
    479  1.1  cgd 					close(1);
    480  1.1  cgd 					copyfd(pip[1], 1);
    481  1.1  cgd 					close(pip[1]);
    482  1.1  cgd 				}
    483  1.1  cgd 			}
    484  1.1  cgd 			evaltree(lp->n, EV_EXIT);
    485  1.1  cgd 		}
    486  1.1  cgd 		if (prevfd >= 0)
    487  1.1  cgd 			close(prevfd);
    488  1.1  cgd 		prevfd = pip[0];
    489  1.1  cgd 		close(pip[1]);
    490  1.1  cgd 	}
    491  1.1  cgd 	INTON;
    492  1.1  cgd 	if (n->npipe.backgnd == 0) {
    493  1.1  cgd 		INTOFF;
    494  1.1  cgd 		exitstatus = waitforjob(jp);
    495  1.1  cgd 		TRACE(("evalpipe:  job done exit status %d\n", exitstatus));
    496  1.1  cgd 		INTON;
    497  1.1  cgd 	}
    498  1.1  cgd }
    499  1.1  cgd 
    500  1.1  cgd 
    501  1.1  cgd 
    502  1.1  cgd /*
    503  1.1  cgd  * Execute a command inside back quotes.  If it's a builtin command, we
    504  1.1  cgd  * want to save its output in a block obtained from malloc.  Otherwise
    505  1.1  cgd  * we fork off a subprocess and get the output of the command via a pipe.
    506  1.1  cgd  * Should be called with interrupts off.
    507  1.1  cgd  */
    508  1.1  cgd 
    509  1.1  cgd void
    510  1.1  cgd evalbackcmd(n, result)
    511  1.1  cgd 	union node *n;
    512  1.1  cgd 	struct backcmd *result;
    513  1.1  cgd 	{
    514  1.1  cgd 	int pip[2];
    515  1.1  cgd 	struct job *jp;
    516  1.1  cgd 	struct stackmark smark;		/* unnecessary */
    517  1.1  cgd 
    518  1.1  cgd 	setstackmark(&smark);
    519  1.1  cgd 	result->fd = -1;
    520  1.1  cgd 	result->buf = NULL;
    521  1.1  cgd 	result->nleft = 0;
    522  1.1  cgd 	result->jp = NULL;
    523  1.1  cgd 	if (n->type == NCMD) {
    524  1.1  cgd 		evalcommand(n, EV_BACKCMD, result);
    525  1.1  cgd 	} else {
    526  1.1  cgd 		if (pipe(pip) < 0)
    527  1.1  cgd 			error("Pipe call failed");
    528  1.1  cgd 		jp = makejob(n, 1);
    529  1.1  cgd 		if (forkshell(jp, n, FORK_NOJOB) == 0) {
    530  1.1  cgd 			FORCEINTON;
    531  1.1  cgd 			close(pip[0]);
    532  1.1  cgd 			if (pip[1] != 1) {
    533  1.1  cgd 				close(1);
    534  1.1  cgd 				copyfd(pip[1], 1);
    535  1.1  cgd 				close(pip[1]);
    536  1.1  cgd 			}
    537  1.1  cgd 			evaltree(n, EV_EXIT);
    538  1.1  cgd 		}
    539  1.1  cgd 		close(pip[1]);
    540  1.1  cgd 		result->fd = pip[0];
    541  1.1  cgd 		result->jp = jp;
    542  1.1  cgd 	}
    543  1.1  cgd 	popstackmark(&smark);
    544  1.1  cgd 	TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
    545  1.1  cgd 		result->fd, result->buf, result->nleft, result->jp));
    546  1.1  cgd }
    547  1.1  cgd 
    548  1.1  cgd 
    549  1.1  cgd 
    550  1.1  cgd /*
    551  1.1  cgd  * Execute a simple command.
    552  1.1  cgd  */
    553  1.1  cgd 
    554  1.1  cgd STATIC void
    555  1.1  cgd evalcommand(cmd, flags, backcmd)
    556  1.1  cgd 	union node *cmd;
    557  1.1  cgd 	struct backcmd *backcmd;
    558  1.1  cgd 	{
    559  1.1  cgd 	struct stackmark smark;
    560  1.1  cgd 	union node *argp;
    561  1.1  cgd 	struct arglist arglist;
    562  1.1  cgd 	struct arglist varlist;
    563  1.1  cgd 	char **argv;
    564  1.1  cgd 	int argc;
    565  1.1  cgd 	char **envp;
    566  1.1  cgd 	int varflag;
    567  1.1  cgd 	struct strlist *sp;
    568  1.1  cgd 	register char *p;
    569  1.1  cgd 	int mode;
    570  1.1  cgd 	int pip[2];
    571  1.1  cgd 	struct cmdentry cmdentry;
    572  1.1  cgd 	struct job *jp;
    573  1.1  cgd 	struct jmploc jmploc;
    574  1.1  cgd 	struct jmploc *volatile savehandler;
    575  1.1  cgd 	char *volatile savecmdname;
    576  1.1  cgd 	volatile struct shparam saveparam;
    577  1.1  cgd 	struct localvar *volatile savelocalvars;
    578  1.1  cgd 	volatile int e;
    579  1.1  cgd 	char *lastarg;
    580  1.1  cgd 
    581  1.1  cgd 	/* First expand the arguments. */
    582  1.1  cgd 	TRACE(("evalcommand(0x%x, %d) called\n", (int)cmd, flags));
    583  1.1  cgd 	setstackmark(&smark);
    584  1.1  cgd 	arglist.lastp = &arglist.list;
    585  1.1  cgd 	varlist.lastp = &varlist.list;
    586  1.1  cgd 	varflag = 1;
    587  1.1  cgd 	for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
    588  1.1  cgd 		p = argp->narg.text;
    589  1.1  cgd 		if (varflag && is_name(*p)) {
    590  1.1  cgd 			do {
    591  1.1  cgd 				p++;
    592  1.1  cgd 			} while (is_in_name(*p));
    593  1.1  cgd 			if (*p == '=') {
    594  1.1  cgd 				expandarg(argp, &varlist, 0);
    595  1.1  cgd 				continue;
    596  1.1  cgd 			}
    597  1.1  cgd 		}
    598  1.1  cgd 		expandarg(argp, &arglist, 1);
    599  1.1  cgd 		varflag = 0;
    600  1.1  cgd 	}
    601  1.1  cgd 	*arglist.lastp = NULL;
    602  1.1  cgd 	*varlist.lastp = NULL;
    603  1.1  cgd 	expredir(cmd->ncmd.redirect);
    604  1.1  cgd 	argc = 0;
    605  1.1  cgd 	for (sp = arglist.list ; sp ; sp = sp->next)
    606  1.1  cgd 		argc++;
    607  1.1  cgd 	argv = stalloc(sizeof (char *) * (argc + 1));
    608  1.1  cgd 	for (sp = arglist.list ; sp ; sp = sp->next)
    609  1.1  cgd 		*argv++ = sp->text;
    610  1.1  cgd 	*argv = NULL;
    611  1.1  cgd 	lastarg = NULL;
    612  1.1  cgd 	if (iflag && funcnest == 0 && argc > 0)
    613  1.1  cgd 		lastarg = argv[-1];
    614  1.1  cgd 	argv -= argc;
    615  1.1  cgd 
    616  1.1  cgd 	/* Print the command if xflag is set. */
    617  1.1  cgd 	if (xflag) {
    618  1.1  cgd 		outc('+', &errout);
    619  1.1  cgd 		for (sp = varlist.list ; sp ; sp = sp->next) {
    620  1.1  cgd 			outc(' ', &errout);
    621  1.1  cgd 			out2str(sp->text);
    622  1.1  cgd 		}
    623  1.1  cgd 		for (sp = arglist.list ; sp ; sp = sp->next) {
    624  1.1  cgd 			outc(' ', &errout);
    625  1.1  cgd 			out2str(sp->text);
    626  1.1  cgd 		}
    627  1.1  cgd 		outc('\n', &errout);
    628  1.1  cgd 		flushout(&errout);
    629  1.1  cgd 	}
    630  1.1  cgd 
    631  1.1  cgd 	/* Now locate the command. */
    632  1.1  cgd 	if (argc == 0) {
    633  1.1  cgd 		cmdentry.cmdtype = CMDBUILTIN;
    634  1.1  cgd 		cmdentry.u.index = BLTINCMD;
    635  1.1  cgd 	} else {
    636  1.1  cgd 		find_command(argv[0], &cmdentry, 1);
    637  1.1  cgd 		if (cmdentry.cmdtype == CMDUNKNOWN) {	/* command not found */
    638  1.1  cgd 			exitstatus = 2;
    639  1.1  cgd 			flushout(&errout);
    640  1.1  cgd 			return;
    641  1.1  cgd 		}
    642  1.1  cgd 		/* implement the bltin builtin here */
    643  1.1  cgd 		if (cmdentry.cmdtype == CMDBUILTIN && cmdentry.u.index == BLTINCMD) {
    644  1.1  cgd 			for (;;) {
    645  1.1  cgd 				argv++;
    646  1.1  cgd 				if (--argc == 0)
    647  1.1  cgd 					break;
    648  1.1  cgd 				if ((cmdentry.u.index = find_builtin(*argv)) < 0) {
    649  1.1  cgd 					outfmt(&errout, "%s: not found\n", *argv);
    650  1.1  cgd 					exitstatus = 2;
    651  1.1  cgd 					flushout(&errout);
    652  1.1  cgd 					return;
    653  1.1  cgd 				}
    654  1.1  cgd 				if (cmdentry.u.index != BLTINCMD)
    655  1.1  cgd 					break;
    656  1.1  cgd 			}
    657  1.1  cgd 		}
    658  1.1  cgd 	}
    659  1.1  cgd 
    660  1.1  cgd 	/* Fork off a child process if necessary. */
    661  1.1  cgd 	if (cmd->ncmd.backgnd
    662  1.1  cgd 	 || cmdentry.cmdtype == CMDNORMAL && (flags & EV_EXIT) == 0
    663  1.1  cgd 	 || (flags & EV_BACKCMD) != 0
    664  1.1  cgd 	    && (cmdentry.cmdtype != CMDBUILTIN
    665  1.1  cgd 		 || cmdentry.u.index == DOTCMD
    666  1.1  cgd 		 || cmdentry.u.index == EVALCMD)) {
    667  1.1  cgd 		jp = makejob(cmd, 1);
    668  1.1  cgd 		mode = cmd->ncmd.backgnd;
    669  1.1  cgd 		if (flags & EV_BACKCMD) {
    670  1.1  cgd 			mode = FORK_NOJOB;
    671  1.1  cgd 			if (pipe(pip) < 0)
    672  1.1  cgd 				error("Pipe call failed");
    673  1.1  cgd 		}
    674  1.1  cgd 		if (forkshell(jp, cmd, mode) != 0)
    675  1.1  cgd 			goto parent;	/* at end of routine */
    676  1.1  cgd 		if (flags & EV_BACKCMD) {
    677  1.1  cgd 			FORCEINTON;
    678  1.1  cgd 			close(pip[0]);
    679  1.1  cgd 			if (pip[1] != 1) {
    680  1.1  cgd 				close(1);
    681  1.1  cgd 				copyfd(pip[1], 1);
    682  1.1  cgd 				close(pip[1]);
    683  1.1  cgd 			}
    684  1.1  cgd 		}
    685  1.1  cgd 		flags |= EV_EXIT;
    686  1.1  cgd 	}
    687  1.1  cgd 
    688  1.1  cgd 	/* This is the child process if a fork occurred. */
    689  1.1  cgd 	/* Execute the command. */
    690  1.1  cgd 	if (cmdentry.cmdtype == CMDFUNCTION) {
    691  1.1  cgd 		trputs("Shell function:  ");  trargs(argv);
    692  1.1  cgd 		redirect(cmd->ncmd.redirect, REDIR_PUSH);
    693  1.1  cgd 		saveparam = shellparam;
    694  1.1  cgd 		shellparam.malloc = 0;
    695  1.1  cgd 		shellparam.nparam = argc - 1;
    696  1.1  cgd 		shellparam.p = argv + 1;
    697  1.1  cgd 		shellparam.optnext = NULL;
    698  1.1  cgd 		INTOFF;
    699  1.1  cgd 		savelocalvars = localvars;
    700  1.1  cgd 		localvars = NULL;
    701  1.1  cgd 		INTON;
    702  1.1  cgd 		if (setjmp(jmploc.loc)) {
    703  1.1  cgd 			if (exception == EXSHELLPROC)
    704  1.1  cgd 				freeparam((struct shparam *)&saveparam);
    705  1.1  cgd 			else {
    706  1.1  cgd 				freeparam(&shellparam);
    707  1.1  cgd 				shellparam = saveparam;
    708  1.1  cgd 			}
    709  1.1  cgd 			poplocalvars();
    710  1.1  cgd 			localvars = savelocalvars;
    711  1.1  cgd 			handler = savehandler;
    712  1.1  cgd 			longjmp(handler->loc, 1);
    713  1.1  cgd 		}
    714  1.1  cgd 		savehandler = handler;
    715  1.1  cgd 		handler = &jmploc;
    716  1.1  cgd 		for (sp = varlist.list ; sp ; sp = sp->next)
    717  1.1  cgd 			mklocal(sp->text);
    718  1.1  cgd 		funcnest++;
    719  1.1  cgd 		evaltree(cmdentry.u.func, 0);
    720  1.1  cgd 		funcnest--;
    721  1.1  cgd 		INTOFF;
    722  1.1  cgd 		poplocalvars();
    723  1.1  cgd 		localvars = savelocalvars;
    724  1.1  cgd 		freeparam(&shellparam);
    725  1.1  cgd 		shellparam = saveparam;
    726  1.1  cgd 		handler = savehandler;
    727  1.1  cgd 		popredir();
    728  1.1  cgd 		INTON;
    729  1.1  cgd 		if (evalskip == SKIPFUNC) {
    730  1.1  cgd 			evalskip = 0;
    731  1.1  cgd 			skipcount = 0;
    732  1.1  cgd 		}
    733  1.1  cgd 		if (flags & EV_EXIT)
    734  1.1  cgd 			exitshell(exitstatus);
    735  1.1  cgd 	} else if (cmdentry.cmdtype == CMDBUILTIN) {
    736  1.1  cgd 		trputs("builtin command:  ");  trargs(argv);
    737  1.1  cgd 		mode = (cmdentry.u.index == EXECCMD)? 0 : REDIR_PUSH;
    738  1.1  cgd 		if (flags == EV_BACKCMD) {
    739  1.1  cgd 			memout.nleft = 0;
    740  1.1  cgd 			memout.nextc = memout.buf;
    741  1.1  cgd 			memout.bufsize = 64;
    742  1.1  cgd 			mode |= REDIR_BACKQ;
    743  1.1  cgd 		}
    744  1.1  cgd 		redirect(cmd->ncmd.redirect, mode);
    745  1.1  cgd 		savecmdname = commandname;
    746  1.1  cgd 		cmdenviron = varlist.list;
    747  1.1  cgd 		e = -1;
    748  1.1  cgd 		if (setjmp(jmploc.loc)) {
    749  1.1  cgd 			e = exception;
    750  1.1  cgd 			exitstatus = (e == EXINT)? SIGINT+128 : 2;
    751  1.1  cgd 			goto cmddone;
    752  1.1  cgd 		}
    753  1.1  cgd 		savehandler = handler;
    754  1.1  cgd 		handler = &jmploc;
    755  1.1  cgd 		commandname = argv[0];
    756  1.1  cgd 		argptr = argv + 1;
    757  1.1  cgd 		optptr = NULL;			/* initialize nextopt */
    758  1.1  cgd 		exitstatus = (*builtinfunc[cmdentry.u.index])(argc, argv);
    759  1.1  cgd 		flushall();
    760  1.1  cgd cmddone:
    761  1.1  cgd 		out1 = &output;
    762  1.1  cgd 		out2 = &errout;
    763  1.1  cgd 		freestdout();
    764  1.1  cgd 		if (e != EXSHELLPROC) {
    765  1.1  cgd 			commandname = savecmdname;
    766  1.1  cgd 			if (flags & EV_EXIT) {
    767  1.1  cgd 				exitshell(exitstatus);
    768  1.1  cgd 			}
    769  1.1  cgd 		}
    770  1.1  cgd 		handler = savehandler;
    771  1.1  cgd 		if (e != -1) {
    772  1.1  cgd 			if (e != EXERROR || cmdentry.u.index == BLTINCMD
    773  1.1  cgd 					       || cmdentry.u.index == DOTCMD
    774  1.1  cgd 					       || cmdentry.u.index == EVALCMD
    775  1.1  cgd 					       || cmdentry.u.index == EXECCMD)
    776  1.1  cgd 				exraise(e);
    777  1.1  cgd 			FORCEINTON;
    778  1.1  cgd 		}
    779  1.1  cgd 		if (cmdentry.u.index != EXECCMD)
    780  1.1  cgd 			popredir();
    781  1.1  cgd 		if (flags == EV_BACKCMD) {
    782  1.1  cgd 			backcmd->buf = memout.buf;
    783  1.1  cgd 			backcmd->nleft = memout.nextc - memout.buf;
    784  1.1  cgd 			memout.buf = NULL;
    785  1.1  cgd 		}
    786  1.1  cgd 	} else {
    787  1.1  cgd 		trputs("normal command:  ");  trargs(argv);
    788  1.1  cgd 		clearredir();
    789  1.1  cgd 		redirect(cmd->ncmd.redirect, 0);
    790  1.1  cgd 		if (varlist.list) {
    791  1.1  cgd 			p = stalloc(strlen(pathval()) + 1);
    792  1.1  cgd 			scopy(pathval(), p);
    793  1.1  cgd 		} else {
    794  1.1  cgd 			p = pathval();
    795  1.1  cgd 		}
    796  1.1  cgd 		for (sp = varlist.list ; sp ; sp = sp->next)
    797  1.1  cgd 			setvareq(sp->text, VEXPORT|VSTACK);
    798  1.1  cgd 		envp = environment();
    799  1.1  cgd 		shellexec(argv, envp, p, cmdentry.u.index);
    800  1.1  cgd 		/*NOTREACHED*/
    801  1.1  cgd 	}
    802  1.1  cgd 	goto out;
    803  1.1  cgd 
    804  1.1  cgd parent:	/* parent process gets here (if we forked) */
    805  1.1  cgd 	if (mode == 0) {	/* argument to fork */
    806  1.1  cgd 		INTOFF;
    807  1.1  cgd 		exitstatus = waitforjob(jp);
    808  1.1  cgd 		INTON;
    809  1.1  cgd 	} else if (mode == 2) {
    810  1.1  cgd 		backcmd->fd = pip[0];
    811  1.1  cgd 		close(pip[1]);
    812  1.1  cgd 		backcmd->jp = jp;
    813  1.1  cgd 	}
    814  1.1  cgd 
    815  1.1  cgd out:
    816  1.1  cgd 	if (lastarg)
    817  1.1  cgd 		setvar("_", lastarg, 0);
    818  1.1  cgd 	popstackmark(&smark);
    819  1.1  cgd }
    820  1.1  cgd 
    821  1.1  cgd 
    822  1.1  cgd 
    823  1.1  cgd /*
    824  1.1  cgd  * Search for a command.  This is called before we fork so that the
    825  1.1  cgd  * location of the command will be available in the parent as well as
    826  1.1  cgd  * the child.  The check for "goodname" is an overly conservative
    827  1.1  cgd  * check that the name will not be subject to expansion.
    828  1.1  cgd  */
    829  1.1  cgd 
    830  1.1  cgd STATIC void
    831  1.1  cgd prehash(n)
    832  1.1  cgd 	union node *n;
    833  1.1  cgd 	{
    834  1.1  cgd 	struct cmdentry entry;
    835  1.1  cgd 
    836  1.1  cgd 	if (n->type == NCMD && goodname(n->ncmd.args->narg.text))
    837  1.1  cgd 		find_command(n->ncmd.args->narg.text, &entry, 0);
    838  1.1  cgd }
    839  1.1  cgd 
    840  1.1  cgd 
    841  1.1  cgd 
    842  1.1  cgd /*
    843  1.1  cgd  * Builtin commands.  Builtin commands whose functions are closely
    844  1.1  cgd  * tied to evaluation are implemented here.
    845  1.1  cgd  */
    846  1.1  cgd 
    847  1.1  cgd /*
    848  1.1  cgd  * No command given, or a bltin command with no arguments.  Set the
    849  1.1  cgd  * specified variables.
    850  1.1  cgd  */
    851  1.1  cgd 
    852  1.1  cgd bltincmd(argc, argv)  char **argv; {
    853  1.1  cgd 	listsetvar(cmdenviron);
    854  1.1  cgd 	return exitstatus;
    855  1.1  cgd }
    856  1.1  cgd 
    857  1.1  cgd 
    858  1.1  cgd /*
    859  1.1  cgd  * Handle break and continue commands.  Break, continue, and return are
    860  1.1  cgd  * all handled by setting the evalskip flag.  The evaluation routines
    861  1.1  cgd  * above all check this flag, and if it is set they start skipping
    862  1.1  cgd  * commands rather than executing them.  The variable skipcount is
    863  1.1  cgd  * the number of loops to break/continue, or the number of function
    864  1.1  cgd  * levels to return.  (The latter is always 1.)  It should probably
    865  1.1  cgd  * be an error to break out of more loops than exist, but it isn't
    866  1.1  cgd  * in the standard shell so we don't make it one here.
    867  1.1  cgd  */
    868  1.1  cgd 
    869  1.1  cgd breakcmd(argc, argv)  char **argv; {
    870  1.1  cgd 	int n;
    871  1.1  cgd 
    872  1.1  cgd 	n = 1;
    873  1.1  cgd 	if (argc > 1)
    874  1.1  cgd 		n = number(argv[1]);
    875  1.1  cgd 	if (n > loopnest)
    876  1.1  cgd 		n = loopnest;
    877  1.1  cgd 	if (n > 0) {
    878  1.1  cgd 		evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
    879  1.1  cgd 		skipcount = n;
    880  1.1  cgd 	}
    881  1.1  cgd 	return 0;
    882  1.1  cgd }
    883  1.1  cgd 
    884  1.1  cgd 
    885  1.1  cgd /*
    886  1.1  cgd  * The return command.
    887  1.1  cgd  */
    888  1.1  cgd 
    889  1.1  cgd returncmd(argc, argv)  char **argv; {
    890  1.1  cgd 	int ret;
    891  1.1  cgd 
    892  1.1  cgd 	ret = exitstatus;
    893  1.1  cgd 	if (argc > 1)
    894  1.1  cgd 		ret = number(argv[1]);
    895  1.1  cgd 	if (funcnest) {
    896  1.1  cgd 		evalskip = SKIPFUNC;
    897  1.1  cgd 		skipcount = 1;
    898  1.1  cgd 	}
    899  1.1  cgd 	return ret;
    900  1.1  cgd }
    901  1.1  cgd 
    902  1.1  cgd 
    903  1.1  cgd truecmd(argc, argv)  char **argv; {
    904  1.1  cgd 	return 0;
    905  1.1  cgd }
    906  1.1  cgd 
    907  1.1  cgd 
    908  1.1  cgd execcmd(argc, argv)  char **argv; {
    909  1.1  cgd 	if (argc > 1) {
    910  1.1  cgd 		iflag = 0;		/* exit on error */
    911  1.1  cgd 		setinteractive(0);
    912  1.1  cgd #if JOBS
    913  1.1  cgd 		jflag = 0;
    914  1.1  cgd 		setjobctl(0);
    915  1.1  cgd #endif
    916  1.1  cgd 		shellexec(argv + 1, environment(), pathval(), 0);
    917  1.1  cgd 
    918  1.1  cgd 	}
    919  1.1  cgd 	return 0;
    920  1.1  cgd }
    921