172339Sabial#define Extern extern
272339Sabial#include <sys/types.h>
372339Sabial#include <signal.h>
472339Sabial#define _NSIG NSIG
572339Sabial#include <errno.h>
672339Sabial#include <setjmp.h>
772339Sabial#include <stddef.h>
872339Sabial#include <time.h>
972339Sabial#include <sys/times.h>
1072339Sabial#include <sys/stat.h>
1172339Sabial#include <sys/wait.h>
1272339Sabial#undef NULL
1372339Sabial#include "sh.h"
1472339Sabial
1572339Sabial/* -------- exec.c -------- */
1672339Sabial/* #include "sh.h" */
1772339Sabial
1872339Sabial/*
1972339Sabial * execute tree
2072339Sabial */
2172339Sabial
2272339Sabialstatic	char	*signame[] = {
2372339Sabial	"Signal 0",
2472339Sabial	"Hangup",
2572339Sabial	(char *)NULL,	/* interrupt */
2672339Sabial	"Quit",
2772339Sabial	"Illegal instruction",
2872339Sabial	"Trace/BPT trap",
2972339Sabial	"Abort",
3072339Sabial	"EMT trap",
3172339Sabial	"Floating exception",
3272339Sabial	"Killed",
3372339Sabial	"Bus error",
3472339Sabial	"Memory fault",
3572339Sabial	"Bad system call",
3672339Sabial	(char *)NULL,	/* broken pipe */
3772339Sabial	"Alarm clock",
3872339Sabial	"Terminated",
3972339Sabial};
4072339Sabial#define	NSIGNAL (sizeof(signame)/sizeof(signame[0]))
4172339Sabial
4272339Sabial
4372339Sabial_PROTOTYPE(static int forkexec, (struct op *t, int *pin, int *pout, int act, char **wp, int *pforked ));
4472339Sabial_PROTOTYPE(static int parent, (void));
4572339Sabial_PROTOTYPE(int iosetup, (struct ioword *iop, int pipein, int pipeout ));
4672339Sabial_PROTOTYPE(static void echo, (char **wp ));
4772339Sabial_PROTOTYPE(static struct op **find1case, (struct op *t, char *w ));
4872339Sabial_PROTOTYPE(static struct op *findcase, (struct op *t, char *w ));
4972339Sabial_PROTOTYPE(static void brkset, (struct brkcon *bc ));
5072339Sabial_PROTOTYPE(int dolabel, (void));
5172339Sabial_PROTOTYPE(int dochdir, (struct op *t ));
5272339Sabial_PROTOTYPE(int doshift, (struct op *t ));
5372339Sabial_PROTOTYPE(int dologin, (struct op *t ));
5472339Sabial_PROTOTYPE(int doumask, (struct op *t ));
5572339Sabial_PROTOTYPE(int doexec, (struct op *t ));
5672339Sabial_PROTOTYPE(int dodot, (struct op *t ));
5772339Sabial_PROTOTYPE(int dowait, (struct op *t ));
5872339Sabial_PROTOTYPE(int doread, (struct op *t ));
5972339Sabial_PROTOTYPE(int doeval, (struct op *t ));
6072339Sabial_PROTOTYPE(int dotrap, (struct op *t ));
6172339Sabial_PROTOTYPE(int getsig, (char *s ));
6272339Sabial_PROTOTYPE(void setsig, (int n, void (*f)()));
6372339Sabial_PROTOTYPE(int getn, (char *as ));
6472339Sabial_PROTOTYPE(int dobreak, (struct op *t ));
6572339Sabial_PROTOTYPE(int docontinue, (struct op *t ));
6672339Sabial_PROTOTYPE(static int brkcontin, (char *cp, int val ));
6772339Sabial_PROTOTYPE(int doexit, (struct op *t ));
6872339Sabial_PROTOTYPE(int doexport, (struct op *t ));
6972339Sabial_PROTOTYPE(int doreadonly, (struct op *t ));
7072339Sabial_PROTOTYPE(static void rdexp, (char **wp, void (*f)(), int key));
7172339Sabial_PROTOTYPE(static void badid, (char *s ));
7272339Sabial_PROTOTYPE(int doset, (struct op *t ));
7372339Sabial_PROTOTYPE(void varput, (char *s, int out ));
7472339Sabial_PROTOTYPE(int dotimes, (void));
7572339Sabial
7672339Sabialint
7772339Sabialexecute(t, pin, pout, act)
7872339Sabialregister struct op *t;
7972339Sabialint *pin, *pout;
8072339Sabialint act;
8172339Sabial{
8272339Sabial	register struct op *t1;
8372339Sabial	int i, pv[2], rv, child, a;
8472339Sabial	char *cp, **wp, **wp2;
8572339Sabial	struct var *vp;
8672339Sabial	struct brkcon bc;
8772339Sabial
8872339Sabial	if (t == NULL)
8972339Sabial		return(0);
9072339Sabial	rv = 0;
9172339Sabial	a = areanum++;
9272339Sabial	wp = (wp2 = t->words) != NULL
9372339Sabial	     ? eval(wp2, t->type == TCOM ? DOALL : DOALL & ~DOKEY)
9472339Sabial	     : NULL;
9572339Sabial
9672339Sabial	switch(t->type) {
9772339Sabial	case TPAREN:
9872339Sabial	case TCOM:
9972339Sabial		rv = forkexec(t, pin, pout, act, wp, &child);
10072339Sabial		if (child) {
10172339Sabial			exstat = rv;
10272339Sabial			leave();
10372339Sabial		}
10472339Sabial		break;
10572339Sabial
10672339Sabial	case TPIPE:
10772339Sabial		if ((rv = openpipe(pv)) < 0)
10872339Sabial			break;
10972339Sabial		pv[0] = remap(pv[0]);
11072339Sabial		pv[1] = remap(pv[1]);
11172339Sabial		(void) execute(t->left, pin, pv, 0);
11272339Sabial		rv = execute(t->right, pv, pout, 0);
11372339Sabial		break;
11472339Sabial
11572339Sabial	case TLIST:
11672339Sabial		(void) execute(t->left, pin, pout, 0);
11772339Sabial		rv = execute(t->right, pin, pout, 0);
11872339Sabial		break;
11972339Sabial
12072339Sabial	case TASYNC:
12172339Sabial		i = parent();
12272339Sabial		if (i != 0) {
12372339Sabial			if (i != -1) {
12472339Sabial				setval(lookup("!"), putn(i));
12572339Sabial				if (pin != NULL)
12672339Sabial					closepipe(pin);
12772339Sabial				if (talking) {
12872339Sabial					prs(putn(i));
12972339Sabial					prs("\n");
13072339Sabial				}
13172339Sabial			} else
13272339Sabial				rv = -1;
13372339Sabial			setstatus(rv);
13472339Sabial		} else {
13572339Sabial			signal(SIGINT, SIG_IGN);
13672339Sabial			signal(SIGQUIT, SIG_IGN);
13772339Sabial			if (talking)
13872339Sabial				signal(SIGTERM, SIG_DFL);
13972339Sabial			talking = 0;
14072339Sabial			if (pin == NULL) {
14172339Sabial				close(0);
14272339Sabial				open("/dev/null", 0);
14372339Sabial			}
14472339Sabial			exit(execute(t->left, pin, pout, FEXEC));
14572339Sabial		}
14672339Sabial		break;
14772339Sabial
14872339Sabial	case TOR:
14972339Sabial	case TAND:
15072339Sabial		rv = execute(t->left, pin, pout, 0);
15172339Sabial		if ((t1 = t->right)!=NULL && (rv == 0) == (t->type == TAND))
15272339Sabial			rv = execute(t1, pin, pout, 0);
15372339Sabial		break;
15472339Sabial
15572339Sabial	case TFOR:
15672339Sabial		if (wp == NULL) {
15772339Sabial			wp = dolv+1;
15872339Sabial			if ((i = dolc) < 0)
15972339Sabial				i = 0;
16072339Sabial		} else {
16172339Sabial			i = -1;
16272339Sabial			while (*wp++ != NULL)
16372339Sabial				;
16472339Sabial		}
16572339Sabial		vp = lookup(t->str);
16672339Sabial		while (setjmp(bc.brkpt))
16772339Sabial			if (isbreak)
16872339Sabial				goto broken;
16972339Sabial		brkset(&bc);
17072339Sabial		for (t1 = t->left; i-- && *wp != NULL;) {
17172339Sabial			setval(vp, *wp++);
17272339Sabial			rv = execute(t1, pin, pout, 0);
17372339Sabial		}
17472339Sabial		brklist = brklist->nextlev;
17572339Sabial		break;
17672339Sabial
17772339Sabial	case TWHILE:
17872339Sabial	case TUNTIL:
17972339Sabial		while (setjmp(bc.brkpt))
18072339Sabial			if (isbreak)
18172339Sabial				goto broken;
18272339Sabial		brkset(&bc);
18372339Sabial		t1 = t->left;
18472339Sabial		while ((execute(t1, pin, pout, 0) == 0) == (t->type == TWHILE))
18572339Sabial			rv = execute(t->right, pin, pout, 0);
18672339Sabial		brklist = brklist->nextlev;
18772339Sabial		break;
18872339Sabial
18972339Sabial	case TIF:
19072339Sabial	case TELIF:
19172339Sabial	 	if (t->right != NULL) {
19272339Sabial		rv = !execute(t->left, pin, pout, 0) ?
19372339Sabial			execute(t->right->left, pin, pout, 0):
19472339Sabial			execute(t->right->right, pin, pout, 0);
19572339Sabial		}
19672339Sabial		break;
19772339Sabial
19872339Sabial	case TCASE:
19972339Sabial		if ((cp = evalstr(t->str, DOSUB|DOTRIM)) == 0)
20072339Sabial			cp = "";
20172339Sabial		if ((t1 = findcase(t->left, cp)) != NULL)
20272339Sabial			rv = execute(t1, pin, pout, 0);
20372339Sabial		break;
20472339Sabial
20572339Sabial	case TBRACE:
20672339Sabial/*
20772339Sabial		if (iopp = t->ioact)
20872339Sabial			while (*iopp)
20972339Sabial				if (iosetup(*iopp++, pin!=NULL, pout!=NULL)) {
21072339Sabial					rv = -1;
21172339Sabial					break;
21272339Sabial				}
21372339Sabial*/
21472339Sabial		if (rv >= 0 && (t1 = t->left))
21572339Sabial			rv = execute(t1, pin, pout, 0);
21672339Sabial		break;
21772339Sabial	}
21872339Sabial
21972339Sabialbroken:
22072339Sabial	t->words = wp2;
22172339Sabial	isbreak = 0;
22272339Sabial	freehere(areanum);
22372339Sabial	freearea(areanum);
22472339Sabial	areanum = a;
22572339Sabial	if (talking && intr) {
22672339Sabial		closeall();
22772339Sabial		fail();
22872339Sabial	}
22972339Sabial	if ((i = trapset) != 0) {
23072339Sabial		trapset = 0;
23172339Sabial		runtrap(i);
23272339Sabial	}
23372339Sabial	return(rv);
23472339Sabial}
23572339Sabial
23672339Sabialstatic int
23772339Sabialforkexec(t, pin, pout, act, wp, pforked)
23872339Sabialregister struct op *t;
23972339Sabialint *pin, *pout;
24072339Sabialint act;
24172339Sabialchar **wp;
24272339Sabialint *pforked;
24372339Sabial{
24472339Sabial	int i, rv, (*shcom)();
24572339Sabial	register int f;
24672339Sabial	char *cp;
24772339Sabial	struct ioword **iopp;
24872339Sabial	int resetsig;
24972339Sabial	char **owp;
25072339Sabial
25172339Sabial	owp = wp;
25272339Sabial	resetsig = 0;
25372339Sabial	*pforked = 0;
25472339Sabial	shcom = NULL;
25572339Sabial	rv = -1;	/* system-detected error */
25672339Sabial	if (t->type == TCOM) {
25772339Sabial		while ((cp = *wp++) != NULL)
25872339Sabial			;
25972339Sabial		cp = *wp;
26072339Sabial
26172339Sabial		/* strip all initial assignments */
26272339Sabial		/* not correct wrt PATH=yyy command  etc */
26372339Sabial		if (flag['x'])
26472339Sabial			echo (cp ? wp: owp);
26572339Sabial		if (cp == NULL && t->ioact == NULL) {
26672339Sabial			while ((cp = *owp++) != NULL && assign(cp, COPYV))
26772339Sabial				;
26872339Sabial			return(setstatus(0));
26972339Sabial		}
27072339Sabial		else if (cp != NULL)
27172339Sabial			shcom = inbuilt(cp);
27272339Sabial	}
27372339Sabial	t->words = wp;
27472339Sabial	f = act;
27572339Sabial	if (shcom == NULL && (f & FEXEC) == 0) {
27672339Sabial		i = parent();
27772339Sabial		if (i != 0) {
27872339Sabial			if (i == -1)
27972339Sabial				return(rv);
28072339Sabial			if (pin != NULL)
28172339Sabial				closepipe(pin);
28272339Sabial			return(pout==NULL? setstatus(waitfor(i,0)): 0);
28372339Sabial		}
28472339Sabial		if (talking) {
28572339Sabial			signal(SIGINT, SIG_IGN);
28672339Sabial			signal(SIGQUIT, SIG_IGN);
28772339Sabial			resetsig = 1;
28872339Sabial		}
28972339Sabial		talking = 0;
29072339Sabial		intr = 0;
29172339Sabial		(*pforked)++;
29272339Sabial		brklist = 0;
29372339Sabial		execflg = 0;
29472339Sabial	}
29572339Sabial	if (owp != NULL)
29672339Sabial		while ((cp = *owp++) != NULL && assign(cp, COPYV))
29772339Sabial			if (shcom == NULL)
29872339Sabial				export(lookup(cp));
29972339Sabial#ifdef COMPIPE
30072339Sabial	if ((pin != NULL || pout != NULL) && shcom != NULL && shcom != doexec) {
30172339Sabial		err("piping to/from shell builtins not yet done");
30272339Sabial		return(-1);
30372339Sabial	}
30472339Sabial#endif
30572339Sabial	if (pin != NULL) {
30672339Sabial		dup2(pin[0], 0);
30772339Sabial		closepipe(pin);
30872339Sabial	}
30972339Sabial	if (pout != NULL) {
31072339Sabial		dup2(pout[1], 1);
31172339Sabial		closepipe(pout);
31272339Sabial	}
31372339Sabial	if ((iopp = t->ioact) != NULL) {
31472339Sabial		if (shcom != NULL && shcom != doexec) {
31572339Sabial			prs(cp);
31672339Sabial			err(": cannot redirect shell command");
31772339Sabial			return(-1);
31872339Sabial		}
31972339Sabial		while (*iopp)
32072339Sabial			if (iosetup(*iopp++, pin!=NULL, pout!=NULL))
32172339Sabial				return(rv);
32272339Sabial	}
32372339Sabial	if (shcom)
32472339Sabial		return(setstatus((*shcom)(t)));
32572339Sabial	/* should use FIOCEXCL */
32672339Sabial	for (i=FDBASE; i<NOFILE; i++)
32772339Sabial		close(i);
32872339Sabial	if (resetsig) {
32972339Sabial		signal(SIGINT, SIG_DFL);
33072339Sabial		signal(SIGQUIT, SIG_DFL);
33172339Sabial	}
33272339Sabial	if (t->type == TPAREN)
33372339Sabial		exit(execute(t->left, NOPIPE, NOPIPE, FEXEC));
33472339Sabial	if (wp[0] == NULL)
33572339Sabial		exit(0);
33672339Sabial	cp = rexecve(wp[0], wp, makenv());
33772339Sabial	prs(wp[0]); prs(": "); warn(cp);
33872339Sabial	if (!execflg)
33972339Sabial		trap[0] = NULL;
34072339Sabial	leave();
34172339Sabial	/* NOTREACHED */
34272339Sabial}
34372339Sabial
34472339Sabial/*
34572339Sabial * common actions when creating a new child
34672339Sabial */
34772339Sabialstatic int
34872339Sabialparent()
34972339Sabial{
35072339Sabial	register int i;
35172339Sabial
35272339Sabial	i = fork();
35372339Sabial	if (i != 0) {
35472339Sabial		if (i == -1)
35572339Sabial			warn("try again");
35672339Sabial	}
35772339Sabial	return(i);
35872339Sabial}
35972339Sabial
36072339Sabial/*
36172339Sabial * 0< 1> are ignored as required
36272339Sabial * within pipelines.
36372339Sabial */
36472339Sabialint
36572339Sabialiosetup(iop, pipein, pipeout)
36672339Sabialregister struct ioword *iop;
36772339Sabialint pipein, pipeout;
36872339Sabial{
36972339Sabial	register u;
37072339Sabial	char *cp, *msg;
37172339Sabial
37272339Sabial	if (iop->io_unit == IODEFAULT)	/* take default */
37372339Sabial		iop->io_unit = iop->io_flag&(IOREAD|IOHERE)? 0: 1;
37472339Sabial	if (pipein && iop->io_unit == 0)
37572339Sabial		return(0);
37672339Sabial	if (pipeout && iop->io_unit == 1)
37772339Sabial		return(0);
37872339Sabial	msg = iop->io_flag&(IOREAD|IOHERE)? "open": "create";
37972339Sabial	if ((iop->io_flag & IOHERE) == 0) {
38072339Sabial		cp = iop->io_name;
38172339Sabial		if ((cp = evalstr(cp, DOSUB|DOTRIM)) == NULL)
38272339Sabial			return(1);
38372339Sabial	}
38472339Sabial	if (iop->io_flag & IODUP) {
38572339Sabial		if (cp[1] || (!digit(*cp) && *cp != '-')) {
38672339Sabial			prs(cp);
38772339Sabial			err(": illegal >& argument");
38872339Sabial			return(1);
38972339Sabial		}
39072339Sabial		if (*cp == '-')
39172339Sabial			iop->io_flag = IOCLOSE;
39272339Sabial		iop->io_flag &= ~(IOREAD|IOWRITE);
39372339Sabial	}
39472339Sabial	switch (iop->io_flag) {
39572339Sabial	case IOREAD:
39672339Sabial		u = open(cp, 0);
39772339Sabial		break;
39872339Sabial
39972339Sabial	case IOHERE:
40072339Sabial	case IOHERE|IOXHERE:
40172339Sabial		u = herein(iop->io_name, iop->io_flag&IOXHERE);
40272339Sabial		cp = "here file";
40372339Sabial		break;
40472339Sabial
40572339Sabial	case IOWRITE|IOCAT:
40672339Sabial		if ((u = open(cp, 1)) >= 0) {
40772339Sabial			lseek(u, (long)0, 2);
40872339Sabial			break;
40972339Sabial		}
41072339Sabial	case IOWRITE:
41172339Sabial		u = creat(cp, 0666);
41272339Sabial		break;
41372339Sabial
41472339Sabial	case IODUP:
41572339Sabial		u = dup2(*cp-'0', iop->io_unit);
41672339Sabial		break;
41772339Sabial
41872339Sabial	case IOCLOSE:
41972339Sabial		close(iop->io_unit);
42072339Sabial		return(0);
42172339Sabial	}
42272339Sabial	if (u < 0) {
42372339Sabial		prs(cp);
42472339Sabial		prs(": cannot ");
42572339Sabial		warn(msg);
42672339Sabial		return(1);
42772339Sabial	} else {
42872339Sabial		if (u != iop->io_unit) {
42972339Sabial			dup2(u, iop->io_unit);
43072339Sabial			close(u);
43172339Sabial		}
43272339Sabial	}
43372339Sabial	return(0);
43472339Sabial}
43572339Sabial
43672339Sabialstatic void
43772339Sabialecho(wp)
43872339Sabialregister char **wp;
43972339Sabial{
44072339Sabial	register i;
44172339Sabial
44272339Sabial	prs("+");
44372339Sabial	for (i=0; wp[i]; i++) {
44472339Sabial		if (i)
44572339Sabial			prs(" ");
44672339Sabial		prs(wp[i]);
44772339Sabial	}
44872339Sabial	prs("\n");
44972339Sabial}
45072339Sabial
45172339Sabialstatic struct op **
45272339Sabialfind1case(t, w)
45372339Sabialstruct op *t;
45472339Sabialchar *w;
45572339Sabial{
45672339Sabial	register struct op *t1;
45772339Sabial	struct op **tp;
45872339Sabial	register char **wp, *cp;
45972339Sabial
46072339Sabial	if (t == NULL)
46172339Sabial		return((struct op **)NULL);
46272339Sabial	if (t->type == TLIST) {
46372339Sabial		if ((tp = find1case(t->left, w)) != NULL)
46472339Sabial			return(tp);
46572339Sabial		t1 = t->right;	/* TPAT */
46672339Sabial	} else
46772339Sabial		t1 = t;
46872339Sabial	for (wp = t1->words; *wp;)
46972339Sabial		if ((cp = evalstr(*wp++, DOSUB)) && gmatch(w, cp))
47072339Sabial			return(&t1->left);
47172339Sabial	return((struct op **)NULL);
47272339Sabial}
47372339Sabial
47472339Sabialstatic struct op *
47572339Sabialfindcase(t, w)
47672339Sabialstruct op *t;
47772339Sabialchar *w;
47872339Sabial{
47972339Sabial	register struct op **tp;
48072339Sabial
48172339Sabial	return((tp = find1case(t, w)) != NULL? *tp: (struct op *)NULL);
48272339Sabial}
48372339Sabial
48472339Sabial/*
48572339Sabial * Enter a new loop level (marked for break/continue).
48672339Sabial */
48772339Sabialstatic void
48872339Sabialbrkset(bc)
48972339Sabialstruct brkcon *bc;
49072339Sabial{
49172339Sabial	bc->nextlev = brklist;
49272339Sabial	brklist = bc;
49372339Sabial}
49472339Sabial
49572339Sabial/*
49672339Sabial * Wait for the last process created.
49772339Sabial * Print a message for each process found
49872339Sabial * that was killed by a signal.
49972339Sabial * Ignore interrupt signals while waiting
50072339Sabial * unless `canintr' is true.
50172339Sabial */
50272339Sabialint
50372339Sabialwaitfor(lastpid, canintr)
50472339Sabialregister int lastpid;
50572339Sabialint canintr;
50672339Sabial{
50772339Sabial	register int pid, rv;
50872339Sabial	int s;
50972339Sabial	int oheedint = heedint;
51072339Sabial
51172339Sabial	heedint = 0;
51272339Sabial	rv = 0;
51372339Sabial	do {
51472339Sabial		pid = wait(&s);
51572339Sabial		if (pid == -1) {
51672339Sabial			if (errno != EINTR || canintr)
51772339Sabial				break;
51872339Sabial		} else {
51972339Sabial			if ((rv = WAITSIG(s)) != 0) {
52072339Sabial				if (rv < NSIGNAL) {
52172339Sabial					if (signame[rv] != NULL) {
52272339Sabial						if (pid != lastpid) {
52372339Sabial							prn(pid);
52472339Sabial							prs(": ");
52572339Sabial						}
52672339Sabial						prs(signame[rv]);
52772339Sabial					}
52872339Sabial				} else {
52972339Sabial					if (pid != lastpid) {
53072339Sabial						prn(pid);
53172339Sabial						prs(": ");
53272339Sabial					}
53372339Sabial					prs("Signal "); prn(rv); prs(" ");
53472339Sabial				}
53572339Sabial				if (WAITCORE(s))
53672339Sabial					prs(" - core dumped");
53772339Sabial				if (rv >= NSIGNAL || signame[rv])
53872339Sabial					prs("\n");
53972339Sabial				rv = -1;
54072339Sabial			} else
54172339Sabial				rv = WAITVAL(s);
54272339Sabial		}
54372339Sabial	} while (pid != lastpid);
54472339Sabial	heedint = oheedint;
54572339Sabial	if (intr)
54672339Sabial		if (talking) {
54772339Sabial			if (canintr)
54872339Sabial				intr = 0;
54972339Sabial		} else {
55072339Sabial			if (exstat == 0) exstat = rv;
55172339Sabial			onintr(0);
55272339Sabial		}
55372339Sabial	return(rv);
55472339Sabial}
55572339Sabial
55672339Sabialint
55772339Sabialsetstatus(s)
55872339Sabialregister int s;
55972339Sabial{
56072339Sabial	exstat = s;
56172339Sabial	setval(lookup("?"), putn(s));
56272339Sabial	return(s);
56372339Sabial}
56472339Sabial
56572339Sabial/*
56672339Sabial * PATH-searching interface to execve.
56772339Sabial * If getenv("PATH") were kept up-to-date,
56872339Sabial * execvp might be used.
56972339Sabial */
57072339Sabialchar *
57172339Sabialrexecve(c, v, envp)
57272339Sabialchar *c, **v, **envp;
57372339Sabial{
57472339Sabial	register int i;
57572339Sabial	register char *sp, *tp;
57672339Sabial	int eacces = 0, asis = 0;
57772339Sabial
57872339Sabial	sp = any('/', c)? "": path->value;
57972339Sabial	asis = *sp == '\0';
58072339Sabial	while (asis || *sp != '\0') {
58172339Sabial		asis = 0;
58272339Sabial		tp = e.linep;
58372339Sabial		for (; *sp != '\0'; tp++)
58472339Sabial			if ((*tp = *sp++) == ':') {
58572339Sabial				asis = *sp == '\0';
58672339Sabial				break;
58772339Sabial			}
58872339Sabial		if (tp != e.linep)
58972339Sabial			*tp++ = '/';
59072339Sabial		for (i = 0; (*tp++ = c[i++]) != '\0';)
59172339Sabial			;
59272339Sabial		execve(e.linep, v, envp);
59372339Sabial		switch (errno) {
59472339Sabial		case ENOEXEC:
59572339Sabial			*v = e.linep;
59672339Sabial			tp = *--v;
59772339Sabial			*v = e.linep;
59872339Sabial			execve("/bin/sh", v, envp);
59972339Sabial			*v = tp;
60072339Sabial			return("no Shell");
60172339Sabial
60272339Sabial		case ENOMEM:
60372339Sabial			return("program too big");
60472339Sabial
60572339Sabial		case E2BIG:
60672339Sabial			return("argument list too long");
60772339Sabial
60872339Sabial		case EACCES:
60972339Sabial			eacces++;
61072339Sabial			break;
61172339Sabial		}
61272339Sabial	}
61372339Sabial	return(errno==ENOENT ? "not found" : "cannot execute");
61472339Sabial}
61572339Sabial
61672339Sabial/*
61772339Sabial * Run the command produced by generator `f'
61872339Sabial * applied to stream `arg'.
61972339Sabial */
62072339Sabialint
62172339Sabialrun(argp, f)
62272339Sabialstruct ioarg *argp;
62372339Sabialint (*f)();
62472339Sabial{
62572339Sabial	struct op *otree;
62672339Sabial	struct wdblock *swdlist;
62772339Sabial	struct wdblock *siolist;
62872339Sabial	jmp_buf ev, rt;
62972339Sabial	xint *ofail;
63072339Sabial	int rv;
63172339Sabial
63272339Sabial	areanum++;
63372339Sabial	swdlist = wdlist;
63472339Sabial	siolist = iolist;
63572339Sabial	otree = outtree;
63672339Sabial	ofail = failpt;
63772339Sabial	rv = -1;
63872339Sabial	if (newenv(setjmp(errpt = ev)) == 0) {
63972339Sabial		wdlist = 0;
64072339Sabial		iolist = 0;
64172339Sabial		pushio(argp, f);
64272339Sabial		e.iobase = e.iop;
64372339Sabial		yynerrs = 0;
64472339Sabial		if (setjmp(failpt = rt) == 0 && yyparse() == 0)
64572339Sabial			rv = execute(outtree, NOPIPE, NOPIPE, 0);
64672339Sabial		quitenv();
64772339Sabial	}
64872339Sabial	wdlist = swdlist;
64972339Sabial	iolist = siolist;
65072339Sabial	failpt = ofail;
65172339Sabial	outtree = otree;
65272339Sabial	freearea(areanum--);
65372339Sabial	return(rv);
65472339Sabial}
65572339Sabial
65672339Sabial/* -------- do.c -------- */
65772339Sabial/* #include "sh.h" */
65872339Sabial
65972339Sabial/*
66072339Sabial * built-in commands: doX
66172339Sabial */
66272339Sabial
66372339Sabialint
66472339Sabialdolabel()
66572339Sabial{
66672339Sabial	return(0);
66772339Sabial}
66872339Sabial
66972339Sabialint
67072339Sabialdochdir(t)
67172339Sabialregister struct op *t;
67272339Sabial{
67372339Sabial	register char *cp, *er;
67472339Sabial
67572339Sabial	if ((cp = t->words[1]) == NULL && (cp = homedir->value) == NULL)
67672339Sabial		er = ": no home directory";
67772339Sabial	else if(chdir(cp) < 0)
67872339Sabial		er = ": bad directory";
67972339Sabial	else
68072339Sabial		return(0);
68172339Sabial	prs(cp != NULL? cp: "cd");
68272339Sabial	err(er);
68372339Sabial	return(1);
68472339Sabial}
68572339Sabial
68672339Sabialint
68772339Sabialdoshift(t)
68872339Sabialregister struct op *t;
68972339Sabial{
69072339Sabial	register n;
69172339Sabial
69272339Sabial	n = t->words[1]? getn(t->words[1]): 1;
69372339Sabial	if(dolc < n) {
69472339Sabial		err("nothing to shift");
69572339Sabial		return(1);
69672339Sabial	}
69772339Sabial	dolv[n] = dolv[0];
69872339Sabial	dolv += n;
69972339Sabial	dolc -= n;
70072339Sabial	setval(lookup("#"), putn(dolc));
70172339Sabial	return(0);
70272339Sabial}
70372339Sabial
70472339Sabial/*
70572339Sabial * execute login and newgrp directly
70672339Sabial */
70772339Sabialint
70872339Sabialdologin(t)
70972339Sabialstruct op *t;
71072339Sabial{
71172339Sabial	register char *cp;
71272339Sabial
71372339Sabial	if (talking) {
71472339Sabial		signal(SIGINT, SIG_DFL);
71572339Sabial		signal(SIGQUIT, SIG_DFL);
71672339Sabial	}
71772339Sabial	cp = rexecve(t->words[0], t->words, makenv());
71872339Sabial	prs(t->words[0]); prs(": "); err(cp);
71972339Sabial	return(1);
72072339Sabial}
72172339Sabial
72272339Sabialint
72372339Sabialdoumask(t)
72472339Sabialregister struct op *t;
72572339Sabial{
72672339Sabial	register int i, n;
72772339Sabial	register char *cp;
72872339Sabial
72972339Sabial	if ((cp = t->words[1]) == NULL) {
73072339Sabial		i = umask(0);
73172339Sabial		umask(i);
73272339Sabial		for (n=3*4; (n-=3) >= 0;)
73372339Sabial			putc('0'+((i>>n)&07));
73472339Sabial		putc('\n');
73572339Sabial	} else {
73672339Sabial		for (n=0; *cp>='0' && *cp<='9'; cp++)
73772339Sabial			n = n*8 + (*cp-'0');
73872339Sabial		umask(n);
73972339Sabial	}
74072339Sabial	return(0);
74172339Sabial}
74272339Sabial
74372339Sabialint
74472339Sabialdoexec(t)
74572339Sabialregister struct op *t;
74672339Sabial{
74772339Sabial	register i;
74872339Sabial	jmp_buf ex;
74972339Sabial	xint *ofail;
75072339Sabial
75172339Sabial	t->ioact = NULL;
75272339Sabial	for(i = 0; (t->words[i]=t->words[i+1]) != NULL; i++)
75372339Sabial		;
75472339Sabial	if (i == 0)
75572339Sabial		return(1);
75672339Sabial	execflg = 1;
75772339Sabial	ofail = failpt;
75872339Sabial	if (setjmp(failpt = ex) == 0)
75972339Sabial		execute(t, NOPIPE, NOPIPE, FEXEC);
76072339Sabial	failpt = ofail;
76172339Sabial	execflg = 0;
76272339Sabial	return(1);
76372339Sabial}
76472339Sabial
76572339Sabialint
76672339Sabialdodot(t)
76772339Sabialstruct op *t;
76872339Sabial{
76972339Sabial	register i;
77072339Sabial	register char *sp, *tp;
77172339Sabial	char *cp;
77272339Sabial
77372339Sabial	if ((cp = t->words[1]) == NULL)
77472339Sabial		return(0);
77572339Sabial	sp = any('/', cp)? ":": path->value;
77672339Sabial	while (*sp) {
77772339Sabial		tp = e.linep;
77872339Sabial		while (*sp && (*tp = *sp++) != ':')
77972339Sabial			tp++;
78072339Sabial		if (tp != e.linep)
78172339Sabial			*tp++ = '/';
78272339Sabial		for (i = 0; (*tp++ = cp[i++]) != '\0';)
78372339Sabial			;
78472339Sabial		if ((i = open(e.linep, 0)) >= 0) {
78572339Sabial			exstat = 0;
78672339Sabial			next(remap(i));
78772339Sabial			return(exstat);
78872339Sabial		}
78972339Sabial	}
79072339Sabial	prs(cp);
79172339Sabial	err(": not found");
79272339Sabial	return(-1);
79372339Sabial}
79472339Sabial
79572339Sabialint
79672339Sabialdowait(t)
79772339Sabialstruct op *t;
79872339Sabial{
79972339Sabial	register i;
80072339Sabial	register char *cp;
80172339Sabial
80272339Sabial	if ((cp = t->words[1]) != NULL) {
80372339Sabial		i = getn(cp);
80472339Sabial		if (i == 0)
80572339Sabial			return(0);
80672339Sabial	} else
80772339Sabial		i = -1;
80872339Sabial	setstatus(waitfor(i, 1));
80972339Sabial	return(0);
81072339Sabial}
81172339Sabial
81272339Sabialint
81372339Sabialdoread(t)
81472339Sabialstruct op *t;
81572339Sabial{
81672339Sabial	register char *cp, **wp;
81772339Sabial	register nb;
81872339Sabial	register int  nl = 0;
81972339Sabial
82072339Sabial	if (t->words[1] == NULL) {
82195258Sdes		err("usage: read name ...");
82272339Sabial		return(1);
82372339Sabial	}
82472339Sabial	for (wp = t->words+1; *wp; wp++) {
82572339Sabial		for (cp = e.linep; !nl && cp < elinep-1; cp++)
82672339Sabial			if ((nb = read(0, cp, sizeof(*cp))) != sizeof(*cp) ||
82772339Sabial			    (nl = (*cp == '\n')) ||
82872339Sabial			    (wp[1] && any(*cp, ifs->value)))
82972339Sabial				break;
83072339Sabial		*cp = 0;
83172339Sabial		if (nb <= 0)
83272339Sabial			break;
83372339Sabial		setval(lookup(*wp), e.linep);
83472339Sabial	}
83572339Sabial	return(nb <= 0);
83672339Sabial}
83772339Sabial
83872339Sabialint
83972339Sabialdoeval(t)
84072339Sabialregister struct op *t;
84172339Sabial{
84272339Sabial	return(RUN(awordlist, t->words+1, wdchar));
84372339Sabial}
84472339Sabial
84572339Sabialint
84672339Sabialdotrap(t)
84772339Sabialregister struct op *t;
84872339Sabial{
84972339Sabial	register int  n, i;
85072339Sabial	register int  resetsig;
85172339Sabial
85272339Sabial	if (t->words[1] == NULL) {
85372339Sabial		for (i=0; i<=_NSIG; i++)
85472339Sabial			if (trap[i]) {
85572339Sabial				prn(i);
85672339Sabial				prs(": ");
85772339Sabial				prs(trap[i]);
85872339Sabial				prs("\n");
85972339Sabial			}
86072339Sabial		return(0);
86172339Sabial	}
86272339Sabial	resetsig = digit(*t->words[1]);
86372339Sabial	for (i = resetsig ? 1 : 2; t->words[i] != NULL; ++i) {
86472339Sabial		n = getsig(t->words[i]);
86572339Sabial		xfree(trap[n]);
86672339Sabial		trap[n] = 0;
86772339Sabial		if (!resetsig) {
86872339Sabial			if (*t->words[1] != '\0') {
86972339Sabial				trap[n] = strsave(t->words[1], 0);
87072339Sabial				setsig(n, sig);
87172339Sabial			} else
87272339Sabial				setsig(n, SIG_IGN);
87372339Sabial		} else {
87472339Sabial			if (talking)
87572339Sabial				if (n == SIGINT)
87672339Sabial					setsig(n, onintr);
87772339Sabial				else
87872339Sabial					setsig(n, n == SIGQUIT ? SIG_IGN
87972339Sabial							       : SIG_DFL);
88072339Sabial			else
88172339Sabial				setsig(n, SIG_DFL);
88272339Sabial		}
88372339Sabial	}
88472339Sabial	return(0);
88572339Sabial}
88672339Sabial
88772339Sabialint
88872339Sabialgetsig(s)
88972339Sabialchar *s;
89072339Sabial{
89172339Sabial	register int n;
89272339Sabial
89372339Sabial	if ((n = getn(s)) < 0 || n > _NSIG) {
89472339Sabial		err("trap: bad signal number");
89572339Sabial		n = 0;
89672339Sabial	}
89772339Sabial	return(n);
89872339Sabial}
89972339Sabial
90072339Sabialvoid
90172339Sabialsetsig(n, f)
90272339Sabialregister n;
90372339Sabial_PROTOTYPE(void (*f), (int));
90472339Sabial{
90572339Sabial	if (n == 0)
90672339Sabial		return;
90772339Sabial	if (signal(n, SIG_IGN) != SIG_IGN || ourtrap[n]) {
90872339Sabial		ourtrap[n] = 1;
90972339Sabial		signal(n, f);
91072339Sabial	}
91172339Sabial}
91272339Sabial
91372339Sabialint
91472339Sabialgetn(as)
91572339Sabialchar *as;
91672339Sabial{
91772339Sabial	register char *s;
91872339Sabial	register n, m;
91972339Sabial
92072339Sabial	s = as;
92172339Sabial	m = 1;
92272339Sabial	if (*s == '-') {
92372339Sabial		m = -1;
92472339Sabial		s++;
92572339Sabial	}
92672339Sabial	for (n = 0; digit(*s); s++)
92772339Sabial		n = (n*10) + (*s-'0');
92872339Sabial	if (*s) {
92972339Sabial		prs(as);
93072339Sabial		err(": bad number");
93172339Sabial	}
93272339Sabial	return(n*m);
93372339Sabial}
93472339Sabial
93572339Sabialint
93672339Sabialdobreak(t)
93772339Sabialstruct op *t;
93872339Sabial{
93972339Sabial	return(brkcontin(t->words[1], 1));
94072339Sabial}
94172339Sabial
94272339Sabialint
94372339Sabialdocontinue(t)
94472339Sabialstruct op *t;
94572339Sabial{
94672339Sabial	return(brkcontin(t->words[1], 0));
94772339Sabial}
94872339Sabial
94972339Sabialstatic int
95072339Sabialbrkcontin(cp, val)
95172339Sabialregister char *cp;
95272339Sabialint val;
95372339Sabial{
95472339Sabial	register struct brkcon *bc;
95572339Sabial	register nl;
95672339Sabial
95772339Sabial	nl = cp == NULL? 1: getn(cp);
95872339Sabial	if (nl <= 0)
95972339Sabial		nl = 999;
96072339Sabial	do {
96172339Sabial		if ((bc = brklist) == NULL)
96272339Sabial			break;
96372339Sabial		brklist = bc->nextlev;
96472339Sabial	} while (--nl);
96572339Sabial	if (nl) {
96672339Sabial		err("bad break/continue level");
96772339Sabial		return(1);
96872339Sabial	}
96972339Sabial	isbreak = val;
97072339Sabial	longjmp(bc->brkpt, 1);
97172339Sabial	/* NOTREACHED */
97272339Sabial}
97372339Sabial
97472339Sabialint
97572339Sabialdoexit(t)
97672339Sabialstruct op *t;
97772339Sabial{
97872339Sabial	register char *cp;
97972339Sabial
98072339Sabial	execflg = 0;
98172339Sabial	if ((cp = t->words[1]) != NULL)
98272339Sabial		setstatus(getn(cp));
98372339Sabial	leave();
98472339Sabial	/* NOTREACHED */
98572339Sabial}
98672339Sabial
98772339Sabialint
98872339Sabialdoexport(t)
98972339Sabialstruct op *t;
99072339Sabial{
99172339Sabial	rdexp(t->words+1, export, EXPORT);
99272339Sabial	return(0);
99372339Sabial}
99472339Sabial
99572339Sabialint
99672339Sabialdoreadonly(t)
99772339Sabialstruct op *t;
99872339Sabial{
99972339Sabial	rdexp(t->words+1, ronly, RONLY);
100072339Sabial	return(0);
100172339Sabial}
100272339Sabial
100372339Sabialstatic void
100472339Sabialrdexp(wp, f, key)
100572339Sabialregister char **wp;
100672339Sabialvoid (*f)();
100772339Sabialint key;
100872339Sabial{
100972339Sabial	if (*wp != NULL) {
101072339Sabial		for (; *wp != NULL; wp++)
101172339Sabial			if (checkname(*wp))
101272339Sabial				(*f)(lookup(*wp));
101372339Sabial			else
101472339Sabial				badid(*wp);
101572339Sabial	} else
101672339Sabial		putvlist(key, 1);
101772339Sabial}
101872339Sabial
101972339Sabialstatic void
102072339Sabialbadid(s)
102172339Sabialregister char *s;
102272339Sabial{
102372339Sabial	prs(s);
102472339Sabial	err(": bad identifier");
102572339Sabial}
102672339Sabial
102772339Sabialint
102872339Sabialdoset(t)
102972339Sabialregister struct op *t;
103072339Sabial{
103172339Sabial	register struct var *vp;
103272339Sabial	register char *cp;
103372339Sabial	register n;
103472339Sabial
103572339Sabial	if ((cp = t->words[1]) == NULL) {
103672339Sabial		for (vp = vlist; vp; vp = vp->next)
103772339Sabial			varput(vp->name, 1);
103872339Sabial		return(0);
103972339Sabial	}
104072339Sabial	if (*cp == '-') {
104172339Sabial		/* bad: t->words++; */
104272339Sabial		for(n = 0; (t->words[n]=t->words[n+1]) != NULL; n++)
104372339Sabial			;
104472339Sabial		if (*++cp == 0)
104572339Sabial			flag['x'] = flag['v'] = 0;
104672339Sabial		else
104772339Sabial			for (; *cp; cp++)
104872339Sabial				switch (*cp) {
104972339Sabial				case 'e':
105072339Sabial					if (!talking)
105172339Sabial						flag['e']++;
105272339Sabial					break;
105372339Sabial
105472339Sabial				default:
105572339Sabial					if (*cp>='a' && *cp<='z')
105672339Sabial						flag[*cp]++;
105772339Sabial					break;
105872339Sabial				}
105972339Sabial		setdash();
106072339Sabial	}
106172339Sabial	if (t->words[1]) {
106272339Sabial		t->words[0] = dolv[0];
106372339Sabial		for (n=1; t->words[n]; n++)
106472339Sabial			setarea((char *)t->words[n], 0);
106572339Sabial		dolc = n-1;
106672339Sabial		dolv = t->words;
106772339Sabial		setval(lookup("#"), putn(dolc));
106872339Sabial		setarea((char *)(dolv-1), 0);
106972339Sabial	}
107072339Sabial	return(0);
107172339Sabial}
107272339Sabial
107372339Sabialvoid
107472339Sabialvarput(s, out)
107572339Sabialregister char *s;
107672339Sabialint out;
107772339Sabial{
107872339Sabial	if (letnum(*s)) {
107972339Sabial		write(out, s, strlen(s));
108072339Sabial		write(out, "\n", 1);
108172339Sabial	}
108272339Sabial}
108372339Sabial
108472339Sabial
108572339Sabial#define	SECS	60L
108672339Sabial#define	MINS	3600L
108772339Sabial
108872339Sabialint
108972339Sabialdotimes()
109072339Sabial{
109172339Sabial	struct tms tbuf;
109272339Sabial
109372339Sabial	times(&tbuf);
109472339Sabial
109572339Sabial	prn((int)(tbuf.tms_cutime / MINS));
109672339Sabial	prs("m");
109772339Sabial	prn((int)((tbuf.tms_cutime % MINS) / SECS));
109872339Sabial	prs("s ");
109972339Sabial	prn((int)(tbuf.tms_cstime / MINS));
110072339Sabial	prs("m");
110172339Sabial	prn((int)((tbuf.tms_cstime % MINS) / SECS));
110272339Sabial	prs("s\n");
110372339Sabial	return(0);
110472339Sabial}
110572339Sabial
110672339Sabialstruct	builtin {
110772339Sabial	char	*command;
110872339Sabial	int	(*fn)();
110972339Sabial};
111072339Sabialstatic struct	builtin	builtin[] = {
111172339Sabial	":",		dolabel,
111272339Sabial	"cd",		dochdir,
111372339Sabial	"shift",	doshift,
111472339Sabial	"exec",		doexec,
111572339Sabial	"wait",		dowait,
111672339Sabial	"read",		doread,
111772339Sabial	"eval",		doeval,
111872339Sabial	"trap",		dotrap,
111972339Sabial	"break",	dobreak,
112072339Sabial	"continue",	docontinue,
112172339Sabial	"exit",		doexit,
112272339Sabial	"export",	doexport,
112372339Sabial	"readonly",	doreadonly,
112472339Sabial	"set",		doset,
112572339Sabial	".",		dodot,
112672339Sabial	"umask",	doumask,
112772339Sabial	"login",	dologin,
112872339Sabial	"newgrp",	dologin,
112972339Sabial	"times",	dotimes,
113072339Sabial	0,
113172339Sabial};
113272339Sabial
113372339Sabialint (*inbuilt(s))()
113472339Sabialregister char *s;
113572339Sabial{
113672339Sabial	register struct builtin *bp;
113772339Sabial
113872339Sabial	for (bp = builtin; bp->command != NULL; bp++)
113972339Sabial		if (strcmp(bp->command, s) == 0)
114072339Sabial			return(bp->fn);
114172339Sabial	return((int(*)())NULL);
114272339Sabial}
114372339Sabial
1144