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

unix.superglobalmegacorp.com

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