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"
10276e7d6dSDavid du Colombier
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 };
27bad30d5dSDavid du Colombier char *Rcmain = "/rc/lib/rcmain";
28bad30d5dSDavid du Colombier char *Fdprefix = "/fd/";
29bad30d5dSDavid du Colombier
303e12c5d1SDavid du Colombier void execfinit(void);
313e12c5d1SDavid du Colombier void execbind(void);
323e12c5d1SDavid du Colombier void execmount(void);
333e12c5d1SDavid du Colombier void execnewpgrp(void);
34bad30d5dSDavid du Colombier
353e12c5d1SDavid du Colombier builtin Builtin[] = {
363e12c5d1SDavid du Colombier "cd", execcd,
373e12c5d1SDavid du Colombier "whatis", execwhatis,
383e12c5d1SDavid du Colombier "eval", execeval,
393e12c5d1SDavid du Colombier "exec", execexec, /* but with popword first */
403e12c5d1SDavid du Colombier "exit", execexit,
413e12c5d1SDavid du Colombier "shift", execshift,
423e12c5d1SDavid du Colombier "wait", execwait,
433e12c5d1SDavid du Colombier ".", execdot,
443e12c5d1SDavid du Colombier "finit", execfinit,
453e12c5d1SDavid du Colombier "flag", execflag,
463e12c5d1SDavid du Colombier "rfork", execnewpgrp,
473e12c5d1SDavid du Colombier 0
483e12c5d1SDavid du Colombier };
49dc5a79c1SDavid du Colombier
50dc5a79c1SDavid du Colombier void
execnewpgrp(void)51dc5a79c1SDavid du Colombier execnewpgrp(void)
52dc5a79c1SDavid du Colombier {
533e12c5d1SDavid du Colombier int arg;
543e12c5d1SDavid du Colombier char *s;
553e12c5d1SDavid du Colombier switch(count(runq->argv->words)){
56dc5a79c1SDavid du Colombier case 1:
57dc5a79c1SDavid du Colombier arg = RFENVG|RFNAMEG|RFNOTEG;
58dc5a79c1SDavid du Colombier break;
593e12c5d1SDavid du Colombier case 2:
603e12c5d1SDavid du Colombier arg = 0;
61*c6df1444SDavid du Colombier for(s = runq->argv->words->next->word;*s;s++)
62*c6df1444SDavid du Colombier switch(*s){
633e12c5d1SDavid du Colombier default:
643e12c5d1SDavid du Colombier goto Usage;
65dc5a79c1SDavid du Colombier case 'n':
66dc5a79c1SDavid du Colombier arg|=RFNAMEG; break;
67dc5a79c1SDavid du Colombier case 'N':
68dc5a79c1SDavid du Colombier arg|=RFCNAMEG;
69dc5a79c1SDavid du Colombier break;
70dc5a79c1SDavid du Colombier case 'm':
71dc5a79c1SDavid du Colombier arg|=RFNOMNT; break;
72dc5a79c1SDavid du Colombier case 'e':
73dc5a79c1SDavid du Colombier arg|=RFENVG; break;
74dc5a79c1SDavid du Colombier case 'E':
75dc5a79c1SDavid du Colombier arg|=RFCENVG; break;
76dc5a79c1SDavid du Colombier case 's':
77dc5a79c1SDavid du Colombier arg|=RFNOTEG; break;
78dc5a79c1SDavid du Colombier case 'f':
79dc5a79c1SDavid du Colombier arg|=RFFDG; break;
80dc5a79c1SDavid du Colombier case 'F':
81dc5a79c1SDavid du Colombier arg|=RFCFDG; break;
823e12c5d1SDavid du Colombier }
833e12c5d1SDavid du Colombier break;
843e12c5d1SDavid du Colombier default:
853e12c5d1SDavid du Colombier Usage:
867dd7cddfSDavid du Colombier pfmt(err, "Usage: %s [fnesFNEm]\n", runq->argv->words->word);
873e12c5d1SDavid du Colombier setstatus("rfork usage");
883e12c5d1SDavid du Colombier poplist();
893e12c5d1SDavid du Colombier return;
903e12c5d1SDavid du Colombier }
913e12c5d1SDavid du Colombier if(rfork(arg)==-1){
923e12c5d1SDavid du Colombier pfmt(err, "rc: %s failed\n", runq->argv->words->word);
933e12c5d1SDavid du Colombier setstatus("rfork failed");
943e12c5d1SDavid du Colombier }
953e12c5d1SDavid du Colombier else
963e12c5d1SDavid du Colombier setstatus("");
973e12c5d1SDavid du Colombier poplist();
983e12c5d1SDavid du Colombier }
99dc5a79c1SDavid du Colombier
100*c6df1444SDavid du Colombier int
openenv(char * shortname)101*c6df1444SDavid du Colombier openenv(char *shortname)
102*c6df1444SDavid du Colombier {
103*c6df1444SDavid du Colombier int f;
104*c6df1444SDavid du Colombier io *envname;
105*c6df1444SDavid du Colombier
106*c6df1444SDavid du Colombier envname = openstr();
107*c6df1444SDavid du Colombier pfmt(envname, "/env/%s", shortname);
108*c6df1444SDavid du Colombier f = open((char *)envname->strp, OREAD);
109*c6df1444SDavid du Colombier closeio(envname);
110*c6df1444SDavid du Colombier return f;
111*c6df1444SDavid du Colombier }
112*c6df1444SDavid du Colombier
113*c6df1444SDavid du Colombier int
createenv(char * pfx,char * shortname)114*c6df1444SDavid du Colombier createenv(char *pfx, char *shortname)
115*c6df1444SDavid du Colombier {
116*c6df1444SDavid du Colombier int f;
117*c6df1444SDavid du Colombier io *envname;
118*c6df1444SDavid du Colombier
119*c6df1444SDavid du Colombier envname = openstr();
120*c6df1444SDavid du Colombier pfmt(envname, "/env/%s%s", pfx, shortname);
121*c6df1444SDavid du Colombier f = Creat((char *)envname->strp);
122*c6df1444SDavid du Colombier if (f < 0)
123*c6df1444SDavid du Colombier pfmt(err, "rc: can't create %s: %r\n", (char *)envname->strp);
124*c6df1444SDavid du Colombier closeio(envname);
125*c6df1444SDavid du Colombier return f;
126*c6df1444SDavid du Colombier }
127*c6df1444SDavid du Colombier
128dc5a79c1SDavid du Colombier void
Vinit(void)129dc5a79c1SDavid du Colombier Vinit(void)
130dc5a79c1SDavid du Colombier {
131276e7d6dSDavid du Colombier int dir, f, len, i, n, nent;
132*c6df1444SDavid du Colombier char *buf, *s, *name;
133*c6df1444SDavid du Colombier var *namevar;
134276e7d6dSDavid du Colombier word *val;
1359a747e4fSDavid du Colombier Dir *ent;
136276e7d6dSDavid du Colombier
1379a747e4fSDavid du Colombier dir = open("/env", OREAD);
1383e12c5d1SDavid du Colombier if(dir<0){
1399a747e4fSDavid du Colombier pfmt(err, "rc: can't open /env: %r\n");
1403e12c5d1SDavid du Colombier return;
1413e12c5d1SDavid du Colombier }
1429a747e4fSDavid du Colombier ent = nil;
143*c6df1444SDavid du Colombier while ((nent = dirread(dir, &ent)) > 0) {
1449a747e4fSDavid du Colombier for(i = 0; i<nent; i++){
1459a747e4fSDavid du Colombier len = ent[i].length;
146*c6df1444SDavid du Colombier name = ent[i].name;
147*c6df1444SDavid du Colombier if(len <= 0 || strncmp(name, "fn#", 3) == 0)
148*c6df1444SDavid du Colombier continue;
149*c6df1444SDavid du Colombier if((f = openenv(name)) < 0)
150*c6df1444SDavid du Colombier continue;
151276e7d6dSDavid du Colombier buf = emalloc(len+1);
152276e7d6dSDavid du Colombier n = readn(f, buf, len);
153276e7d6dSDavid du Colombier if (n <= 0)
154276e7d6dSDavid du Colombier buf[0] = '\0';
155276e7d6dSDavid du Colombier else
156276e7d6dSDavid du Colombier buf[n] = '\0';
1573e12c5d1SDavid du Colombier val = 0;
1583e12c5d1SDavid du Colombier /* Charitably add a 0 at the end if need be */
159dc5a79c1SDavid du Colombier if(buf[len-1])
160dc5a79c1SDavid du Colombier buf[len++]='\0';
1613e12c5d1SDavid du Colombier s = buf+len-1;
1623e12c5d1SDavid du Colombier for(;;){
163*c6df1444SDavid du Colombier while(s!=buf && s[-1]!='\0')
164*c6df1444SDavid du Colombier --s;
1653e12c5d1SDavid du Colombier val = newword(s, val);
166dc5a79c1SDavid du Colombier if(s==buf)
167dc5a79c1SDavid du Colombier break;
1683e12c5d1SDavid du Colombier --s;
1693e12c5d1SDavid du Colombier }
170*c6df1444SDavid du Colombier setvar(name, val);
171*c6df1444SDavid du Colombier namevar = vlook(name);
172*c6df1444SDavid du Colombier assert(namevar != nil);
173*c6df1444SDavid du Colombier namevar->changed = 0;
1743e12c5d1SDavid du Colombier close(f);
1753e12c5d1SDavid du Colombier efree(buf);
1763e12c5d1SDavid du Colombier }
1779a747e4fSDavid du Colombier free(ent);
1789a747e4fSDavid du Colombier }
1793e12c5d1SDavid du Colombier close(dir);
1803e12c5d1SDavid du Colombier }
181*c6df1444SDavid du Colombier
1823e12c5d1SDavid du Colombier int envdir;
183dc5a79c1SDavid du Colombier
184dc5a79c1SDavid du Colombier void
Xrdfn(void)185dc5a79c1SDavid du Colombier Xrdfn(void)
186dc5a79c1SDavid du Colombier {
187*c6df1444SDavid du Colombier int f;
188276e7d6dSDavid du Colombier Dir *e;
1899a747e4fSDavid du Colombier static Dir *ent, *allocent;
1909a747e4fSDavid du Colombier static int nent;
1919a747e4fSDavid du Colombier
1929a747e4fSDavid du Colombier for(;;){
1939a747e4fSDavid du Colombier if(nent == 0){
1949a747e4fSDavid du Colombier free(allocent);
1959a747e4fSDavid du Colombier nent = dirread(envdir, &allocent);
1969a747e4fSDavid du Colombier ent = allocent;
1979a747e4fSDavid du Colombier }
1989a747e4fSDavid du Colombier if(nent <= 0)
1999a747e4fSDavid du Colombier break;
2009a747e4fSDavid du Colombier while(nent){
2019a747e4fSDavid du Colombier e = ent++;
2029a747e4fSDavid du Colombier nent--;
203*c6df1444SDavid du Colombier if(e->length && strncmp(e->name, "fn#", 3)==0){
204*c6df1444SDavid du Colombier if((f = openenv(e->name)) >= 0){
2053e12c5d1SDavid du Colombier execcmds(openfd(f));
2063e12c5d1SDavid du Colombier return;
2073e12c5d1SDavid du Colombier }
2083e12c5d1SDavid du Colombier }
2093e12c5d1SDavid du Colombier }
2109a747e4fSDavid du Colombier }
2113e12c5d1SDavid du Colombier close(envdir);
2123e12c5d1SDavid du Colombier Xreturn();
2133e12c5d1SDavid du Colombier }
214*c6df1444SDavid du Colombier
2153e12c5d1SDavid du Colombier union code rdfns[4];
216dc5a79c1SDavid du Colombier
217dc5a79c1SDavid du Colombier void
execfinit(void)218dc5a79c1SDavid du Colombier execfinit(void)
219dc5a79c1SDavid du Colombier {
2203e12c5d1SDavid du Colombier static int first = 1;
2213e12c5d1SDavid du Colombier if(first){
2223e12c5d1SDavid du Colombier rdfns[0].i = 1;
2233e12c5d1SDavid du Colombier rdfns[1].f = Xrdfn;
2243e12c5d1SDavid du Colombier rdfns[2].f = Xjump;
2253e12c5d1SDavid du Colombier rdfns[3].i = 1;
2263e12c5d1SDavid du Colombier first = 0;
2273e12c5d1SDavid du Colombier }
2283e12c5d1SDavid du Colombier Xpopm();
2299a747e4fSDavid du Colombier envdir = open("/env", 0);
2303e12c5d1SDavid du Colombier if(envdir<0){
2319a747e4fSDavid du Colombier pfmt(err, "rc: can't open /env: %r\n");
2323e12c5d1SDavid du Colombier return;
2333e12c5d1SDavid du Colombier }
2343e12c5d1SDavid du Colombier start(rdfns, 1, runq->local);
2353e12c5d1SDavid du Colombier }
236dc5a79c1SDavid du Colombier
237dc5a79c1SDavid du Colombier int
Waitfor(int pid,int)238dc5a79c1SDavid du Colombier Waitfor(int pid, int)
239dc5a79c1SDavid du Colombier {
2403e12c5d1SDavid du Colombier thread *p;
2419a747e4fSDavid du Colombier Waitmsg *w;
2429a747e4fSDavid du Colombier char errbuf[ERRMAX];
2439a747e4fSDavid du Colombier
244d3907fe5SDavid du Colombier if(pid >= 0 && !havewaitpid(pid))
245d3907fe5SDavid du Colombier return 0;
246d3907fe5SDavid du Colombier
2479a747e4fSDavid du Colombier while((w = wait()) != nil){
248*c6df1444SDavid du Colombier /* this would otherwise go unreported by rc */
249*c6df1444SDavid du Colombier if(strstr(w->msg, "error in demand load") != nil)
250*c6df1444SDavid du Colombier pfmt(err, "rc: %s\n", w->msg);
251d3907fe5SDavid du Colombier delwaitpid(w->pid);
2529a747e4fSDavid du Colombier if(w->pid==pid){
2539a747e4fSDavid du Colombier setstatus(w->msg);
2549a747e4fSDavid du Colombier free(w);
255219b2ee8SDavid du Colombier return 0;
2563e12c5d1SDavid du Colombier }
2573e12c5d1SDavid du Colombier for(p = runq->ret;p;p = p->ret)
2589a747e4fSDavid du Colombier if(p->pid==w->pid){
2593e12c5d1SDavid du Colombier p->pid=-1;
2609a747e4fSDavid du Colombier strcpy(p->status, w->msg);
2613e12c5d1SDavid du Colombier }
2629a747e4fSDavid du Colombier free(w);
2633e12c5d1SDavid du Colombier }
2649a747e4fSDavid du Colombier
2659a747e4fSDavid du Colombier errstr(errbuf, sizeof errbuf);
26699eb86a7SDavid du Colombier if(strcmp(errbuf, "interrupted")==0) return -1;
2673e12c5d1SDavid du Colombier return 0;
2683e12c5d1SDavid du Colombier }
269dc5a79c1SDavid du Colombier
270276e7d6dSDavid du Colombier char **
mkargv(word * a)271276e7d6dSDavid du Colombier mkargv(word *a)
2723e12c5d1SDavid du Colombier {
2733e12c5d1SDavid du Colombier char **argv = (char **)emalloc((count(a)+2)*sizeof(char *));
2743e12c5d1SDavid du Colombier char **argp = argv+1; /* leave one at front for runcoms */
27599eb86a7SDavid du Colombier for(;a;a = a->next) *argp++=a->word;
2763e12c5d1SDavid du Colombier *argp = 0;
2773e12c5d1SDavid du Colombier return argv;
2783e12c5d1SDavid du Colombier }
279dc5a79c1SDavid du Colombier
280dc5a79c1SDavid du Colombier void
addenv(var * v)281dc5a79c1SDavid du Colombier addenv(var *v)
2823e12c5d1SDavid du Colombier {
2833e12c5d1SDavid du Colombier word *w;
2843e12c5d1SDavid du Colombier int f;
2853e12c5d1SDavid du Colombier io *fd;
2863e12c5d1SDavid du Colombier if(v->changed){
2873e12c5d1SDavid du Colombier v->changed = 0;
288*c6df1444SDavid du Colombier if((f = createenv("", v->name)) >= 0) {
2893e12c5d1SDavid du Colombier for(w = v->val;w;w = w->next)
290*c6df1444SDavid du Colombier write(f, w->word, strlen(w->word)+1);
2913e12c5d1SDavid du Colombier close(f);
2923e12c5d1SDavid du Colombier }
2933e12c5d1SDavid du Colombier }
2943e12c5d1SDavid du Colombier if(v->fnchanged){
2953e12c5d1SDavid du Colombier v->fnchanged = 0;
296*c6df1444SDavid du Colombier if((f = createenv("fn#", v->name)) >= 0) {
2973e12c5d1SDavid du Colombier if(v->fn){
2983e12c5d1SDavid du Colombier fd = openfd(f);
299fed0fa9eSDavid du Colombier pfmt(fd, "fn %q %s\n", v->name, v->fn[v->pc-1].s);
3003e12c5d1SDavid du Colombier closeio(fd);
3013e12c5d1SDavid du Colombier }
3023e12c5d1SDavid du Colombier close(f);
3033e12c5d1SDavid du Colombier }
3043e12c5d1SDavid du Colombier }
3053e12c5d1SDavid du Colombier }
306dc5a79c1SDavid du Colombier
307dc5a79c1SDavid du Colombier void
updenvlocal(var * v)308dc5a79c1SDavid du Colombier updenvlocal(var *v)
3093e12c5d1SDavid du Colombier {
3103e12c5d1SDavid du Colombier if(v){
3113e12c5d1SDavid du Colombier updenvlocal(v->next);
3123e12c5d1SDavid du Colombier addenv(v);
3133e12c5d1SDavid du Colombier }
3143e12c5d1SDavid du Colombier }
315dc5a79c1SDavid du Colombier
316dc5a79c1SDavid du Colombier void
Updenv(void)317dc5a79c1SDavid du Colombier Updenv(void)
318dc5a79c1SDavid du Colombier {
3193e12c5d1SDavid du Colombier var *v, **h;
3203e12c5d1SDavid du Colombier for(h = gvar;h!=&gvar[NVAR];h++)
3213e12c5d1SDavid du Colombier for(v=*h;v;v = v->next)
3223e12c5d1SDavid du Colombier addenv(v);
323dc5a79c1SDavid du Colombier if(runq)
324dc5a79c1SDavid du Colombier updenvlocal(runq->local);
3253e12c5d1SDavid du Colombier }
326dc5a79c1SDavid du Colombier
3275acbe002SDavid du Colombier /* not used on plan 9 */
328dc5a79c1SDavid du Colombier int
ForkExecute(char * file,char ** argv,int sin,int sout,int serr)329dc5a79c1SDavid du Colombier ForkExecute(char *file, char **argv, int sin, int sout, int serr)
330dc5a79c1SDavid du Colombier {
331dc5a79c1SDavid du Colombier int pid;
332dc5a79c1SDavid du Colombier
333dc5a79c1SDavid du Colombier if(access(file, 1) != 0)
334dc5a79c1SDavid du Colombier return -1;
335dc5a79c1SDavid du Colombier switch(pid = fork()){
336dc5a79c1SDavid du Colombier case -1:
337dc5a79c1SDavid du Colombier return -1;
338dc5a79c1SDavid du Colombier case 0:
339dc5a79c1SDavid du Colombier if(sin >= 0)
340dc5a79c1SDavid du Colombier dup(sin, 0);
341dc5a79c1SDavid du Colombier else
342dc5a79c1SDavid du Colombier close(0);
343dc5a79c1SDavid du Colombier if(sout >= 0)
344dc5a79c1SDavid du Colombier dup(sout, 1);
345dc5a79c1SDavid du Colombier else
346dc5a79c1SDavid du Colombier close(1);
347dc5a79c1SDavid du Colombier if(serr >= 0)
348dc5a79c1SDavid du Colombier dup(serr, 2);
349dc5a79c1SDavid du Colombier else
350dc5a79c1SDavid du Colombier close(2);
351dc5a79c1SDavid du Colombier exec(file, argv);
352dc5a79c1SDavid du Colombier exits(file);
353dc5a79c1SDavid du Colombier }
354dc5a79c1SDavid du Colombier return pid;
355dc5a79c1SDavid du Colombier }
356dc5a79c1SDavid du Colombier
357dc5a79c1SDavid du Colombier void
Execute(word * args,word * path)358dc5a79c1SDavid du Colombier Execute(word *args, word *path)
3593e12c5d1SDavid du Colombier {
3603e12c5d1SDavid du Colombier char **argv = mkargv(args);
361*c6df1444SDavid du Colombier char file[1024], errstr[ERRMAX+1];
362219b2ee8SDavid du Colombier int nc;
3635acbe002SDavid du Colombier
3643e12c5d1SDavid du Colombier Updenv();
3655acbe002SDavid du Colombier errstr[0] = '\0';
3663e12c5d1SDavid du Colombier for(;path;path = path->next){
367219b2ee8SDavid du Colombier nc = strlen(path->word);
368*c6df1444SDavid du Colombier if(nc >= sizeof file - 1){ /* 1 for / */
369*c6df1444SDavid du Colombier werrstr("path component too long");
370*c6df1444SDavid du Colombier continue;
371*c6df1444SDavid du Colombier }
3723e12c5d1SDavid du Colombier strcpy(file, path->word);
373219b2ee8SDavid du Colombier if(file[0]){
374219b2ee8SDavid du Colombier strcat(file, "/");
375219b2ee8SDavid du Colombier nc++;
376219b2ee8SDavid du Colombier }
377*c6df1444SDavid du Colombier if(nc + strlen(argv[1]) >= sizeof file){
378*c6df1444SDavid du Colombier werrstr("command name too long");
379*c6df1444SDavid du Colombier continue;
380*c6df1444SDavid du Colombier }
3813e12c5d1SDavid du Colombier strcat(file, argv[1]);
3823e12c5d1SDavid du Colombier exec(file, argv+1);
3835acbe002SDavid du Colombier /*
384*c6df1444SDavid du Colombier * if file exists and is executable, exec should have worked,
385*c6df1444SDavid du Colombier * unless it's a directory or an executable for another
386*c6df1444SDavid du Colombier * architecture. in particular, if it failed due to lack of
387*c6df1444SDavid du Colombier * swap/vm (e.g., arg. list too long) or other allocation or
388*c6df1444SDavid du Colombier * i/o failure, stop searching and print the reason for failure.
3895acbe002SDavid du Colombier */
390*c6df1444SDavid du Colombier rerrstr(errstr, sizeof errstr);
391d9cef801SDavid du Colombier if (strstr(errstr, " allocat") != nil ||
392*c6df1444SDavid du Colombier strstr(errstr, " full") != nil ||
393*c6df1444SDavid du Colombier strstr(errstr, "i/o error") != nil)
3945acbe002SDavid du Colombier break;
3953e12c5d1SDavid du Colombier }
396*c6df1444SDavid du Colombier if(errstr[0] == '\0') /* pick up any werrstr "too long"s */
397*c6df1444SDavid du Colombier rerrstr(errstr, sizeof errstr);
3985acbe002SDavid du Colombier pfmt(err, "%s: %s\n", argv[1], errstr);
3993e12c5d1SDavid du Colombier efree((char *)argv);
4003e12c5d1SDavid du Colombier }
401*c6df1444SDavid du Colombier
402*c6df1444SDavid du Colombier #define NDIR 256 /* should be a better way */
403dc5a79c1SDavid du Colombier
404dc5a79c1SDavid du Colombier int
Globsize(char * p)405dc5a79c1SDavid du Colombier Globsize(char *p)
4063e12c5d1SDavid du Colombier {
40773e742d7SDavid du Colombier int isglob = 0, globlen = NDIR+1;
4083e12c5d1SDavid du Colombier for(;*p;p++){
4093e12c5d1SDavid du Colombier if(*p==GLOB){
4103e12c5d1SDavid du Colombier p++;
411dc5a79c1SDavid du Colombier if(*p!=GLOB)
412dc5a79c1SDavid du Colombier isglob++;
4139a747e4fSDavid du Colombier globlen+=*p=='*'?NDIR:1;
4143e12c5d1SDavid du Colombier }
4153e12c5d1SDavid du Colombier else
4163e12c5d1SDavid du Colombier globlen++;
4173e12c5d1SDavid du Colombier }
4183e12c5d1SDavid du Colombier return isglob?globlen:0;
4193e12c5d1SDavid du Colombier }
4203e12c5d1SDavid du Colombier #define NFD 50
421276e7d6dSDavid du Colombier
4223e12c5d1SDavid du Colombier struct{
4239a747e4fSDavid du Colombier Dir *dbuf;
4249a747e4fSDavid du Colombier int i;
4253e12c5d1SDavid du Colombier int n;
4263e12c5d1SDavid du Colombier }dir[NFD];
427dc5a79c1SDavid du Colombier
428dc5a79c1SDavid du Colombier int
Opendir(char * name)429dc5a79c1SDavid du Colombier Opendir(char *name)
4303e12c5d1SDavid du Colombier {
4319a747e4fSDavid du Colombier Dir *db;
4323e12c5d1SDavid du Colombier int f;
4333e12c5d1SDavid du Colombier f = open(name, 0);
4343e12c5d1SDavid du Colombier if(f==-1)
4353e12c5d1SDavid du Colombier return f;
4369a747e4fSDavid du Colombier db = dirfstat(f);
4379a747e4fSDavid du Colombier if(db!=nil && (db->mode&DMDIR)){
4389a747e4fSDavid du Colombier if(f<NFD){
4399a747e4fSDavid du Colombier dir[f].i = 0;
4409a747e4fSDavid du Colombier dir[f].n = 0;
4413e12c5d1SDavid du Colombier }
4429a747e4fSDavid du Colombier free(db);
4433e12c5d1SDavid du Colombier return f;
4443e12c5d1SDavid du Colombier }
4459a747e4fSDavid du Colombier free(db);
4463e12c5d1SDavid du Colombier close(f);
4473e12c5d1SDavid du Colombier return -1;
4483e12c5d1SDavid du Colombier }
4496b6b9ac8SDavid du Colombier
4506b6b9ac8SDavid du Colombier static int
trimdirs(Dir * d,int nd)4516b6b9ac8SDavid du Colombier trimdirs(Dir *d, int nd)
4526b6b9ac8SDavid du Colombier {
4536b6b9ac8SDavid du Colombier int r, w;
4546b6b9ac8SDavid du Colombier
4556b6b9ac8SDavid du Colombier for(r=w=0; r<nd; r++)
4566b6b9ac8SDavid du Colombier if(d[r].mode&DMDIR)
4576b6b9ac8SDavid du Colombier d[w++] = d[r];
4586b6b9ac8SDavid du Colombier return w;
4596b6b9ac8SDavid du Colombier }
4606b6b9ac8SDavid du Colombier
4616b6b9ac8SDavid du Colombier /*
4626b6b9ac8SDavid du Colombier * onlydirs is advisory -- it means you only
4636b6b9ac8SDavid du Colombier * need to return the directories. it's okay to
4646b6b9ac8SDavid du Colombier * return files too (e.g., on unix where you can't
4656b6b9ac8SDavid du Colombier * tell during the readdir), but that just makes
4666b6b9ac8SDavid du Colombier * the globber work harder.
4676b6b9ac8SDavid du Colombier */
468dc5a79c1SDavid du Colombier int
Readdir(int f,void * p,int onlydirs)469276e7d6dSDavid du Colombier Readdir(int f, void *p, int onlydirs)
4703e12c5d1SDavid du Colombier {
4713e12c5d1SDavid du Colombier int n;
472dc5a79c1SDavid du Colombier
4739a747e4fSDavid du Colombier if(f<0 || f>=NFD)
4743e12c5d1SDavid du Colombier return 0;
4756b6b9ac8SDavid du Colombier Again:
4769a747e4fSDavid du Colombier if(dir[f].i==dir[f].n){ /* read */
4779a747e4fSDavid du Colombier free(dir[f].dbuf);
4789a747e4fSDavid du Colombier dir[f].dbuf = 0;
4799a747e4fSDavid du Colombier n = dirread(f, &dir[f].dbuf);
4806b6b9ac8SDavid du Colombier if(n>0){
4816b6b9ac8SDavid du Colombier if(onlydirs){
4826b6b9ac8SDavid du Colombier n = trimdirs(dir[f].dbuf, n);
4836b6b9ac8SDavid du Colombier if(n == 0)
4846b6b9ac8SDavid du Colombier goto Again;
4856b6b9ac8SDavid du Colombier }
4869a747e4fSDavid du Colombier dir[f].n = n;
4876b6b9ac8SDavid du Colombier }else
4883e12c5d1SDavid du Colombier dir[f].n = 0;
4899a747e4fSDavid du Colombier dir[f].i = 0;
4903e12c5d1SDavid du Colombier }
4919a747e4fSDavid du Colombier if(dir[f].i == dir[f].n)
4923e12c5d1SDavid du Colombier return 0;
4939a747e4fSDavid du Colombier strcpy(p, dir[f].dbuf[dir[f].i].name);
4949a747e4fSDavid du Colombier dir[f].i++;
4953e12c5d1SDavid du Colombier return 1;
4963e12c5d1SDavid du Colombier }
497dc5a79c1SDavid du Colombier
498dc5a79c1SDavid du Colombier void
Closedir(int f)499dc5a79c1SDavid du Colombier Closedir(int f)
500dc5a79c1SDavid du Colombier {
5019a747e4fSDavid du Colombier if(f>=0 && f<NFD){
5029a747e4fSDavid du Colombier free(dir[f].dbuf);
5039a747e4fSDavid du Colombier dir[f].i = 0;
5049a747e4fSDavid du Colombier dir[f].n = 0;
5059a747e4fSDavid du Colombier dir[f].dbuf = 0;
5063e12c5d1SDavid du Colombier }
5073e12c5d1SDavid du Colombier close(f);
5083e12c5d1SDavid du Colombier }
509*c6df1444SDavid du Colombier
5103e12c5d1SDavid du Colombier int interrupted = 0;
511*c6df1444SDavid du Colombier
5123e12c5d1SDavid du Colombier void
notifyf(void *,char * s)5137dd7cddfSDavid du Colombier notifyf(void*, char *s)
5143e12c5d1SDavid du Colombier {
5153e12c5d1SDavid du Colombier int i;
516*c6df1444SDavid du Colombier
517*c6df1444SDavid du Colombier for (i = 0; syssigname[i]; i++)
518*c6df1444SDavid du Colombier if (strncmp(s, syssigname[i], strlen(syssigname[i])) == 0) {
519*c6df1444SDavid du Colombier if (strncmp(s, "sys: ", 5) != 0)
520*c6df1444SDavid du Colombier interrupted = 1;
5213e12c5d1SDavid du Colombier goto Out;
5223e12c5d1SDavid du Colombier }
5233e12c5d1SDavid du Colombier pfmt(err, "rc: note: %s\n", s);
5243e12c5d1SDavid du Colombier noted(NDFLT);
5253e12c5d1SDavid du Colombier return;
5263e12c5d1SDavid du Colombier Out:
527219b2ee8SDavid du Colombier if (strcmp(s, "interrupt") != 0 || trap[i] == 0) {
5283e12c5d1SDavid du Colombier trap[i]++;
5293e12c5d1SDavid du Colombier ntrap++;
530219b2ee8SDavid du Colombier }
5313e12c5d1SDavid du Colombier if (ntrap >= 32) { /* rc is probably in a trap loop */
5323e12c5d1SDavid du Colombier pfmt(err, "rc: Too many traps (trap %s), aborting\n", s);
5333e12c5d1SDavid du Colombier abort();
5343e12c5d1SDavid du Colombier }
5353e12c5d1SDavid du Colombier noted(NCONT);
5363e12c5d1SDavid du Colombier }
537dc5a79c1SDavid du Colombier
538dc5a79c1SDavid du Colombier void
Trapinit(void)539dc5a79c1SDavid du Colombier Trapinit(void)
540dc5a79c1SDavid du Colombier {
5413e12c5d1SDavid du Colombier notify(notifyf);
5423e12c5d1SDavid du Colombier }
543dc5a79c1SDavid du Colombier
544dc5a79c1SDavid du Colombier void
Unlink(char * name)545dc5a79c1SDavid du Colombier Unlink(char *name)
5463e12c5d1SDavid du Colombier {
5473e12c5d1SDavid du Colombier remove(name);
5483e12c5d1SDavid du Colombier }
549dc5a79c1SDavid du Colombier
550dc5a79c1SDavid du Colombier long
Write(int fd,void * buf,long cnt)551276e7d6dSDavid du Colombier Write(int fd, void *buf, long cnt)
5523e12c5d1SDavid du Colombier {
553276e7d6dSDavid du Colombier return write(fd, buf, cnt);
5543e12c5d1SDavid du Colombier }
555dc5a79c1SDavid du Colombier
556dc5a79c1SDavid du Colombier long
Read(int fd,void * buf,long cnt)557276e7d6dSDavid du Colombier Read(int fd, void *buf, long cnt)
5583e12c5d1SDavid du Colombier {
5593e12c5d1SDavid du Colombier return read(fd, buf, cnt);
5603e12c5d1SDavid du Colombier }
561dc5a79c1SDavid du Colombier
562dc5a79c1SDavid du Colombier int
Executable(char * file)563dc5a79c1SDavid du Colombier Executable(char *file)
5643e12c5d1SDavid du Colombier {
5659a747e4fSDavid du Colombier Dir *statbuf;
5669a747e4fSDavid du Colombier int ret;
5673e12c5d1SDavid du Colombier
5689a747e4fSDavid du Colombier statbuf = dirstat(file);
569dc5a79c1SDavid du Colombier if(statbuf == nil)
570dc5a79c1SDavid du Colombier return 0;
57199eb86a7SDavid du Colombier ret = ((statbuf->mode&0111)!=0 && (statbuf->mode&DMDIR)==0);
5729a747e4fSDavid du Colombier free(statbuf);
5739a747e4fSDavid du Colombier return ret;
5743e12c5d1SDavid du Colombier }
575dc5a79c1SDavid du Colombier
576dc5a79c1SDavid du Colombier int
Creat(char * file)577dc5a79c1SDavid du Colombier Creat(char *file)
5783e12c5d1SDavid du Colombier {
579*c6df1444SDavid du Colombier return create(file, 1, 0666);
5803e12c5d1SDavid du Colombier }
581dc5a79c1SDavid du Colombier
582dc5a79c1SDavid du Colombier int
Dup(int a,int b)583dc5a79c1SDavid du Colombier Dup(int a, int b)
584dc5a79c1SDavid du Colombier {
5853e12c5d1SDavid du Colombier return dup(a, b);
5863e12c5d1SDavid du Colombier }
587dc5a79c1SDavid du Colombier
588dc5a79c1SDavid du Colombier int
Dup1(int)589dc5a79c1SDavid du Colombier Dup1(int)
590dc5a79c1SDavid du Colombier {
5913e12c5d1SDavid du Colombier return -1;
5923e12c5d1SDavid du Colombier }
593dc5a79c1SDavid du Colombier
594dc5a79c1SDavid du Colombier void
Exit(char * stat)595dc5a79c1SDavid du Colombier Exit(char *stat)
5963e12c5d1SDavid du Colombier {
5973e12c5d1SDavid du Colombier Updenv();
5983e12c5d1SDavid du Colombier setstatus(stat);
5993e12c5d1SDavid du Colombier exits(truestatus()?"":getstatus());
6003e12c5d1SDavid du Colombier }
601dc5a79c1SDavid du Colombier
602dc5a79c1SDavid du Colombier int
Eintr(void)603dc5a79c1SDavid du Colombier Eintr(void)
604dc5a79c1SDavid du Colombier {
6053e12c5d1SDavid du Colombier return interrupted;
6063e12c5d1SDavid du Colombier }
607dc5a79c1SDavid du Colombier
608dc5a79c1SDavid du Colombier void
Noerror(void)609dc5a79c1SDavid du Colombier Noerror(void)
610dc5a79c1SDavid du Colombier {
6113e12c5d1SDavid du Colombier interrupted = 0;
6123e12c5d1SDavid du Colombier }
613dc5a79c1SDavid du Colombier
614dc5a79c1SDavid du Colombier int
Isatty(int fd)615dc5a79c1SDavid du Colombier Isatty(int fd)
616dc5a79c1SDavid du Colombier {
6174f281771SDavid du Colombier char buf[64];
6183e12c5d1SDavid du Colombier
6194f281771SDavid du Colombier if(fd2path(fd, buf, sizeof buf) != 0)
620dc5a79c1SDavid du Colombier return 0;
6214f281771SDavid du Colombier
6223806af99SDavid du Colombier /* might be #c/cons during boot - fixed 22 april 2005, remove this later */
6233806af99SDavid du Colombier if(strcmp(buf, "#c/cons") == 0)
6243806af99SDavid du Colombier return 1;
6253806af99SDavid du Colombier
6264f281771SDavid du Colombier /* might be /mnt/term/dev/cons */
6274f281771SDavid du Colombier return strlen(buf) >= 9 && strcmp(buf+strlen(buf)-9, "/dev/cons") == 0;
6283e12c5d1SDavid du Colombier }
629dc5a79c1SDavid du Colombier
630dc5a79c1SDavid du Colombier void
Abort(void)631dc5a79c1SDavid du Colombier Abort(void)
632dc5a79c1SDavid du Colombier {
6333e12c5d1SDavid du Colombier pfmt(err, "aborting\n");
6343e12c5d1SDavid du Colombier flush(err);
6353e12c5d1SDavid du Colombier Exit("aborting");
6363e12c5d1SDavid du Colombier }
637dc5a79c1SDavid du Colombier
638dc5a79c1SDavid du Colombier void
Memcpy(void * a,void * b,long n)639276e7d6dSDavid du Colombier Memcpy(void *a, void *b, long n)
6403e12c5d1SDavid du Colombier {
641276e7d6dSDavid du Colombier memmove(a, b, n);
6423e12c5d1SDavid du Colombier }
643dc5a79c1SDavid du Colombier
644dc5a79c1SDavid du Colombier void*
Malloc(ulong n)645dc5a79c1SDavid du Colombier Malloc(ulong n)
646dc5a79c1SDavid du Colombier {
6474e3613abSDavid du Colombier return mallocz(n, 1);
6483e12c5d1SDavid du Colombier }
649d3907fe5SDavid du Colombier
650d3907fe5SDavid du Colombier int *waitpids;
651d3907fe5SDavid du Colombier int nwaitpids;
652d3907fe5SDavid du Colombier
653d3907fe5SDavid du Colombier void
addwaitpid(int pid)654d3907fe5SDavid du Colombier addwaitpid(int pid)
655d3907fe5SDavid du Colombier {
656d3907fe5SDavid du Colombier waitpids = realloc(waitpids, (nwaitpids+1)*sizeof waitpids[0]);
657d3907fe5SDavid du Colombier if(waitpids == 0)
658d3907fe5SDavid du Colombier panic("Can't realloc %d waitpids", nwaitpids+1);
659d3907fe5SDavid du Colombier waitpids[nwaitpids++] = pid;
660d3907fe5SDavid du Colombier }
661d3907fe5SDavid du Colombier
662d3907fe5SDavid du Colombier void
delwaitpid(int pid)663d3907fe5SDavid du Colombier delwaitpid(int pid)
664d3907fe5SDavid du Colombier {
665d3907fe5SDavid du Colombier int r, w;
666d3907fe5SDavid du Colombier
667d3907fe5SDavid du Colombier for(r=w=0; r<nwaitpids; r++)
668d3907fe5SDavid du Colombier if(waitpids[r] != pid)
669d3907fe5SDavid du Colombier waitpids[w++] = waitpids[r];
670d3907fe5SDavid du Colombier nwaitpids = w;
671d3907fe5SDavid du Colombier }
672d3907fe5SDavid du Colombier
673d3907fe5SDavid du Colombier void
clearwaitpids(void)674d3907fe5SDavid du Colombier clearwaitpids(void)
675d3907fe5SDavid du Colombier {
676d3907fe5SDavid du Colombier nwaitpids = 0;
677d3907fe5SDavid du Colombier }
678d3907fe5SDavid du Colombier
679d3907fe5SDavid du Colombier int
havewaitpid(int pid)680d3907fe5SDavid du Colombier havewaitpid(int pid)
681d3907fe5SDavid du Colombier {
682d3907fe5SDavid du Colombier int i;
683d3907fe5SDavid du Colombier
684d3907fe5SDavid du Colombier for(i=0; i<nwaitpids; i++)
685d3907fe5SDavid du Colombier if(waitpids[i] == pid)
686d3907fe5SDavid du Colombier return 1;
687d3907fe5SDavid du Colombier return 0;
688d3907fe5SDavid du Colombier }
689f07722aaSDavid du Colombier
690f07722aaSDavid du Colombier /* avoid loading any floating-point library code */
691f07722aaSDavid du Colombier int
_efgfmt(Fmt *)692f07722aaSDavid du Colombier _efgfmt(Fmt *)
693f07722aaSDavid du Colombier {
694f07722aaSDavid du Colombier return -1;
695f07722aaSDavid du Colombier }
696