Annotation of researchv10dc/630/src/mux.c, revision 1.1

1.1     ! root        1: #if    TRACING | PSTATISTICS
        !             2: #include <stdio.h>
        !             3: #endif
        !             4: 
        !             5: #include <sys/param.h>
        !             6: #include <sys/types.h>
        !             7: #include <sys/stream.h>
        !             8: #include <sys/ttyio.h>
        !             9: #include <sys/filio.h>
        !            10: #include <signal.h>
        !            11: #include <errno.h>
        !            12: #include <jioctl.h>
        !            13: #include <tty.h>
        !            14: 
        !            15: #include "msgs.h"
        !            16: #include "pconfig.h"
        !            17: #include "proto.h"
        !            18: #include "packets.h"
        !            19: #include "pstats.h"
        !            20: 
        !            21: /*
        !            22:  *     One layer structure per file-descriptor
        !            23:  */
        !            24: struct layer {
        !            25:        char            chan;           /* jerq protocol channel */
        !            26:        char            busy;
        !            27:        char            dx, dy;         /* Window size in characters */
        !            28:        short           bitsx, bitsy;   /* Window size in bits */
        !            29:        int             more;
        !            30:        struct ttychars ttychars;
        !            31:        char            bchan;          /* holding area for blocked data */
        !            32:        char            bcount;
        !            33:        char            bbuf[MAXPKTDSIZE];
        !            34: };
        !            35: 
        !            36: #define        NLAYERS 16              /* Same as in jerq itself */
        !            37: #define        NSELFD  20              /* Maximum file descriptors for 'select' */
        !            38: #define        SELTIMO (1000*3)        /* 'select' timeout in millisecs */
        !            39: #define        CDSIZE  (sizeof(struct sgttyb)-1)
        !            40: 
        !            41: char           *jerqprog;
        !            42: char           *jerqstart;
        !            43: char           *progname;
        !            44: char           *shell;
        !            45: int            quitflag;
        !            46: fd_set         rdfd;
        !            47: int            enabled=1;
        !            48: int            blocked=0;
        !            49: struct layer   layer[NSELFD];
        !            50: char           buf[MAXPKTDSIZE+MSGHLEN];
        !            51: struct sgttyb  sttymodes;
        !            52: struct sgttyb  sttysave;
        !            53: struct ttydevb devmodes;
        !            54: struct ttydevb devsave;
        !            55: struct tchars  tcharssave;
        !            56: struct ttychars        ttychars;
        !            57: struct ttychars zerochars;
        !            58: short          booted;
        !            59: extern int     receive();
        !            60: extern int     creceive();
        !            61: void           dosig();
        !            62: int            twrite();
        !            63: void           wrmesgb();
        !            64: extern char    *sys_errlist[];
        !            65: extern char    *getenv();
        !            66: extern char    *itoa();
        !            67: extern char    *strcpy();
        !            68: extern char    *strcat();
        !            69: extern int     tty_ld;
        !            70: extern int     mesg_ld;
        !            71: extern int     errno;
        !            72: extern int     sys_nerr;
        !            73: extern int     strlen();
        !            74: extern int     write();
        !            75: 
        !            76: struct{
        !            77:        short   speed;
        !            78:        short   bytes;
        !            79: } speeds[] = {
        !            80:        EXTA, 1920,
        !            81:        B9600, 960,
        !            82:        B4800, 480,
        !            83:        B1200, 120,
        !            84:        B300, 30,
        !            85:        0, 960,         /* default */
        !            86: };
        !            87: #define        NSPEEDS ((sizeof speeds)/(sizeof speeds[0]))
        !            88: #define        max(A,B)        (((A)>(B))?(A):(B))
        !            89: 
        !            90: struct Pchannel        pconvs[NLAYERS];
        !            91: struct Pconfig pconfig = {
        !            92: #      ifndef  TRACING
        !            93:        write,
        !            94: #      else
        !            95:        twrite,
        !            96: #      endif
        !            97:        receive,
        !            98:        (void(*)())creceive,
        !            99: };
        !           100: 
        !           101: #ifdef TRACING
        !           102: int    twrite();
        !           103: FILE   *tracefd;
        !           104: void   trace();
        !           105: void   tread();
        !           106: #define        ifdeftracing(a)         a
        !           107: #else
        !           108: #define trace(a, b)
        !           109: #define        tread(a, b)
        !           110: #define        ifdeftracing(a)
        !           111: #endif
        !           112: 
        !           113: #if    TRACING==1 || PDEBUG==1
        !           114: char   tracefile[]="traces";
        !           115: #define        _exit   exit
        !           116: #endif
        !           117: 
        !           118: main(argc, argv)
        !           119:        char *argv[];
        !           120: {
        !           121:        register int n;
        !           122:        char cmdline[64];
        !           123:        progname=argv[0];
        !           124:        for(n=1; n<argc; n++) {
        !           125:                if(strcmp(argv[n], "-L")==0)
        !           126:                        jerqstart=argv[++n];
        !           127:                else if(strcmp(argv[n], "-l")==0){
        !           128:                        register fd; char jfd[32];
        !           129:                        fd = creat(mktemp(strcpy(jfd, "/tmp/.muxXXXXXX")), 0744);
        !           130:                        write(fd, "#!/bin/sh\n", 10);
        !           131:                        ++n, write(fd, argv[n], strlen(argv[n]));
        !           132:                        close(fd);
        !           133:                        strcpy(cmdline, jfd);
        !           134:                        strcat(strcat(strcat(cmdline, "; rm "), jfd), "; exit");
        !           135:                        jerqstart = cmdline;
        !           136:                }else{
        !           137:                        n=argc+1; break;
        !           138:                }
        !           139:        }
        !           140:        if(n!=argc)
        !           141:                return service(argc-1, argv+1);
        !           142:        if((jerqprog=getenv("MUXTERM")) == 0)
        !           143:                jerqprog="/usr/jerq/lib/muxterm";
        !           144:        if((shell=getenv("SHELL")) == 0)
        !           145:                shell="sh";
        !           146:        ioctl(0, TIOCGETP, &sttymodes);
        !           147:        sttysave=sttymodes;
        !           148:        if(ioctl(0, TIOCGDEV, &devmodes)>=0)    /* band-aid for old systems */
        !           149:                devsave=devmodes;
        !           150:        else {
        !           151:                devsave.ispeed=devmodes.ispeed=sttymodes.sg_ispeed;
        !           152:                devsave.ospeed=devmodes.ospeed=sttymodes.sg_ospeed;
        !           153:        }
        !           154:        ioctl(0, TIOCGETC, &tcharssave);
        !           155:        setmodes(&ttychars, &sttymodes);
        !           156:        settchars(&ttychars, &tcharssave);
        !           157:        sttymodes.sg_flags|=RAW;
        !           158:        sttymodes.sg_flags&=~ECHO;
        !           159:        ioctl(0, TIOCSETP, &sttymodes);
        !           160:        devmodes.flags|=F8BIT;
        !           161:        ioctl(0, TIOCSDEV, &devmodes);
        !           162:        signal(SIGPIPE, (int (*)())1);
        !           163: #ifdef TRACING
        !           164:        tracefd=fopen(tracefile, "w");
        !           165: #ifdef PDEBUG
        !           166:        ptracefd = tracefd;
        !           167: #endif
        !           168: #endif
        !           169: #if    TRACING!=1 && PDEBUG==1
        !           170:        ptracefd=fopen(tracefile, "w");
        !           171: #endif
        !           172:        if(boot(jerqprog))
        !           173:                quit("can't boot terminal program");
        !           174:        booted++;
        !           175:        ioctl(0, TIOCEXCL, 0);
        !           176:        trace(0, 0);
        !           177:        trace("start\n", 0);
        !           178:        for(n=0; n<NSPEEDS; n++)
        !           179:                if(speeds[n].speed<=devmodes.ospeed)
        !           180:                        break;
        !           181:        n=speeds[n].bytes;
        !           182:        Pxtimeout=max((((NLAYERS-2)*sizeof(struct Packet)*NPCBUFS+n-1)/n), 3);
        !           183:        Prtimeout=max(((sizeof(struct Packet)+n-1)/n), 2);
        !           184:        Pscanrate=1;
        !           185:        trace("speed = %d", n);
        !           186:        trace(" xtimo = %d", Pxtimeout);
        !           187:        trace(" rtimo = %d\n", Prtimeout);
        !           188:        Pxfdesc=1;
        !           189:        if(pinit(NLAYERS)==-1)
        !           190:                quit("bad protocol initialization");
        !           191:        buf[0]=JTIMO;
        !           192:        buf[1]=Prtimeout;
        !           193:        buf[2]=Pxtimeout;
        !           194:        if (jerqstart && (n = strlen(jerqstart)) <= MAXPKTDSIZE-3) {
        !           195:                strncpy(&buf[3], jerqstart, n);
        !           196:                n += 3;
        !           197:        } else
        !           198:                n = 3;
        !           199:        (void)psend(0, buf, n);
        !           200:        while(scan()!=-1){
        !           201:                if(quitflag)
        !           202:                        quit(NULL);
        !           203:                ifdeftracing(fflush(tracefd));
        !           204:        }
        !           205:        trace("errno = %d\n", errno);
        !           206:        quit("select");
        !           207: }
        !           208: scan()
        !           209: {
        !           210:        register fd, bit, n, ret=0;
        !           211: 
        !           212:        trace(0, 0);
        !           213:        trace("enabled %o\n", enabled);
        !           214:        if(blocked){            /* try to clear blocked channels */
        !           215:                for(fd=0, bit=1; fd<NSELFD; fd++, bit<<=1)
        !           216:                        if((bit&blocked) &&
        !           217:                           psend(layer[fd].bchan, layer[fd].bbuf, layer[fd].bcount)!=-1){
        !           218:                                blocked&=~bit;
        !           219:                                return 0;
        !           220:                        }
        !           221:        }
        !           222:        rdfd.fds_bits[0]=enabled&~blocked;
        !           223:        while(select(NSELFD, &rdfd, (fd_set *)0, SELTIMO)==-1){
        !           224:                if(errno!=EINTR)
        !           225:                        return -1;
        !           226:                ret++;
        !           227:        }
        !           228:        trace(0, 0);
        !           229:        trace("selected %o\n", rdfd.fds_bits[0]);
        !           230:        if(rdfd.fds_bits[0]==0) {
        !           231:                if(Ptflag)
        !           232:                        ptimeout(SIGALRM);
        !           233:        }else for(fd=0, bit=1; fd<NSELFD; fd++, bit<<=1)
        !           234:                if(bit&rdfd.fds_bits[0]){
        !           235:                        while((n=read(fd, buf, sizeof buf))==-1)
        !           236:                                if(errno!=EINTR)
        !           237:                                        return -1;
        !           238:                                else{
        !           239:                                        trace("read error, errno=%d\n", errno);
        !           240:                                        return 0;
        !           241:                                }
        !           242:                        ifdeftracing(if(n==0) trace("0 byte read", 0));
        !           243:                        if(fd==0){
        !           244:                                if(n==0)
        !           245:                                        quit("EOF on jerq");
        !           246:                                tread(buf, n);
        !           247:                                precv(buf, n);
        !           248:                        } else if(unpack(fd, buf, n))
        !           249:                                enabled&=~bit;
        !           250:                }
        !           251:        return ret;     /* used in quit */
        !           252: }
        !           253: psend_hold(chan, bufp, count, fd)
        !           254:        int chan;
        !           255:        register char *bufp;
        !           256:        int count;
        !           257:        register fd;
        !           258: {
        !           259:        int ret;
        !           260:        register i;
        !           261:        if((ret=psend(chan, bufp, count))==-1){
        !           262:                trace("psend hold on fd %d\n", fd);
        !           263:                layer[fd].bchan=chan;
        !           264:                layer[fd].bcount=count;
        !           265:                for(i=0; i<count; i++)
        !           266:                        layer[fd].bbuf[i]=bufp[i];
        !           267:                blocked|=1<<fd;
        !           268:        }
        !           269:        return ret;
        !           270: }
        !           271: quit(s)
        !           272:        register char *s;
        !           273: {
        !           274:        register l, i;
        !           275: 
        !           276:        ifdeftracing(trace("\nmux: %s\n", s); trace(0, 0); fflush(tracefd));
        !           277:        if(booted){
        !           278:                for(i=0; i<NSELFD; i++)
        !           279:                        if(layer[i].busy)
        !           280:                                (void)close(i);
        !           281:                layer[0].chan=0;
        !           282:                sendioctl(0, JTERM);    /* kill demux ==> boot terminal */
        !           283:                for(i=Pxtimeout+1; Ptflag && i>0;){
        !           284:                        enabled=1;
        !           285:                        if((l=scan())==-1)
        !           286:                                break;
        !           287:                        i-=l;
        !           288:                }
        !           289:                alarm(0);
        !           290:        }
        !           291:        ioctl(0, TIOCSDEV, &devsave);
        !           292:        ioctl(0, TIOCSETP, &sttysave);
        !           293:        ioctl(0, TIOCNXCL, 0);
        !           294:        sleep(2);
        !           295:        if (s) {
        !           296:                write(2, progname, strlen(progname));
        !           297:                write(2, ": ", 2);
        !           298:                write(2, s, strlen(s));
        !           299:                write(2, "\n", 1);
        !           300:        }
        !           301: #ifdef PSTATISTICS
        !           302:        for(i=0, l=0; i<PS_NSTATS; i++)
        !           303:                if (pstats[i].count) {
        !           304:                        if(l++==0)
        !           305:                                fprintf(stderr, "\nPacket protocol statistics:\n");
        !           306:                        fprintf(stderr, "%6ld %s\n"
        !           307:                                ,pstats[i].count
        !           308: #ifdef PSTATSDESC
        !           309:                                ,pstats[i].descp
        !           310: #else
        !           311:                                ,""
        !           312: #endif
        !           313:                                );
        !           314:                        trace("%6ld ", pstats[i].count);
        !           315:                        trace("%s\n", pstats[i].descp);
        !           316:                }
        !           317:        fflush(stderr);
        !           318: #endif
        !           319: #if    TRACING == 1 || PDEBUG == 1
        !           320:        fprintf(stderr, "\nThere are traces in '%s'\n", tracefile);
        !           321: #endif
        !           322:        ifdeftracing(fflush(tracefd); abort());
        !           323: #ifdef MONITOR
        !           324:        monitor(0);
        !           325: #endif
        !           326:        _exit(0);
        !           327: }
        !           328: /*
        !           329:  *     Unpack a message buffer bp of length n.
        !           330:  */
        !           331: unpack(fd, bp, n)
        !           332:        register int fd;
        !           333:        char *bp;
        !           334:        int n;
        !           335: {
        !           336:        register struct mesg *mp;
        !           337:        struct ttychars tempchars;
        !           338:        static char cdbuf[256];
        !           339:        char *s;
        !           340:        register int size;
        !           341:        mp = (struct mesg *)bp;
        !           342:        size = mp->losize + (mp->hisize<<8);
        !           343:        trace("unpack fd %d", fd);
        !           344:        trace(" size %d", n);
        !           345:        trace(" count %d\n", size);
        !           346:        if(n<=0)
        !           347:                mp->type=M_HANGUP;
        !           348:        else if(layer[fd].more>0){
        !           349:                layer[fd].more-=n;
        !           350:                return sendchars(fd, bp, n);
        !           351:        }
        !           352:        switch (mp->type) {
        !           353:        case M_HANGUP:
        !           354:                trace("shell died\n", 0);
        !           355:                wait((int *)0);
        !           356:                if(layer[fd].busy){
        !           357:                        sendioctl(fd, JDELETE);
        !           358:                        /*(void)psend(layer[fd].chan, "Shell died.\n", 12);*/
        !           359:                }
        !           360:                layer[fd].busy = 0;
        !           361:                close(fd);
        !           362:                enabled &= ~(1<<fd);
        !           363:                return 1;
        !           364:        case M_DELAY:
        !           365:        default:
        !           366:                trace("ignore type 0%o\n", mp->type);
        !           367:                return 0;
        !           368:        case M_DELIM:
        !           369:        case M_DATA:
        !           370:                if(size==0){
        !           371:                        trace("size 0 %s ignored\n", mp->type==M_DELIM? "delim" : "data");
        !           372:                        return 0;
        !           373:                }
        !           374:                break;
        !           375:        case M_IOCTL:
        !           376:                mp->type = M_IOCACK;
        !           377:                switch (*(int *)(bp+MSGHLEN)) {
        !           378:                case TIOCSETP:
        !           379:                case TIOCSETN:
        !           380:                        tempchars=layer[fd].ttychars;
        !           381:                        setmodes(&tempchars, (struct sgttyb *)(bp+MSGHLEN+sizeof(int)));
        !           382:                        ttyset(fd, &tempchars);
        !           383:                        size = 0;
        !           384:                        break;
        !           385:                case TIOCGETP:
        !           386:                        tempchars=layer[fd].ttychars;
        !           387:                        getmodes(&tempchars, (struct sgttyb *)(bp+MSGHLEN+sizeof(int)));
        !           388:                        size=sizeof(struct sgttyb)+sizeof(int);
        !           389:                        ttyset(fd, &tempchars);
        !           390:                        break;
        !           391:                case TIOCSETC:
        !           392:                        tempchars=layer[fd].ttychars;
        !           393:                        settchars(&tempchars, (struct tchars *)(bp+MSGHLEN+sizeof(int)));
        !           394:                        ttyset(fd, &tempchars);
        !           395:                        size=0;
        !           396:                        break;
        !           397:                case TIOCGETC:
        !           398:                        gettchars(&layer[fd].ttychars, (struct tchars *)(bp+MSGHLEN+sizeof(int)));
        !           399:                        size=sizeof (struct tchars) + sizeof (int);
        !           400:                        break;
        !           401:                case TIOCSDEV:
        !           402:                        size=0;
        !           403:                        break;
        !           404:                case TIOCGDEV:
        !           405:                        size=sizeof(devsave)+sizeof(int);
        !           406:                        *(struct ttydevb *)(bp+MSGHLEN+sizeof(int))=devsave;
        !           407:                        break;
        !           408:                case JMUX:
        !           409:                        size=0;
        !           410:                        break;
        !           411:                case JWINSIZE:
        !           412:                        *((int *)(bp+MSGHLEN))=JWINSIZE;        /* answering JWINSIZE ioctl */
        !           413: #define        BP      ((struct winsize *)(bp+MSGHLEN+sizeof(int)))
        !           414:                        BP->bytesx=layer[fd].dx;
        !           415:                        BP->bytesy=layer[fd].dy;
        !           416:                        BP->bitsx=layer[fd].bitsx;
        !           417:                        BP->bitsy=layer[fd].bitsy;
        !           418:                        size=sizeof(struct winsize)+sizeof(int);
        !           419:                        break;
        !           420:                case JTERM:
        !           421:                case JBOOT:
        !           422:                case JZOMBOOT:
        !           423:                case JEXIT:
        !           424:                        sendioctl(fd, *(int *)(bp+MSGHLEN));
        !           425:                        size=0;
        !           426:                        break;
        !           427:                case JCHDIR:
        !           428:                        s=bp+MSGHLEN+sizeof(int);
        !           429:                        if(*s==0){
        !           430:                                if(chdir(cdbuf)!=0) 
        !           431:                                        mp->type = M_IOCNAK;
        !           432:                                cdbuf[0]=0;
        !           433:                        }else
        !           434:                                strcat(cdbuf, s);
        !           435:                        size = 0;
        !           436:                        break;
        !           437:                default:
        !           438:                        mp->type = M_IOCNAK;
        !           439:                        size = 0;
        !           440:                }
        !           441:                mp->magic = MSGMAGIC;           /* safety net */
        !           442:                mp->losize = size;
        !           443:                mp->hisize = size>>8;
        !           444:                write(fd, bp, MSGHLEN+size);
        !           445:                trace("unpack ioctl type '%c'", *(int *)(bp+MSGHLEN)>>8);
        !           446:                trace(" %d\n", *(int *)(bp+MSGHLEN)&0xff);
        !           447:                return 0;
        !           448:        }
        !           449:        if(size>MAXPKTDSIZE){
        !           450:                layer[fd].more=size-MAXPKTDSIZE;
        !           451:                size=MAXPKTDSIZE;
        !           452:        }
        !           453:        return sendchars(fd, bp+MSGHLEN, size);
        !           454: }
        !           455: getmodes(tp, bp)
        !           456:        register struct ttychars *tp;
        !           457:        register struct sgttyb *bp;
        !           458: {
        !           459:        bp->sg_ispeed=sttysave.sg_ispeed;
        !           460:        bp->sg_ospeed=sttysave.sg_ospeed;
        !           461:        bp->sg_flags=(tp->flags1<<8)|(tp->flags0&0xFF);
        !           462:        bp->sg_erase=tp->erase;
        !           463:        bp->sg_kill=tp->kill;
        !           464: }
        !           465: setmodes(tp, bp)
        !           466:        register struct ttychars *tp;
        !           467:        register struct sgttyb *bp;
        !           468: {
        !           469:        tp->flags0=bp->sg_flags;
        !           470:        tp->flags1=bp->sg_flags>>8;
        !           471:        tp->erase=bp->sg_erase;
        !           472:        tp->kill=bp->sg_kill;
        !           473: }
        !           474: gettchars(tp, bp)
        !           475:        register struct ttychars *tp;
        !           476:        register struct tchars *bp;
        !           477: {
        !           478:        bp->t_intrc=tp->intrc;
        !           479:        bp->t_quitc=tp->quitc;
        !           480:        bp->t_startc=tp->startc;
        !           481:        bp->t_stopc=tp->stopc;
        !           482:        bp->t_eofc=tp->eofc;
        !           483:        bp->t_brkc=tp->brkc;
        !           484: }
        !           485: settchars(tp, bp)
        !           486:        register struct ttychars *tp;
        !           487:        register struct tchars *bp;
        !           488: {
        !           489:        tp->intrc=bp->t_intrc;
        !           490:        tp->quitc=bp->t_quitc;
        !           491:        tp->startc=bp->t_startc;
        !           492:        tp->stopc=bp->t_stopc;
        !           493:        tp->eofc=bp->t_eofc;
        !           494:        tp->brkc=bp->t_brkc;
        !           495: }
        !           496: ttyset(fd, tp)
        !           497:        struct ttychars *tp;
        !           498: {
        !           499:        register char *p, *q;
        !           500:        register i;
        !           501:        static struct ttycmesg m={JTTYC};
        !           502:        for(i=0, p=(char *)tp, q=(char *)&layer[fd].ttychars; *p++==*q++; i++)
        !           503:                if(i>=sizeof(struct ttychars))
        !           504:                        return; /* no need to send; they're identical */
        !           505:        m.chan=layer[fd].chan;
        !           506:        layer[fd].ttychars=*tp;
        !           507:        m.ttychars=*tp;
        !           508:        (void)psend_hold(0, (char *)&m, sizeof m, fd);
        !           509: }
        !           510: sendioctl(fd, cmd)
        !           511: {
        !           512:        char ioctlvec[2];
        !           513:        ioctlvec[0]=cmd;
        !           514:        ioctlvec[1]=layer[fd].chan;
        !           515:        if(psend_hold(0, ioctlvec, sizeof ioctlvec, fd)!=-1)
        !           516:                unblock(fd);
        !           517: }
        !           518: int
        !           519: sendchars(fd, s, cc)
        !           520:        char *s;
        !           521:        int cc;
        !           522: {
        !           523:        register int    l=layer[fd].chan;
        !           524:        register int    n;
        !           525: 
        !           526: #      ifdef TRACING
        !           527:        char buf[256];
        !           528:        trace("write %d chars ", cc);
        !           529:        trace("to layer %d\n", l);
        !           530:        strncpy(buf, s, cc);
        !           531:        buf[cc]=0;
        !           532:        trace("<%s>\n", buf);
        !           533: #      endif
        !           534:        if(fd!=0 && layer[fd].busy==0)
        !           535:                return 0;               /* layer was deleted, but there's still data */
        !           536:        if(cc>0)
        !           537:                do{
        !           538:                        if((n=cc)>MAXPKTDSIZE)
        !           539:                                n=MAXPKTDSIZE;
        !           540:                        if(psend(l, s, n)==-1){
        !           541:                                trace("layer %d blocked\n", l);
        !           542:                                return fd;      /* BUG */
        !           543:                        }
        !           544:                }while(s+=n, (cc-=n)>0);
        !           545:        unblock(fd);
        !           546:        return 0;
        !           547: }
        !           548: unblock(fd)
        !           549:        int fd;
        !           550: {
        !           551:        register Pch_p  pcp=&pconvs[layer[fd].chan];
        !           552: 
        !           553:        trace("unblock for layer %d", layer[fd].chan);
        !           554:        trace(" freepkts=%d\n", pcp->freepkts);
        !           555:        if(fd==0)
        !           556:                return;
        !           557:        if(pcp->freepkts>=1)
        !           558:                enabled|=1<<fd;
        !           559:        else
        !           560:                enabled&=~(1<<fd);
        !           561: }
        !           562: void
        !           563: lerror(l, s, t)
        !           564:        int l;
        !           565:        char *s, t;
        !           566: {
        !           567:        char    ebuf[128];
        !           568:        int     busy;
        !           569:        strcpy(ebuf, s);
        !           570:        if(errno){
        !           571:                strcat(ebuf, ": ");
        !           572:                if(errno < sys_nerr)
        !           573:                        strcat(ebuf, sys_errlist[errno]);
        !           574:                else{
        !           575:                        strcat(ebuf, "error ");
        !           576:                        strcat(ebuf, itoa(errno));
        !           577:                }
        !           578:                errno=0;
        !           579:        }
        !           580:        strcat(ebuf, "\n");
        !           581:        trace("lerror type %d", t);
        !           582:        trace(" for layer %d", l);
        !           583:        trace(" %s\n", ebuf);
        !           584:        layer[0].chan=l;
        !           585:        sendchars(0, ebuf, strlen(ebuf));
        !           586: }
        !           587: int
        !           588: creceive(l, s, n)
        !           589:        char *s;
        !           590: {
        !           591:        if(s[0]!=C_UNBLK || n!=1)
        !           592:                quit("bad control type");
        !           593:        (void)receive(l, s, n);
        !           594: }
        !           595: int
        !           596: receive(l, s, cc)
        !           597:        int l;
        !           598:        register char *s;
        !           599:        register int cc;
        !           600: {
        !           601:        register int i;
        !           602:        struct mesg hupmsg;
        !           603:        if((i=ltofd(l))==-1)
        !           604:                switch(*s){
        !           605:                case C_NEW:
        !           606:                case C_EXIT:
        !           607:                        break;
        !           608:                default:
        !           609:                        errno = 0;
        !           610:                        lerror(l, "inactive layer", *s);
        !           611:                case C_UNBLK:
        !           612:                        return 0;
        !           613:                }
        !           614:        while(cc--){
        !           615:                trace("receive C type %d", *s);
        !           616:                trace(" for layer %d", l);
        !           617:                trace(" fd %d\n", i);
        !           618:                switch(*s++){
        !           619:                case C_SENDCHAR:        /* send layer char */
        !           620:                        wrmesgb(i, s++, 1);
        !           621:                        delim(i);
        !           622:                        cc--;
        !           623:                        break;
        !           624:                case C_DELIM:           /* send delimiter */
        !           625:                        delim(i);
        !           626:                        break;
        !           627:                case C_NEW:             /* make layer */
        !           628:                        if((i=doshell())==-1){
        !           629:                                lerror(l, "new layer", C_NEW);
        !           630:                                trace("can't start\n", i);
        !           631:                                cc-=6;
        !           632:                                break;
        !           633:                        }
        !           634:                        layer[i].busy=1;
        !           635:                        layer[i].chan=l;
        !           636:                        ttyset(i, &ttychars);
        !           637:                        trace("new fd %d ", i);
        !           638:                        trace("layer %d ", l);
        !           639:                        enabled |= (1<<i);
        !           640:                case C_RESHAPE:
        !           641:                        layer[i].dx=*s++;
        !           642:                        trace("x wid %d ", layer[i].dx);
        !           643:                        layer[i].dy=*s++;
        !           644:                        trace("y wid %d\n", layer[i].dy);
        !           645:                        layer[i].bitsx=(unsigned char)*s++;
        !           646:                        layer[i].bitsx|=(*s++)<<8;
        !           647:                        layer[i].bitsy=(unsigned char)*s++;
        !           648:                        layer[i].bitsy|=(*s++)<<8;
        !           649:                        cc-=6;
        !           650:                        break;
        !           651:                case C_UNBLK:           /* unblock layer */
        !           652:                        unblock(i);
        !           653:                        break;
        !           654:                case C_PUSHLD:          /* obsolescent */
        !           655:                case C_POPLD:
        !           656:                        break;
        !           657:                case C_DELETE:          /* delete layer */
        !           658:                        hupmsg.losize=0;
        !           659:                        hupmsg.hisize=0;
        !           660:                        hupmsg.magic=MSGMAGIC;
        !           661:                        hupmsg.type=M_HANGUP;
        !           662:                        write(i, (char *)&hupmsg, MSGHLEN);
        !           663:                        layer[i].busy=0;
        !           664:                        pconvs[layer[i].chan].freepkts=1;       /* hack */
        !           665:                        unblock(i);
        !           666:                        layer[i].ttychars=zerochars;
        !           667:                        break;
        !           668:                case C_EXIT:            /* exit */
        !           669:                        quitflag++;
        !           670:                        return 0;
        !           671:                case C_SENDNCHARS:      /* send cc characters */
        !           672:                        wrmesgb(i, s, cc);
        !           673:                        return 0;
        !           674:                case C_SENDNCHARD:      /* send cc characters with delimeter */
        !           675:                        wrmesgb(i, s, cc);
        !           676:                        delim(i);
        !           677:                        return 0;
        !           678:                case C_KILL:    /* send layer signal */
        !           679:                        dosig(i, *s++);
        !           680:                        cc--;
        !           681:                        break;
        !           682:                default:
        !           683:                        quit("unknown state incase 0");
        !           684:                }
        !           685:                ifdeftracing(if(cc<0) quit("bad count in receive"));
        !           686:        }
        !           687:        return 0;
        !           688: }
        !           689: int
        !           690: ltofd(l)
        !           691: {
        !           692:        register i;
        !           693:        if(l==0)
        !           694:                return 0;
        !           695:        for(i=1; i<NSELFD; i++)
        !           696:                if(layer[i].busy && layer[i].chan==l)
        !           697:                        return i;
        !           698:        trace("unknown layer %d\n", l);
        !           699:        return -1;
        !           700: }
        !           701: void
        !           702: dosig(fd, sig)         /* Interrupt shell */
        !           703: {
        !           704:        char sigbuf[MSGHLEN+1];
        !           705:        register struct mesg *mp;
        !           706: 
        !           707:        mp = (struct mesg *)sigbuf;
        !           708:        mp->type=M_SIGNAL;
        !           709:        mp->magic=MSGMAGIC;
        !           710:        mp->losize=sizeof(char);
        !           711:        mp->hisize=0;
        !           712:        sigbuf[MSGHLEN]=sig;
        !           713:        write(fd, sigbuf, MSGHLEN+1);
        !           714:        mp->type=M_FLUSH;
        !           715:        mp->magic=MSGMAGIC;
        !           716:        mp->losize=0;
        !           717:        mp->hisize=0;
        !           718:        write(fd, sigbuf, MSGHLEN);
        !           719: }
        !           720: void
        !           721: wrmesgb(fd, cp, n)
        !           722:        register char *cp;
        !           723:        int n;
        !           724: {
        !           725:        char wrbuf[MAXPKTDSIZE+MSGHLEN];
        !           726:        register char *bp;
        !           727:        register struct mesg *mp;
        !           728:        register int i;
        !           729: 
        !           730:        ifdeftracing(fprintf(tracefd, "mesg to fd %d: <%.*s>\n", fd, n, cp));
        !           731:        mp = (struct mesg *)wrbuf;
        !           732:        mp->type=M_DATA;
        !           733:        mp->magic=MSGMAGIC;
        !           734:        mp->losize=n;
        !           735:        mp->hisize=n>>8;
        !           736:        bp=wrbuf+MSGHLEN;
        !           737:        i=n;
        !           738:        while(i--)
        !           739:                *bp++=*cp++;
        !           740:        write(fd, wrbuf, MSGHLEN+n);
        !           741: }
        !           742: delim(fd)
        !           743: {
        !           744:        struct mesg delbuf;
        !           745: 
        !           746:        ifdeftracing(fprintf(tracefd, "delim fd %d\n", fd));
        !           747:        delbuf.type=M_DELIM;
        !           748:        delbuf.magic=MSGMAGIC;
        !           749:        delbuf.losize=0;
        !           750:        delbuf.hisize=0;
        !           751:        write(fd, (char *)&delbuf, MSGHLEN);
        !           752: }
        !           753: int
        !           754: doshell()
        !           755: {
        !           756:        register fd, slave;
        !           757:        int fp[2];
        !           758:        trace("do shell\n", 0);
        !           759:        if(pipe(fp)<0){
        !           760:                trace("can't pipe, errno=%d\n", errno);
        !           761:                return -1;
        !           762:        }
        !           763:        slave=fp[0];
        !           764:        fd=fp[1];
        !           765:        trace("pipe %d\n", fd);
        !           766:        if(ioctl(fd, FIOPUSHLD, &mesg_ld) == -1){
        !           767:                trace("FIOPUSHLD fails, errno=%d\n", errno);
        !           768:                close(fd);
        !           769:                return -1;
        !           770:        }
        !           771:        setdelim(fd);   /* hack */
        !           772:        switch(fork()){
        !           773:        case 0:
        !           774:                /* close every file descriptor in sight, and then some */
        !           775:                for(fd=0; fd<5+NLAYERS; fd++)
        !           776:                        if(fd!=slave)
        !           777:                                close(fd);
        !           778:                dup(slave); dup(slave); dup(slave); dup(slave);
        !           779:                close(slave);
        !           780:                ioctl(0, TIOCSPGRP, 0);
        !           781:                signal(SIGPIPE, (int (*)())0);
        !           782:                execlp(shell, shell, 0);
        !           783:                perror(shell);
        !           784:                exit(1);
        !           785:                break;
        !           786:        case -1:
        !           787:                close(fd);
        !           788:                close(slave);
        !           789:                return -1;
        !           790:        }
        !           791:        trace("doshell succeeds\n", 0);
        !           792:        close(slave);
        !           793:        return fd;
        !           794: }
        !           795: setdelim(fd)
        !           796: {
        !           797:        struct mesg m;
        !           798: 
        !           799:        m.type = M_YDEL;
        !           800:        m.magic = MSGMAGIC;
        !           801:        m.losize = m.hisize = 0;
        !           802:        write(fd, (char *)&m, MSGHLEN);
        !           803: }
        !           804: int
        !           805: boot(s)
        !           806:        char *s;
        !           807: {
        !           808:        if(system("/usr/jerq/bin/32ld", "32ld", s))
        !           809:                return 1;
        !           810:        sleep(2);
        !           811:        return 0;
        !           812: }
        !           813: int
        !           814: system(s, t, u)
        !           815: char *s, *t, *u;
        !           816: {
        !           817:        int status, pid, l;
        !           818: 
        !           819:        if ((pid=fork())==0){
        !           820:                execl(s, t, u, 0);
        !           821:                _exit(127);
        !           822:        }
        !           823:        while ((l = wait(&status)) != pid && l != -1)
        !           824:                ;
        !           825:        if (l == -1)
        !           826:                status = -1;
        !           827:        return(status);
        !           828: }
        !           829: char *
        !           830: itoa(i)
        !           831:        register int i;
        !           832: {
        !           833:        static char str[11];
        !           834:        register char * sp = &str[sizeof str];
        !           835: 
        !           836:        *--sp = '\0';
        !           837:        if(i>0){
        !           838:                do
        !           839:                        *--sp=i%10+'0';
        !           840:                while((i/=10)>0);
        !           841:        }else
        !           842:                *--sp='0';
        !           843:        return sp;
        !           844: }
        !           845: service(argc, argv)
        !           846:        char *argv[];
        !           847: {
        !           848:        if(strcmp(argv[0], "cd")==0){
        !           849:                char *where=argv[1];
        !           850:                char buf[CDSIZE+1];
        !           851:                buf[CDSIZE]=0;
        !           852:                if(where==0 && (where=getenv("HOME"))==0){
        !           853:                        write(2, "cd: no HOME set\n", 16);
        !           854:                        return 1;
        !           855:                }
        !           856:                while(*where){
        !           857:                        strncpy(buf, where, CDSIZE);
        !           858:                        ioctl(0, JCHDIR, buf);
        !           859:                        where+=strlen(buf);
        !           860:                }
        !           861:                if(ioctl(0, JCHDIR, where)!=0){
        !           862:                        write(2, "cd: bad directory\n", 18);
        !           863:                        return 1;
        !           864:                }
        !           865:                return 0;
        !           866:        }
        !           867:        if(strcmp(argv[0], "exit")==0)
        !           868:                return ioctl(0, JEXIT, 0);
        !           869:        write(2, "mux: no such command ", 21);
        !           870:        write(2, argv[0], strlen(argv[0]));
        !           871:        write(2, "\n", 1);
        !           872:        return 1;
        !           873: }
        !           874: #ifdef TRACING
        !           875: /*VARARGS1*/
        !           876: void
        !           877: trace(s, a)
        !           878:        char *s, *a;
        !           879: {
        !           880:        long t;
        !           881:        extern long time();
        !           882:        extern char *ctime();
        !           883: 
        !           884:        if(s)
        !           885:                fprintf(tracefd, s, a);
        !           886:        else{
        !           887:                (void)time(&t);
        !           888:                fprintf(tracefd, "%.9s", ctime(&t)+11);
        !           889:        }
        !           890: }
        !           891: int
        !           892: twrite(fd, s, n)
        !           893:        unsigned char * s;
        !           894: {
        !           895:        register i;
        !           896:        fprintf(tracefd, "to jerq: ");
        !           897:        for(i=0; i<n; i++)
        !           898:                fprintf(tracefd, "<%o>", s[i]);
        !           899:        fprintf(tracefd, "\n");
        !           900:        return write(fd, s, n);
        !           901: }
        !           902: void
        !           903: tread(s, n)
        !           904:        unsigned char * s;
        !           905: {
        !           906:        register i;
        !           907:        fprintf(tracefd, "from jerq: ");
        !           908:        for(i=0; i<n; i++)
        !           909:                fprintf(tracefd, "<%o>", s[i]);
        !           910:        fprintf(tracefd, "\n");
        !           911: }
        !           912: #endif

unix.superglobalmegacorp.com

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