.section "Dynamically loaded module support" "SECTdynamicmodules"
.cindex "lookup modules"
.cindex "router modules"
+.cindex "transport modules"
.cindex "dynamic modules"
.cindex ".so building"
On some platforms, Exim supports not compiling all lookup types directly into
Most, but not all, lookup types can be built this way.
.new
-Similarly, router drivers can be built as external modules.
+Similarly, router and transport drivers can be built as external modules.
This permits a smaller exim binary, growing only as needed for the
runtime cofiguration.
.wen
3. Events smtp:fail:protocol and smtp:fail:syntax
- 4. JSON lookup support, and all the router driver except manualroute,
- can now be built as lodable modules
+ 4. JSON lookup support, all the router drivers except manualroute, and all the transport
+ drivers except smtp can now be built as lodable modules
Version 4.98
------------
LC_ALL=C
export LC_ALL
+set -e
# First off, get the OS type, and check that there is a make file for it.
cp ../src/lookups/Makefile $look_mf_pre
../scripts/lookups-Makefile
-class="routers"
-cp ../src/$class/Makefile $class/Makefile.predynamic
-../scripts/$class-Makefile
-mv routers/Makefile.postdynamic $class/Makefile
-rm $class/Makefile.predynamic
-class=
+while read class classdef names
+do
+ cp ../src/$class/Makefile $class/Makefile.predynamic
+ CLASS=$class CLASSDEF=$classdef DRNAMES="$names" ../scripts/drivers-Makefile
+ mv $class/Makefile.postdynamic $class/Makefile
+ rm $class/Makefile.predynamic
+done <<-END
+ routers ROUTER ACCEPT DNSLOOKUP IPLITERAL IPLOOKUP MANUALROUTE QUERYPROGRAM REDIRECT
+ transports TRANSPORT APPENDFILE AUTOREPLY LMTP PIPE QUEUEFILE SMTP
+END
# 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,
d="transports"
mkdir $d
cd $d
-for f in README Makefile appendfile.h appendfile.c autoreply.h \
+# Makefile is generated
+for f in README appendfile.h appendfile.c autoreply.h \
autoreply.c lmtp.h lmtp.c pipe.h pipe.c queuefile.c queuefile.h \
smtp.h smtp.c smtp_socks.c tf_maildir.c tf_maildir.h
do
--- /dev/null
+#! /bin/sh
+
+# Copyright (c) The Exim Maintainers 1995 - 2024
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+set -e
+class=${CLASS:?}
+classdef=${CLASSDEF:?}
+drnames="${DRNAMES:?}"
+
+# We turn the configure-built build-$foo/$class/Makefile.predynamic into Makefile.
+# This is used for router and transport drivers, called from scripts/Configure-Makefile.
+
+# We always re-exec ourselves at least once, because it's the cleanest and
+# most portable way to turn on various features we expect of POSIX sh.
+if [ -z "$EXIM_DRIVER_MAKEFILE_ADJUSTED" ]
+then
+ SHELL=/bin/sh
+ EXIM_DRIVER_MAKEFILE_ADJUSTED=yes
+ export EXIM_DRIVER_MAKEFILE_ADJUSTED
+
+ # Solaris sh and tr are problematic until we get xpg4 variants
+ if [ -x /usr/xpg4/bin/sh ]
+ then
+ PATH="/usr/xpg4/bin:$PATH"
+ export PATH
+ SHELL=/usr/xpg4/bin/sh
+ export SHELL
+ fi
+
+ # IRIX uses /bin/ksh for sh but in a compatibility mode unless $_XPG == 1,
+ # where said compatibility mode disables $(...)
+ _XPG=1
+ export _XPG
+
+ # We need the _right_ tr, so must do that first; but if a shell which
+ # we're more confident is sane is available, let's try that. Mostly,
+ # the problem is that "local" is not actually in "the" standard, it's
+ # just in every not-insane shell. Though arguably, there are no shells
+ # with POSIX-ish syntax which qualify as "not insane".
+ for b in /bin/dash /bin/bash /usr/local/bin/bash
+ do
+ if [ -x "$b" ]
+ then
+ SHELL="$b"
+ break
+ fi
+ done
+ # if we get a report of a system with zsh but not bash, we can add that
+ # to the list, but be sure to enable sh_word_split in that case.
+
+ exec "$SHELL" "$0" "$@"
+fi
+
+input=$class/Makefile.predynamic
+target=$class/Makefile.postdynamic
+defs_source=Makefile-t
+tag_marker='MAGIC-TAG-MODS-OBJ-RULES-GO-HERE'
+
+tab=' '
+
+# We rely on tr(1) for translating case below. Some people export
+# values of LC_CTYPE and LC_COLLATE which apparently break our assumptions.
+# We're a script expecting certain output based on known inputs and not dealing
+# with UTF8, so we should be safe doing this:
+LC_ALL=C
+export LC_ALL
+
+if [ -f "$defs_source" ]
+then
+ :
+ # we are happy
+else
+ echo >&2 "$0: ERROR: MISSING FILE '${defs_source}'"
+ echo >&2 "$0: SHOULD HAVE BEEN CALLED FROM scripts/Configure-Makefile"
+ exit 1
+fi
+
+# nb: do not permit leading whitespace for this, as CFLAGS_DYNAMIC is exported
+# to the lookups subdir via a line with leading whitespace which otherwise
+# matches
+if grep -q "^CFLAGS_DYNAMIC[ $tab?:]*=" "$defs_source"
+then
+ # we have a definition, we're good to go
+ echo >&2 ">>> Creating $class/Makefile for building dynamic modules"
+ enable_dynamic=yes
+else
+ echo >&2 ">>> Creating $class/Makefile without dynamic module support"
+ enable_dynamic=''
+ # We always do something now, since there should always be a lookup,
+ # and now we need to run in order to put the OBJ=$(OBJ)+ rules in. So we
+ # continue on.
+fi
+
+# For the want_ checks, we need to let the user override values from the make
+# command-line, not just check the Makefile.
+
+want_dynamic() {
+ local dyn_name="$1"
+ local re="(${classdef}|EXPERIMENTAL)_${dyn_name}[ $tab]*=[ $tab]*2"
+ env | grep -E -q "^$re"
+ if [ $? -eq 0 ]; then return 0; fi
+ grep -E -q "^[ $tab]*$re" "$defs_source"
+}
+
+want_at_all() {
+ local want_name="$1"
+ local re="(${classdef}|EXPERIMENTAL)_${want_name}[ $tab]*=[ $tab]*."
+ env | grep -E -q "^$re"
+ if [ $? -eq 0 ]; then return 0; fi
+ grep -E -q "^[ $tab]*$re" "$defs_source"
+}
+
+# The values of these variables will be emitted into the Makefile.
+
+MODS=""
+OBJ=""
+
+emit_module_rule() {
+ local name="$1"
+ local mod_name pkgconf
+ if [ "${name%:*}" = "$name" ]
+ then
+ # Square brackets are redundant but benign for POSIX compliant tr,
+ # however Solaris /usr/bin/tr requires them. Sometimes Solaris
+ # gets installed without a complete set of xpg4 tools, sigh.
+ mod_name=$(echo $name | tr [A-Z] [a-z])
+ else
+ mod_name="${name#*:}"
+ name="${name%:*}"
+ fi
+
+ if want_dynamic "$name"
+ then
+ if [ -z "$enable_dynamic" ]; then
+ echo >&2 "Missing CFLAGS_DYNAMIC prevents building dynamic $name"
+ exit 1
+ fi
+ MODS="${MODS} ${mod_name}.so"
+# pkgconf=$(grep "^${classdef}_${name}_PC" "$defs_source")
+# if [ $? -eq 0 ]; then
+# pkgconf=$(echo $pkgconf | sed 's/^.*= *//')
+# echo "${classdef}_${mod_name}_INCLUDE = $(pkg-config --cflags $pkgconf)"
+# echo "${classdef}_${mod_name}_LIBS = $(pkg-config --libs $pkgconf)"
+# else
+# grep "^${classdef}_${name}_" "$defs_source"
+# echo "${classdef}_${mod_name}_INCLUDE = \$(${classdef}_${name}_INCLUDE)"
+# echo "${classdef}_${mod_name}_LIBS = \$(${classdef}_${name}_LIBS)"
+# fi
+ elif want_at_all "$name"
+ then
+ OBJ="${OBJ} ${mod_name}.o"
+ fi
+}
+
+rm -f "$target"
+exec 5>&1
+exec > "$target"
+
+sed -n "1,/$tag_marker/p" < "$input"
+
+for name_mod in $drnames
+do
+ emit_module_rule $name_mod
+done
+
+echo "MODS = $MODS"
+echo "OBJ = $OBJ"
+
+sed -n "/$tag_marker/,\$p" < "$input"
+
+exec >&5
+
+# Configure-Makefile will move $target into place
+
+# vim: set ft=sh sw=2 :
+++ /dev/null
-#! /bin/sh
-
-# Copyright (c) The Exim Maintainers 1995 - 2021
-# SPDX-License-Identifier: GPL-2.0-or-later
-
-# We turn the configure-built build-$foo/routers/Makefile.predynamic into Makefile
-
-# We always re-exec ourselves at least once, because it's the cleanest and
-# most portable way to turn on various features we expect of POSIX sh.
-if [ -z "$EXIM_ROUTER_MAKEFILE_ADJUSTED" ]
-then
- SHELL=/bin/sh
- EXIM_ROUTER_MAKEFILE_ADJUSTED=yes
- export EXIM_ROUTER_MAKEFILE_ADJUSTED
-
- # Solaris sh and tr are problematic until we get xpg4 variants
- if [ -x /usr/xpg4/bin/sh ]
- then
- PATH="/usr/xpg4/bin:$PATH"
- export PATH
- SHELL=/usr/xpg4/bin/sh
- export SHELL
- fi
-
- # IRIX uses /bin/ksh for sh but in a compatibility mode unless $_XPG == 1,
- # where said compatibility mode disables $(...)
- _XPG=1
- export _XPG
-
- # We need the _right_ tr, so must do that first; but if a shell which
- # we're more confident is sane is available, let's try that. Mostly,
- # the problem is that "local" is not actually in "the" standard, it's
- # just in every not-insane shell. Though arguably, there are no shells
- # with POSIX-ish syntax which qualify as "not insane".
- for b in /bin/dash /bin/bash /usr/local/bin/bash
- do
- if [ -x "$b" ]
- then
- SHELL="$b"
- break
- fi
- done
- # if we get a report of a system with zsh but not bash, we can add that
- # to the list, but be sure to enable sh_word_split in that case.
-
- exec "$SHELL" "$0" "$@"
-fi
-
-input=routers/Makefile.predynamic
-target=routers/Makefile.postdynamic
-defs_source=Makefile-t
-tag_marker='MAGIC-TAG-MODS-OBJ-RULES-GO-HERE'
-
-tab=' '
-
-# We rely on tr(1) for translating case below. Some people export
-# values of LC_CTYPE and LC_COLLATE which apparently break our assumptions.
-# We're a script expecting certain output based on known inputs and not dealing
-# with UTF8, so we should be safe doing this:
-LC_ALL=C
-export LC_ALL
-
-if [ -f "$defs_source" ]
-then
- :
- # we are happy
-else
- echo >&2 "$0: ERROR: MISSING FILE '${defs_source}'"
- echo >&2 "$0: SHOULD HAVE BEEN CALLED FROM scripts/Configure-Makefile"
- exit 1
-fi
-
-# nb: do not permit leading whitespace for this, as CFLAGS_DYNAMIC is exported
-# to the lookups subdir via a line with leading whitespace which otherwise
-# matches
-if grep -q "^CFLAGS_DYNAMIC[ $tab?:]*=" "$defs_source"
-then
- # we have a definition, we're good to go
- echo >&2 ">>> Creating routers/Makefile for building dynamic modules"
- enable_dynamic=yes
-else
- echo >&2 ">>> Creating routers/Makefile without dynamic module support"
- enable_dynamic=''
- # We always do something now, since there should always be a lookup,
- # and now we need to run in order to put the OBJ=$(OBJ)+ rules in. So we
- # continue on.
-fi
-
-# For the want_ checks, we need to let the user override values from the make
-# command-line, not just check the Makefile.
-
-want_dynamic() {
- local dyn_name="$1"
- local re="ROUTER_${dyn_name}[ $tab]*=[ $tab]*2"
- env | grep -q "^$re"
- if [ $? -eq 0 ]; then return 0; fi
- grep -q "^[ $tab]*$re" "$defs_source"
-}
-
-want_at_all() {
- local want_name="$1"
- local re="ROUTER_${want_name}[ $tab]*=[ $tab]*."
- env | grep -q "^$re"
- if [ $? -eq 0 ]; then return 0; fi
- grep -q "^[ $tab]*$re" "$defs_source"
-}
-
-# Adapted want_at_all above to work for EXPERIMENTAL features
-want_experimental() {
- local want_name="$1"
- local re="EXPERIMENTAL_${want_name}[ $tab]*=[ $tab]*."
- env | grep -q "^$re"
- if [ $? -eq 0 ]; then return 0; fi
- grep -q "^[ $tab]*$re" "$defs_source"
-}
-
-# The values of these variables will be emitted into the Makefile.
-
-MODS=""
-OBJ=""
-
-emit_module_rule() {
- local name="$1"
- local mod_name pkgconf
- if [ "${name%:*}" = "$name" ]
- then
- # Square brackets are redundant but benign for POSIX compliant tr,
- # however Solaris /usr/bin/tr requires them. Sometimes Solaris
- # gets installed without a complete set of xpg4 tools, sigh.
- mod_name=$(echo $name | tr [A-Z] [a-z])
- else
- mod_name="${name#*:}"
- name="${name%:*}"
- fi
-
- if want_dynamic "$name"
- then
- if [ -z "$enable_dynamic" ]; then
- echo >&2 "Missing CFLAGS_DYNAMIC prevents building dynamic $name"
- exit 1
- fi
- MODS="${MODS} ${mod_name}.so"
-# pkgconf=$(grep "^ROUTER_${name}_PC" "$defs_source")
-# if [ $? -eq 0 ]; then
-# pkgconf=$(echo $pkgconf | sed 's/^.*= *//')
-# echo "ROUTER_${mod_name}_INCLUDE = $(pkg-config --cflags $pkgconf)"
-# echo "ROUTER_${mod_name}_LIBS = $(pkg-config --libs $pkgconf)"
-# else
-# grep "^ROUTER_${name}_" "$defs_source"
-# echo "ROUTER_${mod_name}_INCLUDE = \$(ROUTER_${name}_INCLUDE)"
-# echo "ROUTER_${mod_name}_LIBS = \$(ROUTER_${name}_LIBS)"
-# fi
- elif want_at_all "$name"
- then
- OBJ="${OBJ} ${mod_name}.o"
- fi
-}
-
-rm -f "$target"
-exec 5>&1
-exec > "$target"
-
-sed -n "1,/$tag_marker/p" < "$input"
-
-for name_mod in \
- ACCEPT DNSLOOKUP IPLITERAL IPLOOKUP MANUALROUTE QUERYPROGRAM REDIRECT
-do
- emit_module_rule $name_mod
-done
-
-echo "MODS = $MODS"
-echo "OBJ = $OBJ"
-
-sed -n "/$tag_marker/,\$p" < "$input"
-
-exec >&5
-
-# Configure-Makefile will move $target into place
-
-# vim: set ft=sh sw=2 :
# file. By commenting out those you know you don't want to use, you can make
# the binary a bit smaller. If you are unsure, leave all of these included for
# now.
+#
+# If set to "2" instead of "yes" then the corresponding driver will be
+# built as a module and must be installed into LOOKUP_MODULE_DIR (the name
+# is historic).
+# 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 CFLAGS_DYNAIC and LOOKUP_MODULE_DIR below so the builds are done right,
+# and so the exim binary actually loads dynamic lookup modules.
+# The smtp transport cannot be built as a module.
TRANSPORT_APPENDFILE=yes
TRANSPORT_AUTOREPLY=yes
#include "routers/rf_functions.h"
-#ifdef TRANSPORT_APPENDFILE
-# include "transports/appendfile.h"
-#endif
-
-#ifdef TRANSPORT_AUTOREPLY
-# include "transports/autoreply.h"
-#endif
-
-#ifdef TRANSPORT_LMTP
-# include "transports/lmtp.h"
-#endif
-
-#ifdef TRANSPORT_PIPE
-# include "transports/pipe.h"
-#endif
-
-#ifdef EXPERIMENTAL_QUEUEFILE
-# include "transports/queuefile.h"
-#endif
-
-#ifdef TRANSPORT_SMTP
-# include "transports/smtp.h"
-#endif
-
router_info * routers_available = NULL;
+transport_info * transports_available = NULL;
-transport_info * transports_available_newlist = NULL;
-transport_info transports_available_oldarray[] = {
-#ifdef TRANSPORT_APPENDFILE
- {
- .drinfo = {
- .driver_name = US"appendfile",
- .options = appendfile_transport_options,
- .options_count = &appendfile_transport_options_count,
- .options_block = &appendfile_transport_option_defaults, /* private options defaults */
- .options_len = sizeof(appendfile_transport_options_block),
- .init = appendfile_transport_init,
- },
- .code = appendfile_transport_entry,
- .tidyup = NULL,
- .closedown = NULL,
- .local = TRUE
- },
-#endif
-#ifdef TRANSPORT_AUTOREPLY
- {
- .drinfo = {
- .driver_name = US"autoreply",
- .options = autoreply_transport_options,
- .options_count = &autoreply_transport_options_count,
- .options_block = &autoreply_transport_option_defaults,
- .options_len = sizeof(autoreply_transport_options_block),
- .init = autoreply_transport_init,
- },
- .code = autoreply_transport_entry,
- .tidyup = NULL,
- .closedown = NULL,
- .local = TRUE
- },
-#endif
-#ifdef TRANSPORT_LMTP
- {
- .drinfo = {
- .driver_name = US"lmtp",
- .options = lmtp_transport_options,
- .options_count = &lmtp_transport_options_count,
- .options_block = &lmtp_transport_option_defaults,
- .options_len = sizeof(lmtp_transport_options_block),
- .init = lmtp_transport_init,
- },
- .code = lmtp_transport_entry,
- .tidyup = NULL,
- .closedown = NULL,
- .local = TRUE
- },
-#endif
-#ifdef TRANSPORT_PIPE
- {
- .drinfo = {
- .driver_name = US"pipe",
- .options = pipe_transport_options,
- .options_count = &pipe_transport_options_count,
- .options_block = &pipe_transport_option_defaults,
- .options_len = sizeof(pipe_transport_options_block),
- .init = pipe_transport_init,
- },
- .code = pipe_transport_entry,
- .tidyup = NULL,
- .closedown = NULL,
- .local = TRUE
- },
-#endif
-#ifdef EXPERIMENTAL_QUEUEFILE
- {
- .drinfo = {
- .driver_name = US"queuefile",
- .options = queuefile_transport_options,
- .options_count = &queuefile_transport_options_count,
- .options_block = &queuefile_transport_option_defaults,
- .options_len = sizeof(queuefile_transport_options_block),
- .init = queuefile_transport_init,
- },
- .code = queuefile_transport_entry,
- .tidyup = NULL,
- .closedown = NULL,
- .local = TRUE
- },
-#endif
-#ifdef TRANSPORT_SMTP
- {
- .drinfo = {
- .driver_name = US"smtp",
- .options = smtp_transport_options,
- .options_count = &smtp_transport_options_count,
- .options_block = &smtp_transport_option_defaults,
- .options_len = sizeof(smtp_transport_options_block),
- .init = smtp_transport_init,
- },
- .code = smtp_transport_entry,
- .tidyup = NULL,
- .closedown = smtp_transport_closedown,
- .local = FALSE
- },
-#endif
- { .drinfo = { .driver_name = US"" }}
-};
#ifndef MACRO_PREDEF
gstring *
transport_show_supported(gstring * g)
{
-g = string_cat(g, US"Transports:");
-#ifdef TRANSPORT_APPENDFILE
- g = string_cat(g, US" appendfile");
- #ifdef SUPPORT_MAILDIR
- g = string_cat(g, US"/maildir"); /* damn these subclasses */
- #endif
- #ifdef SUPPORT_MAILSTORE
- g = string_cat(g, US"/mailstore");
- #endif
- #ifdef SUPPORT_MBX
- g = string_cat(g, US"/mbx");
- #endif
-#endif
-#ifdef TRANSPORT_AUTOREPLY
- g = string_cat(g, US" autoreply");
-#endif
-#ifdef TRANSPORT_LMTP
- g = string_cat(g, US" lmtp");
-#endif
-#ifdef TRANSPORT_PIPE
- g = string_cat(g, US" pipe");
-#endif
-#ifdef EXPERIMENTAL_QUEUEFILE
- g = string_cat(g, US" queuefile");
-#endif
-#ifdef TRANSPORT_SMTP
- g = string_cat(g, US" smtp");
+uschar * b = US"" /* static-build transportnames */
+#if defined(TRANSPORT_APPENDFILE) && TRANSPORT_APPENDFILE!=2
+ " appendfile"
+# ifdef SUPPORT_MAILDIR
+ "/maildir"
+# endif
+# ifdef SUPPORT_MAILSTORE
+ "/mailstore"
+# endif
+# ifdef SUPPORT_MBX
+ "/mbx"
+# endif
+#endif
+#if defined(TRANSPORT_AUTOREPLY) && TRANSPORT_AUTOREPLY!=2
+ " autoreply"
+#endif
+#if defined(TRANSPORT_LMTP) && TRANSPORT_LMTP!=2
+ " lmtp"
+#endif
+#if defined(TRANSPORT_PIPE) && TRANSPORT_PIPE!=2
+ " pipe"
+#endif
+#if defined(EXPERIMENTAL_QUEUEFILE) && EXPERIMENTAL_QUEUEFILE!=2
+ " queuefile"
+#endif
+#if defined(TRANSPORT_SMTP) && TRANSPORT_SMTP!=2
+ " smtp"
#endif
-return string_cat(g, US"\n");
+ ;
+
+uschar * d = US"" /* dynamic-module transportnames */
+#if defined(TRANSPORT_APPENDFILE) && TRANSPORT_APPENDFILE==2
+ " appendfile"
+# ifdef SUPPORT_MAILDIR
+ "/maildir"
+# endif
+# ifdef SUPPORT_MAILSTORE
+ "/mailstore"
+# endif
+# ifdef SUPPORT_MBX
+ "/mbx"
+# endif
+#endif
+#if defined(TRANSPORT_AUTOREPLY) && TRANSPORT_AUTOREPLY==2
+ " autoreply"
+#endif
+#if defined(TRANSPORT_LMTP) && TRANSPORT_LMTP==2
+ " lmtp"
+#endif
+#if defined(TRANSPORT_PIPE) && TRANSPORT_PIPE==2
+ " pipe"
+#endif
+#if defined(EXPERIMENTAL_QUEUEFILE) && EXPERIMENTAL_QUEUEFILE==2
+ " queuefile"
+#endif
+#if defined(TRANSPORT_SMTP) && TRANSPORT_SMTP==2
+ " smtp"
+#endif
+ ;
+
+if (*b) g = string_fmt_append(g, "Transports (built-in):%s\n", b);
+if (*d) g = string_fmt_append(g, "Transports (dynamic): %s\n", d);
+return g;
}
extern const uschar **transport_filter_argv; /* For on-the-fly filtering */
extern int transport_filter_timeout; /* Timeout for same */
-extern transport_info transports_available_oldarray[]; /* Vector of available transports */
-extern transport_info * transports_available_newlist;
-extern transport_instance *transports; /* Chain of instantiated transports */
-extern transport_instance transport_defaults; /* Default values */
+extern transport_info * transports_available; /* Listof available transports */
+extern transport_instance *transports; /* Chain of instantiated transports */
+extern transport_instance transport_defaults; /* Default values */
extern int transport_write_timeout;/* Set to time out individual writes */
void
route_init(void)
{
-
int old_pool = store_pool;
store_pool = POOL_PERM;
{
# nb: at build time, the version of this file used will have had some
# extra variable definitions and prepended to it and module build rules
-# interpolated below. This is done by scripts/routers-Makefile.
+# interpolated below. This is done by scripts/drivers-Makefile.
# MAGIC-TAG-MODS-OBJ-RULES-GO-HERE
options_from_list(optionlist_transports, nelem(optionlist_transports), US"TRANSPORTS", NULL);
-//for (transport_info * ti= transports_available; ti->drinfo.driver_name[0]; ti++)
-for (driver_info * di= (driver_info *)transports_available_newlist; di; di = di->next)
+for (driver_info * di= (driver_info *)transports_available; di; di = di->next)
{
spf(buf, sizeof(buf), US"_DRIVER_TRANSPORT_%T", di->driver_name);
builtin_macro_create(buf);
void
transport_init(void)
{
-for (transport_info * tblent = transports_available_oldarray;
- *tblent->drinfo.driver_name; tblent++)
+int old_pool = store_pool;
+store_pool = POOL_PERM;
{
- driver_info * listent = store_get(sizeof(transport_info), tblent);
- memcpy(listent, tblent, sizeof(transport_info));
- listent->next = (driver_info *)transports_available_newlist;
- transports_available_newlist = (transport_info *)listent;
+ driver_info ** anchor = (driver_info **) &transports_available;
+ extern transport_info appendfile_transport_info;
+ extern transport_info autoreply_transport_info;
+ extern transport_info lmtp_transport_info;
+ extern transport_info pipe_transport_info;
+ extern transport_info queuefile_transport_info;
+ extern transport_info smtp_transport_info;
+
+ /* Add the transport drivers that are built for static linkage to the
+ list of availables. */
+
+#if defined(TRANSPORT_APPENDFILE) && TRANSPORT_APPENDFILE!=2
+ add_driver_info(anchor, &appendfile_transport_info.drinfo, sizeof(transport_info));
+#endif
+#if defined(TRANSPORT_AUTOREPLY) && TRANSPORT_AUTOREPLY!=2
+ add_driver_info(anchor, &autoreply_transport_info.drinfo, sizeof(transport_info));
+#endif
+#if defined(TRANSPORT_LMTP) && TRANSPORT_LMTP!=2
+ add_driver_info(anchor, &lmtp_transport_info.drinfo, sizeof(transport_info));
+#endif
+#if defined(TRANSPORT_PIPE) && TRANSPORT_PIPE!=2
+ add_driver_info(anchor, &pipe_transport_info.drinfo, sizeof(transport_info));
+#endif
+#if defined(EXPERIMENTAL_QUEUEFILE) && EXPERIMENTAL_QUEUEFILE!=2
+ add_driver_info(anchor, &queuefile_transport_info.drinfo, sizeof(transport_info));
+#endif
+#if defined(TRANSPORT_SMTP) && TRANSPORT_SMTP!=2
+ add_driver_info(anchor, &smtp_transport_info.drinfo, sizeof(transport_info));
+#endif
}
+store_pool = old_pool;
+
+/* Read the config file "transports" section, creating a transportsinstance list.
+For any yet-undiscovered driver, check for a loadable module and add it to
+those available. */
readconf_driver_init((driver_instance **)&transports, /* chain anchor */
- (driver_info **)&transports_available_newlist, /* available drivers */
- sizeof(transport_info), /* size of info block */
- &transport_defaults, /* default values for generic options */
- sizeof(transport_instance), /* size of instance block */
- optionlist_transports, /* generic options */
+ (driver_info **)&transports_available, /* available drivers */
+ sizeof(transport_info), /* size of info block */
+ &transport_defaults, /* default values for generic options */
+ sizeof(transport_instance), /* size of instance block */
+ optionlist_transports, /* generic options */
optionlist_transports_size,
US"transport");
# Make file for building a library containing all the available transports and
# calling it transports.a. This is called from the main make file, after cd'ing
# to the transports subdirectory.
+#
+# Copyright (c) The Exim Maintainers 2021 - 2024
-OBJ = appendfile.o autoreply.o lmtp.o pipe.o queuefile.o smtp.o smtp_socks.o tf_maildir.o
+# nb: at build time, the version of this file used will have had some
+# extra variable definitions and prepended to it and module build rules
+# interpolated below. This is done by scripts/drivers-Makefile.
+
+# MAGIC-TAG-MODS-OBJ-RULES-GO-HERE
+
+all: transports.a $(MODS)
transports.a: $(OBJ)
@$(RM_COMMAND) -f transports.a
@$(AR) transports.a $(OBJ)
$(RANLIB) $@
-.SUFFIXES: .o .c
+.SUFFIXES: .o .c .so
.c.o:; @echo "$(CC) $*.c"
$(FE)$(CC) -c $(CFLAGS) $(INCLUDE) $*.c
-appendfile.o: $(HDRS) appendfile.c appendfile.h tf_maildir.h
-autoreply.o: $(HDRS) autoreply.c autoreply.h
-lmtp.o: $(HDRS) lmtp.c lmtp.h
-pipe.o: $(HDRS) pipe.c pipe.h
-queuefile.o: $(HDRS) queuefile.c queuefile.h
-smtp.o: $(HDRS) smtp.c smtp.h
-smtp_socks.o: $(HDRS) smtp_socks.c smtp.h
+.c.so:; @echo "$(CC) -shared $*.c"
+ $(FE)$(CC) -DDYNLOOKUP $(CFLAGS_DYNAMIC) $(CFLAGS) $(INCLUDE) $(DLFLAGS) $*.c -o $@
+
+
+$(OBJ) $(MOD): $(HDRS)
+
+autoreply.o autoreply.so: autoreply.c autoreply.h
+lmtp.o lmtp.so: lmtp.c lmtp.h
+pipe.o pipe.so: pipe.c pipe.h
+queuefile.o queuefile.so: queuefile.c queuefile.h
+
+
+# These ones depend on more than one .c source
+
+appendfile.o: appendfile.c appendfile.h tf_maildir.c tf_maildir.h
+ @echo "$(CC) appendfile.c tf_maildir.c"
+ $(FE)$(CC) $(CFLAGS) $(INCLUDE) appendfile.c tf_maildir.c -r -o $@
+
+appendfile.so: appendfile.c appendfile.h tf_maildir.c tf_maildir.h
+ @echo "$(CC) -shared appendfile.c tf_maildir.c"
+ $(FE)$(CC) -DDYNLOOKUP $(CFLAGS_DYNAMIC) $(CFLAGS) $(INCLUDE) $(DLFLAGS) \
+ appendfile.c tf_maildir.c -o $@
+
+smtp.o: smtp.c smtp_socks.c smtp.h
+ @echo "$(CC) smtp.c smtp_socks.c"
+ $(FE)$(CC) $(CFLAGS) $(INCLUDE) smtp.c smtp_socks.c -r -o $@
-tf_maildir.o: $(HDRS) tf_maildir.c tf_maildir.h appendfile.h
+smtp.so: smtp.c smtp_socks.c smtp.h
+ @echo "$(CC) -shared smtp.c smtp_socks.c"
+ $(FE)$(CC) -DDYNLOOKUP $(CFLAGS_DYNAMIC) $(CFLAGS) $(INCLUDE) $(DLFLAGS) \
+ smtp.c smtp_socks.c -o $@
# End
return FALSE;
}
+
+
+
+# ifdef DYNLOOKUP
+# define appendfile_transport_info _transport_info
+# endif
+
+transport_info appendfile_transport_info = {
+.drinfo = {
+ .driver_name = US"appendfile",
+ .options = appendfile_transport_options,
+ .options_count = &appendfile_transport_options_count,
+ .options_block = &appendfile_transport_option_defaults, /* private options defaults */
+ .options_len = sizeof(appendfile_transport_options_block),
+ .init = appendfile_transport_init,
+# ifdef DYNLOOKUP
+ .dyn_magic = TRANSPORT_MAGIC,
+# endif
+ },
+.code = appendfile_transport_entry,
+.tidyup = NULL,
+.closedown = NULL,
+.local = TRUE
+};
+
#endif /*!MACRO_PREDEF*/
#endif /*TRANSPORT_APPENDFILE*/
/* End of transport/appendfile.c */
return FALSE;
}
+
+
+
+# ifdef DYNLOOKUP
+# define autoreply_transport_info _transport_info
+# endif
+
+transport_info autoreply_transport_info = {
+.drinfo = {
+ .driver_name = US"autoreply",
+ .options = autoreply_transport_options,
+ .options_count = &autoreply_transport_options_count,
+ .options_block = &autoreply_transport_option_defaults,
+ .options_len = sizeof(autoreply_transport_options_block),
+ .init = autoreply_transport_init,
+# ifdef DYNLOOKUP
+ .dyn_magic = TRANSPORT_MAGIC,
+# endif
+ },
+.code = autoreply_transport_entry,
+.tidyup = NULL,
+.closedown = NULL,
+.local = TRUE
+};
+
#endif /*!MACRO_PREDEF*/
#endif /*TRANSPORT_AUTOREPOL*/
/* End of transport/autoreply.c */
return FALSE;
}
+
+
+
+# ifdef DYNLOOKUP
+# define lmtp_transport_info _transport_info
+# endif
+
+transport_info lmtp_transport_info = {
+.drinfo = {
+ .driver_name = US"lmtp",
+ .options = lmtp_transport_options,
+ .options_count = &lmtp_transport_options_count,
+ .options_block = &lmtp_transport_option_defaults,
+ .options_len = sizeof(lmtp_transport_options_block),
+ .init = lmtp_transport_init,
+# ifdef DYNLOOKUP
+ .dyn_magic = TRANSPORT_MAGIC,
+# endif
+ },
+.code = lmtp_transport_entry,
+.tidyup = NULL,
+.closedown = NULL,
+.local = TRUE
+};
+
#endif /*!MACRO_PREDEF*/
#endif /*TRANSPORT_LMTP*/
/* End of transport/lmtp.c */
return FALSE;
}
+
+
+
+# ifdef DYNLOOKUP
+# define pipe_transport_info _transport_info
+# endif
+
+transport_info pipe_transport_info = {
+.drinfo = {
+ .driver_name = US"pipe",
+ .options = pipe_transport_options,
+ .options_count = &pipe_transport_options_count,
+ .options_block = &pipe_transport_option_defaults,
+ .options_len = sizeof(pipe_transport_options_block),
+ .init = pipe_transport_init,
+# ifdef DYNLOOKUP
+ .dyn_magic = TRANSPORT_MAGIC,
+# endif
+ },
+.code = pipe_transport_entry,
+.tidyup = NULL,
+.closedown = NULL,
+.local = TRUE
+};
+
#endif /*!MACRO_PREDEF*/
#endif /*TRASPORT_PIPE*/
/* End of transport/pipe.c */
return FALSE;
}
+
+
+
+# ifdef DYNLOOKUP
+# define queuefile_transport_info _transport_info
+# endif
+
+transport_info queuefile_transport_info = {
+.drinfo = {
+ .driver_name = US"queuefile",
+ .options = queuefile_transport_options,
+ .options_count = &queuefile_transport_options_count,
+ .options_block = &queuefile_transport_option_defaults,
+ .options_len = sizeof(queuefile_transport_options_block),
+ .init = queuefile_transport_init,
+# ifdef DYNLOOKUP
+ .dyn_magic = TRANSPORT_MAGIC,
+# endif
+ },
+.code = queuefile_transport_entry,
+.tidyup = NULL,
+.closedown = NULL,
+.local = TRUE
+};
+
#endif /*!MACRO_PREDEF*/
#endif /*EXPERIMENTAL_QUEUEFILE*/
return TRUE; /* Each address has its status */
}
+
+
+
+# ifdef DYNLOOKUP
+# define smtp_transport_info _transport_info
+# endif
+
+transport_info smtp_transport_info = {
+.drinfo = {
+ .driver_name = US"smtp",
+ .options = smtp_transport_options,
+ .options_count = &smtp_transport_options_count,
+ .options_block = &smtp_transport_option_defaults,
+ .options_len = sizeof(smtp_transport_options_block),
+ .init = smtp_transport_init,
+# ifdef DYNLOOKUP
+ .dyn_magic = TRANSPORT_MAGIC,
+# endif
+ },
+.code = smtp_transport_entry,
+.tidyup = NULL,
+.closedown = smtp_transport_closedown,
+.local = FALSE
+};
+
#endif /*!MACRO_PREDEF*/
/* vi: aw ai sw=2
*/
keep_environment =
begin routers
+begin transports
# End
| Lookups(?:\(built-in\))?:
| Support\ for:
| Routers\ \((?:built-in|dynamic)\):
- | Transports:
+ | Transports\ \((?:built-in|dynamic)\):
| Malware:
| log\ selectors\ =
| cwd=
print;
@temp = split /(\s+)/, $1;
push(@temp, ' ');
- my %temp_routers= @temp;
+ my %temp_routers = @temp;
@parm_routers{keys %temp_routers} = values %temp_routers;
}
# that the basic transport name is set, and then the name with each of the
# options.
- elsif (/^Transports: (.*)/)
+ elsif (/^Transports \((?:built-in|dynamic)\): (.*)/)
{
print;
@temp = split /(\s+)/, $1;
my($i,$k);
push(@temp, ' ');
- %parm_transports = @temp;
+ my %temp_transports = @temp;
+ @parm_transports{keys %temp_transports} = values %temp_transports;
+
foreach $k (keys %parm_transports)
{
if ($k =~ "/")