diff options
author | Philip Hazel <ph10@hermes.cam.ac.uk> | 2006-09-19 11:28:44 +0000 |
---|---|---|
committer | Philip Hazel <ph10@hermes.cam.ac.uk> | 2006-09-19 11:28:44 +0000 |
commit | 38a0a95ff69327042421b9ee6982e386175f141b (patch) | |
tree | 30f841f97c161410d550780e3fa3aa47e6afe5b8 /src | |
parent | d45b1de81aa47cef4ca098a4b2725d855b154162 (diff) |
Apply Jakob Hirsch's patch for arbitrary ACL variable names, tidied up
just a little bit.
Diffstat (limited to 'src')
-rw-r--r-- | src/ACKNOWLEDGMENTS | 5 | ||||
-rw-r--r-- | src/exim_monitor/em_globals.c | 7 | ||||
-rw-r--r-- | src/exim_monitor/em_queue.c | 25 | ||||
-rw-r--r-- | src/src/acl.c | 113 | ||||
-rw-r--r-- | src/src/config.h.defaults | 5 | ||||
-rw-r--r-- | src/src/expand.c | 67 | ||||
-rw-r--r-- | src/src/functions.h | 5 | ||||
-rw-r--r-- | src/src/globals.c | 6 | ||||
-rw-r--r-- | src/src/globals.h | 6 | ||||
-rw-r--r-- | src/src/readconf.c | 3 | ||||
-rw-r--r-- | src/src/smtp_in.c | 13 | ||||
-rw-r--r-- | src/src/spool_in.c | 71 | ||||
-rw-r--r-- | src/src/spool_out.c | 19 | ||||
-rw-r--r-- | src/src/structs.h | 4 | ||||
-rw-r--r-- | src/src/tree.c | 24 |
15 files changed, 244 insertions, 129 deletions
diff --git a/src/ACKNOWLEDGMENTS b/src/ACKNOWLEDGMENTS index c04f4018c..43b171e00 100644 --- a/src/ACKNOWLEDGMENTS +++ b/src/ACKNOWLEDGMENTS @@ -1,4 +1,4 @@ -$Cambridge: exim/src/ACKNOWLEDGMENTS,v 1.54 2006/07/26 14:39:13 ph10 Exp $ +$Cambridge: exim/src/ACKNOWLEDGMENTS,v 1.55 2006/09/19 11:28:44 ph10 Exp $ EXIM ACKNOWLEDGEMENTS @@ -20,7 +20,7 @@ relatively small patches. Philip Hazel Lists created: 20 November 2002 -Last updated: 25 July 2006 +Last updated: 19 September 2006 THE OLD LIST @@ -158,6 +158,7 @@ Steve Haslam Lots of stuff, including Sheldon Hearn Suggested patch for smtp_accept_max_nonmail_hosts Bryan Henderson Patch to use RM_COMMAND everywhere during building Jakob Hirsch Patch for % operator + Patch for arbitrarily named ACL variables Magnus Holmgren Patch for filter_prepend_home Patch for "h" flag in Domain Keys Kjetil Torgrim Homme Patch for require_files problem on NFS file systems diff --git a/src/exim_monitor/em_globals.c b/src/exim_monitor/em_globals.c index 621d8b207..361ac4e78 100644 --- a/src/exim_monitor/em_globals.c +++ b/src/exim_monitor/em_globals.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/exim_monitor/em_globals.c,v 1.9 2006/02/07 11:18:59 ph10 Exp $ */ +/* $Cambridge: exim/src/exim_monitor/em_globals.c,v 1.10 2006/09/19 11:28:45 ph10 Exp $ */ /************************************************* * Exim Monitor * @@ -117,9 +117,8 @@ that fires up the monitor fishes the value out by using -bP anyway. */ #define SPOOL_DIRECTORY "" #endif - -uschar *acl_var[ACL_CVARS + ACL_MVARS]; - +tree_node *acl_var_c = NULL; +tree_node *acl_var_m = NULL; uschar *active_hostname = NULL; BOOL allow_unqualified_recipient = FALSE; BOOL allow_unqualified_sender = FALSE; diff --git a/src/exim_monitor/em_queue.c b/src/exim_monitor/em_queue.c index ec54116a0..212b15136 100644 --- a/src/exim_monitor/em_queue.c +++ b/src/exim_monitor/em_queue.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/exim_monitor/em_queue.c,v 1.4 2006/02/14 14:26:15 ph10 Exp $ */ +/* $Cambridge: exim/src/exim_monitor/em_queue.c,v 1.5 2006/09/19 11:28:45 ph10 Exp $ */ /************************************************* * Exim Monitor * @@ -125,6 +125,29 @@ store_free(p); /************************************************* +* Set up an ACL variable * +*************************************************/ + +/* The spool_read_header() function calls acl_var_create() when it reads in an +ACL variable. We know that in this case, the variable will be new, not re-used, +so this is a cut-down version, to save including the whole acl.c module (which +would need conditional compilation to cut most of it out). */ + +tree_node * +acl_var_create(uschar *name) +{ +tree_node *node, **root; +root = (name[0] == 'c')? &acl_var_c : &acl_var_m; +node = store_get(sizeof(tree_node) + Ustrlen(name)); +Ustrcpy(node->name, name); +node->data.ptr = NULL; +(void)tree_insertnode(root, node); +return node; +} + + + +/************************************************* * Set up new queue item * *************************************************/ diff --git a/src/src/acl.c b/src/src/acl.c index 6c06e466c..8c2ab699a 100644 --- a/src/src/acl.c +++ b/src/src/acl.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/acl.c,v 1.63 2006/09/05 14:05:43 ph10 Exp $ */ +/* $Cambridge: exim/src/src/acl.c,v 1.64 2006/09/19 11:28:45 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -805,36 +805,44 @@ while ((s = (*func)()) != NULL) /* The "set" modifier is different in that its argument is "name=value" rather than just a value, and we can check the validity of the name, which - gives us a variable number to insert into the data block. */ + gives us a variable name to insert into the data block. The original ACL + variable names were acl_c0 ... acl_c9 and acl_m0 ... acl_m9. This was + extended to 20 of each type, but after that people successfully argued for + arbitrary names. For compatibility, however, the names must still start with + acl_c or acl_m. After that, we allow alphanumerics and underscores. */ if (c == ACLC_SET) { - int offset, max, n; uschar *endptr; - if (Ustrncmp(s, "acl_", 4) != 0) goto BAD_ACL_VAR; - if (s[4] == 'c') + if (Ustrncmp(s, "acl_c", 5) != 0 && + Ustrncmp(s, "acl_m", 5) != 0) { - offset = 0; - max = ACL_CVARS; + *error = string_sprintf("invalid variable name after \"set\" in ACL " + "modifier \"set %s\" (must start \"acl_c\" or \"acl_m\")", s); + return NULL; } - else if (s[4] == 'm') + + endptr = s + 5; + while (*endptr != 0 && *endptr != '=' && !isspace(*endptr)) { - offset = ACL_CVARS; - max = ACL_MVARS; + if (!isalnum(*endptr) && *endptr != '_') + { + *error = string_sprintf("invalid character \"%c\" in variable name " + "in ACL modifier \"set %s\"", *endptr, s); + return NULL; + } + endptr++; } - else goto BAD_ACL_VAR; - n = Ustrtoul(s + 5, &endptr, 10); - if ((*endptr != 0 && *endptr != '=' && !isspace(*endptr)) || n >= max) + if (endptr - s < 6) { - BAD_ACL_VAR: - *error = string_sprintf("syntax error or unrecognized name after " - "\"set\" in ACL modifier \"set %s\"", s); + *error = string_sprintf("invalid variable name after \"set\" in ACL " + "modifier \"set %s\" (must be at least 6 characters)", s); return NULL; } - cond->u.varnumber = n + offset; + cond->u.varname = string_copyn(s + 4, endptr - s - 4); s = endptr; while (isspace(*s)) s++; } @@ -2426,11 +2434,8 @@ for (; cb != NULL; cb = cb->next) if (cb->type == ACLC_SET) { - int n = cb->u.varnumber; - int t = (n < ACL_CVARS)? 'c' : 'm'; - if (n >= ACL_CVARS) n -= ACL_CVARS; - debug_printf("acl_%c%d ", t, n); - lhswidth += 7; + debug_printf("acl_%s ", cb->u.varname); + lhswidth += 5 + Ustrlen(cb->u.varname); } debug_printf("= %s\n", cb->arg); @@ -2926,8 +2931,8 @@ for (; cb != NULL; cb = cb->next) case ACLC_SET: { int old_pool = store_pool; - if (cb->u.varnumber < ACL_CVARS) store_pool = POOL_PERM; - acl_var[cb->u.varnumber] = string_copy(arg); + if (cb->u.varname[0] == 'c') store_pool = POOL_PERM; + acl_var_create(cb->u.varname)->data.ptr = string_copy(arg); store_pool = old_pool; } break; @@ -3597,4 +3602,64 @@ if (rc != OK && *user_msgptr != NULL && Ustrlen(*user_msgptr) > 75) return rc; } + + +/************************************************* +* Create ACL variable * +*************************************************/ + +/* Create an ACL variable or reuse an existing one. ACL variables are in a +binary tree (see tree.c) with acl_var_c and acl_var_m as root nodes. + +Argument: + name pointer to the variable's name, starting with c or m + +Returns the pointer to variable's tree node +*/ + +tree_node * +acl_var_create(uschar *name) +{ +tree_node *node, **root; +root = (name[0] == 'c')? &acl_var_c : &acl_var_m; +node = tree_search(*root, name); +if (node == NULL) + { + node = store_get(sizeof(tree_node) + Ustrlen(name)); + Ustrcpy(node->name, name); + (void)tree_insertnode(root, node); + } +node->data.ptr = NULL; +return node; +} + + + +/************************************************* +* Write an ACL variable in spool format * +*************************************************/ + +/* This function is used as a callback for tree_walk when writing variables to +the spool file. To retain spool file compatibility, what is written is -aclc or +-aclm followed by the rest of the name and the data length, space separated, +then the value itself, starting on a new line, and terminated by an additional +newline. When we had only numbered ACL variables, the first line might look +like this: "-aclc 5 20". Now it might be "-aclc foo 20" for the variable called +acl_cfoo. + +Arguments: + name of the variable + value of the variable + ctx FILE pointer (as a void pointer) + +Returns: nothing +*/ + +void +acl_var_write(uschar *name, uschar *value, void *ctx) +{ +FILE *f = (FILE *)ctx; +fprintf(f, "-acl%c %s %d\n%s\n", name[0], name+1, Ustrlen(value), value); +} + /* End of acl.c */ diff --git a/src/src/config.h.defaults b/src/src/config.h.defaults index 92f894e4c..e754e39e4 100644 --- a/src/src/config.h.defaults +++ b/src/src/config.h.defaults @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/config.h.defaults,v 1.10 2006/02/10 14:25:43 ph10 Exp $ */ +/* $Cambridge: exim/src/src/config.h.defaults,v 1.11 2006/09/19 11:28:45 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -12,9 +12,6 @@ any data just defines the existence of the variable; it won't get included in config.h unless some value is defined in Local/Makefile. If there is data, it's a default value. */ -#define ACL_CVARS 20 -#define ACL_MVARS 20 - #define ALT_CONFIG_PREFIX #define ALT_CONFIG_ROOT_ONLY diff --git a/src/src/expand.c b/src/src/expand.c index 1517c0625..2e39f2638 100644 --- a/src/src/expand.c +++ b/src/src/expand.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/expand.c,v 1.60 2006/09/18 14:49:23 ph10 Exp $ */ +/* $Cambridge: exim/src/src/expand.c,v 1.61 2006/09/19 11:28:45 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -300,6 +300,8 @@ enum { /* This table must be kept in alphabetical order. */ static var_entry var_table[] = { + /* WARNING: Do not invent variables whose names start acl_c or acl_m because + they will be confused with user-creatable ACL variables. */ { "acl_verify_message", vtype_stringptr, &acl_verify_message }, { "address_data", vtype_stringptr, &deliver_address_data }, { "address_file", vtype_stringptr, &address_file }, @@ -1231,37 +1233,25 @@ find_variable(uschar *name, BOOL exists_only, BOOL skipping, int *newsize) int first = 0; int last = var_table_size; -/* Handle ACL variables, which are not in the table because their number may -vary depending on a build-time setting. If the variable's name is not of the -form acl_mddd or acl_cddd, where the d's are digits, fall through to look for -other names that start with acl_. */ +/* Handle ACL variables, whose names are of the form acl_cxxx or acl_mxxx. +Originally, xxx had to be a number in the range 0-9 (later 0-19), but from +release 4.64 onwards arbitrary names are permitted, as long as the first 5 +characters are acl_c or acl_m (this gave backwards compatibility at the +changeover). There may be built-in variables whose names start acl_ but they +should never start acl_c or acl_m. This slightly messy specification is a +consequence of the history, needless to say. -if (Ustrncmp(name, "acl_", 4) == 0) - { - uschar *endptr; - int offset = -1; - int max = 0; - - if (name[4] == 'm') - { - offset = ACL_CVARS; - max = ACL_MVARS; - } - else if (name[4] == 'c') - { - offset = 0; - max = ACL_CVARS; - } +If an ACL variable does not exist, treat it as empty, unless strict_acl_vars is +set, in which case give an error. */ - if (offset >= 0) - { - int n = Ustrtoul(name + 5, &endptr, 10); - if (*endptr == 0 && n < max) - return (acl_var[offset + n] == NULL)? US"" : acl_var[offset + n]; - } +if (Ustrncmp(name, "acl_c", 5) == 0 || Ustrncmp(name, "acl_m", 5) == 0) + { + tree_node *node = + tree_search((name[4] == 'c')? acl_var_c : acl_var_m, name + 4); + return (node == NULL)? (strict_acl_vars? NULL : US"") : node->data.ptr; } -/* Similarly for $auth<n> variables. */ +/* Handle $auth<n> variables. */ if (Ustrncmp(name, "auth", 4) == 0) { @@ -1681,6 +1671,13 @@ switch(cond_type) expand_string_message = (name[0] == 0)? string_sprintf("variable name omitted after \"def:\"") : string_sprintf("unknown variable \"%s\" after \"def:\"", name); + + if (strict_acl_vars && + Ustrncmp(name, "acl_", 4) == 0 && + (name[4] == 'c' || name[4] == 'm')) + expand_string_message = string_sprintf("%s (strict_acl_vars is set)", + expand_string_message); + return NULL; } if (yield != NULL) *yield = (value[0] != 0) == testfor; @@ -2959,6 +2956,13 @@ while (*s != 0) { expand_string_message = string_sprintf("unknown variable name \"%s\"", name); + + if (strict_acl_vars && + Ustrncmp(name, "acl_", 4) == 0 && + (name[4] == 'c' || name[4] == 'm')) + expand_string_message = string_sprintf("%s (strict_acl_vars is set)", + expand_string_message); + goto EXPAND_FAILED; } } @@ -5118,6 +5122,13 @@ while (*s != 0) { expand_string_message = string_sprintf("unknown variable in \"${%s}\"", name); + + if (strict_acl_vars && + Ustrncmp(name, "acl_", 4) == 0 && + (name[4] == 'c' || name[4] == 'm')) + expand_string_message = string_sprintf("%s (strict_acl_vars is set)", + expand_string_message); + goto EXPAND_FAILED; } len = Ustrlen(value); diff --git a/src/src/functions.h b/src/src/functions.h index eb1a7a5b4..85b48ee37 100644 --- a/src/src/functions.h +++ b/src/src/functions.h @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/functions.h,v 1.26 2006/09/18 14:49:23 ph10 Exp $ */ +/* $Cambridge: exim/src/src/functions.h,v 1.27 2006/09/19 11:28:45 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -40,6 +40,8 @@ extern int tls_write(const uschar *, size_t); extern acl_block *acl_read(uschar *(*)(void), uschar **); extern int acl_check(int, uschar *, uschar *, uschar **, uschar **); +extern tree_node *acl_var_create(uschar *); +extern void acl_var_write(uschar *, uschar *, void *); extern uschar *auth_b64encode(uschar *, int); extern int auth_b64decode(uschar *, uschar **); extern int auth_call_pam(uschar *, uschar **); @@ -327,6 +329,7 @@ extern void tree_add_unusable(host_item *); extern int tree_insertnode(tree_node **, tree_node *); extern tree_node *tree_search(tree_node *, uschar *); extern void tree_write(tree_node *, FILE *); +extern void tree_walk(tree_node *, void (*)(uschar*, uschar*, void*), void *); #ifdef WITH_CONTENT_SCAN extern void unspool_mbox(void); diff --git a/src/src/globals.c b/src/src/globals.c index 84d564ab8..a694053c5 100644 --- a/src/src/globals.c +++ b/src/src/globals.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/globals.c,v 1.57 2006/07/28 11:39:11 ph10 Exp $ */ +/* $Cambridge: exim/src/src/globals.c,v 1.58 2006/09/19 11:28:45 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -186,7 +186,8 @@ uschar *acl_smtp_rcpt = NULL; uschar *acl_smtp_starttls = NULL; uschar *acl_smtp_vrfy = NULL; BOOL acl_temp_details = FALSE; -uschar *acl_var[ACL_CVARS + ACL_MVARS]; +tree_node *acl_var_c = NULL; +tree_node *acl_var_m = NULL; uschar *acl_verify_message = NULL; string_item *acl_warn_logged = NULL; @@ -1102,6 +1103,7 @@ uschar *srs_status = NULL; BOOL srs_usehash = TRUE; BOOL srs_usetimestamp = TRUE; #endif +BOOL strict_acl_vars = FALSE; int string_datestamp_offset= -1; BOOL strip_excess_angle_brackets = FALSE; BOOL strip_trailing_dot = FALSE; diff --git a/src/src/globals.h b/src/src/globals.h index a235869c1..cd5fb4e36 100644 --- a/src/src/globals.h +++ b/src/src/globals.h @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/globals.h,v 1.39 2006/07/13 13:53:33 ph10 Exp $ */ +/* $Cambridge: exim/src/src/globals.h,v 1.40 2006/09/19 11:28:45 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -128,7 +128,8 @@ extern uschar *acl_smtp_rcpt; /* ACL run for RCPT */ extern uschar *acl_smtp_starttls; /* ACL run for STARTTLS */ extern uschar *acl_smtp_vrfy; /* ACL run for VRFY */ extern BOOL acl_temp_details; /* TRUE to give details for 4xx error */ -extern uschar *acl_var[ACL_CVARS+ACL_MVARS]; /* User ACL variables */ +extern tree_node *acl_var_c; /* ACL connection variables */ +extern tree_node *acl_var_m; /* ACL messsage variables */ extern uschar *acl_verify_message; /* User message for verify failure */ extern string_item *acl_warn_logged; /* Logged lines */ extern uschar *acl_wherecodes[]; /* Response codes for ACL fails */ @@ -688,6 +689,7 @@ extern uschar *srs_status; /* SRS staus */ extern BOOL srs_usehash; /* SRS use hash flag */ extern BOOL srs_usetimestamp; /* SRS use timestamp flag */ #endif +extern BOOL strict_acl_vars; /* ACL variables have to be set before being used */ extern int string_datestamp_offset;/* After insertion by string_format */ extern BOOL strip_excess_angle_brackets; /* Surrounding route-addrs */ extern BOOL strip_trailing_dot; /* Remove dots at ends of domains */ diff --git a/src/src/readconf.c b/src/src/readconf.c index 75d444ef1..fd04ab328 100644 --- a/src/src/readconf.c +++ b/src/src/readconf.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/readconf.c,v 1.23 2006/06/28 16:00:24 ph10 Exp $ */ +/* $Cambridge: exim/src/src/readconf.c,v 1.24 2006/09/19 11:28:45 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -354,6 +354,7 @@ static optionlist optionlist_config[] = { { "srs_usehash", opt_bool, &srs_usehash }, { "srs_usetimestamp", opt_bool, &srs_usetimestamp }, #endif + { "strict_acl_vars", opt_bool, &strict_acl_vars }, { "strip_excess_angle_brackets", opt_bool, &strip_excess_angle_brackets }, { "strip_trailing_dot", opt_bool, &strip_trailing_dot }, { "syslog_duplication", opt_bool, &syslog_duplication }, diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c index 6c27c15de..614a3ffe0 100644 --- a/src/src/smtp_in.c +++ b/src/src/smtp_in.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/smtp_in.c,v 1.42 2006/09/18 14:49:23 ph10 Exp $ */ +/* $Cambridge: exim/src/src/smtp_in.c,v 1.43 2006/09/19 11:28:45 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -793,8 +793,6 @@ return TRUE; - - /************************************************* * Reset for new message * *************************************************/ @@ -809,7 +807,6 @@ Returns: nothing static void smtp_reset(void *reset_point) { -int i; store_reset(reset_point); recipients_list = NULL; rcpt_count = rcpt_defer_count = rcpt_fail_count = @@ -855,9 +852,9 @@ sender_rate = sender_rate_limit = sender_rate_period = NULL; ratelimiters_mail = NULL; /* Updated by ratelimit ACL condition */ /* Note that ratelimiters_conn persists across resets. */ -/* The message variables follow the connection variables. */ +/* Reset message ACL variables */ -for (i = 0; i < ACL_MVARS; i++) acl_var[ACL_CVARS + i] = NULL; +acl_var_m = NULL; /* The message body variables use malloc store. They may be set if this is not the first message in an SMTP session and the previous message caused them @@ -1144,7 +1141,7 @@ BOOL smtp_start_session(void) { int size = 256; -int i, ptr; +int ptr; uschar *p, *s, *ss; /* Default values for certain variables */ @@ -1172,7 +1169,7 @@ tls_advertised = FALSE; /* Reset ACL connection variables */ -for (i = 0; i < ACL_CVARS; i++) acl_var[i] = NULL; +acl_var_c = NULL; /* Allow for trailing 0 in the command buffer. */ diff --git a/src/src/spool_in.c b/src/src/spool_in.c index 03379f092..c45914058 100644 --- a/src/src/spool_in.c +++ b/src/src/spool_in.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/spool_in.c,v 1.15 2006/02/07 11:19:00 ph10 Exp $ */ +/* $Cambridge: exim/src/src/spool_in.c,v 1.16 2006/09/19 11:28:45 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -236,8 +236,7 @@ uschar *p; one exception. DO NOT change the default value of dont_deliver, because it may be forced by an external setting. */ -for (n = 0; n < ACL_CVARS + ACL_MVARS; n++) acl_var[n] = NULL; - +acl_var_c = acl_var_m = NULL; authenticated_id = NULL; authenticated_sender = NULL; allow_unqualified_recipient = FALSE; @@ -378,48 +377,52 @@ for (;;) if (big_buffer[0] != '-') break; big_buffer[Ustrlen(big_buffer) - 1] = 0; - /* For backward compatibility, we recognize "-acl", which was used before the - number of ACL variables changed. Its variable number is 0-9 for connection - variables, and 10-19 for message variables. */ + /* For long-term backward compatibility, we recognize "-acl", which was used + before the number of ACL variables changed from 10 to 20. This was before the + subsequent change to an arbitrary number of named variables. This code is + retained so that upgrades from very old versions can still handle old-format + spool files. The value given after "-acl" is a number that is 0-9 for + connection variables, and 10-19 for message variables. */ if (Ustrncmp(big_buffer, "-acl ", 5) == 0) { int index, count; + uschar name[4]; + tree_node *node; + if (sscanf(CS big_buffer + 5, "%d %d", &index, &count) != 2) goto SPOOL_FORMAT_ERROR; - acl_var[index] = store_get(count + 1); - if (fread(acl_var[index], 1, count+1, f) < count) goto SPOOL_READ_ERROR; - acl_var[index][count] = 0; - } - /* Nowadays we use "-aclc" and "-aclm" for the different types of ACL - variable, because Exim may be built with different numbers of them. */ + (void) string_format(name, 4, "%c%d", (index < 10 ? 'c' : 'm'), index); + node = acl_var_create(name); + node->data.ptr = store_get(count + 1); - else if (Ustrncmp(big_buffer, "-aclc ", 6) == 0) - { - int index, count; - if (sscanf(CS big_buffer + 6, "%d %d", &index, &count) != 2) - goto SPOOL_FORMAT_ERROR; - if (index < ACL_CVARS) - { - acl_var[index] = store_get(count + 1); - if (fread(acl_var[index], 1, count+1, f) < count) goto SPOOL_READ_ERROR; - acl_var[index][count] = 0; - } + if (fread(node->data.ptr, 1, count+1, f) < count) goto SPOOL_READ_ERROR; + ((uschar*)node->data.ptr)[count] = 0; } - else if (Ustrncmp(big_buffer, "-aclm ", 6) == 0) + /* Nowadays we use "-aclc" and "-aclm" for the different types of ACL + variable, because Exim allows any number of them, with arbitrary names. + The line in the spool file is "-acl[cm] <name> <length>". The name excludes + the c or m. */ + + else if (Ustrncmp(big_buffer, "-aclc ", 6) == 0 || + Ustrncmp(big_buffer, "-aclm ", 6) == 0) { - int index, count; - if (sscanf(CS big_buffer + 6, "%d %d", &index, &count) != 2) - goto SPOOL_FORMAT_ERROR; - if (index < ACL_MVARS) - { - index += ACL_CVARS; - acl_var[index] = store_get(count + 1); - if (fread(acl_var[index], 1, count+1, f) < count) goto SPOOL_READ_ERROR; - acl_var[index][count] = 0; - } + uschar *name, *endptr; + int count; + tree_node *node; + + endptr = Ustrchr(big_buffer + 6, ' '); + if (endptr == NULL) goto SPOOL_FORMAT_ERROR; + name = string_sprintf("%c%.*s", big_buffer[4], endptr - big_buffer - 6, + big_buffer + 6); + if (sscanf(CS endptr, " %d", &count) != 1) goto SPOOL_FORMAT_ERROR; + + node = acl_var_create(name); + node->data.ptr = store_get(count + 1); + if (fread(node->data.ptr, 1, count+1, f) < count) goto SPOOL_READ_ERROR; + ((uschar*)node->data.ptr)[count] = 0; } /* Other values */ diff --git a/src/src/spool_out.c b/src/src/spool_out.c index bbfd785d2..0a17b7a13 100644 --- a/src/src/spool_out.c +++ b/src/src/spool_out.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/spool_out.c,v 1.10 2006/02/07 11:19:00 ph10 Exp $ */ +/* $Cambridge: exim/src/src/spool_out.c,v 1.11 2006/09/19 11:28:45 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -190,21 +190,10 @@ if (sender_ident != NULL) fprintf(f, "-ident %s\n", sender_ident); if (received_protocol != NULL) fprintf(f, "-received_protocol %s\n", received_protocol); -/* Preserve any ACL variables that are set. Because the values may contain -newlines, we use an explicit length. */ +/* Preserve any ACL variables that are set. */ -for (i = 0; i < ACL_CVARS; i++) - { - if (acl_var[i] != NULL) - fprintf(f, "-aclc %d %d\n%s\n", i, Ustrlen(acl_var[i]), acl_var[i]); - } - -for (i = 0; i < ACL_MVARS; i++) - { - int j = i + ACL_CVARS; - if (acl_var[j] != NULL) - fprintf(f, "-aclm %d %d\n%s\n", i, Ustrlen(acl_var[j]), acl_var[j]); - } +tree_walk(acl_var_c, &acl_var_write, f); +tree_walk(acl_var_m, &acl_var_write, f); /* Now any other data that needs to be remembered. */ diff --git a/src/src/structs.h b/src/src/structs.h index c0fa960d3..890867d0a 100644 --- a/src/src/structs.h +++ b/src/src/structs.h @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/structs.h,v 1.10 2006/02/21 16:24:19 ph10 Exp $ */ +/* $Cambridge: exim/src/src/structs.h,v 1.11 2006/09/19 11:28:45 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -779,7 +779,7 @@ typedef struct acl_condition_block { int type; union { BOOL negated; - int varnumber; + uschar *varname; } u; } acl_condition_block; diff --git a/src/src/tree.c b/src/src/tree.c index 17216052b..219a53580 100644 --- a/src/src/tree.c +++ b/src/src/tree.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/tree.c,v 1.3 2006/02/07 11:19:00 ph10 Exp $ */ +/* $Cambridge: exim/src/src/tree.c,v 1.4 2006/09/19 11:28:45 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -342,4 +342,26 @@ return NULL; } + +/************************************************* +* Walk tree recursively and execute function * +*************************************************/ + +/* +Arguments: + p root of the tree + f function to execute for each name-value-pair + ctx context data for f +*/ + +void +tree_walk(tree_node *p, void (*f)(uschar*, uschar*, void*), void *ctx) +{ +if (p == NULL) return; +f(p->name, p->data.ptr, ctx); +if (p->left != NULL) tree_walk(p->left, f, ctx); +if (p->right != NULL) tree_walk(p->right, f, ctx); +} + + /* End of tree.c */ |