xref: /plan9/sys/src/cmd/rc/plan9.c (revision 73e742d79f6b0cfc24f3b01d7ade790955db63c2)
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 
2109a747e4fSDavid du Colombier 	while((w = wait()) != nil){
2119a747e4fSDavid du Colombier 		if(w->pid==pid){
2129a747e4fSDavid du Colombier 			setstatus(w->msg);
2139a747e4fSDavid du Colombier 			free(w);
214219b2ee8SDavid du Colombier 			return 0;
2153e12c5d1SDavid du Colombier 		}
2163e12c5d1SDavid du Colombier 		for(p = runq->ret;p;p = p->ret)
2179a747e4fSDavid du Colombier 			if(p->pid==w->pid){
2183e12c5d1SDavid du Colombier 				p->pid=-1;
2199a747e4fSDavid du Colombier 				strcpy(p->status, w->msg);
2203e12c5d1SDavid du Colombier 			}
2219a747e4fSDavid du Colombier 		free(w);
2223e12c5d1SDavid du Colombier 	}
2239a747e4fSDavid du Colombier 
2249a747e4fSDavid du Colombier 	errstr(errbuf, sizeof errbuf);
225219b2ee8SDavid du Colombier 	if(strcmp(errbuf, "interrupted")==0) return -1;
2263e12c5d1SDavid du Colombier 	return 0;
2273e12c5d1SDavid du Colombier }
228dc5a79c1SDavid du Colombier 
229dc5a79c1SDavid du Colombier char*
230dc5a79c1SDavid du Colombier *mkargv(word *a)
2313e12c5d1SDavid du Colombier {
2323e12c5d1SDavid du Colombier 	char **argv = (char **)emalloc((count(a)+2)*sizeof(char *));
2333e12c5d1SDavid du Colombier 	char **argp = argv+1;	/* leave one at front for runcoms */
2343e12c5d1SDavid du Colombier 	for(;a;a = a->next) *argp++=a->word;
2353e12c5d1SDavid du Colombier 	*argp = 0;
2363e12c5d1SDavid du Colombier 	return argv;
2373e12c5d1SDavid du Colombier }
238dc5a79c1SDavid du Colombier 
239dc5a79c1SDavid du Colombier void
240dc5a79c1SDavid du Colombier addenv(var *v)
2413e12c5d1SDavid du Colombier {
2429a747e4fSDavid du Colombier 	char envname[256];
2433e12c5d1SDavid du Colombier 	word *w;
2443e12c5d1SDavid du Colombier 	int f;
2453e12c5d1SDavid du Colombier 	io *fd;
2463e12c5d1SDavid du Colombier 	if(v->changed){
2473e12c5d1SDavid du Colombier 		v->changed = 0;
2489a747e4fSDavid du Colombier 		snprint(envname, sizeof envname, "/env/%s", v->name);
2493e12c5d1SDavid du Colombier 		if((f = Creat(envname))<0)
2509a747e4fSDavid du Colombier 			pfmt(err, "rc: can't open %s: %r\n", envname);
2513e12c5d1SDavid du Colombier 		else{
2523e12c5d1SDavid du Colombier 			for(w = v->val;w;w = w->next)
2533e12c5d1SDavid du Colombier 				write(f, w->word, strlen(w->word)+1L);
2543e12c5d1SDavid du Colombier 			close(f);
2553e12c5d1SDavid du Colombier 		}
2563e12c5d1SDavid du Colombier 	}
2573e12c5d1SDavid du Colombier 	if(v->fnchanged){
2583e12c5d1SDavid du Colombier 		v->fnchanged = 0;
2599a747e4fSDavid du Colombier 		snprint(envname, sizeof envname, "/env/fn#%s", v->name);
2603e12c5d1SDavid du Colombier 		if((f = Creat(envname))<0)
2619a747e4fSDavid du Colombier 			pfmt(err, "rc: can't open %s: %r\n", envname);
2623e12c5d1SDavid du Colombier 		else{
2633e12c5d1SDavid du Colombier 			if(v->fn){
2643e12c5d1SDavid du Colombier 				fd = openfd(f);
2653e12c5d1SDavid du Colombier 				pfmt(fd, "fn %s %s\n", v->name, v->fn[v->pc-1].s);
2663e12c5d1SDavid du Colombier 				closeio(fd);
2673e12c5d1SDavid du Colombier 			}
2683e12c5d1SDavid du Colombier 			close(f);
2693e12c5d1SDavid du Colombier 		}
2703e12c5d1SDavid du Colombier 	}
2713e12c5d1SDavid du Colombier }
272dc5a79c1SDavid du Colombier 
273dc5a79c1SDavid du Colombier void
274dc5a79c1SDavid du Colombier updenvlocal(var *v)
2753e12c5d1SDavid du Colombier {
2763e12c5d1SDavid du Colombier 	if(v){
2773e12c5d1SDavid du Colombier 		updenvlocal(v->next);
2783e12c5d1SDavid du Colombier 		addenv(v);
2793e12c5d1SDavid du Colombier 	}
2803e12c5d1SDavid du Colombier }
281dc5a79c1SDavid du Colombier 
282dc5a79c1SDavid du Colombier void
283dc5a79c1SDavid du Colombier Updenv(void)
284dc5a79c1SDavid du Colombier {
2853e12c5d1SDavid du Colombier 	var *v, **h;
2863e12c5d1SDavid du Colombier 	for(h = gvar;h!=&gvar[NVAR];h++)
2873e12c5d1SDavid du Colombier 		for(v=*h;v;v = v->next)
2883e12c5d1SDavid du Colombier 			addenv(v);
289dc5a79c1SDavid du Colombier 	if(runq)
290dc5a79c1SDavid du Colombier 		updenvlocal(runq->local);
2913e12c5d1SDavid du Colombier }
292dc5a79c1SDavid du Colombier 
293dc5a79c1SDavid du Colombier int
294dc5a79c1SDavid du Colombier ForkExecute(char *file, char **argv, int sin, int sout, int serr)
295dc5a79c1SDavid du Colombier {
296dc5a79c1SDavid du Colombier 	int pid;
297dc5a79c1SDavid du Colombier 
298dc5a79c1SDavid du Colombier 	if(access(file, 1) != 0)
299dc5a79c1SDavid du Colombier 		return -1;
300dc5a79c1SDavid du Colombier 	switch(pid = fork()){
301dc5a79c1SDavid du Colombier 	case -1:
302dc5a79c1SDavid du Colombier 		return -1;
303dc5a79c1SDavid du Colombier 	case 0:
304dc5a79c1SDavid du Colombier 		if(sin >= 0)
305dc5a79c1SDavid du Colombier 			dup(sin, 0);
306dc5a79c1SDavid du Colombier 		else
307dc5a79c1SDavid du Colombier 			close(0);
308dc5a79c1SDavid du Colombier 		if(sout >= 0)
309dc5a79c1SDavid du Colombier 			dup(sout, 1);
310dc5a79c1SDavid du Colombier 		else
311dc5a79c1SDavid du Colombier 			close(1);
312dc5a79c1SDavid du Colombier 		if(serr >= 0)
313dc5a79c1SDavid du Colombier 			dup(serr, 2);
314dc5a79c1SDavid du Colombier 		else
315dc5a79c1SDavid du Colombier 			close(2);
316dc5a79c1SDavid du Colombier 		exec(file, argv);
317dc5a79c1SDavid du Colombier 		exits(file);
318dc5a79c1SDavid du Colombier 	}
319dc5a79c1SDavid du Colombier 	return pid;
320dc5a79c1SDavid du Colombier }
321dc5a79c1SDavid du Colombier 
322dc5a79c1SDavid du Colombier void
323dc5a79c1SDavid du Colombier Execute(word *args, word *path)
3243e12c5d1SDavid du Colombier {
3253e12c5d1SDavid du Colombier 	char **argv = mkargv(args);
326219b2ee8SDavid du Colombier 	char file[1024];
327219b2ee8SDavid du Colombier 	int nc;
3283e12c5d1SDavid du Colombier 	Updenv();
3293e12c5d1SDavid du Colombier 	for(;path;path = path->next){
330219b2ee8SDavid du Colombier 		nc = strlen(path->word);
331219b2ee8SDavid du Colombier 		if(nc<1024){
3323e12c5d1SDavid du Colombier 			strcpy(file, path->word);
333219b2ee8SDavid du Colombier 			if(file[0]){
334219b2ee8SDavid du Colombier 				strcat(file, "/");
335219b2ee8SDavid du Colombier 				nc++;
336219b2ee8SDavid du Colombier 			}
337219b2ee8SDavid du Colombier 			if(nc+strlen(argv[1])<1024){
3383e12c5d1SDavid du Colombier 				strcat(file, argv[1]);
3393e12c5d1SDavid du Colombier 				exec(file, argv+1);
3403e12c5d1SDavid du Colombier 			}
341219b2ee8SDavid du Colombier 			else werrstr("command name too long");
342219b2ee8SDavid du Colombier 		}
343219b2ee8SDavid du Colombier 	}
3449a747e4fSDavid du Colombier 	rerrstr(file, sizeof file);
3453e12c5d1SDavid du Colombier 	pfmt(err, "%s: %s\n", argv[1], file);
3463e12c5d1SDavid du Colombier 	efree((char *)argv);
3473e12c5d1SDavid du Colombier }
3489a747e4fSDavid du Colombier #define	NDIR	256		/* shoud be a better way */
349dc5a79c1SDavid du Colombier 
350dc5a79c1SDavid du Colombier int
351dc5a79c1SDavid du Colombier Globsize(char *p)
3523e12c5d1SDavid du Colombier {
353*73e742d7SDavid du Colombier 	int isglob = 0, globlen = NDIR+1;
3543e12c5d1SDavid du Colombier 	for(;*p;p++){
3553e12c5d1SDavid du Colombier 		if(*p==GLOB){
3563e12c5d1SDavid du Colombier 			p++;
357dc5a79c1SDavid du Colombier 			if(*p!=GLOB)
358dc5a79c1SDavid du Colombier 				isglob++;
3599a747e4fSDavid du Colombier 			globlen+=*p=='*'?NDIR:1;
3603e12c5d1SDavid du Colombier 		}
3613e12c5d1SDavid du Colombier 		else
3623e12c5d1SDavid du Colombier 			globlen++;
3633e12c5d1SDavid du Colombier 	}
3643e12c5d1SDavid du Colombier 	return isglob?globlen:0;
3653e12c5d1SDavid du Colombier }
3663e12c5d1SDavid du Colombier #define	NFD	50
3673e12c5d1SDavid du Colombier #define	NDBUF	32
3683e12c5d1SDavid du Colombier struct{
3699a747e4fSDavid du Colombier 	Dir	*dbuf;
3709a747e4fSDavid du Colombier 	int	i;
3713e12c5d1SDavid du Colombier 	int	n;
3723e12c5d1SDavid du Colombier }dir[NFD];
373dc5a79c1SDavid du Colombier 
374dc5a79c1SDavid du Colombier int
375dc5a79c1SDavid du Colombier Opendir(char *name)
3763e12c5d1SDavid du Colombier {
3779a747e4fSDavid du Colombier 	Dir *db;
3783e12c5d1SDavid du Colombier 	int f;
3793e12c5d1SDavid du Colombier 	f = open(name, 0);
3803e12c5d1SDavid du Colombier 	if(f==-1)
3813e12c5d1SDavid du Colombier 		return f;
3829a747e4fSDavid du Colombier 	db = dirfstat(f);
3839a747e4fSDavid du Colombier 	if(db!=nil && (db->mode&DMDIR)){
3849a747e4fSDavid du Colombier 		if(f<NFD){
3859a747e4fSDavid du Colombier 			dir[f].i = 0;
3869a747e4fSDavid du Colombier 			dir[f].n = 0;
3873e12c5d1SDavid du Colombier 		}
3889a747e4fSDavid du Colombier 		free(db);
3893e12c5d1SDavid du Colombier 		return f;
3903e12c5d1SDavid du Colombier 	}
3919a747e4fSDavid du Colombier 	free(db);
3923e12c5d1SDavid du Colombier 	close(f);
3933e12c5d1SDavid du Colombier 	return -1;
3943e12c5d1SDavid du Colombier }
3956b6b9ac8SDavid du Colombier 
3966b6b9ac8SDavid du Colombier static int
3976b6b9ac8SDavid du Colombier trimdirs(Dir *d, int nd)
3986b6b9ac8SDavid du Colombier {
3996b6b9ac8SDavid du Colombier 	int r, w;
4006b6b9ac8SDavid du Colombier 
4016b6b9ac8SDavid du Colombier 	for(r=w=0; r<nd; r++)
4026b6b9ac8SDavid du Colombier 		if(d[r].mode&DMDIR)
4036b6b9ac8SDavid du Colombier 			d[w++] = d[r];
4046b6b9ac8SDavid du Colombier 	return w;
4056b6b9ac8SDavid du Colombier }
4066b6b9ac8SDavid du Colombier 
4076b6b9ac8SDavid du Colombier /*
4086b6b9ac8SDavid du Colombier  * onlydirs is advisory -- it means you only
4096b6b9ac8SDavid du Colombier  * need to return the directories.  it's okay to
4106b6b9ac8SDavid du Colombier  * return files too (e.g., on unix where you can't
4116b6b9ac8SDavid du Colombier  * tell during the readdir), but that just makes
4126b6b9ac8SDavid du Colombier  * the globber work harder.
4136b6b9ac8SDavid du Colombier  */
414dc5a79c1SDavid du Colombier int
415dc5a79c1SDavid du Colombier Readdir(int f, char *p, int onlydirs)
4163e12c5d1SDavid du Colombier {
4173e12c5d1SDavid du Colombier 	int n;
418dc5a79c1SDavid du Colombier 
4199a747e4fSDavid du Colombier 	if(f<0 || f>=NFD)
4203e12c5d1SDavid du Colombier 		return 0;
4216b6b9ac8SDavid du Colombier Again:
4229a747e4fSDavid du Colombier 	if(dir[f].i==dir[f].n){	/* read */
4239a747e4fSDavid du Colombier 		free(dir[f].dbuf);
4249a747e4fSDavid du Colombier 		dir[f].dbuf = 0;
4259a747e4fSDavid du Colombier 		n = dirread(f, &dir[f].dbuf);
4266b6b9ac8SDavid du Colombier 		if(n>0){
4276b6b9ac8SDavid du Colombier 			if(onlydirs){
4286b6b9ac8SDavid du Colombier 				n = trimdirs(dir[f].dbuf, n);
4296b6b9ac8SDavid du Colombier 				if(n == 0)
4306b6b9ac8SDavid du Colombier 					goto Again;
4316b6b9ac8SDavid du Colombier 			}
4329a747e4fSDavid du Colombier 			dir[f].n = n;
4336b6b9ac8SDavid du Colombier 		}else
4343e12c5d1SDavid du Colombier 			dir[f].n = 0;
4359a747e4fSDavid du Colombier 		dir[f].i = 0;
4363e12c5d1SDavid du Colombier 	}
4379a747e4fSDavid du Colombier 	if(dir[f].i == dir[f].n)
4383e12c5d1SDavid du Colombier 		return 0;
4399a747e4fSDavid du Colombier 	strcpy(p, dir[f].dbuf[dir[f].i].name);
4409a747e4fSDavid du Colombier 	dir[f].i++;
4413e12c5d1SDavid du Colombier 	return 1;
4423e12c5d1SDavid du Colombier }
443dc5a79c1SDavid du Colombier 
444dc5a79c1SDavid du Colombier void
445dc5a79c1SDavid du Colombier Closedir(int f)
446dc5a79c1SDavid du Colombier {
4479a747e4fSDavid du Colombier 	if(f>=0 && f<NFD){
4489a747e4fSDavid du Colombier 		free(dir[f].dbuf);
4499a747e4fSDavid du Colombier 		dir[f].i = 0;
4509a747e4fSDavid du Colombier 		dir[f].n = 0;
4519a747e4fSDavid du Colombier 		dir[f].dbuf = 0;
4523e12c5d1SDavid du Colombier 	}
4533e12c5d1SDavid du Colombier 	close(f);
4543e12c5d1SDavid du Colombier }
4553e12c5d1SDavid du Colombier int interrupted = 0;
4563e12c5d1SDavid du Colombier void
4577dd7cddfSDavid du Colombier notifyf(void*, char *s)
4583e12c5d1SDavid du Colombier {
4593e12c5d1SDavid du Colombier 	int i;
4603e12c5d1SDavid du Colombier 	for(i = 0;syssigname[i];i++) if(strncmp(s, syssigname[i], strlen(syssigname[i]))==0){
4613e12c5d1SDavid du Colombier 		if(strncmp(s, "sys: ", 5)!=0) interrupted = 1;
4623e12c5d1SDavid du Colombier 		goto Out;
4633e12c5d1SDavid du Colombier 	}
4643e12c5d1SDavid du Colombier 	pfmt(err, "rc: note: %s\n", s);
4653e12c5d1SDavid du Colombier 	noted(NDFLT);
4663e12c5d1SDavid du Colombier 	return;
4673e12c5d1SDavid du Colombier Out:
468219b2ee8SDavid du Colombier 	if(strcmp(s, "interrupt")!=0 || trap[i]==0){
4693e12c5d1SDavid du Colombier 		trap[i]++;
4703e12c5d1SDavid du Colombier 		ntrap++;
471219b2ee8SDavid du Colombier 	}
4723e12c5d1SDavid du Colombier 	if(ntrap>=32){	/* rc is probably in a trap loop */
4733e12c5d1SDavid du Colombier 		pfmt(err, "rc: Too many traps (trap %s), aborting\n", s);
4743e12c5d1SDavid du Colombier 		abort();
4753e12c5d1SDavid du Colombier 	}
4763e12c5d1SDavid du Colombier 	noted(NCONT);
4773e12c5d1SDavid du Colombier }
478dc5a79c1SDavid du Colombier 
479dc5a79c1SDavid du Colombier void
480dc5a79c1SDavid du Colombier Trapinit(void)
481dc5a79c1SDavid du Colombier {
4823e12c5d1SDavid du Colombier 	notify(notifyf);
4833e12c5d1SDavid du Colombier }
484dc5a79c1SDavid du Colombier 
485dc5a79c1SDavid du Colombier void
486dc5a79c1SDavid du Colombier Unlink(char *name)
4873e12c5d1SDavid du Colombier {
4883e12c5d1SDavid du Colombier 	remove(name);
4893e12c5d1SDavid du Colombier }
490dc5a79c1SDavid du Colombier 
491dc5a79c1SDavid du Colombier long
492dc5a79c1SDavid du Colombier Write(int fd, char *buf, long cnt)
4933e12c5d1SDavid du Colombier {
4943e12c5d1SDavid du Colombier 	return write(fd, buf, (long)cnt);
4953e12c5d1SDavid du Colombier }
496dc5a79c1SDavid du Colombier 
497dc5a79c1SDavid du Colombier long
498dc5a79c1SDavid du Colombier Read(int fd, char *buf, long cnt)
4993e12c5d1SDavid du Colombier {
5003e12c5d1SDavid du Colombier 	return read(fd, buf, cnt);
5013e12c5d1SDavid du Colombier }
502dc5a79c1SDavid du Colombier 
503dc5a79c1SDavid du Colombier long
504dc5a79c1SDavid du Colombier Seek(int fd, long cnt, long whence)
5053e12c5d1SDavid du Colombier {
5063e12c5d1SDavid du Colombier 	return seek(fd, cnt, whence);
5073e12c5d1SDavid du Colombier }
508dc5a79c1SDavid du Colombier 
509dc5a79c1SDavid du Colombier int
510dc5a79c1SDavid du Colombier Executable(char *file)
5113e12c5d1SDavid du Colombier {
5129a747e4fSDavid du Colombier 	Dir *statbuf;
5139a747e4fSDavid du Colombier 	int ret;
5143e12c5d1SDavid du Colombier 
5159a747e4fSDavid du Colombier 	statbuf = dirstat(file);
516dc5a79c1SDavid du Colombier 	if(statbuf == nil)
517dc5a79c1SDavid du Colombier 		return 0;
5189a747e4fSDavid du Colombier 	ret = ((statbuf->mode&0111)!=0 && (statbuf->mode&DMDIR)==0);
5199a747e4fSDavid du Colombier 	free(statbuf);
5209a747e4fSDavid du Colombier 	return ret;
5213e12c5d1SDavid du Colombier }
522dc5a79c1SDavid du Colombier 
523dc5a79c1SDavid du Colombier int
524dc5a79c1SDavid du Colombier Creat(char *file)
5253e12c5d1SDavid du Colombier {
5263e12c5d1SDavid du Colombier 	return create(file, 1, 0666L);
5273e12c5d1SDavid du Colombier }
528dc5a79c1SDavid du Colombier 
529dc5a79c1SDavid du Colombier int
530dc5a79c1SDavid du Colombier Dup(int a, int b)
531dc5a79c1SDavid du Colombier {
5323e12c5d1SDavid du Colombier 	return dup(a, b);
5333e12c5d1SDavid du Colombier }
534dc5a79c1SDavid du Colombier 
535dc5a79c1SDavid du Colombier int
536dc5a79c1SDavid du Colombier Dup1(int)
537dc5a79c1SDavid du Colombier {
5383e12c5d1SDavid du Colombier 	return -1;
5393e12c5d1SDavid du Colombier }
540dc5a79c1SDavid du Colombier 
541dc5a79c1SDavid du Colombier void
542dc5a79c1SDavid du Colombier Exit(char *stat)
5433e12c5d1SDavid du Colombier {
5443e12c5d1SDavid du Colombier 	Updenv();
5453e12c5d1SDavid du Colombier 	setstatus(stat);
5463e12c5d1SDavid du Colombier 	exits(truestatus()?"":getstatus());
5473e12c5d1SDavid du Colombier }
548dc5a79c1SDavid du Colombier 
549dc5a79c1SDavid du Colombier int
550dc5a79c1SDavid du Colombier Eintr(void)
551dc5a79c1SDavid du Colombier {
5523e12c5d1SDavid du Colombier 	return interrupted;
5533e12c5d1SDavid du Colombier }
554dc5a79c1SDavid du Colombier 
555dc5a79c1SDavid du Colombier void
556dc5a79c1SDavid du Colombier Noerror(void)
557dc5a79c1SDavid du Colombier {
5583e12c5d1SDavid du Colombier 	interrupted = 0;
5593e12c5d1SDavid du Colombier }
560dc5a79c1SDavid du Colombier 
561dc5a79c1SDavid du Colombier int
562dc5a79c1SDavid du Colombier Isatty(int fd)
563dc5a79c1SDavid du Colombier {
5644f281771SDavid du Colombier 	char buf[64];
5653e12c5d1SDavid du Colombier 
5664f281771SDavid du Colombier 	if(fd2path(fd, buf, sizeof buf) != 0)
567dc5a79c1SDavid du Colombier 		return 0;
5684f281771SDavid du Colombier 
5693806af99SDavid du Colombier 	/* might be #c/cons during boot - fixed 22 april 2005, remove this later */
5703806af99SDavid du Colombier 	if(strcmp(buf, "#c/cons") == 0)
5713806af99SDavid du Colombier 		return 1;
5723806af99SDavid du Colombier 
5734f281771SDavid du Colombier 	/* might be /mnt/term/dev/cons */
5744f281771SDavid du Colombier 	return strlen(buf) >= 9 && strcmp(buf+strlen(buf)-9, "/dev/cons") == 0;
5753e12c5d1SDavid du Colombier }
576dc5a79c1SDavid du Colombier 
577dc5a79c1SDavid du Colombier void
578dc5a79c1SDavid du Colombier Abort(void)
579dc5a79c1SDavid du Colombier {
5803e12c5d1SDavid du Colombier 	pfmt(err, "aborting\n");
5813e12c5d1SDavid du Colombier 	flush(err);
5823e12c5d1SDavid du Colombier 	Exit("aborting");
5833e12c5d1SDavid du Colombier }
584dc5a79c1SDavid du Colombier 
585dc5a79c1SDavid du Colombier void
586dc5a79c1SDavid du Colombier Memcpy(char *a, char *b, long n)
5873e12c5d1SDavid du Colombier {
5883e12c5d1SDavid du Colombier 	memmove(a, b, (long)n);
5893e12c5d1SDavid du Colombier }
590dc5a79c1SDavid du Colombier 
591dc5a79c1SDavid du Colombier void*
592dc5a79c1SDavid du Colombier Malloc(ulong n)
593dc5a79c1SDavid du Colombier {
5943e12c5d1SDavid du Colombier 	return malloc(n);
5953e12c5d1SDavid du Colombier }
596