xref: /plan9/sys/src/cmd/rc/plan9.c (revision f07722aa9aa44fa6461f2bd97fbae077cfb58962)
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 
306dc5a79c1SDavid du Colombier int
307dc5a79c1SDavid du Colombier ForkExecute(char *file, char **argv, int sin, int sout, int serr)
308dc5a79c1SDavid du Colombier {
309dc5a79c1SDavid du Colombier 	int pid;
310dc5a79c1SDavid du Colombier 
311dc5a79c1SDavid du Colombier 	if(access(file, 1) != 0)
312dc5a79c1SDavid du Colombier 		return -1;
313dc5a79c1SDavid du Colombier 	switch(pid = fork()){
314dc5a79c1SDavid du Colombier 	case -1:
315dc5a79c1SDavid du Colombier 		return -1;
316dc5a79c1SDavid du Colombier 	case 0:
317dc5a79c1SDavid du Colombier 		if(sin >= 0)
318dc5a79c1SDavid du Colombier 			dup(sin, 0);
319dc5a79c1SDavid du Colombier 		else
320dc5a79c1SDavid du Colombier 			close(0);
321dc5a79c1SDavid du Colombier 		if(sout >= 0)
322dc5a79c1SDavid du Colombier 			dup(sout, 1);
323dc5a79c1SDavid du Colombier 		else
324dc5a79c1SDavid du Colombier 			close(1);
325dc5a79c1SDavid du Colombier 		if(serr >= 0)
326dc5a79c1SDavid du Colombier 			dup(serr, 2);
327dc5a79c1SDavid du Colombier 		else
328dc5a79c1SDavid du Colombier 			close(2);
329dc5a79c1SDavid du Colombier 		exec(file, argv);
330dc5a79c1SDavid du Colombier 		exits(file);
331dc5a79c1SDavid du Colombier 	}
332dc5a79c1SDavid du Colombier 	return pid;
333dc5a79c1SDavid du Colombier }
334dc5a79c1SDavid du Colombier 
335dc5a79c1SDavid du Colombier void
336dc5a79c1SDavid du Colombier Execute(word *args, word *path)
3373e12c5d1SDavid du Colombier {
3383e12c5d1SDavid du Colombier 	char **argv = mkargv(args);
339219b2ee8SDavid du Colombier 	char file[1024];
340219b2ee8SDavid du Colombier 	int nc;
3413e12c5d1SDavid du Colombier 	Updenv();
3423e12c5d1SDavid du Colombier 	for(;path;path = path->next){
343219b2ee8SDavid du Colombier 		nc = strlen(path->word);
344276e7d6dSDavid du Colombier 		if(nc < sizeof file - 1){	/* 1 for / */
3453e12c5d1SDavid du Colombier 			strcpy(file, path->word);
346219b2ee8SDavid du Colombier 			if(file[0]){
347219b2ee8SDavid du Colombier 				strcat(file, "/");
348219b2ee8SDavid du Colombier 				nc++;
349219b2ee8SDavid du Colombier 			}
350276e7d6dSDavid du Colombier 			if(nc + strlen(argv[1]) < sizeof file){
3513e12c5d1SDavid du Colombier 				strcat(file, argv[1]);
3523e12c5d1SDavid du Colombier 				exec(file, argv+1);
3533e12c5d1SDavid du Colombier 			}
35499eb86a7SDavid du Colombier 			else werrstr("command name too long");
355219b2ee8SDavid du Colombier 		}
356219b2ee8SDavid du Colombier 	}
3579a747e4fSDavid du Colombier 	rerrstr(file, sizeof file);
3583e12c5d1SDavid du Colombier 	pfmt(err, "%s: %s\n", argv[1], file);
3593e12c5d1SDavid du Colombier 	efree((char *)argv);
3603e12c5d1SDavid du Colombier }
36199eb86a7SDavid du Colombier #define	NDIR	256		/* shoud be a better way */
362dc5a79c1SDavid du Colombier 
363dc5a79c1SDavid du Colombier int
364dc5a79c1SDavid du Colombier Globsize(char *p)
3653e12c5d1SDavid du Colombier {
36673e742d7SDavid du Colombier 	int isglob = 0, globlen = NDIR+1;
3673e12c5d1SDavid du Colombier 	for(;*p;p++){
3683e12c5d1SDavid du Colombier 		if(*p==GLOB){
3693e12c5d1SDavid du Colombier 			p++;
370dc5a79c1SDavid du Colombier 			if(*p!=GLOB)
371dc5a79c1SDavid du Colombier 				isglob++;
3729a747e4fSDavid du Colombier 			globlen+=*p=='*'?NDIR:1;
3733e12c5d1SDavid du Colombier 		}
3743e12c5d1SDavid du Colombier 		else
3753e12c5d1SDavid du Colombier 			globlen++;
3763e12c5d1SDavid du Colombier 	}
3773e12c5d1SDavid du Colombier 	return isglob?globlen:0;
3783e12c5d1SDavid du Colombier }
3793e12c5d1SDavid du Colombier #define	NFD	50
380276e7d6dSDavid du Colombier 
3813e12c5d1SDavid du Colombier struct{
3829a747e4fSDavid du Colombier 	Dir	*dbuf;
3839a747e4fSDavid du Colombier 	int	i;
3843e12c5d1SDavid du Colombier 	int	n;
3853e12c5d1SDavid du Colombier }dir[NFD];
386dc5a79c1SDavid du Colombier 
387dc5a79c1SDavid du Colombier int
388dc5a79c1SDavid du Colombier Opendir(char *name)
3893e12c5d1SDavid du Colombier {
3909a747e4fSDavid du Colombier 	Dir *db;
3913e12c5d1SDavid du Colombier 	int f;
3923e12c5d1SDavid du Colombier 	f = open(name, 0);
3933e12c5d1SDavid du Colombier 	if(f==-1)
3943e12c5d1SDavid du Colombier 		return f;
3959a747e4fSDavid du Colombier 	db = dirfstat(f);
3969a747e4fSDavid du Colombier 	if(db!=nil && (db->mode&DMDIR)){
3979a747e4fSDavid du Colombier 		if(f<NFD){
3989a747e4fSDavid du Colombier 			dir[f].i = 0;
3999a747e4fSDavid du Colombier 			dir[f].n = 0;
4003e12c5d1SDavid du Colombier 		}
4019a747e4fSDavid du Colombier 		free(db);
4023e12c5d1SDavid du Colombier 		return f;
4033e12c5d1SDavid du Colombier 	}
4049a747e4fSDavid du Colombier 	free(db);
4053e12c5d1SDavid du Colombier 	close(f);
4063e12c5d1SDavid du Colombier 	return -1;
4073e12c5d1SDavid du Colombier }
4086b6b9ac8SDavid du Colombier 
4096b6b9ac8SDavid du Colombier static int
4106b6b9ac8SDavid du Colombier trimdirs(Dir *d, int nd)
4116b6b9ac8SDavid du Colombier {
4126b6b9ac8SDavid du Colombier 	int r, w;
4136b6b9ac8SDavid du Colombier 
4146b6b9ac8SDavid du Colombier 	for(r=w=0; r<nd; r++)
4156b6b9ac8SDavid du Colombier 		if(d[r].mode&DMDIR)
4166b6b9ac8SDavid du Colombier 			d[w++] = d[r];
4176b6b9ac8SDavid du Colombier 	return w;
4186b6b9ac8SDavid du Colombier }
4196b6b9ac8SDavid du Colombier 
4206b6b9ac8SDavid du Colombier /*
4216b6b9ac8SDavid du Colombier  * onlydirs is advisory -- it means you only
4226b6b9ac8SDavid du Colombier  * need to return the directories.  it's okay to
4236b6b9ac8SDavid du Colombier  * return files too (e.g., on unix where you can't
4246b6b9ac8SDavid du Colombier  * tell during the readdir), but that just makes
4256b6b9ac8SDavid du Colombier  * the globber work harder.
4266b6b9ac8SDavid du Colombier  */
427dc5a79c1SDavid du Colombier int
428276e7d6dSDavid du Colombier Readdir(int f, void *p, int onlydirs)
4293e12c5d1SDavid du Colombier {
4303e12c5d1SDavid du Colombier 	int n;
431dc5a79c1SDavid du Colombier 
4329a747e4fSDavid du Colombier 	if(f<0 || f>=NFD)
4333e12c5d1SDavid du Colombier 		return 0;
4346b6b9ac8SDavid du Colombier Again:
4359a747e4fSDavid du Colombier 	if(dir[f].i==dir[f].n){	/* read */
4369a747e4fSDavid du Colombier 		free(dir[f].dbuf);
4379a747e4fSDavid du Colombier 		dir[f].dbuf = 0;
4389a747e4fSDavid du Colombier 		n = dirread(f, &dir[f].dbuf);
4396b6b9ac8SDavid du Colombier 		if(n>0){
4406b6b9ac8SDavid du Colombier 			if(onlydirs){
4416b6b9ac8SDavid du Colombier 				n = trimdirs(dir[f].dbuf, n);
4426b6b9ac8SDavid du Colombier 				if(n == 0)
4436b6b9ac8SDavid du Colombier 					goto Again;
4446b6b9ac8SDavid du Colombier 			}
4459a747e4fSDavid du Colombier 			dir[f].n = n;
4466b6b9ac8SDavid du Colombier 		}else
4473e12c5d1SDavid du Colombier 			dir[f].n = 0;
4489a747e4fSDavid du Colombier 		dir[f].i = 0;
4493e12c5d1SDavid du Colombier 	}
4509a747e4fSDavid du Colombier 	if(dir[f].i == dir[f].n)
4513e12c5d1SDavid du Colombier 		return 0;
4529a747e4fSDavid du Colombier 	strcpy(p, dir[f].dbuf[dir[f].i].name);
4539a747e4fSDavid du Colombier 	dir[f].i++;
4543e12c5d1SDavid du Colombier 	return 1;
4553e12c5d1SDavid du Colombier }
456dc5a79c1SDavid du Colombier 
457dc5a79c1SDavid du Colombier void
458dc5a79c1SDavid du Colombier Closedir(int f)
459dc5a79c1SDavid du Colombier {
4609a747e4fSDavid du Colombier 	if(f>=0 && f<NFD){
4619a747e4fSDavid du Colombier 		free(dir[f].dbuf);
4629a747e4fSDavid du Colombier 		dir[f].i = 0;
4639a747e4fSDavid du Colombier 		dir[f].n = 0;
4649a747e4fSDavid du Colombier 		dir[f].dbuf = 0;
4653e12c5d1SDavid du Colombier 	}
4663e12c5d1SDavid du Colombier 	close(f);
4673e12c5d1SDavid du Colombier }
4683e12c5d1SDavid du Colombier int interrupted = 0;
4693e12c5d1SDavid du Colombier void
4707dd7cddfSDavid du Colombier notifyf(void*, char *s)
4713e12c5d1SDavid du Colombier {
4723e12c5d1SDavid du Colombier 	int i;
47399eb86a7SDavid du Colombier 	for(i = 0;syssigname[i];i++) if(strncmp(s, syssigname[i], strlen(syssigname[i]))==0){
47499eb86a7SDavid du Colombier 		if(strncmp(s, "sys: ", 5)!=0) interrupted = 1;
4753e12c5d1SDavid du Colombier 		goto Out;
4763e12c5d1SDavid du Colombier 	}
4773e12c5d1SDavid du Colombier 	pfmt(err, "rc: note: %s\n", s);
4783e12c5d1SDavid du Colombier 	noted(NDFLT);
4793e12c5d1SDavid du Colombier 	return;
4803e12c5d1SDavid du Colombier Out:
481219b2ee8SDavid du Colombier 	if(strcmp(s, "interrupt")!=0 || trap[i]==0){
4823e12c5d1SDavid du Colombier 		trap[i]++;
4833e12c5d1SDavid du Colombier 		ntrap++;
484219b2ee8SDavid du Colombier 	}
4853e12c5d1SDavid du Colombier 	if(ntrap>=32){	/* rc is probably in a trap loop */
4863e12c5d1SDavid du Colombier 		pfmt(err, "rc: Too many traps (trap %s), aborting\n", s);
4873e12c5d1SDavid du Colombier 		abort();
4883e12c5d1SDavid du Colombier 	}
4893e12c5d1SDavid du Colombier 	noted(NCONT);
4903e12c5d1SDavid du Colombier }
491dc5a79c1SDavid du Colombier 
492dc5a79c1SDavid du Colombier void
493dc5a79c1SDavid du Colombier Trapinit(void)
494dc5a79c1SDavid du Colombier {
4953e12c5d1SDavid du Colombier 	notify(notifyf);
4963e12c5d1SDavid du Colombier }
497dc5a79c1SDavid du Colombier 
498dc5a79c1SDavid du Colombier void
499dc5a79c1SDavid du Colombier Unlink(char *name)
5003e12c5d1SDavid du Colombier {
5013e12c5d1SDavid du Colombier 	remove(name);
5023e12c5d1SDavid du Colombier }
503dc5a79c1SDavid du Colombier 
504dc5a79c1SDavid du Colombier long
505276e7d6dSDavid du Colombier Write(int fd, void *buf, long cnt)
5063e12c5d1SDavid du Colombier {
507276e7d6dSDavid du Colombier 	return write(fd, buf, cnt);
5083e12c5d1SDavid du Colombier }
509dc5a79c1SDavid du Colombier 
510dc5a79c1SDavid du Colombier long
511276e7d6dSDavid du Colombier Read(int fd, void *buf, long cnt)
5123e12c5d1SDavid du Colombier {
5133e12c5d1SDavid du Colombier 	return read(fd, buf, cnt);
5143e12c5d1SDavid du Colombier }
515dc5a79c1SDavid du Colombier 
516dc5a79c1SDavid du Colombier long
517dc5a79c1SDavid du Colombier Seek(int fd, long cnt, long whence)
5183e12c5d1SDavid du Colombier {
5193e12c5d1SDavid du Colombier 	return seek(fd, cnt, whence);
5203e12c5d1SDavid du Colombier }
521dc5a79c1SDavid du Colombier 
522dc5a79c1SDavid du Colombier int
523dc5a79c1SDavid du Colombier Executable(char *file)
5243e12c5d1SDavid du Colombier {
5259a747e4fSDavid du Colombier 	Dir *statbuf;
5269a747e4fSDavid du Colombier 	int ret;
5273e12c5d1SDavid du Colombier 
5289a747e4fSDavid du Colombier 	statbuf = dirstat(file);
529dc5a79c1SDavid du Colombier 	if(statbuf == nil)
530dc5a79c1SDavid du Colombier 		return 0;
53199eb86a7SDavid du Colombier 	ret = ((statbuf->mode&0111)!=0 && (statbuf->mode&DMDIR)==0);
5329a747e4fSDavid du Colombier 	free(statbuf);
5339a747e4fSDavid du Colombier 	return ret;
5343e12c5d1SDavid du Colombier }
535dc5a79c1SDavid du Colombier 
536dc5a79c1SDavid du Colombier int
537dc5a79c1SDavid du Colombier Creat(char *file)
5383e12c5d1SDavid du Colombier {
53999eb86a7SDavid du Colombier 	return create(file, 1, 0666L);
5403e12c5d1SDavid du Colombier }
541dc5a79c1SDavid du Colombier 
542dc5a79c1SDavid du Colombier int
543dc5a79c1SDavid du Colombier Dup(int a, int b)
544dc5a79c1SDavid du Colombier {
5453e12c5d1SDavid du Colombier 	return dup(a, b);
5463e12c5d1SDavid du Colombier }
547dc5a79c1SDavid du Colombier 
548dc5a79c1SDavid du Colombier int
549dc5a79c1SDavid du Colombier Dup1(int)
550dc5a79c1SDavid du Colombier {
5513e12c5d1SDavid du Colombier 	return -1;
5523e12c5d1SDavid du Colombier }
553dc5a79c1SDavid du Colombier 
554dc5a79c1SDavid du Colombier void
555dc5a79c1SDavid du Colombier Exit(char *stat)
5563e12c5d1SDavid du Colombier {
5573e12c5d1SDavid du Colombier 	Updenv();
5583e12c5d1SDavid du Colombier 	setstatus(stat);
5593e12c5d1SDavid du Colombier 	exits(truestatus()?"":getstatus());
5603e12c5d1SDavid du Colombier }
561dc5a79c1SDavid du Colombier 
562dc5a79c1SDavid du Colombier int
563dc5a79c1SDavid du Colombier Eintr(void)
564dc5a79c1SDavid du Colombier {
5653e12c5d1SDavid du Colombier 	return interrupted;
5663e12c5d1SDavid du Colombier }
567dc5a79c1SDavid du Colombier 
568dc5a79c1SDavid du Colombier void
569dc5a79c1SDavid du Colombier Noerror(void)
570dc5a79c1SDavid du Colombier {
5713e12c5d1SDavid du Colombier 	interrupted = 0;
5723e12c5d1SDavid du Colombier }
573dc5a79c1SDavid du Colombier 
574dc5a79c1SDavid du Colombier int
575dc5a79c1SDavid du Colombier Isatty(int fd)
576dc5a79c1SDavid du Colombier {
5774f281771SDavid du Colombier 	char buf[64];
5783e12c5d1SDavid du Colombier 
5794f281771SDavid du Colombier 	if(fd2path(fd, buf, sizeof buf) != 0)
580dc5a79c1SDavid du Colombier 		return 0;
5814f281771SDavid du Colombier 
5823806af99SDavid du Colombier 	/* might be #c/cons during boot - fixed 22 april 2005, remove this later */
5833806af99SDavid du Colombier 	if(strcmp(buf, "#c/cons") == 0)
5843806af99SDavid du Colombier 		return 1;
5853806af99SDavid du Colombier 
5864f281771SDavid du Colombier 	/* might be /mnt/term/dev/cons */
5874f281771SDavid du Colombier 	return strlen(buf) >= 9 && strcmp(buf+strlen(buf)-9, "/dev/cons") == 0;
5883e12c5d1SDavid du Colombier }
589dc5a79c1SDavid du Colombier 
590dc5a79c1SDavid du Colombier void
591dc5a79c1SDavid du Colombier Abort(void)
592dc5a79c1SDavid du Colombier {
5933e12c5d1SDavid du Colombier 	pfmt(err, "aborting\n");
5943e12c5d1SDavid du Colombier 	flush(err);
5953e12c5d1SDavid du Colombier 	Exit("aborting");
5963e12c5d1SDavid du Colombier }
597dc5a79c1SDavid du Colombier 
598dc5a79c1SDavid du Colombier void
599276e7d6dSDavid du Colombier Memcpy(void *a, void *b, long n)
6003e12c5d1SDavid du Colombier {
601276e7d6dSDavid du Colombier 	memmove(a, b, n);
6023e12c5d1SDavid du Colombier }
603dc5a79c1SDavid du Colombier 
604dc5a79c1SDavid du Colombier void*
605dc5a79c1SDavid du Colombier Malloc(ulong n)
606dc5a79c1SDavid du Colombier {
6073e12c5d1SDavid du Colombier 	return malloc(n);
6083e12c5d1SDavid du Colombier }
609d3907fe5SDavid du Colombier 
610d3907fe5SDavid du Colombier int *waitpids;
611d3907fe5SDavid du Colombier int nwaitpids;
612d3907fe5SDavid du Colombier 
613d3907fe5SDavid du Colombier void
614d3907fe5SDavid du Colombier addwaitpid(int pid)
615d3907fe5SDavid du Colombier {
616d3907fe5SDavid du Colombier 	waitpids = realloc(waitpids, (nwaitpids+1)*sizeof waitpids[0]);
617d3907fe5SDavid du Colombier 	if(waitpids == 0)
618d3907fe5SDavid du Colombier 		panic("Can't realloc %d waitpids", nwaitpids+1);
619d3907fe5SDavid du Colombier 	waitpids[nwaitpids++] = pid;
620d3907fe5SDavid du Colombier }
621d3907fe5SDavid du Colombier 
622d3907fe5SDavid du Colombier void
623d3907fe5SDavid du Colombier delwaitpid(int pid)
624d3907fe5SDavid du Colombier {
625d3907fe5SDavid du Colombier 	int r, w;
626d3907fe5SDavid du Colombier 
627d3907fe5SDavid du Colombier 	for(r=w=0; r<nwaitpids; r++)
628d3907fe5SDavid du Colombier 		if(waitpids[r] != pid)
629d3907fe5SDavid du Colombier 			waitpids[w++] = waitpids[r];
630d3907fe5SDavid du Colombier 	nwaitpids = w;
631d3907fe5SDavid du Colombier }
632d3907fe5SDavid du Colombier 
633d3907fe5SDavid du Colombier void
634d3907fe5SDavid du Colombier clearwaitpids(void)
635d3907fe5SDavid du Colombier {
636d3907fe5SDavid du Colombier 	nwaitpids = 0;
637d3907fe5SDavid du Colombier }
638d3907fe5SDavid du Colombier 
639d3907fe5SDavid du Colombier int
640d3907fe5SDavid du Colombier havewaitpid(int pid)
641d3907fe5SDavid du Colombier {
642d3907fe5SDavid du Colombier 	int i;
643d3907fe5SDavid du Colombier 
644d3907fe5SDavid du Colombier 	for(i=0; i<nwaitpids; i++)
645d3907fe5SDavid du Colombier 		if(waitpids[i] == pid)
646d3907fe5SDavid du Colombier 			return 1;
647d3907fe5SDavid du Colombier 	return 0;
648d3907fe5SDavid du Colombier }
649*f07722aaSDavid du Colombier 
650*f07722aaSDavid du Colombier /* avoid loading any floating-point library code */
651*f07722aaSDavid du Colombier int
652*f07722aaSDavid du Colombier _efgfmt(Fmt *)
653*f07722aaSDavid du Colombier {
654*f07722aaSDavid du Colombier 	return -1;
655*f07722aaSDavid du Colombier }
656