|
|
1.1 root 1: /*
2: * Plan 9 versions of system-specific functions
3: * By convention, exported routines herein have names beginning with an
4: * upper case letter.
5: */
6: #include "rc.h"
7: #include "exec.h"
8: #include "io.h"
9: #include "fns.h"
10: #include "getflags.h"
11: char *Signame[]={
12: "sigexit", "sighup", "sigint", "sigquit",
13: "sigalrm", "sigkill", "sigfpe", "sigterm",
14: 0
15: };
16: char *syssigname[]={
17: "exit", /* can't happen */
18: "hangup",
19: "interrupt",
20: "quit", /* can't happen */
21: "alarm",
22: "kill",
23: "sys: fp: ",
24: "term",
25: 0
26: };
27: char Rcmain[]="/rc/lib/rcmain";
28: char Fdprefix[]="/fd/";
29: void execfinit(void);
30: void execbind(void);
31: void execmount(void);
32: void execnewpgrp(void);
33: builtin Builtin[]={
34: "cd", execcd,
35: "whatis", execwhatis,
36: "eval", execeval,
37: "exec", execexec, /* but with popword first */
38: "exit", execexit,
39: "shift", execshift,
40: "wait", execwait,
41: ".", execdot,
42: "finit", execfinit,
43: "flag", execflag,
44: "rfork", execnewpgrp,
45: 0
46: };
47: void execnewpgrp(void){
48: int arg;
49: char *s;
50: switch(count(runq->argv->words)){
51: case 1: arg=RFENVG|RFNAMEG|RFNOTEG; break;
52: case 2:
53: arg=0;
54: for(s=runq->argv->words->next->word;*s;s++) switch(*s){
55: default:
56: goto Usage;
57: case 'n': arg|=RFNAMEG; break;
58: case 'N': arg|=RFCNAMEG; break;
59: case 'e': arg|=RFENVG; break;
60: case 'E': arg|=RFCENVG; break;
61: case 's': arg|=RFNOTEG; break;
62: case 'f': arg|=RFFDG; break;
63: case 'F': arg|=RFCFDG; break;
64: }
65: break;
66: default:
67: Usage:
68: pfmt(err, "Usage: %s [fnesFNE]\n", runq->argv->words->word);
69: setstatus("rfork usage");
70: poplist();
71: return;
72: }
73: if(rfork(arg)==-1){
74: pfmt(err, "rc: %s failed\n", runq->argv->words->word);
75: setstatus("rfork failed");
76: }
77: else
78: setstatus("");
79: poplist();
80: }
81: void Vinit(void){
82: int dir=open("#e", 0), f, len;
83: word *val;
84: char *buf, *s;
85: Dir ent;
86: char envname[NAMELEN+6];
87: if(dir<0){
88: pfmt(err, "rc: can't open #e\n");
89: return;
90: }
91: while(dirread(dir, &ent, sizeof ent)==sizeof ent){
92: len=ent.length;
93: if(len && strncmp(ent.name, "fn#", 3)!=0){
94: strcpy(envname, "#e/");
95: strcat(envname, ent.name);
96: if((f=open(envname, 0))>=0){
97: buf=emalloc((int)len+1);
98: read(f, buf, (long)len);
99: val=0;
100: /* Charitably add a 0 at the end if need be */
101: if(buf[len-1]) buf[len++]='\0';
102: s=buf+len-1;
103: for(;;){
104: while(s!=buf && s[-1]!='\0') --s;
105: val=newword(s, val);
106: if(s==buf) break;
107: --s;
108: }
109: setvar(ent.name, val);
110: vlook(ent.name)->changed=0;
111: close(f);
112: efree(buf);
113: }
114: }
115: }
116: close(dir);
117: }
118: #ifdef old_execfinit
119: void Xrdfn(void){}
120: void execfinit(void){
121: Xpopm();
122: }
123: #else
124: int envdir;
125: void Xrdfn(void){
126: int f, len;
127: Dir ent;
128: char envname[NAMELEN+6];
129: while(dirread(envdir, &ent, sizeof ent)==sizeof ent){
130: len=ent.length;
131: if(len && strncmp(ent.name, "fn#", 3)==0){
132: strcpy(envname, "#e/");
133: strcat(envname, ent.name);
134: if((f=open(envname, 0))>=0){
135: execcmds(openfd(f));
136: return;
137: }
138: }
139: }
140: close(envdir);
141: Xreturn();
142: }
143: union code rdfns[4];
144: void execfinit(void){
145: static int first=1;
146: if(first){
147: rdfns[0].i=1;
148: rdfns[1].f=Xrdfn;
149: rdfns[2].f=Xjump;
150: rdfns[3].i=1;
151: first=0;
152: }
153: Xpopm();
154: envdir=open("#e", 0);
155: if(envdir<0){
156: pfmt(err, "rc: can't open #e\n");
157: return;
158: }
159: start(rdfns, 1, runq->local);
160: }
161: #endif
162: int Waitfor(int pid, int persist){
163: thread *p;
164: Waitmsg w;
165: int cpid;
166: char errbuf[ERRLEN];
167: while((cpid=wait(&w))>=0){
168: if(pid==cpid){
169: setstatus(w.msg);
170: return 0;
171: }
172: for(p=runq->ret;p;p=p->ret)
173: if(p->pid==cpid){
174: p->pid=-1;
175: strcpy(p->status, w.msg);
176: }
177: }
178: errstr(errbuf);
179: if(strcmp(errbuf, "interrupted")==0) return -1;
180: return 0;
181: }
182: char **mkargv(word *a)
183: {
184: char **argv=(char **)emalloc((count(a)+2)*sizeof(char *));
185: char **argp=argv+1; /* leave one at front for runcoms */
186: for(;a;a=a->next) *argp++=a->word;
187: *argp=0;
188: return argv;
189: }
190: void addenv(var *v)
191: {
192: char envname[NAMELEN+9];
193: word *w;
194: int f;
195: io *fd;
196: if(v->changed){
197: v->changed=0;
198: strcpy(envname, "#e/");
199: strcat(envname, v->name);
200: if((f=Creat(envname))<0)
201: pfmt(err, "rc: can't open %s\n", envname);
202: else{
203: for(w=v->val;w;w=w->next)
204: write(f, w->word, strlen(w->word)+1L);
205: close(f);
206: }
207: }
208: if(v->fnchanged){
209: v->fnchanged=0;
210: strcpy(envname, "#e/fn#");
211: strcat(envname, v->name);
212: if((f=Creat(envname))<0)
213: pfmt(err, "rc: can't open %s\n", envname);
214: else{
215: if(v->fn){
216: fd=openfd(f);
217: pfmt(fd, "fn %s %s\n", v->name, v->fn[v->pc-1].s);
218: closeio(fd);
219: }
220: close(f);
221: }
222: }
223: }
224: void updenvlocal(var *v)
225: {
226: if(v){
227: updenvlocal(v->next);
228: addenv(v);
229: }
230: }
231: void Updenv(void){
232: var *v, **h;
233: for(h=gvar;h!=&gvar[NVAR];h++)
234: for(v=*h;v;v=v->next)
235: addenv(v);
236: if(runq) updenvlocal(runq->local);
237: }
238: void Execute(word *args, word *path)
239: {
240: char **argv=mkargv(args);
241: char file[1024];
242: int nc;
243: Updenv();
244: for(;path;path=path->next){
245: nc=strlen(path->word);
246: if(nc<1024){
247: strcpy(file, path->word);
248: if(file[0]){
249: strcat(file, "/");
250: nc++;
251: }
252: if(nc+strlen(argv[1])<1024){
253: strcat(file, argv[1]);
254: exec(file, argv+1);
255: }
256: else werrstr("command name too long");
257: }
258: }
259: errstr(file);
260: pfmt(err, "%s: %s\n", argv[1], file);
261: efree((char *)argv);
262: }
263: int Globsize(char *p)
264: {
265: ulong isglob=0, globlen=NAMELEN+1;
266: for(;*p;p++){
267: if(*p==GLOB){
268: p++;
269: if(*p!=GLOB) isglob++;
270: globlen+=*p=='*'?NAMELEN:1;
271: }
272: else
273: globlen++;
274: }
275: return isglob?globlen:0;
276: }
277: #define NFD 50
278: #define NDBUF 32
279: struct{
280: char *buf;
281: int n;
282: }dir[NFD];
283: int Opendir(char *name)
284: {
285: Dir db;
286: int f;
287: f=open(name, 0);
288: if(f==-1)
289: return f;
290: if(dirfstat(f, &db)!=-1 && (db.mode&0x80000000)){
291: if(f<NFD && dir[f].buf){
292: free(dir[f].buf);
293: dir[f].buf=0;
294: }
295: return f;
296: }
297: close(f);
298: return -1;
299: }
300: int Readdir(int f, char *p)
301: {
302: char dirent[DIRLEN];
303: int n;
304: if(f<0 || f>=NFD){
305: slow:
306: while(read(f, dirent, sizeof dirent)==sizeof dirent){
307: strcpy(p, dirent);
308: return 1;
309: }
310: return 0;
311: }
312: if(dir[f].buf==0){ /* allocate */
313: dir[f].buf=malloc(NDBUF*DIRLEN);
314: if(dir[f].buf==0)
315: goto slow;
316: dir[f].n=0;
317: }
318: if(dir[f].n==0){ /* read */
319: memset(dir[f].buf, 0, NDBUF*DIRLEN);
320: n = read(f, dir[f].buf, NDBUF*DIRLEN);
321: if(n>0 && n<NDBUF*DIRLEN){
322: memmove(dir[f].buf+NDBUF*DIRLEN-n, dir[f].buf, n);
323: dir[f].n=NDBUF-n/DIRLEN;
324: }else
325: dir[f].n=0;
326: }
327: if(dir[f].buf[dir[f].n*DIRLEN]==0)
328: return 0;
329: strcpy(p, &dir[f].buf[dir[f].n*DIRLEN]);
330: dir[f].n++;
331: if(dir[f].n==NDBUF)
332: dir[f].n=0;
333: return 1;
334: }
335: void Closedir(int f){
336: if(f>=0 && f<NFD && dir[f].buf){
337: free(dir[f].buf);
338: dir[f].buf=0;
339: }
340: close(f);
341: }
342: int interrupted = 0;
343: void
344: notifyf(void *a, char *s)
345: {
346: int i;
347: for(i=0;syssigname[i];i++) if(strncmp(s, syssigname[i], strlen(syssigname[i]))==0){
348: if(strncmp(s, "sys: ", 5)!=0) interrupted=1;
349: goto Out;
350: }
351: pfmt(err, "rc: note: %s\n", s);
352: noted(NDFLT);
353: return;
354: Out:
355: if(strcmp(s, "interrupt")!=0 || trap[i]==0){
356: trap[i]++;
357: ntrap++;
358: }
359: if(ntrap>=32){ /* rc is probably in a trap loop */
360: pfmt(err, "rc: Too many traps (trap %s), aborting\n", s);
361: abort();
362: }
363: noted(NCONT);
364: }
365: void Trapinit(void){
366: notify(notifyf);
367: }
368: void Unlink(char *name)
369: {
370: remove(name);
371: }
372: long Write(int fd, char *buf, long cnt)
373: {
374: return write(fd, buf, (long)cnt);
375: }
376: long Read(int fd, char *buf, long cnt)
377: {
378: int n;
379:
380: return read(fd, buf, cnt);
381: }
382: long Seek(int fd, long cnt, int whence)
383: {
384: return seek(fd, cnt, whence);
385: }
386: int Executable(char *file)
387: {
388: Dir statbuf;
389:
390: return dirstat(file, &statbuf)!=-1 && (statbuf.mode&0111)!=0 && (statbuf.mode&CHDIR)==0;
391: }
392: int Creat(char *file)
393: {
394: return create(file, 1, 0666L);
395: }
396: int Dup(int a, int b){
397: return dup(a, b);
398: }
399: int Dup1(int a){
400: return -1;
401: }
402: void Exit(char *stat)
403: {
404: Updenv();
405: setstatus(stat);
406: exits(truestatus()?"":getstatus());
407: }
408: int Eintr(void){
409: return interrupted;
410: }
411: void Noerror(void){
412: interrupted=0;
413: }
414: int Isatty(int fd){
415: Dir d1, d2;
416:
417: if(dirfstat(0, &d1)==-1) return 0;
418: if(strncmp(d1.name, "ptty", 4)==0) return 1; /* fwd complaints to philw */
419: if(dirstat("/dev/cons", &d2)==-1) return 0;
420: return d1.type==d2.type&&d1.dev==d2.dev&&d1.qid.path==d2.qid.path;
421: }
422: void Abort(void){
423: pfmt(err, "aborting\n");
424: flush(err);
425: Exit("aborting");
426: }
427: void Memcpy(char *a, char *b, long n)
428: {
429: memmove(a, b, (long)n);
430: }
431: void *Malloc(ulong n){
432: return malloc(n);
433: }
434: char *Geterrstr(void){
435: static char error[ERRLEN];
436: error[0]='\0';
437: errstr(error);
438: return error;
439: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.