|
|
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.