Modified Gentoo qmail with custom-smtp-reject patch

From Qmailwiki
Jump to: navigation, search

This article explains how you can modify your gentoo qmail ebuild to include the custom smtp rejection patch and keep enjoying a safe portage-managed system.

Contents

Create a portage overlay

First you need a portage overlay directory. Normally, portage searches for its ebuilds in /usr/portage, where the official gentoo ebuilds are stored. An overlay is an ebuild directory where portage will look before checking the official ebuild repository.

You create a portage overlay by adding the following line to your /etc/make.conf:

# /etc/make.conf

# Add this line to set up a portage overlay
PORTDIR_OVERLAY="/usr/local/portage"

Of course, if you don't have a /usr/local/portage directory yet, you'll have to create it.

Clone the qmail ebuild

Simple: Copy the official qmail ebuild into your portage overlay at /usr/local/portage. Also create the category directory so the qmail ebuild will be located at (as full path) /usr/local/portage/mail-mta/qmail:

mkdir -p /usr/local/portage/mail-mta/qmail
cp -R /usr/portage/mail-mta/qmail /usr/local/portage/mail-mta/qmail

Add the custom smtp reject patch

I've modified the custom smtp reject patch so it will work with together with all the patches currently applied to the gentoo qmail build (including the qmail-queue patch) as of qmail-1.03-r16.

Paste the following lines into a new files named /usr/local/portage/mail-mta/qmail/files/qmail-queue-custom-error.patch:

% diff -u3 qmail.c.orig qmail.c
--- qmail.c.orig        1998-06-15 12:53:16.000000000 +0200
+++ qmail.c     2004-10-13 22:35:37.000000000 +0200
@@ -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(4,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,6 +152,9 @@
     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 "Zqq temporary problem (#4.3.0)";


% diff -u3 qmail.h.orig qmail.h
--- qmail.h.orig        1998-06-15 12:53:16.000000000 +0200
+++ qmail.h     2004-05-26 14:48:23.000000000 +0200
@@ -8,6 +8,7 @@
   unsigned long pid;
   int fdm;
   int fde;
+  int fderr;
   substdio ss;
   char buf[1024];
 } ;

Modify your qmail ebuild

Another easy one. Open up your cloned qmail ebuild at /usr/local/portage/mail-mta/qmail/qmail-1.03-r16.ebuild in your favorite editor and scroll down to the end of the function src_unpack(). You'll see a lot of patches being applied using the epatch command. Add the command

epatch ${FILESDIR}/qmail-queue-custom-error.patch

as the very last line into that function so that region of the ebuild file looks like this:

        echo -n "$(tc-getCC) ${LDFLAGS}" > ${S}/conf-ld
        echo -n "500" > ${S}/conf-spawn

        # fix coreutils messup
        ht_fix_file ${S}/Makefile

        # custom smtp reject patch
        epatch ${FILESDIR}/qmail-queue-custom-error.patch
}

src_compile() {
        emake it man || die

After you've modified the ebuild, you also have to update its md5 checksums by typing

ebuild qmail-1.03-r16.ebuild digest

Test it

Just as you would normally, type

emerge qmail

to emerge your modified qmail. While the build is progressing, you can press ctrl+s to freeze the console and watch for the qmail-queue-custom-error.patch line to be sure everything worked out as expected. To continue after you freezed the console, press ctrl+q.

Troubleshooting

Patch Failing

For whatever reason, I was having troubles with the patch as documented above--it kept failing on hunk 1 of 4 for qmail.c. However all other stuff looked correct.

I manually re-diffed the file, and ended up with a patch that worked. In the case you're having patch issues with the qmail-1.03-r16.ebuild as I was, try using this instead. Everything else in this article worked fine. It should also be noted that none of the USE flags were enabled for the ebuild in diff'ing this patch. Not sure if that has bearing on the diff result or not.

--- qmail.c.orig        2006-05-18 14:03:57.000000000 -0400
+++ qmail.c     2006-05-18 14:04:04.000000000 -0400
@@ -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(4,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,11 +104,23 @@
 {
   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)";
   if (wait_crashed(wstat))
@@ -129,6 +152,9 @@
     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 "Zqq temporary problem (#4.3.0)";

--- qmail.h.orig        2006-05-18 14:04:00.000000000 -0400
+++ qmail.h     2006-05-18 14:04:05.000000000 -0400
@@ -8,6 +8,7 @@
   unsigned long pid;
   int fdm;
   int fde;
+  int fderr;
   substdio ss;
   char buf[1024];
 } ;

Bdowne01 13:17, 18 May 2006 (CDT)

Personal tools