Exemplo n.º 1
0
void doLinemode(struct WindRec *tw)
{
	short i;
	unsigned char subBeginSeq[4] = {IAC,TEL_SB,N_LINEMODE,L_SLC};
	unsigned char subEndSeq[2] = {IAC,TEL_SE};
	unsigned char toSend[3];
	
	
	tw->lmodeBits = 0;
	tw->lmode = TRUE;
	tw->litNext = FALSE;

	netwrite(tw->port,subBeginSeq,4);
	opts_debug_print("SENT: IAC SB LINEMODE SLC");
	
	for (i=1; i<= SLC_MAX; i++)
	{
		if (tw->slc[i]==255) 
		{
			toSend[0] = i;
			toSend[1] = SLC_NOSUPPORT;
			toSend[2] = 0;
#ifdef OPTS_DEBUG
			sprintf(munger,"     %s NO_SUPPORT 0",LMoptions[i]);
#endif
		}
		else
		{
			toSend[0] = i;
			toSend[1] = SLC_VALUE;
			toSend[2] = tw->slc[i];
#ifdef OPTS_DEBUG
			sprintf(munger,"     %s VALUE %d",LMoptions[i],(short)tw->slc[i]);
#endif
		}
		opts_debug_print(munger);
		netwrite(tw->port,toSend,3);
	}
	opts_debug_print("SENT: IAC SE");
	netpush(tw->port);
	netwrite(tw->port,subEndSeq,2); 
} 
Exemplo n.º 2
0
void process_key(unsigned char ascii,struct WindRec *tw)
{
	if (tw->litNext) {
		//do no processing on next key
		tw->litNext = FALSE;

		kbwrite(tw, &ascii, 1);

		if (tw->echo) {
			if (ascii>31 && ascii <127) {
				/* add these chars to buffer */
				parse(tw, &ascii, 1);
			}
			return;
		}
	}

	if (tw->lmodeBits & 2) {		
		// TRAPSIG mode active
		unsigned char toSend[2] = {IAC,0};
		short whichSignal = 0;
		if (ascii == tw->slc[SLC_IP]) {
			whichSignal = SLC_IP;
			toSend[1] = TEL_IP;
		} else if (ascii == tw->slc[SLC_SUSP]) {
			whichSignal = SLC_SUSP;
			toSend[1] = TEL_SUSP;
		}
// RAB BetterTelnet 2.0b1
// The defaults in parse.h are to send ABORT on ^\ which is usually correct, but
// feel free to hack this (in parse.h, not here) if BRK is better in your configuration.
		else if (ascii == tw->slc[SLC_ABORT])
		{
			whichSignal = SLC_ABORT;
			toSend[1] = TEL_ABORT;
		}
		else if (ascii == tw->slc[SLC_BRK]) // RAB BetterTelnet 2.0b1
		{
			whichSignal = SLC_BRK;
			toSend[1] = TEL_BREAK;
		}
		if (toSend[1]) //if we have a signal to catch
		{
//			if (tw->echo)
//				parse(tw, &ascii, 1); // echo if we should
			tw->kblen=0; //zero out the buffer
			netpush(tw->port);
			netwrite(tw->port,toSend,2); //send IAC whatever
			if (tw->slcLevel[whichSignal] & SLC_FLUSHIN)
			{
				unsigned char dm[2] = {IAC,TEL_DM};
				netpush(tw->port);
				netUrgent();//send next as urgent data
				netwrite(tw->port,dm,2);//send IAC DM
			}
			if (tw->slcLevel[whichSignal] & SLC_FLUSHOUT)
			{
				unsigned char tm[3] = {IAC,TEL_DOTEL,N_TIMING};
				tw->timing = 1;	//tell ourselves to wait for WILL TIMING
				netpush(tw->port);
				netwrite(tw->port,tm,3);//send DO TIMING
			}
			return;
		}
	}
	
	if ((tw->lmodeBits & L_SOFT_TAB)&&(ascii == 0x09)) // SOFT_TAB mode active; expand tab into spaces
	{
		short numSpaces = VSIgetNextTabDistance();
		unsigned char spacechar = ' ';
		while (numSpaces-- > 0) {
			kbwrite(tw, &spacechar, 1);
		}
		if (tw->echo)
			parse(tw, &ascii, 1);
		return;
	}
	


	if (tw->lmodeBits & L_EDIT) //handle editing functions
	{
			

		if (ascii == '\015') //CR
		{ //since we are in edit, send the buffer and CR-LF
			kbflush(tw);
			netpush(tw->port);
			netwrite(tw->port,"\015\012",2);
			if (tw->echo)
				parse(tw,(unsigned char *) "\012\015",2);
			return;
		}
		
		if (ascii == tw->slc[SLC_EC]) //kill the character
		{
			if (tw->echo)
				parse(tw,(unsigned char *) "\010 \010",3);	
			tw->kblen--;
			return;
		}
		else if (ascii == tw->slc[SLC_AO]) //kill the line
		{
			while (tw->kblen >0) 
			{
				if (tw->echo)
					parse(tw,(unsigned char *) "\010 \010",3);
				tw->kblen--;
			}
			return;
		}
		else if (ascii == tw->slc[SLC_EL]) //kill the line
		{
			while (tw->kblen >0) 
			{
				if (tw->echo)
					parse(tw,(unsigned char *) "\010 \010",3);
				tw->kblen--;
			}
			return;
		}
		else if ((ascii == tw->slc[SLC_EOF]) && (tw->lmodeBits & 2))
		{ //push the buffer, send IAC EOF (RAB BetterTelnet 2.0b1 - only under TRAPSIG)
			char eofString[2] = { IAC, TEL_EOF };
			kbflush(tw);
// RAB BetterTelnet 2.0b1 - BAD! BAD! BAD!
// Fix for *BSD (and probably others):
// Putting ^D into Telnet's key buffer after sending an EOF could make it pop up later, so
// hitting some keys (arrows seemed to do the trick) that flushed Telnet's key buffer
// after a cat command which terminated with ^D caused a logout. Yuck.
//			tw->kbbuf[0]=ascii;
//			tw->kblen=1;
			netpush(tw->port);
			netwrite(tw->port,eofString, 2);
			return;
		}
// RAB BetterTelnet 2.0b1
// We don't need to do this down here if we're already handling TRAPSIG mode
// separately. The SUSP (usually ^Z) char is part of TRAPSIG, not EDIT.
//		else if (ascii == tw->slc[SLC_SUSP])
//		{
//			char eofString[2] = { IAC, TEL_SUSP };
//			if (tw->kblen > 0)
//				netwrite(tw->port, tw->kbbuf, tw->kblen);
//			tw->kblen = 0;
//			netpush(tw->port);
//			netwrite(tw->port,eofString, 2);
//			return;
//		}
		else if (ascii == tw->slc[SLC_EW])
		{
			while ((tw->kbbuf[tw->kblen-1] != 0x20)&&(tw->kblen >= 0)) //while its not a space
			{
				if (tw->echo)
					parse(tw,(unsigned char *)"\010 \010",3);
				tw->kblen--;
			}
		}
		else if (ascii == tw->slc[SLC_RP])
		{
			VSredrawLine(tw->vs);
			return;
		}
		else if (ascii == tw->slc[SLC_LNEXT])
		{
			tw->litNext = TRUE;
			return;
		}
		else if (ascii == tw->slc[SLC_XON])
		{
			if (tw->allow_flow) { //remote flow control can turn this off
				tw->enabled = 1; // oops small bug (RAB BetterTelnet 2.0b1)
				changeport(scrn, scrn);
			}
			return;
		}	
		else if (ascii == tw->slc[SLC_XOFF])
		{
			if (tw->allow_flow) { //remote flow control can turn this off
				tw->enabled = 0;
				changeport(scrn, scrn);
			}
			return;
		}
		else if ((ascii == tw->slc[SLC_FORW1])||(ascii == tw->slc[SLC_FORW1]))
		{
			kbflush(tw);
			netwrite(tw->port,&ascii,1);
			return;

		}
		//ok, at this point, we are past all local editing functions.  Now, add the character to the buffer.
		else
		{
			kbwrite(tw, &ascii, 1);
		}

	}
	else if (ascii == '\015') //CR; map this to CR-LF
	{
		unsigned char toSend[2] = {0x0D,0x00};
		netpush(tw->port);
		netwrite(tw->port,toSend,2);
		if (tw->echo)
			parse(tw,(unsigned char *) "\012\015",2);
		return;	
	}
	else //not editing; send it
	{
		netpush(tw->port);
		netwrite( tw->port, &ascii, 1);	// if full send buffer 
	}

	if (tw->echo)	/* Handle local ECHOs */
	{
		if (ascii>31 && ascii <127)	/* add these chars to buffer */
			parse(tw, &ascii, 1);
		else			/* not printable char */
		{
			if (!(tw->lmodeBits & L_LIT_ECHO)) //don't echo if this is set
			{		
				ascii='@'+ascii;
				parse(tw,(unsigned char *) "^",1);
				parse(tw, &ascii, 1);
			}
		}
	}
}
Exemplo n.º 3
0
void	linemode_suboption(struct WindRec *tw)
{
	switch(tw->parsedat[1]) {
		char s[80];

		case L_MODE:	/* change mode */
#ifdef OPTS_DEBUG
			strcpy(s, "RECV: SB LINEMODE MODE => ");
			DemangleLineModeShort(s, tw->parsedat[2]);
			opts_debug_print(s);
#endif
			if (tw->lineAllow) {			// First make sure we allowed linemode in the first place.
				// RFC 1184 says client should ignore MODE negotiations with the MODE_ACK bit set, and should not
				//	generate a response if the negotiated MODE matches the current MODE
				if (!((tw->parsedat[2] & L_MODE_ACK) || ((tw->parsedat[2] & L_MODE_MASK) == tw->lmodeBits))) 
				{
					tw->lmodeBits = tw->parsedat[2];	// Accept the mode
					tw->parsedat[2] |= L_MODE_ACK;  // Set the MODE_ACK bit
 
					sprintf(s,"%c%c%c%c",IAC,TEL_SB,N_LINEMODE,L_MODE);
					netwrite(tw->port,s,4);
					sprintf(s,"%c%c%c",tw->parsedat[2],IAC,TEL_SE);
					netwrite(tw->port,s,3); 
#ifdef OPTS_DEBUG
					opts_debug_print("SENT: IAC SB");
					strcpy(s, "SENT: LM MODE = ");
					DemangleLineModeShort(s, tw->parsedat[2]);
					opts_debug_print(s);
					opts_debug_print("SENT: IAC SE");
#endif
				}
#ifdef OPTS_DEBUG
				else {
					strcpy(s, "LINEMODE MODE = ");
					DemangleLineModeShort(s, tw->parsedat[2]);
					opts_debug_print(s);
					if (tw->parsedat[2] & L_MODE_ACK) 
						opts_debug_print("\tignored because MODE_ACK was set.");
					else
						opts_debug_print("\tIgnored because we are already at that mode.");
					strcpy(s, "Curr Linemode = ");
					DemangleLineModeShort(s, tw->lmodeBits);
					opts_debug_print(s);
				}
#endif
				
			}
			break;
		
		case TEL_DOTEL:	
#ifdef OPTS_DEBUG
			sprintf(munger,"RECV: SB LINEMODE DO %c", tw->parsedat[2]);
			opts_debug_print(munger);
#endif
			tw->forwardMask = TRUE;
			setForwardMask(tw);
			str_lm[3] = TEL_WILLTEL;
			str_lm[4] = L_FORWARDMASK;
			netpush(tw->port);
			netwrite(tw->port, str_lm, sizeof(str_lm));
#ifdef OPTS_DEBUG
			sprintf(munger,"SENT: IAC SB LINEMODE WILL %c IAC SE", tw->parsedat[2]);
			opts_debug_print(munger);
#endif
			break;

		case TEL_DONTTEL:	
#ifdef OPTS_DEBUG
			sprintf(munger,"RECV: SB LINEMODE DO %c", tw->parsedat[2]);
			opts_debug_print(munger);
#endif
			tw->forwardMask = FALSE;
			str_lm[3] = TEL_WONTTEL;
			str_lm[4] = L_FORWARDMASK;
			netpush(tw->port);
			netwrite(tw->port, str_lm, sizeof(str_lm));
#ifdef OPTS_DEBUG
			sprintf(munger,"SENT: IAC SB LINEMODE WONT %c IAC SE", tw->parsedat[2]);
			opts_debug_print(munger);
#endif
			break;

		case L_SLC:		/* set local chars */
			negotiateSLC(tw);
		break;
			
		default:
#ifdef OPTS_DEBUG
		sprintf(munger, "RECV: SB LINEMODE ?? (?? = %c)", tw->parsedat[1]);
		opts_debug_print(munger);
#endif
		break;

	}//switch parsedat
}
Exemplo n.º 4
0
void negotiateSLC(struct WindRec *tw)
{
	short	lmslcflag = 0;
	unsigned char *ourValues = tw->slc;
	unsigned char *ourLevels = tw->slcLevel;
	short i;
	
#ifdef OPTS_DEBUG
	sprintf(munger,"RECV: IAC SB LINEMODE SLC");
	opts_debug_print(munger);
	for(i=2;i <= tw->parseIndex - 3; i+=3) 
	{
		if (tw->parsedat[i] > 30) break; // RAB BetterTelnet 2.0b3
										 // we shouldn't panic on bad data
//		if (tw->parsedat[i] > 30)
//			DebugStr("\pAck! Bad option number");
		if(tw->parsedat[i+1] & SLC_AWK)
			sprintf(munger,"     %s %s|AWK %d",LMoptions[tw->parsedat[i]],LMflags[tw->parsedat[i+1] & SLC_LEVELBITS],tw->parsedat[i+2]);
		else
			sprintf(munger,"     %s %s %d",LMoptions[tw->parsedat[i]],LMflags[tw->parsedat[i+1] & SLC_LEVELBITS],tw->parsedat[i+2]);
		opts_debug_print(munger);
	}	
	sprintf(munger,"RECV: IAC SE");
	opts_debug_print(munger);

#endif


	for (i=2, lmslcflag=0; i <= tw->parseIndex - 3; i+=3) 
	{
		short optionNumber = tw->parsedat[i];
		Boolean awked = (tw->parsedat[i+1] & SLC_AWK);
		unsigned char requestedValue = tw->parsedat[i+2];
		unsigned char requestedLevel = tw->parsedat[i+1] & SLC_LEVELBITS;
		Boolean flushin = tw->parsedat[i+1] & SLC_FLUSHIN;
		Boolean flushout = tw->parsedat[i+1] & SLC_FLUSHOUT;

		if ((ourValues[optionNumber] != requestedValue)||(ourLevels[optionNumber] != tw->parsedat[i+1])) //if we are sent what we already have, ignore it
		{
			if (requestedLevel == SLC_NOSUPPORT)
			{
				if (ourLevels[optionNumber] & SLC_LEVELBITS != SLC_NOSUPPORT)
				{
				 	ourValues[optionNumber] = 255;
					ourLevels[optionNumber] = SLC_NOSUPPORT;//ok, we wont support this
					if (!awked)
						respondSLC(optionNumber,&lmslcflag, tw, TRUE);//awk only if he didnt awk
#ifdef OPTS_DEBUG
					else
					{
						sprintf(munger,"\t %s %s %d accepted; no response sent because it was AWKED",
							LMoptions[optionNumber],LMflags[requestedLevel],requestedValue);				
						opts_debug_print(munger);
					}
#endif
				}
#ifdef OPTS_DEBUG
				else
				{
					sprintf(munger, "\t %s %s %d Ignored because we are already at nosupport",
						LMoptions[optionNumber],LMflags[requestedLevel],ourValues[optionNumber]);
					opts_debug_print(munger);
				}
#endif
			}
			else if (requestedLevel == SLC_DEFAULT)
			{
				ourValues[optionNumber] = default_slc[optionNumber]; //get our default
				if (ourValues[optionNumber] == 255)
					ourLevels[optionNumber] = SLC_NOSUPPORT;
				else
					ourLevels[optionNumber] = SLC_VALUE;
				respondSLC(optionNumber, &lmslcflag, tw, FALSE);	//tell him about our choice
			}
			else if (requestedLevel > ourLevels[optionNumber])
				respondSLC(optionNumber, &lmslcflag, tw, FALSE);  //keep lower setting
			else
			{
				ourValues[optionNumber] = requestedValue;
				ourLevels[optionNumber] = requestedLevel;
				if (flushin)
					ourLevels[optionNumber] |= SLC_FLUSHIN;
				if (flushout)
					ourLevels[optionNumber] |= SLC_FLUSHOUT;
				if (!awked)
					respondSLC(optionNumber, &lmslcflag, tw, TRUE); //agree to his new setting
			}
		}
#ifdef OPTS_DEBUG
		else
		{
			sprintf(munger, "\t %s %s Ignored because %d is already the current value",
				LMoptions[optionNumber],LMflags[requestedLevel],ourValues[optionNumber]);
			opts_debug_print(munger);
		}
#endif
		
	}//end for on parseindex
	if (lmslcflag) 
	{
		unsigned char toSend[2] = {IAC,TEL_SE};
		netpush(tw->port);
		netwrite(tw->port,toSend,2);
		opts_debug_print("SENT: IAC SE");	
	}
}
Exemplo n.º 5
0
/*
 *  parse
 *   Do the telnet negotiation parsing.
 *
 *   look at the string which has just come in from outside and
 *   check for special sequences that we are interested in.
 *
 *   Tries to pass through routine strings immediately, waiting for special
 *   characters ESC and IAC to change modes.
 */
void
parse(CONNECTION *con,unsigned char *st,int cnt)
{
  static int sub_pos; /* the position we are in the subnegotiation parsing */
  static int end_sub; /* index of last byte in parsedat in a subnegotiation */
  unsigned char *mark, *orig;
  char buf[256];
  kstream ks;
        
  ks = con->ks;
   
#ifdef PRINT_EVERYTHING
  hexdump("Options to process:", st, cnt);
#endif /* PRINT_EVERYTHING */
      
  orig = st;                /* remember beginning point */
  mark = st + cnt;            /* set to end of input string */

#ifdef HUH
  netpush(tw->pnum);
#endif

  /*
   *  traverse string, looking for any special characters which indicate that
   *  we need to change modes.
   */
  while(st < mark) {

    while(con->telstate != STNORM && st < mark) {   
      switch(con->telstate) {
      case IACFOUND:              /* telnet option negotiation */
	if(*st == IAC) {          /* real data=255 */
	  st++;                   /* real 255 will get sent */
	  con->telstate = STNORM;
	  break;
	} /* end if */

	if(*st > 239) {
	  con->telstate = *st++; /* by what the option is */
	  break;
	} /* end if */

#ifdef NEGOTIATEDEBUG
	wsprintf(buf, "\r\n strange telnet option");
	OutputDebugString(buf);
#endif                    
	orig=++st;
	con->telstate=STNORM;
	break;

      case EL:     /* received a telnet erase line command */
      case EC:     /* received a telnet erase character command */
      case AYT:    /* received a telnet Are-You-There command */
      case AO:     /* received a telnet Abort Output command */
      case IP:     /* received a telnet Interrupt Process command */
      case BREAK:  /* received a telnet Break command */
      case DM:     /* received a telnet Data Mark command */
      case NOP:    /* received a telnet No Operation command */
      case SE:     /* received a telnet Subnegotiation End command */
      case ABORT:  /* received a telnet Abort Process command */
      case SUSP:   /* received a telnet Suspend Process command */
      case xEOF:   /* received a telnet EOF command */
#ifdef NEGOTIATEDEBUG
	wsprintf(buf,"RECV: %s\r\n",
		 telstates[con->telstate-TELCMD_FIRST]);
	OutputDebugString(buf);
#endif
	con->telstate=STNORM;
	orig=++st;
	break;

      case GA:       /* telnet go ahead option*/
#ifdef NEGOTIATEDEBUG
	wsprintf(buf,"RECV: %s\r\n",
		 telstates[con->telstate-TELCMD_FIRST]);
	OutputDebugString(buf);
#endif
	con->telstate=STNORM;
	orig=++st;
	break;

      case DO:     /* received a telnet DO negotiation */
#ifdef NEGOTIATEDEBUG
	wsprintf(buf,"RECV: %s %s\r\n",
		 telstates[con->telstate-TELCMD_FIRST],teloptions[*st]);
	OutputDebugString(buf);
#endif
	switch(*st) {
#ifdef NOT
	case TELOPT_BINARY:       /* DO: binary transmission */
	  if(!tw->ibinary) { /* binary */
	    if(!tw->iwantbinary) { 
	      netprintf(tw->pnum,"%c%c%c",
			IAC,WILL,BINARY);
	      if(tw->condebug>0)
		tprintf(cv,"SEND: %s %s\r\n",
			telstates[WILL - TELCMD_FIRST],
			teloptions[BINARY]);
	    } /* end if */
	    else
	      tw->iwantbinary=0;  /* turn off this now */
	    tw->ibinary=1;
	  } /* end if */
	  else {
	    if(tw->condebug>0)
	      tprintf(cv,"NO REPLY NEEDED: %s %s\r\n",
		      telstates[WILL - TELCMD_FIRST],
		      teloptions[BINARY]);
	  } /* end else */
	  break;
#endif

	case TELOPT_SGA:       /* DO: Suppress go-ahead */
	  if(!con->igoahead) { /* suppress go-ahead */
	    wsprintf(buf,"%c%c%c",IAC,WILL,TELOPT_SGA);
	    TelnetSend(ks,buf,lstrlen(buf),0);
#ifdef NEGOTIATEDEBUG
	    wsprintf(strTmp,"SEND: %s %s\r\n",
		     telstates[WILL - TELCMD_FIRST],
		     teloptions[TELOPT_SGA]);
	    OutputDebugString(strTmp);
	    OutputDebugString("igoahead");
#endif
	    con->igoahead=1;
	  } /* end if */
	  else {
#ifdef NEGOTIATEDEBUG
	    wsprintf(strTmp,
		     "NO REPLY NEEDED: %s %s\r\n",
		     telstates[WILL - TELCMD_FIRST],
		     teloptions[TELOPT_SGA]);
	    OutputDebugString(strTmp);
#endif
	  } /* end else */
	  break;

	case TELOPT_TTYPE:      /* DO: terminal type negotiation */
	  if(!con->termsent) {
	    con->termsent=TRUE;
	    wsprintf(buf,"%c%c%c",IAC,WILL,TELOPT_TTYPE);
	    TelnetSend(ks,buf,lstrlen(buf),0);
#ifdef NEGOTIATEDEBUG
	    wsprintf(strTmp,"SEND: %s %s\r\n",
		     telstates[WILL - TELCMD_FIRST],
		     teloptions[TELOPT_TTYPE]);
	    OutputDebugString(strTmp);
#endif
	  } /* end if */
	  else {
#ifdef NEGOTIATEDEBUG
	    wsprintf(strTmp,"NO REPLY NEEDED: %s %s\r\n",
		     telstates[WILL - TELCMD_FIRST],
		     teloptions[TELOPT_TTYPE]);
	    OutputDebugString(strTmp);
#endif
	  } /* end else */
	  break;

#ifdef LATER
	case TELOPT_LINEMODE:      /* DO: linemode negotiation */
	  tw->lmflag=1;   /* set the linemode flag */
	  netprintf(tw->pnum,"%c%c%c",IAC,WILL,TELOPT_LINEMODE);
	  /*
	   * Tell the other side to send us
	   * its default character set
	   */
	  netprintf(tw->pnum,"%c%c%c%c",
		    IAC,SB,TELOPT_LINEMODE,SLC,0,SLC_DEFAULT,0,IAC,SE);  
	  if(tw->condebug>0) {
	    tprintf(cv,"SEND: %s %s\r\n",
		    telstates[WILL - TELCMD_FIRST],
		    teloptions[TELOPT_LINEMODE]);
	    tprintf(cv,
		    "SEND: SB LINEMODE SLC 0 SLC_DEFAULT 0 IAC SE\r\n");
	  } /* end if */
	  break;
#endif
	case TELOPT_NAWS:      /* DO: Negotiate About Window Size */
	  con->bResizeable=TRUE;
	  send_naws(con);
	  break;

	case TELOPT_AUTHENTICATION: /* DO: Authentication requested */
	  wsprintf(buf, "%c%c%c", IAC, WILL, TELOPT_AUTHENTICATION);
	  TelnetSend(ks, buf, lstrlen(buf), 0);
#ifdef NEGOTIATEDEBUG
	  wsprintf(strTmp,"SEND: %s %s\r\n",
		   telstates[WILL - TELCMD_FIRST],
		   teloptions[TELOPT_AUTHENTICATION]);
	  OutputDebugString(strTmp);
#endif
	  break;

#ifdef ENCRYPTION
	case TELOPT_ENCRYPT: /* DO: Remote is willing to receive encrypted */
	  wsprintf(buf, "%c%c%c", IAC,
		   (encrypt_flag ? WILL : WONT), TELOPT_ENCRYPT);
	  TelnetSend(ks, buf, lstrlen(buf), 0);
#ifdef NEGOTIATEDEBUG
	  wsprintf(strTmp,"SEND: %s %s\r\n",
		   telstates[(encrypt_flag ? WILL : WONT)
			    - TELCMD_FIRST],
		   teloptions[TELOPT_ENCRYPT]);
	  OutputDebugString(strTmp);
#endif
	  break;
#endif /* ENCRYPTION */

	default:        /* DO: */
	  wsprintf(buf, "%c%c%c", IAC, WONT, *st);
	  TelnetSend(ks, buf, lstrlen(buf), 0);
#ifdef NEGOTIATEDEBUG
	  wsprintf(strTmp,"SEND: %s %s\r\n",
		   telstates[WONT - TELCMD_FIRST], teloptions[*st]);
	  OutputDebugString(strTmp);
#endif
	  break;

	} /* end switch */
	con->telstate = STNORM;
	orig = ++st;
	break;

      case DONT:       /* Received a telnet DONT option */
	switch (*st) {
	case TELOPT_NAWS:
	  con->bResizeable=FALSE;
#ifdef NEGOTIATEDEBUG
	  wsprintf(strTmp,"RECV: %s %s\r\n",
		   telstates[con->telstate-TELCMD_FIRST],teloptions[*st]);
	  OutputDebugString(strTmp);
#endif
	  break;

#ifdef NOT
	case BINARY: /* DONT: check for binary neg. */
	  if(tw->ibinary) {   /* binary */
	    if(!tw->iwantbinary) { 
	      netprintf(tw->pnum,"%c%c%c",IAC,WONT,BINARY);
	      if(tw->condebug>0)
		tprintf(cv,"SEND: %s %s\r\n",
			telstates[WONT-TELCMD_FIRST],
			teloptions[BINARY]);
	    } /* end if */
	    else
	      tw->iwantbinary=0;  /* turn off this now */
	    tw->ibinary=0;
	    tw->mapoutput=0;    /* turn output mapping off */
	  } /* end if */
#ifdef NEGOTIATEDEBUG
	  wsprintf(strTmp,"NO REPLY NEEDED: %s %s\r\n",
		   telstates[WONT-TELCMD_FIRST],
		   teloptions[BINARY]);
	  OutputDebugString(strTmp);
#endif
	  break;
#endif
#ifdef ENCRYPTION
	case ENCRYPTION:
	  break;
#endif
	}
	
	/* all these just fall through to here... */

	con->telstate=STNORM;
	orig=++st;
	break;
	
      case WILL:       /* received a telnet WILL option */
#ifdef NEGOTIATEDEBUG
	wsprintf(strTmp,"RECV: %s %s\r\n",
		 telstates[con->telstate-TELCMD_FIRST],
		 teloptions[*st]);
	OutputDebugString(strTmp);
#endif
	switch(*st) {
#ifdef NOT
	case TELOPT_BINARY:            /* WILL: binary */
	  if(!tw->ubinary) {   /* binary */
	    if(!tw->uwantbinary) {
	      netprintf(tw->pnum,"%c%c%c",
			IAC,DO,TELOPT_BINARY);
	      if(tw->condebug>0)
		tprintf(cv,"SEND: %s %s\r\n",
			telstates[DO - TELCMD_FIRST],
			teloptions[TELOPT_BINARY]);
	    } /* end if */
	    else
	      tw->uwantbinary=0;  /* turn off this now */
	    tw->ubinary=1;
	  } /* end if */
	  else {
	    if(tw->condebug>0)    
	      tprintf(cv,"NO REPLY NEEDED: %s %s\r\n",
		      telstates[DO - TELCMD_FIRST],
		      teloptions[TELOPT_BINARY]);
	  } /* end else */
	  break;
#endif

	case TELOPT_SGA:               /* WILL: suppress go-ahead */
	  if(!con->ugoahead) {
	    con->ugoahead=1;
	    wsprintf(buf,"%c%c%c",IAC,DO,TELOPT_SGA); /* ack */
	    TelnetSend(ks,buf,lstrlen(buf),0);
#ifdef NEGOTIATEDEBUG
	    wsprintf(strTmp,"SEND: %s %s\r\n",
		     telstates[DO - TELCMD_FIRST],
		     teloptions[TELOPT_SGA]);
	    OutputDebugString(strTmp);
#endif
	  } /* end if */
	  break;

	case TELOPT_ECHO:              /* WILL: echo */
	  if(!con->echo) {
	    con->echo = 1;
	    wsprintf(buf, "%c%c%c", IAC, DO, TELOPT_ECHO); /* ack */
	    TelnetSend(ks, buf, lstrlen(buf), 0);
#ifdef NEGOTIATEDEBUG
	    wsprintf(strTmp,"SEND: %s %s\r\n",
		     telstates[DO - TELCMD_FIRST],
		     teloptions[TELOPT_ECHO]);
	    OutputDebugString(strTmp);
#endif
	  } /* end if */
	  break;

	case TELOPT_TM:        /* WILL: Timing mark */
	  con->timing=0;
	  break;
#ifdef ENCRYPTION
	case TELOPT_ENCRYPT:   /* WILL: decrypt our input */
	  wsprintf(buf, "%c%c%c", IAC,
		   (encrypt_flag ? DO : DONT), TELOPT_ENCRYPT);
	  TelnetSend(ks, buf, lstrlen(buf), 0);
	  if (encrypt_flag)
	    encrypt_send_support();

#ifdef NEGOTIATEDEBUG
	  wsprintf(strTmp,"SEND: %s %s\r\n",
		   telstates[(encrypt_flag ? DO : DONT) - TELCMD_FIRST],
		   teloptions[TELOPT_ENCRYPT]);
	  OutputDebugString(strTmp);
#endif
	  break;
#endif
	  
	default:
	  wsprintf(buf,"%c%c%c",IAC,DONT,*st);
	  TelnetSend(ks,buf,lstrlen(buf),0);
#ifdef NEGOTIATEDEBUG
	  wsprintf(strTmp,"SEND: %s %s\r\n",
		   telstates[DONT-TELCMD_FIRST],teloptions[*st]);
	  OutputDebugString(strTmp);
#endif
	  break;
	} /* end switch */
	con->telstate=STNORM;
	orig=++st;
	break;

      case WONT:       /* Received a telnet WONT option */
#ifdef NEGOTIATEDEBUG
	wsprintf(strTmp,"RECV: %s %s\r\n",
		 telstates[con->telstate-TELCMD_FIRST],teloptions[*st]);
	OutputDebugString((LPSTR)strTmp);
#endif
	con->telstate=STNORM;
	switch(*st++) {     /* which option? */
#ifdef NOT
	case BINARY:            /* WONT: binary */
	  if(tw->ubinary) {  /* binary */
	    if(!tw->uwantbinary) {
	      netprintf(tw->pnum,"%c%c%c",
			IAC,DONT,BINARY);
	      if(tw->condebug>0)
		tprintf(cv,"SEND: %s %s\r\n",
			telstates[DONT-TELCMD_FIRST],
			teloptions[BINARY]);
	    } /* end if */
	    else
	      tw->uwantbinary=0;  /* turn off this now */
	    tw->ubinary=0;
	    tw->mapoutput=0; /* turn output mapping off */
	  } /* end if */
	  else {
	    if(tw->condebug>0) 
	      tprintf(cv,"NO REPLY NEEDED: %s %s\r\n",
		      telstates[DONT-TELCMD_FIRST],
		      teloptions[BINARY]);
	  } /* end else */
	  break;

#endif
	case TELOPT_ECHO:              /* WONT: echo */
	  if(con->echo) {
	    con->echo=0;
	    wsprintf(buf,"%c%c%c",IAC,DONT,TELOPT_ECHO);
	    TelnetSend(ks,buf,lstrlen(buf),0);
#ifdef NEGOTIATEDEBUG
	    wsprintf(strTmp,"SEND: %s %s\r\n",
		     telstates[DONT-TELCMD_FIRST],
		     teloptions[TELOPT_ECHO]);
	    OutputDebugString(strTmp);
	    OutputDebugString("Other side won't echo!");
#endif
	  } /* end if */
	  break;

	case TELOPT_TM:    /* WONT: Telnet timing mark option */
	  con->timing=0;
	  break;

#ifdef ENCRYPTION
	case TELOPT_ENCRYPT:   /* WONT: don't encrypt our input */
	  break;
#endif
	  
	default:
	  break;
	} /* end switch */
	orig=st;
	break;

      case SB:        /* telnet sub-options negotiation */
	con->telstate=NEGOTIATE;
	orig=st;
	end_sub=0;
	sub_pos=con->substate=0;     /* Defined for each */
#ifdef OLD_WAY
	break;
#endif

      case NEGOTIATE:
        /* until we change sub-negotiation states, accumulate bytes */
	if(con->substate==0) { 
	  if(*st==IAC) {  /* check if we found an IAC byte */
	    if(*(st+1)==IAC) {  /* skip over double IAC's */
	      st++;
	      parsedat[sub_pos++]=*st++;
	    } /* end if */
	    else {
	      end_sub=sub_pos;
	      con->substate=*st++;
	    } /* end else */
	  } /* end if */
	  else     /* otherwise, just stash the byte */
	    parsedat[sub_pos++]=*st++;
	} /* end if */
	else {
	  con->substate=*st++;
	  /* check if we've really ended the sub-negotiations */
	  if(con->substate==SE)    
	    parse_subnegotiat(ks,end_sub);

	  orig=st;
	  /*
	   * XXX hack to decrypt the rest of the buffer
	   */
	  if (encrypt_flag == 2) {
	    decrypt_ks_hack(orig, mark - orig);
	    encrypt_flag = 1;
	  }

	  con->telstate=STNORM;
	} /* end else */
	break;

      default:
	con->telstate=STNORM;
	break;
      } /* end switch */
    } /* end while */

    /*
     * quick scan of the remaining string, skip chars while they are
     * uninteresting
     */
    if(con->telstate==STNORM && st<mark) {
      /*
       *  skip along as fast as possible until an interesting character is found
       */
      while(st<mark && *st!=27 && *st!=IAC) {
#if 0
	if(!tw->ubinary)
	  *st&=127;                 /* mask off high bit */
#endif
	st++;
      } /* end while */
#if 0
      if(!tw->timing) 
	parsewrite(tw,orig,st-orig);
#endif
      orig=st;                /* forget what we have sent already */
      if(st<mark)
	switch(*st) {
	case IAC:           /* telnet IAC */
	  con->telstate=IACFOUND;
	  st++;
	  break;

	default:
#ifdef NEGOTIATEDEBUG
	  wsprintf(buf," strange char>128 0x%x\r\n", *st);
	  OutputDebugString(buf);
#endif
	  st++;
	  break;
	} /* end switch */
    } /* end if */
  } /* end while */
}   /* end parse() */