Annotation of researchv8dc/sys/chunix/chaos.c, revision 1.1.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.