1. Added Tony F's ${dlfunc expansion, slightly modified (see NewStuff).
authorPhilip Hazel <ph10@hermes.cam.ac.uk>
Tue, 22 Mar 2005 14:11:54 +0000 (14:11 +0000)
committerPhilip Hazel <ph10@hermes.cam.ac.uk>
Tue, 22 Mar 2005 14:11:54 +0000 (14:11 +0000)
2. Recognize ${perl even if not compiled, and give suitable error
message.

13 files changed:
doc/doc-txt/ChangeLog
doc/doc-txt/NewStuff
src/ACKNOWLEDGMENTS
src/src/EDITME
src/src/config.h.defaults
src/src/exim.c
src/src/exim.h
src/src/expand.c
src/src/globals.c
src/src/globals.h
src/src/local_scan.h
src/src/macros.h
src/src/routers/redirect.c

index b2a43652cdc560574359f2f8ff6a8e839b29e5a6..f366edf2cbf20f747efd8e50d2bd11df3ea18052 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.93 2005/03/22 10:11:42 ph10 Exp $
+$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.94 2005/03/22 14:11:54 ph10 Exp $
 
 Change log file for Exim from version 4.21
 -------------------------------------------
@@ -7,53 +7,59 @@ Change log file for Exim from version 4.21
 Exim version 4.51
 -----------------
 
-TK/01. Added Yahoo DomainKeys support via libdomainkeys. See
-       doc/experimental-spec.txt for details. (http://domainkeys.sf.net)
-
-TK/02. Fix ACL "control" statment not being available in MIME ACL.
-
-TK/03. Fix ACL "regex" condition not being available in MIME ACL.
-
-PH/01. Installed a patch from the Sieve maintainer that allows -bf to be used
-       to test Sieve filters that use "vacation".
-
-PH/02. Installed a slightly modified version of Nikos Mavrogiannopoulos' patch
-       that changes the way the GnuTLS parameters are stored in the cache file.
-       The new format can be generated externally. For backward compatibility,
-       if the data in the cache doesn't make sense, Exim assumes it has read an
-       old-format file, and it generates new data and writes a new file. This
-       means that you can't go back to an older release without removing the
-       file.
-
-PH/03. A redirect router that has both "unseen" and "one_time" set does not
-       work if there are any delivery delays because "one_time" forces the
-       parent to be marked "delivered", so its unseen clone is never tried
-       again. For this reason, Exim now forbids the simultaneous setting of
-       these two options.
-
-PH/04. Change 4.11/85 fixed an obscure bug concerned with addresses that are
-       redirected to themselves ("homonym" addresses). Read the long ChangeLog
-       entry if you want to know the details. The fix, however, neglected to
-       consider the case when local delivery batching is involved. The test for
-       "previously delivered" was not happening when checking to see if an
-       address could be batched with a previous (undelivered) one; under
-       certain circumstances this could lead to multiple deliveries to the same
-       address. A one-line patch to add the appropriate test fixes the bug.
-
-PH/05. Renamed the macro SOCKLEN_T as EXIM_SOCKLEN_T because AIX uses SOCKLEN_T
-       in its include files, and this causes problems building Exim.
-
-PH/06. A number of "verify =" ACL conditions have no options (e.g. verify =
-       header_syntax) but Exim was just ignoring anything given after a slash.
-       In particular, this caused confusion with an attempt to use "verify =
-       reverse_host_lookup/defer_ok". An error is now given when options are
-       supplied for verify items that do not have them. (Maybe reverse_host_
-       lookup should have a defer_ok option, but that's a different point.)
-
-PH/07. Increase the size of the buffer for incoming SMTP commands from 512 (as
-       defined by RFC 821) to 2048, because there were problems with some AUTH
-       commands, and RFC 1869 says the size should be increased for extended
-       SMTP commands that take arguments.
+TK/01 Added Yahoo DomainKeys support via libdomainkeys. See
+      doc/experimental-spec.txt for details. (http://domainkeys.sf.net)
+
+TK/02 Fix ACL "control" statment not being available in MIME ACL.
+
+TK/03 Fix ACL "regex" condition not being available in MIME ACL.
+
+PH/01 Installed a patch from the Sieve maintainer that allows -bf to be used
+      to test Sieve filters that use "vacation".
+
+PH/02 Installed a slightly modified version of Nikos Mavrogiannopoulos' patch
+      that changes the way the GnuTLS parameters are stored in the cache file.
+      The new format can be generated externally. For backward compatibility,
+      if the data in the cache doesn't make sense, Exim assumes it has read an
+      old-format file, and it generates new data and writes a new file. This
+      means that you can't go back to an older release without removing the
+      file.
+
+PH/03 A redirect router that has both "unseen" and "one_time" set does not
+      work if there are any delivery delays because "one_time" forces the
+      parent to be marked "delivered", so its unseen clone is never tried
+      again. For this reason, Exim now forbids the simultaneous setting of
+      these two options.
+
+PH/04 Change 4.11/85 fixed an obscure bug concerned with addresses that are
+      redirected to themselves ("homonym" addresses). Read the long ChangeLog
+      entry if you want to know the details. The fix, however, neglected to
+      consider the case when local delivery batching is involved. The test for
+      "previously delivered" was not happening when checking to see if an
+      address could be batched with a previous (undelivered) one; under
+      certain circumstances this could lead to multiple deliveries to the same
+      address. A one-line patch to add the appropriate test fixes the bug.
+
+PH/05 Renamed the macro SOCKLEN_T as EXIM_SOCKLEN_T because AIX uses SOCKLEN_T
+      in its include files, and this causes problems building Exim.
+
+PH/06 A number of "verify =" ACL conditions have no options (e.g. verify =
+      header_syntax) but Exim was just ignoring anything given after a slash.
+      In particular, this caused confusion with an attempt to use "verify =
+      reverse_host_lookup/defer_ok". An error is now given when options are
+      supplied for verify items that do not have them. (Maybe reverse_host_
+      lookup should have a defer_ok option, but that's a different point.)
+
+PH/07 Increase the size of the buffer for incoming SMTP commands from 512 (as
+      defined by RFC 821) to 2048, because there were problems with some AUTH
+      commands, and RFC 1869 says the size should be increased for extended
+      SMTP commands that take arguments.
+
+PH/08 Added ${dlfunc dynamically loaded function for expansion (code from Tony
+      Finch).
+
+PH/09 Previously, an attempt to use ${perl when it wasn't compiled gave an
+      "unknown" error; now it says that the functionality isn't in the binary.
 
 
 A note about Exim versions 4.44 and 4.50
index 827c5d1dce664164bab87beb954e99829498907b..383c0f6f4fab857ac060e61b84b28d91e3f7c9d1 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/NewStuff,v 1.27 2005/03/08 11:38:21 ph10 Exp $
+$Cambridge: exim/doc/doc-txt/NewStuff,v 1.28 2005/03/22 14:11:54 ph10 Exp $
 
 New Features in Exim
 --------------------
@@ -12,32 +12,72 @@ file contains a listing of all changes, including bug fixes.
 Version 4.51
 ------------
 
-PH/01. The format in which GnuTLS parameters are written to the gnutls-param
-       file in the spool directory has been changed. This change has been made
-       to alleviate problems that some people had with the generation of the
-       parameters by Exim when /dev/random was exhausted. In this situation,
-       Exim would hang until /dev/random acquired some more entropy.
-
-       The new code exports and imports the DH and RSA parameters in PEM
-       format. This means that the parameters can be generated externally using
-       the certtool command that is part of GnuTLS.
-
-       To replace the parameters with new ones, instead of deleting the file
-       and letting Exim re-create it, you can generate new parameters using
-       certtool and, when this has been done, replace Exim's cache file by
-       renaming. The relevant commands are something like this:
-
-         # rm -f new.params
-         # touch new.params
-         # chown exim:exim new.params
-         # chmod 0400 new.params
-         # certtool --generate-privkey --bits 512 >new.params
-         # echo "" >>new.params
-         # certtool --generate-dh-params --bits 1024 >> new.params
-         # mv new.params params
-
-       If Exim never has to generate the parameters itself, the possibility of
-       stalling is removed.
+PH/01 The format in which GnuTLS parameters are written to the gnutls-param
+      file in the spool directory has been changed. This change has been made
+      to alleviate problems that some people had with the generation of the
+      parameters by Exim when /dev/random was exhausted. In this situation,
+      Exim would hang until /dev/random acquired some more entropy.
+
+      The new code exports and imports the DH and RSA parameters in PEM
+      format. This means that the parameters can be generated externally using
+      the certtool command that is part of GnuTLS.
+
+      To replace the parameters with new ones, instead of deleting the file
+      and letting Exim re-create it, you can generate new parameters using
+      certtool and, when this has been done, replace Exim's cache file by
+      renaming. The relevant commands are something like this:
+
+        # rm -f new.params
+        # touch new.params
+        # chown exim:exim new.params
+        # chmod 0400 new.params
+        # certtool --generate-privkey --bits 512 >new.params
+        # echo "" >>new.params
+        # certtool --generate-dh-params --bits 1024 >> new.params
+        # mv new.params params
+
+      If Exim never has to generate the parameters itself, the possibility of
+      stalling is removed.
+
+PH/02 A new expansion item for dynamically loading and calling a locally-
+      written C function is now provided, if Exim is compiled with
+
+        EXPAND_DLFUNC=yes
+
+      set in Local/Makefile. The facility is not included by default (a
+      suitable error is given if you try to use it when it is not there.)
+      You load and call the function like this:
+
+        ${dlfunc{/some/file}{function}{arg1}{arg2}...}
+
+      Once loaded, Exim remembers it so that it doesn't reload it in the same
+      Exim process (but of course Exim does start new processes frequently).
+
+      There may be from zero to eight arguments to the function. When compiling
+      a local function that is to be called in this way, local_scan.h should be
+      included. The Exim variables and functions that are defined by that API
+      are also available for dynamically loaded functions. The function itself
+      must have the following type:
+
+        int dlfunction(uschar **yield, int argc, uschar *argv[])
+
+      Where "uschar" is a typedef for "unsigned char" in local_scan.h. The
+      function should return one of the following values:
+
+      OK            Success. The string that is placed in "yield" is put into
+                    the expanded string that is being built.
+
+      FAIL          A non-forced expansion failure occurs, with the error
+                    message taken from "yield", if it is set.
+
+      FAIL_FORCED   A forced expansion failure occurs, with the error message
+                    taken from "yield" if it is set.
+
+      ERROR         Same as FAIL, except that a panic log entry is written.
+
+      When compiling a function that is to be used in this way with gcc,
+      you need to add -shared to the gcc command. Also, in the Exim build-time
+      configuration, you must add -export-dynamic to EXTRALIBS.
 
 
 Version 4.50
index 8314c699af17a40db1d48957f87ef0e6d18de016..0982973d2e5383dfc30c2d1ee7bb9b1a18c8fde9 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/src/ACKNOWLEDGMENTS,v 1.15 2005/03/15 12:27:54 ph10 Exp $
+$Cambridge: exim/src/ACKNOWLEDGMENTS,v 1.16 2005/03/22 14:11:54 ph10 Exp $
 
 EXIM ACKNOWLEDGEMENTS
 
@@ -20,7 +20,7 @@ relatively small patches.
 Philip Hazel
 
 Lists created: 20 November 2002
-Last updated:  15 March 2005
+Last updated:  22 March 2005
 
 
 THE OLD LIST
@@ -78,7 +78,7 @@ Richard Birkett           Fix for empty -f address crash
 Nick Burrett              Patch for CONFIGURE_FILE_USE_EUID in exicyclog
 Matthew Byng-Maddick      Patch for qualify_domain in redirect router
                           Patch for ignore_target_hosts in ipliteral router
-                          The cyrus_sasl authenticator 
+                          The cyrus_sasl authenticator
 Steve Campbell            eximstats extensions and continued maintenance
 Brian Candler             Use h_errno for gethostbyname()
                           Suggested patch for .ifdef etc
@@ -93,7 +93,7 @@ Andrew Doran              Patch for NetBSD configuration files
                           Patch for ifreq alignment and size problems
 Michael Deutschmann       Suggested patch for treating bind() failure like connect()
                           Patch for $sender_data and $recipient_data
-                          Suggested patch for null address match lookup bug 
+                          Suggested patch for null address match lookup bug
 Oliver Eikemeier          Patch to skip Received: if expansion is empty
                           Patch for "eqi"
 Nico Erfurth              Fix for bug in ${readfile}
@@ -121,9 +121,10 @@ Tony Finch                Expansion extensions
                             A number of useful code criticisms
                             Timezone patch for exiwhat
                             Patch for more daemon exiwhat information
-                            Patch for -dd 
-                            Patch for mxh lookup type in dnsdb 
-                            Patch for defer_foo in dndsb 
+                            Patch for -dd
+                            Patch for mxh lookup type in dnsdb
+                            Patch for defer_foo in dndsb
+                            Patch for ${dlfunc
 Giuliano Gavazzi          Patches for OSX compilation
 Dominic Germain           Patch for exiqgrep MacOS X bug
 Oliver Gorwits            $load_average patch
@@ -138,7 +139,7 @@ Michael Haardt            Tidies to make the code stricter
                           Module to support Sieve (RFC 3028) filters and
                             continued maintenance of same
                           Patch for faster sort algorithm in queue.c
-                          Patch for LDAP timeout handling 
+                          Patch for LDAP timeout handling
 Thomas Hager              Patch for saslauthd crash bug
 Richard Hall              Fix for file descriptor leak in redirection
 Steve Haslam              Lots of stuff, including
@@ -154,7 +155,7 @@ Christian Kellner         Patch for LDAP dereferencing
 Alex Kiernan              Patch for libradius
                           Diagnosis of milliwait clock-backwards bug
 Tom Kistner               SPA server code
-                          Writing and maintaining the content scanning 
+                          Writing and maintaining the content scanning
                             extension (exiscan)
 Friso Kuipers             Patch for GDBM problem
 Chris Liddiard            Fix for bug in exiqsumm
@@ -174,9 +175,9 @@ Marc Merlin               Many suggestions and patches for callouts and
                             SMTP error message features
 Andreas Metzler           Patch for message_id_header_domain
                           Suggested patch for multi-config files in scripts bug
-Alex Miller               Suggested readline() patch                           
+Alex Miller               Suggested readline() patch
                           Patch for LDAP_RES_SEARCH_REFERENCE handling
-                          Support for the DrWeb content scanner 
+                          Support for the DrWeb content scanner
 Andreas Mueller           Patch for logging uncompleted SMTP transactions
 Pete Naylor               Patch for LDAP TCP connect timeout setting
 Marcin Owsiany            Diagnosis of a tricky timeout failure bug
index 60774cf498757150eed498dcb9f799bf855ca33c..72f797bb355ab23ae1fbe1d7a62eeac3c51a7aee 100644 (file)
@@ -1,4 +1,4 @@
-# $Cambridge: exim/src/src/EDITME,v 1.8 2005/02/17 11:58:25 ph10 Exp $
+# $Cambridge: exim/src/src/EDITME,v 1.9 2005/03/22 14:11:54 ph10 Exp $
 
 ##################################################
 #          The Exim mail transport agent         #
@@ -689,6 +689,15 @@ ZCAT_COMMAND=/usr/bin/zcat
 # EXIM_PERL=perl.o
 
 
+#------------------------------------------------------------------------------
+# Support for dynamically-loaded string expansion functions via ${dlfunc. If
+# you are using gcc the dynamically-loaded object must be compiled with the
+# -shared option, and you will need to add -export-dynamic to EXTRALIBS so
+# that the local_scan API is made available by the linker.
+
+# EXPAND_DLFUNC=yes
+
+
 #------------------------------------------------------------------------------
 # Exim has support for PAM (Pluggable Authentication Modules), a facility
 # which is available in the latest releases of Solaris and in some GNU/Linux
index ea63c888f9465ea56b908ab8f72a2a67ad0e6e4a..2825f98c1ca35649824c068bee90c56aa54f562f 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/config.h.defaults,v 1.5 2005/03/08 15:32:02 tom Exp $ */
+/* $Cambridge: exim/src/src/config.h.defaults,v 1.6 2005/03/22 14:11:54 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -42,11 +42,10 @@ in config.h unless some value is defined in Local/Makefile. */
 #define EXIMDB_LOCK_TIMEOUT          60
 #define EXIMDB_LOCKFILE_MODE       0640
 #define EXIMDB_MODE                0640
-
 #define EXIM_PERL
-
 /* Both uid and gid are triggered by this */
 #define EXIM_UID
+#define EXPAND_DLFUNC
 
 #define FIXED_NEVER_USERS         "root"
 
index 14cd032280eca7305e12d480b5b27812cac95b68..ffe596d15d8cdbe879a5c92521b29406ac2d3aa8 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/exim.c,v 1.16 2005/03/15 14:09:12 ph10 Exp $ */
+/* $Cambridge: exim/src/src/exim.c,v 1.17 2005/03/22 14:11:54 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -829,6 +829,9 @@ fprintf(f, "Support for:");
 #ifdef EXIM_PERL
   fprintf(f, " Perl");
 #endif
+#ifdef EXPAND_DLFUNC
+  fprintf(f, " Expand_dlfunc");
+#endif
 #ifdef USE_TCP_WRAPPERS
   fprintf(f, " TCPwrappers");
 #endif
index 42f7980c2ec0b23223022d66e7bc04359976f317..b28edb79bf80ab90ef14b7bec3650f0440f1a6e8 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/exim.h,v 1.9 2005/03/15 14:09:12 ph10 Exp $ */
+/* $Cambridge: exim/src/src/exim.h,v 1.10 2005/03/22 14:11:54 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -60,7 +60,7 @@ making unique names. */
 /* Unix includes */
 
 #include <errno.h>
-#if    defined(__svr4__) && defined(__sparc) && ! defined(__EXTENSIONS__)
+#if defined(__svr4__) && defined(__sparc) && ! defined(__EXTENSIONS__)
 #define __EXTENSIONS__  /* so that SunOS 5 gets NGROUPS_MAX */
 #include <limits.h>
 #undef  __EXTENSIONS__
@@ -207,7 +207,7 @@ or a macro with entries f_frsize and f_bsize. */
 #endif
 
 
-#ifndef  SIOCGIFCONF    /* HACK for SunOS 5 */
+#ifndef  SIOCGIFCONF   /* HACK for SunOS 5 */
 #include <sys/sockio.h>
 #endif
 
@@ -414,7 +414,7 @@ requires various things that are set therein. */
 #include <iconv.h>
 #endif
 
-#ifdef USE_READLINE
+#if defined(USE_READLINE) || defined(EXPAND_DLFUNC)
 #include <dlfcn.h>
 #endif
 
index 6e7d3550f41b7a4d360d3b4659ee7c52ff515644..d27530bd7b16059ce9beb9bc4e313b02792c55c5 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/expand.c,v 1.16 2005/03/09 08:27:51 tom Exp $ */
+/* $Cambridge: exim/src/src/expand.c,v 1.17 2005/03/22 14:11:54 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -48,6 +48,7 @@ static uschar *expand_string_internal(uschar *, BOOL, uschar **, BOOL);
 alphabetical order. */
 
 static uschar *item_table[] = {
+  US"dlfunc",
   US"extract",
   US"hash",
   US"hmac",
@@ -55,9 +56,7 @@ static uschar *item_table[] = {
   US"length",
   US"lookup",
   US"nhash",
-  #ifdef EXIM_PERL
-    US"perl",
-  #endif
+  US"perl",
   US"readfile",
   US"readsocket",
   US"run",
@@ -66,6 +65,7 @@ static uschar *item_table[] = {
   US"tr" };
 
 enum {
+  EITEM_DLFUNC,
   EITEM_EXTRACT,
   EITEM_HASH,
   EITEM_HMAC,
@@ -73,9 +73,7 @@ enum {
   EITEM_LENGTH,
   EITEM_LOOKUP,
   EITEM_NHASH,
-  #ifdef EXIM_PERL
-    EITEM_PERL,
-  #endif
+  EITEM_PERL,
   EITEM_READFILE,
   EITEM_READSOCK,
   EITEM_RUN,
@@ -3072,10 +3070,15 @@ while (*s != 0)
     or ${perl{sub}{arg1}{arg2}} or up to a maximum of EXIM_PERL_MAX_ARGS
     arguments (defined below). */
 
-    #ifdef EXIM_PERL
     #define EXIM_PERL_MAX_ARGS 8
 
     case EITEM_PERL:
+    #ifndef EXIM_PERL
+    expand_string_message = US"\"${perl\" encountered, but this facility "
+      "is not included in this binary";
+    goto EXPAND_FAILED;
+
+    #else   /* EXIM_PERL */
       {
       uschar *sub_arg[EXIM_PERL_MAX_ARGS + 2];
       uschar *new_yield;
@@ -3847,6 +3850,106 @@ while (*s != 0)
 
       continue;
       }
+
+
+    /* If ${dlfunc support is configured, handle calling dynamically-loaded
+    functions, unless locked out at this time. Syntax is ${dlfunc{file}{func}}
+    or ${dlfunc{file}{func}{arg}} or ${dlfunc{file}{func}{arg1}{arg2}} or up to
+    a maximum of EXPAND_DLFUNC_MAX_ARGS arguments (defined below). */
+
+    #define EXPAND_DLFUNC_MAX_ARGS 8
+
+    case EITEM_DLFUNC:
+    #ifndef EXPAND_DLFUNC
+    expand_string_message = US"\"${dlfunc\" encountered, but this facility "
+      "is not included in this binary";
+    goto EXPAND_FAILED;
+
+    #else   /* EXPAND_DLFUNC */
+      {
+      tree_node *t;
+      exim_dlfunc_t *func;
+      uschar *result;
+      int status, argc;
+      uschar *argv[EXPAND_DLFUNC_MAX_ARGS + 3];
+
+      if ((expand_forbid & RDO_DLFUNC) != 0)
+        {
+        expand_string_message =
+          US"dynamically-loaded functions are not permitted";
+        goto EXPAND_FAILED;
+        }
+
+      switch(read_subs(argv, EXPAND_DLFUNC_MAX_ARGS + 2, 2, &s, skipping,
+           TRUE, US"dlfunc"))
+        {
+        case 1: goto EXPAND_FAILED_CURLY;
+        case 2:
+        case 3: goto EXPAND_FAILED;
+        }
+
+      /* If skipping, we don't actually do anything */
+
+      if (skipping) continue;
+
+      /* Look up the dynamically loaded object handle in the tree. If it isn't
+      found, dlopen() the file and put the handle in the tree for next time. */
+
+      t = tree_search(dlobj_anchor, argv[0]);
+      if (t == NULL)
+        {
+        void *handle = dlopen(CS argv[0], RTLD_LAZY);
+        if (handle == NULL)
+          {
+          expand_string_message = string_sprintf("dlopen \"%s\" failed: %s",
+            argv[0], dlerror());
+          log_write(0, LOG_MAIN|LOG_PANIC, "%s", expand_string_message);
+          goto EXPAND_FAILED;
+          }
+        t = store_get_perm(sizeof(tree_node) + Ustrlen(argv[0]));
+        Ustrcpy(t->name, argv[0]);
+        t->data.ptr = handle;
+        (void)tree_insertnode(&dlobj_anchor, t);
+        }
+
+      /* Having obtained the dynamically loaded object handle, look up the
+      function pointer. */
+
+      func = (exim_dlfunc_t *)dlsym(t->data.ptr, CS argv[1]);
+      if (func == NULL)
+        {
+        expand_string_message = string_sprintf("dlsym \"%s\" in \"%s\" failed: "
+          "%s", argv[1], argv[0], dlerror());
+       log_write(0, LOG_MAIN|LOG_PANIC, "%s", expand_string_message);
+        goto EXPAND_FAILED;
+        }
+
+      /* Call the function and work out what to do with the result. If it
+      returns OK, we have a replacement string; if it returns DEFER then
+      expansion has failed in a non-forced manner; if it returns FAIL then
+      failure was forced; if it returns ERROR or any other value there's a
+      problem, so panic slightly. */
+
+      result = NULL;
+      for (argc = 0; argv[argc] != NULL; argc++);
+      status = func(&result, argc - 2, &argv[2]);
+      if(status == OK)
+        {
+        if (result == NULL) result = US"";
+        yield = string_cat(yield, &size, &ptr, result, Ustrlen(result));
+        continue;
+        }
+      else
+        {
+        expand_string_message = result == NULL ? US"(no message)" : result;
+        if(status == FAIL_FORCED) expand_string_forcedfail = TRUE;
+          else if(status != FAIL)
+            log_write(0, LOG_MAIN|LOG_PANIC, "dlfunc{%s}{%s} failed (%d): %s",
+              argv[0], argv[1], status, expand_string_message);
+        goto EXPAND_FAILED;
+        }
+      }
+    #endif /* EXPAND_DLFUNC */
     }
 
   /* Control reaches here if the name is not recognized as one of the more
index fdccc0b989165a36f10b0dedb1ea3a07472ece4c..2324e40723a99f27581c95c18b44ea1a8fc903c3 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/globals.c,v 1.19 2005/03/08 15:32:02 tom Exp $ */
+/* $Cambridge: exim/src/src/globals.c,v 1.20 2005/03/22 14:11:54 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -62,6 +62,10 @@ BOOL    opt_perl_at_start      = FALSE;
 BOOL    opt_perl_started       = FALSE;
 #endif
 
+#ifdef EXPAND_DLFUNC
+tree_node *dlobj_anchor        = NULL;
+#endif
+
 #ifdef LOOKUP_IBASE
 uschar *ibase_servers          = NULL;
 #endif
index 2bb61c14534a7ff05ffeddd3e62781b089a8c153..404838126e355c8901c31f913de462b5e2cde7f9 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/globals.h,v 1.12 2005/03/08 15:32:02 tom Exp $ */
+/* $Cambridge: exim/src/src/globals.h,v 1.13 2005/03/22 14:11:54 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -26,6 +26,10 @@ extern BOOL    opt_perl_at_start;      /* Start Perl interpreter at start */
 extern BOOL    opt_perl_started;       /* Set once interpreter started */
 #endif
 
+#ifdef EXPAND_DLFUNC
+extern tree_node *dlobj_anchor;        /* Tree of dynamically-loaded objects */
+#endif
+
 #ifdef LOOKUP_IBASE
 extern uschar *ibase_servers;
 #endif
index e612ccd84c6dc9bd8a35bb6ef7b74e9a5de4336b..fdc73bed57d9cc7d7a20697681cc293fb5207c64 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/local_scan.h,v 1.3 2005/01/04 10:00:42 ph10 Exp $ */
+/* $Cambridge: exim/src/src/local_scan.h,v 1.4 2005/03/22 14:11:54 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -9,7 +9,9 @@
 
 /* This file is the header that is the only Exim header to be included in the
 source for the local_scan.c() function. It contains definitions that are made
-available for use in that function, and which are documented. */
+available for use in that function, and which are documented.
+
+This API is also used for functions called by the ${dlfunc expansion item. */
 
 
 /* Some basic types that make some things easier, and the store functions. */
@@ -34,13 +36,27 @@ enum {
 };
 
 
-/* Return codes from the support functions lss_match_xxx(). */
+/* Functions called by ${dlfunc{file}{func}{arg}...} return one of the five
+status codes defined immediately below. The function's first argument is either
+the result of expansion, or the error message in case of failure. The second
+and third arguments are standard argument count and vector, comprising the
+{arg} values specified in the expansion item. */
+
+typedef int exim_dlfunc_t(uschar **yield, int argc, uschar *argv[]);
+
+
+/* Return codes from the support functions lss_match_xxx(). These are also the
+codes that dynamically-loaded ${dlfunc functions must return. */
 
 #define  OK            0          /* Successful match */
 #define  DEFER         1          /* Defer - some problem */
 #define  FAIL          2          /* Matching failed */
 #define  ERROR         3          /* Internal or config error */
 
+/* Extra return code for ${dlfunc functions */
+
+#define  FAIL_FORCED   4          /* "Forced" failure */
+
 
 /* Available logging destinations */
 
index d69da22f7cc048c3d3c7a6e855fa5544cc5d4e69..86bb84f1281dbb295d64aff5435e1def3f1b9a1f 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/macros.h,v 1.10 2005/03/10 08:56:03 tom Exp $ */
+/* $Cambridge: exim/src/src/macros.h,v 1.11 2005/03/22 14:11:54 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -237,27 +237,29 @@ enum {
 apply to all of them). Some other functions also use these convenient values,
 and some additional values are used only by non-driver functions.
 
-OK, FAIL, DEFER, and ERROR are also declared in local_scan.h for use in the
-local_scan() function. Do not change them unilaterally. */
+OK, FAIL, DEFER, ERROR, and FAIL_FORCED are also declared in local_scan.h for
+use in the local_scan() function and in ${dlfunc loaded functions. Do not
+change them unilaterally. */
 
 #define  OK            0    /* Successful match */
 #define  DEFER         1    /* Defer - some problem */
 #define  FAIL          2    /* Matching failed */
 #define  ERROR         3    /* Internal or config error */
+#define  FAIL_FORCED   4    /* "Forced" failure */
 /***********/
-#define DECLINE        4    /* Declined to handle the address, pass to next
+#define DECLINE        5    /* Declined to handle the address, pass to next
                                  router unless no_more is set */
-#define PASS           5    /* Pass to next driver, or to pass_router,
+#define PASS           6    /* Pass to next driver, or to pass_router,
                                  even if no_more is set */
-#define DISCARD        6    /* Address routed to :blackhole: or "seen finish" */
-#define SKIP           7    /* Skip this router (used in route_address only) */
-#define REROUTED       8    /* Address was changed and child created*/
-#define PANIC          9    /* Hard failed with internal error */
-#define BAD64         10    /* Bad base64 data (auth) */
-#define UNEXPECTED    11    /* Unexpected initial auth data */
-#define CANCELLED     12    /* Authentication cancelled */
-#define FAIL_SEND     13    /* send() failed in authenticator */
-#define FAIL_DROP     14    /* Fail and drop connection (used in ACL) */
+#define DISCARD        7    /* Address routed to :blackhole: or "seen finish" */
+#define SKIP           8    /* Skip this router (used in route_address only) */
+#define REROUTED       9    /* Address was changed and child created*/
+#define PANIC         10    /* Hard failed with internal error */
+#define BAD64         11    /* Bad base64 data (auth) */
+#define UNEXPECTED    12    /* Unexpected initial auth data */
+#define CANCELLED     13    /* Authentication cancelled */
+#define FAIL_SEND     14    /* send() failed in authenticator */
+#define FAIL_DROP     15    /* Fail and drop connection (used in ACL) */
 
 /* Returns from the deliver_message() function */
 
@@ -489,15 +491,16 @@ router, which were chosen to represent the standard situation for users'
 #define RDO_READFILE     0x00001000  /* Forbid "readfile" in exp in filter */
 #define RDO_READSOCK     0x00002000  /* Forbid "readsocket" in exp in filter */
 #define RDO_RUN          0x00004000  /* Forbid "run" in expansion in filter */
-#define RDO_REALLOG      0x00008000  /* Really do log (not testing/verifying) */
-#define RDO_REWRITE      0x00010000  /* Rewrite generated addresses */
-#define RDO_EXIM_FILTER  0x00020000  /* Forbid Exim filters */
-#define RDO_SIEVE_FILTER 0x00040000  /* Forbid Sieve filters */
+#define RDO_DLFUNC       0x00008000  /* Forbid "dlfunc" in expansion in filter */
+#define RDO_REALLOG      0x00010000  /* Really do log (not testing/verifying) */
+#define RDO_REWRITE      0x00020000  /* Rewrite generated addresses */
+#define RDO_EXIM_FILTER  0x00040000  /* Forbid Exim filters */
+#define RDO_SIEVE_FILTER 0x00080000  /* Forbid Sieve filters */
 
 /* This is the set that apply to expansions in filters */
 
 #define RDO_FILTER_EXPANSIONS \
-  (RDO_EXISTS|RDO_LOOKUP|RDO_PERL|RDO_READFILE|RDO_READSOCK|RDO_RUN)
+  (RDO_EXISTS|RDO_LOOKUP|RDO_PERL|RDO_READFILE|RDO_READSOCK|RDO_RUN|RDO_DLFUNC)
 
 /* As well as the RDO bits themselves, we need the bit numbers in order to
 access (most of) the individual bits as separate options. This could be
@@ -505,7 +508,7 @@ automated, but I haven't bothered. Keep this list in step with the above! */
 
 enum { RDON_BLACKHOLE, RDON_DEFER, RDON_EACCES, RDON_ENOTDIR, RDON_EXISTS,
   RDON_FAIL, RDON_FILTER, RDON_FREEZE, RDON_INCLUDE, RDON_LOG, RDON_LOOKUP,
-  RDON_PERL, RDON_READFILE, RDON_READSOCK, RDON_RUN, RDON_REALLOG,
+  RDON_PERL, RDON_READFILE, RDON_READSOCK, RDON_RUN, RDON_DLFUNC, RDON_REALLOG,
   RDON_REWRITE, RDON_EXIM_FILTER, RDON_SIEVE_FILTER };
 
 /* Results of filter or forward file processing. Some are only from a filter;
index 461fc5d92252e136b6a547e72c974837310419c3..65b5e40994cc75fed58eafcdc8595a2d031a4a5d 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/routers/redirect.c,v 1.6 2005/03/15 11:37:21 ph10 Exp $ */
+/* $Cambridge: exim/src/src/routers/redirect.c,v 1.7 2005/03/22 14:11:55 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -45,6 +45,10 @@ optionlist redirect_router_options[] = {
       (void *)offsetof(redirect_router_options_block, bit_options) },
   { "forbid_file",        opt_bool,
       (void *)offsetof(redirect_router_options_block, forbid_file) },
+  #ifdef EXPAND_DLFUNC
+  { "forbid_filter_dlfunc", opt_bit | (RDON_DLFUNC << 16),
+      (void *)offsetof(redirect_router_options_block, bit_options) },
+  #endif
   { "forbid_filter_existstest",  opt_bit | (RDON_EXISTS << 16),
       (void *)offsetof(redirect_router_options_block, bit_options) },
   { "forbid_filter_logwrite",opt_bit | (RDON_LOG << 16),