2007-08-27 Version 2.0 of the patch (netqmail 1.05 version) WARNING, NEW BEHAVIOUR: The patch is using descriptor 6 instead of fd 4 now! fd 4 is also used by qmail-qfilter, so this patch is using fd 6. Hopefully forever now :) Thanks to Amitai Schlair for finding this and including the patch the pkgsrc qmail package. 2005-05-27 WARNING, NEW BEHAVIOUR: The patch is using descriptor 4 instead of STDERR now! Adds the possibility for a qmail-queue-replacement to offer custom error (=bounce) messages. You have to write the error message to filedescriptor 4 and exit 82, in order to use the custom message. Format of the message: Dthis is a custom fatal error message Zthis is a custom temporary failure message Thanks to Richard Lyons for spotting a wrong errstr declaration. Thanks to Jeremy Hinton for noting that I forget to include the patch to qmail.h This patch has been made by Flavio Curti and is provided AS IS. Do with it as you wish, I'm not responsible for anything that breaks because of this patch. EXAMPLES Perl: open(FD,">&6"); print FD "Ztemporary failure message"; close(FD); exit(82); Shell: echo -n "Zpermanent failure after data" >&4 exit 82; C (non-djb-style): #include #include #include char err[] = "Zpermanently refusing"; int main() { write(6,err,(strlen(err)+1)); exit(82); } --- netqmail-1.05.orig/qmail.c Mon Apr 4 03:54:50 2005 +++ netqmail-1.05/qmail.c Mon Apr 4 03:57:59 2005 @@ -23,22 +23,32 @@ { int pim[2]; int pie[2]; + int pierr[2]; setup_qqargs(); if (pipe(pim) == -1) return -1; if (pipe(pie) == -1) { close(pim[0]); close(pim[1]); return -1; } + if (pipe(pierr) == -1) { + close(pim[0]); close(pim[1]); + close(pie[0]); close(pie[1]); + close(pierr[0]); close(pierr[1]); + return -1; + } switch(qq->pid = vfork()) { case -1: + close(pierr[0]); close(pierr[1]); close(pim[0]); close(pim[1]); close(pie[0]); close(pie[1]); return -1; case 0: close(pim[1]); close(pie[1]); + close(pierr[0]); /* we want to receive data */ if (fd_move(0,pim[0]) == -1) _exit(120); if (fd_move(1,pie[0]) == -1) _exit(120); + if (fd_move(6,pierr[1]) == -1) _exit(120); if (chdir(auto_qmail) == -1) _exit(61); execv(*binqqargs,binqqargs); _exit(120); @@ -46,6 +56,7 @@ qq->fdm = pim[1]; close(pim[0]); qq->fde = pie[1]; close(pie[0]); + qq->fderr = pierr[0]; close(pierr[1]); substdio_fdbuf(&qq->ss,write,qq->fdm,qq->buf,sizeof(qq->buf)); qq->flagerr = 0; return 0; @@ -93,10 +104,22 @@ { int wstat; int exitcode; + int match; + char ch; + static char errstr[256]; + int len = 0; qmail_put(qq,"",1); if (!qq->flagerr) if (substdio_flush(&qq->ss) == -1) qq->flagerr = 1; close(qq->fde); + substdio_fdbuf(&qq->ss,read,qq->fderr,qq->buf,sizeof(qq->buf)); + while( substdio_bget(&qq->ss,&ch,1) && len < 255){ + errstr[len]=ch; + len++; + } + if (len > 0) errstr[len]='\0'; /* add str-term */ + + close(qq->fderr); if (wait_pid(&wstat,qq->pid) != qq->pid) return "Zqq waitpid surprise (#4.3.0)"; @@ -129,8 +152,11 @@ case 81: return "Zqq internal bug (#4.3.0)"; case 120: return "Zunable to exec qq (#4.3.0)"; default: + if (exitcode == 82 && len > 2){ + return errstr; + } if ((exitcode >= 11) && (exitcode <= 40)) - return "Dqq permanent problem (#5.3.0)"; + return "Dqq permanent problem (#5.3.0)"; return "Zqq temporary problem (#4.3.0)"; } } --- netqmail-1.05.orig/qmail.h Mon Jun 15 12:53:16 1998 +++ netqmail-1.05/qmail.h Mon Apr 4 03:55:56 2005 @@ -8,6 +8,7 @@ unsigned long pid; int fdm; int fde; + int fderr; substdio ss; char buf[1024]; } ;