We need 'uncontrol' under all circumstances.
[unix-history] / usr / src / usr.bin / tn3270 / telnet.c
index fab7493..c25a61d 100644 (file)
@@ -114,6 +114,7 @@ extern char *inet_ntoa();
 #include "ctlr/options.ext"
 #include "ctlr/outbound.ext"
 #include "keyboard/termin.ext"
 #include "ctlr/options.ext"
 #include "ctlr/outbound.ext"
 #include "keyboard/termin.ext"
+#include "general.h"
 #endif /* defined(TN3270) */
 
 
 #endif /* defined(TN3270) */
 
 
@@ -136,10 +137,10 @@ extern char       *inet_ntoa();
 #define min(x,y)       ((x<y)? x:y)
 
 #if    defined(TN3270)
 #define min(x,y)       ((x<y)? x:y)
 
 #if    defined(TN3270)
-static char    Ibuf[8*BUFSIZ], *Ifrontp = Ibuf, *Ibackp = Ibuf;
+static char    Ibuf[8*BUFSIZ], *Ifrontp, *Ibackp;
 #endif /* defined(TN3270) */
 
 #endif /* defined(TN3270) */
 
-static char    ttyobuf[2*BUFSIZ], *tfrontp = ttyobuf, *tbackp = ttyobuf;
+static char    ttyobuf[2*BUFSIZ], *tfrontp, *tbackp;
 #define        TTYADD(c)       { if (!(SYNCHing||flushout)) { *tfrontp++ = c; } }
 #define        TTYLOC()        (tfrontp)
 #define        TTYMAX()        (ttyobuf+sizeof ttyobuf-1)
 #define        TTYADD(c)       { if (!(SYNCHing||flushout)) { *tfrontp++ = c; } }
 #define        TTYLOC()        (tfrontp)
 #define        TTYMAX()        (ttyobuf+sizeof ttyobuf-1)
@@ -147,17 +148,17 @@ static char       ttyobuf[2*BUFSIZ], *tfrontp = ttyobuf, *tbackp = ttyobuf;
 #define        TTYBYTES()      (tfrontp-tbackp)
 #define        TTYROOM()       (TTYMAX()-TTYLOC()+1)
 
 #define        TTYBYTES()      (tfrontp-tbackp)
 #define        TTYROOM()       (TTYMAX()-TTYLOC()+1)
 
-static char    netobuf[2*BUFSIZ], *nfrontp = netobuf, *nbackp = netobuf;
+static char    netobuf[2*BUFSIZ], *nfrontp, *nbackp;
 #define        NETADD(c)       { *nfrontp++ = c; }
 #define        NET2ADD(c1,c2)  { NETADD(c1); NETADD(c2); }
 #define NETLOC()       (nfrontp)
 #define        NETMAX()        (netobuf+sizeof netobuf-1)
 #define        NETBYTES()      (nfrontp-nbackp)
 #define        NETROOM()       (NETMAX()-NETLOC()+1)
 #define        NETADD(c)       { *nfrontp++ = c; }
 #define        NET2ADD(c1,c2)  { NETADD(c1); NETADD(c2); }
 #define NETLOC()       (nfrontp)
 #define        NETMAX()        (netobuf+sizeof netobuf-1)
 #define        NETBYTES()      (nfrontp-nbackp)
 #define        NETROOM()       (NETMAX()-NETLOC()+1)
-static char    *neturg = 0;            /* one past last byte of urgent data */
+static char    *neturg;                /* one past last byte of urgent data */
 
 
-static char    subbuffer[100] = { 0 },
-               *subpointer, *subend = 0;        /* buffer for sub-options */
+static char    subbuffer[100],
+               *subpointer, *subend;    /* buffer for sub-options */
 #define        SB_CLEAR()      subpointer = subbuffer;
 #define        SB_TERM()       subend = subpointer;
 #define        SB_ACCUM(c)     if (subpointer < (subbuffer+sizeof subbuffer)) { \
 #define        SB_CLEAR()      subpointer = subbuffer;
 #define        SB_TERM()       subend = subpointer;
 #define        SB_ACCUM(c)     if (subpointer < (subbuffer+sizeof subbuffer)) { \
@@ -171,8 +172,8 @@ static char sb_terminal[] = { IAC, SB,
 #define        SBTERMMODEL     13
 
 
 #define        SBTERMMODEL     13
 
 
-static char    hisopts[256] = { 0 };
-static char    myopts[256] = { 0 };
+static char    hisopts[256];
+static char    myopts[256];
 
 static char    doopt[] = { IAC, DO, '%', 'c', 0 };
 static char    dont[] = { IAC, DONT, '%', 'c', 0 };
 
 static char    doopt[] = { IAC, DO, '%', 'c', 0 };
 static char    dont[] = { IAC, DONT, '%', 'c', 0 };
@@ -187,71 +188,86 @@ struct cmd {
        int     needconnect;    /* Do we need to be connected to execute? */
 };
 
        int     needconnect;    /* Do we need to be connected to execute? */
 };
 
-static char    sibuf[BUFSIZ], *sbp = 0;
+static char    sibuf[BUFSIZ], *sbp;
 static char    tibuf[BUFSIZ], *tbp;
 static fd_set ibits, obits, xbits;
 
 
 static int
 static char    tibuf[BUFSIZ], *tbp;
 static fd_set ibits, obits, xbits;
 
 
 static int
-       connected = 0,
-       net = 0,
-       scc = 0,
-       tcc = 0,
-       showoptions = 0,
-       In3270 = 0,             /* Are we in 3270 mode? */
-       ISend = 0,              /* trying to send network data in */
+       connected,
+       net,
+       scc,
+       tcc,
+       showoptions,
+       In3270,         /* Are we in 3270 mode? */
+       ISend,          /* trying to send network data in */
        debug = 0,
        debug = 0,
-       crmod = 0,
-       netdata = 0,
+       crmod,
+       netdata,
+       askedSGA = 0,   /* We have talked about suppress go ahead */
        telnetport = 1;
 
        telnetport = 1;
 
-static FILE    *NetTrace = 0;
+static FILE    *NetTrace = 0;          /* Not in bss, since needs to stay */
 
 #define        CONTROL(x)      ((x)&0x1f)              /* CTRL(x) is not portable */
 
 static char
        *prompt = 0,
 
 #define        CONTROL(x)      ((x)&0x1f)              /* CTRL(x) is not portable */
 
 static char
        *prompt = 0,
-       escape = CONTROL(']'),
-       echoc = CONTROL('E');
+       escape,
+       echoc;
 
 static int
 
 static int
-       SYNCHing = 0,           /* we are in TELNET SYNCH mode */
-       flushout = 0,           /* flush output */
+       SYNCHing,               /* we are in TELNET SYNCH mode */
+       flushout,               /* flush output */
        autoflush = 0,          /* flush output when interrupting? */
        autoflush = 0,          /* flush output when interrupting? */
-       autosynch = 0,          /* send interrupt characters with SYNCH? */
-       localchars = 0,         /* we recognize interrupt/quit */
-       donelclchars = 0,       /* the user has set "localchars" */
-       dontlecho = 0;          /* do we suppress local echoing right now? */
+       autosynch,              /* send interrupt characters with SYNCH? */
+       localchars,             /* we recognize interrupt/quit */
+       donelclchars,   /* the user has set "localchars" */
+       dontlecho;              /* do we suppress local echoing right now? */
 
 /*     The following are some tn3270 specific flags */
 #if    defined(TN3270)
 
 static int
 
 /*     The following are some tn3270 specific flags */
 #if    defined(TN3270)
 
 static int
-       Sent3270TerminalType = 0;       /* Have we said we are a 3270? */
+       Sent3270TerminalType;   /* Have we said we are a 3270? */
 
 
+/*
+ * Telnet receiver states for fsm
+ */
+#define        TS_DATA         0
+#define        TS_IAC          1
+#define        TS_WILL         2
+#define        TS_WONT         3
+#define        TS_DO           4
+#define        TS_DONT         5
+#define        TS_CR           6
+#define        TS_SB           7               /* sub-option collection */
+#define        TS_SE           8               /* looking for sub-option end */
+
+static int     telrcv_state = TS_DATA;
 /* Some real, live, globals. */
 int
 #if    defined(unix)
 /* Some real, live, globals. */
 int
 #if    defined(unix)
-       HaveInput = 0,          /* There is input available to scan */
+       HaveInput,              /* There is input available to scan */
 #endif /* defined(unix) */
 #endif /* defined(unix) */
-       tout = 0,                       /* Output file descriptor */
-       tin = 0;                        /* Input file descriptor */
+       tout,                   /* Output file descriptor */
+       tin;                    /* Input file descriptor */
 #if    defined(unix)
 char   *transcom = 0;  /* transparent mode command (default: none) */
 #endif /* defined(unix) */
 
 #else  /* defined(TN3270) */
 #if    defined(unix)
 char   *transcom = 0;  /* transparent mode command (default: none) */
 #endif /* defined(unix) */
 
 #else  /* defined(TN3270) */
-static int tin = 0, tout = 0;          /* file descriptors */
+static int tin, tout;          /* file descriptors */
 #endif /* defined(TN3270) */
 
 static char    line[200];
 #if    defined(TN3270) && defined(unix)
 static char    tline[200];
 #endif /* defined(TN3270) && defined(unix) */
 #endif /* defined(TN3270) */
 
 static char    line[200];
 #if    defined(TN3270) && defined(unix)
 static char    tline[200];
 #endif /* defined(TN3270) && defined(unix) */
-static int     margc = 0;
+static int     margc;
 static char    *margv[20];
 
 static char    *margv[20];
 
-static jmp_buf toplevel;
+static jmp_buf toplevel = 0;
 static jmp_buf peerdied;
 
 extern int errno;
 static jmp_buf peerdied;
 
 extern int errno;
@@ -264,9 +280,9 @@ static struct       servent *sp = 0;
 static struct  tchars otc = { 0 }, ntc = { 0 };
 static struct  ltchars oltc = { 0 }, nltc = { 0 };
 static struct  sgttyb ottyb = { 0 }, nttyb = { 0 };
 static struct  tchars otc = { 0 }, ntc = { 0 };
 static struct  ltchars oltc = { 0 }, nltc = { 0 };
 static struct  sgttyb ottyb = { 0 }, nttyb = { 0 };
-static int     flushline = 1;
+static int     flushline;
 
 
-static char    *hostname = 0;
+static char    *hostname;
 static char    hnamebuf[32];
 
 /*
 static char    hnamebuf[32];
 
 /*
@@ -281,10 +297,61 @@ static struct {
        modenegotiated,         /* last time operating mode negotiated */
        didnetreceive,          /* last time we read data from network */
        gotDM;                  /* when did we last see a data mark */
        modenegotiated,         /* last time operating mode negotiated */
        didnetreceive,          /* last time we read data from network */
        gotDM;                  /* when did we last see a data mark */
-} clocks = { 0 };
+} clocks;
 
 #define        settimer(x)     clocks.x = clocks.system++
 \f
 
 #define        settimer(x)     clocks.x = clocks.system++
 \f
+/*
+ * Initialize variables.
+ */
+
+static void
+tninit()
+{
+    Ifrontp = Ibackp = Ibuf;
+    tfrontp = tbackp = ttyobuf;
+    nfrontp = nbackp = netobuf;
+    
+    /* Don't change telnetport */
+    SB_CLEAR();
+    ClearArray(hisopts);
+    ClearArray(myopts);
+    sbp = sibuf;
+    tbp = tibuf;
+
+    connected = net = scc = tcc = In3270 = ISend = 0;
+    telnetport = 0;
+
+    SYNCHing = 0;
+    Sent3270TerminalType = 0;
+
+#if    defined(unix)
+    HaveInput = 0;
+#endif /* defined(unix) */
+    errno = 0;
+
+    flushline = 0;
+
+    /* Don't change NetTrace */
+
+    escape = CONTROL(']');
+    echoc = CONTROL('E');
+
+    flushline = 1;
+    sp = getservbyname("telnet", "tcp");
+    if (sp == 0) {
+       ExitString(stderr, "telnet: tcp/telnet: unknown service\n",1);
+       /*NOTREACHED*/
+    }
+
+#if    defined(TN3270)
+    init_ctlr();               /* Initialize some things */
+    init_keyboard();
+    init_screen();
+    init_system();
+#endif /* defined(TN3270) */
+}
+\f
 /*
  * Various utility routines.
  */
 /*
  * Various utility routines.
  */
@@ -976,6 +1043,7 @@ mode(f)
            tc = &notc2;
            noltc2 = oltc;
            ltc = &noltc2;
            tc = &notc2;
            noltc2 = oltc;
            ltc = &noltc2;
+#if defined(unix)
            /*
             * If user hasn't specified one way or the other,
             * then default to trapping signals.
            /*
             * If user hasn't specified one way or the other,
             * then default to trapping signals.
@@ -989,6 +1057,9 @@ mode(f)
            } else {
                notc2.t_intrc = notc2.t_quitc = -1;
            }
            } else {
                notc2.t_intrc = notc2.t_quitc = -1;
            }
+#else  /* defined(unix) */
+           notc2.t_intrc = -1;
+#endif /* defined(unix) */
            noltc2.t_suspc = escape;
            noltc2.t_dsuspc = -1;
            onoff = 1;
            noltc2.t_suspc = escape;
            noltc2.t_dsuspc = -1;
            onoff = 1;
@@ -1067,11 +1138,33 @@ willoption(option, reply)
 
        switch (option) {
 
 
        switch (option) {
 
+       case TELOPT_ECHO:
 #      if defined(TN3270)
 #      if defined(TN3270)
+           /*
+            * The following is a pain in the rear-end.
+            * Various IBM servers (some versions of Wiscnet,
+            * possibly Fibronics/Spartacus, and who knows who
+            * else) will NOT allow us to send "DO SGA" too early
+            * in the setup proceedings.  On the other hand,
+            * 4.2 servers (telnetd) won't set SGA correctly.
+            * So, we are stuck.  Empirically (but, based on
+            * a VERY small sample), the IBM servers don't send
+            * out anything about ECHO, so we postpone our sending
+            * "DO SGA" until we see "WILL ECHO" (which 4.2 servers
+            * DO send).
+            */
+           {
+               if (askedSGA == 0) {
+                   askedSGA = 1;
+                   if (!hisopts[TELOPT_SGA]) {
+                       willoption(TELOPT_SGA, 0);
+                   }
+               }
+           }
+               /* Fall through */
        case TELOPT_EOR:
        case TELOPT_BINARY:
 #endif /* defined(TN3270) */
        case TELOPT_EOR:
        case TELOPT_BINARY:
 #endif /* defined(TN3270) */
-       case TELOPT_ECHO:
        case TELOPT_SGA:
                settimer(modenegotiated);
                hisopts[option] = 1;
        case TELOPT_SGA:
                settimer(modenegotiated);
                hisopts[option] = 1;
@@ -1183,7 +1276,7 @@ suboption()
 
 #if    defined(TN3270)
            /*
 
 #if    defined(TN3270)
            /*
-            * Try to send a 3270 type terminal name.  Decide which one base
+            * Try to send a 3270 type terminal name.  Decide which one based
             * on the format of our screen, and (in the future) color
             * capaiblities.
             */
             * on the format of our screen, and (in the future) color
             * capaiblities.
             */
@@ -1253,10 +1346,9 @@ SetIn3270()
                                        && hisopts[TELOPT_BINARY]) {
        if (!In3270) {
            In3270 = 1;
                                        && hisopts[TELOPT_BINARY]) {
        if (!In3270) {
            In3270 = 1;
-           OptInit();          /* initialize mappings */
+           Init3270();         /* Initialize 3270 functions */
            /* initialize terminal key mapping */
            /* initialize terminal key mapping */
-           (void) DataFromTerminal(ttyobuf, 0);
-           StartScreen();      /* Start terminal going */
+           InitTerminal();     /* Start terminal going */
            setconnmode();
        }
     } else {
            setconnmode();
        }
     } else {
@@ -1269,24 +1361,12 @@ SetIn3270()
 }
 #endif /* defined(TN3270) */
 \f
 }
 #endif /* defined(TN3270) */
 \f
-/*
- * Telnet receiver states for fsm
- */
-#define        TS_DATA         0
-#define        TS_IAC          1
-#define        TS_WILL         2
-#define        TS_WONT         3
-#define        TS_DO           4
-#define        TS_DONT         5
-#define        TS_CR           6
-#define        TS_SB           7               /* sub-option collection */
-#define        TS_SE           8               /* looking for sub-option end */
 
 static void
 telrcv()
 {
     register int c;
 
 static void
 telrcv()
 {
     register int c;
-    static int state = TS_DATA;
+    static int telrcv_state = TS_DATA;
 #   if defined(TN3270)
     register int Scc;
     register char *Sbp;
 #   if defined(TN3270)
     register int Scc;
     register char *Sbp;
@@ -1294,10 +1374,10 @@ telrcv()
 
     while ((scc > 0) && (TTYROOM() > 2)) {
        c = *sbp++ & 0xff, scc--;
 
     while ((scc > 0) && (TTYROOM() > 2)) {
        c = *sbp++ & 0xff, scc--;
-       switch (state) {
+       switch (telrcv_state) {
 
        case TS_CR:
 
        case TS_CR:
-           state = TS_DATA;
+           telrcv_state = TS_DATA;
            if (c == '\0') {
                break;  /* Ignore \0 after CR */
            } else if (c == '\n') {
            if (c == '\0') {
                break;  /* Ignore \0 after CR */
            } else if (c == '\n') {
@@ -1310,7 +1390,7 @@ telrcv()
 
        case TS_DATA:
            if (c == IAC) {
 
        case TS_DATA:
            if (c == IAC) {
-               state = TS_IAC;
+               telrcv_state = TS_IAC;
                continue;
            }
 #          if defined(TN3270)
                continue;
            }
 #          if defined(TN3270)
@@ -1321,7 +1401,7 @@ telrcv()
                while (Scc > 0) {
                    c = *Sbp++ & 0377, Scc--;
                    if (c == IAC) {
                while (Scc > 0) {
                    c = *Sbp++ & 0377, Scc--;
                    if (c == IAC) {
-                       state = TS_IAC;
+                       telrcv_state = TS_IAC;
                        break;
                    }
                    *Ifrontp++ = c;
                        break;
                    }
                    *Ifrontp++ = c;
@@ -1355,7 +1435,7 @@ telrcv()
                        }
                    }
                } else {
                        }
                    }
                } else {
-                   state = TS_CR;
+                   telrcv_state = TS_CR;
                    TTYADD('\r');
                    if (crmod) {
                            TTYADD('\n');
                    TTYADD('\r');
                    if (crmod) {
                            TTYADD('\n');
@@ -1370,19 +1450,19 @@ telrcv()
            switch (c) {
            
            case WILL:
            switch (c) {
            
            case WILL:
-               state = TS_WILL;
+               telrcv_state = TS_WILL;
                continue;
 
            case WONT:
                continue;
 
            case WONT:
-               state = TS_WONT;
+               telrcv_state = TS_WONT;
                continue;
 
            case DO:
                continue;
 
            case DO:
-               state = TS_DO;
+               telrcv_state = TS_DO;
                continue;
 
            case DONT:
                continue;
 
            case DONT:
-               state = TS_DONT;
+               telrcv_state = TS_DONT;
                continue;
 
            case DM:
                continue;
 
            case DM:
@@ -1403,7 +1483,7 @@ telrcv()
 
            case SB:
                SB_CLEAR();
 
            case SB:
                SB_CLEAR();
-               state = TS_SB;
+               telrcv_state = TS_SB;
                continue;
 
 #          if defined(TN3270)
                continue;
 
 #          if defined(TN3270)
@@ -1435,7 +1515,7 @@ telrcv()
            default:
                break;
            }
            default:
                break;
            }
-           state = TS_DATA;
+           telrcv_state = TS_DATA;
            continue;
 
        case TS_WILL:
            continue;
 
        case TS_WILL:
@@ -1448,7 +1528,7 @@ telrcv()
                willoption(c, 1);
            }
            SetIn3270();
                willoption(c, 1);
            }
            SetIn3270();
-           state = TS_DATA;
+           telrcv_state = TS_DATA;
            continue;
 
        case TS_WONT:
            continue;
 
        case TS_WONT:
@@ -1461,7 +1541,7 @@ telrcv()
                wontoption(c, 1);
            }
            SetIn3270();
                wontoption(c, 1);
            }
            SetIn3270();
-           state = TS_DATA;
+           telrcv_state = TS_DATA;
            continue;
 
        case TS_DO:
            continue;
 
        case TS_DO:
@@ -1469,7 +1549,7 @@ telrcv()
            if (!myopts[c])
                dooption(c);
            SetIn3270();
            if (!myopts[c])
                dooption(c);
            SetIn3270();
-           state = TS_DATA;
+           telrcv_state = TS_DATA;
            continue;
 
        case TS_DONT:
            continue;
 
        case TS_DONT:
@@ -1483,12 +1563,12 @@ telrcv()
                printoption(">SENT", wont, c, 0);
            }
            SetIn3270();
                printoption(">SENT", wont, c, 0);
            }
            SetIn3270();
-           state = TS_DATA;
+           telrcv_state = TS_DATA;
            continue;
 
        case TS_SB:
            if (c == IAC) {
            continue;
 
        case TS_SB:
            if (c == IAC) {
-               state = TS_SE;
+               telrcv_state = TS_SE;
            } else {
                SB_ACCUM(c);
            }
            } else {
                SB_ACCUM(c);
            }
@@ -1500,12 +1580,12 @@ telrcv()
                    SB_ACCUM(IAC);
                }
                SB_ACCUM(c);
                    SB_ACCUM(IAC);
                }
                SB_ACCUM(c);
-               state = TS_SB;
+               telrcv_state = TS_SB;
            } else {
                SB_TERM();
                suboption();    /* handle sub-option */
                SetIn3270();
            } else {
                SB_TERM();
                suboption();    /* handle sub-option */
                SetIn3270();
-               state = TS_DATA;
+               telrcv_state = TS_DATA;
            }
        }
     }
            }
        }
     }
@@ -1849,7 +1929,7 @@ int       block;                  /* should we block in the select ? */
        if (scc == 0) {
            sbp = sibuf;
        }
        if (scc == 0) {
            sbp = sibuf;
        }
-       canread = sibuf + sizeof sibuf - sbp;
+       canread = sibuf + sizeof sibuf - (sbp+scc);
 #if    !defined(SO_OOBINLINE)
            /*
             * In 4.2 (and some early 4.3) systems, the
 #if    !defined(SO_OOBINLINE)
            /*
             * In 4.2 (and some early 4.3) systems, the
@@ -1890,22 +1970,22 @@ int     block;                  /* should we block in the select ? */
 
            ioctl(net, SIOCATMARK, (char *)&atmark);
            if (atmark) {
 
            ioctl(net, SIOCATMARK, (char *)&atmark);
            if (atmark) {
-               c = recv(net, sibuf, canread, MSG_OOB);
+               c = recv(net, sbp+scc, canread, MSG_OOB);
                if ((c == -1) && (errno == EINVAL)) {
                if ((c == -1) && (errno == EINVAL)) {
-                   c = read(net, sibuf, canread);
+                   c = read(net, sbp+scc, canread);
                    if (clocks.didnetreceive < clocks.gotDM) {
                        SYNCHing = stilloob(net);
                    }
                }
            } else {
                    if (clocks.didnetreceive < clocks.gotDM) {
                        SYNCHing = stilloob(net);
                    }
                }
            } else {
-               c = read(net, sibuf, canread);
+               c = read(net, sbp+scc, canread);
            }
        } else {
            }
        } else {
-           c = read(net, sibuf, canread);
+           c = read(net, sbp+scc, canread);
        }
        settimer(didnetreceive);
 #else  /* !defined(SO_OOBINLINE) */
        }
        settimer(didnetreceive);
 #else  /* !defined(SO_OOBINLINE) */
-       c = read(net, sbp, canread);
+       c = read(net, sbp+scc, canread);
 #endif /* !defined(SO_OOBINLINE) */
        if (c < 0 && errno == EWOULDBLOCK) {
            c = 0;
 #endif /* !defined(SO_OOBINLINE) */
        if (c < 0 && errno == EWOULDBLOCK) {
            c = 0;
@@ -1913,7 +1993,7 @@ int       block;                  /* should we block in the select ? */
            return -1;
        }
        if (netdata) {
            return -1;
        }
        if (netdata) {
-           Dump('<', sbp, c);
+           Dump('<', sbp+scc, c);
        }
        scc += c;
        returnValue = 1;
        }
        scc += c;
        returnValue = 1;
@@ -2772,7 +2852,9 @@ suspend()
 
 /*VARARGS*/
 static
 
 /*VARARGS*/
 static
-bye()
+bye(argc, argv)
+int    argc;           /* Number of arguments */
+char   *argv[];        /* arguments */
 {
     if (connected) {
        shutdown(net, 2);
 {
     if (connected) {
        shutdown(net, 2);
@@ -2780,30 +2862,22 @@ bye()
        close(net);
        connected = 0;
        /* reset options */
        close(net);
        connected = 0;
        /* reset options */
-       bzero((char *)hisopts, sizeof hisopts);
-       bzero((char *)myopts, sizeof myopts);
-       SYNCHing = flushout = 0;
-       flushline = 1;
+       tninit();
 #if    defined(TN3270)
 #if    defined(TN3270)
-               /*
-                * The problem is that we were called from command() which
-                * was called from DataFrom3270() which was called from
-                * DataFromTerminal() which was called from...
-                *
-                * So, just quit.
-                */
-       if (In3270) {
-           Exit(0);
-       }
+       SetIn3270();            /* Get out of 3270 mode */
 #endif /* defined(TN3270) */
     }
 #endif /* defined(TN3270) */
     }
-    return 1;
+    if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) {
+       longjmp(toplevel, 1);
+       /* NOTREACHED */
+    }
+    return 1;                  /* Keep lint, etc., happy */
 }
 
 /*VARARGS*/
 quit()
 {
 }
 
 /*VARARGS*/
 quit()
 {
-       (void) call(bye, "bye", 0);
+       (void) call(bye, "bye", "fromquit", 0);
        Exit(0);
        /*NOTREACHED*/
        return 1;                       /* just to keep lint happy */
        Exit(0);
        /*NOTREACHED*/
        return 1;                       /* just to keep lint happy */
@@ -3185,11 +3259,8 @@ main(argc, argv)
        int argc;
        char *argv[];
 {
        int argc;
        char *argv[];
 {
-    sp = getservbyname("telnet", "tcp");
-    if (sp == 0) {
-       ExitString(stderr, "telnet: tcp/telnet: unknown service\n",1);
-       /*NOTREACHED*/
-    }
+    tninit();          /* Clear out things */
+
     NetTrace = stdout;
     ioctl(0, TIOCGETP, (char *)&ottyb);
     ioctl(0, TIOCGETC, (char *)&otc);
     NetTrace = stdout;
     ioctl(0, TIOCGETP, (char *)&ottyb);
     ioctl(0, TIOCGETC, (char *)&otc);