xref: /plan9/sys/src/cmd/rc/plan9.c (revision 5acbe0025e00f34f264450beb4ca57e62c7b4c3a)
13e12c5d1SDavid du Colombier /*
23e12c5d1SDavid du Colombier  * Plan 9 versions of system-specific functions
33e12c5d1SDavid du Colombier  *	By convention, exported routines herein have names beginning with an
43e12c5d1SDavid du Colombier  *	upper case letter.
53e12c5d1SDavid du Colombier  */
63e12c5d1SDavid du Colombier #include "rc.h"
73e12c5d1SDavid du Colombier #include "exec.h"
83e12c5d1SDavid du Colombier #include "io.h"
93e12c5d1SDavid du Colombier #include "fns.h"
103e12c5d1SDavid du Colombier #include "getflags.h"
11276e7d6dSDavid du Colombier 
12276e7d6dSDavid du Colombier enum {
13276e7d6dSDavid du Colombier 	Maxenvname = 256,	/* undocumented limit */
14276e7d6dSDavid du Colombier };
15276e7d6dSDavid du Colombier 
163e12c5d1SDavid du Colombier char *Signame[] = {
173e12c5d1SDavid du Colombier 	"sigexit",	"sighup",	"sigint",	"sigquit",
18219b2ee8SDavid du Colombier 	"sigalrm",	"sigkill",	"sigfpe",	"sigterm",
19219b2ee8SDavid du Colombier 	0
203e12c5d1SDavid du Colombier };
213e12c5d1SDavid du Colombier char *syssigname[] = {
223e12c5d1SDavid du Colombier 	"exit",		/* can't happen */
233e12c5d1SDavid du Colombier 	"hangup",
243e12c5d1SDavid du Colombier 	"interrupt",
253e12c5d1SDavid du Colombier 	"quit",		/* can't happen */
263e12c5d1SDavid du Colombier 	"alarm",
27219b2ee8SDavid du Colombier 	"kill",
283e12c5d1SDavid du Colombier 	"sys: fp: ",
29219b2ee8SDavid du Colombier 	"term",
303e12c5d1SDavid du Colombier 	0
313e12c5d1SDavid du Colombier };
323e12c5d1SDavid du Colombier char Rcmain[]="/rc/lib/rcmain";
333e12c5d1SDavid du Colombier char Fdprefix[]="/fd/";
343e12c5d1SDavid du Colombier void execfinit(void);
353e12c5d1SDavid du Colombier void execbind(void);
363e12c5d1SDavid du Colombier void execmount(void);
373e12c5d1SDavid du Colombier void execnewpgrp(void);
383e12c5d1SDavid du Colombier builtin Builtin[] = {
393e12c5d1SDavid du Colombier 	"cd",		execcd,
403e12c5d1SDavid du Colombier 	"whatis",	execwhatis,
413e12c5d1SDavid du Colombier 	"eval",		execeval,
423e12c5d1SDavid du Colombier 	"exec",		execexec,	/* but with popword first */
433e12c5d1SDavid du Colombier 	"exit",		execexit,
443e12c5d1SDavid du Colombier 	"shift",	execshift,
453e12c5d1SDavid du Colombier 	"wait",		execwait,
463e12c5d1SDavid du Colombier 	".",		execdot,
473e12c5d1SDavid du Colombier 	"finit",	execfinit,
483e12c5d1SDavid du Colombier 	"flag",		execflag,
493e12c5d1SDavid du Colombier 	"rfork",	execnewpgrp,
503e12c5d1SDavid du Colombier 	0
513e12c5d1SDavid du Colombier };
52dc5a79c1SDavid du Colombier 
53dc5a79c1SDavid du Colombier void
54dc5a79c1SDavid du Colombier execnewpgrp(void)
55dc5a79c1SDavid du Colombier {
563e12c5d1SDavid du Colombier 	int arg;
573e12c5d1SDavid du Colombier 	char *s;
583e12c5d1SDavid du Colombier 	switch(count(runq->argv->words)){
59dc5a79c1SDavid du Colombier 	case 1:
60dc5a79c1SDavid du Colombier 		arg = RFENVG|RFNAMEG|RFNOTEG;
61dc5a79c1SDavid du Colombier 		break;
623e12c5d1SDavid du Colombier 	case 2:
633e12c5d1SDavid du Colombier 		arg = 0;
643e12c5d1SDavid du Colombier 		for(s = runq->argv->words->next->word;*s;s++) switch(*s){
653e12c5d1SDavid du Colombier 		default:
663e12c5d1SDavid du Colombier 			goto Usage;
67dc5a79c1SDavid du Colombier 		case 'n':
68dc5a79c1SDavid du Colombier 			arg|=RFNAMEG;  break;
69dc5a79c1SDavid du Colombier 		case 'N':
70dc5a79c1SDavid du Colombier 			arg|=RFCNAMEG;
71dc5a79c1SDavid du Colombier 			break;
72dc5a79c1SDavid du Colombier 		case 'm':
73dc5a79c1SDavid du Colombier 			arg|=RFNOMNT;  break;
74dc5a79c1SDavid du Colombier 		case 'e':
75dc5a79c1SDavid du Colombier 			arg|=RFENVG;   break;
76dc5a79c1SDavid du Colombier 		case 'E':
77dc5a79c1SDavid du Colombier 			arg|=RFCENVG;  break;
78dc5a79c1SDavid du Colombier 		case 's':
79dc5a79c1SDavid du Colombier 			arg|=RFNOTEG;  break;
80dc5a79c1SDavid du Colombier 		case 'f':
81dc5a79c1SDavid du Colombier 			arg|=RFFDG;    break;
82dc5a79c1SDavid du Colombier 		case 'F':
83dc5a79c1SDavid du Colombier 			arg|=RFCFDG;   break;
843e12c5d1SDavid du Colombier 		}
853e12c5d1SDavid du Colombier 		break;
863e12c5d1SDavid du Colombier 	default:
873e12c5d1SDavid du Colombier 	Usage:
887dd7cddfSDavid du Colombier 		pfmt(err, "Usage: %s [fnesFNEm]\n", runq->argv->words->word);
893e12c5d1SDavid du Colombier 		setstatus("rfork usage");
903e12c5d1SDavid du Colombier 		poplist();
913e12c5d1SDavid du Colombier 		return;
923e12c5d1SDavid du Colombier 	}
933e12c5d1SDavid du Colombier 	if(rfork(arg)==-1){
943e12c5d1SDavid du Colombier 		pfmt(err, "rc: %s failed\n", runq->argv->words->word);
953e12c5d1SDavid du Colombier 		setstatus("rfork failed");
963e12c5d1SDavid du Colombier 	}
973e12c5d1SDavid du Colombier 	else
983e12c5d1SDavid du Colombier 		setstatus("");
993e12c5d1SDavid du Colombier 	poplist();
1003e12c5d1SDavid du Colombier }
101dc5a79c1SDavid du Colombier 
102dc5a79c1SDavid du Colombier void
103dc5a79c1SDavid du Colombier Vinit(void)
104dc5a79c1SDavid du Colombier {
105276e7d6dSDavid du Colombier 	int dir, f, len, i, n, nent;
1063e12c5d1SDavid du Colombier 	char *buf, *s;
107276e7d6dSDavid du Colombier 	char envname[Maxenvname];
108276e7d6dSDavid du Colombier 	word *val;
1099a747e4fSDavid du Colombier 	Dir *ent;
110276e7d6dSDavid du Colombier 
1119a747e4fSDavid du Colombier 	dir = open("/env", OREAD);
1123e12c5d1SDavid du Colombier 	if(dir<0){
1139a747e4fSDavid du Colombier 		pfmt(err, "rc: can't open /env: %r\n");
1143e12c5d1SDavid du Colombier 		return;
1153e12c5d1SDavid du Colombier 	}
1169a747e4fSDavid du Colombier 	ent = nil;
1179a747e4fSDavid du Colombier 	for(;;){
1189a747e4fSDavid du Colombier 		nent = dirread(dir, &ent);
1199a747e4fSDavid du Colombier 		if(nent <= 0)
1209a747e4fSDavid du Colombier 			break;
1219a747e4fSDavid du Colombier 		for(i = 0; i<nent; i++){
1229a747e4fSDavid du Colombier 			len = ent[i].length;
1239a747e4fSDavid du Colombier 			if(len && strncmp(ent[i].name, "fn#", 3)!=0){
12499eb86a7SDavid du Colombier 				snprint(envname, sizeof envname, "/env/%s", ent[i].name);
1253e12c5d1SDavid du Colombier 				if((f = open(envname, 0))>=0){
126276e7d6dSDavid du Colombier 					buf = emalloc(len+1);
127276e7d6dSDavid du Colombier 					n = readn(f, buf, len);
128276e7d6dSDavid du Colombier 					if (n <= 0)
129276e7d6dSDavid du Colombier 						buf[0] = '\0';
130276e7d6dSDavid du Colombier 					else
131276e7d6dSDavid du Colombier 						buf[n] = '\0';
1323e12c5d1SDavid du Colombier 					val = 0;
1333e12c5d1SDavid du Colombier 					/* Charitably add a 0 at the end if need be */
134dc5a79c1SDavid du Colombier 					if(buf[len-1])
135dc5a79c1SDavid du Colombier 						buf[len++]='\0';
1363e12c5d1SDavid du Colombier 					s = buf+len-1;
1373e12c5d1SDavid du Colombier 					for(;;){
13899eb86a7SDavid du Colombier 						while(s!=buf && s[-1]!='\0') --s;
1393e12c5d1SDavid du Colombier 						val = newword(s, val);
140dc5a79c1SDavid du Colombier 						if(s==buf)
141dc5a79c1SDavid du Colombier 							break;
1423e12c5d1SDavid du Colombier 						--s;
1433e12c5d1SDavid du Colombier 					}
1449a747e4fSDavid du Colombier 					setvar(ent[i].name, val);
1459a747e4fSDavid du Colombier 					vlook(ent[i].name)->changed = 0;
1463e12c5d1SDavid du Colombier 					close(f);
1473e12c5d1SDavid du Colombier 					efree(buf);
1483e12c5d1SDavid du Colombier 				}
1493e12c5d1SDavid du Colombier 			}
1503e12c5d1SDavid du Colombier 		}
1519a747e4fSDavid du Colombier 		free(ent);
1529a747e4fSDavid du Colombier 	}
1533e12c5d1SDavid du Colombier 	close(dir);
1543e12c5d1SDavid du Colombier }
1553e12c5d1SDavid du Colombier int envdir;
156dc5a79c1SDavid du Colombier 
157dc5a79c1SDavid du Colombier void
158dc5a79c1SDavid du Colombier Xrdfn(void)
159dc5a79c1SDavid du Colombier {
1603e12c5d1SDavid du Colombier 	int f, len;
161276e7d6dSDavid du Colombier 	Dir *e;
162276e7d6dSDavid du Colombier 	char envname[Maxenvname];
1639a747e4fSDavid du Colombier 	static Dir *ent, *allocent;
1649a747e4fSDavid du Colombier 	static int nent;
1659a747e4fSDavid du Colombier 
1669a747e4fSDavid du Colombier 	for(;;){
1679a747e4fSDavid du Colombier 		if(nent == 0){
1689a747e4fSDavid du Colombier 			free(allocent);
1699a747e4fSDavid du Colombier 			nent = dirread(envdir, &allocent);
1709a747e4fSDavid du Colombier 			ent = allocent;
1719a747e4fSDavid du Colombier 		}
1729a747e4fSDavid du Colombier 		if(nent <= 0)
1739a747e4fSDavid du Colombier 			break;
1749a747e4fSDavid du Colombier 		while(nent){
1759a747e4fSDavid du Colombier 			e = ent++;
1769a747e4fSDavid du Colombier 			nent--;
1779a747e4fSDavid du Colombier 			len = e->length;
1789a747e4fSDavid du Colombier 			if(len && strncmp(e->name, "fn#", 3)==0){
17999eb86a7SDavid du Colombier 				snprint(envname, sizeof envname, "/env/%s", e->name);
1803e12c5d1SDavid du Colombier 				if((f = open(envname, 0))>=0){
1813e12c5d1SDavid du Colombier 					execcmds(openfd(f));
1823e12c5d1SDavid du Colombier 					return;
1833e12c5d1SDavid du Colombier 				}
1843e12c5d1SDavid du Colombier 			}
1853e12c5d1SDavid du Colombier 		}
1869a747e4fSDavid du Colombier 	}
1873e12c5d1SDavid du Colombier 	close(envdir);
1883e12c5d1SDavid du Colombier 	Xreturn();
1893e12c5d1SDavid du Colombier }
1903e12c5d1SDavid du Colombier union code rdfns[4];
191dc5a79c1SDavid du Colombier 
192dc5a79c1SDavid du Colombier void
193dc5a79c1SDavid du Colombier execfinit(void)
194dc5a79c1SDavid du Colombier {
1953e12c5d1SDavid du Colombier 	static int first = 1;
1963e12c5d1SDavid du Colombier 	if(first){
1973e12c5d1SDavid du Colombier 		rdfns[0].i = 1;
1983e12c5d1SDavid du Colombier 		rdfns[1].f = Xrdfn;
1993e12c5d1SDavid du Colombier 		rdfns[2].f = Xjump;
2003e12c5d1SDavid du Colombier 		rdfns[3].i = 1;
2013e12c5d1SDavid du Colombier 		first = 0;
2023e12c5d1SDavid du Colombier 	}
2033e12c5d1SDavid du Colombier 	Xpopm();
2049a747e4fSDavid du Colombier 	envdir = open("/env", 0);
2053e12c5d1SDavid du Colombier 	if(envdir<0){
2069a747e4fSDavid du Colombier 		pfmt(err, "rc: can't open /env: %r\n");
2073e12c5d1SDavid du Colombier 		return;
2083e12c5d1SDavid du Colombier 	}
2093e12c5d1SDavid du Colombier 	start(rdfns, 1, runq->local);
2103e12c5d1SDavid du Colombier }
211dc5a79c1SDavid du Colombier 
212dc5a79c1SDavid du Colombier int
213dc5a79c1SDavid du Colombier Waitfor(int pid, int)
214dc5a79c1SDavid du Colombier {
2153e12c5d1SDavid du Colombier 	thread *p;
2169a747e4fSDavid du Colombier 	Waitmsg *w;
2179a747e4fSDavid du Colombier 	char errbuf[ERRMAX];
2189a747e4fSDavid du Colombier 
219d3907fe5SDavid du Colombier 	if(pid >= 0 && !havewaitpid(pid))
220d3907fe5SDavid du Colombier 		return 0;
221d3907fe5SDavid du Colombier 
2229a747e4fSDavid du Colombier 	while((w = wait()) != nil){
223d3907fe5SDavid du Colombier 		delwaitpid(w->pid);
2249a747e4fSDavid du Colombier 		if(w->pid==pid){
2259a747e4fSDavid du Colombier 			setstatus(w->msg);
2269a747e4fSDavid du Colombier 			free(w);
227219b2ee8SDavid du Colombier 			return 0;
2283e12c5d1SDavid du Colombier 		}
2293e12c5d1SDavid du Colombier 		for(p = runq->ret;p;p = p->ret)
2309a747e4fSDavid du Colombier 			if(p->pid==w->pid){
2313e12c5d1SDavid du Colombier 				p->pid=-1;
2329a747e4fSDavid du Colombier 				strcpy(p->status, w->msg);
2333e12c5d1SDavid du Colombier 			}
2349a747e4fSDavid du Colombier 		free(w);
2353e12c5d1SDavid du Colombier 	}
2369a747e4fSDavid du Colombier 
2379a747e4fSDavid du Colombier 	errstr(errbuf, sizeof errbuf);
23899eb86a7SDavid du Colombier 	if(strcmp(errbuf, "interrupted")==0) return -1;
2393e12c5d1SDavid du Colombier 	return 0;
2403e12c5d1SDavid du Colombier }
241dc5a79c1SDavid du Colombier 
242276e7d6dSDavid du Colombier char **
243276e7d6dSDavid du Colombier mkargv(word *a)
2443e12c5d1SDavid du Colombier {
2453e12c5d1SDavid du Colombier 	char **argv = (char **)emalloc((count(a)+2)*sizeof(char *));
2463e12c5d1SDavid du Colombier 	char **argp = argv+1;	/* leave one at front for runcoms */
24799eb86a7SDavid du Colombier 	for(;a;a = a->next) *argp++=a->word;
2483e12c5d1SDavid du Colombier 	*argp = 0;
2493e12c5d1SDavid du Colombier 	return argv;
2503e12c5d1SDavid du Colombier }
251dc5a79c1SDavid du Colombier 
252dc5a79c1SDavid du Colombier void
253dc5a79c1SDavid du Colombier addenv(var *v)
2543e12c5d1SDavid du Colombier {
255276e7d6dSDavid du Colombier 	char envname[Maxenvname];
2563e12c5d1SDavid du Colombier 	word *w;
2573e12c5d1SDavid du Colombier 	int f;
2583e12c5d1SDavid du Colombier 	io *fd;
2593e12c5d1SDavid du Colombier 	if(v->changed){
2603e12c5d1SDavid du Colombier 		v->changed = 0;
2619a747e4fSDavid du Colombier 		snprint(envname, sizeof envname, "/env/%s", v->name);
2623e12c5d1SDavid du Colombier 		if((f = Creat(envname))<0)
2639a747e4fSDavid du Colombier 			pfmt(err, "rc: can't open %s: %r\n", envname);
2643e12c5d1SDavid du Colombier 		else{
2653e12c5d1SDavid du Colombier 			for(w = v->val;w;w = w->next)
26699eb86a7SDavid du Colombier 				write(f, w->word, strlen(w->word)+1L);
2673e12c5d1SDavid du Colombier 			close(f);
2683e12c5d1SDavid du Colombier 		}
2693e12c5d1SDavid du Colombier 	}
2703e12c5d1SDavid du Colombier 	if(v->fnchanged){
2713e12c5d1SDavid du Colombier 		v->fnchanged = 0;
2729a747e4fSDavid du Colombier 		snprint(envname, sizeof envname, "/env/fn#%s", v->name);
2733e12c5d1SDavid du Colombier 		if((f = Creat(envname))<0)
2749a747e4fSDavid du Colombier 			pfmt(err, "rc: can't open %s: %r\n", envname);
2753e12c5d1SDavid du Colombier 		else{
2763e12c5d1SDavid du Colombier 			if(v->fn){
2773e12c5d1SDavid du Colombier 				fd = openfd(f);
278fed0fa9eSDavid du Colombier 				pfmt(fd, "fn %q %s\n", v->name, v->fn[v->pc-1].s);
2793e12c5d1SDavid du Colombier 				closeio(fd);
2803e12c5d1SDavid du Colombier 			}
2813e12c5d1SDavid du Colombier 			close(f);
2823e12c5d1SDavid du Colombier 		}
2833e12c5d1SDavid du Colombier 	}
2843e12c5d1SDavid du Colombier }
285dc5a79c1SDavid du Colombier 
286dc5a79c1SDavid du Colombier void
287dc5a79c1SDavid du Colombier updenvlocal(var *v)
2883e12c5d1SDavid du Colombier {
2893e12c5d1SDavid du Colombier 	if(v){
2903e12c5d1SDavid du Colombier 		updenvlocal(v->next);
2913e12c5d1SDavid du Colombier 		addenv(v);
2923e12c5d1SDavid du Colombier 	}
2933e12c5d1SDavid du Colombier }
294dc5a79c1SDavid du Colombier 
295dc5a79c1SDavid du Colombier void
296dc5a79c1SDavid du Colombier Updenv(void)
297dc5a79c1SDavid du Colombier {
2983e12c5d1SDavid du Colombier 	var *v, **h;
2993e12c5d1SDavid du Colombier 	for(h = gvar;h!=&gvar[NVAR];h++)
3003e12c5d1SDavid du Colombier 		for(v=*h;v;v = v->next)
3013e12c5d1SDavid du Colombier 			addenv(v);
302dc5a79c1SDavid du Colombier 	if(runq)
303dc5a79c1SDavid du Colombier 		updenvlocal(runq->local);
3043e12c5d1SDavid du Colombier }
305dc5a79c1SDavid du Colombier 
306*5acbe002SDavid du Colombier /* not used on plan 9 */
307dc5a79c1SDavid du Colombier int
308dc5a79c1SDavid du Colombier ForkExecute(char *file, char **argv, int sin, int sout, int serr)
309dc5a79c1SDavid du Colombier {
310dc5a79c1SDavid du Colombier 	int pid;
311dc5a79c1SDavid du Colombier 
312dc5a79c1SDavid du Colombier 	if(access(file, 1) != 0)
313dc5a79c1SDavid du Colombier 		return -1;
314dc5a79c1SDavid du Colombier 	switch(pid = fork()){
315dc5a79c1SDavid du Colombier 	case -1:
316dc5a79c1SDavid du Colombier 		return -1;
317dc5a79c1SDavid du Colombier 	case 0:
318dc5a79c1SDavid du Colombier 		if(sin >= 0)
319dc5a79c1SDavid du Colombier 			dup(sin, 0);
320dc5a79c1SDavid du Colombier 		else
321dc5a79c1SDavid du Colombier 			close(0);
322dc5a79c1SDavid du Colombier 		if(sout >= 0)
323dc5a79c1SDavid du Colombier 			dup(sout, 1);
324dc5a79c1SDavid du Colombier 		else
325dc5a79c1SDavid du Colombier 			close(1);
326dc5a79c1SDavid du Colombier 		if(serr >= 0)
327dc5a79c1SDavid du Colombier 			dup(serr, 2);
328dc5a79c1SDavid du Colombier 		else
329dc5a79c1SDavid du Colombier 			close(2);
330dc5a79c1SDavid du Colombier 		exec(file, argv);
331dc5a79c1SDavid du Colombier 		exits(file);
332dc5a79c1SDavid du Colombier 	}
333dc5a79c1SDavid du Colombier 	return pid;
334dc5a79c1SDavid du Colombier }
335dc5a79c1SDavid du Colombier 
336dc5a79c1SDavid du Colombier void
337dc5a79c1SDavid du Colombier Execute(word *args, word *path)
3383e12c5d1SDavid du Colombier {
3393e12c5d1SDavid du Colombier 	char **argv = mkargv(args);
340*5acbe002SDavid du Colombier 	char file[1024], errstr[1024];
341219b2ee8SDavid du Colombier 	int nc;
342*5acbe002SDavid du Colombier 
3433e12c5d1SDavid du Colombier 	Updenv();
344*5acbe002SDavid du Colombier 	errstr[0] = '\0';
3453e12c5d1SDavid du Colombier 	for(;path;path = path->next){
346219b2ee8SDavid du Colombier 		nc = strlen(path->word);
347276e7d6dSDavid du Colombier 		if(nc < sizeof file - 1){	/* 1 for / */
3483e12c5d1SDavid du Colombier 			strcpy(file, path->word);
349219b2ee8SDavid du Colombier 			if(file[0]){
350219b2ee8SDavid du Colombier 				strcat(file, "/");
351219b2ee8SDavid du Colombier 				nc++;
352219b2ee8SDavid du Colombier 			}
353276e7d6dSDavid du Colombier 			if(nc + strlen(argv[1]) < sizeof file){
3543e12c5d1SDavid du Colombier 				strcat(file, argv[1]);
3553e12c5d1SDavid du Colombier 				exec(file, argv+1);
356*5acbe002SDavid du Colombier 				rerrstr(errstr, sizeof errstr);
357*5acbe002SDavid du Colombier 				/*
358*5acbe002SDavid du Colombier 				 * if file is executable, exec should have
359*5acbe002SDavid du Colombier 				 * worked.  stop searching and print the
360*5acbe002SDavid du Colombier 				 * reason for failure.
361*5acbe002SDavid du Colombier 				 */
362*5acbe002SDavid du Colombier 				if (access(file, AEXEC) == 0)
363*5acbe002SDavid du Colombier 					break;
3643e12c5d1SDavid du Colombier 			}
36599eb86a7SDavid du Colombier 			else werrstr("command name too long");
366219b2ee8SDavid du Colombier 		}
367219b2ee8SDavid du Colombier 	}
368*5acbe002SDavid du Colombier 	pfmt(err, "%s: %s\n", argv[1], errstr);
3693e12c5d1SDavid du Colombier 	efree((char *)argv);
3703e12c5d1SDavid du Colombier }
37199eb86a7SDavid du Colombier #define	NDIR	256		/* shoud be a better way */
372dc5a79c1SDavid du Colombier 
373dc5a79c1SDavid du Colombier int
374dc5a79c1SDavid du Colombier Globsize(char *p)
3753e12c5d1SDavid du Colombier {
37673e742d7SDavid du Colombier 	int isglob = 0, globlen = NDIR+1;
3773e12c5d1SDavid du Colombier 	for(;*p;p++){
3783e12c5d1SDavid du Colombier 		if(*p==GLOB){
3793e12c5d1SDavid du Colombier 			p++;
380dc5a79c1SDavid du Colombier 			if(*p!=GLOB)
381dc5a79c1SDavid du Colombier 				isglob++;
3829a747e4fSDavid du Colombier 			globlen+=*p=='*'?NDIR:1;
3833e12c5d1SDavid du Colombier 		}
3843e12c5d1SDavid du Colombier 		else
3853e12c5d1SDavid du Colombier 			globlen++;
3863e12c5d1SDavid du Colombier 	}
3873e12c5d1SDavid du Colombier 	return isglob?globlen:0;
3883e12c5d1SDavid du Colombier }
3893e12c5d1SDavid du Colombier #define	NFD	50
390276e7d6dSDavid du Colombier 
3913e12c5d1SDavid du Colombier struct{
3929a747e4fSDavid du Colombier 	Dir	*dbuf;
3939a747e4fSDavid du Colombier 	int	i;
3943e12c5d1SDavid du Colombier 	int	n;
3953e12c5d1SDavid du Colombier }dir[NFD];
396dc5a79c1SDavid du Colombier 
397dc5a79c1SDavid du Colombier int
398dc5a79c1SDavid du Colombier Opendir(char *name)
3993e12c5d1SDavid du Colombier {
4009a747e4fSDavid du Colombier 	Dir *db;
4013e12c5d1SDavid du Colombier 	int f;
4023e12c5d1SDavid du Colombier 	f = open(name, 0);
4033e12c5d1SDavid du Colombier 	if(f==-1)
4043e12c5d1SDavid du Colombier 		return f;
4059a747e4fSDavid du Colombier 	db = dirfstat(f);
4069a747e4fSDavid du Colombier 	if(db!=nil && (db->mode&DMDIR)){
4079a747e4fSDavid du Colombier 		if(f<NFD){
4089a747e4fSDavid du Colombier 			dir[f].i = 0;
4099a747e4fSDavid du Colombier 			dir[f].n = 0;
4103e12c5d1SDavid du Colombier 		}
4119a747e4fSDavid du Colombier 		free(db);
4123e12c5d1SDavid du Colombier 		return f;
4133e12c5d1SDavid du Colombier 	}
4149a747e4fSDavid du Colombier 	free(db);
4153e12c5d1SDavid du Colombier 	close(f);
4163e12c5d1SDavid du Colombier 	return -1;
4173e12c5d1SDavid du Colombier }
4186b6b9ac8SDavid du Colombier 
4196b6b9ac8SDavid du Colombier static int
4206b6b9ac8SDavid du Colombier trimdirs(Dir *d, int nd)
4216b6b9ac8SDavid du Colombier {
4226b6b9ac8SDavid du Colombier 	int r, w;
4236b6b9ac8SDavid du Colombier 
4246b6b9ac8SDavid du Colombier 	for(r=w=0; r<nd; r++)
4256b6b9ac8SDavid du Colombier 		if(d[r].mode&DMDIR)
4266b6b9ac8SDavid du Colombier 			d[w++] = d[r];
4276b6b9ac8SDavid du Colombier 	return w;
4286b6b9ac8SDavid du Colombier }
4296b6b9ac8SDavid du Colombier 
4306b6b9ac8SDavid du Colombier /*
4316b6b9ac8SDavid du Colombier  * onlydirs is advisory -- it means you only
4326b6b9ac8SDavid du Colombier  * need to return the directories.  it's okay to
4336b6b9ac8SDavid du Colombier  * return files too (e.g., on unix where you can't
4346b6b9ac8SDavid du Colombier  * tell during the readdir), but that just makes
4356b6b9ac8SDavid du Colombier  * the globber work harder.
4366b6b9ac8SDavid du Colombier  */
437dc5a79c1SDavid du Colombier int
438276e7d6dSDavid du Colombier Readdir(int f, void *p, int onlydirs)
4393e12c5d1SDavid du Colombier {
4403e12c5d1SDavid du Colombier 	int n;
441dc5a79c1SDavid du Colombier 
4429a747e4fSDavid du Colombier 	if(f<0 || f>=NFD)
4433e12c5d1SDavid du Colombier 		return 0;
4446b6b9ac8SDavid du Colombier Again:
4459a747e4fSDavid du Colombier 	if(dir[f].i==dir[f].n){	/* read */
4469a747e4fSDavid du Colombier 		free(dir[f].dbuf);
4479a747e4fSDavid du Colombier 		dir[f].dbuf = 0;
4489a747e4fSDavid du Colombier 		n = dirread(f, &dir[f].dbuf);
4496b6b9ac8SDavid du Colombier 		if(n>0){
4506b6b9ac8SDavid du Colombier 			if(onlydirs){
4516b6b9ac8SDavid du Colombier 				n = trimdirs(dir[f].dbuf, n);
4526b6b9ac8SDavid du Colombier 				if(n == 0)
4536b6b9ac8SDavid du Colombier 					goto Again;
4546b6b9ac8SDavid du Colombier 			}
4559a747e4fSDavid du Colombier 			dir[f].n = n;
4566b6b9ac8SDavid du Colombier 		}else
4573e12c5d1SDavid du Colombier 			dir[f].n = 0;
4589a747e4fSDavid du Colombier 		dir[f].i = 0;
4593e12c5d1SDavid du Colombier 	}
4609a747e4fSDavid du Colombier 	if(dir[f].i == dir[f].n)
4613e12c5d1SDavid du Colombier 		return 0;
4629a747e4fSDavid du Colombier 	strcpy(p, dir[f].dbuf[dir[f].i].name);
4639a747e4fSDavid du Colombier 	dir[f].i++;
4643e12c5d1SDavid du Colombier 	return 1;
4653e12c5d1SDavid du Colombier }
466dc5a79c1SDavid du Colombier 
467dc5a79c1SDavid du Colombier void
468dc5a79c1SDavid du Colombier Closedir(int f)
469dc5a79c1SDavid du Colombier {
4709a747e4fSDavid du Colombier 	if(f>=0 && f<NFD){
4719a747e4fSDavid du Colombier 		free(dir[f].dbuf);
4729a747e4fSDavid du Colombier 		dir[f].i = 0;
4739a747e4fSDavid du Colombier 		dir[f].n = 0;
4749a747e4fSDavid du Colombier 		dir[f].dbuf = 0;
4753e12c5d1SDavid du Colombier 	}
4763e12c5d1SDavid du Colombier 	close(f);
4773e12c5d1SDavid du Colombier }
4783e12c5d1SDavid du Colombier int interrupted = 0;
4793e12c5d1SDavid du Colombier void
4807dd7cddfSDavid du Colombier notifyf(void*, char *s)
4813e12c5d1SDavid du Colombier {
4823e12c5d1SDavid du Colombier 	int i;
48399eb86a7SDavid du Colombier 	for(i = 0;syssigname[i];i++) if(strncmp(s, syssigname[i], strlen(syssigname[i]))==0){
48499eb86a7SDavid du Colombier 		if(strncmp(s, "sys: ", 5)!=0) interrupted = 1;
4853e12c5d1SDavid du Colombier 		goto Out;
4863e12c5d1SDavid du Colombier 	}
4873e12c5d1SDavid du Colombier 	pfmt(err, "rc: note: %s\n", s);
4883e12c5d1SDavid du Colombier 	noted(NDFLT);
4893e12c5d1SDavid du Colombier 	return;
4903e12c5d1SDavid du Colombier Out:
491219b2ee8SDavid du Colombier 	if(strcmp(s, "interrupt")!=0 || trap[i]==0){
4923e12c5d1SDavid du Colombier 		trap[i]++;
4933e12c5d1SDavid du Colombier 		ntrap++;
494219b2ee8SDavid du Colombier 	}
4953e12c5d1SDavid du Colombier 	if(ntrap>=32){	/* rc is probably in a trap loop */
4963e12c5d1SDavid du Colombier 		pfmt(err, "rc: Too many traps (trap %s), aborting\n", s);
4973e12c5d1SDavid du Colombier 		abort();
4983e12c5d1SDavid du Colombier 	}
4993e12c5d1SDavid du Colombier 	noted(NCONT);
5003e12c5d1SDavid du Colombier }
501dc5a79c1SDavid du Colombier 
502dc5a79c1SDavid du Colombier void
503dc5a79c1SDavid du Colombier Trapinit(void)
504dc5a79c1SDavid du Colombier {
5053e12c5d1SDavid du Colombier 	notify(notifyf);
5063e12c5d1SDavid du Colombier }
507dc5a79c1SDavid du Colombier 
508dc5a79c1SDavid du Colombier void
509dc5a79c1SDavid du Colombier Unlink(char *name)
5103e12c5d1SDavid du Colombier {
5113e12c5d1SDavid du Colombier 	remove(name);
5123e12c5d1SDavid du Colombier }
513dc5a79c1SDavid du Colombier 
514dc5a79c1SDavid du Colombier long
515276e7d6dSDavid du Colombier Write(int fd, void *buf, long cnt)
5163e12c5d1SDavid du Colombier {
517276e7d6dSDavid du Colombier 	return write(fd, buf, cnt);
5183e12c5d1SDavid du Colombier }
519dc5a79c1SDavid du Colombier 
520dc5a79c1SDavid du Colombier long
521276e7d6dSDavid du Colombier Read(int fd, void *buf, long cnt)
5223e12c5d1SDavid du Colombier {
5233e12c5d1SDavid du Colombier 	return read(fd, buf, cnt);
5243e12c5d1SDavid du Colombier }
525dc5a79c1SDavid du Colombier 
526dc5a79c1SDavid du Colombier long
527dc5a79c1SDavid du Colombier Seek(int fd, long cnt, long whence)
5283e12c5d1SDavid du Colombier {
5293e12c5d1SDavid du Colombier 	return seek(fd, cnt, whence);
5303e12c5d1SDavid du Colombier }
531dc5a79c1SDavid du Colombier 
532dc5a79c1SDavid du Colombier int
533dc5a79c1SDavid du Colombier Executable(char *file)
5343e12c5d1SDavid du Colombier {
5359a747e4fSDavid du Colombier 	Dir *statbuf;
5369a747e4fSDavid du Colombier 	int ret;
5373e12c5d1SDavid du Colombier 
5389a747e4fSDavid du Colombier 	statbuf = dirstat(file);
539dc5a79c1SDavid du Colombier 	if(statbuf == nil)
540dc5a79c1SDavid du Colombier 		return 0;
54199eb86a7SDavid du Colombier 	ret = ((statbuf->mode&0111)!=0 && (statbuf->mode&DMDIR)==0);
5429a747e4fSDavid du Colombier 	free(statbuf);
5439a747e4fSDavid du Colombier 	return ret;
5443e12c5d1SDavid du Colombier }
545dc5a79c1SDavid du Colombier 
546dc5a79c1SDavid du Colombier int
547dc5a79c1SDavid du Colombier Creat(char *file)
5483e12c5d1SDavid du Colombier {
54999eb86a7SDavid du Colombier 	return create(file, 1, 0666L);
5503e12c5d1SDavid du Colombier }
551dc5a79c1SDavid du Colombier 
552dc5a79c1SDavid du Colombier int
553dc5a79c1SDavid du Colombier Dup(int a, int b)
554dc5a79c1SDavid du Colombier {
5553e12c5d1SDavid du Colombier 	return dup(a, b);
5563e12c5d1SDavid du Colombier }
557dc5a79c1SDavid du Colombier 
558dc5a79c1SDavid du Colombier int
559dc5a79c1SDavid du Colombier Dup1(int)
560dc5a79c1SDavid du Colombier {
5613e12c5d1SDavid du Colombier 	return -1;
5623e12c5d1SDavid du Colombier }
563dc5a79c1SDavid du Colombier 
564dc5a79c1SDavid du Colombier void
565dc5a79c1SDavid du Colombier Exit(char *stat)
5663e12c5d1SDavid du Colombier {
5673e12c5d1SDavid du Colombier 	Updenv();
5683e12c5d1SDavid du Colombier 	setstatus(stat);
5693e12c5d1SDavid du Colombier 	exits(truestatus()?"":getstatus());
5703e12c5d1SDavid du Colombier }
571dc5a79c1SDavid du Colombier 
572dc5a79c1SDavid du Colombier int
573dc5a79c1SDavid du Colombier Eintr(void)
574dc5a79c1SDavid du Colombier {
5753e12c5d1SDavid du Colombier 	return interrupted;
5763e12c5d1SDavid du Colombier }
577dc5a79c1SDavid du Colombier 
578dc5a79c1SDavid du Colombier void
579dc5a79c1SDavid du Colombier Noerror(void)
580dc5a79c1SDavid du Colombier {
5813e12c5d1SDavid du Colombier 	interrupted = 0;
5823e12c5d1SDavid du Colombier }
583dc5a79c1SDavid du Colombier 
584dc5a79c1SDavid du Colombier int
585dc5a79c1SDavid du Colombier Isatty(int fd)
586dc5a79c1SDavid du Colombier {
5874f281771SDavid du Colombier 	char buf[64];
5883e12c5d1SDavid du Colombier 
5894f281771SDavid du Colombier 	if(fd2path(fd, buf, sizeof buf) != 0)
590dc5a79c1SDavid du Colombier 		return 0;
5914f281771SDavid du Colombier 
5923806af99SDavid du Colombier 	/* might be #c/cons during boot - fixed 22 april 2005, remove this later */
5933806af99SDavid du Colombier 	if(strcmp(buf, "#c/cons") == 0)
5943806af99SDavid du Colombier 		return 1;
5953806af99SDavid du Colombier 
5964f281771SDavid du Colombier 	/* might be /mnt/term/dev/cons */
5974f281771SDavid du Colombier 	return strlen(buf) >= 9 && strcmp(buf+strlen(buf)-9, "/dev/cons") == 0;
5983e12c5d1SDavid du Colombier }
599dc5a79c1SDavid du Colombier 
600dc5a79c1SDavid du Colombier void
601dc5a79c1SDavid du Colombier Abort(void)
602dc5a79c1SDavid du Colombier {
6033e12c5d1SDavid du Colombier 	pfmt(err, "aborting\n");
6043e12c5d1SDavid du Colombier 	flush(err);
6053e12c5d1SDavid du Colombier 	Exit("aborting");
6063e12c5d1SDavid du Colombier }
607dc5a79c1SDavid du Colombier 
608dc5a79c1SDavid du Colombier void
609276e7d6dSDavid du Colombier Memcpy(void *a, void *b, long n)
6103e12c5d1SDavid du Colombier {
611276e7d6dSDavid du Colombier 	memmove(a, b, n);
6123e12c5d1SDavid du Colombier }
613dc5a79c1SDavid du Colombier 
614dc5a79c1SDavid du Colombier void*
615dc5a79c1SDavid du Colombier Malloc(ulong n)
616dc5a79c1SDavid du Colombier {
6173e12c5d1SDavid du Colombier 	return malloc(n);
6183e12c5d1SDavid du Colombier }
619d3907fe5SDavid du Colombier 
620d3907fe5SDavid du Colombier int *waitpids;
621d3907fe5SDavid du Colombier int nwaitpids;
622d3907fe5SDavid du Colombier 
623d3907fe5SDavid du Colombier void
624d3907fe5SDavid du Colombier addwaitpid(int pid)
625d3907fe5SDavid du Colombier {
626d3907fe5SDavid du Colombier 	waitpids = realloc(waitpids, (nwaitpids+1)*sizeof waitpids[0]);
627d3907fe5SDavid du Colombier 	if(waitpids == 0)
628d3907fe5SDavid du Colombier 		panic("Can't realloc %d waitpids", nwaitpids+1);
629d3907fe5SDavid du Colombier 	waitpids[nwaitpids++] = pid;
630d3907fe5SDavid du Colombier }
631d3907fe5SDavid du Colombier 
632d3907fe5SDavid du Colombier void
633d3907fe5SDavid du Colombier delwaitpid(int pid)
634d3907fe5SDavid du Colombier {
635d3907fe5SDavid du Colombier 	int r, w;
636d3907fe5SDavid du Colombier 
637d3907fe5SDavid du Colombier 	for(r=w=0; r<nwaitpids; r++)
638d3907fe5SDavid du Colombier 		if(waitpids[r] != pid)
639d3907fe5SDavid du Colombier 			waitpids[w++] = waitpids[r];
640d3907fe5SDavid du Colombier 	nwaitpids = w;
641d3907fe5SDavid du Colombier }
642d3907fe5SDavid du Colombier 
643d3907fe5SDavid du Colombier void
644d3907fe5SDavid du Colombier clearwaitpids(void)
645d3907fe5SDavid du Colombier {
646d3907fe5SDavid du Colombier 	nwaitpids = 0;
647d3907fe5SDavid du Colombier }
648d3907fe5SDavid du Colombier 
649d3907fe5SDavid du Colombier int
650d3907fe5SDavid du Colombier havewaitpid(int pid)
651d3907fe5SDavid du Colombier {
652d3907fe5SDavid du Colombier 	int i;
653d3907fe5SDavid du Colombier 
654d3907fe5SDavid du Colombier 	for(i=0; i<nwaitpids; i++)
655d3907fe5SDavid du Colombier 		if(waitpids[i] == pid)
656d3907fe5SDavid du Colombier 			return 1;
657d3907fe5SDavid du Colombier 	return 0;
658d3907fe5SDavid du Colombier }
659f07722aaSDavid du Colombier 
660f07722aaSDavid du Colombier /* avoid loading any floating-point library code */
661f07722aaSDavid du Colombier int
662f07722aaSDavid du Colombier _efgfmt(Fmt *)
663f07722aaSDavid du Colombier {
664f07722aaSDavid du Colombier 	return -1;
665f07722aaSDavid du Colombier }
666