home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Telnet 2.7b5 / source / parse / parse.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-17  |  23.4 KB  |  916 lines  |  [TEXT/CWIE]

  1. /****************************************************************
  2. *    NCSA Telnet for the Macintosh                                *
  3. *                                                                *
  4. *    National Center for Supercomputing Applications                *
  5. *    Software Development Group                                    *
  6. *    152 Computing Applications Building                            *
  7. *    605 E. Springfield Ave.                                        *
  8. *    Champaign, IL  61820                                        *
  9. *                                                                *
  10. *    Copyright (c) 1986-1994,                                    *
  11. *    Board of Trustees of the University of Illinois                *
  12. ****************************************************************/
  13.  
  14. #ifdef MPW
  15. #pragma segment Parse
  16. #endif
  17.  
  18.  
  19. #include "parse.h"                // For our #defines
  20. #include "wind.h"                /* For WindRec structure */
  21.                 /* For putln proto */
  22.  
  23. #include "network.proto.h"                /* For net functions */
  24. #include "linemode.proto.h"
  25. #include "vgtek.proto.h"
  26. #include "vsdata.h"
  27. #include "vsinterf.proto.h"
  28. #include "maclook.proto.h"
  29. #include "tekrgmac.proto.h"
  30. #include "menuseg.proto.h"
  31. #include "translate.proto.h"
  32. #include "vr.h"
  33. #include "vr.proto.h"
  34. #include "tnae.h"
  35. #include "authencrypt.h"
  36. #include "authencrypt.proto.h"
  37. #include "wdefpatch.proto.h"
  38.  
  39. //#define    OPTS_DEBUG
  40. #ifdef    OPTS_DEBUG
  41. #include "optsdebug.h"
  42. #define    opts_debug_print(x)    putln(x)    
  43. static char munger[255];
  44. #else
  45. #define    opts_debug_print(x)
  46. #endif
  47.  
  48. #include "Profiler.h"
  49.  
  50. extern short     scrn;
  51. extern WindRec    *screens;
  52.  
  53. #include "parse.proto.h"
  54.  
  55. static    char    *getcname(struct WindRec *tw);
  56. static    void    encryptStatechange(struct WindRec *tw);
  57. static    void    process_suboption(struct WindRec *tw, unsigned char *start, unsigned char *end);
  58. static    void    send_will(short port, short option);
  59. static    void    send_wont(short port, short option);
  60. static    void    telnet_do(struct WindRec *tw, short option);
  61. static    void    telnet_dont(struct WindRec *tw, short option);
  62. static    void    telnet_will(struct WindRec *tw, short option);
  63. static    void    telnet_wont(struct WindRec *tw, short option);
  64.  
  65. void    Parseunload(void) {}
  66.  
  67. void    SendStringAsIfTyped(struct WindRec *tw, char *string, short len)
  68. {
  69.     trbuf_nat_mac((unsigned char *)string, len, tw->national);
  70.  
  71.     netpush(tw->port);
  72.  
  73.     if (tw->kblen > 0) {     /* need to flush buffer */
  74.         netwrite(tw->port, tw->kbbuf, tw->kblen);
  75.         tw->kblen=0;
  76.     }
  77.  
  78.     netwrite(tw->port, string, len);
  79.  
  80.     if (tw->echo)
  81.         parse(tw, (unsigned char *)string, len);
  82. }
  83.  
  84. /*********************************************************************/
  85. /*  parse
  86. *   look at the string which has just come in from outside and
  87. *   check for special sequences that we are interested in.
  88. *
  89. *   Tries to pass through routine strings immediately, waiting for special
  90. *   characters ESC and 255 to change modes.
  91. */
  92.  
  93. void parse (struct WindRec *tw, unsigned char *st, short cnt)
  94. {
  95.     short i,temptw;
  96.     unsigned char *mark,*orig;
  97.  
  98. //    ProfilerSetStatus(true);
  99.  
  100.     orig = st;                /* remember beginning point */
  101.     mark = st + cnt;        /* set to end of input string */
  102. /*
  103. * raw mode for debugging, passes through escape sequences and other
  104. * special characters as <27> symbols
  105. */
  106.     if (tw->termstate == DUMBTYPE)
  107.         {
  108.         for (i=0; i < cnt; i++,st++)            /* put on screen raw */
  109.             if (*st == 27 || *st > 126)
  110.                 {
  111.                 sprintf((char *)tw->parsedat,"<%d>",*st);
  112.                 VSwrite(tw->vs,(char *)tw->parsedat,strlen((char *)tw->parsedat));    /* send to virtual screen */
  113.                 }
  114.             else
  115.                 VSwrite(tw->vs,(char *) st,1);        /* BYU LSC */
  116.         }
  117.     else
  118.         {
  119.  
  120. /*
  121. *  traverse string, looking for any special characters which indicate that
  122. *  we need to change modes.
  123. */
  124.     while (st < mark) 
  125.         {
  126.         switch (tw->telstate)
  127.             {
  128.             case GS:
  129.             case ESCFOUND:
  130.                 if (tw->tektype >= 0) {    /* we'll allow the TEK */
  131.                     if ((*st == 12) || (tw->telstate == GS)) {    /* esc-FF */
  132.                         if ((*st == 12) && 
  133.                             ((tw->termstate == VTEKTYPE) || (!tw->tekclear))) {
  134.                             if (tw->termstate == VTEKTYPE)
  135.                                 putln("Entering Tek mode");
  136.                             else if (tw->curgraph > -1)
  137.                                 detachGraphics(tw->curgraph);
  138.  
  139.                             if (tw->curgraph <=  -1) {        // No current TEK window
  140.                                 temptw = VGnewwin(TEK_DEVICE_WINDOW,tw->vs);
  141.  
  142.                                 if (temptw > -1) {
  143.                                     Str255    scratchPstring;
  144.                                     
  145.                                     tw->curgraph = temptw;
  146.     
  147.                                     VGgiveinfo(temptw);
  148.                                     GetWTitle(tw->wind, scratchPstring);
  149.                                     PtoCstr(scratchPstring);
  150.                                     RGattach(temptw,tw->vs,(char *)scratchPstring, tw->tektype);
  151.                                 }
  152.                                 else
  153.                                     tw->telstate = TS_NORM;  // Can't create TEK window
  154.                             }
  155.  
  156.                             if (tw->telstate != TS_NORM)
  157.                                 tw->termstate = TEKTYPE;
  158.                         }
  159.  
  160.                         if (tw->telstate == GS) {
  161.                             st++;
  162.                             VGwrite(tw->curgraph,"\035",1);
  163.                         }
  164.                         else if (tw->telstate != TS_NORM)
  165.                             VGwrite(tw->curgraph,"\037\033\014",3);
  166.  
  167.                         tw->telstate = TS_NORM;
  168.                         break;
  169.                     } // FF or GS
  170.                 } // tw->tektype >= 0
  171.     
  172.                 if (*st == '^')    {            /* ESC- ^ */
  173.                     tw->termstate = RASTYPE;
  174.                     tw->telstate = TS_NORM;
  175.                     VRwrite("\033^",2);        /* Put it through */
  176.                     orig = ++st;
  177.                     break;
  178.                 }
  179.                 
  180.                 if (tw->termstate == TEKTYPE)
  181.                     VGwrite(tw->curgraph,"\033",1);
  182.                 else if (tw->termstate  == RASTYPE)
  183.                     VRwrite("\033",1);
  184.                 else
  185.                     VSwrite(tw->vs,"\033",1);    /* send the missing ESC */
  186.                 tw->telstate = TS_NORM;
  187.                 break;
  188.  
  189.  
  190. /*------------------------------------------------------------------------------*
  191.  *     IACFOUND:  This is the start of the Telnet option negotiation.  If Telnet    *
  192.  *    gets an IAC character, then negotiation data follows, and is ready to be    *
  193.  *     parsed.                                                                     *
  194.  *------------------------------------------------------------------------------*/
  195.             case IACFOUND:         /* telnet option negotiation- START */
  196.                 if (*st == TEL_IAC) {    /* real data = 255 */
  197.                     orig = st;            // MP: translation mod (break will make it miss
  198.                                         // this assignment later on in the case, Jim!)
  199.                     st++;                /* real 255 will get sent */
  200.                     tw->telstate = TS_NORM;
  201.                     break;
  202.                     }
  203.                 else {
  204.                     switch (*st++) {
  205.                         case TEL_EOF:        /* BYU LSC */
  206.                         case TEL_EL:                /* thanx Quincey!!! */
  207.                         case TEL_EC:
  208.                         case TEL_AYT:
  209.                         case TEL_AO:
  210.                         case TEL_IP:
  211.                         case TEL_BREAK:
  212.                         case TEL_DM:
  213.                         case TEL_NOP:
  214.                         case TEL_SE:
  215.                         case TEL_GA:
  216.             #ifdef OPTS_DEBUG
  217.                             sprintf(munger,"RECV: %s",telstates[tw->telstate]);
  218.                             opts_debug_print(munger); 
  219.             #endif
  220.                             tw->telstate = TS_NORM;
  221.                             orig=st;
  222.                             break;
  223.  
  224.                         case TEL_DOTEL:
  225.                             tw->telstate = TS_DO;
  226.                             orig = st;
  227.                             break;
  228.  
  229.                         case TEL_WILLTEL:
  230.                             tw->telstate = TS_WILL;
  231.                             orig = st;
  232.                             break;
  233.  
  234.                         case TEL_DONTTEL:
  235.                             tw->telstate = TS_DONT;
  236.                             orig = st;
  237.                             break;
  238.  
  239.                         case TEL_WONTTEL:
  240.                             tw->telstate = TS_WONT;
  241.                             orig = st;
  242.                             break;
  243.  
  244.             /*------------------------------------------------------------------------------*
  245.              *     SUBNEGOTIATION -- If there is an SB token found, then Telnet needs to do     *
  246.              *    some subnegotiating.  The subnegotiation data follows, and needs to be put    *
  247.              *    somewhere safe.  Make sure and update the state, so that we know that        *
  248.              *    Telnet is doing some subnegotiations and not just horsing around            *
  249.              *------------------------------------------------------------------------------*/
  250.                         case TEL_SB:
  251.                             tw->telstate = TS_SB;        /* Guess what I'm doing... */
  252.                             orig=st;
  253.                             tw->parseIndex = 0;        /* No data yet! Clear any possible garbage */
  254.                             break;
  255.                             
  256.                         default:        // Means we got IAC <xx> where xx isn't recognized
  257.                             orig = st;
  258.                             tw->telstate = TS_NORM;
  259. #ifdef OPTS_DEBUG
  260.                             sprintf(munger,"RECVD: IAC %c",*(st-1));
  261.                             opts_debug_print(munger);
  262. #endif                            
  263.                             break;
  264.                     }    // switch (*st++)    
  265.                 } // else from it (*st == TEL_IAC)
  266.             break; // case IACFOUND
  267.  
  268.             case TS_DO:
  269.                 telnet_do(tw, *st++);
  270.                 orig = st;
  271.                 tw->telstate = TS_NORM;
  272.                 break;
  273.  
  274.             case TS_DONT:
  275.                 telnet_dont(tw, *st++);
  276.                 orig = st;
  277.                 tw->telstate = TS_NORM;
  278.                 break;
  279.  
  280.             case TS_WILL:
  281.                 telnet_will(tw, *st++);
  282.                 orig = st;
  283.                 tw->telstate = TS_NORM;
  284.                 break;
  285.  
  286.             case TS_WONT:
  287.                 telnet_wont(tw, *st++);
  288.                 orig = st;
  289.                 tw->telstate = TS_NORM;
  290.                 break;
  291.             
  292.             case TS_SB:
  293.                 if (*st == TEL_IAC) 
  294.                 {
  295.                     st++;
  296.                     if (*st == TEL_SE) //subnegotiation over 
  297.                     {
  298.                         st++;
  299.                         process_suboption(tw, st, mark);
  300.                         orig = st;
  301.                         tw->telstate = TS_NORM;
  302.                     }    
  303.                     else
  304.                     {
  305.                         if (*st == TEL_IAC) //doubled IAC
  306.                             tw->parsedat[tw->parseIndex++] = *st++;
  307.                         else
  308.                         {    //process this, then go IAC found
  309.                             
  310.                             tw->parsedat[tw->parseIndex++] = TEL_IAC; //why do we add this to 
  311.                             tw->parsedat[tw->parseIndex++] = *st;     //the parsedat?   We don't 
  312.                             process_suboption(tw, st, mark);        //need it for the options
  313.                             tw->substat = IACFOUND;
  314.                         }
  315.                     }
  316.                 }
  317.                 else     // Collect subnegotiation data
  318.                     tw->parsedat[tw->parseIndex++] = *st++;
  319.                 break;
  320.                                         
  321.             default:
  322.                 tw->telstate = TS_NORM;
  323.                 break;
  324.         } // switch(tw->telstate)
  325.  
  326. /*
  327. * quick scan of the remaining string, skip chars while they are
  328. * uninteresting
  329. */
  330.         if (tw->telstate == TS_NORM) {
  331. /*
  332. *  skip along as fast as possible until an interesting character is found
  333. */
  334.  
  335.             if (!tw->eightbit) {                                            /* BYU 2.4.10 */
  336.                 while (st < mark) {                                            /* BYU 2.4.10 */
  337.                     if (*st == IAC)                                         /* BYU 2.4.10 */
  338.                         break;                                                /* BYU 2.4.10 */
  339.                     else {                                                    /* BYU 2.4.10 */
  340.                         *st &= 0x7f;                                         /* BYU 2.4.10 */
  341.                         if (*st == ESC  || *st == GS)                         /* BYU 2.4.10 */
  342.                             break;                                            /* BYU 2.4.10 */
  343.                         st++;                                                /* BYU 2.4.10 */
  344.                 }    }                                                        /* BYU 2.4.10 */
  345.             } else                                                             /* BYU 2.4.10 */
  346.                 while (st < mark && *st != ESC  && *st < 255 && *st != GS)     // MP: translation mod
  347.                     st++;                                                     /* BYU 2.4.10 */
  348. /*
  349. *  send the string where it belongs
  350. */
  351.             if (!tw->timing) {
  352.                 if (tw->termstate == TEKTYPE) {
  353.                     short i;
  354.                     
  355.                     i = VGwrite( tw->curgraph,(char *) orig,  st-orig);    /* BYU LSC */
  356.                     if (i < (st - orig)) {
  357.                         detachGraphics(tw->curgraph);
  358.                         st = orig + i;
  359.                         }
  360.                     }
  361.                 else if (tw->termstate == RASTYPE) {
  362.                     short i;
  363.                     
  364.                     i= VRwrite((char *) orig, st-orig);        /* BYU LSC */
  365.                     if (i <(st-orig)) {
  366.                         tw->termstate = VTEKTYPE;
  367.                         st = orig +i;                /* Next char to parse */
  368.                         }
  369.                     }
  370.                 else 
  371.                     VSwrite( tw->vs,(char *) orig,st-orig);    /* BYU LSC - send to virtual VT102 */
  372.                 }
  373.  
  374.             orig = st;                /* forget what we have sent already */
  375.  
  376.             if (st < mark)
  377.                 switch (*st) {
  378.                     case TEL_IAC:            /* telnet IAC */
  379.                         tw->telstate = IACFOUND;
  380.                         st++;
  381.                         break;
  382.                     case GS:
  383.                         if (tw->telstate != GS) {
  384.                             tw->telstate = GS;
  385.                             }
  386.                         else
  387.                             tw->telstate = TS_NORM;
  388.                         st++;
  389.                         break;
  390.                         
  391.                     case ESC:            /* ESCape code */
  392.                         if (st == mark-1 || *(st+1) == 12 || *(st+1) == '^' ) {
  393.                             tw->telstate = ESCFOUND;
  394.                         }
  395.                         st++;            /* strip or accept ESC char */
  396.                         break;
  397.     
  398.                     default:
  399.                         if (*st++ > 127) {
  400.                             if (st==mark)                            /*new addition */
  401.                                 VSwrite(tw->vs,(char *) orig,1);    /* BYU LSC */
  402.                              }
  403.                         break;
  404.                 }    // switch(*st)
  405.             } // tw->telstate == TS_NORM
  406.     } // while (st < mark)
  407.     } // tw->termstate != DUMBTYPE
  408.     
  409. //    ProfilerSetStatus(false);
  410.     
  411. } /* parse */
  412.  
  413. void    SendNAWSinfo(WindRec *s, short horiz, short vert)
  414. {
  415.     char            blah[20];
  416.     unsigned char    height, width;
  417.  
  418.     height = vert & 0xff;
  419.     width = horiz & 0xff;
  420.     
  421.     /* 931112, ragge, NADA, KTH, ugly patch to not send IAC as window size  */
  422.     if(height == 0xFF) height = 0xFE;
  423.     if(width == 0xFF) width = 0xFE;
  424.  
  425.     netpush (s->port);
  426.  
  427. /* NCSA: syntax for command is:  IAC SB NAWS widthHI widthLO heightHI heightLO IAC SE */
  428.  
  429.     netwrite(s->port,"\377\372\037\000",4);
  430.     sprintf(blah,"%c\000", width);
  431.     netwrite(s->port,blah,2);
  432.     sprintf(blah,"%c\377\360", height);
  433.     netwrite(s->port,blah,3);
  434.     opts_debug_print("SENT: IAC SB NAWS <data> IAC SE");        
  435. }
  436.  
  437. /*
  438.  * Implementation specific Kerberos routines
  439.  */
  440.  
  441.  
  442. /*
  443.  * getcname
  444.  * Return a pointer to the cannonical host name
  445.  */
  446. static char    *getcname (WindRec *tw)
  447. {
  448.     char *cp;
  449.     static char *b, buf[100];
  450.  
  451.     cp = 0;
  452.     if (tw->cannon[0])
  453.         cp = tw->cannon;
  454.  
  455. //    Doing the following is bad because we disposed of our init params!
  456. //    else if ((*(*(ConnInitParams **)(tw->myInitParams))->session)->hostname)
  457. //        cp = (char *)(*(*(ConnInitParams **)(tw->myInitParams))->session)->hostname;
  458.  
  459.     /* make a local copy to avoid locking handles */
  460.     if (cp) {
  461.         b = buf;        
  462.         while (*cp)
  463.             *b++ = *cp++;            
  464.         *b++ = '\0';
  465.         return buf;
  466.     }
  467.  
  468.     return cp;
  469. }
  470.  
  471.  
  472. /*
  473.  * encryptStatechange
  474.  * Called when the encryption state changes
  475.  */
  476. #define kOurHit    32
  477. static    void encryptStatechange (struct WindRec *tw)
  478. {
  479.     MyWDEFPatch(zoomDocProc, tw->wind, wDraw, kOurHit);
  480. }
  481.  
  482. void    telnet_send_initial_options(WindRec *tw)
  483. {
  484.     if (tw->authenticate) {
  485.         send_will(tw->port, OPT_AUTHENTICATION);
  486.         (tw->myopts)[OPT_AUTHENTICATION-MHOPTS_BASE] = 1;
  487.  
  488.         if (tw->encrypt) {
  489.             send_will(tw->port, OPT_ENCRYPT);        /* will encrypt */
  490.             (tw->myopts)[OPT_ENCRYPT-MHOPTS_BASE] = 1;
  491.         }
  492.     }
  493.  
  494.     send_do(tw->port, N_ECHO);        // Do ECHO
  495.     tw->echo = 1;
  496.  
  497.     send_do(tw->port, N_SGA);        // Do SGA
  498.     tw->Usga=1;
  499.     
  500.     send_wont(tw->port, N_XDISPLOC);
  501.     
  502.     send_will(tw->port, N_NAWS);
  503.  
  504. }
  505.     
  506. static    void    process_suboption(struct WindRec *tw, unsigned char *start, unsigned char *end)
  507. {    
  508.     unsigned long    sendlength;
  509.     unsigned char    sendbuffer[1500];
  510.     short            s;
  511.     char            IACSB[] = { TEL_IAC, TEL_SB, 0, 0};
  512.     char            IACSE[] = { TEL_IAC, TEL_SE};
  513.  
  514.     switch(tw->parsedat[0]) {
  515.     /*------------------------------------------------------------------------------*
  516.     *     SUBNegotiate Termtype:  send the term type data now                            *
  517.     *------------------------------------------------------------------------------*/
  518.         case N_TERMTYP:            
  519.             if (tw->parsedat[1]==1) {
  520.                 char s[60], termtmp[40];
  521.                 BlockMove(tw->answerback, termtmp, 32);
  522.                 PtoCstr((StringPtr)termtmp);
  523. #ifdef OPTS_DEBUG
  524.                 sprintf(munger,"RECV: SB TERMINAL-TYPE SEND\r\nSEND: SB TERMINAL-TYPE IS %s\r\n",termtmp);
  525.                 opts_debug_print(munger); 
  526. #endif
  527.                 IACSB[2] = '\030';
  528.                 IACSB[3] = 0;
  529.                 netpush(tw->port);
  530.                 netwrite(tw->port,IACSB,4);
  531.                 netpush(tw->port);
  532.                 sprintf(s,"%s%c%c",termtmp, TEL_IAC, TEL_SE);
  533.                 netwrite(tw->port, s, strlen(s));
  534.                 }
  535.             break;
  536.                 
  537. /*------------------------------------------------------------------------------*
  538. *     SUBNegotiate ENCRYPTION:                                                     *
  539. *------------------------------------------------------------------------------*/
  540.             case N_ENCRYPT:
  541.                 sendlength = sizeof(sendbuffer);
  542.                 s = encrypt_suboption((tnParams **)&tw->aedata, tw->parsedat,
  543.                                       tw->parseIndex,
  544.                                       sendbuffer, &sendlength, getcname(tw), 
  545.                                       tw->hisopts[OPT_ENCRYPT - MHOPTS_BASE], 
  546.                                       tw->myopts[OPT_ENCRYPT - MHOPTS_BASE]);
  547.                 netportencryptstate(tw->port, (Ptr)tw->aedata);
  548.                 encryptStatechange(tw);
  549.  
  550.                 /*
  551.                  * If we turned on encryption, we must decrypt the rest of the buffer.
  552.                  */
  553.                 if (s == TNREP_START_DECRYPT) {
  554.                     unsigned char *cp = start;
  555.                     while (cp < end) {
  556.                         *cp = decrypt((tnParams *)tw->aedata, (long)(*cp));
  557.                         cp++;
  558.                     }
  559.                 }
  560.  
  561.                 if (sizeof(sendbuffer) - sendlength)
  562.                     netwrite(tw->port, sendbuffer, sizeof(sendbuffer)-sendlength);
  563.                 
  564.                 /*
  565.                  * transfer the encrypting flag here, after the buffer 
  566.                  * with encrypt-start has gone out.
  567.                  */
  568.                 if (((tnParams *)tw->aedata)->startencrypting) {
  569.                     ((tnParams *)tw->aedata)->startencrypting = false;
  570.                     ((tnParams *)tw->aedata)->encrypting = true;
  571.                     }
  572.             break;
  573.                 
  574.     /*------------------------------------------------------------------------------*
  575.     *     SUBNegotiate Authentication:  send the authentication data now                 *
  576.     *------------------------------------------------------------------------------*/
  577.         case N_AUTHENTICATION:            
  578.             sendlength = sizeof(sendbuffer);
  579.             auth_suboption((tnParams **)&tw->aedata, tw->parsedat,
  580.                            tw->parseIndex,
  581.                            sendbuffer, &sendlength, getcname(tw), 
  582.                            tw->hisopts[OPT_ENCRYPT-MHOPTS_BASE], 
  583.                            tw->myopts[OPT_ENCRYPT-MHOPTS_BASE]);
  584.             if (sizeof(sendbuffer) - sendlength) {
  585.                 netwrite(tw->port, sendbuffer, sizeof(sendbuffer)-sendlength);
  586.                 }
  587.             break;
  588.             
  589.     /*------------------------------------------------------------------------------*
  590.     *     SUBNegotiate Linemode:  set up local characters, modes, and such            *
  591.     *------------------------------------------------------------------------------*/
  592.         case N_LINEMODE:
  593.             linemode_suboption(tw);
  594.             break;
  595.  
  596.     /*------------------------------------------------------------------------------*
  597.     *     SUBNegotiate REMOTE_FLOW_CONTROL:  determine whether we control flow, and   *
  598.     *                                       what restarts flow                         *
  599.     *------------------------------------------------------------------------------*/
  600.         case N_REMOTEFLOW:
  601.             switch (tw->parsedat[1])
  602.             {
  603.  
  604.                 case FLOW_OFF:
  605. #ifdef OPTS_DEBUG
  606.                     sprintf(munger,"RECV: SB REMOTE_FLOW FLOW_OFF");
  607.                     opts_debug_print(munger); 
  608. #endif
  609.                     tw->allow_flow = FALSE;
  610.                 break;
  611.                 
  612.                 case FLOW_ON:
  613. #ifdef OPTS_DEBUG
  614.                     sprintf(munger,"RECV: SB REMOTE_FLOW FLOW_ON");
  615.                     opts_debug_print(munger); 
  616. #endif    
  617.                     tw->allow_flow = TRUE;
  618.                 break;
  619.                 
  620.                 case FLOW_RESTART_ANY:
  621. #ifdef OPTS_DEBUG
  622.                     sprintf(munger,"RECV: SB REMOTE_FLOW FLOW_RESTART_ANY");
  623.                     opts_debug_print(munger); 
  624. #endif    
  625.                     tw->restart_any_flow = TRUE;
  626.                 break;
  627.                 
  628.                 case FLOW_RESTART_XON:
  629. #ifdef OPTS_DEBUG
  630.                     sprintf(munger,"RECV: SB REMOTE_FLOW FLOW_RESTART_XON");
  631.                     opts_debug_print(munger); 
  632. #endif    
  633.                     tw->restart_any_flow = FALSE;
  634.                 break;
  635.                 
  636.                 default:
  637.                 break;    
  638.             }
  639.         
  640.         default: //dont know this subnegotiation!!
  641.             break;
  642.     }
  643. }            
  644.  
  645. static    void    telnet_do(struct WindRec *tw, short option)
  646. {
  647. #ifdef OPTS_DEBUG
  648.     sprintf(munger,"RECV: %s %s",telstates[TEL_DOTEL-TEL_SE],teloptions[option]);
  649.     opts_debug_print(munger); 
  650. #endif
  651.     switch(option) {
  652.         case  N_SGA:        /* Sure we'll supress GA */
  653.             if (!tw->Isga) {
  654.                 tw->Isga=1;
  655.                 send_will(tw->port, N_SGA);
  656.                 }
  657.             break;
  658.         
  659.         case N_TERMTYP:        /* And we'll even tell you about ourselves */
  660.             if (!tw->Ittype) {
  661.                 tw->Ittype=1;
  662.                 send_will(tw->port, N_TERMTYP);
  663.                 }
  664.             break;
  665.  
  666.         case  N_NAWS:            /* NCSA: sure, I like changing the window size! */
  667.             tw->naws =1;        /* NCSA: this session is now NAWS */
  668.             send_will(tw->port, N_NAWS);
  669.  
  670.             SendNAWSinfo(tw, VSmaxwidth(tw->vs) + 1, VSgetlines(tw->vs));
  671. #ifdef OPTS_DEBUG
  672.             opts_debug_print("SENT: IAC TEL_SB N_NAWS <data> IAC TEL_SE"); 
  673. #endif
  674.             break;                                            /* NCSA */
  675.  
  676.         case N_LINEMODE:  /* Sure I'll do line mode... */
  677.             if (tw->lineAllow)  
  678.             {
  679.                 send_will(tw->port, N_LINEMODE);
  680.                 doLinemode(tw);
  681.             }
  682.             else
  683.                 send_wont(tw->port, N_LINEMODE);
  684.             break;
  685.  
  686.         case N_AUTHENTICATION:        /* do auth */
  687.             if (!tw->myopts[OPT_AUTHENTICATION-MHOPTS_BASE]) {
  688.                 if (tw->authenticate) {
  689.                     (tw->myopts)[OPT_AUTHENTICATION-MHOPTS_BASE] = 1;
  690.                     send_will(tw->port, N_AUTHENTICATION);
  691.                     }
  692.                 else {
  693.                     send_wont(tw->port, N_AUTHENTICATION);
  694.                     }
  695.             }
  696.             break;
  697.  
  698.         case N_ENCRYPT:             /* do encrypt */
  699.             if (!tw->myopts[OPT_ENCRYPT-MHOPTS_BASE]) {
  700.                 if (tw->encrypt) {
  701.                     (tw->myopts)[OPT_ENCRYPT-MHOPTS_BASE] = 1;
  702.                     send_will(tw->port, N_ENCRYPT);
  703.                 } else {
  704.                     send_wont(tw->port, N_ENCRYPT);
  705.                 }
  706.             }
  707.             break;
  708.         
  709.         case N_REMOTEFLOW:
  710.             if (!tw->remote_flow)
  711.             {
  712.                 tw->remote_flow = TRUE;
  713.                 send_will(tw->port, option); 
  714.             }            
  715.             break;
  716.             
  717.         default:                /* But, we won't do .... */
  718.             send_wont(tw->port, option);
  719.             break;
  720.         }
  721. }
  722.  
  723. static    void    telnet_dont(struct WindRec *tw, short option)
  724. {
  725. #ifdef OPTS_DEBUG
  726.     sprintf(munger,"RECV: %s %s",telstates[TEL_DONTTEL-TEL_SE],teloptions[option]);
  727.     opts_debug_print(munger); 
  728. #endif
  729.  
  730.     switch (option) {
  731.         case N_ENCRYPT:                    /* dont encrypt */
  732.         case N_AUTHENTICATION:            /* dont authenticate */
  733.             tw->myopts[option - MHOPTS_BASE] = 0;
  734.             send_wont(tw->port, option);
  735.             break;
  736.         case N_LINEMODE:  /* Ok. turn it off if its on */
  737.             if (tw->lmode)  
  738.             {
  739.                 send_wont(tw->port, N_LINEMODE);
  740.                 if (tw->kblen > 0)
  741.                 {
  742.                     netpush(tw->port);
  743.                     netwrite(tw->port, tw->kbbuf, tw->kblen);
  744.                 }    
  745.                 tw->lmode = 0;
  746.                 tw->lmodeBits = 0;
  747.                 tw->litNext = 0;
  748.             }
  749.             break;
  750.  
  751.  
  752.     }
  753. }
  754.  
  755. static    void    telnet_will(struct WindRec *tw, short option)
  756. {
  757. #ifdef OPTS_DEBUG
  758.     sprintf(munger,"RECV: %s %s",telstates[TEL_WILLTEL-TEL_SE],teloptions[option]);
  759.     opts_debug_print(munger); 
  760. #endif
  761.     switch(option) 
  762.         {
  763.         case N_ECHO:             /* Echo on the other end*/
  764. #ifdef    OPTS_DEBUG
  765.             if (!tw->echo)
  766.                 opts_debug_print("tw->echo is False.");
  767. #endif
  768.             if (!tw->echo)
  769.                 break;
  770.             tw->echo = 0;    /* Ok, in that case they can echo... */
  771.             changeport(scrn,scrn);
  772.             send_do(tw->port, N_ECHO);
  773.             break;
  774.         
  775.         case N_SGA:                /* Supress GA */
  776. #ifdef    OPTS_DEBUG
  777.             if (tw->Usga)
  778.                 opts_debug_print("tw->Usga is True.");
  779. #endif
  780.             if (tw->Usga)
  781.                 break;
  782.             tw->Usga = 1;    /* Go Ahead and supress GA */
  783.             send_do(tw->port, N_SGA);
  784.             break;
  785.         
  786.         case N_TIMING:                /* Timing Mark */
  787.             tw->timing = 0;
  788.             break;
  789.         
  790.         case N_AUTHENTICATION:        /* will auth */
  791.             if (!tw->hisopts[OPT_AUTHENTICATION-MHOPTS_BASE]) {
  792.                 if (tw->authenticate) {
  793.                     (tw->hisopts)[OPT_AUTHENTICATION-MHOPTS_BASE] = 1;
  794.                     send_do(tw->port, N_AUTHENTICATION);
  795.                     }
  796.                 else {
  797.                     send_dont(tw->port, N_AUTHENTICATION);
  798.                 }
  799.             }
  800.             break;
  801.  
  802.         case N_ENCRYPT:             /* will encrypt */
  803.             if (!tw->hisopts[OPT_ENCRYPT-MHOPTS_BASE]) {
  804.                 if (tw->encrypt) {
  805.                     (tw->hisopts)[OPT_ENCRYPT-MHOPTS_BASE] = 1;
  806.                     send_do(tw->port, N_ENCRYPT);
  807.                 } else {
  808.                     send_dont(tw->port, N_ENCRYPT);
  809.                 }
  810.             }
  811.             break;
  812.  
  813.         case N_REMOTEFLOW:     /* they want to toggle flow control */
  814.             if (!tw->remote_flow)
  815.             {
  816.                 tw->remote_flow = 1;
  817. #ifdef    OPTS_DEBUG
  818.                 opts_debug_print("tw->remote_flow is True.");
  819. #endif
  820.                 send_do(tw->port, N_REMOTEFLOW);
  821.             }
  822.  
  823.         default:
  824.             send_dont(tw->port, option);
  825.         }
  826. }
  827.  
  828. static    void    telnet_wont(struct WindRec *tw, short option)
  829. {
  830. #ifdef OPTS_DEBUG
  831.     sprintf(munger,"RECV: %s %s",telstates[TEL_WONTTEL-TEL_SE],teloptions[option]);
  832.     opts_debug_print(munger); 
  833. #endif
  834.     switch(option) 
  835.         {         /* which option? */
  836.         case N_ECHO:             /* echo */
  837.             if (tw->echo)
  838.                 break;
  839.             tw->echo = 1;    /* Ok, I will echo if I have to... */
  840.             changeport(scrn,scrn);
  841.             send_dont(tw->port,N_ECHO);
  842.             break;
  843.         
  844.         case N_SGA:
  845.             if (!tw->Usga)
  846.                 break;
  847.             tw->Usga = 0;
  848.                send_dont(tw->port,N_SGA);
  849.             break;
  850.         
  851.         case N_TIMING:                /* Timing Mark */
  852.             tw->timing = 0;
  853.             break;
  854.         
  855.         case N_ENCRYPT:                    /* wont encrypt */
  856.         case N_AUTHENTICATION:            /* wont authenticate */
  857.             tw->hisopts[option-MHOPTS_BASE] = 0;
  858.             send_dont(tw->port, option);
  859.             break;
  860.  
  861.         default:
  862.             break;
  863.         }
  864. }
  865.  
  866. void    send_do(short port, short option)
  867. {
  868.     char    data[] = { IAC, TEL_DOTEL, 0};
  869.     
  870.     data[2] = option;
  871.     netpush(port);
  872.     netwrite(port, data, 3);
  873. #ifdef OPTS_DEBUG
  874.     sprintf(munger,"SENT: DO %s",teloptions[option]);
  875.     opts_debug_print(munger); 
  876. #endif
  877. }
  878.  
  879. void    send_dont(short port, short option)
  880. {
  881.     char    data[] = { IAC, TEL_DONTTEL, 0};
  882.  
  883.     data[2] = option;
  884.     netpush(port);
  885.     netwrite(port, data, 3);
  886. #ifdef OPTS_DEBUG
  887.     sprintf(munger,"SENT: DONT %s",teloptions[option]);
  888.     opts_debug_print(munger); 
  889. #endif
  890. }
  891.  
  892. static    void    send_will(short port, short option)
  893. {
  894.     char    data[] = { IAC, TEL_WILLTEL, 0};
  895.  
  896.     data[2] = option;
  897.     netpush(port);
  898.     netwrite(port, data, 3);
  899. #ifdef OPTS_DEBUG
  900.     sprintf(munger,"SENT: WILL %s",teloptions[option]);
  901.     opts_debug_print(munger); 
  902. #endif
  903. }
  904.  
  905. static    void    send_wont(short port, short option)
  906. {
  907.     char    data[] = { IAC, TEL_WONTTEL, 0};
  908.     
  909.     data[2] = option;
  910.     netpush(port);
  911.     netwrite(port, data, 3);
  912. #ifdef OPTS_DEBUG
  913.     sprintf(munger,"SENT: WONT %s",teloptions[option]);
  914.     opts_debug_print(munger); 
  915. #endif
  916. }