Annotation of researchv8dc/sys/chunix/chaos.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * UNIX device driver interface to the Chaos N.C.P.
        !             3:  */
        !             4: #include "../chunix/chsys.h"
        !             5: #include "../chunix/chconf.h"
        !             6: #include "../chaos/chaos.h"
        !             7: #include "../chaos/user.h"
        !             8: #include "../chaos/dev.h"
        !             9: #include "../h/inode.h"
        !            10: #include "../h/file.h"
        !            11: #include "../h/dir.h"
        !            12: #include "../h/user.h"
        !            13: #include "../h/conf.h"
        !            14: #include "../h/ioctl.h"
        !            15: #include "../h/buf.h"
        !            16: #include "../h/systm.h"
        !            17: #include "../h/tty.h"
        !            18: 
        !            19: #ifdef VMUNIX
        !            20: #include "cht.h"
        !            21: #endif
        !            22: 
        !            23: static int             initted;        /* NCP initialization flag */
        !            24: int                    Rfcwaiting;     /* Someone waiting on unmatched RFC */
        !            25: static char *chnames[][3] = {
        !            26: /* reading     writing         read/write */
        !            27: { "uread",     "ucreate",      "ureadwrite", },
        !            28: };
        !            29: 
        !            30: #define CHFCONN(fp)    ((fp)->f_conn)
        !            31: #define CHIOPRIO       (PZERO+1)       /* Just interruptible */
        !            32: #ifndef VMUNIX
        !            33: #define setjmp save
        !            34: #endif
        !            35: static struct packet *fillpacket();
        !            36: /*
        !            37:  * Open a chaos channel. 
        !            38:  *     Special case devices are indicated if CHHOST(dev) == CHHSPEC.
        !            39:  *     See <chaos/dev.h> for the definitions.
        !            40:  *     Non-special device opens imply a request to create a new connection
        !            41:  *     via an RFC to a specified host, with a specified contact name string.
        !            42:  *     The host number is specified one of three ways (CHHOST(dev)):
        !            43:  *             CHHREAD         Read an ascii host number from the remainder
        !            44:  *                             of the pathname (after the component that
        !            45:  *                             matched this device).
        !            46:  *             CHHUSE          Use the component that matched itself
        !            47:  *                             as an ascii number.
        !            48:  *             else            Use the CHHOST(dev) as an index into an
        !            49:  *                             internal host table where frequently used
        !            50:  *                             host numbers should reside.
        !            51:  *     The contact name can also be specified in three ways (CHNAME(dev)):
        !            52:  *             CHNREAD         Read the contact string from the rest of the
        !            53:  *                             path name (possibly after host number).
        !            54:  *             CHNUSE          Read the contact string from the path
        !            55:  *                             component that matched (possibly after host
        !            56:  *                             number).
        !            57:  *             else            Use the CHNAME(dev) as an index into an
        !            58:  *                             internal array of contact names, also
        !            59:  *                             indexed by the type of open (read, write, rw).
        !            60:  */
        !            61: chropen(dev, flag)
        !            62: dev_t dev;
        !            63: {
        !            64:        register struct connection *conn;
        !            65:        register struct packet *pkt;
        !            66:        int host, name, wstate;
        !            67: 
        !            68:        ch_bufalloc();
        !            69:        /* initialize the NCP somewhere else? */
        !            70:        if (!initted) {
        !            71:                chrreset();     /* Reset drivers */
        !            72:                chtimeout();    /* Start clock "process" */
        !            73:                initted++;
        !            74:        }
        !            75:        conn = NOCONN;
        !            76:        name = CHNAME(dev);
        !            77:        host = CHHOST(dev);
        !            78:        wstate = 0;
        !            79:        if (host == CHHSPEC)
        !            80:                switch (name) {
        !            81:                case CHUNMATCHED:
        !            82:                        if(Chrfcrcv == 0) {
        !            83:                                Chrfcrcv++;
        !            84:                                return;
        !            85:                        }
        !            86:                        break;
        !            87:                /*
        !            88:                 * Listens create a connection waiting for RFC's containing
        !            89:                 * the given contact name.  The returned file descriptor
        !            90:                 * corresponds to a connection that may not be open yet.
        !            91:                 * Use ioctls (CHIOCGSTAT, CHIOCSWAIT), to check or
        !            92:                 * hang on the state of the connection.
        !            93:                 */
        !            94:                case CHLISTEN:
        !            95:                        if ((pkt = fillpacket("", 0)) != NOPKT)
        !            96:                                conn = ch_listen(pkt);
        !            97:                        break;
        !            98:                }
        !            99:        else {
        !           100:                register int len = DIRSIZ;
        !           101:                char *namp = u.u_dbuf;
        !           102: 
        !           103:                switch(host) {
        !           104:                case CHHREAD:
        !           105:                        host = uatoi((char **)0);
        !           106:                        break;
        !           107:                case CHHUSE:
        !           108:                        host = uatoi(&namp);    /* stuffs namp */
        !           109:                        break;
        !           110:                default:
        !           111:                        host = chhosts[host];
        !           112:                }
        !           113:                if (u.u_error)
        !           114:                        host = 0;
        !           115:                switch(name) {
        !           116:                case CHNREAD:
        !           117:                        namp = "";
        !           118:                        len = 0;
        !           119:                        break;
        !           120:                case CHNUSE:
        !           121:                        len = DIRSIZ - (namp - u.u_dbuf);
        !           122:                        break;
        !           123:                default:
        !           124:                        len = CHMAXRFC;
        !           125:                        if ((namp = chnames[name][flag-1]) == NONAME)
        !           126:                                host = 0;
        !           127:                }
        !           128:                if (host != 0 && (pkt = fillpacket(namp, len)) != NOPKT &&
        !           129:                    (conn = ch_open(host, CHDRWSIZE, pkt)) != NOCONN &&
        !           130:                    CHHANGDEV(dev))
        !           131:                        wstate = CSRFCSENT;     /* Wait until OPEN/CLOSED */
        !           132:        }
        !           133:        if (conn == NOCONN) {
        !           134:                u.u_error = ENXIO;
        !           135:                ch_buffree();
        !           136:        } else {
        !           137:                register struct file *fp;
        !           138: 
        !           139:                fp = u.u_ofile[u.u_r.r_val1];   /* Yick. (see mx2.c) */
        !           140:                CHFCONN(fp) = (caddr_t)conn;
        !           141:                if (wstate) {
        !           142:                        /*
        !           143:                         * We should hang until the connection changes from
        !           144:                         * its initial state.
        !           145:                         * If interrupted, flush the connection.
        !           146:                         */
        !           147: #ifdef VMUNIX
        !           148:                        if (setjmp(u.u_qsav) == 0) {
        !           149: #else
        !           150:                        if (save(u.u_qsav) == 0) {
        !           151: #endif
        !           152:                                spl6();
        !           153:                                while (conn->cn_state == wstate)        
        !           154:                                        sleep((caddr_t)conn, CHIOPRIO);
        !           155:                                spl0();
        !           156: #ifdef DEBUG
        !           157:                                if (ch_badaddr((char *)conn))
        !           158:                                        panic("chopen");
        !           159: #endif DEBUG
        !           160:                        }
        !           161:                        /*
        !           162:                         * If the connection is not open, the open failed.
        !           163:                         * Unless is got an ANS back.
        !           164:                         */
        !           165:                        if (conn->cn_state != CSOPEN &&
        !           166:                            (conn->cn_state != CSCLOSED ||
        !           167:                             (pkt = conn->cn_rhead) == NOPKT ||
        !           168:                             pkt->pk_op != ANSOP)) {
        !           169:                                rlsconn(conn);
        !           170:                                u.u_error = ENXIO;
        !           171:                                return;
        !           172:                        }
        !           173:                }
        !           174:                conn->cn_sflags |= CHRAW;
        !           175:                conn->cn_mode = CHSTREAM;
        !           176:        }
        !           177: }
        !           178: 
        !           179: /* ARGSUSED */
        !           180: chrclose(dev, flag, cp)
        !           181: dev_t dev;
        !           182: struct chan *cp;
        !           183: {
        !           184:        register struct connection *conn = (struct connection *)cp;
        !           185: 
        !           186:        if (minor(dev) == CHURFCMIN) {
        !           187:                Chrfcrcv = 0;
        !           188:                freelist(Chrfclist);
        !           189:                Chrfclist = NOPKT;
        !           190:                return;
        !           191:        }
        !           192:        /*
        !           193:         * If this connection has been turned into a tty, then the
        !           194:         * tty owns it and we don't do anything.
        !           195:         */
        !           196:        if (conn->cn_mode != CHTTY)
        !           197:                chclose(conn, flag);
        !           198: }
        !           199: chclose(conn, flag)
        !           200: register struct connection *conn;
        !           201: {
        !           202:        register struct packet *pkt;
        !           203: 
        !           204:        switch (conn->cn_mode) {
        !           205:        case CHTTY:
        !           206:                panic("chclose on tty");
        !           207:        case CHSTREAM:
        !           208:                spl6();
        !           209:                if (setjmp(u.u_qsav)) {
        !           210:                        pkt = pktstr(NOPKT, "User interrupted", 16);
        !           211:                        if (pkt != NOPKT)
        !           212:                                pkt->pk_op = CLSOP;
        !           213:                        ch_close(conn, pkt, 0);
        !           214:                        goto shut;
        !           215:                }
        !           216:                if (flag & FWRITE) {
        !           217:                        /*
        !           218:                         * If any input packets other than the RFC are around
        !           219:                         * something is wrong and we just abort the connection
        !           220:                         */
        !           221:                        while ((pkt = conn->cn_rhead) != NOPKT) {
        !           222:                                ch_read(conn);
        !           223:                                if (pkt->pk_op != RFCOP)
        !           224:                                        goto recclose;
        !           225:                        }
        !           226:                        /*
        !           227:                         * We set this flag telling the interrupt time
        !           228:                         * receiver to abort the connection if any new packets
        !           229:                         * arrive.
        !           230:                         */
        !           231:                        conn->cn_sflags |= CHCLOSING;
        !           232:                        /*
        !           233:                         * Closing a stream transmitter involves flushing
        !           234:                         * the last packet, sending an EOF and waiting for
        !           235:                         * it to be acknowledged.  If the connection was
        !           236:                         * bidirectional, the reader should have already
        !           237:                         * read until EOF if everything is to be closed
        !           238:                         * cleanly.
        !           239:                         */
        !           240:                checkfull:
        !           241:                        while (chtfull(conn)) {
        !           242:                                conn->cn_sflags |= CHOWAIT;
        !           243:                                sleep((caddr_t)&conn->cn_thead, CHIOPRIO);
        !           244:                        }
        !           245:                        if (conn->cn_state == CSOPEN ||
        !           246:                            conn->cn_state == CSRFCRCVD) {
        !           247:                                if (conn->cn_toutput) {
        !           248:                                        ch_sflush(conn);
        !           249:                                        goto checkfull;
        !           250:                                }
        !           251:                                if (conn->cn_state == CSOPEN)
        !           252:                                        (void)ch_eof(conn);
        !           253:                        }
        !           254:                        while (!chtempty(conn)) {
        !           255:                                conn->cn_sflags |= CHOWAIT;
        !           256:                                sleep((caddr_t)&conn->cn_thead, CHIOPRIO);
        !           257:                        }
        !           258:                } else if (conn->cn_state == CSOPEN) {
        !           259:                        /*
        !           260:                         * If we are only reading then we should read the EOF
        !           261:                         * before closing and wiat for the other end to close.
        !           262:                         */
        !           263:                        if (conn->cn_flags & CHEOFSEEN)
        !           264:                                while (conn->cn_state == CSOPEN)
        !           265:                                        sleep((caddr_t)conn, CHIOPRIO);
        !           266:                }
        !           267:        recclose:
        !           268:                spl0();
        !           269:                /* Fall into... */
        !           270:        case CHRECORD:  /* Record oriented close is just sending a CLOSE */
        !           271:                if (conn->cn_state == CSOPEN) {
        !           272:                        pkt = pkalloc(0, 0);
        !           273:                        if (pkt != NOPKT) {
        !           274:                                pkt->pk_op = CLSOP;
        !           275:                                pkt->pk_len = 0;
        !           276:                        }
        !           277:                        ch_close(conn, pkt, 0);
        !           278:                }
        !           279:        }
        !           280: shut:
        !           281:        spl0();
        !           282:        ch_close(conn, NOPKT, 1);
        !           283:        ch_buffree();
        !           284: }
        !           285: /*
        !           286:  * Raw read routine.
        !           287:  */
        !           288: chrread(dev)
        !           289: dev_t dev;
        !           290: {
        !           291:        register struct connection *conn;
        !           292:        register struct packet *pkt;
        !           293:        register int count, n;
        !           294: 
        !           295:        if(minor(dev) == CHURFCMIN) {
        !           296:                spl6();
        !           297:                while ((pkt = ch_rnext()) == NOPKT) {
        !           298:                        Rfcwaiting++;
        !           299:                        sleep((caddr_t)&Chrfclist, CHIOPRIO);
        !           300:                }
        !           301:                spl0(); 
        !           302:                if (u.u_count < pkt->pk_len)
        !           303:                        u.u_error = EIO;
        !           304:                else
        !           305:                        iomove((caddr_t)pkt->pk_cdata, pkt->pk_len, B_READ);
        !           306:                return;
        !           307:        }
        !           308:        conn = (struct connection *)CHFCONN(getf(u.u_arg[0]));
        !           309: 
        !           310:        switch (conn->cn_mode) {
        !           311:        case CHTTY:
        !           312:                panic("chread on tty");
        !           313:                break;
        !           314:        case CHSTREAM:
        !           315:                for (count = u.u_count; u.u_count != 0; )
        !           316:                        switch (n = ch_sread(conn, (char*)0, u.u_count)) {
        !           317:                        case 0: /* No data to read */
        !           318:                                if (count != u.u_count)
        !           319:                                        return;
        !           320:                                spl6();
        !           321:                                while (chrempty(conn)) {
        !           322:                                        conn->cn_sflags |= CHIWAIT;
        !           323:                                        sleep((char *)&conn->cn_rhead,
        !           324:                                                CHIOPRIO);
        !           325:                                }
        !           326:                                spl0();
        !           327:                                break;
        !           328:                        case CHEOF:
        !           329:                                return;
        !           330:                        default:
        !           331:                                if (n < 0) {
        !           332:                                        u.u_error = EIO;
        !           333:                                        return;
        !           334:                                }
        !           335:                        }
        !           336:                break;
        !           337:        /*
        !           338:         * Record oriented mode gives a one byte packet opcode
        !           339:         * followed by the data in the packet.  The buffer must
        !           340:         * be large enough to fit the data and the opcode, otherwise an
        !           341:         * i/o error results.
        !           342:         */
        !           343:        case CHRECORD:
        !           344:                spl6();
        !           345:                while (chrempty(conn)) {
        !           346:                        conn->cn_sflags |= CHIWAIT;
        !           347:                        sleep((char *)&conn->cn_rhead,
        !           348:                                CHIOPRIO);
        !           349:                }
        !           350:                spl0();
        !           351:                if ((pkt = conn->cn_rhead) == NOPKT ||
        !           352:                    pkt->pk_len + 1 > u.u_count)        /* + 1 for opcode */
        !           353:                        u.u_error = EIO;
        !           354:                else {
        !           355:                        iomove((caddr_t)&pkt->pk_op, 1, B_READ);
        !           356:                        iomove((caddr_t)pkt->pk_cdata, pkt->pk_len, B_READ);
        !           357:                        spl6();
        !           358:                        ch_read(conn);
        !           359:                        spl0();
        !           360:                }
        !           361:        }
        !           362: }
        !           363: /*
        !           364:  * Raw write routine
        !           365:  * Note that user programs can write to a connection
        !           366:  * that has been CHIOCANSWER"'d, implying transmission of an ANS packet
        !           367:  * rather than a normal packet.  This is illegal for TTY mode connections,
        !           368:  * is handled in the system independent stream code for STREAM mode, and
        !           369:  * is handled here for RECORD mode.
        !           370:  */
        !           371: chrwrite(dev)
        !           372: dev_t dev;
        !           373: {
        !           374:        register struct connection *conn;
        !           375:        
        !           376:        if(minor(dev) == CHURFCMIN) {
        !           377:                u.u_error = EIO;
        !           378:                return;
        !           379:        }
        !           380:        conn = (struct connection *)CHFCONN(getf(u.u_arg[0]));
        !           381:        chwrite(conn);
        !           382: }
        !           383: chwrite(conn)
        !           384:        register struct connection *conn;
        !           385: {
        !           386:        register struct packet *pkt;
        !           387:        register int n;
        !           388:        
        !           389:        if (conn->cn_rhead != NOPKT && conn->cn_rhead->pk_op == RFCOP) {
        !           390:                spl6();
        !           391:                ch_read(conn);
        !           392:                spl0();
        !           393:        }
        !           394:        switch (conn->cn_mode) {
        !           395:        case CHTTY:
        !           396:                /* Fall into (on RAW mode only) */
        !           397:        case CHSTREAM:
        !           398:                while (u.u_count != 0)
        !           399:                        switch (n = ch_swrite(conn, (char *)0, u.u_count)) {
        !           400:                        case 0:
        !           401:                                spl6();
        !           402:                                while (chtfull(conn)) {
        !           403:                                        conn->cn_sflags |= CHOWAIT;
        !           404:                                        sleep((caddr_t)&conn->cn_thead,
        !           405:                                                CHIOPRIO);
        !           406:                                }
        !           407:                                spl0();
        !           408:                                break;
        !           409:                        case CHTEMP:
        !           410:                                sleep((caddr_t)&lbolt, CHIOPRIO);
        !           411:                                break;
        !           412:                        default:
        !           413:                                if (n < 0) {
        !           414:                                        u.u_error = EIO;
        !           415:                                        return;
        !           416:                                }
        !           417:                        }
        !           418:                break;
        !           419:        case CHRECORD:  /* one write call -> one packet */
        !           420:                if (u.u_count < 1 || u.u_count - 1 > CHMAXDATA) {
        !           421:                        u.u_error = EIO;
        !           422:                        return;
        !           423:                }
        !           424:        loop:
        !           425:                spl6();
        !           426:                while (chtfull(conn)) {
        !           427:                        conn->cn_sflags |= CHOWAIT;
        !           428:                        sleep((caddr_t)&conn->cn_thead, CHIOPRIO);
        !           429:                }
        !           430:                spl0();
        !           431:                if ((pkt = pkalloc((int)(u.u_count - 1), 0)) == NOPKT) {
        !           432:                        sleep((caddr_t)&lbolt, CHIOPRIO);
        !           433:                        goto loop;
        !           434:                }
        !           435:                iomove(&pkt->pk_op, 1, B_WRITE);
        !           436:                pkt->pk_len = u.u_count;
        !           437:                if (u.u_count)
        !           438:                        iomove(pkt->pk_cdata, u.u_count, B_WRITE);
        !           439:                if (u.u_error == 0) {
        !           440:                        spl6();
        !           441:                        if (ch_write(conn, pkt))
        !           442:                                u.u_error = EIO;
        !           443:                        spl0();
        !           444:                }
        !           445:        }
        !           446: }
        !           447: 
        !           448: /*
        !           449:  * This routine allocates a packet and fills it with data from pointer in
        !           450:  * user space until null or CHMAXDATA characters
        !           451:  */
        !           452: static struct packet *
        !           453: fillpacket(str, len)
        !           454: register char *str;
        !           455: int len;       /* assumed <= CHMAXDATA */
        !           456: {
        !           457:        register char *ptr;
        !           458:        register struct packet *pkt;
        !           459:        int c;
        !           460:        extern uchar();
        !           461: 
        !           462:        if ((pkt = pkalloc(CHMAXDATA, 0)) != NOPKT) {
        !           463:                ptr = pkt->pk_cdata;
        !           464:                for (pkt->pk_len = 0; *str != '\0' && pkt->pk_len < len; pkt->pk_len++)
        !           465:                        *ptr++ = *str++;
        !           466:                while ((c = uchar()) > 0 && pkt->pk_len < CHMAXDATA) {
        !           467:                        *ptr++ = c;
        !           468:                        pkt->pk_len++;
        !           469:                }
        !           470:                if (c > 0) {
        !           471:                        debug(DABNOR,
        !           472:                                printf("Fillpacket too long: %s\n",
        !           473:                                        pkt->pk_cdata));
        !           474:                        ch_free((char *)pkt);
        !           475:                } else
        !           476:                        return(pkt);
        !           477:        }
        !           478:        u.u_error = ENXIO;
        !           479:        return(NOPKT);
        !           480: }
        !           481: /*
        !           482:  * This is atoi from users space terminates on / or null.
        !           483:  * If cpp is not NULL then get the number from *cpp (u.u_dbuf).
        !           484:  * *cpp is stuffed where the scan stopped, enabling further usage of the
        !           485:  * contents of u.u_dbuf.
        !           486:  */
        !           487: static
        !           488: uatoi(cpp)
        !           489: char **cpp;
        !           490: {
        !           491:        register char *p = cpp ? *cpp - 1 : (char *)0;
        !           492:        register int i = 0, chr;
        !           493:        extern uchar();
        !           494: 
        !           495:        for (;;) {
        !           496:                if (p)
        !           497:                        if (++p >= &u.u_dbuf[DIRSIZ])
        !           498:                                break;
        !           499:                        else
        !           500:                                chr = *p;
        !           501:                else if ((chr = uchar()) == '/')
        !           502:                        break;
        !           503:                if ((chr -= '0') < 0 || chr > 9)
        !           504:                        break;
        !           505:                i *= 10;
        !           506:                i += chr;
        !           507:        }
        !           508:        if (cpp)
        !           509:                *cpp = p;
        !           510:        return(i);
        !           511: }
        !           512: 
        !           513: /*
        !           514:  * Raw ioctl routine - perform non-connection functions, otherwise call down
        !           515:  */
        !           516: chrioctl(dev, cmd, addr, flag)
        !           517: register int cmd;
        !           518: caddr_t addr;
        !           519: {
        !           520:        register char *cp;
        !           521:        register int c;
        !           522: 
        !           523:        switch (cmd) {
        !           524:        /*
        !           525:         * Skip the first unmatched RFC at the head of the queue
        !           526:         * and mark it so that ch_rnext will never pick it up again.
        !           527:         */
        !           528:        case CHIOCRSKIP:
        !           529:                if (minor(dev) != CHURFCMIN)
        !           530:                        break;
        !           531:                spl6();
        !           532:                ch_rskip();
        !           533:                spl0();
        !           534:                return;
        !           535:        /*
        !           536:         * Specify the chaosnet address of an interlan ethernet interface.
        !           537:         */
        !           538:        case CHIOCILADDR:
        !           539:                if (minor(dev) != CHURFCMIN)
        !           540:                        break;
        !           541: #if NCHIL > 0
        !           542:                {
        !           543:                        struct chiladdr ca;
        !           544: 
        !           545:                        if (addr == 0 || copyin(addr, (caddr_t)&ca, sizeof(ca)))
        !           546:                                break;
        !           547:                        if (chilseta(ca.cil_device, ca.cil_address))
        !           548:                                break;
        !           549:                        return;
        !           550:                }
        !           551: #else
        !           552:                break;
        !           553: #endif
        !           554:        case CHIOCNAME:
        !           555:                if (minor(dev) != CHURFCMIN)
        !           556:                        break;
        !           557:                for (cp = Chmyname; c = fubyte(addr); *cp++ = c, addr++)
        !           558:                        if (c < 0) {
        !           559:                                cp = Chmyname;
        !           560:                                u.u_error = EFAULT;
        !           561:                                break;
        !           562:                        } else if(cp >= &Chmyname[CHSTATNAME])
        !           563:                                break;
        !           564:                while (cp < &Chmyname[CHSTATNAME])
        !           565:                        *cp++ = '\0';
        !           566:                if (c >= 0)
        !           567:                        return;
        !           568:                break;
        !           569:        /*
        !           570:         * Specify my own network number.
        !           571:         */
        !           572:        case CHIOCADDR:
        !           573:                if (minor(dev) != CHURFCMIN)
        !           574:                        break;
        !           575:                Chmyaddr = (int)addr;
        !           576:                return;
        !           577:        default:
        !           578:                if (minor(dev) == CHURFCMIN)
        !           579:                        break;
        !           580:                chioctl(CHFCONN(getf(u.u_arg[0])), dev, cmd, addr, flag);
        !           581:                return;
        !           582:        }
        !           583:        u.u_error = ENXIO;
        !           584: }
        !           585: /* ARGSUSED */
        !           586: chioctl(conn, dev, cmd, addr, flag)
        !           587: register struct connection *conn;
        !           588: dev_t dev;
        !           589: caddr_t addr;
        !           590: {
        !           591:        register struct packet *pkt;
        !           592:        struct chstatus chst;
        !           593: 
        !           594:        switch(cmd) {
        !           595:        /*
        !           596:         * Read the first packet in the read queue for a connection.
        !           597:         * This call is primarily intended for those who want to read
        !           598:         * non-data packets (which are normally ignored) like RFC
        !           599:         * (for arguments in the contact string), CLS (for error string) etc.
        !           600:         * The reader's buffer is assumed to be CHMAXDATA long.  When ioctl's
        !           601:         * change on the VAX to have data length arguments, this will be done
        !           602:         * right. An error results if there is no packet to read.
        !           603:         * No hanging is currently provided for.
        !           604:         * The normal mode of operation for reading such packets is to
        !           605:         * first do a CHIOCGSTAT call to find out whether there is a packet
        !           606:         * to read (and what kind) and then make this call - except for
        !           607:         * RFC's when you know it must be there.
        !           608:         */     
        !           609:        case CHIOCPREAD:
        !           610:                if ((pkt = conn->cn_rhead) == NULL)
        !           611:                        break;
        !           612:                if (copyout((caddr_t)pkt->pk_cdata, addr, pkt->pk_len))
        !           613:                        break;
        !           614:                spl6();
        !           615:                ch_read(conn);
        !           616:                spl0();
        !           617:                return;
        !           618:        /*
        !           619:         * Change the mode of the connection.
        !           620:         * The default mode is CHSTREAM.
        !           621:         */
        !           622:        case CHIOCSMODE:
        !           623:                switch ((int)addr) {
        !           624:                case CHTTY:
        !           625: #if NCHT > 0
        !           626:                        if (conn->cn_state == CSOPEN &&
        !           627:                            conn->cn_mode != CHTTY) {
        !           628:                                register struct tty *tp;
        !           629:                                extern struct tty cht_tty[];
        !           630:                                extern int cht_cnt;
        !           631:                                /*
        !           632:                                 * To turn a connection into a tty,
        !           633:                                 * we need to find a tty that is waiting to
        !           634:                                 * be opened and connect ourselves to it.
        !           635:                                 */
        !           636:                                 for (tp = cht_tty; tp < &cht_tty[cht_cnt]; tp++)
        !           637:                                        if (tp->t_addr == 0 &&
        !           638:                                            tp->t_state & WOPEN) {
        !           639:                                                tp->t_addr = (caddr_t)conn;
        !           640:                                                tp->t_state |= CARR_ON;
        !           641:                                                conn->cn_ttyp = tp;
        !           642:                                                conn->cn_mode = CHTTY;
        !           643:                                                wakeup((caddr_t)&tp->t_rawq);
        !           644:                                                return;
        !           645:                                        }
        !           646: 
        !           647:                        }
        !           648: #endif
        !           649:                        break;
        !           650:                case CHSTREAM:
        !           651:                case CHRECORD:
        !           652:                        if (conn->cn_mode == CHTTY)
        !           653:                                break;
        !           654:                        conn->cn_mode = (int)addr;
        !           655:                        return;
        !           656:                }
        !           657:                break;
        !           658:        /*
        !           659:         * Flush the current output packet if there is one.
        !           660:         * This is only valid in stream mode.
        !           661:         * If the argument is non-zero an error is returned if the
        !           662:         * transmit window is full, otherwise we hang.
        !           663:         */
        !           664:        case CHIOCFLUSH:
        !           665:                if (conn->cn_mode == CHSTREAM) {
        !           666:                        spl6();
        !           667:                        while ((flag = ch_sflush(conn)) == CHTEMP)
        !           668:                                if (addr)
        !           669:                                        break;
        !           670:                                else {
        !           671:                                        conn->cn_sflags |= CHOWAIT;
        !           672:                                        sleep((caddr_t)&conn->cn_thead,
        !           673:                                                CHIOPRIO);
        !           674:                                }
        !           675:                        if (flag)
        !           676:                                u.u_error = EIO;
        !           677:                        spl0();
        !           678:                        return;                 
        !           679:                }
        !           680:                break;
        !           681:        /*
        !           682:         * Wait for all output to be acknowledged.  If addr is non-zero
        !           683:         * an EOF packet is also sent before waiting.
        !           684:         * If in stream mode, output is flushed first.
        !           685:         */
        !           686:        case CHIOCOWAIT:
        !           687:                if (conn->cn_mode == CHSTREAM) {
        !           688:                        spl6();
        !           689:                        while ((flag = ch_sflush(conn)) == CHTEMP) {
        !           690:                                conn->cn_sflags |= CHOWAIT;
        !           691:                                sleep((caddr_t)&conn->cn_thead, CHIOPRIO);
        !           692:                        }
        !           693:                        spl0();
        !           694:                        if (flag) {
        !           695:                                u.u_error = EIO;
        !           696:                                return;
        !           697:                        }
        !           698:                }
        !           699:                if (addr) {
        !           700:                        spl6();
        !           701:                        while (chtfull(conn)) {
        !           702:                                conn->cn_sflags |= CHOWAIT;
        !           703:                                sleep((caddr_t)&conn->cn_thead, CHIOPRIO);
        !           704:                        }
        !           705:                        flag = ch_eof(conn);
        !           706:                        spl0();
        !           707:                        if (flag) {
        !           708:                                u.u_error = EIO;
        !           709:                                return;
        !           710:                        }
        !           711:                }
        !           712:                spl6();
        !           713:                while (!chtempty(conn)) {
        !           714:                        conn->cn_sflags |= CHOWAIT;
        !           715:                        sleep((caddr_t)&conn->cn_thead, CHIOPRIO);
        !           716:                }
        !           717:                spl0();
        !           718:                if (conn->cn_state != CSOPEN)
        !           719:                        u.u_error = EIO;
        !           720:                return;
        !           721:        /*
        !           722:         * Return the status of the connection in a structure supplied
        !           723:         * by the user program.
        !           724:         */
        !           725:        case CHIOCGSTAT:
        !           726:                chst.st_fhost = conn->cn_faddr;
        !           727:                chst.st_cnum = conn->cn_ltidx;
        !           728:                chst.st_rwsize = conn->cn_rwsize;
        !           729:                chst.st_twsize = conn->cn_twsize;
        !           730:                chst.st_state = conn->cn_state;
        !           731:                chst.st_cmode = conn->cn_mode;
        !           732:                chst.st_oroom = conn->cn_twsize - (conn->cn_tlast - conn->cn_tacked);
        !           733:                if ((pkt = conn->cn_rhead) != NOPKT) {
        !           734:                        chst.st_ptype = pkt->pk_op;
        !           735:                        chst.st_plength = pkt->pk_len;
        !           736:                } else {
        !           737:                        chst.st_ptype = 0;
        !           738:                        chst.st_plength = 0;
        !           739:                }
        !           740:                if (copyout((caddr_t)&chst, addr, sizeof(chst)))
        !           741:                        break;
        !           742:                return;
        !           743:        /*
        !           744:         * Wait for the state of the connection to be different from
        !           745:         * the given state.
        !           746:         */
        !           747:        case CHIOCSWAIT:
        !           748:                spl6();
        !           749:                while (conn->cn_state == (int)addr)
        !           750:                        sleep((caddr_t)conn, CHIOPRIO);
        !           751:                spl0();
        !           752:                return;
        !           753:        /*
        !           754:         * Answer an RFC.  Basically this call does nothing except
        !           755:         * setting a bit that says this connection should be of the
        !           756:         * datagram variety so that the connection automatically gets
        !           757:         * closed after the first write, whose data is immediately sent
        !           758:         * in an ANS packet.
        !           759:         */
        !           760:        case CHIOCANSWER:
        !           761:                spl6();
        !           762:                if (conn->cn_state == CSRFCRCVD && conn->cn_mode != CHTTY)
        !           763:                        conn->cn_flags |= CHANSWER;
        !           764:                else
        !           765:                        u.u_error = EIO;
        !           766:                spl0();
        !           767:                return;
        !           768:        /*
        !           769:         * Reject a RFC, giving a string (null terminated), to put in the
        !           770:         * close packet.  This call can also be used to shut down a connection
        !           771:         * prematurely giving an ascii close reason.
        !           772:         */
        !           773:        case CHIOCREJECT:
        !           774:                spl6();
        !           775:                if (conn->cn_state == CSRFCRCVD || conn->cn_state == CSOPEN) {
        !           776:                        u.u_dirp = addr;        /* a kludge for fillpacket */
        !           777:                        pkt = fillpacket("", 0);
        !           778:                        pkt->pk_op = CLSOP;
        !           779:                        ch_close(conn, pkt, 0);
        !           780:                } else
        !           781:                        u.u_error = EIO;
        !           782:                spl0();
        !           783:                return;
        !           784:        /*
        !           785:         * Accept an RFC causing the OPEN packet to be sent
        !           786:         */
        !           787:        case CHIOCACCEPT:
        !           788:                spl6();
        !           789:                if (conn->cn_state == CSRFCRCVD)
        !           790:                        ch_accept(conn);
        !           791:                else
        !           792:                        u.u_error = EIO;
        !           793:                spl0();
        !           794:                return;
        !           795:        /*
        !           796:         * Count how many bytes can be immediately read.
        !           797:         */
        !           798:        case FIONREAD:
        !           799:                if (conn->cn_mode != CHTTY) {
        !           800:                        off_t nread = 0;
        !           801: 
        !           802:                        for (pkt = conn->cn_rhead; pkt != NOPKT; pkt = pkt->pk_next)
        !           803:                                if (ISDATOP(pkt))
        !           804:                                        nread += pkt->pk_len;
        !           805:                        if (conn->cn_rhead != NOPKT)
        !           806:                                nread -= conn->cn_roffset;
        !           807:                        if (copyout((caddr_t)&nread, addr, sizeof(off_t)))
        !           808:                                u.u_error = EFAULT;
        !           809:                        return;
        !           810:                }
        !           811:        default:
        !           812:                break;
        !           813:        }
        !           814:        u.u_error = ENXIO;
        !           815: }
        !           816: /*
        !           817:  * Timeout routine that implements the chaosnet clock process.
        !           818:  */
        !           819: chtimeout()
        !           820: {
        !           821:        register int s = spl6();
        !           822:        ch_clock();
        !           823:        timeout(chtimeout, 0, 1);
        !           824:        splx(s);
        !           825: }

unix.superglobalmegacorp.com

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