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