summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPhilip Hazel <ph10@hermes.cam.ac.uk>2007-02-06 10:00:24 +0000
committerPhilip Hazel <ph10@hermes.cam.ac.uk>2007-02-06 10:00:24 +0000
commit0ce9abe687c08503facdd9f4f94dfa27ada83da9 (patch)
treef5fa00b073bf46c891bdd26ecce2d8ae08449418 /src
parent047bdd8ce4bf9cc9fd22fb22a2ebaf190d492343 (diff)
Add forany/forall (Marcus Holmgren's patch, basically).
Diffstat (limited to 'src')
-rw-r--r--src/ACKNOWLEDGMENTS5
-rw-r--r--src/src/expand.c69
-rw-r--r--src/src/globals.c3
-rw-r--r--src/src/globals.h3
4 files changed, 75 insertions, 5 deletions
diff --git a/src/ACKNOWLEDGMENTS b/src/ACKNOWLEDGMENTS
index 1a39046c3..d9238db38 100644
--- a/src/ACKNOWLEDGMENTS
+++ b/src/ACKNOWLEDGMENTS
@@ -1,4 +1,4 @@
-$Cambridge: exim/src/ACKNOWLEDGMENTS,v 1.71 2007/01/31 16:52:12 ph10 Exp $
+$Cambridge: exim/src/ACKNOWLEDGMENTS,v 1.72 2007/02/06 10:00:24 ph10 Exp $
EXIM ACKNOWLEDGEMENTS
@@ -20,7 +20,7 @@ relatively small patches.
Philip Hazel
Lists created: 20 November 2002
-Last updated: 31 January 2007
+Last updated: 06 February 2007
THE OLD LIST
@@ -168,6 +168,7 @@ Magnus Holmgren Patch for filter_prepend_home
Patch for "h" flag in Domain Keys
Patch for $sending_ip_address/$sending_port
Patch for ${rfc2047d:
+ ... and several more
Lots of other maintenance support
Kjetil Torgrim Homme Patch for require_files problem on NFS file systems
Tom Hughes Suggested patch for $n bug in pipe command from filter
diff --git a/src/src/expand.c b/src/src/expand.c
index b2674dd42..1409437d4 100644
--- a/src/src/expand.c
+++ b/src/src/expand.c
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/expand.c,v 1.79 2007/01/31 11:30:08 ph10 Exp $ */
+/* $Cambridge: exim/src/src/expand.c,v 1.80 2007/02/06 10:00:24 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -240,6 +240,8 @@ static uschar *cond_table[] = {
US"eqi",
US"exists",
US"first_delivery",
+ US"forall",
+ US"forany",
US"ge",
US"gei",
US"gt",
@@ -279,6 +281,8 @@ enum {
ECOND_STR_EQI,
ECOND_EXISTS,
ECOND_FIRST_DELIVERY,
+ ECOND_FORALL,
+ ECOND_FORANY,
ECOND_STR_GE,
ECOND_STR_GEI,
ECOND_STR_GT,
@@ -420,6 +424,7 @@ static var_entry var_table[] = {
{ "inode", vtype_ino, &deliver_inode },
{ "interface_address", vtype_stringptr, &interface_address },
{ "interface_port", vtype_int, &interface_port },
+ { "item", vtype_stringptr, &iterate_item },
#ifdef LOOKUP_LDAP
{ "ldap_dn", vtype_stringptr, &eldap_dn },
#endif
@@ -2349,6 +2354,68 @@ switch(cond_type)
return ++s;
+ /* forall/forany: iterates a condition with different values */
+
+ case ECOND_FORALL:
+ case ECOND_FORANY:
+ {
+ int sep = 0;
+ uschar *iterate_item_save = iterate_item;
+
+ while (isspace(*s)) s++;
+ if (*s++ != '{') goto COND_FAILED_CURLY_START;
+
+ sub[0] = expand_string_internal(s, TRUE, &s, (yield == NULL));
+ if (sub[0] == NULL) return NULL;
+ if (*s++ != '}') goto COND_FAILED_CURLY_END;
+
+ while (isspace(*s)) s++;
+ if (*s++ != '{') goto COND_FAILED_CURLY_START;
+
+ sub[1] = s;
+
+ /* Call eval_condition once, with result discarded (as if scanning a
+ "false" part). This allows us to find the end of the condition, because if
+ the list it empty, we won't actually evaluate the condition for real. */
+
+ s = eval_condition(sub[1], NULL);
+ if (s == NULL)
+ {
+ expand_string_message = string_sprintf("%s inside \"%s\" condition",
+ expand_string_message, name);
+ return NULL;
+ }
+ while (isspace(*s)) s++;
+
+ if (*s++ != '}')
+ {
+ expand_string_message = string_sprintf("missing } at end of condition "
+ "inside \"%s\"", name);
+ return NULL;
+ }
+
+ if (yield != NULL) *yield = !testfor;
+ while ((iterate_item = string_nextinlist(&sub[0], &sep, NULL, 0)) != NULL)
+ {
+ DEBUG(D_expand) debug_printf("%s: $item = \"%s\"\n", name, iterate_item);
+ if (eval_condition(sub[1], &tempcond) == NULL)
+ {
+ expand_string_message = string_sprintf("%s inside \"%s\" condition",
+ expand_string_message, name);
+ return NULL;
+ }
+ DEBUG(D_expand) debug_printf("%s: condition evaluated to %s\n", name,
+ tempcond? "true":"false");
+
+ if (yield != NULL) *yield = (tempcond == testfor);
+ if (tempcond == (cond_type == ECOND_FORANY)) break;
+ }
+
+ iterate_item = iterate_item_save;
+ return s;
+ }
+
+
/* Unknown condition */
default:
diff --git a/src/src/globals.c b/src/src/globals.c
index b3bbd7faf..4d790ee9e 100644
--- a/src/src/globals.c
+++ b/src/src/globals.c
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/globals.c,v 1.68 2007/02/05 12:35:46 ph10 Exp $ */
+/* $Cambridge: exim/src/src/globals.c,v 1.69 2007/02/06 10:00:24 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -630,6 +630,7 @@ uschar *ignore_fromline_hosts = NULL;
uschar *interface_address = NULL;
int interface_port = -1;
BOOL is_inetd = FALSE;
+uschar *iterate_item = NULL;
int journal_fd = -1;
diff --git a/src/src/globals.h b/src/src/globals.h
index 570e4c87b..77662b376 100644
--- a/src/src/globals.h
+++ b/src/src/globals.h
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/globals.h,v 1.48 2007/02/05 12:35:46 ph10 Exp $ */
+/* $Cambridge: exim/src/src/globals.h,v 1.49 2007/02/06 10:00:24 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -385,6 +385,7 @@ extern int ignore_bounce_errors_after; /* Keep them for this time. */
extern BOOL ignore_fromline_local; /* Local SMTP ignore fromline */
extern uschar *ignore_fromline_hosts; /* Hosts permitted to send "From " */
extern BOOL is_inetd; /* True for inetd calls */
+extern uschar *iterate_item; /* Item from iterate list */
extern int journal_fd; /* Fd for journal file */