#include "strerr.h"
#include "getln.h"
#include "subfd.h"
#include "substdio.h"
#include "readwrite.h"
#include "open.h"
#include "timeoutread.h"
#include "timeoutwrite.h"
#include "exit.h"
#include "stralloc.h"
#include "sig.h"
#include "str.h"
#include "case.h"
#include "quote.h"
#include "scan.h"
#include "env.h"

#define FATAL "relaytest: fatal: "

void die_nomem() {
  strerr_die2x(111,FATAL,"out of memory");
}
void die_output() {
  strerr_die2sys(111,FATAL,"unable to write output: ");
}
void die_readmess() {
  strerr_die2sys(111,FATAL,"unable to read file: ");
}
void die_neteof() {
  strerr_die2x(111,FATAL,"network read error: end of file");
}
void die_netread() {
  strerr_die2sys(111,FATAL,"network read error: ");
}
void die_netwrite() {
  strerr_die2sys(111,FATAL,"network write error: ");
}
void die_proto() {
  strerr_die2x(111,FATAL,"protocol violation");
}

int saferead(fd,buf,len) int fd; char *buf; int len;
{
  int r;
  r = timeoutread(81,fd,buf,len);
  if (r == 0) die_neteof();
  if (r < 0) die_netread();
  return r;
}

int safewrite(fd,buf,len) int fd; char *buf; int len;
{
  int r;
  r = timeoutwrite(73,fd,buf,len);
  if (r <= 0) die_netwrite();
  return r;
}

char buf6[2048];
substdio ss6 = SUBSTDIO_FDBUF(saferead,6,buf6,sizeof buf6);

char buf7[2048];
substdio ss7 = SUBSTDIO_FDBUF(safewrite,7,buf7,sizeof buf7);

stralloc smtpline = {0};

unsigned long smtpcode()
{
  unsigned long code;
  int flagfirst;
  int match;
  char num[4];
 
  flagfirst = 1;
  do {
    if (getln(&ss6,&smtpline,&match,'\n') != 0) die_proto();
    if (!match) die_proto();
    if ((smtpline.len >= 1) && (smtpline.s[smtpline.len - 1] == '\n'))
      --smtpline.len;
    if ((smtpline.len >= 1) && (smtpline.s[smtpline.len - 1] == '\r'))
      --smtpline.len;
    if (smtpline.len < 3) die_proto();
    byte_copy(num,3,smtpline.s);
    num[3] = 0;
    if (scan_ulong(num,&code) != 3) die_proto();
    if (smtpline.len == 3) return code;
    flagfirst = 0;
  }
  while (smtpline.s[3] == '-');

  return code;
}

void quit() /* what a stupid protocol */
{
  substdio_puts(&ss7,"QUIT\r\n");
  substdio_flush(&ss7);
}

void main(argc,argv)
int argc;
char **argv;
{

  if (smtpcode() != 220) {
    quit();
    strerr_die2x(111,FATAL,"connected but greeting failed");
  }

  substdio_puts(&ss7,"EHLO tester.com\r\n");
  substdio_flush(&ss7);

  if (smtpcode() != 250) {
    substdio_puts(&ss7,"HELO tester.com\r\n");
    substdio_flush(&ss7);

    if (smtpcode() != 250) {
      quit();
      exit(1);
    }
  }

  substdio_puts(&ss7,"MAIL FROM: test@tester.com\r\n");
  substdio_flush(&ss7);

  if (smtpcode() != 250) {
    quit();
    exit(1);
  }

  substdio_puts(&ss7,"RCPT TO: test@relay-test-invalid.com\r\n");
  substdio_flush(&ss7);

  if (smtpcode() != 250) {
    quit();
    exit(1);
  }

  substdio_puts(&ss7,"DATA\r\n");
  substdio_flush(&ss7);

  if (smtpcode() != 354) {
    exit(1);
  }

  exit(0);
}
