home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Telnet 2.7b5 / source / Linemode / linemode.c next >
Encoding:
C/C++ Source or Header  |  1995-03-20  |  17.6 KB  |  671 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. #include "wind.h"
  14. #include "parse.h"
  15.  
  16. #include "linemode.proto.h"
  17. #include "network.proto.h"
  18. #include "parse.proto.h"
  19. #include "vsdata.h"
  20. #include "vsinterf.proto.h"
  21. #ifdef MPW
  22. #pragma segment Parse
  23. #endif
  24.  
  25. //#define    OPTS_DEBUG
  26. #ifdef    OPTS_DEBUG
  27. extern char *telstates[];
  28. extern char *teloptions[];
  29. extern char *LMoptions[];
  30. extern char *LMflags[];
  31. extern char *LMmodes[];
  32. extern char *LMmodeBits[];
  33. #define    opts_debug_print(x)    putln(x)    
  34. #else
  35. #define    opts_debug_print(x)
  36. #endif
  37.  
  38. static    void    DemangleLineMode(char *s, short mode);
  39. static void setForwardMask(struct WindRec *tw); //set the keys on which we forward on
  40. static void negotiateSLC(struct WindRec *tw);
  41. static void respondSLC(short optionNumber,short *alreadySentSB,struct WindRec *tw, Boolean AWK);
  42.  
  43.  
  44.  
  45. static    unsigned char str_lm[] = { TEL_IAC, TEL_SB, N_LINEMODE, 0, 0, TEL_IAC, TEL_SE };
  46. static    unsigned char str_lm_mode[] = { TEL_IAC, TEL_SB, N_LINEMODE, L_MODE, 0, TEL_IAC, TEL_SE };
  47.  
  48. static unsigned char default_slc[] = 
  49.     { 255, 255, 255, DEFAULT_SLC_IP,DEFAULT_SLC_AO,0,0,DEFAULT_SLC_ABORT,DEFAULT_SLC_EOF,
  50.         DEFAULT_SLC_SUSP,DEFAULT_SLC_EC,DEFAULT_SLC_EL,DEFAULT_SLC_EW,DEFAULT_SLC_RP,
  51.         DEFAULT_SLC_LNEXT,DEFAULT_SLC_XON,DEFAULT_SLC_XOFF,DEFAULT_SLC_FORW1,DEFAULT_SLC_FORW2,255,255,255,255,255,255,255,255,255,255,255,255 };
  52.  
  53. #ifdef OPTS_DEBUG
  54.     static char munger[255]; 
  55. #endif
  56.  
  57. void    LinemodeUnload(void) {}
  58.  
  59. void initLinemode(struct WindRec *tw)
  60. {
  61.     short temp;
  62.     for (temp=0; temp<= SLC_MAX; temp++)
  63.     {
  64.         tw->slc[temp] = default_slc[temp];
  65.         if (default_slc[temp] == 255)
  66.             tw->slcLevel[temp] = SLC_NOSUPPORT;
  67.         else
  68.             tw->slcLevel[temp] = SLC_VALUE;
  69.     }
  70.     tw->lmodeBits = 0;
  71.     tw->litNext = 0;
  72.     tw->lmode = 0;
  73. }
  74.  
  75. void process_key(unsigned char ascii,struct WindRec *tw)
  76. {
  77.     if (tw->litNext) //do no processing on next key
  78.     {
  79.         tw->litNext = FALSE;
  80.         if (tw->kblen < (MAXKB -1))     /* Add to buffer if not full */
  81.             tw->kbbuf[tw->kblen++] = ascii;
  82.         else 
  83.         {                
  84.             netpush(tw->port);
  85.             netwrite( tw->port, tw->kbbuf, tw->kblen);    /* if full send buffer */
  86.             tw->kbbuf[0]=ascii;
  87.             tw->kblen=1;
  88.         }
  89.         if (tw->echo)
  90.         {
  91.             if (ascii>31 && ascii <127)    /* add these chars to buffer */
  92.             {
  93.                 parse(tw, &ascii, 1);
  94.                 return;
  95.             }
  96.             else
  97.                 return;
  98.         }
  99.     }
  100.  
  101.     if (tw->lmodeBits & 2) // TRAPSIG mode active
  102.     {        
  103.         unsigned char toSend[2] = {IAC,0};
  104.         short whichSignal = 0;
  105.         if (ascii == tw->slc[SLC_IP])
  106.         {
  107.             whichSignal = SLC_IP;
  108.             toSend[1] = TEL_SUSP;
  109.         }
  110.         else if (ascii == tw->slc[SLC_ABORT])
  111.         {
  112.             whichSignal = SLC_ABORT;
  113.             toSend[1] = TEL_ABORT;
  114.         }
  115.         if (toSend[1]) //if we have a signal to catch
  116.         {
  117.             if (tw->echo)
  118.                 parse(tw, &ascii, 1); // echo if we should
  119.             tw->kblen=0; //zero out the buffer
  120.             netpush(tw->port);
  121.             netwrite(tw->port,toSend,2); //send IAC whatever
  122.             if (tw->slcLevel[whichSignal] & SLC_FLUSHIN)
  123.             {
  124.                 unsigned char dm[2] = {IAC,TEL_DM};
  125.                 netpush(tw->port);
  126.                 netUrgent();//send next as urgent data
  127.                 netwrite(tw->port,dm,2);//send IAC DM
  128.             }
  129.             if (tw->slcLevel[whichSignal] & SLC_FLUSHOUT)
  130.             {
  131.                 unsigned char tm[3] = {IAC,TEL_DOTEL,N_TIMING};
  132.                 tw->timing = 1;    //tell ourselves to wait for WILL TIMING
  133.                 netpush(tw->port);
  134.                 netwrite(tw->port,tm,3);//send DO TIMING
  135.             }
  136.             return;
  137.         }
  138.     }
  139.     
  140.     if ((tw->lmodeBits & L_SOFT_TAB)&&(ascii == 0x09)) // SOFT_TAB mode active; expand tab into spaces
  141.     {
  142.         short numSpaces = VSIgetNextTabDistance();
  143.         while (numSpaces > 0)
  144.         {
  145.             while ((numSpaces > 0)&&(tw->kblen < (MAXKB -1)))
  146.             {
  147.                 tw->kbbuf[tw->kblen++] = 0x20; //space
  148.                 numSpaces--;
  149.             }
  150.             if (tw->kblen == (MAXKB -1))
  151.             {
  152.                 netpush(tw->port);
  153.                 netwrite( tw->port, tw->kbbuf, tw->kblen);    /* if full send buffer */
  154.                 tw->kblen=0;
  155.             }
  156.         }
  157.         if (tw->echo)
  158.             parse(tw, &ascii, 1);
  159.         return;
  160.     }
  161.     
  162.  
  163.  
  164.     if (tw->lmodeBits & L_EDIT) //handle editing functions
  165.     {
  166.             
  167.  
  168.         if (ascii == '\015') //CR
  169.         { //since we are in edit, send the buffer and CR-LF
  170.             if (tw->kblen > 0)
  171.                 netwrite(tw->port, tw->kbbuf, tw->kblen);
  172.             netpush(tw->port);
  173.             netwrite(tw->port,"\015\012",2);
  174.             tw->kblen = 0;
  175.             if (tw->echo)
  176.                 parse(tw,(unsigned char *) "\012\015",2);
  177.             return;
  178.         }
  179.         
  180.         if (ascii == tw->slc[SLC_EC]) //kill the character
  181.         {
  182.             if (tw->echo)
  183.                 parse(tw,(unsigned char *) "\010 \010",3);    
  184.             tw->kblen--;
  185.             return;
  186.         }
  187.         else if (ascii == tw->slc[SLC_AO]) //kill the line
  188.         {
  189.             while (tw->kblen >0) 
  190.             {
  191.                 if (tw->echo)
  192.                     parse(tw,(unsigned char *) "\010 \010",3);
  193.                 tw->kblen--;
  194.             }
  195.             return;
  196.         }
  197.         else if (ascii == tw->slc[SLC_EL]) //kill the line
  198.         {
  199.             while (tw->kblen >0) 
  200.             {
  201.                 if (tw->echo)
  202.                     parse(tw,(unsigned char *) "\010 \010",3);
  203.                 tw->kblen--;
  204.             }
  205.             return;
  206.         }
  207.         else if (ascii == tw->slc[SLC_EOF])
  208.         { //push the buffer, send IAC EOF
  209.             char eofString[2] = { IAC, TEL_EOF };
  210.             if (tw->kblen > 0)
  211.                 netwrite(tw->port, tw->kbbuf, tw->kblen);
  212.             tw->kbbuf[0]=ascii;
  213.             tw->kblen=1;
  214.             netpush(tw->port);
  215.             netwrite(tw->port,eofString, 2);
  216.             return;
  217.         }
  218.         else if (ascii == tw->slc[SLC_SUSP])
  219.         {
  220.             char eofString[2] = { IAC, TEL_SUSP };
  221.             if (tw->kblen > 0)
  222.                 netwrite(tw->port, tw->kbbuf, tw->kblen);
  223.             tw->kblen = 0;
  224.             netpush(tw->port);
  225.             netwrite(tw->port,eofString, 2);
  226.             return;
  227.         }
  228.         else if (ascii == tw->slc[SLC_EW])
  229.         {
  230.             while ((tw->kbbuf[tw->kblen-1] != 0x20)&&(tw->kblen >= 0)) //while its not a space
  231.             {
  232.                 if (tw->echo)
  233.                     parse(tw,(unsigned char *)"\010 \010",3);
  234.                 tw->kblen--;
  235.             }
  236.         }
  237.         else if (ascii == tw->slc[SLC_RP])
  238.         {
  239.             VSredrawLine(tw->vs);
  240.             return;
  241.         }
  242.         else if (ascii == tw->slc[SLC_LNEXT])
  243.         {
  244.             tw->litNext = TRUE;
  245.             return;
  246.         }
  247.         else if (ascii == tw->slc[SLC_XON])
  248.         {
  249.             if (tw->allow_flow) //remote flow control can turn this off
  250.                 tw->enabled = 0;
  251.             return;
  252.         }    
  253.         else if (ascii == tw->slc[SLC_XOFF])
  254.         {
  255.             if (tw->allow_flow) //remote flow control can turn this off
  256.                 tw->enabled = 0;
  257.             return;
  258.         }
  259.         else if ((ascii == tw->slc[SLC_FORW1])||(ascii == tw->slc[SLC_FORW1]))
  260.         {
  261.             if (tw->kblen > 0)
  262.                 netwrite(tw->port, tw->kbbuf, tw->kblen);
  263.             netpush(tw->port);
  264.             netwrite(tw->port,&ascii,1);
  265.             tw->kblen = 0;
  266.             return;
  267.  
  268.         }
  269.         //ok, at this point, we are past all local editing functions.  Now, add the character to the buffer.
  270.         else
  271.         {
  272.             if (tw->kblen < (MAXKB -1))     // Add to buffer if not full
  273.                 tw->kbbuf[tw->kblen++] = ascii;
  274.             else 
  275.             {                
  276.                 netpush(tw->port);
  277.                 netwrite( tw->port, tw->kbbuf, tw->kblen);    // if full send buffer 
  278.                 tw->kbbuf[0]=ascii;
  279.                 tw->kblen=1;
  280.             }
  281.         }
  282.  
  283.     }
  284.     else if (ascii == '\015') //CR; map this to CR-LF
  285.     {
  286.         unsigned char toSend[2] = {0x0D,0x00};
  287.         netpush(tw->port);
  288.         netwrite(tw->port,toSend,2);
  289.         if (tw->echo)
  290.             parse(tw,(unsigned char *) "\012\015",2);
  291.         return;    
  292.     }
  293.     else //not editing; send it
  294.     {
  295.         netpush(tw->port);
  296.         netwrite( tw->port, &ascii, 1);    // if full send buffer 
  297.     }
  298.  
  299.     if (tw->echo)    /* Handle local ECHOs */
  300.     {
  301.         if (ascii>31 && ascii <127)    /* add these chars to buffer */
  302.             parse(tw, &ascii, 1);
  303.         else            /* not printable char */
  304.         {
  305.             if (!(tw->lmodeBits & L_LIT_ECHO)) //don't echo if this is set
  306.             {        
  307.                 ascii='@'+ascii;
  308.                 parse(tw,(unsigned char *) "^",1);
  309.                 parse(tw, &ascii, 1);
  310.             }
  311.         }
  312.     }
  313. }
  314.  
  315.  
  316. void    linemode_suboption(struct WindRec *tw)
  317. {
  318.     switch(tw->parsedat[1]) {
  319.         char s[80];
  320.  
  321.         case L_MODE:    /* change mode */
  322. #ifdef OPTS_DEBUG
  323.             strcpy(s, "RECV: SB LINEMODE MODE => ");
  324.             DemangleLineModeShort(s, tw->parsedat[2]);
  325.             opts_debug_print(s);
  326. #endif
  327.             if (tw->lineAllow) {            // First make sure we allowed linemode in the first place.
  328.                 // RFC 1184 says client should ignore MODE negotiations with the MODE_ACK bit set, and should not
  329.                 //    generate a response if the negotiated MODE matches the current MODE
  330.                 if (!((tw->parsedat[2] & L_MODE_ACK) || ((tw->parsedat[2] & L_MODE_MASK) == tw->lmodeBits))) 
  331.                 {
  332.                     tw->lmodeBits = tw->parsedat[2];    // Accept the mode
  333.                     tw->parsedat[2] |= L_MODE_ACK;  // Set the MODE_ACK bit
  334.  
  335.                     sprintf(s,"%c%c%c%c",IAC,TEL_SB,N_LINEMODE,L_MODE);
  336.                     netwrite(tw->port,s,4);
  337.                     sprintf(s,"%c%c%c",tw->parsedat[2],IAC,TEL_SE);
  338.                     netwrite(tw->port,s,3); 
  339. #ifdef OPTS_DEBUG
  340.                     opts_debug_print("SENT: IAC SB");
  341.                     strcpy(s, "SENT: LM MODE = ");
  342.                     DemangleLineModeShort(s, tw->parsedat[2]);
  343.                     opts_debug_print(s);
  344.                     opts_debug_print("SENT: IAC SE");
  345. #endif
  346.                 }
  347. #ifdef OPTS_DEBUG
  348.                 else {
  349.                     strcpy(s, "LINEMODE MODE = ");
  350.                     DemangleLineModeShort(s, tw->parsedat[2]);
  351.                     opts_debug_print(s);
  352.                     if (tw->parsedat[2] & L_MODE_ACK) 
  353.                         opts_debug_print("\tignored because MODE_ACK was set.");
  354.                     else
  355.                         opts_debug_print("\tIgnored because we are already at that mode.");
  356.                     strcpy(s, "Curr Linemode = ");
  357.                     DemangleLineModeShort(s, tw->lmodeBits);
  358.                     opts_debug_print(s);
  359.                 }
  360. #endif
  361.                 
  362.             }
  363.             break;
  364.         
  365.         case TEL_DOTEL:    
  366. #ifdef OPTS_DEBUG
  367.             sprintf(munger,"RECV: SB LINEMODE DO %c", tw->parsedat[2]);
  368.             opts_debug_print(munger);
  369. #endif
  370.             tw->forwardMask = TRUE;
  371.             setForwardMask(tw);
  372.             str_lm[3] = TEL_WILLTEL;
  373.             str_lm[4] = L_FORWARDMASK;
  374.             netpush(tw->port);
  375.             netwrite(tw->port, str_lm, sizeof(str_lm));
  376. #ifdef OPTS_DEBUG
  377.             sprintf(munger,"SENT: IAC SB LINEMODE WILL %c IAC SE", tw->parsedat[2]);
  378.             opts_debug_print(munger);
  379. #endif
  380.             break;
  381.  
  382.         case TEL_DONTTEL:    
  383. #ifdef OPTS_DEBUG
  384.             sprintf(munger,"RECV: SB LINEMODE DO %c", tw->parsedat[2]);
  385.             opts_debug_print(munger);
  386. #endif
  387.             tw->forwardMask = FALSE;
  388.             str_lm[3] = TEL_WONTTEL;
  389.             str_lm[4] = L_FORWARDMASK;
  390.             netpush(tw->port);
  391.             netwrite(tw->port, str_lm, sizeof(str_lm));
  392. #ifdef OPTS_DEBUG
  393.             sprintf(munger,"SENT: IAC SB LINEMODE WONT %c IAC SE", tw->parsedat[2]);
  394.             opts_debug_print(munger);
  395. #endif
  396.             break;
  397.  
  398.         case L_SLC:        /* set local chars */
  399.             negotiateSLC(tw);
  400.         break;
  401.             
  402.         default:
  403. #ifdef OPTS_DEBUG
  404.         sprintf(munger, "RECV: SB LINEMODE ?? (?? = %c)", tw->parsedat[1]);
  405.         opts_debug_print(munger);
  406. #endif
  407.         break;
  408.  
  409.     }//switch parsedat
  410. }
  411.  
  412.  
  413. void setForwardMask(struct WindRec *tw) //set the keys on which we forward on
  414. {
  415.     short j, i = 3;
  416.     Boolean anotherByte = TRUE;
  417.     tw->numForwardKeys = 1;
  418.     while((tw->parsedat[i] != 0)&&(i < 35))
  419.     {
  420.         if (tw->parsedat[i] == 255)
  421.         {
  422.             i++; //could be doubled IAC
  423.             if(tw->parsedat[i+1] == TEL_SE)
  424.             {
  425.                 anotherByte = FALSE; //but its not
  426.                 i--;
  427.             }
  428.         }
  429.         if (anotherByte)
  430.             for(j = 0; j < 8; j++)
  431.             {
  432.                 if (tw->parsedat[i] & (j*2))
  433.                 {
  434.                     tw->forwardKeys[tw->numForwardKeys-1] = (i-3)*8 + j;
  435.                     tw->numForwardKeys++;
  436.                 }
  437.             }
  438.         else
  439.             break;
  440.         i++;//next byte
  441.     }        
  442.     for (i = tw->numForwardKeys; i < 32; i++)  //zero the rest of the array
  443.         tw->forwardKeys[i] = 0;
  444. }            
  445.  
  446. void respondSLC(short optionNumber,short *alreadySentSB,struct WindRec *tw, Boolean AWK)
  447. {
  448.     unsigned char stuffToSend[3];
  449.     unsigned char subBeginSeq[4] = {IAC,TEL_SB,N_LINEMODE,L_SLC};
  450.     stuffToSend[0] = optionNumber;
  451.     stuffToSend[1] = tw->slcLevel[optionNumber];
  452.     if (AWK) 
  453.         stuffToSend[1] |= SLC_AWK;    
  454.     stuffToSend[2] = tw->slc[optionNumber];    
  455.     
  456.     if (!(*alreadySentSB))
  457.     {
  458.         *alreadySentSB = TRUE;
  459.         netwrite(tw->port, subBeginSeq, 4);
  460.         opts_debug_print("SENT: IAC SB LINEMODE SLC");
  461.     }
  462.     if (stuffToSend[2] == IAC)
  463.     {
  464.         netwrite(tw->port, stuffToSend,2);
  465.         netwrite(tw->port, subBeginSeq,1); //double the IAC
  466.         netwrite(tw->port, subBeginSeq,1);
  467.     }
  468.     else
  469.         netwrite(tw->port, stuffToSend, 3);
  470. #ifdef OPTS_DEBUG
  471.     if (AWK)
  472.     {
  473.         if ((tw->slcLevel[optionNumber] & (SLC_FLUSHIN | SLC_FLUSHOUT)) == (SLC_FLUSHIN | SLC_FLUSHOUT))
  474.             sprintf(munger,"\t %s %s | AWK | FLUSHIN | FLUSHOUT %d",LMoptions[optionNumber],LMflags[SLC_LEVELBITS & tw->slcLevel[optionNumber]],tw->slc[optionNumber]);
  475.         else if (tw->slcLevel[optionNumber] & SLC_FLUSHIN)
  476.             sprintf(munger,"\t %s %s | AWK | FLUSHIN %d",LMoptions[optionNumber],LMflags[SLC_LEVELBITS & tw->slcLevel[optionNumber]],tw->slc[optionNumber]);
  477.         else if (tw->slcLevel[optionNumber] & SLC_FLUSHOUT)
  478.             sprintf(munger,"\t %s %s | AWK | FLUSHOUT %d",LMoptions[optionNumber],LMflags[SLC_LEVELBITS & tw->slcLevel[optionNumber]],tw->slc[optionNumber]);
  479.         else
  480.             sprintf(munger,"\t %s %s | AWK %d",LMoptions[optionNumber],LMflags[tw->slcLevel[optionNumber]],tw->slc[optionNumber]);
  481.     }
  482.     else
  483.     {
  484.         if ((tw->slcLevel[optionNumber] & (SLC_FLUSHIN | SLC_FLUSHOUT)) == (SLC_FLUSHIN | SLC_FLUSHOUT))
  485.             sprintf(munger,"\t %s %s | AWK | FLUSHIN | FLUSHOUT %d",LMoptions[optionNumber],LMflags[SLC_LEVELBITS & tw->slcLevel[optionNumber]],tw->slc[optionNumber]);
  486.         else if (tw->slcLevel[optionNumber] & SLC_FLUSHIN)
  487.             sprintf(munger,"\t %s %s | FLUSHIN %d",LMoptions[optionNumber],LMflags[SLC_LEVELBITS & tw->slcLevel[optionNumber]],tw->slc[optionNumber]);
  488.         else if (tw->slcLevel[optionNumber] & SLC_FLUSHOUT)
  489.             sprintf(munger,"\t %s %s | FLUSHOUT %d",LMoptions[optionNumber],LMflags[SLC_LEVELBITS & tw->slcLevel[optionNumber]],tw->slc[optionNumber]);
  490.         else
  491.             sprintf(munger,"\t %s %s %d",LMoptions[optionNumber],LMflags[tw->slcLevel[optionNumber]],tw->slc[optionNumber]);
  492.     }
  493.     opts_debug_print(munger);
  494. #endif
  495. }
  496.  
  497. void negotiateSLC(struct WindRec *tw)
  498. {
  499.     short    lmslcflag = 0;
  500.     unsigned char *ourValues = tw->slc;
  501.     unsigned char *ourLevels = tw->slcLevel;
  502.     short i;
  503.     
  504. #ifdef OPTS_DEBUG
  505.     sprintf(munger,"RECV: IAC SB LINEMODE SLC");
  506.     opts_debug_print(munger);
  507.     for(i=2;i <= tw->parseIndex - 3; i+=3) 
  508.     {
  509.         if (tw->parsedat[i] > 30)
  510.             DebugStr("\pAck! Bad option number");
  511.         if(tw->parsedat[i+1] & SLC_AWK)
  512.             sprintf(munger,"     %s %s|AWK %d",LMoptions[tw->parsedat[i]],LMflags[tw->parsedat[i+1] & SLC_LEVELBITS],tw->parsedat[i+2]);
  513.         else
  514.             sprintf(munger,"     %s %s %d",LMoptions[tw->parsedat[i]],LMflags[tw->parsedat[i+1] & SLC_LEVELBITS],tw->parsedat[i+2]);
  515.         opts_debug_print(munger);
  516.     }    
  517.     sprintf(munger,"RECV: IAC SE");
  518.     opts_debug_print(munger);
  519.  
  520. #endif
  521.  
  522.  
  523.     for (i=2, lmslcflag=0; i <= tw->parseIndex - 3; i+=3) 
  524.     {
  525.         short optionNumber = tw->parsedat[i];
  526.         Boolean awked = (tw->parsedat[i+1] & SLC_AWK);
  527.         unsigned char requestedValue = tw->parsedat[i+2];
  528.         unsigned char requestedLevel = tw->parsedat[i+1] & SLC_LEVELBITS;
  529.         Boolean flushin = tw->parsedat[i+1] & SLC_FLUSHIN;
  530.         Boolean flushout = tw->parsedat[i+1] & SLC_FLUSHOUT;
  531.  
  532.         if ((ourValues[optionNumber] != requestedValue)||(ourLevels[optionNumber] != tw->parsedat[i+1])) //if we are sent what we already have, ignore it
  533.         {
  534.             if (requestedLevel == SLC_NOSUPPORT)
  535.             {
  536.                 if (ourLevels[optionNumber] & SLC_LEVELBITS != SLC_NOSUPPORT)
  537.                 {
  538.                      ourValues[optionNumber] = 255;
  539.                     ourLevels[optionNumber] = SLC_NOSUPPORT;//ok, we wont support this
  540.                     if (!awked)
  541.                         respondSLC(optionNumber,&lmslcflag, tw, TRUE);//awk only if he didnt awk
  542. #ifdef OPTS_DEBUG
  543.                     else
  544.                     {
  545.                         sprintf(munger,"\t %s %s %d accepted; no response sent because it was AWKED",
  546.                             LMoptions[optionNumber],LMflags[requestedLevel],requestedValue);                
  547.                         opts_debug_print(munger);
  548.                     }
  549. #endif
  550.                 }
  551. #ifdef OPTS_DEBUG
  552.                 else
  553.                 {
  554.                     sprintf(munger, "\t %s %s %d Ignored because we are already at nosupport",
  555.                         LMoptions[optionNumber],LMflags[requestedLevel],ourValues[optionNumber]);
  556.                     opts_debug_print(munger);
  557.                 }
  558. #endif
  559.             }
  560.             else if (requestedLevel == SLC_DEFAULT)
  561.             {
  562.                 ourValues[optionNumber] = default_slc[optionNumber]; //get our default
  563.                 if (ourValues[optionNumber] == 255)
  564.                     ourLevels[optionNumber] = SLC_NOSUPPORT;
  565.                 else
  566.                     ourLevels[optionNumber] = SLC_VALUE;
  567.                 respondSLC(optionNumber, &lmslcflag, tw, FALSE);    //tell him about our choice
  568.             }
  569.             else if (requestedLevel > ourLevels[optionNumber])
  570.                 respondSLC(optionNumber, &lmslcflag, tw, FALSE);  //keep lower setting
  571.             else
  572.             {
  573.                 ourValues[optionNumber] = requestedValue;
  574.                 ourLevels[optionNumber] = requestedLevel;
  575.                 if (flushin)
  576.                     ourLevels[optionNumber] |= SLC_FLUSHIN;
  577.                 if (flushout)
  578.                     ourLevels[optionNumber] |= SLC_FLUSHOUT;
  579.                 if (!awked)
  580.                     respondSLC(optionNumber, &lmslcflag, tw, TRUE); //agree to his new setting
  581.             }
  582.         }
  583. #ifdef OPTS_DEBUG
  584.         else
  585.         {
  586.             sprintf(munger, "\t %s %s Ignored because %d is already the current value",
  587.                 LMoptions[optionNumber],LMflags[requestedLevel],ourValues[optionNumber]);
  588.             opts_debug_print(munger);
  589.         }
  590. #endif
  591.         
  592.     }//end for on parseindex
  593.     if (lmslcflag) 
  594.     {
  595.         unsigned char toSend[2] = {IAC,TEL_SE};
  596.         netpush(tw->port);
  597.         netwrite(tw->port,toSend,2);
  598.         opts_debug_print("SENT: IAC SE");    
  599.     }
  600. }
  601.             
  602.  
  603. void doLinemode(struct WindRec *tw)
  604. {
  605.     short i;
  606.     unsigned char subBeginSeq[4] = {IAC,TEL_SB,N_LINEMODE,L_SLC};
  607.     unsigned char subEndSeq[2] = {IAC,TEL_SE};
  608.     unsigned char toSend[3];
  609.     
  610.     
  611.     tw->lmodeBits = 0;
  612.     tw->lmode = TRUE;
  613.     tw->litNext = FALSE;
  614.  
  615.     netwrite(tw->port,subBeginSeq,4);
  616.     opts_debug_print("SENT: IAC SB LINEMODE SLC");
  617.     
  618.     for (i=1; i<= SLC_MAX; i++)
  619.     {
  620.         if (tw->slc[i]==255) 
  621.         {
  622.             toSend[0] = i;
  623.             toSend[1] = SLC_NOSUPPORT;
  624.             toSend[2] = 0;
  625. #ifdef OPTS_DEBUG
  626.             sprintf(munger,"     %s NO_SUPPORT 0",LMoptions[i]);
  627. #endif
  628.         }
  629.         else
  630.         {
  631.             toSend[0] = i;
  632.             toSend[1] = SLC_VALUE;
  633.             toSend[2] = tw->slc[i];
  634. #ifdef OPTS_DEBUG
  635.             sprintf(munger,"     %s VALUE %d",LMoptions[i],(short)tw->slc[i]);
  636. #endif
  637.         }
  638.         opts_debug_print(munger);
  639.         netwrite(tw->port,toSend,3);
  640.     }
  641.     opts_debug_print("SENT: IAC SE");
  642.     netpush(tw->port);
  643.     netwrite(tw->port,subEndSeq,2); 
  644.  
  645. static    void    DemangleLineMode(char *s, short mode)
  646. {
  647. #ifdef OPTS_DEBUG
  648.     short     i;
  649.     
  650.     for (i=0; i<5; i++) {
  651.         if (mode & (1 << i))
  652.             strcat(s, LMmodes[i]);
  653.     }
  654. #endif
  655. }
  656.  
  657. void    DemangleLineModeShort(char *s, short mode)
  658. {
  659. #ifdef OPTS_DEBUG
  660.     short     i;
  661.     
  662.     for (i=0; i<5; i++) {
  663.         if (mode & (1 << i))
  664.             strcat(s, LMmodeBits[i]);
  665.         else
  666.             strcat(s," ");
  667.     }
  668. #endif
  669. }
  670.