|
|
1.1 ! root 1: #include "rc.h" ! 2: #include "getflags.h" ! 3: #include "exec.h" ! 4: #include "io.h" ! 5: #include "fns.h" ! 6: /* ! 7: * Start executing the given code at the given pc with the given redirection ! 8: */ ! 9: void start(code *c, int pc, var *local) ! 10: { ! 11: struct thread *p=new(struct thread); ! 12: p->code=codecopy(c); ! 13: p->pc=pc; ! 14: p->argv=0; ! 15: p->redir=p->startredir=runq?runq->redir:0; ! 16: p->local=local; ! 17: p->cmdfile=0; ! 18: p->cmdfd=0; ! 19: p->eof=0; ! 20: p->iflag=0; ! 21: p->lineno=1; ! 22: p->ret=runq; ! 23: runq=p; ! 24: } ! 25: word *newword(char *wd, word *next) ! 26: { ! 27: word *p=new(word); ! 28: p->word=strdup(wd); ! 29: p->next=next; ! 30: return p; ! 31: } ! 32: void pushword(char *wd) ! 33: { ! 34: if(runq->argv==0) panic("pushword but no argv!", 0); ! 35: runq->argv->words=newword(wd, runq->argv->words); ! 36: } ! 37: void popword(void){ ! 38: word *p; ! 39: if(runq->argv==0) panic("popword but no argv!", 0); ! 40: p=runq->argv->words; ! 41: if(p==0) panic("popword but no word!", 0); ! 42: runq->argv->words=p->next; ! 43: efree(p->word); ! 44: efree((char *)p); ! 45: } ! 46: void freelist(word *w) ! 47: { ! 48: word *nw; ! 49: while(w){ ! 50: nw=w->next; ! 51: efree(w->word); ! 52: efree((char *)w); ! 53: w=nw; ! 54: } ! 55: } ! 56: void pushlist(void){ ! 57: list *p=new(list); ! 58: p->next=runq->argv; ! 59: p->words=0; ! 60: runq->argv=p; ! 61: } ! 62: void poplist(void){ ! 63: list *p=runq->argv; ! 64: if(p==0) panic("poplist but no argv", 0); ! 65: freelist(p->words); ! 66: runq->argv=p->next; ! 67: efree((char *)p); ! 68: } ! 69: int count(word *w) ! 70: { ! 71: int n; ! 72: for(n=0;w;n++) w=w->next; ! 73: return n; ! 74: } ! 75: void pushredir(int type, int from, int to){ ! 76: redir * rp=new(redir); ! 77: rp->type=type; ! 78: rp->from=from; ! 79: rp->to=to; ! 80: rp->next=runq->redir; ! 81: runq->redir=rp; ! 82: } ! 83: var *newvar(char *name, var *next) ! 84: { ! 85: var *v=new(var); ! 86: v->name=name; ! 87: v->val=0; ! 88: v->fn=0; ! 89: v->changed=0; ! 90: v->fnchanged=0; ! 91: v->next=next; ! 92: return v; ! 93: } ! 94: /* ! 95: * get command line flags, initialize keywords & traps. ! 96: * get values from environment. ! 97: * set $pid, $cflag, $* ! 98: * fabricate bootstrap code and start it (*=(argv);. /usr/lib/rcmain $*) ! 99: * start interpreting code ! 100: */ ! 101: main(int argc, char *argv[]) ! 102: { ! 103: code bootstrap[17]; ! 104: char num[12]; ! 105: int i; ! 106: argc=getflags(argc, argv, "srdiIlxepvVc:1[command]", 1); ! 107: if(argc==-1) usage("[file [arg ...]]"); ! 108: if(argc==1 && Isatty(0)) flag['i']=flagset; ! 109: if(argv[0][0]=='-') flag['l']=flagset; ! 110: if(flag['I']) flag['i']=0; ! 111: err=openfd(2); ! 112: kinit(); ! 113: Trapinit(); ! 114: Vinit(); ! 115: itoa(num, mypid=getpid()); ! 116: setvar("pid", newword(num, (word *)0)); ! 117: setvar("cflag", flag['c']?newword(flag['c'][0], (word *)0) ! 118: :(word *)0); ! 119: setvar("rcname", newword(argv[0], (word *)0)); ! 120: i=0; ! 121: bootstrap[i++].i=1; ! 122: bootstrap[i++].f=Xmark; ! 123: bootstrap[i++].f=Xword; ! 124: bootstrap[i++].s="*"; ! 125: bootstrap[i++].f=Xassign; ! 126: bootstrap[i++].f=Xmark; ! 127: bootstrap[i++].f=Xmark; ! 128: bootstrap[i++].f=Xword; ! 129: bootstrap[i++].s="*"; ! 130: bootstrap[i++].f=Xdol; ! 131: bootstrap[i++].f=Xword; ! 132: bootstrap[i++].s=Rcmain; ! 133: bootstrap[i++].f=Xword; ! 134: bootstrap[i++].s="."; ! 135: bootstrap[i++].f=Xsimple; ! 136: bootstrap[i++].f=Xexit; ! 137: bootstrap[i].i=0; ! 138: start(bootstrap, 1, (var *)0); ! 139: /* prime bootstrap argv */ ! 140: pushlist(); ! 141: for(i=argc-1;i!=0;--i) pushword(argv[i]); ! 142: for(;;){ ! 143: if(flag['r']) pfnc(err, runq); ! 144: runq->pc++; ! 145: (*runq->code[runq->pc-1].f)(); ! 146: if(ntrap) dotrap(); ! 147: } ! 148: } ! 149: /* ! 150: * Opcode routines ! 151: * Arguments on stack (...) ! 152: * Arguments in line [...] ! 153: * Code in line with jump around {...} ! 154: * ! 155: * Xappend(file)[fd] open file to append ! 156: * Xassign(name, val) assign val to name ! 157: * Xasync{... Xexit} make thread for {}, no wait ! 158: * Xbackq{... Xreturn} make thread for {}, push stdout ! 159: * Xbang complement condition ! 160: * Xcase(pat, value){...} exec code on match, leave (value) on ! 161: * stack ! 162: * Xclose[i] close file descriptor ! 163: * Xconc(left, right) concatenate, push results ! 164: * Xcount(name) push var count ! 165: * Xdelfn(name) delete function definition ! 166: * Xdeltraps(names) delete named traps ! 167: * Xdol(name) get variable value ! 168: * Xqdol(name) concatenate variable components ! 169: * Xdup[i j] dup file descriptor ! 170: * Xexit rc exits with status ! 171: * Xfalse{...} execute {} if false ! 172: * Xfn(name){... Xreturn} define function ! 173: * Xfor(var, list){... Xreturn} for loop ! 174: * Xjump[addr] goto ! 175: * Xlocal(name, val) create local variable, assign value ! 176: * Xmark mark stack ! 177: * Xmatch(pat, str) match pattern, set status ! 178: * Xpipe[i j]{... Xreturn}{... Xreturn} construct a pipe between 2 new threads, ! 179: * wait for both ! 180: * Xpipefd[type]{... Xreturn} connect {} to pipe (input or output, ! 181: * depending on type), push /dev/fd/?? ! 182: * Xpopm(value) pop value from stack ! 183: * Xread(file)[fd] open file to read ! 184: * Xsettraps(names){... Xreturn} define trap functions ! 185: * Xshowtraps print trap list ! 186: * Xsimple(args) run command and wait ! 187: * Xreturn kill thread ! 188: * Xsubshell{... Xexit} execute {} in a subshell and wait ! 189: * Xtrue{...} execute {} if true ! 190: * Xunlocal delete local variable ! 191: * Xword[string] push string ! 192: * Xwrite(file)[fd] open file to write ! 193: */ ! 194: void Xappend(void){ ! 195: char *file; ! 196: int f; ! 197: switch(count(runq->argv->words)){ ! 198: default: Xerror(">> requires singleton"); return; ! 199: case 0: Xerror(">> requires file"); return; ! 200: case 1: break; ! 201: } ! 202: file=runq->argv->words->word; ! 203: if((f=open(file, 1))<0 && (f=Creat(file))<0){ ! 204: Xperror(file); ! 205: return; ! 206: } ! 207: Seek(f, 0L, 2); ! 208: pushredir(ROPEN, f, runq->code[runq->pc].i); ! 209: runq->pc++; ! 210: poplist(); ! 211: } ! 212: void Xasync(void){ ! 213: int null=open("/dev/null", 0); ! 214: int pid; ! 215: char npid[10]; ! 216: if(null<0){ ! 217: Xperror("/dev/null"); ! 218: return; ! 219: } ! 220: switch(pid=rfork(RFFDG|RFPROC|RFNOTEG)){ ! 221: case -1: ! 222: close(null); ! 223: Xperror("rfork"); ! 224: break; ! 225: case 0: ! 226: pushredir(ROPEN, null, 0); ! 227: start(runq->code, runq->pc+1, runq->local); ! 228: runq->ret=0; ! 229: break; ! 230: default: ! 231: close(null); ! 232: runq->pc=runq->code[runq->pc].i; ! 233: itoa(npid, pid); ! 234: setvar("apid", newword(npid, (word *)0)); ! 235: break; ! 236: } ! 237: } ! 238: void Xsettrue(void){ ! 239: setstatus(""); ! 240: } ! 241: void Xbang(void){ ! 242: setstatus(truestatus()?"false":""); ! 243: } ! 244: void Xclose(void){ ! 245: pushredir(RCLOSE, runq->code[runq->pc].i, 0); ! 246: runq->pc++; ! 247: } ! 248: void Xdup(void){ ! 249: pushredir(RDUP, runq->code[runq->pc].i, runq->code[runq->pc+1].i); ! 250: runq->pc+=2; ! 251: } ! 252: void Xeflag(void){ ! 253: if(eflagok && !truestatus()) Xexit(); ! 254: } ! 255: void Xexit(void){ ! 256: struct var *trapreq; ! 257: struct word *starval; ! 258: static int beenhere=0; ! 259: if(getpid()==mypid && !beenhere){ ! 260: trapreq=vlook("sigexit"); ! 261: if(trapreq->fn){ ! 262: beenhere=1; ! 263: --runq->pc; ! 264: starval=vlook("*")->val; ! 265: start(trapreq->fn, trapreq->pc, (struct var *)0); ! 266: runq->local=newvar(strdup("*"), runq->local); ! 267: runq->local->val=copywords(starval, (struct word *)0); ! 268: runq->local->changed=1; ! 269: runq->redir=runq->startredir=0; ! 270: return; ! 271: } ! 272: } ! 273: Exit(getstatus()); ! 274: } ! 275: void Xfalse(void){ ! 276: if(truestatus()) runq->pc=runq->code[runq->pc].i; ! 277: else runq->pc++; ! 278: } ! 279: int ifnot; /* dynamic if not flag */ ! 280: void Xifnot(void){ ! 281: if(ifnot) ! 282: runq->pc++; ! 283: else ! 284: runq->pc=runq->code[runq->pc].i; ! 285: } ! 286: void Xjump(void){ ! 287: runq->pc=runq->code[runq->pc].i; ! 288: } ! 289: void Xmark(void){ ! 290: pushlist(); ! 291: } ! 292: void Xpopm(void){ ! 293: poplist(); ! 294: } ! 295: void Xread(void){ ! 296: char *file; ! 297: int f; ! 298: switch(count(runq->argv->words)){ ! 299: default: Xerror("< requires singleton\n"); return; ! 300: case 0: Xerror("< requires file\n"); return; ! 301: case 1: break; ! 302: } ! 303: file=runq->argv->words->word; ! 304: if((f=open(file, 0))<0){ ! 305: Xperror(file); ! 306: return; ! 307: } ! 308: pushredir(ROPEN, f, runq->code[runq->pc].i); ! 309: runq->pc++; ! 310: poplist(); ! 311: } ! 312: void turfredir(void){ ! 313: while(runq->redir!=runq->startredir) ! 314: Xpopredir(); ! 315: } ! 316: void Xpopredir(void){ ! 317: struct redir *rp=runq->redir; ! 318: if(rp==0) panic("turfredir null!", 0); ! 319: runq->redir=rp->next; ! 320: if(rp->type==ROPEN) close(rp->from); ! 321: efree((char *)rp); ! 322: } ! 323: void Xreturn(void){ ! 324: struct thread *p=runq; ! 325: turfredir(); ! 326: while(p->argv) poplist(); ! 327: codefree(p->code); ! 328: runq=p->ret; ! 329: efree((char *)p); ! 330: if(runq==0) Exit(getstatus()); ! 331: } ! 332: void Xtrue(void){ ! 333: if(truestatus()) runq->pc++; ! 334: else runq->pc=runq->code[runq->pc].i; ! 335: } ! 336: void Xif(void){ ! 337: ifnot=1; ! 338: if(truestatus()) runq->pc++; ! 339: else runq->pc=runq->code[runq->pc].i; ! 340: } ! 341: void Xwastrue(void){ ! 342: ifnot=0; ! 343: } ! 344: void Xword(void){ ! 345: pushword(runq->code[runq->pc++].s); ! 346: } ! 347: void Xwrite(void){ ! 348: char *file; ! 349: int f; ! 350: switch(count(runq->argv->words)){ ! 351: default: Xerror("> requires singleton\n"); return; ! 352: case 0: Xerror("> requires file\n"); return; ! 353: case 1: break; ! 354: } ! 355: file=runq->argv->words->word; ! 356: if((f=Creat(file))<0){ ! 357: Xperror(file); ! 358: return; ! 359: } ! 360: pushredir(ROPEN, f, runq->code[runq->pc].i); ! 361: runq->pc++; ! 362: poplist(); ! 363: } ! 364: char *list2str(word *words){ ! 365: char *value, *s, *t; ! 366: int len=0; ! 367: word *ap; ! 368: for(ap=words;ap;ap=ap->next) ! 369: len+=1+strlen(ap->word); ! 370: value=emalloc(len+1); ! 371: s=value; ! 372: for(ap=words;ap;ap=ap->next){ ! 373: for(t=ap->word;*t;) *s++=*t++; ! 374: *s++=' '; ! 375: } ! 376: if(s==value) *s='\0'; ! 377: else s[-1]='\0'; ! 378: return value; ! 379: } ! 380: void Xmatch(void){ ! 381: word *p; ! 382: char *subject; ! 383: subject=list2str(runq->argv->words); ! 384: setstatus("no match"); ! 385: for(p=runq->argv->next->words;p;p=p->next) ! 386: if(match(subject, p->word, '\0')){ ! 387: setstatus(""); ! 388: break; ! 389: } ! 390: efree(subject); ! 391: poplist(); ! 392: poplist(); ! 393: } ! 394: void Xcase(void){ ! 395: word *p; ! 396: char *s; ! 397: int ok=0; ! 398: s=list2str(runq->argv->next->words); ! 399: for(p=runq->argv->words;p;p=p->next){ ! 400: if(match(s, p->word, '\0')){ ! 401: ok=1; ! 402: break; ! 403: } ! 404: } ! 405: efree(s); ! 406: if(ok) ! 407: runq->pc++; ! 408: else ! 409: runq->pc=runq->code[runq->pc].i; ! 410: poplist(); ! 411: } ! 412: word *conclist(word *lp, word *rp, word *tail) ! 413: { ! 414: char *buf; ! 415: word *v; ! 416: if(lp->next || rp->next) ! 417: tail=conclist(lp->next==0?lp:lp->next, rp->next==0?rp:rp->next, ! 418: tail); ! 419: buf=emalloc(strlen(lp->word)+strlen(rp->word)+1); ! 420: strcpy(buf, lp->word); ! 421: strcat(buf, rp->word); ! 422: v=newword(buf, tail); ! 423: efree(buf); ! 424: return v; ! 425: } ! 426: void Xconc(void){ ! 427: word *lp=runq->argv->words; ! 428: word *rp=runq->argv->next->words; ! 429: word *vp=runq->argv->next->next->words; ! 430: int lc=count(lp), rc=count(rp); ! 431: if(lc!=0 || rc!=0){ ! 432: if(lc==0 || rc==0){ ! 433: Xerror("null list in concatenation"); ! 434: return; ! 435: } ! 436: if(lc!=1 && rc!=1 && lc!=rc){ ! 437: Xerror("mismatched list lengths in concatenation"); ! 438: return; ! 439: } ! 440: vp=conclist(lp, rp, vp); ! 441: } ! 442: poplist(); ! 443: poplist(); ! 444: runq->argv->words=vp; ! 445: } ! 446: void Xassign(void){ ! 447: var *v; ! 448: if(count(runq->argv->words)!=1){ ! 449: Xerror("variable name not singleton!"); ! 450: return; ! 451: } ! 452: deglob(runq->argv->words->word); ! 453: v=vlook(runq->argv->words->word); ! 454: poplist(); ! 455: globlist(); ! 456: freewords(v->val); ! 457: v->val=runq->argv->words; ! 458: v->changed=1; ! 459: runq->argv->words=0; ! 460: poplist(); ! 461: } ! 462: /* ! 463: * copy arglist a, adding the copy to the front of tail ! 464: */ ! 465: word *copywords(word *a, word *tail) ! 466: { ! 467: word *v=0, **end; ! 468: for(end=&v;a;a=a->next,end=&(*end)->next) ! 469: *end=newword(a->word, 0); ! 470: *end=tail; ! 471: return v; ! 472: } ! 473: void Xdol(void){ ! 474: word *a, *star; ! 475: char *s, *t; ! 476: int n; ! 477: if(count(runq->argv->words)!=1){ ! 478: Xerror("variable name not singleton!"); ! 479: return; ! 480: } ! 481: s=runq->argv->words->word; ! 482: deglob(s); ! 483: n=0; ! 484: for(t=s;'0'<=*t && *t<='9';t++) n=n*10+*t-'0'; ! 485: a=runq->argv->next->words; ! 486: if(n==0 || *t) ! 487: a=copywords(vlook(s)->val, a); ! 488: else{ ! 489: star=vlook("*")->val; ! 490: if(star && 1<=n && n<=count(star)){ ! 491: while(--n) star=star->next; ! 492: a=newword(star->word, a); ! 493: } ! 494: } ! 495: poplist(); ! 496: runq->argv->words=a; ! 497: } ! 498: void Xqdol(void){ ! 499: word *a, *p; ! 500: char *s; ! 501: int n; ! 502: if(count(runq->argv->words)!=1){ ! 503: Xerror("variable name not singleton!"); ! 504: return; ! 505: } ! 506: s=runq->argv->words->word; ! 507: deglob(s); ! 508: a=vlook(s)->val; ! 509: poplist(); ! 510: n=count(a); ! 511: if(n==0){ ! 512: pushword(""); ! 513: return; ! 514: } ! 515: for(p=a;p;p=p->next) n+=strlen(p->word); ! 516: s=emalloc(n); ! 517: if(a){ ! 518: strcpy(s, a->word); ! 519: for(p=a->next;p;p=p->next){ ! 520: strcat(s, " "); ! 521: strcat(s, p->word); ! 522: } ! 523: } ! 524: else ! 525: s[0]='\0'; ! 526: pushword(s); ! 527: efree(s); ! 528: } ! 529: word *subwords(word *val, int len, word *sub, word *a) ! 530: { ! 531: int n; ! 532: char *s; ! 533: if(!sub) return a; ! 534: a=subwords(val, len, sub->next, a); ! 535: s=sub->word; ! 536: deglob(s); ! 537: n=0; ! 538: while('0'<=*s && *s<='9') n=n*10+ *s++ -'0'; ! 539: if(n<1 || len<n) return a; ! 540: for(;n!=1;--n) val=val->next; ! 541: return newword(val->word, a); ! 542: } ! 543: void Xsub(void){ ! 544: word *a, *v; ! 545: char *s; ! 546: if(count(runq->argv->next->words)!=1){ ! 547: Xerror("variable name not singleton!"); ! 548: return; ! 549: } ! 550: s=runq->argv->next->words->word; ! 551: deglob(s); ! 552: a=runq->argv->next->next->words; ! 553: v=vlook(s)->val; ! 554: a=subwords(v, count(v), runq->argv->words, a); ! 555: poplist(); ! 556: poplist(); ! 557: runq->argv->words=a; ! 558: } ! 559: void Xcount(void){ ! 560: word *a; ! 561: char *s, *t; ! 562: int n; ! 563: char num[12]; ! 564: if(count(runq->argv->words)!=1){ ! 565: Xerror("variable name not singleton!"); ! 566: return; ! 567: } ! 568: s=runq->argv->words->word; ! 569: deglob(s); ! 570: n=0; ! 571: for(t=s;'0'<=*t && *t<='9';t++) n=n*10+*t-'0'; ! 572: if(n==0 || *t){ ! 573: a=vlook(s)->val; ! 574: itoa(num, count(a)); ! 575: } ! 576: else{ ! 577: a=vlook("*")->val; ! 578: itoa(num, a && 1<=n && n<=count(a)?1:0); ! 579: } ! 580: poplist(); ! 581: pushword(num); ! 582: } ! 583: void Xlocal(void){ ! 584: if(count(runq->argv->words)!=1){ ! 585: Xerror("variable name must be singleton\n"); ! 586: return; ! 587: } ! 588: deglob(runq->argv->words->word); ! 589: runq->local=newvar(strdup(runq->argv->words->word), runq->local); ! 590: runq->local->val=copywords(runq->argv->next->words, (word *)0); ! 591: runq->local->changed=1; ! 592: poplist(); ! 593: poplist(); ! 594: } ! 595: void Xunlocal(void){ ! 596: var *v=runq->local, *hid; ! 597: if(v==0) panic("Xunlocal: no locals!", 0); ! 598: runq->local=v->next; ! 599: hid=vlook(v->name); ! 600: hid->changed=1; ! 601: efree(v->name); ! 602: freewords(v->val); ! 603: efree((char *)v); ! 604: } ! 605: void freewords(word *w) ! 606: { ! 607: word *nw; ! 608: while(w){ ! 609: efree(w->word); ! 610: nw=w->next; ! 611: efree((char *)w); ! 612: w=nw; ! 613: } ! 614: } ! 615: void Xfn(void){ ! 616: var *v; ! 617: word *a; ! 618: int end; ! 619: end=runq->code[runq->pc].i; ! 620: for(a=runq->argv->words;a;a=a->next){ ! 621: v=gvlook(a->word); ! 622: if(v->fn) codefree(v->fn); ! 623: v->fn=codecopy(runq->code); ! 624: v->pc=runq->pc+2; ! 625: v->fnchanged=1; ! 626: } ! 627: runq->pc=end; ! 628: poplist(); ! 629: } ! 630: void Xdelfn(void){ ! 631: var *v; ! 632: word *a; ! 633: for(a=runq->argv->words;a;a=a->next){ ! 634: v=gvlook(a->word); ! 635: if(v->fn) codefree(v->fn); ! 636: v->fn=0; ! 637: v->fnchanged=1; ! 638: } ! 639: poplist(); ! 640: } ! 641: void Xpipe(void){ ! 642: struct thread *p=runq; ! 643: int pc=p->pc, forkid; ! 644: int lfd=p->code[pc++].i; ! 645: int rfd=p->code[pc++].i; ! 646: int pfd[2]; ! 647: if(pipe(pfd)<0){ ! 648: Xperror("can't get pipe"); ! 649: return; ! 650: } ! 651: switch(forkid=fork()){ ! 652: case -1: ! 653: Xperror("can't fork"); ! 654: break; ! 655: case 0: ! 656: start(p->code, pc+2, runq->local); ! 657: runq->ret=0; ! 658: close(pfd[PRD]); ! 659: pushredir(ROPEN, pfd[PWR], lfd); ! 660: break; ! 661: default: ! 662: start(p->code, p->code[pc].i, runq->local); ! 663: close(pfd[PWR]); ! 664: pushredir(ROPEN, pfd[PRD], rfd); ! 665: p->pc=p->code[pc+1].i; ! 666: p->pid=forkid; ! 667: break; ! 668: } ! 669: } ! 670: char *concstatus(char *s, char *t) ! 671: { ! 672: static char v[NSTATUS+1]; ! 673: int n=strlen(s); ! 674: strncpy(v, s, NSTATUS); ! 675: if(n<NSTATUS){ ! 676: v[n]='|'; ! 677: strncpy(v+n+1, t, NSTATUS-n-1); ! 678: } ! 679: v[NSTATUS]='\0'; ! 680: return v; ! 681: } ! 682: void Xpipewait(void){ ! 683: char status[NSTATUS+1]; ! 684: if(runq->pid==-1) ! 685: setstatus(concstatus(runq->status, getstatus())); ! 686: else{ ! 687: strncpy(status, getstatus(), NSTATUS); ! 688: status[NSTATUS]='\0'; ! 689: Waitfor(runq->pid, 1); ! 690: runq->pid=-1; ! 691: setstatus(concstatus(getstatus(), status)); ! 692: } ! 693: } ! 694: void Xrdcmds(void){ ! 695: struct thread *p=runq; ! 696: word *prompt; ! 697: flush(err); ! 698: nerror=0; ! 699: if(flag['s'] && !truestatus()) ! 700: pfmt(err, "status=%v\n", vlook("status")->val); ! 701: if(runq->iflag){ ! 702: prompt=vlook("prompt")->val; ! 703: if(prompt) ! 704: promptstr=prompt->word; ! 705: else ! 706: promptstr="% "; ! 707: } ! 708: Noerror(); ! 709: if(yyparse()){ ! 710: if(!p->iflag || p->eof && !Eintr()){ ! 711: if(p->cmdfile) efree(p->cmdfile); ! 712: closeio(p->cmdfd); ! 713: Xreturn(); /* should this be omitted? */ ! 714: } ! 715: else{ ! 716: if(Eintr()){ ! 717: pchr(err, '\n'); ! 718: p->eof=0; ! 719: } ! 720: --p->pc; /* go back for next command */ ! 721: } ! 722: } ! 723: else{ ! 724: --p->pc; /* re-execute Xrdcmds after codebuf runs */ ! 725: start(codebuf, 1, runq->local); ! 726: } ! 727: freenodes(); ! 728: } ! 729: void Xerror(char *s) ! 730: { ! 731: pfmt(err, "rc: %s\n", s); ! 732: flush(err); ! 733: while(!runq->iflag) Xreturn(); ! 734: } ! 735: void Xperror(char *s) ! 736: { ! 737: pfmt(err, "rc: %s: %s\n", s, Geterrstr()); ! 738: flush(err); ! 739: while(!runq->iflag) Xreturn(); ! 740: } ! 741: void Xbackq(void){ ! 742: char wd[8193]; ! 743: int c; ! 744: char *s, *ewd=&wd[8192], *stop; ! 745: struct io *f; ! 746: var *ifs=vlook("ifs"); ! 747: word *v, *nextv; ! 748: int pfd[2]; ! 749: int pid; ! 750: stop=ifs->val?ifs->val->word:""; ! 751: if(pipe(pfd)<0){ ! 752: Xerror("can't make pipe"); ! 753: return; ! 754: } ! 755: switch(pid=fork()){ ! 756: case -1: Xerror("try again"); ! 757: close(pfd[PRD]); ! 758: close(pfd[PWR]); ! 759: return; ! 760: case 0: ! 761: close(pfd[PRD]); ! 762: start(runq->code, runq->pc+1, runq->local); ! 763: pushredir(ROPEN, pfd[PWR], 1); ! 764: return; ! 765: default: ! 766: close(pfd[PWR]); ! 767: f=openfd(pfd[PRD]); ! 768: s=wd; ! 769: v=0; ! 770: while((c=rchr(f))!=EOF){ ! 771: if(strchr(stop, c) || s==ewd){ ! 772: if(s!=wd){ ! 773: *s='\0'; ! 774: v=newword(wd, v); ! 775: s=wd; ! 776: } ! 777: } ! 778: else *s++=c; ! 779: } ! 780: if(s!=wd){ ! 781: *s='\0'; ! 782: v=newword(wd, v); ! 783: } ! 784: closeio(f); ! 785: Waitfor(pid, 0); ! 786: /* v points to reversed arglist -- reverse it onto argv */ ! 787: while(v){ ! 788: nextv=v->next; ! 789: v->next=runq->argv->words; ! 790: runq->argv->words=v; ! 791: v=nextv; ! 792: } ! 793: runq->pc=runq->code[runq->pc].i; ! 794: return; ! 795: } ! 796: } ! 797: /* ! 798: * Who should wait for the exit from the fork? ! 799: */ ! 800: void Xpipefd(void){ ! 801: struct thread *p=runq; ! 802: int pc=p->pc; ! 803: char name[40]; ! 804: int pfd[2]; ! 805: int sidefd, mainfd; ! 806: if(pipe(pfd)<0){ ! 807: Xerror("can't get pipe"); ! 808: return; ! 809: } ! 810: if(p->code[pc].i==READ){ ! 811: sidefd=pfd[PWR]; ! 812: mainfd=pfd[PRD]; ! 813: } ! 814: else{ ! 815: sidefd=pfd[PRD]; ! 816: mainfd=pfd[PWR]; ! 817: } ! 818: switch(fork()){ ! 819: case -1: ! 820: Xerror("try again"); ! 821: break; ! 822: case 0: ! 823: start(p->code, pc+2, runq->local); ! 824: close(mainfd); ! 825: pushredir(ROPEN, sidefd, p->code[pc].i==READ?1:0); ! 826: runq->ret=0; ! 827: break; ! 828: default: ! 829: close(sidefd); ! 830: pushredir(ROPEN, mainfd, mainfd); /* isn't this a noop? */ ! 831: strcpy(name, Fdprefix); ! 832: itoa(name+strlen(name), mainfd); ! 833: pushword(name); ! 834: p->pc=p->code[pc+1].i; ! 835: break; ! 836: } ! 837: } ! 838: void Xsubshell(void){ ! 839: int pid; ! 840: switch(pid=fork()){ ! 841: case -1: ! 842: Xerror("try again"); ! 843: break; ! 844: case 0: ! 845: start(runq->code, runq->pc+1, runq->local); ! 846: runq->ret=0; ! 847: break; ! 848: default: ! 849: Waitfor(pid, 1); ! 850: runq->pc=runq->code[runq->pc].i; ! 851: break; ! 852: } ! 853: } ! 854: void setstatus(char *s) ! 855: { ! 856: setvar("status", newword(s, (word *)0)); ! 857: } ! 858: char *getstatus(void){ ! 859: var *status=vlook("status"); ! 860: return status->val?status->val->word:""; ! 861: } ! 862: int truestatus(void){ ! 863: char *s; ! 864: for(s=getstatus();*s;s++) ! 865: if(*s!='|' && *s!='0') return 0; ! 866: return 1; ! 867: } ! 868: void Xdelhere(void){ ! 869: Unlink(runq->code[runq->pc++].s); ! 870: } ! 871: void Xfor(void){ ! 872: if(runq->argv->words==0){ ! 873: poplist(); ! 874: runq->pc=runq->code[runq->pc].i; ! 875: } ! 876: else{ ! 877: freelist(runq->local->val); ! 878: runq->local->val=runq->argv->words; ! 879: runq->local->changed=1; ! 880: runq->argv->words=runq->argv->words->next; ! 881: runq->local->val->next=0; ! 882: runq->pc++; ! 883: } ! 884: } ! 885: void Xglob(void){ ! 886: globlist(); ! 887: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.