BSD 4_3_Reno release
[unix-history] / usr / src / usr.bin / telnet / network.c
index 27f5611..204f3ee 100644 (file)
@@ -1,3 +1,26 @@
+/*
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted provided
+ * that: (1) source distributions retain this entire copyright notice and
+ * comment, and (2) distributions including binaries display the following
+ * acknowledgement:  ``This product includes software developed by the
+ * University of California, Berkeley and its contributors'' in the
+ * documentation or other materials provided with the distribution and in
+ * all advertising materials mentioning features or use of this software.
+ * Neither the name of the University nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)network.c  1.15 (Berkeley) 6/28/90";
+#endif /* not lint */
+
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/time.h>
 
 #include <arpa/telnet.h>
 
 
 #include <arpa/telnet.h>
 
+#include "ring.h"
+
 #include "defines.h"
 #include "externs.h"
 #include "defines.h"
 #include "externs.h"
+#include "fdset.h"
 
 
-char   netobuf[2*BUFSIZ], *nfrontp, *nbackp;
-static char    *neturg;                /* one past last byte of urgent data */
+Ring   netoring, netiring;
+char   netobuf[2*BUFSIZ], netibuf[BUFSIZ];
 
 /*
  * Initialize internal network data structures.
 
 /*
  * Initialize internal network data structures.
@@ -18,7 +44,12 @@ static char  *neturg;                /* one past last byte of urgent data */
 
 init_network()
 {
 
 init_network()
 {
-    nfrontp = nbackp = netobuf;
+    if (ring_init(&netoring, netobuf, sizeof netobuf) != 1) {
+       exit(1);
+    }
+    if (ring_init(&netiring, netibuf, sizeof netibuf) != 1) {
+       exit(1);
+    }
     NetTrace = stdout;
 }
 
     NetTrace = stdout;
 }
 
@@ -29,8 +60,7 @@ init_network()
  */
 
 int
  */
 
 int
-stilloob(s)
-int    s;              /* socket number */
+stilloob()
 {
     static struct timeval timeout = { 0 };
     fd_set     excepts;
 {
     static struct timeval timeout = { 0 };
     fd_set     excepts;
@@ -38,15 +68,16 @@ int s;              /* socket number */
 
     do {
        FD_ZERO(&excepts);
 
     do {
        FD_ZERO(&excepts);
-       FD_SET(s, &excepts);
-       value = select(s+1, (fd_set *)0, (fd_set *)0, &excepts, &timeout);
+       FD_SET(net, &excepts);
+       value = select(net+1, (fd_set *)0, (fd_set *)0, &excepts, &timeout);
     } while ((value == -1) && (errno == EINTR));
 
     if (value < 0) {
        perror("select");
     } while ((value == -1) && (errno == EINTR));
 
     if (value < 0) {
        perror("select");
-       quit();
+       (void) quit();
+       /* NOTREACHED */
     }
     }
-    if (FD_ISSET(s, &excepts)) {
+    if (FD_ISSET(net, &excepts)) {
        return 1;
     } else {
        return 0;
        return 1;
     } else {
        return 0;
@@ -54,6 +85,19 @@ int  s;              /* socket number */
 }
 
 
 }
 
 
+/*
+ *  setneturg()
+ *
+ *     Sets "neturg" to the current location.
+ */
+
+void
+setneturg()
+{
+    ring_mark(&netoring);
+}
+
+
 /*
  *  netflush
  *             Send as much data as possible to the network,
 /*
  *  netflush
  *             Send as much data as possible to the network,
@@ -67,13 +111,12 @@ int        s;              /* socket number */
 int
 netflush()
 {
 int
 netflush()
 {
-    int n;
+    register int n, n1;
 
 
-    if ((n = nfrontp - nbackp) > 0) {
-       if (!neturg) {
-           n = send(net, nbackp, n, 0);        /* normal write */
+    if ((n1 = n = ring_full_consecutive(&netoring)) > 0) {
+       if (!ring_at_mark(&netoring)) {
+           n = send(net, netoring.consume, n, 0);      /* normal write */
        } else {
        } else {
-           n = neturg - nbackp;
            /*
             * In 4.2 (and 4.3) systems, there is some question about
             * what byte in a sendOOB operation is the "OOB" data.
            /*
             * In 4.2 (and 4.3) systems, there is some question about
             * what byte in a sendOOB operation is the "OOB" data.
@@ -82,209 +125,34 @@ netflush()
             * we really have more the TCP philosophy of urgent data
             * rather than the Unix philosophy of OOB data).
             */
             * we really have more the TCP philosophy of urgent data
             * rather than the Unix philosophy of OOB data).
             */
-           if (n > 1) {
-               n = send(net, nbackp, n-1, 0);  /* send URGENT all by itself */
-           } else {
-               n = send(net, nbackp, n, MSG_OOB);      /* URGENT data */
-           }
+           n = send(net, netoring.consume, 1, MSG_OOB);/* URGENT data */
        }
     }
     if (n < 0) {
        if (errno != ENOBUFS && errno != EWOULDBLOCK) {
            setcommandmode();
            perror(hostname);
        }
     }
     if (n < 0) {
        if (errno != ENOBUFS && errno != EWOULDBLOCK) {
            setcommandmode();
            perror(hostname);
-           NetClose(net);
-           neturg = 0;
+           (void)NetClose(net);
+           ring_clear_mark(&netoring);
            longjmp(peerdied, -1);
            /*NOTREACHED*/
        }
        n = 0;
     }
     if (netdata && n) {
            longjmp(peerdied, -1);
            /*NOTREACHED*/
        }
        n = 0;
     }
     if (netdata && n) {
-       Dump('>', nbackp, n);
-    }
-    nbackp += n;
-    if (nbackp >= neturg) {
-       neturg = 0;
-    }
-    if (nbackp == nfrontp) {
-       nbackp = nfrontp = netobuf;
-    }
-    return n > 0;
-}
-\f
-/*
- * nextitem()
- *
- *     Return the address of the next "item" in the TELNET data
- * stream.  This will be the address of the next character if
- * the current address is a user data character, or it will
- * be the address of the character following the TELNET command
- * if the current address is a TELNET IAC ("I Am a Command")
- * character.
- */
-
-static char *
-nextitem(current)
-char   *current;
-{
-    if ((*current&0xff) != IAC) {
-       return current+1;
-    }
-    switch (*(current+1)&0xff) {
-    case DO:
-    case DONT:
-    case WILL:
-    case WONT:
-       return current+3;
-    case SB:           /* loop forever looking for the SE */
-       {
-           register char *look = current+2;
-
-           for (;;) {
-               if ((*look++&0xff) == IAC) {
-                   if ((*look++&0xff) == SE) {
-                       return look;
-                   }
-               }
-           }
+       Dump('>', netoring.consume, n);
+    }
+    if (n) {
+       ring_consumed(&netoring, n);
+       /*
+        * If we sent all, and more to send, then recurse to pick
+        * up the other half.
+        */
+       if ((n1 == n) && ring_full_consecutive(&netoring)) {
+           (void) netflush();
        }
        }
-    default:
-       return current+2;
-    }
-}
-/*
- * netclear()
- *
- *     We are about to do a TELNET SYNCH operation.  Clear
- * the path to the network.
- *
- *     Things are a bit tricky since we may have sent the first
- * byte or so of a previous TELNET command into the network.
- * So, we have to scan the network buffer from the beginning
- * until we are up to where we want to be.
- *
- *     A side effect of what we do, just to keep things
- * simple, is to clear the urgent data pointer.  The principal
- * caller should be setting the urgent data pointer AFTER calling
- * us in any case.
- */
-
-static void
-netclear()
-{
-    register char *thisitem, *next;
-    char *good;
-#define        wewant(p)       ((nfrontp > p) && ((*p&0xff) == IAC) && \
-                               ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))
-
-    thisitem = netobuf;
-
-    while ((next = nextitem(thisitem)) <= nbackp) {
-       thisitem = next;
-    }
-
-    /* Now, thisitem is first before/at boundary. */
-
-    good = netobuf;    /* where the good bytes go */
-
-    while (nfrontp > thisitem) {
-       if (wewant(thisitem)) {
-           int length;
-
-           next = thisitem;
-           do {
-               next = nextitem(next);
-           } while (wewant(next) && (nfrontp > next));
-           length = next-thisitem;
-           memcpy(good, thisitem, length);
-           good += length;
-           thisitem = next;
-       } else {
-           thisitem = nextitem(thisitem);
-       }
-    }
-
-    nbackp = netobuf;
-    nfrontp = good;            /* next byte to be sent */
-    neturg = 0;
-}
-\f
-/*
- * These routines add various telnet commands to the data stream.
- */
-
-void
-xmitAO()
-{
-    NET2ADD(IAC, AO);
-    if (autoflush) {
-       doflush();
-    }
-}
-
-
-void
-xmitEL()
-{
-    NET2ADD(IAC, EL);
-}
-
-void
-xmitEC()
-{
-    NET2ADD(IAC, EC);
-}
-
-
-#if    defined(NOT43)
-int
-#else  /* defined(NOT43) */
-void
-#endif /* defined(NOT43) */
-dosynch()
-{
-    netclear();                        /* clear the path to the network */
-    NET2ADD(IAC, DM);
-    neturg = NETLOC()-1;       /* Some systems are off by one XXX */
-
-#if    defined(NOT43)
-    return 0;
-#endif /* defined(NOT43) */
-}
-
-void
-doflush()
-{
-    NET2ADD(IAC, DO);
-    NETADD(TELOPT_TM);
-    flushline = 1;
-    flushout = 1;
-    ttyflush();
-    /* do printoption AFTER flush, otherwise the output gets tossed... */
-    printoption("<SENT", doopt, TELOPT_TM, 0);
-}
-
-void
-intp()
-{
-    NET2ADD(IAC, IP);
-    if (autoflush) {
-       doflush();
-    }
-    if (autosynch) {
-       dosynch();
-    }
-}
-
-void
-sendbrk()
-{
-    NET2ADD(IAC, BREAK);
-    if (autoflush) {
-       doflush();
-    }
-    if (autosynch) {
-       dosynch();
+       return 1;
+    } else {
+       return 0;
     }
 }
     }
 }