Annotation of lucent/sys/src/cmd/rc/exec.c, revision 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.