X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/77bb000fa965b786ddb1085dd5af6c80c7d425b0..6a8de8541c16d12eceab2c6610cd209e7641217a:/src/src/readconf.c?ds=sidebyside diff --git a/src/src/readconf.c b/src/src/readconf.c index adb62205d..6b11621e0 100644 --- a/src/src/readconf.c +++ b/src/src/readconf.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/readconf.c,v 1.40 2010/06/05 09:10:10 pdp Exp $ */ +/* $Cambridge: exim/src/src/readconf.c,v 1.43 2010/06/07 08:23:20 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,39 @@ 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_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. + 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 + another bit from opt_type to indicate "malloced"; this seems like + quite a hack, especially for this one case. It also means that + we can't ever reclaim the store from the *first* condition. + + 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 + { + *str_target = sptr; + freesptr = FALSE; + } + break; + case opt_rewrite: if (data_block == NULL) *((uschar **)(ol->value)) = sptr; @@ -2751,7 +2790,6 @@ void readconf_main(void) { int sep = 0; -long dummy_l; struct stat statbuf; uschar *s, *filename; uschar *list = config_main_filelist;