#include "stralloc.h"
#include "substdio.h"
#include "subfd.h"
#include "getline.h"
#include "token822.h"
#include "parse.h"
#include "exit.h"
#include "case.h"
#include "error.h"
#include "open.h"
#include "readwrite.h"
#include "conf-home.h"
#include "conf-mailhome.h"
#include "control.h"
#include "cdbmss.h"

void die() { _exit(1); }
void die_temp() { _exit(111); }
void die_nomem() {
 substdio_putsflush(subfderr,"newaliases: fatal: out of memory\n");
 die_temp(); }
void die_chdir() {
 substdio_putsflush(subfderr,"newaliases: fatal: unable to chdir\n");
 die_temp(); }
void die_opena() {
 substdio_putsflush(subfderr,"newaliases: fatal: unable to open etc/aliases\n");
 die_temp(); }
void die_reada() {
 substdio_putsflush(subfderr,"newaliases: fatal: unable to read etc/aliases\n");
 die_temp(); }
void die_readctl() {
 substdio_putsflush(subfderr,"newaliases: fatal: trouble reading controls\n");
 die_temp(); }
void die_opent() {
 substdio_putsflush(subfderr,"newaliases: fatal: unable to open etc/temp\n");
 die_temp(); }
void die_writet() {
 substdio_putsflush(subfderr,"newaliases: fatal: unable to write etc/temp\n");
 die_temp(); }
void die_rename() {
 substdio_putsflush(subfderr,"newaliases: fatal: unable to move etc/temp to etc/compiled\n");
 die_temp(); }
void perm_parse(sa) stralloc *sa; {
 substdio_puts(subfderr,"newaliases: fatal: unable to parse this instruction:\n");
 substdio_put(subfderr,sa->s,sa->len);
 substdio_flush(subfderr);
 die();
}

stralloc lastline = {0};
stralloc line = {0};
stralloc cbuf = {0};
token822_alloc toks = {0};

char inbuf[1024];

struct cdbmss cdbmss;

void main()
{
 int r;
 int match;
 int fd;
 substdio ssin;
 int fdtemp;

 if (chdir(CONF_MAILHOME) == -1) die_chdir();
 if (control_init() == -1) die_readctl();
 if (control_rldef(&parse_defaultdomain,"control/defaultdomain",1,"defaultdomain") != 1) die_readctl();
 if (control_rldef(&parse_defaulthost,"control/defaulthost",1,"defaulthost") != 1) die_readctl();
 if (control_rldef(&parse_plusdomain,"control/plusdomain",1,"plusdomain") != 1) die_readctl();

 if (chdir(CONF_HOME) == -1) die_chdir();
 fd = open_read("etc/aliases");
 if (fd == -1) die_opena();
 substdio_fdbuf(&ssin,read,fd,inbuf,sizeof(inbuf));

 umask(033);
 fdtemp = open_trunc("etc/temp");
 if (fdtemp == -1) die_opent();
 if (cdbmss_start(&cdbmss,fdtemp) == -1) die_writet();

 if (!stralloc_copys(&lastline,"")) die_nomem();

 for (;;)
  {
   if (getline2(&ssin,&line,&match,'\n') != 0)
     die_reada();

   if (match && (line.s[0] == '\n'))
     continue;

   if (match && ((line.s[0] == ' ') || (line.s[0] == '\t')))
    {
     if (!stralloc_cat(&lastline,&line)) die_nomem();
     continue;
    }

   if (lastline.len)
     if (lastline.s[0] != '#')
      {
       r = token822_parse(&toks,&lastline,&cbuf);
       if (r == -1) die_nomem();
       if (r == 0) perm_parse(&lastline);

       r = parse(&toks);
       if (r == 0) die_nomem();
       if (r == -1) perm_parse(&lastline);

       if (parse_flagalias)
	{
	 case_lowerb(parse_alias.s,parse_alias.len);
	 if (cdbmss_add(&cdbmss,parse_alias.s,parse_alias.len,parse_recips.s,parse_recips.len) == -1)
	   die_writet();
	}
      }

   if (!match) break;

   if (!stralloc_copy(&lastline,&line)) die_nomem();
  }

 if (cdbmss_finish(&cdbmss) == -1) die_writet();
 if (fsync(fdtemp) == -1) die_writet();
 if (close(fdtemp) == -1) die_writet(); /* NFS stupidity */
 if (rename("etc/temp","etc/compiled") == -1) die_rename();

 _exit(0);
}
