home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / inetutils-1.2-src.tgz / tar.out / fsf / inetutils / telnet / utilities.c < prev   
C/C++ Source or Header  |  1996-09-28  |  23KB  |  944 lines

  1. /*
  2.  * Copyright (c) 1988, 1993
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. static char sccsid[] = "@(#)utilities.c    8.3 (Berkeley) 5/30/95";
  36. #endif /* not lint */
  37.  
  38. #ifdef HAVE_CONFIG_H
  39. #include <config.h>
  40. #endif
  41.  
  42. #define    TELOPTS
  43. #define    TELCMDS
  44. #define    SLC_NAMES
  45. #include <arpa/telnet.h>
  46. #include <sys/types.h>
  47. #include <sys/time.h>
  48.  
  49. #include <ctype.h>
  50.  
  51. #include "general.h"
  52.  
  53. #include "fdset.h"
  54.  
  55. #include "ring.h"
  56.  
  57. #include "defines.h"
  58.  
  59. #include "externs.h"
  60.  
  61. FILE    *NetTrace = 0;        /* Not in bss, since needs to stay */
  62. int    prettydump;
  63.  
  64. /*
  65.  * upcase()
  66.  *
  67.  *    Upcase (in place) the argument.
  68.  */
  69.  
  70.     void
  71. upcase(argument)
  72.     register char *argument;
  73. {
  74.     register int c;
  75.  
  76.     while ((c = *argument) != 0) {
  77.     if (islower(c)) {
  78.         *argument = toupper(c);
  79.     }
  80.     argument++;
  81.     }
  82. }
  83.  
  84. /*
  85.  * SetSockOpt()
  86.  *
  87.  * Compensate for differences in 4.2 and 4.3 systems.
  88.  */
  89.  
  90.     int
  91. SetSockOpt(fd, level, option, yesno)
  92.     int fd, level, option, yesno;
  93. {
  94. #ifndef    NOT43
  95.     return setsockopt(fd, level, option,
  96.                 (char *)&yesno, sizeof yesno);
  97. #else    /* NOT43 */
  98.     if (yesno == 0) {        /* Can't do that in 4.2! */
  99.     fprintf(stderr, "Error: attempt to turn off an option 0x%x.\n",
  100.                 option);
  101.     return -1;
  102.     }
  103.     return setsockopt(fd, level, option, 0, 0);
  104. #endif    /* NOT43 */
  105. }
  106.  
  107. /*
  108.  * The following are routines used to print out debugging information.
  109.  */
  110.  
  111. unsigned char NetTraceFile[256] = "(standard output)";
  112.  
  113.     void
  114. SetNetTrace(file)
  115.     register char *file;
  116. {
  117.     if (NetTrace && NetTrace != stdout)
  118.     fclose(NetTrace);
  119.     if (file  && (strcmp(file, "-") != 0)) {
  120.     NetTrace = fopen(file, "w");
  121.     if (NetTrace) {
  122.         strcpy((char *)NetTraceFile, file);
  123.         return;
  124.     }
  125.     fprintf(stderr, "Cannot open %s.\n", file);
  126.     }
  127.     NetTrace = stdout;
  128.     strcpy((char *)NetTraceFile, "(standard output)");
  129. }
  130.  
  131.     void
  132. Dump(direction, buffer, length)
  133.     char direction;
  134.     unsigned char *buffer;
  135.     int length;
  136. {
  137. #   define BYTES_PER_LINE    32
  138. #   define min(x,y)    ((x<y)? x:y)
  139.     unsigned char *pThis;
  140.     int offset;
  141.     extern pettydump;
  142.  
  143.     offset = 0;
  144.  
  145.     while (length) {
  146.     /* print one line */
  147.     fprintf(NetTrace, "%c 0x%x\t", direction, offset);
  148.     pThis = buffer;
  149.     if (prettydump) {
  150.         buffer = buffer + min(length, BYTES_PER_LINE/2);
  151.         while (pThis < buffer) {
  152.         fprintf(NetTrace, "%c%.2x",
  153.             (((*pThis)&0xff) == 0xff) ? '*' : ' ',
  154.             (*pThis)&0xff);
  155.         pThis++;
  156.         }
  157.         length -= BYTES_PER_LINE/2;
  158.         offset += BYTES_PER_LINE/2;
  159.     } else {
  160.         buffer = buffer + min(length, BYTES_PER_LINE);
  161.         while (pThis < buffer) {
  162.         fprintf(NetTrace, "%.2x", (*pThis)&0xff);
  163.         pThis++;
  164.         }
  165.         length -= BYTES_PER_LINE;
  166.         offset += BYTES_PER_LINE;
  167.     }
  168.     if (NetTrace == stdout) {
  169.         fprintf(NetTrace, "\r\n");
  170.     } else {
  171.         fprintf(NetTrace, "\n");
  172.     }
  173.     if (length < 0) {
  174.         fflush(NetTrace);
  175.         return;
  176.     }
  177.     /* find next unique line */
  178.     }
  179.     fflush(NetTrace);
  180. }
  181.  
  182.  
  183.     void
  184. printoption(direction, cmd, option)
  185.     char *direction;
  186.     int cmd, option;
  187. {
  188.     if (!showoptions)
  189.         return;
  190.     if (cmd == IAC) {
  191.         if (TELCMD_OK(option))
  192.             fprintf(NetTrace, "%s IAC %s", direction, TELCMD(option));
  193.         else
  194.             fprintf(NetTrace, "%s IAC %d", direction, option);
  195.     } else {
  196.         register char *fmt;
  197.         fmt = (cmd == WILL) ? "WILL" : (cmd == WONT) ? "WONT" :
  198.             (cmd == DO) ? "DO" : (cmd == DONT) ? "DONT" : 0;
  199.         if (fmt) {
  200.             fprintf(NetTrace, "%s %s ", direction, fmt);
  201.             if (TELOPT_OK(option))
  202.             fprintf(NetTrace, "%s", TELOPT(option));
  203.             else if (option == TELOPT_EXOPL)
  204.             fprintf(NetTrace, "EXOPL");
  205.             else
  206.             fprintf(NetTrace, "%d", option);
  207.         } else
  208.             fprintf(NetTrace, "%s %d %d", direction, cmd, option);
  209.     }
  210.     if (NetTrace == stdout) {
  211.         fprintf(NetTrace, "\r\n");
  212.         fflush(NetTrace);
  213.     } else {
  214.         fprintf(NetTrace, "\n");
  215.     }
  216.     return;
  217. }
  218.  
  219.     void
  220. optionstatus()
  221. {
  222.     register int i;
  223.     extern char will_wont_resp[], do_dont_resp[];
  224.  
  225.     for (i = 0; i < 256; i++) {
  226.     if (do_dont_resp[i]) {
  227.         if (TELOPT_OK(i))
  228.         printf("resp DO_DONT %s: %d\n", TELOPT(i), do_dont_resp[i]);
  229.         else if (TELCMD_OK(i))
  230.         printf("resp DO_DONT %s: %d\n", TELCMD(i), do_dont_resp[i]);
  231.         else
  232.         printf("resp DO_DONT %d: %d\n", i,
  233.                 do_dont_resp[i]);
  234.         if (my_want_state_is_do(i)) {
  235.         if (TELOPT_OK(i))
  236.             printf("want DO   %s\n", TELOPT(i));
  237.         else if (TELCMD_OK(i))
  238.             printf("want DO   %s\n", TELCMD(i));
  239.         else
  240.             printf("want DO   %d\n", i);
  241.         } else {
  242.         if (TELOPT_OK(i))
  243.             printf("want DONT %s\n", TELOPT(i));
  244.         else if (TELCMD_OK(i))
  245.             printf("want DONT %s\n", TELCMD(i));
  246.         else
  247.             printf("want DONT %d\n", i);
  248.         }
  249.     } else {
  250.         if (my_state_is_do(i)) {
  251.         if (TELOPT_OK(i))
  252.             printf("     DO   %s\n", TELOPT(i));
  253.         else if (TELCMD_OK(i))
  254.             printf("     DO   %s\n", TELCMD(i));
  255.         else
  256.             printf("     DO   %d\n", i);
  257.         }
  258.     }
  259.     if (will_wont_resp[i]) {
  260.         if (TELOPT_OK(i))
  261.         printf("resp WILL_WONT %s: %d\n", TELOPT(i), will_wont_resp[i]);
  262.         else if (TELCMD_OK(i))
  263.         printf("resp WILL_WONT %s: %d\n", TELCMD(i), will_wont_resp[i]);
  264.         else
  265.         printf("resp WILL_WONT %d: %d\n",
  266.                 i, will_wont_resp[i]);
  267.         if (my_want_state_is_will(i)) {
  268.         if (TELOPT_OK(i))
  269.             printf("want WILL %s\n", TELOPT(i));
  270.         else if (TELCMD_OK(i))
  271.             printf("want WILL %s\n", TELCMD(i));
  272.         else
  273.             printf("want WILL %d\n", i);
  274.         } else {
  275.         if (TELOPT_OK(i))
  276.             printf("want WONT %s\n", TELOPT(i));
  277.         else if (TELCMD_OK(i))
  278.             printf("want WONT %s\n", TELCMD(i));
  279.         else
  280.             printf("want WONT %d\n", i);
  281.         }
  282.     } else {
  283.         if (my_state_is_will(i)) {
  284.         if (TELOPT_OK(i))
  285.             printf("     WILL %s\n", TELOPT(i));
  286.         else if (TELCMD_OK(i))
  287.             printf("     WILL %s\n", TELCMD(i));
  288.         else
  289.             printf("     WILL %d\n", i);
  290.         }
  291.     }
  292.     }
  293.  
  294. }
  295.  
  296.     void
  297. printsub(direction, pointer, length)
  298.     char direction;    /* '<' or '>' */
  299.     unsigned char *pointer;    /* where suboption data sits */
  300.     int          length;    /* length of suboption data */
  301. {
  302.     register int i;
  303.     char buf[512];
  304.     extern int want_status_response;
  305.  
  306.     if (showoptions || direction == 0 ||
  307.     (want_status_response && (pointer[0] == TELOPT_STATUS))) {
  308.     if (direction) {
  309.         fprintf(NetTrace, "%s IAC SB ",
  310.                 (direction == '<')? "RCVD":"SENT");
  311.         if (length >= 3) {
  312.         register int j;
  313.  
  314.         i = pointer[length-2];
  315.         j = pointer[length-1];
  316.  
  317.         if (i != IAC || j != SE) {
  318.             fprintf(NetTrace, "(terminated by ");
  319.             if (TELOPT_OK(i))
  320.             fprintf(NetTrace, "%s ", TELOPT(i));
  321.             else if (TELCMD_OK(i))
  322.             fprintf(NetTrace, "%s ", TELCMD(i));
  323.             else
  324.             fprintf(NetTrace, "%d ", i);
  325.             if (TELOPT_OK(j))
  326.             fprintf(NetTrace, "%s", TELOPT(j));
  327.             else if (TELCMD_OK(j))
  328.             fprintf(NetTrace, "%s", TELCMD(j));
  329.             else
  330.             fprintf(NetTrace, "%d", j);
  331.             fprintf(NetTrace, ", not IAC SE!) ");
  332.         }
  333.         }
  334.         length -= 2;
  335.     }
  336.     if (length < 1) {
  337.         fprintf(NetTrace, "(Empty suboption??\?)");
  338.         if (NetTrace == stdout)
  339.         fflush(NetTrace);
  340.         return;
  341.     }
  342.     switch (pointer[0]) {
  343.     case TELOPT_TTYPE:
  344.         fprintf(NetTrace, "TERMINAL-TYPE ");
  345.         switch (pointer[1]) {
  346.         case TELQUAL_IS:
  347.         fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2);
  348.         break;
  349.         case TELQUAL_SEND:
  350.         fprintf(NetTrace, "SEND");
  351.         break;
  352.         default:
  353.         fprintf(NetTrace,
  354.                 "- unknown qualifier %d (0x%x).",
  355.                 pointer[1], pointer[1]);
  356.         }
  357.         break;
  358.     case TELOPT_TSPEED:
  359.         fprintf(NetTrace, "TERMINAL-SPEED");
  360.         if (length < 2) {
  361.         fprintf(NetTrace, " (empty suboption??\?)");
  362.         break;
  363.         }
  364.         switch (pointer[1]) {
  365.         case TELQUAL_IS:
  366.         fprintf(NetTrace, " IS ");
  367.         fprintf(NetTrace, "%.*s", length-2, (char *)pointer+2);
  368.         break;
  369.         default:
  370.         if (pointer[1] == 1)
  371.             fprintf(NetTrace, " SEND");
  372.         else
  373.             fprintf(NetTrace, " %d (unknown)", pointer[1]);
  374.         for (i = 2; i < length; i++)
  375.             fprintf(NetTrace, " ?%d?", pointer[i]);
  376.         break;
  377.         }
  378.         break;
  379.  
  380.     case TELOPT_LFLOW:
  381.         fprintf(NetTrace, "TOGGLE-FLOW-CONTROL");
  382.         if (length < 2) {
  383.         fprintf(NetTrace, " (empty suboption??\?)");
  384.         break;
  385.         }
  386.         switch (pointer[1]) {
  387.         case LFLOW_OFF:
  388.         fprintf(NetTrace, " OFF"); break;
  389.         case LFLOW_ON:
  390.         fprintf(NetTrace, " ON"); break;
  391.         case LFLOW_RESTART_ANY:
  392.         fprintf(NetTrace, " RESTART-ANY"); break;
  393.         case LFLOW_RESTART_XON:
  394.         fprintf(NetTrace, " RESTART-XON"); break;
  395.         default:
  396.         fprintf(NetTrace, " %d (unknown)", pointer[1]);
  397.         }
  398.         for (i = 2; i < length; i++)
  399.         fprintf(NetTrace, " ?%d?", pointer[i]);
  400.         break;
  401.  
  402.     case TELOPT_NAWS:
  403.         fprintf(NetTrace, "NAWS");
  404.         if (length < 2) {
  405.         fprintf(NetTrace, " (empty suboption??\?)");
  406.         break;
  407.         }
  408.         if (length == 2) {
  409.         fprintf(NetTrace, " ?%d?", pointer[1]);
  410.         break;
  411.         }
  412.         fprintf(NetTrace, " %d %d (%d)",
  413.         pointer[1], pointer[2],
  414.         (int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2])));
  415.         if (length == 4) {
  416.         fprintf(NetTrace, " ?%d?", pointer[3]);
  417.         break;
  418.         }
  419.         fprintf(NetTrace, " %d %d (%d)",
  420.         pointer[3], pointer[4],
  421.         (int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4])));
  422.         for (i = 5; i < length; i++)
  423.         fprintf(NetTrace, " ?%d?", pointer[i]);
  424.         break;
  425.  
  426. #if    defined(AUTHENTICATION)
  427.     case TELOPT_AUTHENTICATION:
  428.         fprintf(NetTrace, "AUTHENTICATION");
  429.         if (length < 2) {
  430.         fprintf(NetTrace, " (empty suboption??\?)");
  431.         break;
  432.         }
  433.         switch (pointer[1]) {
  434.         case TELQUAL_REPLY:
  435.         case TELQUAL_IS:
  436.         fprintf(NetTrace, " %s ", (pointer[1] == TELQUAL_IS) ?
  437.                             "IS" : "REPLY");
  438.         if (AUTHTYPE_NAME_OK(pointer[2]))
  439.             fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[2]));
  440.         else
  441.             fprintf(NetTrace, "%d ", pointer[2]);
  442.         if (length < 3) {
  443.             fprintf(NetTrace, "(partial suboption??\?)");
  444.             break;
  445.         }
  446.         fprintf(NetTrace, "%s|%s",
  447.             ((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
  448.             "CLIENT" : "SERVER",
  449.             ((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
  450.             "MUTUAL" : "ONE-WAY");
  451.  
  452.         auth_printsub(&pointer[1], length - 1, buf, sizeof(buf));
  453.         fprintf(NetTrace, "%s", buf);
  454.         break;
  455.  
  456.         case TELQUAL_SEND:
  457.         i = 2;
  458.         fprintf(NetTrace, " SEND ");
  459.         while (i < length) {
  460.             if (AUTHTYPE_NAME_OK(pointer[i]))
  461.             fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[i]));
  462.             else
  463.             fprintf(NetTrace, "%d ", pointer[i]);
  464.             if (++i >= length) {
  465.             fprintf(NetTrace, "(partial suboption??\?)");
  466.             break;
  467.             }
  468.             fprintf(NetTrace, "%s|%s ",
  469.             ((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
  470.                             "CLIENT" : "SERVER",
  471.             ((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
  472.                             "MUTUAL" : "ONE-WAY");
  473.             ++i;
  474.         }
  475.         break;
  476.  
  477.         case TELQUAL_NAME:
  478.         i = 2;
  479.         fprintf(NetTrace, " NAME \"");
  480.         while (i < length)
  481.             putc(pointer[i++], NetTrace);
  482.         putc('"', NetTrace);
  483.         break;
  484.  
  485.         default:
  486.             for (i = 2; i < length; i++)
  487.             fprintf(NetTrace, " ?%d?", pointer[i]);
  488.             break;
  489.         }
  490.         break;
  491. #endif
  492.  
  493. #ifdef    ENCRYPTION
  494.     case TELOPT_ENCRYPT:
  495.         fprintf(NetTrace, "ENCRYPT");
  496.         if (length < 2) {
  497.         fprintf(NetTrace, " (empty suboption??\?)");
  498.         break;
  499.         }
  500.         switch (pointer[1]) {
  501.         case ENCRYPT_START:
  502.         fprintf(NetTrace, " START");
  503.         break;
  504.  
  505.         case ENCRYPT_END:
  506.         fprintf(NetTrace, " END");
  507.         break;
  508.  
  509.         case ENCRYPT_REQSTART:
  510.         fprintf(NetTrace, " REQUEST-START");
  511.         break;
  512.  
  513.         case ENCRYPT_REQEND:
  514.         fprintf(NetTrace, " REQUEST-END");
  515.         break;
  516.  
  517.         case ENCRYPT_IS:
  518.         case ENCRYPT_REPLY:
  519.         fprintf(NetTrace, " %s ", (pointer[1] == ENCRYPT_IS) ?
  520.                             "IS" : "REPLY");
  521.         if (length < 3) {
  522.             fprintf(NetTrace, " (partial suboption??\?)");
  523.             break;
  524.         }
  525.         if (ENCTYPE_NAME_OK(pointer[2]))
  526.             fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[2]));
  527.         else
  528.             fprintf(NetTrace, " %d (unknown)", pointer[2]);
  529.  
  530.         encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf));
  531.         fprintf(NetTrace, "%s", buf);
  532.         break;
  533.  
  534.         case ENCRYPT_SUPPORT:
  535.         i = 2;
  536.         fprintf(NetTrace, " SUPPORT ");
  537.         while (i < length) {
  538.             if (ENCTYPE_NAME_OK(pointer[i]))
  539.             fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[i]));
  540.             else
  541.             fprintf(NetTrace, "%d ", pointer[i]);
  542.             i++;
  543.         }
  544.         break;
  545.  
  546.         case ENCRYPT_ENC_KEYID:
  547.         fprintf(NetTrace, " ENC_KEYID ");
  548.         goto encommon;
  549.  
  550.         case ENCRYPT_DEC_KEYID:
  551.         fprintf(NetTrace, " DEC_KEYID ");
  552.         goto encommon;
  553.  
  554.         default:
  555.         fprintf(NetTrace, " %d (unknown)", pointer[1]);
  556.         encommon:
  557.         for (i = 2; i < length; i++)
  558.             fprintf(NetTrace, " %d", pointer[i]);
  559.         break;
  560.         }
  561.         break;
  562. #endif    /* ENCRYPTION */
  563.  
  564.     case TELOPT_LINEMODE:
  565.         fprintf(NetTrace, "LINEMODE ");
  566.         if (length < 2) {
  567.         fprintf(NetTrace, " (empty suboption??\?)");
  568.         break;
  569.         }
  570.         switch (pointer[1]) {
  571.         case WILL:
  572.         fprintf(NetTrace, "WILL ");
  573.         goto common;
  574.         case WONT:
  575.         fprintf(NetTrace, "WONT ");
  576.         goto common;
  577.         case DO:
  578.         fprintf(NetTrace, "DO ");
  579.         goto common;
  580.         case DONT:
  581.         fprintf(NetTrace, "DONT ");
  582.         common:
  583.         if (length < 3) {
  584.             fprintf(NetTrace, "(no option??\?)");
  585.             break;
  586.         }
  587.         switch (pointer[2]) {
  588.         case LM_FORWARDMASK:
  589.             fprintf(NetTrace, "Forward Mask");
  590.             for (i = 3; i < length; i++)
  591.             fprintf(NetTrace, " %x", pointer[i]);
  592.             break;
  593.         default:
  594.             fprintf(NetTrace, "%d (unknown)", pointer[2]);
  595.             for (i = 3; i < length; i++)
  596.             fprintf(NetTrace, " %d", pointer[i]);
  597.             break;
  598.         }
  599.         break;
  600.         
  601.         case LM_SLC:
  602.         fprintf(NetTrace, "SLC");
  603.         for (i = 2; i < length - 2; i += 3) {
  604.             if (SLC_NAME_OK(pointer[i+SLC_FUNC]))
  605.             fprintf(NetTrace, " %s", SLC_NAME(pointer[i+SLC_FUNC]));
  606.             else
  607.             fprintf(NetTrace, " %d", pointer[i+SLC_FUNC]);
  608.             switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) {
  609.             case SLC_NOSUPPORT:
  610.             fprintf(NetTrace, " NOSUPPORT"); break;
  611.             case SLC_CANTCHANGE:
  612.             fprintf(NetTrace, " CANTCHANGE"); break;
  613.             case SLC_VARIABLE:
  614.             fprintf(NetTrace, " VARIABLE"); break;
  615.             case SLC_DEFAULT:
  616.             fprintf(NetTrace, " DEFAULT"); break;
  617.             }
  618.             fprintf(NetTrace, "%s%s%s",
  619.             pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "",
  620.             pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "",
  621.             pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : "");
  622.             if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN|
  623.                         SLC_FLUSHOUT| SLC_LEVELBITS))
  624.             fprintf(NetTrace, "(0x%x)", pointer[i+SLC_FLAGS]);
  625.             fprintf(NetTrace, " %d;", pointer[i+SLC_VALUE]);
  626.             if ((pointer[i+SLC_VALUE] == IAC) &&
  627.             (pointer[i+SLC_VALUE+1] == IAC))
  628.                 i++;
  629.         }
  630.         for (; i < length; i++)
  631.             fprintf(NetTrace, " ?%d?", pointer[i]);
  632.         break;
  633.  
  634.         case LM_MODE:
  635.         fprintf(NetTrace, "MODE ");
  636.         if (length < 3) {
  637.             fprintf(NetTrace, "(no mode??\?)");
  638.             break;
  639.         }
  640.         {
  641.             char tbuf[64];
  642.             sprintf(tbuf, "%s%s%s%s%s",
  643.             pointer[2]&MODE_EDIT ? "|EDIT" : "",
  644.             pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "",
  645.             pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "",
  646.             pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "",
  647.             pointer[2]&MODE_ACK ? "|ACK" : "");
  648.             fprintf(NetTrace, "%s", tbuf[1] ? &tbuf[1] : "0");
  649.         }
  650.         if (pointer[2]&~(MODE_MASK))
  651.             fprintf(NetTrace, " (0x%x)", pointer[2]);
  652.         for (i = 3; i < length; i++)
  653.             fprintf(NetTrace, " ?0x%x?", pointer[i]);
  654.         break;
  655.         default:
  656.         fprintf(NetTrace, "%d (unknown)", pointer[1]);
  657.         for (i = 2; i < length; i++)
  658.             fprintf(NetTrace, " %d", pointer[i]);
  659.         }
  660.         break;
  661.  
  662.     case TELOPT_STATUS: {
  663.         register char *cp;
  664.         register int j, k;
  665.  
  666.         fprintf(NetTrace, "STATUS");
  667.  
  668.         switch (pointer[1]) {
  669.         default:
  670.         if (pointer[1] == TELQUAL_SEND)
  671.             fprintf(NetTrace, " SEND");
  672.         else
  673.             fprintf(NetTrace, " %d (unknown)", pointer[1]);
  674.         for (i = 2; i < length; i++)
  675.             fprintf(NetTrace, " ?%d?", pointer[i]);
  676.         break;
  677.         case TELQUAL_IS:
  678.         if (--want_status_response < 0)
  679.             want_status_response = 0;
  680.         if (NetTrace == stdout)
  681.             fprintf(NetTrace, " IS\r\n");
  682.         else
  683.             fprintf(NetTrace, " IS\n");
  684.  
  685.         for (i = 2; i < length; i++) {
  686.             switch(pointer[i]) {
  687.             case DO:    cp = "DO"; goto common2;
  688.             case DONT:    cp = "DONT"; goto common2;
  689.             case WILL:    cp = "WILL"; goto common2;
  690.             case WONT:    cp = "WONT"; goto common2;
  691.             common2:
  692.             i++;
  693.             if (TELOPT_OK((int)pointer[i]))
  694.                 fprintf(NetTrace, " %s %s", cp, TELOPT(pointer[i]));
  695.             else
  696.                 fprintf(NetTrace, " %s %d", cp, pointer[i]);
  697.  
  698.             if (NetTrace == stdout)
  699.                 fprintf(NetTrace, "\r\n");
  700.             else
  701.                 fprintf(NetTrace, "\n");
  702.             break;
  703.  
  704.             case SB:
  705.             fprintf(NetTrace, " SB ");
  706.             i++;
  707.             j = k = i;
  708.             while (j < length) {
  709.                 if (pointer[j] == SE) {
  710.                 if (j+1 == length)
  711.                     break;
  712.                 if (pointer[j+1] == SE)
  713.                     j++;
  714.                 else
  715.                     break;
  716.                 }
  717.                 pointer[k++] = pointer[j++];
  718.             }
  719.             printsub(0, &pointer[i], k - i);
  720.             if (i < length) {
  721.                 fprintf(NetTrace, " SE");
  722.                 i = j;
  723.             } else
  724.                 i = j - 1;
  725.  
  726.             if (NetTrace == stdout)
  727.                 fprintf(NetTrace, "\r\n");
  728.             else
  729.                 fprintf(NetTrace, "\n");
  730.  
  731.             break;
  732.                 
  733.             default:
  734.             fprintf(NetTrace, " %d", pointer[i]);
  735.             break;
  736.             }
  737.         }
  738.         break;
  739.         }
  740.         break;
  741.       }
  742.  
  743.     case TELOPT_XDISPLOC:
  744.         fprintf(NetTrace, "X-DISPLAY-LOCATION ");
  745.         switch (pointer[1]) {
  746.         case TELQUAL_IS:
  747.         fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2);
  748.         break;
  749.         case TELQUAL_SEND:
  750.         fprintf(NetTrace, "SEND");
  751.         break;
  752.         default:
  753.         fprintf(NetTrace, "- unknown qualifier %d (0x%x).",
  754.                 pointer[1], pointer[1]);
  755.         }
  756.         break;
  757.  
  758.     case TELOPT_NEW_ENVIRON:
  759.         fprintf(NetTrace, "NEW-ENVIRON ");
  760. #ifdef    OLD_ENVIRON
  761.         goto env_common1;
  762.     case TELOPT_OLD_ENVIRON:
  763.         fprintf(NetTrace, "OLD-ENVIRON");
  764.     env_common1:
  765. #endif
  766.         switch (pointer[1]) {
  767.         case TELQUAL_IS:
  768.         fprintf(NetTrace, "IS ");
  769.         goto env_common;
  770.         case TELQUAL_SEND:
  771.         fprintf(NetTrace, "SEND ");
  772.         goto env_common;
  773.         case TELQUAL_INFO:
  774.         fprintf(NetTrace, "INFO ");
  775.         env_common:
  776.         {
  777.             register int noquote = 2;
  778. #if defined(ENV_HACK) && defined(OLD_ENVIRON)
  779.             extern int old_env_var, old_env_value;
  780. #endif
  781.             for (i = 2; i < length; i++ ) {
  782.             switch (pointer[i]) {
  783.             case NEW_ENV_VALUE:
  784. #ifdef OLD_ENVIRON
  785.              /*    case NEW_ENV_OVAR: */
  786.                 if (pointer[0] == TELOPT_OLD_ENVIRON) {
  787. # ifdef    ENV_HACK
  788.                 if (old_env_var == OLD_ENV_VALUE)
  789.                     fprintf(NetTrace, "\" (VALUE) " + noquote);
  790.                 else
  791. # endif
  792.                     fprintf(NetTrace, "\" VAR " + noquote);
  793.                 } else
  794. #endif /* OLD_ENVIRON */
  795.                 fprintf(NetTrace, "\" VALUE " + noquote);
  796.                 noquote = 2;
  797.                 break;
  798.  
  799.             case NEW_ENV_VAR:
  800. #ifdef OLD_ENVIRON
  801.              /* case OLD_ENV_VALUE: */
  802.                 if (pointer[0] == TELOPT_OLD_ENVIRON) {
  803. # ifdef    ENV_HACK
  804.                 if (old_env_value == OLD_ENV_VAR)
  805.                     fprintf(NetTrace, "\" (VAR) " + noquote);
  806.                 else
  807. # endif
  808.                     fprintf(NetTrace, "\" VALUE " + noquote);
  809.                 } else
  810. #endif /* OLD_ENVIRON */
  811.                 fprintf(NetTrace, "\" VAR " + noquote);
  812.                 noquote = 2;
  813.                 break;
  814.  
  815.             case ENV_ESC:
  816.                 fprintf(NetTrace, "\" ESC " + noquote);
  817.                 noquote = 2;
  818.                 break;
  819.  
  820.             case ENV_USERVAR:
  821.                 fprintf(NetTrace, "\" USERVAR " + noquote);
  822.                 noquote = 2;
  823.                 break;
  824.  
  825.             default:
  826.             def_case:
  827.                 if (isprint(pointer[i]) && pointer[i] != '"') {
  828.                 if (noquote) {
  829.                     putc('"', NetTrace);
  830.                     noquote = 0;
  831.                 }
  832.                 putc(pointer[i], NetTrace);
  833.                 } else {
  834.                 fprintf(NetTrace, "\" %03o " + noquote,
  835.                             pointer[i]);
  836.                 noquote = 2;
  837.                 }
  838.                 break;
  839.             }
  840.             }
  841.             if (!noquote)
  842.             putc('"', NetTrace);
  843.             break;
  844.         }
  845.         }
  846.         break;
  847.  
  848.     default:
  849.         if (TELOPT_OK(pointer[0]))
  850.         fprintf(NetTrace, "%s (unknown)", TELOPT(pointer[0]));
  851.         else
  852.         fprintf(NetTrace, "%d (unknown)", pointer[0]);
  853.         for (i = 1; i < length; i++)
  854.         fprintf(NetTrace, " %d", pointer[i]);
  855.         break;
  856.     }
  857.     if (direction) {
  858.         if (NetTrace == stdout)
  859.         fprintf(NetTrace, "\r\n");
  860.         else
  861.         fprintf(NetTrace, "\n");
  862.     }
  863.     if (NetTrace == stdout)
  864.         fflush(NetTrace);
  865.     }
  866. }
  867.  
  868. /* EmptyTerminal - called to make sure that the terminal buffer is empty.
  869.  *            Note that we consider the buffer to run all the
  870.  *            way to the kernel (thus the select).
  871.  */
  872.  
  873.     void
  874. EmptyTerminal()
  875. {
  876. #if    defined(unix)
  877.     fd_set    o;
  878.  
  879.     FD_ZERO(&o);
  880. #endif    /* defined(unix) */
  881.  
  882.     if (TTYBYTES() == 0) {
  883. #if    defined(unix)
  884.     FD_SET(tout, &o);
  885.     (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
  886.             (struct timeval *) 0);    /* wait for TTLOWAT */
  887. #endif    /* defined(unix) */
  888.     } else {
  889.     while (TTYBYTES()) {
  890.         (void) ttyflush(0);
  891. #if    defined(unix)
  892.         FD_SET(tout, &o);
  893.         (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
  894.                 (struct timeval *) 0);    /* wait for TTLOWAT */
  895. #endif    /* defined(unix) */
  896.     }
  897.     }
  898. }
  899.  
  900.     void
  901. SetForExit()
  902. {
  903.     setconnmode(0);
  904. #if    defined(TN3270)
  905.     if (In3270) {
  906.     Finish3270();
  907.     }
  908. #else    /* defined(TN3270) */
  909.     do {
  910.     (void)telrcv();            /* Process any incoming data */
  911.     EmptyTerminal();
  912.     } while (ring_full_count(&netiring));    /* While there is any */
  913. #endif    /* defined(TN3270) */
  914.     setcommandmode();
  915.     fflush(stdout);
  916.     fflush(stderr);
  917. #if    defined(TN3270)
  918.     if (In3270) {
  919.     StopScreen(1);
  920.     }
  921. #endif    /* defined(TN3270) */
  922.     setconnmode(0);
  923.     EmptyTerminal();            /* Flush the path to the tty */
  924.     setcommandmode();
  925. }
  926.  
  927.     void
  928. Exit(returnCode)
  929.     int returnCode;
  930. {
  931.     SetForExit();
  932.     exit(returnCode);
  933. }
  934.  
  935.     void
  936. ExitString(string, returnCode)
  937.     char *string;
  938.     int returnCode;
  939. {
  940.     SetForExit();
  941.     fwrite(string, 1, strlen(string), stderr);
  942.     exit(returnCode);
  943. }
  944.