#include <stdio.h>

/*
 * Intended to be run at checkline < /dev/ttys0 > /dev/ttys0
 * (assumeing ttys0 is your modem).
 *
 * Gives a list of all the characters that get eaten..

 wriiten by micheal o'reilly
 seriously bashed about by by quarters
 jefftep@cs.utexas.edu
 jeff grills

 lots of code to handle spurious shit
 all packets are \n terminated

 both clients send handshake
 if a client receives a handshake, it sends an handshake ack, and drops into processing
 if a client receives a a handshake ack, it drops into processing

 while not all done
 {
 
 // send the textual int value in a packe 
 local: int_header int_value_of_char int_trailer
 remote: int_ack
 
 // send the char, and an xon incase of flow control 
 local: char_header char char_trailer xon char_trailer_xon
 
 // says wether it got the char that the int says it would be
 remote: ack_header {ack,nak} ack_trailer
 
 // sends the char in the same format to see if it goes the other way
 remote: reply_header char reply_trailer xon reply_trailer_xon
 
 }
 */

#define START 0
#define STOP  256

#define HANDSHAKE		'A'
#define HANDSHAKE_ACK		'B'
#define START_INT		'C'
#define STOP_INT		'D'
#define START_CHAR		'E'
#define STOP_CHAR		'F'
#define STOP_CHAR_XON		'G'
#define START_ACK		'H'
#define STOP_ACK		'I'
#define START_REPLY		'J'
#define STOP_REPLY		'K'
#define STOP_REPLY_XON		'L'
#define INT_ACK			'M'
#define ACK                     '1'
#define NAK                     '0'
#define XON			'\021'

char buff[200];

void debug(void)
{
  char *s;
  s = buff;
  fprintf(stderr, "\tpacket:");
  while (*s)
  {
    fprintf(stderr, " %d", (int) *(s++));
  }
  fprintf(stderr, "\n");
}

void main(void)
{
  int i, j, valid;
  char c;

  fprintf(stderr, "Handshaking\n");

  printf("\n%c\n", HANDSHAKE);
  
  i = 0;
  while ( ! i )
  {
    gets(buff);
    if ( ( buff[0] == HANDSHAKE ) && ( buff[1] == '\0' ) )
    {
      i = 1;
      printf("\n%c\n", HANDSHAKE_ACK);
    }
    if ( ( buff[0] == HANDSHAKE_ACK ) && ( buff[1] == '\0' ) )
      i = 1;
  }

  fprintf(stderr, "Handshaking sucessful\n");

  /* test all the chars */
  for (i = START, c=(char)START; i < STOP; i++, c++ )
  {
    if ( c == '\n' )
    {
      fprintf(stderr, "10 Known to be valid,Skipping\n");
      continue;
    }

    fprintf(stderr, "Trying char %d\n", i );

    /* send the integer rep */ 
    printf("%c%d%c\n", START_INT, i, STOP_INT );

    valid = 0;
    while ( ! valid )
    {
      gets(buff);
      if ( ( buff[1] != INT_ACK ) && ( buff[1] == '\0' ) )
	valid = 1;
      else
      {
	fprintf(stderr, "\texpected a sync packet");
	debug();
      }
    }


    /* send the char packet */
    printf("%c%c%c%c%c\n", START_CHAR, c, STOP_CHAR, XON, STOP_CHAR_XON );

    j=strlen(gets(buff));

    /* munch a stray ack from the handshake */
    if ( (i == 0) && ( buff[0] == HANDSHAKE_ACK ) && ( buff[1] == '\0' ) )
    {
      fprintf (stderr, "\tmunched stray ack\n");
      j=strlen(gets(buff));
    }
      
    if ( j != 3 )
    {
      fprintf(stderr, "\tfatal - ACK packet length incorrect\n");
      debug();
    }
    else
      if ( buff[0] != START_ACK )
      {
	fprintf(stderr, "\tfatal - ACK packet start header incorrect\n");
	debug();
      }
      else
	if ( buff[2] != STOP_ACK )
	{
	  fprintf(stderr, "\tfatal - ACK packet end header incorrect\n");
	  debug();
	}
	else
	  if ( buff[1] == NAK )
	  {
	    fprintf (stderr, "\tescape %d\n", i);
	    debug();
	  }
	  else
	    if ( buff[1] == ACK )
	      fprintf (stderr, "\tsent okay\n");
	    else
	    {
	      fprintf (stderr, "\tfatal - unknown ACK response");
	      debug();
	    }

    /* get the reply packet */	
    j = strlen(gets(buff));
    
    if ( buff[0] != START_REPLY )
    {
      fprintf(stderr, "\tescape %d - REPLY packet start header incorrect\n", i);
      debug();
    }
    else
       if ( buff[j-1] != STOP_REPLY_XON )
       {
	 fprintf(stderr, "\tescape %d - REPLY packet end header incorrect\n", i);
	 debug();
       }
      else
	if ( buff[1] != c )
	{
	  fprintf(stderr, "\tescape %d\n", i );
	  debug();
	}
	else
	  fprintf(stderr, "\treceived okay\n" );
  }
}

