/*$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); } }