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