BSD 4_4_Lite2 release
[unix-history] / usr / src / usr.bin / telnet / utilities.c
index 8f4e0f5..06d08a4 100644 (file)
@@ -1,30 +1,46 @@
 /*
 /*
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  *
- * Redistribution and use in source and binary forms are permitted
- * provided that: (1) source distributions retain this entire copyright
- * notice and comment, and (2) distributions including binaries display
- * the following acknowledgement:  ``This product includes software
- * developed by the University of California, Berkeley and its contributors''
- * in the documentation or other materials provided with the distribution
- * and in all advertising materials mentioning features or use of this
- * software. Neither the name of the University nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * 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[] = "@(#)utilities.c        1.17 (Berkeley) 6/1/90";
+static char sccsid[] = "@(#)utilities.c        8.3 (Berkeley) 5/30/95";
 #endif /* not lint */
 
 #define        TELOPTS
 #define        TELCMDS
 #endif /* not lint */
 
 #define        TELOPTS
 #define        TELCMDS
+#define        SLC_NAMES
 #include <arpa/telnet.h>
 #include <sys/types.h>
 #include <arpa/telnet.h>
 #include <sys/types.h>
+#include <sys/time.h>
 
 #include <ctype.h>
 
 
 #include <ctype.h>
 
@@ -47,9 +63,9 @@ int   prettydump;
  *     Upcase (in place) the argument.
  */
 
  *     Upcase (in place) the argument.
  */
 
-void
+    void
 upcase(argument)
 upcase(argument)
-register char *argument;
+    register char *argument;
 {
     register int c;
 
 {
     register int c;
 
@@ -67,13 +83,9 @@ register char *argument;
  * Compensate for differences in 4.2 and 4.3 systems.
  */
 
  * Compensate for differences in 4.2 and 4.3 systems.
  */
 
-int
+    int
 SetSockOpt(fd, level, option, yesno)
 SetSockOpt(fd, level, option, yesno)
-int
-       fd,
-       level,
-       option,
-       yesno;
+    int fd, level, option, yesno;
 {
 #ifndef        NOT43
     return setsockopt(fd, level, option,
 {
 #ifndef        NOT43
     return setsockopt(fd, level, option,
@@ -94,33 +106,33 @@ int
 
 unsigned char NetTraceFile[256] = "(standard output)";
 
 
 unsigned char NetTraceFile[256] = "(standard output)";
 
-void
+    void
 SetNetTrace(file)
 SetNetTrace(file)
-register char *file;
+    register char *file;
 {
     if (NetTrace && NetTrace != stdout)
        fclose(NetTrace);
     if (file  && (strcmp(file, "-") != 0)) {
        NetTrace = fopen(file, "w");
        if (NetTrace) {
 {
     if (NetTrace && NetTrace != stdout)
        fclose(NetTrace);
     if (file  && (strcmp(file, "-") != 0)) {
        NetTrace = fopen(file, "w");
        if (NetTrace) {
-           strcpy(NetTraceFile, file);
+           strcpy((char *)NetTraceFile, file);
            return;
        }
        fprintf(stderr, "Cannot open %s.\n", file);
     }
     NetTrace = stdout;
            return;
        }
        fprintf(stderr, "Cannot open %s.\n", file);
     }
     NetTrace = stdout;
-    strcpy(NetTraceFile, "(standard output)");
+    strcpy((char *)NetTraceFile, "(standard output)");
 }
 
 }
 
-void
+    void
 Dump(direction, buffer, length)
 Dump(direction, buffer, length)
-char   direction;
-char   *buffer;
-int    length;
+    char direction;
+    unsigned char *buffer;
+    int length;
 {
 #   define BYTES_PER_LINE      32
 #   define min(x,y)    ((x<y)? x:y)
 {
 #   define BYTES_PER_LINE      32
 #   define min(x,y)    ((x<y)? x:y)
-    char *pThis;
+    unsigned char *pThis;
     int offset;
     extern pettydump;
 
     int offset;
     extern pettydump;
 
@@ -164,27 +176,43 @@ int       length;
 }
 
 
 }
 
 
-void
-printoption(direction, fmt, option)
-       char *direction, *fmt;
-       int option;
+       void
+printoption(direction, cmd, option)
+       char *direction;
+       int cmd, option;
 {
        if (!showoptions)
                return;
 {
        if (!showoptions)
                return;
-       fprintf(NetTrace, "%s ", direction);
-       if (TELOPT_OK(option))
-               fprintf(NetTrace, "%s %s", fmt, TELOPT(option));
-       else if (TELCMD_OK(option))
-               fprintf(NetTrace, "%s %s", fmt, TELCMD(option));
-       else
-               fprintf(NetTrace, "%s %d", fmt, option);
-       if (NetTrace == stdout)
+       if (cmd == IAC) {
+               if (TELCMD_OK(option))
+                   fprintf(NetTrace, "%s IAC %s", direction, TELCMD(option));
+               else
+                   fprintf(NetTrace, "%s IAC %d", direction, option);
+       } else {
+               register char *fmt;
+               fmt = (cmd == WILL) ? "WILL" : (cmd == WONT) ? "WONT" :
+                       (cmd == DO) ? "DO" : (cmd == DONT) ? "DONT" : 0;
+               if (fmt) {
+                   fprintf(NetTrace, "%s %s ", direction, fmt);
+                   if (TELOPT_OK(option))
+                       fprintf(NetTrace, "%s", TELOPT(option));
+                   else if (option == TELOPT_EXOPL)
+                       fprintf(NetTrace, "EXOPL");
+                   else
+                       fprintf(NetTrace, "%d", option);
+               } else
+                   fprintf(NetTrace, "%s %d %d", direction, cmd, option);
+       }
+       if (NetTrace == stdout) {
            fprintf(NetTrace, "\r\n");
            fprintf(NetTrace, "\r\n");
-       else
+           fflush(NetTrace);
+       } else {
            fprintf(NetTrace, "\n");
            fprintf(NetTrace, "\n");
+       }
        return;
 }
 
        return;
 }
 
+    void
 optionstatus()
 {
     register int i;
 optionstatus()
 {
     register int i;
@@ -261,26 +289,21 @@ optionstatus()
 
 }
 
 
 }
 
-char *slcnames[] = { SLC_NAMES };
-
-#ifdef KERBEROS
-static char *authtypes[3] = { "NONE", "PRIVATE", "KERBEROS" };
-#else
-static char *authtypes[2] = { "NONE", "PRIVATE" };
-#endif
-
-void
+    void
 printsub(direction, pointer, length)
 printsub(direction, pointer, length)
-char   direction;              /* '<' or '>' */
-unsigned char  *pointer;       /* where suboption data sits */
-int    length;                 /* length of suboption data */
+    char direction;    /* '<' or '>' */
+    unsigned char *pointer;    /* where suboption data sits */
+    int                  length;       /* length of suboption data */
 {
     register int i;
 {
     register int i;
+    char buf[512];
+    extern int want_status_response;
 
 
-    if (showoptions) {
+    if (showoptions || direction == 0 ||
+       (want_status_response && (pointer[0] == TELOPT_STATUS))) {
        if (direction) {
        if (direction) {
-           fprintf(NetTrace, "%s suboption ",
-                               (direction == '<')? "Received":"Sent");
+           fprintf(NetTrace, "%s IAC SB ",
+                               (direction == '<')? "RCVD":"SENT");
            if (length >= 3) {
                register int j;
 
            if (length >= 3) {
                register int j;
 
@@ -307,7 +330,9 @@ int length;                 /* length of suboption data */
            length -= 2;
        }
        if (length < 1) {
            length -= 2;
        }
        if (length < 1) {
-           fprintf(NetTrace, "(Empty suboption???)");
+           fprintf(NetTrace, "(Empty suboption??\?)");
+           if (NetTrace == stdout)
+               fflush(NetTrace);
            return;
        }
        switch (pointer[0]) {
            return;
        }
        switch (pointer[0]) {
@@ -315,7 +340,7 @@ int length;                 /* length of suboption data */
            fprintf(NetTrace, "TERMINAL-TYPE ");
            switch (pointer[1]) {
            case TELQUAL_IS:
            fprintf(NetTrace, "TERMINAL-TYPE ");
            switch (pointer[1]) {
            case TELQUAL_IS:
-               fprintf(NetTrace, "IS \"%.*s\"", length-2, pointer+2);
+               fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2);
                break;
            case TELQUAL_SEND:
                fprintf(NetTrace, "SEND");
                break;
            case TELQUAL_SEND:
                fprintf(NetTrace, "SEND");
@@ -329,19 +354,19 @@ int       length;                 /* length of suboption data */
        case TELOPT_TSPEED:
            fprintf(NetTrace, "TERMINAL-SPEED");
            if (length < 2) {
        case TELOPT_TSPEED:
            fprintf(NetTrace, "TERMINAL-SPEED");
            if (length < 2) {
-               fprintf(NetTrace, " (empty suboption???)");
+               fprintf(NetTrace, " (empty suboption??\?)");
                break;
            }
            switch (pointer[1]) {
            case TELQUAL_IS:
                fprintf(NetTrace, " IS ");
                break;
            }
            switch (pointer[1]) {
            case TELQUAL_IS:
                fprintf(NetTrace, " IS ");
-               fprintf(NetTrace, "%.*s", length-2, pointer+2);
+               fprintf(NetTrace, "%.*s", length-2, (char *)pointer+2);
                break;
            default:
                if (pointer[1] == 1)
                    fprintf(NetTrace, " SEND");
                else
                break;
            default:
                if (pointer[1] == 1)
                    fprintf(NetTrace, " SEND");
                else
-                   fprintf(NetTrace, " %d (unknown)");
+                   fprintf(NetTrace, " %d (unknown)", pointer[1]);
                for (i = 2; i < length; i++)
                    fprintf(NetTrace, " ?%d?", pointer[i]);
                break;
                for (i = 2; i < length; i++)
                    fprintf(NetTrace, " ?%d?", pointer[i]);
                break;
@@ -351,16 +376,20 @@ int       length;                 /* length of suboption data */
        case TELOPT_LFLOW:
            fprintf(NetTrace, "TOGGLE-FLOW-CONTROL");
            if (length < 2) {
        case TELOPT_LFLOW:
            fprintf(NetTrace, "TOGGLE-FLOW-CONTROL");
            if (length < 2) {
-               fprintf(NetTrace, " (empty suboption???)");
+               fprintf(NetTrace, " (empty suboption??\?)");
                break;
            }
            switch (pointer[1]) {
                break;
            }
            switch (pointer[1]) {
-           case 0:
+           case LFLOW_OFF:
                fprintf(NetTrace, " OFF"); break;
                fprintf(NetTrace, " OFF"); break;
-           case 1:
+           case LFLOW_ON:
                fprintf(NetTrace, " ON"); break;
                fprintf(NetTrace, " ON"); break;
+           case LFLOW_RESTART_ANY:
+               fprintf(NetTrace, " RESTART-ANY"); break;
+           case LFLOW_RESTART_XON:
+               fprintf(NetTrace, " RESTART-XON"); break;
            default:
            default:
-               fprintf(NetTrace, " %d (unknown)");
+               fprintf(NetTrace, " %d (unknown)", pointer[1]);
            }
            for (i = 2; i < length; i++)
                fprintf(NetTrace, " ?%d?", pointer[i]);
            }
            for (i = 2; i < length; i++)
                fprintf(NetTrace, " ?%d?", pointer[i]);
@@ -369,7 +398,7 @@ int length;                 /* length of suboption data */
        case TELOPT_NAWS:
            fprintf(NetTrace, "NAWS");
            if (length < 2) {
        case TELOPT_NAWS:
            fprintf(NetTrace, "NAWS");
            if (length < 2) {
-               fprintf(NetTrace, " (empty suboption???)");
+               fprintf(NetTrace, " (empty suboption??\?)");
                break;
            }
            if (length == 2) {
                break;
            }
            if (length == 2) {
@@ -378,67 +407,160 @@ int      length;                 /* length of suboption data */
            }
            fprintf(NetTrace, " %d %d (%d)",
                pointer[1], pointer[2],
            }
            fprintf(NetTrace, " %d %d (%d)",
                pointer[1], pointer[2],
-               (((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2]));
+               (int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2])));
            if (length == 4) {
                fprintf(NetTrace, " ?%d?", pointer[3]);
                break;
            }
            fprintf(NetTrace, " %d %d (%d)",
                pointer[3], pointer[4],
            if (length == 4) {
                fprintf(NetTrace, " ?%d?", pointer[3]);
                break;
            }
            fprintf(NetTrace, " %d %d (%d)",
                pointer[3], pointer[4],
-               (((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4]));
+               (int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4])));
            for (i = 5; i < length; i++)
                fprintf(NetTrace, " ?%d?", pointer[i]);
            break;
 
            for (i = 5; i < length; i++)
                fprintf(NetTrace, " ?%d?", pointer[i]);
            break;
 
-#ifdef KERBEROS
+#if    defined(AUTHENTICATION)
        case TELOPT_AUTHENTICATION:
        case TELOPT_AUTHENTICATION:
-           fprintf(NetTrace, "Authentication information ");
+           fprintf(NetTrace, "AUTHENTICATION");
+           if (length < 2) {
+               fprintf(NetTrace, " (empty suboption??\?)");
+               break;
+           }
            switch (pointer[1]) {
            switch (pointer[1]) {
+           case TELQUAL_REPLY:
            case TELQUAL_IS:
            case TELQUAL_IS:
-               switch (pointer[2]) {
-               case TELQUAL_AUTHTYPE_NONE:
-               case TELQUAL_AUTHTYPE_PRIVATE:
-               case TELQUAL_AUTHTYPE_KERBEROS:
+               fprintf(NetTrace, " %s ", (pointer[1] == TELQUAL_IS) ?
+                                                       "IS" : "REPLY");
+               if (AUTHTYPE_NAME_OK(pointer[2]))
+                   fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[2]));
+               else
+                   fprintf(NetTrace, "%d ", pointer[2]);
+               if (length < 3) {
+                   fprintf(NetTrace, "(partial suboption??\?)");
+                   break;
+               }
+               fprintf(NetTrace, "%s|%s",
+                       ((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
+                       "CLIENT" : "SERVER",
+                       ((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
+                       "MUTUAL" : "ONE-WAY");
+
+               auth_printsub(&pointer[1], length - 1, buf, sizeof(buf));
+               fprintf(NetTrace, "%s", buf);
+               break;
 
 
-                       fprintf(NetTrace, "is type %s\r\n", authtypes[pointer[2]]);
-                       break;
-               default:
-                       fprintf(NetTrace, "is type unknown\r\n");
+           case TELQUAL_SEND:
+               i = 2;
+               fprintf(NetTrace, " SEND ");
+               while (i < length) {
+                   if (AUTHTYPE_NAME_OK(pointer[i]))
+                       fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[i]));
+                   else
+                       fprintf(NetTrace, "%d ", pointer[i]);
+                   if (++i >= length) {
+                       fprintf(NetTrace, "(partial suboption??\?)");
                        break;
                        break;
+                   }
+                   fprintf(NetTrace, "%s|%s ",
+                       ((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
+                                                       "CLIENT" : "SERVER",
+                       ((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
+                                                       "MUTUAL" : "ONE-WAY");
+                   ++i;
                }
                }
+               break;
 
 
-           case TELQUAL_SEND:
-           {
-               int     idx = 2;
-               fprintf(NetTrace, "- request to send, types");
-               for (idx = 2; idx < length - 1; idx++)
-                       switch (pointer[idx]) {
-                       case TELQUAL_AUTHTYPE_NONE:
-                       case TELQUAL_AUTHTYPE_PRIVATE:
-                       case TELQUAL_AUTHTYPE_KERBEROS:
-                               fprintf(NetTrace, " %s",
-                                       authtypes[pointer[idx]]);
-                                       break;
-                       default:
-                               fprintf(NetTrace, " <unknown %u>",
-                                       pointer[idx]);
-                               break;
-                       }
-               fprintf(NetTrace, "\r\n");
+           case TELQUAL_NAME:
+               i = 2;
+               fprintf(NetTrace, " NAME \"");
+               while (i < length)
+                   putc(pointer[i++], NetTrace);
+               putc('"', NetTrace);
+               break;
+
+           default:
+                   for (i = 2; i < length; i++)
+                       fprintf(NetTrace, " ?%d?", pointer[i]);
+                   break;
            }
            }
+           break;
+#endif
+
+#ifdef ENCRYPTION
+       case TELOPT_ENCRYPT:
+           fprintf(NetTrace, "ENCRYPT");
+           if (length < 2) {
+               fprintf(NetTrace, " (empty suboption??\?)");
+               break;
+           }
+           switch (pointer[1]) {
+           case ENCRYPT_START:
+               fprintf(NetTrace, " START");
+               break;
+
+           case ENCRYPT_END:
+               fprintf(NetTrace, " END");
+               break;
+
+           case ENCRYPT_REQSTART:
+               fprintf(NetTrace, " REQUEST-START");
+               break;
+
+           case ENCRYPT_REQEND:
+               fprintf(NetTrace, " REQUEST-END");
                break;
 
                break;
 
+           case ENCRYPT_IS:
+           case ENCRYPT_REPLY:
+               fprintf(NetTrace, " %s ", (pointer[1] == ENCRYPT_IS) ?
+                                                       "IS" : "REPLY");
+               if (length < 3) {
+                   fprintf(NetTrace, " (partial suboption??\?)");
+                   break;
+               }
+               if (ENCTYPE_NAME_OK(pointer[2]))
+                   fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[2]));
+               else
+                   fprintf(NetTrace, " %d (unknown)", pointer[2]);
+
+               encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf));
+               fprintf(NetTrace, "%s", buf);
+               break;
+
+           case ENCRYPT_SUPPORT:
+               i = 2;
+               fprintf(NetTrace, " SUPPORT ");
+               while (i < length) {
+                   if (ENCTYPE_NAME_OK(pointer[i]))
+                       fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[i]));
+                   else
+                       fprintf(NetTrace, "%d ", pointer[i]);
+                   i++;
+               }
+               break;
+
+           case ENCRYPT_ENC_KEYID:
+               fprintf(NetTrace, " ENC_KEYID ");
+               goto encommon;
+
+           case ENCRYPT_DEC_KEYID:
+               fprintf(NetTrace, " DEC_KEYID ");
+               goto encommon;
+
            default:
            default:
-               fprintf(NetTrace, " - unknown qualifier %d (0x%x).\r\n",
-                       pointer[1], pointer[1]);
+               fprintf(NetTrace, " %d (unknown)", pointer[1]);
+           encommon:
+               for (i = 2; i < length; i++)
+                   fprintf(NetTrace, " %d", pointer[i]);
+               break;
            }
            break;
            }
            break;
-#endif /* KERBEROS */
+#endif /* ENCRYPTION */
 
        case TELOPT_LINEMODE:
            fprintf(NetTrace, "LINEMODE ");
            if (length < 2) {
 
        case TELOPT_LINEMODE:
            fprintf(NetTrace, "LINEMODE ");
            if (length < 2) {
-               fprintf(NetTrace, " (empty suboption???)");
+               fprintf(NetTrace, " (empty suboption??\?)");
                break;
            }
            switch (pointer[1]) {
                break;
            }
            switch (pointer[1]) {
@@ -455,7 +577,7 @@ int length;                 /* length of suboption data */
                fprintf(NetTrace, "DONT ");
            common:
                if (length < 3) {
                fprintf(NetTrace, "DONT ");
            common:
                if (length < 3) {
-                   fprintf(NetTrace, "(no option???)");
+                   fprintf(NetTrace, "(no option??\?)");
                    break;
                }
                switch (pointer[2]) {
                    break;
                }
                switch (pointer[2]) {
@@ -471,12 +593,12 @@ int       length;                 /* length of suboption data */
                    break;
                }
                break;
                    break;
                }
                break;
-               
+
            case LM_SLC:
                fprintf(NetTrace, "SLC");
                for (i = 2; i < length - 2; i += 3) {
            case LM_SLC:
                fprintf(NetTrace, "SLC");
                for (i = 2; i < length - 2; i += 3) {
-                   if (pointer[i+SLC_FUNC] <= NSLC)
-                       fprintf(NetTrace, " %s", slcnames[pointer[i+SLC_FUNC]]);
+                   if (SLC_NAME_OK(pointer[i+SLC_FUNC]))
+                       fprintf(NetTrace, " %s", SLC_NAME(pointer[i+SLC_FUNC]));
                    else
                        fprintf(NetTrace, " %d", pointer[i+SLC_FUNC]);
                    switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) {
                    else
                        fprintf(NetTrace, " %d", pointer[i+SLC_FUNC]);
                    switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) {
@@ -497,6 +619,9 @@ int length;                 /* length of suboption data */
                                                SLC_FLUSHOUT| SLC_LEVELBITS))
                        fprintf(NetTrace, "(0x%x)", pointer[i+SLC_FLAGS]);
                    fprintf(NetTrace, " %d;", pointer[i+SLC_VALUE]);
                                                SLC_FLUSHOUT| SLC_LEVELBITS))
                        fprintf(NetTrace, "(0x%x)", pointer[i+SLC_FLAGS]);
                    fprintf(NetTrace, " %d;", pointer[i+SLC_VALUE]);
+                   if ((pointer[i+SLC_VALUE] == IAC) &&
+                       (pointer[i+SLC_VALUE+1] == IAC))
+                               i++;
                }
                for (; i < length; i++)
                    fprintf(NetTrace, " ?%d?", pointer[i]);
                }
                for (; i < length; i++)
                    fprintf(NetTrace, " ?%d?", pointer[i]);
@@ -505,18 +630,20 @@ int       length;                 /* length of suboption data */
            case LM_MODE:
                fprintf(NetTrace, "MODE ");
                if (length < 3) {
            case LM_MODE:
                fprintf(NetTrace, "MODE ");
                if (length < 3) {
-                   fprintf(NetTrace, "(no mode???)");
+                   fprintf(NetTrace, "(no mode??\?)");
                    break;
                }
                {
                    break;
                }
                {
-                   char tbuf[32];
-                   sprintf(tbuf, "%s%s%s",
+                   char tbuf[64];
+                   sprintf(tbuf, "%s%s%s%s%s",
                        pointer[2]&MODE_EDIT ? "|EDIT" : "",
                        pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "",
                        pointer[2]&MODE_EDIT ? "|EDIT" : "",
                        pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "",
+                       pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "",
+                       pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "",
                        pointer[2]&MODE_ACK ? "|ACK" : "");
                    fprintf(NetTrace, "%s", tbuf[1] ? &tbuf[1] : "0");
                }
                        pointer[2]&MODE_ACK ? "|ACK" : "");
                    fprintf(NetTrace, "%s", tbuf[1] ? &tbuf[1] : "0");
                }
-               if (pointer[2]&~(MODE_EDIT|MODE_TRAPSIG|MODE_ACK))
+               if (pointer[2]&~(MODE_MASK))
                    fprintf(NetTrace, " (0x%x)", pointer[2]);
                for (i = 3; i < length; i++)
                    fprintf(NetTrace, " ?0x%x?", pointer[i]);
                    fprintf(NetTrace, " (0x%x)", pointer[2]);
                for (i = 3; i < length; i++)
                    fprintf(NetTrace, " ?0x%x?", pointer[i]);
@@ -539,11 +666,13 @@ int       length;                 /* length of suboption data */
                if (pointer[1] == TELQUAL_SEND)
                    fprintf(NetTrace, " SEND");
                else
                if (pointer[1] == TELQUAL_SEND)
                    fprintf(NetTrace, " SEND");
                else
-                   fprintf(NetTrace, " %d (unknown)");
+                   fprintf(NetTrace, " %d (unknown)", pointer[1]);
                for (i = 2; i < length; i++)
                    fprintf(NetTrace, " ?%d?", pointer[i]);
                break;
            case TELQUAL_IS:
                for (i = 2; i < length; i++)
                    fprintf(NetTrace, " ?%d?", pointer[i]);
                break;
            case TELQUAL_IS:
+               if (--want_status_response < 0)
+                   want_status_response = 0;
                if (NetTrace == stdout)
                    fprintf(NetTrace, " IS\r\n");
                else
                if (NetTrace == stdout)
                    fprintf(NetTrace, " IS\r\n");
                else
@@ -557,7 +686,7 @@ int length;                 /* length of suboption data */
                    case WONT:  cp = "WONT"; goto common2;
                    common2:
                        i++;
                    case WONT:  cp = "WONT"; goto common2;
                    common2:
                        i++;
-                       if (TELOPT_OK(pointer[i]))
+                       if (TELOPT_OK((int)pointer[i]))
                            fprintf(NetTrace, " %s %s", cp, TELOPT(pointer[i]));
                        else
                            fprintf(NetTrace, " %s %d", cp, pointer[i]);
                            fprintf(NetTrace, " %s %s", cp, TELOPT(pointer[i]));
                        else
                            fprintf(NetTrace, " %s %d", cp, pointer[i]);
@@ -596,7 +725,7 @@ int length;                 /* length of suboption data */
                            fprintf(NetTrace, "\n");
 
                        break;
                            fprintf(NetTrace, "\n");
 
                        break;
-                               
+
                    default:
                        fprintf(NetTrace, " %d", pointer[i]);
                        break;
                    default:
                        fprintf(NetTrace, " %d", pointer[i]);
                        break;
@@ -607,9 +736,117 @@ int       length;                 /* length of suboption data */
            break;
          }
 
            break;
          }
 
+       case TELOPT_XDISPLOC:
+           fprintf(NetTrace, "X-DISPLAY-LOCATION ");
+           switch (pointer[1]) {
+           case TELQUAL_IS:
+               fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2);
+               break;
+           case TELQUAL_SEND:
+               fprintf(NetTrace, "SEND");
+               break;
+           default:
+               fprintf(NetTrace, "- unknown qualifier %d (0x%x).",
+                               pointer[1], pointer[1]);
+           }
+           break;
+
+       case TELOPT_NEW_ENVIRON:
+           fprintf(NetTrace, "NEW-ENVIRON ");
+#ifdef OLD_ENVIRON
+           goto env_common1;
+       case TELOPT_OLD_ENVIRON:
+           fprintf(NetTrace, "OLD-ENVIRON");
+       env_common1:
+#endif
+           switch (pointer[1]) {
+           case TELQUAL_IS:
+               fprintf(NetTrace, "IS ");
+               goto env_common;
+           case TELQUAL_SEND:
+               fprintf(NetTrace, "SEND ");
+               goto env_common;
+           case TELQUAL_INFO:
+               fprintf(NetTrace, "INFO ");
+           env_common:
+               {
+                   register int noquote = 2;
+#if defined(ENV_HACK) && defined(OLD_ENVIRON)
+                   extern int old_env_var, old_env_value;
+#endif
+                   for (i = 2; i < length; i++ ) {
+                       switch (pointer[i]) {
+                       case NEW_ENV_VALUE:
+#ifdef OLD_ENVIRON
+                    /* case NEW_ENV_OVAR: */
+                           if (pointer[0] == TELOPT_OLD_ENVIRON) {
+# ifdef        ENV_HACK
+                               if (old_env_var == OLD_ENV_VALUE)
+                                   fprintf(NetTrace, "\" (VALUE) " + noquote);
+                               else
+# endif
+                                   fprintf(NetTrace, "\" VAR " + noquote);
+                           } else
+#endif /* OLD_ENVIRON */
+                               fprintf(NetTrace, "\" VALUE " + noquote);
+                           noquote = 2;
+                           break;
+
+                       case NEW_ENV_VAR:
+#ifdef OLD_ENVIRON
+                    /* case OLD_ENV_VALUE: */
+                           if (pointer[0] == TELOPT_OLD_ENVIRON) {
+# ifdef        ENV_HACK
+                               if (old_env_value == OLD_ENV_VAR)
+                                   fprintf(NetTrace, "\" (VAR) " + noquote);
+                               else
+# endif
+                                   fprintf(NetTrace, "\" VALUE " + noquote);
+                           } else
+#endif /* OLD_ENVIRON */
+                               fprintf(NetTrace, "\" VAR " + noquote);
+                           noquote = 2;
+                           break;
+
+                       case ENV_ESC:
+                           fprintf(NetTrace, "\" ESC " + noquote);
+                           noquote = 2;
+                           break;
+
+                       case ENV_USERVAR:
+                           fprintf(NetTrace, "\" USERVAR " + noquote);
+                           noquote = 2;
+                           break;
+
+                       default:
+                       def_case:
+                           if (isprint(pointer[i]) && pointer[i] != '"') {
+                               if (noquote) {
+                                   putc('"', NetTrace);
+                                   noquote = 0;
+                               }
+                               putc(pointer[i], NetTrace);
+                           } else {
+                               fprintf(NetTrace, "\" %03o " + noquote,
+                                                       pointer[i]);
+                               noquote = 2;
+                           }
+                           break;
+                       }
+                   }
+                   if (!noquote)
+                       putc('"', NetTrace);
+                   break;
+               }
+           }
+           break;
+
        default:
        default:
-           fprintf(NetTrace, "Unknown option ");
-           for (i = 0; i < length; i++)
+           if (TELOPT_OK(pointer[0]))
+               fprintf(NetTrace, "%s (unknown)", TELOPT(pointer[0]));
+           else
+               fprintf(NetTrace, "%d (unknown)", pointer[0]);
+           for (i = 1; i < length; i++)
                fprintf(NetTrace, " %d", pointer[i]);
            break;
        }
                fprintf(NetTrace, " %d", pointer[i]);
            break;
        }
@@ -619,6 +856,8 @@ int length;                 /* length of suboption data */
            else
                fprintf(NetTrace, "\n");
        }
            else
                fprintf(NetTrace, "\n");
        }
+       if (NetTrace == stdout)
+           fflush(NetTrace);
     }
 }
 
     }
 }
 
@@ -627,7 +866,7 @@ int length;                 /* length of suboption data */
  *                     way to the kernel (thus the select).
  */
 
  *                     way to the kernel (thus the select).
  */
 
-void
+    void
 EmptyTerminal()
 {
 #if    defined(unix)
 EmptyTerminal()
 {
 #if    defined(unix)
@@ -644,7 +883,7 @@ EmptyTerminal()
 #endif /* defined(unix) */
     } else {
        while (TTYBYTES()) {
 #endif /* defined(unix) */
     } else {
        while (TTYBYTES()) {
-           ttyflush(0);
+           (void) ttyflush(0);
 #if    defined(unix)
            FD_SET(tout, &o);
            (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
 #if    defined(unix)
            FD_SET(tout, &o);
            (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
@@ -654,7 +893,7 @@ EmptyTerminal()
     }
 }
 
     }
 }
 
-void
+    void
 SetForExit()
 {
     setconnmode(0);
 SetForExit()
 {
     setconnmode(0);
@@ -664,7 +903,7 @@ SetForExit()
     }
 #else  /* defined(TN3270) */
     do {
     }
 #else  /* defined(TN3270) */
     do {
-       telrcv();                       /* Process any incoming data */
+       (void)telrcv();                 /* Process any incoming data */
        EmptyTerminal();
     } while (ring_full_count(&netiring));      /* While there is any */
 #endif /* defined(TN3270) */
        EmptyTerminal();
     } while (ring_full_count(&netiring));      /* While there is any */
 #endif /* defined(TN3270) */
@@ -681,18 +920,18 @@ SetForExit()
     setcommandmode();
 }
 
     setcommandmode();
 }
 
-void
+    void
 Exit(returnCode)
 Exit(returnCode)
-int returnCode;
+    int returnCode;
 {
     SetForExit();
     exit(returnCode);
 }
 
 {
     SetForExit();
     exit(returnCode);
 }
 
-void
+    void
 ExitString(string, returnCode)
 ExitString(string, returnCode)
-char *string;
-int returnCode;
+    char *string;
+    int returnCode;
 {
     SetForExit();
     fwrite(string, 1, strlen(string), stderr);
 {
     SetForExit();
     fwrite(string, 1, strlen(string), stderr);