BSD 4_3_Net_2 release
[unix-history] / usr / src / usr.bin / telnet / telnet.c
index 66f7656..46a980c 100644 (file)
@@ -1,36 +1,42 @@
 /*
 /*
- * Copyright (c) 1988 Regents of the University of California.
+ * Copyright (c) 1988, 1990 Regents of the University of California.
  * All rights reserved.
  *
  * 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.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. 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 BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)telnet.c   5.50 (Berkeley) 6/28/90";
+static char sccsid[] = "@(#)telnet.c   5.53 (Berkeley) 3/22/91";
 #endif /* not lint */
 
 #include <sys/types.h>
 
 #endif /* not lint */
 
 #include <sys/types.h>
 
-#ifdef KERBEROS
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <kerberosIV/des.h>
-#include <kerberosIV/krb.h>
-#include "krb4-proto.h"
-#endif
-
 #if    defined(unix)
 #include <signal.h>
 /* By the way, we need to include curses.h before telnet.h since,
 #if    defined(unix)
 #include <signal.h>
 /* By the way, we need to include curses.h before telnet.h since,
@@ -41,12 +47,6 @@ static char sccsid[] = "@(#)telnet.c 5.50 (Berkeley) 6/28/90";
 
 #include <arpa/telnet.h>
 
 
 #include <arpa/telnet.h>
 
-#if    defined(unix)
-#include <strings.h>
-#else  /* defined(unix) */
-#include <string.h>
-#endif /* defined(unix) */
-
 #include <ctype.h>
 
 #include "ring.h"
 #include <ctype.h>
 
 #include "ring.h"
@@ -59,28 +59,31 @@ static char sccsid[] = "@(#)telnet.c        5.50 (Berkeley) 6/28/90";
 \f
 #define        strip(x)        ((x)&0x7f)
 
 \f
 #define        strip(x)        ((x)&0x7f)
 
-extern char *env_getvalue();
-
-static char    subbuffer[SUBBUFSIZE],
-               *subpointer, *subend;    /* buffer for sub-options */
+static unsigned char   subbuffer[SUBBUFSIZE],
+                       *subpointer, *subend;    /* buffer for sub-options */
 #define        SB_CLEAR()      subpointer = subbuffer;
 #define        SB_CLEAR()      subpointer = subbuffer;
-#define        SB_TERM()       subend = subpointer;
+#define        SB_TERM()       { subend = subpointer; SB_CLEAR(); }
 #define        SB_ACCUM(c)     if (subpointer < (subbuffer+sizeof subbuffer)) { \
                                *subpointer++ = (c); \
                        }
 
 #define        SB_ACCUM(c)     if (subpointer < (subbuffer+sizeof subbuffer)) { \
                                *subpointer++ = (c); \
                        }
 
+#define        SB_GET()        ((*subpointer++)&0xff)
+#define        SB_PEEK()       ((*subpointer)&0xff)
+#define        SB_EOF()        (subpointer >= subend)
+#define        SB_LEN()        (subend - subpointer)
+
 char   options[256];           /* The combined options */
 char   do_dont_resp[256];
 char   will_wont_resp[256];
 
 int
 char   options[256];           /* The combined options */
 char   do_dont_resp[256];
 char   will_wont_resp[256];
 
 int
+       eight = 0,
+       autologin = 0,  /* Autologin anyone? */
+       skiprc = 0,
        connected,
        showoptions,
        In3270,         /* Are we in 3270 mode? */
        ISend,          /* trying to send network data in */
        connected,
        showoptions,
        In3270,         /* Are we in 3270 mode? */
        ISend,          /* trying to send network data in */
-#ifdef KERBEROS
-       kerberized = 0, /* Are we using Kerberos authentication ? */
-#endif
        debug = 0,
        crmod,
        netdata,        /* Print out network data flow */
        debug = 0,
        crmod,
        netdata,        /* Print out network data flow */
@@ -105,6 +108,7 @@ int
 char *prompt = 0;
 
 cc_t escape;
 char *prompt = 0;
 
 cc_t escape;
+cc_t rlogin;
 #ifdef KLUDGELINEMODE
 cc_t echoc;
 #endif
 #ifdef KLUDGELINEMODE
 cc_t echoc;
 #endif
@@ -158,6 +162,7 @@ Modelist modelist[] = {
  * Initialize telnet environment.
  */
 
  * Initialize telnet environment.
  */
 
+    void
 init_telnet()
 {
     env_init();
 init_telnet()
 {
     env_init();
@@ -166,12 +171,16 @@ init_telnet()
     ClearArray(options);
 
     connected = In3270 = ISend = localflow = donebinarytoggle = 0;
     ClearArray(options);
 
     connected = In3270 = ISend = localflow = donebinarytoggle = 0;
+#if    defined(ENCRYPT) || defined(AUTHENTICATE)
+    auth_encrypt_connect(connected);
+#endif
 
     SYNCHing = 0;
 
     /* Don't change NetTrace */
 
     escape = CONTROL(']');
 
     SYNCHing = 0;
 
     /* Don't change NetTrace */
 
     escape = CONTROL(']');
+    rlogin = _POSIX_VDISABLE;
 #ifdef KLUDGELINEMODE
     echoc = CONTROL('E');
 #endif
 #ifdef KLUDGELINEMODE
     echoc = CONTROL('E');
 #endif
@@ -184,10 +193,10 @@ init_telnet()
 #ifdef notdef
 #include <varargs.h>
 
 #ifdef notdef
 #include <varargs.h>
 
-/*VARARGS*/
-static void
+    /*VARARGS*/
+    static void
 printring(va_alist)
 printring(va_alist)
-va_dcl
+    va_dcl
 {
     va_list ap;
     char buffer[100];          /* where things go */
 {
     va_list ap;
     char buffer[100];          /* where things go */
@@ -239,8 +248,9 @@ va_dcl
  * is in disagreement as to what the current state should be.
  */
 
  * is in disagreement as to what the current state should be.
  */
 
+    void
 send_do(c, init)
 send_do(c, init)
-register int c, init;
+    register int c, init;
 {
     if (init) {
        if (((do_dont_resp[c] == 0) && my_state_is_do(c)) ||
 {
     if (init) {
        if (((do_dont_resp[c] == 0) && my_state_is_do(c)) ||
@@ -251,12 +261,12 @@ register int c, init;
     }
     NET2ADD(IAC, DO);
     NETADD(c);
     }
     NET2ADD(IAC, DO);
     NETADD(c);
-    printoption("SENT", "do", c);
+    printoption("SENT", DO, c);
 }
 
 }
 
-void
+    void
 send_dont(c, init)
 send_dont(c, init)
-register int c, init;
+    register int c, init;
 {
     if (init) {
        if (((do_dont_resp[c] == 0) && my_state_is_dont(c)) ||
 {
     if (init) {
        if (((do_dont_resp[c] == 0) && my_state_is_dont(c)) ||
@@ -267,12 +277,12 @@ register int c, init;
     }
     NET2ADD(IAC, DONT);
     NETADD(c);
     }
     NET2ADD(IAC, DONT);
     NETADD(c);
-    printoption("SENT", "dont", c);
+    printoption("SENT", DONT, c);
 }
 
 }
 
-void
+    void
 send_will(c, init)
 send_will(c, init)
-register int c, init;
+    register int c, init;
 {
     if (init) {
        if (((will_wont_resp[c] == 0) && my_state_is_will(c)) ||
 {
     if (init) {
        if (((will_wont_resp[c] == 0) && my_state_is_will(c)) ||
@@ -283,12 +293,12 @@ register int c, init;
     }
     NET2ADD(IAC, WILL);
     NETADD(c);
     }
     NET2ADD(IAC, WILL);
     NETADD(c);
-    printoption("SENT", "will", c);
+    printoption("SENT", WILL, c);
 }
 
 }
 
-void
+    void
 send_wont(c, init)
 send_wont(c, init)
-register int c, init;
+    register int c, init;
 {
     if (init) {
        if (((will_wont_resp[c] == 0) && my_state_is_wont(c)) ||
 {
     if (init) {
        if (((will_wont_resp[c] == 0) && my_state_is_wont(c)) ||
@@ -299,11 +309,11 @@ register int c, init;
     }
     NET2ADD(IAC, WONT);
     NETADD(c);
     }
     NET2ADD(IAC, WONT);
     NETADD(c);
-    printoption("SENT", "wont", c);
+    printoption("SENT", WONT, c);
 }
 
 
 }
 
 
-void
+       void
 willoption(option)
        int option;
 {
 willoption(option)
        int option;
 {
@@ -349,6 +359,12 @@ willoption(option)
                settimer(modenegotiated);
                /* FALL THROUGH */
            case TELOPT_STATUS:
                settimer(modenegotiated);
                /* FALL THROUGH */
            case TELOPT_STATUS:
+#if    defined(AUTHENTICATE)
+           case TELOPT_AUTHENTICATION:
+#endif
+#if    defined(ENCRYPT)
+           case TELOPT_ENCRYPT:
+#endif
                new_state_ok = 1;
                break;
 
                new_state_ok = 1;
                break;
 
@@ -378,9 +394,13 @@ willoption(option)
            }
        }
        set_my_state_do(option);
            }
        }
        set_my_state_do(option);
+#if    defined(ENCRYPT)
+       if (option == TELOPT_ENCRYPT)
+               encrypt_send_support();
+#endif
 }
 
 }
 
-void
+       void
 wontoption(option)
        int option;
 {
 wontoption(option)
        int option;
 {
@@ -429,7 +449,7 @@ wontoption(option)
        set_my_state_dont(option);
 }
 
        set_my_state_dont(option);
 }
 
-static void
+       static void
 dooption(option)
        int option;
 {
 dooption(option)
        int option;
 {
@@ -456,12 +476,6 @@ dooption(option)
                set_my_state_wont(TELOPT_TM);
                return;
 
                set_my_state_wont(TELOPT_TM);
                return;
 
-#ifdef KERBEROS
-           case TELOPT_AUTHENTICATION:
-               if (kerberized)
-                       new_state_ok = 1;
-               break;
-#endif
 #      if defined(TN3270)
            case TELOPT_EOR:            /* end of record */
 #      endif   /* defined(TN3270) */
 #      if defined(TN3270)
            case TELOPT_EOR:            /* end of record */
 #      endif   /* defined(TN3270) */
@@ -472,11 +486,20 @@ dooption(option)
            case TELOPT_TTYPE:          /* terminal type option */
            case TELOPT_SGA:            /* no big deal */
            case TELOPT_ENVIRON:        /* environment variable option */
            case TELOPT_TTYPE:          /* terminal type option */
            case TELOPT_SGA:            /* no big deal */
            case TELOPT_ENVIRON:        /* environment variable option */
+#if    defined(ENCRYPT)
+           case TELOPT_ENCRYPT:        /* encryption variable option */
+#endif
                new_state_ok = 1;
                break;
                new_state_ok = 1;
                break;
+#if    defined(AUTHENTICATE)
+           case TELOPT_AUTHENTICATION:
+               if (autologin)
+                       new_state_ok = 1;
+               break;
+#endif
 
            case TELOPT_XDISPLOC:       /* X Display location */
 
            case TELOPT_XDISPLOC:       /* X Display location */
-               if (env_getvalue("DISPLAY"))
+               if (env_getvalue((unsigned char *)"DISPLAY"))
                    new_state_ok = 1;
                break;
 
                    new_state_ok = 1;
                break;
 
@@ -499,6 +522,7 @@ dooption(option)
            if (new_state_ok) {
                set_my_want_state_will(option);
                send_will(option, 0);
            if (new_state_ok) {
                set_my_want_state_will(option);
                send_will(option, 0);
+               setconnmode(0);                 /* Set new tty mode */
            } else {
                will_wont_resp[option]++;
                send_wont(option, 0);
            } else {
                will_wont_resp[option]++;
                send_wont(option, 0);
@@ -524,7 +548,7 @@ dooption(option)
        set_my_state_will(option);
 }
 
        set_my_state_will(option);
 }
 
-static void
+       static void
 dontoption(option)
        int option;
 {
 dontoption(option)
        int option;
 {
@@ -557,24 +581,26 @@ dontoption(option)
  * duplicate, or verbose names (names with spaces).
  */
 
  * duplicate, or verbose names (names with spaces).
  */
 
-static char *unknown[] = { "UNKNOWN", 0 };
+static char *name_unknown = "UNKNOWN";
+static char *unknown[] = { 0, 0 };
 
 
-char **
+       char **
 mklist(buf, name)
 mklist(buf, name)
-char *buf, *name;
+       char *buf, *name;
 {
        register int n;
 {
        register int n;
-       register char c, *cp, **argvp, *cp2, **argv;
-       char *malloc();
+       register char c, *cp, **argvp, *cp2, **argv, **avt;
 
        if (name) {
 
        if (name) {
-               if (strlen(name) > 40)
+               if (strlen(name) > 40) {
                        name = 0;
                        name = 0;
-               else {
+                       unknown[0] = name_unknown;
+               } else {
                        unknown[0] = name;
                        upcase(name);
                }
                        unknown[0] = name;
                        upcase(name);
                }
-       }
+       } else
+               unknown[0] = name_unknown;
        /*
         * Count up the number of names.
         */
        /*
         * Count up the number of names.
         */
@@ -639,9 +665,10 @@ char *buf, *name;
         * only 2 characters long, move it to the end of the array.
         */
        if ((argv[1] == buf) && (strlen(argv[1]) == 2)) {
         * only 2 characters long, move it to the end of the array.
         */
        if ((argv[1] == buf) && (strlen(argv[1]) == 2)) {
+               --argvp;
+               for (avt = &argv[1]; avt < argvp; avt++)
+                       *avt = *(avt+1);
                *argvp++ = buf;
                *argvp++ = buf;
-               cp = *argv++;
-               *argv = cp;
        }
 
        /*
        }
 
        /*
@@ -656,8 +683,11 @@ char *buf, *name;
        if (*argv == 0) {
                if (name)
                        *argv = name;
        if (*argv == 0) {
                if (name)
                        *argv = name;
-               else
-                       argv++;
+               else {
+                       --argvp;
+                       for (avt = argv; avt < argvp; avt++)
+                               *avt = *(avt+1);
+               }
        }
        if (*argv)
                return(argv);
        }
        if (*argv)
                return(argv);
@@ -665,8 +695,9 @@ char *buf, *name;
                return(unknown);
 }
 
                return(unknown);
 }
 
+       int
 is_unique(name, as, ae)
 is_unique(name, as, ae)
-register char *name, **as, **ae;
+       register char *name, **as, **ae;
 {
        register char **ap;
        register int n;
 {
        register char **ap;
        register int n;
@@ -680,10 +711,12 @@ register char *name, **as, **ae;
 
 #ifdef TERMCAP
 char termbuf[1024];
 
 #ifdef TERMCAP
 char termbuf[1024];
-/*ARGSUSED*/
+
+       /*ARGSUSED*/
+       int
 setupterm(tname, fd, errp)
 setupterm(tname, fd, errp)
-char *tname;
-int fd, *errp;
+       char *tname;
+       int fd, *errp;
 {
        if (tgetent(termbuf, tname) == 1) {
                termbuf[1023] = '\0';
 {
        if (tgetent(termbuf, tname) == 1) {
                termbuf[1023] = '\0';
@@ -700,25 +733,29 @@ int fd, *errp;
 extern char ttytype[];
 #endif
 
 extern char ttytype[];
 #endif
 
-char *
+int resettermname = 1;
+
+       char *
 gettermname()
 {
        char *tname;
 gettermname()
 {
        char *tname;
-       static int first = 1;
-       static char **tnamep;
+       static char **tnamep = 0;
        static char **next;
        int err;
 
        static char **next;
        int err;
 
-       if (first) {
-               first = 0;
-               if ((tname = env_getvalue("TERM")) &&
+       if (resettermname) {
+               resettermname = 0;
+               if (tnamep && tnamep != unknown)
+                       free(tnamep);
+               if ((tname = (char *)env_getvalue((unsigned char *)"TERM")) &&
                                (setupterm(tname, 1, &err) == 0)) {
                        tnamep = mklist(termbuf, tname);
                } else {
                        if (tname && (strlen(tname) <= 40)) {
                                unknown[0] = tname;
                                upcase(tname);
                                (setupterm(tname, 1, &err) == 0)) {
                        tnamep = mklist(termbuf, tname);
                } else {
                        if (tname && (strlen(tname) <= 40)) {
                                unknown[0] = tname;
                                upcase(tname);
-                       }
+                       } else
+                               unknown[0] = name_unknown;
                        tnamep = unknown;
                }
                next = tnamep;
                        tnamep = unknown;
                }
                next = tnamep;
@@ -741,19 +778,19 @@ gettermname()
  *             Linemode
  */
 
  *             Linemode
  */
 
-static void
+    static void
 suboption()
 {
 suboption()
 {
-    printsub('<', subbuffer, subend-subbuffer+2);
-    switch (subbuffer[0]&0xff) {
+    printsub('<', subbuffer, SB_LEN()+2);
+    switch (SB_GET()) {
     case TELOPT_TTYPE:
        if (my_want_state_is_wont(TELOPT_TTYPE))
            return;
     case TELOPT_TTYPE:
        if (my_want_state_is_wont(TELOPT_TTYPE))
            return;
-       if ((subbuffer[1]&0xff) != TELQUAL_SEND) {
-           ;
+       if (SB_EOF() || SB_GET() != TELQUAL_SEND) {
+           return;
        } else {
            char *name;
        } else {
            char *name;
-           char temp[50];
+           unsigned char temp[50];
            int len;
 
 #if    defined(TN3270)
            int len;
 
 #if    defined(TN3270)
@@ -764,7 +801,7 @@ suboption()
            name = gettermname();
            len = strlen(name) + 4 + 2;
            if (len < NETROOM()) {
            name = gettermname();
            len = strlen(name) + 4 + 2;
            if (len < NETROOM()) {
-               sprintf(temp, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE,
+               sprintf((char *)temp, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE,
                                TELQUAL_IS, name, IAC, SE);
                ring_supply_data(&netoring, temp, len);
                printsub('>', &temp[2], len-2);
                                TELQUAL_IS, name, IAC, SE);
                ring_supply_data(&netoring, temp, len);
                printsub('>', &temp[2], len-2);
@@ -777,16 +814,18 @@ suboption()
     case TELOPT_TSPEED:
        if (my_want_state_is_wont(TELOPT_TSPEED))
            return;
     case TELOPT_TSPEED:
        if (my_want_state_is_wont(TELOPT_TSPEED))
            return;
-       if ((subbuffer[1]&0xff) == TELQUAL_SEND) {
-           int ospeed, ispeed;
-           char temp[50];
+       if (SB_EOF())
+           return;
+       if (SB_GET() == TELQUAL_SEND) {
+           long ospeed, ispeed;
+           unsigned char temp[50];
            int len;
 
            TerminalSpeeds(&ispeed, &ospeed);
 
            int len;
 
            TerminalSpeeds(&ispeed, &ospeed);
 
-           sprintf(temp, "%c%c%c%c%d,%d%c%c", IAC, SB, TELOPT_TSPEED,
+           sprintf((char *)temp, "%c%c%c%c%d,%d%c%c", IAC, SB, TELOPT_TSPEED,
                    TELQUAL_IS, ospeed, ispeed, IAC, SE);
                    TELQUAL_IS, ospeed, ispeed, IAC, SE);
-           len = strlen(temp+4) + 4;   /* temp[3] is 0 ... */
+           len = strlen((char *)temp+4) + 4;   /* temp[3] is 0 ... */
 
            if (len < NETROOM()) {
                ring_supply_data(&netoring, temp, len);
 
            if (len < NETROOM()) {
                ring_supply_data(&netoring, temp, len);
@@ -798,10 +837,17 @@ suboption()
     case TELOPT_LFLOW:
        if (my_want_state_is_wont(TELOPT_LFLOW))
            return;
     case TELOPT_LFLOW:
        if (my_want_state_is_wont(TELOPT_LFLOW))
            return;
-       if ((subbuffer[1]&0xff) == 1) {
+       if (SB_EOF())
+           return;
+       switch(SB_GET()) {
+       case 1:
            localflow = 1;
            localflow = 1;
-       } else if ((subbuffer[1]&0xff) == 0) {
+           break;
+       case 0:
            localflow = 0;
            localflow = 0;
+           break;
+       default:
+           return;
        }
        setcommandmode();
        setconnmode(0);
        }
        setcommandmode();
        setconnmode(0);
@@ -810,24 +856,26 @@ suboption()
     case TELOPT_LINEMODE:
        if (my_want_state_is_wont(TELOPT_LINEMODE))
            return;
     case TELOPT_LINEMODE:
        if (my_want_state_is_wont(TELOPT_LINEMODE))
            return;
-       switch (subbuffer[1]&0xff) {
+       if (SB_EOF())
+           return;
+       switch (SB_GET()) {
        case WILL:
        case WILL:
-           lm_will(&subbuffer[2], subend - &subbuffer[2]);
+           lm_will(subpointer, SB_LEN());
            break;
        case WONT:
            break;
        case WONT:
-           lm_wont(&subbuffer[2], subend - &subbuffer[2]);
+           lm_wont(subpointer, SB_LEN());
            break;
        case DO:
            break;
        case DO:
-           lm_do(&subbuffer[2], subend - &subbuffer[2]);
+           lm_do(subpointer, SB_LEN());
            break;
        case DONT:
            break;
        case DONT:
-           lm_dont(&subbuffer[2], subend - &subbuffer[2]);
+           lm_dont(subpointer, SB_LEN());
            break;
        case LM_SLC:
            break;
        case LM_SLC:
-           slc(&subbuffer[2], subend - &subbuffer[2]);
+           slc(subpointer, SB_LEN());
            break;
        case LM_MODE:
            break;
        case LM_MODE:
-           lm_mode(&subbuffer[2], subend - &subbuffer[2], 0);
+           lm_mode(subpointer, SB_LEN(), 0);
            break;
        default:
            break;
            break;
        default:
            break;
@@ -835,7 +883,9 @@ suboption()
        break;
 
     case TELOPT_ENVIRON:
        break;
 
     case TELOPT_ENVIRON:
-       switch(subbuffer[1]&0xff) {
+       if (SB_EOF())
+           return;
+       switch(SB_PEEK()) {
        case TELQUAL_IS:
        case TELQUAL_INFO:
            if (my_want_state_is_dont(TELOPT_ENVIRON))
        case TELQUAL_IS:
        case TELQUAL_INFO:
            if (my_want_state_is_dont(TELOPT_ENVIRON))
@@ -849,17 +899,19 @@ suboption()
        default:
            return;
        }
        default:
            return;
        }
-       env_opt(&subbuffer[1], subend - &subbuffer[1]);
+       env_opt(subpointer, SB_LEN());
        break;
 
     case TELOPT_XDISPLOC:
        if (my_want_state_is_wont(TELOPT_XDISPLOC))
            return;
        break;
 
     case TELOPT_XDISPLOC:
        if (my_want_state_is_wont(TELOPT_XDISPLOC))
            return;
-       if ((subbuffer[1]&0xff) == TELQUAL_SEND) {
-           char temp[50], *dp;
+       if (SB_EOF())
+           return;
+       if (SB_GET() == TELQUAL_SEND) {
+           unsigned char temp[50], *dp;
            int len;
 
            int len;
 
-           if ((dp = env_getvalue("DISPLAY")) == NULL) {
+           if ((dp = env_getvalue((unsigned char *)"DISPLAY")) == NULL) {
                /*
                 * Something happened, we no longer have a DISPLAY
                 * variable.  So, turn off the option.
                /*
                 * Something happened, we no longer have a DISPLAY
                 * variable.  So, turn off the option.
@@ -867,9 +919,9 @@ suboption()
                send_wont(TELOPT_XDISPLOC, 1);
                break;
            }
                send_wont(TELOPT_XDISPLOC, 1);
                break;
            }
-           sprintf(temp, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC,
+           sprintf((char *)temp, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC,
                    TELQUAL_IS, dp, IAC, SE);
                    TELQUAL_IS, dp, IAC, SE);
-           len = strlen(temp+4) + 4;   /* temp[3] is 0 ... */
+           len = strlen((char *)temp+4) + 4;   /* temp[3] is 0 ... */
 
            if (len < NETROOM()) {
                ring_supply_data(&netoring, temp, len);
 
            if (len < NETROOM()) {
                ring_supply_data(&netoring, temp, len);
@@ -879,135 +931,109 @@ suboption()
        }
        break;
 
        }
        break;
 
-#ifdef KERBEROS
-    case TELOPT_AUTHENTICATION:
-       if ((subbuffer[1] & 0xff) == TELQUAL_SEND) {
-               register char *cp = &subbuffer[2];
-               char tmp[256];
-               int dokrb4 = 0, unknowntypes = 0, noresponse = 1;
-
-               while (cp < subend) {
-                       switch (*cp) {
-                       case TELQUAL_AUTHTYPE_KERBEROS_V4:
-                               dokrb4 = 1;
-                               break;
-                       default:
-                               unknowntypes++;
-                       }
-                       cp++;
+#if    defined(AUTHENTICATE)
+       case TELOPT_AUTHENTICATION: {
+               if (!autologin)
+                       break;
+               if (SB_EOF())
+                       return;
+               switch(SB_GET()) {
+               case TELQUAL_IS:
+                       if (my_want_state_is_dont(TELOPT_AUTHENTICATION))
+                               return;
+                       auth_is(subpointer, SB_LEN());
+                       break;
+               case TELQUAL_SEND:
+                       if (my_want_state_is_wont(TELOPT_AUTHENTICATION))
+                               return;
+                       auth_send(subpointer, SB_LEN());
+                       break;
+               case TELQUAL_REPLY:
+                       if (my_want_state_is_wont(TELOPT_AUTHENTICATION))
+                               return;
+                       auth_reply(subpointer, SB_LEN());
+                       break;
+               case TELQUAL_NAME:
+                       if (my_want_state_is_dont(TELOPT_AUTHENTICATION))
+                               return;
+                       auth_name(subpointer, SB_LEN());
+                       break;
                }
                }
-
-               if (noresponse && dokrb4) {
-                       register unsigned char *ucp = (unsigned char *)cp;
-                       char *krb_realm;
-                       char hst_inst[INST_SZ];
-                       KTEXT_ST authent_st;
-                       int space = 0;
-                       int retval;
-                       extern char *krb_realmofhost(), *krb_get_phost();
-
-                       fprintf(stderr,
-                               "[Trying Kerberos V4 authentication]\n");
-
-                       krb_realm = krb_get_phost(hostname);
-                       bzero(hst_inst, sizeof(hst_inst));
-                       if (krb_realm)
-                           strncpy(hst_inst, krb_realm, sizeof(hst_inst));
-                       hst_inst[sizeof(hst_inst)-1] = '\0';
-                       if (!(krb_realm = krb_realmofhost(hst_inst))) {
-                           fprintf(stderr, "no realm for %s\n", hostname);
-                           goto cantsend4;
-                       }
-                       if (retval = krb_mk_req(&authent_st, "rcmd", hst_inst,
-                           krb_realm, 0L)) {
-                               fprintf(stderr, "mk_req failed: %s\n",
-                                   krb_err_txt[retval]);
-                               goto cantsend4;
-                       }
-                       space = authent_st.length;
-                       for (ucp = authent_st.dat; ucp < authent_st.dat +
-                            authent_st.length; ucp++) {
-                               if (*ucp == IAC)
-                                       space++;
-                       }
-                       if (NETROOM() < 6 + 1 + 2 +
-                           space + 2) {
-                               fprintf(stderr,
-                                  "no room to send V4 ticket/authenticator\n");
-cantsend4:
-                           if (7 < NETROOM()) {
-                               printring(&netoring, "%c%c%c%c%c%c%c", IAC, SB,
-                                 TELOPT_AUTHENTICATION,
-                                 TELQUAL_IS, TELQUAL_AUTHTYPE_NONE, IAC, SE);
-                               sprintf(tmp, "%c%c%c%c%c", TELOPT_AUTHENTICATION,
-                                       TELQUAL_IS, TELQUAL_AUTHTYPE_NONE, IAC, SE);
-                               printsub(">", tmp, 4+2-2-2);
-                           } else
-                               exit(1);
-                       } else {
-#ifdef notdef
-                   printring(&netoring, "%c%c%c%c%c%c", IAC, SB,
-                             TELOPT_AUTHENTICATION,
-                             TELQUAL_IS, TELQUAL_AUTHTYPE_KERBEROS,
-                             TELQUAL_AUTHTYPE_KERBEROS_V4);
-                   sprintf(tmp, "%c%c%c%c%c%c", TELOPT_AUTHENTICATION,
-                           TELQUAL_IS, TELQUAL_AUTHTYPE_KERBEROS,
-                           TELQUAL_AUTHTYPE_KERBEROS_V4, IAC, SE);
-#else
-                           printring(&netoring, "%c%c%c%c%c", IAC, SB,
-                             TELOPT_AUTHENTICATION,
-                             TELQUAL_IS,
-                             TELQUAL_AUTHTYPE_KERBEROS_V4);
-                           sprintf(tmp, "%c%c%c%c%c", TELOPT_AUTHENTICATION,
-                             TELQUAL_IS,
-                             TELQUAL_AUTHTYPE_KERBEROS_V4, IAC, SE);
-#endif
-                           printsub(">", tmp, 4+2-2-2);
-                           ring_supply_bindata(&netoring,
-                               (char *)authent_st.dat, authent_st.length, IAC);
-                           printring(&netoring, "%c%c", IAC, SE);
-                       }
-                       noresponse = 0;
-               }
-               if (noresponse) {
-                       if (NETROOM() < 7) {
-                           ExitString("not enough room to reject unhandled authtype\n", 1);
-                       } else {
-                           fprintf(stderr,"[Sending empty auth info in response to request for %d unknown type(s):\n\t", unknowntypes);
-#ifdef notdef
-                           cp = &subbuffer[3];
-#else
-                           cp = &subbuffer[2];
-#endif
-                           while (cp < subend) {
-                               switch (*cp) {
-                               case TELQUAL_AUTHTYPE_KERBEROS_V4:
-                                       break;
-                               default:
-                                       fprintf(stderr, "%d,", *cp);
-                                       break;
-                               }
-                               cp++;
-                           }
-                           fputs("]\n", stderr);
-                           printring(&netoring, "%c%c%c%c%c%c%c", IAC, SB,
-                             TELOPT_AUTHENTICATION,
-                             TELQUAL_IS, TELQUAL_AUTHTYPE_NONE, IAC, SE);
-                       }
-               }
        }
        break;
        }
        break;
-#endif /* KERBEROS */
-
+#endif
+#if    defined(ENCRYPT)
+       case TELOPT_ENCRYPT:
+               if (SB_EOF())
+                       return;
+               switch(SB_GET()) {
+               case ENCRYPT_START:
+                       if (my_want_state_is_dont(TELOPT_ENCRYPT))
+                               return;
+                       encrypt_start(subpointer, SB_LEN());
+                       break;
+               case ENCRYPT_END:
+                       if (my_want_state_is_dont(TELOPT_ENCRYPT))
+                               return;
+                       encrypt_end();
+                       break;
+               case ENCRYPT_SUPPORT:
+                       if (my_want_state_is_wont(TELOPT_ENCRYPT))
+                               return;
+                       encrypt_support(subpointer, SB_LEN());
+                       break;
+               case ENCRYPT_REQSTART:
+                       if (my_want_state_is_wont(TELOPT_ENCRYPT))
+                               return;
+                       encrypt_request_start(subpointer, SB_LEN());
+                       break;
+               case ENCRYPT_REQEND:
+                       if (my_want_state_is_wont(TELOPT_ENCRYPT))
+                               return;
+                       /*
+                        * We can always send an REQEND so that we cannot
+                        * get stuck encrypting.  We should only get this
+                        * if we have been able to get in the correct mode
+                        * anyhow.
+                        */
+                       encrypt_request_end();
+                       break;
+               case ENCRYPT_IS:
+                       if (my_want_state_is_dont(TELOPT_ENCRYPT))
+                               return;
+                       encrypt_is(subpointer, SB_LEN());
+                       break;
+               case ENCRYPT_REPLY:
+                       if (my_want_state_is_wont(TELOPT_ENCRYPT))
+                               return;
+                       encrypt_reply(subpointer, SB_LEN());
+                       break;
+               case ENCRYPT_ENC_KEYID:
+                       if (my_want_state_is_dont(TELOPT_ENCRYPT))
+                               return;
+                       encrypt_enc_keyid(subpointer, SB_LEN());
+                       break;
+               case ENCRYPT_DEC_KEYID:
+                       if (my_want_state_is_wont(TELOPT_ENCRYPT))
+                               return;
+                       encrypt_dec_keyid(subpointer, SB_LEN());
+                       break;
+               default:
+                       break;
+               }
+               break;
+#endif
     default:
        break;
     }
 }
 
     default:
        break;
     }
 }
 
-static char str_lm[] = { IAC, SB, TELOPT_LINEMODE, 0, 0, IAC, SE };
+static unsigned char str_lm[] = { IAC, SB, TELOPT_LINEMODE, 0, 0, IAC, SE };
 
 
+    void
 lm_will(cmd, len)
 lm_will(cmd, len)
-char *cmd;
+    unsigned char *cmd;
+    int len;
 {
     if (len < 1) {
 /*@*/  printf("lm_will: no command!!!\n");     /* Should not happen... */
 {
     if (len < 1) {
 /*@*/  printf("lm_will: no command!!!\n");     /* Should not happen... */
@@ -1027,8 +1053,10 @@ char *cmd;
     }
 }
 
     }
 }
 
+    void
 lm_wont(cmd, len)
 lm_wont(cmd, len)
-char *cmd;
+    unsigned char *cmd;
+    int len;
 {
     if (len < 1) {
 /*@*/  printf("lm_wont: no command!!!\n");     /* Should not happen... */
 {
     if (len < 1) {
 /*@*/  printf("lm_wont: no command!!!\n");     /* Should not happen... */
@@ -1042,8 +1070,10 @@ char *cmd;
     }
 }
 
     }
 }
 
+    void
 lm_do(cmd, len)
 lm_do(cmd, len)
-char *cmd;
+    unsigned char *cmd;
+    int len;
 {
     if (len < 1) {
 /*@*/  printf("lm_do: no command!!!\n");       /* Should not happen... */
 {
     if (len < 1) {
 /*@*/  printf("lm_do: no command!!!\n");       /* Should not happen... */
@@ -1063,8 +1093,10 @@ char *cmd;
     }
 }
 
     }
 }
 
+    void
 lm_dont(cmd, len)
 lm_dont(cmd, len)
-char *cmd;
+    unsigned char *cmd;
+    int len;
 {
     if (len < 1) {
 /*@*/  printf("lm_dont: no command!!!\n");     /* Should not happen... */
 {
     if (len < 1) {
 /*@*/  printf("lm_dont: no command!!!\n");     /* Should not happen... */
@@ -1078,11 +1110,14 @@ char *cmd;
     }
 }
 
     }
 }
 
-static char str_lm_mode[] = { IAC, SB, TELOPT_LINEMODE, LM_MODE, 0, IAC, SE };
+static unsigned char str_lm_mode[] = {
+       IAC, SB, TELOPT_LINEMODE, LM_MODE, 0, IAC, SE
+};
 
 
+       void
 lm_mode(cmd, len, init)
 lm_mode(cmd, len, init)
-char *cmd;
-int len, init;
+       unsigned char *cmd;
+       int len, init;
 {
        if (len != 1)
                return;
 {
        if (len != 1)
                return;
@@ -1121,10 +1156,10 @@ struct spc {
 #define SLC_RVALUE     2
 static int slc_mode = SLC_EXPORT;
 
 #define SLC_RVALUE     2
 static int slc_mode = SLC_EXPORT;
 
+       void
 slc_init()
 {
        register struct spc *spcp;
 slc_init()
 {
        register struct spc *spcp;
-       extern cc_t *tcval();
 
        localchars = 1;
        for (spcp = spc_data; spcp < &spc_data[NSLC+1]; spcp++) {
 
        localchars = 1;
        for (spcp = spc_data; spcp < &spc_data[NSLC+1]; spcp++) {
@@ -1183,6 +1218,7 @@ slc_init()
 
 }
 
 
 }
 
+    void
 slcstate()
 {
     printf("Special characters are %s values\n",
 slcstate()
 {
     printf("Special characters are %s values\n",
@@ -1191,6 +1227,7 @@ slcstate()
                                         "remote");
 }
 
                                         "remote");
 }
 
+    void
 slc_mode_export()
 {
     slc_mode = SLC_EXPORT;
 slc_mode_export()
 {
     slc_mode = SLC_EXPORT;
@@ -1198,22 +1235,25 @@ slc_mode_export()
        slc_export();
 }
 
        slc_export();
 }
 
+    void
 slc_mode_import(def)
 slc_mode_import(def)
+    int def;
 {
     slc_mode = def ? SLC_IMPORT : SLC_RVALUE;
     if (my_state_is_will(TELOPT_LINEMODE))
        slc_import(def);
 }
 
 {
     slc_mode = def ? SLC_IMPORT : SLC_RVALUE;
     if (my_state_is_will(TELOPT_LINEMODE))
        slc_import(def);
 }
 
-char slc_import_val[] = {
+unsigned char slc_import_val[] = {
        IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_VARIABLE, 0, IAC, SE
 };
        IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_VARIABLE, 0, IAC, SE
 };
-char slc_import_def[] = {
+unsigned char slc_import_def[] = {
        IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_DEFAULT, 0, IAC, SE
 };
 
        IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_DEFAULT, 0, IAC, SE
 };
 
+    void
 slc_import(def)
 slc_import(def)
-int def;
+    int def;
 {
     if (NETROOM() > sizeof(slc_import_val)) {
        if (def) {
 {
     if (NETROOM() > sizeof(slc_import_val)) {
        if (def) {
@@ -1227,6 +1267,7 @@ int def;
 /*@*/ else printf("slc_import: not enough room\n");
 }
 
 /*@*/ else printf("slc_import: not enough room\n");
 }
 
+    void
 slc_export()
 {
     register struct spc *spcp;
 slc_export()
 {
     register struct spc *spcp;
@@ -1236,20 +1277,24 @@ slc_export()
     slc_start_reply();
     for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
        if (spcp->mylevel != SLC_NOSUPPORT) {
     slc_start_reply();
     for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
        if (spcp->mylevel != SLC_NOSUPPORT) {
-           spcp->flags = spcp->mylevel;
+           if (spcp->val == (cc_t)(_POSIX_VDISABLE))
+               spcp->flags = SLC_NOSUPPORT;
+           else
+               spcp->flags = spcp->mylevel;
            if (spcp->valp)
                spcp->val = *spcp->valp;
            if (spcp->valp)
                spcp->val = *spcp->valp;
-           slc_add_reply(spcp - spc_data, spcp->mylevel, spcp->val);
+           slc_add_reply(spcp - spc_data, spcp->flags, spcp->val);
        }
     }
     slc_end_reply();
        }
     }
     slc_end_reply();
-    if (slc_update())
-       setconnmode(1); /* set the  new character values */
+    (void)slc_update();
+    setconnmode(1);    /* Make sure the character values are set */
 }
 
 }
 
+       void
 slc(cp, len)
 slc(cp, len)
-register char *cp;
-int len;
+       register unsigned char *cp;
+       int len;
 {
        register struct spc *spcp;
        register int func,level;
 {
        register struct spc *spcp;
        register int func,level;
@@ -1267,7 +1312,7 @@ int len;
                        continue;
                }
                if (func > NSLC) {
                        continue;
                }
                if (func > NSLC) {
-                       if (cp[SLC_FLAGS] & SLC_LEVELBITS != SLC_NOSUPPORT)
+                       if ((cp[SLC_FLAGS] & SLC_LEVELBITS) != SLC_NOSUPPORT)
                                slc_add_reply(func, SLC_NOSUPPORT, 0);
                        continue;
                }
                                slc_add_reply(func, SLC_NOSUPPORT, 0);
                        continue;
                }
@@ -1316,6 +1361,7 @@ int len;
                setconnmode(1); /* set the  new character values */
 }
 
                setconnmode(1); /* set the  new character values */
 }
 
+    void
 slc_check()
 {
     register struct spc *spcp;
 slc_check()
 {
     register struct spc *spcp;
@@ -1324,7 +1370,11 @@ slc_check()
     for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
        if (spcp->valp && spcp->val != *spcp->valp) {
            spcp->val = *spcp->valp;
     for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
        if (spcp->valp && spcp->val != *spcp->valp) {
            spcp->val = *spcp->valp;
-           slc_add_reply(spcp - spc_data, spcp->mylevel, spcp->val);
+           if (spcp->val == (cc_t)(_POSIX_VDISABLE))
+               spcp->flags = SLC_NOSUPPORT;
+           else
+               spcp->flags = spcp->mylevel;
+           slc_add_reply(spcp - spc_data, spcp->flags, spcp->val);
        }
     }
     slc_end_reply();
        }
     }
     slc_end_reply();
@@ -1334,6 +1384,8 @@ slc_check()
 
 unsigned char slc_reply[128];
 unsigned char *slc_replyp;
 
 unsigned char slc_reply[128];
 unsigned char *slc_replyp;
+
+       void
 slc_start_reply()
 {
        slc_replyp = slc_reply;
 slc_start_reply()
 {
        slc_replyp = slc_reply;
@@ -1343,10 +1395,11 @@ slc_start_reply()
        *slc_replyp++ = LM_SLC;
 }
 
        *slc_replyp++ = LM_SLC;
 }
 
+       void
 slc_add_reply(func, flags, value)
 slc_add_reply(func, flags, value)
-char func;
-char flags;
-cc_t value;
+       unsigned char func;
+       unsigned char flags;
+       cc_t value;
 {
        if ((*slc_replyp++ = func) == IAC)
                *slc_replyp++ = IAC;
 {
        if ((*slc_replyp++ = func) == IAC)
                *slc_replyp++ = IAC;
@@ -1356,6 +1409,7 @@ cc_t value;
                *slc_replyp++ = IAC;
 }
 
                *slc_replyp++ = IAC;
 }
 
+    void
 slc_end_reply()
 {
     register int len;
 slc_end_reply()
 {
     register int len;
@@ -1372,6 +1426,7 @@ slc_end_reply()
 /*@*/else printf("slc_end_reply: not enough room\n");
 }
 
 /*@*/else printf("slc_end_reply: not enough room\n");
 }
 
+       int
 slc_update()
 {
        register struct spc *spcp;
 slc_update()
 {
        register struct spc *spcp;
@@ -1389,20 +1444,21 @@ slc_update()
        return(need_update);
 }
 
        return(need_update);
 }
 
+       void
 env_opt(buf, len)
 env_opt(buf, len)
-register char *buf;
-register int len;
+       register unsigned char *buf;
+       register int len;
 {
 {
-       register char *ep = 0, *epc = 0;
+       register unsigned char *ep = 0, *epc = 0;
        register int i;
 
        register int i;
 
-       switch(buf[0]) {
+       switch(buf[0]&0xff) {
        case TELQUAL_SEND:
                env_opt_start();
                if (len == 1) {
                        env_opt_add(NULL);
                } else for (i = 1; i < len; i++) {
        case TELQUAL_SEND:
                env_opt_start();
                if (len == 1) {
                        env_opt_add(NULL);
                } else for (i = 1; i < len; i++) {
-                       switch (buf[i]) {
+                       switch (buf[i]&0xff) {
                        case ENV_VALUE:
                                if (ep) {
                                        *epc = 0;
                        case ENV_VALUE:
                                if (ep) {
                                        *epc = 0;
@@ -1441,11 +1497,9 @@ unsigned char *opt_reply;
 unsigned char *opt_replyp;
 unsigned char *opt_replyend;
 
 unsigned char *opt_replyp;
 unsigned char *opt_replyend;
 
+       void
 env_opt_start()
 {
 env_opt_start()
 {
-       extern char *realloc();
-       extern char *malloc();
-
        if (opt_reply)
                opt_reply = (unsigned char *)realloc(opt_reply, OPT_REPLY_SIZE);
        else
        if (opt_reply)
                opt_reply = (unsigned char *)realloc(opt_reply, OPT_REPLY_SIZE);
        else
@@ -1463,6 +1517,7 @@ env_opt_start()
        *opt_replyp++ = TELQUAL_IS;
 }
 
        *opt_replyp++ = TELQUAL_IS;
 }
 
+       void
 env_opt_start_info()
 {
        env_opt_start();
 env_opt_start_info()
 {
        env_opt_start();
@@ -1470,12 +1525,11 @@ env_opt_start_info()
            opt_replyp[-1] = TELQUAL_INFO;
 }
 
            opt_replyp[-1] = TELQUAL_INFO;
 }
 
+       void
 env_opt_add(ep)
 env_opt_add(ep)
-register char *ep;
+       register unsigned char *ep;
 {
 {
-       register char *vp, c;
-       extern char *realloc();
-       extern char *env_default();
+       register unsigned char *vp, c;
 
        if (opt_reply == NULL)          /*XXX*/
                return;                 /*XXX*/
 
        if (opt_reply == NULL)          /*XXX*/
                return;                 /*XXX*/
@@ -1487,7 +1541,9 @@ register char *ep;
                return;
        }
        vp = env_getvalue(ep);
                return;
        }
        vp = env_getvalue(ep);
-       if (opt_replyp + (vp?strlen(vp):0) + strlen(ep) + 6 > opt_replyend) {
+       if (opt_replyp + (vp ? strlen((char *)vp) : 0) +
+                               strlen((char *)ep) + 6 > opt_replyend)
+       {
                register int len;
                opt_replyend += OPT_REPLY_SIZE;
                len = opt_replyend - opt_reply;
                register int len;
                opt_replyend += OPT_REPLY_SIZE;
                len = opt_replyend - opt_reply;
@@ -1503,7 +1559,7 @@ register char *ep;
        *opt_replyp++ = ENV_VAR;
        for (;;) {
                while (c = *ep++) {
        *opt_replyp++ = ENV_VAR;
        for (;;) {
                while (c = *ep++) {
-                       switch(c) {
+                       switch(c&0xff) {
                        case IAC:
                                *opt_replyp++ = IAC;
                                break;
                        case IAC:
                                *opt_replyp++ = IAC;
                                break;
@@ -1523,8 +1579,9 @@ register char *ep;
        }
 }
 
        }
 }
 
+       void
 env_opt_end(emptyok)
 env_opt_end(emptyok)
-register int emptyok;
+       register int emptyok;
 {
        register int len;
 
 {
        register int len;
 
@@ -1546,12 +1603,12 @@ register int emptyok;
 
 \f
 
 
 \f
 
-int
+    int
 telrcv()
 {
     register int c;
     register int scc;
 telrcv()
 {
     register int c;
     register int scc;
-    register char *sbp;
+    register unsigned char *sbp;
     int count;
     int returnValue = 0;
 
     int count;
     int returnValue = 0;
 
@@ -1573,6 +1630,10 @@ telrcv()
        }
 
        c = *sbp++ & 0xff, scc--; count++;
        }
 
        c = *sbp++ & 0xff, scc--; count++;
+#if    defined(ENCRYPT)
+       if (decrypt_input)
+               c = (*decrypt_input)(c);
+#endif
 
        switch (telrcv_state) {
 
 
        switch (telrcv_state) {
 
@@ -1597,6 +1658,10 @@ telrcv()
                *Ifrontp++ = c;
                while (scc > 0) {
                    c = *sbp++ & 0377, scc--; count++;
                *Ifrontp++ = c;
                while (scc > 0) {
                    c = *sbp++ & 0377, scc--; count++;
+#if    defined(ENCRYPT)
+                   if (decrypt_input)
+                       c = (*decrypt_input)(c);
+#endif
                    if (c == IAC) {
                        telrcv_state = TS_IAC;
                        break;
                    if (c == IAC) {
                        telrcv_state = TS_IAC;
                        break;
@@ -1615,6 +1680,10 @@ telrcv()
            if ((c == '\r') && my_want_state_is_dont(TELOPT_BINARY)) {
                if (scc > 0) {
                    c = *sbp&0xff;
            if ((c == '\r') && my_want_state_is_dont(TELOPT_BINARY)) {
                if (scc > 0) {
                    c = *sbp&0xff;
+#if    defined(ENCRYPT)
+                   if (decrypt_input)
+                       c = (*decrypt_input)(c);
+#endif
                    if (c == 0) {
                        sbp++, scc--; count++;
                        /* a "true" CR */
                    if (c == 0) {
                        sbp++, scc--; count++;
                        /* a "true" CR */
@@ -1624,6 +1693,11 @@ telrcv()
                        sbp++, scc--; count++;
                        TTYADD('\n');
                    } else {
                        sbp++, scc--; count++;
                        TTYADD('\n');
                    } else {
+#if    defined(ENCRYPT)
+                       if (decrypt_input)
+                           (*decrypt_input)(-1);
+#endif
+
                        TTYADD('\r');
                        if (crmod) {
                                TTYADD('\n');
                        TTYADD('\r');
                        if (crmod) {
                                TTYADD('\n');
@@ -1667,6 +1741,7 @@ process_iac:
                     * so make sure we flush whatever is in the
                     * buffer currently.
                     */
                     * so make sure we flush whatever is in the
                     * buffer currently.
                     */
+               printoption("RCVD", IAC, DM);
                SYNCHing = 1;
                (void) ttyflush(1);
                SYNCHing = stilloob();
                SYNCHing = 1;
                (void) ttyflush(1);
                SYNCHing = stilloob();
@@ -1676,7 +1751,6 @@ process_iac:
            case SB:
                SB_CLEAR();
                telrcv_state = TS_SB;
            case SB:
                SB_CLEAR();
                telrcv_state = TS_SB;
-               printoption("RCVD", "IAC", SB);
                continue;
 
 #          if defined(TN3270)
                continue;
 
 #          if defined(TN3270)
@@ -1690,6 +1764,7 @@ process_iac:
                        ISend = 1;
                    }
                }
                        ISend = 1;
                    }
                }
+               printoption("RCVD", IAC, EOR);
                break;
 #          endif /* defined(TN3270) */
 
                break;
 #          endif /* defined(TN3270) */
 
@@ -1708,28 +1783,28 @@ process_iac:
            case NOP:
            case GA:
            default:
            case NOP:
            case GA:
            default:
-               printoption("RCVD", "IAC", c);
+               printoption("RCVD", IAC, c);
                break;
            }
            telrcv_state = TS_DATA;
            continue;
 
        case TS_WILL:
                break;
            }
            telrcv_state = TS_DATA;
            continue;
 
        case TS_WILL:
-           printoption("RCVD", "will", c);
+           printoption("RCVD", WILL, c);
            willoption(c);
            SetIn3270();
            telrcv_state = TS_DATA;
            continue;
 
        case TS_WONT:
            willoption(c);
            SetIn3270();
            telrcv_state = TS_DATA;
            continue;
 
        case TS_WONT:
-           printoption("RCVD", "wont", c);
+           printoption("RCVD", WONT, c);
            wontoption(c);
            SetIn3270();
            telrcv_state = TS_DATA;
            continue;
 
        case TS_DO:
            wontoption(c);
            SetIn3270();
            telrcv_state = TS_DATA;
            continue;
 
        case TS_DO:
-           printoption("RCVD", "do", c);
+           printoption("RCVD", DO, c);
            dooption(c);
            SetIn3270();
            if (c == TELOPT_NAWS) {
            dooption(c);
            SetIn3270();
            if (c == TELOPT_NAWS) {
@@ -1743,7 +1818,7 @@ process_iac:
            continue;
 
        case TS_DONT:
            continue;
 
        case TS_DONT:
-           printoption("RCVD", "dont", c);
+           printoption("RCVD", DONT, c);
            dontoption(c);
            flushline = 1;
            setconnmode(0);     /* set new tty mode (maybe) */
            dontoption(c);
            flushline = 1;
            setconnmode(0);     /* set new tty mode (maybe) */
@@ -1774,10 +1849,12 @@ process_iac:
                     * we terminate the suboption, and process the
                     * partial suboption if we can.
                     */
                     * we terminate the suboption, and process the
                     * partial suboption if we can.
                     */
-                   SB_TERM();
                    SB_ACCUM(IAC);
                    SB_ACCUM(c);
                    SB_ACCUM(IAC);
                    SB_ACCUM(c);
-                   printoption("In SUBOPTION processing, RCVD", "IAC", c);
+                   subpointer -= 2;
+                   SB_TERM();
+
+                   printoption("In SUBOPTION processing, RCVD", IAC, c);
                    suboption();        /* handle sub-option */
                    SetIn3270();
                    telrcv_state = TS_IAC;
                    suboption();        /* handle sub-option */
                    SetIn3270();
                    telrcv_state = TS_IAC;
@@ -1786,9 +1863,10 @@ process_iac:
                SB_ACCUM(c);
                telrcv_state = TS_SB;
            } else {
                SB_ACCUM(c);
                telrcv_state = TS_SB;
            } else {
-               SB_TERM();
                SB_ACCUM(IAC);
                SB_ACCUM(SE);
                SB_ACCUM(IAC);
                SB_ACCUM(SE);
+               subpointer -= 2;
+               SB_TERM();
                suboption();    /* handle sub-option */
                SetIn3270();
                telrcv_state = TS_DATA;
                suboption();    /* handle sub-option */
                SetIn3270();
                telrcv_state = TS_DATA;
@@ -1800,13 +1878,27 @@ process_iac:
     return returnValue||count;
 }
 
     return returnValue||count;
 }
 
-static int
+static int bol = 1, local = 0;
+
+    int
+rlogin_susp()
+{
+    if (local) {
+       local = 0;
+       bol = 1;
+       command(0, "z\n", 2);
+       return(1);
+    }
+    return(0);
+}
+
+    static int
 telsnd()
 {
     int tcc;
     int count;
     int returnValue = 0;
 telsnd()
 {
     int tcc;
     int count;
     int returnValue = 0;
-    char *tbp;
+    unsigned char *tbp;
 
     tcc = 0;
     count = 0;
 
     tcc = 0;
     count = 0;
@@ -1827,7 +1919,43 @@ telsnd()
            }
        }
        c = *tbp++ & 0xff, sc = strip(c), tcc--; count++;
            }
        }
        c = *tbp++ & 0xff, sc = strip(c), tcc--; count++;
-       if (sc == escape) {
+       if (rlogin != _POSIX_VDISABLE) {
+               if (bol) {
+                       bol = 0;
+                       if (sc == rlogin) {
+                               local = 1;
+                               continue;
+                       }
+               } else if (local) {
+                       local = 0;
+                       if (sc == '.' || c == termEofChar) {
+                               bol = 1;
+                               command(0, "close\n", 6);
+                               continue;
+                       }
+                       if (sc == termSuspChar) {
+                               bol = 1;
+                               command(0, "z\n", 2);
+                               continue;
+                       }
+                       if (sc == escape) {
+                               command(0, (char *)tbp, tcc);
+                               bol = 1;
+                               count += tcc;
+                               tcc = 0;
+                               flushline = 1;
+                               break;
+                       }
+                       if (sc != rlogin) {
+                               ++tcc;
+                               --tbp;
+                               --count;
+                               c = sc = rlogin;
+                       }
+               }
+               if ((sc == '\n') || (sc == '\r'))
+                       bol = 1;
+       } else if (sc == escape) {
            /*
             * Double escape is a pass through of a single escape character.
             */
            /*
             * Double escape is a pass through of a single escape character.
             */
@@ -1835,14 +1963,17 @@ telsnd()
                tbp++;
                tcc--;
                count++;
                tbp++;
                tcc--;
                count++;
+               bol = 0;
            } else {
            } else {
-               command(0, tbp, tcc);
+               command(0, (char *)tbp, tcc);
+               bol = 1;
                count += tcc;
                tcc = 0;
                flushline = 1;
                break;
            }
                count += tcc;
                tcc = 0;
                flushline = 1;
                break;
            }
-       }
+       } else
+           bol = 0;
 #ifdef KLUDGELINEMODE
        if (kludgelinemode && (globalmode&MODE_EDIT) && (sc == echoc)) {
            if (tcc > 0 && strip(*tbp) == echoc) {
 #ifdef KLUDGELINEMODE
        if (kludgelinemode && (globalmode&MODE_EDIT) && (sc == echoc)) {
            if (tcc > 0 && strip(*tbp) == echoc) {
@@ -1858,6 +1989,7 @@ telsnd()
 #endif
        if (MODE_LOCAL_CHARS(globalmode)) {
            if (TerminalSpecialChars(sc) == 0) {
 #endif
        if (MODE_LOCAL_CHARS(globalmode)) {
            if (TerminalSpecialChars(sc) == 0) {
+               bol = 1;
                break;
            }
        }
                break;
            }
        }
@@ -1873,7 +2005,7 @@ telsnd()
                    NETADD('\r');
                }
                NETADD('\n');
                    NETADD('\r');
                }
                NETADD('\n');
-               flushline = 1;
+               bol = flushline = 1;
                break;
            case '\r':
                if (!crlf) {
                break;
            case '\r':
                if (!crlf) {
@@ -1881,7 +2013,7 @@ telsnd()
                } else {
                    NET2ADD('\r', '\n');
                }
                } else {
                    NET2ADD('\r', '\n');
                }
-               flushline = 1;
+               bol = flushline = 1;
                break;
            case IAC:
                NET2ADD(IAC, IAC);
                break;
            case IAC:
                NET2ADD(IAC, IAC);
@@ -1911,9 +2043,9 @@ telsnd()
  */
 
 
  */
 
 
-int
+    int
 Scheduler(block)
 Scheduler(block)
-int    block;                  /* should we block in the select ? */
+    int        block;                  /* should we block in the select ? */
 {
                /* One wants to be a bit careful about setting returnValue
                 * to one, since a one implies we did some useful work,
 {
                /* One wants to be a bit careful about setting returnValue
                 * to one, since a one implies we did some useful work,
@@ -1995,27 +2127,47 @@ int     block;                  /* should we block in the select ? */
 /*
  * Select from tty and network...
  */
 /*
  * Select from tty and network...
  */
-void
-telnet()
+    void
+telnet(user)
+    char *user;
 {
     sys_telnet_init();
 
 {
     sys_telnet_init();
 
+#if defined(ENCRYPT) || defined(AUTHENTICATE)
+    {
+       static char local_host[256] = { 0 };
+       int len = sizeof(local_host);
+
+       if (!local_host[0]) {
+               gethostname(local_host, &len);
+               local_host[sizeof(local_host)-1] = 0;
+       }
+       auth_encrypt_init(local_host, hostname, "TELNET", 0);
+       auth_encrypt_user(user);
+    }
+#endif
 #   if !defined(TN3270)
     if (telnetport) {
 #   if !defined(TN3270)
     if (telnetport) {
+#if    defined(AUTHENTICATE)
+       if (autologin)
+               send_will(TELOPT_AUTHENTICATION, 1);
+#endif
+#if    defined(ENCRYPT)
+       send_do(TELOPT_ENCRYPT, 1);
+       send_will(TELOPT_ENCRYPT, 1);
+#endif
        send_do(TELOPT_SGA, 1);
        send_will(TELOPT_TTYPE, 1);
        send_will(TELOPT_NAWS, 1);
        send_will(TELOPT_TSPEED, 1);
        send_will(TELOPT_LFLOW, 1);
        send_will(TELOPT_LINEMODE, 1);
        send_do(TELOPT_SGA, 1);
        send_will(TELOPT_TTYPE, 1);
        send_will(TELOPT_NAWS, 1);
        send_will(TELOPT_TSPEED, 1);
        send_will(TELOPT_LFLOW, 1);
        send_will(TELOPT_LINEMODE, 1);
-#ifdef KERBEROS
-       if (kerberized)
-               send_will(TELOPT_AUTHENTICATION, 1);
-#endif
+       send_will(TELOPT_ENVIRON, 1);
        send_do(TELOPT_STATUS, 1);
        send_do(TELOPT_STATUS, 1);
-       if (env_getvalue("DISPLAY"))
+       if (env_getvalue((unsigned char *)"DISPLAY"))
            send_will(TELOPT_XDISPLOC, 1);
            send_will(TELOPT_XDISPLOC, 1);
-       send_will(TELOPT_ENVIRON, 1);
+       if (eight)
+           tel_enter_binary(eight);
     }
 #   endif /* !defined(TN3270) */
 
     }
 #   endif /* !defined(TN3270) */
 
@@ -2088,9 +2240,9 @@ telnet()
  * character.
  */
 
  * character.
  */
 
-static char *
+    static char *
 nextitem(current)
 nextitem(current)
-char   *current;
+    char *current;
 {
     if ((*current&0xff) != IAC) {
        return current+1;
 {
     if ((*current&0xff) != IAC) {
        return current+1;
@@ -2136,7 +2288,7 @@ char      *current;
  * us in any case.
  */
 
  * us in any case.
  */
 
-static void
+    static void
 netclear()
 {
 #if    0       /* XXX */
 netclear()
 {
 #if    0       /* XXX */
@@ -2179,7 +2331,7 @@ netclear()
  * These routines add various telnet commands to the data stream.
  */
 
  * These routines add various telnet commands to the data stream.
  */
 
-static void
+    static void
 doflush()
 {
     NET2ADD(IAC, DO);
 doflush()
 {
     NET2ADD(IAC, DO);
@@ -2188,66 +2340,58 @@ doflush()
     flushout = 1;
     (void) ttyflush(1);                        /* Flush/drop output */
     /* do printoption AFTER flush, otherwise the output gets tossed... */
     flushout = 1;
     (void) ttyflush(1);                        /* Flush/drop output */
     /* do printoption AFTER flush, otherwise the output gets tossed... */
-    printoption("SENT", "do", TELOPT_TM);
+    printoption("SENT", DO, TELOPT_TM);
 }
 
 }
 
-void
+    void
 xmitAO()
 {
     NET2ADD(IAC, AO);
 xmitAO()
 {
     NET2ADD(IAC, AO);
-    printoption("SENT", "IAC", AO);
+    printoption("SENT", IAC, AO);
     if (autoflush) {
        doflush();
     }
 }
 
 
     if (autoflush) {
        doflush();
     }
 }
 
 
-void
+    void
 xmitEL()
 {
     NET2ADD(IAC, EL);
 xmitEL()
 {
     NET2ADD(IAC, EL);
-    printoption("SENT", "IAC", EL);
+    printoption("SENT", IAC, EL);
 }
 
 }
 
-void
+    void
 xmitEC()
 {
     NET2ADD(IAC, EC);
 xmitEC()
 {
     NET2ADD(IAC, EC);
-    printoption("SENT", "IAC", EC);
+    printoption("SENT", IAC, EC);
 }
 
 
 }
 
 
-#if    defined(NOT43)
-int
-#else  /* defined(NOT43) */
-void
-#endif /* defined(NOT43) */
+    int
 dosynch()
 {
     netclear();                        /* clear the path to the network */
     NETADD(IAC);
     setneturg();
     NETADD(DM);
 dosynch()
 {
     netclear();                        /* clear the path to the network */
     NETADD(IAC);
     setneturg();
     NETADD(DM);
-    printoption("SENT", "IAC", DM);
-
-#if    defined(NOT43)
-    return 0;
-#endif /* defined(NOT43) */
+    printoption("SENT", IAC, DM);
+    return 1;
 }
 
 }
 
-void
+int want_status_response = 0;
+
+    int
 get_status()
 {
 get_status()
 {
-    char tmp[16];
-    register char *cp;
+    unsigned char tmp[16];
+    register unsigned char *cp;
 
     if (my_want_state_is_dont(TELOPT_STATUS)) {
        printf("Remote side does not support STATUS option\n");
 
     if (my_want_state_is_dont(TELOPT_STATUS)) {
        printf("Remote side does not support STATUS option\n");
-       return;
+       return 0;
     }
     }
-    if (!showoptions)
-       printf("You will not see the response unless you set \"options\"\n");
-
     cp = tmp;
 
     *cp++ = IAC;
     cp = tmp;
 
     *cp++ = IAC;
@@ -2260,13 +2404,15 @@ get_status()
        ring_supply_data(&netoring, tmp, cp-tmp);
        printsub('>', tmp+2, cp - tmp - 2);
     }
        ring_supply_data(&netoring, tmp, cp-tmp);
        printsub('>', tmp+2, cp - tmp - 2);
     }
+    ++want_status_response;
+    return 1;
 }
 
 }
 
-void
+    void
 intp()
 {
     NET2ADD(IAC, IP);
 intp()
 {
     NET2ADD(IAC, IP);
-    printoption("SENT", "IAC", IP);
+    printoption("SENT", IAC, IP);
     flushline = 1;
     if (autoflush) {
        doflush();
     flushline = 1;
     if (autoflush) {
        doflush();
@@ -2276,11 +2422,11 @@ intp()
     }
 }
 
     }
 }
 
-void
+    void
 sendbrk()
 {
     NET2ADD(IAC, BREAK);
 sendbrk()
 {
     NET2ADD(IAC, BREAK);
-    printoption("SENT", "IAC", BREAK);
+    printoption("SENT", IAC, BREAK);
     flushline = 1;
     if (autoflush) {
        doflush();
     flushline = 1;
     if (autoflush) {
        doflush();
@@ -2290,11 +2436,11 @@ sendbrk()
     }
 }
 
     }
 }
 
-void
+    void
 sendabort()
 {
     NET2ADD(IAC, ABORT);
 sendabort()
 {
     NET2ADD(IAC, ABORT);
-    printoption("SENT", "IAC", ABORT);
+    printoption("SENT", IAC, ABORT);
     flushline = 1;
     if (autoflush) {
        doflush();
     flushline = 1;
     if (autoflush) {
        doflush();
@@ -2304,11 +2450,11 @@ sendabort()
     }
 }
 
     }
 }
 
-void
+    void
 sendsusp()
 {
     NET2ADD(IAC, SUSP);
 sendsusp()
 {
     NET2ADD(IAC, SUSP);
-    printoption("SENT", "IAC", SUSP);
+    printoption("SENT", IAC, SUSP);
     flushline = 1;
     if (autoflush) {
        doflush();
     flushline = 1;
     if (autoflush) {
        doflush();
@@ -2318,18 +2464,25 @@ sendsusp()
     }
 }
 
     }
 }
 
-void
+    void
 sendeof()
 {
     NET2ADD(IAC, xEOF);
 sendeof()
 {
     NET2ADD(IAC, xEOF);
-    printoption("SENT", "IAC", xEOF);
+    printoption("SENT", IAC, xEOF);
+}
+
+    void
+sendayt()
+{
+    NET2ADD(IAC, AYT);
+    printoption("SENT", IAC, AYT);
 }
 
 /*
  * Send a window size update to the remote system.
  */
 
 }
 
 /*
  * Send a window size update to the remote system.
  */
 
-void
+    void
 sendnaws()
 {
     long rows, cols;
 sendnaws()
 {
     long rows, cols;
@@ -2361,8 +2514,9 @@ sendnaws()
     }
 }
 
     }
 }
 
+    void
 tel_enter_binary(rw)
 tel_enter_binary(rw)
-int rw;
+    int rw;
 {
     if (rw&1)
        send_do(TELOPT_BINARY, 1);
 {
     if (rw&1)
        send_do(TELOPT_BINARY, 1);
@@ -2370,8 +2524,9 @@ int rw;
        send_will(TELOPT_BINARY, 1);
 }
 
        send_will(TELOPT_BINARY, 1);
 }
 
+    void
 tel_leave_binary(rw)
 tel_leave_binary(rw)
-int rw;
+    int rw;
 {
     if (rw&1)
        send_dont(TELOPT_BINARY, 1);
 {
     if (rw&1)
        send_dont(TELOPT_BINARY, 1);