xref: /plan9-contrib/sys/src/cmd/rc/simple.c (revision d3907fe5a68251e8b016f54f72acf8767ba044bb)
13e12c5d1SDavid du Colombier /*
23e12c5d1SDavid du Colombier  * Maybe `simple' is a misnomer.
33e12c5d1SDavid du Colombier  */
43e12c5d1SDavid du Colombier #include "rc.h"
53e12c5d1SDavid du Colombier #include "getflags.h"
63e12c5d1SDavid du Colombier #include "exec.h"
73e12c5d1SDavid du Colombier #include "io.h"
83e12c5d1SDavid du Colombier #include "fns.h"
93e12c5d1SDavid du Colombier /*
103e12c5d1SDavid du Colombier  * Search through the following code to see if we're just going to exit.
113e12c5d1SDavid du Colombier  */
12*d3907fe5SDavid du Colombier int
133e12c5d1SDavid du Colombier exitnext(void){
143e12c5d1SDavid du Colombier 	union code *c=&runq->code[runq->pc];
153e12c5d1SDavid du Colombier 	while(c->f==Xpopredir) c++;
163e12c5d1SDavid du Colombier 	return c->f==Xexit;
173e12c5d1SDavid du Colombier }
18dc5a79c1SDavid du Colombier 
19dc5a79c1SDavid du Colombier void
20dc5a79c1SDavid du Colombier Xsimple(void)
21dc5a79c1SDavid du Colombier {
223e12c5d1SDavid du Colombier 	word *a;
233e12c5d1SDavid du Colombier 	thread *p = runq;
243e12c5d1SDavid du Colombier 	var *v;
253e12c5d1SDavid du Colombier 	struct builtin *bp;
26dc5a79c1SDavid du Colombier 	int pid;
273e12c5d1SDavid du Colombier 	globlist();
283e12c5d1SDavid du Colombier 	a = runq->argv->words;
293e12c5d1SDavid du Colombier 	if(a==0){
309a747e4fSDavid du Colombier 		Xerror1("empty argument list");
313e12c5d1SDavid du Colombier 		return;
323e12c5d1SDavid du Colombier 	}
333e12c5d1SDavid du Colombier 	if(flag['x'])
343e12c5d1SDavid du Colombier 		pfmt(err, "%v\n", p->argv->words); /* wrong, should do redirs */
353e12c5d1SDavid du Colombier 	v = gvlook(a->word);
363e12c5d1SDavid du Colombier 	if(v->fn)
373e12c5d1SDavid du Colombier 		execfunc(v);
383e12c5d1SDavid du Colombier 	else{
393e12c5d1SDavid du Colombier 		if(strcmp(a->word, "builtin")==0){
403e12c5d1SDavid du Colombier 			if(count(a)==1){
413e12c5d1SDavid du Colombier 				pfmt(err, "builtin: empty argument list\n");
423e12c5d1SDavid du Colombier 				setstatus("empty arg list");
433e12c5d1SDavid du Colombier 				poplist();
443e12c5d1SDavid du Colombier 				return;
453e12c5d1SDavid du Colombier 			}
463e12c5d1SDavid du Colombier 			a = a->next;
473e12c5d1SDavid du Colombier 			popword();
483e12c5d1SDavid du Colombier 		}
493e12c5d1SDavid du Colombier 		for(bp = Builtin;bp->name;bp++)
503e12c5d1SDavid du Colombier 			if(strcmp(a->word, bp->name)==0){
513e12c5d1SDavid du Colombier 				(*bp->fnc)();
523e12c5d1SDavid du Colombier 				return;
533e12c5d1SDavid du Colombier 			}
543e12c5d1SDavid du Colombier 		if(exitnext()){
553e12c5d1SDavid du Colombier 			/* fork and wait is redundant */
563e12c5d1SDavid du Colombier 			pushword("exec");
573e12c5d1SDavid du Colombier 			execexec();
583e12c5d1SDavid du Colombier 			Xexit();
593e12c5d1SDavid du Colombier 		}
603e12c5d1SDavid du Colombier 		else{
613e12c5d1SDavid du Colombier 			flush(err);
629a747e4fSDavid du Colombier 			Updenv();	/* necessary so changes don't go out again */
63dc5a79c1SDavid du Colombier 			if((pid = execforkexec()) < 0){
647dd7cddfSDavid du Colombier 				Xerror("try again");
653e12c5d1SDavid du Colombier 				return;
66dc5a79c1SDavid du Colombier 			}
67dc5a79c1SDavid du Colombier 
683e12c5d1SDavid du Colombier 			/* interrupts don't get us out */
69dc5a79c1SDavid du Colombier 			poplist();
703e12c5d1SDavid du Colombier 			while(Waitfor(pid, 1) < 0)
713e12c5d1SDavid du Colombier 				;
723e12c5d1SDavid du Colombier 		}
733e12c5d1SDavid du Colombier 	}
743e12c5d1SDavid du Colombier }
753e12c5d1SDavid du Colombier struct word nullpath = { "", 0};
76dc5a79c1SDavid du Colombier 
77dc5a79c1SDavid du Colombier void
78dc5a79c1SDavid du Colombier doredir(redir *rp)
793e12c5d1SDavid du Colombier {
803e12c5d1SDavid du Colombier 	if(rp){
813e12c5d1SDavid du Colombier 		doredir(rp->next);
823e12c5d1SDavid du Colombier 		switch(rp->type){
833e12c5d1SDavid du Colombier 		case ROPEN:
843e12c5d1SDavid du Colombier 			if(rp->from!=rp->to){
853e12c5d1SDavid du Colombier 				Dup(rp->from, rp->to);
863e12c5d1SDavid du Colombier 				close(rp->from);
873e12c5d1SDavid du Colombier 			}
883e12c5d1SDavid du Colombier 			break;
89dc5a79c1SDavid du Colombier 		case RDUP:
90dc5a79c1SDavid du Colombier 			Dup(rp->from, rp->to);
91dc5a79c1SDavid du Colombier 			break;
92dc5a79c1SDavid du Colombier 		case RCLOSE:
93dc5a79c1SDavid du Colombier 			close(rp->from);
94dc5a79c1SDavid du Colombier 			break;
953e12c5d1SDavid du Colombier 		}
963e12c5d1SDavid du Colombier 	}
973e12c5d1SDavid du Colombier }
98dc5a79c1SDavid du Colombier 
99dc5a79c1SDavid du Colombier word*
100dc5a79c1SDavid du Colombier searchpath(char *w)
101dc5a79c1SDavid du Colombier {
1023e12c5d1SDavid du Colombier 	word *path;
1033e12c5d1SDavid du Colombier 	if(strncmp(w, "/", 1)==0
1043e12c5d1SDavid du Colombier 	|| strncmp(w, "#", 1)==0
1053e12c5d1SDavid du Colombier 	|| strncmp(w, "./", 2)==0
1063e12c5d1SDavid du Colombier 	|| strncmp(w, "../", 3)==0
1073e12c5d1SDavid du Colombier 	|| (path = vlook("path")->val)==0)
1083e12c5d1SDavid du Colombier 		path=&nullpath;
1093e12c5d1SDavid du Colombier 	return path;
1103e12c5d1SDavid du Colombier }
111dc5a79c1SDavid du Colombier 
112dc5a79c1SDavid du Colombier void
113dc5a79c1SDavid du Colombier execexec(void)
114dc5a79c1SDavid du Colombier {
1153e12c5d1SDavid du Colombier 	popword();	/* "exec" */
1163e12c5d1SDavid du Colombier 	if(runq->argv->words==0){
1179a747e4fSDavid du Colombier 		Xerror1("empty argument list");
1183e12c5d1SDavid du Colombier 		return;
1193e12c5d1SDavid du Colombier 	}
1203e12c5d1SDavid du Colombier 	doredir(runq->redir);
1213e12c5d1SDavid du Colombier 	Execute(runq->argv->words, searchpath(runq->argv->words->word));
1223e12c5d1SDavid du Colombier 	poplist();
1233e12c5d1SDavid du Colombier }
124dc5a79c1SDavid du Colombier 
125dc5a79c1SDavid du Colombier void
126dc5a79c1SDavid du Colombier execfunc(var *func)
1273e12c5d1SDavid du Colombier {
1283e12c5d1SDavid du Colombier 	word *starval;
1293e12c5d1SDavid du Colombier 	popword();
1303e12c5d1SDavid du Colombier 	starval = runq->argv->words;
1313e12c5d1SDavid du Colombier 	runq->argv->words = 0;
1323e12c5d1SDavid du Colombier 	poplist();
1333e12c5d1SDavid du Colombier 	start(func->fn, func->pc, (struct var *)0);
1343e12c5d1SDavid du Colombier 	runq->local = newvar(strdup("*"), runq->local);
1353e12c5d1SDavid du Colombier 	runq->local->val = starval;
1363e12c5d1SDavid du Colombier 	runq->local->changed = 1;
1373e12c5d1SDavid du Colombier }
138dc5a79c1SDavid du Colombier 
139dc5a79c1SDavid du Colombier int
140dc5a79c1SDavid du Colombier dochdir(char *word)
141dc5a79c1SDavid du Colombier {
1427dd7cddfSDavid du Colombier 	/* report to /dev/wdir if it exists and we're interactive */
1437dd7cddfSDavid du Colombier 	static int wdirfd = -2;
1447dd7cddfSDavid du Colombier 	if(chdir(word)<0) return -1;
1457dd7cddfSDavid du Colombier 	if(flag['i']!=0){
1467dd7cddfSDavid du Colombier 		if(wdirfd==-2)	/* try only once */
1477dd7cddfSDavid du Colombier 			wdirfd = open("/dev/wdir", OWRITE|OCEXEC);
1487dd7cddfSDavid du Colombier 		if(wdirfd>=0)
1497dd7cddfSDavid du Colombier 			write(wdirfd, word, strlen(word));
1507dd7cddfSDavid du Colombier 	}
1517dd7cddfSDavid du Colombier 	return 1;
1527dd7cddfSDavid du Colombier }
153dc5a79c1SDavid du Colombier 
154dc5a79c1SDavid du Colombier void
155dc5a79c1SDavid du Colombier execcd(void)
156dc5a79c1SDavid du Colombier {
1573e12c5d1SDavid du Colombier 	word *a = runq->argv->words;
1583e12c5d1SDavid du Colombier 	word *cdpath;
1593e12c5d1SDavid du Colombier 	char dir[512];
1603e12c5d1SDavid du Colombier 	setstatus("can't cd");
1613e12c5d1SDavid du Colombier 	cdpath = vlook("cdpath")->val;
1623e12c5d1SDavid du Colombier 	switch(count(a)){
1633e12c5d1SDavid du Colombier 	default:
1643e12c5d1SDavid du Colombier 		pfmt(err, "Usage: cd [directory]\n");
1653e12c5d1SDavid du Colombier 		break;
1663e12c5d1SDavid du Colombier 	case 2:
167dc5a79c1SDavid du Colombier 		if(a->next->word[0]=='/' || cdpath==0)
168dc5a79c1SDavid du Colombier 			cdpath=&nullpath;
1693e12c5d1SDavid du Colombier 		for(;cdpath;cdpath = cdpath->next){
1703e12c5d1SDavid du Colombier 			strcpy(dir, cdpath->word);
171dc5a79c1SDavid du Colombier 			if(dir[0])
172dc5a79c1SDavid du Colombier 				strcat(dir, "/");
1733e12c5d1SDavid du Colombier 			strcat(dir, a->next->word);
1747dd7cddfSDavid du Colombier 			if(dochdir(dir)>=0){
1753e12c5d1SDavid du Colombier 				if(strlen(cdpath->word)
1763e12c5d1SDavid du Colombier 				&& strcmp(cdpath->word, ".")!=0)
1773e12c5d1SDavid du Colombier 					pfmt(err, "%s\n", dir);
1783e12c5d1SDavid du Colombier 				setstatus("");
1793e12c5d1SDavid du Colombier 				break;
1803e12c5d1SDavid du Colombier 			}
1813e12c5d1SDavid du Colombier 		}
182dc5a79c1SDavid du Colombier 		if(cdpath==0)
183dc5a79c1SDavid du Colombier 			pfmt(err, "Can't cd %s: %r\n", a->next->word);
1843e12c5d1SDavid du Colombier 		break;
1853e12c5d1SDavid du Colombier 	case 1:
1863e12c5d1SDavid du Colombier 		a = vlook("home")->val;
1873e12c5d1SDavid du Colombier 		if(count(a)>=1){
1887dd7cddfSDavid du Colombier 			if(dochdir(a->word)>=0)
1893e12c5d1SDavid du Colombier 				setstatus("");
1903e12c5d1SDavid du Colombier 			else
1919a747e4fSDavid du Colombier 				pfmt(err, "Can't cd %s: %r\n", a->word);
1923e12c5d1SDavid du Colombier 		}
1933e12c5d1SDavid du Colombier 		else
1943e12c5d1SDavid du Colombier 			pfmt(err, "Can't cd -- $home empty\n");
1953e12c5d1SDavid du Colombier 		break;
1963e12c5d1SDavid du Colombier 	}
1973e12c5d1SDavid du Colombier 	poplist();
1983e12c5d1SDavid du Colombier }
199dc5a79c1SDavid du Colombier 
200dc5a79c1SDavid du Colombier void
201dc5a79c1SDavid du Colombier execexit(void)
202dc5a79c1SDavid du Colombier {
2033e12c5d1SDavid du Colombier 	switch(count(runq->argv->words)){
204dc5a79c1SDavid du Colombier 	default:
205dc5a79c1SDavid du Colombier 		pfmt(err, "Usage: exit [status]\nExiting anyway\n");
206dc5a79c1SDavid du Colombier 	case 2:
207dc5a79c1SDavid du Colombier 		setstatus(runq->argv->words->next->word);
2083e12c5d1SDavid du Colombier 	case 1:	Xexit();
2093e12c5d1SDavid du Colombier 	}
2103e12c5d1SDavid du Colombier }
211dc5a79c1SDavid du Colombier 
212dc5a79c1SDavid du Colombier void
213dc5a79c1SDavid du Colombier execshift(void)
214dc5a79c1SDavid du Colombier {
2153e12c5d1SDavid du Colombier 	int n;
2163e12c5d1SDavid du Colombier 	word *a;
2173e12c5d1SDavid du Colombier 	var *star;
2183e12c5d1SDavid du Colombier 	switch(count(runq->argv->words)){
2193e12c5d1SDavid du Colombier 	default:
2203e12c5d1SDavid du Colombier 		pfmt(err, "Usage: shift [n]\n");
2213e12c5d1SDavid du Colombier 		setstatus("shift usage");
2223e12c5d1SDavid du Colombier 		poplist();
2233e12c5d1SDavid du Colombier 		return;
224dc5a79c1SDavid du Colombier 	case 2:
225dc5a79c1SDavid du Colombier 		n = atoi(runq->argv->words->next->word);
226dc5a79c1SDavid du Colombier 		break;
227dc5a79c1SDavid du Colombier 	case 1:
228dc5a79c1SDavid du Colombier 		n = 1;
229dc5a79c1SDavid du Colombier 		break;
2303e12c5d1SDavid du Colombier 	}
2313e12c5d1SDavid du Colombier 	star = vlook("*");
2323e12c5d1SDavid du Colombier 	for(;n && star->val;--n){
2333e12c5d1SDavid du Colombier 		a = star->val->next;
2343e12c5d1SDavid du Colombier 		efree(star->val->word);
2353e12c5d1SDavid du Colombier 		efree((char *)star->val);
2363e12c5d1SDavid du Colombier 		star->val = a;
2373e12c5d1SDavid du Colombier 		star->changed = 1;
2383e12c5d1SDavid du Colombier 	}
2393e12c5d1SDavid du Colombier 	setstatus("");
2403e12c5d1SDavid du Colombier 	poplist();
2413e12c5d1SDavid du Colombier }
242dc5a79c1SDavid du Colombier 
243dc5a79c1SDavid du Colombier int
244dc5a79c1SDavid du Colombier octal(char *s)
2453e12c5d1SDavid du Colombier {
2463e12c5d1SDavid du Colombier 	int n = 0;
2473e12c5d1SDavid du Colombier 	while(*s==' ' || *s=='\t' || *s=='\n') s++;
2483e12c5d1SDavid du Colombier 	while('0'<=*s && *s<='7') n = n*8+*s++-'0';
2493e12c5d1SDavid du Colombier 	return n;
2503e12c5d1SDavid du Colombier }
251dc5a79c1SDavid du Colombier 
252dc5a79c1SDavid du Colombier int
253dc5a79c1SDavid du Colombier mapfd(int fd)
2543e12c5d1SDavid du Colombier {
2553e12c5d1SDavid du Colombier 	redir *rp;
2563e12c5d1SDavid du Colombier 	for(rp = runq->redir;rp;rp = rp->next){
2573e12c5d1SDavid du Colombier 		switch(rp->type){
2583e12c5d1SDavid du Colombier 		case RCLOSE:
259dc5a79c1SDavid du Colombier 			if(rp->from==fd)
260dc5a79c1SDavid du Colombier 				fd=-1;
2613e12c5d1SDavid du Colombier 			break;
2623e12c5d1SDavid du Colombier 		case RDUP:
2633e12c5d1SDavid du Colombier 		case ROPEN:
264dc5a79c1SDavid du Colombier 			if(rp->to==fd)
265dc5a79c1SDavid du Colombier 				fd = rp->from;
2663e12c5d1SDavid du Colombier 			break;
2673e12c5d1SDavid du Colombier 		}
2683e12c5d1SDavid du Colombier 	}
2693e12c5d1SDavid du Colombier 	return fd;
2703e12c5d1SDavid du Colombier }
2713e12c5d1SDavid du Colombier union code rdcmds[4];
272dc5a79c1SDavid du Colombier 
273dc5a79c1SDavid du Colombier void
274dc5a79c1SDavid du Colombier execcmds(io *f)
2753e12c5d1SDavid du Colombier {
2763e12c5d1SDavid du Colombier 	static int first = 1;
2773e12c5d1SDavid du Colombier 	if(first){
2783e12c5d1SDavid du Colombier 		rdcmds[0].i = 1;
2793e12c5d1SDavid du Colombier 		rdcmds[1].f = Xrdcmds;
2803e12c5d1SDavid du Colombier 		rdcmds[2].f = Xreturn;
2813e12c5d1SDavid du Colombier 		first = 0;
2823e12c5d1SDavid du Colombier 	}
2833e12c5d1SDavid du Colombier 	start(rdcmds, 1, runq->local);
2843e12c5d1SDavid du Colombier 	runq->cmdfd = f;
2853e12c5d1SDavid du Colombier 	runq->iflast = 0;
2863e12c5d1SDavid du Colombier }
287dc5a79c1SDavid du Colombier 
288dc5a79c1SDavid du Colombier void
289dc5a79c1SDavid du Colombier execeval(void)
290dc5a79c1SDavid du Colombier {
2913e12c5d1SDavid du Colombier 	char *cmdline, *s, *t;
2923e12c5d1SDavid du Colombier 	int len = 0;
2933e12c5d1SDavid du Colombier 	word *ap;
2943e12c5d1SDavid du Colombier 	if(count(runq->argv->words)<=1){
2959a747e4fSDavid du Colombier 		Xerror1("Usage: eval cmd ...");
2963e12c5d1SDavid du Colombier 		return;
2973e12c5d1SDavid du Colombier 	}
298219b2ee8SDavid du Colombier 	eflagok = 1;
2993e12c5d1SDavid du Colombier 	for(ap = runq->argv->words->next;ap;ap = ap->next)
3003e12c5d1SDavid du Colombier 		len+=1+strlen(ap->word);
3013e12c5d1SDavid du Colombier 	cmdline = emalloc(len);
3023e12c5d1SDavid du Colombier 	s = cmdline;
3033e12c5d1SDavid du Colombier 	for(ap = runq->argv->words->next;ap;ap = ap->next){
3043e12c5d1SDavid du Colombier 		for(t = ap->word;*t;) *s++=*t++;
3053e12c5d1SDavid du Colombier 		*s++=' ';
3063e12c5d1SDavid du Colombier 	}
3073e12c5d1SDavid du Colombier 	s[-1]='\n';
3083e12c5d1SDavid du Colombier 	poplist();
3093e12c5d1SDavid du Colombier 	execcmds(opencore(cmdline, len));
3103e12c5d1SDavid du Colombier 	efree(cmdline);
3113e12c5d1SDavid du Colombier }
3123e12c5d1SDavid du Colombier union code dotcmds[14];
313dc5a79c1SDavid du Colombier 
314dc5a79c1SDavid du Colombier void
315dc5a79c1SDavid du Colombier execdot(void)
316dc5a79c1SDavid du Colombier {
3173e12c5d1SDavid du Colombier 	int iflag = 0;
3183e12c5d1SDavid du Colombier 	int fd;
3193e12c5d1SDavid du Colombier 	list *av;
3203e12c5d1SDavid du Colombier 	thread *p = runq;
3213e12c5d1SDavid du Colombier 	char *zero;
3223e12c5d1SDavid du Colombier 	static int first = 1;
3233e12c5d1SDavid du Colombier 	char file[512];
3243e12c5d1SDavid du Colombier 	word *path;
3253e12c5d1SDavid du Colombier 	if(first){
3263e12c5d1SDavid du Colombier 		dotcmds[0].i = 1;
3273e12c5d1SDavid du Colombier 		dotcmds[1].f = Xmark;
3283e12c5d1SDavid du Colombier 		dotcmds[2].f = Xword;
3293e12c5d1SDavid du Colombier 		dotcmds[3].s="0";
3303e12c5d1SDavid du Colombier 		dotcmds[4].f = Xlocal;
3313e12c5d1SDavid du Colombier 		dotcmds[5].f = Xmark;
3323e12c5d1SDavid du Colombier 		dotcmds[6].f = Xword;
3333e12c5d1SDavid du Colombier 		dotcmds[7].s="*";
3343e12c5d1SDavid du Colombier 		dotcmds[8].f = Xlocal;
3353e12c5d1SDavid du Colombier 		dotcmds[9].f = Xrdcmds;
3363e12c5d1SDavid du Colombier 		dotcmds[10].f = Xunlocal;
3373e12c5d1SDavid du Colombier 		dotcmds[11].f = Xunlocal;
3383e12c5d1SDavid du Colombier 		dotcmds[12].f = Xreturn;
3393e12c5d1SDavid du Colombier 		first = 0;
3403e12c5d1SDavid du Colombier 	}
341219b2ee8SDavid du Colombier 	else
342219b2ee8SDavid du Colombier 		eflagok = 1;
3433e12c5d1SDavid du Colombier 	popword();
3443e12c5d1SDavid du Colombier 	if(p->argv->words && strcmp(p->argv->words->word, "-i")==0){
3453e12c5d1SDavid du Colombier 		iflag = 1;
3463e12c5d1SDavid du Colombier 		popword();
3473e12c5d1SDavid du Colombier 	}
3483e12c5d1SDavid du Colombier 	/* get input file */
3493e12c5d1SDavid du Colombier 	if(p->argv->words==0){
3509a747e4fSDavid du Colombier 		Xerror1("Usage: . [-i] file [arg ...]");
3513e12c5d1SDavid du Colombier 		return;
3523e12c5d1SDavid du Colombier 	}
3533e12c5d1SDavid du Colombier 	zero = strdup(p->argv->words->word);
3543e12c5d1SDavid du Colombier 	popword();
3557dd7cddfSDavid du Colombier 	fd=-1;
3563e12c5d1SDavid du Colombier 	for(path = searchpath(zero);path;path = path->next){
3573e12c5d1SDavid du Colombier 		strcpy(file, path->word);
358dc5a79c1SDavid du Colombier 		if(file[0])
359dc5a79c1SDavid du Colombier 			strcat(file, "/");
3603e12c5d1SDavid du Colombier 		strcat(file, zero);
3613e12c5d1SDavid du Colombier 		if((fd = open(file, 0))>=0) break;
3623e12c5d1SDavid du Colombier 		if(strcmp(file, "/dev/stdin")==0){	/* for sun & ucb */
3633e12c5d1SDavid du Colombier 			fd = Dup1(0);
364dc5a79c1SDavid du Colombier 			if(fd>=0)
365dc5a79c1SDavid du Colombier 				break;
3663e12c5d1SDavid du Colombier 		}
3673e12c5d1SDavid du Colombier 	}
3683e12c5d1SDavid du Colombier 	if(fd<0){
3697dd7cddfSDavid du Colombier 		pfmt(err, "%s: ", zero);
3707dd7cddfSDavid du Colombier 		setstatus("can't open");
3717dd7cddfSDavid du Colombier 		Xerror(".: can't open");
3723e12c5d1SDavid du Colombier 		return;
3733e12c5d1SDavid du Colombier 	}
3743e12c5d1SDavid du Colombier 	/* set up for a new command loop */
3753e12c5d1SDavid du Colombier 	start(dotcmds, 1, (struct var *)0);
3763e12c5d1SDavid du Colombier 	pushredir(RCLOSE, fd, 0);
3773e12c5d1SDavid du Colombier 	runq->cmdfile = zero;
3783e12c5d1SDavid du Colombier 	runq->cmdfd = openfd(fd);
3793e12c5d1SDavid du Colombier 	runq->iflag = iflag;
3803e12c5d1SDavid du Colombier 	runq->iflast = 0;
3813e12c5d1SDavid du Colombier 	/* push $* value */
3823e12c5d1SDavid du Colombier 	pushlist();
3833e12c5d1SDavid du Colombier 	runq->argv->words = p->argv->words;
3843e12c5d1SDavid du Colombier 	/* free caller's copy of $* */
3853e12c5d1SDavid du Colombier 	av = p->argv;
3863e12c5d1SDavid du Colombier 	p->argv = av->next;
3873e12c5d1SDavid du Colombier 	efree((char *)av);
3883e12c5d1SDavid du Colombier 	/* push $0 value */
3893e12c5d1SDavid du Colombier 	pushlist();
3903e12c5d1SDavid du Colombier 	pushword(zero);
3913e12c5d1SDavid du Colombier 	ndot++;
3923e12c5d1SDavid du Colombier }
393dc5a79c1SDavid du Colombier 
394dc5a79c1SDavid du Colombier void
395dc5a79c1SDavid du Colombier execflag(void)
396dc5a79c1SDavid du Colombier {
3973e12c5d1SDavid du Colombier 	char *letter, *val;
3983e12c5d1SDavid du Colombier 	switch(count(runq->argv->words)){
3993e12c5d1SDavid du Colombier 	case 2:
400*d3907fe5SDavid du Colombier 		setstatus(flag[(uchar)runq->argv->words->next->word[0]]?"":"flag not set");
4013e12c5d1SDavid du Colombier 		break;
4023e12c5d1SDavid du Colombier 	case 3:
4033e12c5d1SDavid du Colombier 		letter = runq->argv->words->next->word;
4043e12c5d1SDavid du Colombier 		val = runq->argv->words->next->next->word;
4053e12c5d1SDavid du Colombier 		if(strlen(letter)==1){
4063e12c5d1SDavid du Colombier 			if(strcmp(val, "+")==0){
407*d3907fe5SDavid du Colombier 				flag[(uchar)letter[0]] = flagset;
4083e12c5d1SDavid du Colombier 				break;
4093e12c5d1SDavid du Colombier 			}
4103e12c5d1SDavid du Colombier 			if(strcmp(val, "-")==0){
411*d3907fe5SDavid du Colombier 				flag[(uchar)letter[0]] = 0;
4123e12c5d1SDavid du Colombier 				break;
4133e12c5d1SDavid du Colombier 			}
4143e12c5d1SDavid du Colombier 		}
4153e12c5d1SDavid du Colombier 	default:
4169a747e4fSDavid du Colombier 		Xerror1("Usage: flag [letter] [+-]");
4173e12c5d1SDavid du Colombier 		return;
4183e12c5d1SDavid du Colombier 	}
4193e12c5d1SDavid du Colombier 	poplist();
4203e12c5d1SDavid du Colombier }
421dc5a79c1SDavid du Colombier 
422dc5a79c1SDavid du Colombier void
423dc5a79c1SDavid du Colombier execwhatis(void){	/* mildly wrong -- should fork before writing */
4243e12c5d1SDavid du Colombier 	word *a, *b, *path;
4253e12c5d1SDavid du Colombier 	var *v;
4263e12c5d1SDavid du Colombier 	struct builtin *bp;
4273e12c5d1SDavid du Colombier 	char file[512];
4283e12c5d1SDavid du Colombier 	struct io out[1];
4293e12c5d1SDavid du Colombier 	int found, sep;
4303e12c5d1SDavid du Colombier 	a = runq->argv->words->next;
4313e12c5d1SDavid du Colombier 	if(a==0){
4329a747e4fSDavid du Colombier 		Xerror1("Usage: whatis name ...");
4333e12c5d1SDavid du Colombier 		return;
4343e12c5d1SDavid du Colombier 	}
4353e12c5d1SDavid du Colombier 	setstatus("");
4363e12c5d1SDavid du Colombier 	out->fd = mapfd(1);
4373e12c5d1SDavid du Colombier 	out->bufp = out->buf;
4383e12c5d1SDavid du Colombier 	out->ebuf = &out->buf[NBUF];
4393e12c5d1SDavid du Colombier 	out->strp = 0;
4403e12c5d1SDavid du Colombier 	for(;a;a = a->next){
4413e12c5d1SDavid du Colombier 		v = vlook(a->word);
4423e12c5d1SDavid du Colombier 		if(v->val){
4433e12c5d1SDavid du Colombier 			pfmt(out, "%s=", a->word);
4443e12c5d1SDavid du Colombier 			if(v->val->next==0)
4453e12c5d1SDavid du Colombier 				pfmt(out, "%q\n", v->val->word);
4463e12c5d1SDavid du Colombier 			else{
4473e12c5d1SDavid du Colombier 				sep='(';
4483e12c5d1SDavid du Colombier 				for(b = v->val;b && b->word;b = b->next){
4493e12c5d1SDavid du Colombier 					pfmt(out, "%c%q", sep, b->word);
4503e12c5d1SDavid du Colombier 					sep=' ';
4513e12c5d1SDavid du Colombier 				}
4523e12c5d1SDavid du Colombier 				pfmt(out, ")\n");
4533e12c5d1SDavid du Colombier 			}
4543e12c5d1SDavid du Colombier 			found = 1;
4553e12c5d1SDavid du Colombier 		}
4563e12c5d1SDavid du Colombier 		else
4573e12c5d1SDavid du Colombier 			found = 0;
4583e12c5d1SDavid du Colombier 		v = gvlook(a->word);
459dc5a79c1SDavid du Colombier 		if(v->fn)
460dc5a79c1SDavid du Colombier 			pfmt(out, "fn %s %s\n", v->name, v->fn[v->pc-1].s);
4613e12c5d1SDavid du Colombier 		else{
4623e12c5d1SDavid du Colombier 			for(bp = Builtin;bp->name;bp++)
4633e12c5d1SDavid du Colombier 				if(strcmp(a->word, bp->name)==0){
4643e12c5d1SDavid du Colombier 					pfmt(out, "builtin %s\n", a->word);
4653e12c5d1SDavid du Colombier 					break;
4663e12c5d1SDavid du Colombier 				}
4673e12c5d1SDavid du Colombier 			if(!bp->name){
4683e12c5d1SDavid du Colombier 				for(path = searchpath(a->word);path;path = path->next){
4693e12c5d1SDavid du Colombier 					strcpy(file, path->word);
470dc5a79c1SDavid du Colombier 					if(file[0])
471dc5a79c1SDavid du Colombier 						strcat(file, "/");
4723e12c5d1SDavid du Colombier 					strcat(file, a->word);
4733e12c5d1SDavid du Colombier 					if(Executable(file)){
4743e12c5d1SDavid du Colombier 						pfmt(out, "%s\n", file);
4753e12c5d1SDavid du Colombier 						break;
4763e12c5d1SDavid du Colombier 					}
4773e12c5d1SDavid du Colombier 				}
4783e12c5d1SDavid du Colombier 				if(!path && !found){
4793e12c5d1SDavid du Colombier 					pfmt(err, "%s: not found\n", a->word);
4803e12c5d1SDavid du Colombier 					setstatus("not found");
4813e12c5d1SDavid du Colombier 				}
4823e12c5d1SDavid du Colombier 			}
4833e12c5d1SDavid du Colombier 		}
4843e12c5d1SDavid du Colombier 	}
4853e12c5d1SDavid du Colombier 	poplist();
4863e12c5d1SDavid du Colombier 	flush(err);
4873e12c5d1SDavid du Colombier }
488dc5a79c1SDavid du Colombier 
489dc5a79c1SDavid du Colombier void
490dc5a79c1SDavid du Colombier execwait(void)
491dc5a79c1SDavid du Colombier {
4923e12c5d1SDavid du Colombier 	switch(count(runq->argv->words)){
493dc5a79c1SDavid du Colombier 	default:
494dc5a79c1SDavid du Colombier 		Xerror1("Usage: wait [pid]");
495dc5a79c1SDavid du Colombier 		return;
496dc5a79c1SDavid du Colombier 	case 2:
497dc5a79c1SDavid du Colombier 		Waitfor(atoi(runq->argv->words->next->word), 0);
498dc5a79c1SDavid du Colombier 		break;
499dc5a79c1SDavid du Colombier 	case 1:
500dc5a79c1SDavid du Colombier 		Waitfor(-1, 0);
501dc5a79c1SDavid du Colombier 		break;
5023e12c5d1SDavid du Colombier 	}
503219b2ee8SDavid du Colombier 	poplist();
5043e12c5d1SDavid du Colombier }
505