/*$Id: ezmlm-gate.c,v 1.18 1999/10/09 16:49:56 lindberg Exp $*/
/*$Name: ezmlm-idx-040 $*/

#include "stralloc.h"
#include "strerr.h"
#include "error.h"
#include "env.h"
#include "sig.h"
#include "str.h"
#include "seek.h"
#include "fork.h"
#include "wait.h"
#include "exit.h"
#include "getconf.h"
#include "auto_bin.h"
#include "sgetopt.h"
#include "errtxt.h"
#include "idx.h"
#include "subscribe.h"

#define FATAL "ezmlm-gate: fatal: "

void die_usage()
{
  strerr_die1x(100,"ezmlm-gate: usage: ezmlm-gate [-cCmMpPqrRsSvV] "
			"dir [moddir [...]]");
}
void die_nomem() { strerr_die2x(111,FATAL,ERR_NOMEM); }

stralloc line = {0};
stralloc cmds = {0};
stralloc send = {0};
stralloc sendopt = {0};
stralloc storeopt = {0};
void *psql = (void *) 0;

char szchar[2] = "-";
  char *sendargs[4];
  int child;
  int wstat;
  char *pmod;

int mailprog(s)
  char *s;
{
    int r;

    sendargs[0] = "/bin/sh";	/* 100 perm error, 111 temp, 99 dom ok */
    sendargs[1] = "-c";		/* 0 rec ok, others bounce */
    sendargs[2] = s;
    sendargs[3] = (char *)0;
    switch(child = fork()) {
      case -1:
	strerr_die2sys(111,FATAL,ERR_FORK);
      case 0:
	execv(*sendargs,sendargs);
	if (errno == error_txtbsy || errno == error_nomem ||
	  errno == error_io)
	        strerr_die5sys(111,FATAL,ERR_EXECUTE,
		  "/bin/sh -c ",sendargs[2],": ");
        else
		strerr_die5sys(100,FATAL,ERR_EXECUTE,
		  "/bin/sh -c ",sendargs[2],": ");
    }
         /* parent */
    wait_pid(&wstat,child);
    if (wait_crashed(wstat))
	strerr_die2x(111,FATAL,ERR_CHILD_CRASHED);
    switch((r = wait_exitcode(wstat))) {
      case 0: case 99: case 100: break;
      case 111:					/* temp error */
        strerr_die2x(111,FATAL,ERR_CHILD_TEMP);
      default:
        strerr_die2x(100,FATAL,ERR_REJECT);	/* other errors => bounce */
    }
    if (seek_begin(0) == -1)			/* rewind */
      strerr_die2sys(111,FATAL,ERR_SEEK_INPUT);
    return r;
}

void main(argc,argv)
int argc;
char **argv;
{
  char *dir;
  char *sender;
  char *moddir;
  char *queryext = (char *) 0;
  int opt;
  int ret = 0;
  unsigned int i,j,k;

  umask(022);
  sig_pipeignore();
	/* storeopts to ezmlm-store only. Others to both (ezmlm-store may */
	/* pass them on to ezmlm-send. */
  if (!stralloc_copys(&sendopt," -")) die_nomem();
  if (!stralloc_copys(&storeopt," -")) die_nomem();

  while ((opt = getopt(argc,argv,
      "cCmMpPq:Q:sSrRt:T:vV")) != opteof)
    switch(opt) {	/* pass on unrecognized options */
      case 'c':			/* ezmlm-send flags */
      case 'C':
      case 'r':
      case 'R':
        szchar[0] = opt;
        if (!stralloc_append(&sendopt,szchar)) die_nomem();
        break;
      case 'm':			/* ezmlm-store flags */
      case 'M':
      case 'p':
      case 'P':
      case 's':
      case 'S':
        szchar[0] = opt;
        if (!stralloc_append(&storeopt,szchar)) die_nomem();
        break;
      case 'q':			/* allow both qQ to be nice */
      case 'Q': if (optarg) queryext = optarg; break;
      case 'v':
      case 'V': strerr_die2x(0,"ezmlm-gate version: ",EZIDX_VERSION);
      default:			/* ezmlm-store flags */
        die_usage();
    }

  dir = argv[optind++];
  if (!dir) die_usage();
  if (chdir(dir) == -1)
    strerr_die4sys(111,FATAL,ERR_SWITCH,dir,": ");

  sender = env_get("SENDER");

  pmod = (char *) 0;

  if (queryext) {
    getconf(&cmds,queryext,1,FATAL,dir);
    i = 0;
    for (j = 0;j < cmds.len; ++j)
      if (!cmds.s[j]) {
	switch (cmds.s[i]) {
	  case '\0': case '#': break;	/* ignore blank/comment */
	  case '|':
		ret = mailprog(cmds.s + i + 1); break;
	  default:
		ret = mailprog(cmds.s + i); break;
	}
	if (ret) break;
	i = j + 1;
    }
    if (!ret || ret == 99)		/* 111 => temp error */
      pmod = "";			/* 0, 99 => post */
					/* other => moderate */
  }
  moddir = argv[optind++];
  if (moddir && !ret) {			/* if exit 0 and moddir, add issub */
    pmod = (char *) 0;
    while (moddir && !pmod && sender) {
      pmod = issub(moddir,sender,(char *) 0,FATAL);
      closesql();
      moddir = argv[optind++];
    }
  }

  sendargs[0] = "sh";
  sendargs[1] = "-c";
  if (!stralloc_copys(&send,auto_bin)) die_nomem();
  if (pmod) {
    if (!stralloc_cats(&send,"/ezmlm-send")) die_nomem();
    if (sendopt.len > 2)
      if (!stralloc_cat(&send,&sendopt)) die_nomem();

  } else {
    if (!stralloc_cats(&send,"/ezmlm-store")) die_nomem();
    if (storeopt.len > 2)
      if (!stralloc_cat(&send,&storeopt)) die_nomem();
    if (sendopt.len > 2)
      if (!stralloc_cat(&send,&sendopt)) die_nomem();
  }
  if (!stralloc_cats(&send," '")) die_nomem();
  if (!stralloc_cats(&send,dir)) die_nomem();
  if (!stralloc_cats(&send,"'")) die_nomem();
  if (!stralloc_0(&send)) die_nomem();
  sendargs[2] = send.s;
  sendargs[3] = 0;

  switch(child = fork()) {
    case -1:
      strerr_die2sys(111,FATAL,ERR_FORK);
    case 0:
      execvp(*sendargs,sendargs);
      if (errno == error_txtbsy || errno == error_nomem ||
          errno == error_io)
        strerr_die4sys(111,FATAL,ERR_EXECUTE,sendargs[2],": ");
      else
        strerr_die4sys(100,FATAL,ERR_EXECUTE,sendargs[2],": ");
   }
         /* parent */
   wait_pid(&wstat,child);
   if (wait_crashed(wstat))
     strerr_die2x(111,FATAL,ERR_CHILD_CRASHED);
   switch(wait_exitcode(wstat)) {
     case 100:
       strerr_die2x(100,FATAL,ERR_CHILD_FATAL);
     case 111:
        strerr_die2x(111,FATAL,ERR_CHILD_TEMP);
     case 0:
       _exit(0);
     default:
       strerr_die2x(111,FATAL,ERR_CHILD_UNKNOWN);
   }
}

