[exim-cvs] Retire Exim 3 up-conversion scripts and docs

Αρχική Σελίδα
Delete this message
Reply to this message
Συντάκτης: Exim Git Commits Mailing List
Ημερομηνία:  
Προς: exim-cvs
Αντικείμενο: [exim-cvs] Retire Exim 3 up-conversion scripts and docs
Gitweb: https://git.exim.org/exim.git/commitdiff/56ed4f42c83f576badd797a6ec6ba81ad73166ea
Commit:     56ed4f42c83f576badd797a6ec6ba81ad73166ea
Parent:     c7ff32cf0e6d2089261b223012aa8fdc3ed37933
Author:     Jeremy Harris <jgh146exb@???>
AuthorDate: Tue Jul 23 12:36:19 2024 +0100
Committer:  Jeremy Harris <jgh146exb@???>
CommitDate: Tue Jul 23 13:22:27 2024 +0100


    Retire Exim 3 up-conversion scripts and docs
---
 doc/doc-txt/ChangeLog     |    3 +
 doc/doc-txt/Exim3.upgrade |  671 ------------
 doc/doc-txt/Exim4.upgrade | 1734 -------------------------------
 src/OS/Makefile-Base      |   27 +-
 src/README                |    2 +-
 src/src/convert4r3.src    | 1382 -------------------------
 src/src/convert4r4.src    | 2527 ---------------------------------------------
 7 files changed, 5 insertions(+), 6341 deletions(-)


diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog
index abf90ca1f..2a7a70c47 100644
--- a/doc/doc-txt/ChangeLog
+++ b/doc/doc-txt/ChangeLog
@@ -19,6 +19,9 @@ JH/02 Add transaction support for hintsdbs. The providers supported are tdb and
 JH/03 With dkim_verify_minimal, avoid calling the DKIM ACL after the first
       good verify.


+JH/04 Remove the docs and support scripts dealing with conversion of Exim
+      version 3 installations.
+
 Exim version 4.98
 -----------------


diff --git a/doc/doc-txt/Exim3.upgrade b/doc/doc-txt/Exim3.upgrade
deleted file mode 100644
index 4ab94c4e9..000000000
--- a/doc/doc-txt/Exim3.upgrade
+++ /dev/null
@@ -1,671 +0,0 @@
-This document contains information about upgrading Exim to the last of the 3.xx
-releases. It is provided to help anybody who is upgrading to release 4.xx from
-a release that is earlier than 3.33. It goes back as far as release 2.12. If
-you are upgrading to release 4.xx from an even earlier release, it is probably
-best to start again from the default configuration.
-
-
-Upgrading from release 3.16
----------------------------
-
-1. The way LDAP returns values for multiple attributes has been changed to be
-the same as the NIS+ lookup.
-
-If you specify multiple attributes, they are returned as space-separated
-strings, quoted if necessary.
-
-e.g.   ldap:///o=base?attr1,attr2?sub?(uid=fred)
-
-       used to give:    attr1=value one, attr2=value2
-       now gives:       attr1="value one" attr2=value2
-
-If you don't specify any attributes in the search, you now get them in
-the tagged format as well.
-
-e.g.   ldap:///o=base??sub?(uid=fred)
-
-       used to give:    top, value one, value2
-       now gives:       objectClass=top attr1="value one" attr2=value2
-
-The reason for these changes is so that the results can be safely parsed -
-in fact, the existing ${extract{key}{val}} function does this nicely.
-This in turn allows a single LDAP query to be reused - one query can return
-the destination delivery address, the quota, and so forth.
-
-This is NOT a backwards compatible change, so there is a compile-time option
-to reverse it in the src/lookups/ldap.c module, for use in emergency. But it is
-not thought that the old behaviour was particularly useful as it stood, because
-a field that contained ',' or '=' would make the result unparseable.
-
-In the common case where you explicitly ask for a single attribute in your
-LDAP query, the behaviour is unchanged - the result is not quoted, and if there
-are multiple values they are comma-separated.
-
-2. The hosts_max_try option in the smtp transport limits the number of IP
-addresses that will actually be tried during one delivery attempt. The default
-is 5. Previously, all available addresses were tried.
-
-3. The extension of the "extract" expansion item has resulted in a change to
-the way Exim decides between the keyed form and the numeric form. If the first
-argument consists entirely of digits, the numeric form is assumed. This means
-that it is impossible to have keys that are digit strings, without manipulating
-the data first (e.g. by using ${sg} to add a letter to each key).
-
-
-Upgrading from release 3.15
----------------------------
-
-1. The handling of "freeze" and "fail" in system filter files has changed.
-Previously, any deliveries set up by a filter that ended with "freeze" or
-"fail" were discarded. This no longer happens; such deliveries are honoured.
-A consequence of this is that first_delivery becomes false after freezing in a
-system filter; previously it remained true until a real delivery attempt
-happened.
-
-
-Upgrading from release 3.13
----------------------------
-
-1. The handling of maildir_tag has been changed (see NewStuff). There are two
-small incompatibilities: (a) Exim now inserts a leading colon only if the
-string begins with an alphanumeric character. So if you were using a string
-starting with a special character, you will have to add the leading colon to
-it to remain compatible. (b) The expansion of maildir_tag now happens after the
-file has been written, and $message_size is updated to the correct file size
-before the expansion. The tag is not used on the temporary file (it was
-previously).
-
-2. The handling of Exim's configuration has changed in two ways:
-
-  (a) Any line may be continued by ending it with a backslash. Trailing white
-  space after the backslash, and leading white space on continuation lines is
-  ignored. This means that quotes are no longer needed just to make it possible
-  to continue an option setting. The difference between quoted and non-quoted
-  strings is that quoted strings are processed for internal backslashed items
-  such as \n. The only possible incompatibility of this change is if any
-  existing configuration has a non-quoted line ended in backslash, which seems
-  a very remote possibility.
-
-  (b) All lists, with the exception of log_file_path, can now use a different
-  character to colon as the separator. This is specified by starting the list
-  with <x where x is any punctuation character. For example:
-
-    local_interfaces = <; 127.0.0.1 ; ::1
-
-  The new feature is provided to make life easier with IPv6 addresses. It is
-  recommended that its use be confined to circumstances where it really is
-  needed, and that colon be used in most cases. I don't believe this change
-  is incompatible, because I don't think any list item can legitimately begin
-  with a '<' character.
-
-3. Previously, Exim took no action to ensure that the timestamps in its log
-files were "wall clock time". If the TZ environment variable was set when Exim
-was called, it could cause strange times to be logged. For the majority of
-operating systems, I have been able to fix this problem by deleting the entire
-environment. However, this doesn't work in some systems, and a macro called
-HANDS_OFF_ENVIRONMENT is defined in their OS/os.h files to suppress the action.
-These OS are: AIX, DGUX, HP-UX, IRIX, and SCO, and their behaviour should be
-unchanged from previous releases. On any other OS, if you find you are getting
-weird timestamps, it may be that your OS needs HANDS_OFF_ENVIRONMENT.
-
-4. As a result of the change described in 3, there may be some cases where Exim
-runs an external program that previously got passed the environment, and now do
-not. This does *not* apply to the pipe transport, where the environment has
-always been set up specifically, as described in the manual.
-
-5. The way in which Exim scans its queue when split_spool_directory is set has
-changed, but this shouldn't make any noticeable difference. See doc/NewStuff
-for details.
-
-
-Upgrading from release 3.03
----------------------------
-
-The from_hack option in the appendfile and pipe transports has been replace by
-two string options, check_string and escape_string. If your configuration
-contains any references to from_hack they should be replaced. Exim continues to
-recognize from_hack as a transitional measure. If no_from_hack is specified in
-an appendfile transport, the two new options are forced to be unset. Otherwise
-the setting of from_hack is ignored.
-
-
-Upgrading from release 3.02
----------------------------
-
-The exim_dbmbuild utility has been changed to write a warning to stderr on
-encountering a duplicate key, and to return a value of 1. Formerly, it ignored
-all but the last of a set of duplicates; now it ignores all but the first, to
-make dbm-searched files behave the same way as lsearch-searched files. However,
-there is an option -lastdup which makes it behave as before. The -nowarn option
-suppresses the individual warnings, but the number of duplicates is always
-listed on stdout at the end.
-
-
-Updating from a release prior to 3.00
--------------------------------------
-
-Prior to release 3.00 a lot of options which contained lists of various kinds
-came in groups such as sender_accept, sender_reject, sender_reject_except. This
-style of configuration has been abolished. Instead, it is now possible to put
-negative entries in such lists, so that a single option is all that is
-required. In addition to this, net lists have been abolished, and instead,
-host lists can now contain items that specify networks as well as hosts. The
-names of some of these options have also been changed.
-
-As a result of these changes, most configuration files used for earlier
-versions of Exim need to be changed. The opportunity has therefore been taken
-to remove a number of other obsolete features and options.
-
-A Perl script is built in the file util/convert4r3 to assist in updating Exim
-configuration files. It reads a configuration file on the standard input,
-writes a modified file on the standard output, and writes comments about what
-it has done to the standard error file. It assumes that the input is a valid
-Exim configuration file. A typical call to the conversion script might be
-
-  util/convert4r3  </opt/exim/configure  >/opt/exim/configure.new
-
-The way the script merges an accept/reject/reject_except triple into a single
-accept option is to put the reject_except list first, followed by the reject
-list with every item negated, followed by the accept list. For example, if an
-old configuration file contains
-
-  sender_host_accept_relay        = *.c.d : e.f.g
-  sender_host_reject_relay        = *.b.c.d
-  sender_host_reject_relay_except = a.b.c.d
-
-the new configuration will contain
-
-  host_accept_relay = a.b.c.d : ! *.b.c.d : *.c.d : e.f.g
-
-The same ordering is used to merge a triple into a reject option, but this time
-the first and third sublists are negated. For example, if an old configuration
-file contains
-
-  sender_host_accept        = *.c.d : e.f.g
-  sender_host_reject        = *.b.c.d
-  sender_host_reject_except = a.b.c.d
-
-the new configuration file will contain
-
-  host_reject = ! a.b.c.d : *.b.c.d : ! *.c.d : ! e.f.g : *
-
-The output file should be checked before trying to use it. Each option change
-is preceded by an identifying comment. There are several specific things that
-you should look out for when checking:
-
-(1) If you are using macros to contain lists of items, and these have to be
-    negated in the new world, convert4r3 won't get it right. For example, if
-    the old configuration contains
-
-      ACCEPTHOSTS = *.c.d : e.f.g
-      sender_host_reject = ACCEPTHOSTS
-
-    then the rewritten configuration will be
-
-      ACCEPTHOSTS = *.c.d : e.f.g
-      host_reject = !ACCEPTHOSTS
-
-    but because this is just textual macro handling, that is equivalent to
-
-      host_reject = !*.c.d : e.f.g
-
-    which is not the correct translation, because the second item is not
-    negated. There is unfortunately no easy way to use a macro to provide a
-    list of things that are sometimes negated.
-
-(2) The conversion adds some settings of file_transport, pipe_transport, and
-    reply_transport to aliasfile and forwardfile directors. This is done
-    because the global implicit defaults for these options have been removed.
-    The default configuration now contains explicit settings, so convert4r3
-    makes these additions to be compatible with that. If your aliasfile and
-    forwardfile directors do not make use of the pipe, file, or autoreply
-    facilities, you can remove these new settings.
-
-(3) If you are using +allow_unknown in a host list which also has an exception
-    list, you may need to move +allow_unknown in the new configuration. For
-    example, if the old configuration contains
-
-      sender_host_reject = +allow_unknown : *.b.c
-      sender_host_reject_except = *.a.b.c
-
-    then the rewritten configuration will be
-
-      host_reject = ! *.a.b.c : +allow_unknown : *.b.c
-
-    Because the negated item contains a wild card, the reverse lookup for the
-    host name will occur before +allow_unknown is encountered, and therefore
-    +allow_unknown will have no effect. It should be moved to the start of the
-    list.
-
-One way of upgrading Exim from a pre-3.00 release to a post-3.00 release is as
-follows:
-
-1. Suppose your configuration file is called /opt/exim/configure, and you want
-   to continue with this name after upgrading. The first thing to do is to make
-   another copy of this file called, say, /opt/exim/configure.pre-3.00.
-
-2. Rebuild your existing Exim to use the copy of the configuration file instead
-   of the standard file. Install this version of Exim under a special name such
-   as exim-2.12, and point a symbolic link called "exim" at it. Then HUP your
-   daemon. You can check on the name of the configuration file by running
-
-     exim -bP configure_file
-
-   Ensure that everything is running smoothly.
-
-3. Build the new release, configured to use the standard configuration file.
-
-4. Use the convert4r3 utility to upgrade your configuration file for the new
-   release. After running it, check the file by hand.
-
-5. If any of the options that convert4r3 rewrote contained regular expressions
-   that had backslashes in them, and were not previously in quotes, they will
-   need modification if convert4r3 has put them into quotes. Either re-arrange
-   the option to remove the quoting, or escape each backslash. For example, if
-   you had
-
-     sender_reject_recipients = ^\d{8}@
-     sender_reject_except = ^\d{8}@???
-
-   convert4r3 will have combined the two settings into
-
-     sender_reject_recipients = "! ^\d{8}@??? : \
-        ^\d{8}@"
-
-   This must be changed to
-
-     sender_reject_recipients = ! ^\d{8}@??? : ^\d{8}@
-   or
-     sender_reject_recipients = "! ^\\d{8}@??? : ^\\d{8}@"
-
-   In the second case, the quoted string could of course still be split
-   over several lines.
-
-6. If your configuration refers to any external lists of networks, check them
-   to ensure that all the masks are in the single-number form, because Exim no
-   longer recognizes the dotted quad form of mask. For example, if an item in
-   a netlist file is
-
-      131.111.8.0/255.255.255.0
-
-   you must change it to
-
-      131.111.8.0/24
-
-   Otherwise Exim will not recognize it as a masked IP address, and will treat
-   it as a host name. The convert4r3 utility makes this conversion for networks
-   that are mentioned inline in the configuration, but it does not handle
-   referenced files.
-
-7. Check the newly-built Exim as much as possible without installing; you can,
-   for example, use a command such as
-
-     ./exim -bV
-
-   in the build directory to test that it successfully reads the new
-   configuration file. You can also do tests using -bt and -bh.
-
-8. Install the new release under a special name such as exim-3.00.
-
-9. You can then easily change between the new and old releases simply by moving
-   the symbolic link and HUPping your daemon.
-
-
-Details of syntax changes at 3.00
-=================================
-
-1. A bare file name without a preceding search type may appear in a domain
-list; this causes each line of the file to be read and processed as if it were
-an item in the list, except that it cannot itself be a bare file name (that is,
-this facility cannot be used recursively). Wild cards and regular expressions
-may be used in the lines of the file just as in the main list.
-For example, if
-
-  local_domains = /etc/local-domains
-
-then the file could contain lines like
-
-  *.mydomain.com
-
-This is different to an lsearch file, which operates like any other lookup type
-and does an exact search for the key. If a # character appears anywhere in a
-line of the file, it and all following characters are ignored. Blank lines are
-also ignored.
-
-2. Any item in a domain list (including a bare file name) can be preceded by an
-exclamation mark character, to indicate negation. White space after the ! is
-ignored. If the domain matches the rest of the item, it is *not* in the set of
-domains that the option is defining. If the end of the list is reached, the
-domain is accepted if the last item was a negative one, but not if it was a
-positive one. If ! precedes a bare file name, then all items in the file are
-negated, unless they are preceded by another exclamation mark. For example:
-
-  relay_domains = !a.b.c : *.b.c
-
-sets up a.b.c as an exception to the more general item *.b.c, because lists are
-processed from left to right. If the domain that is being checked matches
-neither a.b.c nor *.b.c, then it is not accepted as a relay domain, because the
-last item in the list is a positive item. However, if the option were just
-
-  relay_domains = !a.b.c
-
-then all domains other than a.b.c would be relay domains, because the last item
-in the list is a negative item. In effect, a list that ends with a negative
-item has ": *" appended to it.
-
-3. Negation and bare file names are available as above in lists of local parts
-(e.g. in local_parts options) and complete addresses (address lists). For the
-special "@@" lookup form in address lists, negation also can be used in the
-list of local parts that is looked up for the domain. For example, with
-
-  sender_reject_recipients = @@dbm;/etc/reject-by-domain
-
-the file could contain lines like this:
-
-  baddomain.com:  !postmaster : !hostmaster : *
-
-If a local part that actually begins with ! is required, it has to be specified
-using a regular expression. Because local parts may legitimately contain #
-characters, a comment in the file is recognized only if # is followed by white
-space or the end of the line.
-
-4. Host lists may now contain network items, as in the former net list options,
-which have all been abolished. The only form of network masking is the /n
-variety. Negation and bare file names can appear in host lists, and there is a
-new type of item which allows masked network numbers to be used as keys in
-lookups, thus making it possible to used DBM files for faster checking when the
-list of networks is large.
-
-The complete list of types of item which can now appear in a host list is:
-
-. An item may be a bare file name; each line of the file may take the form of
-  any of the items below, but it may not itself be another bare file name. If
-  the file name is preceded by ! then all items in the file are negated, unless
-  they are preceded by another exclamation mark. Comments in the file are
-  introduced by # and blank lines are ignored.
-
-. If the entire item is "*" it matches any host.
-
-. If the item is in the form of an IP address, it is matched against the IP
-  address of the incoming call.
-
-. If the item is in the form of an IP address followed by a slash and a mask
-  length (e.g. 131.111.0.0/16) then it is matched against the IP address of the
-  incoming call, subject to the mask.
-
-. If the item is of the form "net<number>-<search-type>;<search-data>", for
-  example:
-
-    net24-dbm;/networks.db
-
-  then the IP address of the incoming call is masked using <number> as the mask
-  length; a textual string is then constructed from the masked value, followed
-  by the mask, and this is then used as the key for the lookup. For example, if
-  the incoming IP address is 192.152.34.6 then the key that is looked up for
-  the above example is "192.152.34.0/24".
-
-. If the entire item is "@" the primary host name is used as the the match
-  item, and the following applies:
-
-. If the item is a plain domain name, then a forward DNS lookup is done on that
-  name to find its IP address(es), and the result is compared with the IP
-  address of the incoming call.
-
-The remaining items require the host name to be obtained by a reverse DNS
-lookup. If the lookup fails, Exim takes a hard line by default and access is
-not permitted. If the list is an "accept" list, Exim behaves as if the current
-host is not in the set defined by the list, whereas if it is a "reject" list,
-it behaves as if it is.
-
-To change this behaviour, the special item "+allow_unknown" may appear in the
-list (at top level - it is not recognized in an indirected file); if any
-subsequent items require a host name, and the reverse DNS lookup fails, Exim
-permits the access, that is, its behaviour is the opposite to the default.
-
-. If the item starts with "*" then the remainder of the item must match the end
-  of the host name. For example, *.b.c matches all hosts whose names end in
-  .b.c. This special simple form is provided because this is a very common
-  requirement. Other kinds of wildcarding require the use of a regular
-  expression.
-
-. If the item starts with "^" then it is taken to be a regular expression which
-  is matched against the host name. For example, ^(a|b)\.c\.d$ matches either
-  of the two hosts a.c.d or b.c.d. If the option string in which this occurs is
-  given in quotes, then the backslash characters must be doubled, because they
-  are significant in quoted strings. The following two settings are exactly
-  equivalent:
-
-    host_accept = ^(a|b)\.c\.d$
-    host_accept = "^(a|b)\\.c\\.d$"
-
-. If the item is of the form <search-type>;<filename or query>, for example
-
-    dbm;/host/accept/list
-
-  then the host name is looked up using the search type and file name or query
-  (as appropriate). The actual data that is looked up is not used.
-
-5. Early versions of Exim required commas and semicolons to terminate option
-settings in drivers. This hasn't been the case for quite some time. The code to
-handle them has now been removed.
-
-
-Details of option changes at 3.00
-=================================
-
-Main options
-------------
-
-  * address_directory_transport, address_directory2_transport,
-    address_file_transport, address_pipe_transport, and address_reply_transport
-    have been abolished as obsolete. The aliasfile and forwardfile directors
-    have been able for some time to set the transports they want to use for
-    these special kinds of delivery; there seems little need for global
-    defaults. The default configuration has been altered to add settings for
-    file_transport and pipe_transport to the aliasfile and forwardfile
-    directors, and to add reply_transport to forwardfile.
-
-  * check_dns_names, a deprecated synonym for dns_check_names, has been
-    abolished.
-
-  * helo_accept_junk_nets is abolished; nets can now appear in
-    helo_accept_junk_hosts.
-
-  * helo_verify_except_hosts and helo_verify_except_nets have been abolished,
-    and helo_verify has been changed from a boolean to a host list, listing
-    those hosts for which HELO verification is required.
-
-  * the obsolete option helo_verify_nets (a synonym for host_lookup_nets) has
-    been abolished. Note that host_lookup_nets itself has been replaced by
-    host_lookup.
-
-  * hold_domains_except has been abolished. Use negated items in hold_domains.
-
-  * host_lookup_nets has been replaced by host_lookup, which can contain hosts
-    and nets.
-
-  * ignore_fromline_nets has been replaced by ignore_fromline_hosts.
-
-  * If message_filter is set and the filter generates any deliveries to files,
-    pipes, or any autoreplies, then the appropriate message_filter_*_transport
-    options must be set to define the transports, following the abolition of
-    the global defaults (see above).
-
-  * queue_remote and queue_remote_except have been abolished and replaced by
-    queue_remote_domains, which lists those domains that should be queued. The
-    effect of queue_remote=true is now obtained by queue_remote_domains=*.
-
-  * queue_smtp and queue_smtp_except have been abolished and replaced by
-    queue_smtp_domains, which lists those domains that should be queued after
-    routing. The effect of queue_smtp=true is now obtained by
-    queue_smtp_domains=*.
-
-  * rbl_except_nets has been abolished and replaced by rbl_hosts, which can
-    contain hosts and nets. This defaults to "*" and defines the set of hosts
-    for which RBL checking is done.
-
-  * receiver_unqualified_nets is abolished; nets can now appear in
-    receiver_unqualified_hosts.
-
-  * receiver_verify_except_hosts and receiver_verify_except_nets have been
-    abolished and replaced by receiver_verify_hosts, which defaults to "*".
-    This is used, however, only when receiver_verify is set - together with the
-    other conditions (receiver_verify_addresses, receiver_verify_senders).
-
-  * receiver_verify_senders_except has been abolished; the functionality is now
-    available by using negation in receiver_verify_senders.
-
-  * rfc1413_except_hosts and rfc1413_except_nets have been abolished, and
-    replaced by rfc1413_hosts, which defaults to "*".
-
-  * sender_accept, sender_accept_recipients and sender_reject_except have
-    been abolished; the functionality is now available via sender_reject and
-    sender_reject_recipients.
-
-  * sender_host_accept, sender_net_accept, sender_host_reject,
-    sender_net_reject, sender_host_reject_except, sender_net_reject_except,
-    sender_host_reject_recipients and sender_net_reject_recipients
-    have all been abolished, and replaced by the options host_reject and
-    host_reject_recipients.
-
-  * sender_host_accept_relay, sender_net_accept_relay,
-    sender_host_reject_relay, sender_host_reject_relay_except,
-    sender_net_reject_relay, and sender_net_reject_relay_except are abolished,
-    and replaced by host_accept_relay. This defaults unset, and this means that
-    all relaying is now by default locked out in the Exim binary. Previously,
-    if no relaying options were set, relaying was permitted.
-
-  * sender_unqualified_nets has been abolished; nets can now appear in
-    sender_unqualified_hosts.
-
-  * sender_verify_except_hosts and sender_verify_except_nets have been
-    abolished and replaced by sender_verify_hosts, which defaults to "*". This
-    is used, however, only when sender_verify is set (to make it similar to
-    receiver_verify, even though there aren't at present any other conditions.)
-
-  * sender_verify_log_details has been abolished. This was a little-used
-    debugging option.
-
-  * smtp_etrn_nets has been abolished; nets can now appear in smtp_etrn_hosts.
-
-  * smtp_expn_nets has been abolished; nets can now appear in smtp_expn_hosts.
-
-  * smtp_log_connections, a deprecated synonym for log_smtp_connections, has
-    been abolished.
-
-  * smtp_reserve_nets is abolished; nets can now appear in smtp_reserve_hosts.
-
-Generic director and router options
------------------------------------
-
-  * except_domains, except_local_parts, and except_senders have been abolished.
-    Use negated items in domains, local_parts, and senders instead, for
-    example, replace
-
-      except_domains = a.b.c
-
-    with
-
-      domains = !a.b.c
-
-    If you already have a domains setting, add any negative items to the front
-    of it.
-
-The aliasfile director
-----------------------
-
-  * The option "directory", an obsolete synonym for home_directory, has been
-    abolished.
-
-The forwardfile director
-------------------------
-
-  * The option "directory", an obsolete synonym for file_directory, has been
-    abolished.
-
-  * The option forbid_filter_log, an obsolete synonym for
-    forbid_filter_logwrite, has been abolished.
-
-The localuser director
-----------------------
-
-  * The option "directory", an obsolete synonym for match_directory, has been
-    abolished.
-
-The lookuphost router
----------------------
-
-  * mx_domains_except and its obsolete old name non_mx_domains have been
-    abolished. Use negated items in mx_domains.
-
-The pipe transport
-------------------
-
-  * The option "directory", an obsolete synonym for home_directory, has been
-    abolished.
-
-The smtp transport
-------------------
-
-  * mx_domains_except and its obsolete old name non_mx_domains have been
-    abolished. Use negated items in mx_domains.
-
-  * serialize_nets has been abolished; nets may now appear in serialize_hosts.
-
-
-Other items relevant to upgrading from Exim 2.12
-================================================
-
-1. RFC 2505 (Anti-Spam Recommendations for SMTP MTAs) recommends that the
-checking of addresses for spam blocks should be done entirely caselessly.
-Previously, although Exim retained the case of the local part, in accordance
-with the RFC 821 rule that local parts are case sensitive, some of the string
-comparisons were nevertheless done caselessly, but file lookups used the
-unmodified address.
-
-The way addresses are compared with options whose values are address lists has
-been changed. At the start of the comparison, both the local part and the
-domain are now forced to lower case, and any comparisons that are done with
-in-line strings are done caselessly. For example,
-
-  sender_reject = A@???
-
-rejects both A@??? and a@???. Any lookups that occur use lowercased strings as
-their keys. If the @@ lookup facility is used, the lookup is done on the lower
-cased domain name, but any subsequent string comparisons on local parts are
-done caselessly.
-
-To retain possibility of caseful matching, the pseudo-item "+caseful" can
-appear in an address list. It causes any subsequent items to do caseful matches
-on local parts. The domain, however, remains lower cased.
-
-2. The handling of incoming batched SMTP has been re-worked so as to behave in
-a more useful way in cases of error:
-
-  (i)   The option sender_verify_batch now defaults false.
-  (ii)  EOF is no longer interpreted as end-of-message; the "." line must be
-        present.
-  (iii) Exim stops immediately in cases of error, writing information to stdout
-        and stderr, and setting the return code to 1 if some messages have been
-        accepted, and 2 otherwise.
-
-3. The first message delivered by -R, and all messages delivered by -Rf and -qf
-are "forced" in the sense that retry information is over-ridden. Previously,
-Exim also forcibly thawed any of these messages that was frozen. This no longer
-happens. Additional options -Rff and -qff have been implemented to force
-thawing as well as delivery.
-
-4. When recipients are being rejected because the sending host is in an RBL
-list, Exim used just to show the RBL text, if any, as part of the rejection
-response. Now, if prohibition_message is set, it expands that string instead,
-with the RBL message available in $rbl_text, and $prohibition_reason set to
-"rbl_reject".
-
-5. When a trusted caller passed a message to Exim, it used to check the From:
-header against the caller's login (even though the caller was trusted) unless
-the -f option had been used to supply a different sender. This has been changed
-so that From: is never checked if the caller is trusted.
-
-Philip Hazel
-May 1999
-
diff --git a/doc/doc-txt/Exim4.upgrade b/doc/doc-txt/Exim4.upgrade
deleted file mode 100644
index 86d4a4dda..000000000
--- a/doc/doc-txt/Exim4.upgrade
+++ /dev/null
@@ -1,1734 +0,0 @@
-Upgrading Exim from Release 3.33 to 4.xx
-----------------------------------------
-
-Exim 4.00 represents the largest upheaval in Exim's history. There are a lot of
-changes to the way some parts of Exim work, and a lot of incompatible changes
-to the run time configuration file.
-
-This document is in two parts. The first part contains instructions and
-suggestions for how you might go about performing the upgrade. The second part
-is a brief list of all the changes that have taken place. For full details of
-all the new features, please consult the current version of the reference
-manual.
-
-
-HOW TO UPGRADE YOUR EXIM
-------------------------
-
-When you compile Exim 4, a Perl script called convert4r4 is built in the build
-directory. It is not installed by the install script, because it is likely that
-you will run it only once.
-
-This script is provided to assist in updating Exim configuration files. It
-reads an Exim 3 configuration file on the standard input, and writes a modified
-file on the standard output. It also writes comments about what it has done to
-the standard error file. It assumes that the input is a valid Exim 3
-configuration file. A typical call to the conversion script might be
-
-  ./convert4r4  </etc/exim/configure  >/etc/exim/configure.new
-
-The output file MUST be checked and tested before trying to use it on a live
-system. The conversion script is just an aid which does a lot of the "grunt
-work". It does not guarantee to produce an Exim 4 configuration that behaves
-exactly the same as the Exim 3 configuration it reads.
-
-Each option change in the new file is preceded by an identifying comment. In
-fact, the conversion script tends to make quite a mess of your configuration,
-and you should expect to go through it afterwards and tidy it up by hand.
-
-Unless you are running a very straightforward configuration, the automatic
-conversion is likely to generate a non-optimal configuration. You should not
-only check it thoroughly, but also run as many tests as you can, to ensure that
-it is working as you expect. In particular, you should test address routing,
-using -bt and -bv, and the policy controls, using -bh. If possible, you should
-also do some live tests (i.e. send and receive some messages) before putting
-Exim 4 into service.
-
-If you have a very complicated configuration, it is possible that convert4r4
-will break it in some situations, which is why thorough testing is strongly
-recommended.
-
-                   *********************************
-                   ***** You Have Been Warned ******
-                   *********************************
-
-
-HOW TO MOVE FROM AN EXIM 3 RELEASE TO AN EXIM 4 RELEASE
--------------------------------------------------------
-
-One way of upgrading to Exim 4 from a version 3 release is as follows:
-
-1. Suppose your run time configuration file is called /usr/exim/configure, and
-   you want to continue with this name after upgrading. The first thing to do
-   is to make another copy of this file called, say, /usr/exim/configure.r3.
-
-2. Rebuild your existing Exim to use the copy of the run time configuration
-   file instead of the standard file. Install this version of Exim and HUP your
-   daemon. You can check on the name of the configuration file by running
-
-     exim -bP configure_file
-
-   Ensure that everything is running smoothly. You now have something you can
-   fall back to. IMPORTANT: when you do this re-install, you should also
-   re-install the utilities because four of them (exicyclog, eximon, exinext,
-   and exiwhat) also refer to the configuration file.
-
-3. Build the new release, configured to use the standard configuration file.
-
-4. Use the convert4r4 utility to upgrade your configuration file for the new
-   release. After running the conversion utility, check the file by hand, and
-   tidy it up.
-
-5. Test, test, test! And test some more!
-
-6. You can run complete tests, including actual deliveries, from an uninstalled
-   binary, but you have to tell it where it is, so that any re-executions can
-   be done. You can do this by temporarily inserting a setting such as
-
-   exim_path = /source/exim/exim-4.00/build-SunOS5-5.8-sparc/exim
-
-   into the run time configuration. If you want to, you can also insert
-   settings for spool_directory and log_file_path to divert those away from
-   their normal places. Remember to remove these temporary settings when you
-   eventually install the binary for real.
-
-7. The new installation script installs the new release as exim-4.00-1, and
-   set a symbolic link called "exim" to point to it. The old version of Exim
-   will be renamed to something like exim-3.33-1.
-
-8. You can now easily change between the new and old releases simply by moving
-   the symbolic link and HUPping your daemon. The format of message files on
-   Exim's spool has _not_ changed, so there should be no problem in changing
-   between releases while there are messages on the queue.
-
-9. HOWEVER: If you do change back and forth between releases, you must also
-   change the utilities exicyclog, eximon, exinext, and exiwhat if you are
-   going to use them. Installing Exim 4 will have left the old versions with a
-   .O suffix. It might be helpful to rename these so that you don't lose them.
-
-
-WHAT HAS NOT CHANGED IN EXIM 4.00
----------------------------------
-
-The basic overall philosophy, design, and process structure has not changed.
-The format of spool files is the same. The transports have had only minor
-modifications. The command line options remain the same, with a couple of
-additions.
-
-The general run time configuration approach has not changed, but the actual
-details of the configuration file are different.
-
-The Exim monitor has not changed, and there have been only very minor changes
-to other Exim utilities.
-
-
-WHAT HAS CHANGED IN EXIM 4.00
------------------------------
-
-The rest of this document lists the very many changes that have taken place.
-I'm going to give only brief details here, because this part of the document is
-intended as a way of alerting you to areas of difference. The reference manual
-describes how the new features work in detail.
-
-
-Named domain, host, address, and local part lists
--------------------------------------------------
-
-A new feature makes it possible to give names to lists of domains, hosts,
-addresses, and local parts. The syntax used is
-
-  domainlist    <name> = <a domain list>
-  hostlist      <name> = <a host list>
-  addresslist   <name> = <an address list>
-  localpartlist <name> = <a list of local parts>
-
-For example:
-
-  domainlist  local_domains = *.my.domain
-  addresslist bad_senders = cdb;/etc/badsenders
-
-These lists are referenced in options by giving the name preceded by a + sign.
-For example, in a router you might have
-
-  domains = +local_domains
-
-At first sight, these lists might seem to be the same as macros, but they are
-not. Macros are just textual substitutions. If you write
-
-  ALIST = host1 : host2
-  auth_advertise_hosts = !ALIST
-
-it probably won't do what you want, because that is exactly the same as
-
-  auth_advertise_hosts = !host1 : host2
-
-Notice that the second host name is not negated. However, if you use a host
-list, and write
-
-  hostlist alist = host1 : host2
-  auth_advertise_hosts = ! +alist
-
-the negation applies to the whole list, and so that is equivalent to
-
-  auth_advertise_hosts = !host1 : !host2
-
-These named lists also have a performance advantage. When Exim is routing an
-address or checking an incoming message, it caches the result of tests on the
-lists. So, if you have a setting such as
-
-  domains = +local_domains
-
-on several of your routers, the actual test is done only for the first one.
-However, this caching works only if there are no expansions within the list
-itself or any sublists that it references. In other words, caching happens only
-if the list is known to be the same each time it is referenced.
-
-By default, there may be up to 16 named lists of each type. This limit can be
-extended by changing a compile-time variable.
-
-The use of domain and host lists is recommended for concepts such as local
-domains, relay domains, and relay hosts. The default configuration is set up
-like this.
-
-
-Processing of domain, host, local part, and address lists
----------------------------------------------------------
-
-The handling of these lists is now more uniform. Every list is expanded as a
-single string before it is used. (In Exim 3, some options were expanded and
-some weren't, and query-style lookup items were then re-expanded.)
-
-If an expansion is forced to fail, Exim behaves as if the item has not been
-found in the list.
-
-The confusing $key variable has been abolished. When processing a domain list,
-$domain contains the relevant domain and can be used in generating database
-queries. Other appropriate variables are set when processing other kinds of
-list; $sender_host and $sender_host_address for checking incoming hosts and
-$host and $host_address for checking outgoing hosts.
-
-Note that this means that any \ and $ characters in regular expressions must be
-escaped if they appear in one of these lists. The new expansion feature to turn
-off expansion (\N ... \N) which is described below can be helpful here.
-
-IMPORTANT: The details of the processing of address lists has been revised. In
-particular, the handling of the case of an item that is a single-key lookup has
-changed. It no longer looks up the domain on its own before looking up the
-complete address. You need to supply an explicit "*@" before the lookup if you
-want just the domain to be looked up. Please check the manual for full details.
-
-If an item in a host list is the empty string, it matches only when no host is
-defined. If used when checking an incoming message, it matches only when the
-message is arriving by SMTP on the standard input from a local process (using
--bs). This provides a way of distinguishing between SMTP mail from local
-processes and from remote hosts.
-
-The +allow_unknown and +warn_unknown settings for host lists have been replaced
-by a single item, +include_unknown. By default, failure to find a host name
-when needed causes Exim to behave as if the host does not match the list, but
-if +include_unknown is set, the opposite behaviour happens. Whenever
-+include_unknown is invoked, the incident is logged.
-
-
-Merge of Directors and Routers
-------------------------------
-
-There are no longer any directors in Exim 4. There are just routers. All
-addresses are passed to a single list of routers which typically makes use of
-the "domains" option to choose which way to handle specific groups of domains.
-
-A consequence of this is that the code no longer contains any concept of "local
-domains". However, a typical configuration will probably define a named domain
-list (see above) called local_domains, and use it to control routing something
-like this:
-
-  route_remote:
-    driver = dnslookup
-    domains = ! +local_domains
-    transport = remote_smtp
-    no_more
-
-  system_aliases:
-    ....
-
-The first router does DNS routing for all domains that are not in the named
-list of local domains, and no_more ensures that it is the last router for those
-domains. All other domains fall through to the system_aliases and subsequent
-routers. For a complete configuration example, look at the default
-configuration file in src/configure.default.
-
-
-Router Actions
---------------
-
-The concept of how the routers work is as follows:
-
-A number of pre-conditions are tested (details below). If any of them fails,
-control is passed to the next router. We say "the router is skipped". Otherwise
-the router is run, and can yield one of several different results:
-
-. accept: The router accepts the address, and either queues it for a transport,
-or generates one or more "child" addresses. Processing the original address
-ceases, unless "unseen" is set on the router, in which case the address is
-passed to the next router. Processing of any child addresses starts with the
-first router by default, or at the router defined by redirect_router if it is
-set. This may be any router in the list.
-
-. decline: The router declines to accept the address because it does not
-recognize it at all. The address is passed to the next router, unless no_more
-is set, in which case the address fails.
-
-. pass: The router recognizes the address, but cannot handle it itself. It
-requests that the address be passed to another router. This overrides no_more.
-By default the address is passed to the next router, but this can be changed by
-setting pass_router. However, in this case (unlike redirect_router) the named
-router must be below the current router (to avoid loops).
-
-. fail: The router determines that the address should fail, and queues it for
-the generation of a bounce message. There is no further processing of the
-original address, unless "unseen" is set.
-
-. defer: The router cannot handle the address at the present time. (For
-example, a database may be offline.) No further processing of the address
-happens in this delivery attempt. It is tried again next time.
-
-. error: There is some error in the router (for example, a syntax error in
-its configuration). The action is as for defer.
-
-
-Router pre-conditions
----------------------
-
-In Exim 3 there are some strange interactions between the generic options that
-test things before running a director or router and the no_more test that
-happens afterwards.
-
-In Exim 4 it is all more straightforward. If any of the pre-condition tests
-fail, the router is skipped and control passes to the next router. The no_more
-option has an effect only if the router is actually run - that is, if all the
-pre-condition tests succeed. The order in which these tests are run is:
-
-  verify status, expn status, domains, local_parts, check_local_user
-
-If all those match, the debug_print string is output when debugging. Exim then
-goes on to test
-
-  senders, require_files, condition
-
-Note that require_files comes near the end of the list, so you cannot use it to
-check for the existence of a file in which to lookup up a domain, local part,
-or sender. However, as these options are all expanded, you can use the "exists"
-expansion condition to make such tests. The require_files option is intended
-for checking files that the router may be going to use internally, or which are
-needed by a specific transport (e.g. .procmailrc).
-
-In Exim 4, local part prefixes and suffixes are recognized and removed before
-any of the other pre-condition tests are done (in Exim 3 they were removed
-afterwards). Note that this means that the local_parts option now tests the
-local part without its prefix or suffix.
-
-If you want to use local parts that include any affixes in a pre-condition
-test, you can do so by using a "condition" option that uses the variables
-$local_part, $local_part_prefix, and $local_part_suffix as necessary.
-
-
-A New Set of Routers
---------------------
-
-The two sets of routers and directors of Exim 3 have been replaced by a single
-set of routers for Exim 4. These are as follows:
-
-. accept        Always accepts an address. It has no private options.
-
-. dnslookup     Routes by DNS lookup (descended from lookuphost).
-
-. ipliteral     Routes IP literal addresses (unchanged).
-
-. iplookup      Special-purpose lookup router (unchanged).
-
-. manualroute   Routes domains from explicit data (descended from domainlist).
-
-. queryprogram  Routes addresses by running a program (detail changed).
-
-. redirect      Redirects addresses; handles all the functions previously
-                supported by aliasfile, forwardfile, and smartuser without
-                a transport.
-
-
-Saving duplication of effort while routing
-------------------------------------------
-
-Early versions of Exim used to copy the routing of one address for all other
-addresses in the same domain, thereby possibly saving some repeated DNS
-lookups. This feature was removed for release 2.12, after the possibility of
-varying the router actions according to the local part (the local_parts option)
-was added. (In fact, the use of $local_part could have broken it earlier.)
-
-For Exim 4, I have added an option called same_domain_copy_routing to the
-dnslookup and manualroute routers. When one of these routers routes an address
-to a remote transport and this option is set, any other addresses in the
-message that have the same domain are automatically given the same routing, but
-only if the router does not set headers_add or headers_remove, and does not
-`widen' the domain during the routing.
-
-
-Generic Router Options
-----------------------
-
-. The global locally_caseless option is replaced by a generic router option
-  called caseful_local_part. By default, routers handle local parts caselessly.
-
-. check_local_user is now a generic option that is needed to check for a local
-  account. Typically used on redirect (for user's forward files) and on accept
-  (for local deliveries).
-
-. The setting self=local has been removed (since there's no concept of local
-  domains in the code). The same kind of effect can be achieved by using
-  self=reroute or self=pass.
-
-. expn is now a generic router option.
-
-. local_part_prefix and local_part_suffix are now generic router options,
-  replacing prefix and suffix on directors.
-
-. Exim 3 has two logging styles for delivery, depending on whether the domain
-  is a local domain or not. For local domains, the address is given just as the
-  local part - this makes these deliveries easier to spot in the log. In Exim 4
-  there's no concept of local domains, so this functionality cannot be
-  automatic. Instead, there's a generic router option called log_as_local which
-  requests "local-style" logging. This option defaults on for the "accept"
-  router, and off for all the others.
-
-. There's an option called retry_use_local_part which is the default for any
-  router that has check_local_user set, and it applies to routing delays. (The
-  same option for transports applies to transport delays.)
-
-. transport_home_directory and transport_current_directory are new generic
-  options on all routers. They set up default values for home_directory and
-  current_directory on the transport to which they route an address. Any
-  settings in the transport override.
-
-. If transport_home_directory is not set, but check_local_user is set, the
-  user's home directory is used as a default value.
-
-. The special fudge that exists in Exim 3 for handling home_directory settings
-  in forwardfile directors is not needed in Exim 4. It has therefore been
-  removed.
-
-. The new_director option in Exim 3 allows the direction of redirected
-  addresses to start at a given director, instead of the first one. In Exim 4,
-  this option is now called redirect_router. The option is used when a redirect
-  router succeeds, and when a queryprogram router returns a "redirect"
-  response.
-
-. There is a new option called pass_router, which specifies the router to go to
-  when a router "passes" on an address. The named router must follow the
-  current router (to avoid routing loops). Note: if a router declines, control
-  always passes to the next router, unless no_more is set.
-
-. There is a new router option called address_data. This is set to a string
-  which is expanded just before the router is run, that is, after all the
-  pre-tests have succeeded. If the expansion is forced to fail, the router
-  declines. Other expansion failures cause delivery of the address to be
-  deferred.
-
-  When the expansion succeeds, the value is retained with the address, and can
-  be accessed using the variable $address_data. Even if the router declines or
-  passes, the value remains with the address, though it can be changed by
-  another address_data setting on a subsequent router. If a router generates
-  child addresses, the value of $address_data propagates to them.
-
-  The idea of address_data is that you can use it to look up a lot of data for
-  the address once, then then pick out parts of the data later. For example,
-  you could use an LDAP lookup to return a string of the form
-
-    uid=1234 gid=5678 mailbox=/mail/xyz forward=/home/xyz/.forward
-
-  In the transport you could then pick out the mailbox by a setting such as
-
-    file = ${extract{mailbox}{$address_data}}
-
-  This makes the configuration file less messy, and also reduces the number of
-  lookups. (Exim does cache the most recent lookup, but there may be several
-  addresses with different lookups.)
-
-. When a transport is run for several addresses simultaneously, the values of
-  $address_data, $local_part_data, and $domain_data are taken from the first
-  address that the transport handles. However, the order in which multiple
-  addresses are processed is not defined. You therefore need to be careful if
-  you want to use these variables with multiple addresses. The smtp transport
-  is the only one which by default handles multiple addresses.
-
-. When an address is routed by a router with the "unseen" option set, a "clone"
-  address is created, and it starts being routed at the next router. (This is
-  what people expect. In Exim 3 it starts at the top - in simple cases that has
-  the same effect because of the anti-looping rule, but if aliases are involved
-  it sometimes doesn't do what you want.)
-
-. The way that require_files works has been changed. Each item in the list is
-  now separately expanded as the test proceeds. The use of leading ! and +
-  characters is unchanged. However, user and group checking is done differently.
-  Previously, seteuid() was used, but seteuid() is no longer used (see
-  "Security" below) for checking the files required by this option. Instead,
-  Exim now scans along the components of the file path and checks the access
-  for the given uid and gid. It expects "x" access on directories and "r" on
-  the final file. This means that file access control lists (on those
-  operating systems that have them) are ignored.
-
-
-Other Consequences of the Director/Router Merge
------------------------------------------------
-
-. The -odqr option is abolished, as there is no inbuilt concept of remote
-  domains.
-
-. The -odqs option is equivalent to queue_smtp_domains = *.
-
-. queue_remote_domains is renamed queue_domains, and applies to any domain.
-
-. The -ql option now suppresses remote delivery; routing always happens.
-
-. The "remote" facility of queue_only_file has been removed.
-
-. The match_directory option for forwardfile and localuser has been entirely
-  abolished. Its function can be achieved using the "condition" option in
-  conjunction with check_local_user.
-
-. When an address is being verified, if it is redirected to a single new
-  address, verification continues with that address. If it is redirected to
-  more than one address, verification ceases with a success result. (In Exim 3,
-  this applied only to aliasing, not to forwarding.)
-
-
-The dnslookup router
---------------------
-
-This router replaces the lookuphost router of Exim 3. It is much the same,
-except that the "gethostbyname" option has been removed. It now does only DNS
-routing - hence the change of name. Routing using gethostbyname() can be done
-by the manualroute router.
-
-
-The manualroute router
-----------------------
-
-This is the new name for the domainlist router, supposedly to make its function
-clearer and to avoid confusion with the "domainlist" that is used to set up
-named domain lists. Several things have been removed and reorganized.
-
-. The old search mechanism (route_file, route_query, route_queries,
-  search_type) have been removed. Instead there is a new option called
-  route_data, which is an expanded string. It should expand to a single routing
-  entry. If the expansion ends up empty (or is forced to fail), the router
-  declines. The route_list option still exists, for convenient listing of a few
-  inline routes.
-
-. There is no longer any MX processing function in this router. The keywords
-  bydns_mx and bydns_a have been removed, leaving just
-
-    bydns  => find IP addresses from address records in the DNS
-    byname => find IP addresses by calling gethostbyname()
-
-  The default lookup type is "byname", and this can be omitted from a route
-  data line. If an IP address is given, both "byname" and "bydns" are ignored
-  (so typically you omit this field).
-
-. The qualify_single and search_parents options have also been removed.
-
-. A transport is always required to be set, unless verify_only is set.
-
-. The host_find_failed option can be set to "decline", to cause the router to
-  decline if it can't find an IP address for a listed host.
-
-. If manualroute routes to a local transport, there is no need to specify
-  byname or bydns in the routing data. Any supplied host list is passed as a
-  string in $host, but $host_address is unset.
-
-
-The queryprogram router
------------------------
-
-This router has been re-designed:
-
-. You must now specify a user and group for the program to be run using
-  command_user and (if necessary) command_group. It no longer defaults to
-  "nobody". These options are expanded.
-
-. The command is now split up and each argument expanded separately, as happens
-  for the pipe transport. The command name is also expanded.
-
-. The return value "forcefail" has been renamed "fail", and it causes delivery
-  to fail. (The original usage of "fail" meaning "decline" has finally been
-  removed.)
-
-. The $route_option variable, which queryprogram used to be able to set has
-  been abolished. A facility to set the new $address_data variable replaces it.
-
-. The string returned from queryprogram must now be one of:
-
-  DECLINE
-  FAIL text
-  DEFER text
-  PASS
-  FREEZE text
-  REDIRECT text
-  ACCEPT TRANSPORT=transport HOSTS=host list LOOKUP=byname|bydns DATA=text
-
-The text returned for "redirect" is a list of new addresses. The text for FAIL
-is returned in the SMTP dialogue when the router is run as part of address
-verification. It is also logged. The text for DEFER and FREEZE is just logged.
-
-The data items in the "accept" return can be given in any order, and all are
-optional. If no transport is included in the "accept" return, the router's
-default transport is used. The host list and lookup type are needed only if the
-transport is an smtp transport that does not itself have a host list. The
-default lookup type is "byname". If the "data" field is set, its value is
-placed in the $address_data variable.
-
-
-The redirect router
--------------------
-
-This router replaces forwardfile, appendfile, and the use of smartuser without
-a transport. It has two mutually exclusive options for specifying the data that
-it uses. If "file" is set, the data is taken from a file. Otherwise "data" must
-be set, and the data is the expanded value of that option.
-
-The data may be an alias list, possibly including special entries such as
-:fail:, or it may be a list of filtering instructions.
-
-If "file" is set, but the file does not exist or is empty, or its contents have
-no effect (entirely comments, or a filter that does nothing), the router
-declines. This also happens if the expansion of "file" is forced to fail. Any
-other expansion failure causes the router to defer.
-
-Ownership of the file is checked if check_local_user is set or if owners is
-set, unless check_owner is explicitly set false.
-
-Likewise, the group is checked if owngroups is set, or if check_local_user is
-set and a modemask not containing 020 is set, unless check_group is explicitly
-set false.
-
-If "data" is set, a forced expansion causes the router to decline. This also
-happens if "data" is an empty string or a string that causes nothing to be
-generated and no action to be taken.
-
-Because "data" is now used for traditional /etc/aliases lookups, an empty alias
-no longer gives an error. It behaves in the same way as :unknown: (which is
-still recognized, but ignored).
-
-. If no_repeat_use is set, the router is skipped if _any_ ancestor of the
-  current address was routed by this router. This pre-test happens before any
-  of the others. (Contrast the default loop avoidance logic, which skips a
-  router if an ancestor with the same local part was routed by the router.)
-
-. If include_directory is set, :include: files are constrained to this
-  directory.
-
-. When an address is redirected to a file or a pipe, $address_file or
-  $address_pipe (as appropriate) is set when expanding the value of
-  file_transport or directory_transport.
-
-. There are new options forbid_filter_readfile and forbid_filter_run to lock
-  out the use of the new ${readfile and ${run expansion items in filters.
-
-. If one_time is set, forbid_pipe, forbid_file, and forbid_filter_reply are
-  forced to be true, and headers_add and headers_remove are forbidden.
-
-
-Generic transport options
--------------------------
-
-. All remote deliveries are now done in subprocesses running with specified
-  UIDs and GIDs. (Formerly, only remote parallel deliveries were done in
-  subprocesses.) As a result, user and group are now generic options that can
-  be used on all transports. The default for both local and remote transports
-  is to run as the Exim user and group. For remote transports, this should not
-  normally be changed, but if it is, the user or group should be able to access
-  the hints databases, though failure to open a hints database is always
-  ignored.
-
-  If it turns out that a transport user is in the never_users list, Exim now
-  defers delivery and writes to the panic log. (Previously it just ran the
-  delivery as "nobody".) Because subprocesses (usually running as "exim")
-  are now always used for remote deliveries, you should *not* include "exim" in
-  the never_users list.
-
-. initgroups is now also a generic transport option.
-
-. home_directory and current_directory are generic options on all transports,
-  though some transports (e.g. smtp) make no use of them. If they are unset,
-  values supplied by the router are used.
-
-. The message_size_limit option is now expanded, which makes it possible to
-  have different limits for different hosts, for example.
-
-
-Multiple (batch) deliveries in the appendfile, lmtp, and pipe transports
-------------------------------------------------------------------------
-
-The options controlling batch deliveries, including BSMTP, were a mess, and
-have been reworked.
-
-. The batch option has been removed from all three transports, and the bsmtp
-  and bsmtp_helo options have been removed from appendfile and pipe.
-
-. The batch_max option defaults to 1 in all three transports.
-
-. A new option called use_bsmtp has been added to appendfile and pipe. When
-  set, the message is delivered in BSMTP format. If you want to have a HELO
-  line at the start of the message, you can configure this by making use of the
-  message_prefix option. You must include the terminating newline.
-
-. A new option called batch_id has been added to all three transports.
-
-Batching is now achieved by setting batch_max to a value greater than 1. This
-is recommended for lmtp. When multiple addresses are routed to the same
-transport that has a batch_max value greater than one, the addresses are
-delivered in a batch, subject to certain conditions:
-
-. If any of the transport's options contain a reference to "$local_part", no
-  batching is possible.
-
-. If any of the transport's options contain a reference to "$domain", only
-  addresses with the same domain are batched.
-
-. If batch_id is set, it is expanded for each address, and only those addresses
-  with the same expanded value are batched.
-
-. Batched addresses must also have the same errors address (where to send
-  delivery errors), the same header additions and removals, the same user and
-  group for the transport, and if a host list is present, the first host must
-  be the same.
-
-
-The appendfile transport
-------------------------
-
-. The prefix and suffix options have been renamed message_prefix and
-  message_suffix to avoid confusion with address affixes. The default values,
-  which are suitable for mbox deliveries, now apply only if "file" is set and
-  use_bsmtp is not set. Otherwise, the default values for these options are
-  unset. They can, of course, always be overridden.
-
-. If "directory" is set (which means that "file" is not set), the check_string
-  and escape_string options now default unset.
-
-. The require_lockfile options has been abolished. If use_lockfile is set, a
-  lock file is always required.
-
-. The quota_filecount option is now expanded.
-
-. The create_file option now also applies when delivering into an individual
-  file in a given directory, as well as when appending to a single file. In the
-  case of maildir delivery, the restriction applies to the top directory of the
-  maildir folder.
-
-. There's a new option called directory_file which is expanded to form the
-  final leaf name of files when "directory" is set, but neither maildir nor
-  mailstore is set. The default is "q${base62:$tod_epoch}-$inode", which
-  reproduces the old fixed value. The variable $inode is available only when
-  expanding this new option.
-
-
-The pipe transport
-------------------
-
-. The prefix and suffix options have been renamed message_prefix and
-  message_suffix to avoid confusion with address affixes. The default values
-  that are suitable for vacation deliveries now apply only if use_bsmtp is not
-  set. Otherwise the default values for these options are unset. They can, of
-  course, always be overridden.
-
-
-The smtp transport
-------------------
-
-. The badly-named batch_max option is now called connection_max_messages.
-
-. If hosts_randomize is set, it now affects host lists that come from a router
-  as well as the contents of the "hosts" option, but only if the hosts were not
-  obtained from MX records. Typically, such lists come from the manualroute
-  router. This change means that the router can provide the same host list for
-  multiple addresses - causing them all to be sent to the transport at once.
-  Randomizing is then done each time the transport is called. (If you set
-  hosts_randomize on the router, the randomizing happens for each address.)
-
-. The way that smtp operates when there are multiple addresses to be sent to
-  the same host is now different. Previously, the transport was called many
-  times, with a maximum of max_rcpt addresses per call. Each call made a new
-  connection to the host. When remote_max_parallel = 1, all the addresses are
-  now passed to the transport at once. It makes a single TCP/IP call, but may
-  send multiple copies of the message, each with no more than max_rcpt
-  recipients.
-
-  When remote_max_parallel is greater than 1, a heuristic is used. The number
-  of addresses passed to a single call of the transport is limited to
-
-    (the total number of recipients) / (the value of remote_max_parallel)
-
-  so, for example, if there are 100 recipients and remote_max_parallel is 2, no
-  more than 50 are passed in one call, even if max_rcpt is 100. (The idea is
-  that the other 50 will be passed to another call running in parallel.)
-
-  There is an option of the smtp transport called connection_max_messages
-  which limits the number of messages, or copies of a message, that Exim sends
-  down a single TCP/IP connection. This applies both to this mechanism for
-  multiple copies of a single message, and the re-use of a TCP/IP connection
-  for sending other messages destined for the same host, after a delivery
-  delay. The default value is 500.
-
-. The "interface" option is now expanded. If the result is a forced failure or
-  an empty string, it is ignored. Otherwise, the result must be a list of IP
-  addresses. The first one of the correct type (IPv4 or IPv6) for the outgoing
-  connection is used. If there isn't one of the correct type, the option is
-  ignored.
-
-. At the start of running the transport, the value of $host is taken from the
-  first host in a multi-host list. However, just before the transport connects
-  to a host, the value is changed to refer to that particular host. (This
-  applies to $host_address as well.) This means that options such as helo_data
-  and the tls_options can be made host-specific.
-
-. The tls_verify_ciphers option has been renamed tls_require_ciphers, in order
-  to leave the word "verify" as something that refers to the verification of
-  certificates.
-
-. The resolution of hosts and fallback_hosts used to look up MX records. This
-  was some kind of ancient silliness that I recently noticed. These are
-  definitely hosts, not mail domains. Exim 4 just looks up address records.
-  As a consequence of this, the mx_domains option of the smtp transport is
-  removed.
-
-. The authenticate_hosts option has been renamed as hosts_try_auth. A new
-  option called hosts_require_auth has been added; if authentication fails for
-  one of these hosts, Exim does _not_ try to send unauthenticated. It defers
-  instead. The deferral error is detectable in the retry rules, so this can be
-  turned into a hard failure if required.
-
-
-The System Filter
------------------
-
-. The system filter options that were called message_filter_xxx have all been
-  renamed as system_filter_xxx.
-
-. The value of system_filter is expanded.
-
-. message_filter_directory_transport and message_filter_file_transport are now
-  both expanded before use. If the filter set up any file or pipe deliveries,
-  $address_file and $address_pipe are set as appropriate while doing the
-  expansions.
-
-. message_filter_directory2_transport has been removed. The effect of using
-  different directory-style transports can be achieved by specifying a suitable
-  expansion string to system_filter_directory_transport.
-
-. When a system filter added recipients to a message, Exim 3 added an
-  X-Envelope-To: header, listing the real recipients (up to 100). This has been
-  abolished because you can do this kind of thing using "headers_add" nowadays.
-
-. The "fail" command has been extended to allow for two different messages, one
-  for Exim's log and the other to be returned to the sender. The syntax is
-
-    fail "<<log message>>user message"
-
-  That is, if the first two characters of the message are "<<" the following
-  text, up to ">>", is written to the log, and the remainder is returned to the
-  user. If there is no log message, the user message is logged. The motivation
-  for this feature was to reduce the amount of text logged, while being able to
-  send quite long (maybe even multi-line) messages back to the sender.
-
-
-Changes to Lookups
-------------------
-
-. Oracle support is available. It works like the mysql and pgsql support,
-  except that there is no "database name" involved, and the "host name" field
-  is used for what is called "service name" in Oracle. This often looks like a
-  host name. Also, semicolons are not used at the end of an SQL query for
-  Oracle.
-
-. There's a new single-key lookup type called dsearch. It searches a directory
-  for a file whose name matches the key. The result of a successful search is
-  the key. One possible use of this could be for recognizing virtual domains.
-  If each domain is represented by a file whose name is the domain name, you
-  needn't make a separate list of the domains. You could test for them in an
-  ACL (see below), for example, by a line like this
-
-     accept domains = dsearch;/etc/virtual/domains
-
-. The format of LDAP output has been changed for cases where multiple
-  attributes are requested. The data for each attribute is now always quoted.
-  Within the quotes, the quote character, backslash, and newline are escaped
-  with backslashes and commas are used to separate multiple values for the
-  attribute. Thus, the string in quotes takes the same form as the output when
-  a single attribute is requested. If multiple entries are found, their data is
-  still separated by a newline.
-
-. There's a new expansion condition called ldapauth which exists so that the
-  LDAP authentication mechanism can be used for user authentication. It is
-  described under "string expansion" below.
-
-. Exim now supports ldaps:// URLs as well as ldap:// URLs. The former do LDAP
-  over TLS (i.e. encrypted) connections.
-
-. There is now support for the "whoson" mechanism for doing "POP-before-SMTP"
-  authentication. This is provided by new query-style lookup type called
-  "whoson", with queries that consist of IP addresses. For example, in an ACL
-  you can write
-
-    require condition = ${lookup whoson {$sender_host_address}{yes}{no}}
-
-
-Special items in domain and host lists
---------------------------------------
-
-. In a domain list, the special item @ matches the primary host name, and the
-  special item @[] matches any local interface address enclosed in square
-  brackets (as in domain literal email addresses). The special item @mx_any
-  matches any domain that has an MX record pointing to the local host. The
-  special items @mx_primary and @mx_secondary are similar, except that the
-  first matches only when the primary MX is to the local host, and the second
-  only when the primary MX is not the local host, but a secondary MX is.
-
-. In a host list, the special item @ matches the primary host name, and the
-  special item @[] matches any local interface address (not in brackets).
-
-
-Access Control Lists (ACLs)
----------------------------
-
-All the policy control options for incoming messages have been replaced by
-Access Control Lists (ACLs). These give more flexibility to the sysadmin, and
-allow the order of testing to be specified. For example, using an ACL, it is
-possible to specify "accept if authenticated, even if from an RBL host, but
-otherwise deny if from an RBL host", which is not possible in Exim 3.
-
-ACLs are defined in a new part of the configuration file, and given names.
-Which ones to run are controlled by a new set of options that are placed in the
-main part of the configuration.
-
-  acl_smtp_auth   specifies the ACL to run when AUTH is received
-  acl_smtp_data   specifies the ACL to run after a message has been received
-  acl_smtp_etrn   specifies the ACL to run when ETRN is received
-  acl_smtp_expn   specifies the ACL to run when EXPN is received
-  acl_smtp_rcpt   specifies the ACL to run when RCPT is received
-  acl_smtp_vrfy   specifies the ACL to run when VRFY is received
-
-The default actions vary. If acl_smtp_auth is not defined, AUTH is always
-accepted (and an attempt is made to authenticate the session). If acl_smtp_data
-is not defined, no checks are done after a message has been received, and it is
-always accepted at that point.
-
-However, if any of the others are not defined, the relevant SMTP command is
-rejected. In particular, this means that acl_smtp_rcpt must be defined in order
-to receive any messages over an SMTP connection. The default configuration file
-contains a suitable default for this.
-
-ACLs can be provided in line, or in files, or looked up from databases. One ACL
-can call another in a subroutine-like manner. String expansion is used, and
-which ACL to run can be varied according to sender host or any other criterion
-that a string expansion can test.
-
-This is not the place to give a full specification of ACLs, but here is a
-typical example for checking RCPT commands, taken from the default
-configuration. The tests are performed in order.
-
-acl_check_rcpt:
-  # Accept if source is local SMTP (i.e. not over TCP/IP - undefined host)
-  accept  hosts = :
-
-  # Deny if the local part contains @ or % or /
-  deny    local_parts   = ^.*[@%/]
-
-  # Accept mail to postmaster in any local domain, regardless of the source,
-  # and without verifying the sender.
-  accept  domains       = +local_domains
-          local_parts   = postmaster
-
-  # Deny unless the sender address can be verified.
-  require verify        = sender
-
-  # Accept if the address is in a local domain, but only if the recipient can
-  # be verified. Otherwise deny. The "endpass" line is the border between
-  # passing on to the next ACL statement (if tests above it fail) or denying
-  # access (if tests below it fail).
-  accept  domains       = +local_domains
-          endpass
-          message       = unknown user
-          verify        = recipient
-
-  # We get here only for non-local domains. Accept if the message arrived over
-  # an authenticated connection, from any host. These messages are usually from
-  # MUAs, so recipient verification is omitted.
-  accept  authenticated = *
-
-  # Reaching the end of the ACL causes a "deny", but we might as well give
-  # an explicit message.
-  deny    message       = relay not permitted
-
-The following options have been abolished as a consequence of the introduction
-of ACLs:
-
-auth_hosts, auth_over_tls_hosts, headers_checks_fail, headers_check_syntax,
-headers_sender_verify, headers_sender_verify_errmsg, host_accept_relay,
-host_auth_accept_relay, host_reject_recipients, prohibition_message,
-rbl_domains, rbl_hosts, rbl_log_headers, rbl_log_rcpt_count,
-rbl_reject_recipients, rbl_warn_header, receiver_try_verify, receiver_verify,
-receiver_verify_addresses, receiver_verify_hosts, receiver_verify_senders,
-recipients_reject_except, recipients_reject_except_senders, relay_domains,
-relay_domains_include_local_mx, relay_match_host_or_sender,
-sender_address_relay, sender_address_relay_hosts, sender_reject,
-sender_reject_recipients, sender_try_verify, sender_verify,
-sender_verify_batch, sender_verify_hosts, sender_verify_fixup,
-sender_verify_hosts_callback, sender_verify_callback_domains,
-sender_verify_callback_timeout, sender_verify_max_retry_rate,
-sender_verify_reject, smtp_etrn_hosts, smtp_expn_hosts. smtp_verify, tls_hosts.
-
-The variable $prohibition_reason has been abolished.
-
-The host_reject option has been retained, but with its name changed to
-host_reject_connection, to emphasize that it causes a rejection at connection
-time. I've left it available just in case it is needed - but its use is not
-recommended in normal circumstances.
-
-
-Other Incoming SMTP Session Controls
-------------------------------------
-
-. The option smtp_accept_max_per_connection (default 1000) limits the number of
-  messages accepted over a single SMTP connection. This is a safety catch in
-  case some sender goes mad (incidents of this kind have been seen). After the
-  limit is reached, a 421 response is given to MAIL commands.
-
-. Some sites find it helpful to be able to limit the rate at which certain
-  hosts can send them messages, and the rate at which an individual message can
-  specify recipients. There are now options for controlling these two different
-  rates.
-
-  Rate limiting applies only to those hosts that match smtp_ratelimit_hosts,
-  whose value is a host list. When a host matches, one or both of the options
-  smtp_ratelimit_mail and smtp_ratelimit_rcpt may be set. They apply to the
-  rate of acceptance of MAIL and RCPT commands in a single SMTP session,
-  respectively.
-
-  The value of each option is a set of four comma-separated values:
-
-    1. A threshold, before which there is no rate limiting.
-    2. An initial time delay. Unlike other times in Exim, fractions are allowed
-       here.
-    3. A factor by which to increase the delay each time.
-    4. A maximum value for the delay.
-
-  For example, these settings have been used successfully at the site which
-  first suggested this feature, for controlling mail from their customers:
-
-    smtp_ratelimit_mail = 2, 0.5s, 1.05, 4m
-    smtp_ratelimit_rcpt = 4, 0.25s, 1.015, 4m
-
-. The default value for smtp_connect_backlog has been increased to 20.
-
-. The SMTP protocol specification requires the client to wait for a response
-  from the server at certain points in the dialogue. (Without PIPELINING these
-  are after every command; with PIPELINING they are fewer, but still exist.)
-  Some spamming sites send out a complete set of SMTP commands without waiting
-  for any response. Exim 4 protects against this by rejecting messages if the
-  client has sent further input when it should not have. The error response
-  "554 SMTP synchronization error" is sent, and the connection is dropped.
-
-  This check is controlled by smtp_enforce_sync, which is true by default.
-
-. helo_strict_syntax has been abolished. The default is now to enforce strict
-  domain syntax for HELO/EHLO arguments. You can use helo_accept_junk_hosts if
-  you want to avoid this.
-
-. There's a new option called helo_lookup_domains. If the domain given in a
-  HELO or EHLO command matches this list, a reverse lookup is done in order to
-  establish the host's true name. The default setting is
-
-    helo_lookup_domains = @ : @[]
-
-  That is, a lookup is forced if the client host gives the server's name or
-  [one of its IP addresses] in HELO or EHLO. (In Exim 3 this happened
-  automatically and was not configurable.)
-
-. The value of the global message_size_limit option is now expanded. For
-  locally submitted messages this happens at the start of message reception.
-  For messages from remote hosts, the expansion is done just after the host
-  connects, so that the value can depend on the host.
-
-
-Handling of Resent- Fields
---------------------------
-
-RFC 2822 makes it clear that Resent- fields are purely informational. Exim used
-to make use of Resent-Reply-To: which does not actually exist, and it also used
-to use the last set of resent- fields for all the address fields it recognized.
-
-In Exim 4, resent- headers are dealt with as follows:
-
-. A Resent-From: header that just contains the login id as the address is
-  automatically rewritten in the same way as From: is (using qualify domain,
-  and user name from the passwd data).
-
-. If there's a rewrite rule for a header, it is also applied to resent- headers
-  of the same type. For example, a rule that rewrites From: headers also
-  rewrites Resent-From: headers.
-
-. For local messages, if Sender: is being removed on input, Resent-Sender: is
-  also removed.
-
-. If there are any resent- headers but no Resent-Date: or Resent-From: they are
-  added.
-
-. The logic for adding Sender: is now duplicated for Resent-Sender.
-
-. If there's no Resent-Message-Id: one is created, and it is the
-  Resent-Message-Id: which is included in the log line.
-
-
-Authentication
---------------
-
-. The auth_hosts option has been abolished; this functionality is now
-  controlled by ACLs.
-
-. The auth_always_advertise option has been abolished because it depended on
-  auth_hosts and host_auth_accept_relay, both of which are no more. In its
-  place there is a new option called auth_advertise_hosts, whose default value
-  is *, meaning "advertise AUTH to all".
-
-. The value of server_setid is now used when logging failed authentication
-  attempts.
-
-. The -oMaa option allows trusted users to set the value of
-  $sender_host_authenticated (the authenticator name). This is normally used in
-  conjunction with -oMa.
-
-
-Encryption
-----------
-
-. Because tls_hosts is no more, tls_advertise_hosts is now the only means of
-  controlling the advertisement of STARTTLS (previously, tls_hosts overrode).
-
-. The global option tls_verify_ciphers has been abolished. There are now
-  facilities for checking which cipher is in use in ACLs.
-
-. There's a new option called tls_try_verify_hosts. Like tls_verify_hosts, this
-  causes the server to request a certificate from a client, and it verifies the
-  certificate that it receives. However, unlike tls_verify_hosts, Exim
-  continues with the SMTP connection (encrypted) if a client certificate is not
-  received, or if the certificate does not verify. This state can be detected
-  in an ACL, which makes it possible to implement policies such as "accept for
-  relay only if a verified certificate has been received but accept for local
-  delivery if encrypted, even without a verified certificate".
-
-  A match in tls_verify_hosts overrides tls_try_verify_hosts.
-
-
-The Daemon
-----------
-
-. local_interfaces can now specify a port number with each address, thus
-  allowing a single Exim daemon to listen on multiple ports. The format of each
-  address is either [aaaa]:ppp or aaaa.ppp where aaaa is an IP address and ppp
-  is a port number. For example:
-
-    local_interfaces = 192.168.3.4.25 : 192.168.3.4.26
-
-  If an address is listed without a port, the setting of daemon_smtp_port, or
-  the value of the -oX option, is the default.
-
-. The -oX option can now override local_interfaces. That is, it can supply IP
-  addresses as well as just a port. It is interpreted in this way if its value
-  contains any of the characters . : or []. For example:
-
-  exim -bd -oX 10.9.8.7:10.11.12.13.2525
-
-  The format of the string is identical to the format recognized by the
-  local_interfaces option.
-
-. The way the daemon wrote PID files was overly complicated and messy. It no
-  longer tries to be clever. A PID file is written if, and only if, -bd is used
-  and -oX is _not_ used. In other words, only if the daemon is started with its
-  standard options. There is only one PID file. If pid_file_path is unset, it
-  is exim-daemon.pid in Exim's spool directory. Otherwise the value of
-  pid_file_path is used. For backwards compatibility, "%s" in this value is
-  replaced by an empty string.
-
-
-Logging
--------
-
-The log_level option and all the various independent logging control options
-have been abolished. In their place there is a single option called
-log_selector. It takes a string argument composed of names preceded by + or -
-characters. These turn on or off the logging of different things. For example:
-
-  log_selector = +arguments -retry_defer
-
-The optional logging items (defaults marked *) are:
-
-  address_rewrite             address rewriting
-  all_parents                 all parents in => lines
-  arguments                   exim arguments
- *connection_reject           connection rejections
- *delay_delivery              immediate delivery delayed (message queued)
-  delivery_size               add S=nnn to delivery lines
- *dnslist_defer               defers of DNS list (aka RBL) lookups
-  incoming_interface          incoming interface on <= lines
-  incoming_port               incoming port on <= lines
- *lost_incoming_connection    as it says (includes timeouts)
- *queue_run                   start and end queue runs
-  received_sender             sender on <= lines
-  received_recipients         recipients on <= lines
- *retry_defer                 "retry time not reached"
-  sender_on_delivery          add sender to => lines
- *size_reject                 rejection because too big
- *skip_delivery               "message is frozen"
-  smtp_confirmation           SMTP confirmation on <= lines
-  smtp_connection             SMTP connections
-  smtp_protocol_error         SMTP protocol errors
-  smtp_syntax_error           SMTP syntax errors
-  subject                     contents of Subject: on <= lines
- *tls_cipher                  TLS cipher on <= lines
-  tls_peerdn                  TLS peer DN on <= lines
-
-  all                         all of the above
-
-"retry time not reached" is always omitted from individual message logs after
-the first delivery attempt.
-
-The log line "error message sent to" has been abolished, because the R= item on
-the incoming message line gives the relationship between the original message
-and the bounce.
-
-The logging options that have been abolished are: log_all_parents,
-log_arguments, log_incoming_port, log_interface, log_ip_options,
-log_level, log_queue_run_level, log_received_sender, log_received_recipients,
-log_rewrites, log_sender_on_delivery, log_smtp_confirmation,
-log_smtp_connections, log_smtp_syntax_errors, log_subject, tls_log_cipher,
-tls_log_peerdn.
-
-
-Debugging
----------
-
-The debug_level option has been removed. The -dm option has been removed. The
--df option has also be removed, along with its related build-time option
-STDERR_FILE. (To debug inetd usage, an auxiliary script should be used.)
-
-The -d option has been reworked. It no longer takes a debug level number
-argument, but instead takes a list of debugging names, each preceded by + or -
-to turn on or off individual sets of debugging messages.
-
-. The -v option now shows just the SMTP dialog and any log lines.
-
-. -d with no argument gives a lot of standard debugging data. This is in effect
-  the equivalent of the old -d9, the thing you ask people to set for an initial
-  debugging test.
-
-. -d+x      adds debugging option x to the default set
-  -d-x      removes debugging option x from the default set
-  -d-all+x  leaves only debugging option x
-
-The available debugging names are:
-
-  acl            ACL interpretation
-  auth           authenticators
-  deliver        general delivery logic
-  dns            DNS lookups (see also resolver)
-  dnsbl          DNS black list (aka RBL) code
-  exec           arguments for execv() calls
-  filter         filter handling
-  hints_lookup   hints data lookups
-  host_lookup    all types of name->IP address handling
-  ident          ident lookup
-  interface      lists of local interfaces
-  lists          matching things in lists
-  load           system load checks
-  lookup         general lookup code and all lookups
-  memory         memory handling (replaces the old -dm)
-  process_info   setting info for the process log
-  queue_run      queue runs
-  receive        general message reception logic
-  resolver       turn on the DNS resolver's debugging output; goes to stdout
-  retry          retry handling
-  rewrite        rewriting
-  route          address routing
-  tls            TLS logic
-  transport      transports
-  uid            changes of uid/gid and looking up uid/gid
-  verify         address verification logic
-
-  all            all of the above, and also -v
-
-The default (-d with no argument) includes all of the above, plus -v, with the
-exception of filter, interface, load, memory, and resolver. Some debugging
-output always happens unconditionally whenever any debugging is selected. This
-includes some initial output and every log line.
-
--d without any value was previously allowed for non-admin users because it used
-to be synonymous with -v. In Exim 4, non-admin users may use -v, but not -d.
-
-If the debug_print option is set in any driver, it produces output whenever any
-debugging is selected, or if -v is used.
-
-
-Local Scan Function
--------------------
-
-For customized message scanning, you can now supply a C function that is linked
-into the Exim binary. The function is called local_scan(), and it is called
-when Exim has received a message, but has not yet sent a final
-acknowledgement to the sender. This applies to all messages, whether local or
-remote, SMTP or not.
-
-From within your function you can inspect the message, change the recipients,
-add or remove headers, and tell Exim whether to accept or reject the message.
-
-The manual contains the specification of the API for this function.
-
-
-String Expansion
-----------------
-
-. The lookup feature that allowed for subkeys using the syntax
-
-    ${lookup {key:subkey} type {data...
-
-  has been abolished (a) because the effect can be achieved using ${extract,
-  and (b) because in non-lsearch lookups, a colon can be a valid character in a
-  key.
-
-. When a string key is used in a ${extract expansion item, it is now handled
-  case-insensitively.
-
-. A new expansion variable called $tod_epoch gives the time as a single decimal
-  number representing the number of seconds from the start of the Unix epoch.
-
-. There's a new expansion operator that can turn numbers into base 62, for
-  example, ${base62:$tod_epoch}.
-
-. ${extract{number} now recognizes a negative number as a request to count
-  fields from the right.
-
-. There's a new expansion feature for reading files:
-
-    ${readfile{/some/file}{eolstring}}
-
-  The contents of the file replace the item. If {eolstring} is present (it's
-  optional) any newlines in the file are replaced by that string.
-
-. There's a new expansion feature for running commands:
-
-    ${run{command args}{yes}{no}}
-
-  Like all the other conditional items, the {yes} and {no} strings are
-  optional. Omitting both is equivalent to {$value}. The standard output of the
-  command is put into $value if the command succeeds (returns a zero code). The
-  value of the code itself is put into $runrc, and this remains set afterwards,
-  so in a filter file you can do things like
-
-    if "${run{x y z}{}}$runrc" is 1 then ...
-    elsif $runrc is 2 then ...
-
-  As in other command executions from Exim, a shell is not used by default.
-  If you want a shell, you must explicitly code it.
-
-. The redirect router has options for forbidding ${readfile and ${run in
-  filters.
-
-. A feature is provided to suppress expansion of part of a string. Any
-  characters between two occurrences of \N are copied to the output string
-  verbatim. This is particularly useful for protecting regular expressions from
-  unwanted expansion effects. For example:
-
-    queue_smtp_domains = ! \N^ten-\d+\.testing\.com$\N
-
-  Without \N the \ and $ characters in the regex would have to be escaped.
-
-. Radius authentication is supported in a similar way to PAM. You must set
-  RADIUS_CONFIG_FILE in Local/Makefile to specify the location of the Radius
-  client configuration file. Then you can use expansions such as
-
-    server_condition = ${if radius{arguments}{yes}{no}}
-
-. User authentication can now also be done by attempting to bind to an LDAP
-  server. The syntax is again similar to PAM and Radius.
-
-    server_condition = ${if ldapauth{ldap query}{yes}{no}}
-
-  A user and password are required to be supplied with the query. No actual
-  data is looked up; Exim just does a bind to the LDAP server and sets the
-  condition according to the result. Here's an example of an SMTP
-  authenticator:
-
-    login:
-      driver = plaintext
-      public_name = LOGIN
-      server_prompts = "Username:: : Password::"
-      server_condition = ${if ldapauth \
-        {user="uid=${quote_ldap:$1},ou=people,o=example.org" pass="$2" \
-        ldap://ldap.example.org/}{yes}{no}}
-      server_set_id = uid=$1,ou=people,o=example.org
-
-
-
-Security
---------
-
-Exim 3 could be run in a variety of ways as far as security was concerned. This
-has all been simplified in Exim 4. Exim dropped the use of seteuid() in
-most places. But recent (2020-10/2021-04) vulnerabilities forced us to
-re-introduce seteuid() for opening the database files (hint files) as secure as
-possible. For future (>= 4.95) versions we work on a solution that
-does not need the seteuid call.
-
-. A UID and GID are required to be specified when Exim is compiled. They can be
-  now specified by name as well as by number, so the relevant options are now
-  called EXIM_USER and EXIM_GROUP. If you really feel you have to run Exim as
-  root, you can specify root here, but it is not recommended.
-
-. The "security" option has been abolished. Exim always releases its root
-  privilege when it can. In a conventional configuration, that means when it is
-  receiving a message, when it is delivering a message, when it is running a
-  queryprogram router, and when it is obeying users' filter files (and system
-  filters if it has been given a user for that purpose).
-
-. One important change is that Exim 4 runs as root while routing addresses for
-  delivery. Exim 3 used seteuid() to give up privilege temporarily while
-  routing. Apart from the unliked use of seteuid(), this sometimes gave rise to
-  permissions problems on configuration files.
-
-. However, Exim still runs as the Exim user while receiving messages, and
-  therefore while using the routing logic for verifying at SMTP time.
-
-. There is a new option called deliver_drop_privilege. If this is set, Exim
-  gives up its privilege right at the start of a delivery process, and runs the
-  entire delivery as the Exim user. This is the same action that used to be
-  requested by setting security=unprivileged.
-
-
-Hints Databases
----------------
-
-. A single "misc" hints database is now used for ETRN and host serialization.
-  There have been appropriate consequential changes to the utilities for
-  managing the hints.
-
-. The exim_tidydb -f option has been abolished. A full tidy is now always done
-  (it hasn't proved to be very expensive).
-
-
-The run time Configuration File
-------------------------------
-
-. The format of the configuration file has changed. Instead of using "end" to
-  terminate sections, it now uses "begin <name>" to start sections. This means
-  that the sections, apart from the first, may appear in any order.
-
-. You can now include other files inside Exim run time configuration files, by
-  using this syntax:
-
-  .include <file name>
-
-. Quotes round the file name are optional. Includes may be nested to any depth,
-  but remember that Exim reads its configuration file often. The processing of
-  .include happens early, at a physical line level, so, like comment lines, it
-  can be used in the middle of an options setting, for example:
-
-  hosts_lookup = a.b.c \
-                 .include /some/file
-
-  Include processing happens _before_ macro processing. Its effect is simply to
-  process the lines of the file as if they occurred inline where the .include
-  appears.
-
-. A macro at the start of a configuration line can now turn the line into an
-  empty line or a comment line. This applies to _logical_ input lines, that is,
-  after any concatenations have been done.
-
-
-Format of spool files
----------------------
-
-. -local_scan is used in spool files to record the value of $local_scan_data,
-  the string returned from the locally-provided local_scan() function.
-
-
-Renamed Options
----------------
-
-Some options have been renamed, to make their function clearer, or for
-consistency.
-
-. receiver_unqualified_hosts has been renamed as recipient_unqualified_hosts.
-  I'm going to use "recipient" everywhere in future.
-
-. helo_verify has become helo_verify_hosts.
-
-. remote_sort has become remote_sort_domains.
-
-. In the appendfile and pipe transports, "prefix" and "suffix" have become
-  "message_prefix" and "message_suffix". In the generic router options,
-  "prefix" and "suffix" have become "local_part_prefix" and "local_part_suffix".
-
-
-Miscellaneous
--------------
-
-. ETRN serialization now uses a double fork, so that an Exim process (detached
-  from the original input process) can wait for the command to finish. This
-  means that it works whatever command ETRN causes to run. (Previously it
-  worked only if ETRN ran "exim -Rxxx".)
-
-. For incoming messages, the server's port number is preserved, and is
-  available in $interface_port. The privileged option -oMi can be used to
-  set this value.
-
-. The -Mmd option (to mark addresses delivered) now operates in a
-  case-sensitive manner.
-
-. Checks for duplicate deliveries are now case-sensitive in the local part.
-
-. The number of situations where Exim panics has been reduced. For example,
-  expansion failures for the "domains" or "local_parts" options in a router now
-  cause deferral instead of a panic.
-
-. EXPN no longer attempts to distinguish local and remote addresses (but you
-  can cause it to be rejected for certain arguments in the ACL).
-
-. accept_timeout has been renamed as receive_timeout, to match
-  smtp_receive_timeout.
-
-. The ability to check an ident value as part of an item in a host list has
-  been removed.
-
-. The reject log shows a message's headers only if the rejection happens after
-  the SMTP DATA command (because they aren't available for earlier checks). The
-  sender, and up to five recipients are listed in Envelope-from: and
-  Envelope-to: header lines. After the headers, a line of separator characters
-  is output. Separators are no longer used for other reject log entries.
-
-. Because header checks are now done as part of ACLs, they now apply only to
-  SMTP input.
-
-. The port number on SMTP connections is now logged in the format [aaaa]:ppp
-  where aaaa is an IP address and ppp is a port, instead of in the format
-  [aaaa.ppp] because the former format causes some software to complain about
-  bad IP addresses.
-
-. The -oMa and -oMi options can now use the [aaaa]:ppp notation to set a port
-  number, but they still also recognize the aaaa.ppp notation.
-
-. The build-time option HAVE_AUTH is abolished. Exim automatically includes
-  authentication code if any authenticators are configured.
-
-. The nobody_user and nobody_group options have been abolished.
-
-. The $message_precedence variable has been abolished. The value is now
-  available as $h_precedence:.
-
-. There's a new utility script called exim_checkaccess which packages up a call
-  to Exim with the -bh option, for access control checking. The syntax is
-
-    exim_checkaccess <IP address> <email address> [exim options]
-
-  It runs "exim -bh <IP address>", does the SMTP dialogue, tests the result and
-  outputs either "accepted" or "Rejected" and the SMTP response to the RCPT TO
-  command. The sender is <> by default, but can be changed by the use of the
-  -f option.
-
-. The default state of Exim is now to forbid domain literals. For this reason,
-  the option that changes this has been renamed as allow_domain_literals.
-
-. The dns_check_names boolean option has been abolished. Checking is now turned
-  off by unsetting dns_check_names_pattern.
-
-. The errors_address and freeze_tell_mailmaster options have been abolished. In
-  their place there is a new option called freeze_tell, which can be set to a
-  list of addresses. A message is sent to these addresses whenever a message is
-  frozen - with the exception of failed bounce messages (this is not changed).
-
-. The message_size_limit_count_recipients option has been abolished on the
-  grounds that it was a failed experiment.
-
-. The very-special-purpose X rewrite flag has been abolished. The facility it
-  provided can now be done using the features of ACLs.
-
-. The timestamps_utc option has been abolished. The facility is now provided by
-  setting timezone = utc.
-
-. The value of remote_max_parallel now defaults to 2.
-
-. ignore_errmsg_errors has been abolished. The effect can be achieved by
-  setting ignore_bounce_errors_after = 0s. This option has been renamed from
-  ignore_errmsg_errors_after to make its function clearer. The default value
-  for ignore_bounce_errors_after is now 10w (10 weeks - i.e. likely to be
-  longer than any other timeouts, thereby disabling the facility).
-
-. The default for message_size_limit is now 50M as a guard against DoS attacks.
-
-. The -qi option does only initial (first time) deliveries. This can be helpful
-  if you are injecting message onto the queue using -odq and want a queue
-  runner just to process new messages. You can also use -qqi if you want.
-
-. Rewriting and retry patterns are now anything that can be single address list
-  items. They are processed by the same code, and are therefore expanded before
-  the matching takes place. Regular expressions must be suitably quoted. These
-  patterns may now be enclosed in double quotes so that white space may be
-  included. Normal quote processing applies.
-
-. Some scripts were built in the util directory, which was a mistake, because
-  they might be different for different platforms. Everything that is built is
-  now built in the build directory. The util directory just contains a couple
-  of scripts that are not modified at build time.
-
-. The installation script now installs the Exim binary as exim-v.vv-bb (where
-  v.vv is the version number and bb is the build number), and points a symbolic
-  link called "exim" to this binary. It does this in an atomic way so that
-  there is no time when "exim" is non-existent. The script is clever enough to
-  cope with an existing non-symbolic-link binary, converting it to the new
-  scheme automatically (and atomically).
-
-. When installing utilities, Exim now uses cp instead of mv to add .O to the
-  old ones, in order to preserve the permissions.
-
-. If the installation script is installing the default configuration, and
-  /etc/aliases does not exist, the script installs a default version. This does
-  not actually contain any aliases, but it does contain comments about ones
-  that should be created. A warning is output to the user.
-
-. A delay warning message is not sent if all the addresses in a message get a
-  "retry time not reached" error. Exim waits until a delivery is actually
-  attempted, so as to be able to give a more informative message.
-
-. The existence of the three options deliver_load_max, queue_only_load, and
-  deliver_queue_load_max was confusing, because their function overlapped. The
-  first of them has been abolished. We are left with
-
-    queue_only_load         no immediate delivery if load is high when
-                            message arrives
-    deliver_queue_load_max  no queued delivery if load is too high
-
-. The ability to edit message bodies (-Meb and the Eximon menu item) has been
-  removed, on the grounds that it is bad practice to do this.
-
-. Eximstats is now Steve Campbell's patched version, which displays sizes in K
-  and M and G, and can optionally generate HTML.
-
-. If bounce_sender_authentication is set to an email address, this address is
-  used in an AUTH option of the MAIL command when sending bounce messages, if
-  authentication is being used. For example, if you set
-
-    bounce_sender_authentication = mailer-daemon@???
-
-  a bounce message will be sent over an authenticated connection using
-
-    MAIL FROM:<> AUTH=mailer-daemon@???
-
-. untrusted_set_sender has changed from a boolean to an address pattern. It
-  permits untrusted users to set sender addresses that match the pattern. Like
-  all address patterns, it is expanded. The identity of the user is in
-  $sender_ident, so you can, for example, restrict users to setting senders
-  that start with their login ids by setting
-
-    untrusted_set_sender = ^$sender_ident-
-
-  The effect of the previous boolean can be achieved by setting the value to *.
-  This option applies to all forms of local input.
-
-. The always_bcc option has been abolished. If an incoming message has no To:
-  or Cc: headers, Exim now always adds an empty Bcc: line. This makes the
-  message valid for RFC 822 (sic). In time, this can be removed, because RFC
-  2822 does not require there to be a recipient header.
-
-. ACTION_OUTPUT=no is now the default in the Exim monitor.
-
-. dns_ipv4_lookup has changed from a boolean into a domain list, and it now
-  applies only to those domains. Setting this option does not stop Exim from
-  making IPv6 calls: if an MX lookup returns AAAA records, Exim will use them.
-  What it does is to stop Exim looking for AAAA records explicitly.
-
-. The -G option is ignored (another Sendmail thing).
-
-. If no_bounce_return_message is set, the original message is not included in
-  bounce messages. If you want to include additional information in the bounce
-  message itself, you can use the existing errmsg_file and errmsg_text
-  facilities.
-
-. -bdf runs the daemon in the foreground (i.e. not detached from the terminal),
-  even when no debugging is requested.
-
-. Options for changing Exim's behaviour on receiving IPv4 options have been
-  abolished. Exim now always refuses calls that set these options, and logs the
-  incident. The abolished options are kill_ip_options, log_ip_options, and
-  refuse_ip_options.
-
-. The pattern for each errors_copy entry is now matched as an item in an
-  address list.
-
-. A number of options and variables that used the word "errmsg" have been
-  changed to use "bounce" instead, because it seems that "bounce message" is
-  now a reasonably well-understood term. I used it in the book and am now using
-  it in the manual; it's a lot less cumbersome than "delivery error
-  notification message". The changes are:
-
-  $errmsg_recipient          => $bounce_recipient
-  errmsg_file                => bounce_message_file
-  errmsg_text                => bounce_message_text
-  ignore_errmsg_errors_after => ignore_bounce_errors_after
-
-  For consistency, warnmsg_file has been changed to warn_message_file. However,
-  the two variables $warnmsg_delay and $warnmsg_recipients are unchanged.
-
-  The hide_child_in_errmsg option has not changed, because it applies to both
-  bounce and delay warning messages.
-
-. smtp_accept_max_per_host is now an expanded string, so it can be varied on
-  a per-host basis. However, because this test happens in the daemon before it
-  forks, the expansion should be kept as simple as possible (e.g. just inline
-  tests of $sender_host_address).
-
-. The retry rules can now recognize the error "auth_failed", which happens when
-  authentication is required, but cannot be done.
-
-. There's a new option called local_sender_retain which can be set if
-  no_local_from_check is set. It causes Sender: headers to be retained in
-  locally-submitted messages.
-
-. The -dropcr command line option now turns CRLF into LF, and leaves isolated
-  CRs alone. Previously it simply dropped _all_ CR characters. There is now
-  also a drop_cr main option which, if turned on, assumes -dropcr for all
-  non-SMTP input.
-
-
-Removal of Obsolete Things
---------------------------
-
-. The obsolete values "fail_soft" and "fail_hard" for the "self" option have
-  been removed.
-
-. The obsolete "log" command has been removed from the filter language.
-
-. "service" was an obsolete synonym for "port" when specifying IP port numbers.
-  It has been removed.
-
-. The obsolete option collapse_source_routes has been removed. It has done
-  nothing since release 3.10.
-
-. The obsolete from_hack option in appendfile and pipe transports has been
-  removed.
-
-. The obsolete ipv4_address_lookup has been abolished (dns_ipv4_lookup has been
-  a synonym for some time, but it's changed - see above).
-
-. The obsolete generic transport options add_headers and remove_headers have
-  been abolished. The new names, headers_add and headers_remove, have been
-  available for some time.
-
-Philip Hazel
-February 2002
diff --git a/src/OS/Makefile-Base b/src/OS/Makefile-Base
index a6354a4c9..1daded431 100644
--- a/src/OS/Makefile-Base
+++ b/src/OS/Makefile-Base
@@ -250,8 +250,7 @@ macro.c: macro_predef


 utils: $(EXIM_MONITOR) exicyclog exinext exiwhat \
         exigrep eximstats exipick exiqgrep exiqsumm \
-        transport-filter.pl convert4r3 convert4r4 \
-        exim_checkaccess \
+        transport-filter.pl exim_checkaccess \
         exim_dbmbuild exim_dumpdb exim_fixdb exim_tidydb \
     exim_lock exim_msgdate exim_id_update


@@ -490,30 +489,6 @@ transport-filter.pl: config ../src/transport-filter.src
     @chmod a+x transport-filter.pl
     @echo ">>> transport-filter.pl script built"


-convert4r3: config ../src/convert4r3.src
-    @rm -f convert4r3
-    @. ./version.sh && sed \
-      -e "s?PERL_COMMAND?$(PERL_COMMAND)?" \
-      -e "s?EXIM_RELEASE_VERSION?$${EXIM_RELEASE_VERSION}?" \
-      -e "s?EXIM_VARIANT_VERSION?$${EXIM_VARIANT_VERSION}?" \
-      ../src/convert4r3.src > convert4r3-t
-    @mv convert4r3-t convert4r3
-    @chmod a+x convert4r3
-    @./convert4r3 -v 2>&1 >/dev/null
-    @echo ">>> convert4r3 script built"
-
-convert4r4: config ../src/convert4r4.src
-    @rm -f convert4r4
-    @. ./version.sh && sed \
-      -e "s?PERL_COMMAND?$(PERL_COMMAND)?" \
-      -e "s?EXIM_RELEASE_VERSION?$${EXIM_RELEASE_VERSION}?" \
-      -e "s?EXIM_VARIANT_VERSION?$${EXIM_VARIANT_VERSION}?" \
-      ../src/convert4r4.src > convert4r4-t
-    @mv convert4r4-t convert4r4
-    @chmod a+x convert4r4
-    @./convert4r4 -v 2>&1 >/dev/null
-    @echo ">>> convert4r4 script built"
-


# These are objects of optional features. They are always compiled, but
# if the corresponding #defines are not set, they wind up empty and
diff --git a/src/README b/src/README
index e335cc22e..768eabbe8 100644
--- a/src/README
+++ b/src/README
@@ -10,7 +10,7 @@ published by UIT Cambridge in May 2003. This is the official guide for Exim 4.
The current edition covers release 4.10 and a few later extensions.

 The O'Reilly book about Exim ("Exim The Mail Transfer Agent" by Philip Hazel)
-covers Exim 3, which is now deprecated. Exim 4 has a large number of changes
+covers Exim 3, which is now obsolete. Exim 4 has a large number of changes
 from Exim 3, though the basic structure and philosophy remains the same. The
 older book may be helpful for the background, but a lot of the detail has
 changed, so it is likely to be confusing to newcomers.
diff --git a/src/src/convert4r3.src b/src/src/convert4r3.src
deleted file mode 100755
index d0b94d15e..000000000
--- a/src/src/convert4r3.src
+++ /dev/null
@@ -1,1382 +0,0 @@
-#! PERL_COMMAND
-
-# This is a Perl script that reads an Exim run-time configuration file and
-# checks for settings that were valid prior to release 3.00 but which were
-# obsoleted by that release. It writes a new file with suggested changes to
-# the standard output, and commentary about what it has done to stderr.
-
-# It is assumed that the input is a valid Exim configuration file.
-
-use warnings;
-BEGIN { pop @INC if $INC[-1] eq '.' };
-
-use Getopt::Long;
-use File::Basename;
-
-GetOptions(
-    'version' => sub {
-        print basename($0) . ": $0\n",
-            "build: EXIM_RELEASE_VERSIONEXIM_VARIANT_VERSION\n",
-            "perl(runtime): $^V\n";
-            exit 0;
-    },
-);
-
-##################################################
-#             Analyse one line                   #
-##################################################
-
-# This is called for the main and the driver sections, not for retry
-# or rewrite sections (which are unmodified).
-
-sub checkline{
-my($line) = $_[0];
-
-return "comment" if $line =~ /^\s*(#|$)/;
-return "end"     if $line =~ /^\s*end\s*$/;
-
-# Macros are recognized only in the first section of the file.
-
-return "macro" if $prefix eq "" && $line =~ /^\s*[A-Z]/;
-
-# Pick out the name at the start and the rest of the line (into global
-# variables) and return whether the start of a driver or not.
-
-($i1,$name,$i2,$rest) = $line =~ /^(\s*)([a-z0-9_]+)(\s*)(.*?)\s*$/;
-return ($rest =~ /^:/)? "driver" : "option";
-}
-
-
-
-
-##################################################
-#       Add transport setting to a director      #
-##################################################
-
-# This function adds a transport setting to an aliasfile or forwardfile
-# director if a global setting exists and a local one does not. If neither
-# exist, it adds file/pipe/reply, but not the directory ones.
-
-sub add_transport{
-my($option) = @_;
-
-my($key) = "$prefix$driver.${option}_transport";
-if (!exists $o{$key})
-  {
-  if (exists $o{"address_${option}_transport"})
-    {
-    print STDOUT "# >> Option added by convert4r3\n";
-    printf STDOUT "${i1}${option}_transport = %s\n",
-      $o{"address_${option}_transport"};
-    printf STDERR
-      "\n%03d ${option}_transport added to $driver director.\n",
-      ++$count;
-    }
-  else
-    {
-    if ($option eq "pipe" || $option eq "file" || $option eq "reply")
-      {
-      print STDOUT "# >> Option added by convert4r3\n";
-      printf STDOUT "${i1}${option}_transport = address_${option}\n";
-      printf STDERR
-        "\n%03d ${option}_transport added to $driver director.\n",
-        ++$count;
-      }
-    }
-  }
-}
-
-
-
-
-##################################################
-#       Negate a list of things                  #
-##################################################
-
-sub negate {
-my($list) = $_[0];
-
-return $list if ! defined $list;
-
-($list) = $list =~ /^"?(.*?)"?\s*$/s;
-
-# Under Perl 5.005 we can split very nicely at colons, ignoring double
-# colons, like this:
-#
-# @split = split /\s*(?<!:):(?!:)\s*(?:\\\s*)?/s, $list;
-#
-# However, we'd better make this work under Perl 5.004, since there is
-# a lot of that about.
-
-$list =~ s/::/>%%%%</g;
-@split = split /\s*:\s*(?:\\\s*)?/s, $list;
-foreach $item (@split)
-  {
-  $item =~ s/>%%%%</::/g;
-  }
-
-$" = " : \\\n    ! ";
-return "! @split";
-}
-
-
-
-
-
-##################################################
-#          Skip blank lines                      #
-##################################################
-
-# This function is called after we have generated no output for an option;
-# it skips subsequent blank lines if the previous line was blank.
-
-sub skipblanks {
-my($i) = $_[0];
-if ($last_was_blank)
-  {
-  $i++ while $c[$i+1] =~ /^\s*$/;
-  }
-return $i;
-}
-
-
-
-
-
-##################################################
-#       Get base name of data key                #
-##################################################
-
-sub base {
-return "$_[0]" if $_[0] !~ /^(?:d|r|t)\.[^.]+\.(.*)/;
-return $1;
-}
-
-
-
-##################################################
-#     Amalgamate accept/reject/reject_except     #
-##################################################
-
-# This function amalgamates the three previous kinds of
-# option into a single list, using negation for the middle one if
-# the final argument is "+", or for the outer two if the final
-# argument is "-".
-
-sub amalgamate {
-my($accept,$reject,$reject_except,$name);
-my($last_was_negated) = 0;
-my($join) = "";
-
-$accept = $o{$_[0]};
-$reject = $o{$_[1]};
-$reject_except = $o{$_[2]};
-$name = $_[3];
-
-if ($_[4] eq "+")
-  {
-  ($accept) = $accept =~ /^"?(.*?)"?\s*$/s if defined $accept;
-  $reject = &negate($reject) if defined $reject;
-  ($reject_except) = $reject_except =~ /^"?(.*?)"?\s*$/s if defined $reject_except;
-  }
-else
-  {
-  $accept = &negate($accept) if defined $accept;
-  ($reject) = $reject =~ /^"?(.*?)"?\s*$/s if defined $reject;
-  $reject_except = &negate($reject_except) if defined $reject_except;
-  }
-
-print STDOUT "# >> Option rewritten by convert4r3\n";
-print STDOUT "${i1}$name = \"";
-
-if (defined $reject_except)
-  {
-  print STDOUT "$reject_except";
-  $join = " : \\\n    ";
-  $last_was_negated = ($_[4] ne "+");
-  }
-if (defined $reject)
-  {
-  print STDOUT "$join$reject";
-  $join = " : \\\n    ";
-  $last_was_negated = ($_[4] eq "+");
-  }
-if (defined $accept)
-  {
-  print STDOUT "$join$accept";
-  $last_was_negated = ($_[4] ne "+");
-  $join = " : \\\n    ";
-  }
-
-print STDOUT "$join*" if $last_was_negated;
-
-print STDOUT "\"\n";
-
-my($driver_name);
-my($driver_type) = "";
-
-if ($_[0] =~ /^(d|r|t)\.([^.]+)\./ ||
-    $_[1] =~ /^(d|r|t)\.([^.]+)\./ ||
-    $_[2] =~ /^(d|r|t)\.([^.]+)\./)
-  {
-  $driver_type = ($1 eq 'd')? "director" : ($1 eq 'r')? "router" : "transport";
-  $driver_name = $2;
-  }
-
-my($x) = ($driver_type ne "")? " in \"$driver_name\" $driver_type" : "";
-
-my($l0) = &base($_[0]);
-my($l1) = &base($_[1]);
-my($l2) = &base($_[2]);
-
-
-if ($l2 eq "")
-  {
-  if ($l0 eq "")
-    {
-    printf STDERR "\n%03d $l1 converted to $name$x.\n", ++$count;
-    }
-  else
-    {
-    printf STDERR "\n%03d $l0 and $l1\n    amalgamated into $name$x.\n",
-      ++$count;
-    }
-  }
-else
-  {
-  if ($l1 eq "")
-    {
-    printf STDERR "\n%03d $l0 and $l2\n    amalgamated into $name$x.\n",
-      ++$count;
-    }
-  else
-    {
-    printf STDERR "\n%03d $l0, $l1 and $l2\n    amalgamated into " .
-      "$name$x.\n", ++$count;
-    }
-  }
-}
-
-
-
-
-##################################################
-#         Join two lists, if they exist          #
-##################################################
-
-sub pair{
-my($l1) = $o{"$_[0]"};
-my($l2) = $o{"$_[1]"};
-
-return $l2 if (!defined $l1);
-return $l1 if (!defined $l2);
-
-($l1) = $l1 =~ /^"?(.*?)"?\s*$/s;
-($l2) = $l2 =~ /^"?(.*?)"?\s*$/s;
-
-return "$l1 : $l2";
-}
-
-
-
-
-##################################################
-#  Amalgamate accept/reject/reject_except pairs  #
-##################################################
-
-# This is like amalgamate, but it combines pairs of arguments, and
-# doesn't output commentary (easier to write a generic one for the few
-# cases).
-
-sub amalgamatepairs {
-my($accept) = &pair($_[0], $_[1]);
-my($reject) = &pair($_[2], $_[3]);
-my($reject_except) = &pair($_[4], $_[5]);
-my($last_was_negated) = 0;
-my($join) = "";
-
-if ($_[7] eq "+")
-  {
-  ($accept) = $accept =~ /^"?(.*?)"?\s*$/s if defined $accept;
-  $reject = &negate($reject) if defined $reject;
-  ($reject_except) = $reject_except =~ /^"?(.*?)"?\s*$/s if defined $reject_except;
-  }
-else
-  {
-  $accept = &negate($accept) if defined $accept;
-  ($reject) = $reject =~ /^"?(.*?)"?$/s if defined $reject;
-  $reject_except = &negate($reject_except) if defined $reject_except;
-  }
-
-print STDOUT "# >> Option rewritten by convert4r3\n";
-print STDOUT "${i1}$_[6] = \"";
-
-if (defined $reject_except)
-  {
-  print STDOUT "$reject_except";
-  $join = " : \\\n    ";
-  $last_was_negated = ($_[7] ne "+");
-  }
-if (defined $reject)
-  {
-  print STDOUT "$join$reject";
-  $join = " : \\\n    ";
-  $last_was_negated = ($_[7] eq "+");
-  }
-if (defined $accept)
-  {
-  print STDOUT "$join$accept";
-  $last_was_negated = ($_[7] ne "+");
-  $join = " : \\\n    ";
-  }
-
-print STDOUT "$join*" if $last_was_negated;
-print STDOUT "\"\n";
-}
-
-
-
-##################################################
-#      Amalgamate boolean and exception list(s)  #
-##################################################
-
-sub amalgboolandlist {
-my($name,$bool,$e1,$e2) = @_;
-
-print STDOUT "# >> Option rewritten by convert4r3\n";
-if ($bool eq "false")
-  {
-  printf STDOUT "$i1$name =\n";
-  }
-else
-  {
-  printf STDOUT "$i1$name = ";
-  my($n1) = &negate($o{$e1});
-  my($n2) = &negate($o{$e2});
-  if (!defined $n1 && !defined $n2)
-    {
-    print STDOUT "*\n";
-    }
-  elsif (!defined $n1)
-    {
-    print STDOUT "\"$n2 : \\\n    *\"\n";
-    }
-  elsif (!defined $n2)
-    {
-    print STDOUT "\"$n1 : \\\n    *\"\n";
-    }
-  else
-    {
-    print STDOUT "\"$n1 : \\\n    $n2 : \\\n    *\"\n";
-    }
-  }
-}
-
-
-
-##################################################
-#             Convert mask format                #
-##################################################
-
-# This function converts an address and mask in old-fashioned dotted-quad
-# format into an address plus a new format mask.
-
-@byte_list = (0, 128, 192, 224, 240, 248, 252, 254, 255);
-
-sub mask {
-my($address,$mask) = @_;
-my($length) = 0;
-my($i, $j);
-
-my(@bytes) = split /\./, $mask;
-
-for ($i = 0; $i < 4; $i++)
-  {
-  for ($j = 0; $j <= 8; $j++)
-    {
-    if ($bytes[$i] == $byte_list[$j])
-      {
-      $length += $j;
-      if ($j != 8)
-        {
-        for ($i++; $i < 4; $i++)
-          {
-          $j = 9 if ($bytes[$i] != 0);
-          }
-        }
-      last;
-      }
-    }
-
-  if ($j > 8)
-    {
-    print STDERR "*** IP mask $mask cannot be converted to /n format. ***\n";
-    return "$address/$mask";
-    }
-  }
-
-if (!defined $masks{$mask})
-  {
-  printf STDERR "\n%03d IP address mask $mask converted to /$length\n",
-    ++$count, $mask, $length;
-  $masks{$mask} = 1;
-  }
-
-return sprintf "$address/%d", $length;
-}
-
-
-
-
-
-##################################################
-#                  Main program                  #
-##################################################
-
-print STDERR "Exim pre-release 3.00 configuration file converter.\n";
-
-$count = 0;
-$seen_helo_accept_junk = 0;
-$seen_hold_domains = 0;
-$seen_receiver_unqualified = 0;
-$seen_receiver_verify_except = 0;
-$seen_receiver_verify_senders = 0;
-$seen_rfc1413_except = 0;
-$seen_sender_accept = 0;
-$seen_sender_accept_recipients = 0;
-$seen_sender_host_accept = 0;
-$seen_sender_host_accept_recipients = 0;
-$seen_sender_host_accept_relay = 0;
-$seen_sender_unqualified = 0;
-$seen_sender_verify_except_hosts = 0;
-$seen_smtp_etrn = 0;
-$seen_smtp_expn = 0;
-$seen_smtp_reserve = 0;
-$semicomma = 0;
-
-# Read the entire file into an array
-
-chomp(@c = <STDIN>);
-
-# First, go through the input and covert any net masks in the old dotted-quad
-# style into the new /n style.
-
-for ($i = 0; $i < scalar(@c); $i++)
-  {
-  $c[$i] =~
-    s"((?:\d{1,3}\.){3}\d{1,3})/((?:\d{1,3}\.){3}\d{1,3})"&mask($1,$2)"eg;
-  }
-
-# We now make two more passes over the input. In the first pass, we place all
-# the option values into an associative array. Main options are keyed by their
-# names; options for drivers are keyed by a driver type letter, the driver
-# name, and the option name, dot-separated. In the second pass we modify
-# the options if necessary, and write the output file.
-
-for ($pass = 1; $pass < 3; $pass++)
-  {
-  $prefix = "";
-  $driver = "";
-  $last_was_blank = 0;
-
-  for ($i = 0; $i < scalar(@c); $i++)
-    {
-    # Everything after the router section is just copied in pass 2 and
-    # ignored in pass 1.
-
-    if ($prefix eq "end")
-      {
-      print STDOUT "$c[$i]\n" if $pass == 2;
-      next;
-      }
-
-    # Analyze the line
-
-    $type = &checkline($c[$i]);
-
-    # Skip comments in pass 1; copy in pass 2
-
-    if ($type eq "comment")
-      {
-      $last_was_blank = ($c[$i] =~ /^\s*$/)? 1 : 0;
-      print STDOUT "$c[$i]\n" if $pass == 2;
-      next;
-      }
-
-    # Skip/copy macro definitions, but must handle continuations
-
-    if ($type eq "macro")
-      {
-      print STDOUT "$c[$i]\n" if $pass == 2;
-      while ($c[$i] =~ /\\\s*$/)
-        {
-        $i++;
-        print STDOUT "$c[$i]\n" if $pass == 2;
-        }
-      $last_was_blank = 0;
-      next;
-      }
-
-    # Handle end of section
-
-    if ($type eq "end")
-      {
-      $prefix = "end"if $prefix eq "r.";
-      $prefix = "r." if $prefix eq "d.";
-      $prefix = "d." if $prefix eq "t.";
-      $prefix = "t." if $prefix eq "";
-      print STDOUT "$c[$i]\n" if $pass == 2;
-      $last_was_blank = 0;
-      next;
-      }
-
-    # Handle start of a new driver
-
-    if ($type eq "driver")
-      {
-      $driver = $name;
-      print STDOUT "$c[$i]\n" if $pass == 2;
-      $last_was_blank = 0;
-      $seen_domains = 0;
-      $seen_local_parts = 0;
-      $seen_senders = 0;
-      $seen_mx_domains = 0;
-      $seen_serialize = 0;
-      next;
-      }
-
-    # Handle definition of an option
-
-    if ($type eq "option")
-      {
-      # Handle continued strings
-
-      if ($rest =~ /^=\s*".*\\$/)
-        {
-        for (;;)
-          {
-          $rest .= "\n$c[++$i]";
-          last unless $c[$i] =~ /(\\\s*$|^\s*#)/;
-          }
-        }
-
-      # Remove any terminating commas and semicolons in pass 2
-
-      if ($pass == 2 && $rest =~ /[;,]\s*$/)
-        {
-        $rest =~ s/\s*[;,]\s*$//;
-        if (!$semicomma)
-          {
-          printf STDERR
-            "\n%03d Terminating semicolons and commas removed from driver " .
-            "options.\n", ++$count;
-          $semicomma = 1;
-          }
-        }
-
-      # Convert all booleans to "x = true/false" format, but save the
-      # original so that it can be reproduced unchanged for options that
-      # are not of interest.
-
-      $origname = $name;
-      $origrest = $rest;
-
-      if ($name =~ /^not?_(.*)/)
-        {
-        $name = $1;
-        $rest = "= false";
-        }
-      elsif ($rest !~ /^=/)
-        {
-        $rest = "= true";
-        }
-
-      # Set up the associative array key, and get rid of the = on the data
-
-      $key = ($prefix eq "")? "$name" : "$prefix$driver.$name";
-      ($rest) = $rest =~ /^=\s*(.*)/s;
-
-      # Create the associative array of values in pass 1
-
-      if ($pass == 1)
-        {
-        $o{$key} = $rest;
-        }
-
-      # In pass 2, test for interesting options and do the necessary; copy
-      # all the rest.
-
-      else
-        {
-        ##########  Global configuration ##########
-
-        # These global options are abolished
-
-        if ($name eq "address_directory_transport" ||
-            $name eq "address_directory2_transport" ||
-            $name eq "address_file_transport" ||
-            $name eq "address_pipe_transport" ||
-            $name eq "address_reply_transport")
-          {
-          ($n2) = $name =~ /^address_(.*)/;
-          printf STDERR "\n%03d $name option deleted.\n", ++$count;
-          printf STDERR "    $n2 will be added to appropriate directors.\n";
-          $i = &skipblanks($i);
-          next;
-          }
-
-        # This debugging option is abolished
-
-        elsif ($name eq "sender_verify_log_details")
-          {
-          printf STDERR "\n%03d $name option deleted.\n", ++$count;
-          printf STDERR "    (Little used facility abolished.)\n";
-          }
-
-        # This option has been renamed
-
-        elsif ($name eq "check_dns_names")
-          {
-          $origname =~ s/check_dns/dns_check/;
-          print STDOUT "# >> Option rewritten by convert4r3\n";
-          print STDOUT "$i1$origname$i2$origrest\n";
-          printf STDERR "\n%03d check_dns_names renamed as dns_check_names.\n",
-            ++$count;
-          }
-
-        # helo_accept_junk_nets is abolished
-
-        elsif ($name eq "helo_accept_junk_nets" ||
-               $name eq "helo_accept_junk_hosts")
-          {
-          if (!$seen_helo_accept_junk)
-            {
-            &amalgamate("helo_accept_junk_nets", "",
-              "helo_accept_junk_hosts", "helo_accept_junk_hosts", "+");
-            $seen_helo_accept_junk = 1;
-            }
-          else
-            {
-            $i = &skipblanks($i);
-            next;
-            }
-          }
-
-        # helo_verify_except_{hosts,nets} are abolished, and helo_verify
-        # is now a host list instead of a boolean.
-
-        elsif ($name eq "helo_verify")
-          {
-          &amalgboolandlist("helo_verify", $rest, "helo_verify_except_hosts",
-            "helo_verify_except_nets");
-          printf STDERR "\n%03d helo_verify converted to host list.\n",
-            ++$count;
-          }
-        elsif ($name eq "helo_verify_except_hosts" ||
-               $name eq "helo_verify_except_nets")
-          {
-          $i = &skipblanks($i);
-          next;
-          }
-
-        # helo_verify_nets was an old synonym for host_lookup_nets; only
-        # one of them will be encountered. Change to a new name.
-
-        elsif ($name eq "helo_verify_nets" ||
-               $name eq "host_lookup_nets")
-          {
-          print STDOUT "# >> Option rewritten by convert4r3\n";
-          print STDOUT "${i1}host_lookup$i2$origrest\n";
-          printf STDERR "\n%03d $name renamed as host_lookup.\n", ++$count;
-          }
-
-        # hold_domains_except is abolished; add as negated items to
-        # hold_domains.
-
-        elsif ($name eq "hold_domains_except" ||
-               $name eq "hold_domains")
-          {
-          if ($seen_hold_domains)         # If already done with these
-            {                             # omit, and following blanks.
-            $i = &skipblanks($i);
-            next;
-            }
-          $seen_hold_domains = 1;
-
-          if (exists $o{"hold_domains_except"})
-            {
-            &amalgamate("hold_domains", "hold_domains_except", "",
-              "hold_domains", "+");
-            }
-          else
-            {
-            print STDOUT "$i1$origname$i2$origrest\n";
-            }
-          }
-
-        # ignore_fromline_nets is renamed as ignore_fromline_hosts
-
-        elsif ($name eq "ignore_fromline_nets")
-          {
-          $origname =~ s/_nets/_hosts/;
-          print STDOUT "# >> Option rewritten by convert4r3\n";
-          print STDOUT "$i1$origname$i2$origrest\n";
-          printf STDERR
-            "\n%03d ignore_fromline_nets renamed as ignore_fromline_hosts.\n",
-            ++$count;
-          }
-
-        # Output a warning for message filters with no transports set
-
-        elsif ($name eq "message_filter")
-          {
-          print STDOUT "$i1$origname$i2$origrest\n";
-
-          if (!exists $o{"message_filter_directory_transport"} &&
-              !exists $o{"message_filter_directory2_transport"} &&
-              !exists $o{"message_filter_file_transport"} &&
-              !exists $o{"message_filter_pipe_transport"} &&
-              !exists $o{"message_filter_reply_transport"})
-            {
-            printf STDERR
-              "\n%03d message_filter is set, but no message_filter transports "
-              . "are defined.\n"
-              . "    If your filter generates file or pipe deliveries, or "
-              . "auto-replies,\n"
-              . "    you will need to define "
-              . "message_filter_{file,pipe,reply}_transport\n"
-              . "    options, as required.\n", ++$count;
-            }
-          }
-
-        # queue_remote_except is abolished, and queue_remote is replaced by
-        # queue_remote_domains, which is a host list.
-
-        elsif ($name eq "queue_remote")
-          {
-          &amalgboolandlist("queue_remote_domains", $rest,
-            "queue_remote_except", "");
-          printf STDERR
-            "\n%03d queue_remote converted to domain list queue_remote_domains.\n",
-            ++$count;
-          }
-        elsif ($name eq "queue_remote_except")
-          {
-          $i = &skipblanks($i);
-          next;
-          }
-
-        # queue_smtp_except is abolished, and queue_smtp is replaced by
-        # queue_smtp_domains, which is a host list.
-
-        elsif ($name eq "queue_smtp")
-          {
-          &amalgboolandlist("queue_smtp_domains", $rest,
-            "queue_smtp_except", "");
-          printf STDERR
-            "\n%03d queue_smtp converted to domain list queue_smtp_domains.\n",
-            ++$count;
-          }
-        elsif ($name eq "queue_smtp_except")
-          {
-          $i = &skipblanks($i);
-          next;
-          }
-
-        # rbl_except_nets is replaced by rbl_hosts
-
-        elsif ($name eq "rbl_except_nets")
-          {
-          &amalgamate("", "rbl_except_nets", "", "rbl_hosts", "+");
-          }
-
-        # receiver_unqualified_nets is abolished
-
-        elsif ($name eq "receiver_unqualified_nets" ||
-               $name eq "receiver_unqualified_hosts")
-          {
-          if (!$seen_receiver_unqualified)
-            {
-            &amalgamate("receiver_unqualified_nets", "",
-              "receiver_unqualified_hosts", "receiver_unqualified_hosts", "+");
-            $seen_receiver_unqualified = 1;
-            }
-          else
-            {
-            $i = &skipblanks($i);
-            next;
-            }
-          }
-
-        # receiver_verify_except_{hosts,nets} are replaced by
-        # receiver_verify_hosts.
-
-        elsif ($name eq "receiver_verify_except_hosts" ||
-               $name eq "receiver_verify_except_nets")
-          {
-          if (!$seen_receiver_verify_except)
-            {
-            &amalgboolandlist("receiver_verify_hosts", "true",
-              "receiver_verify_except_hosts", "receiver_verify_except_nets");
-            printf STDERR
-              "\n%03d receiver_verify_except_{hosts,nets} converted to " .
-              "receiver_verify_hosts.\n",
-              ++$count;
-            $seen_receiver_verify_except = 1;
-            }
-          else
-            {
-            $i = &skipblanks($i);
-            next;
-            }
-          }
-
-        # receiver_verify_senders_except is abolished
-
-        elsif ($name eq "receiver_verify_senders" ||
-               $name eq "receiver_verify_senders_except")
-          {
-          if (defined $o{"receiver_verify_senders_except"})
-            {
-            if (!$seen_receiver_verify_senders)
-              {
-              &amalgamate("receiver_verify_senders",
-                "receiver_verify_senders_except", "",
-                "receiver_verify_senders", "+");
-              $seen_receiver_verify_senders = 1;
-              }
-            else
-              {
-              $i = &skipblanks($i);
-              next;
-              }
-            }
-          else
-            {
-            print STDOUT "$i1$origname$i2$origrest\n";
-            }
-          }
-
-        # rfc1413_except_{hosts,nets} are replaced by rfc1413_hosts.
-
-        elsif ($name eq "rfc1413_except_hosts" ||
-               $name eq "rfc1413_except_nets")
-          {
-          if (!$seen_rfc1413_except)
-            {
-            &amalgboolandlist("rfc1413_hosts", "true",
-              "rfc1413_except_hosts", "rfc1413_except_nets");
-            printf STDERR
-              "\n%03d rfc1413_except_{hosts,nets} converted to rfc1413_hosts.\n",
-              ++$count;
-            $seen_rfc1413_except = 1;
-            }
-          else
-            {
-            $i = &skipblanks($i);
-            next;
-            }
-          }
-
-        # sender_accept and sender_reject_except are abolished
-
-        elsif ($name eq "sender_accept" ||
-               $name eq "sender_reject")
-          {
-          if (!$seen_sender_accept)
-            {
-            &amalgamate("sender_accept", "sender_reject",
-              "sender_reject_except", "sender_reject", "-");
-            $seen_sender_accept = 1;
-            }
-          else
-            {
-            $i = &skipblanks($i);
-            next;
-            }
-          }
-
-        # sender_accept_recipients is also abolished; sender_reject_except
-        # also used to apply to this, so we include it here as well.
-
-        elsif ($name eq "sender_accept_recipients" ||
-               $name eq "sender_reject_recipients")
-          {
-          if (!$seen_sender_accept_recipients)
-            {
-            &amalgamate("sender_accept_recipients", "sender_reject_recipients",
-              "sender_reject_except", "sender_reject_recipients", "-");
-            $seen_sender_accept_recipients = 1;
-            }
-          else
-            {
-            $i = &skipblanks($i);
-            next;
-            }
-          }
-
-        # sender_reject_except must be removed
-
-        elsif ($name eq "sender_reject_except")
-          {
-          $i = &skipblanks($i);
-          next;
-          }
-
-        # sender_{host,net}_{accept,reject}[_except] all collapse into
-        # host_reject.
-
-        elsif ($name eq "sender_host_accept" ||
-               $name eq "sender_net_accept" ||
-               $name eq "sender_host_reject" ||
-               $name eq "sender_net_reject")
-          {
-          if (!$seen_sender_host_accept)
-            {
-            &amalgamatepairs("sender_host_accept", "sender_net_accept",
-              "sender_host_reject", "sender_net_reject",
-              "sender_host_reject_except", "sender_net_reject_except",
-              "host_reject", "-");
-            printf STDERR "\n%03d sender_{host,net}_{accept,reject} and " .
-              "sender_{host_net}_reject_except\n" .
-              "    amalgamated into host_reject.\n", ++$count;
-            $seen_sender_host_accept = 1;
-            }
-          else
-            {
-            $i = &skipblanks($i);
-            next;
-            }
-          }
-
-        # sender_{host,net}_{accept,reject}_recipients all collapse into
-        # host_reject_recipients.
-
-        elsif ($name eq "sender_host_accept_recipients" ||
-               $name eq "sender_net_accept_recipients" ||
-               $name eq "sender_host_reject_recipients" ||
-               $name eq "sender_net_reject_recipients")
-          {
-          if (!$seen_sender_host_accept_recipients)
-            {
-            &amalgamatepairs("sender_host_accept_recipients",
-              "sender_net_accept_recipients",
-              "sender_host_reject_recipients",
-              "sender_net_reject_recipients",
-              "sender_host_reject_except", "sender_net_reject_except",
-              "host_reject_recipients", "-");
-            printf STDERR "\n%03d sender_{host,net}_{accept,reject}_recipients"
-              . "\n    and sender_{host_net}_reject_except"
-              . "\n    amalgamated into host_reject_recipients.\n", ++$count;
-            $seen_sender_host_accept_recipients = 1;
-            }
-          else
-            {
-            $i = &skipblanks($i);
-            next;
-            }
-          }
-
-        # sender_{host,net}_reject_except must be removed
-
-        elsif ($name eq "sender_host_reject_except" ||
-               $name eq "sender_net_reject_except")
-          {
-          $i = &skipblanks($i);
-          next;
-          }
-
-        # sender_{host,net}_{accept,reject}_relay all collapse into
-        # host_accept_relay.
-
-        elsif ($name eq "sender_host_accept_relay" ||
-               $name eq "sender_net_accept_relay" ||
-               $name eq "sender_host_reject_relay" ||
-               $name eq "sender_net_reject_relay")
-          {
-          if (!$seen_sender_host_accept_relay)
-            {
-            &amalgamatepairs("sender_host_accept_relay",
-              "sender_net_accept_relay",
-              "sender_host_reject_relay",
-              "sender_net_reject_relay",
-              "sender_host_reject_relay_except",
-              "sender_net_reject_relay_except",
-              "host_accept_relay", "+");
-            printf STDERR "\n%03d sender_{host,net}_{accept,reject}_relay"
-              . "\n    and sender_{host_net}_reject_relay_except"
-              . "\n    amalgamated into host_accept_relay.\n", ++$count;
-            $seen_sender_host_accept_relay = 1;
-            }
-          else
-            {
-            $i = &skipblanks($i);
-            next;
-            }
-          }
-
-        # sender_{host,net}_reject_relay_except must be removed
-
-        elsif ($name eq "sender_host_reject_relay_except" ||
-               $name eq "sender_net_reject_relay_except")
-          {
-          $i = &skipblanks($i);
-          next;
-          }
-
-
-        # sender_unqualified_nets is abolished
-
-        elsif ($name eq "sender_unqualified_nets" ||
-               $name eq "sender_unqualified_hosts")
-          {
-          if (!$seen_sender_unqualified)
-            {
-            &amalgamate("sender_unqualified_nets", "",
-              "sender_unqualified_hosts", "sender_unqualified_hosts", "+");
-            $seen_sender_unqualified = 1;
-            }
-          else
-            {
-            $i = &skipblanks($i);
-            next;
-            }
-          }
-
-        # sender_verify_except_{hosts,nets} are replaced by sender_verify_hosts.
-
-        elsif ($name eq "sender_verify_except_hosts" ||
-               $name eq "sender_verify_except_nets")
-          {
-          if (!$seen_sender_verify_except_hosts)
-            {
-            &amalgboolandlist("sender_verify_hosts", "true",
-              "sender_verify_except_hosts", "sender_verify_except_nets");
-            printf STDERR
-              "\n%03d sender_verify_except_{hosts,nets} converted to " .
-              "sender_verify_hosts.\n",
-              ++$count;
-            $seen_sender_verify_except_hosts = 1;
-            }
-          else
-            {
-            $i = &skipblanks($i);
-            next;
-            }
-          }
-
-        # smtp_etrn_nets is abolished
-
-        elsif ($name eq "smtp_etrn_nets" ||
-               $name eq "smtp_etrn_hosts")
-          {
-          if (!$seen_smtp_etrn)
-            {
-            &amalgamate("smtp_etrn_nets", "",
-              "smtp_etrn_hosts", "smtp_etrn_hosts", "+");
-            $seen_smtp_etrn = 1;
-            }
-          else
-            {
-            $i = &skipblanks($i);
-            next;
-            }
-          }
-
-        # smtp_expn_nets is abolished
-
-        elsif ($name eq "smtp_expn_nets" ||
-               $name eq "smtp_expn_hosts")
-          {
-          if (!$seen_smtp_expn)
-            {
-            &amalgamate("smtp_expn_nets", "",
-              "smtp_expn_hosts", "smtp_expn_hosts", "+");
-            $seen_smtp_expn = 1;
-            }
-          else
-            {
-            $i = &skipblanks($i);
-            next;
-            }
-          }
-
-        # This option has been renamed
-
-        elsif ($name eq "smtp_log_connections")
-          {
-          $origname =~ s/smtp_log/log_smtp/;
-          print STDOUT "# >> Option rewritten by convert4r3\n";
-          print STDOUT "$i1$origname$i2$origrest\n";
-          printf STDERR "\n%03d smtp_log_connections renamed as " .
-            "log_smtp_connections.\n",
-            ++$count;
-          }
-
-        # smtp_reserve_nets is abolished
-
-        elsif ($name eq "smtp_reserve_nets" ||
-               $name eq "smtp_reserve_hosts")
-          {
-          if (!$seen_smtp_reserve)
-            {
-            &amalgamate("smtp_reserve_nets", "",
-              "smtp_reserve_hosts", "smtp_reserve_hosts", "+");
-            $seen_smtp_reserve = 1;
-            }
-          else
-            {
-            $i = &skipblanks($i);
-            next;
-            }
-          }
-
-        ###########  Driver configurations  ##########
-
-        # For aliasfile and forwardfile directors, add file, pipe, and
-        # reply transports - copying from the globals if they are set.
-
-        elsif ($name eq "driver")
-          {
-          $driver_type = $rest;
-          print STDOUT "$i1$origname$i2$origrest\n";
-          if ($rest eq "aliasfile" || $rest eq "forwardfile")
-            {
-            &add_transport("directory");
-            &add_transport("directory2");
-            &add_transport("file");
-            &add_transport("pipe");
-            &add_transport("reply") if $rest eq "forwardfile";
-            }
-          }
-
-        # except_domains is abolished; add as negated items to domains.
-
-        elsif ($name eq "except_domains" ||
-               $name eq "domains")
-          {
-          if ($seen_domains)              # If already done with these
-            {                             # omit, and following blanks.
-            $i = &skipblanks($i);
-            next;
-            }
-          $seen_domains = 1;
-
-          if (exists $o{"$prefix$driver.except_domains"})
-            {
-            &amalgamate("$prefix$driver.domains",
-                         "$prefix$driver.except_domains", "",
-              "domains", "+");
-            }
-          else
-            {
-            print STDOUT "$i1$origname$i2$origrest\n";
-            }
-          }
-
-        # except_local_parts is abolished; add as negated items to
-        # local_parts.
-
-        elsif ($name eq "except_local_parts" ||
-               $name eq "local_parts")
-          {
-          if ($seen_local_parts)              # If already done with these
-            {                             # omit, and following blanks.
-            $i = &skipblanks($i);
-            next;
-            }
-          $seen_local_parts = 1;
-
-          if (exists $o{"$prefix$driver.except_local_parts"})
-            {
-            &amalgamate("$prefix$driver.local_parts",
-                         "$prefix$driver.except_local_parts", "",
-              "local_parts", "+");
-            }
-          else
-            {
-            print STDOUT "$i1$origname$i2$origrest\n";
-            }
-          }
-
-        # except_senders is abolished; add as negated items to senders
-
-        elsif ($name eq "except_senders" ||
-               $name eq "senders")
-          {
-          if ($seen_senders)              # If already done with these
-            {                             # omit, and following blanks.
-            $i = &skipblanks($i);
-            next;
-            }
-          $seen_senders = 1;
-
-          if (exists $o{"$prefix$driver.except_senders"})
-            {
-            &amalgamate("$prefix$driver.senders",
-                         "$prefix$driver.except_senders", "",
-              "senders", "+");
-            }
-          else
-            {
-            print STDOUT "$i1$origname$i2$origrest\n";
-            }
-          }
-
-        # This option has been renamed
-
-        elsif ($name eq "directory" && $driver_type eq "aliasfile")
-          {
-          $origname =~ s/directory/home_directory/;
-          print STDOUT "# >> Option rewritten by convert4r3\n";
-          print STDOUT "$i1$origname$i2$origrest\n";
-          printf STDERR "\n%03d directory renamed as " .
-            "home_directory in \"$driver\" director.\n",
-            ++$count;
-          }
-
-        # This option has been renamed
-
-        elsif ($name eq "directory" && $driver_type eq "forwardfile")
-          {
-          $origname =~ s/directory/file_directory/;
-          print STDOUT "# >> Option rewritten by convert4r3\n";
-          print STDOUT "$i1$origname$i2$origrest\n";
-          printf STDERR "\n%03d directory renamed as " .
-            "file_directory in \"$driver\" director.\n",
-            ++$count;
-          }
-
-        # This option has been renamed
-
-        elsif ($name eq "forbid_filter_log" && $driver_type eq "forwardfile")
-          {
-          $origname =~ s/log/logwrite/;
-          print STDOUT "# >> Option rewritten by convert4r3\n";
-          print STDOUT "$i1$origname$i2$origrest\n";
-          printf STDERR "\n%03d forbid_filter_log renamed as " .
-            "forbid_filter_logwrite in \"$driver\" director.\n",
-            ++$count;
-          }
-
-        # This option has been renamed
-
-        elsif ($name eq "directory" && $driver_type eq "localuser")
-          {
-          $origname =~ s/directory/match_directory/;
-          print STDOUT "# >> Option rewritten by convert4r3\n";
-          print STDOUT "$i1$origname$i2$origrest\n";
-          printf STDERR "\n%03d directory renamed as " .
-            "match_directory in \"$driver\" director.\n",
-            ++$count;
-          }
-
-        # mx_domains_except (and old synonym non_mx_domains) are abolished
-        # (both lookuphost router and smtp transport)
-
-        elsif ($name eq "mx_domains" ||
-               $name eq "mx_domains_except" ||
-               $name eq "non_mx_domains")
-          {
-          if ($seen_mx_domains)              # If already done with these
-            {                             # omit, and following blanks.
-            $i = &skipblanks($i);
-            next;
-            }
-          $seen_mx_domains = 1;
-
-          if (exists $o{"$prefix$driver.mx_domains_except"} ||
-              exists $o{"$prefix$driver.non_mx_domains"})
-            {
-            $o{"$prefix$driver.mx_domains_except"} =
-              &pair("$prefix$driver.mx_domains_except",
-                    "$prefix$driver.non_mx_domains");
-
-            &amalgamate("$prefix$driver.mx_domains",
-                        "$prefix$driver.mx_domains_except", "",
-              "mx_domains", "+");
-            }
-          else
-            {
-            print STDOUT "$i1$origname$i2$origrest\n";
-            }
-          }
-
-        # This option has been renamed
-
-        elsif ($name eq "directory" && $driver_type eq "pipe")
-          {
-          $origname =~ s/directory/home_directory/;
-          print STDOUT "# >> Option rewritten by convert4r3\n";
-          print STDOUT "$i1$origname$i2$origrest\n";
-          printf STDERR "\n%03d directory renamed as " .
-            "home_directory in \"$driver\" director.\n",
-            ++$count;
-          }
-
-        # serialize_nets is abolished
-
-        elsif ($name eq "serialize_nets" ||
-               $name eq "serialize_hosts")
-          {
-          if (!$seen_serialize)
-            {
-            &amalgamate("$prefix$driver.serialize_nets", "",
-              "$prefix$driver.serialize_hosts", "serialize_hosts", "+");
-            $seen_serialize = 1;
-            }
-          else
-            {
-            $i = &skipblanks($i);
-            next;
-            }
-          }
-
-
-        # Option not of interest; reproduce verbatim
-
-        else
-          {
-          print STDOUT "$i1$origname$i2$origrest\n";
-          }
-
-
-        $last_was_blank = 0;
-        }
-      }
-    }
-
-  }
-
-# Debugging: show the associative array
-# foreach $key (sort keys %o) { print STDERR "$key = $o{$key}\n"; }
-
-print STDERR "\nEnd of configuration file conversion.\n";
-print STDERR "\n*******************************************************\n";
-print STDERR   "***** Please review the generated file carefully. *****\n";
-print STDERR   "*******************************************************\n\n";
-
-print STDERR "In particular:\n\n";
-
-print STDERR "(1) If you use regular expressions in any options that have\n";
-print STDERR "    been rewritten by this script, they might have been put\n";
-print STDERR "    inside quotes, when then were not previously quoted. This\n";
-print STDERR "    means that any backslashes in them must now be escaped.\n\n";
-
-print STDERR "(2) If your configuration refers to any external files that\n";
-print STDERR "    contain lists of network addresses, check that the masks\n";
-print STDERR "    are specified as single numbers, e.g. /24 and NOT as dotted\n";
-print STDERR "    quads (e.g. 255.255.255.0) because Exim release 3.00 does\n";
-print STDERR "    not recognize the dotted quad form.\n\n";
-
-print STDERR "(3) If your configuration uses macros for lists of domains or\n";
-print STDERR "    hosts or addresses, check to see if any of the references\n";
-print STDERR "    have been negated. If so, you will have to rework things,\n";
-print STDERR "    because the negation will apply only to the first item in\n";
-print STDERR "    the macro-generated list.\n\n";
-
-print STDERR "(4) If you do not generate deliveries to pipes, files, or\n";
-print STDERR "    auto-replies in your aliasfile and forwardfile directors,\n";
-print STDERR "    you can remove the added transport settings.\n\n";
-
-# End of convert4r3
diff --git a/src/src/convert4r4.src b/src/src/convert4r4.src
deleted file mode 100755
index 47987fc8f..000000000
--- a/src/src/convert4r4.src
+++ /dev/null
@@ -1,2527 +0,0 @@
-#! PERL_COMMAND
-
-# This is a Perl script that reads an Exim run-time configuration file for
-# Exim 3. It makes what changes it can for Exim 4, and also output commentary
-# on what it has done, and on things it cannot do.
-
-# It is assumed that the input is a valid Exim 3 configuration file.
-
-use warnings;
-BEGIN { pop @INC if $INC[-1] eq '.' };
-
-use Getopt::Long;
-use File::Basename;
-
-GetOptions(
-    'version' => sub {
-        print basename($0) . ": $0\n",
-            "build: EXIM_RELEASE_VERSIONEXIM_VARIANT_VERSION\n",
-            "perl(runtime): $^V\n";
-            exit 0;
-    },
-);
-
-# These are lists of main options which are abolished in Exim 4.
-# The first contains options that are used to construct new options.
-
-@skipped_options = (
-"auth_hosts",
-"auth_over_tls_hosts",
-"errors_address",
-"headers_check_syntax",
-"headers_checks_fail",
-"headers_sender_verify",
-"headers_sender_verify_errmsg",
-"host_accept_relay",
-"host_auth_accept_relay",
-"host_reject_recipients",
-"local_domains",
-"local_domains_include_host",
-"local_domains_include_host_literals",
-"log_all_parents",
-"log_arguments",
-"log_incoming_port",
-"log_interface",
-"log_level",
-"log_received_sender",
-"log_received_recipients",
-"log_rewrites",
-"log_sender_on_delivery",
-"log_smtp_confirmation",
-"log_smtp_connections",
-"log_smtp_syntax_errors",
-"log_subject",
-"log_queue_run_level",
-"rbl_domains",
-"rbl_hosts",
-"rbl_reject_recipients",
-"receiver_verify",
-"receiver_verify_addresses",
-"receiver_verify_hosts",
-"receiver_verify_senders",
-"recipients_reject_except",
-"recipients_reject_except_senders",
-"relay_domains",
-"relay_domains_include_local_mx",
-"sender_address_relay",
-"sender_address_relay_hosts",
-"sender_reject_recipients",
-"sender_verify",
-"sender_verify_hosts_callback",
-"sender_verify_callback_domains",
-"sender_verify_callback_timeout",
-"sender_verify_hosts",
-"smtp_etrn_hosts",
-"smtp_expn_hosts",
-"smtp_verify",
-"tls_host_accept_relay",
-"tls_hosts",
-"tls_log_cipher",
-"tls_log_peerdn",
-"tls_verify_ciphers"
-);
-
-# The second contains options that are completely abolished and have
-# no equivalent.
-
-@abolished_options = (
-"always_bcc",
-"debug_level",
-"helo_strict_syntax",
-"kill_ip_options",
-"log_ip_options",
-"log_refused_recipients",
-"message_size_limit_count_recipients",
-"rbl_log_headers",
-"rbl_log_rcpt_count",
-"receiver_try_verify",
-"refuse_ip_options",
-"relay_match_host_or_sender",
-"sender_try_verify",
-"sender_verify_batch",
-"sender_verify_fixup",
-"sender_verify_reject",
-"sender_verify_max_retry_rate",
-);
-
-# This is a list of options that are not otherwise handled, but which
-# contain domain or host lists that have to be processed so that any
-# regular expressions are marked "not for expansion".
-
-@list_options = (
-"dns_again_means_nonexist",
-"hold_domains",
-"hosts_treat_as_local",
-"percent_hack_domains",
-"queue_smtp_domains",
-"helo_accept_junk_hosts",
-"host_lookup",
-"ignore_fromline_hosts",
-"rfc1413_hosts",
-"sender_unqualified_hosts",
-"smtp_reserve_hosts",
-"tls_advertise_hosts",
-"tls_verify_hosts",
-);
-
-
-
-##################################################
-#          Output problem rubric once            #
-##################################################
-
-sub rubric {
-return if $rubric_output;
-$rubric_output = 1;
-print STDERR "\n" .
-"** The following comments describe problems that have been encountered\n" .
-"   while converting an Exim 3 runtime file for Exim 4. More detail can\n" .
-"   be found in the file doc/Exim4.upgrade.\n";
-}
-
-
-##################################################
-#             Analyse one line                   #
-##################################################
-
-sub checkline{
-my($line) = $_[0];
-
-return "comment" if $line =~ /^\s*(#|$)/;
-return "end"     if $line =~ /^\s*end\s*$/i;
-
-# Macros are recognized only in the first section of the file.
-
-return "macro" if $prefix eq "" && $line =~ /^\s*[A-Z]/;
-
-# In retry and rewrite sections, the type is always "other"
-
-return "other" if $prefix eq "=retry" || $prefix eq "=rewrite";
-
-# Pick out the name at the start and the rest of the line (into global
-# variables) and return whether the start of a driver or not.
-
-($hide,$name,$rest) = $line =~ /^\s*(hide\s+|)([a-z0-9_]+)\s*(.*?)\s*$/;
-
-# If $rest begins with a colon, this is a driver name
-
-return "driver" if $rest =~ /^:/;
-
-# If $rest begins with an = the value of the option is given explicitly;
-# remove the = from the start. Turn "yes"/"no" into "true"/"false".
-
-if ($rest =~ /^=/)
-  {
-  $rest =~ s/^=\s*//;
-  $rest = "true" if $rest eq "yes";
-  $rest = "false" if $rest eq "no";
-  }
-
-# Otherwise we have a boolean option. Set up a "true"/"false" value.
-
-else
-  {
-  if ($name =~ /^not?_/)     # Recognize "no_" or "not_"
-    {
-    $rest = "false";
-    $name =~ s/^not?_//;
-    }
-  else
-    {
-    $rest = "true";
-    }
-  }
-
-return "option";
-}
-
-
-
-##################################################
-#       Negate a list of things                  #
-##################################################
-
-# Can be tricky, because there may be comment lines in the list.
-# Also, lists may have different delimiters.
-
-sub negate {
-my($list) = $_[0];
-my($delim) = ":";
-my($leadin) = "";
-
-return $list if ! defined $list;
-
-($list) = $list =~ /^"?(.*?)"?\s*$/s;      # Remove surrounding quotes
-$list =~ s/\\\s*\n\s*//g;                  # Remove continuation markers
-
-if ($list =~ /^(\s*<(\S)\s*)(.*)/s)
-  {
-  $leadin = $1;
-  $delim = $2;
-  $list = $3;
-  }
-
-$list =~ s/^\s+//;
-$list =~ s/\Q$delim$delim/>%%%%</g;
-@split = split /\s*\Q$delim\E\s*/s, $list;
-
-foreach $item (@split)
-  {
-  $item =~ s/>%%%%</$delim$delim/g;
-
-  if ($item =~ /^\s*#/)
-    {
-    $item =~ s/((?:^\s*#[^\n]*\n)+\s*)/$1! /mg;
-    $item =~ s/!\s*!//sg;
-    }
-  else
-    {
-    if ($item =~ /^\s*!(.*)/)
-      { $item = $1; }
-    else
-      { $item = "! " . $item; }
-    }
-  }
-
-$" = " $delim \\\n    ";
-$leadin .= " " if $leadin !~ /(^|\s)$/;
-return "$leadin@split";
-}
-
-
-
-##################################################
-#   Prevent regex expansion in a list of things  #
-##################################################
-
-# Can be tricky, because there may be comment lines in the list.
-# Also, lists may have different delimiters.
-
-sub no_expand_regex {
-my($list) = $_[0];
-my($delim) = ":";
-my($leadin) = "";
-
-return $list if ! defined $list;
-
-$delim = $_[1] if (defined $_[1]);
-
-my($is_route_list) = $delim eq ";";
-
-($list) = $list =~ /^"?(.*?)"?\s*$/s;      # Remove surrounding quotes
-$list =~ s/\\\s*\n\s*//g;                  # Remove continuation markers
-
-if ($list =~ /^(\s*<(\S)\s*)(.*)/s)
-  {
-  $leadin = $1;
-  $delim = $2;
-  $list = $3;
-  }
-
-$list =~ s/^\s+//;
-$list =~ s/\Q$delim$delim/>%%%%</g;
-@split = split /\s*\Q$delim\E\s*/s, $list;
-
-my($changed) = 0;
-foreach $item (@split)
-  {
-  $item =~ s/>%%%%</$delim$delim/g;
-  if ($item =~ /^\^/)
-    {
-    # Fudge for route_list items
-
-    if ($is_route_list)
-      {
-      $item = "\\N$item";      # Only one item ...
-      }
-    else
-      {
-      $item = "\\N$item\\N";
-      }
-    $changed = 1;
-    }
-  }
-print STDOUT
-  "#!!# Regular expressions enclosed in \\N...\\N to avoid expansion\n"
-    if $changed;
-
-$" = " $delim \\\n    ";
-$leadin .= " " if $leadin !~ /(^|\s)$/;
-return "$leadin@split";
-}
-
-
-
-##################################################
-#      Sort out lookups in an address list       #
-##################################################
-
-# Can be tricky, because there may be comment lines in the list.
-# Also, lists may have different delimiters.
-
-sub sort_address_list {
-my($list) = $_[0];
-my($name) = $_[1];
-my($delim) = ":";
-my($leadin) = "";
-my($quoted) = 0;
-
-return $list if ! defined $list;
-
-if ($list =~ /^"(.*?)"\s*$/s)            # Remove surrounding quotes
-  {
-  $list = $1;
-  $quoted = 1;
-  }
-
-$list =~ s/\\\s*\n\s*//g;                  # Remove continuation markers
-
-if ($list =~ /^(\s*<(\S)\s*)(.*)/s)
-  {
-  $leadin = $1;
-  $delim = $2;
-  $list = $3;
-  }
-
-$list =~ s/^\s+//;
-$list =~ s/\Q$delim$delim/>%%%%</g;
-@split = split /\s*\Q$delim\E\s*/s, $list;
-
-foreach $item (@split)
-  {
-  $item =~ s/>%%%%</$delim$delim/g;
-  if ($item =~ /^\s*(?:partial-)?(\w+;.*)$/)
-    {
-    my($lookup) = $1;
-    if ($lookup =~ /^lsearch|^dbm|^cdb|^nis[^p]/)
-      {
-      &rubric();
-      print STDERR "\n" .
-"** The Exim 3 \"$name\" option specifies an address\n" .
-"   list that includes the item\n\n" .
-"     $item\n\n" .
-"   In Exim 4 address lists, single-key lookups without a local part just\n" .
-"   look up the complete address. They don't also try the domain, as\n" .
-"   happened in Exim 3. The item has been rewritten as two items to make\n" .
-"   it behave in the same way as Exim 3, but you should check to see if\n" .
-"   this is actually what you want.\n";
-
-      $item = "*\@$item $delim $lookup";
-      }
-    }
-  }
-
-$" = " $delim \\\n    ";
-$leadin .= " " if $leadin !~ /(^|\s)$/;
-
-return $quoted? "\"$leadin@split\"" : "$leadin@split";
-}
-
-
-
-##################################################
-#       Quote a string against expansion         #
-##################################################
-
-# Used for setting up new "domains" options
-
-sub expquote {
-my($s) = $_[0];
-$s =~ s/\$/\\\$/sg;
-$s =~ s/\\(?!\s*\n)/\\\\/sg;
-return $s;
-}
-
-
-
-##################################################
-#          Dequote an option string              #
-##################################################
-
-# If the original list is not quoted, do nothing.
-# If it is quoted, just get rid of the quotes.
-
-sub unquote {
-my($s) = $_[0];
-$s =~ s/^"(.*)"$/$1/s;
-return $s;
-}
-
-
-##################################################
-#      Quote/dequote an option string            #
-##################################################
-
-# If the original list is not quoted, quote it against expansion.
-# If it is quoted, just get rid of the quotes. Also, indent any
-# continuations.
-
-sub acl_quote {
-my($s) = $_[0];
-$s = ($s =~ /^"(.*)"$/s)? $1 : &expquote($s);
-$s =~ s/\n/\n  /g;
-$s =~ s/\n\s{11,}/\n           /g;
-return $s;
-}
-
-
-##################################################
-#       Handle abolished driver options          #
-##################################################
-
-sub abolished {
-my($hash) = shift @_;
-my($name) = shift @_;
-for $abolished (@_)
-  {
-  if (defined $$hash{$abolished})
-    {
-    &rubric();
-    print STDERR "\n" .
-"** $name used the \"$abolished\" option, which no\n".
-"   longer exists. The option has been removed.\n";
-    print STDOUT "#!!# $abolished option removed\n";
-    delete $$hash{$abolished};
-    }
-  }
-}
-
-
-
-##################################################
-#        Handle renamed driver options           #
-##################################################
-
-sub renamed {
-my($hash,$old,$new) = @_;
-if (defined $$hash{$old})
-  {
-  print STDOUT "#!!# $old renamed $new\n";
-  $$hash{$new} = $$hash{$old};
-  delete $$hash{$old};
-  }
-}
-
-
-
-##################################################
-#      Comment on user names in require_files    #
-##################################################
-
-sub check_require {
-my($string, $name) = @_;
-
-$string =~ s/::/[[[]]]/g;
-my(@list) = split /:/, $string;
-my($item);
-
-for $item (@list)
-  {
-  if ($item =~ /^\s*[\w,]+\s*$/)
-    {
-    &rubric();
-    $item =~ s/^\s*//;
-    $item =~ s/\s*$//;
-    print STDERR "\n" .
-"** A setting of require_files in the $name contains\n" .
-"   what appears to be a user name ('$item'). The ability to check files\n" .
-"   as a specific user is done differently in Exim 4. In fact, because the\n" .
-"   routers run as root, you may not need this at all.\n"
-    }
-  }
-}
-
-
-##################################################
-#        Handle current and home directory       #
-##################################################
-
-sub handle_current_and_home_directory {
-my($hash,$driver,$name) = @_;
-
-for ("current_directory", "home_directory")
-  {
-  if (defined $$hash{$_} && $$hash{$_} eq "check_local_user")
-    {
-    my($article) = (substr($driver, 0, 1) eq "a")? "an" : "a";
-    &rubric();
-    print STDERR "\n" .
-"** The Exim 3 configuration contains $article '$driver' director called\n" .
-"   '$name', which set '$_' to the special value\n" .
-"   'check_local_user'. This facility has been abolished in Exim 4 because\n" .
-"   it is no longer necessary. The setting has therefore been omitted. See\n" .
-"   note X.\n";
-    delete $$hash{$_};
-    }
-  else
-    {
-    &renamed($hash, $_, "transport_$_");
-    }
-  }
-}
-
-
-
-##################################################
-#    Handle batch/bsmtp for appendfile/pipe      #
-##################################################
-
-sub handle_batch_and_bsmtp{
-my($hash) = @_;
-
-if (defined $$hash{"bsmtp"})
-  {
-  if ($$hash{"bsmtp"} ne "none")
-    {
-    $$hash{"use_bsmtp"} = "true";
-    $$hash{"message_prefix"} = "\"HELO \$primary_host_name\\n\""
-      if defined $$hash{"bsmtp_helo"} && $$hash{"bsmtp_helo"} eq "true";
-    }
-
-  if ($$hash{"bsmtp"} eq "one")
-    {
-    delete $$hash{"batch"};
-    }
-  else
-    {
-    $$hash{"batch"} = $$hash{"bsmtp"};
-    }
-
-  delete $$hash{"bsmtp"};
-  delete $$hash{"bsmtp_helo"};
-  }
-
-if (defined $$hash{"batch"} && $$hash{"batch"} ne "none")
-  {
-  $$hash{"batch_max"} = "100" if !defined $$hash{"batch_max"};
-  $$hash{"batch_id"} = "\$domain" if $$hash{"batch"} eq "domain";
-  }
-else
-  {
-  $$hash{"batch_max"} = "1" if defined $$hash{"batch_max"};
-  }
-delete $$hash{"batch"};
-}
-
-
-
-##################################################
-#              Output one option                 #
-##################################################
-
-sub outopt {
-my($hash, $key, $no_expand) = @_;
-my($data) = $$hash{$key};
-
-print STDOUT "hide " if defined $$hash{"$key-hide"};
-
-# Output booleans in the form that doesn't use "="
-
-if ($data eq "true")
-  {
-  print STDOUT "$key\n";
-  }
-elsif ($data eq "false")
-  {
-  print STDOUT "no_$key\n";
-  }
-else
-  {
-  if ($no_expand)
-    {
-    printf STDOUT ("$key = %s\n", &no_expand_regex($data));
-    }
-  else
-    {
-    print STDOUT "$key = $data\n";
-    }
-  }
-}
-
-
-
-##################################################
-#       Output the options for one driver        #
-##################################################
-
-# Put the "driver" option first
-
-sub outdriver {
-my($hash) = $_[0];
-print STDOUT "  driver = $$hash{'driver'}\n";
-foreach $key (sort keys %$hash)
-  {
-  next if $key eq "driver" || $key =~ /-hide$/;
-  print STDOUT "  ";
-  &outopt($hash, $key, 0);
-  }
-}
-
-
-
-##################################################
-#      Output a rewrite or a retry line          #
-##################################################
-
-# These lines start with patterns which are now always expanded. If the
-# pattern is a regex, arrange for it not to expand.
-
-sub print_no_expand {
-my($s) = $_[0];
-if ($s =~ /^\^/)
-  {
-  if (!$escape_output)
-    {
-    &rubric();
-    print STDERR "\n" .
-"** You have a retry or rewrite pattern that is a regular expression. Because\n" .
-"   these patterns are now always expanded, you need to be sure that the\n" .
-"   special characters in the regex are not interpreted by the expander.\n" .
-"   \\N has been inserted at the start of the regex to prevent the rest of\n" .
-"   it from being expanded.\n";
-    $escape_output = 1;
-    }
-  print STDOUT "\\N";
-  }
-print STDOUT "$s\n";
-}
-
-
-
-##################################################
-#          Test a boolean main option            #
-##################################################
-
-# This just saves a lot of typing
-
-sub bool {
-return defined $main{$_[0]} && $main{$_[0]} eq "true";
-}
-
-
-
-##################################################
-#                  Main program                  #
-##################################################
-
-print STDERR "Runtime configuration file converter for Exim release 4.\n";
-
-$transport_start = $director_start = $router_start = $retry_start
-  = $rewrite_start = $auth_start = 999999;
-
-$macro_output = "";
-$rubric_output = 0;
-$errmsg_output = 0;
-$key_output = 0;
-$unk_output = 0;
-$escape_output = 0;
-$add_no_more = 0;
-$add_caseful_local_part = 0;
-$done_dns_check_names = 0;
-
-$queue_only_load_was_present = 0;
-$deliver_queue_load_max_was_present = 0;
-
-# Read the entire file into an array
-
-chomp(@c = <STDIN>);
-$clen = scalar @c;
-
-# Remove the standard comment that appears at the end of the default
-
-if ($clen > 0 && $c[$clen-1] =~ /^#\s*End of Exim configuration file\s*/i)
-  {
-  pop @c;
-  $clen--;
-  }
-
-# The first pass over the input fishes out all the options settings in the
-# main, transport, director, and router sections, and places their values in
-# associative arrays. It also notes the starting position of all the sections.
-
-$prefix = "";
-%main = ();
-$hash = \%main;
-
-for ($i = 0; $i < $clen; $i++)
-  {
-  # Change references to +allow_unknown and +warn_unknown into +include_unknown
-
-  if ($c[$i] =~ /\+(?:allow|warn)_unknown/)
-    {
-    if (!$unk_output)
-      {
-      &rubric();
-      print STDERR "\n" .
-"** You have used '+allow_unknown' or '+warn_unknown' in a configuration\n" .
-"   option. This has been converted to '+include_unknown', but the action\n" .
-"   is different in Exim 4, so you should review all the relevant options.\n";
-      $unk_output = 1;
-      }
-    $c[$i] =~ s/\+(?:allow|warn)_unknown/+include_unknown/g;
-    }
-
-  # Any reference to $errmsg_recipient is changed to $bounce_recipient
-
-  if ($c[$i] =~ /\$errmsg_recipient/)
-    {
-    if (!$errmsg_output)
-      {
-      &rubric();
-      print STDERR "\n" .
-"** References to \$errmsg_recipient have been changed to \$bounce_recipient\n";
-      $errmsg_output = 1;
-      }
-    $c[$i] =~ s/\$errmsg_recipient/\$bounce_recipient/g;
-    }
-
-
-  # Analyse the type of line
-
-  $type = &checkline($c[$i]);
-  next if $type eq "comment";
-
-  # Output a warning if $key is used
-
-  if ($c[$i] =~ /\$key/ && !$key_output)
-    {
-    &rubric();
-    print STDERR "\n" .
-"** You have used '\$key' in a configuration option. This variable does not\n" .
-"   exist in Exim 4. Instead, the value you need for your lookup will be\n" .
-"   in one of the other variables such as '\$domain' or '\$host'. You will\n" .
-"   need to edit the new configuration to sort this out.\n";
-    $key_output = 1;
-    }
-
-  # Save macro definitions so we can output them first; must handle
-  # continuations.
-
-  if ($type eq "macro")
-    {
-    $macro_output .= "$c[$i++]\n" while $c[$i] =~ /\\\s*$|^\s*#/;
-    $macro_output .= "$c[$i]\n";
-    }
-
-  # Handle end of section
-
-  elsif ($type eq "end")
-    {
-    if ($prefix eq "=rewrite")
-      {
-      $prefix = "a.";
-      $auth_start = $i + 1;
-      last;
-      }
-    elsif ($prefix eq "=retry")
-      {
-      $prefix = "=rewrite";
-      $rewrite_start = $i + 1;
-      }
-    elsif ($prefix eq "r.")
-      {
-      $prefix = "=retry";
-      $retry_start = $i + 1;
-      }
-    elsif ($prefix eq "d.")
-      {
-      $prefix = "r.";
-      $router_start = $i + 1;
-      }
-    elsif ($prefix eq "t.")
-      {
-      $prefix = "d.";
-      $director_start = $i + 1;
-      }
-    elsif ($prefix eq "")
-      {
-      $prefix = "t.";
-      $transport_start = $i + 1;
-      }
-    }
-
-  # Handle start of a new director, router or transport driver
-
-  elsif ($type eq "driver" && $prefix !~ /^=/)
-    {
-    $hash = {};
-    if (defined $driverlist{"$prefix$name"})
-      {
-      die "*** There are two drivers with the name \"$name\"\n";
-      }
-    $driverlist{"$prefix$name"} = $hash;
-    $first_director = $name if !defined $first_director && $prefix eq "d.";
-    }
-
-  # Handle definition of an option; we must pull in any continuation
-  # strings, and save the value in the current hash. Note if the option
-  # is hidden.
-
-  elsif ($type eq "option")
-    {
-    my($nextline) = "";
-
-    while ($i < $clen - 1 && ($rest =~ /\\\s*$/s || $nextline =~ /^\s*#/))
-      {
-      $nextline = $c[++$i];
-      $rest .= "\n$nextline";
-      }
-
-    $$hash{$name} = $rest;
-    $$hash{"$name-hide"} = 1 if $hide ne "";
-    }
-  }
-
-
-# Generate the new configuration. Start with a warning rubric.
-
-print STDOUT "#!!# This file is output from the convert4r4 script, which tries\n";
-print STDOUT "#!!# to convert Exim 3 configurations into Exim 4 configurations.\n";
-print STDOUT "#!!# However, it is not perfect, especially with non-simple\n";
-print STDOUT "#!!# configurations. You must check it before running it.\n";
-print STDOUT "\n\n";
-
-# Output the macro definitions
-
-if ($macro_output ne "")
-  {
-  print STDOUT "#!!# All macro definitions have been gathered here to ensure\n";
-  print STDOUT "#!!# they precede any references to them.\n\n";
-  print STDOUT "$macro_output\n";
-  }
-
-# Output some default pointers to ACLs for RCPT and DATA time. If no Exim 3
-# options that apply are set, non-restricting ACLs are generated.
-
-print STDOUT "#!!# These options specify the Access Control Lists (ACLs) that\n";
-print STDOUT "#!!# are used for incoming SMTP messages - after the RCPT and DATA\n";
-print STDOUT "#!!# commands, respectively.\n\n";
-
-print STDOUT "acl_smtp_rcpt = check_recipient\n";
-print STDOUT "acl_smtp_data = check_message\n\n";
-
-if (defined $main{"auth_over_tls_hosts"})
-  {
-  print STDOUT "#!!# This option specifies the Access Control List (ACL) that\n";
-  print STDOUT "#!!# is used after an AUTH command.\n\n";
-  print STDOUT "acl_smtp_auth = check_auth\n\n";
-  }
-
-if (&bool("smtp_verify") ||
-    defined $main{"smtp_etrn_hosts"} ||
-    defined $main{"smtp_expn_hosts"})
-  {
-  print STDOUT "#!!# These options specify the Access Control Lists (ACLs) that\n";
-  print STDOUT "#!!# are used to control the ETRN, EXPN, and VRFY commands.\n";
-  print STDOUT "#!!# Where no ACL is defined, the command is locked out.\n\n";
-
-  print STDOUT "acl_smtp_etrn = check_etrn\n" if defined $main{"smtp_etrn_hosts"};
-  print STDOUT "acl_smtp_expn = check_expn\n" if defined $main{"smtp_expn_hosts"};
-  print STDOUT "acl_smtp_vrfy = check_vrfy\n" if &bool("smtp_verify");
-  print STDOUT "\n";
-  }
-
-# If local_domains was set, get its value; otherwise set to "@". Add into it
-# appropriate magic for local_domains_include_host[_literals].
-
-$local_domains = (defined $main{"local_domains"})? $main{"local_domains"} : "@";
-
-$ldsep = ":";
-if ($local_domains =~ /^\s*<(.)\s*(.*)/s)
-  {
-  $ldsep = $1;
-  $local_domains = $2;
-  }
-
-$local_domains = "\@[] $ldsep " . $local_domains
-  if defined $main{"local_domains_include_host_literals"} &&
-     $main{"local_domains_include_host_literals"} eq "true";
-
-$local_domains = "\@ $ldsep " . $local_domains
-  if defined $main{"local_domains_include_host"} &&
-     $main{"local_domains_include_host"} eq "true";
-
-$local_domains = "<$ldsep " . $local_domains if $ldsep ne ":";
-
-# Output a domain list setting for these domains, provided something is defined
-
-if ($local_domains !~ /^\s*$/)
-  {
-  print STDOUT "#!!# This setting defines a named domain list called\n";
-  print STDOUT "#!!# local_domains, created from the old options that\n";
-  print STDOUT "#!!# referred to local domains. It will be referenced\n";
-  print STDOUT "#!!# later on by the syntax \"+local_domains\".\n";
-  print STDOUT "#!!# Other domain and host lists may follow.\n\n";
-
-  printf STDOUT ("domainlist local_domains = %s\n\n",
-    &no_expand_regex($local_domains));
-  }
-
-$relay_domains = (defined $main{"relay_domains"})? $main{"relay_domains"} : "";
-
-$ldsep = ":";
-if ($relay_domains =~ /^\s*<(.)\s*(.*)/s)
-  {
-  $ldsep = $1;
-  }
-
-if (defined $main{"relay_domains_include_local_mx"})
-  {
-  $relay_domains .= ($relay_domains =~ /^\s*$/)? "\@mx_any" :
-    " $ldsep \@mx_any";
-  }
-
-printf STDOUT ("domainlist relay_domains = %s\n",
-  &no_expand_regex($relay_domains))
-    if $relay_domains !~ /^\s*$/;
-
-
-# If ignore_errmsg_errors is set, we are going to force 0s as the value
-# for ignore_errmsg_errors_after, so arrange to skip any other value.
-
-push @skipped_options, "ignore_errmsg_errors_after"
-   if &bool("ignore_errmsg_errors");
-
-
-# If rbl_domains is set, split it up and generate six lists:
-#   rbl_warn_domains, rbl_warn_domains_skiprelay
-#   rbl_reject_domains, rbl_reject_domains_skiprelay
-#   rbl_accept_domains, rbl_accept_domains_skiprelay
-
-if (defined $main{"rbl_domains"})
-  {
-  my($s) = &unquote($main{"rbl_domains"});
-  $s =~ s/\s*\\\s*\n\s*/ /g;
-  my(@list) = split /\s*:\s*/, $s;
-
-  foreach $d (@list)
-    {
-    my(@sublist) = split /\//, $d;
-    my($name) = shift @sublist;
-    my($warn) = 0;
-    if (defined $main{"rbl_reject_recipients"})
-      {
-      $warn = $main{"rbl_reject_recipients"} ne "true";
-      }
-
-    foreach $o (@sublist)
-      {
-      $warn = 1 if $o eq "warn";
-      $warn = 0 if $o eq "reject";
-      $warn = 2 if $o eq "accept";
-      $skiprelay = 1 if $o eq "skiprelay";
-      }
-
-    if ($skiprelay)
-      {
-      if ($warn == 0)
-        {
-        $rbl_reject_skiprelay .= ((defined $rbl_reject_skiprelay)? ":":"").$name;
-        }
-      elsif ($warn == 1)
-        {
-        $rbl_warn_skiprelay .= ((defined $rbl_warn_skiprelay)? ":":"").$name;
-        }
-      elsif ($warn == 2)
-        {
-        $rbl_accept_skiprelay .= ((defined $rbl_accept_skiprelay)? ":":"").$name;
-        }
-      }
-    else
-      {
-      if ($warn == 0)
-        {
-        $rbl_reject_domains .= ((defined $rbl_reject_domains)? ":":"").$name;
-        }
-      elsif ($warn == 1)
-        {
-        $rbl_warn_domains .= ((defined $rbl_warn_domains)? ":":"").$name;
-        }
-      elsif ($warn == 2)
-        {
-        $rbl_accept_domains .= ((defined $rbl_accept_domains)? ":":"").$name;
-        }
-      }
-    }
-  }
-
-
-# Output host list settings
-
-printf STDOUT ("hostlist auth_hosts = %s\n",
-  &no_expand_regex($main{"auth_hosts"}))
-    if defined $main{"auth_hosts"};
-printf STDOUT ("hostlist rbl_hosts = %s\n",
-  &no_expand_regex($main{"rbl_hosts"}))
-    if defined $main{"rbl_hosts"};
-printf STDOUT ("hostlist relay_hosts = %s\n",
-  &no_expand_regex($main{"host_accept_relay"}))
-    if defined $main{"host_accept_relay"};
-printf STDOUT ("hostlist auth_relay_hosts = %s\n",
-  &no_expand_regex($main{"host_auth_accept_relay"}))
-    if defined $main{"host_auth_accept_relay"};
-
-printf STDOUT ("hostlist auth_over_tls_hosts = %s\n",
-  &no_expand_regex($main{"auth_over_tls_hosts"}))
-    if defined $main{"auth_over_tls_hosts"};
-printf STDOUT ("hostlist tls_hosts = %s\n",
-  &no_expand_regex($main{"tls_hosts"}))
-    if defined $main{"tls_hosts"};
-printf STDOUT ("hostlist tls_relay_hosts = %s\n",
-  &no_expand_regex($main{"tls_host_accept_relay"}))
-    if defined $main{"tls_host_accept_relay"};
-
-print STDOUT "\n";
-
-
-# Convert various logging options
-
-$log_selector = "";
-$sep = " \\\n             ";
-
-if (defined $main{"log_level"})
-  {
-  my($level) = $main{"log_level"};
-  $log_selector .= "$sep -retry_defer$sep -skip_delivery" if $level < 5;
-  $log_selector .= "$sep -lost_incoming_connection$sep -smtp_syntax_error" .
-                   "$sep -delay_delivery" if $level < 4;
-  $log_selector .= "$sep -size_reject" if $level < 2;
-  }
-
-$log_selector .= "$sep -queue_run"
-  if defined $main{"log_queue_run_level"} &&
-     defined $main{"log_level"} &&
-     $main{"log_queue_run_level"} > $main{"log_level"};
-
-$log_selector .= "$sep +address_rewrite"       if &bool("log_rewrites");
-$log_selector .= "$sep +all_parents"           if &bool("log_all_parents");
-$log_selector .= "$sep +arguments"             if &bool("log_arguments");
-$log_selector .= "$sep +incoming_port"         if &bool("log_incoming_port");
-$log_selector .= "$sep +incoming_interface"    if &bool("log_interface");
-$log_selector .= "$sep +received_sender"       if &bool("log_received_sender");
-$log_selector .= "$sep +received_recipients"   if &bool("log_received_recipients");
-$log_selector .= "$sep +sender_on_delivery"    if &bool("log_sender_on_delivery");
-$log_selector .= "$sep +smtp_confirmation"     if &bool("log_smtp_confirmation");
-$log_selector .= "$sep +smtp_connection"       if &bool("log_smtp_connections");
-$log_selector .= "$sep +smtp_syntax_error"     if &bool("log_smtp_syntax_errors");
-$log_selector .= "$sep +subject"               if &bool("log_subject");
-$log_selector .= "$sep +tls_cipher"            if &bool("tls_log_cipher");
-$log_selector .= "$sep +tls_peerdn"            if &bool("tls_log_peerdn");
-
-
-if ($log_selector ne "")
-  {
-  print STDOUT "#!!# All previous logging options are combined into a single\n"
-             . "#!!# option in Exim 4. This setting is an approximation to\n"
-             . "#!!# the previous state - some logging has changed.\n\n";
-  print STDOUT "log_selector = $log_selector\n\n";
-  }
-
-# If deliver_load_max is set, replace it with queue_only_load (taking the
-# lower value if both set) and also set deliver_queue_load_max if it is
-# not already set. When scanning for output, deliver_load_max is skipped.
-
-if (defined $main{"deliver_load_max"})
-  {
-  &rubric();
-  print STDERR "\n" .
-"** deliver_load_max is abolished in Exim 4.\n";
-
-  if (defined $main{"queue_only_load"})
-    {
-    $queue_only_load_was_present = 1;
-    if ($main{"queue_only_load"} < $main{"deliver_load_max"})
-      {
-      print STDERR
-"   As queue_only_load was set lower, deliver_load_max is just removed.\n";
-      }
-    else
-      {
-      print STDERR
-"   As queue_only_load was set higher, it's value has been replaced by\n" .
-"   the value of deliver_load_max.\n";
-      $main{"queue_only_load"} = $main{"deliver_load_max"};
-      }
-    }
-  else
-    {
-    print STDERR
-"   queue_only_load has been set to the load value.\n";
-    $main{"queue_only_load"} = $main{"deliver_load_max"};
-    }
-
-  if (!defined $main{"deliver_queue_load_max"})
-    {
-    print STDERR
-"   deliver_queue_load_max has been set to the value of queue_only_load.\n";
-    $main{"deliver_queue_load_max"} = $main{"queue_only_load"};
-    }
-  else
-    {
-    $deliver_queue_load_max_was_present = 1;
-    }
-  }
-
-
-# Now we scan through the various parts of the file again, making changes
-# as necessary.
-
-# -------- The main configuration --------
-
-$prefix = "";
-MainLine: for ($i = 0; $i < $clen; $i++)
-  {
-  my($nextline) = "";
-  $type = &checkline($c[$i]);
-  last if $type eq "end";
-
-  if ($type eq "macro")
-    {
-    $i++ while $c[$i] =~ /\\\s*$|^\s*#/;
-    next;
-    }
-
-  if ($type eq "comment") { print STDOUT "$c[$i]\n"; next; }
-
-  # Collect any continuation lines for an option setting
-
-  while ($rest =~ /\\\s*$/s || $nextline =~ /^\s*#/)
-    {
-    $nextline = $c[++$i];
-    $rest .= "\n$nextline";
-    }
-
-  $rest =~ s/^=\s*//;
-
-  # Deal with main options that are skipped (they are used in other
-  # options in other places).
-
-  for $skipped (@skipped_options)
-    {
-    next MainLine if $name eq $skipped;
-    }
-
-  # Deal with main options that are totally abolished
-
-  for $abolished (@abolished_options)
-    {
-    if ($name eq $abolished)
-      {
-      &rubric();
-      print STDERR "\n" .
-"** The $name option no longer exists, and has no equivalent\n" .
-"   in Exim 4.\n";
-      next MainLine;
-      }
-    }
-
-  # There is a special case for rbl_warn_header
-
-  if ($name eq "rbl_warn_header")
-    {
-    &rubric();
-    print STDERR "\n" .
-"** The $name option no longer exists. In Exim 4 you can achieve the\n" .
-"   effect by adding a suitable \"message\" statement in the ACL.\n";
-    }
-
-  # There is a special case for sender_reject and host_reject
-
-  elsif ($name eq "sender_reject" || $name eq "host_reject")
-    {
-    &rubric();
-    print STDERR "\n" .
-"** The $name option no longer exists. Its data has been used in\n" .
-"   an Access Control List as if it were in ${name}_recipients.\n";
-    }
-
-  # And a special message for prohibition_message
-
-  elsif ($name eq "prohibition_message")
-    {
-    &rubric();
-    print STDERR "\n" .
-"** The prohibition_message option no longer exists. The facility is\n" .
-"   provided in a different way in Exim 4, via the \"message\" keyword\n" .
-"   in Access Control Lists. It isn't possible to do an automatic conversion,\n" .
-"   so the value of prohibition_message has been ignored. You will have to\n" .
-"   modify the ACLs if you want to reinstate the feature.\n";
-    }
-
-  # auth_always_advertise gets converted to auth_advertise_hosts
-
-  elsif ($name eq "auth_always_advertise")
-    {
-    print STDOUT "#!!# auth_always_advertise converted to auth_advertise_hosts\n";
-    if (&bool("auth_always_advertise"))
-      {
-      print STDOUT "auth_advertise_hosts = *\n";
-      }
-    else
-      {
-      $sep = "";
-      print STDOUT "auth_advertise_hosts =";
-      if (defined $main{"auth_hosts"})
-        {
-        print STDOUT "$sep +auth_hosts";
-        $sep = " :";
-        }
-      if (defined $main{"host_accept_relay"})
-        {
-        print STDOUT "$sep !+relay_hosts";
-        $sep = " :";
-        }
-      if (defined $main{"host_auth_accept_relay"})
-        {
-        print STDOUT "$sep +auth_relay_hosts";
-        }
-      print STDOUT "\n";
-      }
-    }
-
-  # Deal with main options that have to be rewritten
-
-  elsif ($name eq "accept_timeout")
-    {
-    print STDOUT "#!!# accept_timeout renamed receive_timeout\n";
-    print STDOUT "receive_timeout = $rest\n";
-    }
-
-  elsif ($name eq "collapse_source_routes")
-    {
-    print STDOUT "#!!# collapse_source_routes removed\n";
-    print STDOUT "#!!# It has been a no-op since 3.10.\n";
-    }
-
-  elsif ($name eq "daemon_smtp_service")
-    {
-    print STDOUT "#!!# daemon_smtp_service renamed daemon_smtp_port\n";
-    print STDOUT "daemon_smtp_port = $rest\n";
-    }
-
-  elsif ($name eq "dns_check_names" || $name eq "dns_check_names_pattern")
-    {
-    if (!$done_dns_check_names)
-      {
-      if (&bool("dns_check_names"))
-        {
-        if (defined $main{"dns_check_names_pattern"})
-          {
-          &outopt(\%main, "dns_check_names_pattern", 0);
-          }
-        }
-
-      else
-        {
-        print STDOUT "#!!# dns_check_names has been abolished\n";
-        print STDOUT "#!!# setting dns_check_pattern empty to turn off check\n";
-        print STDOUT "dns_check_names_pattern =\n";
-        }
-
-      $done_dns_check_names = 1;
-      }
-    }
-
-  elsif ($name eq "deliver_load_max")
-    {
-    print STDOUT "deliver_queue_load_max = $main{'deliver_queue_load_max'}\n"
-      if !$deliver_queue_load_max_was_present;
-    print STDOUT "queue_only_load = $main{'queue_only_load'}\n"
-      if !$queue_only_load_was_present;
-    }
-
-  elsif ($name eq "errmsg_file")
-    {
-    print STDOUT "#!!# errmsg_file renamed bounce_message_file\n";
-    print STDOUT "bounce_message_file = $rest\n";
-    }
-
-  elsif ($name eq "errmsg_text")
-    {
-    print STDOUT "#!!# errmsg_text renamed bounce_message_text\n";
-    print STDOUT "bounce_message_text = $rest\n";
-    }
-
-  elsif ($name eq "forbid_domain_literals")
-    {
-    print STDOUT "#!!# forbid_domain_literals replaced by allow_domain_literals\n";
-    print STDOUT "allow_domain_literals = ",
-          &bool("forbid_domain_literals")? "false" : "true", "\n";
-    }
-
-  elsif ($name eq "freeze_tell_mailmaster")
-    {
-    print STDOUT "#!!# freeze_tell_mailmaster replaced by freeze_tell\n";
-    if (&bool("freeze_tell_mailmaster"))
-      {
-      print STDOUT "freeze_tell = ",
-        ((defined $main{"errors_address"})?
-          $main{"errors_address"} : "postmaster"), "\n";
-      }
-    else
-      {
-      print STDOUT "#!!# freeze_tell is unset by default\n";
-      }
-    }
-
-  elsif ($name eq "helo_verify")
-    {
-    print STDOUT "#!!# helo_verify renamed helo_verify_hosts\n";
-    printf STDOUT ("helo_verify_hosts = %s\n", &no_expand_regex($rest));
-    }
-
-  elsif ($name eq "ignore_errmsg_errors")
-    {
-    print STDOUT "ignore_bounce_errors_after = 0s\n";
-    }
-
-  elsif ($name eq "ignore_errmsg_errors_after")
-    {
-    print STDOUT "#!!# ignore_errmsg_errors_after renamed ignore_bounce_errors_after\n";
-    print STDOUT "ignore_bounce_errors_after = $rest\n";
-    }
-
-  elsif ($name eq "ipv4_address_lookup" || $name eq "dns_ipv4_lookup")
-    {
-    print STDOUT "#!!# $name changed to dns_ipv4_lookup\n"
-      if $name eq "ipv4_address_lookup";
-    print STDOUT "#!!# dns_ipv4_lookup is now a domain list\n";
-    if (&bool($name))
-      {
-      print STDOUT "dns_ipv4_lookup = *\n";
-      }
-    else
-      {
-      print STDOUT "#!!# default for dns_ipv4_lookup is unset\n";
-      }
-    }
-
-  elsif ($name eq "locally_caseless")
-    {
-    print STDOUT "#!!# locally_caseless removed\n";
-    print STDOUT "#!!# caseful_local_part will be added to ex-directors\n";
-    $add_caseful_local_part = 1;
-    }
-
-  elsif ($name eq "message_filter_directory2_transport")
-    {
-    print STDOUT "#!!# message_filter_directory2_transport removed\n";
-    }
-
-  elsif ($name =~ /^message_filter(.*)/)
-    {
-    print STDOUT "#!!# $name renamed system_filter$1\n";
-    print STDOUT "system_filter$1 = $rest\n";
-    }
-
-  elsif ($name eq "queue_remote_domains")
-    {
-    print STDOUT "#!!# queue_remote_domains renamed queue_domains\n";
-    printf STDOUT ("queue_domains = %s\n", &no_expand_regex($rest));
-    }
-
-  elsif ($name eq "receiver_unqualified_hosts")
-    {
-    print STDOUT "#!!# receiver_unqualified_hosts renamed recipient_unqualified_hosts\n";
-    printf STDOUT ("recipient_unqualified_hosts = %s\n",
-      &no_expand_regex($rest));
-    }
-
-  elsif ($name eq "remote_sort")
-    {
-    print STDOUT "#!!# remote_sort renamed remote_sort_domains\n";
-    printf STDOUT ("remote_sort_domains = %s\n", &no_expand_regex($rest));
-    }
-
-  elsif ($name eq "security")
-    {
-    if ($rest eq "unprivileged")
-      {
-      print STDOUT "#!!# security=unprivileged changed to deliver_drop_privilege\n";
-      print STDOUT "deliver_drop_privilege\n";
-      }
-    else
-      {
-      &rubric();
-      print STDERR "\n" .
-"** The 'security' option no longer exists.\n";
-      }
-    }
-
-  elsif ($name eq "timestamps_utc")
-    {
-    print STDOUT "#!!# timestamps_utc changed to use timezone\n";
-    print STDOUT "timezone = utc\n";
-    }
-
-  elsif ($name eq "untrusted_set_sender")
-    {
-    print STDOUT "#!!# untrusted_set_sender is now a list of what can be set\n";
-    print STDOUT "#!!# The default is an empty list.\n";
-    if (&bool("untrusted_set_sender"))
-      {
-      print STDOUT "untrusted_set_sender = *\n";
-      }
-    }
-
-  elsif ($name eq "warnmsg_file")
-    {
-    print STDOUT "#!!# warnmsg_file renamed warn_message_file\n";
-    print STDOUT "warn_message_file = $rest\n";
-    }
-
-  # Remaining options just get copied unless they are one of those that's
-  # a list where any regular expressions have to be escaped.
-
-  else
-    {
-    my($no_expand) = 0;
-    foreach $o (@list_options)
-      {
-      if ($name eq $o)
-        {
-        $no_expand = 1;
-        last;
-        }
-      }
-    &outopt(\%main, $name, $no_expand);
-    }
-  }
-
-
-# -------- The ACL configuration --------
-
-print STDOUT "\n";
-print STDOUT "#!!#######################################################!!#\n";
-print STDOUT "#!!# This new section of the configuration contains ACLs #!!#\n";
-print STDOUT "#!!# (Access Control Lists) derived from the Exim 3      #!!#\n";
-print STDOUT "#!!# policy control options.                             #!!#\n";
-print STDOUT "#!!#######################################################!!#\n";
-
-print STDOUT "\n";
-print STDOUT "#!!# These ACLs are crudely constructed from Exim 3 options.\n";
-print STDOUT "#!!# They are almost certainly not optimal. You should study\n";
-print STDOUT "#!!# them and rewrite as necessary.\n";
-
-print STDOUT "\nbegin acl\n\n";
-
-
-# Output an ACL for use after the RCPT command. This combines all the previous
-# policy checking options.
-
-print STDOUT "#!!# ACL that is used after the RCPT command\n";
-print STDOUT "check_recipient:\n";
-
-print STDOUT "  # Exim 3 had no checking on -bs messages, so for compatibility\n";
-print STDOUT "  # we accept if the source is local SMTP (i.e. not over TCP/IP).\n";
-print STDOUT "  # We do this by testing for an empty sending host field.\n";
-print STDOUT "  accept  hosts = :\n";
-
-if (defined $main{"tls_verify_ciphers"})
-  {
-  print STDOUT "  deny    ";
-  print STDOUT "hosts = $main{'tls_verify_hosts'}\n         "
-    if defined $main{"tls_verify_hosts"};
-  print STDOUT " encrypted = *\n         ";
-  print STDOUT "!encrypted = $main{'tls_verify_ciphers'}\n";
-  }
-
-print STDOUT "  deny    hosts = +auth_hosts\n" .
-             "          message = authentication required\n" .
-             "         !authenticated = *\n"
-  if defined $main{"auth_hosts"};
-
-print STDOUT "  deny    hosts = +tls_hosts\n" .
-             "          message = encryption required\n" .
-             "         !encrypted = *\n"
-  if defined $main{"tls_hosts"};
-
-printf STDOUT ("  accept  recipients = %s\n",
-  &acl_quote(&sort_address_list($main{"recipients_reject_except"},
-    "recipients_reject_except")))
-      if defined $main{"recipients_reject_except"};
-
-printf STDOUT ("  accept  senders = %s\n",
-  &acl_quote(&sort_address_list($main{"recipients_reject_except_senders"},
-    "recipients_reject_except_senders")))
-      if defined $main{"recipients_reject_except_senders"};
-
-printf STDOUT ("  deny    hosts = %s\n", &acl_quote($main{"host_reject"}))
-  if defined $main{"host_reject"};
-
-printf STDOUT ("  deny    hosts = %s\n",
-  &acl_quote($main{"host_reject_recipients"}))
-    if defined $main{"host_reject_recipients"};
-
-if (defined $main{"rbl_domains"})
-  {
-  my($msg) = "message = host is listed in \$dnslist_domain\n          ";
-  my($hlist) = (defined $main{"rbl_hosts"})?
-    "hosts = +rbl_hosts\n          " : "";
-
-  print STDOUT "  accept  ${hlist}dnslists = $rbl_accept_domains\n"
-    if defined $rbl_accept_domains;
-  print STDOUT "  deny    ${hlist}${msg}dnslists = $rbl_reject_domains\n"
-    if defined $rbl_reject_domains;
-  print STDOUT "  warn    ${hlist}" .
-    "message = X-Warning: \$sender_host_address is listed at \$dnslist_domain\n" .
-    "          dnslists = $rbl_warn_domains\n"
-      if defined $rbl_warn_domains;
-
-  if (defined $main{"host_accept_relay"})
-    {
-    $hlist .= "hosts = !+relay_hosts\n          ";
-    print STDOUT "  accept  ${hlist}dnslists = $rbl_accept_skiprelay\n"
-      if defined $rbl_accept_skiprelay;
-    print STDOUT "  deny    ${hlist}${msg}dnslists = $rbl_reject_skiprelay\n"
-      if defined $rbl_reject_skiprelay;
-    print STDOUT "  warn    ${hlist}" .
-      "message = X-Warning: \$sender_host_address is listed at \$dnslist_domain\n" .
-      "          dnslists = $rbl_warn_skiprelay\n"
-        if defined $rbl_warn_skiprelay;
-    }
-  }
-
-printf STDOUT ("  deny    senders = %s\n",
-  &acl_quote(&sort_address_list($main{"sender_reject"}, "sender_reject")))
-    if defined $main{"sender_reject"};
-
-printf STDOUT ("  deny    senders = %s\n",
-  &acl_quote(&sort_address_list($main{"sender_reject_recipients"},
-    "sender_reject_recipients")))
-      if defined $main{"sender_reject_recipients"};
-
-if (&bool("sender_verify"))
-  {
-  if (defined $main{"sender_verify_hosts_callback"} &&
-      defined $main{"sender_verify_callback_domains"})
-    {
-    printf STDOUT ("  deny    hosts = %s\n",
-      &acl_quote($main{"sender_verify_hosts_callback"}));
-    printf STDOUT ("          sender_domains = %s\n",
-      &acl_quote($main{"sender_verify_callback_domains"}));
-    print  STDOUT  "         !verify = sender/callout";
-    print  STDOUT  "=$main{\"sender_verify_callback_timeout\"}"
-      if defined $main{"sender_verify_callback_timeout"};
-    print  STDOUT  "\n";
-    }
-
-  if (defined $main{"sender_verify_hosts"})
-    {
-    printf STDOUT ("  deny    hosts = %s\n",
-      &acl_quote($main{"sender_verify_hosts"}));
-    print  STDOUT  "         !verify = sender\n";
-    }
-  else
-    {
-    print STDOUT "  require verify = sender\n";
-    }
-  }
-
-if (&bool("receiver_verify"))
-  {
-  print  STDOUT  "  deny    message = unrouteable address\n";
-  printf STDOUT ("          recipients = %s\n",
-    &acl_quote(&sort_address_list($main{"receiver_verify_addresses"},
-      "receiver_verify_addresses")))
-        if defined $main{"receiver_verify_addresses"};
-  printf STDOUT ("          hosts = %s\n",
-    &acl_quote($main{"receiver_verify_hosts"}))
-      if defined $main{"receiver_verify_hosts"};
-  printf STDOUT ("          senders = %s\n",
-    &acl_quote(&sort_address_list($main{"receiver_verify_senders"},
-      "receiver_verify_senders")))
-        if defined $main{"receiver_verify_senders"};
-  print  STDOUT  "         !verify = recipient\n";
-  }
-
-print STDOUT "  accept  domains = +local_domains\n"
-  if $local_domains !~ /^\s*$/;
-
-print STDOUT "  accept  domains = +relay_domains\n"
-  if $relay_domains !~ /^\s*$/;
-
-if (defined $main{"host_accept_relay"})
-  {
-  if (defined $main{"sender_address_relay"})
-    {
-    if (defined $main{"sender_address_relay_hosts"})
-      {
-      printf STDOUT ("  accept  hosts = %s\n",
-        &acl_quote($main{"sender_address_relay_hosts"}));
-      print  STDOUT  "          endpass\n";
-      print  STDOUT  "          message = invalid sender\n";
-      printf STDOUT ("          senders = %s\n",
-        &acl_quote(&sort_address_list($main{"sender_address_relay"},
-          "sender_address_relay")));
-      print  STDOUT  "  accept  hosts = +relay_hosts\n";
-      }
-    else
-      {
-      print  STDOUT  "  accept  hosts = +relay_hosts\n";
-      print  STDOUT  "          endpass\n";
-      print  STDOUT  "          message = invalid sender\n";
-      printf STDOUT ("          senders = %s\n",
-        &acl_quote(&sort_address_list($main{"sender_address_relay"},
-          "sender_address_relay")));
-      }
-    }
-  else
-    {
-    print STDOUT "  accept  hosts = +relay_hosts\n";
-    }
-  }
-
-print STDOUT "  accept  hosts = +auth_relay_hosts\n" .
-             "          endpass\n" .
-             "          message = authentication required\n" .
-             "          authenticated = *\n"
-  if defined $main{"host_auth_accept_relay"};
-
-print STDOUT "  accept  hosts = +tls_relay_hosts\n" .
-             "          endpass\n" .
-             "          message = encryption required\n" .
-             "          encrypted = *\n"
-  if defined $main{"tls_host_accept_relay"};
-
-print STDOUT "  deny    message = relay not permitted\n\n";
-
-
-# Output an ACL for use after the DATA command. This is concerned with
-# header checking.
-
-print STDOUT "#!!# ACL that is used after the DATA command\n";
-print STDOUT "check_message:\n";
-
-# Default for headers_checks_fail is true
-
-if (!defined $main{"headers_checks_fail"} ||
-    $main{"headers_checks_fail"} eq "true")
-  {
-  print STDOUT "  require verify = header_syntax\n"
-    if &bool("headers_check_syntax");
-  print STDOUT "  require verify = header_sender\n"
-    if &bool("headers_sender_verify");
-  print STDOUT "  accept  senders = !:\n  require verify = header_sender\n"
-    if &bool("headers_sender_verify_errmsg");
-  }
-else
-  {
-  print STDOUT "  warn    !verify = header_syntax\n"
-    if &bool("headers_check_syntax");
-  print STDOUT "  warn    !verify = header_sender\n"
-    if &bool("headers_sender_verify");
-  print STDOUT "  accept  senders = !:\n  warn    !verify = header_sender\n"
-    if &bool("headers_sender_verify_errmsg");
-  }
-
-print STDOUT "  accept\n\n";
-
-
-# Output an ACL for AUTH if required
-
-if (defined $main{"auth_over_tls_hosts"})
-  {
-  print STDOUT "#!!# ACL that is used after the AUTH command\n" .
-               "check_auth:\n" .
-               "  accept  hosts = +auth_over_tls_hosts\n" .
-               "          endpass\n" .
-               "          message = STARTTLS required before AUTH\n" .
-               "          encrypted = *\n" .
-               "  accept\n";
-  }
-
-
-# Output ACLs for ETRN, EXPN, and VRFY if required
-
-if (defined $main{"smtp_etrn_hosts"})
-  {
-  print STDOUT "#!!# ACL that is used after the ETRN command\n" .
-               "check_etrn:\n";
-  print STDOUT "  deny    hosts = +auth_hosts\n" .
-               "          message = authentication required\n" .
-               "         !authenticated = *\n"
-    if defined $main{"auth_hosts"};
-  print STDOUT "  accept  hosts = $main{\"smtp_etrn_hosts\"}\n\n";
-  }
-
-if (defined $main{"smtp_expn_hosts"})
-  {
-  print STDOUT "#!!# ACL that is used after the EXPN command\n" .
-               "check_expn:\n";
-  print STDOUT "  deny    hosts = +auth_hosts\n" .
-               "          message = authentication required\n" .
-               "         !authenticated = *\n"
-    if defined $main{"auth_hosts"};
-  print STDOUT "  accept  hosts = $main{\"smtp_expn_hosts\"}\n\n";
-  }
-
-if (&bool("smtp_verify"))
-  {
-  print STDOUT "#!!# ACL that is used after the VRFY command\n" .
-               "check_vrfy:\n";
-  print STDOUT "  deny    hosts = +auth_hosts\n" .
-               "          message = authentication required\n" .
-               "         !authenticated = *\n"
-    if defined $main{"auth_hosts"};
-  print STDOUT "  accept\n\n";
-  }
-
-# -------- The authenticators --------
-
-$started = 0;
-for ($i = $auth_start; $i < $clen; $i++)
-  {
-  if (!$started)
-    {
-    if ($c[$i] !~ /^\s*(#|$)/)
-      {
-      print STDOUT "\nbegin authenticators\n\n";
-      $started = 1;
-      }
-    }
-  print STDOUT "$c[$i]\n";
-  }
-
-
-# -------- Rewrite section --------
-
-$started = 0;
-for ($i = $rewrite_start; $i < $clen && $i < $auth_start - 1; $i++)
-  {
-  if (!$started)
-    {
-    if ($c[$i] !~ /^\s*(#|$)/)
-      {
-      print STDOUT "\nbegin rewrite\n\n";
-      $started = 1;
-      }
-    }
-  &print_no_expand($c[$i]);
-  }
-
-
-# -------- The routers configuration --------
-
-# The new routers configuration is created out of the old directors and routers
-# configuration. We put the old routers first, adding a "domains" option to
-# any that don't have one, to make them select the domains that do not match
-# the original local_domains. The routers get modified as necessary, and the
-# final one has "no_more" set, unless it has conditions. In that case we have
-# to add an extra router to be sure of failing all non-local addresses that
-# fall through. We do this also if there are no routers at all. The old
-# directors follow, modified as required.
-
-$prefix = "r.";
-undef @comments;
-
-print STDOUT "\n";
-print STDOUT "#!!#######################################################!!#\n";
-print STDOUT "#!!# Here follow routers created from the old routers,   #!!#\n";
-print STDOUT "#!!# for handling non-local domains.                     #!!#\n";
-print STDOUT "#!!#######################################################!!#\n";
-
-print STDOUT "\nbegin routers\n\n";
-
-for ($i = $router_start; $i < $clen; $i++)
-  {
-  $type = &checkline($c[$i]);
-  last if $type eq "end";
-
-  if ($type eq "comment") { push(@comments, "$c[$i]\n"); next; }
-
-  # When we hit the start of a driver, modify its options as necessary,
-  # and then output it from the stored option settings, having first output
-  # and previous comments.
-
-  if ($type eq "driver")
-    {
-    print STDOUT shift @comments while scalar(@comments) > 0;
-
-    $hash = $driverlist{"$prefix$name"};
-    $driver = $$hash{"driver"};
-    print STDOUT "$name:\n";
-
-    $add_no_more =
-      ! defined $$hash{"domains"} &&
-      ! defined $$hash{"local_parts"} &&
-      ! defined $$hash{"senders"} &&
-      ! defined $$hash{"condition"} &&
-      ! defined $$hash{"require_files"} &&
-      (!defined $$hash{"verify_only"} || $$hash{"verify_only"} eq "false") &&
-      (!defined $$hash{"verify"} || $$hash{"verify"} eq "true");
-
-    # Create a "domains" setting if there isn't one, unless local domains
-    # was explicitly empty.
-
-    $$hash{"domains"} = "! +local_domains"
-      if !defined $$hash{"domains"} && $local_domains !~ /^\s*$/;
-
-    # If the router had a local_parts setting, add caseful_local_part
-
-    $$hash{"caseful_local_part"} = "true" if defined $$hash{"local_parts"};
-
-    # If the router has "self=local" set, change it to "self=pass", and
-    # set pass_router to the router that was the first director. Change the
-    # obsolete self settings of "fail_hard" and "fail_soft" to "fail" and
-    # "pass".
-
-    if (defined $$hash{"self"})
-      {
-      if ($$hash{"self"} eq "local")
-        {
-        $$hash{"self"} = "pass";
-        $$hash{"pass_router"} = $first_director;
-        }
-      elsif ($$hash{"self"} eq "fail_hard")
-        {
-        $$hash{"self"} = "fail";
-        }
-      elsif ($$hash{"self"} eq "fail_soft")
-        {
-        $$hash{"self"} = "pass";
-        }
-      }
-
-    # If the router had a require_files setting, check it for user names
-    # and colons that are part of expansion items
-
-    if (defined $$hash{"require_files"})
-      {
-      &check_require($$hash{"require_files"}, "'$name' router");
-      if (($$hash{"require_files"} =~ s/(\$\{\w+):/$1::/g) > 0 ||
-          ($$hash{"require_files"} =~ s/ldap:/ldap::/g) > 0)
-        {
-        &rubric();
-        print STDERR "\n" .
-"*** A setting of require_files in the $name router contains\n" .
-"    a colon in what appears to be an expansion item. In Exim 3, the\n" .
-"    whole string was expanded before splitting the list, but in Exim 4\n" .
-"    each item is expanded separately, so colons that are not list\n" .
-"    item separators have to be doubled. One or more such colons in this\n" .
-"    list have been doubled as a precaution. Please check the result.\n";
-        }
-      }
-
-    # If the router had a "senders" setting, munge the address list
-
-    $$hash{"senders"} = &sort_address_list($$hash{"senders"}, "senders")
-      if defined $$hash{"senders"};
-
-    # ---- Changes to domainlist router ----
-
-    if ($driver eq "domainlist")
-      {
-      &abolished($hash, "A domainlist router",
-        "modemask", "owners", "owngroups",
-        "qualify_single", "search_parents");
-
-      # The name has changed
-
-      $$hash{"driver"} = "manualroute";
-
-      # Turn "route_file", "route_query" and "route_queries" into lookups for
-      # route_data.
-
-      if (defined $$hash{"route_file"})
-        {
-        $$hash{"route_data"} = "\${lookup\{\$domain\}$$hash{'search_type'}" .
-                         "\{$$hash{'route_file'}\}\}";
-        }
-      elsif (defined $$hash{"route_query"})
-        {
-        $$hash{"route_data"} = "\${lookup $$hash{'search_type'}" .
-                               "\{" . &unquote($$hash{'route_query'}) . "\}\}";
-        }
-      elsif (defined $$hash{"route_queries"})
-        {
-        $endkets = 0;
-        $$hash{"route_data"} = "";
-        $route_queries = $$hash{'route_queries'};
-        $route_queries =~ s/^"(.*)"$/$1/s;
-        $route_queries =~ s/::/++colons++/g;
-        @qq = split(/:/, $route_queries);
-
-        foreach $q (@qq)
-          {
-          $q =~ s/\+\+colons\+\+/:/g;
-          $q =~ s/^\s+//;
-          $q =~ s/\s+$//;
-          if ($endkets > 0)
-            {
-            $$hash{"route_data"} .= "\\\n    {";
-            $endkets++;
-            }
-          $$hash{"route_data"} .= "\${lookup $$hash{'search_type'} \{$q\}\{\$value\}";
-          $endkets++;
-          }
-
-        $$hash{"route_data"} .= "}" x $endkets;
-        }
-
-      delete $$hash{"route_file"};
-      delete $$hash{"route_query"};
-      delete $$hash{"route_queries"};
-      delete $$hash{"search_type"};
-
-      # But we can't allow both route_data and route_list
-
-      if (defined $$hash{"route_data"} && defined $$hash{"route_list"})
-        {
-        &rubric();
-        print STDERR "\n" .
-"** An Exim 3 'domainlist' router called '$name' contained a 'route_list'\n" .
-"   option as well as a setting of 'route_file', 'route_query', or\n" .
-"   'route_queries'. The latter has been turned into a 'route_data' setting,\n".
-"   but in Exim 4 you can't have both 'route_data' and 'route_list'. You'll\n" .
-"   have to rewrite this router; in the meantime, 'route_list' has been\n" .
-"   omitted.\n";
-        print STDOUT "#!!# route_list option removed\n";
-        delete $$hash{"route_list"};
-        }
-
-      # Change bydns_a into bydns in a route_list; also bydns_mx, but that
-      # works differently.
-
-      if (defined $$hash{"route_list"})
-        {
-        $$hash{"route_list"} =~ s/bydns_a/bydns/g;
-        if ($$hash{"route_list"} =~ /bydns_mx/)
-          {
-          $$hash{"route_list"} =~ s/bydns_mx/bydns/g;
-          &rubric();
-          print STDERR "\n" .
-"*** An Exim 3 'domainlist' router called '$name' contained a 'route_list'\n" .
-"    option which used 'bydns_mx'. This feature no longer exists in Exim 4.\n" .
-"    It has been changed to 'bydns', but it won't have the same effect,\n" .
-"    because it will look for A rather than MX records. Use the 'dnslookup'\n" .
-"    router to do MX lookups - if you want to override the hosts found from\n" .
-"    MX records, you should route to a special 'smtp' transport which has\n" .
-"    both 'hosts' and 'hosts_override' set.\n";
-          }
-        }
-
-      # Arrange to not expand regex
-
-      $$hash{"route_list"} = &no_expand_regex($$hash{"route_list"}, ";")
-        if (defined $$hash{"route_list"})
-      }
-
-
-    # ---- Changes to iplookup router ----
-
-    elsif ($driver eq "iplookup")
-      {
-      &renamed($hash, "service", "port");
-      }
-
-
-    # ---- Changes to lookuphost router ----
-
-    elsif ($driver eq "lookuphost")
-      {
-      $$hash{"driver"} = "dnslookup";
-
-      if (defined $$hash{"gethostbyname"})
-        {
-        &rubric();
-        print STDERR "\n" .
-"** An Exim 3 'lookuphost' router called '$name' used the 'gethostbyname'\n" .
-"   option, which no longer exists. You will have to rewrite it.\n";
-        print STDOUT "#!!# gethostbyname option removed\n";
-        delete $$hash{"gethostbyname"};
-        }
-
-      $$hash{"mx_domains"} = &no_expand_regex($$hash{"mx_domains"})
-        if defined $$hash{"mx_domains"};
-      }
-
-
-    # ---- Changes to the queryprogram router ----
-
-    elsif ($driver eq "queryprogram")
-      {
-      &rubric();
-      print STDERR "\n" .
-"** The configuration contains a 'queryprogram' router. Please note that\n" .
-"   the specification for the text that is returned by the program run\n" .
-"   by this router has changed in Exim 4. You will need to modify your\n" .
-"   program.\n";
-
-      if (!defined $$hash{'command_user'})
-        {
-        &rubric();
-        print STDERR "\n" .
-"** The 'queryprogram' router called '$name' does not have a setting for\n" .
-"   the 'command_user' option. This is mandatory in Exim 4. A setting of\n" .
-"   'nobody' has been created.\n";
-        $$hash{"command_user"} = "nobody";
-        }
-      }
-
-
-    # -------------------------------------
-
-    # Output the router's option settings
-
-    &outdriver($hash);
-    next;
-    }
-
-  # Skip past any continuation lines for an option setting
-  while ($c[$i] =~ /\\\s*$/s && $i < $clen - 1)
-    {
-    $i++;
-    $i++ while ($c[$i] =~ /^\s*#/);
-    }
-  }
-
-# Add "no_more" to the final driver from the old routers, provided it had no
-# conditions. Otherwise, or if there were no routers, make up one to fail all
-# non-local domains.
-
-if ($add_no_more)
-  {
-  print STDOUT "  no_more\n";
-  print STDOUT shift @comments while scalar(@comments) > 0;
-  }
-else
-  {
-  print STDOUT shift @comments while scalar(@comments) > 0;
-  print STDOUT "\n#!!# This new router is put here to fail all domains that\n";
-  print STDOUT "#!!# were not in local_domains in the Exim 3 configuration.\n\n";
-  print STDOUT "fail_remote_domains:\n";
-  print STDOUT "  driver = redirect\n";
-  print STDOUT "  domains = ! +local_domains\n";
-  print STDOUT "  allow_fail\n";
-  print STDOUT "  data = :fail: unrouteable mail domain \"\$domain\"\n\n";
-  }
-
-# Now copy the directors, making appropriate changes
-
-print STDOUT "\n";
-print STDOUT "#!!#######################################################!!#\n";
-print STDOUT "#!!# Here follow routers created from the old directors, #!!#\n";
-print STDOUT "#!!# for handling local domains.                         #!!#\n";
-print STDOUT "#!!#######################################################!!#\n";
-
-$prefix = "d.";
-for ($i = $director_start; $i < $clen; $i++)
-  {
-  $type = &checkline($c[$i]);
-  last if $type eq "end";
-
-  if ($type eq "comment") { print STDOUT "$c[$i]\n"; next; }
-
-  undef $second_router;
-
-  if ($type eq "driver")
-    {
-    $hash = $driverlist{"$prefix$name"};
-    $driver = $$hash{"driver"};
-    print STDOUT "$name:\n";
-
-    $$hash{"caseful_local_part"} = "true" if $add_caseful_local_part;
-
-    if (defined $$hash{"local_parts"} &&
-        (defined $$hash{"prefix"} || defined $hash{"suffix"}))
-      {
-      &rubric();
-      print STDERR "\n" .
-"** The Exim 3 configuration contains a director called '$name' which has\n" .
-"   'local_parts' set, together with either or both of 'prefix' and 'suffix'\n".
-"   This combination has a different effect in Exim 4, where the affix\n" .
-"   is removed *before* 'local_parts' is tested. You will probably need\n" .
-"   to make changes to this driver.\n";
-      }
-
-    &renamed($hash, "prefix", "local_part_prefix");
-    &renamed($hash, "prefix_optional", "local_part_prefix_optional");
-    &renamed($hash, "suffix", "local_part_suffix");
-    &renamed($hash, "suffix_optional", "local_part_suffix_optional");
-    &renamed($hash, "new_director", "redirect_router");
-
-    &handle_current_and_home_directory($hash, $driver, $name);
-
-    # If the director had a require_files setting, check it for user names
-    # and colons that are part of expansion items
-
-    if (defined $$hash{"require_files"})
-      {
-      &check_require($$hash{"require_files"}, "'$name' director");
-      if (($$hash{"require_files"} =~ s/(\$\{\w+):/$1::/g) > 0 ||
-          ($$hash{"require_files"} =~ s/ldap:/ldap::/g) > 0)
-        {
-        &rubric();
-        print STDERR "\n" .
-"*** A setting of require_files in the $name director contains\n" .
-"    a colon in what appears to be an expansion item. In Exim 3, the\n" .
-"    whole string was expanded before splitting the list, but in Exim 4\n" .
-"    each item is expanded separately, so colons that are not list\n" .
-"    item separators have to be doubled. One or more such colons in this\n" .
-"    list have been doubled as a precaution. Please check the result.\n";
-        }
-      }
-
-    # If the director had a "senders" setting, munge the address list
-
-    $$hash{"senders"} = &sort_address_list($$hash{"senders"}, "senders")
-      if defined $$hash{"senders"};
-
-    # ---- Changes to aliasfile director ----
-
-    if ($driver eq "aliasfile")
-      {
-      &abolished($hash, "An aliasfile director",
-        "directory2_transport", "freeze_missing_include",
-        "modemask", "owners", "owngroups");
-
-      $$hash{"driver"} = "redirect";
-
-      $key = "\$local_part";
-      $key = "\$local_part\@\$domain"
-        if defined $$hash{"include_domain"} &&
-          $$hash{"include_domain"} eq "true";
-      delete $$hash{"include_domain"};
-
-      if (defined $$hash{"forbid_special"} && $$hash{"forbid_special"} eq "true")
-        {
-        $$hash{"forbid_blackhole"} = "true";
-        }
-      else
-        {
-        $$hash{"allow_defer"} = "true";
-        $$hash{"allow_fail"} = "true";
-        }
-      delete $$hash{"forbid_special"};
-
-      # Deal with "file", "query", or "queries"
-
-      if (defined $$hash{"file"})
-        {
-        $$hash{"data"} =
-          "\$\{lookup\{$key\}$$hash{'search_type'}\{$$hash{'file'}\}\}";
-        if (defined $$hash{"optional"} && $$hash{"optional"} eq "true")
-          {
-          $$hash{"data"} =
-            "\$\{if exists\{$$hash{'file'}\}\{$$hash{'data'}\}\}";
-          }
-        delete $$hash{"optional"};
-        }
-      elsif (defined $$hash{"query"})
-        {
-        &abolished($hash, "An aliasfile director", "optional");
-        $$hash{"data"} = "\${lookup $$hash{'search_type'} " .
-                         "\{" . &unquote($$hash{'query'}) . "\}\}";
-        }
-      else   # Must be queries
-        {
-        &abolished($hash, "An aliasfile director", "optional");
-        $endkets = 0;
-        $$hash{"data"} = "";
-        $queries = $$hash{'queries'};
-        $queries =~ s/^"(.*)"$/$1/s;
-        $queries =~ s/::/++colons++/g;
-        @qq = split(/:/, $queries);
-
-        foreach $q (@qq)
-          {
-          $q =~ s/\+\+colons\+\+/:/g;
-          $q =~ s/^\s+//;
-          $q =~ s/\s+$//;
-          if ($endkets > 0)
-            {
-            $$hash{"data"} .= "\\\n    {";
-            $endkets++;
-            }
-          $$hash{"data"} .= "\${lookup $$hash{'search_type'} \{$q\}\{\$value\}";
-          $endkets++;
-          }
-
-        $$hash{"data"} .= "}" x $endkets;
-        }
-
-      $$hash{"data"} = "\${expand:$$hash{'data'}\}"
-        if (defined $$hash{"expand"} && $$hash{"expand"} eq "true");
-
-      delete $$hash{"expand"};
-      delete $$hash{"file"};
-      delete $$hash{"query"};
-      delete $$hash{"queries"};
-      delete $$hash{"search_type"};
-
-      # Turn aliasfile + transport into accept + condition
-
-      if (defined $$hash{'transport'})
-        {
-        &rubric();
-        if (!defined $$hash{'condition'})
-          {
-          print STDERR "\n" .
-"** The Exim 3 configuration contains an aliasfile director called '$name',\n".
-"   which has 'transport' set. This has been turned into an 'accept' router\n".
-"   with a 'condition' setting, but should be carefully checked.\n";
-          $$hash{'driver'} = "accept";
-          $$hash{'condition'} =
-            "\$\{if eq \{\}\{$$hash{'data'}\}\{no\}\{yes\}\}";
-          delete $$hash{'data'};
-          delete $$hash{'allow_defer'};
-          delete $$hash{'allow_fail'};
-          }
-        else
-          {
-          print STDERR "\n" .
-"** The Exim 3 configuration contains an aliasfile director called '$name',\n".
-"   which has 'transport' set. This cannot be turned into an 'accept' router\n".
-"   with a 'condition' setting, because there is already a 'condition'\n" .
-"   setting. It has been left as 'redirect' with a transport, which is\n" .
-"   invalid - you must sort this one out.\n";
-          }
-        }
-      }
-
-
-    # ---- Changes to forwardfile director ----
-
-    elsif ($driver eq "forwardfile")
-      {
-      &abolished($hash, "A forwardfile director",
-        "check_group", "directory2_transport",
-        "freeze_missing_include", "match_directory",
-        "seteuid");
-
-      &renamed($hash, "filter", "allow_filter");
-
-      $$hash{"driver"} = "redirect";
-      $$hash{"check_local_user"} = "true"
-        if !defined $$hash{"check_local_user"};
-
-      if (defined $$hash{"forbid_pipe"} && $$hash{"forbid_pipe"} eq "true")
-        {
-        print STDOUT "#!!# forbid_filter_run added because forbid_pipe is set\n";
-        $$hash{"forbid_filter_run"} = "true";
-        }
-
-      if (defined $$hash{'allow_system_actions'} &&
-          $$hash{'allow_system_actions'} eq 'true')
-        {
-        $$hash{'allow_freeze'} = "true";
-        }
-      delete $$hash{'allow_system_actions'};
-
-      # If file_directory is defined, use it to qualify relative paths; if not,
-      # and check_local_user is defined, use $home. Remove file_directory from
-      # the output.
-
-      $dir = "";
-      if (defined $$hash{"file_directory"})
-        {
-        $dir = $$hash{"file_directory"} . "/";
-        delete $$hash{"file_directory"};
-        }
-      elsif ($$hash{"check_local_user"} eq "true")
-        {
-        $dir = "\$home/";
-        }
-
-      # If it begins with an upper case letter, guess that this is really
-      # a macro.
-
-      if (defined $$hash{"file"} && $$hash{"file"} !~ /^[\/A-Z]/)
-        {
-        $$hash{"file"} = $dir . $$hash{"file"};
-        }
-      }
-
-
-    # ---- Changes to localuser director ----
-
-    elsif ($driver eq "localuser")
-      {
-      &abolished($hash, "A localuser director", "match_directory");
-      $$hash{"driver"} = "accept";
-      $$hash{"check_local_user"} = "true";
-      }
-
-
-    # ---- Changes to smartuser director ----
-
-    elsif ($driver eq "smartuser")
-      {
-      &abolished($hash, "A smartuser director", "panic_expansion_fail");
-
-      $transport = $$hash{"transport"};
-      $new_address = $$hash{"new_address"};
-
-      if (defined $transport && defined $new_address)
-        {
-        &rubric();
-        print STDERR "\n" .
-"** The Exim 3 configuration contains a smartuser director called '$name',\n".
-"   which has both 'transport' and 'new_address' set. This has been turned\n".
-"   into two routers for Exim 4. However, if the new address contains a\n" .
-"   reference to \$local_part, this won't work correctly. In any case, you\n".
-"   may be able to make it tidier by rewriting.\n";
-        $$hash{"driver"} = "redirect";
-        $$hash{"data"} = $new_address;
-        $$hash{"redirect_router"} = "${name}_part2";
-
-        $second_router = "\n".
-          "#!!# This router is invented to go with the previous one because\n".
-          "#!!# in Exim 4 you can't have a change of address and a transport\n".
-          "#!!# setting in the same router as you could in Exim 3.\n\n" .
-          "${name}_part2:\n".
-          "  driver = accept\n".
-          "  condition = \$\{if eq\{\$local_part@\$domain\}" .
-          "\{$new_address\}\{yes\}\{no\}\}\n".
-          "  transport = $$hash{'transport'}\n";
-
-        delete $$hash{"new_address"};
-        delete $$hash{"transport"};
-        }
-      elsif (defined $new_address)
-        {
-        $$hash{"driver"} = "redirect";
-        $$hash{"data"} = $new_address;
-        $$hash{"allow_defer"} = "true";
-        $$hash{"allow_fail"} = "true";
-        delete $$hash{"new_address"};
-        }
-      else     # Includes the case of neither set (verify_only)
-        {
-        $$hash{"driver"} = "accept";
-        if (defined $$hash{"rewrite"})
-          {
-          &rubric();
-          print STDERR "\n" .
-"** The Exim 3 configuration contains a setting of the 'rewrite' option on\n".
-"   a smartuser director called '$name', but this director does not have\n".
-"   a setting of 'new_address', so 'rewrite' has no effect. The director\n".
-"   has been turned into an 'accept' router, and 'rewrite' has been discarded.";
-          delete $$hash{"rewrite"};
-          }
-        }
-      }
-
-
-    # -------------------------------------
-
-    # For ex-directors that don't have check_local_user set, add
-    # retry_use_local_part to imitate what Exim 3 would have done.
-
-    $$hash{"retry_use_local_part"} = "true"
-      if (!defined $$hash{"check_local_user"} ||
-          $$hash{"check_local_user"} eq "false") ;
-
-    # Output the router's option settings
-
-    &outdriver($hash);
-
-    # Output an auxiliary router if one is needed
-
-    print STDOUT $second_router if defined $second_router;
-
-    next;
-    }
-
-  # Skip past any continuation lines for an option setting
-  while ($c[$i] =~ /\\\s*$/s)
-    {
-    $i++;
-    $i++ while ($c[$i] =~ /^\s*#/);
-    }
-  }
-
-
-
-# -------- The transports configuration --------
-
-$started = 0;
-$prefix = "t.";
-for ($i = $transport_start; $i < $clen; $i++)
-  {
-  $type = &checkline($c[$i]);
-  last if $type eq "end";
-
-  if ($type eq "comment") { print STDOUT "$c[$i]\n"; next; }
-
-  if (!$started)
-    {
-    print STDOUT "begin transports\n\n";
-    $started = 1;
-    }
-
-  if ($type eq "driver")
-    {
-    $hash = $driverlist{"$prefix$name"};
-    $driver = $$hash{"driver"};
-    print STDOUT "$name:\n";
-
-    # ---- Changes to the appendfile transport ----
-
-    if ($driver eq "appendfile")
-      {
-      &renamed($hash, "prefix", "message_prefix");
-      &renamed($hash, "suffix", "message_suffix");
-      &abolished($hash, "An appendfile transport",
-        "require_lockfile");
-      &handle_batch_and_bsmtp($hash);
-      if (defined $$hash{"from_hack"} && $$hash{"from_hack"} eq "false")
-        {
-        print STDOUT "#!!# no_from_hack replaced by check_string\n";
-        $$hash{"check_string"} = "";
-        }
-      delete $$hash{"from_hack"};
-      }
-
-    # ---- Changes to the lmtp transport ----
-
-    elsif ($driver eq "lmtp")
-      {
-      if (defined $$hash{"batch"} && $$hash{"batch"} ne "none")
-        {
-        $$hash{"batch_max"} = "100" if !defined $$hash{"batch_max"};
-        $$hash{"batch_id"} = "\$domain" if $$hash{"batch"} eq "domain";
-        }
-      else
-        {
-        $$hash{"batch_max"} = "1" if defined $$hash{"batch_max"};
-        }
-      delete $$hash{"batch"};
-      }
-
-    # ---- Changes to the pipe transport ----
-
-    elsif ($driver eq "pipe")
-      {
-      &renamed($hash, "prefix", "message_prefix");
-      &renamed($hash, "suffix", "message_suffix");
-      &handle_batch_and_bsmtp($hash);
-      if (defined $$hash{"from_hack"} && $$hash{"from_hack"} eq "false")
-        {
-        print STDOUT "#!!# no_from_hack replaced by check_string\n";
-        $$hash{"check_string"} = "";
-        }
-      delete $$hash{"from_hack"};
-      }
-
-    # ---- Changes to the smtp transport ----
-
-    elsif ($driver eq "smtp")
-      {
-      &abolished($hash, "An smtp transport", "mx_domains");
-      &renamed($hash, "service", "port");
-      &renamed($hash, "tls_verify_ciphers", "tls_require_ciphers");
-      &renamed($hash, "authenticate_hosts", "hosts_try_auth");
-
-      if (defined $$hash{"batch_max"})
-        {
-        print STDOUT "#!!# batch_max renamed connection_max_messages\n";
-        $$hash{"connection_max_messages"} = $$hash{"batch_max"};
-        delete $$hash{"batch_max"};
-        }
-
-      foreach $o ("hosts_try_auth", "hosts_avoid_tls", "hosts_require_tls",
-                  "mx_domains", "serialize_hosts")
-        {
-        $$hash{$o} = &no_expand_regex($$hash{$o}) if defined $$hash{$o};
-        }
-      }
-
-    &outdriver($driverlist{"$prefix$name"});
-    next;
-    }
-
-  # Skip past any continuation lines for an option setting
-  while ($c[$i] =~ /\\\s*$/s)
-    {
-    $i++;
-    $i++ while ($c[$i] =~ /^\s*#/);
-    }
-  }
-
-
-# -------- The retry configuration --------
-
-$started = 0;
-for ($i = $retry_start; $i < $clen && $i < $rewrite_start - 1; $i++)
-  {
-  if (!$started)
-    {
-    if ($c[$i] !~ /^\s*(#|$)/)
-      {
-      print STDOUT "\nbegin retry\n\n";
-      $started = 1;
-      }
-    }
-  &print_no_expand($c[$i]);
-  }
-
-print STDOUT "\n# End of Exim 4 configuration\n";
-
-print STDERR "\n*******************************************************\n";
-print STDERR   "***** Please review the generated file carefully. *****\n";
-print STDERR   "*******************************************************\n\n";
-
-# End of convert4r4
-


--
## subscription configuration (requires account):
## https://lists.exim.org/mailman3/postorius/lists/exim-cvs.lists.exim.org/
## unsubscribe (doesn't require an account):
## exim-cvs-unsubscribe@???
## Exim details at http://www.exim.org/
## Please use the Wiki with this list - http://wiki.exim.org/