Annotation of lucent/sys/src/cmd/rc/exec.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.