#include "signal.h"
#include "env.h"
#include "substdio.h"
#include "stralloc.h"
#include "subfd.h"
#include "getline.h"
#include "alloc.h"
#include "str.h"
#include "hfield.h"
#include "token.h"
#include "error.h"
#include "gen_alloc.h"
#include "gen_allocdefs.h"
#include "headerbody.h"
#include "exit.h"
#include "open.h"
#include "quote.h"
#include "qqtalk.h"

void die_noreceipt() { _exit(0); }
void die() { _exit(1); }
void die_temp() { _exit(111); }
void die_nomem() {
 substdio_putsflush(subfderr,"qreceipt: fatal: out of memory\n"); die_temp(); }
void die_fork() {
 substdio_putsflush(subfderr,"qreceipt: fatal: unable to fork\n"); die_temp(); }
void die_qqperm() {
 substdio_putsflush(subfderr,"qreceipt: fatal: permanent qmail-queue error\n"); die(); }
void die_qqtemp() {
 substdio_putsflush(subfderr,"qreceipt: fatal: temporary qmail-queue error\n"); die_temp(); }
void die_usage() {
 substdio_putsflush(subfderr,
 "qreceipt: usage: qreceipt deliveryaddress\n"); die(); }
void die_read() {
 if (errno == error_nomem) die_nomem();
 substdio_putsflush(subfderr,"qreceipt: fatal: read error\n"); die_temp(); }
void doordie(sa,r) stralloc *sa; int r; {
 if (r == 1) return; if (r == -1) die_nomem();
 substdio_putsflush(subfderr,"qreceipt: fatal: unable to parse this: ");
 substdio_putflush(subfderr,sa->s,sa->len); die(); }

char *target;

int flagreceipt = 0;

char *returnpath;
stralloc messageid = {0};
stralloc sanotice = {0};

int rwnotice(addr) token_alloc *addr; { token_reverse(addr);
 if (token_unquote(&sanotice,addr) != 1) die_nomem();
 if (sanotice.len == str_len(target))
   if (!str_diffn(sanotice.s,target,sanotice.len))
     flagreceipt = 1;
 token_reverse(addr); return 1; }

struct qqtalk qqt;

stralloc quoted = {0};

void finishheader()
{
 if (!flagreceipt) die_noreceipt();
 if (!str_diff(returnpath,"")) die_noreceipt();
 if (!str_diff(returnpath,"#@[]")) die_noreceipt();

 if (!quote2(&quoted,returnpath)) die_nomem();

 if (qqtalk_open(&qqt,1) == -1) die_fork();

 qqtalk_puts(&qqt,"From: DELIVERY NOTICE SYSTEM <");
 qqtalk_put(&qqt,quoted.s,quoted.len);
 qqtalk_puts(&qqt,">\n");
 qqtalk_puts(&qqt,"To: <");
 qqtalk_put(&qqt,quoted.s,quoted.len);
 qqtalk_puts(&qqt,">\n");
 qqtalk_puts(&qqt,"\n\
Hi! This is the qreceipt program. Your message was delivered to the\n\
following address: ");
 qqtalk_puts(&qqt,target);
 qqtalk_puts(&qqt,". Thanks for asking.\n");
 if (messageid.s)
  {
   qqtalk_puts(&qqt,"Your ");
   qqtalk_put(&qqt,messageid.s,messageid.len);
  }

 qqtalk_from(&qqt,"");
 qqtalk_to(&qqt,returnpath);

 switch(qqtalk_close(&qqt))
  {
   case 0: break;
   case QQT_TOOLONG:
   case QQT_EXECHARD: die_qqperm();
   default: die_qqtemp();
  }
}

stralloc hfbuf = {0};
token_alloc hfin = {0};
token_alloc hfrewrite = {0};
token_alloc hfaddr = {0};

void doheaderfield(h)
stralloc *h;
{
 switch(hfield_known(h->s,h->len))
  {
   case H_MESSAGEID:
     if (!stralloc_copy(&messageid,h)) die_nomem();
     break;
   case H_NOTICEREQUESTEDUPONDELIVERYTO:
     doordie(h,token_parse(&hfin,h,&hfbuf));
     doordie(h,token_addrlist(&hfrewrite,&hfaddr,&hfin,rwnotice));
     break;
  }
}

void dobody(h) stralloc *h; { ; }

void main(argc,argv)
int argc;
char **argv;
{
 signal_init();
 if (!(target = argv[1])) die_usage();
 if (!(returnpath = env_get("SENDER"))) die_usage();
 if (headerbody(subfdin,doheaderfield,finishheader,dobody) == -1) die_read();
 _exit(0);
}
