Closing the gap slightly between qmail-local and procmail... I've
implemented a flow control feature in qmail-local for .qmail files.
If you have a sequence of lines like:
    ?label command arg ...
    ...
    :label
it'll deliver the message to the command, and if the command exits
with status 99, qmail-local will skip down to the `:label' line -
delivery instructions in the intervening lines are ignored.  `:' lines
are otherwise treated as comments.  A label is a (possibly empty)
sequence of non-space, non-tab, nonzero bytes.  Text following a label
on a `:' line is ignored.  If there is no command, it's an
unconditional jump.  If a command exits 99 and the corresponding label
is not found, all following delivery instructions are skipped (as with
`|command').  There are no backward jumps.  This makes the .qmail
language a little more useful, IMO, but not enough to cause
trouble. :)  (You get if-then-else, but not while.)  The syntax is a
little ugly, but it gets the job done.

The same functionality is already available with `|' command lines,
but then you need multiple .qmail files, which exposes extra addresses
to outside senders, so it gets a little more complicated.

Does anyone know:
- whether this has already been done?
- whether this is already in the works for qmail proper?
- whether this would be likely to be accepted into qmail proper?
  (Does DJB read this list?)

If you use it, let me know if it breaks, so I can fix it, or if it
works, so I'll have a feeling of accomplishment.  (It's passed my
tests.)

Also, while writing this I noticed what appears to be a bug:
qmail-local trims trailing whitespace from a delivery instruction
before processing it.  This breaks instructions like `|command foo\ '.
The fix, I guess, would be to do the trimming only for lines beginning
with other than `|' (and `?', and, as long as we're special-casing,
`#', to save a few cycles).  mbox files could have names ending in
spaces, too, but if whitespace were left at the end of `.' and `/'
lines, then `./foo/ ' would be reinterpreted as an mbox instead of a
maildir, as it is now, so that might not be a good idea.

Here's the diff -u:
--------8<--------
--- qmail-local.c       Sat Jun 17 05:02:16 2000
+++ qmail-local.c~      Mon Jun 15 05:53:16 1998
@@ -653,7 +653,6 @@
         if (i) break;
          strerr_die1x(111,"Uh-oh: first line of .qmail file is blank. (#4.2.1)");
        case '#':
-       case ':':
          break;
        case '.':
        case '/':
@@ -671,46 +670,6 @@
         if (flagforwardonly) strerr_die1x(111,"Uh-oh: .qmail has prog delivery but 
has x bit set. (#4.7.0)");
          if (flagdoit) mailprogram(cmds.s + i + 1);
          else sayit("program ",cmds.s + i + 1,k - i - 1);
-         break;
-       case '?':
-         ++i;
-         {
-           int l;
-           for (l = i;l < k;++l)
-             if (cmds.s[l] == ' ' || cmds.s[l] == '\t') {
-               cmds.s[l] = 0;
-               for (++l;l < k;++l)
-                 if (cmds.s[l] != ' ' && cmds.s[l] != '\t') {
-                   ++count_program;
-                   if (flagforwardonly) strerr_die1x(111,"Uh-oh: .qmail has prog 
delivery but has x bit set. (#4.7.0)");
-                   if (flagdoit) mailprogram(cmds.s + l);
-                   else sayit("program ",cmds.s + l,k - l);
-                   break;
-                 }
-               break;
-             }
-           if (l == k || flag99) {
-             flag99 = 0;
-             cmds.s[j] = '\n';
-             for (;j + 1 < cmds.len;++j)
-               if (cmds.s[j] == '\n' && cmds.s[j + 1] == ':') {
-                 j += 2;
-                 l = j;
-                 for (; j < cmds.len;++j) {
-                   if (cmds.s[j] == 0) break;
-                   if (cmds.s[j] == '\t') break;
-                   if (cmds.s[j] == '\n') break;
-                   if (cmds.s[j] == ' ') break;
-                 }
-                 if (!str_diffn(cmds.s + i,cmds.s + l,j - l)) {
-                   for (; j < cmds.len;++j)
-                     if (cmds.s[j] == '\n') break;
-                   break;
-                 }
-                 --j;
-               }
-           }
-         }
          break;
        case '+':
         if (str_equal(cmds.s + i + 1,"list"))
--------8<--------


paul

Reply via email to