diff -u orig/condredirect.c ./condredirect.c --- orig/condredirect.c 1998-06-15 06:53:16.000000000 -0400 +++ ./condredirect.c 2004-07-19 12:06:45.000000000 -0400 @@ -34,6 +34,7 @@ { char *sender; char *dtline; + char *qqeh; int pid; int wstat; char *qqx; @@ -71,6 +72,11 @@ if (qmail_open(&qqt) == -1) strerr_die2sys(111,FATAL,"unable to fork: "); qmail_puts(&qqt,dtline); + + qqeh = env_get("QQEH"); + if (qqeh) + qmail_puts(&qqt,qqeh); + if (substdio_copy(&ssout,&ssin) != 0) strerr_die2sys(111,FATAL,"unable to read message: "); substdio_flush(&ssout); diff -u orig/forward.c ./forward.c --- orig/forward.c 1998-06-15 06:53:16.000000000 -0400 +++ ./forward.c 2004-07-19 12:06:45.000000000 -0400 @@ -32,6 +32,7 @@ { char *sender; char *dtline; + char *qqeh; char *qqx; sig_pipeignore(); @@ -46,6 +47,11 @@ if (qmail_open(&qqt) == -1) strerr_die2sys(111,FATAL,"unable to fork: "); qmail_puts(&qqt,dtline); + + qqeh = env_get("QQEH"); + if (qqeh) + qmail_puts(&qqt,qqeh); + if (substdio_copy(&ssout,&ssin) != 0) strerr_die2sys(111,FATAL,"unable to read message: "); substdio_flush(&ssout); diff -u orig/Makefile ./Makefile --- orig/Makefile 1998-06-15 06:53:16.000000000 -0400 +++ ./Makefile 2004-07-19 12:06:45.000000000 -0400 @@ -1421,11 +1421,14 @@ qmail-queue: \ load qmail-queue.o triggerpull.o fmtqfn.o now.o date822fmt.o \ datetime.a seek.a ndelay.a open.a sig.a alloc.a substdio.a error.a \ -str.a fs.a auto_qmail.o auto_split.o auto_uids.o +str.a fs.a auto_qmail.o auto_split.o auto_uids.o \ +../libdomainkeys.a env.a control.o stralloc.a dns.lib ./load qmail-queue triggerpull.o fmtqfn.o now.o \ date822fmt.o datetime.a seek.a ndelay.a open.a sig.a \ - alloc.a substdio.a error.a str.a fs.a auto_qmail.o \ - auto_split.o auto_uids.o + substdio.a error.a fs.a auto_qmail.o \ + auto_split.o auto_uids.o \ + ../libdomainkeys.a -lcrypto env.a control.o open.a getln.a \ + stralloc.a alloc.a scan_ulong.o str.a `cat dns.lib` qmail-queue.0: \ qmail-queue.8 @@ -1434,6 +1437,7 @@ qmail-queue.o: \ compile qmail-queue.c readwrite.h sig.h exit.h open.h seek.h fmt.h \ alloc.h substdio.h datetime.h now.h datetime.h triggerpull.h extra.h \ +env.h \ auto_qmail.h auto_uids.h date822fmt.h fmtqfn.h ./compile qmail-queue.c diff -u orig/preline.1 ./preline.1 --- orig/preline.1 1998-06-15 06:53:16.000000000 -0400 +++ ./preline.1 2004-07-19 12:06:45.000000000 -0400 @@ -39,6 +39,11 @@ .B control/virtualdomains for manual routing. .TP +.B \-e +Do not include the +.B QQEH +contents. +.TP .B \-f Do not include the .B From_ diff -u orig/preline.c ./preline.c --- orig/preline.c 1998-06-15 06:53:16.000000000 -0400 +++ ./preline.c 2004-07-19 12:06:45.000000000 -0400 @@ -20,6 +20,7 @@ int flagufline = 1; char *ufline; int flagrpline = 1; char *rpline; int flagdtline = 1; char *dtline; +int flagqqeh = 1; char *qqeh; char outbuf[SUBSTDIO_OUTSIZE]; char inbuf[SUBSTDIO_INSIZE]; @@ -46,9 +47,11 @@ case 'f': flagufline = 0; break; case 'r': flagrpline = 0; break; case 'd': flagdtline = 0; break; + case 'e': flagqqeh = 0; break; case 'F': flagufline = 1; break; case 'R': flagrpline = 1; break; case 'D': flagdtline = 1; break; + case 'E': flagqqeh = 1; break; default: die_usage(); } argc -= optind; @@ -77,6 +80,7 @@ if (flagufline) substdio_bputs(&ssout,ufline); if (flagrpline) substdio_bputs(&ssout,rpline); if (flagdtline) substdio_bputs(&ssout,dtline); + if (flagqqeh) substdio_bputs(&ssout,qqeh); if (substdio_copy(&ssout,&ssin) != 0) strerr_die2sys(111,FATAL,"unable to copy input: "); substdio_flush(&ssout); diff -u orig/qmail-command.8 ./qmail-command.8 --- orig/qmail-command.8 1998-06-15 06:53:16.000000000 -0400 +++ ./qmail-command.8 2004-07-19 12:06:45.000000000 -0400 @@ -143,6 +143,10 @@ adds to .IR mbox -format files. +.B QQEH +is the same QQEH that was set when +.B qmail-queue +was invoked for this email. .SH "SEE ALSO" dot-qmail(5), envelopes(5), diff -u orig/qmail-local.8 ./qmail-local.8 --- orig/qmail-local.8 1998-06-15 06:53:16.000000000 -0400 +++ ./qmail-local.8 2004-07-19 12:06:45.000000000 -0400 @@ -14,6 +14,7 @@ .I domain .I sender .I defaultdelivery +.I qqeh .SH DESCRIPTION .B qmail-local reads a mail message @@ -70,6 +71,9 @@ .BR .qmail\fIext : namely, following the delivery instructions in .IR defaultdelivery . +Prepend the contents of +.IR qqeh +to the message on standard input. The standard input for .B qmail-local diff -u orig/qmail-local.c ./qmail-local.c --- orig/qmail-local.c 1998-06-15 06:53:16.000000000 -0400 +++ ./qmail-local.c 2004-07-20 00:10:58.000000000 -0400 @@ -52,6 +52,7 @@ char *host; char *sender; char *aliasempty; +char *qqeh; stralloc safeext = {0}; stralloc ufline = {0}; @@ -116,6 +117,7 @@ substdio_fdbuf(&ssout,write,fd,outbuf,sizeof(outbuf)); if (substdio_put(&ssout,rpline.s,rpline.len) == -1) goto fail; if (substdio_put(&ssout,dtline.s,dtline.len) == -1) goto fail; + if (substdio_puts(&ssout,qqeh) == -1) goto fail; switch(substdio_copy(&ssout,&ss)) { @@ -196,6 +198,7 @@ if (substdio_put(&ssout,ufline.s,ufline.len)) goto writeerrs; if (substdio_put(&ssout,rpline.s,rpline.len)) goto writeerrs; if (substdio_put(&ssout,dtline.s,dtline.len)) goto writeerrs; + if (substdio_puts(&ssout,qqeh) == -1) goto writeerrs; for (;;) { if (getln(&ss,&messline,&match,'\n') != 0) @@ -241,6 +244,7 @@ case -1: temp_fork(); case 0: + if (!env_put2("QQEH",qqeh)) temp_nomem(); args[0] = "/bin/sh"; args[1] = "-c"; args[2] = prog; args[3] = 0; sig_pipedefault(); execv(*args,args); @@ -276,6 +280,7 @@ if (qmail_open(&qqt) == -1) temp_fork(); mailforward_qp = qmail_qp(&qqt); qmail_put(&qqt,dtline.s,dtline.len); + qmail_puts(&qqt,qqeh); do { if (getln(&ss,&messline,&match,'\n') != 0) { qmail_fail(&qqt); break; } @@ -484,6 +489,7 @@ if (!(host = *argv++)) usage(); if (!(sender = *argv++)) usage(); if (!(aliasempty = *argv++)) usage(); + if (!(qqeh = *argv++)) usage(); if (*argv) usage(); if (homedir[0] != '/') usage(); diff -u orig/qmail-lspawn.c ./qmail-lspawn.c --- orig/qmail-lspawn.c 1998-06-15 06:53:16.000000000 -0400 +++ ./qmail-lspawn.c 2004-07-19 12:06:45.000000000 -0400 @@ -165,15 +165,15 @@ } } -int spawn(fdmess,fdout,s,r,at) +int spawn(fdmess,fdout,s,qqeh,r,at) int fdmess; int fdout; -char *s; char *r; int at; +char *s; char *qqeh; char *r; int at; { int f; if (!(f = fork())) { - char *(args[11]); + char *(args[12]); unsigned long u; int n; int uid; @@ -217,7 +217,8 @@ args[7] = r + at + 1; args[8] = s; args[9] = aliasempty; - args[10] = 0; + args[10] = qqeh; + args[11] = 0; if (fd_move(0,fdmess) == -1) _exit(QLX_SYS); if (fd_move(1,fdout) == -1) _exit(QLX_SYS); diff -u orig/qmail-queue.8 ./qmail-queue.8 --- orig/qmail-queue.8 1998-06-15 06:53:16.000000000 -0400 +++ ./qmail-queue.8 2004-08-08 16:18:40.000000000 -0400 @@ -33,6 +33,14 @@ always adds a .B Received line to the top of the message. +.B qmail-queue +keeps a copy of the +.B QQEH +environment variable (if set), and passes it into the queue. +.B qmail-local +and +.B qmail-remote +will prepend it to the headers of the email when it is delivered. Other than this, .B qmail-queue does not inspect the message @@ -40,6 +48,64 @@ However, the recipients probably expect to see a proper header, as described in .BR qmail-header(5) . + +.SH "DOMAINKEY" +.B qmail-queue +supports DomainKey signing and verification. It uses the libdomainkey +and OpenSSL libraries. To sign a message, set the +.B DKSIGN +environment variable to the pathname to the private key that will be +used to sign the message. If there is a % character in the environment +variable, it is removed and replaced by the domain name in the From: header. +The selector will be taken from the +basename of the file. The private key should be created by +.BR dknewkey , +which comes with libdomainkey. + +To verify a message, set the +.B DKVERIFY +environment variable to a desired set of letters. Precisely, if you +want a libdomainkey return status to generate an error, include that +letter, where A is the first return status (DK_STAT_OK), B is the +second (DK_STAT_BADSIG), etc. The letter should be uppercase if you +want a permanent error to be returned (exit code 13), and lowercase if +you want a temporary error to be returned (exit code 82). + +For example, if you want to permanently reject messages that have a +signature that has been revoked, include the letter 'K' in the +.B DKVERIFY +environment variable. A conservative set of letters is +.BR DEGIJKfh . +Reject permanently BADSIG, NOKEY, BADKEY, SYNTAX, ARGS, REVOKED, and +INTERNAL errors, and temporarily CANTVRFY and NORESOURCE. Add in +.B B +if you want to reject messages that have a signature that doesn't +verify (presumably because the message is a forgery or has been +damaged in transit. Note that +.B qmail-queue +always inserts the +.B DomainKey-Status +header, so that messages can be +rejected at delivery time, or in the mail reader. + +Typically, you would sign messages generated on-host by setting +.B DKSIGN +in the environment before running an email program. DKSIGN will be carried +through qmail's sendmail emulation through +.B qmail-inject +to +.BR qmail-queue . +You would also set it for +.B qmail-smtpd +at the same time +.B RELAYCLIENT +is set, most often in the tcpserver cdb file. If a host is authorized +to relay, you probably want to sign messages sent by that host. There +is currently no way to sign using a different key for different hosts. +Suggestions entertained for the best way to do that. +.B DKVERIFY +should be set for all other hosts. + .SH "FILESYSTEM RESTRICTIONS" .B qmail-queue imposes two constraints on the queue structure: diff -u orig/qmail-queue.c ./qmail-queue.c --- orig/qmail-queue.c 1998-06-15 06:53:16.000000000 -0400 +++ ./qmail-queue.c 2004-08-08 16:14:37.000000000 -0400 @@ -7,6 +7,7 @@ #include "seek.h" #include "fmt.h" #include "alloc.h" +#include "stralloc.h" #include "substdio.h" #include "datetime.h" #include "now.h" @@ -16,6 +17,9 @@ #include "auto_uids.h" #include "date822fmt.h" #include "fmtqfn.h" +#include "env.h" +#include "control.h" +#include "../domainkeys.h" #define DEATH 86400 /* 24 hours; _must_ be below q-s's OSSIFIED (36 hours) */ #define ADDR 1003 @@ -59,6 +63,15 @@ void die_read() { cleanup(); die(54); } void sigalrm() { /* thou shalt not clean up here */ die(52); } void sigbug() { die(81); } +void maybe_die_dk(e) DK_STAT e; { + switch(e) { + case DK_STAT_BADKEY: _exit(55); + case DK_STAT_CANTVRFY: _exit(74); + case DK_STAT_NORESOURCE: _exit(51); + case DK_STAT_ARGS: _exit(12); + case DK_STAT_INTERNAL: _exit(81); + } +} unsigned int receivedlen; char *received; @@ -151,16 +164,90 @@ char tmp[FMT_ULONG]; +char *dksign = 0; +stralloc dksignature = {0}; +stralloc dkoutput = {0}; +char *dkverify = 0; +DK_LIB *dklib; +DK *dk; +DK_STAT st; + +static void write_signature(DK *dk, char *keyfn) +{ + char advice[2048]; + char *selector; + char *from; + static stralloc keyfnfrom = {0}; + int i; + + from = dk_from(dk); + i = str_chr(keyfn, '%'); + if (keyfn[i]) { + if (!stralloc_copyb(&keyfnfrom,keyfn,i)) die(51); + if (!stralloc_cats(&keyfnfrom,from)) die(51); + if (!stralloc_cats(&keyfnfrom,keyfn + i + 1)) die(51); + } else { + if (!stralloc_copys(&keyfnfrom,keyfn)) die(51); + } + if (!stralloc_0(&keyfnfrom)) die(51); + + if (control_readfile(&dksignature,keyfn,0) != 1) die(31); + for(i=0; i < dksignature.len; i++) + if (dksignature.s[i] == '\0') dksignature.s[i] = '\n'; + if (!stralloc_0(&dksignature)) die(51); + + st = dk_getsig(dk, dksignature.s, advice, sizeof(advice)); + maybe_die_dk(st); + + if (!stralloc_cats(&dkoutput, + "Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys\n" + "DomainKey-Signature: a=rsa-sha1; q=dns; c=simple;\n" + " s=")) die(51); + selector = keyfn; + while (*keyfn) { + if (*keyfn == '/') selector = keyfn+1; + keyfn++; + } + if (!stralloc_cats(&dkoutput,selector)) die(51); + if (!stralloc_cats(&dkoutput,"; d=")) die(51); + if (from) { + if (!stralloc_cats(&dkoutput,from)) die(51); + } else if (!stralloc_cats(&dkoutput,"unknown")) die(51); + if (!stralloc_cats(&dkoutput,";\n b=")) die(51); + if (!stralloc_cats(&dkoutput,advice)) die(51); + if (!stralloc_cats(&dkoutput," ;\n")) die(51); +} + void main() { unsigned int len; char ch; + char *qqeh; + qqeh = env_get("QQEH"); sig_blocknone(); umask(033); if (chdir(auto_qmail) == -1) die(61); if (chdir("queue") == -1) die(62); + dksign = env_get("DKSIGN"); + dkverify = env_get("DKVERIFY"); + + if (dksign || dkverify) { + if (qqeh && *qqeh) { + if (!stralloc_cats(&dkoutput,qqeh)) die(51); + } + dklib = dk_init(0); + if (!dklib) die(51); + } + if (dksign) { + dk = dk_sign(dklib, &st); + if (!dk) die(31); + } else if (dkverify) { + dk = dk_verify(dklib, &st); + if (!dk) die(31); + } + mypid = getpid(); uid = getuid(); starttime = now(); @@ -191,15 +278,61 @@ substdio_fdbuf(&ssin,read,0,inbuf,sizeof(inbuf)); if (substdio_bput(&ssout,received,receivedlen) == -1) die_write(); - - switch(substdio_copy(&ssout,&ssin)) - { - case -2: die_read(); - case -3: die_write(); - } + if (dksign) { + maybe_die_dk(dk_message(dk, received,receivedlen-1)); + maybe_die_dk(dk_message(dk, "\r\n", 2)); + } + + for (;;) { + register int n; + register char *x; + int i; + + n = substdio_feed(&ssin); + if (n < 0) die_read(); + if (!n) break; + x = substdio_PEEK(&ssin); + if (dksign || dkverify) + for(i=0; i < n; i++) { + if (x[i] == '\n') st = dk_message(dk, "\r\n", 2); + else st = dk_message(dk, x+i, 1); + maybe_die_dk(st); + } + if (substdio_put(&ssout,x,n) == -1) die_write(); + substdio_SEEK(&ssin,n); + } if (substdio_flush(&ssout) == -1) die_write(); if (fsync(messfd) == -1) die_write(); + if (dksign || dkverify) { + st = dk_eom(dk, (void *)0); + maybe_die_dk(st); + if (dksign) { + write_signature(dk, dksign); + } else if (dkverify) { + char *status; + if (!stralloc_copys(&dkoutput,"DomainKey-Status: ")) die(51); + switch(st) { + case DK_STAT_OK: status = "good "; break; + case DK_STAT_BADSIG: status = "bad "; break; + case DK_STAT_NOSIG: status = "no signature"; break; + case DK_STAT_NOKEY: + case DK_STAT_CANTVRFY: status = "no key "; break; + case DK_STAT_BADKEY: status = "bad key "; break; + case DK_STAT_INTERNAL: + case DK_STAT_ARGS: + case DK_STAT_SYNTAX: status = "bad format "; break; + case DK_STAT_NORESOURCE: status = "no resources"; break; + case DK_STAT_REVOKED: status = "revoked "; break; + } + if (!stralloc_cats(&dkoutput,status)) die(51); + if (!stralloc_cats(&dkoutput,"\n")) die(51); + if (dkverify[str_chr(dkverify, 'A'+st)]) die(13); + if (dkverify[str_chr(dkverify, 'a'+st)]) die(82); + } + if (!stralloc_0(&dkoutput)) die(51); + qqeh = dkoutput.s; + } intdfd = open_excl(intdfn); if (intdfd == -1) die(65); @@ -216,6 +349,12 @@ if (substdio_bput(&ssout,tmp,fmt_ulong(tmp,mypid)) == -1) die_write(); if (substdio_bput(&ssout,"",1) == -1) die_write(); + if (qqeh && *qqeh) { + if (substdio_bput(&ssout,"e",1) == -1) die_write(); + if (substdio_bputs(&ssout,qqeh) == -1) die_write(); + if (substdio_bput(&ssout,"",1) == -1) die_write(); + } + if (substdio_get(&ssin,&ch,1) < 1) die_read(); if (ch != 'F') die(91); if (substdio_bput(&ssout,&ch,1) == -1) die_write(); diff -u orig/qmail-remote.8 ./qmail-remote.8 --- orig/qmail-remote.8 1998-06-15 06:53:16.000000000 -0400 +++ ./qmail-remote.8 2004-07-19 12:06:45.000000000 -0400 @@ -5,6 +5,7 @@ .B qmail-remote .I host .I sender +.I qqeh .I recip [ .I recip ... @@ -46,6 +47,8 @@ .BR qmail-remote . The envelope sender address is listed as .I sender\fP. +Any QQEH information passed to qmail-queue is passed in +.I qqeh\fP. Note that .B qmail-remote diff -u orig/qmail-remote.c ./qmail-remote.c --- orig/qmail-remote.c 1998-06-15 06:53:16.000000000 -0400 +++ ./qmail-remote.c 2004-07-19 12:06:45.000000000 -0400 @@ -43,6 +43,7 @@ struct constmap maproutes; stralloc host = {0}; stralloc sender = {0}; +stralloc qqeh = {0}; saa reciplist = {0}; @@ -193,7 +194,13 @@ { int r; char ch; + int i; + for (i = 0; i < qqeh.len; i++) { + if (qqeh.s[i] == '\n') + substdio_put(&smtpto,"\r",1); + substdio_put(&smtpto,qqeh.s + i,1); + } for (;;) { r = substdio_get(&ssin,&ch,1); if (r == 0) break; @@ -366,11 +373,13 @@ addrmangle(&sender,argv[2],&flagalias,0); + if (!stralloc_copys(&qqeh,argv[3])) temp_nomem(); + if (!saa_readyplus(&reciplist,0)) temp_nomem(); if (ipme_init() != 1) temp_oserr(); flagallaliases = 1; - recips = argv + 3; + recips = argv + 4; while (*recips) { if (!saa_readyplus(&reciplist,1)) temp_nomem(); reciplist.sa[reciplist.len] = sauninit; diff -u orig/qmail-rspawn.c ./qmail-rspawn.c --- orig/qmail-rspawn.c 1998-06-15 06:53:16.000000000 -0400 +++ ./qmail-rspawn.c 2004-07-19 12:06:45.000000000 -0400 @@ -77,18 +77,19 @@ } } -int spawn(fdmess,fdout,s,r,at) +int spawn(fdmess,fdout,s,qqeh,r,at) int fdmess; int fdout; -char *s; char *r; int at; +char *s; char *qqeh; char *r; int at; { int f; - char *(args[5]); + char *(args[6]); args[0] = "qmail-remote"; args[1] = r + at + 1; args[2] = s; - args[3] = r; - args[4] = 0; + args[3] = qqeh; + args[4] = r; + args[5] = 0; if (!(f = vfork())) { diff -u orig/qmail-send.c ./qmail-send.c --- orig/qmail-send.c 1998-06-15 06:53:16.000000000 -0400 +++ ./qmail-send.c 2004-07-19 21:11:37.000000000 -0400 @@ -195,8 +195,9 @@ /* this file is too long ---------------------------------------------- INFO */ -int getinfo(sa,dt,id) +int getinfo(sa,eh,dt,id) stralloc *sa; +stralloc *eh; datetime_sec *dt; unsigned long id; { @@ -212,14 +213,22 @@ if (fdinfo == -1) return 0; if (fstat(fdinfo,&st) == -1) { close(fdinfo); return 0; } substdio_fdbuf(&ss,read,fdinfo,buf,sizeof(buf)); - if (getln(&ss,&line,&match,'\0') == -1) { close(fdinfo); return 0; } + sa->len = eh->len = 0; + for (;;) { + if (getln(&ss,&line,&match,'\0') == -1) { close(fdinfo); return 0; } + if (!match) break; + if (line.s[0] == 'F') { + while (!stralloc_copys(sa,line.s + 1)) nomem(); + } + if (line.s[0] == 'e') { + while (!stralloc_copys(eh,line.s + 1)) nomem(); + } + } close(fdinfo); - if (!match) return 0; - if (line.s[0] != 'F') return 0; + while (!stralloc_0(sa)) nomem(); + while (!stralloc_0(eh)) nomem(); *dt = st.st_mtime; - while (!stralloc_copys(sa,line.s + 1)) nomem(); - while (!stralloc_0(sa)) nomem(); return 1; } @@ -250,11 +259,12 @@ return 1; } -void comm_write(c,delnum,id,sender,recip) +void comm_write(c,delnum,id,sender,qqeh,recip) int c; int delnum; unsigned long id; char *sender; +char *qqeh; char *recip; { char ch; @@ -267,6 +277,8 @@ while (!stralloc_0(&comm_buf[c])) nomem(); senderadd(&comm_buf[c],sender,recip); while (!stralloc_0(&comm_buf[c])) nomem(); + while (!stralloc_cats(&comm_buf[c],qqeh)) nomem(); + while (!stralloc_0(&comm_buf[c])) nomem(); while (!stralloc_cats(&comm_buf[c],recip)) nomem(); while (!stralloc_0(&comm_buf[c])) nomem(); comm_pos[c] = 0; @@ -486,6 +498,7 @@ int channel; datetime_sec retry; stralloc sender; + stralloc qqeh; int numtodo; int flaghiteof; int flagdying; @@ -503,6 +516,7 @@ { jo[j].refs = 0; jo[j].sender.s = 0; + jo[j].qqeh.s = 0; } } @@ -658,11 +672,12 @@ char buf[128]; char inbuf[128]; static stralloc sender = {0}; + static stralloc qqeh = {0}; static stralloc quoted = {0}; datetime_sec birth; unsigned long qp; - if (!getinfo(&sender,&birth,id)) return 0; /* XXX: print warning */ + if (!getinfo(&sender,&qqeh,&birth,id)) return 0; /* XXX: print warning */ /* owner-@host-@[] -> owner-@host */ if (sender.len >= 5) @@ -855,7 +870,7 @@ d[c][i].mpos = mpos; d[c][i].used = 1; ++concurrencyused[c]; - comm_write(c,i,jo[j].id,jo[j].sender.s,recip); + comm_write(c,i,jo[j].id,jo[j].sender.s,jo[j].qqeh.s,recip); strnum2[fmt_ulong(strnum2,d[c][i].delid)] = 0; strnum3[fmt_ulong(strnum3,jo[j].id)] = 0; @@ -1059,6 +1074,7 @@ datetime_sec birth; struct prioq_elt pe; static stralloc line = {0}; + static stralloc qqeh = {0}; int match; if (flagexitasap) return; @@ -1074,13 +1090,14 @@ pass[c].mpos = 0; pass[c].fd = open_read(fn.s); if (pass[c].fd == -1) goto trouble; - if (!getinfo(&line,&birth,pe.id)) { close(pass[c].fd); goto trouble; } + if (!getinfo(&line,&qqeh,&birth,pe.id)) { close(pass[c].fd); goto trouble; } pass[c].id = pe.id; substdio_fdbuf(&pass[c].ss,read,pass[c].fd,pass[c].buf,sizeof(pass[c].buf)); pass[c].j = job_open(pe.id,c); jo[pass[c].j].retry = nextretry(birth,c); jo[pass[c].j].flagdying = (recent > birth + lifetime); while (!stralloc_copy(&jo[pass[c].j].sender,&line)) nomem(); + while (!stralloc_copy(&jo[pass[c].j].qqeh,&qqeh)) nomem(); } if (!del_avail(c)) return; @@ -1346,8 +1363,15 @@ case 'p': scan_ulong(todoline.s + 1,&pid); break; + case 'e': + if (substdio_put(&ssinfo,todoline.s,todoline.len) == -1) + { + fnmake_info(id); + log3("warning: trouble writing to ",fn.s,"\n"); goto fail; + } + break; case 'F': - if (substdio_putflush(&ssinfo,todoline.s,todoline.len) == -1) + if (substdio_put(&ssinfo,todoline.s,todoline.len) == -1) { fnmake_info(id); log3("warning: trouble writing to ",fn.s,"\n"); goto fail; diff -u orig/spawn.c ./spawn.c --- orig/spawn.c 1998-06-15 06:53:16.000000000 -0400 +++ ./spawn.c 2004-07-19 12:06:46.000000000 -0400 @@ -68,6 +68,7 @@ int delnum; stralloc messid = {0}; stralloc sender = {0}; +stralloc qqeh = {0}; stralloc recip = {0}; void err(s) char *s; @@ -119,7 +120,7 @@ coe(pi[0]); - f = spawn(fdmess,pi[1],sender.s,recip.s,j); + f = spawn(fdmess,pi[1],sender.s,qqeh.s,recip.s,j); close(fdmess); if (f == -1) { close(pi[0]); close(pi[1]); err("Zqmail-spawn unable to fork. (#4.3.0)\n"); return; } @@ -163,8 +164,12 @@ case 2: if (!stralloc_append(&sender,&ch)) flagabort = 1; if (ch) break; - recip.len = 0; stage = 3; break; + qqeh.len = 0; stage = 3; break; case 3: + if (!stralloc_append(&qqeh,&ch)) flagabort = 1; + if (ch) break; + recip.len = 0; stage = 4; break; + case 4: if (!stralloc_append(&recip,&ch)) flagabort = 1; if (ch) break; docmd();