xref: /plan9/sys/src/cmd/rc/plan9.c (revision d3907fe5a68251e8b016f54f72acf8767ba044bb)
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"
113e12c5d1SDavid du Colombier char *Signame[] = {
123e12c5d1SDavid du Colombier 	"sigexit",	"sighup",	"sigint",	"sigquit",
13219b2ee8SDavid du Colombier 	"sigalrm",	"sigkill",	"sigfpe",	"sigterm",
14219b2ee8SDavid du Colombier 	0
153e12c5d1SDavid du Colombier };
163e12c5d1SDavid du Colombier char *syssigname[] = {
173e12c5d1SDavid du Colombier 	"exit",		/* can't happen */
183e12c5d1SDavid du Colombier 	"hangup",
193e12c5d1SDavid du Colombier 	"interrupt",
203e12c5d1SDavid du Colombier 	"quit",		/* can't happen */
213e12c5d1SDavid du Colombier 	"alarm",
22219b2ee8SDavid du Colombier 	"kill",
233e12c5d1SDavid du Colombier 	"sys: fp: ",
24219b2ee8SDavid du Colombier 	"term",
253e12c5d1SDavid du Colombier 	0
263e12c5d1SDavid du Colombier };
273e12c5d1SDavid du Colombier char Rcmain[]="/rc/lib/rcmain";
283e12c5d1SDavid du Colombier char Fdprefix[]="/fd/";
293e12c5d1SDavid du Colombier void execfinit(void);
303e12c5d1SDavid du Colombier void execbind(void);
313e12c5d1SDavid du Colombier void execmount(void);
323e12c5d1SDavid du Colombier void execnewpgrp(void);
333e12c5d1SDavid du Colombier builtin Builtin[] = {
343e12c5d1SDavid du Colombier 	"cd",		execcd,
353e12c5d1SDavid du Colombier 	"whatis",	execwhatis,
363e12c5d1SDavid du Colombier 	"eval",		execeval,
373e12c5d1SDavid du Colombier 	"exec",		execexec,	/* but with popword first */
383e12c5d1SDavid du Colombier 	"exit",		execexit,
393e12c5d1SDavid du Colombier 	"shift",	execshift,
403e12c5d1SDavid du Colombier 	"wait",		execwait,
413e12c5d1SDavid du Colombier 	".",		execdot,
423e12c5d1SDavid du Colombier 	"finit",	execfinit,
433e12c5d1SDavid du Colombier 	"flag",		execflag,
443e12c5d1SDavid du Colombier 	"rfork",	execnewpgrp,
453e12c5d1SDavid du Colombier 	0
463e12c5d1SDavid du Colombier };
47dc5a79c1SDavid du Colombier 
48dc5a79c1SDavid du Colombier void
49dc5a79c1SDavid du Colombier execnewpgrp(void)
50dc5a79c1SDavid du Colombier {
513e12c5d1SDavid du Colombier 	int arg;
523e12c5d1SDavid du Colombier 	char *s;
533e12c5d1SDavid du Colombier 	switch(count(runq->argv->words)){
54dc5a79c1SDavid du Colombier 	case 1:
55dc5a79c1SDavid du Colombier 		arg = RFENVG|RFNAMEG|RFNOTEG;
56dc5a79c1SDavid du Colombier 		break;
573e12c5d1SDavid du Colombier 	case 2:
583e12c5d1SDavid du Colombier 		arg = 0;
593e12c5d1SDavid du Colombier 		for(s = runq->argv->words->next->word;*s;s++) switch(*s){
603e12c5d1SDavid du Colombier 		default:
613e12c5d1SDavid du Colombier 			goto Usage;
62dc5a79c1SDavid du Colombier 		case 'n':
63dc5a79c1SDavid du Colombier 			arg|=RFNAMEG;  break;
64dc5a79c1SDavid du Colombier 		case 'N':
65dc5a79c1SDavid du Colombier 			arg|=RFCNAMEG;
66dc5a79c1SDavid du Colombier 			break;
67dc5a79c1SDavid du Colombier 		case 'm':
68dc5a79c1SDavid du Colombier 			arg|=RFNOMNT;  break;
69dc5a79c1SDavid du Colombier 		case 'e':
70dc5a79c1SDavid du Colombier 			arg|=RFENVG;   break;
71dc5a79c1SDavid du Colombier 		case 'E':
72dc5a79c1SDavid du Colombier 			arg|=RFCENVG;  break;
73dc5a79c1SDavid du Colombier 		case 's':
74dc5a79c1SDavid du Colombier 			arg|=RFNOTEG;  break;
75dc5a79c1SDavid du Colombier 		case 'f':
76dc5a79c1SDavid du Colombier 			arg|=RFFDG;    break;
77dc5a79c1SDavid du Colombier 		case 'F':
78dc5a79c1SDavid du Colombier 			arg|=RFCFDG;   break;
793e12c5d1SDavid du Colombier 		}
803e12c5d1SDavid du Colombier 		break;
813e12c5d1SDavid du Colombier 	default:
823e12c5d1SDavid du Colombier 	Usage:
837dd7cddfSDavid du Colombier 		pfmt(err, "Usage: %s [fnesFNEm]\n", runq->argv->words->word);
843e12c5d1SDavid du Colombier 		setstatus("rfork usage");
853e12c5d1SDavid du Colombier 		poplist();
863e12c5d1SDavid du Colombier 		return;
873e12c5d1SDavid du Colombier 	}
883e12c5d1SDavid du Colombier 	if(rfork(arg)==-1){
893e12c5d1SDavid du Colombier 		pfmt(err, "rc: %s failed\n", runq->argv->words->word);
903e12c5d1SDavid du Colombier 		setstatus("rfork failed");
913e12c5d1SDavid du Colombier 	}
923e12c5d1SDavid du Colombier 	else
933e12c5d1SDavid du Colombier 		setstatus("");
943e12c5d1SDavid du Colombier 	poplist();
953e12c5d1SDavid du Colombier }
96dc5a79c1SDavid du Colombier 
97dc5a79c1SDavid du Colombier void
98dc5a79c1SDavid du Colombier Vinit(void)
99dc5a79c1SDavid du Colombier {
1009a747e4fSDavid du Colombier 	int dir, f, len;
1013e12c5d1SDavid du Colombier 	word *val;
1023e12c5d1SDavid du Colombier 	char *buf, *s;
1039a747e4fSDavid du Colombier 	Dir *ent;
1049a747e4fSDavid du Colombier 	int i, nent;
1059a747e4fSDavid du Colombier 	char envname[256];
1069a747e4fSDavid du Colombier 	dir = open("/env", OREAD);
1073e12c5d1SDavid du Colombier 	if(dir<0){
1089a747e4fSDavid du Colombier 		pfmt(err, "rc: can't open /env: %r\n");
1093e12c5d1SDavid du Colombier 		return;
1103e12c5d1SDavid du Colombier 	}
1119a747e4fSDavid du Colombier 	ent = nil;
1129a747e4fSDavid du Colombier 	for(;;){
1139a747e4fSDavid du Colombier 		nent = dirread(dir, &ent);
1149a747e4fSDavid du Colombier 		if(nent <= 0)
1159a747e4fSDavid du Colombier 			break;
1169a747e4fSDavid du Colombier 		for(i = 0; i<nent; i++){
1179a747e4fSDavid du Colombier 			len = ent[i].length;
1189a747e4fSDavid du Colombier 			if(len && strncmp(ent[i].name, "fn#", 3)!=0){
1199a747e4fSDavid du Colombier 				snprint(envname, sizeof envname, "/env/%s", ent[i].name);
1203e12c5d1SDavid du Colombier 				if((f = open(envname, 0))>=0){
1213e12c5d1SDavid du Colombier 					buf = emalloc((int)len+1);
1223e12c5d1SDavid du Colombier 					read(f, buf, (long)len);
1233e12c5d1SDavid du Colombier 					val = 0;
1243e12c5d1SDavid du Colombier 					/* Charitably add a 0 at the end if need be */
125dc5a79c1SDavid du Colombier 					if(buf[len-1])
126dc5a79c1SDavid du Colombier 						buf[len++]='\0';
1273e12c5d1SDavid du Colombier 					s = buf+len-1;
1283e12c5d1SDavid du Colombier 					for(;;){
1293e12c5d1SDavid du Colombier 						while(s!=buf && s[-1]!='\0') --s;
1303e12c5d1SDavid du Colombier 						val = newword(s, val);
131dc5a79c1SDavid du Colombier 						if(s==buf)
132dc5a79c1SDavid du Colombier 							break;
1333e12c5d1SDavid du Colombier 						--s;
1343e12c5d1SDavid du Colombier 					}
1359a747e4fSDavid du Colombier 					setvar(ent[i].name, val);
1369a747e4fSDavid du Colombier 					vlook(ent[i].name)->changed = 0;
1373e12c5d1SDavid du Colombier 					close(f);
1383e12c5d1SDavid du Colombier 					efree(buf);
1393e12c5d1SDavid du Colombier 				}
1403e12c5d1SDavid du Colombier 			}
1413e12c5d1SDavid du Colombier 		}
1429a747e4fSDavid du Colombier 		free(ent);
1439a747e4fSDavid du Colombier 	}
1443e12c5d1SDavid du Colombier 	close(dir);
1453e12c5d1SDavid du Colombier }
1463e12c5d1SDavid du Colombier int envdir;
147dc5a79c1SDavid du Colombier 
148dc5a79c1SDavid du Colombier void
149dc5a79c1SDavid du Colombier Xrdfn(void)
150dc5a79c1SDavid du Colombier {
1513e12c5d1SDavid du Colombier 	int f, len;
1529a747e4fSDavid du Colombier 	static Dir *ent, *allocent;
1539a747e4fSDavid du Colombier 	static int nent;
1549a747e4fSDavid du Colombier 	Dir *e;
1559a747e4fSDavid du Colombier 	char envname[256];
1569a747e4fSDavid du Colombier 
1579a747e4fSDavid du Colombier 	for(;;){
1589a747e4fSDavid du Colombier 		if(nent == 0){
1599a747e4fSDavid du Colombier 			free(allocent);
1609a747e4fSDavid du Colombier 			nent = dirread(envdir, &allocent);
1619a747e4fSDavid du Colombier 			ent = allocent;
1629a747e4fSDavid du Colombier 		}
1639a747e4fSDavid du Colombier 		if(nent <= 0)
1649a747e4fSDavid du Colombier 			break;
1659a747e4fSDavid du Colombier 		while(nent){
1669a747e4fSDavid du Colombier 			e = ent++;
1679a747e4fSDavid du Colombier 			nent--;
1689a747e4fSDavid du Colombier 			len = e->length;
1699a747e4fSDavid du Colombier 			if(len && strncmp(e->name, "fn#", 3)==0){
1709a747e4fSDavid du Colombier 				snprint(envname, sizeof envname, "/env/%s", e->name);
1713e12c5d1SDavid du Colombier 				if((f = open(envname, 0))>=0){
1723e12c5d1SDavid du Colombier 					execcmds(openfd(f));
1733e12c5d1SDavid du Colombier 					return;
1743e12c5d1SDavid du Colombier 				}
1753e12c5d1SDavid du Colombier 			}
1763e12c5d1SDavid du Colombier 		}
1779a747e4fSDavid du Colombier 	}
1783e12c5d1SDavid du Colombier 	close(envdir);
1793e12c5d1SDavid du Colombier 	Xreturn();
1803e12c5d1SDavid du Colombier }
1813e12c5d1SDavid du Colombier union code rdfns[4];
182dc5a79c1SDavid du Colombier 
183dc5a79c1SDavid du Colombier void
184dc5a79c1SDavid du Colombier execfinit(void)
185dc5a79c1SDavid du Colombier {
1863e12c5d1SDavid du Colombier 	static int first = 1;
1873e12c5d1SDavid du Colombier 	if(first){
1883e12c5d1SDavid du Colombier 		rdfns[0].i = 1;
1893e12c5d1SDavid du Colombier 		rdfns[1].f = Xrdfn;
1903e12c5d1SDavid du Colombier 		rdfns[2].f = Xjump;
1913e12c5d1SDavid du Colombier 		rdfns[3].i = 1;
1923e12c5d1SDavid du Colombier 		first = 0;
1933e12c5d1SDavid du Colombier 	}
1943e12c5d1SDavid du Colombier 	Xpopm();
1959a747e4fSDavid du Colombier 	envdir = open("/env", 0);
1963e12c5d1SDavid du Colombier 	if(envdir<0){
1979a747e4fSDavid du Colombier 		pfmt(err, "rc: can't open /env: %r\n");
1983e12c5d1SDavid du Colombier 		return;
1993e12c5d1SDavid du Colombier 	}
2003e12c5d1SDavid du Colombier 	start(rdfns, 1, runq->local);
2013e12c5d1SDavid du Colombier }
202dc5a79c1SDavid du Colombier 
203dc5a79c1SDavid du Colombier int
204dc5a79c1SDavid du Colombier Waitfor(int pid, int)
205dc5a79c1SDavid du Colombier {
2063e12c5d1SDavid du Colombier 	thread *p;
2079a747e4fSDavid du Colombier 	Waitmsg *w;
2089a747e4fSDavid du Colombier 	char errbuf[ERRMAX];
2099a747e4fSDavid du Colombier 
210*d3907fe5SDavid du Colombier 	if(pid >= 0 && !havewaitpid(pid))
211*d3907fe5SDavid du Colombier 		return 0;
212*d3907fe5SDavid du Colombier 
2139a747e4fSDavid du Colombier 	while((w = wait()) != nil){
214*d3907fe5SDavid du Colombier 		delwaitpid(w->pid);
2159a747e4fSDavid du Colombier 		if(w->pid==pid){
2169a747e4fSDavid du Colombier 			setstatus(w->msg);
2179a747e4fSDavid du Colombier 			free(w);
218219b2ee8SDavid du Colombier 			return 0;
2193e12c5d1SDavid du Colombier 		}
2203e12c5d1SDavid du Colombier 		for(p = runq->ret;p;p = p->ret)
2219a747e4fSDavid du Colombier 			if(p->pid==w->pid){
2223e12c5d1SDavid du Colombier 				p->pid=-1;
2239a747e4fSDavid du Colombier 				strcpy(p->status, w->msg);
2243e12c5d1SDavid du Colombier 			}
2259a747e4fSDavid du Colombier 		free(w);
2263e12c5d1SDavid du Colombier 	}
2279a747e4fSDavid du Colombier 
2289a747e4fSDavid du Colombier 	errstr(errbuf, sizeof errbuf);
229219b2ee8SDavid du Colombier 	if(strcmp(errbuf, "interrupted")==0) return -1;
2303e12c5d1SDavid du Colombier 	return 0;
2313e12c5d1SDavid du Colombier }
232dc5a79c1SDavid du Colombier 
233dc5a79c1SDavid du Colombier char*
234dc5a79c1SDavid du Colombier *mkargv(word *a)
2353e12c5d1SDavid du Colombier {
2363e12c5d1SDavid du Colombier 	char **argv = (char **)emalloc((count(a)+2)*sizeof(char *));
2373e12c5d1SDavid du Colombier 	char **argp = argv+1;	/* leave one at front for runcoms */
2383e12c5d1SDavid du Colombier 	for(;a;a = a->next) *argp++=a->word;
2393e12c5d1SDavid du Colombier 	*argp = 0;
2403e12c5d1SDavid du Colombier 	return argv;
2413e12c5d1SDavid du Colombier }
242dc5a79c1SDavid du Colombier 
243dc5a79c1SDavid du Colombier void
244dc5a79c1SDavid du Colombier addenv(var *v)
2453e12c5d1SDavid du Colombier {
2469a747e4fSDavid du Colombier 	char envname[256];
2473e12c5d1SDavid du Colombier 	word *w;
2483e12c5d1SDavid du Colombier 	int f;
2493e12c5d1SDavid du Colombier 	io *fd;
2503e12c5d1SDavid du Colombier 	if(v->changed){
2513e12c5d1SDavid du Colombier 		v->changed = 0;
2529a747e4fSDavid du Colombier 		snprint(envname, sizeof envname, "/env/%s", v->name);
2533e12c5d1SDavid du Colombier 		if((f = Creat(envname))<0)
2549a747e4fSDavid du Colombier 			pfmt(err, "rc: can't open %s: %r\n", envname);
2553e12c5d1SDavid du Colombier 		else{
2563e12c5d1SDavid du Colombier 			for(w = v->val;w;w = w->next)
2573e12c5d1SDavid du Colombier 				write(f, w->word, strlen(w->word)+1L);
2583e12c5d1SDavid du Colombier 			close(f);
2593e12c5d1SDavid du Colombier 		}
2603e12c5d1SDavid du Colombier 	}
2613e12c5d1SDavid du Colombier 	if(v->fnchanged){
2623e12c5d1SDavid du Colombier 		v->fnchanged = 0;
2639a747e4fSDavid du Colombier 		snprint(envname, sizeof envname, "/env/fn#%s", v->name);
2643e12c5d1SDavid du Colombier 		if((f = Creat(envname))<0)
2659a747e4fSDavid du Colombier 			pfmt(err, "rc: can't open %s: %r\n", envname);
2663e12c5d1SDavid du Colombier 		else{
2673e12c5d1SDavid du Colombier 			if(v->fn){
2683e12c5d1SDavid du Colombier 				fd = openfd(f);
2693e12c5d1SDavid du Colombier 				pfmt(fd, "fn %s %s\n", v->name, v->fn[v->pc-1].s);
2703e12c5d1SDavid du Colombier 				closeio(fd);
2713e12c5d1SDavid du Colombier 			}
2723e12c5d1SDavid du Colombier 			close(f);
2733e12c5d1SDavid du Colombier 		}
2743e12c5d1SDavid du Colombier 	}
2753e12c5d1SDavid du Colombier }
276dc5a79c1SDavid du Colombier 
277dc5a79c1SDavid du Colombier void
278dc5a79c1SDavid du Colombier updenvlocal(var *v)
2793e12c5d1SDavid du Colombier {
2803e12c5d1SDavid du Colombier 	if(v){
2813e12c5d1SDavid du Colombier 		updenvlocal(v->next);
2823e12c5d1SDavid du Colombier 		addenv(v);
2833e12c5d1SDavid du Colombier 	}
2843e12c5d1SDavid du Colombier }
285dc5a79c1SDavid du Colombier 
286dc5a79c1SDavid du Colombier void
287dc5a79c1SDavid du Colombier Updenv(void)
288dc5a79c1SDavid du Colombier {
2893e12c5d1SDavid du Colombier 	var *v, **h;
2903e12c5d1SDavid du Colombier 	for(h = gvar;h!=&gvar[NVAR];h++)
2913e12c5d1SDavid du Colombier 		for(v=*h;v;v = v->next)
2923e12c5d1SDavid du Colombier 			addenv(v);
293dc5a79c1SDavid du Colombier 	if(runq)
294dc5a79c1SDavid du Colombier 		updenvlocal(runq->local);
2953e12c5d1SDavid du Colombier }
296dc5a79c1SDavid du Colombier 
297dc5a79c1SDavid du Colombier int
298dc5a79c1SDavid du Colombier ForkExecute(char *file, char **argv, int sin, int sout, int serr)
299dc5a79c1SDavid du Colombier {
300dc5a79c1SDavid du Colombier 	int pid;
301dc5a79c1SDavid du Colombier 
302dc5a79c1SDavid du Colombier 	if(access(file, 1) != 0)
303dc5a79c1SDavid du Colombier 		return -1;
304dc5a79c1SDavid du Colombier 	switch(pid = fork()){
305dc5a79c1SDavid du Colombier 	case -1:
306dc5a79c1SDavid du Colombier 		return -1;
307dc5a79c1SDavid du Colombier 	case 0:
308dc5a79c1SDavid du Colombier 		if(sin >= 0)
309dc5a79c1SDavid du Colombier 			dup(sin, 0);
310dc5a79c1SDavid du Colombier 		else
311dc5a79c1SDavid du Colombier 			close(0);
312dc5a79c1SDavid du Colombier 		if(sout >= 0)
313dc5a79c1SDavid du Colombier 			dup(sout, 1);
314dc5a79c1SDavid du Colombier 		else
315dc5a79c1SDavid du Colombier 			close(1);
316dc5a79c1SDavid du Colombier 		if(serr >= 0)
317dc5a79c1SDavid du Colombier 			dup(serr, 2);
318dc5a79c1SDavid du Colombier 		else
319dc5a79c1SDavid du Colombier 			close(2);
320dc5a79c1SDavid du Colombier 		exec(file, argv);
321dc5a79c1SDavid du Colombier 		exits(file);
322dc5a79c1SDavid du Colombier 	}
323dc5a79c1SDavid du Colombier 	return pid;
324dc5a79c1SDavid du Colombier }
325dc5a79c1SDavid du Colombier 
326dc5a79c1SDavid du Colombier void
327dc5a79c1SDavid du Colombier Execute(word *args, word *path)
3283e12c5d1SDavid du Colombier {
3293e12c5d1SDavid du Colombier 	char **argv = mkargv(args);
330219b2ee8SDavid du Colombier 	char file[1024];
331219b2ee8SDavid du Colombier 	int nc;
3323e12c5d1SDavid du Colombier 	Updenv();
3333e12c5d1SDavid du Colombier 	for(;path;path = path->next){
334219b2ee8SDavid du Colombier 		nc = strlen(path->word);
335219b2ee8SDavid du Colombier 		if(nc<1024){
3363e12c5d1SDavid du Colombier 			strcpy(file, path->word);
337219b2ee8SDavid du Colombier 			if(file[0]){
338219b2ee8SDavid du Colombier 				strcat(file, "/");
339219b2ee8SDavid du Colombier 				nc++;
340219b2ee8SDavid du Colombier 			}
341219b2ee8SDavid du Colombier 			if(nc+strlen(argv[1])<1024){
3423e12c5d1SDavid du Colombier 				strcat(file, argv[1]);
3433e12c5d1SDavid du Colombier 				exec(file, argv+1);
3443e12c5d1SDavid du Colombier 			}
345219b2ee8SDavid du Colombier 			else werrstr("command name too long");
346219b2ee8SDavid du Colombier 		}
347219b2ee8SDavid du Colombier 	}
3489a747e4fSDavid du Colombier 	rerrstr(file, sizeof file);
3493e12c5d1SDavid du Colombier 	pfmt(err, "%s: %s\n", argv[1], file);
3503e12c5d1SDavid du Colombier 	efree((char *)argv);
3513e12c5d1SDavid du Colombier }
3529a747e4fSDavid du Colombier #define	NDIR	256		/* shoud be a better way */
353dc5a79c1SDavid du Colombier 
354dc5a79c1SDavid du Colombier int
355dc5a79c1SDavid du Colombier Globsize(char *p)
3563e12c5d1SDavid du Colombier {
35773e742d7SDavid du Colombier 	int isglob = 0, globlen = NDIR+1;
3583e12c5d1SDavid du Colombier 	for(;*p;p++){
3593e12c5d1SDavid du Colombier 		if(*p==GLOB){
3603e12c5d1SDavid du Colombier 			p++;
361dc5a79c1SDavid du Colombier 			if(*p!=GLOB)
362dc5a79c1SDavid du Colombier 				isglob++;
3639a747e4fSDavid du Colombier 			globlen+=*p=='*'?NDIR:1;
3643e12c5d1SDavid du Colombier 		}
3653e12c5d1SDavid du Colombier 		else
3663e12c5d1SDavid du Colombier 			globlen++;
3673e12c5d1SDavid du Colombier 	}
3683e12c5d1SDavid du Colombier 	return isglob?globlen:0;
3693e12c5d1SDavid du Colombier }
3703e12c5d1SDavid du Colombier #define	NFD	50
3713e12c5d1SDavid du Colombier #define	NDBUF	32
3723e12c5d1SDavid du Colombier struct{
3739a747e4fSDavid du Colombier 	Dir	*dbuf;
3749a747e4fSDavid du Colombier 	int	i;
3753e12c5d1SDavid du Colombier 	int	n;
3763e12c5d1SDavid du Colombier }dir[NFD];
377dc5a79c1SDavid du Colombier 
378dc5a79c1SDavid du Colombier int
379dc5a79c1SDavid du Colombier Opendir(char *name)
3803e12c5d1SDavid du Colombier {
3819a747e4fSDavid du Colombier 	Dir *db;
3823e12c5d1SDavid du Colombier 	int f;
3833e12c5d1SDavid du Colombier 	f = open(name, 0);
3843e12c5d1SDavid du Colombier 	if(f==-1)
3853e12c5d1SDavid du Colombier 		return f;
3869a747e4fSDavid du Colombier 	db = dirfstat(f);
3879a747e4fSDavid du Colombier 	if(db!=nil && (db->mode&DMDIR)){
3889a747e4fSDavid du Colombier 		if(f<NFD){
3899a747e4fSDavid du Colombier 			dir[f].i = 0;
3909a747e4fSDavid du Colombier 			dir[f].n = 0;
3913e12c5d1SDavid du Colombier 		}
3929a747e4fSDavid du Colombier 		free(db);
3933e12c5d1SDavid du Colombier 		return f;
3943e12c5d1SDavid du Colombier 	}
3959a747e4fSDavid du Colombier 	free(db);
3963e12c5d1SDavid du Colombier 	close(f);
3973e12c5d1SDavid du Colombier 	return -1;
3983e12c5d1SDavid du Colombier }
3996b6b9ac8SDavid du Colombier 
4006b6b9ac8SDavid du Colombier static int
4016b6b9ac8SDavid du Colombier trimdirs(Dir *d, int nd)
4026b6b9ac8SDavid du Colombier {
4036b6b9ac8SDavid du Colombier 	int r, w;
4046b6b9ac8SDavid du Colombier 
4056b6b9ac8SDavid du Colombier 	for(r=w=0; r<nd; r++)
4066b6b9ac8SDavid du Colombier 		if(d[r].mode&DMDIR)
4076b6b9ac8SDavid du Colombier 			d[w++] = d[r];
4086b6b9ac8SDavid du Colombier 	return w;
4096b6b9ac8SDavid du Colombier }
4106b6b9ac8SDavid du Colombier 
4116b6b9ac8SDavid du Colombier /*
4126b6b9ac8SDavid du Colombier  * onlydirs is advisory -- it means you only
4136b6b9ac8SDavid du Colombier  * need to return the directories.  it's okay to
4146b6b9ac8SDavid du Colombier  * return files too (e.g., on unix where you can't
4156b6b9ac8SDavid du Colombier  * tell during the readdir), but that just makes
4166b6b9ac8SDavid du Colombier  * the globber work harder.
4176b6b9ac8SDavid du Colombier  */
418dc5a79c1SDavid du Colombier int
419dc5a79c1SDavid du Colombier Readdir(int f, char *p, int onlydirs)
4203e12c5d1SDavid du Colombier {
4213e12c5d1SDavid du Colombier 	int n;
422dc5a79c1SDavid du Colombier 
4239a747e4fSDavid du Colombier 	if(f<0 || f>=NFD)
4243e12c5d1SDavid du Colombier 		return 0;
4256b6b9ac8SDavid du Colombier Again:
4269a747e4fSDavid du Colombier 	if(dir[f].i==dir[f].n){	/* read */
4279a747e4fSDavid du Colombier 		free(dir[f].dbuf);
4289a747e4fSDavid du Colombier 		dir[f].dbuf = 0;
4299a747e4fSDavid du Colombier 		n = dirread(f, &dir[f].dbuf);
4306b6b9ac8SDavid du Colombier 		if(n>0){
4316b6b9ac8SDavid du Colombier 			if(onlydirs){
4326b6b9ac8SDavid du Colombier 				n = trimdirs(dir[f].dbuf, n);
4336b6b9ac8SDavid du Colombier 				if(n == 0)
4346b6b9ac8SDavid du Colombier 					goto Again;
4356b6b9ac8SDavid du Colombier 			}
4369a747e4fSDavid du Colombier 			dir[f].n = n;
4376b6b9ac8SDavid du Colombier 		}else
4383e12c5d1SDavid du Colombier 			dir[f].n = 0;
4399a747e4fSDavid du Colombier 		dir[f].i = 0;
4403e12c5d1SDavid du Colombier 	}
4419a747e4fSDavid du Colombier 	if(dir[f].i == dir[f].n)
4423e12c5d1SDavid du Colombier 		return 0;
4439a747e4fSDavid du Colombier 	strcpy(p, dir[f].dbuf[dir[f].i].name);
4449a747e4fSDavid du Colombier 	dir[f].i++;
4453e12c5d1SDavid du Colombier 	return 1;
4463e12c5d1SDavid du Colombier }
447dc5a79c1SDavid du Colombier 
448dc5a79c1SDavid du Colombier void
449dc5a79c1SDavid du Colombier Closedir(int f)
450dc5a79c1SDavid du Colombier {
4519a747e4fSDavid du Colombier 	if(f>=0 && f<NFD){
4529a747e4fSDavid du Colombier 		free(dir[f].dbuf);
4539a747e4fSDavid du Colombier 		dir[f].i = 0;
4549a747e4fSDavid du Colombier 		dir[f].n = 0;
4559a747e4fSDavid du Colombier 		dir[f].dbuf = 0;
4563e12c5d1SDavid du Colombier 	}
4573e12c5d1SDavid du Colombier 	close(f);
4583e12c5d1SDavid du Colombier }
4593e12c5d1SDavid du Colombier int interrupted = 0;
4603e12c5d1SDavid du Colombier void
4617dd7cddfSDavid du Colombier notifyf(void*, char *s)
4623e12c5d1SDavid du Colombier {
4633e12c5d1SDavid du Colombier 	int i;
4643e12c5d1SDavid du Colombier 	for(i = 0;syssigname[i];i++) if(strncmp(s, syssigname[i], strlen(syssigname[i]))==0){
4653e12c5d1SDavid du Colombier 		if(strncmp(s, "sys: ", 5)!=0) interrupted = 1;
4663e12c5d1SDavid du Colombier 		goto Out;
4673e12c5d1SDavid du Colombier 	}
4683e12c5d1SDavid du Colombier 	pfmt(err, "rc: note: %s\n", s);
4693e12c5d1SDavid du Colombier 	noted(NDFLT);
4703e12c5d1SDavid du Colombier 	return;
4713e12c5d1SDavid du Colombier Out:
472219b2ee8SDavid du Colombier 	if(strcmp(s, "interrupt")!=0 || trap[i]==0){
4733e12c5d1SDavid du Colombier 		trap[i]++;
4743e12c5d1SDavid du Colombier 		ntrap++;
475219b2ee8SDavid du Colombier 	}
4763e12c5d1SDavid du Colombier 	if(ntrap>=32){	/* rc is probably in a trap loop */
4773e12c5d1SDavid du Colombier 		pfmt(err, "rc: Too many traps (trap %s), aborting\n", s);
4783e12c5d1SDavid du Colombier 		abort();
4793e12c5d1SDavid du Colombier 	}
4803e12c5d1SDavid du Colombier 	noted(NCONT);
4813e12c5d1SDavid du Colombier }
482dc5a79c1SDavid du Colombier 
483dc5a79c1SDavid du Colombier void
484dc5a79c1SDavid du Colombier Trapinit(void)
485dc5a79c1SDavid du Colombier {
4863e12c5d1SDavid du Colombier 	notify(notifyf);
4873e12c5d1SDavid du Colombier }
488dc5a79c1SDavid du Colombier 
489dc5a79c1SDavid du Colombier void
490dc5a79c1SDavid du Colombier Unlink(char *name)
4913e12c5d1SDavid du Colombier {
4923e12c5d1SDavid du Colombier 	remove(name);
4933e12c5d1SDavid du Colombier }
494dc5a79c1SDavid du Colombier 
495dc5a79c1SDavid du Colombier long
496dc5a79c1SDavid du Colombier Write(int fd, char *buf, long cnt)
4973e12c5d1SDavid du Colombier {
4983e12c5d1SDavid du Colombier 	return write(fd, buf, (long)cnt);
4993e12c5d1SDavid du Colombier }
500dc5a79c1SDavid du Colombier 
501dc5a79c1SDavid du Colombier long
502dc5a79c1SDavid du Colombier Read(int fd, char *buf, long cnt)
5033e12c5d1SDavid du Colombier {
5043e12c5d1SDavid du Colombier 	return read(fd, buf, cnt);
5053e12c5d1SDavid du Colombier }
506dc5a79c1SDavid du Colombier 
507dc5a79c1SDavid du Colombier long
508dc5a79c1SDavid du Colombier Seek(int fd, long cnt, long whence)
5093e12c5d1SDavid du Colombier {
5103e12c5d1SDavid du Colombier 	return seek(fd, cnt, whence);
5113e12c5d1SDavid du Colombier }
512dc5a79c1SDavid du Colombier 
513dc5a79c1SDavid du Colombier int
514dc5a79c1SDavid du Colombier Executable(char *file)
5153e12c5d1SDavid du Colombier {
5169a747e4fSDavid du Colombier 	Dir *statbuf;
5179a747e4fSDavid du Colombier 	int ret;
5183e12c5d1SDavid du Colombier 
5199a747e4fSDavid du Colombier 	statbuf = dirstat(file);
520dc5a79c1SDavid du Colombier 	if(statbuf == nil)
521dc5a79c1SDavid du Colombier 		return 0;
5229a747e4fSDavid du Colombier 	ret = ((statbuf->mode&0111)!=0 && (statbuf->mode&DMDIR)==0);
5239a747e4fSDavid du Colombier 	free(statbuf);
5249a747e4fSDavid du Colombier 	return ret;
5253e12c5d1SDavid du Colombier }
526dc5a79c1SDavid du Colombier 
527dc5a79c1SDavid du Colombier int
528dc5a79c1SDavid du Colombier Creat(char *file)
5293e12c5d1SDavid du Colombier {
5303e12c5d1SDavid du Colombier 	return create(file, 1, 0666L);
5313e12c5d1SDavid du Colombier }
532dc5a79c1SDavid du Colombier 
533dc5a79c1SDavid du Colombier int
534dc5a79c1SDavid du Colombier Dup(int a, int b)
535dc5a79c1SDavid du Colombier {
5363e12c5d1SDavid du Colombier 	return dup(a, b);
5373e12c5d1SDavid du Colombier }
538dc5a79c1SDavid du Colombier 
539dc5a79c1SDavid du Colombier int
540dc5a79c1SDavid du Colombier Dup1(int)
541dc5a79c1SDavid du Colombier {
5423e12c5d1SDavid du Colombier 	return -1;
5433e12c5d1SDavid du Colombier }
544dc5a79c1SDavid du Colombier 
545dc5a79c1SDavid du Colombier void
546dc5a79c1SDavid du Colombier Exit(char *stat)
5473e12c5d1SDavid du Colombier {
5483e12c5d1SDavid du Colombier 	Updenv();
5493e12c5d1SDavid du Colombier 	setstatus(stat);
5503e12c5d1SDavid du Colombier 	exits(truestatus()?"":getstatus());
5513e12c5d1SDavid du Colombier }
552dc5a79c1SDavid du Colombier 
553dc5a79c1SDavid du Colombier int
554dc5a79c1SDavid du Colombier Eintr(void)
555dc5a79c1SDavid du Colombier {
5563e12c5d1SDavid du Colombier 	return interrupted;
5573e12c5d1SDavid du Colombier }
558dc5a79c1SDavid du Colombier 
559dc5a79c1SDavid du Colombier void
560dc5a79c1SDavid du Colombier Noerror(void)
561dc5a79c1SDavid du Colombier {
5623e12c5d1SDavid du Colombier 	interrupted = 0;
5633e12c5d1SDavid du Colombier }
564dc5a79c1SDavid du Colombier 
565dc5a79c1SDavid du Colombier int
566dc5a79c1SDavid du Colombier Isatty(int fd)
567dc5a79c1SDavid du Colombier {
5684f281771SDavid du Colombier 	char buf[64];
5693e12c5d1SDavid du Colombier 
5704f281771SDavid du Colombier 	if(fd2path(fd, buf, sizeof buf) != 0)
571dc5a79c1SDavid du Colombier 		return 0;
5724f281771SDavid du Colombier 
5733806af99SDavid du Colombier 	/* might be #c/cons during boot - fixed 22 april 2005, remove this later */
5743806af99SDavid du Colombier 	if(strcmp(buf, "#c/cons") == 0)
5753806af99SDavid du Colombier 		return 1;
5763806af99SDavid du Colombier 
5774f281771SDavid du Colombier 	/* might be /mnt/term/dev/cons */
5784f281771SDavid du Colombier 	return strlen(buf) >= 9 && strcmp(buf+strlen(buf)-9, "/dev/cons") == 0;
5793e12c5d1SDavid du Colombier }
580dc5a79c1SDavid du Colombier 
581dc5a79c1SDavid du Colombier void
582dc5a79c1SDavid du Colombier Abort(void)
583dc5a79c1SDavid du Colombier {
5843e12c5d1SDavid du Colombier 	pfmt(err, "aborting\n");
5853e12c5d1SDavid du Colombier 	flush(err);
5863e12c5d1SDavid du Colombier 	Exit("aborting");
5873e12c5d1SDavid du Colombier }
588dc5a79c1SDavid du Colombier 
589dc5a79c1SDavid du Colombier void
590dc5a79c1SDavid du Colombier Memcpy(char *a, char *b, long n)
5913e12c5d1SDavid du Colombier {
5923e12c5d1SDavid du Colombier 	memmove(a, b, (long)n);
5933e12c5d1SDavid du Colombier }
594dc5a79c1SDavid du Colombier 
595dc5a79c1SDavid du Colombier void*
596dc5a79c1SDavid du Colombier Malloc(ulong n)
597dc5a79c1SDavid du Colombier {
5983e12c5d1SDavid du Colombier 	return malloc(n);
5993e12c5d1SDavid du Colombier }
600*d3907fe5SDavid du Colombier 
601*d3907fe5SDavid du Colombier int *waitpids;
602*d3907fe5SDavid du Colombier int nwaitpids;
603*d3907fe5SDavid du Colombier 
604*d3907fe5SDavid du Colombier void
605*d3907fe5SDavid du Colombier addwaitpid(int pid)
606*d3907fe5SDavid du Colombier {
607*d3907fe5SDavid du Colombier 	waitpids = realloc(waitpids, (nwaitpids+1)*sizeof waitpids[0]);
608*d3907fe5SDavid du Colombier 	if(waitpids == 0)
609*d3907fe5SDavid du Colombier 		panic("Can't realloc %d waitpids", nwaitpids+1);
610*d3907fe5SDavid du Colombier 	waitpids[nwaitpids++] = pid;
611*d3907fe5SDavid du Colombier }
612*d3907fe5SDavid du Colombier 
613*d3907fe5SDavid du Colombier void
614*d3907fe5SDavid du Colombier delwaitpid(int pid)
615*d3907fe5SDavid du Colombier {
616*d3907fe5SDavid du Colombier 	int r, w;
617*d3907fe5SDavid du Colombier 
618*d3907fe5SDavid du Colombier 	for(r=w=0; r<nwaitpids; r++)
619*d3907fe5SDavid du Colombier 		if(waitpids[r] != pid)
620*d3907fe5SDavid du Colombier 			waitpids[w++] = waitpids[r];
621*d3907fe5SDavid du Colombier 	nwaitpids = w;
622*d3907fe5SDavid du Colombier }
623*d3907fe5SDavid du Colombier 
624*d3907fe5SDavid du Colombier void
625*d3907fe5SDavid du Colombier clearwaitpids(void)
626*d3907fe5SDavid du Colombier {
627*d3907fe5SDavid du Colombier 	nwaitpids = 0;
628*d3907fe5SDavid du Colombier }
629*d3907fe5SDavid du Colombier 
630*d3907fe5SDavid du Colombier int
631*d3907fe5SDavid du Colombier havewaitpid(int pid)
632*d3907fe5SDavid du Colombier {
633*d3907fe5SDavid du Colombier 	int i;
634*d3907fe5SDavid du Colombier 
635*d3907fe5SDavid du Colombier 	for(i=0; i<nwaitpids; i++)
636*d3907fe5SDavid du Colombier 		if(waitpids[i] == pid)
637*d3907fe5SDavid du Colombier 			return 1;
638*d3907fe5SDavid du Colombier 	return 0;
639*d3907fe5SDavid du Colombier }
640