Import ezmlm-idx 0.40
[ezmlm] / ezmlm-gate.c
diff --git a/ezmlm-gate.c b/ezmlm-gate.c
new file mode 100644 (file)
index 0000000..25d9b59
--- /dev/null
@@ -0,0 +1,213 @@
+/*$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);
+   }
+}
+