From d0bc09e53681e207a3e1af846cd245c597b06d21 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Fri, 9 Aug 2024 13:21:21 +0100 Subject: [PATCH] Build: Dynamic-load modules - quieten build, add to -bV output Also add info to template Makefile, fix testsuite --- doc/doc-docbook/spec.xfpt | 4 +- doc/doc-txt/ChangeLog | 3 + src/src/EDITME | 24 ++++- src/src/drtables.c | 2 +- src/src/exim.c | 202 +++++++++++++++++++++++++++----------- test/README | 3 + test/runtest | 21 +++- 7 files changed, 187 insertions(+), 72 deletions(-) diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt index 816db59f9..ebc44978b 100644 --- a/doc/doc-docbook/spec.xfpt +++ b/doc/doc-docbook/spec.xfpt @@ -2077,7 +2077,7 @@ On some platforms, Exim supports not compiling all lookup types directly into the main binary, instead putting some into external modules which can be loaded on demand. This permits packagers to build Exim with support for lookups with extensive -library dependencies without requiring all users to install all of those +library dependencies without requiring all systems to install all of those dependencies. Most, but not all, lookup types can be built this way. @@ -2091,7 +2091,7 @@ see &_src/EDITME_& for details. Then, for each module to be loaded dynamically, define the relevant &`LOOKUP_`&<&'lookup_type'&> flags to have the value "2" instead of "yes". For example, this will build in lsearch but load sqlite and mysql support -on demand: +only if each is installed: .code LOOKUP_LSEARCH=yes LOOKUP_SQLITE=2 diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index 7c888dbc0..3a0e3efc5 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -37,6 +37,9 @@ JH/07 Bug 3106: Fix coding in SPA authenticator. A macro argument was not from this macro made me want to replace it with a real function so more extensive rework becamse needed. +JH/08 The output of "exim -bV" now includes lookup types built as dynamic-load + modules. + Exim version 4.98 ----------------- diff --git a/src/src/EDITME b/src/src/EDITME index ebfaf640a..08dcf1e30 100644 --- a/src/src/EDITME +++ b/src/src/EDITME @@ -398,7 +398,11 @@ TRANSPORT_SMTP=yes # (where * is the name as given here in this list). That ensures that only # the dynamic library and not the exim binary will be linked against the # library. +# # NOTE: LDAP cannot be built as a module! +# JSON cannot (yet). +# Also, PASSWD, DBM and DNSDB can but there is little point since the accesses +# are always needed by the Exim core. # # For Redis you need to have hiredis installed on your system # (https://github.com/redis/hiredis). @@ -407,7 +411,8 @@ TRANSPORT_SMTP=yes # If your system has pkg-config then the _INCLUDE/_LIBS setting can be # handled for you automatically by also defining the _PC variable to reference -# the name of the pkg-config package, if such is available. +# the name of the pkg-config package, if such is available. This should not +# be done for module builds. LOOKUP_DBM=yes LOOKUP_LSEARCH=yes @@ -440,11 +445,9 @@ LOOKUP_DNSDB=yes # LOOKUP_NWILDLSEARCH=yes -# Some platforms may need this for LOOKUP_NIS: -# LIBS += -lnsl #------------------------------------------------------------------------------ -# If you have set LOOKUP_LDAP=yes, you should set LDAP_LIB_TYPE to indicate +# If you have set LOOKUP_LDAP, you should set LDAP_LIB_TYPE to indicate # which LDAP library you have. Unfortunately, though most of their functions # are the same, there are minor differences. Currently Exim knows about four # LDAP libraries: the one from the University of Michigan (also known as @@ -494,11 +497,24 @@ SUPPORT_DANE=yes # is for Redis, -ljansson for JSON. # # You do not need to use this for any lookup information added via pkg-config. +# +# Libraries being built as modules should be added to respective +# LOOKUP_*_INCLUDE and LOOKUP_*_LIBS rather than the the ones for the +# core exim build. This gets them linked with the module instead +# +# LSEARCH, DSEARCH & CDB have no external library needs. +# DNSDB needs the resolver library which the core uses anyway. # LOOKUP_INCLUDE=-I /usr/local/ldap/include -I /usr/local/mysql/include -I /usr/local/pgsql/include # LOOKUP_INCLUDE +=-I /usr/local/include # LOOKUP_LIBS=-L/usr/local/lib -lldap -llber -lmysqlclient -lpq -lgds -lsqlite3 -llmdb +LOOKUP_LIBS=-L/usr/local/lib -lldap -llber +# Some platforms may need this for LOOKUP_NIS: +#LOOKUP_LIBS += -lnsl +#LOOKUP_LIBS += -ljansson +#LOOKUP_LIBS += -lhiredis + #------------------------------------------------------------------------------ # If you included LOOKUP_LMDB above you will need the library. Depending # on where installed you may also need an include directory diff --git a/src/src/drtables.c b/src/src/drtables.c index 1e3269f4a..800d9e4db 100644 --- a/src/src/drtables.c +++ b/src/src/drtables.c @@ -722,7 +722,7 @@ addlookupmodule(NULL, &whoson_lookup_module_info); addlookupmodule(NULL, &readsock_lookup_module_info); #ifdef LOOKUP_MODULE_DIR -if (!(dd = exim_opendir(LOOKUP_MODULE_DIR))) +if (!(dd = exim_opendir(CUS LOOKUP_MODULE_DIR))) { DEBUG(D_lookup) debug_printf("Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR); log_write(0, LOG_MAIN, "Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR); diff --git a/src/src/exim.c b/src/src/exim.c index 0d0396e3e..8a67b2aad 100644 --- a/src/src/exim.c +++ b/src/src/exim.c @@ -1033,6 +1033,147 @@ return g; } +static gstring * +lookup_show_supported(gstring * g) +{ +gstring * b = NULL, * d = NULL; + +#if defined(LOOKUP_LSEARCH) +# if LOOKUP_LSEARCH!=2 + b = string_cat(b, US" lsearch wildlsearch nwildlsearch iplsearch"); +# else + d = string_cat(d, US" lsearch wildlsearch nwildlsearch iplsearch"); +# endif +#endif +#if defined(LOOKUP_CDB) +# if LOOKUP_CDB!=2 + b = string_cat(b, US" cdb"); +# else + d = string_cat(d, US" cdb"); +# endif +#endif +#if defined(LOOKUP_DBM) +# if LOOKUP_DBM!=2 + b = string_cat(b, US" dbm dbmjz dbmnz"); +# else + d = string_cat(d, US" dbm dbmjz dbmnz"); +# endif +#endif +#if defined(LOOKUP_DNSDB) +# if LOOKUP_DNSDB!=2 + b = string_cat(b, US" dnsdb"); +# else + d = string_cat(d, US" dnsdb"); +# endif +#endif +#if defined(LOOKUP_DSEARCH) +# if LOOKUP_DSEARCH!=2 + b = string_cat(b, US" dsearch"); +# else + d = string_cat(d, US" dsearch"); +# endif +#endif +#if defined(LOOKUP_IBASE) +# if LOOKUP_IBASE!=2 + b = string_cat(b, US" ibase"); +# else + d = string_cat(d, US" ibase"); +# endif +#endif +#if defined(LOOKUP_JSON) +# if LOOKUP_JSON!=2 + b = string_cat(b, US" json"); +# else + d = string_cat(d, US" json"); +# endif +#endif +#if defined(LOOKUP_LDAP) +# if LOOKUP_LDAP!=2 + b = string_cat(b, US" ldap ldapdn ldapm"); +# else + d = string_cat(d, US" ldap ldapdn ldapm"); +# endif +#endif +#ifdef LOOKUP_LMDB + b = string_cat(b, US" lmdb"); +#endif +#if defined(LOOKUP_MYSQL) +# if LOOKUP_MYSQL!=2 + b = string_cat(b, US" mysql"); +# else + d = string_cat(d, US" mysql"); +# endif +#endif +#if defined(LOOKUP_NIS) +# if LOOKUP_NIS!=2 + b = string_cat(b, US" nis nis0"); +# else + d = string_cat(d, US" nis nis0"); +# endif +#endif +#if defined(LOOKUP_NISPLUS) +# if LOOKUP_NISPLUS!=2 + b = string_cat(b, US" nisplus"); +# else + d = string_cat(d, US" nisplus"); +# endif +#endif +#if defined(LOOKUP_ORACLE) +# if LOOKUP_ORACLE!=2 + b = string_cat(b, US" oracle"); +# else + d = string_cat(d, US" oracle"); +# endif +#endif +#if defined(LOOKUP_PASSWD) +# if LOOKUP_PASSWD!=2 + b = string_cat(b, US" passwd"); +# else + d = string_cat(d, US" passwd"); +# endif +#endif +#if defined(LOOKUP_PGSQL) +# if LOOKUP_PGSQL!=2 + b = string_cat(b, US" pgsql"); +# else + d = string_cat(d, US" pgsql"); +# endif +#endif +#if defined(LOOKUP_REDIS) +# if LOOKUP_REDIS!=2 + b = string_cat(b, US" redis"); +# else + d = string_cat(d, US" redis"); +# endif +#endif +#if defined(LOOKUP_SQLITE) +# if LOOKUP_SQLITE!=2 + b = string_cat(b, US" sqlite"); +# else + d = string_cat(d, US" sqlite"); +# endif +#endif +#if defined(LOOKUP_TESTDB) +# if LOOKUP_TESTDB!=2 + b = string_cat(b, US" testdb"); +# else + d = string_cat(d, US" testdb"); +# endif +#endif +#if defined(LOOKUP_WHOSON) +# if LOOKUP_WHOSON!=2 + b = string_cat(b, US" whoson"); +# else + d = string_cat(d, US" whoson"); +# endif +#endif + +if (b) g = string_fmt_append(g, "Lookups (built-in):%Y\n", b); +if (d) g = string_fmt_append(g, "Lookups (dynamic): %Y\n", d); +return g; +} + + /* This function is called for -bV/--version and for -d to output the optional features of the current Exim binary. @@ -1169,66 +1310,7 @@ g = string_cat(g, US"Support for:"); #endif g = string_cat(g, US"\n"); -g = string_cat(g, US"Lookups (built-in):"); -#if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2 - g = string_cat(g, US" lsearch wildlsearch nwildlsearch iplsearch"); -#endif -#if defined(LOOKUP_CDB) && LOOKUP_CDB!=2 - g = string_cat(g, US" cdb"); -#endif -#if defined(LOOKUP_DBM) && LOOKUP_DBM!=2 - g = string_cat(g, US" dbm dbmjz dbmnz"); -#endif -#if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2 - g = string_cat(g, US" dnsdb"); -#endif -#if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2 - g = string_cat(g, US" dsearch"); -#endif -#if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2 - g = string_cat(g, US" ibase"); -#endif -#if defined(LOOKUP_JSON) && LOOKUP_JSON!=2 - g = string_cat(g, US" json"); -#endif -#if defined(LOOKUP_LDAP) && LOOKUP_LDAP!=2 - g = string_cat(g, US" ldap ldapdn ldapm"); -#endif -#ifdef LOOKUP_LMDB - g = string_cat(g, US" lmdb"); -#endif -#if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2 - g = string_cat(g, US" mysql"); -#endif -#if defined(LOOKUP_NIS) && LOOKUP_NIS!=2 - g = string_cat(g, US" nis nis0"); -#endif -#if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2 - g = string_cat(g, US" nisplus"); -#endif -#if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2 - g = string_cat(g, US" oracle"); -#endif -#if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2 - g = string_cat(g, US" passwd"); -#endif -#if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2 - g = string_cat(g, US" pgsql"); -#endif -#if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2 - g = string_cat(g, US" redis"); -#endif -#if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2 - g = string_cat(g, US" sqlite"); -#endif -#if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2 - g = string_cat(g, US" testdb"); -#endif -#if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2 - g = string_cat(g, US" whoson"); -#endif -g = string_cat(g, US"\n"); - +g = lookup_show_supported(g); g = auth_show_supported(g); g = route_show_supported(g); g = transport_show_supported(g); diff --git a/test/README b/test/README index 67df47453..fe31bda43 100644 --- a/test/README +++ b/test/README @@ -132,6 +132,9 @@ In order to run this test suite, the following requirements must be met: assumes the simpler I/O model. Exim must *not* be built with HEADERS_CHARSET set to UTF-8. +(11) If building any dynamically-loaded lookups, LOOKUP_MODULE_DIR should + be set to .../exim/test/eximdir. + OPTIONAL EXTRAS diff --git a/test/runtest b/test/runtest index d3cea20a8..b89960a8b 100755 --- a/test/runtest +++ b/test/runtest @@ -1297,7 +1297,8 @@ RESET_AFTER_EXTRA_LINE_READ: next if /^tls_set_watch\(\) fail on '\/usr\/(?:lib\/ssl|local\/openssl3\/etc\/pki\/tls)\/cert.pem': No such file or directory$/; # drop lookups - next if /^$time_pid?(?: Lookups\ \(built-in\): + next if /^$time_pid?(?: Lookups\ \((?:built-in|dynamic)\): + |Loaded\ "[^.]+\.so"\ \(\d+\ lookup\ types\) | Loading\ lookup\ modules\ from | Loaded\ \d+\ lookup\ modules | Total\ \d+\ lookups)/x; @@ -3727,12 +3728,13 @@ while () %parm_support = @temp; } - elsif (/^Lookups \(built-in\): (.*)/) + elsif (/^Lookups \((?:built-in|dynamic)\): ?(.*)/) { print; @temp = split /(\s+)/, $1; push(@temp, ' '); - %parm_lookups = @temp; + my %temp_lookups = @temp; + @parm_lookups{keys %temp_lookups} = values %temp_lookups; } elsif (/^Authenticators: (.*)/) @@ -4131,6 +4133,17 @@ system("sudo cp eximdir/exim eximdir/exim_exim;" . "sudo chgrp $parm_eximgroup eximdir/exim_exim;" . "sudo chmod 06755 eximdir/exim_exim"); +# Copy any libraries that were built for dynamic load +# Currently this is only for lookup methods + +($parm_exim_dir) = $parm_exim =~ m?^(.*)/exim?; + +while (my $file = glob("$parm_exim_dir/lookups/*.so")) { + my $base = basename($file); + cp("$file", "eximdir/"); + system("sudo chmod 755 eximdir/$base"); + } + ################################################## # Make copies of utilities we might need # ################################################## @@ -4138,8 +4151,6 @@ system("sudo cp eximdir/exim eximdir/exim_exim;" . # Certain of the tests make use of some of Exim's utilities. We do not need # to be root to copy these. -($parm_exim_dir) = $parm_exim =~ m?^(.*)/exim?; - $dbm_build_deleted = 0; if (defined $parm_lookups{dbm} && not cp("$parm_exim_dir/exim_dbmbuild", "eximdir/exim_dbmbuild")) { -- 2.30.2