[exim-cvs] Add dynamic lookup support

トップ ページ
このメッセージを削除
このメッセージに返信
著者: Exim Git Commits Mailing List
日付:  
To: exim-cvs
題目: [exim-cvs] Add dynamic lookup support
Gitweb: http://git.exim.org/exim.git/commitdiff/e6d225ae6e6811d3c88dc201642a2127ff6c11bd
Commit:     e6d225ae6e6811d3c88dc201642a2127ff6c11bd
Parent:     d3cdb3e0489effeb3134c0a7b9da24aee532b1ba
Author:     David Woodhouse <David.Woodhouse@???>
AuthorDate: Wed Jan 5 22:55:50 2011 +0000
Committer:  David Woodhouse <David.Woodhouse@???>
CommitDate: Wed Jan 5 23:06:09 2011 +0000


    Add dynamic lookup support


    Fixed: bug #139
---
 src/Makefile                   |    2 +-
 src/OS/Makefile-Base           |    1 +
 src/scripts/Configure-Makefile |    2 +-
 src/scripts/MakeLinks          |   17 +-
 src/src/EDITME                 |   16 +
 src/src/config.h.defaults      |    2 +
 src/src/drtables.c             |  747 ++++++++++++----------------------------
 src/src/exim.c                 |   38 ++-
 src/src/expand.c               |    4 +-
 src/src/globals.c              |   15 -
 src/src/globals.h              |    2 +-
 src/src/lookupapi.h            |   58 +++
 src/src/lookups/Makefile       |  229 +++++++++++--
 src/src/lookups/cdb.c          |   29 ++-
 src/src/lookups/cdb.h          |   59 ----
 src/src/lookups/dbmdb.c        |   40 ++-
 src/src/lookups/dbmdb.h        |   21 --
 src/src/lookups/dnsdb.c        |   23 +-
 src/src/lookups/dnsdb.h        |   16 -
 src/src/lookups/dsearch.c      |   27 ++-
 src/src/lookups/dsearch.h      |   18 -
 src/src/lookups/ibase.c        |   31 +-
 src/src/lookups/ibase.h        |   18 -
 src/src/lookups/ldap.c         |   66 +++--
 src/src/lookups/ldap.h         |   11 +-
 src/src/lookups/lsearch.c      |   69 ++++-
 src/src/lookups/lsearch.h      |   25 --
 src/src/lookups/mysql.c        |   45 ++--
 src/src/lookups/mysql.h        |   18 -
 src/src/lookups/nis.c          |   48 ++-
 src/src/lookups/nis.h          |   18 -
 src/src/lookups/nisplus.c      |   39 +-
 src/src/lookups/nisplus.h      |   17 -
 src/src/lookups/oracle.c       |   41 ++-
 src/src/lookups/oracle.h       |   18 -
 src/src/lookups/passwd.c       |   23 +-
 src/src/lookups/passwd.h       |   16 -
 src/src/lookups/pgsql.c        |   41 ++-
 src/src/lookups/pgsql.h        |   18 -
 src/src/lookups/spf.c          |   25 ++-
 src/src/lookups/spf.h          |   26 --
 src/src/lookups/sqlite.c       |   30 ++-
 src/src/lookups/sqlite.h       |   18 -
 src/src/lookups/testdb.c       |   23 +-
 src/src/lookups/testdb.h       |   16 -
 src/src/lookups/whoson.c       |   37 +-
 src/src/lookups/whoson.h       |   16 -
 src/src/macros.h               |    2 +-
 src/src/search.c               |   22 +-
 src/src/structs.h              |   29 +--
 src/src/verify.c               |    2 +-
 51 files changed, 992 insertions(+), 1182 deletions(-)


diff --git a/src/Makefile b/src/Makefile
index 0a48ff9..eb9df50 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -81,7 +81,7 @@ clean:; @echo ""; echo '*** "make clean" just removes all .o and .a files'

 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-*

diff --git a/src/OS/Makefile-Base b/src/OS/Makefile-Base
index 451fcd2..5793869 100644
--- a/src/OS/Makefile-Base
+++ b/src/OS/Makefile-Base
@@ -313,6 +313,7 @@ OBJ_EXIM = acl.o child.o crypt16.o daemon.o dbfn.o debug.o deliver.o \
         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)


diff --git a/src/scripts/Configure-Makefile b/src/scripts/Configure-Makefile
index 35bb2c3..1b2ea1e 100755
--- a/src/scripts/Configure-Makefile
+++ b/src/scripts/Configure-Makefile
@@ -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,
diff --git a/src/scripts/MakeLinks b/src/scripts/MakeLinks
index bb6dd49..5918139 100755
--- a/src/scripts/MakeLinks
+++ b/src/scripts/MakeLinks
@@ -32,39 +32,23 @@ mkdir lookups
 cd lookups
 ln -s ../../src/lookups/README           README
 ln -s ../../src/lookups/Makefile         Makefile
-ln -s ../../src/lookups/cdb.h            cdb.h
 ln -s ../../src/lookups/cdb.c            cdb.c
-ln -s ../../src/lookups/dbmdb.h          dbmdb.h
 ln -s ../../src/lookups/dbmdb.c          dbmdb.c
-ln -s ../../src/lookups/dnsdb.h          dnsdb.h
 ln -s ../../src/lookups/dnsdb.c          dnsdb.c
-ln -s ../../src/lookups/dsearch.h        dsearch.h
 ln -s ../../src/lookups/dsearch.c        dsearch.c
-ln -s ../../src/lookups/ibase.h          ibase.h
 ln -s ../../src/lookups/ibase.c          ibase.c
 ln -s ../../src/lookups/ldap.h           ldap.h
 ln -s ../../src/lookups/ldap.c           ldap.c
-ln -s ../../src/lookups/lsearch.h        lsearch.h
 ln -s ../../src/lookups/lsearch.c        lsearch.c
-ln -s ../../src/lookups/mysql.h          mysql.h
 ln -s ../../src/lookups/mysql.c          mysql.c
-ln -s ../../src/lookups/nis.h            nis.h
 ln -s ../../src/lookups/nis.c            nis.c
-ln -s ../../src/lookups/nisplus.h        nisplus.h
 ln -s ../../src/lookups/nisplus.c        nisplus.c
-ln -s ../../src/lookups/oracle.h         oracle.h
 ln -s ../../src/lookups/oracle.c         oracle.c
-ln -s ../../src/lookups/passwd.h         passwd.h
 ln -s ../../src/lookups/passwd.c         passwd.c
-ln -s ../../src/lookups/pgsql.h          pgsql.h
 ln -s ../../src/lookups/pgsql.c          pgsql.c
-ln -s ../../src/lookups/spf.h            spf.h
 ln -s ../../src/lookups/spf.c            spf.c
-ln -s ../../src/lookups/sqlite.h         sqlite.h
 ln -s ../../src/lookups/sqlite.c         sqlite.c
-ln -s ../../src/lookups/testdb.h         testdb.h
 ln -s ../../src/lookups/testdb.c         testdb.c
-ln -s ../../src/lookups/whoson.h         whoson.h
 ln -s ../../src/lookups/whoson.c         whoson.c


 ln -s ../../src/lookups/lf_functions.h   lf_functions.h
@@ -197,6 +181,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
diff --git a/src/src/EDITME b/src/src/EDITME
index 3c162c9..be15e4e 100644
--- a/src/src/EDITME
+++ b/src/src/EDITME
@@ -249,6 +249,10 @@ TRANSPORT_SMTP=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
# in the binary. See the manual chapter entitled "File and database lookups"
# for discussion. DBM and lsearch (linear search) are included by default. If
@@ -256,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
diff --git a/src/src/config.h.defaults b/src/src/config.h.defaults
index 5cff6ad..8d951ae 100644
--- a/src/src/config.h.defaults
+++ b/src/src/config.h.defaults
@@ -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)
diff --git a/src/src/drtables.c b/src/src/drtables.c
index e2d989c..92b4878 100644
--- a/src/src/drtables.c
+++ b/src/src/drtables.c
@@ -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
@@ -17,527 +19,8 @@ various macros in config.h that ultimately come from Local/Makefile. They are
all described in src/EDITME. */


-/* The OSF1 (Digital Unix) linker puts out a worrying warning if any sections
-contain no executable code. It says
-
-Warning: Linking some objects which contain exception information sections
-        and some which do not. This may cause fatal runtime exception handling
-        problems.
-
-As this may cause people to worry needlessly, include a dummy function here
-to stop the message from appearing. Make it call itself to stop picky compilers
-compilers complaining that it is unused, and put in a dummy argument to stop
-even pickier compilers complaining about infinite loops. */
-
-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
-
-/* 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
-  },
-
-/* 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
@@ -865,4 +348,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(US"\\.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_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);
+    log_write(0, LOG_MAIN, "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, "Loading lookup modules: %s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
+          log_write(0, LOG_MAIN|LOG_PANIC, "%s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
+          continue;
+        }
+
+        /* SRH: snprintf here? */
+        sprintf(CS big_buffer, "%s/%s", LOOKUP_MODULE_DIR, name);
+
+        dl = dlopen(CS big_buffer, RTLD_NOW);// TJ was LAZY
+        if (dl == NULL) {
+          fprintf(stderr, "Error loading %s: %s\n", name, dlerror());
+          moduleerrors++;
+          log_write(0, LOG_MAIN|LOG_PANIC, "Error loading lookup module %s: %s\n", name, dlerror());
+          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++;
+          log_write(0, LOG_MAIN|LOG_PANIC, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
+          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++;
+          log_write(0, LOG_MAIN|LOG_PANIC, "Lookup module %s is not compatible with this version of Exim\n", name);
+          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 */
diff --git a/src/src/exim.c b/src/src/exim.c
index dce42f0..bda6190 100644
--- a/src/src/exim.c
+++ b/src/src/exim.c
@@ -776,53 +776,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");
@@ -3510,6 +3510,10 @@ if (opt_perl_at_start && opt_perl_startup != NULL)
}
#endif /* EXIM_PERL */

+/* Initialise lookup_list */
+extern void init_lookup_list(void);
+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
diff --git a/src/src/expand.c b/src/src/expand.c
index 7adf673..702faab 100644
--- a/src/src/expand.c
+++ b/src/src/expand.c
@@ -5506,8 +5506,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)
diff --git a/src/src/globals.c b/src/src/globals.c
index 71de52a..6653d62 100644
--- a/src/src/globals.c
+++ b/src/src/globals.c
@@ -13,21 +13,6 @@ that they are easy to find. */
 #include "exim.h"



-/* The OSF1 linker puts out a worrying warning if any sections contain no
-executable code. It says
-
-Warning: Linking some objects which contain exception information sections
-        and some which do not. This may cause fatal runtime exception handling
-        problems.
-
-As this may cause people to worry needlessly, include a dummy function here
-to stop the message from appearing. 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. */
-
-static void dummy(int x) { dummy(x-1); }
-
-
 /* Generic options for auths, all of which live inside auth_instance
 data blocks and hence have the opt_public flag set. */


diff --git a/src/src/globals.h b/src/src/globals.h
index b4e3f2a..db7a79b 100644
--- a/src/src/globals.h
+++ b/src/src/globals.h
@@ -441,7 +441,7 @@ extern BOOL    log_testing_mode;       /* TRUE in various testing modes */
 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 */
diff --git a/src/src/lookupapi.h b/src/src/lookupapi.h
new file mode 100644
index 0000000..97f92ab
--- /dev/null
+++ b/src/src/lookupapi.h
@@ -0,0 +1,58 @@
+/* $Cambridge$ */
+
+/*************************************************
+*     Exim - an Internet mail transport agent    *
+*************************************************/
+
+/* Copyright (c) University of Cambridge 1995 - 2009 */
+/* See the file NOTICE for conditions of use and distribution. */
+
+
+/* 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;
+
+/* This magic number is used by the following lookup_module_info structure
+   for checking API compatibility. It's equivalent to the string"LMM1" */
+#define LOOKUP_MODULE_INFO_MAGIC 0x4c4d4d31
+
+typedef struct lookup_module_info {
+  uint magic;
+  lookup_info **lookups;
+  uint lookupcount;
+} lookup_module_info;
+
+/* End of lookupapi.h */
diff --git a/src/src/lookups/Makefile b/src/src/lookups/Makefile
index 2c7cb87..76e56da 100644
--- a/src/src/lookups/Makefile
+++ b/src/src/lookups/Makefile
@@ -1,13 +1,171 @@
 # $Cambridge: exim/src/src/lookups/Makefile,v 1.9 2009/06/10 07:34:05 tom 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.
+# Make file for building all the available lookups.
+# This is called from the main make file, after cd'ing
+# to the lookups subdirectory.

-OBJ = cdb.o dbmdb.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
+# 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_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,30 +173,51 @@ 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
-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
+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
+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
diff --git a/src/src/lookups/cdb.c b/src/src/lookups/cdb.c
index 68000c6..6e8b887 100644
--- a/src/src/lookups/cdb.c
+++ b/src/src/lookups/cdb.c
@@ -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 */
diff --git a/src/src/lookups/cdb.h b/src/src/lookups/cdb.h
deleted file mode 100644
index 084cafc..0000000
--- a/src/src/lookups/cdb.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/* $Cambridge: 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 */
diff --git a/src/src/lookups/dbmdb.c b/src/src/lookups/dbmdb.c
index 200a204..29a4a3a 100644
--- a/src/src/lookups/dbmdb.c
+++ b/src/src/lookups/dbmdb.c
@@ -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, we know it is tdb or gdbm, which do
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)
{
@@ -122,7 +121,7 @@ return FAIL;
/* See local README for interface description */

int
-dbmnz_find(void *handle, uschar *filename, uschar *keystring, int length,
+static dbmnz_find(void *handle, uschar *filename, uschar *keystring, int length,
uschar **result, uschar **errmsg, BOOL *do_cache)
{
return dbmdb_find(handle, filename, keystring, length-1, result, errmsg,
@@ -138,9 +137,38 @@ return dbmdb_find(handle, filename, keystring, length-1, result, errmsg,
/* See local README for interface description */

void
-dbmdb_close(void *handle)
+static 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 */
diff --git a/src/src/lookups/dbmdb.h b/src/src/lookups/dbmdb.h
deleted file mode 100644
index d791383..0000000
--- a/src/src/lookups/dbmdb.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* $Cambridge: exim/src/src/lookups/dbmdb.h,v 1.5 2009/11/16 19:50:38 nm4 Exp $ */
-
-/*************************************************
-*     Exim - an Internet mail transport agent    *
-*************************************************/
-
-/* Copyright (c) University of Cambridge 1995 - 2009 */
-/* 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 */
diff --git a/src/src/lookups/dnsdb.c b/src/src/lookups/dnsdb.c
index 89ad67d..5c9f96b 100644
--- a/src/src/lookups/dnsdb.c
+++ b/src/src/lookups/dnsdb.c
@@ -9,7 +9,6 @@


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



@@ -67,7 +66,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 */
@@ -108,7 +107,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)
{
@@ -430,4 +429,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 */
diff --git a/src/src/lookups/dnsdb.h b/src/src/lookups/dnsdb.h
deleted file mode 100644
index c0e3a55..0000000
--- a/src/src/lookups/dnsdb.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/* $Cambridge: exim/src/src/lookups/dnsdb.h,v 1.5 2009/11/16 19:50:38 nm4 Exp $ */
-
-/*************************************************
-*     Exim - an Internet mail transport agent    *
-*************************************************/
-
-/* Copyright (c) University of Cambridge 1995 - 2009 */
-/* 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 */
diff --git a/src/src/lookups/dsearch.c b/src/src/lookups/dsearch.c
index ab468ca..575872c 100644
--- a/src/src/lookups/dsearch.c
+++ b/src/src/lookups/dsearch.c
@@ -14,7 +14,6 @@ lstat()) rather than a directory scan). */


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



@@ -27,7 +26,7 @@ whether it exists and whether it is searchable. However, we don't need to keep
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);
@@ -51,7 +50,7 @@ return (void *)(-1);
integer as this gives warnings on 64-bit systems. */

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

int
-dsearch_find(void *handle, uschar *dirname, uschar *keystring, int length,
+static dsearch_find(void *handle, uschar *dirname, uschar *keystring, int length,
uschar **result, uschar **errmsg, BOOL *do_cache)
{
struct stat statbuf;
@@ -115,9 +114,27 @@ return DEFER;
/* See local README for interface description */

void
-dsearch_close(void *handle)
+static 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 */
diff --git a/src/src/lookups/dsearch.h b/src/src/lookups/dsearch.h
deleted file mode 100644
index 771e736..0000000
--- a/src/src/lookups/dsearch.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* $Cambridge: exim/src/src/lookups/dsearch.h,v 1.5 2009/11/16 19:50:38 nm4 Exp $ */
-
-/*************************************************
-*     Exim - an Internet mail transport agent    *
-*************************************************/
-
-/* Copyright (c) University of Cambridge 1995 - 2009 */
-/* 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 */
diff --git a/src/src/lookups/ibase.c b/src/src/lookups/ibase.c
index 4ab153d..553d368 100644
--- a/src/src/lookups/ibase.c
+++ b/src/src/lookups/ibase.c
@@ -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_connections = NULL;

/* 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, uschar ** errmsg)


/* 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 terminating zero. */
 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 * opt)
     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 */
diff --git a/src/src/lookups/ibase.h b/src/src/lookups/ibase.h
deleted file mode 100644
index 640772a..0000000
--- a/src/src/lookups/ibase.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* $Cambridge: exim/src/src/lookups/ibase.h,v 1.5 2009/11/16 19:50:38 nm4 Exp $ */
-
-/*************************************************
-*     Exim - an Internet mail transport agent    *
-*************************************************/
-
-/* Copyright (c) University of Cambridge 1995 - 2009 */
-/* 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 */
diff --git a/src/src/lookups/ldap.c b/src/src/lookups/ldap.c
index 936fe36..461ec15 100644
--- a/src/src/lookups/ldap.c
+++ b/src/src/lookups/ldap.c
@@ -15,20 +15,6 @@ researching how to handle the different kinds of error. */


#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
@@ -1196,7 +1182,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 +1191,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 +1200,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 +1226,7 @@ return(control_ldap_search(ldap_url, SEARCH_LDAP_AUTH, result, errmsg));

/* 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 +1241,7 @@ return (void *)(1);    /* Just return something non-null */
 /* 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 +1337,7 @@ quote_ldap_dn, respectively. */



-uschar *
+static uschar *
eldap_quote(uschar *s, uschar *opt)
{
register int c;
@@ -1470,6 +1456,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 */
diff --git a/src/src/lookups/ldap.h b/src/src/lookups/ldap.h
index b0f0ae5..21069e0 100644
--- a/src/src/lookups/ldap.h
+++ b/src/src/lookups/ldap.h
@@ -7,18 +7,9 @@
/* Copyright (c) University of Cambridge 1995 - 2009 */
/* 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 */
diff --git a/src/src/lookups/lsearch.c b/src/src/lookups/lsearch.c
index ccb4850..5d64638 100644
--- a/src/src/lookups/lsearch.c
+++ b/src/src/lookups/lsearch.c
@@ -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)
{
@@ -324,7 +323,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)
{
@@ -341,7 +340,7 @@ return internal_lsearch_find(handle, filename, keystring, length, result,

/* 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)
{
@@ -358,7 +357,7 @@ return internal_lsearch_find(handle, filename, keystring, length, result,

/* 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)
{
@@ -376,7 +375,7 @@ return internal_lsearch_find(handle, filename, keystring, length, result,

/* 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)
{
@@ -405,10 +404,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 */
diff --git a/src/src/lookups/lsearch.h b/src/src/lookups/lsearch.h
deleted file mode 100644
index 332b01c..0000000
--- a/src/src/lookups/lsearch.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* $Cambridge: exim/src/src/lookups/lsearch.h,v 1.5 2009/11/16 19:50:38 nm4 Exp $ */
-
-/*************************************************
-*     Exim - an Internet mail transport agent    *
-*************************************************/
-
-/* Copyright (c) University of Cambridge 1995 - 2009 */
-/* 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 */
diff --git a/src/src/lookups/mysql.c b/src/src/lookups/mysql.c
index f2e9a15..97b9c11 100644
--- a/src/src/lookups/mysql.c
+++ b/src/src/lookups/mysql.c
@@ -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_connections = NULL;

/* 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 something non-null */


/* See local README for interface description. */

-void
+static void
mysql_tidy(void)
{
mysql_connection *cn;
@@ -357,7 +341,7 @@ arguments are not used. The code to loop through a list of servers while the
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)
 {
@@ -387,7 +371,7 @@ Arguments:
 Returns:     the processed string or NULL for a bad option
 */


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

-
-#endif  /* MYSQL_LOOKUP */
+/* 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
+
+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 */
diff --git a/src/src/lookups/mysql.h b/src/src/lookups/mysql.h
deleted file mode 100644
index df7b555..0000000
--- a/src/src/lookups/mysql.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* $Cambridge: exim/src/src/lookups/mysql.h,v 1.5 2009/11/16 19:50:38 nm4 Exp $ */
-
-/*************************************************
-*     Exim - an Internet mail transport agent    *
-*************************************************/
-
-/* Copyright (c) University of Cambridge 1995 - 2009 */
-/* 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 */
diff --git a/src/src/lookups/nis.c b/src/src/lookups/nis.c
index ad04e0a..8177f4b 100644
--- a/src/src/lookups/nis.c
+++ b/src/src/lookups/nis.c
@@ -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_MAP)? FAIL : DEFER;

/* 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 filename, CS keystring, length + 1,
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 */
diff --git a/src/src/lookups/nis.h b/src/src/lookups/nis.h
deleted file mode 100644
index cd4ca58..0000000
--- a/src/src/lookups/nis.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* $Cambridge: exim/src/src/lookups/nis.h,v 1.5 2009/11/16 19:50:38 nm4 Exp $ */
-
-/*************************************************
-*     Exim - an Internet mail transport agent    *
-*************************************************/
-
-/* Copyright (c) University of Cambridge 1995 - 2009 */
-/* 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 */
diff --git a/src/src/lookups/nisplus.c b/src/src/lookups/nisplus.c
index 33d4ffe..5213af3 100644
--- a/src/src/lookups/nisplus.c
+++ b/src/src/lookups/nisplus.c
@@ -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 there is no result-field name, the
 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 */
diff --git a/src/src/lookups/nisplus.h b/src/src/lookups/nisplus.h
deleted file mode 100644
index aa25696..0000000
--- a/src/src/lookups/nisplus.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* $Cambridge: exim/src/src/lookups/nisplus.h,v 1.5 2009/11/16 19:50:38 nm4 Exp $ */
-
-/*************************************************
-*     Exim - an Internet mail transport agent    *
-*************************************************/
-
-/* Copyright (c) University of Cambridge 1995 - 2009 */
-/* 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 */
diff --git a/src/src/lookups/oracle.c b/src/src/lookups/oracle.c
index 5997f19..50dfb4a 100644
--- a/src/src/lookups/oracle.c
+++ b/src/src/lookups/oracle.c
@@ -15,27 +15,12 @@ some comments from my position of Oracle ignorance. */
 #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 something non-null */


/* 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 */
diff --git a/src/src/lookups/oracle.h b/src/src/lookups/oracle.h
deleted file mode 100644
index b642796..0000000
--- a/src/src/lookups/oracle.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* $Cambridge: exim/src/src/lookups/oracle.h,v 1.5 2009/11/16 19:50:38 nm4 Exp $ */
-
-/*************************************************
-*     Exim - an Internet mail transport agent    *
-*************************************************/
-
-/* Copyright (c) University of Cambridge 1995 - 2009 */
-/* 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 */
diff --git a/src/src/lookups/passwd.c b/src/src/lookups/passwd.c
index 481be2c..420eefc 100644
--- a/src/src/lookups/passwd.c
+++ b/src/src/lookups/passwd.c
@@ -8,7 +8,6 @@
 /* See the file NOTICE for conditions of use and distribution. */


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



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

/* See local README for interface description */

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


/* 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 +52,22 @@ if (!route_finduser(keystring, &pw, NULL)) return FAIL;
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 */
diff --git a/src/src/lookups/passwd.h b/src/src/lookups/passwd.h
deleted file mode 100644
index 5624a01..0000000
--- a/src/src/lookups/passwd.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/* $Cambridge: exim/src/src/lookups/passwd.h,v 1.5 2009/11/16 19:50:38 nm4 Exp $ */
-
-/*************************************************
-*     Exim - an Internet mail transport agent    *
-*************************************************/
-
-/* Copyright (c) University of Cambridge 1995 - 2009 */
-/* 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 */
diff --git a/src/src/lookups/pgsql.c b/src/src/lookups/pgsql.c
index 287ddcd..5bd9627 100644
--- a/src/src/lookups/pgsql.c
+++ b/src/src/lookups/pgsql.c
@@ -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_connections = NULL;

/* 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 something non-null */


/* 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 through a list of servers while the
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 */
diff --git a/src/src/lookups/pgsql.h b/src/src/lookups/pgsql.h
deleted file mode 100644
index 228e314..0000000
--- a/src/src/lookups/pgsql.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* $Cambridge: exim/src/src/lookups/pgsql.h,v 1.5 2009/11/16 19:50:38 nm4 Exp $ */
-
-/*************************************************
-*     Exim - an Internet mail transport agent    *
-*************************************************/
-
-/* Copyright (c) University of Cambridge 1995 - 2009 */
-/* 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 */
diff --git a/src/src/lookups/spf.c b/src/src/lookups/spf.c
index ee2a2c7..2ca4bba 100644
--- a/src/src/lookups/spf.c
+++ b/src/src/lookups/spf.c
@@ -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,12 +41,12 @@ void *spf_open(uschar *filename, uschar **errmsg) {
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,
+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;
@@ -75,4 +74,22 @@ int spf_find(void *handle, uschar *filename, uschar *keystring, int key_len,
   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 */
diff --git a/src/src/lookups/spf.h b/src/src/lookups/spf.h
deleted file mode 100644
index 6b9056a..0000000
--- a/src/src/lookups/spf.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* $Cambridge: 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 *);
-
diff --git a/src/src/lookups/sqlite.c b/src/src/lookups/sqlite.c
index 654c5c6..5759c43 100644
--- a/src/src/lookups/sqlite.c
+++ b/src/src/lookups/sqlite.c
@@ -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 */
diff --git a/src/src/lookups/sqlite.h b/src/src/lookups/sqlite.h
deleted file mode 100644
index 15df25f..0000000
--- a/src/src/lookups/sqlite.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* $Cambridge: exim/src/src/lookups/sqlite.h,v 1.4 2009/11/16 19:50:38 nm4 Exp $ */
-
-/*************************************************
-*     Exim - an Internet mail transport agent    *
-*************************************************/
-
-/* Copyright (c) University of Cambridge 1995 - 2009 */
-/* 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 */
diff --git a/src/src/lookups/testdb.c b/src/src/lookups/testdb.c
index ec23e13..03404d8 100644
--- a/src/src/lookups/testdb.c
+++ b/src/src/lookups/testdb.c
@@ -9,7 +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
@@ -23,7 +22,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 +38,7 @@ return (void *)(1);    /* Just return something non-null */


/* 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 +65,22 @@ if (Ustrcmp(query, "nocache") == 0) *do_cache = FALSE;
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 */
diff --git a/src/src/lookups/testdb.h b/src/src/lookups/testdb.h
deleted file mode 100644
index 0e9cdde..0000000
--- a/src/src/lookups/testdb.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/* $Cambridge: exim/src/src/lookups/testdb.h,v 1.5 2009/11/16 19:50:38 nm4 Exp $ */
-
-/*************************************************
-*     Exim - an Internet mail transport agent    *
-*************************************************/
-
-/* Copyright (c) University of Cambridge 1995 - 2009 */
-/* 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 */
diff --git a/src/src/lookups/whoson.c b/src/src/lookups/whoson.c
index 3b0960f..d197905 100644
--- a/src/src/lookups/whoson.c
+++ b/src/src/lookups/whoson.c
@@ -12,22 +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 */



/*************************************************
@@ -36,7 +21,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 +36,7 @@ return (void *)(1);    /* Just return something non-null */


/* 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 +62,22 @@ switch (wso_query(query, CS buffer, sizeof(buffer)))
}
}

-#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 */
diff --git a/src/src/lookups/whoson.h b/src/src/lookups/whoson.h
deleted file mode 100644
index 2a3a5c0..0000000
--- a/src/src/lookups/whoson.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/* $Cambridge: exim/src/src/lookups/whoson.h,v 1.5 2009/11/16 19:50:38 nm4 Exp $ */
-
-/*************************************************
-*     Exim - an Internet mail transport agent    *
-*************************************************/
-
-/* Copyright (c) University of Cambridge 1995 - 2009 */
-/* 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 */
diff --git a/src/src/macros.h b/src/src/macros.h
index 09bc601..3f24025 100644
--- a/src/src/macros.h
+++ b/src/src/macros.h
@@ -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 */

diff --git a/src/src/search.c b/src/src/search.c
index 6e52cf2..528dc72 100644
--- a/src/src/search.c
+++ b/src/src/search.c
@@ -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->left);
 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_type, int modemask, uid_t *owners,
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_filecount >= lookup_open_max)
       ((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, keystring)) == NULL)
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;
diff --git a/src/src/structs.h b/src/src/structs.h
index cf967a6..483539f 100644
--- a/src/src/structs.h
+++ b/src/src/structs.h
@@ -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
diff --git a/src/src/verify.c b/src/src/verify.c
index 371883a..1ead302 100644
--- a/src/src/verify.c
+++ b/src/src/verify.c
@@ -2256,7 +2256,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);