From b732a73bc773789894466b0e5320b2f1fe42c7e9 Mon Sep 17 00:00:00 2001 From: John Denker Date: Fri, 1 Jun 2012 18:58:45 -0700 Subject: original, as downloaded from http://www.qmail.org/netqmail-1.06.tar.gz --- qsmhook.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 qsmhook.c (limited to 'qsmhook.c') diff --git a/qsmhook.c b/qsmhook.c new file mode 100644 index 0000000..d5b38aa --- /dev/null +++ b/qsmhook.c @@ -0,0 +1,137 @@ +#include "fd.h" +#include "stralloc.h" +#include "readwrite.h" +#include "sgetopt.h" +#include "wait.h" +#include "env.h" +#include "byte.h" +#include "str.h" +#include "alloc.h" +#include "exit.h" +#include "fork.h" +#include "case.h" +#include "subfd.h" +#include "error.h" +#include "substdio.h" +#include "sig.h" + +void die(e,s) int e; char *s; { substdio_putsflush(subfderr,s); _exit(e); } +void die_usage() { die(100,"qsmhook: fatal: incorrect usage\n"); } +void die_temp() { die(111,"qsmhook: fatal: temporary problem\n"); } +void die_read() { die(111,"qsmhook: fatal: unable to read message\n"); } +void die_badcmd() { die(100,"qsmhook: fatal: command not found\n"); } + +int flagrpline = 0; char *rpline; +int flagufline = 1; char *ufline; +int flagdtline = 0; char *dtline; +char *host; +char *sender; +char *recip; + +stralloc newarg = {0}; + +substdio ssout; +char outbuf[SUBSTDIO_OUTSIZE]; +substdio ssin; +char inbuf[SUBSTDIO_INSIZE]; + +void main(argc,argv) +int argc; +char **argv; +{ + int pid; + int wstat; + int pi[2]; + int opt; + char **arg; + char *x; + int i; + int flagesc; + + sig_pipeignore(); + + if (!(dtline = env_get("DTLINE"))) die_usage(); + if (!(rpline = env_get("RPLINE"))) die_usage(); + if (!(ufline = env_get("UFLINE"))) die_usage(); + if (!(recip = env_get("LOCAL"))) die_usage(); + if (!(host = env_get("HOST"))) die_usage(); + if (!(sender = env_get("SENDER"))) die_usage(); + + while ((opt = getopt(argc,argv,"DFlMmnPsx:")) != opteof) + switch(opt) + { + case 'D': case 'F': case 'M': break; /* be serious */ + case 'l': flagdtline = 1; break; /* also return-receipt-to? blech */ + case 'm': break; /* we only handle one recipient anyway */ + case 'n': flagufline = 0; break; + case 's': break; /* could call quote() otherwise, i suppose... */ + case 'P': flagrpline = 1; break; + case 'x': + if (case_starts(recip,optarg)) + recip += str_len(optarg); + break; + default: + _exit(100); + } + argc -= optind; + argv += optind; + + if (!*argv) die_usage(); + + for (arg = argv;x = *arg;++arg) + { + if (!stralloc_copys(&newarg,"")) die_temp(); + flagesc = 0; + for (i = 0;x[i];++i) + if (flagesc) + { + switch(x[i]) + { + case '%': if (!stralloc_cats(&newarg,"%")) die_temp(); break; + case 'g': if (!stralloc_cats(&newarg,sender)) die_temp(); break; + case 'h': if (!stralloc_cats(&newarg,host)) die_temp(); break; + case 'u': if (!stralloc_cats(&newarg,recip)) die_temp(); break; + } + flagesc = 0; + } + else + if (x[i] == '%') + flagesc = 1; + else + if (!stralloc_append(&newarg,&x[i])) die_temp(); + if (!stralloc_0(&newarg)) die_temp(); + i = str_len(newarg.s) + 1; + if (!(x = alloc(i))) die_temp(); + byte_copy(x,i,newarg.s); + *arg = x; + } + + if (pipe(pi) == -1) die_temp(); + + switch(pid = fork()) + { + case -1: + die_temp(); + case 0: + close(pi[1]); + if (fd_move(0,pi[0]) == -1) die_temp(); + sig_pipedefault(); + execvp(*argv,argv); + if (error_temp(errno)) die_temp(); + die_badcmd(); + } + close(pi[0]); + + substdio_fdbuf(&ssout,write,pi[1],outbuf,sizeof(outbuf)); + substdio_fdbuf(&ssin,read,0,inbuf,sizeof(inbuf)); + if (flagufline) substdio_bputs(&ssout,ufline); + if (flagrpline) substdio_bputs(&ssout,rpline); + if (flagdtline) substdio_bputs(&ssout,dtline); + if (substdio_copy(&ssout,&ssin) == -2) die_read(); + substdio_flush(&ssout); + close(pi[1]); + + if (wait_pid(&wstat,pid) == -1) die_temp(); + if (wait_crashed(wstat)) die_temp(); + _exit(wait_exitcode(wstat)); +} -- cgit v1.2.3