BSD 4_3_Net_2 release
[unix-history] / usr / src / usr.bin / telnet / commands.c
index f9648f6..4880a22 100644 (file)
@@ -1,34 +1,53 @@
 /*
 /*
- * 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[] = "@(#)commands.c 1.32 (Berkeley) 7/28/90";
+static char sccsid[] = "@(#)commands.c 5.5 (Berkeley) 3/22/91";
 #endif /* not lint */
 
 #endif /* not lint */
 
-#include <sys/types.h>
 #if    defined(unix)
 #if    defined(unix)
+#include <sys/param.h>
+#ifdef CRAY
+#include <sys/types.h>
+#endif
 #include <sys/file.h>
 #include <sys/file.h>
+#else
+#include <sys/types.h>
 #endif /* defined(unix) */
 #include <sys/socket.h>
 #include <netinet/in.h>
 #ifdef CRAY
 #endif /* defined(unix) */
 #include <sys/socket.h>
 #include <netinet/in.h>
 #ifdef CRAY
-#include <sys/fcntl.h>
+#include <fcntl.h>
 #endif /* CRAY */
 
 #include <signal.h>
 #endif /* CRAY */
 
 #include <signal.h>
@@ -36,6 +55,7 @@ static char sccsid[] = "@(#)commands.c        1.32 (Berkeley) 7/28/90";
 #include <ctype.h>
 #include <pwd.h>
 #include <varargs.h>
 #include <ctype.h>
 #include <pwd.h>
 #include <varargs.h>
+#include <errno.h>
 
 #include <arpa/telnet.h>
 
 
 #include <arpa/telnet.h>
 
@@ -47,26 +67,32 @@ static char sccsid[] = "@(#)commands.c      1.32 (Berkeley) 7/28/90";
 #include "defines.h"
 #include "types.h"
 
 #include "defines.h"
 #include "types.h"
 
-#ifdef SRCRT
-# ifndef CRAY
-# include <netinet/in_systm.h>
-#  if (defined(vax) || defined(tahoe) || defined(hp300)) && !defined(ultrix)
-#  include <machine/endian.h>
-#  endif /* vax */
-# endif /* CRAY */
+#ifndef CRAY
+#include <netinet/in_systm.h>
+# if (defined(vax) || defined(tahoe) || defined(hp300)) && !defined(ultrix)
+# include <machine/endian.h>
+# endif /* vax */
+#endif /* CRAY */
 #include <netinet/ip.h>
 #include <netinet/ip.h>
-#endif /* SRCRT */
 
 
-#if defined(CRAY) && defined(IP_TOS) && !defined(HAS_IP_TOS)
-# define HAS_IP_TOS
-#endif
 
 
+#ifndef       MAXHOSTNAMELEN
+#define       MAXHOSTNAMELEN 64
+#endif        MAXHOSTNAMELEN
+
+#if    defined(IPPROTO_IP) && defined(IP_TOS)
+int tos = -1;
+#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */
 
 char   *hostname;
 
 char   *hostname;
+static char _hostname[MAXHOSTNAMELEN];
+
 extern char *getenv();
 
 extern char *getenv();
 
-#define Ambiguous(s)   ((char **)s == &ambiguous)
-static char *ambiguous;                /* special return value for command routines */
+extern int isprefix();
+extern char **genget();
+extern int Ambiguous();
+
 static call();
 
 typedef struct {
 static call();
 
 typedef struct {
@@ -81,46 +107,7 @@ static char saveline[256];
 static int margc;
 static char *margv[20];
 
 static int margc;
 static char *margv[20];
 
-/*
- * Various utility routines.
- */
-
-#if    !defined(BSD) || (BSD <= 43)
-
-char   *h_errlist[] = {
-       "Error 0",
-       "Unknown host",                         /* 1 HOST_NOT_FOUND */
-       "Host name lookup failure",             /* 2 TRY_AGAIN */
-       "Unknown server error",                 /* 3 NO_RECOVERY */
-       "No address associated with name",      /* 4 NO_ADDRESS */
-};
-int    h_nerr = { sizeof(h_errlist)/sizeof(h_errlist[0]) };
-
-int h_errno;           /* In some version of SunOS this is necessary */
-
-/*
- * herror --
- *     print the error indicated by the h_errno value.
- */
-herror(s)
-       char *s;
-{
-       if (s && *s) {
-               fprintf(stderr, "%s: ", s);
-       }
-       if ((h_errno < 0) || (h_errno >= h_nerr)) {
-               fprintf(stderr, "Unknown error\n");
-       } else if (h_errno == 0) {
-#if    defined(sun)
-               fprintf(stderr, "Host unknown\n");
-#endif /* defined(sun) */
-       } else {
-               fprintf(stderr, "%s\n", h_errlist[h_errno]);
-       }
-}
-#endif /* !define(BSD) || (BSD <= 43) */
-
-static void
+    static void
 makeargv()
 {
     register char *cp, *cp2, c;
 makeargv()
 {
     register char *cp, *cp2, c;
@@ -171,51 +158,15 @@ makeargv()
     *argp++ = 0;
 }
 
     *argp++ = 0;
 }
 
-
-static char **
-genget(name, table, next)
-char   *name;          /* name to match */
-char   **table;                /* name entry in table */
-char   **(*next)();    /* routine to return next entry in table */
-{
-       register char *p, *q;
-       register char **c, **found;
-       register int nmatches, longest;
-
-       if (name == 0) {
-           return 0;
-       }
-       longest = 0;
-       nmatches = 0;
-       found = 0;
-       for (c = table; (p = *c) != 0; c = (*next)(c)) {
-               for (q = name;
-                   (*q == *p) || (isupper(*q) && tolower(*q) == *p); p++, q++)
-                       if (*q == 0)            /* exact match? */
-                               return (c);
-               if (!*q) {                      /* the name was a prefix */
-                       if (q - name > longest) {
-                               longest = q - name;
-                               nmatches = 1;
-                               found = c;
-                       } else if (q - name == longest)
-                               nmatches++;
-               }
-       }
-       if (nmatches > 1)
-               return &ambiguous;
-       return (found);
-}
-
 /*
  * Make a character string into a number.
  *
  * Todo:  1.  Could take random integers (12, 0x12, 012, 0b1).
  */
 
 /*
  * Make a character string into a number.
  *
  * Todo:  1.  Could take random integers (12, 0x12, 012, 0b1).
  */
 
-static
+       static
 special(s)
 special(s)
-register char *s;
+       register char *s;
 {
        register char c;
        char b;
 {
        register char c;
        char b;
@@ -240,24 +191,32 @@ register char *s;
  * Construct a control character sequence
  * for a special character.
  */
  * Construct a control character sequence
  * for a special character.
  */
-static char *
+       static char *
 control(c)
        register cc_t c;
 {
        static char buf[5];
 control(c)
        register cc_t c;
 {
        static char buf[5];
+       /*
+        * The only way I could get the Sun 3.5 compiler
+        * to shut up about
+        *      if ((unsigned int)c >= 0x80)
+        * was to assign "c" to an unsigned int variable...
+        * Arggg....
+        */
+       register unsigned int uic = (unsigned int)c;
 
 
-       if (c == 0x7f)
+       if (uic == 0x7f)
                return ("^?");
                return ("^?");
-       if (c == (cc_t)-1) {
+       if (c == (cc_t)_POSIX_VDISABLE) {
                return "off";
        }
                return "off";
        }
-       if (c >= 0x80) {
+       if (uic >= 0x80) {
                buf[0] = '\\';
                buf[1] = ((c>>6)&07) + '0';
                buf[2] = ((c>>3)&07) + '0';
                buf[3] = (c&07) + '0';
                buf[4] = 0;
                buf[0] = '\\';
                buf[1] = ((c>>6)&07) + '0';
                buf[2] = ((c>>3)&07) + '0';
                buf[3] = (c&07) + '0';
                buf[4] = 0;
-       } else if (c >= 0x20) {
+       } else if (uic >= 0x20) {
                buf[0] = c;
                buf[1] = 0;
        } else {
                buf[0] = c;
                buf[1] = 0;
        } else {
@@ -279,83 +238,66 @@ control(c)
 struct sendlist {
     char       *name;          /* How user refers to it (case independent) */
     char       *help;          /* Help information (0 ==> no help) */
 struct sendlist {
     char       *name;          /* How user refers to it (case independent) */
     char       *help;          /* Help information (0 ==> no help) */
-#if    defined(NOT43)
+    int                needconnect;    /* Need to be connected */
+    int                narg;           /* Number of arguments */
     int                (*handler)();   /* Routine to perform (for special ops) */
     int                (*handler)();   /* Routine to perform (for special ops) */
-#else  /* defined(NOT43) */
-    void       (*handler)();   /* Routine to perform (for special ops) */
-#endif /* defined(NOT43) */
+    int                nbyte;          /* Number of bytes to send this command */
     int                what;           /* Character to be sent (<0 ==> special) */
 };
 \f
     int                what;           /* Character to be sent (<0 ==> special) */
 };
 \f
-#define        SENDQUESTION    -1
-#define        SENDESCAPE      -3
-
-static struct sendlist Sendlist[] = {
-    { "ao",    "Send Telnet Abort output",             0,      AO },
-    { "ayt",   "Send Telnet 'Are You There'",          0,      AYT },
-    { "brk",   "Send Telnet Break",                    0,      BREAK },
-    { "ec",    "Send Telnet Erase Character",          0,      EC },
-    { "el",    "Send Telnet Erase Line",               0,      EL },
-    { "escape",        "Send current escape character",        0,      SENDESCAPE },
-    { "ga",    "Send Telnet 'Go Ahead' sequence",      0,      GA },
-    { "ip",    "Send Telnet Interrupt Process",        0,      IP },
-    { "nop",   "Send Telnet 'No operation'",           0,      NOP },
-    { "eor",   "Send Telnet 'End of Record'",          0,      EOR },
-    { "abort", "Send Telnet 'Abort Process'",          0,      ABORT },
-    { "susp",  "Send Telnet 'Suspend Process'",        0,      SUSP },
-    { "eof",   "Send Telnet End of File Character",    0,      xEOF },
-    { "synch", "Perform Telnet 'Synch operation'",     dosynch, SYNCH },
-    { "getstatus", "Send request for STATUS",          get_status, 0 },
-    { "?",     "Display send options",                 0,      SENDQUESTION },
-    { 0 }
-};
-
-static struct sendlist Sendlist2[] = {         /* some synonyms */
-    { "break",         0, 0, BREAK },
 
 
-    { "intp",          0, 0, IP },
-    { "interrupt",     0, 0, IP },
-    { "intr",          0, 0, IP },
-
-    { "help",          0, 0, SENDQUESTION },
+extern int
+       send_esc P((void)),
+       send_help P((void)),
+       send_docmd P((char *)),
+       send_dontcmd P((char *)),
+       send_willcmd P((char *)),
+       send_wontcmd P((char *));
 
 
+static struct sendlist Sendlist[] = {
+    { "ao",    "Send Telnet Abort output",             1, 0, 0, 2, AO },
+    { "ayt",   "Send Telnet 'Are You There'",          1, 0, 0, 2, AYT },
+    { "brk",   "Send Telnet Break",                    1, 0, 0, 2, BREAK },
+    { "break", 0,                                      1, 0, 0, 2, BREAK },
+    { "ec",    "Send Telnet Erase Character",          1, 0, 0, 2, EC },
+    { "el",    "Send Telnet Erase Line",               1, 0, 0, 2, EL },
+    { "escape",        "Send current escape character",        1, 0, send_esc, 1, 0 },
+    { "ga",    "Send Telnet 'Go Ahead' sequence",      1, 0, 0, 2, GA },
+    { "ip",    "Send Telnet Interrupt Process",        1, 0, 0, 2, IP },
+    { "intp",  0,                                      1, 0, 0, 2, IP },
+    { "interrupt", 0,                                  1, 0, 0, 2, IP },
+    { "intr",  0,                                      1, 0, 0, 2, IP },
+    { "nop",   "Send Telnet 'No operation'",           1, 0, 0, 2, NOP },
+    { "eor",   "Send Telnet 'End of Record'",          1, 0, 0, 2, EOR },
+    { "abort", "Send Telnet 'Abort Process'",          1, 0, 0, 2, ABORT },
+    { "susp",  "Send Telnet 'Suspend Process'",        1, 0, 0, 2, SUSP },
+    { "eof",   "Send Telnet End of File Character",    1, 0, 0, 2, xEOF },
+    { "synch", "Perform Telnet 'Synch operation'",     1, 0, dosynch, 2, 0 },
+    { "getstatus", "Send request for STATUS",          1, 0, get_status, 6, 0 },
+    { "?",     "Display send options",                 0, 0, send_help, 0, 0 },
+    { "help",  0,                                      0, 0, send_help, 0, 0 },
+    { "do",    0,                                      0, 1, send_docmd, 3, 0 },
+    { "dont",  0,                                      0, 1, send_dontcmd, 3, 0 },
+    { "will",  0,                                      0, 1, send_willcmd, 3, 0 },
+    { "wont",  0,                                      0, 1, send_wontcmd, 3, 0 },
     { 0 }
 };
 
     { 0 }
 };
 
-static char **
-getnextsend(name)
-char *name;
-{
-    struct sendlist *c = (struct sendlist *) name;
-
-    return (char **) (c+1);
-}
+#define        GETSEND(name) ((struct sendlist *) genget(name, (char **) Sendlist, \
+                               sizeof(struct sendlist)))
 
 
-static struct sendlist *
-getsend(name)
-char *name;
-{
-    struct sendlist *sl;
-
-    if ((sl = (struct sendlist *)
-                       genget(name, (char **) Sendlist, getnextsend)) != 0) {
-       return sl;
-    } else {
-       return (struct sendlist *)
-                               genget(name, (char **) Sendlist2, getnextsend);
-    }
-}
-
-static
+    static int
 sendcmd(argc, argv)
 sendcmd(argc, argv)
-int    argc;
-char   **argv;
+    int  argc;
+    char **argv;
 {
     int what;          /* what we are sending this time */
     int count;         /* how many bytes we are going to need to send */
     int i;
     int question = 0;  /* was at least one argument a question */
     struct sendlist *s;        /* pointer to current command */
 {
     int what;          /* what we are sending this time */
     int count;         /* how many bytes we are going to need to send */
     int i;
     int question = 0;  /* was at least one argument a question */
     struct sendlist *s;        /* pointer to current command */
+    int success = 0;
+    int needconnect = 0;
 
     if (argc < 2) {
        printf("need at least one argument for 'send' command\n");
 
     if (argc < 2) {
        printf("need at least one argument for 'send' command\n");
@@ -370,7 +312,7 @@ char        **argv;
      */
     count = 0;
     for (i = 1; i < argc; i++) {
      */
     count = 0;
     for (i = 1; i < argc; i++) {
-       s = getsend(argv[i]);
+       s = GETSEND(argv[i]);
        if (s == 0) {
            printf("Unknown send argument '%s'\n'send ?' for help.\n",
                        argv[i]);
        if (s == 0) {
            printf("Unknown send argument '%s'\n'send ?' for help.\n",
                        argv[i]);
@@ -380,31 +322,25 @@ char      **argv;
                        argv[i]);
            return 0;
        }
                        argv[i]);
            return 0;
        }
-       switch (s->what) {
-       case SENDQUESTION:
-           question = 1;
-           break;
-       case SENDESCAPE:
-           count += 1;
-           break;
-       case SYNCH:
-           count += 2;
-           break;
-       default:
-           count += 2;
-           break;
+       if (i + s->narg >= argc) {
+           fprintf(stderr,
+           "Need %d argument%s to 'send %s' command.  'send %s ?' for help.\n",
+               s->narg, s->narg == 1 ? "" : "s", s->name, s->name);
+           return 0;
+       }
+       count += s->nbyte;
+       if (s->handler == send_help) {
+           send_help();
+           return 0;
        }
        }
+
+       i += s->narg;
+       needconnect += s->needconnect;
     }
     }
-    if (!connected) {
-       if (count)
-           printf("?Need to be connected first.\n");
-       if (question) {
-           for (s = Sendlist; s->name; s++)
-               if (s->help)
-                   printf("%-15s %s\n", s->name, s->help);
-       } else
-           printf("'send ?' for help\n");
-       return !question;
+    if (!connected && needconnect) {
+       printf("?Need to be connected first.\n");
+       printf("'send ?' for help\n");
+       return 0;
     }
     /* Now, do we have enough room? */
     if (NETROOM() < count) {
     }
     /* Now, do we have enough room? */
     if (NETROOM() < count) {
@@ -415,36 +351,118 @@ char     **argv;
        return 0;
     }
     /* OK, they are all OK, now go through again and actually send */
        return 0;
     }
     /* OK, they are all OK, now go through again and actually send */
+    count = 0;
     for (i = 1; i < argc; i++) {
     for (i = 1; i < argc; i++) {
-       if ((s = getsend(argv[i])) == 0) {
+       if ((s = GETSEND(argv[i])) == 0) {
            fprintf(stderr, "Telnet 'send' error - argument disappeared!\n");
            (void) quit();
            /*NOTREACHED*/
        }
        if (s->handler) {
            fprintf(stderr, "Telnet 'send' error - argument disappeared!\n");
            (void) quit();
            /*NOTREACHED*/
        }
        if (s->handler) {
-           (*s->handler)(s);
+           count++;
+           success += (*s->handler)((s->narg > 0) ? argv[i+1] : 0,
+                                 (s->narg > 1) ? argv[i+2] : 0);
+           i += s->narg;
        } else {
        } else {
-           switch (what = s->what) {
-           case SYNCH:
-               dosynch();
-               break;
-           case SENDQUESTION:
-               for (s = Sendlist; s->name; s++) {
-                   if (s->help)
-                       printf("%-15s %s\n", s->name, s->help);
-               }
-               question = 1;
-               break;
-           case SENDESCAPE:
-               NETADD(escape);
-               break;
-           default:
-               NET2ADD(IAC, what);
-               break;
+           NET2ADD(IAC, what);
+           printoption("SENT", IAC, what);
+       }
+    }
+    return (count == success);
+}
+
+    static int
+send_esc()
+{
+    NETADD(escape);
+    return 1;
+}
+
+    static int
+send_docmd(name)
+    char *name;
+{
+    void send_do();
+    return(send_tncmd(send_do, "do", name));
+}
+
+    static int
+send_dontcmd(name)
+    char *name;
+{
+    void send_dont();
+    return(send_tncmd(send_dont, "dont", name));
+}
+    static int
+send_willcmd(name)
+    char *name;
+{
+    void send_will();
+    return(send_tncmd(send_will, "will", name));
+}
+    static int
+send_wontcmd(name)
+    char *name;
+{
+    void send_wont();
+    return(send_tncmd(send_wont, "wont", name));
+}
+
+    int
+send_tncmd(func, cmd, name)
+    void       (*func)();
+    char       *cmd, *name;
+{
+    char **cpp;
+    extern char *telopts[];
+
+    if (isprefix(name, "help") || isprefix(name, "?")) {
+       register int col, len;
+
+       printf("Usage: send %s <option>\n", cmd);
+       printf("Valid options are:\n\t");
+
+       col = 8;
+       for (cpp = telopts; *cpp; cpp++) {
+           len = strlen(*cpp) + 1;
+           if (col + len > 65) {
+               printf("\n\t");
+               col = 8;
            }
            }
+           printf(" %s", *cpp);
+           col += len;
        }
        }
+       printf("\n");
+       return 0;
+    }
+    cpp = (char **)genget(name, telopts, sizeof(char *));
+    if (Ambiguous(cpp)) {
+       fprintf(stderr,"'%s': ambiguous argument ('send %s ?' for help).\n",
+                                       name, cmd);
+       return 0;
+    }
+    if (cpp == 0) {
+       fprintf(stderr, "'%s': unknown argument ('send %s ?' for help).\n",
+                                       name, cmd);
+       return 0;
+    }
+    if (!connected) {
+       printf("?Need to be connected first.\n");
+       return 0;
+    }
+    (*func)(cpp - telopts, 1);
+    return 1;
+}
+
+    static int
+send_help()
+{
+    struct sendlist *s;        /* pointer to current command */
+    for (s = Sendlist; s->name; s++) {
+       if (s->help)
+           printf("%-15s %s\n", s->name, s->help);
     }
     }
-    return !question;
+    return(0);
 }
 \f
 /*
 }
 \f
 /*
@@ -452,14 +470,14 @@ char      **argv;
  * to by the arguments to the "toggle" command.
  */
 
  * to by the arguments to the "toggle" command.
  */
 
-static
+    static int
 lclchars()
 {
     donelclchars = 1;
     return 1;
 }
 
 lclchars()
 {
     donelclchars = 1;
     return 1;
 }
 
-static
+    static int
 togdebug()
 {
 #ifndef        NOT43
 togdebug()
 {
 #ifndef        NOT43
@@ -478,7 +496,7 @@ togdebug()
 }
 
 
 }
 
 
-static int
+    static int
 togcrlf()
 {
     if (crlf) {
 togcrlf()
 {
     if (crlf) {
@@ -491,9 +509,9 @@ togcrlf()
 
 int binmode;
 
 
 int binmode;
 
-static int
+    static int
 togbinary(val)
 togbinary(val)
-int val;
+    int val;
 {
     donebinarytoggle = 1;
 
 {
     donebinarytoggle = 1;
 
@@ -530,9 +548,9 @@ int val;
     return 1;
 }
 
     return 1;
 }
 
-static int
+    static int
 togrbinary(val)
 togrbinary(val)
-int val;
+    int val;
 {
     donebinarytoggle = 1;
 
 {
     donebinarytoggle = 1;
 
@@ -557,9 +575,9 @@ int val;
     return 1;
 }
 
     return 1;
 }
 
-static int
+    static int
 togxbinary(val)
 togxbinary(val)
-int val;
+    int val;
 {
     donebinarytoggle = 1;
 
 {
     donebinarytoggle = 1;
 
@@ -585,8 +603,16 @@ int val;
 }
 
 
 }
 
 
-extern int togglehelp();
-extern int slc_check();
+extern int togglehelp P((void));
+#if    defined(AUTHENTICATE)
+extern int auth_togdebug P((int));
+#endif
+#if    defined(ENCRYPT)
+extern int EncryptAutoEnc P((int));
+extern int EncryptAutoDec P((int));
+extern int EncryptDebug P((int));
+extern int EncryptVerbose P((int));
+#endif
 
 struct togglelist {
     char       *name;          /* name of toggle */
 
 struct togglelist {
     char       *name;          /* name of toggle */
@@ -607,6 +633,45 @@ static struct togglelist Togglelist[] = {
            0,
                &autosynch,
                    "send interrupt characters in urgent mode" },
            0,
                &autosynch,
                    "send interrupt characters in urgent mode" },
+#if    defined(AUTHENTICATE)
+    { "autologin",
+       "automatic sending of login and/or authentication info",
+           0,
+               &autologin,
+                   "send login name and/or authentication information" },
+    { "authdebug",
+       "Toggle authentication debugging",
+           auth_togdebug,
+               0,
+                    "print authentication debugging information" },
+#endif
+#if    defined(ENCRYPT)
+    { "autoencrypt",
+       "automatic encryption of data stream",
+           EncryptAutoEnc,
+               0,
+                   "automatically encrypt output" },
+    { "autodecrypt",
+       "automatic decryption of data stream",
+           EncryptAutoDec,
+               0,
+                   "automatically decrypt input" },
+    { "verbose_encrypt",
+       "Toggle verbose encryption output",
+           EncryptVerbose,
+               0,
+                   "print verbose encryption output" },
+    { "encdebug",
+       "Toggle encryption debugging",
+           EncryptDebug,
+               0,
+                   "print encryption debugging information" },
+#endif
+    { "skiprc",
+       "don't read ~/.telnetrc file",
+           0,
+               &skiprc,
+                   "read ~/.telnetrc file" },
     { "binary",
        "sending and receiving of binary data",
            togbinary,
     { "binary",
        "sending and receiving of binary data",
            togbinary,
@@ -637,13 +702,6 @@ static struct togglelist Togglelist[] = {
            lclchars,
                &localchars,
                    "recognize certain control characters" },
            lclchars,
                &localchars,
                    "recognize certain control characters" },
-#ifdef KERBEROS
-    { "kerberos",
-       "toggle use of Kerberos authentication",
-           0,
-               &kerberized,
-                   "use Kerberos authentication" },
-#endif
     { " ", "", 0 },            /* empty line */
 #if    defined(unix) && defined(TN3270)
     { "apitrace",
     { " ", "", 0 },            /* empty line */
 #if    defined(unix) && defined(TN3270)
     { "apitrace",
@@ -693,7 +751,7 @@ static struct togglelist Togglelist[] = {
     { 0 }
 };
 
     { 0 }
 };
 
-static
+    static int
 togglehelp()
 {
     struct togglelist *c;
 togglehelp()
 {
     struct togglelist *c;
@@ -711,9 +769,9 @@ togglehelp()
     return 0;
 }
 
     return 0;
 }
 
-static
+    static void
 settogglehelp(set)
 settogglehelp(set)
-int set;
+    int set;
 {
     struct togglelist *c;
 
 {
     struct togglelist *c;
 
@@ -728,27 +786,13 @@ int set;
     }
 }
 
     }
 }
 
-static char **
-getnexttoggle(name)
-char *name;
-{
-    struct togglelist *c = (struct togglelist *) name;
-
-    return (char **) (c+1);
-}
-
-static struct togglelist *
-gettoggle(name)
-char *name;
-{
-    return (struct togglelist *)
-                       genget(name, (char **) Togglelist, getnexttoggle);
-}
+#define        GETTOGGLE(name) (struct togglelist *) \
+               genget(name, (char **) Togglelist, sizeof(struct togglelist))
 
 
-static
+    static int
 toggle(argc, argv)
 toggle(argc, argv)
-int    argc;
-char   *argv[];
+    int  argc;
+    char *argv[];
 {
     int retval = 1;
     char *name;
 {
     int retval = 1;
     char *name;
@@ -763,7 +807,7 @@ char        *argv[];
     argv++;
     while (argc--) {
        name = *argv++;
     argv++;
     while (argc--) {
        name = *argv++;
-       c = gettoggle(name);
+       c = GETTOGGLE(name);
        if (Ambiguous(c)) {
            fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\n",
                                        name);
        if (Ambiguous(c)) {
            fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\n",
                                        name);
@@ -808,10 +852,11 @@ static struct setlist Setlist[] = {
     { "echo",  "character to toggle local echoing on/off", 0, &echoc },
 #endif
     { "escape",        "character to escape back to telnet command mode", 0, &escape },
     { "echo",  "character to toggle local echoing on/off", 0, &echoc },
 #endif
     { "escape",        "character to escape back to telnet command mode", 0, &escape },
-    { "tracefile", "file to write trace intormation to", SetNetTrace, (cc_t *)NetTraceFile},
+    { "rlogin", "rlogin escape character", 0, &rlogin },
+    { "tracefile", "file to write trace information to", SetNetTrace, (cc_t *)NetTraceFile},
     { " ", "" },
     { " ", "The following need 'localchars' to be toggled true", 0, 0 },
     { " ", "" },
     { " ", "The following need 'localchars' to be toggled true", 0, 0 },
-    { "flushoutput", "character to cause an Abort Oubput", 0, termFlushCharp },
+    { "flushoutput", "character to cause an Abort Output", 0, termFlushCharp },
     { "interrupt", "character to cause an Interrupt Process", 0, termIntCharp },
     { "quit",  "character to cause an Abort process", 0, termQuitCharp },
     { "eof",   "character to cause an EOF ", 0, termEofCharp },
     { "interrupt", "character to cause an Interrupt Process", 0, termIntCharp },
     { "quit",  "character to cause an Abort process", 0, termQuitCharp },
     { "eof",   "character to cause an EOF ", 0, termEofCharp },
@@ -827,17 +872,19 @@ static struct setlist Setlist[] = {
     { "stop",  "character to use for XOFF", 0, termStopCharp },
     { "forw1", "alternate end of line character", 0, termForw1Charp },
     { "forw2", "alternate end of line character", 0, termForw2Charp },
     { "stop",  "character to use for XOFF", 0, termStopCharp },
     { "forw1", "alternate end of line character", 0, termForw1Charp },
     { "forw2", "alternate end of line character", 0, termForw2Charp },
+    { "ayt",   "alternate AYT character", 0, termAytCharp },
     { 0 }
 };
 
     { 0 }
 };
 
-#ifdef CRAY
-/* Work around compiler bug */
+#if    defined(CRAY) && !defined(__STDC__)
+/* Work around compiler bug in pcc 4.1.5 */
+    void
 _setlist_init()
 {
 #ifndef        KLUDGELINEMODE
 _setlist_init()
 {
 #ifndef        KLUDGELINEMODE
-#define        N 4
-#else
 #define        N 5
 #define        N 5
+#else
+#define        N 6
 #endif
        Setlist[N+0].charp = &termFlushChar;
        Setlist[N+1].charp = &termIntChar;
 #endif
        Setlist[N+0].charp = &termFlushChar;
        Setlist[N+1].charp = &termIntChar;
@@ -853,37 +900,37 @@ _setlist_init()
        Setlist[N+13].charp = &termStopChar;
        Setlist[N+14].charp = &termForw1Char;
        Setlist[N+15].charp = &termForw2Char;
        Setlist[N+13].charp = &termStopChar;
        Setlist[N+14].charp = &termForw1Char;
        Setlist[N+15].charp = &termForw2Char;
+       Setlist[N+16].charp = &termAytChar;
 #undef N
 }
 #undef N
 }
-#endif /* CRAY */
+#endif /* defined(CRAY) && !defined(__STDC__) */
 
 
-static char **
-getnextset(name)
-char *name;
-{
-    struct setlist *c = (struct setlist *)name;
-
-    return (char **) (c+1);
-}
-
-static struct setlist *
+    static struct setlist *
 getset(name)
 getset(name)
-char *name;
+    char *name;
 {
 {
-    return (struct setlist *) genget(name, (char **) Setlist, getnextset);
+    return (struct setlist *)
+               genget(name, (char **) Setlist, sizeof(struct setlist));
 }
 
 }
 
+    void
 set_escape_char(s)
 set_escape_char(s)
-char *s;
+    char *s;
 {
 {
-       escape = (s && *s) ? special(s) : -1;
-       printf("escape character is '%s'.\n", control(escape));
+       if (rlogin != _POSIX_VDISABLE) {
+               rlogin = (s && *s) ? special(s) : _POSIX_VDISABLE;
+               printf("Telnet rlogin escape character is '%s'.\n",
+                                       control(rlogin));
+       } else {
+               escape = (s && *s) ? special(s) : _POSIX_VDISABLE;
+               printf("Telnet escape character is '%s'.\n", control(escape));
+       }
 }
 
 }
 
-static
+    static int
 setcmd(argc, argv)
 setcmd(argc, argv)
-int    argc;
-char   *argv[];
+    int  argc;
+    char *argv[];
 {
     int value;
     struct setlist *ct;
 {
     int value;
     struct setlist *ct;
@@ -893,8 +940,7 @@ char        *argv[];
        printf("Format is 'set Name Value'\n'set ?' for help.\n");
        return 0;
     }
        printf("Format is 'set Name Value'\n'set ?' for help.\n");
        return 0;
     }
-    if ((argc == 2) &&
-               ((!strcmp(argv[1], "?")) || (!strcmp(argv[1], "help")))) {
+    if ((argc == 2) && (isprefix(argv[1], "?") || isprefix(argv[1], "help"))) {
        for (ct = Setlist; ct->name; ct++)
            printf("%-15s %s\n", ct->name, ct->help);
        printf("\n");
        for (ct = Setlist; ct->name; ct++)
            printf("%-15s %s\n", ct->name, ct->help);
        printf("\n");
@@ -905,7 +951,7 @@ char        *argv[];
 
     ct = getset(argv[1]);
     if (ct == 0) {
 
     ct = getset(argv[1]);
     if (ct == 0) {
-       c = gettoggle(argv[1]);
+       c = GETTOGGLE(argv[1]);
        if (c == 0) {
            fprintf(stderr, "'%s': unknown argument ('set ?' for help).\n",
                        argv[1]);
        if (c == 0) {
            fprintf(stderr, "'%s': unknown argument ('set ?' for help).\n",
                        argv[1]);
@@ -945,7 +991,7 @@ char        *argv[];
        if (strcmp("off", argv[2])) {
            value = special(argv[2]);
        } else {
        if (strcmp("off", argv[2])) {
            value = special(argv[2]);
        } else {
-           value = -1;
+           value = _POSIX_VDISABLE;
        }
        *(ct->charp) = (cc_t)value;
        printf("%s character is '%s'.\n", ct->name, control(*(ct->charp)));
        }
        *(ct->charp) = (cc_t)value;
        printf("%s character is '%s'.\n", ct->name, control(*(ct->charp)));
@@ -954,10 +1000,10 @@ char     *argv[];
     return 1;
 }
 
     return 1;
 }
 
-static
+    static int
 unsetcmd(argc, argv)
 unsetcmd(argc, argv)
-int    argc;
-char   *argv[];
+    int  argc;
+    char *argv[];
 {
     struct setlist *ct;
     struct togglelist *c;
 {
     struct setlist *ct;
     struct togglelist *c;
@@ -968,7 +1014,7 @@ char       *argv[];
            "Need an argument to 'unset' command.  'unset ?' for help.\n");
        return 0;
     }
            "Need an argument to 'unset' command.  'unset ?' for help.\n");
        return 0;
     }
-    if ((!strcmp(argv[1], "?")) || (!strcmp(argv[1], "help"))) {
+    if (isprefix(argv[1], "?") || isprefix(argv[1], "help")) {
        for (ct = Setlist; ct->name; ct++)
            printf("%-15s %s\n", ct->name, ct->help);
        printf("\n");
        for (ct = Setlist; ct->name; ct++)
            printf("%-15s %s\n", ct->name, ct->help);
        printf("\n");
@@ -983,7 +1029,7 @@ char       *argv[];
        name = *argv++;
        ct = getset(name);
        if (ct == 0) {
        name = *argv++;
        ct = getset(name);
        if (ct == 0) {
-           c = gettoggle(name);
+           c = GETTOGGLE(name);
            if (c == 0) {
                fprintf(stderr, "'%s': unknown argument ('unset ?' for help).\n",
                        name);
            if (c == 0) {
                fprintf(stderr, "'%s': unknown argument ('unset ?' for help).\n",
                        name);
@@ -1010,7 +1056,7 @@ char      *argv[];
            (*ct->handler)(0);
            printf("%s reset to \"%s\".\n", ct->name, (char *)ct->charp);
        } else {
            (*ct->handler)(0);
            printf("%s reset to \"%s\".\n", ct->name, (char *)ct->charp);
        } else {
-           *(ct->charp) = -1;
+           *(ct->charp) = _POSIX_VDISABLE;
            printf("%s character is '%s'.\n", ct->name, control(*(ct->charp)));
        }
     }
            printf("%s character is '%s'.\n", ct->name, control(*(ct->charp)));
        }
     }
@@ -1024,6 +1070,7 @@ char      *argv[];
 #ifdef KLUDGELINEMODE
 extern int kludgelinemode;
 
 #ifdef KLUDGELINEMODE
 extern int kludgelinemode;
 
+    static int
 dokludgemode()
 {
     kludgelinemode = 1;
 dokludgemode()
 {
     kludgelinemode = 1;
@@ -1033,7 +1080,7 @@ dokludgemode()
 }
 #endif
 
 }
 #endif
 
-static
+    static int
 dolinemode()
 {
 #ifdef KLUDGELINEMODE
 dolinemode()
 {
 #ifdef KLUDGELINEMODE
@@ -1045,7 +1092,7 @@ dolinemode()
     return 1;
 }
 
     return 1;
 }
 
-static
+    static int
 docharmode()
 {
 #ifdef KLUDGELINEMODE
 docharmode()
 {
 #ifdef KLUDGELINEMODE
@@ -1058,20 +1105,11 @@ docharmode()
     return 1;
 }
 
     return 1;
 }
 
-setmode(bit)
-{
-    return dolmmode(bit, 1);
-}
-
-clearmode(bit)
-{
-    return dolmmode(bit, 0);
-}
-
+    static int
 dolmmode(bit, on)
 dolmmode(bit, on)
-int bit, on;
+    int bit, on;
 {
 {
-    char c;
+    unsigned char c;
     extern int linemode;
 
     if (my_want_state_is_wont(TELOPT_LINEMODE)) {
     extern int linemode;
 
     if (my_want_state_is_wont(TELOPT_LINEMODE)) {
@@ -1088,6 +1126,18 @@ int bit, on;
     return 1;
 }
 
     return 1;
 }
 
+    int
+setmode(bit)
+{
+    return dolmmode(bit, 1);
+}
+
+    int
+clearmode(bit)
+{
+    return dolmmode(bit, 0);
+}
+
 struct modelist {
        char    *name;          /* command name */
        char    *help;          /* help string */
 struct modelist {
        char    *name;          /* command name */
        char    *help;          /* help string */
@@ -1130,20 +1180,8 @@ static struct modelist ModeList[] = {
     { 0 },
 };
 
     { 0 },
 };
 
-static char **
-getnextmode(name)
-char *name;
-{
-    return (char **) (((struct modelist *)name)+1);
-}
-
-static struct modelist *
-getmodecmd(name)
-char *name;
-{
-    return (struct modelist *) genget(name, (char **) ModeList, getnextmode);
-}
 
 
+    int
 modehelp()
 {
     struct modelist *mt;
 modehelp()
 {
     struct modelist *mt;
@@ -1160,17 +1198,20 @@ modehelp()
     return 0;
 }
 
     return 0;
 }
 
-static
+#define        GETMODECMD(name) (struct modelist *) \
+               genget(name, (char **) ModeList, sizeof(struct modelist))
+
+    static int
 modecmd(argc, argv)
 modecmd(argc, argv)
-int    argc;
-char   *argv[];
+    int  argc;
+    char *argv[];
 {
     struct modelist *mt;
 
     if (argc != 2) {
        printf("'mode' command requires an argument\n");
        printf("'mode ?' for help.\n");
 {
     struct modelist *mt;
 
     if (argc != 2) {
        printf("'mode' command requires an argument\n");
        printf("'mode ?' for help.\n");
-    } else if ((mt = getmodecmd(argv[1])) == 0) {
+    } else if ((mt = GETMODECMD(argv[1])) == 0) {
        fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", argv[1]);
     } else if (Ambiguous(mt)) {
        fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]);
        fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", argv[1]);
     } else if (Ambiguous(mt)) {
        fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]);
@@ -1188,11 +1229,14 @@ char    *argv[];
  * "display" command.
  */
 
  * "display" command.
  */
 
-static
+    static int
 display(argc, argv)
 display(argc, argv)
-int    argc;
-char   *argv[];
+    int  argc;
+    char *argv[];
 {
 {
+    struct togglelist *tl;
+    struct setlist *sl;
+
 #define        dotog(tl)       if (tl->variable && tl->actionexplanation) { \
                            if (*tl->variable) { \
                                printf("will"); \
 #define        dotog(tl)       if (tl->variable && tl->actionexplanation) { \
                            if (*tl->variable) { \
                                printf("will"); \
@@ -1209,9 +1253,6 @@ char      *argv[];
                            printf("%-15s \"%s\"\n", sl->name, (char *)sl->charp); \
                    }
 
                            printf("%-15s \"%s\"\n", sl->name, (char *)sl->charp); \
                    }
 
-    struct togglelist *tl;
-    struct setlist *sl;
-
     if (argc == 1) {
        for (tl = Togglelist; tl->name; tl++) {
            dotog(tl);
     if (argc == 1) {
        for (tl = Togglelist; tl->name; tl++) {
            dotog(tl);
@@ -1225,7 +1266,7 @@ char      *argv[];
 
        for (i = 1; i < argc; i++) {
            sl = getset(argv[i]);
 
        for (i = 1; i < argc; i++) {
            sl = getset(argv[i]);
-           tl = gettoggle(argv[i]);
+           tl = GETTOGGLE(argv[i]);
            if (Ambiguous(sl) || Ambiguous(tl)) {
                printf("?Ambiguous argument '%s'.\n", argv[i]);
                return 0;
            if (Ambiguous(sl) || Ambiguous(tl)) {
                printf("?Ambiguous argument '%s'.\n", argv[i]);
                return 0;
@@ -1243,6 +1284,9 @@ char      *argv[];
        }
     }
 /*@*/optionstatus();
        }
     }
 /*@*/optionstatus();
+#if    defined(ENCRYPT)
+    EncryptStatus();
+#endif
     return 1;
 #undef doset
 #undef dotog
     return 1;
 #undef doset
 #undef dotog
@@ -1256,7 +1300,7 @@ char      *argv[];
 /*
  * Set the escape character.
  */
 /*
  * Set the escape character.
  */
-static
+       static int
 setescape(argc, argv)
        int argc;
        char *argv[];
 setescape(argc, argv)
        int argc;
        char *argv[];
@@ -1271,7 +1315,7 @@ setescape(argc, argv)
                arg = argv[1];
        else {
                printf("new escape character: ");
                arg = argv[1];
        else {
                printf("new escape character: ");
-               (void) gets(buf);
+               (void) fgets(buf, sizeof(buf), stdin);
                arg = buf;
        }
        if (arg[0] != '\0')
                arg = buf;
        }
        if (arg[0] != '\0')
@@ -1283,8 +1327,8 @@ setescape(argc, argv)
        return 1;
 }
 
        return 1;
 }
 
-/*VARARGS*/
-static
+    /*VARARGS*/
+    static int
 togcrmod()
 {
     crmod = !crmod;
 togcrmod()
 {
     crmod = !crmod;
@@ -1294,7 +1338,8 @@ togcrmod()
     return 1;
 }
 
     return 1;
 }
 
-/*VARARGS*/
+    /*VARARGS*/
+    int
 suspend()
 {
 #ifdef SIGTSTP
 suspend()
 {
 #ifdef SIGTSTP
@@ -1320,13 +1365,12 @@ suspend()
 }
 
 #if    !defined(TN3270)
 }
 
 #if    !defined(TN3270)
-/*ARGSUSED*/
+    /*ARGSUSED*/
+    int
 shell(argc, argv)
 shell(argc, argv)
-int argc;
-char *argv[];
+    int argc;
+    char *argv[];
 {
 {
-    extern char *rindex();
-
     setcommandmode();
     switch(vfork()) {
     case -1:
     setcommandmode();
     switch(vfork()) {
     case -1:
@@ -1338,39 +1382,47 @@ char *argv[];
            /*
             * Fire up the shell in the child.
             */
            /*
             * Fire up the shell in the child.
             */
-           register char *shell, *shellname;
-
-           shell = getenv("SHELL");
-           if (shell == NULL)
-               shell = "/bin/sh";
-           if ((shellname = rindex(shell, '/')) == 0)
-               shellname = shell;
+           register char *shellp, *shellname;
+           extern char *rindex();
+
+           shellp = getenv("SHELL");
+           if (shellp == NULL)
+               shellp = "/bin/sh";
+           if ((shellname = rindex(shellp, '/')) == 0)
+               shellname = shellp;
            else
                shellname++;
            if (argc > 1)
            else
                shellname++;
            if (argc > 1)
-               execl(shell, shellname, "-c", &saveline[1], 0);
+               execl(shellp, shellname, "-c", &saveline[1], 0);
            else
            else
-               execl(shell, shellname, 0);
+               execl(shellp, shellname, 0);
            perror("Execl");
            _exit(1);
        }
     default:
            (void)wait((int *)0);       /* Wait for the shell to complete */
     }
            perror("Execl");
            _exit(1);
        }
     default:
            (void)wait((int *)0);       /* Wait for the shell to complete */
     }
+    return 1;
 }
 #endif /* !defined(TN3270) */
 
 }
 #endif /* !defined(TN3270) */
 
-/*VARARGS*/
-static
+    /*VARARGS*/
+    static
 bye(argc, argv)
 bye(argc, argv)
-int    argc;           /* Number of arguments */
-char   *argv[];        /* arguments */
+    int  argc;         /* Number of arguments */
+    char *argv[];      /* arguments */
 {
 {
+    extern int resettermname;
+
     if (connected) {
        (void) shutdown(net, 2);
        printf("Connection closed.\n");
        (void) NetClose(net);
        connected = 0;
     if (connected) {
        (void) shutdown(net, 2);
        printf("Connection closed.\n");
        (void) NetClose(net);
        connected = 0;
+       resettermname = 1;
+#if    defined(AUTHENTICATE) || defined(ENCRYPT)
+       auth_encrypt_connect(connected);
+#endif
        /* reset options */
        tninit();
 #if    defined(TN3270)
        /* reset options */
        tninit();
 #if    defined(TN3270)
@@ -1391,6 +1443,16 @@ quit()
        Exit(0);
        /*NOTREACHED*/
 }
        Exit(0);
        /*NOTREACHED*/
 }
+
+/*VARARGS*/
+       int
+logout()
+{
+       send_do(TELOPT_LOGOUT, 1);
+       (void) netflush();
+       return 1;
+}
+
 \f
 /*
  * The SLC command.
 \f
 /*
  * The SLC command.
@@ -1399,12 +1461,11 @@ quit()
 struct slclist {
        char    *name;
        char    *help;
 struct slclist {
        char    *name;
        char    *help;
-       int     (*handler)();
+       void    (*handler)();
        int     arg;
 };
 
        int     arg;
 };
 
-extern int slc_help();
-extern int slc_mode_export(), slc_mode_import(), slcstate();
+extern void slc_help();
 
 struct slclist SlcList[] = {
     { "export",        "Use local special character definitions",
 
 struct slclist SlcList[] = {
     { "export",        "Use local special character definitions",
@@ -1418,7 +1479,7 @@ struct slclist SlcList[] = {
     { 0 },
 };
 
     { 0 },
 };
 
-static
+    static void
 slc_help()
 {
     struct slclist *c;
 slc_help()
 {
     struct slclist *c;
@@ -1433,24 +1494,18 @@ slc_help()
     }
 }
 
     }
 }
 
-static char **
-getnextslc(name)
-char *name;
-{
-    return (char **)(((struct slclist *)name)+1);
-}
-
-static struct slclist *
+    static struct slclist *
 getslc(name)
 getslc(name)
-char *name;
+    char *name;
 {
 {
-    return (struct slclist *)genget(name, (char **) SlcList, getnextslc);
+    return (struct slclist *)
+               genget(name, (char **) SlcList, sizeof(struct slclist));
 }
 
 }
 
-static
+    static
 slccmd(argc, argv)
 slccmd(argc, argv)
-int    argc;
-char   *argv[];
+    int  argc;
+    char *argv[];
 {
     struct slclist *c;
 
 {
     struct slclist *c;
 
@@ -1482,24 +1537,30 @@ char    *argv[];
 struct envlist {
        char    *name;
        char    *help;
 struct envlist {
        char    *name;
        char    *help;
-       int     (*handler)();
+       void    (*handler)();
        int     narg;
 };
 
        int     narg;
 };
 
-extern struct env_lst *env_define();
-extern int env_undefine();
-extern int env_export(), env_unexport();
-extern int env_list(), env_help();
+extern struct env_lst *
+       env_define P((unsigned char *, unsigned char *));
+extern void
+       env_undefine P((unsigned char *)),
+       env_export P((unsigned char *)),
+       env_unexport P((unsigned char *)),
+       env_send P((unsigned char *)),
+       env_list P((void)),
+       env_help P((void));
 
 struct envlist EnvList[] = {
     { "define",        "Define an environment variable",
 
 struct envlist EnvList[] = {
     { "define",        "Define an environment variable",
-                                               (int (*)())env_define,  2 },
+                                               (void (*)())env_define, 2 },
     { "undefine", "Undefine an environment variable",
                                                env_undefine,   1 },
     { "export",        "Mark an environment variable for automatic export",
                                                env_export,     1 },
     { "undefine", "Undefine an environment variable",
                                                env_undefine,   1 },
     { "export",        "Mark an environment variable for automatic export",
                                                env_export,     1 },
-    { "unexport", "Dont mark an environment variable for automatic export",
+    { "unexport", "Don't mark an environment variable for automatic export",
                                                env_unexport,   1 },
                                                env_unexport,   1 },
+    { "send",  "Send an environment variable", env_send,       1 },
     { "list",  "List the current environment variables",
                                                env_list,       0 },
     { "help",  0,                              env_help,               0 },
     { "list",  "List the current environment variables",
                                                env_list,       0 },
     { "help",  0,                              env_help,               0 },
@@ -1507,7 +1568,7 @@ struct envlist EnvList[] = {
     { 0 },
 };
 
     { 0 },
 };
 
-static
+    static void
 env_help()
 {
     struct envlist *c;
 env_help()
 {
     struct envlist *c;
@@ -1522,23 +1583,17 @@ env_help()
     }
 }
 
     }
 }
 
-static char **
-getnextenv(name)
-char *name;
-{
-    return (char **)(((struct envlist *)name)+1);
-}
-
-static struct envlist *
+    static struct envlist *
 getenvcmd(name)
 getenvcmd(name)
-char *name;
+    char *name;
 {
 {
-    return (struct envlist *)genget(name, (char **) EnvList, getnextenv);
+    return (struct envlist *)
+               genget(name, (char **) EnvList, sizeof(struct envlist));
 }
 
 env_cmd(argc, argv)
 }
 
 env_cmd(argc, argv)
-int    argc;
-char   *argv[];
+    int  argc;
+    char *argv[];
 {
     struct envlist *c;
 
 {
     struct envlist *c;
 
@@ -1565,42 +1620,46 @@ char    *argv[];
                c->narg, c->narg == 1 ? "" : "s", c->name);
        return 0;
     }
                c->narg, c->narg == 1 ? "" : "s", c->name);
        return 0;
     }
-    (void)(*c->handler)(argv[2], argv[3]);
+    (*c->handler)(argv[2], argv[3]);
     return 1;
 }
 
 struct env_lst {
        struct env_lst *next;   /* pointer to next structure */
        struct env_lst *prev;   /* pointer to next structure */
     return 1;
 }
 
 struct env_lst {
        struct env_lst *next;   /* pointer to next structure */
        struct env_lst *prev;   /* pointer to next structure */
-       char *var;              /* pointer to variable name */
-       char *value;            /* pointer to varialbe value */
+       unsigned char *var;     /* pointer to variable name */
+       unsigned char *value;   /* pointer to varialbe value */
        int export;             /* 1 -> export with default list of variables */
 };
 
 struct env_lst envlisthead;
 
        int export;             /* 1 -> export with default list of variables */
 };
 
 struct env_lst envlisthead;
 
-struct env_lst *
+       struct env_lst *
 env_find(var)
 env_find(var)
+       unsigned char *var;
 {
        register struct env_lst *ep;
 
        for (ep = envlisthead.next; ep; ep = ep->next) {
 {
        register struct env_lst *ep;
 
        for (ep = envlisthead.next; ep; ep = ep->next) {
-               if (strcmp(ep->var, var) == 0)
+               if (strcmp((char *)ep->var, (char *)var) == 0)
                        return(ep);
        }
        return(NULL);
 }
 
                        return(ep);
        }
        return(NULL);
 }
 
+       void
 env_init()
 {
 env_init()
 {
-       extern char **environ, *index();
+       extern char **environ;
        register char **epp, *cp;
        register struct env_lst *ep;
        register char **epp, *cp;
        register struct env_lst *ep;
+       extern char *index();
 
        for (epp = environ; *epp; epp++) {
                if (cp = index(*epp, '=')) {
                        *cp = '\0';
 
        for (epp = environ; *epp; epp++) {
                if (cp = index(*epp, '=')) {
                        *cp = '\0';
-                       ep = env_define(*epp, cp+1);
+                       ep = env_define((unsigned char *)*epp,
+                                       (unsigned char *)cp+1);
                        ep->export = 0;
                        *cp = '=';
                }
                        ep->export = 0;
                        *cp = '=';
                }
@@ -1610,37 +1669,37 @@ env_init()
         * "unix:0.0", we have to get rid of "unix" and insert our
         * hostname.
         */
         * "unix:0.0", we have to get rid of "unix" and insert our
         * hostname.
         */
-       if ((ep = env_find("DISPLAY")) &&
-           ((*ep->value == ':') || (strncmp(ep->value, "unix:", 5) == 0))) {
+       if ((ep = env_find("DISPLAY"))
+           && ((*ep->value == ':')
+               || (strncmp((char *)ep->value, "unix:", 5) == 0))) {
                char hbuf[256+1];
                char hbuf[256+1];
-               char *cp2 = index(ep->value, ':');
+               char *cp2 = index((char *)ep->value, ':');
 
                gethostname(hbuf, 256);
                hbuf[256] = '\0';
                cp = (char *)malloc(strlen(hbuf) + strlen(cp2) + 1);
 
                gethostname(hbuf, 256);
                hbuf[256] = '\0';
                cp = (char *)malloc(strlen(hbuf) + strlen(cp2) + 1);
-               sprintf(cp, "%s%s", hbuf, cp2);
+               sprintf((char *)cp, "%s%s", hbuf, cp2);
                free(ep->value);
                free(ep->value);
-               ep->value = cp;
+               ep->value = (unsigned char *)cp;
        }
        }
-#ifdef notdef
        /*
         * If USER is not defined, but LOGNAME is, then add
        /*
         * If USER is not defined, but LOGNAME is, then add
-        * USER with the value from LOGNAME.
+        * USER with the value from LOGNAME.  By default, we
+        * don't export the USER variable.
         */
         */
-       if ((env_find("USER") == NULL) && (ep = env_find("LOGNAME")))
-               env_define("USER", ep->value);
-       env_export("USER");
-#endif
-       env_export("DISPLAY");
-       env_export("PRINTER");
+       if ((env_find("USER") == NULL) && (ep = env_find("LOGNAME"))) {
+               env_define((unsigned char *)"USER", ep->value);
+               env_unexport((unsigned char *)"USER");
+       }
+       env_export((unsigned char *)"DISPLAY");
+       env_export((unsigned char *)"PRINTER");
 }
 
 }
 
-struct env_lst *
+       struct env_lst *
 env_define(var, value)
 env_define(var, value)
-char *var, *value;
+       unsigned char *var, *value;
 {
        register struct env_lst *ep;
 {
        register struct env_lst *ep;
-       extern char *savestr();
 
        if (ep = env_find(var)) {
                if (ep->var)
 
        if (ep = env_find(var)) {
                if (ep->var)
@@ -1656,19 +1715,21 @@ char *var, *value;
                        ep->next->prev = ep;
        }
        ep->export = 1;
                        ep->next->prev = ep;
        }
        ep->export = 1;
-       ep->var = savestr(var);
-       ep->value = savestr(value);
+       ep->var = (unsigned char *)strdup((char *)var);
+       ep->value = (unsigned char *)strdup((char *)value);
        return(ep);
 }
 
        return(ep);
 }
 
+       void
 env_undefine(var)
 env_undefine(var)
-char *var;
+       unsigned char *var;
 {
        register struct env_lst *ep;
 
        if (ep = env_find(var)) {
                ep->prev->next = ep->next;
 {
        register struct env_lst *ep;
 
        if (ep = env_find(var)) {
                ep->prev->next = ep->next;
-               ep->next->prev = ep->prev;
+               if (ep->next)
+                       ep->next->prev = ep->prev;
                if (ep->var)
                        free(ep->var);
                if (ep->value)
                if (ep->var)
                        free(ep->var);
                if (ep->value)
@@ -1677,8 +1738,9 @@ char *var;
        }
 }
 
        }
 }
 
+       void
 env_export(var)
 env_export(var)
-char *var;
+       unsigned char *var;
 {
        register struct env_lst *ep;
 
 {
        register struct env_lst *ep;
 
@@ -1686,8 +1748,9 @@ char *var;
                ep->export = 1;
 }
 
                ep->export = 1;
 }
 
+       void
 env_unexport(var)
 env_unexport(var)
-char *var;
+       unsigned char *var;
 {
        register struct env_lst *ep;
 
 {
        register struct env_lst *ep;
 
@@ -1695,6 +1758,30 @@ char *var;
                ep->export = 0;
 }
 
                ep->export = 0;
 }
 
+       void
+env_send(var)
+       unsigned char *var;
+{
+       register struct env_lst *ep;
+
+        if (my_state_is_wont(TELOPT_ENVIRON)) {
+               fprintf(stderr,
+                   "Cannot send '%s': Telnet ENVIRON option not enabled\n",
+                                                                       var);
+               return;
+       }
+       ep = env_find(var);
+       if (ep == 0) {
+               fprintf(stderr, "Cannot send '%s': variable not defined\n",
+                                                                       var);
+               return;
+       }
+       env_opt_start_info();
+       env_opt_add(ep->var);
+       env_opt_end(0);
+}
+
+       void
 env_list()
 {
        register struct env_lst *ep;
 env_list()
 {
        register struct env_lst *ep;
@@ -1705,8 +1792,9 @@ env_list()
        }
 }
 
        }
 }
 
-char *
+       unsigned char *
 env_default(init)
 env_default(init)
+       int init;
 {
        static struct env_lst *nep = NULL;
 
 {
        static struct env_lst *nep = NULL;
 
@@ -1723,9 +1811,9 @@ env_default(init)
        return(NULL);
 }
 
        return(NULL);
 }
 
-char *
+       unsigned char *
 env_getvalue(var)
 env_getvalue(var)
-char *var;
+       unsigned char *var;
 {
        register struct env_lst *ep;
 
 {
        register struct env_lst *ep;
 
@@ -1734,83 +1822,199 @@ char *var;
        return(NULL);
 }
 
        return(NULL);
 }
 
-char *
-savestr(s)
-register char *s;
+#if    defined(AUTHENTICATE)
+/*
+ * The AUTHENTICATE command.
+ */
+
+struct authlist {
+       char    *name;
+       char    *help;
+       int     (*handler)();
+       int     narg;
+};
+
+extern int
+       auth_enable P((int)),
+       auth_disable P((int)),
+       auth_status P((void)),
+       auth_help P((void));
+
+struct authlist AuthList[] = {
+    { "status",        "Display current status of authentication information",
+                                               auth_status,    0 },
+    { "disable", "Disable an authentication type ('auth disable ?' for more)",
+                                               auth_disable,   1 },
+    { "enable", "Enable an authentication type ('auth enable ?' for more)",
+                                               auth_enable,    1 },
+    { "help",  0,                              auth_help,              0 },
+    { "?",     "Print help information",       auth_help,              0 },
+    { 0 },
+};
+
+    static int
+auth_help()
+{
+    struct authlist *c;
+
+    for (c = AuthList; c->name; c++) {
+       if (c->help) {
+           if (*c->help)
+               printf("%-15s %s\n", c->name, c->help);
+           else
+               printf("\n");
+       }
+    }
+    return 0;
+}
+
+auth_cmd(argc, argv)
+    int  argc;
+    char *argv[];
 {
 {
-       register char *ret;
-       if (ret = (char *)malloc(strlen(s)+1))
-               strcpy(ret, s);
-       return(ret);
+    struct authlist *c;
+
+    c = (struct authlist *)
+               genget(argv[1], (char **) AuthList, sizeof(struct authlist));
+    if (c == 0) {
+        fprintf(stderr, "'%s': unknown argument ('auth ?' for help).\n",
+                               argv[1]);
+        return 0;
+    }
+    if (Ambiguous(c)) {
+        fprintf(stderr, "'%s': ambiguous argument ('auth ?' for help).\n",
+                               argv[1]);
+        return 0;
+    }
+    if (c->narg + 2 != argc) {
+       fprintf(stderr,
+           "Need %s%d argument%s to 'auth %s' command.  'auth ?' for help.\n",
+               c->narg < argc + 2 ? "only " : "",
+               c->narg, c->narg == 1 ? "" : "s", c->name);
+       return 0;
+    }
+    return((*c->handler)(argv[2], argv[3]));
 }
 }
+#endif
 
 
-#if    defined(unix)
-#ifdef notdef
+#if    defined(ENCRYPT)
 /*
 /*
- * Some information about our file descriptors.
+ * The ENCRYPT command.
  */
 
  */
 
-char *
-decodeflags(mask)
-int mask;
+struct encryptlist {
+       char    *name;
+       char    *help;
+       int     (*handler)();
+       int     needconnect;
+       int     minarg;
+       int     maxarg;
+};
+
+extern int
+       EncryptEnable P((char *, char *)),
+       EncryptDisable P((char *, char *)),
+       EncryptType P((char *, char *)),
+       EncryptStart P((char *)),
+       EncryptStartInput P((void)),
+       EncryptStartOutput P((void)),
+       EncryptStop P((char *)),
+       EncryptStopInput P((void)),
+       EncryptStopOutput P((void)),
+       EncryptStatus P((void)),
+       EncryptHelp P((void));
+
+struct encryptlist EncryptList[] = {
+    { "enable", "Enable encryption. ('encrypt enable ?' for more)",
+                                               EncryptEnable, 1, 1, 2 },
+    { "disable", "Disable encryption. ('encrypt enable ?' for more)",
+                                               EncryptDisable, 0, 1, 2 },
+    { "type", "Set encryptiong type. ('encrypt type ?' for more)",
+                                               EncryptType, 0, 1, 1 },
+    { "start", "Start encryption. ('encrypt start ?' for more)",
+                                               EncryptStart, 1, 0, 1 },
+    { "stop", "Stop encryption. ('encrypt stop ?' for more)",
+                                               EncryptStop, 1, 0, 1 },
+    { "input", "Start encrypting the input stream",
+                                               EncryptStartInput, 1, 0, 0 },
+    { "-input", "Stop encrypting the input stream",
+                                               EncryptStopInput, 1, 0, 0 },
+    { "output", "Start encrypting the output stream",
+                                               EncryptStartOutput, 1, 0, 0 },
+    { "-output", "Stop encrypting the output stream",
+                                               EncryptStopOutput, 1, 0, 0 },
+
+    { "status",        "Display current status of authentication information",
+                                               EncryptStatus,  0, 0, 0 },
+    { "help",  0,                              EncryptHelp,    0, 0, 0 },
+    { "?",     "Print help information",       EncryptHelp,    0, 0, 0 },
+    { 0 },
+};
+
+    static int
+EncryptHelp()
 {
 {
-    static char buffer[100];
-#define do(m,s) \
-       if (mask&(m)) { \
-           strcat(buffer, (s)); \
-       }
+    struct encryptlist *c;
 
 
-    buffer[0] = 0;                     /* Terminate it */
+    for (c = EncryptList; c->name; c++) {
+       if (c->help) {
+           if (*c->help)
+               printf("%-15s %s\n", c->name, c->help);
+           else
+               printf("\n");
+       }
+    }
+    return 0;
+}
 
 
-#ifdef FREAD
-    do(FREAD, " FREAD");
-#endif
-#ifdef FWRITE
-    do(FWRITE, " FWRITE");
-#endif
-#ifdef F_DUPFP
-    do(F_DUPFD, " F_DUPFD");
-#endif
-#ifdef FNDELAY
-    do(FNDELAY, " FNDELAY");
-#endif
-#ifdef FAPPEND
-    do(FAPPEND, " FAPPEND");
-#endif
-#ifdef FMARK
-    do(FMARK, " FMARK");
-#endif
-#ifdef FDEFER
-    do(FDEFER, " FDEFER");
-#endif
-#ifdef FASYNC
-    do(FASYNC, " FASYNC");
-#endif
-#ifdef FSHLOCK
-    do(FSHLOCK, " FSHLOCK");
-#endif
-#ifdef FEXLOCK
-    do(FEXLOCK, " FEXLOCK");
-#endif
-#ifdef FCREAT
-    do(FCREAT, " FCREAT");
-#endif
-#ifdef FTRUNC
-    do(FTRUNC, " FTRUNC");
-#endif
-#ifdef FEXCL
-    do(FEXCL, " FEXCL");
-#endif
+encrypt_cmd(argc, argv)
+    int  argc;
+    char *argv[];
+{
+    struct encryptlist *c;
 
 
-    return buffer;
+    c = (struct encryptlist *)
+               genget(argv[1], (char **) EncryptList, sizeof(struct encryptlist));
+    if (c == 0) {
+        fprintf(stderr, "'%s': unknown argument ('encrypt ?' for help).\n",
+                               argv[1]);
+        return 0;
+    }
+    if (Ambiguous(c)) {
+        fprintf(stderr, "'%s': ambiguous argument ('encrypt ?' for help).\n",
+                               argv[1]);
+        return 0;
+    }
+    argc -= 2;
+    if (argc < c->minarg || argc > c->maxarg) {
+       if (c->minarg == c->maxarg) {
+           fprintf(stderr, "Need %s%d argument%s ",
+               c->minarg < argc ? "only " : "", c->minarg,
+               c->minarg == 1 ? "" : "s");
+       } else {
+           fprintf(stderr, "Need %s%d-%d arguments ",
+               c->maxarg < argc ? "only " : "", c->minarg, c->maxarg);
+       }
+       fprintf(stderr, "to 'encrypt %s' command.  'encrypt ?' for help.\n",
+               c->name);
+       return 0;
+    }
+    if (c->needconnect && !connected) {
+       if (!(argc && (isprefix(argv[2], "help") || isprefix(argv[2], "?")))) {
+           printf("?Need to be connected first.\n");
+           return 0;
+       }
+    }
+    return ((*c->handler)(argc > 0 ? argv[2] : 0,
+                       argc > 1 ? argv[3] : 0,
+                       argc > 2 ? argv[4] : 0));
 }
 }
-#undef do
-#endif /* notdef */
+#endif
 
 
-#if defined(TN3270)
-static void
+#if    defined(unix) && defined(TN3270)
+    static void
 filestuff(fd)
 filestuff(fd)
-int fd;
+    int fd;
 {
     int res;
 
 {
     int res;
 
@@ -1836,19 +2040,16 @@ int fd;
     }
     printf("\tFlags are 0x%x: %s\n", res, decodeflags(res));
 }
     }
     printf("\tFlags are 0x%x: %s\n", res, decodeflags(res));
 }
-#endif /* defined(TN3270) */
-
-
-#endif /* defined(unix) */
+#endif /* defined(unix) && defined(TN3270) */
 
 /*
  * Print status about the connection.
  */
 
 /*
  * Print status about the connection.
  */
-/*ARGSUSED*/
-static
+    /*ARGSUSED*/
+    static
 status(argc, argv)
 status(argc, argv)
-int    argc;
-char   *argv[];
+    int         argc;
+    char *argv[];
 {
     if (connected) {
        printf("Connected to %s.\n", hostname);
 {
     if (connected) {
        printf("Connected to %s.\n", hostname);
@@ -1873,6 +2074,9 @@ char      *argv[];
            printf("%s character echo\n", (mode&MODE_ECHO) ? "Local" : "Remote");
            if (my_want_state_is_will(TELOPT_LFLOW))
                printf("%s flow control\n", (mode&MODE_FLOW) ? "Local" : "No");
            printf("%s character echo\n", (mode&MODE_ECHO) ? "Local" : "Remote");
            if (my_want_state_is_will(TELOPT_LFLOW))
                printf("%s flow control\n", (mode&MODE_FLOW) ? "Local" : "No");
+#if    defined(ENCRYPT)
+           encrypt_display();
+#endif
        }
     } else {
        printf("No connection.\n");
        }
     } else {
        printf("No connection.\n");
@@ -1911,61 +2115,44 @@ char    *argv[];
     return 1;
 }
 
     return 1;
 }
 
-
-#if    defined(NEED_GETTOS)
-struct tosent {
-       char    *t_name;        /* name */
-       char    **t_aliases;    /* alias list */
-       char    *t_proto;       /* protocol */
-       int     t_tos;          /* Type Of Service bits */
-};
-
-struct tosent *
-gettosbyname(name, proto)
-char *name, *proto;
+#ifdef SIGINFO
+/*
+ * Function that gets called when SIGINFO is received.
+ */
+ayt_status()
 {
 {
-       static struct tosent te;
-       static char *aliasp = 0;
-
-       te.t_name = name;
-       te.t_aliases = &aliasp;
-       te.t_proto = proto;
-       te.t_tos = 020; /* Low Delay bit */
-       return(&te);
+    (void) call(status, "status", "notmuch", 0);
 }
 #endif
 
 }
 #endif
 
-extern int autologin;
-
-int
+    int
 tn(argc, argv)
 tn(argc, argv)
-       int argc;
-       char *argv[];
+    int argc;
+    char *argv[];
 {
     register struct hostent *host = 0;
     struct sockaddr_in sin;
     struct servent *sp = 0;
 {
     register struct hostent *host = 0;
     struct sockaddr_in sin;
     struct servent *sp = 0;
-    static char        hnamebuf[32];
     unsigned long temp, inet_addr();
     extern char *inet_ntoa();
     unsigned long temp, inet_addr();
     extern char *inet_ntoa();
-#if    defined(SRCRT) && defined(IPPROTO_IP)
+#if    defined(IP_OPTIONS) && defined(IPPROTO_IP)
     char *srp = 0, *strrchr();
     unsigned long sourceroute(), srlen;
 #endif
     char *srp = 0, *strrchr();
     unsigned long sourceroute(), srlen;
 #endif
-#if defined(HAS_IP_TOS) || defined(NEED_GETTOS)
-    struct tosent *tp;
-#endif /* defined(HAS_IP_TOS) || defined(NEED_GETTOS) */
     char *cmd, *hostp = 0, *portp = 0, *user = 0;
 
     char *cmd, *hostp = 0, *portp = 0, *user = 0;
 
+    /* clear the socket address prior to use */
+    bzero((char *)&sin, sizeof(sin));
 
     if (connected) {
        printf("?Already connected to %s\n", hostname);
 
     if (connected) {
        printf("?Already connected to %s\n", hostname);
+       setuid(getuid());
        return 0;
     }
     if (argc < 2) {
        return 0;
     }
     if (argc < 2) {
-       (void) strcpy(line, "Connect ");
+       (void) strcpy(line, "open ");
        printf("(to) ");
        printf("(to) ");
-       (void) gets(&line[strlen(line)]);
+       (void) fgets(&line[strlen(line)], sizeof(line) - strlen(line), stdin);
        makeargv();
        argc = margc;
        argv = margv;
        makeargv();
        argc = margc;
        argv = margv;
@@ -1973,6 +2160,8 @@ tn(argc, argv)
     cmd = *argv;
     --argc; ++argv;
     while (argc) {
     cmd = *argv;
     --argc; ++argv;
     while (argc) {
+       if (isprefix(*argv, "help") || isprefix(*argv, "?"))
+           goto usage;
        if (strcmp(*argv, "-l") == 0) {
            --argc; ++argv;
            if (argc == 0)
        if (strcmp(*argv, "-l") == 0) {
            --argc; ++argv;
            if (argc == 0)
@@ -1981,6 +2170,11 @@ tn(argc, argv)
            --argc;
            continue;
        }
            --argc;
            continue;
        }
+       if (strcmp(*argv, "-a") == 0) {
+           --argc; ++argv;
+           autologin = 1;
+           continue;
+       }
        if (hostp == 0) {
            hostp = *argv++;
            --argc;
        if (hostp == 0) {
            hostp = *argv++;
            --argc;
@@ -1992,10 +2186,14 @@ tn(argc, argv)
            continue;
        }
     usage:
            continue;
        }
     usage:
-       printf("usage: %s [-l user] host-name [port]\n", cmd);
+       printf("usage: %s [-l user] [-a] host-name [port]\n", cmd);
+       setuid(getuid());
        return 0;
     }
        return 0;
     }
-#if    defined(SRCRT) && defined(IPPROTO_IP)
+    if (hostp == 0)
+       goto usage;
+
+#if    defined(IP_OPTIONS) && defined(IPPROTO_IP)
     if (hostp[0] == '@' || hostp[0] == '!') {
        if ((hostname = strrchr(hostp, ':')) == NULL)
            hostname = strrchr(hostp, '@');
     if (hostp[0] == '@' || hostp[0] == '!') {
        if ((hostname = strrchr(hostp, ':')) == NULL)
            hostname = strrchr(hostp, '@');
@@ -2004,9 +2202,11 @@ tn(argc, argv)
        temp = sourceroute(hostp, &srp, &srlen);
        if (temp == 0) {
            herror(srp);
        temp = sourceroute(hostp, &srp, &srlen);
        if (temp == 0) {
            herror(srp);
+           setuid(getuid());
            return 0;
        } else if (temp == -1) {
            printf("Bad source route option: %s\n", hostp);
            return 0;
        } else if (temp == -1) {
            printf("Bad source route option: %s\n", hostp);
+           setuid(getuid());
            return 0;
        } else {
            sin.sin_addr.s_addr = temp;
            return 0;
        } else {
            sin.sin_addr.s_addr = temp;
@@ -2018,8 +2218,8 @@ tn(argc, argv)
        if (temp != (unsigned long) -1) {
            sin.sin_addr.s_addr = temp;
            sin.sin_family = AF_INET;
        if (temp != (unsigned long) -1) {
            sin.sin_addr.s_addr = temp;
            sin.sin_family = AF_INET;
-           (void) strcpy(hnamebuf, hostp);
-           hostname = hnamebuf;
+           (void) strcpy(_hostname, hostp);
+           hostname = _hostname;
        } else {
            host = gethostbyname(hostp);
            if (host) {
        } else {
            host = gethostbyname(hostp);
            if (host) {
@@ -2030,13 +2230,16 @@ tn(argc, argv)
 #else  /* defined(h_addr) */
                memcpy((caddr_t)&sin.sin_addr, host->h_addr, host->h_length);
 #endif /* defined(h_addr) */
 #else  /* defined(h_addr) */
                memcpy((caddr_t)&sin.sin_addr, host->h_addr, host->h_length);
 #endif /* defined(h_addr) */
-               hostname = host->h_name;
+               strncpy(_hostname, host->h_name, sizeof(_hostname));
+               _hostname[sizeof(_hostname)-1] = '\0';
+               hostname = _hostname;
            } else {
                herror(hostp);
            } else {
                herror(hostp);
+               setuid(getuid());
                return 0;
            }
        }
                return 0;
            }
        }
-#if    defined(SRCRT) && defined(IPPROTO_IP)
+#if    defined(IP_OPTIONS) && defined(IPPROTO_IP)
     }
 #endif
     if (portp) {
     }
 #endif
     if (portp) {
@@ -2052,6 +2255,7 @@ tn(argc, argv)
                sin.sin_port = sp->s_port;
            else {
                printf("%s: bad port number\n", portp);
                sin.sin_port = sp->s_port;
            else {
                printf("%s: bad port number\n", portp);
+               setuid(getuid());
                return 0;
            }
        } else {
                return 0;
            }
        } else {
@@ -2065,6 +2269,7 @@ tn(argc, argv)
            sp = getservbyname("telnet", "tcp");
            if (sp == 0) {
                fprintf(stderr, "telnet: tcp/telnet: unknown service\n");
            sp = getservbyname("telnet", "tcp");
            if (sp == 0) {
                fprintf(stderr, "telnet: tcp/telnet: unknown service\n");
+               setuid(getuid());
                return 0;
            }
            sin.sin_port = sp->s_port;
                return 0;
            }
            sin.sin_port = sp->s_port;
@@ -2074,19 +2279,30 @@ tn(argc, argv)
     printf("Trying %s...\n", inet_ntoa(sin.sin_addr));
     do {
        net = socket(AF_INET, SOCK_STREAM, 0);
     printf("Trying %s...\n", inet_ntoa(sin.sin_addr));
     do {
        net = socket(AF_INET, SOCK_STREAM, 0);
+       setuid(getuid());
        if (net < 0) {
            perror("telnet: socket");
            return 0;
        }
        if (net < 0) {
            perror("telnet: socket");
            return 0;
        }
-#if    defined(SRCRT) && defined(IPPROTO_IP)
+#if    defined(IP_OPTIONS) && defined(IPPROTO_IP)
        if (srp && setsockopt(net, IPPROTO_IP, IP_OPTIONS, (char *)srp, srlen) < 0)
                perror("setsockopt (IP_OPTIONS)");
 #endif
        if (srp && setsockopt(net, IPPROTO_IP, IP_OPTIONS, (char *)srp, srlen) < 0)
                perror("setsockopt (IP_OPTIONS)");
 #endif
-#if    defined(HAS_IP_TOS) || defined(NEED_GETTOS)
-       if ((tp = gettosbyname("telnet", "tcp")) &&
-           (setsockopt(net, IPPROTO_IP, IP_TOS, &tp->t_tos, sizeof(int)) < 0))
-               perror("telnet: setsockopt TOS (ignored)");
-#endif /* defined(HAS_IP_TOS) || defined(NEED_GETTOS) */
+#if    defined(IPPROTO_IP) && defined(IP_TOS)
+       {
+# if   defined(HAS_GETTOS)
+           struct tosent *tp;
+           if (tos < 0 && (tp = gettosbyname("telnet", "tcp")))
+               tos = tp->t_tos;
+# endif
+           if (tos < 0)
+               tos = 020;      /* Low Delay bit */
+           if (tos
+               && (setsockopt(net, IPPROTO_IP, IP_TOS, &tos, sizeof(int)) < 0)
+               && (errno != ENOPROTOOPT))
+                   perror("telnet: setsockopt (IP_TOS) (ignored)");
+       }
+#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */
 
        if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) {
                perror("setsockopt (SO_DEBUG)");
 
        if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) {
                perror("setsockopt (SO_DEBUG)");
@@ -2112,38 +2328,41 @@ tn(argc, argv)
            return 0;
        }
        connected++;
            return 0;
        }
        connected++;
+#if    defined(AUTHENTICATE) || defined(ENCRYPT)
+       auth_encrypt_connect(connected);
+#endif
     } while (connected == 0);
     cmdrc(hostp, hostname);
     if (autologin && user == NULL) {
        struct passwd *pw;
     } while (connected == 0);
     cmdrc(hostp, hostname);
     if (autologin && user == NULL) {
        struct passwd *pw;
-       uid_t uid = getuid();
 
 
-       user = getlogin();
+       user = getenv("USER");
        if (user == NULL ||
        if (user == NULL ||
-           (pw = getpwnam(user)) && pw->pw_uid != uid)
-               if (pw = getpwuid(uid))
+           (pw = getpwnam(user)) && pw->pw_uid != getuid()) {
+               if (pw = getpwuid(getuid()))
                        user = pw->pw_name;
                else
                        user = NULL;
                        user = pw->pw_name;
                else
                        user = NULL;
+       }
     }
     if (user) {
     }
     if (user) {
-       env_define("USER", user);
-       env_export("USER");
+       env_define((unsigned char *)"USER", (unsigned char *)user);
+       env_export((unsigned char *)"USER");
     }
     (void) call(status, "status", "notmuch", 0);
     if (setjmp(peerdied) == 0)
     }
     (void) call(status, "status", "notmuch", 0);
     if (setjmp(peerdied) == 0)
-       telnet();
+       telnet(user);
     (void) NetClose(net);
     ExitString("Connection closed by foreign host.\n",1);
     /*NOTREACHED*/
 }
 
     (void) NetClose(net);
     ExitString("Connection closed by foreign host.\n",1);
     /*NOTREACHED*/
 }
 
-
 #define HELPINDENT (sizeof ("connect"))
 
 static char
        openhelp[] =    "connect to a site",
        closehelp[] =   "close current connection",
 #define HELPINDENT (sizeof ("connect"))
 
 static char
        openhelp[] =    "connect to a site",
        closehelp[] =   "close current connection",
+       logouthelp[] =  "forcibly logout remote user and close the connection",
        quithelp[] =    "exit telnet",
        statushelp[] =  "print status information",
        helphelp[] =    "print help information",
        quithelp[] =    "exit telnet",
        statushelp[] =  "print status information",
        helphelp[] =    "print help information",
@@ -2156,6 +2375,12 @@ static char
 #if    defined(TN3270) && defined(unix)
        transcomhelp[] = "specify Unix command for transparent mode pipe",
 #endif /* defined(TN3270) && defined(unix) */
 #if    defined(TN3270) && defined(unix)
        transcomhelp[] = "specify Unix command for transparent mode pipe",
 #endif /* defined(TN3270) && defined(unix) */
+#if    defined(AUTHENTICATE)
+       authhelp[] =    "turn on (off) authentication ('auth ?' for more)",
+#endif
+#if    defined(ENCRYPT)
+       encrypthelp[] = "turn on (off) encryption ('encrypt ?' for more)",
+#endif
 #if    defined(unix)
        zhelp[] =       "suspend telnet",
 #endif /* defined(unix) */
 #if    defined(unix)
        zhelp[] =       "suspend telnet",
 #endif /* defined(unix) */
@@ -2163,10 +2388,11 @@ static char
        envhelp[] =     "change environment variables ('environ ?' for more)",
        modestring[] = "try to enter line or character mode ('mode ?' for more)";
 
        envhelp[] =     "change environment variables ('environ ?' for more)",
        modestring[] = "try to enter line or character mode ('mode ?' for more)";
 
-extern int     help(), shell();
+extern int     help();
 
 static Command cmdtab[] = {
        { "close",      closehelp,      bye,            1 },
 
 static Command cmdtab[] = {
        { "close",      closehelp,      bye,            1 },
+       { "logout",     logouthelp,     logout,         1 },
        { "display",    displayhelp,    display,        0 },
        { "mode",       modestring,     modecmd,        0 },
        { "open",       openhelp,       tn,             0 },
        { "display",    displayhelp,    display,        0 },
        { "mode",       modestring,     modecmd,        0 },
        { "open",       openhelp,       tn,             0 },
@@ -2180,6 +2406,12 @@ static Command cmdtab[] = {
 #if    defined(TN3270) && defined(unix)
        { "transcom",   transcomhelp,   settranscom,    0 },
 #endif /* defined(TN3270) && defined(unix) */
 #if    defined(TN3270) && defined(unix)
        { "transcom",   transcomhelp,   settranscom,    0 },
 #endif /* defined(TN3270) && defined(unix) */
+#if    defined(AUTHENTICATE)
+       { "auth",       authhelp,       auth_cmd,       0 },
+#endif
+#if    defined(ENCRYPT)
+       { "encrypt",    encrypthelp,    encrypt_cmd,    0 },
+#endif
 #if    defined(unix)
        { "z",          zhelp,          suspend,        0 },
 #endif /* defined(unix) */
 #if    defined(unix)
        { "z",          zhelp,          suspend,        0 },
 #endif /* defined(unix) */
@@ -2208,10 +2440,10 @@ static Command cmdtab2[] = {
  * Call routine with argc, argv set from args (terminated by 0).
  */
 
  * Call routine with argc, argv set from args (terminated by 0).
  */
 
-/*VARARGS1*/
-static
+    /*VARARGS1*/
+    static
 call(va_alist)
 call(va_alist)
-va_dcl
+    va_dcl
 {
     va_list ap;
     typedef int (*intrtn_t)();
 {
     va_list ap;
     typedef int (*intrtn_t)();
@@ -2229,33 +2461,22 @@ va_dcl
 }
 
 
 }
 
 
-static char **
-getnextcmd(name)
-char *name;
-{
-    Command *c = (Command *) name;
-
-    return (char **) (c+1);
-}
-
-static Command *
+    static Command *
 getcmd(name)
 getcmd(name)
-char *name;
+    char *name;
 {
     Command *cm;
 
 {
     Command *cm;
 
-    if ((cm = (Command *) genget(name, (char **) cmdtab, getnextcmd)) != 0) {
+    if (cm = (Command *) genget(name, (char **) cmdtab, sizeof(Command)))
        return cm;
        return cm;
-    } else {
-       return (Command *) genget(name, (char **) cmdtab2, getnextcmd);
-    }
+    return (Command *) genget(name, (char **) cmdtab2, sizeof(Command));
 }
 
 }
 
-void
+    void
 command(top, tbuf, cnt)
 command(top, tbuf, cnt)
-       int top;
-       char *tbuf;
-       int cnt;
+    int top;
+    char *tbuf;
+    int cnt;
 {
     register Command *c;
 
 {
     register Command *c;
 
@@ -2269,7 +2490,8 @@ command(top, tbuf, cnt)
 #endif /* defined(unix) */
     }
     for (;;) {
 #endif /* defined(unix) */
     }
     for (;;) {
-       printf("%s> ", prompt);
+       if (rlogin == _POSIX_VDISABLE)
+               printf("%s> ", prompt);
        if (tbuf) {
            register char *cp;
            cp = line;
        if (tbuf) {
            register char *cp;
            cp = line;
@@ -2279,10 +2501,13 @@ command(top, tbuf, cnt)
            if (cp == line || *--cp != '\n' || cp == line)
                goto getline;
            *cp = '\0';
            if (cp == line || *--cp != '\n' || cp == line)
                goto getline;
            *cp = '\0';
-           printf("%s\n", line);
+           if (rlogin == _POSIX_VDISABLE)
+               printf("%s\n", line);
        } else {
        getline:
        } else {
        getline:
-           if (gets(line) == NULL) {
+           if (rlogin != _POSIX_VDISABLE)
+               printf("%s> ", prompt);
+           if (fgets(line, sizeof(line), stdin) == NULL) {
                if (feof(stdin) || ferror(stdin)) {
                    (void) quit();
                    /*NOTREACHED*/
                if (feof(stdin) || ferror(stdin)) {
                    (void) quit();
                    /*NOTREACHED*/
@@ -2331,7 +2556,7 @@ command(top, tbuf, cnt)
 /*
  * Help command.
  */
 /*
  * Help command.
  */
-static
+       static
 help(argc, argv)
        int argc;
        char *argv[];
 help(argc, argv)
        int argc;
        char *argv[];
@@ -2374,6 +2599,9 @@ cmdrc(m1, m2)
     int l2 = strlen(m2);
     char m1save[64];
 
     int l2 = strlen(m2);
     char m1save[64];
 
+    if (skiprc)
+       return;
+
     strcpy(m1save, m1);
     m1 = m1save;
 
     strcpy(m1save, m1);
     m1 = m1save;
 
@@ -2398,6 +2626,10 @@ cmdrc(m1, m2)
            break;
        if (line[0] == '#')
            continue;
            break;
        if (line[0] == '#')
            continue;
+       if (gotmachine) {
+           if (!isspace(line[0]))
+               gotmachine = 0;
+       }
        if (gotmachine == 0) {
            if (isspace(line[0]))
                continue;
        if (gotmachine == 0) {
            if (isspace(line[0]))
                continue;
@@ -2405,14 +2637,13 @@ cmdrc(m1, m2)
                strncpy(line, &line[l1], sizeof(line) - l1);
            else if (strncasecmp(line, m2, l2) == 0)
                strncpy(line, &line[l2], sizeof(line) - l2);
                strncpy(line, &line[l1], sizeof(line) - l1);
            else if (strncasecmp(line, m2, l2) == 0)
                strncpy(line, &line[l2], sizeof(line) - l2);
+           else if (strncasecmp(line, "DEFAULT", 7) == 0)
+               strncpy(line, &line[7], sizeof(line) - 7);
            else
                continue;
            else
                continue;
-           gotmachine = 1;
-       } else {
-           if (!isspace(line[0])) {
-               gotmachine = 0;
+           if (line[0] != ' ' && line[0] != '\t' && line[0] != '\n')
                continue;
                continue;
-           }
+           gotmachine = 1;
        }
        makeargv();
        if (margv[0] == 0)
        }
        makeargv();
        if (margv[0] == 0)
@@ -2438,7 +2669,7 @@ cmdrc(m1, m2)
     fclose(rcfile);
 }
 
     fclose(rcfile);
 }
 
-#if    defined(SRCRT) && defined(IPPROTO_IP)
+#if    defined(IP_OPTIONS) && defined(IPPROTO_IP)
 
 /*
  * Source route is handed in as
 
 /*
  * Source route is handed in as
@@ -2479,14 +2710,14 @@ cmdrc(m1, m2)
  *             pointed to by *cpp is.
  *     
  */
  *             pointed to by *cpp is.
  *     
  */
-unsigned long
+       unsigned long
 sourceroute(arg, cpp, lenp)
 sourceroute(arg, cpp, lenp)
-char   *arg;
-char   **cpp;
-int    *lenp;
+       char    *arg;
+       char    **cpp;
+       int     *lenp;
 {
        static char lsr[44];
 {
        static char lsr[44];
-       char *cp, *cp2, *lsrp, *lsrep, *index();
+       char *cp, *cp2, *lsrp, *lsrep;
        register int tmp;
        struct in_addr sin_addr;
        register struct hostent *host = 0;
        register int tmp;
        struct in_addr sin_addr;
        register struct hostent *host = 0;
@@ -2589,19 +2820,3 @@ int      *lenp;
        return(sin_addr.s_addr);
 }
 #endif
        return(sin_addr.s_addr);
 }
 #endif
-
-#if    defined(NOSTRNCASECMP)
-strncasecmp(p1, p2, len)
-register char *p1, *p2;
-int len;
-{
-    while (len--) {
-       if (tolower(*p1) != tolower(*p2))
-          return(tolower(*p1) - tolower(*p2));
-       if (*p1 == '\0')
-           return(0);
-       p1++, p2++;
-    }
-    return(0);
-}
-#endif