Annotation of researchv9/jerq/src/mux/mux.c, revision 1.1.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.