diff options
author | Jeremy Harris <jgh146exb@wizmail.org> | 2019-07-08 17:34:47 +0100 |
---|---|---|
committer | Jeremy Harris <jgh146exb@wizmail.org> | 2019-07-08 17:34:47 +0100 |
commit | fa7b17bdbc8c055c475a50791627cd75d257f4f3 (patch) | |
tree | a9818766f97482a4c860ba3c99b95239bfdc50e4 /src | |
parent | 0cf7a94143a3ff40057ce90b0b23ece76046e188 (diff) |
Routers: named variables
Diffstat (limited to 'src')
-rw-r--r-- | src/src/deliver.c | 42 | ||||
-rw-r--r-- | src/src/expand.c | 9 | ||||
-rw-r--r-- | src/src/globals.c | 3 | ||||
-rw-r--r-- | src/src/globals.h | 1 | ||||
-rw-r--r-- | src/src/route.c | 52 | ||||
-rw-r--r-- | src/src/routers/queryprogram.c | 1 | ||||
-rw-r--r-- | src/src/routers/redirect.c | 1 | ||||
-rw-r--r-- | src/src/structs.h | 2 | ||||
-rw-r--r-- | src/src/verify.c | 2 |
9 files changed, 109 insertions, 4 deletions
diff --git a/src/src/deliver.c b/src/src/deliver.c index 62daff0df..7b794720f 100644 --- a/src/src/deliver.c +++ b/src/src/deliver.c @@ -155,6 +155,47 @@ return addr; +/************************************************/ +/* Set router-assigned variables, forgetting any previous. +Return FALSE on failure */ + +static BOOL +set_router_vars(gstring * g_varlist) +{ +const uschar * varlist; +int sep = 0; + +router_var = NULL; +if (!g_varlist) return TRUE; +varlist = CUS string_from_gstring(g_varlist); + +/* Walk the varlist, creating variables */ + +for (uschar * ele; (ele = string_nextinlist(&varlist, &sep, NULL, 0)); ) + { + const uschar * assignment = ele; + int esep = '='; + uschar * name = string_nextinlist(&assignment, &esep, NULL, 0); + tree_node * node, ** root = &router_var; + + /* Variable name must exist and start "r_". */ + + if (!name || name[0] != 'r' || name[1] != '_' || !name[2]) + return FALSE; + name += 2; + + if (!(node = tree_search(*root, name))) + { + node = store_get(sizeof(tree_node) + Ustrlen(name)); + Ustrcpy(node->name, name); + (void)tree_insertnode(root, node); + } + node->data.ptr = US assignment; + } +return TRUE; +} + + /************************************************* * Set expansion values for an address * *************************************************/ @@ -198,6 +239,7 @@ deliver_recipients = addr; deliver_address_data = addr->prop.address_data; deliver_domain_data = addr->prop.domain_data; deliver_localpart_data = addr->prop.localpart_data; +set_router_vars(addr->prop.set); /*XXX failure cases? */ /* These may be unset for multiple addresses */ diff --git a/src/src/expand.c b/src/src/expand.c index 2ddd22aa6..74267ab0c 100644 --- a/src/src/expand.c +++ b/src/src/expand.c @@ -1773,8 +1773,13 @@ set, in which case give an error. */ if ((Ustrncmp(name, "acl_c", 5) == 0 || Ustrncmp(name, "acl_m", 5) == 0) && !isalpha(name[5])) { - tree_node *node = - tree_search((name[4] == 'c')? acl_var_c : acl_var_m, name + 4); + tree_node * node = + tree_search(name[4] == 'c' ? acl_var_c : acl_var_m, name + 4); + return node ? node->data.ptr : strict_acl_vars ? NULL : US""; + } +else if (Ustrncmp(name, "r_", 2) == 0) + { + tree_node * node = tree_search(router_var, name + 2); return node ? node->data.ptr : strict_acl_vars ? NULL : US""; } diff --git a/src/src/globals.c b/src/src/globals.c index e70e38538..a7b0234b9 100644 --- a/src/src/globals.c +++ b/src/src/globals.c @@ -585,6 +585,7 @@ address_item address_defaults = { .errors_address = NULL, .extra_headers = NULL, .remove_headers = NULL, + .set = NULL, #ifdef EXPERIMENTAL_SRS .srs_sender = NULL, #endif @@ -1340,6 +1341,7 @@ router_instance router_defaults = { .retry_use_local_part = TRUE_UNSET, .same_domain_copy_routing = FALSE, .self_rewrite = FALSE, + .set = NULL, .suffix_optional = FALSE, .verify_only = FALSE, .verify_recipient = TRUE, @@ -1361,6 +1363,7 @@ router_instance router_defaults = { }; uschar *router_name = NULL; +tree_node *router_var = NULL; ip_address_item *running_interfaces = NULL; diff --git a/src/src/globals.h b/src/src/globals.h index 83d29ba9b..18aaad918 100644 --- a/src/src/globals.h +++ b/src/src/globals.h @@ -859,6 +859,7 @@ extern router_info routers_available[];/* Vector of available routers */ extern router_instance *routers; /* Chain of instantiated routers */ extern router_instance router_defaults;/* Default values */ extern uschar *router_name; /* Name of router last started */ +extern tree_node *router_var; /* Variables set by router */ extern ip_address_item *running_interfaces; /* Host's running interfaces */ extern uschar *running_status; /* Flag string for testing */ extern int runrc; /* rc from ${run} */ diff --git a/src/src/route.c b/src/src/route.c index ede153041..74466733e 100644 --- a/src/src/route.c +++ b/src/src/route.c @@ -116,6 +116,8 @@ optionlist optionlist_routers[] = { (void *)(offsetof(router_instance, self)) }, { "senders", opt_stringptr|opt_public, (void *)offsetof(router_instance, senders) }, + { "set", opt_stringptr|opt_public|opt_rep_str, + (void *)offsetof(router_instance, set) }, #ifdef SUPPORT_TRANSLATE_IP_ADDRESS { "translate_ip_address", opt_stringptr|opt_public, (void *)offsetof(router_instance, translate_ip_address) }, @@ -1361,6 +1363,7 @@ new->prop.errors_address = parent->prop.errors_address; new->prop.ignore_error = addr->prop.ignore_error; new->prop.address_data = addr->prop.address_data; +new->prop.set = addr->prop.set; new->dsn_flags = addr->dsn_flags; new->dsn_orcpt = addr->dsn_orcpt; @@ -1602,6 +1605,52 @@ for (r = addr->start_router ? addr->start_router : routers; r; r = nextr) search_error_message = NULL; + /* Add any variable-settings that are on the router, to the list on the + addr. Expansion is done here and not later when the addr is used. There may + be multiple settings, gathered during readconf; this code gathers them during + router traversal. */ + + if (r->set) + { + const uschar * list = r->set; + int sep = 0; + for (uschar * ele; (ele = string_nextinlist(&list, &sep, NULL, 0)); ) + { + uschar * ee; + if (!(ee = expand_string(ele))) + if (f.expand_string_forcedfail) + { + DEBUG(D_route) debug_printf("forced failure in expansion of \"%s\" " + "(router variable): decline action taken\n", ele); + + /* Expand "more" if necessary; DEFER => an expansion failed */ + + yield = exp_bool(addr, US"router", r->name, D_route, + US"more", r->more, r->expand_more, &more); + if (yield != OK) goto ROUTE_EXIT; + + if (!more) + { + DEBUG(D_route) + debug_printf("\"more\"=false: skipping remaining routers\n"); + router_name = NULL; + r = NULL; + break; + } + else continue; /* With next router */ + } + else + { + addr->message = string_sprintf("expansion of \"%s\" failed " + "in %s router: %s", ele, r->name, expand_string_message); + yield = DEFER; + goto ROUTE_EXIT; + } + + addr->prop.set = string_append_listele(addr->prop.set, ':', ee); + } + } + /* Finally, expand the address_data field in the router. Forced failure behaves as if the router declined. Any other failure is more serious. On success, the string is attached to the address for all subsequent processing. @@ -1610,8 +1659,7 @@ for (r = addr->start_router ? addr->start_router : routers; r; r = nextr) if (r->address_data) { DEBUG(D_route) debug_printf("processing address_data\n"); - deliver_address_data = expand_string(r->address_data); - if (!deliver_address_data) + if (!(deliver_address_data = expand_string(r->address_data))) { if (f.expand_string_forcedfail) { diff --git a/src/src/routers/queryprogram.c b/src/src/routers/queryprogram.c index b4d229cd7..02ada2950 100644 --- a/src/src/routers/queryprogram.c +++ b/src/src/routers/queryprogram.c @@ -232,6 +232,7 @@ errors address and extra header stuff. */ bzero(&addr_prop, sizeof(addr_prop)); addr_prop.address_data = deliver_address_data; +addr_prop.set = addr->prop.set; rc = rf_get_errors_address(addr, rblock, verify, &addr_prop.errors_address); if (rc != OK) return rc; diff --git a/src/src/routers/redirect.c b/src/src/routers/redirect.c index 938db3600..920a74a14 100644 --- a/src/src/routers/redirect.c +++ b/src/src/routers/redirect.c @@ -563,6 +563,7 @@ addr_prop.localpart_data = deliver_localpart_data; addr_prop.errors_address = NULL; addr_prop.extra_headers = NULL; addr_prop.remove_headers = NULL; +addr_prop.set = addr->prop.set; #ifdef EXPERIMENTAL_SRS addr_prop.srs_sender = NULL; diff --git a/src/src/structs.h b/src/src/structs.h index 0b01d5880..1925c4932 100644 --- a/src/src/structs.h +++ b/src/src/structs.h @@ -333,6 +333,7 @@ typedef struct router_instance { BOOL retry_use_local_part; /* Just what it says */ BOOL same_domain_copy_routing; /* TRUE => copy routing for same domain */ BOOL self_rewrite; /* TRUE to rewrite headers if making local */ + uschar *set; /* Variable = value to set; list */ BOOL suffix_optional; /* As it says */ BOOL verify_only; /* Skip this router if not verifying */ BOOL verify_recipient; /* Use this router when verifying a recipient*/ @@ -510,6 +511,7 @@ typedef struct address_item_propagated { uschar *errors_address; /* where to send errors (NULL => sender) */ header_line *extra_headers; /* additional headers */ uschar *remove_headers; /* list of those to remove */ + gstring *set; /* list of variables, with values */ #ifdef EXPERIMENTAL_SRS uschar *srs_sender; /* Change return path when delivering */ diff --git a/src/src/verify.c b/src/src/verify.c index 5026a417c..bf91a8388 100644 --- a/src/src/verify.c +++ b/src/src/verify.c @@ -1529,6 +1529,7 @@ if (addr != vaddr) vaddr->basic_errno = addr->basic_errno; vaddr->more_errno = addr->more_errno; vaddr->prop.address_data = addr->prop.address_data; + vaddr->prop.set = addr->prop.set; copyflag(vaddr, addr, af_pass_message); } return yield; @@ -2089,6 +2090,7 @@ while (addr_new) of $address_data to be that of the child */ vaddr->prop.address_data = addr->prop.address_data; + vaddr->prop.set = addr->prop.set; /* If stopped because more than one new address, cannot cutthrough */ |