home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1995 April / Internet Tools.iso / applic / ncsa / Mac / Telnet2.6 / prerelease / d5 / Telnet 2.6.1d5.src.sit.hqx / Telnet 2.6.1d5 src / source / parse / parse.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-19  |  24.1 KB  |  899 lines

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