[exim-cvs] Version reporting & module ABI change.

Góra strony
Delete this message
Reply to this message
Autor: Exim Git Commits Mailing List
Data:  
Dla: exim-cvs
Temat: [exim-cvs] Version reporting & module ABI change.
Gitweb: http://git.exim.org/exim.git/commitdiff/6545de78cb822ab5db97a2f16fe7a42cc9488bd8
Commit:     6545de78cb822ab5db97a2f16fe7a42cc9488bd8
Parent:     56e0c4ce946ae13628c4349f982c3407e1019dd0
Author:     Phil Pennock <pdp@???>
AuthorDate: Fri Jan 21 03:25:51 2011 -0500
Committer:  Phil Pennock <pdp@???>
CommitDate: Fri Jan 21 03:25:51 2011 -0500


    Version reporting & module ABI change.


    Debug version display reports library info.


    Bumps lookup API magic constant, adds new field to module API.


    When invoking { exim -d -bV } we can display more version information.
    Show versions for many external libraries, including both compile-time
    and run-time information if we can.


    Optional for modules, may be NULL.  Implemented for MySQL, SQLite &
    Whoson lookups.  For all lookups, if dynamically loaded, report the
    Exim version number from the build.  (Packagers will bundle stuff, but
    dynamic modules are no longer just available for packagers, so we need
    to deal with less managed environments and people forgetting to install
    new modules).


    Suggest in EDITME that users of modules not using package management
    consider embedding a version number in the path to the modules.


    Should consider removing the TLS (OpenSSL/GnuTLS) reporting from the
    default -bV display and moving it into the debug display.  Not done.


    Created version.h, now support a version extension string for
    distributors who patch heavily. Henceforth release engineer should
    change the version in version.h not version.c.
---
 doc/doc-txt/ChangeLog      |    5 +++++
 src/scripts/MakeLinks      |    1 +
 src/src/EDITME             |    4 ++++
 src/src/auths/cyrus_sasl.c |   15 +++++++++++++++
 src/src/drtables.c         |    6 ++++++
 src/src/exim.c             |   39 ++++++++++++++++++++++++++++++++++++---
 src/src/exim.h             |    7 +++++++
 src/src/lookupapi.h        |    7 +++++--
 src/src/lookups/README     |   15 ++++++++++++++-
 src/src/lookups/cdb.c      |   22 +++++++++++++++++++++-
 src/src/lookups/dbmdb.c    |   25 +++++++++++++++++++++++--
 src/src/lookups/dnsdb.c    |   22 +++++++++++++++++++++-
 src/src/lookups/dsearch.c  |   21 ++++++++++++++++++++-
 src/src/lookups/ibase.c    |   21 ++++++++++++++++++++-
 src/src/lookups/ldap.c     |   28 +++++++++++++++++++++++++---
 src/src/lookups/lsearch.c  |   31 +++++++++++++++++++++++++++----
 src/src/lookups/mysql.c    |   24 +++++++++++++++++++++++-
 src/src/lookups/nis.c      |   25 +++++++++++++++++++++++--
 src/src/lookups/nisplus.c  |   21 ++++++++++++++++++++-
 src/src/lookups/oracle.c   |   21 ++++++++++++++++++++-
 src/src/lookups/passwd.c   |   21 ++++++++++++++++++++-
 src/src/lookups/pgsql.c    |   27 ++++++++++++++++++++++++++-
 src/src/lookups/spf.c      |   21 ++++++++++++++++++++-
 src/src/lookups/sqlite.c   |   24 +++++++++++++++++++++++-
 src/src/lookups/testdb.c   |   21 ++++++++++++++++++++-
 src/src/lookups/whoson.c   |   22 +++++++++++++++++++++-
 src/src/version.c          |    5 ++---
 src/src/version.h          |   15 +++++++++++++++
 28 files changed, 483 insertions(+), 33 deletions(-)


diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog
index 0780fc7..ff375d3 100644
--- a/doc/doc-txt/ChangeLog
+++ b/doc/doc-txt/ChangeLog
@@ -27,6 +27,11 @@ PP/02 Let /dev/null have normal permissions.
       permissions on /dev/null.  Exempt it from some checks.
       Reported by Andreas M. Kirchwitz.


+PP/03 Report version information for many libraries, including
+      Exim version information for dynamically loaded libraries.  Created
+      version.h, now support a version extension string for distributors
+      who patch heavily. Dynamic module ABI change.
+


 Exim version 4.73
 -----------------
diff --git a/src/scripts/MakeLinks b/src/scripts/MakeLinks
index c021ace..ac09209 100755
--- a/src/scripts/MakeLinks
+++ b/src/scripts/MakeLinks
@@ -182,6 +182,7 @@ 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/version.h         version.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 74c507d..833c3f8 100644
--- a/src/src/EDITME
+++ b/src/src/EDITME
@@ -251,6 +251,10 @@ TRANSPORT_SMTP=yes
 #------------------------------------------------------------------------------
 # See below for dynamic lookup modules.
 # LOOKUP_MODULE_DIR=/usr/lib/exim/lookups/
+# If not using package management but using this anyway, then think about how
+# you perform upgrades and revert them. You should consider the benefit of
+# embedding the Exim version number into LOOKUP_MODULE_DIR, so that you can
+# maintain two concurrent sets of modules.


# To build a module dynamically, you'll need to define CFLAGS_DYNAMIC for
# your platform. Eg:
diff --git a/src/src/auths/cyrus_sasl.c b/src/src/auths/cyrus_sasl.c
index 2ab028c..7e97acb 100644
--- a/src/src/auths/cyrus_sasl.c
+++ b/src/src/auths/cyrus_sasl.c
@@ -346,6 +346,21 @@ return 0; /* Stop compiler complaints */
}

 /*************************************************
+*                Diagnostic API                  *
+*************************************************/
+
+void
+auth_cyrus_sasl_version_report(FILE *f)
+{
+  const char *implementation, *version;
+  sasl_version_info(&implementation, &version, NULL, NULL, NULL, NULL);
+  fprintf(f, "Library version: Cyrus SASL: Compile: %d.%d.%d\n"
+             "                             Runtime: %s [%s]\n",
+          SASL_VERSION_MAJOR, SASL_VERSION_MINOR, SASL_VERSION_STEP,
+          version, implementation);
+}
+
+/*************************************************
 *              Client entry point                *
 *************************************************/


diff --git a/src/src/drtables.c b/src/src/drtables.c
index e54202f..563670a 100644
--- a/src/src/drtables.c
+++ b/src/src/drtables.c
@@ -21,6 +21,8 @@ all described in src/EDITME. */
lookup_info **lookup_list;
int lookup_list_count = 0;

+static int lookup_list_init_done = 0;
+
/* Table of information about all possible authentication mechamisms. All
entries are always present if any mechanism is declared, but the functions are
set to NULL for those that are not compiled into the binary. */
@@ -398,6 +400,10 @@ void init_lookup_list(void)
int moduleerrors = 0;
struct lookupmodulestr *p;

+  if (lookup_list_init_done)
+    return;
+  lookup_list_init_done = 1;
+
 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
 extern lookup_module_info cdb_lookup_module_info;
   addlookupmodule(NULL, &cdb_lookup_module_info);
diff --git a/src/src/exim.c b/src/src/exim.c
index bda6190..dd3b5f9 100644
--- a/src/src/exim.c
+++ b/src/src/exim.c
@@ -14,6 +14,8 @@ Also a few functions that don't naturally fit elsewhere. */


#include "exim.h"

+extern void init_lookup_list(void);
+


 /*************************************************
@@ -914,6 +916,33 @@ come. */
 #ifdef SUPPORT_TLS
 tls_version_report(f);
 #endif
+
+/* Everything else is details which are only worth reporting when debugging.
+Perhaps the tls_version_report should move into this too. */
+DEBUG(D_any) do {
+
+  int i;
+
+#ifdef AUTH_CYRUS_SASL
+  auth_cyrus_sasl_version_report(f);
+#endif
+
+  fprintf(f, "Library version: PCRE: Compile: %d.%d%s\n"
+             "                       Runtime: %s\n",
+          PCRE_MAJOR, PCRE_MINOR,
+          /* PRE_PRERELEASE is either defined and empty or a string.
+           * This should work: */
+          PCRE_PRERELEASE "",
+          pcre_version());
+
+  init_lookup_list();
+  for (i = 0; i < lookup_list_count; i++)
+    {
+    if (lookup_list[i]->version_report)
+      lookup_list[i]->version_report(f);
+    }
+
+} while (0);
 }



@@ -3143,7 +3172,8 @@ if (debug_selector != 0)
     debug_printf("Exim version %s uid=%ld gid=%ld pid=%d D=%x\n",
       version_string, (long int)real_uid, (long int)real_gid, (int)getpid(),
       debug_selector);
-    show_whats_supported(stderr);
+    if (!version_printed)
+      show_whats_supported(stderr);
     }
   }


@@ -3510,8 +3540,11 @@ if (opt_perl_at_start && opt_perl_startup != NULL)
}
#endif /* EXIM_PERL */

-/* Initialise lookup_list */
-extern void init_lookup_list(void);
+/* Initialise lookup_list
+If debugging, already called above via version reporting.
+This does mean that debugging causes the list to be initialised while root.
+This *should* be harmless -- all modules are loaded from a fixed dir and
+it's code that would, if not a module, be part of Exim already. */
init_lookup_list();

/* Log the arguments of the call if the configuration file said so. This is
diff --git a/src/src/exim.h b/src/src/exim.h
index b9b2ab0..be7c55e 100644
--- a/src/src/exim.h
+++ b/src/src/exim.h
@@ -533,5 +533,12 @@ default to EDQUOT if it exists, otherwise ENOSPC. */
#endif
#endif

+/* These are for reporting version information from various componenents, to
+figure out what's actually happening. They need to be available to the main
+function, so we declare them here. Unfortunate. */
+
+#ifdef AUTH_CYRUS_SASL
+extern void auth_cyrus_sasl_version_report(FILE *);
+#endif

 /* End of exim.h */
diff --git a/src/src/lookupapi.h b/src/src/lookupapi.h
index 97f92ab..3c9b1bb 100644
--- a/src/src/lookupapi.h
+++ b/src/src/lookupapi.h
@@ -43,11 +43,14 @@ typedef struct lookup_info {
   uschar *(*quote)(               /* quoting function */
     uschar *,                     /* string to quote */
     uschar *);                    /* additional data from quote name */
+  void (*version_report)(         /* diagnostic function */
+    FILE *);                      /* fh to write to */
 } 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
+ for checking API compatibility. It's equivalent to the string"LMM2" */
+#define LOOKUP_MODULE_INFO_MAGIC 0x4c4d4d32
+/* Version 2 adds: version_report */

typedef struct lookup_module_info {
uint magic;
diff --git a/src/src/lookups/README b/src/src/lookups/README
index cdaf308..7490f0a 100644
--- a/src/src/lookups/README
+++ b/src/src/lookups/README
@@ -5,7 +5,10 @@ LOOKUPS

Each lookup type is implemented by 6 functions, xxx_open(), xxx_check(),
xxx_find(), xxx_close(), xxx_tidy(), and xxx_quote(), where xxx is the name of
-the lookup type (e.g. lsearch, dbm, or whatever).
+the lookup type (e.g. lsearch, dbm, or whatever). In addition, there is
+a version reporting function used to trace compile-vs-runtime conflicts and
+to help administrators ensure that the modules from the correct build are
+in use by the main binary.

The xxx_check(), xxx_close(), xxx_tidy(), and xxx_quote() functions need not
exist. There is a table in drtables.c which links the lookup names to the
@@ -158,4 +161,14 @@ needed, it can return its single argument, which is a uschar *. This function
does NOT use the POOL_SEARCH store, because it's usually never called from any
lookup code.

+xxx_report_version()
+--------------------
+
+This is called to report diagnostic information to a file stream.
+Typically it would report both compile-time and run-time version information.
+The arguments are:
+
+  FILE *stream    where to fprintf() the data to
+
+
 ****
diff --git a/src/src/lookups/cdb.c b/src/src/lookups/cdb.c
index 6e8b887..a8fb6b0 100644
--- a/src/src/lookups/cdb.c
+++ b/src/src/lookups/cdb.c
@@ -435,6 +435,25 @@ struct cdb_state * cdbp = handle;
  (void)close(cdbp->fileno);
 }


+
+
+/*************************************************
+*         Version reporting entry point          *
+*************************************************/
+
+/* See local README for interface description. */
+
+#include "../version.h"
+
+void
+cdb_version_report(FILE *f)
+{
+#ifdef DYNLOOKUP
+fprintf(f, "Library version: CDB: Exim version %s\n", EXIM_VERSION_STR);
+#endif
+}
+
+
 lookup_info cdb_lookup_info = {
   US"cdb",                       /* lookup name */
   lookup_absfile,                /* uses absolute file name */
@@ -443,7 +462,8 @@ lookup_info cdb_lookup_info = {
   cdb_find,                      /* find function */
   cdb_close,                     /* close function */
   NULL,                          /* no tidy function */
-  NULL                           /* no quoting function */
+  NULL,                          /* no quoting function */
+  cdb_version_report             /* version reporting */
 };


#ifdef DYNLOOKUP
diff --git a/src/src/lookups/dbmdb.c b/src/src/lookups/dbmdb.c
index 29a4a3a..1b5e69e 100644
--- a/src/src/lookups/dbmdb.c
+++ b/src/src/lookups/dbmdb.c
@@ -142,6 +142,25 @@ static dbmdb_close(void *handle)
EXIM_DBCLOSE((EXIM_DB *)handle);
}

+
+
+/*************************************************
+*         Version reporting entry point          *
+*************************************************/
+
+/* See local README for interface description. */
+
+#include "../version.h"
+
+void
+dbm_version_report(FILE *f)
+{
+#ifdef DYNLOOKUP
+fprintf(f, "Library version: DBM: Exim version %s\n", EXIM_VERSION_STR);
+#endif
+}
+
+
 lookup_info dbm_lookup_info = {
   US"dbm",                       /* lookup name */
   lookup_absfile,                /* uses absolute file name */
@@ -150,7 +169,8 @@ lookup_info dbm_lookup_info = {
   dbmdb_find,                    /* find function */
   dbmdb_close,                   /* close function */
   NULL,                          /* no tidy function */
-  NULL                           /* no quoting function */
+  NULL,                          /* no quoting function */
+  dbm_version_report             /* version reporting */
 };


 lookup_info dbmz_lookup_info = {
@@ -161,7 +181,8 @@ lookup_info dbmz_lookup_info = {
   dbmnz_find,                    /* find function */
   dbmdb_close,     /* sic */     /* close function */
   NULL,                          /* no tidy function */
-  NULL                           /* no quoting function */
+  NULL,                          /* no quoting function */
+  NULL                           /* no version reporting (redundant) */
 };


#ifdef DYNLOOKUP
diff --git a/src/src/lookups/dnsdb.c b/src/src/lookups/dnsdb.c
index 5c9f96b..5e7c158 100644
--- a/src/src/lookups/dnsdb.c
+++ b/src/src/lookups/dnsdb.c
@@ -429,6 +429,25 @@ yield[ptr] = 0;
return OK;
}

+
+
+/*************************************************
+*         Version reporting entry point          *
+*************************************************/
+
+/* See local README for interface description. */
+
+#include "../version.h"
+
+void
+dnsdb_version_report(FILE *f)
+{
+#ifdef DYNLOOKUP
+fprintf(f, "Library version: DNSDB: Exim version %s\n", EXIM_VERSION_STR);
+#endif
+}
+
+
 static lookup_info _lookup_info = {
   US"dnsdb",                     /* lookup name */
   lookup_querystyle,             /* query style */
@@ -437,7 +456,8 @@ static lookup_info _lookup_info = {
   dnsdb_find,                    /* find function */
   NULL,                          /* no close function */
   NULL,                          /* no tidy function */
-  NULL                           /* no quoting function */
+  NULL,                          /* no quoting function */
+  dnsdb_version_report           /* version reporting */
 };


#ifdef DYNLOOKUP
diff --git a/src/src/lookups/dsearch.c b/src/src/lookups/dsearch.c
index 575872c..7395065 100644
--- a/src/src/lookups/dsearch.c
+++ b/src/src/lookups/dsearch.c
@@ -119,6 +119,24 @@ static dsearch_close(void *handle)
handle = handle; /* Avoid compiler warning */
}

+
+/*************************************************
+*         Version reporting entry point          *
+*************************************************/
+
+/* See local README for interface description. */
+
+#include "../version.h"
+
+void
+dsearch_version_report(FILE *f)
+{
+#ifdef DYNLOOKUP
+fprintf(f, "Library version: dsearch: Exim version %s\n", EXIM_VERSION_STR);
+#endif
+}
+
+
 static lookup_info _lookup_info = {
   US"dsearch",                   /* lookup name */
   lookup_absfile,                /* uses absolute file name */
@@ -127,7 +145,8 @@ static lookup_info _lookup_info = {
   dsearch_find,                  /* find function */
   dsearch_close,                 /* close function */
   NULL,                          /* no tidy function */
-  NULL                           /* no quoting function */
+  NULL,                          /* no quoting function */
+  dsearch_version_report         /* version reporting */
 };


 #ifdef DYNLOOKUP
diff --git a/src/src/lookups/ibase.c b/src/src/lookups/ibase.c
index 553d368..72c8de0 100644
--- a/src/src/lookups/ibase.c
+++ b/src/src/lookups/ibase.c
@@ -546,6 +546,24 @@ static uschar *ibase_quote(uschar * s, uschar * opt)
     return quoted;
 }


+
+/*************************************************
+*         Version reporting entry point          *
+*************************************************/
+
+/* See local README for interface description. */
+
+#include "../version.h"
+
+void
+ibase_version_report(FILE *f)
+{
+#ifdef DYNLOOKUP
+fprintf(f, "Library version: ibase: Exim version %s\n", EXIM_VERSION_STR);
+#endif
+}
+
+
 static lookup_info _lookup_info = {
   US"ibase",                     /* lookup name */
   lookup_querystyle,             /* query-style lookup */
@@ -554,7 +572,8 @@ static lookup_info _lookup_info = {
   ibase_find,                    /* find function */
   NULL,                          /* no close function */
   ibase_tidy,                    /* tidy function */
-  ibase_quote                    /* quoting function */
+  ibase_quote,                   /* quoting function */
+  ibase_version_report           /* version reporting */
 };


#ifdef DYNLOOKUP
diff --git a/src/src/lookups/ldap.c b/src/src/lookups/ldap.c
index 461ec15..943e431 100644
--- a/src/src/lookups/ldap.c
+++ b/src/src/lookups/ldap.c
@@ -1456,6 +1456,25 @@ else
return quoted;
}

+
+
+/*************************************************
+*         Version reporting entry point          *
+*************************************************/
+
+/* See local README for interface description. */
+
+#include "../version.h"
+
+void
+ldap_version_report(FILE *f)
+{
+#ifdef DYNLOOKUP
+fprintf(f, "Library version: LDAP: Exim version %s\n", EXIM_VERSION_STR);
+#endif
+}
+
+
 static lookup_info ldap_lookup_info = {
   US"ldap",                      /* lookup name */
   lookup_querystyle,             /* query-style lookup */
@@ -1464,7 +1483,8 @@ static lookup_info ldap_lookup_info = {
   eldap_find,                    /* find function */
   NULL,                          /* no close function */
   eldap_tidy,                    /* tidy function */
-  eldap_quote                    /* quoting function */
+  eldap_quote,                   /* quoting function */
+  ldap_version_report            /* version reporting */
 };


 static lookup_info ldapdn_lookup_info = {
@@ -1475,7 +1495,8 @@ static lookup_info ldapdn_lookup_info = {
   eldapdn_find,                  /* find function */
   NULL,                          /* no close function */
   eldap_tidy,       /* sic */    /* tidy function */
-  eldap_quote       /* sic */    /* quoting function */
+  eldap_quote,      /* sic */    /* quoting function */
+  NULL                           /* no version reporting (redundant) */
 };


 static lookup_info ldapm_lookup_info = {
@@ -1486,7 +1507,8 @@ static lookup_info ldapm_lookup_info = {
   eldapm_find,                   /* find function */
   NULL,                          /* no close function */
   eldap_tidy,       /* sic */    /* tidy function */
-  eldap_quote       /* sic */    /* quoting function */
+  eldap_quote,      /* sic */    /* quoting function */
+  NULL                           /* no version reporting (redundant) */
 };


#ifdef DYNLOOKUP
diff --git a/src/src/lookups/lsearch.c b/src/src/lookups/lsearch.c
index 5d64638..b96f709 100644
--- a/src/src/lookups/lsearch.c
+++ b/src/src/lookups/lsearch.c
@@ -410,6 +410,25 @@ lsearch_close(void *handle)
(void)fclose((FILE *)handle);
}

+
+
+/*************************************************
+*         Version reporting entry point          *
+*************************************************/
+
+/* See local README for interface description. */
+
+#include "../version.h"
+
+void
+lsearch_version_report(FILE *f)
+{
+#ifdef DYNLOOKUP
+fprintf(f, "Library version: lsearch: Exim version %s\n", EXIM_VERSION_STR);
+#endif
+}
+
+
 static lookup_info iplsearch_lookup_info = {
   US"iplsearch",                 /* lookup name */
   lookup_absfile,                /* uses absolute file name */
@@ -418,7 +437,8 @@ static lookup_info iplsearch_lookup_info = {
   iplsearch_find,                /* find function */
   lsearch_close,                 /* close function */
   NULL,                          /* no tidy function */
-  NULL                           /* no quoting function */
+  NULL,                          /* no quoting function */
+  NULL                           /* no version reporting (redundant) */
 };


 static lookup_info lsearch_lookup_info = {
@@ -429,7 +449,8 @@ static lookup_info lsearch_lookup_info = {
   lsearch_find,                  /* find function */
   lsearch_close,                 /* close function */
   NULL,                          /* no tidy function */
-  NULL                           /* no quoting function */
+  NULL,                          /* no quoting function */
+  lsearch_version_report         /* version reporting */
 };


 static lookup_info nwildlsearch_lookup_info = {
@@ -440,7 +461,8 @@ static lookup_info nwildlsearch_lookup_info = {
   nwildlsearch_find,             /* find function */
   lsearch_close,                 /* close function */
   NULL,                          /* no tidy function */
-  NULL                           /* no quoting function */
+  NULL,                          /* no quoting function */
+  NULL                           /* no version reporting (redundant) */
 };


 static lookup_info wildlsearch_lookup_info = {
@@ -451,7 +473,8 @@ static lookup_info wildlsearch_lookup_info = {
   wildlsearch_find,              /* find function */
   lsearch_close,                 /* close function */
   NULL,                          /* no tidy function */
-  NULL                           /* no quoting function */
+  NULL,                          /* no quoting function */
+  NULL                           /* no version reporting (redundant) */
 };


#ifdef DYNLOOKUP
diff --git a/src/src/lookups/mysql.c b/src/src/lookups/mysql.c
index 97b9c11..755676e 100644
--- a/src/src/lookups/mysql.c
+++ b/src/src/lookups/mysql.c
@@ -413,6 +413,27 @@ while ((c = *s++) != 0)
return quoted;
}

+
+/*************************************************
+*         Version reporting entry point          *
+*************************************************/
+
+/* See local README for interface description. */
+
+#include "../version.h"
+
+void
+mysql_version_report(FILE *f)
+{
+fprintf(f, "Library version: MySQL: Compile: %s [%s]\n"
+           "                        Runtime: %s\n",
+        MYSQL_SERVER_VERSION, MYSQL_COMPILATION_COMMENT,
+        mysql_get_client_info());
+#ifdef DYNLOOKUP
+fprintf(f, "                        Exim version %s\n", EXIM_VERSION_STR);
+#endif
+}
+
 /* These are the lookup_info blocks for this driver */


 static lookup_info mysql_lookup_info = {
@@ -423,7 +444,8 @@ static lookup_info mysql_lookup_info = {
   mysql_find,                    /* find function */
   NULL,                          /* no close function */
   mysql_tidy,                    /* tidy function */
-  mysql_quote                    /* quoting function */
+  mysql_quote,                   /* quoting function */
+  mysql_version_report           /* version reporting */
 };


#ifdef DYNLOOKUP
diff --git a/src/src/lookups/nis.c b/src/src/lookups/nis.c
index 8177f4b..995f45d 100644
--- a/src/src/lookups/nis.c
+++ b/src/src/lookups/nis.c
@@ -86,6 +86,25 @@ if ((rc = yp_match(CS handle, CS filename, CS keystring, length + 1,
return (rc == YPERR_KEY || rc == YPERR_MAP)? FAIL : DEFER;
}

+
+
+/*************************************************
+*         Version reporting entry point          *
+*************************************************/
+
+/* See local README for interface description. */
+
+#include "../version.h"
+
+void
+nis_version_report(FILE *f)
+{
+#ifdef DYNLOOKUP
+fprintf(f, "Library version: NIS: Exim version %s\n", EXIM_VERSION_STR);
+#endif
+}
+
+
 static lookup_info nis_lookup_info = {
   US"nis",                       /* lookup name */
   0,                             /* not abs file, not query style*/
@@ -94,7 +113,8 @@ static lookup_info nis_lookup_info = {
   nis_find,                      /* find function */
   NULL,                          /* no close function */
   NULL,                          /* no tidy function */
-  NULL                           /* no quoting function */
+  NULL,                          /* no quoting function */
+  nis_version_report             /* version reporting */
 };


 static lookup_info nis0_lookup_info = {
@@ -105,7 +125,8 @@ static lookup_info nis0_lookup_info = {
   nis0_find,                     /* find function */
   NULL,                          /* no close function */
   NULL,                          /* no tidy function */
-  NULL                           /* no quoting function */
+  NULL,                          /* no quoting function */
+  NULL                           /* no version reporting (redundant) */
 };


#ifdef DYNLOOKUP
diff --git a/src/src/lookups/nisplus.c b/src/src/lookups/nisplus.c
index 5213af3..966fd74 100644
--- a/src/src/lookups/nisplus.c
+++ b/src/src/lookups/nisplus.c
@@ -259,6 +259,24 @@ while (*s != 0)
return quoted;
}

+
+/*************************************************
+*         Version reporting entry point          *
+*************************************************/
+
+/* See local README for interface description. */
+
+#include "../version.h"
+
+void
+nisplus_version_report(FILE *f)
+{
+#ifdef DYNLOOKUP
+fprintf(f, "Library version: NIS+: Exim version %s\n", EXIM_VERSION_STR);
+#endif
+}
+
+
 static lookup_info _lookup_info = {
   US"nisplus",                   /* lookup name */
   lookup_querystyle,             /* query-style lookup */
@@ -267,7 +285,8 @@ static lookup_info _lookup_info = {
   nisplus_find,                  /* find function */
   NULL,                          /* no close function */
   NULL,                          /* no tidy function */
-  nisplus_quote                  /* quoting function */
+  nisplus_quote,                 /* quoting function */
+  nisplus_version_report         /* version reporting */
 };


#ifdef DYNLOOKUP
diff --git a/src/src/lookups/oracle.c b/src/src/lookups/oracle.c
index 50dfb4a..83092f0 100644
--- a/src/src/lookups/oracle.c
+++ b/src/src/lookups/oracle.c
@@ -604,6 +604,24 @@ while ((c = *s++) != 0)
return quoted;
}

+
+/*************************************************
+*         Version reporting entry point          *
+*************************************************/
+
+/* See local README for interface description. */
+
+#include "../version.h"
+
+void
+oracle_version_report(FILE *f)
+{
+#ifdef DYNLOOKUP
+fprintf(f, "Library version: Oracle: Exim version %s\n", EXIM_VERSION_STR);
+#endif
+}
+
+
 static lookup_info _lookup_info = {
   US"oracle",                    /* lookup name */
   lookup_querystyle,             /* query-style lookup */
@@ -612,7 +630,8 @@ static lookup_info _lookup_info = {
   oracle_find,                   /* find function */
   NULL,                          /* no close function */
   oracle_tidy,                   /* tidy function */
-  oracle_quote                   /* quoting function */
+  oracle_quote,                  /* quoting function */
+  oracle_version_report          /* version reporting */
 };


#ifdef DYNLOOKUP
diff --git a/src/src/lookups/passwd.c b/src/src/lookups/passwd.c
index 420eefc..45c9af2 100644
--- a/src/src/lookups/passwd.c
+++ b/src/src/lookups/passwd.c
@@ -52,6 +52,24 @@ if (!route_finduser(keystring, &pw, NULL)) return FAIL;
return OK;
}

+
+
+/*************************************************
+*         Version reporting entry point          *
+*************************************************/
+
+/* See local README for interface description. */
+
+#include "../version.h"
+
+void
+passwd_version_report(FILE *f)
+{
+#ifdef DYNLOOKUP
+fprintf(f, "Library version: passwd: Exim version %s\n", EXIM_VERSION_STR);
+#endif
+}
+
 static lookup_info _lookup_info = {
   US"passwd",                    /* lookup name */
   lookup_querystyle,             /* query-style lookup */
@@ -60,7 +78,8 @@ static lookup_info _lookup_info = {
   passwd_find,                   /* find function */
   NULL,                          /* no close function */
   NULL,                          /* no tidy function */
-  NULL                           /* no quoting function */
+  NULL,                          /* no quoting function */
+  passwd_version_report          /* version reporting */
 };


#ifdef DYNLOOKUP
diff --git a/src/src/lookups/pgsql.c b/src/src/lookups/pgsql.c
index 5bd9627..e94e9a7 100644
--- a/src/src/lookups/pgsql.c
+++ b/src/src/lookups/pgsql.c
@@ -486,6 +486,30 @@ while ((c = *s++) != 0)
return quoted;
}

+
+/*************************************************
+*         Version reporting entry point          *
+*************************************************/
+
+/* See local README for interface description. */
+
+#include "../version.h"
+
+void
+pgsql_version_report(FILE *f)
+{
+#ifdef DYNLOOKUP
+fprintf(f, "Library version: PostgreSQL: Exim version %s\n", EXIM_VERSION_STR);
+#endif
+
+/* Version reporting: there appears to be no available information about
+the client library in libpq-fe.h; once you have a connection object, you
+can access the server version and the chosen protocol version, but those
+aren't really what we want.  It might make sense to debug_printf those
+when the connection is established though? */
+}
+
+
 static lookup_info _lookup_info = {
   US"pgsql",                     /* lookup name */
   lookup_querystyle,             /* query-style lookup */
@@ -494,7 +518,8 @@ static lookup_info _lookup_info = {
   pgsql_find,                    /* find function */
   NULL,                          /* no close function */
   pgsql_tidy,                    /* tidy function */
-  pgsql_quote                    /* quoting function */
+  pgsql_quote,                   /* quoting function */
+  pgsql_version_report           /* version reporting */
 };


#ifdef DYNLOOKUP
diff --git a/src/src/lookups/spf.c b/src/src/lookups/spf.c
index 2ca4bba..b95d0ff 100644
--- a/src/src/lookups/spf.c
+++ b/src/src/lookups/spf.c
@@ -74,6 +74,24 @@ static int spf_find(void *handle, uschar *filename, uschar *keystring, int key_l
return OK;
}

+
+/*************************************************
+*         Version reporting entry point          *
+*************************************************/
+
+/* See local README for interface description. */
+
+#include "../version.h"
+
+void
+spf_version_report(FILE *f)
+{
+#ifdef DYNLOOKUP
+fprintf(f, "Library version: SPF: Exim version %s\n", EXIM_VERSION_STR);
+#endif
+}
+
+
 static lookup_info _lookup_info = {
   US"spf",                       /* lookup name */
   0,                             /* not absfile, not query style */
@@ -82,7 +100,8 @@ static lookup_info _lookup_info = {
   spf_find,                      /* find function */
   spf_close,                     /* close function */
   NULL,                          /* no tidy function */
-  NULL                           /* no quoting function */
+  NULL,                          /* no quoting function */
+  spf_version_report             /* version reporting */
 };


#ifdef DYNLOOKUP
diff --git a/src/src/lookups/sqlite.c b/src/src/lookups/sqlite.c
index 5759c43..e679973 100644
--- a/src/src/lookups/sqlite.c
+++ b/src/src/lookups/sqlite.c
@@ -155,6 +155,27 @@ while ((c = *s++) != 0)
return quoted;
}

+
+
+/*************************************************
+*         Version reporting entry point          *
+*************************************************/
+
+/* See local README for interface description. */
+
+#include "../version.h"
+
+void
+sqlite_version_report(FILE *f)
+{
+fprintf(f, "Library version: SQLite: Compile: %s\n"
+           "                         Runtime: %s\n",
+        SQLITE_VERSION, sqlite3_libversion());
+#ifdef DYNLOOKUP
+fprintf(f, "                         Exim version %s\n", EXIM_VERSION_STR);
+#endif
+}
+
 static lookup_info _lookup_info = {
   US"sqlite",                    /* lookup name */
   lookup_absfilequery,           /* query-style lookup, starts with file name */
@@ -163,7 +184,8 @@ static lookup_info _lookup_info = {
   sqlite_find,                   /* find function */
   sqlite_close,                  /* close function */
   NULL,                          /* no tidy function */
-  sqlite_quote                   /* quoting function */
+  sqlite_quote,                  /* quoting function */
+  sqlite_version_report          /* version reporting */
 };


#ifdef DYNLOOKUP
diff --git a/src/src/lookups/testdb.c b/src/src/lookups/testdb.c
index 03404d8..4c4558f 100644
--- a/src/src/lookups/testdb.c
+++ b/src/src/lookups/testdb.c
@@ -65,6 +65,24 @@ if (Ustrcmp(query, "nocache") == 0) *do_cache = FALSE;
return OK;
}

+
+/*************************************************
+*         Version reporting entry point          *
+*************************************************/
+
+/* See local README for interface description. */
+
+#include "../version.h"
+
+void
+testdb_version_report(FILE *f)
+{
+#ifdef DYNLOOKUP
+fprintf(f, "Library version: TestDB: Exim version %s\n", EXIM_VERSION_STR);
+#endif
+}
+
+
 static lookup_info _lookup_info = {
   US"testdb",                    /* lookup name */
   lookup_querystyle,             /* query-style lookup */
@@ -73,7 +91,8 @@ static lookup_info _lookup_info = {
   testdb_find,                   /* find function */
   NULL,                          /* no close function */
   NULL,                          /* no tidy function */
-  NULL                           /* no quoting function */
+  NULL,                          /* no quoting function */
+  testdb_version_report          /* version reporting */
 };


#ifdef DYNLOOKUP
diff --git a/src/src/lookups/whoson.c b/src/src/lookups/whoson.c
index d197905..b4527a9 100644
--- a/src/src/lookups/whoson.c
+++ b/src/src/lookups/whoson.c
@@ -62,6 +62,25 @@ switch (wso_query(query, CS buffer, sizeof(buffer)))
}
}

+
+
+/*************************************************
+*         Version reporting entry point          *
+*************************************************/
+
+/* See local README for interface description. */
+
+#include "../version.h"
+
+void
+whoson_version_report(FILE *f)
+{
+fprintf(f, "Library version: Whoson: Runtime: %s\n", wso_version());
+#ifdef DYNLOOKUP
+fprintf(f, "                         Exim version %s\n", EXIM_VERSION_STR);
+#endif
+}
+
 static lookup_info _lookup_info = {
   US"whoson",                    /* lookup name */
   lookup_querystyle,             /* query-style lookup */
@@ -70,7 +89,8 @@ static lookup_info _lookup_info = {
   whoson_find,                   /* find function */
   NULL,                          /* no close function */
   NULL,                          /* no tidy function */
-  NULL                           /* no quoting function */
+  NULL,                          /* no quoting function */
+  whoson_version_report          /* version reporting */
 };


#ifdef DYNLOOKUP
diff --git a/src/src/version.c b/src/src/version.c
index 6cddce6..ef994a8 100644
--- a/src/src/version.c
+++ b/src/src/version.c
@@ -11,8 +11,7 @@

#include "exim.h"

-
-#define THIS_VERSION "4.73"
+#include "version.h"


/* The header file cnumber.h contains a single line containing the
@@ -41,7 +40,7 @@ sprintf() call is the gcc -Wall warns about a \0 in a format string. */
version_cnumber = cnumber_buffer;
version_cnumber_format = US"%d\0<<eximcnumber>>";
sprintf(CS version_cnumber, CS version_cnumber_format, cnumber);
-version_string = US THIS_VERSION "\0<<eximversion>>";
+version_string = US EXIM_VERSION_STR "\0<<eximversion>>";

 Ustrcpy(today, __DATE__);
 if (today[4] == ' ') today[4] = '0';
diff --git a/src/src/version.h b/src/src/version.h
new file mode 100644
index 0000000..4e544e0
--- /dev/null
+++ b/src/src/version.h
@@ -0,0 +1,15 @@
+/*************************************************
+*     Exim - an Internet mail transport agent    *
+*************************************************/
+
+/* Copyright (c) Google, Inc. 2010 */
+/* See the file NOTICE for conditions of use and distribution. */
+
+/* This is bumped by the Exim Maintainers, the release engineer: */
+#define EXIM_RELEASE_VERSION_STR        "4.73"
+/* If you apply extensive local patches, consider putting -foo into here */
+#define EXIM_VARIANT_VERSION            ""
+
+#define EXIM_VERSION_STR        EXIM_RELEASE_VERSION_STR EXIM_VARIANT_VERSION
+
+/* End of version.h */