From bec360ab3e1060187724480d109884e56f912b0a Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Mon, 12 Aug 2024 16:08:33 +0100 Subject: [PATCH] linked-lists for driver info structs --- src/src/drtables.c | 20 +++++++++++---- src/src/exim.c | 3 ++- src/src/globals.h | 9 ++++--- src/src/readconf.c | 61 +++++++++++++++++++++++++++++++++++++++++---- src/src/route.c | 24 +++++++++++++++--- src/src/structs.h | 2 ++ src/src/transport.c | 25 ++++++++++++++----- test/confs/0000 | 2 ++ 8 files changed, 122 insertions(+), 24 deletions(-) diff --git a/src/src/drtables.c b/src/src/drtables.c index 19a70ab8b..2782323c3 100644 --- a/src/src/drtables.c +++ b/src/src/drtables.c @@ -61,7 +61,8 @@ set to NULL for those that are not compiled into the binary. */ #include "auths/tls.h" #endif -auth_info auths_available[] = { +auth_info * auths_available_newlist = NULL; +auth_info auths_available_oldarray[] = { /* Checking by an expansion condition on plain text */ @@ -282,9 +283,11 @@ exim binary. */ #endif +router_info * routers_available_newlist = NULL; + /* Now set up the structures, terminated by an entry with a null name. */ -router_info routers_available[] = { +router_info routers_available_oldarray[] = { #ifdef ROUTER_ACCEPT { .drinfo = { @@ -369,6 +372,9 @@ router_info routers_available[] = { .options_block = &queryprogram_router_option_defaults, .options_len = sizeof(queryprogram_router_options_block), .init = queryprogram_router_init, +# if ROUTER_QUIRYPROGRAM==2 + .dynamic = TRUE, +# endif }, .code = queryprogram_router_entry, .tidyup = NULL, /* no tidyup entry */ @@ -395,7 +401,8 @@ router_info routers_available[] = { -transport_info transports_available[] = { +transport_info * transports_available_newlist = NULL; +transport_info transports_available_oldarray[] = { #ifdef TRANSPORT_APPENDFILE { .drinfo = { @@ -501,7 +508,9 @@ gstring * auth_show_supported(gstring * g) { g = string_cat(g, US"Authenticators:"); -for (auth_info * ai = auths_available; ai->drinfo.driver_name[0]; ai++) +/*XXX these run off the static list as we want them before the conf is read */ +/*XXX Could possibly check for dyn flag + file presence */ +for (auth_info * ai = auths_available_oldarray; ai->drinfo.driver_name[0]; ai++) g = string_fmt_append(g, " %s", ai->drinfo.driver_name); return string_cat(g, US"\n"); } @@ -510,7 +519,8 @@ gstring * route_show_supported(gstring * g) { g = string_cat(g, US"Routers:"); -for (router_info * rr = routers_available; rr->drinfo.driver_name[0]; rr++) +/*XXX these run off the static list as we want them before the conf is read */ +for (router_info * rr = routers_available_oldarray; rr->drinfo.driver_name[0]; rr++) g = string_fmt_append(g, " %s", rr->drinfo.driver_name); return string_cat(g, US"\n"); } diff --git a/src/src/exim.c b/src/src/exim.c index d86625f92..8eb602a17 100644 --- a/src/src/exim.c +++ b/src/src/exim.c @@ -1382,7 +1382,8 @@ g = show_db_version(g); show_string(is_stdout, g); g = NULL; -for (auth_info * ai= auths_available; *ai->drinfo.driver_name != '\0'; ai++) +//for (auth_info * ai= auths_available; *ai->drinfo.driver_name != '\0'; ai++) +for (auth_info * ai = auths_available_newlist; ai; ai = (auth_info *)ai->drinfo.next) if (ai->version_report) g = (*ai->version_report)(g); diff --git a/src/src/globals.h b/src/src/globals.h index 8e75f7f93..817c940ed 100644 --- a/src/src/globals.h +++ b/src/src/globals.h @@ -374,7 +374,8 @@ extern uschar *authenticated_sender; /* From AUTH on MAIL */ extern BOOL authentication_failed; /* TRUE if AUTH was tried and failed */ extern uschar *authenticator_name; /* for debug and error messages */ extern uschar *auth_advertise_hosts; /* Only advertise to these */ -extern auth_info auths_available[]; /* Vector of available auth mechanisms */ +extern auth_info auths_available_oldarray[]; /* Vector of available auth mechanisms */ +extern auth_info * auths_available_newlist; extern auth_instance *auths; /* Chain of instantiated auths */ extern auth_instance auth_defaults; /* Default values */ extern uschar *auth_defer_msg; /* Error message for log */ @@ -946,7 +947,8 @@ extern int rfc1413_query_timeout; /* Timeout on RFC 1413 calls */ /* extern BOOL rfc821_domains; */ /* If set, syntax is 821, not 822 => being abolished */ extern uid_t root_gid; /* The gid for root */ extern uid_t root_uid; /* The uid for root */ -extern router_info routers_available[];/* Vector of available routers */ +extern router_info routers_available_oldarray[];/* Vector of available routers */ +extern router_info *routers_available_newlist; extern router_instance *routers; /* Chain of instantiated routers */ extern router_instance router_defaults;/* Default values */ extern const uschar *router_name; /* Name of router last started */ @@ -1110,7 +1112,8 @@ extern int transport_newlines; /* Accurate count of number of newline ch extern const uschar **transport_filter_argv; /* For on-the-fly filtering */ extern int transport_filter_timeout; /* Timeout for same */ -extern transport_info transports_available[]; /* Vector of available transports */ +extern transport_info transports_available_oldarray[]; /* Vector of available transports */ +extern transport_info * transports_available_newlist; extern transport_instance *transports; /* Chain of instantiated transports */ extern transport_instance transport_defaults; /* Default values */ diff --git a/src/src/readconf.c b/src/src/readconf.c index d8f9a53e4..f22ff700e 100644 --- a/src/src/readconf.c +++ b/src/src/readconf.c @@ -435,9 +435,13 @@ uschar buf[EXIM_DRIVERNAME_MAX]; options_from_list(optionlist_auths, optionlist_auths_size, US"AUTHENTICATORS", NULL); +#ifdef old for (struct auth_info * ai = auths_available; ai->drinfo.driver_name[0]; ai++) +#endif +for (driver_info * di = (driver_info *)auths_available_newlist; di; di = di->next) { - driver_info * di = &ai->drinfo; + auth_info * ai = (auth_info *)di; + spf(buf, sizeof(buf), US"_DRIVER_AUTHENTICATOR_%T", di->driver_name); builtin_macro_create(buf); options_from_list(di->options, (unsigned)*di->options_count, @@ -3718,9 +3722,42 @@ static driver_info * init_driver(driver_instance * d, driver_info * drivers_available, int size_of_info, const uschar * class) { -/*XXX this is walking the old-array */ -for (driver_info * dd = drivers_available; *dd->driver_name; +/*XXX if dynamic, the _info entry will be here but code may or may not +be loaded. How to tell? What's the entry point? init call? +Currently that is IN the _info entry. + +For lookups it does it by pulling the info entry out of the dlopen()d +file (for dynamic) or direct from the lookup .o file (for static). +It builds a linked-list with those two classes, +then an array sorted by (? name) and discards the list. +The array is the _info list. + +We'd rather not have to do two passes over the config file(s) section. +With the number of drivers I see no point in sorting, +so we could stick with a one-pass build of an _info linked-list. +This does mean converting any code using the current array. + +DONE: +Rename the array to old. For now, walk it once and build a linked-list. +Find and convert all the uses, + +Move all the element defns to driver code files. +Change the init/build to scan them. + +Move the scan to the place-of-use reading the config, +only load if not already on linked-list. + +Add the build-dynamic wrapper, +and scan from dlopen if marked dynamic. +*/ + +#ifdef old +/*XXX walk the old array */ +for (driver_info * dd = drivers_available; dd->driver_name[0] != 0; dd = (driver_info *)((US dd) + size_of_info)) +#endif + +for (driver_info * dd = drivers_available; dd; dd = dd->next) if (Ustrcmp(d->driver_name, dd->driver_name) == 0) { int len = dd->options_len; @@ -3784,7 +3821,7 @@ Returns: nothing void readconf_driver_init( driver_instance ** anchor, - driver_info * drivers_available, + driver_info * drivers_available, /*XXX now list not array */ int size_of_info, void * instance_default, int instance_size, @@ -4245,8 +4282,21 @@ auths_init(void) int nauths = 0; #endif +/*XXX temp loop just copying the old array to build the new list. +Will replace with haul from either static build file or dyn module +done by readconf_driver_init() */ +for (auth_info * tblent = auths_available_oldarray; + *tblent->drinfo.driver_name; tblent++) + { + driver_info * listent = store_get(sizeof(auth_info), tblent); + memcpy(listent, tblent, sizeof(auth_info)); + listent->next = (driver_info *)auths_available_newlist; + auths_available_newlist = (auth_info *)listent; + } + + readconf_driver_init((driver_instance **)&auths, /* chain anchor */ - (driver_info *)auths_available, /* available drivers */ + (driver_info *)auths_available_newlist, /* available drivers */ sizeof(auth_info), /* size of info block */ &auth_defaults, /* default values for generic options */ sizeof(auth_instance), /* size of instance block */ @@ -4430,6 +4480,7 @@ while(next_section[0] != 0) int mid = last/2; int n = Ustrlen(next_section); + READCONF_DEBUG fprintf(stderr, "%s: %s\n", __FUNCTION__, next_section); if (tolower(next_section[n-1]) != 's') Ustrcpy(next_section+n, US"s"); for (;;) diff --git a/src/src/route.c b/src/src/route.c index 0c7de556d..c0cc1fee9 100644 --- a/src/src/route.c +++ b/src/src/route.c @@ -159,12 +159,15 @@ uschar buf[64]; options_from_list(optionlist_routers, nelem(optionlist_routers), US"ROUTERS", NULL); +#ifdef old for (router_info * ri = routers_available; ri->drinfo.driver_name[0]; ri++) +#endif +for (driver_info * di = (driver_info *)routers_available_newlist; di; di = di->next) { - spf(buf, sizeof(buf), US"_DRIVER_ROUTER_%T", ri->drinfo.driver_name); + spf(buf, sizeof(buf), US"_DRIVER_ROUTER_%T", di->driver_name); builtin_macro_create(buf); - options_from_list(ri->drinfo.options, (unsigned)*ri->drinfo.options_count, - US"ROUTER", ri->drinfo.driver_name); + options_from_list(di->options, (unsigned)*di->options_count, + US"ROUTER", di->driver_name); } } @@ -227,8 +230,21 @@ function. */ void route_init(void) { +/*XXX temp loop just copying the old array to build the new list. +Will replace with haul from either static build file or dyn module +done by readconf_driver_init() */ + +for (router_info * tblent = routers_available_oldarray; + *tblent->drinfo.driver_name; tblent++) + { + driver_info * listent = store_get(sizeof(router_info), tblent); + memcpy(listent, tblent, sizeof(router_info)); + listent->next = (driver_info *)routers_available_newlist; + routers_available_newlist = (router_info *)listent; + } + readconf_driver_init((driver_instance **)&routers, /* chain anchor */ - (driver_info *)routers_available, /* available drivers */ + (driver_info *)routers_available_newlist, /* available drivers */ sizeof(router_info), /* size of info blocks */ &router_defaults, /* default values for generic options */ sizeof(router_instance), /* size of instance block */ diff --git a/src/src/structs.h b/src/src/structs.h index ee312a44e..392a4a08c 100644 --- a/src/src/structs.h +++ b/src/src/structs.h @@ -141,6 +141,7 @@ typedef struct driver_instance { } driver_instance; typedef struct driver_info { + struct driver_info * next; uschar *driver_name; /* Name of driver */ optionlist *options; /* Table of private options names */ @@ -149,6 +150,7 @@ typedef struct driver_info { int options_len; /* Length of same in bytes */ void (*init)( /* Initialization entry point */ struct driver_instance *); + BOOL dynamic; /* Built as dynamic-load module */ } driver_info; diff --git a/src/src/transport.c b/src/src/transport.c index febe7c117..e92541bbf 100644 --- a/src/src/transport.c +++ b/src/src/transport.c @@ -102,12 +102,13 @@ uschar buf[64]; options_from_list(optionlist_transports, nelem(optionlist_transports), US"TRANSPORTS", NULL); -for (transport_info * ti= transports_available; ti->drinfo.driver_name[0]; ti++) +//for (transport_info * ti= transports_available; ti->drinfo.driver_name[0]; ti++) +for (driver_info * di= (driver_info *)transports_available_newlist; di; di = di->next) { - spf(buf, sizeof(buf), US"_DRIVER_TRANSPORT_%T", ti->drinfo.driver_name); + spf(buf, sizeof(buf), US"_DRIVER_TRANSPORT_%T", di->driver_name); builtin_macro_create(buf); - options_from_list(ti->drinfo.options, (unsigned)*ti->drinfo.options_count, - US"TRANSPORT", ti->drinfo.driver_name); + options_from_list(di->options, (unsigned)*di->options_count, + US"TRANSPORT", di->driver_name); } } @@ -145,10 +146,22 @@ the work. */ void transport_init(void) { +/*XXX temp loop just copying the old array to build the new list. +Will replace with haul from either static build file or dyn module +done by readconf_driver_init() */ +for (transport_info * tblent = transports_available_oldarray; + *tblent->drinfo.driver_name; tblent++) + { + driver_info * listent = store_get(sizeof(transport_info), tblent); + memcpy(listent, tblent, sizeof(transport_info)); + listent->next = (driver_info *)transports_available_newlist; + transports_available_newlist = (transport_info *)listent; + } + readconf_driver_init((driver_instance **)&transports, /* chain anchor */ - (driver_info *)transports_available, /* available drivers */ + (driver_info *)transports_available_newlist, /* available drivers */ sizeof(transport_info), /* size of info block */ - &transport_defaults, /* default values for generic options*/ + &transport_defaults, /* default values for generic options */ sizeof(transport_instance), /* size of instance block */ optionlist_transports, /* generic options */ optionlist_transports_size, diff --git a/test/confs/0000 b/test/confs/0000 index 12c91fda1..795701bd7 100644 --- a/test/confs/0000 +++ b/test/confs/0000 @@ -10,4 +10,6 @@ gecos_name = CALLER_NAME tls_advertise_hosts = keep_environment = +begin routers + # End -- 2.30.2