Allow Routers to have multiple conditions, IF each one yields a strict bool.
authorPhil Pennock <pdp@exim.org>
Mon, 7 Jun 2010 07:09:10 +0000 (07:09 +0000)
committerPhil Pennock <pdp@exim.org>
Mon, 7 Jun 2010 07:09:10 +0000 (07:09 +0000)
Fixes: #816

doc/doc-docbook/spec.xfpt
doc/doc-txt/ChangeLog
doc/doc-txt/NewStuff
src/src/readconf.c

index 7a9698e57428fd7d0360d183116de32edffb8b09..dd8db236733e8bcec2c471ad6290df5452516504 100644 (file)
@@ -1,4 +1,4 @@
-. $Cambridge: exim/doc/doc-docbook/spec.xfpt,v 1.82 2010/06/06 02:08:50 pdp Exp $
+. $Cambridge: exim/doc/doc-docbook/spec.xfpt,v 1.83 2010/06/07 07:09:10 pdp Exp $
 .
 . /////////////////////////////////////////////////////////////////////////////
 . This is the primary source of the Exim Manual. It is an xfpt document that is
@@ -15669,6 +15669,12 @@ router is skipped, and the address is offered to the next one.
 If the result is any other value, the router is run (as this is the last
 precondition to be evaluated, all the other preconditions must be true).
 
+This option is unique in that multiple &%condition%& options may be present.
+In this case, the previous statement does not quite apply: the result of each
+&%condition%& option must be a string recognised by the &%bool%& expansion
+operator, or failure will be forced.  The effect is to "and" the conditions
+together, as each must pass.
+
 The &%condition%& option provides a means of applying custom conditions to the
 running of routers. Note that in the case of a simple conditional expansion,
 the default expansion values are exactly what is wanted. For example:
@@ -15679,6 +15685,11 @@ Because of the default behaviour of the string expansion, this is equivalent to
 .code
 condition = ${if >{$message_age}{600}{true}{}}
 .endd
+A multiple condition example:
+.code
+condition = ${if >{$message_age}{600}}
+condition = ${if !eq{${lc:$local_part}}{postmaster}}
+.endd
 If the expansion fails (other than forced failure) delivery is deferred. Some
 of the other precondition options are common special cases that could in fact
 be specified using &%condition%&.
index f5fbbd6399b528e4769c89064add6b352f01672f..65d5d2dc9e2b869588297dd5160e9f1b808700d5 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.627 2010/06/06 22:46:33 pdp Exp $
+$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.628 2010/06/07 07:09:10 pdp Exp $
 
 Change log file for Exim from version 4.21
 -------------------------------------------
@@ -44,6 +44,8 @@ PP/13 Bugzilla 752: Refuse to build/run if Exim user is root/0.
 
 PP/14 Build without WITH_CONTENT_SCAN. Path from Andreas Metzler.
 
+PP/15 Bugzilla 816: support multiple condition rules on Routers.
+
 
 Exim version 4.72
 -----------------
index 03c0d4833f900ccface38360850b478b91295712..559a9f4c0f7efa0cc24c99e28bf4054519e94290 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/NewStuff,v 1.172 2010/06/06 02:46:13 pdp Exp $
+$Cambridge: exim/doc/doc-txt/NewStuff,v 1.173 2010/06/07 07:09:10 pdp Exp $
 
 New Features in Exim
 --------------------
@@ -75,6 +75,15 @@ Version 4.73
     then henceforth you will have to maintain your own local patches to strip
     the safeties off.
 
+ 8. Routers now support multiple "condition" tests, IF each router yields
+    a string which the bool{} operator recognises.  Note that this is a departure
+    from normal Router "condition" truth, requiring the stricter standard of
+    "true" that ACLS use.  This might be relaxed in a future release if there
+    is sufficient demand.
+    When debugging, bear in mind that these are internally wrapped up into
+    a longer, more complicated, string.  There's a reason that the bool{}
+    logic is a dependency.
+
 
 Version 4.72
 ------------
index fbba2069087e50fad83b09962b2a0eefc0c753d0..6fd0dd8ea975095d234aec2be9ebfad69ba293a3 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/readconf.c,v 1.41 2010/06/07 00:12:42 pdp Exp $ */
+/* $Cambridge: exim/src/src/readconf.c,v 1.42 2010/06/07 07:09:10 pdp Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -1358,6 +1358,7 @@ uid_t uid;
 gid_t gid;
 BOOL boolvalue = TRUE;
 BOOL freesptr = TRUE;
+BOOL extra_condition = FALSE;
 optionlist *ol, *ol2;
 struct passwd *pw;
 void *reset_point;
@@ -1365,6 +1366,8 @@ int intbase = 0;
 uschar *inttype = US"";
 uschar *sptr;
 uschar *s = buffer;
+uschar *saved_condition, *strtemp;
+uschar **str_target;
 uschar name[64];
 uschar name2[64];
 
@@ -1422,8 +1425,11 @@ if ((ol->type & opt_set) != 0)
   {
   uschar *mname = name;
   if (Ustrncmp(mname, "no_", 3) == 0) mname += 3;
-  log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
-    "\"%s\" option set for the second time", mname);
+  if (Ustrcmp(mname, "condition") == 0)
+    extra_condition = TRUE;
+  else
+    log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
+      "\"%s\" option set for the second time", mname);
   }
 
 ol->type |= opt_set | issecure;
@@ -1504,6 +1510,26 @@ switch (type)
     control block and flags word. */
 
     case opt_stringptr:
+    if (data_block == NULL)
+      str_target = (uschar **)(ol->value);
+    else
+      str_target = (uschar **)((uschar *)data_block + (long int)(ol->value));
+    if (extra_condition)
+      {
+      /* We already have a condition, we're conducting a crude hack to let multiple
+      condition rules be chained together, despite storing them in text form. */
+      saved_condition = *str_target;
+      strtemp = string_sprintf("${if and{{bool{%s}}{bool{%s}}}}",
+          saved_condition, sptr);
+      *str_target = string_copy_malloc(strtemp);
+      }
+    else
+      {
+      *str_target = sptr;
+      freesptr = FALSE;
+      }
+    break;
+
     case opt_rewrite:
     if (data_block == NULL)
       *((uschar **)(ol->value)) = sptr;