Annotation of researchv8dc/sys/chaosld/chaos_device.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *             C H A O S _ D E V I C E
                      3:  *
                      4:  * Chaosnet pseudo-device.  This is the multiplexer/demultiplexer
                      5:  * used in conjunction with the Chaosnet line discipline.
                      6:  *
                      7:  *
                      8:  * (c) Copyright 1985  Nirvonics, Inc.
                      9:  *
                     10:  * Written by Kurt Gollhardt
                     11:  * Last update Thu Mar 14 16:03:34 1985
                     12:  *
                     13:  * This software is the property of Nirvonics, Inc.
                     14:  * All rights reserved.
                     15:  *
                     16:  */
                     17: 
                     18: #include "ch.h"
                     19: #if NCH > 0
                     20: #include "../h/param.h"
                     21: #include "../h/systm.h"
                     22: #include "../h/stream.h"
                     23: #include "../h/ioctl.h"
                     24: #include "../h/ttyld.h"
                     25: #include "../h/buf.h"
                     26: #include "../h/conf.h"
                     27: #include "../h/dir.h"
                     28: #include "../h/user.h"
                     29: #include "../chaosld/types.h"
                     30: #include "../chaosld/constants.h"
                     31: #include "../chaosld/globals.h"
                     32: 
                     33: #define CHIOPRIO    (PZERO+1)      /* Just interruptible */
                     34: 
                     35: int NCh = NCH; /* For peeking */
                     36: int NChopen;
                     37: 
                     38: int  nodev(), chdopen(), chdclose(), chdput(), chdosrv();
                     39: static struct qinit chdrinit = { nodev, NULL, chdopen, chdclose, 0, 0 },
                     40:               chdwinit = { chdput, chdosrv, chdopen, chdclose, 1024, 129 };
                     41: struct streamtab chdinfo = { &chdrinit, &chdwinit };
                     42: 
                     43: 
                     44: chdopen(q, dev)
                     45:      register struct queue    *q;
                     46:      dev_t                    dev;
                     47: {
                     48:      dev = minor(dev);
                     49: 
                     50:      if (ChaosQ == (struct queue *)0)   /* Make sure line-discipline is on */
                     51:           return 0;
                     52:      if (dev > NCH || Chconn[dev] != NOCONN)
                     53:           return 0;
                     54:      if ((Chconn[dev] = new_conn(dev)) == NOCONN)
                     55:           return 0;
                     56: 
                     57:      NChopen++;
                     58:      Chconn[dev]->cn_rdq = q;
                     59:      Chconn[dev]->cn_state |= CSSTARTING;
                     60:      q->ptr = WR(q)->ptr = (caddr_t)Chconn[dev];
                     61:      q->flag |= QDELIM;
                     62:      WR(q)->flag |= QNOENB|QBIGB;
                     63: 
                     64:      if (!Chtimer)
                     65:          ch_timer();
                     66: 
                     67:      return 1;
                     68: }
                     69: 
                     70: chdclose(q)
                     71:      struct queue   *q;
                     72: {
                     73:      register struct connection    *conn;
                     74:      register struct packet   *pkt;
                     75:      int       ps;
                     76: 
                     77:      if ((conn = (struct connection *)q->ptr) == NOCONN)
                     78:           return;
                     79:      conn->cn_time = Chclock;
                     80: 
                     81:      switch (conn->cn_mode) {
                     82:           case CHSTREAM:
                     83:               ps = spl6();
                     84:                if (setjmp(u.u_qsav)) {
                     85:                     if ((pkt = new_packet()) != NOPKT) {
                     86:                          pkt->pk_op = CLSOP;
                     87:                         append_packet(pkt, "User interrupted", 16);
                     88:                    }
                     89:                     chld_close(conn, pkt);
                     90:                     goto shut;
                     91:                }
                     92:                if (conn->cn_flags & CHWRITER) {
                     93:                     /*
                     94:                      * We set this flag telling the interrupt time
                     95:                      * receiver to abort the connection if any new packets
                     96:                      * arrive.
                     97:                      */
                     98:                     conn->cn_sflags |= CHCLOSING;
                     99:                     /*
                    100:                      * Closing a stream transmitter involves flushing
                    101:                      * the last packet, sending an EOF and waiting for
                    102:                      * it to be acknowledged.  If the connection was
                    103:                      * bidirectional, the reader should have already
                    104:                      * read until EOF if everything is to be closed
                    105:                      * cleanly.
                    106:                      */
                    107:                     if (conn->cn_state == CSOPEN ||
                    108:                               conn->cn_state == CSRFCRCVD) {
                    109:                          if (conn->cn_toutput) {
                    110:                               chld_write(conn, conn->cn_toutput);
                    111:                              conn->cn_toutput = NULL;
                    112:                          }
                    113:                          if (conn->cn_state == CSOPEN)
                    114:                               chld_eof(conn);
                    115:                     }
                    116:                     while (!chtempty(conn)) {
                    117:                          conn->cn_sflags |= CHOWAIT;
                    118:                          sleep((caddr_t)&conn->cn_thead, CHIOPRIO);
                    119:                     }
                    120:                    if (conn->cn_flags & CHREADER) {
                    121:                         if (conn->cn_flags & CHSERVER)
                    122:                              chld_eof(conn);
                    123:                          else
                    124:                              goto close_wait;
                    125:                     }
                    126:                } else if (conn->cn_state == CSOPEN) {
                    127:                     /*
                    128:                      * If we are only reading then we should read the EOF
                    129:                      * before closing and wait for the other end to close.
                    130:                      */
                    131: close_wait:
                    132:                     if (conn->cn_flags & CHEOFSEEN)
                    133:                          while (conn->cn_state == CSOPEN)
                    134:                               sleep((caddr_t)conn, CHIOPRIO);
                    135:                }
                    136:                splx(ps);
                    137:                /* Fall into... */
                    138:           case CHRECORD: /* Record oriented close is just sending a CLOSE */
                    139:                if (conn->cn_state == CSOPEN) {
                    140:                     if ((pkt = new_packet()) != NOPKT)
                    141:                          pkt->pk_op = CLSOP;
                    142:                     chld_close(conn, pkt);
                    143:                }
                    144:      }
                    145: shut:
                    146:      chld_close(conn, NOPKT);
                    147: 
                    148:      free_conn(conn);
                    149:      q->ptr = (caddr_t)0;
                    150:      --NChopen;
                    151: }
                    152: 
                    153: chdstart(q, conn)
                    154:      register struct queue         *q;
                    155:      register struct connection    *conn;
                    156: {
                    157:      register struct packet   *pkt;
                    158:      register struct block    *bp;
                    159:      register struct chopen   *c;
                    160:      int       len, rwsize, err, ps;
                    161: 
                    162:      err = 0;
                    163:      conn->cn_sflags |= CHOPNWAIT;
                    164:      if (block_pullup(q, sizeof(struct chopen)) == 0) {
                    165:           err = EINVAL;
                    166:          goto flush;
                    167:      }
                    168:      c = (struct chopen *)q->first->rptr;
                    169: 
                    170:      len = c->co_clength + c->co_length + (c->co_length? 1 : 0);
                    171:      if (len > CHMAXPKT || c->co_clength <= 0) {
                    172:          err = E2BIG;
                    173: flush:
                    174:           flush_packet(q);
                    175:          goto out;
                    176:      }
                    177:      if (block_pullup(q, len + sizeof(struct chopen)) == 0) {
                    178:           err = EINVAL;
                    179:          goto flush;
                    180:      }
                    181:      bp = getq(q);
                    182:      flush_packet(q);
                    183:      c = (struct chopen *)bp->rptr;
                    184: 
                    185:      if ((pkt = new_packet()) == NOPKT) {
                    186:           err = ENOMEM;
                    187:          goto out;
                    188:      }
                    189:      append_packet(pkt, bp->rptr += sizeof(struct chopen), c->co_clength);
                    190:      if (c->co_length) {
                    191:           append_packet(pkt, " ", 1);
                    192:           append_packet(pkt, bp->rptr += c->co_clength, c->co_length);
                    193:      }
                    194: 
                    195:      conn->cn_mode = c->co_mode;
                    196:      if (c->co_mode == CHSTREAM)
                    197:          RD(q)->flag &= ~QDELIM;
                    198:      rwsize = (c->co_rwsize ? c->co_rwsize : CHDRWSIZE);
                    199:      if (c->co_host)
                    200:           chld_open(conn, c->co_host, rwsize, pkt);
                    201:      else
                    202:           chld_listen(conn, rwsize, pkt);
                    203: 
                    204: out:
                    205:      ps = spl6();
                    206:      if (conn->cn_sflags & CHOPNWAIT) {
                    207:          if (c->co_async || err)
                    208:               chdoreply(conn, err, NOPKT, c->co_async);
                    209:      }
                    210:      splx(ps);
                    211: }
                    212: 
                    213: chdoreply(conn, err, pkt, async)
                    214:      struct connection   *conn;
                    215:      struct packet       *pkt;
                    216: {
                    217:      struct choreply     c;
                    218:      struct queue        *q;
                    219: 
                    220:      conn->cn_sflags &= ~CHOPNWAIT;
                    221:      q = conn->cn_rdq;
                    222: 
                    223:      if (err == 0 && !async) {
                    224:          if (conn->cn_flags & CHSERVER) {
                    225:               if (conn->cn_state != CSRFCRCVD)
                    226:                    err = EIO;
                    227:          } else {
                    228:               if (conn->cn_state != CSOPEN &&
                    229:                         (conn->cn_state != CSCLOSED ||
                    230:                              pkt == NOPKT || pkt->pk_op != ANSOP))
                    231:                    err = EIO;
                    232:          }
                    233:      }
                    234:      c.errno = err;
                    235:      putcpy(q->next, &c, sizeof(c));
                    236:      putctl(q->next, M_DELIM);
                    237: }
                    238: 
                    239: chdput(q, bp)
                    240:      register struct queue    *q;
                    241:      register struct block    *bp;
                    242: {
                    243:      switch(bp->type){
                    244:           case M_IOCTL:
                    245:                chdioctl(q, bp);
                    246:                break;
                    247:           case M_DATA:
                    248:                putq(q, bp);
                    249:                break;
                    250:           case M_DELIM:
                    251:                putq(q, bp);
                    252:               if (!(((struct connection *)q->ptr)->cn_sflags & CHOQWAIT))
                    253:                    qenable(q);
                    254:                break;
                    255:           default:
                    256:                freeb(bp);
                    257:                break;
                    258:      }
                    259: }
                    260: 
                    261: chdioctl(q, bp)
                    262:      register struct queue    *q;
                    263:      register struct block    *bp;
                    264: {
                    265:      register struct connection    *conn;
                    266:      register struct packet   *pkt;
                    267:      union stmsg    *sp;
                    268:      int       ps, len;
                    269: 
                    270:      sp = (union stmsg *)(bp->rptr);
                    271:      if ((conn = (struct connection *)q->ptr) == NOCONN)
                    272:           goto bad;
                    273:      bp->type = M_IOCACK;
                    274: 
                    275:      switch(sp->ioc0.com){
                    276:           case CHIOCRPKT:
                    277:               /* Read a packet that would normally be discarded.
                    278:                * This is typically used to read the error message
                    279:                * given with a CLS packet, or to look at the contact
                    280:                * string for a listener.
                    281:                * The ioctl returns 2 bytes for the opcode, 2 bytes for
                    282:                * the (data) length, and the bytes of data.
                    283:                */
                    284:                ps = spl6();
                    285:               if ((pkt = conn->cn_expkt) == NOPKT || flatten(pkt))
                    286:                    break;
                    287:               conn->cn_expkt = NULL;
                    288:                splx(ps);
                    289:                len = pkt->pk_len + 4 + sizeof(sp->ioc0.com);
                    290:               if (bp->lim - bp->base < len) {
                    291:                    freeb(bp);
                    292:                    if ((bp = allocb(len)) == NOBLOCK
                    293:                              || bp->lim - bp->base < len)
                    294:                          break;
                    295:                     bp->type = M_IOCACK;
                    296:                }
                    297:               sp = (union stmsg *)(bp->rptr = bp->base);
                    298:               bp->wptr = bp->rptr + len;
                    299:               sp->ioc0.com = CHIOCRPKT;
                    300:               *(short *)(&sp->iocx.xxx[0]) = pkt->pk_op;
                    301:               *(short *)(&sp->iocx.xxx[2]) = pkt->pk_len;
                    302:               bcopy(pkt->data->rptr, &sp->iocx.xxx[4], pkt->pk_len);
                    303:               free_packet(pkt);
                    304:               goto reply;
                    305:           case CHIOCFLUSH:
                    306:               /* Flush the current output packet if there is one.
                    307:                * Applicable in stream mode only.
                    308:                */
                    309:               if (conn->cn_toutput != NOPKT) {
                    310:                    chld_write(conn, conn->cn_toutput);
                    311:                    conn->cn_toutput = NULL;
                    312:                }
                    313:               goto noreply;
                    314:           case CHIOCOWAIT:
                    315:                /* Wait for all output to be acknowledged.
                    316:                * If in stream mode, any pending output is flushed first.
                    317:                * If *addr is non-zero, an EOF is also sent before waiting.
                    318:                */
                    319:               if (conn->cn_toutput != NOPKT) {
                    320:                    chld_write(conn, conn->cn_toutput);
                    321:                    conn->cn_toutput = NULL;
                    322:                }
                    323:                if (sp->iocx.xxx[0])
                    324:                    chld_eof(conn);
                    325:                ps = spl6();
                    326:               if (chtempty(conn)) {
                    327:                    /* already empty */
                    328:                    splx(ps);
                    329:                    goto noreply;
                    330:               }
                    331:               conn->cn_sflags |= CHEMPWAIT;
                    332:               conn->cn_wait = bp;
                    333:               splx(ps);
                    334:               return;
                    335:           case CHIOCGSTAT:
                    336:               /* Return the status of the connection */
                    337:               ps = spl6();
                    338:               {
                    339:                    register struct chstatus *chst;
                    340: 
                    341:                     chst = (struct chstatus *)sp->iocx.xxx;
                    342:                    chst->st_fhost = conn->cn_faddr.ch_addr;
                    343:                    chst->st_cnum = conn->cn_lidx.ci_tidx;
                    344:                    chst->st_rwsize = conn->cn_rwsize;
                    345:                    chst->st_twsize = conn->cn_twsize;
                    346:                    chst->st_state = conn->cn_state;
                    347:                    chst->st_cmode = conn->cn_mode;
                    348:                    chst->st_oroom = conn->cn_twsize -
                    349:                                        (conn->cn_tlast - conn->cn_tacked);
                    350:                     chst->st_ptype = chst->st_plength = 0;
                    351:                    bp->wptr = (u_char *)(chst + 1);
                    352:                }
                    353:               splx(ps);
                    354:               goto reply;
                    355:           case CHIOCSWAIT:
                    356:               /* Wait for the state of the connection to be different
                    357:                * from the given state.
                    358:                */
                    359:               ps = spl6();
                    360:               if (conn->cn_state != *(int *)sp->iocx.xxx) {
                    361:                    /* already out of the given state */
                    362:                    splx(ps);
                    363:                    goto noreply;
                    364:               }
                    365:               conn->cn_sflags |= CHSWAIT;
                    366:               conn->cn_wait = bp;
                    367:               splx(ps);
                    368:               return;
                    369:           case CHIOCANSWER:
                    370:               /* Answer an RFC.  This sets a bit saying the next write
                    371:                * call should send an ANS packet and close the connection.
                    372:                */
                    373:                if (conn->cn_state == CSRFCRCVD) {
                    374:                    conn->cn_flags |= CHANSWER;
                    375:                    goto noreply;
                    376:                }
                    377:               break;
                    378:           case CHIOCREJECT:
                    379:               /* Reject an RFC.  This closes the connection with a CLS
                    380:                * packet containing an error message string.  The user
                    381:                * passes in a structure containing a pointer to the error
                    382:                * message (reason) and its length.
                    383:                */
                    384:               {
                    385:                    register struct chreject *cr;
                    386:                     int       flag, c;
                    387: 
                    388:                     cr = (struct chreject *)sp->iocx.xxx;
                    389:                    pkt = NOPKT;
                    390:                    flag = 0;
                    391:                    if (cr->cr_length > 0 && cr->cr_length <= CHMAXPKT) {
                    392:                         if ((pkt = new_packet()) == NOPKT)
                    393:                              ++flag;
                    394:                         else {
                    395:                              pkt->pk_op = CLSOP;
                    396:                               while (cr->cr_length-- > 0) {
                    397:                                   if ((c = fubyte(cr->cr_reason++)) < 0)
                    398:                                        break;
                    399:                                   append_packet(pkt, &c, 1);
                    400:                               }
                    401:                          }
                    402:                     }
                    403:                    chld_close(conn, pkt);
                    404:                    if (flag == 0)
                    405:                         goto noreply;
                    406:                }
                    407:               break;
                    408:           case CHIOCACCEPT:
                    409:               /* Accept an RFC causing the OPN packet to be sent */
                    410:                ps = spl6();
                    411:               if (conn->cn_state == CSRFCRCVD) {
                    412:                    chld_accept(conn);
                    413:                    splx(ps);
                    414:                    goto noreply;
                    415:                }
                    416:               splx(ps);
                    417:               break;
                    418:      }
                    419: 
                    420: bad:
                    421:      bp->type = M_IOCNAK;
                    422: noreply:
                    423:      bp->wptr = bp->rptr;
                    424: reply:
                    425:      qreply(q, bp);
                    426: }
                    427: 
                    428: chdosrv(q)
                    429:      struct queue   *q;
                    430: {
                    431:      register struct block    *bp;
                    432: 
                    433:      if (chdwrite(q))
                    434:          return;
                    435: 
                    436:      /* See if there's another packet on the queue */
                    437:      for (bp = q->first; bp != NOBLOCK; bp = bp->next)
                    438:          if (bp->type == M_DELIM) {
                    439:               qenable(q);    /* re-enable queue for the next packet */
                    440:               break;
                    441:           }
                    442: }
                    443: 
                    444: chdwrite(q)
                    445:      register struct queue    *q;
                    446: {
                    447:      register struct packet   *pkt;
                    448:      register struct block    *bp, *tail;
                    449:      register struct connection        *conn;
                    450:      int       n, ps;
                    451: 
                    452:      if ((conn = (struct connection *)q->ptr) == NOCONN) {
                    453:           flush_packet(q);
                    454:          return 1;
                    455:      }
                    456:      if (conn->cn_state == CSSTARTING) {
                    457:           chdstart(q, conn);
                    458:           return 0;
                    459:      }
                    460:      conn->cn_flags |= CHWRITER;
                    461: 
                    462:      ps = spl6();
                    463:      if (chtfull(conn)) {
                    464:          conn->cn_sflags |= CHOQWAIT;
                    465:          splx(ps);
                    466:          return 1;
                    467:      }
                    468:      splx(ps);
                    469: 
                    470:      switch (conn->cn_mode) {
                    471:           case CHSTREAM:
                    472:                while ((bp = getq(q)) != NOBLOCK) {
                    473:                     if (bp->rptr >= bp->wptr) {
                    474:                          freeb(bp);
                    475:                          continue;
                    476:                     }
                    477:                     if (conn->cn_state != CSOPEN &&
                    478:                               (conn->cn_state != CSRFCRCVD ||
                    479:                                (conn->cn_flags & CHANSWER) == 0)) {
                    480:                          freeb(bp);
                    481:                          flush_packet(q);
                    482:                          return 1;
                    483:                     }
                    484:                     if ((pkt = conn->cn_toutput) == NOPKT) {
                    485:                          if ((pkt = new_packet()) == NOPKT) {
                    486:                               printf("chodsrv: can't allocate packet\n");
                    487:                               return 0;
                    488:                          }
                    489:                          setconn(conn, pkt);
                    490:                          pkt->pk_op = (conn->cn_flags & CHANSWER ?
                    491:                                              ANSOP : DATOP);
                    492:                         conn->cn_toutput = pkt;
                    493:                     }
                    494:                     n = CHMAXDATA - pkt->pk_len;
                    495:                     if (bp->wptr - bp->rptr >= n) {
                    496:                          append_packet(pkt, bp->rptr, n);
                    497:                          bp->rptr += n;
                    498:                          conn->cn_toutput = NOPKT;
                    499:                          if (bp->rptr < bp->wptr)
                    500:                               putbq(q, bp);
                    501:                         chld_write(conn, pkt);
                    502:                     } else {
                    503:                          bp->next = NOBLOCK;
                    504:                          if (pkt->data == NOBLOCK)
                    505:                               pkt->data = bp;
                    506:                          else {
                    507:                               for (tail = pkt->data; tail->next != NOBLOCK;)
                    508:                                    tail = tail->next;
                    509:                               tail->next = bp;
                    510:                          }
                    511:                          pkt->pk_lenword += bp->wptr - bp->rptr;
                    512:                     }
                    513:                }
                    514:                break;
                    515:           case CHRECORD:
                    516:                if ((pkt = get_packet(q, 1)) == NOPKT) {
                    517:                     printf("chdosrv: can't allocate packet\n");
                    518:                     return 0;
                    519:                }
                    520:                setconn(conn, pkt);
                    521:               chld_write(conn, pkt);
                    522:                break;
                    523:      }
                    524: 
                    525:      return 0;
                    526: }
                    527: 
                    528: chdrint(conn, pkt)
                    529:      register struct connection    *conn;
                    530:      register struct packet   *pkt;
                    531: {
                    532:      register struct queue    *q;
                    533: 
                    534:      if (conn->cn_sflags & CHOPNWAIT)
                    535:           chdoreply(conn, 0, pkt, 0);
                    536:      if (ISDATA(pkt) || pkt->pk_op == EOFOP)
                    537:           conn->cn_flags |= CHREADER;
                    538: 
                    539:      q = conn->cn_rdq;
                    540:      if (q) {
                    541:           if (conn->cn_mode == CHSTREAM) {
                    542:               if (pkt->pk_op == EOFOP)
                    543:                    conn->cn_flags |= CHEOFSEEN;
                    544:               else
                    545:                    conn->cn_flags &= ~CHEOFSEEN;
                    546:                if (!READABLE(pkt)) {
                    547:                    conn->cn_expkt = pkt;
                    548:                    return;
                    549:                }
                    550:           }
                    551:           if (q->next->flag & QFULL) {
                    552:                free_packet(pkt);
                    553:                debug(DABNOR,printf("chdrint: QFULL\n"));
                    554:                return;
                    555:           }
                    556:          ch_busy++;
                    557:           if (conn->cn_mode == CHRECORD)     /* Check for RECORD mode */
                    558:                putcpy(q->next, &pkt->pk_op, 1);
                    559:           put_pkdata(q, pkt);
                    560:          --ch_busy;
                    561:      } else
                    562:           free_packet(pkt);
                    563: }
                    564: 
                    565: 
                    566: chd_newstate(conn)
                    567:      register struct connection    *conn;
                    568: {
                    569:      register struct queue    *qnext = conn->cn_rdq->next;
                    570:      int       ps = spl6();
                    571: 
                    572:      if (conn->cn_sflags & CHOPNWAIT)
                    573:          chdoreply(conn, 0, NOPKT);
                    574: 
                    575:      if (conn->cn_sflags & CHSWAIT) {
                    576:           register union stmsg *sp = (union stmsg *)conn->cn_wait->rptr;
                    577: 
                    578:           if (conn->cn_state != *(int *)sp->iocx.xxx) {
                    579:               conn->cn_wait->wptr = (u_char *)sp;
                    580:               (*qnext->qinfo->putp) (qnext, conn->cn_wait);
                    581:               conn->cn_sflags &= ~CHSWAIT;
                    582:               conn->cn_wait = NOBLOCK;
                    583:           }
                    584:      }
                    585: 
                    586:      if (chdead(conn)) {      /* send an end-of-file */
                    587:           putctl(qnext, M_DELIM);
                    588:           putctl(qnext, M_DELIM);
                    589:      }
                    590: 
                    591:      splx(ps);
                    592: }
                    593: 
                    594: chd_newout(conn)
                    595:      register struct connection    *conn;
                    596: {
                    597:      int       ps = spl6();
                    598: 
                    599:      if (conn->cn_sflags & CHOWAIT)
                    600:           wakeup((caddr_t)&conn->cn_thead);
                    601: 
                    602:      if (conn->cn_sflags & CHEMPWAIT) {
                    603:           register union stmsg *sp = (union stmsg *)conn->cn_wait->rptr;
                    604: 
                    605:           if (chtempty(conn)) {
                    606:               conn->cn_wait->wptr = (u_char *)sp;
                    607:               qreply(conn->cn_rdq, conn->cn_wait);
                    608:               conn->cn_sflags &= ~CHEMPWAIT;
                    609:               conn->cn_wait = NOBLOCK;
                    610:           }
                    611:      }
                    612: 
                    613:      if (conn->cn_sflags & CHOQWAIT) {
                    614:          conn->cn_sflags &= ~CHOQWAIT;
                    615:          qenable(WR(conn->cn_rdq));
                    616:      }
                    617: 
                    618:      splx(ps);
                    619: }
                    620: 
                    621: #endif

unix.superglobalmegacorp.com

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