Exemplo n.º 1
0
Arquivo: clc.c Projeto: elanthis/clc
/* redraw all windows */
static void redraw_display (void) {
	/* get size */
	struct winsize ws;
	if (ioctl(0, TIOCGWINSZ, &ws))
		return;

	/* resize */
	resizeterm(ws.ws_row, ws.ws_col);
	mvwin(win_input, LINES-1, 0);
	wresize(win_input, 1, COLS);
	mvwin(win_banner, LINES-2, 0);
	wresize(win_banner, 1, COLS);
	wresize(win_main, LINES-2, COLS);

	/* update */
	paint_banner();

	/* update size */
	if (running)
		send_naws();

	/* input display */
	editbuf_display();

	/* refresh */
	wnoutrefresh(win_main);
	wnoutrefresh(win_banner);
	wnoutrefresh(win_input);
	doupdate();
}
Exemplo n.º 2
0
Arquivo: clc.c Projeto: elanthis/clc
/* telnet event handler */
static void telnet_event (telnet_t* telnet, telnet_event_t* ev, void* ud) {
	switch (ev->type) {
	case TELNET_EV_DATA:
		on_text_ansi(ev->data.buffer, ev->data.size);
		break;
	case TELNET_EV_SEND:
		do_send(ev->data.buffer, ev->data.size);
		break;
	case TELNET_EV_WILL:
		if (ev->neg.telopt == TELNET_TELOPT_ECHO)
			terminal.flags &= ~TERM_FLAG_ECHO;
		else if (ev->neg.telopt == TELNET_TELOPT_ZMP) {
			terminal.flags |= TERM_FLAG_ZMP;
			telnet_send_zmpv(telnet, "zmp.ident", "clc", "n/a", "simple command-line client", NULL);
		}
		break;
	case TELNET_EV_WONT:
		if (ev->neg.telopt == TELNET_TELOPT_ECHO)
			terminal.flags |= TERM_FLAG_ECHO;
		break;
	case TELNET_EV_DO:
		if (ev->neg.telopt == TELNET_TELOPT_NAWS) {
			terminal.flags |= TERM_FLAG_NAWS;
			send_naws();
		}
		break;
	case TELNET_EV_ZMP:
		do_zmp(ev->zmp.argc, ev->zmp.argv);
		break;
	case TELNET_EV_WARNING:
		wattron(win_main, COLOR_PAIR(COLOR_RED));
		on_text_plain("\nWARNING:", 8);
		on_text_plain(ev->error.msg, strlen(ev->error.msg));
		on_text_plain("\n", 1);
		wattron(win_main, COLOR_PAIR(terminal.color));
		break;
	case TELNET_EV_ERROR:
		endwin();
		fprintf(stderr, "TELNET error: %s\n", ev->error.msg);
		exit(1);
	default:
		break;
	}
}
Exemplo n.º 3
0
/*
 * FUNCTION: MainWndProc(HWND, UINT, WPARAM, LPARAM)
 *
 * PURPOSE:  Processes messages
 *
 * MESSAGES:
 *
 * WM_COMMAND    - application menu (About dialog box)
 * WM_DESTROY    - destroy window
 */
LRESULT CALLBACK
MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
  HGLOBAL hBuffer;
  LPSTR lpBuffer; 
  int iEvent, cnt, ret;
  char *tmpCommaLoc;
  struct sockaddr_in remote_addr;
  struct hostent *remote_host;
	
  switch (message) {
  case WM_MYSCREENCHANGEBKSP:
    if (!con)
      break;
    con->backspace = wParam;
    if (con->backspace == VK_BACK) {
      con->ctrl_backspace = 0x7f;
      WritePrivateProfileString(INI_TELNET, INI_BACKSPACE, 
				INI_BACKSPACE_BS, TELNET_INI);
    }
    else {
      con->ctrl_backspace = VK_BACK;
      WritePrivateProfileString(INI_TELNET, INI_BACKSPACE, 
				INI_BACKSPACE_DEL, TELNET_INI);
    }
    GetPrivateProfileString(INI_HOSTS, INI_HOST "0", "", buf, 128, TELNET_INI);
    tmpCommaLoc = strchr(buf, ',');
    if (tmpCommaLoc == NULL) {
      strcat (buf, ",");
      tmpCommaLoc = strchr(buf, ',');
    }
    if (tmpCommaLoc) {
      tmpCommaLoc++;
      if (con->backspace == VK_BACK)
	strcpy(tmpCommaLoc, INI_HOST_BS);
      else
	strcpy(tmpCommaLoc, INI_HOST_DEL);
    }
    WritePrivateProfileString(INI_HOSTS, INI_HOST "0", buf, TELNET_INI);
    break;

  case WM_MYSCREENCHAR:
    {
      unsigned char c;

      if (!con)
	break;
      if (wParam == VK_BACK)
	c = con->backspace;
      else if (wParam == 0x7f)
	c = con->ctrl_backspace;
      else if (wParam == VK_SPACE && GetKeyState(VK_CONTROL) < 0)
	c = 0;
      else
	c = wParam;
      TelnetSend(con->ks, &c, 1, 0);
    }
  break;

  case WM_MYCURSORKEY:
    /* Acts as a send through: buffer is lParam and length in wParam */
    if (!con)
      break;
    memcpy(buf, (char *)lParam, wParam);
    TelnetSend (con->ks, buf, wParam, 0);
    break;

  case WM_MYSCREENBLOCK:
    if (!con)
      break;
    hBuffer = (HGLOBAL) wParam;
    lpBuffer = GlobalLock(hBuffer);
    TelnetSend(con->ks, lpBuffer, lstrlen(lpBuffer), 0);
    GlobalUnlock(hBuffer);
    break;

  case WM_MYSCREENCLOSE:
#if 0
    if (con)
    {
	kstream_destroy(con->ks);
	con->ks = NULL;
    }
#endif
    DestroyWindow(hWnd);
    break;        

  case WM_QUERYOPEN:
    return(0);
    break;

  case WM_DESTROY:          /* message: window being destroyed */
    if (con)
    {
	kstream_destroy(con->ks);
	free(con);
	WSACleanup();
    }
    PostQuitMessage(0);
    break;

  case WM_NETWORKEVENT: 
    iEvent = WSAGETSELECTEVENT(lParam);

    switch (iEvent) {    	

    case FD_READ:
      if (con == NULL)
	break;
      cnt = kstream_read(con->ks, buf, 1500);
      buf[cnt] = 0;
      parse((CONNECTION *)con, (unsigned char *)buf, cnt);
      ScreenEm(buf, cnt, con->pScreen);
      break;

    case FD_CLOSE:
      kstream_destroy(con->ks);
      free(con);
      con = NULL;
      WSACleanup();
      PostQuitMessage(0);
      break;

    case FD_CONNECT:
      ret = WSAGETSELECTERROR(lParam);
      if (ret) {
	wsprintf(buf, "Error %d on Connect", ret);
	MessageBox(NULL, buf, NULL, MB_OK | MB_ICONEXCLAMATION);
	kstream_destroy(con->ks);
	free(con);
	WSACleanup();
	PostQuitMessage(0);
	break;
      }
      start_negotiation(con->ks);
      break;		
    }

    break;  	        

  case WM_HOSTNAMEFOUND:
    ret = WSAGETASYNCERROR(lParam);
    if (ret) {
      wsprintf(buf, "Error %d on GetHostbyName", ret);
      MessageBox(NULL, buf, NULL, MB_OK | MB_ICONEXCLAMATION);
      kstream_destroy(con->ks);
      free(con);
      WSACleanup();
      PostQuitMessage(0);
      break;
    }

    remote_host = (struct hostent *)hostdata;
    remote_addr.sin_family = AF_INET;
    memcpy(&(remote_addr.sin_addr), &(remote_host->h_addr[0]), 4);
    remote_addr.sin_port = htons(port_no);

    connect(con->socket, (struct sockaddr *)&remote_addr, sizeof(struct sockaddr));
    break;

  case WM_MYSCREENSIZE:
    con->width = LOWORD(lParam);		/* width in characters */
    con->height = HIWORD(lParam);		/* height in characters */
    if (con->bResizeable && con->ks)
      send_naws(con);
    wsprintf(buf, "%d", con->height);
    WritePrivateProfileString(INI_TELNET, INI_HEIGHT, buf, TELNET_INI);
    wsprintf(buf, "%d", con->width);
    WritePrivateProfileString(INI_TELNET, INI_WIDTH, buf, TELNET_INI);
    break;
		
  default:              		/* Passes it on if unproccessed */
    return(DefWindowProc(hWnd, message, wParam, lParam));
  }
  return (0);
}
Exemplo n.º 4
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() */