summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJeremy Harris <jgh146exb@wizmail.org>2012-07-08 22:49:18 +0100
committerJeremy Harris <jgh146exb@wizmail.org>2012-07-08 22:49:18 +0100
commit846726c5a374d833fb5211dde62ae6bceb6841c7 (patch)
tree2979952f9671639681283f694827bd3aa82d16d1 /src
parentb5b871aca49fbf0fcc2c91997e70c3c57f77faa9 (diff)
Multiple headers_add/remove options per router/transport - fixes bug 337
Diffstat (limited to 'src')
-rw-r--r--src/src/macros.h4
-rw-r--r--src/src/readconf.c32
-rw-r--r--src/src/route.c6
-rw-r--r--src/src/transport.c4
4 files changed, 25 insertions, 21 deletions
diff --git a/src/src/macros.h b/src/src/macros.h
index d25071aae..3ec94bc6d 100644
--- a/src/src/macros.h
+++ b/src/src/macros.h
@@ -624,7 +624,9 @@ for booleans that are kept in one bit. */
#define opt_public 0x200 /* Stored in the main instance block */
#define opt_set 0x400 /* Option is set */
#define opt_secure 0x800 /* "hide" prefix used */
-#define opt_mask 0x0ff
+#define opt_rep_con 0x1000 /* Can be appended to by a repeated line (condition) */
+#define opt_rep_str 0x2000 /* Can be appended to by a repeated line (string) */
+#define opt_mask 0x00ff
/* Verify types when directing and routing */
diff --git a/src/src/readconf.c b/src/src/readconf.c
index 087ab5b9b..ddd81d1d3 100644
--- a/src/src/readconf.c
+++ b/src/src/readconf.c
@@ -1374,7 +1374,6 @@ 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;
@@ -1437,16 +1436,9 @@ if (ol == NULL)
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, CS unknown_txt, name);
}
-if ((ol->type & opt_set) != 0)
- {
- uschar *mname = name;
- if (Ustrncmp(mname, "no_", 3) == 0) mname += 3;
- 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);
- }
+if ((ol->type & opt_set) && !(ol->type & (opt_rep_con | opt_rep_str)))
+ log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
+ "\"%s\" option set for the second time", name);
ol->type |= opt_set | issecure;
type = ol->type & opt_mask;
@@ -1530,7 +1522,7 @@ switch (type)
str_target = (uschar **)(ol->value);
else
str_target = (uschar **)((uschar *)data_block + (long int)(ol->value));
- if (extra_condition)
+ if (ol->type & opt_rep_con)
{
/* We already have a condition, we're conducting a crude hack to let
multiple condition rules be chained together, despite storing them in
@@ -1539,9 +1531,10 @@ switch (type)
strtemp = string_sprintf("${if and{{bool_lax{%s}}{bool_lax{%s}}}}",
saved_condition, sptr);
*str_target = string_copy_malloc(strtemp);
- /* TODO(pdp): there is a memory leak here when we set 3 or more
- conditions; I still don't understand the store mechanism enough
- to know what's the safe way to free content from an earlier store.
+ /* TODO(pdp): there is a memory leak here and just below
+ when we set 3 or more conditions; I still don't
+ understand the store mechanism enough to know
+ what's the safe way to free content from an earlier store.
AFAICT, stores stack, so freeing an early stored item also stores
all data alloc'd after it. If we knew conditions were adjacent,
we could survive that, but we don't. So I *think* we need to take
@@ -1552,6 +1545,15 @@ switch (type)
Because we only do this once, near process start-up, I'm prepared to
let this slide for the time being, even though it rankles. */
}
+ else if (*str_target && (ol->type & opt_rep_str))
+ {
+ uschar sep = Ustrncmp(name, "headers_add", 11)==0 ? '\n' : ':';
+ saved_condition = *str_target;
+ strtemp = saved_condition + strlen(saved_condition)-1;
+ if (*strtemp == sep) *strtemp = 0; /* eliminate trailing list-sep */
+ strtemp = string_sprintf("%s%c%s", saved_condition, sep, sptr);
+ *str_target = string_copy_malloc(strtemp);
+ }
else
{
*str_target = sptr;
diff --git a/src/src/route.c b/src/src/route.c
index 43ffc25a9..32dbd60ab 100644
--- a/src/src/route.c
+++ b/src/src/route.c
@@ -48,7 +48,7 @@ optionlist optionlist_routers[] = {
(void *)(offsetof(router_instance, caseful_local_part)) },
{ "check_local_user", opt_bool | opt_public,
(void *)(offsetof(router_instance, check_local_user)) },
- { "condition", opt_stringptr|opt_public,
+ { "condition", opt_stringptr|opt_public|opt_rep_con,
(void *)offsetof(router_instance, condition) },
{ "debug_print", opt_stringptr | opt_public,
(void *)offsetof(router_instance, debug_string) },
@@ -72,9 +72,9 @@ optionlist optionlist_routers[] = {
(void *)offsetof(router_instance, fallback_hosts) },
{ "group", opt_expand_gid | opt_public,
(void *)(offsetof(router_instance, gid)) },
- { "headers_add", opt_stringptr|opt_public,
+ { "headers_add", opt_stringptr|opt_public|opt_rep_str,
(void *)offsetof(router_instance, extra_headers) },
- { "headers_remove", opt_stringptr|opt_public,
+ { "headers_remove", opt_stringptr|opt_public|opt_rep_str,
(void *)offsetof(router_instance, remove_headers) },
{ "ignore_target_hosts",opt_stringptr|opt_public,
(void *)offsetof(router_instance, ignore_target_hosts) },
diff --git a/src/src/transport.c b/src/src/transport.c
index 9e533f63e..7c79bb009 100644
--- a/src/src/transport.c
+++ b/src/src/transport.c
@@ -68,11 +68,11 @@ optionlist optionlist_transports[] = {
(void *)(offsetof(transport_instance, envelope_to_add)) },
{ "group", opt_expand_gid|opt_public,
(void *)offsetof(transport_instance, gid) },
- { "headers_add", opt_stringptr|opt_public,
+ { "headers_add", opt_stringptr|opt_public|opt_rep_str,
(void *)offsetof(transport_instance, add_headers) },
{ "headers_only", opt_bool|opt_public,
(void *)offsetof(transport_instance, headers_only) },
- { "headers_remove", opt_stringptr|opt_public,
+ { "headers_remove", opt_stringptr|opt_public|opt_rep_str,
(void *)offsetof(transport_instance, remove_headers) },
{ "headers_rewrite", opt_rewrite|opt_public,
(void *)offsetof(transport_instance, headers_rewrite) },