#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <poll.h>

void dowrite(char *s, int len)
{
  int i = 0;
  while (i < len)
  {
    int cs = ((len-i) > 1) ? 1 : (len-i);
    
    write(1, s+i, cs);
    i += cs;
  }
}

int waitchar(int timeout)
{
  struct pollfd pfd;
  
  pfd.fd = 0;
  pfd.events = POLLIN;
  return poll(&pfd, 1, timeout) == 1;
}

int expect(char *s, int len)
{
  int i;
  char c;
  for (i=0; i < len; i++)
  {
    if (waitchar(1000) == 0)
    {
      fprintf(stderr, "Timeout reached in expect (expected %c)\n", s[i]);
      return 1;
    }
    while (read(0, &c, 1) == 0)
      fprintf(stderr, "Short read...\n");
    if (c != s[i])
    {
      fprintf(stderr, "Expect failed: expected %d, got %d (pos %d)\n", s[i], c, i);
      return 1;
    }
  }
  return 0;
}

void expect_no_chars()
{
  int cs = 0;
  
  while (waitchar(100) == 1)
  {
    char c;
    if (read(0, &c, 1) == 0)
      fprintf(stderr, "enc Short read...\n");
    cs++;
    fprintf(stderr, "Warning: expected no chars, got %d\n", c);
  }
  if (cs)
    fprintf(stderr, "Expect no chars failed: got %d chars\n", cs);
}

void main(int argc, char **argv)
{
  unsigned char buf[259];
  int sz;
  int rfd;
  int tc = 0;
  
  if (argc < 2)
  {
    fprintf(stderr, "Usage: %s [filename]\n", argv[0]);
    exit(1);
  }
  rfd = open(argv[1], O_RDONLY);
  if (rfd < 0)
  {
    perror("open");
    exit(1);
  }
  
  dowrite("\x1B" "A\x00\x00\x00", 5);
  fprintf(stderr, "Address sent\n");
  expect("A", 1);
  expect_no_chars();
  while ((sz = read(rfd, buf+3, 255)) > 0)
  {
    int rv;
    char abuf[5];
    buf[0] = 0x1B;
    buf[1] = 'D';
    buf[2] = sz+1;
    abuf[0] = 0x1B;
    abuf[1] = 'A';
    abuf[2] = (tc >> 16) & 0xFF;
    abuf[3] = (tc >> 8) & 0xFF;
    abuf[4] = tc & 0xFF;
    tc += sz;
    retry:
    dowrite(abuf, 5);
    rv = expect("A", 1);
    dowrite(buf, sz + 3);
    fprintf(stderr, "Data sent (%d)\n", tc);
    rv |= expect("D", 1);
    expect_no_chars();
    if (rv)
    {
      printf("Failure to ack... retrying\n");
      dowrite("...", 3);
      rv = expect("...", 3);
      expect_no_chars();
      goto retry;
    }
  }
  exit(0);
}