Annotation of researchv8dc/sys/chaosld/chaos_device.c, revision 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.