#! /usr/bin/perl

# 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: 4.96\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 optio                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      