Mailing List Archive

[PATCH] dynamically loadable lookup modules
This patch, originally written by Tim Jackson, adopted/fixed by me
and recently forward-ported/updated by David Woodhouse, makes exim
able to (optionally) dynamically load lookup modules rather than
requiring them to all be built in.

This can be used by distributors to avoid shipping O(N^2) packages
for N different database libs or linking one exim binary against
all possible database libraries by providing a package for each
lookup module that isn't built-in or similar packaging.
---
Makefile | 4
OS/Makefile-Base | 1
scripts/Configure-Makefile | 2
scripts/MakeLinks | 1
src/EDITME | 15
src/config.h.defaults | 2
src/drtables.c | 755 +++++++++++++--------------------------------
src/exim.c | 37 +-
src/expand.c | 4
src/globals.h | 2
src/lookupapi.h | 45 ++
src/lookups/Makefile | 245 ++++++++++++--
src/lookups/cdb.c | 29 +
src/lookups/cdb.h | 59 ---
src/lookups/dbmdb.c | 40 ++
src/lookups/dbmdb.h | 21 -
src/lookups/dkim.c | 23 +
src/lookups/dkim.h | 16
src/lookups/dnsdb.c | 24 +
src/lookups/dnsdb.h | 16
src/lookups/dsearch.c | 28 +
src/lookups/dsearch.h | 18 -
src/lookups/ibase.c | 31 +
src/lookups/ibase.h | 18 -
src/lookups/ldap.c | 67 ++-
src/lookups/ldap.h | 11
src/lookups/lsearch.c | 69 +++-
src/lookups/lsearch.h | 25 -
src/lookups/mysql.c | 43 +-
src/lookups/mysql.h | 18 -
src/lookups/nis.c | 48 +-
src/lookups/nis.h | 18 -
src/lookups/nisplus.c | 39 +-
src/lookups/nisplus.h | 17 -
src/lookups/oracle.c | 41 +-
src/lookups/oracle.h | 18 -
src/lookups/passwd.c | 24 +
src/lookups/passwd.h | 16
src/lookups/pgsql.c | 41 +-
src/lookups/pgsql.h | 18 -
src/lookups/spf.c | 28 +
src/lookups/spf.h | 26 -
src/lookups/sqlite.c | 30 +
src/lookups/sqlite.h | 18 -
src/lookups/testdb.c | 24 +
src/lookups/testdb.h | 16
src/lookups/whoson.c | 38 +-
src/lookups/whoson.h | 16
src/macros.h | 2
src/search.c | 22 -
src/structs.h | 29 -
src/verify.c | 2
52 files changed, 1013 insertions(+), 1187 deletions(-)

--- exim-src.orig/Makefile 2008-05-14 12:29:05.000000000 +0200
+++ exim-src/Makefile 2008-05-14 15:10:08.000000000 +0200
@@ -77,11 +77,11 @@ clean:; @echo ""; echo '*** "make clean"
cd build-$(buildname); \
$(RM_COMMAND) -f *.o lookups/*.o lookups/*.a auths/*.o auths/*.a \
routers/*.o routers/*.a transports/*.o transports/*.a \
- pcre/*.o pcre/*.a
+ pcre/*.o pcre/*.a lookups/*.so

clean_exim:; cd build-$(buildname); \
$(RM_COMMAND) -f *.o lookups/*.o lookups/*.a auths/*.o auths/*.a \
- routers/*.o routers/*.a transports/*.o transports/*.a
+ routers/*.o routers/*.a transports/*.o transports/*.a lookups/*.so

distclean:; $(RM_COMMAND) -rf build-*

--- exim-src.orig/OS/Makefile-Base 2008-05-14 12:29:05.000000000 +0200
+++ exim-src/OS/Makefile-Base 2008-05-14 15:10:08.000000000 +0200
@@ -311,6 +311,7 @@ OBJ_EXIM = acl.o child.o crypt16.o daemo
rda.o readconf.o receive.o retry.o rewrite.o rfc2047.o \
route.o search.o sieve.o smtp_in.o smtp_out.o spool_in.o spool_out.o \
store.o string.o tls.o tod.o transport.o tree.o verify.o \
+ lookups/lf_quote.o lookups/lf_check_file.o lookups/lf_sqlperform.o \
local_scan.o $(EXIM_PERL) $(OBJ_WITH_CONTENT_SCAN) \
$(OBJ_WITH_OLD_DEMIME) $(OBJ_EXPERIMENTAL)

--- exim-src.orig/scripts/Configure-Makefile 2008-05-14 12:29:05.000000000 +0200
+++ exim-src/scripts/Configure-Makefile 2008-05-14 15:10:08.000000000 +0200
@@ -107,7 +107,7 @@ do if test -r ../$f
echo "# End of $f"
echo ""
fi
-done >> $mft || exit 1
+done | sed 's/^LOOKUP_/export LOOKUP_/' >> $mft || exit 1

# See if there is a definition of EXIM_PERL in what we have built so far.
# If so, run Perl to find the default values for PERL_CC, PERL_CCOPTS,
--- exim-src.orig/scripts/MakeLinks 2008-05-14 12:29:05.000000000 +0200
+++ exim-src/scripts/MakeLinks 2008-05-14 15:10:08.000000000 +0200
@@ -204,6 +204,7 @@ ln -s ../src/mytypes.h mytypes.h
ln -s ../src/osfunctions.h osfunctions.h
ln -s ../src/store.h store.h
ln -s ../src/structs.h structs.h
+ln -s ../src/lookupapi.h lookupapi.h

ln -s ../src/acl.c acl.c
ln -s ../src/buildconfig.c buildconfig.c
--- exim-src.orig/src/EDITME 2008-05-14 12:29:05.000000000 +0200
+++ exim-src/src/EDITME 2008-05-14 15:10:08.000000000 +0200
@@ -248,6 +248,9 @@ TRANSPORT_SMTP=yes
# SUPPORT_MAILSTORE=yes
# SUPPORT_MBX=yes

+#------------------------------------------------------------------------------
+# See below for dynamic lookup modules.
+# LOOKUP_MODULE_DIR=/usr/lib/exim/lookups/

#------------------------------------------------------------------------------
# These settings determine which file and database lookup methods are included
@@ -257,6 +260,18 @@ TRANSPORT_SMTP=yes
# LOOKUP_DNSDB does *not* refer to general mail routing using the DNS. It is
# for the specialist case of using the DNS as a general database facility (not
# common).
+# If set to "2" instead of "yes" then the corresponding lookup will be
+# built as a module and must be installed into LOOKUP_MODULE_DIR. You need to
+# add -export-dynamic -rdynamic to EXTRALIBS. You may also need to add -ldl to
+# EXTRALIBS so that dlopen() is available to Exim. You need to define
+# LOOKUP_MODULE_DIR above so the exim binary actually loads dynamic lookup
+# modules.
+# Also, instead of adding all the libraries/includes to LOOKUP_INCLUDE and
+# LOOKUP_LIBS, add them to the respective LOOKUP_*_INCLUDE and LOOKUP_*_LIBS
+# (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!

LOOKUP_DBM=yes
LOOKUP_LSEARCH=yes
--- exim-src.orig/src/config.h.defaults 2008-05-14 12:29:05.000000000 +0200
+++ exim-src/src/config.h.defaults 2008-05-14 15:10:09.000000000 +0200
@@ -90,6 +90,8 @@ it's a default value. */
#define LOOKUP_WILDLSEARCH
#define LOOKUP_NWILDLSEARCH

+#define LOOKUP_MODULE_DIR
+
#define MAX_FILTER_SIZE (1024*1024)
#define MAX_LOCALHOST_NUMBER 256
#define MAX_INCLUDE_SIZE (1024*1024)
--- exim-src.orig/src/drtables.c 2008-05-14 12:29:05.000000000 +0200
+++ exim-src/src/drtables.c 2008-05-14 15:10:09.000000000 +0200
@@ -10,6 +10,8 @@

#include "exim.h"

+#include <dlfcn.h>
+#include <string.h>

/* This module contains tables that define the lookup methods and drivers
that are actually included in the binary. Its contents are controlled by
@@ -31,535 +33,8 @@ even pickier compilers complaining about

static void dummy(int x) { dummy(x-1); }

-
-/* Table of information about all possible lookup methods. The entries are
-always present, but the "open" and "find" functions are set to NULL for those
-that are not compiled into the binary. The "check" and "close" functions can
-be NULL for methods that don't need them. */
-
-#ifdef LOOKUP_CDB
-#include "lookups/cdb.h"
-#endif
-
-#ifdef LOOKUP_DBM
-#include "lookups/dbmdb.h"
-#endif
-
-#ifdef LOOKUP_DNSDB
-#include "lookups/dnsdb.h"
-#endif
-
-#ifdef LOOKUP_DSEARCH
-#include "lookups/dsearch.h"
-#endif
-
-#ifdef LOOKUP_IBASE
-#include "lookups/ibase.h"
-#endif
-
-#ifdef LOOKUP_LDAP
-#include "lookups/ldap.h"
-#endif
-
-#ifdef LOOKUP_LSEARCH
-#include "lookups/lsearch.h"
-#endif
-
-#ifdef LOOKUP_MYSQL
-#include "lookups/mysql.h"
-#endif
-
-#ifdef LOOKUP_NIS
-#include "lookups/nis.h"
-#endif
-
-#ifdef LOOKUP_NISPLUS
-#include "lookups/nisplus.h"
-#endif
-
-#ifdef LOOKUP_ORACLE
-#include "lookups/oracle.h"
-#endif
-
-#ifdef LOOKUP_PASSWD
-#include "lookups/passwd.h"
-#endif
-
-#ifdef LOOKUP_PGSQL
-#include "lookups/pgsql.h"
-#endif
-
-#ifdef EXPERIMENTAL_SPF
-#include "lookups/spf.h"
-#endif
-
-#ifdef LOOKUP_SQLITE
-#include "lookups/sqlite.h"
-#endif
-
-#ifdef LOOKUP_TESTDB
-#include "lookups/testdb.h"
-#endif
-
-#ifdef LOOKUP_WHOSON
-#include "lookups/whoson.h"
-#endif
-
-#ifdef EXPERIMENTAL_DKIM
-#include "lookups/dkim.h"
-#endif
-
-
-/* The second field in each item below is a set of bit flags:
-
- lookup_querystyle => this is a query-style lookup,
- else single-key (+ file) style
- lookup_absfile => an absolute file name is required,
- (for single-key style only)
-
-This list must be in alphabetical order of lookup name because it is
-searched by binary chop, having got rather large for the original linear
-searching. */
-
-lookup_info lookup_list[] = {
-
-/* cdb lookup in single file */
-
- {
- US"cdb", /* lookup name */
- lookup_absfile, /* uses absolute file name */
-#ifdef LOOKUP_CDB
- cdb_open, /* open function */
- cdb_check, /* check function */
- cdb_find, /* find function */
- cdb_close, /* close function */
- NULL, /* no tidy function */
- NULL /* no quoting function */
-#else
- NULL, NULL, NULL, NULL, NULL, NULL /* lookup not present */
-#endif
- },
-
-/* DBM file lookup; called "dbm" because that is the name in Exim,
-but the code is called dbmdb to avoid name clashes. */
-
- {
- US"dbm", /* lookup name */
- lookup_absfile, /* uses absolute file name */
-#ifdef LOOKUP_DBM
- dbmdb_open, /* open function */
- dbmdb_check, /* check function */
- dbmdb_find, /* find function */
- dbmdb_close, /* close function */
- NULL, /* no tidy function */
- NULL /* no quoting function */
-#else
- NULL, NULL, NULL, NULL, NULL, NULL /* lookup not present */
-#endif
- },
-
-/* This variant of DBM does not include the binary zero on the end
-of the key strings. */
-
- {
- US"dbmnz", /* lookup name */
- lookup_absfile, /* uses absolute file name */
-#ifdef LOOKUP_DBM
- dbmdb_open, /* sic */ /* open function */
- dbmdb_check, /* sic */ /* check function */
- dbmnz_find, /* find function */
- dbmdb_close, /* sic */ /* close function */
- NULL, /* no tidy function */
- NULL /* no quoting function */
-#else
- NULL, NULL, NULL, NULL, NULL, NULL /* lookup not present */
-#endif
- },
-
-/* DKIM lookups */
-
- {
- US"dkim", /* lookup name */
- lookup_querystyle, /* query style */
-#ifdef EXPERIMENTAL_DKIM
- dkim_open, /* open function */
- NULL, /* check function */
- dkim_find, /* find function */
- NULL, /* no close function */
- NULL, /* no tidy function */
- NULL /* no quoting function */
-#else
- NULL, NULL, NULL, NULL, NULL, NULL /* lookup not present */
-#endif
- },
-
-/* Using DNS TXT records as a database */
-
- {
- US"dnsdb", /* lookup name */
- lookup_querystyle, /* query style */
-#ifdef LOOKUP_DNSDB
- dnsdb_open, /* open function */
- NULL, /* check function */
- dnsdb_find, /* find function */
- NULL, /* no close function */
- NULL, /* no tidy function */
- NULL /* no quoting function */
-#else
- NULL, NULL, NULL, NULL, NULL, NULL /* lookup not present */
-#endif
- },
-
-/* Search of files in a directory */
-
- {
- US"dsearch", /* lookup name */
- lookup_absfile, /* uses absolute file name */
-#ifdef LOOKUP_DSEARCH
- dsearch_open, /* open function */
- dsearch_check, /* check function */
- dsearch_find, /* find function */
- dsearch_close, /* close function */
- NULL, /* no tidy function */
- NULL /* no quoting function */
-#else
- NULL, NULL, NULL, NULL, NULL, NULL /* lookup not present */
-#endif
- },
-
-/* Interbase lookup */
-
- {
- US"ibase", /* lookup name */
- lookup_querystyle, /* query-style lookup */
-#ifdef LOOKUP_IBASE
- ibase_open, /* open function */
- NULL, /* no check function */
- ibase_find, /* find function */
- NULL, /* no close function */
- ibase_tidy, /* tidy function */
- ibase_quote /* quoting function */
-#else
- NULL, NULL, NULL, NULL, NULL, NULL /* lookup not present */
-#endif
- },
-
-/* Linear search of single file with ip-addresses and networks; shares many
-functions with lsearch. */
-
- {
- US"iplsearch", /* lookup name */
- lookup_absfile, /* uses absolute file name */
-#ifdef LOOKUP_LSEARCH
- lsearch_open, /* open function */
- lsearch_check, /* check function */
- iplsearch_find, /* find function */
- lsearch_close, /* close function */
- NULL, /* no tidy function */
- NULL /* no quoting function */
-#else
- NULL, NULL, NULL, NULL, NULL, NULL /* lookup not present */
-#endif
- },
-
-/* LDAP lookup, allowing data from only one entry to be returned */
-
- {
- US"ldap", /* lookup name */
- lookup_querystyle, /* query-style lookup */
-#ifdef LOOKUP_LDAP
- eldap_open, /* open function */
- NULL, /* check function */
- eldap_find, /* find function */
- NULL, /* no close function */
- eldap_tidy, /* tidy function */
- eldap_quote /* quoting function */
-#else
- NULL, NULL, NULL, NULL, NULL, NULL /* lookup not present */
-#endif
- },
-
-/* LDAP lookup, allowing the DN from more one entry to be returned */
-
- {
- US"ldapdn", /* lookup name */
- lookup_querystyle, /* query-style lookup */
-#ifdef LOOKUP_LDAP
- eldap_open, /* sic */ /* open function */
- NULL, /* check function */
- eldapdn_find, /* find function */
- NULL, /* no close function */
- eldap_tidy, /* sic */ /* tidy function */
- eldap_quote /* sic */ /* quoting function */
-#else
- NULL, NULL, NULL, NULL, NULL, NULL /* lookup not present */
-#endif
- },
-
-/* LDAP lookup, allowing data from more than one entry to be returned */
-
- {
- US"ldapm", /* lookup name */
- lookup_querystyle, /* query-style lookup */
-#ifdef LOOKUP_LDAP
- eldap_open, /* sic */ /* open function */
- NULL, /* check function */
- eldapm_find, /* find function */
- NULL, /* no close function */
- eldap_tidy, /* sic */ /* tidy function */
- eldap_quote /* sic */ /* quoting function */
-#else
- NULL, NULL, NULL, NULL, NULL, NULL /* lookup not present */
-#endif
- },
-
-/* Linear search of single file */
-
- {
- US"lsearch", /* lookup name */
- lookup_absfile, /* uses absolute file name */
-#ifdef LOOKUP_LSEARCH
- lsearch_open, /* open function */
- lsearch_check, /* check function */
- lsearch_find, /* find function */
- lsearch_close, /* close function */
- NULL, /* no tidy function */
- NULL /* no quoting function */
-#else
- NULL, NULL, NULL, NULL, NULL, NULL /* lookup not present */
-#endif
- },
-
-/* MYSQL lookup */
-
- {
- US"mysql", /* lookup name */
- lookup_querystyle, /* query-style lookup */
-#ifdef LOOKUP_MYSQL
- mysql_open, /* open function */
- NULL, /* no check function */
- mysql_find, /* find function */
- NULL, /* no close function */
- mysql_tidy, /* tidy function */
- mysql_quote /* quoting function */
-#else
- NULL, NULL, NULL, NULL, NULL, NULL /* lookup not present */
-#endif
- },
-
-/* NIS lookup, excluding trailing 0 from key */
-
- {
- US"nis", /* lookup name */
- 0, /* not abs file, not query style*/
-#ifdef LOOKUP_NIS
- nis_open, /* open function */
- NULL, /* check function */
- nis_find, /* find function */
- NULL, /* no close function */
- NULL, /* no tidy function */
- NULL /* no quoting function */
-#else
- NULL, NULL, NULL, NULL, NULL, NULL /* lookup not present */
-#endif
- },
-
-/* NIS lookup, including trailing 0 in key */
-
- {
- US"nis0", /* lookup name */
- 0, /* not absfile, not query style */
-#ifdef LOOKUP_NIS
- nis_open, /* sic */ /* open function */
- NULL, /* check function */
- nis0_find, /* find function */
- NULL, /* no close function */
- NULL, /* no tidy function */
- NULL /* no quoting function */
-#else
- NULL, NULL, NULL, NULL, NULL, NULL /* lookup not present */
-#endif
- },
-
-/* NIS+ lookup */
-
- {
- US"nisplus", /* lookup name */
- lookup_querystyle, /* query-style lookup */
-#ifdef LOOKUP_NISPLUS
- nisplus_open, /* open function */
- NULL, /* check function */
- nisplus_find, /* find function */
- NULL, /* no close function */
- NULL, /* no tidy function */
- nisplus_quote /* quoting function */
-#else
- NULL, NULL, NULL, NULL, NULL, NULL /* lookup not present */
-#endif
- },
-
-/* Linear search of single file, with wildcarding but no pattern expansion.
-Shares many functions with lsearch. */
-
- {
- US"nwildlsearch", /* lookup name */
- lookup_absfile, /* uses absolute file name */
-#ifdef LOOKUP_LSEARCH
- lsearch_open, /* open function */
- lsearch_check, /* check function */
- nwildlsearch_find, /* find function */
- lsearch_close, /* close function */
- NULL, /* no tidy function */
- NULL /* no quoting function */
-#else
- NULL, NULL, NULL, NULL, NULL, NULL /* lookup not present */
-#endif
- },
-
-/* Oracle lookup */
-
- {
- US"oracle", /* lookup name */
- lookup_querystyle, /* query-style lookup */
-#ifdef LOOKUP_ORACLE
- oracle_open, /* open function */
- NULL, /* check function */
- oracle_find, /* find function */
- NULL, /* no close function */
- oracle_tidy, /* tidy function */
- oracle_quote /* quoting function */
-#else
- NULL, NULL, NULL, NULL, NULL, NULL /* lookup not present */
-#endif
- },
-
-/* passwd lookup */
-
- {
- US"passwd", /* lookup name */
- lookup_querystyle, /* query-style lookup */
-#ifdef LOOKUP_PASSWD
- passwd_open, /* open function */
- NULL, /* no check function */
- passwd_find, /* find function */
- NULL, /* no close function */
- NULL, /* no tidy function */
- NULL /* no quoting function */
-#else
- NULL, NULL, NULL, NULL, NULL, NULL /* lookup not present */
-#endif
- },
-
-/* PGSQL lookup */
-
- {
- US"pgsql", /* lookup name */
- lookup_querystyle, /* query-style lookup */
-#ifdef LOOKUP_PGSQL
- pgsql_open, /* open function */
- NULL, /* no check function */
- pgsql_find, /* find function */
- NULL, /* no close function */
- pgsql_tidy, /* tidy function */
- pgsql_quote /* quoting function */
-#else
- NULL, NULL, NULL, NULL, NULL, NULL /* lookup not present */
-#endif
- },
-
-/* SPF lookup */
-
- {
- US"spf", /* lookup name */
- 0, /* not absfile, not query style */
-#ifdef EXPERIMENTAL_SPF
- spf_open, /* open function */
- NULL, /* no check function */
- spf_find, /* find function */
- spf_close, /* close function */
- NULL, /* no tidy function */
- NULL /* no quoting function */
-#else
- NULL, NULL, NULL, NULL, NULL, NULL /* lookup not present */
-#endif
- },
-
-/* sqlite lookup */
-
- {
- US"sqlite", /* lookup name */
- lookup_absfilequery, /* query-style lookup, starts with file name */
-#ifdef LOOKUP_SQLITE
- sqlite_open, /* open function */
- NULL, /* no check function */
- sqlite_find, /* find function */
- sqlite_close, /* close function */
- NULL, /* no tidy function */
- sqlite_quote /* quoting function */
-#else
- NULL, NULL, NULL, NULL, NULL, NULL /* lookup not present */
-#endif
- },
-
-/* Testdb lookup is for testing Exim, not useful for normal running.
-For that reason, we omit the entry entirely when not building it into
-the binary, so that attempts to use it give "unknown lookup type" instead
-of "lookup type not available". */
-
-#ifdef LOOKUP_TESTDB
- {
- US"testdb", /* lookup name */
- lookup_querystyle, /* query-style lookup */
- testdb_open, /* open function */
- NULL, /* check function */
- testdb_find, /* find function */
- NULL, /* no close function */
- NULL, /* no tidy function */
- NULL /* no quoting function */
- },
-#endif
-
-/* "Whoson" lookup */
-
- {
- US"whoson", /* lookup name */
- lookup_querystyle, /* query-style lookup */
-#ifdef LOOKUP_WHOSON
- whoson_open, /* open function */
- NULL, /* check function */
- whoson_find, /* find function */
- NULL, /* no close function */
- NULL, /* no tidy function */
- NULL /* no quoting function */
-#else
- NULL, NULL, NULL, NULL, NULL, NULL /* lookup not present */
-#endif
- },
-
-/* Linear search of single file, with wildcarding and pattern expansion. Shares
-many functions with lsearch. */
-
- {
- US"wildlsearch", /* lookup name */
- lookup_absfile, /* uses absolute file name */
-#ifdef LOOKUP_LSEARCH
- lsearch_open, /* open function */
- lsearch_check, /* check function */
- wildlsearch_find, /* find function */
- lsearch_close, /* close function */
- NULL, /* no tidy function */
- NULL /* no quoting function */
-#else
- NULL, NULL, NULL, NULL, NULL, NULL /* lookup not present */
-#endif
- }
-};
-
-/* Number of entries in the list */
-
-int lookup_list_count = sizeof(lookup_list)/sizeof(lookup_info);
-
-
+lookup_info **lookup_list;
+int lookup_list_count = 0;

/* Table of information about all possible authentication mechamisms. All
entries are always present if any mechanism is declared, but the functions are
@@ -887,4 +362,226 @@ transport_info transports_available[] =
{ US"", NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, FALSE }
};

+struct lookupmodulestr
+{
+ void *dl;
+ struct lookup_module_info *info;
+ struct lookupmodulestr *next;
+};
+
+static struct lookupmodulestr *lookupmodules = NULL;
+
+static void addlookupmodule(void *dl, struct lookup_module_info *info)
+{
+ struct lookupmodulestr *p = store_malloc(sizeof(struct lookupmodulestr));
+ p->dl = dl;
+ p->info = info;
+ p->next = lookupmodules;
+ lookupmodules = p;
+ lookup_list_count += info->lookupcount;
+}
+
+/* only valid after lookup_list and lookup_list_count are assigned */
+static void add_lookup_to_list(lookup_info *info)
+{
+ /* need to add the lookup to lookup_list, sorted */
+ int pos = 0;
+
+ /* strategy is to go through the list until we find
+ * either an empty spot or a name that is higher.
+ * this can't fail because we have enough space. */
+ while (lookup_list[pos]
+ && (Ustrcmp(lookup_list[pos]->name, info->name) <= 0)) {
+ pos++;
+ }
+ if (lookup_list[pos]) {
+ /* need to insert it, so move all the other items up
+ * (last slot is still empty, of course) */
+ memmove(&lookup_list[pos+1],
+ &lookup_list[pos],
+ sizeof(lookup_info **) * (lookup_list_count-pos-1));
+ }
+ lookup_list[pos] = info;
+}
+
+void init_lookup_list(void)
+{
+ DIR *dd;
+ struct dirent *ent;
+ const pcre *regex_islookupmod = regex_must_compile("\\.so$", FALSE, TRUE);
+ int countmodules = 0;
+ int moduleerrors = 0;
+ struct lookupmodulestr *p;
+
+#if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
+extern lookup_module_info cdb_lookup_module_info;
+ addlookupmodule(NULL, &cdb_lookup_module_info);
+#endif
+
+#if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
+extern lookup_module_info dbmdb_lookup_module_info;
+ addlookupmodule(NULL, &dbmdb_lookup_module_info);
+#endif
+
+#if defined(LOOKUP_DKIM) && LOOKUP_DKIM!=2
+extern lookup_module_info dkim_lookup_module_info;
+ addlookupmodule(NULL, &dkim_lookup_module_info);
+#endif
+
+#if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
+extern lookup_module_info dnsdb_lookup_module_info;
+ addlookupmodule(NULL, &dnsdb_lookup_module_info);
+#endif
+
+#if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
+extern lookup_module_info dsearch_lookup_module_info;
+ addlookupmodule(NULL, &dsearch_lookup_module_info);
+#endif
+
+#if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
+extern lookup_module_info ibase_lookup_module_info;
+ addlookupmodule(NULL, &ibase_lookup_module_info);
+#endif
+
+#ifdef LOOKUP_LDAP
+extern lookup_module_info ldap_lookup_module_info;
+ addlookupmodule(NULL, &ldap_lookup_module_info);
+#endif
+
+#if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
+extern lookup_module_info lsearch_lookup_module_info;
+ addlookupmodule(NULL, &lsearch_lookup_module_info);
+#endif
+
+#if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
+extern lookup_module_info mysql_lookup_module_info;
+ addlookupmodule(NULL, &mysql_lookup_module_info);
+#endif
+
+#if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
+extern lookup_module_info nis_lookup_module_info;
+ addlookupmodule(NULL, &nis_lookup_module_info);
+#endif
+
+#if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
+extern lookup_module_info nisplus_lookup_module_info;
+ addlookupmodule(NULL, &nisplus_lookup_module_info);
+#endif
+
+#if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
+extern lookup_module_info oracle_lookup_module_info;
+ addlookupmodule(NULL, &oracle_lookup_module_info);
+#endif
+
+#if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
+extern lookup_module_info passwd_lookup_module_info;
+ addlookupmodule(NULL, &passwd_lookup_module_info);
+#endif
+
+#if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
+extern lookup_module_info pgsql_lookup_module_info;
+ addlookupmodule(NULL, &pgsql_lookup_module_info);
+#endif
+
+#ifdef EXPERIMENTAL_SPF
+extern lookup_module_info spf_lookup_module_info;
+ addlookupmodule(NULL, &spf_lookup_module_info);
+#endif
+
+#if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
+extern lookup_module_info sqlite_lookup_module_info;
+ addlookupmodule(NULL, &sqlite_lookup_module_info);
+#endif
+
+#if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
+extern lookup_module_info testdb_lookup_module_info;
+ addlookupmodule(NULL, &testdb_lookup_module_info);
+#endif
+
+#if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
+extern lookup_module_info whoson_lookup_module_info;
+ addlookupmodule(NULL, &whoson_lookup_module_info);
+#endif
+
+#ifdef LOOKUP_MODULE_DIR
+ dd = opendir(LOOKUP_MODULE_DIR);
+ if (dd == NULL) {
+ DEBUG(5) debug_printf("Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
+ }
+ else {
+ DEBUG(9) debug_printf("Loading lookup modules from %s\n", LOOKUP_MODULE_DIR);
+ while ((ent = readdir(dd)) != NULL) {
+ char *name = ent->d_name;
+ int len = (int)strlen(name);
+ if (pcre_exec(regex_islookupmod, NULL, name, len, 0, PCRE_EOPT, NULL, 0) >= 0) {
+ int pathnamelen = len + (int)strlen(LOOKUP_MODULE_DIR) + 2;
+ void *dl;
+ struct lookup_module_info *info;
+ char *errormsg;
+
+ /* SRH: am I being paranoid here or what? */
+ if (pathnamelen > big_buffer_size) {
+ fprintf(stderr, "%s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
+ continue;
+ }
+
+ /* SRH: snprintf here? */
+ sprintf(big_buffer, "%s/%s", LOOKUP_MODULE_DIR, name);
+
+ dl = dlopen(big_buffer, RTLD_NOW);// TJ was LAZY
+ if (dl == NULL) {
+ fprintf(stderr, "Error loading %s: %s\n", name, dlerror());
+ moduleerrors++;
+ continue;
+ }
+
+ info = (struct lookup_module_info*) dlsym(dl, "_lookup_module_info");
+ if ((errormsg = dlerror()) != NULL) {
+ fprintf(stderr, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
+ dlclose(dl);
+ moduleerrors++;
+ continue;
+ }
+ if (info->magic != LOOKUP_MODULE_INFO_MAGIC) {
+ fprintf(stderr, "Lookup module %s is not compatible with this version of Exim\n", name);
+ dlclose(dl);
+ moduleerrors++;
+ continue;
+ }
+
+ addlookupmodule(dl, info);
+ DEBUG(9) debug_printf("Loaded \"%s\" (%d lookup types)\n", name, info->lookupcount);
+ countmodules++;
+ }
+ }
+ closedir(dd);
+ }
+
+ DEBUG(9) debug_printf("Loaded %d lookup modules\n", countmodules);
+#endif
+
+ store_free((void*)regex_islookupmod);
+
+ DEBUG(4) debug_printf("Total %d lookups\n", lookup_list_count);
+
+ lookup_list = store_malloc(sizeof(lookup_info *) * lookup_list_count);
+ memset(lookup_list, 0, sizeof(lookup_info *) * lookup_list_count);
+
+ /* now add all lookups to the real list */
+ p = lookupmodules;
+ while (p) {
+ int j;
+ struct lookupmodulestr *pnext;
+
+ for (j = 0; j < p->info->lookupcount; j++)
+ add_lookup_to_list(p->info->lookups[j]);
+
+ pnext = p->next;
+ store_free(p);
+ p = pnext;
+ }
+ /* just to be sure */
+ lookupmodules = NULL;
+}
+
/* End of drtables.c */
--- exim-src.orig/src/exim.c 2008-05-14 12:29:05.000000000 +0200
+++ exim-src/src/exim.c 2008-05-14 15:10:09.000000000 +0200
@@ -928,53 +928,53 @@ fprintf(f, "Support for:");
#endif
fprintf(f, "\n");

-fprintf(f, "Lookups:");
-#ifdef LOOKUP_LSEARCH
+fprintf(f, "Lookups (built-in):");
+#if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
fprintf(f, " lsearch wildlsearch nwildlsearch iplsearch");
#endif
-#ifdef LOOKUP_CDB
+#if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
fprintf(f, " cdb");
#endif
-#ifdef LOOKUP_DBM
+#if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
fprintf(f, " dbm dbmnz");
#endif
-#ifdef LOOKUP_DNSDB
+#if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
fprintf(f, " dnsdb");
#endif
-#ifdef LOOKUP_DSEARCH
+#if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
fprintf(f, " dsearch");
#endif
-#ifdef LOOKUP_IBASE
+#if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
fprintf(f, " ibase");
#endif
-#ifdef LOOKUP_LDAP
+#if defined(LOOKUP_LDAP) && LOOKUP_LDAP!=2
fprintf(f, " ldap ldapdn ldapm");
#endif
-#ifdef LOOKUP_MYSQL
+#if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
fprintf(f, " mysql");
#endif
-#ifdef LOOKUP_NIS
+#if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
fprintf(f, " nis nis0");
#endif
-#ifdef LOOKUP_NISPLUS
+#if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
fprintf(f, " nisplus");
#endif
-#ifdef LOOKUP_ORACLE
+#if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
fprintf(f, " oracle");
#endif
-#ifdef LOOKUP_PASSWD
+#if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
fprintf(f, " passwd");
#endif
-#ifdef LOOKUP_PGSQL
+#if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
fprintf(f, " pgsql");
#endif
-#ifdef LOOKUP_SQLITE
+#if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
fprintf(f, " sqlite");
#endif
-#ifdef LOOKUP_TESTDB
+#if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
fprintf(f, " testdb");
#endif
-#ifdef LOOKUP_WHOSON
+#if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
fprintf(f, " whoson");
#endif
fprintf(f, "\n");
@@ -3427,6 +3427,9 @@ if (opt_perl_at_start && opt_perl_startu
}
#endif /* EXIM_PERL */

+/* Initialise lookup_list */
+init_lookup_list();
+
/* Log the arguments of the call if the configuration file said so. This is
a debugging feature for finding out what arguments certain MUAs actually use.
Don't attempt it if logging is disabled, or if listing variables or if
--- exim-src.orig/src/expand.c 2008-05-14 12:29:05.000000000 +0200
+++ exim-src/src/expand.c 2008-05-14 15:10:09.000000000 +0200
@@ -5378,8 +5378,8 @@ while (*s != 0)
goto EXPAND_FAILED;
}

- if (lookup_list[n].quote != NULL)
- sub = (lookup_list[n].quote)(sub, opt);
+ if (lookup_list[n]->quote != NULL)
+ sub = (lookup_list[n]->quote)(sub, opt);
else if (opt != NULL) sub = NULL;

if (sub == NULL)
--- exim-src.orig/src/globals.h 2008-05-14 12:29:05.000000000 +0200
+++ exim-src/src/globals.h 2008-05-14 15:10:09.000000000 +0200
@@ -438,7 +438,7 @@ extern BOOL log_testing_mode; /
extern BOOL log_timezone; /* TRUE to include the timezone in log lines */
extern unsigned int log_write_selector;/* Bit map of logging options for log_write() */
extern uschar *login_sender_address; /* The actual sender address */
-extern lookup_info lookup_list[]; /* Vector of available lookups */
+extern lookup_info **lookup_list; /* Array of pointers to available lookups */
extern int lookup_list_count; /* Number of entries in the list */
extern int lookup_open_max; /* Max lookup files to cache */
extern uschar *lookup_value; /* Value looked up from file */
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ exim-src/src/lookupapi.h 2008-05-14 15:10:09.000000000 +0200
@@ -0,0 +1,45 @@
+/* The "type" field in each item is a set of bit flags:
+
+ lookup_querystyle => this is a query-style lookup,
+ else single-key (+ file) style
+ lookup_absfile => an absolute file name is required,
+ (for single-key style only)
+*/
+
+typedef struct lookup_info {
+ uschar *name; /* e.g. "lsearch" */
+ int type; /* query/singlekey/abs-file */
+ void *(*open)( /* open function */
+ uschar *, /* file name for those that have one */
+ uschar **); /* for error message */
+ BOOL (*check)( /* file checking function */
+ void *, /* handle */
+ uschar *, /* file name */
+ int, /* modemask for file checking */
+ uid_t *, /* owners for file checking */
+ gid_t *, /* owngroups for file checking */
+ uschar **); /* for error messages */
+ int (*find)( /* find function */
+ void *, /* handle */
+ uschar *, /* file name or NULL */
+ uschar *, /* key or query */
+ int, /* length of key or query */
+ uschar **, /* for returning answer */
+ uschar **, /* for error message */
+ BOOL *); /* to request cache cleanup */
+ void (*close)( /* close function */
+ void *); /* handle */
+ void (*tidy)(void); /* tidy function */
+ uschar *(*quote)( /* quoting function */
+ uschar *, /* string to quote */
+ uschar *); /* additional data from quote name */
+} lookup_info;
+
+/* "LMM1" */
+#define LOOKUP_MODULE_INFO_MAGIC 0x4c4d4d31
+
+typedef struct lookup_module_info {
+ uint magic;
+ lookup_info **lookups;
+ uint lookupcount;
+} lookup_module_info;
--- exim-src.orig/src/lookups/Makefile 2008-05-14 12:29:05.000000000 +0200
+++ exim-src/src/lookups/Makefile 2008-05-14 15:10:09.000000000 +0200
@@ -1,13 +1,181 @@
# $Cambridge: exim/exim-src/src/lookups/Makefile,v 1.8 2008/02/14 13:49:35 fanf2 Exp $

-# Make file for building a library containing all the available lookups and
-# calling it lookups.a. This is called from the main make file, after cd'ing
-# to the lookups subdirectory. When the relevant LOOKUP_ macros are not
-# defined, dummy modules get compiled.
-
-OBJ = cdb.o dbmdb.o dkim.o dnsdb.o dsearch.o ibase.o ldap.o lsearch.o mysql.o nis.o \
- nisplus.o oracle.o passwd.o pgsql.o spf.o sqlite.o testdb.o whoson.o \
- lf_check_file.o lf_quote.o lf_sqlperform.o
+# Make file for building all the available lookups.
+# This is called from the main make file, after cd'ing
+# to the lookups subdirectory.
+
+# because the variable is EXPERIMENTAL_SPF and not LOOKUP_SPF
+# we put this one here by default and compile a dummy if
+# EXPERIMENTAL_SPF is not defined
+OBJ=spf.o
+MODS=
+
+ifeq ($(LOOKUP_CDB),2)
+MODS += cdb.so
+LOOKUP_cdb_INCLUDE = $(LOOKUP_CDB_INCLUDE)
+LOOKUP_cdb_LIBS = $(LOOKUP_CDB_LIBS)
+else
+ifneq ($(LOOKUP_CDB),)
+OBJ += cdb.o
+endif
+endif
+
+ifeq ($(LOOKUP_DBM),2)
+MODS += dbmdb.so
+LOOKUP_dbmdb_INCLUDE = $(LOOKUP_DBM_INCLUDE)
+LOOKUP_dbmdb_LIBS = $(LOOKUP_DBM_LIBS)
+else
+ifneq ($(LOOKUP_DBM),)
+OBJ += dbmdb.o
+endif
+endif
+
+ifeq ($(LOOKUP_DKIM),2)
+MODS += dkim.so
+LOOKUP_dkim_INCLUDE = $(LOOKUP_DKIM_INCLUDE)
+LOOKUP_dkim_LIBS = $(LOOKUP_DKIM_LIBS)
+else
+ifneq ($(LOOKUP_DKIM),)
+OBJ += dkim.o
+endif
+endif
+
+ifeq ($(LOOKUP_DNSDB),2)
+MODS += dnsdb.so
+LOOKUP_dnsdb_INCLUDE = $(LOOKUP_DNSDB_INCLUDE)
+LOOKUP_dnsdb_LIBS = $(LOOKUP_DNSDB_LIBS)
+else
+ifneq ($(LOOKUP_DNSDB),)
+OBJ += dnsdb.o
+endif
+endif
+
+ifeq ($(LOOKUP_DSEARCH),2)
+MODS += dsearch.so
+LOOKUP_dsearch_INCLUDE = $(LOOKUP_DSEARCH_INCLUDE)
+LOOKUP_dsearch_LIBS = $(LOOKUP_DSEARCH_LIBS)
+else
+ifneq ($(LOOKUP_DSEARCH),)
+OBJ += dsearch.o
+endif
+endif
+
+ifeq ($(LOOKUP_IBASE),2)
+MODS += ibase.so
+LOOKUP_ibase_INCLUDE = $(LOOKUP_IBASE_INCLUDE)
+LOOKUP_ibase_LIBS = $(LOOKUP_IBASE_LIBS)
+else
+ifneq ($(LOOKUP_IBASE),)
+OBJ += ibase.o
+endif
+endif
+
+ifneq ($(LOOKUP_LDAP),)
+OBJ += ldap.o
+endif
+
+ifeq ($(LOOKUP_LSEARCH),2)
+MODS += lsearch.so
+LOOKUP_lsearch_INCLUDE = $(LOOKUP_LSEARCH_INCLUDE)
+LOOKUP_lsearch_LIBS = $(LOOKUP_LSEARCH_LIBS)
+else
+ifneq ($(LOOKUP_LSEARCH),)
+OBJ += lsearch.o
+endif
+endif
+
+ifeq ($(LOOKUP_MYSQL),2)
+MODS += mysql.so
+LOOKUP_mysql_INCLUDE = $(LOOKUP_MYSQL_INCLUDE)
+LOOKUP_mysql_LIBS = $(LOOKUP_MYSQL_LIBS)
+else
+ifneq ($(LOOKUP_MYSQL),)
+OBJ += mysql.o
+endif
+endif
+
+ifeq ($(LOOKUP_NIS),2)
+MODS += nis.so
+LOOKUP_nis_INCLUDE = $(LOOKUP_NIS_INCLUDE)
+LOOKUP_nis_LIBS = $(LOOKUP_NIS_LIBS)
+else
+ifneq ($(LOOKUP_NIS),)
+OBJ += nis.o
+endif
+endif
+
+ifeq ($(LOOKUP_NISPLUS),2)
+MODS += nisplus.so
+LOOKUP_nisplus_INCLUDE = $(LOOKUP_NISPLUS_INCLUDE)
+LOOKUP_nisplus_LIBS = $(LOOKUP_NISPLUS_LIBS)
+else
+ifneq ($(LOOKUP_NISPLUS),)
+OBJ += nisplus.o
+endif
+endif
+
+ifeq ($(LOOKUP_ORACLE),2)
+MODS += oracle.so
+LOOKUP_oracle_INCLUDE = $(LOOKUP_ORACLE_INCLUDE)
+LOOKUP_oracle_LIBS = $(LOOKUP_ORACLE_LIBS)
+else
+ifneq ($(LOOKUP_ORACLE),)
+OBJ += oracle.o
+endif
+endif
+
+ifeq ($(LOOKUP_PASSWD),2)
+MODS += passwd.so
+LOOKUP_passwd_INCLUDE = $(LOOKUP_PASSWD_INCLUDE)
+LOOKUP_passwd_LIBS = $(LOOKUP_PASSWD_LIBS)
+else
+ifneq ($(LOOKUP_PASSWD),)
+OBJ += passwd.o
+endif
+endif
+
+ifeq ($(LOOKUP_PGSQL),2)
+MODS += pgsql.so
+LOOKUP_pgsql_INCLUDE = $(LOOKUP_PGSQL_INCLUDE)
+LOOKUP_pgsql_LIBS = $(LOOKUP_PGSQL_LIBS)
+else
+ifneq ($(LOOKUP_PGSQL),)
+OBJ += pgsql.o
+endif
+endif
+
+ifeq ($(LOOKUP_SQLITE),2)
+MODS += sqlite.so
+LOOKUP_sqlite_INCLUDE = $(LOOKUP_SQLITE_INCLUDE)
+LOOKUP_sqlite_LIBS = $(LOOKUP_SQLITE_LIBS)
+else
+ifneq ($(LOOKUP_SQLITE),)
+OBJ += sqlite.o
+endif
+endif
+
+ifeq ($(LOOKUP_TESTDB),2)
+MODS += testdb.so
+LOOKUP_testdb_INCLUDE = $(LOOKUP_TESTDB_INCLUDE)
+LOOKUP_testdb_LIBS = $(LOOKUP_TESTDB_LIBS)
+else
+ifneq ($(LOOKUP_TESTDB),)
+OBJ += testdb.o
+endif
+endif
+
+ifeq ($(LOOKUP_WHOSON),2)
+MODS += whoson.so
+LOOKUP_whoson_INCLUDE = $(LOOKUP_WHOSON_INCLUDE)
+LOOKUP_whoson_LIBS = $(LOOKUP_WHOSON_LIBS)
+else
+ifneq ($(LOOKUP_WHOSON),)
+OBJ += whoson.o
+endif
+endif
+
+
+all: lookups.a lf_quote.o lf_check_file.o lf_sqlperform.o $(MODS)

lookups.a: $(OBJ)
@$(RM_COMMAND) -f lookups.a
@@ -15,31 +183,54 @@ lookups.a: $(OBJ)
@$(AR) lookups.a $(OBJ)
$(RANLIB) $@

-.SUFFIXES: .o .c
+.SUFFIXES: .o .c .so
.c.o:; @echo "$(CC) $*.c"
$(FE)$(CC) -c $(CFLAGS) $(INCLUDE) $*.c

+.c.so:; @echo "$(CC) -shared $*.c"
+ $(FE)$(CC) $(LOOKUP_$*_INCLUDE) $(LOOKUP_$*_LIBS) -DDYNLOOKUP -shared -rdynamic $(CFLAGS) $(INCLUDE) $(DLFLAGS) $*.c -o $@
+
lf_check_file.o: $(HDRS) lf_check_file.c lf_functions.h
lf_quote.o: $(HDRS) lf_quote.c lf_functions.h
lf_sqlperform.o: $(HDRS) lf_sqlperform.c lf_functions.h

-cdb.o: $(HDRS) cdb.c cdb.h
-dbmdb.o: $(HDRS) dbmdb.c dbmdb.h
-dkim.o: $(HDRS) dkim.c dkim.h
-dnsdb.o: $(HDRS) dnsdb.c dnsdb.h
-dsearch.o: $(HDRS) dsearch.c dsearch.h
-ibase.o: $(HDRS) ibase.c ibase.h
-ldap.o: $(HDRS) ldap.c ldap.h
-lsearch.o: $(HDRS) lsearch.c lsearch.h
-mysql.o: $(HDRS) mysql.c mysql.h
-nis.o: $(HDRS) nis.c nis.h
-nisplus.o: $(HDRS) nisplus.c nisplus.h
-oracle.o: $(HDRS) oracle.c oracle.h
-passwd.o: $(HDRS) passwd.c passwd.h
-pgsql.o: $(HDRS) pgsql.c pgsql.h
-spf.o: $(HDRS) spf.c spf.h
-sqlite.o: $(HDRS) sqlite.c sqlite.h
-testdb.o: $(HDRS) testdb.c testdb.h
-whoson.o: $(HDRS) whoson.c whoson.h
+cdb.o: $(HDRS) cdb.c
+dbmdb.o: $(HDRS) dbmdb.c
+dkim.o: $(HDRS) dkim.c
+dnsdb.o: $(HDRS) dnsdb.c
+dsearch.o: $(HDRS) dsearch.c
+ibase.o: $(HDRS) ibase.c
+ldap.o: $(HDRS) ldap.c
+lsearch.o: $(HDRS) lsearch.c
+mysql.o: $(HDRS) mysql.c
+nis.o: $(HDRS) nis.c
+nisplus.o: $(HDRS) nisplus.c
+oracle.o: $(HDRS) oracle.c
+passwd.o: $(HDRS) passwd.c
+pgsql.o: $(HDRS) pgsql.c
+spf.o: $(HDRS) spf.c
+sqlite.o: $(HDRS) sqlite.c
+testdb.o: $(HDRS) testdb.c
+whoson.o: $(HDRS) whoson.c
+
+cdb.so: $(HDRS) cdb.c
+dbmdb.so: $(HDRS) dbmdb.c
+dkim.so: $(HDRS) dkim.c
+dnsdb.so: $(HDRS) dnsdb.c
+dsearch.so: $(HDRS) dsearch.c
+ibase.so: $(HDRS) ibase.c
+ldap.so: $(HDRS) ldap.c
+lsearch.so: $(HDRS) lsearch.c
+mysql.so: $(HDRS) mysql.c
+nis.so: $(HDRS) nis.c
+nisplus.so: $(HDRS) nisplus.c
+oracle.so: $(HDRS) oracle.c
+passwd.so: $(HDRS) passwd.c
+pgsql.so: $(HDRS) pgsql.c
+spf.so: $(HDRS) spf.c
+sqlite.so: $(HDRS) sqlite.c
+testdb.so: $(HDRS) testdb.c
+whoson.so: $(HDRS) whoson.c
+

# End
--- exim-src.orig/src/lookups/cdb.c 2008-05-14 12:29:05.000000000 +0200
+++ exim-src/src/lookups/cdb.c 2008-05-14 15:10:09.000000000 +0200
@@ -56,7 +56,6 @@

#include "../exim.h"
#include "lf_functions.h"
-#include "cdb.h"

#ifdef HAVE_MMAP
# include <sys/mman.h>
@@ -144,7 +143,9 @@ cdb_unpack(uschar *buf)
return num;
}

-void *
+static void cdb_close(void *handle);
+
+static void *
cdb_open(uschar *filename,
uschar **errmsg)
{
@@ -245,7 +246,7 @@ cdb_open(uschar *filename,
* Check entry point *
*************************************************/

-BOOL
+static BOOL
cdb_check(void *handle,
uschar *filename,
int modemask,
@@ -270,7 +271,7 @@ cdb_check(void *handle,
* Find entry point *
*************************************************/

-int
+static int
cdb_find(void *handle,
uschar *filename,
uschar *keystring,
@@ -418,7 +419,7 @@ cdb_find(void *handle,

/* See local README for interface description */

-void
+static void
cdb_close(void *handle)
{
struct cdb_state * cdbp = handle;
@@ -434,4 +435,22 @@ struct cdb_state * cdbp = handle;
(void)close(cdbp->fileno);
}

+lookup_info cdb_lookup_info = {
+ US"cdb", /* lookup name */
+ lookup_absfile, /* uses absolute file name */
+ cdb_open, /* open function */
+ cdb_check, /* check function */
+ cdb_find, /* find function */
+ cdb_close, /* close function */
+ NULL, /* no tidy function */
+ NULL /* no quoting function */
+};
+
+#ifdef DYNLOOKUP
+#define cdb_lookup_module_info _lookup_module_info
+#endif
+
+static lookup_info *_lookup_list[] = { &cdb_lookup_info };
+lookup_module_info cdb_lookup_module_info = { LOOKUP_MODULE_INFO_MAGIC, _lookup_list, 1 };
+
/* End of lookups/cdb.c */
--- exim-src.orig/src/lookups/cdb.h 2008-05-14 12:29:05.000000000 +0200
+++ /dev/null 1970-01-01 00:00:00.000000000 +0000
@@ -1,59 +0,0 @@
-/* $Cambridge: exim/exim-src/src/lookups/cdb.h,v 1.1 2004/10/07 13:10:01 ph10 Exp $ */
-
-/*************************************************
-* Exim - an Internet mail transport agent *
-*************************************************/
-
-/*
- * $Id: cdb.h,v 1.2.2.1 1998/05/29 16:21:36 cvs Exp $
- *
- * Exim - CDB database lookup module
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * Copyright (c) 1998 Nigel Metheringham, Planet Online Ltd
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- *
- * This code implements Dan Bernstein's Constant DataBase (cdb) spec.
- * Information, the spec and sample code for cdb can be obtained from
- * http://www.pobox.com/~djb/cdb.html
- *
- * This implementation borrows some code from Dan Bernstein's
- * implementation (which has no license restrictions applied to it).
- * This (read-only) implementation is completely contained within
- * cdb.[ch] it does *not* link against an external cdb library.
- *
- *
- * There are 2 varients included within this code. One uses MMAP and
- * should give better performance especially for multiple lookups on a
- * modern machine. The other is the default implementation which is
- * used in the case where the MMAP fails or if MMAP was not compiled
- * in. this implementation is the same as the original reference cdb
- * implementation.
- *
- */
-
-
-/* Functions for reading exim cdb files */
-
-extern void *cdb_open(uschar *, uschar **);
-extern BOOL cdb_check(void *, uschar *, int, uid_t *, gid_t *, uschar **);
-extern int cdb_find(void *, uschar *, uschar *, int, uschar **, uschar **,
- BOOL *);
-extern void cdb_close(void *);
-
-/* End of cdb.h */
--- exim-src.orig/src/lookups/dbmdb.c 2008-05-14 12:29:05.000000000 +0200
+++ exim-src/src/lookups/dbmdb.c 2008-05-14 15:10:09.000000000 +0200
@@ -9,7 +9,6 @@

#include "../exim.h"
#include "lf_functions.h"
-#include "dbmdb.h"


/*************************************************
@@ -18,7 +17,7 @@

/* See local README for interface description */

-void *
+static void *
dbmdb_open(uschar *filename, uschar **errmsg)
{
EXIM_DB *yield;
@@ -45,7 +44,7 @@ file name. If USE_TDB or USE_GDBM is set
the same. Otherwise, for safety, we have to check for x.db or x.dir and x.pag.
*/

-BOOL
+static BOOL
dbmdb_check(void *handle, uschar *filename, int modemask, uid_t *owners,
gid_t *owngroups, uschar **errmsg)
{
@@ -88,7 +87,7 @@ return rc == 0;
/* See local README for interface description. This function adds 1 to
the keylength in order to include the terminating zero. */

-int
+static int
dbmdb_find(void *handle, uschar *filename, uschar *keystring, int length,
uschar **result, uschar **errmsg, BOOL *do_cache)
{
@@ -121,7 +120,7 @@ return FAIL;

/* See local README for interface description */

-int
+static int
dbmnz_find(void *handle, uschar *filename, uschar *keystring, int length,
uschar **result, uschar **errmsg, BOOL *do_cache)
{
@@ -137,10 +136,39 @@ return dbmdb_find(handle, filename, keys

/* See local README for interface description */

-void
+static void
dbmdb_close(void *handle)
{
EXIM_DBCLOSE((EXIM_DB *)handle);
}

+lookup_info dbm_lookup_info = {
+ US"dbm", /* lookup name */
+ lookup_absfile, /* uses absolute file name */
+ dbmdb_open, /* open function */
+ dbmdb_check, /* check function */
+ dbmdb_find, /* find function */
+ dbmdb_close, /* close function */
+ NULL, /* no tidy function */
+ NULL /* no quoting function */
+};
+
+lookup_info dbmz_lookup_info = {
+ US"dbmnz", /* lookup name */
+ lookup_absfile, /* uses absolute file name */
+ dbmdb_open, /* sic */ /* open function */
+ dbmdb_check, /* sic */ /* check function */
+ dbmnz_find, /* find function */
+ dbmdb_close, /* sic */ /* close function */
+ NULL, /* no tidy function */
+ NULL /* no quoting function */
+};
+
+#ifdef DYNLOOKUP
+#define dbmdb_lookup_module_info _lookup_module_info
+#endif
+
+static lookup_info *_lookup_list[] = { &dbm_lookup_info, &dbmz_lookup_info };
+lookup_module_info dbmdb_lookup_module_info = { LOOKUP_MODULE_INFO_MAGIC, _lookup_list, 2 };
+
/* End of lookups/dbmdb.c */
--- exim-src.orig/src/lookups/dbmdb.h 2008-05-14 12:29:05.000000000 +0200
+++ /dev/null 1970-01-01 00:00:00.000000000 +0000
@@ -1,21 +0,0 @@
-/* $Cambridge: exim/exim-src/src/lookups/dbmdb.h,v 1.4 2007/01/08 10:50:19 ph10 Exp $ */
-
-/*************************************************
-* Exim - an Internet mail transport agent *
-*************************************************/
-
-/* Copyright (c) University of Cambridge 1995 - 2007 */
-/* See the file NOTICE for conditions of use and distribution. */
-
-/* Header for the dbm lookup. Use dbmdb in the code to avoid name
-clashes with external library names. */
-
-extern void *dbmdb_open(uschar *, uschar **);
-extern BOOL dbmdb_check(void *, uschar *, int, uid_t *, gid_t *, uschar **);
-extern int dbmdb_find(void *, uschar *, uschar *, int, uschar **, uschar **,
- BOOL *);
-extern int dbmnz_find(void *, uschar *, uschar *, int, uschar **, uschar **,
- BOOL *);
-extern void dbmdb_close(void *);
-
-/* End of lookups/dbmdb.h */
--- exim-src.orig/src/lookups/dkim.c 2008-05-14 12:29:05.000000000 +0200
+++ exim-src/src/lookups/dkim.c 2008-05-14 15:10:09.000000000 +0200
@@ -8,7 +8,6 @@
/* See the file NOTICE for conditions of use and distribution. */

#include "../exim.h"
-#include "dkim.h"



@@ -18,7 +17,7 @@

/* See local README for interface description */

-void *
+static void *
dkim_open(uschar *filename, uschar **errmsg)
{
filename = filename; /* Keep picky compilers happy */
@@ -35,7 +34,7 @@ return (void *)(-1); /* Just return

/* See local README for interface description */

-int
+static int
dkim_find(void *handle, uschar *filename, uschar *keystring, int length,
uschar **result, uschar **errmsg, BOOL *do_cache)
{
@@ -49,4 +48,22 @@ dkim_find(void *handle, uschar *filename
#endif
}

+lookup_info cdb_lookup_info = {
+ US"dkim", /* lookup name */
+ lookup_querystyle, /* query style */
+ dkim_open, /* open function */
+ NULL, /* check function */
+ dkim_find, /* find function */
+ NULL, /* no close function */
+ NULL, /* no tidy function */
+ NULL /* no quoting function */
+};
+
+#ifdef DYNLOOKUP
+#define cdb_lookup_module_info _lookup_module_info
+#endif
+
+static lookup_info *_lookup_list[] = { &dkim_lookup_info };
+lookup_module_info cdb_lookup_module_info = { LOOKUP_MODULE_INFO_MAGIC, _lookup_list, 1 };
+
/* End of lookups/dkim.c */
--- exim-src.orig/src/lookups/dkim.h 2008-05-14 12:29:05.000000000 +0200
+++ /dev/null 1970-01-01 00:00:00.000000000 +0000
@@ -1,16 +0,0 @@
-/* $Cambridge: exim/exim-src/src/lookups/dkim.h,v 1.1 2007/09/28 12:21:57 tom Exp $ */
-
-/*************************************************
-* Exim - an Internet mail transport agent *
-*************************************************/
-
-/* Copyright (c) University of Cambridge 1995 - 2007 */
-/* See the file NOTICE for conditions of use and distribution. */
-
-/* Header for the DKIM lookup */
-
-extern void *dkim_open(uschar *, uschar **);
-extern int dkim_find(void *, uschar *, uschar *, int, uschar **, uschar **,
- BOOL *);
-
-/* End of lookups/dkim.h */
--- exim-src.orig/src/lookups/dnsdb.c 2008-05-14 12:29:05.000000000 +0200
+++ exim-src/src/lookups/dnsdb.c 2008-05-14 15:10:09.000000000 +0200
@@ -9,8 +9,6 @@

#include "../exim.h"
#include "lf_functions.h"
-#include "dnsdb.h"
-


/* Ancient systems (e.g. SunOS4) don't appear to have T_TXT defined in their
@@ -67,7 +65,7 @@ static int type_values[] = {

/* See local README for interface description. */

-void *
+static void *
dnsdb_open(uschar *filename, uschar **errmsg)
{
filename = filename; /* Keep picky compilers happy */
@@ -102,7 +100,7 @@ default is "TXT".
which may start with '<' in order to set a specific separator. The default
separator, as always, is colon. */

-int
+static int
dnsdb_find(void *handle, uschar *filename, uschar *keystring, int length,
uschar **result, uschar **errmsg, BOOL *do_cache)
{
@@ -394,4 +392,22 @@ yield[ptr] = 0;
return OK;
}

+static lookup_info _lookup_info = {
+ US"dnsdb", /* lookup name */
+ lookup_querystyle, /* query style */
+ dnsdb_open, /* open function */
+ NULL, /* check function */
+ dnsdb_find, /* find function */
+ NULL, /* no close function */
+ NULL, /* no tidy function */
+ NULL /* no quoting function */
+};
+
+#ifdef DYNLOOKUP
+#define dnsdb_lookup_module_info _lookup_module_info
+#endif
+
+static lookup_info *_lookup_list[] = { &_lookup_info };
+lookup_module_info dnsdb_lookup_module_info = { LOOKUP_MODULE_INFO_MAGIC, _lookup_list, 1 };
+
/* End of lookups/dnsdb.c */
--- exim-src.orig/src/lookups/dnsdb.h 2008-05-14 12:29:05.000000000 +0200
+++ /dev/null 1970-01-01 00:00:00.000000000 +0000
@@ -1,16 +0,0 @@
-/* $Cambridge: exim/exim-src/src/lookups/dnsdb.h,v 1.4 2007/01/08 10:50:19 ph10 Exp $ */
-
-/*************************************************
-* Exim - an Internet mail transport agent *
-*************************************************/
-
-/* Copyright (c) University of Cambridge 1995 - 2007 */
-/* See the file NOTICE for conditions of use and distribution. */
-
-/* Header for the dnsdb lookup */
-
-extern void *dnsdb_open(uschar *, uschar **);
-extern int dnsdb_find(void *, uschar *, uschar *, int, uschar **, uschar **,
- BOOL *);
-
-/* End of lookups/dnsdb.h */
--- exim-src.orig/src/lookups/dsearch.c 2008-05-14 12:29:05.000000000 +0200
+++ exim-src/src/lookups/dsearch.c 2008-05-14 15:10:09.000000000 +0200
@@ -14,8 +14,6 @@ lstat()) rather than a directory scan).

#include "../exim.h"
#include "lf_functions.h"
-#include "dsearch.h"
-


/*************************************************
@@ -27,7 +25,7 @@ whether it exists and whether it is sear
it open, because the "search" can be done by a call to lstat() rather than
actually scanning through the list of files. */

-void *
+static void *
dsearch_open(uschar *dirname, uschar **errmsg)
{
DIR *dp = opendir(CS dirname);
@@ -50,7 +48,7 @@ return (void *)(-1);
/* The handle will always be (void *)(-1), but don't try casting it to an
integer as this gives warnings on 64-bit systems. */

-BOOL
+static BOOL
dsearch_check(void *handle, uschar *filename, int modemask, uid_t *owners,
gid_t *owngroups, uschar **errmsg)
{
@@ -68,7 +66,7 @@ return lf_check_file(-1, filename, S_IFD
scanning the directory, as it is hopefully faster to let the OS do the scanning
for us. */

-int
+static int
dsearch_find(void *handle, uschar *dirname, uschar *keystring, int length,
uschar **result, uschar **errmsg, BOOL *do_cache)
{
@@ -114,10 +112,28 @@ return DEFER;

/* See local README for interface description */

-void
+static void
dsearch_close(void *handle)
{
handle = handle; /* Avoid compiler warning */
}

+static lookup_info _lookup_info = {
+ US"dsearch", /* lookup name */
+ lookup_absfile, /* uses absolute file name */
+ dsearch_open, /* open function */
+ dsearch_check, /* check function */
+ dsearch_find, /* find function */
+ dsearch_close, /* close function */
+ NULL, /* no tidy function */
+ NULL /* no quoting function */
+};
+
+#ifdef DYNLOOKUP
+#define dsearch_lookup_module_info _lookup_module_info
+#endif
+
+static lookup_info *_lookup_list[] = { &_lookup_info };
+lookup_module_info dsearch_lookup_module_info = { LOOKUP_MODULE_INFO_MAGIC, _lookup_list, 1 };
+
/* End of lookups/dsearch.c */
--- exim-src.orig/src/lookups/dsearch.h 2008-05-14 12:29:05.000000000 +0200
+++ /dev/null 1970-01-01 00:00:00.000000000 +0000
@@ -1,18 +0,0 @@
-/* $Cambridge: exim/exim-src/src/lookups/dsearch.h,v 1.4 2007/01/08 10:50:19 ph10 Exp $ */
-
-/*************************************************
-* Exim - an Internet mail transport agent *
-*************************************************/
-
-/* Copyright (c) University of Cambridge 1995 - 2007 */
-/* See the file NOTICE for conditions of use and distribution. */
-
-/* Header for the dsearch lookup */
-
-extern void *dsearch_open(uschar *, uschar **);
-extern BOOL dsearch_check(void *, uschar *, int, uid_t *, gid_t *, uschar **);
-extern int dsearch_find(void *, uschar *, uschar *, int, uschar **, uschar **,
- BOOL *);
-extern void dsearch_close(void *);
-
-/* End of lookups/dsearch.h */
--- exim-src.orig/src/lookups/ibase.c 2008-05-14 12:29:05.000000000 +0200
+++ exim-src/src/lookups/ibase.c 2008-05-14 15:10:09.000000000 +0200
@@ -11,14 +11,7 @@

#include "../exim.h"
#include "lf_functions.h"
-#include "ibase.h"

-#ifndef LOOKUP_IBASE
-static void dummy(int x)
-{
- dummy(x - 1);
-}
-#else
#include <ibase.h> /* The system header */

/* Structure and anchor for caching connections. */
@@ -40,7 +33,7 @@ static ibase_connection *ibase_connectio

/* See local README for interface description. */

-void *ibase_open(uschar * filename, uschar ** errmsg)
+static void *ibase_open(uschar * filename, uschar ** errmsg)
{
return (void *) (1); /* Just return something non-null */
}
@@ -53,7 +46,7 @@ void *ibase_open(uschar * filename, usch

/* See local README for interface description. */

-void ibase_tidy(void)
+static void ibase_tidy(void)
{
ibase_connection *cn;
ISC_STATUS status[20];
@@ -458,7 +451,7 @@ always leaves enough room for a terminat
arguments are not used. Loop through a list of servers while the query is
deferred with a retryable error. */

-int
+static int
ibase_find(void *handle, uschar * filename, uschar * query, int length,
uschar ** result, uschar ** errmsg, BOOL *do_cache)
{
@@ -510,7 +503,7 @@ Arguments:
Returns: the processed string or NULL for a bad option
*/

-uschar *ibase_quote(uschar * s, uschar * opt)
+static uschar *ibase_quote(uschar * s, uschar * opt)
{
register int c;
int count = 0;
@@ -553,6 +546,22 @@ uschar *ibase_quote(uschar * s, uschar *
return quoted;
}

+static lookup_info _lookup_info = {
+ US"ibase", /* lookup name */
+ lookup_querystyle, /* query-style lookup */
+ ibase_open, /* open function */
+ NULL, /* no check function */
+ ibase_find, /* find function */
+ NULL, /* no close function */
+ ibase_tidy, /* tidy function */
+ ibase_quote /* quoting function */
+};
+
+#ifdef DYNLOOKUP
+#define ibase_lookup_module_info _lookup_module_info
#endif

+static lookup_info *_lookup_list[] = { &_lookup_info };
+lookup_module_info ibase_lookup_module_info = { LOOKUP_MODULE_INFO_MAGIC, _lookup_list, 1 };
+
/* End of lookups/ibase.c */
--- exim-src.orig/src/lookups/ibase.h 2008-05-14 12:29:05.000000000 +0200
+++ /dev/null 1970-01-01 00:00:00.000000000 +0000
@@ -1,18 +0,0 @@
-/* $Cambridge: exim/exim-src/src/lookups/ibase.h,v 1.4 2007/01/08 10:50:19 ph10 Exp $ */
-
-/*************************************************
-* Exim - an Internet mail transport agent *
-*************************************************/
-
-/* Copyright (c) University of Cambridge 1995 - 2007 */
-/* See the file NOTICE for conditions of use and distribution. */
-
-/* Header for the Interbase lookup functions */
-
-extern void *ibase_open(uschar *, uschar **);
-extern int ibase_find(void *, uschar *, uschar *, int, uschar **, uschar **,
- BOOL *);
-extern void ibase_tidy(void);
-extern uschar *ibase_quote(uschar *, uschar *);
-
-/* End of lookups/ibase.h */
--- exim-src.orig/src/lookups/ldap.c 2008-05-14 12:29:05.000000000 +0200
+++ exim-src/src/lookups/ldap.c 2008-05-14 15:10:09.000000000 +0200
@@ -15,21 +15,6 @@ researching how to handle the different

#include "../exim.h"
#include "lf_functions.h"
-#include "ldap.h"
-
-
-/* We can't just compile this code and allow the library mechanism to omit the
-functions if they are not wanted, because we need to have the LDAP headers
-available for compiling. Therefore, compile these functions only if LOOKUP_LDAP
-is defined. However, some compilers don't like compiling empty modules, so keep
-them happy with a dummy when skipping the rest. Make it reference itself to
-stop picky compilers complaining that it is unused, and put in a dummy argument
-to stop even pickier compilers complaining about infinite loops. */
-
-#ifndef LOOKUP_LDAP
-static void dummy(int x) { dummy(x-1); }
-#else
-

/* Include LDAP headers. The code below uses some "old" LDAP interfaces that
are deprecated in OpenLDAP. I don't know their status in other LDAP
@@ -1196,7 +1181,7 @@ return DEFER;
are handled by a common function, with a flag to differentiate between them.
The handle and filename arguments are not used. */

-int
+static int
eldap_find(void *handle, uschar *filename, uschar *ldap_url, int length,
uschar **result, uschar **errmsg, BOOL *do_cache)
{
@@ -1205,7 +1190,7 @@ do_cache = do_cache;
return(control_ldap_search(ldap_url, SEARCH_LDAP_SINGLE, result, errmsg));
}

-int
+static int
eldapm_find(void *handle, uschar *filename, uschar *ldap_url, int length,
uschar **result, uschar **errmsg, BOOL *do_cache)
{
@@ -1214,7 +1199,7 @@ do_cache = do_cache;
return(control_ldap_search(ldap_url, SEARCH_LDAP_MULTIPLE, result, errmsg));
}

-int
+static int
eldapdn_find(void *handle, uschar *filename, uschar *ldap_url, int length,
uschar **result, uschar **errmsg, BOOL *do_cache)
{
@@ -1240,7 +1225,7 @@ return(control_ldap_search(ldap_url, SEA

/* See local README for interface description. */

-void *
+static void *
eldap_open(uschar *filename, uschar **errmsg)
{
return (void *)(1); /* Just return something non-null */
@@ -1255,7 +1240,7 @@ return (void *)(1); /* Just return so
/* See local README for interface description.
Make sure that eldap_dn does not refer to reclaimed or worse, freed store */

-void
+static void
eldap_tidy(void)
{
LDAP_CONNECTION *lcp = NULL;
@@ -1351,7 +1336,7 @@ quote_ldap_dn, respectively. */



-uschar *
+static uschar *
eldap_quote(uschar *s, uschar *opt)
{
register int c;
@@ -1470,6 +1455,44 @@ else
return quoted;
}

-#endif /* LOOKUP_LDAP */
+static lookup_info ldap_lookup_info = {
+ US"ldap", /* lookup name */
+ lookup_querystyle, /* query-style lookup */
+ eldap_open, /* open function */
+ NULL, /* check function */
+ eldap_find, /* find function */
+ NULL, /* no close function */
+ eldap_tidy, /* tidy function */
+ eldap_quote /* quoting function */
+};
+
+static lookup_info ldapdn_lookup_info = {
+ US"ldapdn", /* lookup name */
+ lookup_querystyle, /* query-style lookup */
+ eldap_open, /* sic */ /* open function */
+ NULL, /* check function */
+ eldapdn_find, /* find function */
+ NULL, /* no close function */
+ eldap_tidy, /* sic */ /* tidy function */
+ eldap_quote /* sic */ /* quoting function */
+};
+
+static lookup_info ldapm_lookup_info = {
+ US"ldapm", /* lookup name */
+ lookup_querystyle, /* query-style lookup */
+ eldap_open, /* sic */ /* open function */
+ NULL, /* check function */
+ eldapm_find, /* find function */
+ NULL, /* no close function */
+ eldap_tidy, /* sic */ /* tidy function */
+ eldap_quote /* sic */ /* quoting function */
+};
+
+#ifdef DYNLOOKUP
+#define ldap_lookup_module_info _lookup_module_info
+#endif
+
+static lookup_info *_lookup_list[] = { &ldap_lookup_info, &ldapdn_lookup_info, &ldapm_lookup_info };
+lookup_module_info ldap_lookup_module_info = { LOOKUP_MODULE_INFO_MAGIC, _lookup_list, 3 };

/* End of lookups/ldap.c */
--- exim-src.orig/src/lookups/ldap.h 2008-05-14 12:29:05.000000000 +0200
+++ exim-src/src/lookups/ldap.h 2008-05-14 15:10:09.000000000 +0200
@@ -7,18 +7,9 @@
/* Copyright (c) University of Cambridge 1995 - 2007 */
/* See the file NOTICE for conditions of use and distribution. */

-/* Header for the ldap lookups */
+/* Header for eldapauth_find */

-extern void *eldap_open(uschar *, uschar **);
-extern int eldap_find(void *, uschar *, uschar *, int, uschar **, uschar **,
- BOOL *);
extern int eldapauth_find(void *, uschar *, uschar *, int, uschar **,
uschar **, BOOL *);
-extern int eldapdn_find(void *, uschar *, uschar *, int, uschar **,
- uschar **, BOOL *);
-extern int eldapm_find(void *, uschar *, uschar *, int, uschar **,
- uschar **, BOOL *);
-extern void eldap_tidy(void);
-extern uschar *eldap_quote(uschar *, uschar *);

/* End of lookups/ldap.h */
--- exim-src.orig/src/lookups/lsearch.c 2008-05-14 12:29:05.000000000 +0200
+++ exim-src/src/lookups/lsearch.c 2008-05-14 15:10:09.000000000 +0200
@@ -9,7 +9,6 @@

#include "../exim.h"
#include "lf_functions.h"
-#include "lsearch.h"

/* Codes for the different kinds of lsearch that are supported */

@@ -28,7 +27,7 @@ enum {

/* See local README for interface description */

-void *
+static void *
lsearch_open(uschar *filename, uschar **errmsg)
{
FILE *f = Ufopen(filename, "rb");
@@ -48,7 +47,7 @@ return f;
* Check entry point *
*************************************************/

-BOOL
+static BOOL
lsearch_check(void *handle, uschar *filename, int modemask, uid_t *owners,
gid_t *owngroups, uschar **errmsg)
{
@@ -320,7 +319,7 @@ return FAIL;

/* See local README for interface description */

-int
+static int
lsearch_find(void *handle, uschar *filename, uschar *keystring, int length,
uschar **result, uschar **errmsg, BOOL *do_cache)
{
@@ -337,7 +336,7 @@ return internal_lsearch_find(handle, fil

/* See local README for interface description */

-int
+static int
wildlsearch_find(void *handle, uschar *filename, uschar *keystring, int length,
uschar **result, uschar **errmsg, BOOL *do_cache)
{
@@ -354,7 +353,7 @@ return internal_lsearch_find(handle, fil

/* See local README for interface description */

-int
+static int
nwildlsearch_find(void *handle, uschar *filename, uschar *keystring, int length,
uschar **result, uschar **errmsg, BOOL *do_cache)
{
@@ -372,7 +371,7 @@ return internal_lsearch_find(handle, fil

/* See local README for interface description */

-int
+static int
iplsearch_find(void *handle, uschar *filename, uschar *keystring, int length,
uschar **result, uschar **errmsg, BOOL *do_cache)
{
@@ -401,10 +400,64 @@ else

/* See local README for interface description */

-void
+static void
lsearch_close(void *handle)
{
(void)fclose((FILE *)handle);
}

+static lookup_info iplsearch_lookup_info = {
+ US"iplsearch", /* lookup name */
+ lookup_absfile, /* uses absolute file name */
+ lsearch_open, /* open function */
+ lsearch_check, /* check function */
+ iplsearch_find, /* find function */
+ lsearch_close, /* close function */
+ NULL, /* no tidy function */
+ NULL /* no quoting function */
+};
+
+static lookup_info lsearch_lookup_info = {
+ US"lsearch", /* lookup name */
+ lookup_absfile, /* uses absolute file name */
+ lsearch_open, /* open function */
+ lsearch_check, /* check function */
+ lsearch_find, /* find function */
+ lsearch_close, /* close function */
+ NULL, /* no tidy function */
+ NULL /* no quoting function */
+};
+
+static lookup_info nwildlsearch_lookup_info = {
+ US"nwildlsearch", /* lookup name */
+ lookup_absfile, /* uses absolute file name */
+ lsearch_open, /* open function */
+ lsearch_check, /* check function */
+ nwildlsearch_find, /* find function */
+ lsearch_close, /* close function */
+ NULL, /* no tidy function */
+ NULL /* no quoting function */
+};
+
+static lookup_info wildlsearch_lookup_info = {
+ US"wildlsearch", /* lookup name */
+ lookup_absfile, /* uses absolute file name */
+ lsearch_open, /* open function */
+ lsearch_check, /* check function */
+ wildlsearch_find, /* find function */
+ lsearch_close, /* close function */
+ NULL, /* no tidy function */
+ NULL /* no quoting function */
+};
+
+#ifdef DYNLOOKUP
+#define lsearch_lookup_module_info _lookup_module_info
+#endif
+
+static lookup_info *_lookup_list[] = { &iplsearch_lookup_info,
+ &lsearch_lookup_info,
+ &nwildlsearch_lookup_info,
+ &wildlsearch_lookup_info };
+lookup_module_info lsearch_lookup_module_info = { LOOKUP_MODULE_INFO_MAGIC, _lookup_list, 4 };
+
/* End of lookups/lsearch.c */
--- exim-src.orig/src/lookups/lsearch.h 2008-05-14 12:29:05.000000000 +0200
+++ /dev/null 1970-01-01 00:00:00.000000000 +0000
@@ -1,25 +0,0 @@
-/* $Cambridge: exim/exim-src/src/lookups/lsearch.h,v 1.4 2007/01/08 10:50:19 ph10 Exp $ */
-
-/*************************************************
-* Exim - an Internet mail transport agent *
-*************************************************/
-
-/* Copyright (c) University of Cambridge 1995 - 2007 */
-/* See the file NOTICE for conditions of use and distribution. */
-
-/* Header for the lsearch and wildlsearch lookups */
-
-extern void *lsearch_open(uschar *, uschar **);
-extern BOOL lsearch_check(void *, uschar *, int, uid_t *, gid_t *, uschar **);
-extern int lsearch_find(void *, uschar *, uschar *, int, uschar **,
- uschar **, BOOL *);
-extern void lsearch_close(void *);
-
-extern int wildlsearch_find(void *, uschar *, uschar *, int, uschar **,
- uschar **, BOOL *);
-extern int nwildlsearch_find(void *, uschar *, uschar *, int, uschar **,
- uschar **, BOOL *);
-extern int iplsearch_find(void *, uschar *, uschar *, int, uschar **,
- uschar **, BOOL *);
-
-/* End of lookups/lsearch.h */
--- exim-src.orig/src/lookups/mysql.c 2008-05-14 12:29:05.000000000 +0200
+++ exim-src/src/lookups/mysql.c 2008-05-14 15:10:09.000000000 +0200
@@ -13,22 +13,6 @@ functions. */

#include "../exim.h"
#include "lf_functions.h"
-#include "mysql.h" /* The local header */
-
-
-/* We can't just compile this code and allow the library mechanism to omit the
-functions if they are not wanted, because we need to have the MYSQL header
-available for compiling. Therefore, compile these functions only if
-LOOKUP_MYSQL is defined. However, some compilers don't like compiling empty
-modules, so keep them happy with a dummy when skipping the rest. Make it
-reference itself to stop picky compilers complaining that it is unused, and put
-in a dummy argument to stop even pickier compilers complaining about infinite
-loops. */
-
-#ifndef LOOKUP_MYSQL
-static void dummy(int x) { dummy(x-1); }
-#else
-

#include <mysql.h> /* The system header */

@@ -51,7 +35,7 @@ static mysql_connection *mysql_connectio

/* See local README for interface description. */

-void *
+static void *
mysql_open(uschar *filename, uschar **errmsg)
{
return (void *)(1); /* Just return something non-null */
@@ -65,7 +49,7 @@ return (void *)(1); /* Just return so

/* See local README for interface description. */

-void
+static void
mysql_tidy(void)
{
mysql_connection *cn;
@@ -342,7 +326,7 @@ arguments are not used. The code to loop
query is deferred with a retryable error is now in a separate function that is
shared with other SQL lookups. */

-int
+static int
mysql_find(void *handle, uschar *filename, uschar *query, int length,
uschar **result, uschar **errmsg, BOOL *do_cache)
{
@@ -372,7 +356,7 @@ Arguments:
Returns: the processed string or NULL for a bad option
*/

-uschar *
+static uschar *
mysql_quote(uschar *s, uschar *opt)
{
register int c;
@@ -414,7 +398,24 @@ while ((c = *s++) != 0)
return quoted;
}

+/* These are the lookup_info blocks for this driver */
+
+static lookup_info mysql_lookup_info = {
+ US"mysql", /* lookup name */
+ lookup_querystyle, /* query-style lookup */
+ mysql_open, /* open function */
+ NULL, /* no check function */
+ mysql_find, /* find function */
+ NULL, /* no close function */
+ mysql_tidy, /* tidy function */
+ mysql_quote /* quoting function */
+};
+
+#ifdef DYNLOOKUP
+#define mysql_lookup_module_info _lookup_module_info
+#endif

-#endif /* MYSQL_LOOKUP */
+static lookup_info *_lookup_list[] = { &mysql_lookup_info };
+lookup_module_info mysql_lookup_module_info = { LOOKUP_MODULE_INFO_MAGIC, _lookup_list, 1 };

/* End of lookups/mysql.c */
--- exim-src.orig/src/lookups/mysql.h 2008-05-14 12:29:05.000000000 +0200
+++ /dev/null 1970-01-01 00:00:00.000000000 +0000
@@ -1,18 +0,0 @@
-/* $Cambridge: exim/exim-src/src/lookups/mysql.h,v 1.4 2007/01/08 10:50:19 ph10 Exp $ */
-
-/*************************************************
-* Exim - an Internet mail transport agent *
-*************************************************/
-
-/* Copyright (c) University of Cambridge 1995 - 2007 */
-/* See the file NOTICE for conditions of use and distribution. */
-
-/* Header for the mysql lookup functions */
-
-extern void *mysql_open(uschar *, uschar **);
-extern int mysql_find(void *, uschar *, uschar *, int, uschar **, uschar **,
- BOOL *);
-extern void mysql_tidy(void);
-extern uschar *mysql_quote(uschar *, uschar *);
-
-/* End of lookups/mysql.h */
--- exim-src.orig/src/lookups/nis.c 2008-05-14 12:29:05.000000000 +0200
+++ exim-src/src/lookups/nis.c 2008-05-14 15:10:09.000000000 +0200
@@ -9,19 +9,6 @@

#include "../exim.h"
#include "lf_functions.h"
-#include "nis.h"
-
-/* We can't just compile this code and allow the library mechanism to omit the
-functions if they are not wanted, because we need to have the NIS header
-available for compiling. Therefore, compile these functions only if LOOKUP_NIS
-is defined. However, some compilers don't like compiling empty modules, so keep
-them happy with a dummy when skipping the rest. Make it reference itself to
-stop picky compilers complaining that it is unused, and put in a dummy argument
-to stop even pickier compilers complaining about infinite loops. */
-
-#ifndef LOOKUP_NIS
-static void dummy(int x) { dummy(x-1); }
-#else

#include <rpcsvc/ypclnt.h>

@@ -33,7 +20,7 @@ static void dummy(int x) { dummy(x-1); }
/* See local README for interface description. This serves for both
the "nis" and "nis0" lookup types. */

-void *
+static void *
nis_open(uschar *filename, uschar **errmsg)
{
char *nis_domain;
@@ -55,7 +42,7 @@ return nis_domain;
for nis0 because they are so short it isn't worth trying to use any common
code. */

-int
+static int
nis_find(void *handle, uschar *filename, uschar *keystring, int length,
uschar **result, uschar **errmsg, BOOL *do_cache)
{
@@ -81,7 +68,7 @@ return (rc == YPERR_KEY || rc == YPERR_M

/* See local README for interface description. */

-int
+static int
nis0_find(void *handle, uschar *filename, uschar *keystring, int length,
uschar **result, uschar **errmsg, BOOL *do_cache)
{
@@ -99,6 +86,33 @@ if ((rc = yp_match(CS handle, CS filenam
return (rc == YPERR_KEY || rc == YPERR_MAP)? FAIL : DEFER;
}

-#endif /* LOOKUP_NIS */
+static lookup_info nis_lookup_info = {
+ US"nis", /* lookup name */
+ 0, /* not abs file, not query style*/
+ nis_open, /* open function */
+ NULL, /* check function */
+ nis_find, /* find function */
+ NULL, /* no close function */
+ NULL, /* no tidy function */
+ NULL /* no quoting function */
+};
+
+static lookup_info nis0_lookup_info = {
+ US"nis0", /* lookup name */
+ 0, /* not absfile, not query style */
+ nis_open, /* sic */ /* open function */
+ NULL, /* check function */
+ nis0_find, /* find function */
+ NULL, /* no close function */
+ NULL, /* no tidy function */
+ NULL /* no quoting function */
+};
+
+#ifdef DYNLOOKUP
+#define nis_lookup_module_info _lookup_module_info
+#endif
+
+static lookup_info *_lookup_list[] = { &nis_lookup_info, &nis0_lookup_info };
+lookup_module_info nis_lookup_module_info = { LOOKUP_MODULE_INFO_MAGIC, _lookup_list, 2 };

/* End of lookups/nis.c */
--- exim-src.orig/src/lookups/nis.h 2008-05-14 12:29:05.000000000 +0200
+++ /dev/null 1970-01-01 00:00:00.000000000 +0000
@@ -1,18 +0,0 @@
-/* $Cambridge: exim/exim-src/src/lookups/nis.h,v 1.4 2007/01/08 10:50:19 ph10 Exp $ */
-
-/*************************************************
-* Exim - an Internet mail transport agent *
-*************************************************/
-
-/* Copyright (c) University of Cambridge 1995 - 2007 */
-/* See the file NOTICE for conditions of use and distribution. */
-
-/* Header for the nis and nis0 lookups */
-
-extern void *nis_open(uschar *, uschar **);
-extern int nis_find(void *, uschar *, uschar *, int, uschar **, uschar **,
- BOOL *);
-extern int nis0_find(void *, uschar *, uschar *, int, uschar **, uschar **,
- BOOL *);
-
-/* End of lookups/nis.h */
--- exim-src.orig/src/lookups/nisplus.c 2008-05-14 12:29:05.000000000 +0200
+++ exim-src/src/lookups/nisplus.c 2008-05-14 15:10:09.000000000 +0200
@@ -9,21 +9,6 @@

#include "../exim.h"
#include "lf_functions.h"
-#include "nisplus.h"
-
-/* We can't just compile this code and allow the library mechanism to omit the
-functions if they are not wanted, because we need to have the NIS+ header
-available for compiling. Therefore, compile these functions only if
-LOOKUP_NISPLUS is defined. However, some compilers don't like compiling empty
-modules, so keep them happy with a dummy when skipping the rest. Make it
-reference itself to stop picky compilers complaining that it is unused, and put
-in a dummy argument to stop even pickier compilers complaining about infinite
-loops. */
-
-#ifndef LOOKUP_NISPLUS
-static void dummy(int x) { dummy(x-1); }
-#else
-

#include <rpcsvc/nis.h>

@@ -34,7 +19,7 @@ static void dummy(int x) { dummy(x-1); }

/* See local README for interface description. */

-void *
+static void *
nisplus_open(uschar *filename, uschar **errmsg)
{
return (void *)(1); /* Just return something non-null */
@@ -58,7 +43,7 @@ name tagged on the end after a colon. If
yield is the concatenation of all the fields, preceded by their names and an
equals sign. */

-int
+static int
nisplus_find(void *handle, uschar *filename, uschar *query, int length,
uschar **result, uschar **errmsg, BOOL *do_cache)
{
@@ -250,7 +235,7 @@ Arguments:
Returns: the processed string or NULL for a bad option
*/

-uschar *
+static uschar *
nisplus_quote(uschar *s, uschar *opt)
{
int count = 0;
@@ -274,6 +259,22 @@ while (*s != 0)
return quoted;
}

-#endif /* LOOKUP_NISPLUS */
+static lookup_info _lookup_info = {
+ US"nisplus", /* lookup name */
+ lookup_querystyle, /* query-style lookup */
+ nisplus_open, /* open function */
+ NULL, /* check function */
+ nisplus_find, /* find function */
+ NULL, /* no close function */
+ NULL, /* no tidy function */
+ nisplus_quote /* quoting function */
+};
+
+#ifdef DYNLOOKUP
+#define nisplus_lookup_module_info _lookup_module_info
+#endif
+
+static lookup_info *_lookup_list[] = { &_lookup_info };
+lookup_module_info nisplus_lookup_module_info = { LOOKUP_MODULE_INFO_MAGIC, _lookup_list, 1 };

/* End of lookups/nisplus.c */
--- exim-src.orig/src/lookups/nisplus.h 2008-05-14 12:29:05.000000000 +0200
+++ /dev/null 1970-01-01 00:00:00.000000000 +0000
@@ -1,17 +0,0 @@
-/* $Cambridge: exim/exim-src/src/lookups/nisplus.h,v 1.4 2007/01/08 10:50:19 ph10 Exp $ */
-
-/*************************************************
-* Exim - an Internet mail transport agent *
-*************************************************/
-
-/* Copyright (c) University of Cambridge 1995 - 2007 */
-/* See the file NOTICE for conditions of use and distribution. */
-
-/* Header for the nisplus lookup */
-
-extern void *nisplus_open(uschar *, uschar **);
-extern int nisplus_find(void *, uschar *, uschar *, int, uschar **,
- uschar **, BOOL *);
-extern uschar *nisplus_quote(uschar *, uschar *);
-
-/* End of lookups/nisplus.h */
--- exim-src.orig/src/lookups/oracle.c 2008-05-14 12:29:05.000000000 +0200
+++ exim-src/src/lookups/oracle.c 2008-05-14 15:10:09.000000000 +0200
@@ -15,27 +15,12 @@ some comments from my position of Oracle
#include "../exim.h"


-/* We can't just compile this code and allow the library mechanism to omit the
-functions if they are not wanted, because we need to have the ORACLE headers
-available for compiling. Therefore, compile these functions only if
-LOOKUP_ORACLE is defined. However, some compilers don't like compiling empty
-modules, so keep them happy with a dummy when skipping the rest. Make it
-reference itself to stop picky compilers complaining that it is unused, and put
-in a dummy argument to stop even pickier compilers complaining about infinite
-loops. */
-
-#ifndef LOOKUP_ORACLE
-static void dummy(int x) { dummy(x-1); }
-#else
-
/* The Oracle system headers */

#include <oratypes.h>
#include <ocidfn.h>
#include <ocikpr.h>

-#include "oracle.h" /* The local header */
-
#define PARSE_NO_DEFER 0 /* parse straight away */
#define PARSE_V7_LNG 2
#define MAX_ITEM_BUFFER_SIZE 1024 /* largest size of a cell of data */
@@ -212,7 +197,7 @@ return col;

/* See local README for interface description. */

-void *
+static void *
oracle_open(uschar *filename, uschar **errmsg)
{
return (void *)(1); /* Just return something non-null */
@@ -226,7 +211,7 @@ return (void *)(1); /* Just return so

/* See local README for interface description. */

-void
+static void
oracle_tidy(void)
{
oracle_connection *cn;
@@ -532,7 +517,7 @@ else
arguments are not used. Loop through a list of servers while the query is
deferred with a retryable error. */

-int
+static int
oracle_find(void *handle, uschar *filename, uschar *query, int length,
uschar **result, uschar **errmsg, BOOL *do_cache)
{
@@ -577,7 +562,7 @@ Arguments:
Returns: the processed string or NULL for a bad option
*/

-uschar *
+static uschar *
oracle_quote(uschar *s, uschar *opt)
{
register int c;
@@ -619,6 +604,22 @@ while ((c = *s++) != 0)
return quoted;
}

-#endif /* LOOKUP_ORACLE */
+static lookup_info _lookup_info = {
+ US"oracle", /* lookup name */
+ lookup_querystyle, /* query-style lookup */
+ oracle_open, /* open function */
+ NULL, /* check function */
+ oracle_find, /* find function */
+ NULL, /* no close function */
+ oracle_tidy, /* tidy function */
+ oracle_quote /* quoting function */
+};
+
+#ifdef DYNLOOKUP
+#define oracle_lookup_module_info _lookup_module_info
+#endif
+
+static lookup_info *_lookup_list[] = { &_lookup_info };
+lookup_module_info oracle_lookup_module_info = { LOOKUP_MODULE_INFO_MAGIC, _lookup_list, 1 };

/* End of lookups/oracle.c */
--- exim-src.orig/src/lookups/oracle.h 2008-05-14 12:29:05.000000000 +0200
+++ /dev/null 1970-01-01 00:00:00.000000000 +0000
@@ -1,18 +0,0 @@
-/* $Cambridge: exim/exim-src/src/lookups/oracle.h,v 1.4 2007/01/08 10:50:19 ph10 Exp $ */
-
-/*************************************************
-* Exim - an Internet mail transport agent *
-*************************************************/
-
-/* Copyright (c) University of Cambridge 1995 - 2007 */
-/* See the file NOTICE for conditions of use and distribution. */
-
-/* Header for the Oracle lookup functions */
-
-extern void *oracle_open(uschar *, uschar **);
-extern int oracle_find(void *, uschar *, uschar *, int, uschar **,
- uschar **, BOOL *);
-extern void oracle_tidy(void);
-extern uschar *oracle_quote(uschar *, uschar *);
-
-/* End of lookups/oracle.h */
--- exim-src.orig/src/lookups/passwd.c 2008-05-14 12:29:05.000000000 +0200
+++ exim-src/src/lookups/passwd.c 2008-05-14 15:10:09.000000000 +0200
@@ -8,8 +8,6 @@
/* See the file NOTICE for conditions of use and distribution. */

#include "../exim.h"
-#include "passwd.h"
-


/*************************************************
@@ -18,7 +16,7 @@

/* See local README for interface description */

-void *
+static void *
passwd_open(uschar *filename, uschar **errmsg)
{
filename = filename; /* Keep picky compilers happy */
@@ -35,7 +33,7 @@ return (void *)(-1); /* Just return

/* See local README for interface description */

-int
+static int
passwd_find(void *handle, uschar *filename, uschar *keystring, int length,
uschar **result, uschar **errmsg, BOOL *do_cache)
{
@@ -53,4 +51,22 @@ if (!route_finduser(keystring, &pw, NULL
return OK;
}

+static lookup_info _lookup_info = {
+ US"passwd", /* lookup name */
+ lookup_querystyle, /* query-style lookup */
+ passwd_open, /* open function */
+ NULL, /* no check function */
+ passwd_find, /* find function */
+ NULL, /* no close function */
+ NULL, /* no tidy function */
+ NULL /* no quoting function */
+};
+
+#ifdef DYNLOOKUP
+#define passwd_lookup_module_info _lookup_module_info
+#endif
+
+static lookup_info *_lookup_list[] = { &_lookup_info };
+lookup_module_info passwd_lookup_module_info = { LOOKUP_MODULE_INFO_MAGIC, _lookup_list, 1 };
+
/* End of lookups/passwd.c */
--- exim-src.orig/src/lookups/passwd.h 2008-05-14 12:29:05.000000000 +0200
+++ /dev/null 1970-01-01 00:00:00.000000000 +0000
@@ -1,16 +0,0 @@
-/* $Cambridge: exim/exim-src/src/lookups/passwd.h,v 1.4 2007/01/08 10:50:19 ph10 Exp $ */
-
-/*************************************************
-* Exim - an Internet mail transport agent *
-*************************************************/
-
-/* Copyright (c) University of Cambridge 1995 - 2007 */
-/* See the file NOTICE for conditions of use and distribution. */
-
-/* Header for the passwd lookup */
-
-extern void *passwd_open(uschar *, uschar **);
-extern int passwd_find(void *, uschar *, uschar *, int, uschar **, uschar **,
- BOOL *);
-
-/* End of lookups/passwd.h */
--- exim-src.orig/src/lookups/pgsql.c 2008-05-14 12:29:05.000000000 +0200
+++ exim-src/src/lookups/pgsql.c 2008-05-14 15:10:09.000000000 +0200
@@ -13,21 +13,6 @@ socket extension. */

#include "../exim.h"
#include "lf_functions.h"
-#include "pgsql.h" /* The local header */
-
-/* We can't just compile this code and allow the library mechanism to omit the
-functions if they are not wanted, because we need to have the PGSQL header
-available for compiling. Therefore, compile these functions only if
-LOOKUP_PGSQL is defined. However, some compilers don't like compiling empty
-modules, so keep them happy with a dummy when skipping the rest. Make it
-reference itself to stop picky compilers complaining that it is unused, and put
-in a dummy argument to stop even pickier compilers complaining about infinite
-loops. */
-
-#ifndef LOOKUP_PGSQL
-static void dummy(int x) { dummy(x-1); }
-#else
-

#include <libpq-fe.h> /* The system header */

@@ -49,7 +34,7 @@ static pgsql_connection *pgsql_connectio

/* See local README for interface description. */

-void *
+static void *
pgsql_open(uschar *filename, uschar **errmsg)
{
return (void *)(1); /* Just return something non-null */
@@ -63,7 +48,7 @@ return (void *)(1); /* Just return so

/* See local README for interface description. */

-void
+static void
pgsql_tidy(void)
{
pgsql_connection *cn;
@@ -414,7 +399,7 @@ arguments are not used. The code to loop
query is deferred with a retryable error is now in a separate function that is
shared with other SQL lookups. */

-int
+static int
pgsql_find(void *handle, uschar *filename, uschar *query, int length,
uschar **result, uschar **errmsg, BOOL *do_cache)
{
@@ -454,7 +439,7 @@ Arguments:
Returns: the processed string or NULL for a bad option
*/

-uschar *
+static uschar *
pgsql_quote(uschar *s, uschar *opt)
{
register int c;
@@ -501,6 +486,22 @@ while ((c = *s++) != 0)
return quoted;
}

-#endif /* PGSQL_LOOKUP */
+static lookup_info _lookup_info = {
+ US"pgsql", /* lookup name */
+ lookup_querystyle, /* query-style lookup */
+ pgsql_open, /* open function */
+ NULL, /* no check function */
+ pgsql_find, /* find function */
+ NULL, /* no close function */
+ pgsql_tidy, /* tidy function */
+ pgsql_quote /* quoting function */
+};
+
+#ifdef DYNLOOKUP
+#define pgsql_lookup_module_info _lookup_module_info
+#endif
+
+static lookup_info *_lookup_list[] = { &_lookup_info };
+lookup_module_info pgsql_lookup_module_info = { LOOKUP_MODULE_INFO_MAGIC, _lookup_list, 1 };

/* End of lookups/pgsql.c */
--- exim-src.orig/src/lookups/pgsql.h 2008-05-14 12:29:05.000000000 +0200
+++ /dev/null 1970-01-01 00:00:00.000000000 +0000
@@ -1,18 +0,0 @@
-/* $Cambridge: exim/exim-src/src/lookups/pgsql.h,v 1.4 2007/01/08 10:50:19 ph10 Exp $ */
-
-/*************************************************
-* Exim - an Internet mail transport agent *
-*************************************************/
-
-/* Copyright (c) University of Cambridge 1995 - 2007 */
-/* See the file NOTICE for conditions of use and distribution. */
-
-/* Header for the pgsql lookup functions */
-
-extern void *pgsql_open(uschar *, uschar **);
-extern int pgsql_find(void *, uschar *, uschar *, int, uschar **, uschar **,
- BOOL *);
-extern void pgsql_tidy(void);
-extern uschar *pgsql_quote(uschar *, uschar *);
-
-/* End of lookups/pgsql.h */
--- exim-src.orig/src/lookups/spf.c 2008-05-14 12:29:05.000000000 +0200
+++ exim-src/src/lookups/spf.c 2008-05-14 15:10:09.000000000 +0200
@@ -24,7 +24,6 @@ static void dummy(int x) { dummy(x-1); }
#else

#include "lf_functions.h"
-#include "spf.h"
#ifndef HAVE_NS_TYPE
#define HAVE_NS_TYPE
#endif
@@ -32,7 +31,7 @@ static void dummy(int x) { dummy(x-1); }
#include <spf2/spf_dns_resolv.h>
#include <spf2/spf_dns_cache.h>

-void *spf_open(uschar *filename, uschar **errmsg) {
+static void *spf_open(uschar *filename, uschar **errmsg) {
SPF_server_t *spf_server = NULL;
spf_server = SPF_server_new(SPF_DNS_CACHE, 0);
if (spf_server == NULL) {
@@ -42,13 +41,14 @@ void *spf_open(uschar *filename, uschar
return (void *) spf_server;
}

-void spf_close(void *handle) {
+static void spf_close(void *handle) {
SPF_server_t *spf_server = handle;
if (spf_server) SPF_server_free(spf_server);
}

-int spf_find(void *handle, uschar *filename, uschar *keystring, int key_len,
- uschar **result, uschar **errmsg, BOOL *do_cache) {
+static int
+spf_find(void *handle, uschar *filename, uschar *keystring, int key_len,
+ uschar **result, uschar **errmsg, BOOL *do_cache) {
SPF_server_t *spf_server = handle;
SPF_request_t *spf_request = NULL;
SPF_response_t *spf_response = NULL;
@@ -75,4 +75,22 @@ int spf_find(void *handle, uschar *filen
return OK;
}

+static lookup_info _lookup_info = {
+ US"spf", /* lookup name */
+ 0, /* not absfile, not query style */
+ spf_open, /* open function */
+ NULL, /* no check function */
+ spf_find, /* find function */
+ spf_close, /* close function */
+ NULL, /* no tidy function */
+ NULL /* no quoting function */
+};
+
+#ifdef DYNLOOKUP
+#define spf_lookup_module_info _lookup_module_info
+#endif
+
+static lookup_info *_lookup_list[] = { &_lookup_info };
+lookup_module_info spf_lookup_module_info = { LOOKUP_MODULE_INFO_MAGIC, _lookup_list, 1 };
+
#endif /* EXPERIMENTAL_SPF */
--- exim-src.orig/src/lookups/spf.h 2008-05-14 12:29:05.000000000 +0200
+++ /dev/null 1970-01-01 00:00:00.000000000 +0000
@@ -1,26 +0,0 @@
-/* $Cambridge: exim/exim-src/src/lookups/spf.h,v 1.1 2005/05/25 20:07:55 tom Exp $ */
-
-/*************************************************
-* Exim - an Internet mail transport agent *
-*************************************************/
-
-/*
- * Exim - SPF lookup module using libspf2
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * Copyright (c) 2005 Chris Webb, Arachsys Internet Services Ltd
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
-*/
-
-
-
-extern void *spf_open(uschar *, uschar **);
-extern void spf_close(void *);
-extern int spf_find(void *, uschar *, uschar *, int, uschar **, uschar **,
- BOOL *);
-
--- exim-src.orig/src/lookups/sqlite.c 2008-05-14 12:29:05.000000000 +0200
+++ exim-src/src/lookups/sqlite.c 2008-05-14 15:10:09.000000000 +0200
@@ -9,11 +9,7 @@

#include "../exim.h"
#include "lf_functions.h"
-#include "sqlite.h"

-#ifndef LOOKUP_SQLITE
-static void dummy(int x) { dummy(x-1); }
-#else
#include <sqlite3.h>


@@ -23,7 +19,7 @@ static void dummy(int x) { dummy(x-1); }

/* See local README for interface description. */

-void *
+static void *
sqlite_open(uschar *filename, uschar **errmsg)
{
sqlite3 *db = NULL;
@@ -85,7 +81,7 @@ return 0;
}


-int
+static int
sqlite_find(void *handle, uschar *filename, uschar *query, int length,
uschar **result, uschar **errmsg, BOOL *do_cache)
{
@@ -113,7 +109,7 @@ return OK;

/* See local README for interface description. */

-void sqlite_close(void *handle)
+static void sqlite_close(void *handle)
{
sqlite3_close(handle);
}
@@ -134,7 +130,7 @@ Arguments:
Returns: the processed string or NULL for a bad option
*/

-uschar *
+static uschar *
sqlite_quote(uschar *s, uschar *opt)
{
register int c;
@@ -159,6 +155,22 @@ while ((c = *s++) != 0)
return quoted;
}

-#endif /* LOOKUP_SQLITE */
+static lookup_info _lookup_info = {
+ US"sqlite", /* lookup name */
+ lookup_absfilequery, /* query-style lookup, starts with file name */
+ sqlite_open, /* open function */
+ NULL, /* no check function */
+ sqlite_find, /* find function */
+ sqlite_close, /* close function */
+ NULL, /* no tidy function */
+ sqlite_quote /* quoting function */
+};
+
+#ifdef DYNLOOKUP
+#define sqlite_lookup_module_info _lookup_module_info
+#endif
+
+static lookup_info *_lookup_list[] = { &_lookup_info };
+lookup_module_info sqlite_lookup_module_info = { LOOKUP_MODULE_INFO_MAGIC, _lookup_list, 1 };

/* End of lookups/sqlite.c */
--- exim-src.orig/src/lookups/sqlite.h 2008-05-14 12:29:05.000000000 +0200
+++ /dev/null 1970-01-01 00:00:00.000000000 +0000
@@ -1,18 +0,0 @@
-/* $Cambridge: exim/exim-src/src/lookups/sqlite.h,v 1.3 2007/01/08 10:50:19 ph10 Exp $ */
-
-/*************************************************
-* Exim - an Internet mail transport agent *
-*************************************************/
-
-/* Copyright (c) University of Cambridge 1995 - 2007 */
-/* See the file NOTICE for conditions of use and distribution. */
-
-/* Header for the sqlite lookup */
-
-extern void *sqlite_open(uschar *, uschar **);
-extern int sqlite_find(void *, uschar *, uschar *, int, uschar **,
- uschar **, BOOL *);
-extern void sqlite_close(void *);
-extern uschar *sqlite_quote(uschar *, uschar *);
-
-/* End of lookups/sqlite.h */
--- exim-src.orig/src/lookups/testdb.c 2008-05-14 12:29:05.000000000 +0200
+++ exim-src/src/lookups/testdb.c 2008-05-14 15:10:09.000000000 +0200
@@ -9,8 +9,6 @@

#include "../exim.h"
#include "lf_functions.h"
-#include "testdb.h"
-

/* These are not real lookup functions; they are just a way of testing the
rest of Exim by providing an easy way of specifying particular yields from
@@ -23,7 +21,7 @@ the find function. */

/* See local README for interface description. */

-void *
+static void *
testdb_open(uschar *filename, uschar **errmsg)
{
filename = filename; /* Keep picky compilers happy */
@@ -39,7 +37,7 @@ return (void *)(1); /* Just return so

/* See local README for interface description. */

-int
+static int
testdb_find(void *handle, uschar *filename, uschar *query, int length,
uschar **result, uschar **errmsg, BOOL *do_cache)
{
@@ -66,4 +64,22 @@ if (Ustrcmp(query, "nocache") == 0) *do_
return OK;
}

+static lookup_info _lookup_info = {
+ US"testdb", /* lookup name */
+ lookup_querystyle, /* query-style lookup */
+ testdb_open, /* open function */
+ NULL, /* check function */
+ testdb_find, /* find function */
+ NULL, /* no close function */
+ NULL, /* no tidy function */
+ NULL /* no quoting function */
+};
+
+#ifdef DYNLOOKUP
+#define testdb_lookup_module_info _lookup_module_info
+#endif
+
+static lookup_info *_lookup_list[] = { &_lookup_info };
+lookup_module_info testdb_lookup_module_info = { LOOKUP_MODULE_INFO_MAGIC, _lookup_list, 1 };
+
/* End of lookups/testdb.c */
--- exim-src.orig/src/lookups/testdb.h 2008-05-14 12:29:05.000000000 +0200
+++ /dev/null 1970-01-01 00:00:00.000000000 +0000
@@ -1,16 +0,0 @@
-/* $Cambridge: exim/exim-src/src/lookups/testdb.h,v 1.4 2007/01/08 10:50:19 ph10 Exp $ */
-
-/*************************************************
-* Exim - an Internet mail transport agent *
-*************************************************/
-
-/* Copyright (c) University of Cambridge 1995 - 2007 */
-/* See the file NOTICE for conditions of use and distribution. */
-
-/* Header for the testdb lookup */
-
-extern void *testdb_open(uschar *, uschar **);
-extern int testdb_find(void *, uschar *, uschar *, int, uschar **, uschar **,
- BOOL *);
-
-/* End of lookups/testdb.h */
--- exim-src.orig/src/lookups/whoson.c 2008-05-14 12:29:05.000000000 +0200
+++ exim-src/src/lookups/whoson.c 2008-05-14 15:10:09.000000000 +0200
@@ -12,23 +12,7 @@
#include "../exim.h"


-/* We can't just compile this code and allow the library mechanism to omit the
-functions if they are not wanted, because we need to have the WHOSON headers
-available for compiling. Therefore, compile these functions only if
-LOOKUP_WHOSON is defined. However, some compilers don't like compiling empty
-modules, so keep them happy with a dummy when skipping the rest. Make it
-reference itself to stop picky compilers complaining that it is unused, and put
-in a dummy argument to stop even pickier compilers complaining about infinite
-loops. */
-
-#ifndef LOOKUP_WHOSON
-static void dummy(int x) { dummy(x-1); }
-#else
-
-
#include <whoson.h> /* Public header */
-#include "whoson.h" /* Local header */
-

/*************************************************
* Open entry point *
@@ -36,7 +20,7 @@ static void dummy(int x) { dummy(x-1); }

/* See local README for interface description. */

-void *
+static void *
whoson_open(uschar *filename, uschar **errmsg)
{
filename = filename; /* Keep picky compilers happy */
@@ -51,7 +35,7 @@ return (void *)(1); /* Just return so

/* See local README for interface description. */

-int
+static int
whoson_find(void *handle, uschar *filename, uschar *query, int length,
uschar **result, uschar **errmsg, BOOL *do_cache)
{
@@ -77,6 +61,22 @@ switch (wso_query(query, CS buffer, size
}
}

-#endif /* LOOKUP_WHOSON */
+static lookup_info _lookup_info = {
+ US"whoson", /* lookup name */
+ lookup_querystyle, /* query-style lookup */
+ whoson_open, /* open function */
+ NULL, /* check function */
+ whoson_find, /* find function */
+ NULL, /* no close function */
+ NULL, /* no tidy function */
+ NULL /* no quoting function */
+};
+
+#ifdef DYNLOOKUP
+#define whoson_lookup_module_info _lookup_module_info
+#endif
+
+static lookup_info *_lookup_list[] = { &_lookup_info };
+lookup_module_info whoson_lookup_module_info = { LOOKUP_MODULE_INFO_MAGIC, _lookup_list, 1 };

/* End of lookups/whoson.c */
--- exim-src.orig/src/lookups/whoson.h 2008-05-14 12:29:05.000000000 +0200
+++ /dev/null 1970-01-01 00:00:00.000000000 +0000
@@ -1,16 +0,0 @@
-/* $Cambridge: exim/exim-src/src/lookups/whoson.h,v 1.4 2007/01/08 10:50:19 ph10 Exp $ */
-
-/*************************************************
-* Exim - an Internet mail transport agent *
-*************************************************/
-
-/* Copyright (c) University of Cambridge 1995 - 2007 */
-/* See the file NOTICE for conditions of use and distribution. */
-
-/* Header for the whoson lookup */
-
-extern void *whoson_open(uschar *, uschar **);
-extern int whoson_find(void *, uschar *, uschar *, int, uschar **, uschar **,
- BOOL *);
-
-/* End of lookups/whoson.h */
--- exim-src.orig/src/macros.h 2008-05-14 12:29:05.000000000 +0200
+++ exim-src/src/macros.h 2008-05-14 15:10:09.000000000 +0200
@@ -96,7 +96,7 @@ don't make the file descriptors two-way.

/* A macro to simplify testing bits in lookup types */

-#define mac_islookup(a,b) ((lookup_list[a].type & (b)) != 0)
+#define mac_islookup(a,b) ((lookup_list[a]->type & (b)) != 0)

/* Debugging control */

--- exim-src.orig/src/search.c 2008-05-14 12:29:05.000000000 +0200
+++ exim-src/src/search.c 2008-05-14 15:10:09.000000000 +0200
@@ -71,7 +71,7 @@ int top = lookup_list_count;
while (top > bot)
{
int mid = (top + bot)/2;
- int c = Ustrncmp(name, lookup_list[mid].name, len);
+ int c = Ustrncmp(name, lookup_list[mid]->name, len);

/* If c == 0 we have matched the incoming name with the start of the search
type name. However, some search types are substrings of others (e.g. nis and
@@ -81,9 +81,9 @@ while (top > bot)
are testing. By leaving c == 0 when the lengths are different, and doing a
> 0 test below, this all falls out correctly. */

- if (c == 0 && Ustrlen(lookup_list[mid].name) == len)
+ if (c == 0 && Ustrlen(lookup_list[mid]->name) == len)
{
- if (lookup_list[mid].find != NULL) return mid;
+ if (lookup_list[mid]->find != NULL) return mid;
search_error_message = string_sprintf("lookup type \"%.*s\" is not "
"available (not in the binary - check buildtime LOOKUP configuration)",
len, name);
@@ -237,8 +237,8 @@ if (t->left != NULL) tidyup_subtree(t->l
if (t->right != NULL) tidyup_subtree(t->right);
if (c != NULL &&
c->handle != NULL &&
- lookup_list[c->search_type].close != NULL)
- lookup_list[c->search_type].close(c->handle);
+ lookup_list[c->search_type]->close != NULL)
+ lookup_list[c->search_type]->close(c->handle);
}


@@ -270,7 +270,7 @@ open_filecount = 0;
/* Call the general tidyup entry for any drivers that have one. */

for (i = 0; i < lookup_list_count; i++)
- if (lookup_list[i].tidy != NULL) (lookup_list[i].tidy)();
+ if (lookup_list[i]->tidy != NULL) (lookup_list[i]->tidy)();

if (search_reset_point != NULL) store_reset(search_reset_point);
search_reset_point = NULL;
@@ -335,7 +335,7 @@ search_open(uschar *filename, int search
void *handle;
tree_node *t;
search_cache *c;
-lookup_info *lk = lookup_list + search_type;
+lookup_info *lk = lookup_list[search_type];
uschar keybuffer[256];
int old_pool = store_pool;

@@ -388,7 +388,7 @@ if (lk->type == lookup_absfile && open_f
((search_cache *)(open_bot->data.ptr))->down = NULL;
else
open_top = NULL;
- ((lookup_list + c->search_type)->close)(c->handle);
+ ((lookup_list[c->search_type])->close)(c->handle);
c->handle = NULL;
open_filecount--;
}
@@ -480,7 +480,7 @@ search_find_defer = FALSE;

DEBUG(D_lookup) debug_printf("internal_search_find: file=\"%s\"\n "
"type=%s key=\"%s\"\n", filename,
- lookup_list[search_type].name, keystring);
+ lookup_list[search_type]->name, keystring);

/* Insurance. If the keystring is empty, just fail. */

@@ -511,7 +511,7 @@ if ((t = tree_search(c->item_cache, keys
like FAIL, except that search_find_defer is set so the caller can
distinguish if necessary. */

- if (lookup_list[search_type].find(c->handle, filename, keystring, keylength,
+ if (lookup_list[search_type]->find(c->handle, filename, keystring, keylength,
&data, &search_error_message, &do_cache) == DEFER)
{
search_find_defer = TRUE;
@@ -622,7 +622,7 @@ DEBUG(D_lookup)
that opens real files. */

if (open_top != (tree_node *)handle &&
- lookup_list[t->name[0]-'0'].type == lookup_absfile)
+ lookup_list[t->name[0]-'0']->type == lookup_absfile)
{
search_cache *c = (search_cache *)(t->data.ptr);
tree_node *up = c->up;
--- exim-src.orig/src/structs.h 2008-05-14 12:29:05.000000000 +0200
+++ exim-src/src/structs.h 2008-05-14 15:10:09.000000000 +0200
@@ -322,34 +322,7 @@ typedef struct router_info {

/* Structure for holding information about a lookup type. */

-typedef struct lookup_info {
- uschar *name; /* e.g. "lsearch" */
- int type; /* query/singlekey/abs-file */
- void *(*open)( /* open function */
- uschar *, /* file name for those that have one */
- uschar **); /* for error message */
- BOOL (*check)( /* file checking function */
- void *, /* handle */
- uschar *, /* file name */
- int, /* modemask for file checking */
- uid_t *, /* owners for file checking */
- gid_t *, /* owngroups for file checking */
- uschar **); /* for error messages */
- int (*find)( /* find function */
- void *, /* handle */
- uschar *, /* file name or NULL */
- uschar *, /* key or query */
- int, /* length of key or query */
- uschar **, /* for returning answer */
- uschar **, /* for error message */
- BOOL *); /* to request cache cleanup */
- void (*close)( /* close function */
- void *); /* handle */
- void (*tidy)(void); /* tidy function */
- uschar *(*quote)( /* quoting function */
- uschar *, /* string to quote */
- uschar *); /* additional data from quote name */
-} lookup_info;
+#include "lookupapi.h"


/* Structure for holding information about the configured authentication
--- exim-src.orig/src/verify.c 2008-05-14 12:29:05.000000000 +0200
+++ exim-src/src/verify.c 2008-05-14 15:10:09.000000000 +0200
@@ -2219,7 +2219,7 @@ if (iplookup)
}
else /* Single-key style */
{
- int sep = (Ustrcmp(lookup_list[search_type].name, "iplsearch") == 0)?
+ int sep = (Ustrcmp(lookup_list[search_type]->name, "iplsearch") == 0)?
':' : '.';
insize = host_aton(cb->host_address, incoming);
host_mask(insize, incoming, mlen);



--
## List details at http://lists.exim.org/mailman/listinfo/exim-dev Exim details at http://www.exim.org/ ##
Re: [PATCH] dynamically loadable lookup modules [ In reply to ]
On Wed, 14 May 2008, Johannes Berg wrote:

> This patch, originally written by Tim Jackson, adopted/fixed by me
> and recently forward-ported/updated by David Woodhouse, makes exim
> able to (optionally) dynamically load lookup modules rather than
> requiring them to all be built in.

Please could you keep discussion of this topic in bug #139.

Tony.
--
f.anthony.n.finch <dot@dotat.at> http://dotat.at/
BISCAY: VARIABLE BECOMING CYCLONIC 3 OR 4. SLIGHT OR MODERATE. THUNDERY
SHOWERS, WITH FOG PATCHES. MODERATE OR GOOD, OCCASIONALLY VERY POOR.

--
## List details at http://lists.exim.org/mailman/listinfo/exim-dev Exim details at http://www.exim.org/ ##
Re: [PATCH] dynamically loadable lookup modules [ In reply to ]
On Thu, 2008-05-15 at 12:21 +0100, Tony Finch wrote:
> On Wed, 14 May 2008, Johannes Berg wrote:
>
> > This patch, originally written by Tim Jackson, adopted/fixed by me
> > and recently forward-ported/updated by David Woodhouse, makes exim
> > able to (optionally) dynamically load lookup modules rather than
> > requiring them to all be built in.
>
> Please could you keep discussion of this topic in bug #139.

Believe me, I wanted to, but others flogged me for it. I don't care
either way, but it seems that even exim committers don't have a unified
position on how to discuss patches, so... Let's just drop this thread
then and use bugzilla and ignore those who think discussing patches on a
mailing list is the way to go.

Just make it clear, please.

johannes
Re: [PATCH] dynamically loadable lookup modules [ In reply to ]
On Thu, 2008-05-15 at 13:24 +0200, Johannes Berg wrote:
> Just make it clear, please.

My 2p, fwiw:

Commits, comments and such into Bugzilla are gated into the -dev list.
If something more general needs discussing which falls out of a given
Bugzilla ticket, by all means discuss it on the list alone.

IMO if something is specifically relevant to a Bugzilla ticket, put the
info in the ticket and we'll all see it when the update arrives.

Graeme


--
## List details at http://lists.exim.org/mailman/listinfo/exim-dev Exim details at http://www.exim.org/ ##