perl paranoia about @INC
[users/heiko/exim.git] / src / src / convert4r4.src
1 #! PERL_COMMAND
2
3 # This is a Perl script that reads an Exim run-time configuration file for
4 # Exim 3. It makes what changes it can for Exim 4, and also output commentary
5 # on what it has done, and on things it cannot do.
6
7 # It is assumed that the input is a valid Exim 3 configuration file.
8
9 use warnings;
10 BEGIN { pop @INC if $INC[-1] eq '.' };
11
12 # These are lists of main options which are abolished in Exim 4.
13 # The first contains options that are used to construct new options.
14
15 @skipped_options = (
16 "auth_hosts",
17 "auth_over_tls_hosts",
18 "errors_address",
19 "headers_check_syntax",
20 "headers_checks_fail",
21 "headers_sender_verify",
22 "headers_sender_verify_errmsg",
23 "host_accept_relay",
24 "host_auth_accept_relay",
25 "host_reject_recipients",
26 "local_domains",
27 "local_domains_include_host",
28 "local_domains_include_host_literals",
29 "log_all_parents",
30 "log_arguments",
31 "log_incoming_port",
32 "log_interface",
33 "log_level",
34 "log_received_sender",
35 "log_received_recipients",
36 "log_rewrites",
37 "log_sender_on_delivery",
38 "log_smtp_confirmation",
39 "log_smtp_connections",
40 "log_smtp_syntax_errors",
41 "log_subject",
42 "log_queue_run_level",
43 "rbl_domains",
44 "rbl_hosts",
45 "rbl_reject_recipients",
46 "receiver_verify",
47 "receiver_verify_addresses",
48 "receiver_verify_hosts",
49 "receiver_verify_senders",
50 "recipients_reject_except",
51 "recipients_reject_except_senders",
52 "relay_domains",
53 "relay_domains_include_local_mx",
54 "sender_address_relay",
55 "sender_address_relay_hosts",
56 "sender_reject_recipients",
57 "sender_verify",
58 "sender_verify_hosts_callback",
59 "sender_verify_callback_domains",
60 "sender_verify_callback_timeout",
61 "sender_verify_hosts",
62 "smtp_etrn_hosts",
63 "smtp_expn_hosts",
64 "smtp_verify",
65 "tls_host_accept_relay",
66 "tls_hosts",
67 "tls_log_cipher",
68 "tls_log_peerdn",
69 "tls_verify_ciphers"
70 );
71
72 # The second contains options that are completely abolished and have
73 # no equivalent.
74
75 @abolished_options = (
76 "always_bcc",
77 "debug_level",
78 "helo_strict_syntax",
79 "kill_ip_options",
80 "log_ip_options",
81 "log_refused_recipients",
82 "message_size_limit_count_recipients",
83 "rbl_log_headers",
84 "rbl_log_rcpt_count",
85 "receiver_try_verify",
86 "refuse_ip_options",
87 "relay_match_host_or_sender",
88 "sender_try_verify",
89 "sender_verify_batch",
90 "sender_verify_fixup",
91 "sender_verify_reject",
92 "sender_verify_max_retry_rate",
93 );
94
95 # This is a list of options that are not otherwise handled, but which
96 # contain domain or host lists that have to be processed so that any
97 # regular expressions are marked "not for expansion".
98
99 @list_options = (
100 "dns_again_means_nonexist",
101 "hold_domains",
102 "hosts_treat_as_local",
103 "percent_hack_domains",
104 "queue_smtp_domains",
105 "helo_accept_junk_hosts",
106 "host_lookup",
107 "ignore_fromline_hosts",
108 "rfc1413_hosts",
109 "sender_unqualified_hosts",
110 "smtp_reserve_hosts",
111 "tls_advertise_hosts",
112 "tls_verify_hosts",
113 );
114
115
116
117 ##################################################
118 #          Output problem rubric once            #
119 ##################################################
120
121 sub rubric {
122 return if $rubric_output;
123 $rubric_output = 1;
124 print STDERR "\n" .
125 "** The following comments describe problems that have been encountered\n" .
126 "   while converting an Exim 3 runtime file for Exim 4. More detail can\n" .
127 "   be found in the file doc/Exim4.upgrade.\n";
128 }
129
130
131 ##################################################
132 #             Analyse one line                   #
133 ##################################################
134
135 sub checkline{
136 my($line) = $_[0];
137
138 return "comment" if $line =~ /^\s*(#|$)/;
139 return "end"     if $line =~ /^\s*end\s*$/i;
140
141 # Macros are recognized only in the first section of the file.
142
143 return "macro" if $prefix eq "" && $line =~ /^\s*[A-Z]/;
144
145 # In retry and rewrite sections, the type is always "other"
146
147 return "other" if $prefix eq "=retry" || $prefix eq "=rewrite";
148
149 # Pick out the name at the start and the rest of the line (into global
150 # variables) and return whether the start of a driver or not.
151
152 ($hide,$name,$rest) = $line =~ /^\s*(hide\s+|)([a-z0-9_]+)\s*(.*?)\s*$/;
153
154 # If $rest begins with a colon, this is a driver name
155
156 return "driver" if $rest =~ /^:/;
157
158 # If $rest begins with an = the value of the option is given explicitly;
159 # remove the = from the start. Turn "yes"/"no" into "true"/"false".
160
161 if ($rest =~ /^=/)
162   {
163   $rest =~ s/^=\s*//;
164   $rest = "true" if $rest eq "yes";
165   $rest = "false" if $rest eq "no";
166   }
167
168 # Otherwise we have a boolean option. Set up a "true"/"false" value.
169
170 else
171   {
172   if ($name =~ /^not?_/)     # Recognize "no_" or "not_"
173     {
174     $rest = "false";
175     $name =~ s/^not?_//;
176     }
177   else
178     {
179     $rest = "true";
180     }
181   }
182
183 return "option";
184 }
185
186
187
188 ##################################################
189 #       Negate a list of things                  #
190 ##################################################
191
192 # Can be tricky, because there may be comment lines in the list.
193 # Also, lists may have different delimiters.
194
195 sub negate {
196 my($list) = $_[0];
197 my($delim) = ":";
198 my($leadin) = "";
199
200 return $list if ! defined $list;
201
202 ($list) = $list =~ /^"?(.*?)"?\s*$/s;      # Remove surrounding quotes
203 $list =~ s/\\\s*\n\s*//g;                  # Remove continuation markers
204
205 if ($list =~ /^(\s*<(\S)\s*)(.*)/s)
206   {
207   $leadin = $1;
208   $delim = $2;
209   $list = $3;
210   }
211
212 $list =~ s/^\s+//;
213 $list =~ s/\Q$delim$delim/>%%%%</g;
214 @split = split /\s*\Q$delim\E\s*/s, $list;
215
216 foreach $item (@split)
217   {
218   $item =~ s/>%%%%</$delim$delim/g;
219
220   if ($item =~ /^\s*#/)
221     {
222     $item =~ s/((?:^\s*#[^\n]*\n)+\s*)/$1! /mg;
223     $item =~ s/!\s*!//sg;
224     }
225   else
226     {
227     if ($item =~ /^\s*!(.*)/)
228       { $item = $1; }
229     else
230       { $item = "! " . $item; }
231     }
232   }
233
234 $" = " $delim \\\n    ";
235 $leadin .= " " if $leadin !~ /(^|\s)$/;
236 return "$leadin@split";
237 }
238
239
240
241 ##################################################
242 #   Prevent regex expansion in a list of things  #
243 ##################################################
244
245 # Can be tricky, because there may be comment lines in the list.
246 # Also, lists may have different delimiters.
247
248 sub no_expand_regex {
249 my($list) = $_[0];
250 my($delim) = ":";
251 my($leadin) = "";
252
253 return $list if ! defined $list;
254
255 $delim = $_[1] if (defined $_[1]);
256
257 my($is_route_list) = $delim eq ";";
258
259 ($list) = $list =~ /^"?(.*?)"?\s*$/s;      # Remove surrounding quotes
260 $list =~ s/\\\s*\n\s*//g;                  # Remove continuation markers
261
262 if ($list =~ /^(\s*<(\S)\s*)(.*)/s)
263   {
264   $leadin = $1;
265   $delim = $2;
266   $list = $3;
267   }
268
269 $list =~ s/^\s+//;
270 $list =~ s/\Q$delim$delim/>%%%%</g;
271 @split = split /\s*\Q$delim\E\s*/s, $list;
272
273 my($changed) = 0;
274 foreach $item (@split)
275   {
276   $item =~ s/>%%%%</$delim$delim/g;
277   if ($item =~ /^\^/)
278     {
279     # Fudge for route_list items
280
281     if ($is_route_list)
282       {
283       $item = "\\N$item";      # Only one item ...
284       }
285     else
286       {
287       $item = "\\N$item\\N";
288       }
289     $changed = 1;
290     }
291   }
292 print STDOUT
293   "#!!# Regular expressions enclosed in \\N...\\N to avoid expansion\n"
294     if $changed;
295
296 $" = " $delim \\\n    ";
297 $leadin .= " " if $leadin !~ /(^|\s)$/;
298 return "$leadin@split";
299 }
300
301
302
303 ##################################################
304 #      Sort out lookups in an address list       #
305 ##################################################
306
307 # Can be tricky, because there may be comment lines in the list.
308 # Also, lists may have different delimiters.
309
310 sub sort_address_list {
311 my($list) = $_[0];
312 my($name) = $_[1];
313 my($delim) = ":";
314 my($leadin) = "";
315 my($quoted) = 0;
316
317 return $list if ! defined $list;
318
319 if ($list =~ /^"(.*?)"\s*$/s)            # Remove surrounding quotes
320   {
321   $list = $1;
322   $quoted = 1;
323   }
324
325 $list =~ s/\\\s*\n\s*//g;                  # Remove continuation markers
326
327 if ($list =~ /^(\s*<(\S)\s*)(.*)/s)
328   {
329   $leadin = $1;
330   $delim = $2;
331   $list = $3;
332   }
333
334 $list =~ s/^\s+//;
335 $list =~ s/\Q$delim$delim/>%%%%</g;
336 @split = split /\s*\Q$delim\E\s*/s, $list;
337
338 foreach $item (@split)
339   {
340   $item =~ s/>%%%%</$delim$delim/g;
341   if ($item =~ /^\s*(?:partial-)?(\w+;.*)$/)
342     {
343     my($lookup) = $1;
344     if ($lookup =~ /^lsearch|^dbm|^cdb|^nis[^p]/)
345       {
346       &rubric();
347       print STDERR "\n" .
348 "** The Exim 3 \"$name\" option specifies an address\n" .
349 "   list that includes the item\n\n" .
350 "     $item\n\n" .
351 "   In Exim 4 address lists, single-key lookups without a local part just\n" .
352 "   look up the complete address. They don't also try the domain, as\n" .
353 "   happened in Exim 3. The item has been rewritten as two items to make\n" .
354 "   it behave in the same way as Exim 3, but you should check to see if\n" .
355 "   this is actually what you want.\n";
356
357       $item = "*\@$item $delim $lookup";
358       }
359     }
360   }
361
362 $" = " $delim \\\n    ";
363 $leadin .= " " if $leadin !~ /(^|\s)$/;
364
365 return $quoted? "\"$leadin@split\"" : "$leadin@split";
366 }
367
368
369
370 ##################################################
371 #       Quote a string against expansion         #
372 ##################################################
373
374 # Used for setting up new "domains" options
375
376 sub expquote {
377 my($s) = $_[0];
378 $s =~ s/\$/\\\$/sg;
379 $s =~ s/\\(?!\s*\n)/\\\\/sg;
380 return $s;
381 }
382
383
384
385 ##################################################
386 #          Dequote an option string              #
387 ##################################################
388
389 # If the original list is not quoted, do nothing.
390 # If it is quoted, just get rid of the quotes.
391
392 sub unquote {
393 my($s) = $_[0];
394 $s =~ s/^"(.*)"$/$1/s;
395 return $s;
396 }
397
398
399 ##################################################
400 #      Quote/dequote an option string            #
401 ##################################################
402
403 # If the original list is not quoted, quote it against expansion.
404 # If it is quoted, just get rid of the quotes. Also, indent any
405 # continuations.
406
407 sub acl_quote {
408 my($s) = $_[0];
409 $s = ($s =~ /^"(.*)"$/s)? $1 : &expquote($s);
410 $s =~ s/\n/\n  /g;
411 $s =~ s/\n\s{11,}/\n           /g;
412 return $s;
413 }
414
415
416 ##################################################
417 #       Handle abolished driver options          #
418 ##################################################
419
420 sub abolished {
421 my($hash) = shift @_;
422 my($name) = shift @_;
423 for $abolished (@_)
424   {
425   if (defined $$hash{$abolished})
426     {
427     &rubric();
428     print STDERR "\n" .
429 "** $name used the \"$abolished\" option, which no\n".
430 "   longer exists. The option has been removed.\n";
431     print STDOUT "#!!# $abolished option removed\n";
432     delete $$hash{$abolished};
433     }
434   }
435 }
436
437
438
439 ##################################################
440 #        Handle renamed driver options           #
441 ##################################################
442
443 sub renamed {
444 my($hash,$old,$new) = @_;
445 if (defined $$hash{$old})
446   {
447   print STDOUT "#!!# $old renamed $new\n";
448   $$hash{$new} = $$hash{$old};
449   delete $$hash{$old};
450   }
451 }
452
453
454
455 ##################################################
456 #      Comment on user names in require_files    #
457 ##################################################
458
459 sub check_require {
460 my($string, $name) = @_;
461
462 $string =~ s/::/[[[]]]/g;
463 my(@list) = split /:/, $string;
464 my($item);
465
466 for $item (@list)
467   {
468   if ($item =~ /^\s*[\w,]+\s*$/)
469     {
470     &rubric();
471     $item =~ s/^\s*//;
472     $item =~ s/\s*$//;
473     print STDERR "\n" .
474 "** A setting of require_files in the $name contains\n" .
475 "   what appears to be a user name ('$item'). The ability to check files\n" .
476 "   as a specific user is done differently in Exim 4. In fact, because the\n" .
477 "   routers run as root, you may not need this at all.\n"
478     }
479   }
480 }
481
482
483 ##################################################
484 #        Handle current and home directory       #
485 ##################################################
486
487 sub handle_current_and_home_directory {
488 my($hash,$driver,$name) = @_;
489
490 for ("current_directory", "home_directory")
491   {
492   if (defined $$hash{$_} && $$hash{$_} eq "check_local_user")
493     {
494     my($article) = (substr($driver, 0, 1) eq "a")? "an" : "a";
495     &rubric();
496     print STDERR "\n" .
497 "** The Exim 3 configuration contains $article '$driver' director called\n" .
498 "   '$name', which set '$_' to the special value\n" .
499 "   'check_local_user'. This facility has been abolished in Exim 4 because\n" .
500 "   it is no longer necessary. The setting has therefore been omitted. See\n" .
501 "   note X.\n";
502     delete $$hash{$_};
503     }
504   else
505     {
506     &renamed($hash, $_, "transport_$_");
507     }
508   }
509 }
510
511
512
513 ##################################################
514 #    Handle batch/bsmtp for appendfile/pipe      #
515 ##################################################
516
517 sub handle_batch_and_bsmtp{
518 my($hash) = @_;
519
520 if (defined $$hash{"bsmtp"})
521   {
522   if ($$hash{"bsmtp"} ne "none")
523     {
524     $$hash{"use_bsmtp"} = "true";
525     $$hash{"message_prefix"} = "\"HELO \$primary_host_name\\n\""
526       if defined $$hash{"bsmtp_helo"} && $$hash{"bsmtp_helo"} eq "true";
527     }
528
529   if ($$hash{"bsmtp"} eq "one")
530     {
531     delete $$hash{"batch"};
532     }
533   else
534     {
535     $$hash{"batch"} = $$hash{"bsmtp"};
536     }
537
538   delete $$hash{"bsmtp"};
539   delete $$hash{"bsmtp_helo"};
540   }
541
542 if (defined $$hash{"batch"} && $$hash{"batch"} ne "none")
543   {
544   $$hash{"batch_max"} = "100" if !defined $$hash{"batch_max"};
545   $$hash{"batch_id"} = "\$domain" if $$hash{"batch"} eq "domain";
546   }
547 else
548   {
549   $$hash{"batch_max"} = "1" if defined $$hash{"batch_max"};
550   }
551 delete $$hash{"batch"};
552 }
553
554
555
556 ##################################################
557 #              Output one option                 #
558 ##################################################
559
560 sub outopt {
561 my($hash, $key, $no_expand) = @_;
562 my($data) = $$hash{$key};
563
564 print STDOUT "hide " if defined $$hash{"$key-hide"};
565
566 # Output booleans in the form that doesn't use "="
567
568 if ($data eq "true")
569   {
570   print STDOUT "$key\n";
571   }
572 elsif ($data eq "false")
573   {
574   print STDOUT "no_$key\n";
575   }
576 else
577   {
578   if ($no_expand)
579     {
580     printf STDOUT ("$key = %s\n", &no_expand_regex($data));
581     }
582   else
583     {
584     print STDOUT "$key = $data\n";
585     }
586   }
587 }
588
589
590
591 ##################################################
592 #       Output the options for one driver        #
593 ##################################################
594
595 # Put the "driver" option first
596
597 sub outdriver {
598 my($hash) = $_[0];
599 print STDOUT "  driver = $$hash{'driver'}\n";
600 foreach $key (sort keys %$hash)
601   {
602   next if $key eq "driver" || $key =~ /-hide$/;
603   print STDOUT "  ";
604   &outopt($hash, $key, 0);
605   }
606 }
607
608
609
610 ##################################################
611 #      Output a rewrite or a retry line          #
612 ##################################################
613
614 # These lines start with patterns which are now always expanded. If the
615 # pattern is a regex, arrange for it not to expand.
616
617 sub print_no_expand {
618 my($s) = $_[0];
619 if ($s =~ /^\^/)
620   {
621   if (!$escape_output)
622     {
623     &rubric();
624     print STDERR "\n" .
625 "** You have a retry or rewrite pattern that is a regular expression. Because\n" .
626 "   these patterns are now always expanded, you need to be sure that the\n" .
627 "   special characters in the regex are not interpreted by the expander.\n" .
628 "   \\N has been inserted at the start of the regex to prevent the rest of\n" .
629 "   it from being expanded.\n";
630     $escape_output = 1;
631     }
632   print STDOUT "\\N";
633   }
634 print STDOUT "$s\n";
635 }
636
637
638
639 ##################################################
640 #          Test a boolean main option            #
641 ##################################################
642
643 # This just saves a lot of typing
644
645 sub bool {
646 return defined $main{$_[0]} && $main{$_[0]} eq "true";
647 }
648
649
650
651 ##################################################
652 #                  Main program                  #
653 ##################################################
654
655 print STDERR "Runtime configuration file converter for Exim release 4.\n";
656
657 $transport_start = $director_start = $router_start = $retry_start
658   = $rewrite_start = $auth_start = 999999;
659
660 $macro_output = "";
661 $rubric_output = 0;
662 $errmsg_output = 0;
663 $key_output = 0;
664 $unk_output = 0;
665 $escape_output = 0;
666 $add_no_more = 0;
667 $add_caseful_local_part = 0;
668 $done_dns_check_names = 0;
669
670 $queue_only_load_was_present = 0;
671 $deliver_queue_load_max_was_present = 0;
672
673 # Read the entire file into an array
674
675 chomp(@c = <STDIN>);
676 $clen = scalar @c;
677
678 # Remove the standard comment that appears at the end of the default
679
680 if ($clen > 0 && $c[$clen-1] =~ /^#\s*End of Exim configuration file\s*/i)
681   {
682   pop @c;
683   $clen--;
684   }
685
686 # The first pass over the input fishes out all the options settings in the
687 # main, transport, director, and router sections, and places their values in
688 # associative arrays. It also notes the starting position of all the sections.
689
690 $prefix = "";
691 %main = ();
692 $hash = \%main;
693
694 for ($i = 0; $i < $clen; $i++)
695   {
696   # Change references to +allow_unknown and +warn_unknown into +include_unknown
697
698   if ($c[$i] =~ /\+(?:allow|warn)_unknown/)
699     {
700     if (!$unk_output)
701       {
702       &rubric();
703       print STDERR "\n" .
704 "** You have used '+allow_unknown' or '+warn_unknown' in a configuration\n" .
705 "   option. This has been converted to '+include_unknown', but the action\n" .
706 "   is different in Exim 4, so you should review all the relevant options.\n";
707       $unk_output = 1;
708       }
709     $c[$i] =~ s/\+(?:allow|warn)_unknown/+include_unknown/g;
710     }
711
712   # Any reference to $errmsg_recipient is changed to $bounce_recipient
713
714   if ($c[$i] =~ /\$errmsg_recipient/)
715     {
716     if (!$errmsg_output)
717       {
718       &rubric();
719       print STDERR "\n" .
720 "** References to \$errmsg_recipient have been changed to \$bounce_recipient\n";
721       $errmsg_output = 1;
722       }
723     $c[$i] =~ s/\$errmsg_recipient/\$bounce_recipient/g;
724     }
725
726
727   # Analyse the type of line
728
729   $type = &checkline($c[$i]);
730   next if $type eq "comment";
731
732   # Output a warning if $key is used
733
734   if ($c[$i] =~ /\$key/ && !$key_output)
735     {
736     &rubric();
737     print STDERR "\n" .
738 "** You have used '\$key' in a configuration option. This variable does not\n" .
739 "   exist in Exim 4. Instead, the value you need for your lookup will be\n" .
740 "   in one of the other variables such as '\$domain' or '\$host'. You will\n" .
741 "   need to edit the new configuration to sort this out.\n";
742     $key_output = 1;
743     }
744
745   # Save macro definitions so we can output them first; must handle
746   # continuations.
747
748   if ($type eq "macro")
749     {
750     $macro_output .= "$c[$i++]\n" while $c[$i] =~ /\\\s*$|^\s*#/;
751     $macro_output .= "$c[$i]\n";
752     }
753
754   # Handle end of section
755
756   elsif ($type eq "end")
757     {
758     if ($prefix eq "=rewrite")
759       {
760       $prefix = "a.";
761       $auth_start = $i + 1;
762       last;
763       }
764     elsif ($prefix eq "=retry")
765       {
766       $prefix = "=rewrite";
767       $rewrite_start = $i + 1;
768       }
769     elsif ($prefix eq "r.")
770       {
771       $prefix = "=retry";
772       $retry_start = $i + 1;
773       }
774     elsif ($prefix eq "d.")
775       {
776       $prefix = "r.";
777       $router_start = $i + 1;
778       }
779     elsif ($prefix eq "t.")
780       {
781       $prefix = "d.";
782       $director_start = $i + 1;
783       }
784     elsif ($prefix eq "")
785       {
786       $prefix = "t.";
787       $transport_start = $i + 1;
788       }
789     }
790
791   # Handle start of a new director, router or transport driver
792
793   elsif ($type eq "driver" && $prefix !~ /^=/)
794     {
795     $hash = {};
796     if (defined $driverlist{"$prefix$name"})
797       {
798       die "*** There are two drivers with the name \"$name\"\n";
799       }
800     $driverlist{"$prefix$name"} = $hash;
801     $first_director = $name if !defined $first_director && $prefix eq "d.";
802     }
803
804   # Handle definition of an option; we must pull in any continuation
805   # strings, and save the value in the current hash. Note if the option
806   # is hidden.
807
808   elsif ($type eq "option")
809     {
810     my($nextline) = "";
811
812     while ($i < $clen - 1 && ($rest =~ /\\\s*$/s || $nextline =~ /^\s*#/))
813       {
814       $nextline = $c[++$i];
815       $rest .= "\n$nextline";
816       }
817
818     $$hash{$name} = $rest;
819     $$hash{"$name-hide"} = 1 if $hide ne "";
820     }
821   }
822
823
824 # Generate the new configuration. Start with a warning rubric.
825
826 print STDOUT "#!!# This file is output from the convert4r4 script, which tries\n";
827 print STDOUT "#!!# to convert Exim 3 configurations into Exim 4 configurations.\n";
828 print STDOUT "#!!# However, it is not perfect, especially with non-simple\n";
829 print STDOUT "#!!# configurations. You must check it before running it.\n";
830 print STDOUT "\n\n";
831
832 # Output the macro definitions
833
834 if ($macro_output ne "")
835   {
836   print STDOUT "#!!# All macro definitions have been gathered here to ensure\n";
837   print STDOUT "#!!# they precede any references to them.\n\n";
838   print STDOUT "$macro_output\n";
839   }
840
841 # Output some default pointers to ACLs for RCPT and DATA time. If no Exim 3
842 # options that apply are set, non-restricting ACLs are generated.
843
844 print STDOUT "#!!# These options specify the Access Control Lists (ACLs) that\n";
845 print STDOUT "#!!# are used for incoming SMTP messages - after the RCPT and DATA\n";
846 print STDOUT "#!!# commands, respectively.\n\n";
847
848 print STDOUT "acl_smtp_rcpt = check_recipient\n";
849 print STDOUT "acl_smtp_data = check_message\n\n";
850
851 if (defined $main{"auth_over_tls_hosts"})
852   {
853   print STDOUT "#!!# This option specifies the Access Control List (ACL) that\n";
854   print STDOUT "#!!# is used after an AUTH command.\n\n";
855   print STDOUT "acl_smtp_auth = check_auth\n\n";
856   }
857
858 if (&bool("smtp_verify") ||
859     defined $main{"smtp_etrn_hosts"} ||
860     defined $main{"smtp_expn_hosts"})
861   {
862   print STDOUT "#!!# These options specify the Access Control Lists (ACLs) that\n";
863   print STDOUT "#!!# are used to control the ETRN, EXPN, and VRFY commands.\n";
864   print STDOUT "#!!# Where no ACL is defined, the command is locked out.\n\n";
865
866   print STDOUT "acl_smtp_etrn = check_etrn\n" if defined $main{"smtp_etrn_hosts"};
867   print STDOUT "acl_smtp_expn = check_expn\n" if defined $main{"smtp_expn_hosts"};
868   print STDOUT "acl_smtp_vrfy = check_vrfy\n" if &bool("smtp_verify");
869   print STDOUT "\n";
870   }
871
872 # If local_domains was set, get its value; otherwise set to "@". Add into it
873 # appropriate magic for local_domains_include_host[_literals].
874
875 $local_domains = (defined $main{"local_domains"})? $main{"local_domains"} : "@";
876
877 $ldsep = ":";
878 if ($local_domains =~ /^\s*<(.)\s*(.*)/s)
879   {
880   $ldsep = $1;
881   $local_domains = $2;
882   }
883
884 $local_domains = "\@[] $ldsep " . $local_domains
885   if defined $main{"local_domains_include_host_literals"} &&
886      $main{"local_domains_include_host_literals"} eq "true";
887
888 $local_domains = "\@ $ldsep " . $local_domains
889   if defined $main{"local_domains_include_host"} &&
890      $main{"local_domains_include_host"} eq "true";
891
892 $local_domains = "<$ldsep " . $local_domains if $ldsep ne ":";
893
894 # Output a domain list setting for these domains, provided something is defined
895
896 if ($local_domains !~ /^\s*$/)
897   {
898   print STDOUT "#!!# This setting defines a named domain list called\n";
899   print STDOUT "#!!# local_domains, created from the old options that\n";
900   print STDOUT "#!!# referred to local domains. It will be referenced\n";
901   print STDOUT "#!!# later on by the syntax \"+local_domains\".\n";
902   print STDOUT "#!!# Other domain and host lists may follow.\n\n";
903
904   printf STDOUT ("domainlist local_domains = %s\n\n",
905     &no_expand_regex($local_domains));
906   }
907
908 $relay_domains = (defined $main{"relay_domains"})? $main{"relay_domains"} : "";
909
910 $ldsep = ":";
911 if ($relay_domains =~ /^\s*<(.)\s*(.*)/s)
912   {
913   $ldsep = $1;
914   }
915
916 if (defined $main{"relay_domains_include_local_mx"})
917   {
918   $relay_domains .= ($relay_domains =~ /^\s*$/)? "\@mx_any" :
919     " $ldsep \@mx_any";
920   }
921
922 printf STDOUT ("domainlist relay_domains = %s\n",
923   &no_expand_regex($relay_domains))
924     if $relay_domains !~ /^\s*$/;
925
926
927 # If ignore_errmsg_errors is set, we are going to force 0s as the value
928 # for ignore_errmsg_errors_after, so arrange to skip any other value.
929
930 push @skipped_options, "ignore_errmsg_errors_after"
931    if &bool("ignore_errmsg_errors");
932
933
934 # If rbl_domains is set, split it up and generate six lists:
935 #   rbl_warn_domains, rbl_warn_domains_skiprelay
936 #   rbl_reject_domains, rbl_reject_domains_skiprelay
937 #   rbl_accept_domains, rbl_accept_domains_skiprelay
938
939 if (defined $main{"rbl_domains"})
940   {
941   my($s) = &unquote($main{"rbl_domains"});
942   $s =~ s/\s*\\\s*\n\s*/ /g;
943   my(@list) = split /\s*:\s*/, $s;
944
945   foreach $d (@list)
946     {
947     my(@sublist) = split /\//, $d;
948     my($name) = shift @sublist;
949     my($warn) = 0;
950     if (defined $main{"rbl_reject_recipients"})
951       {
952       $warn = $main{"rbl_reject_recipients"} ne "true";
953       }
954
955     foreach $o (@sublist)
956       {
957       $warn = 1 if $o eq "warn";
958       $warn = 0 if $o eq "reject";
959       $warn = 2 if $o eq "accept";
960       $skiprelay = 1 if $o eq "skiprelay";
961       }
962
963     if ($skiprelay)
964       {
965       if ($warn == 0)
966         {
967         $rbl_reject_skiprelay .= ((defined $rbl_reject_skiprelay)? ":":"").$name;
968         }
969       elsif ($warn == 1)
970         {
971         $rbl_warn_skiprelay .= ((defined $rbl_warn_skiprelay)? ":":"").$name;
972         }
973       elsif ($warn == 2)
974         {
975         $rbl_accept_skiprelay .= ((defined $rbl_accept_skiprelay)? ":":"").$name;
976         }
977       }
978     else
979       {
980       if ($warn == 0)
981         {
982         $rbl_reject_domains .= ((defined $rbl_reject_domains)? ":":"").$name;
983         }
984       elsif ($warn == 1)
985         {
986         $rbl_warn_domains .= ((defined $rbl_warn_domains)? ":":"").$name;
987         }
988       elsif ($warn == 2)
989         {
990         $rbl_accept_domains .= ((defined $rbl_accept_domains)? ":":"").$name;
991         }
992       }
993     }
994   }
995
996
997 # Output host list settings
998
999 printf STDOUT ("hostlist auth_hosts = %s\n",
1000   &no_expand_regex($main{"auth_hosts"}))
1001     if defined $main{"auth_hosts"};
1002 printf STDOUT ("hostlist rbl_hosts = %s\n",
1003   &no_expand_regex($main{"rbl_hosts"}))
1004     if defined $main{"rbl_hosts"};
1005 printf STDOUT ("hostlist relay_hosts = %s\n",
1006   &no_expand_regex($main{"host_accept_relay"}))
1007     if defined $main{"host_accept_relay"};
1008 printf STDOUT ("hostlist auth_relay_hosts = %s\n",
1009   &no_expand_regex($main{"host_auth_accept_relay"}))
1010     if defined $main{"host_auth_accept_relay"};
1011
1012 printf STDOUT ("hostlist auth_over_tls_hosts = %s\n",
1013   &no_expand_regex($main{"auth_over_tls_hosts"}))
1014     if defined $main{"auth_over_tls_hosts"};
1015 printf STDOUT ("hostlist tls_hosts = %s\n",
1016   &no_expand_regex($main{"tls_hosts"}))
1017     if defined $main{"tls_hosts"};
1018 printf STDOUT ("hostlist tls_relay_hosts = %s\n",
1019   &no_expand_regex($main{"tls_host_accept_relay"}))
1020     if defined $main{"tls_host_accept_relay"};
1021
1022 print STDOUT "\n";
1023
1024
1025 # Convert various logging options
1026
1027 $log_selector = "";
1028 $sep = " \\\n             ";
1029
1030 if (defined $main{"log_level"})
1031   {
1032   my($level) = $main{"log_level"};
1033   $log_selector .= "$sep -retry_defer$sep -skip_delivery" if $level < 5;
1034   $log_selector .= "$sep -lost_incoming_connection$sep -smtp_syntax_error" .
1035                    "$sep -delay_delivery" if $level < 4;
1036   $log_selector .= "$sep -size_reject" if $level < 2;
1037   }
1038
1039 $log_selector .= "$sep -queue_run"
1040   if defined $main{"log_queue_run_level"} &&
1041      defined $main{"log_level"} &&
1042      $main{"log_queue_run_level"} > $main{"log_level"};
1043
1044 $log_selector .= "$sep +address_rewrite"       if &bool("log_rewrites");
1045 $log_selector .= "$sep +all_parents"           if &bool("log_all_parents");
1046 $log_selector .= "$sep +arguments"             if &bool("log_arguments");
1047 $log_selector .= "$sep +incoming_port"         if &bool("log_incoming_port");
1048 $log_selector .= "$sep +incoming_interface"    if &bool("log_interface");
1049 $log_selector .= "$sep +received_sender"       if &bool("log_received_sender");
1050 $log_selector .= "$sep +received_recipients"   if &bool("log_received_recipients");
1051 $log_selector .= "$sep +sender_on_delivery"    if &bool("log_sender_on_delivery");
1052 $log_selector .= "$sep +smtp_confirmation"     if &bool("log_smtp_confirmation");
1053 $log_selector .= "$sep +smtp_connection"       if &bool("log_smtp_connections");
1054 $log_selector .= "$sep +smtp_syntax_error"     if &bool("log_smtp_syntax_errors");
1055 $log_selector .= "$sep +subject"               if &bool("log_subject");
1056 $log_selector .= "$sep +tls_cipher"            if &bool("tls_log_cipher");
1057 $log_selector .= "$sep +tls_peerdn"            if &bool("tls_log_peerdn");
1058
1059
1060 if ($log_selector ne "")
1061   {
1062   print STDOUT "#!!# All previous logging options are combined into a single\n"
1063              . "#!!# option in Exim 4. This setting is an approximation to\n"
1064              . "#!!# the previous state - some logging has changed.\n\n";
1065   print STDOUT "log_selector = $log_selector\n\n";
1066   }
1067
1068 # If deliver_load_max is set, replace it with queue_only_load (taking the
1069 # lower value if both set) and also set deliver_queue_load_max if it is
1070 # not already set. When scanning for output, deliver_load_max is skipped.
1071
1072 if (defined $main{"deliver_load_max"})
1073   {
1074   &rubric();
1075   print STDERR "\n" .
1076 "** deliver_load_max is abolished in Exim 4.\n";
1077
1078   if (defined $main{"queue_only_load"})
1079     {
1080     $queue_only_load_was_present = 1;
1081     if ($main{"queue_only_load"} < $main{"deliver_load_max"})
1082       {
1083       print STDERR
1084 "   As queue_only_load was set lower, deliver_load_max is just removed.\n";
1085       }
1086     else
1087       {
1088       print STDERR
1089 "   As queue_only_load was set higher, it's value has been replaced by\n" .
1090 "   the value of deliver_load_max.\n";
1091       $main{"queue_only_load"} = $main{"deliver_load_max"};
1092       }
1093     }
1094   else
1095     {
1096     print STDERR
1097 "   queue_only_load has been set to the load value.\n";
1098     $main{"queue_only_load"} = $main{"deliver_load_max"};
1099     }
1100
1101   if (!defined $main{"deliver_queue_load_max"})
1102     {
1103     print STDERR
1104 "   deliver_queue_load_max has been set to the value of queue_only_load.\n";
1105     $main{"deliver_queue_load_max"} = $main{"queue_only_load"};
1106     }
1107   else
1108     {
1109     $deliver_queue_load_max_was_present = 1;
1110     }
1111   }
1112
1113
1114 # Now we scan through the various parts of the file again, making changes
1115 # as necessary.
1116
1117 # -------- The main configuration --------
1118
1119 $prefix = "";
1120 MainLine: for ($i = 0; $i < $clen; $i++)
1121   {
1122   my($nextline) = "";
1123   $type = &checkline($c[$i]);
1124   last if $type eq "end";
1125
1126   if ($type eq "macro")
1127     {
1128     $i++ while $c[$i] =~ /\\\s*$|^\s*#/;
1129     next;
1130     }
1131
1132   if ($type eq "comment") { print STDOUT "$c[$i]\n"; next; }
1133
1134   # Collect any continuation lines for an option setting
1135
1136   while ($rest =~ /\\\s*$/s || $nextline =~ /^\s*#/)
1137     {
1138     $nextline = $c[++$i];
1139     $rest .= "\n$nextline";
1140     }
1141
1142   $rest =~ s/^=\s*//;
1143
1144   # Deal with main options that are skipped (they are used in other
1145   # options in other places).
1146
1147   for $skipped (@skipped_options)
1148     {
1149     next MainLine if $name eq $skipped;
1150     }
1151
1152   # Deal with main options that are totally abolished
1153
1154   for $abolished (@abolished_options)
1155     {
1156     if ($name eq $abolished)
1157       {
1158       &rubric();
1159       print STDERR "\n" .
1160 "** The $name option no longer exists, and has no equivalent\n" .
1161 "   in Exim 4.\n";
1162       next MainLine;
1163       }
1164     }
1165
1166   # There is a special case for rbl_warn_header
1167
1168   if ($name eq "rbl_warn_header")
1169     {
1170     &rubric();
1171     print STDERR "\n" .
1172 "** The $name option no longer exists. In Exim 4 you can achieve the\n" .
1173 "   effect by adding a suitable \"message\" statement in the ACL.\n";
1174     }
1175
1176   # There is a special case for sender_reject and host_reject
1177
1178   elsif ($name eq "sender_reject" || $name eq "host_reject")
1179     {
1180     &rubric();
1181     print STDERR "\n" .
1182 "** The $name option no longer exists. Its data has been used in\n" .
1183 "   an Access Control List as if it were in ${name}_recipients.\n";
1184     }
1185
1186   # And a special message for prohibition_message
1187
1188   elsif ($name eq "prohibition_message")
1189     {
1190     &rubric();
1191     print STDERR "\n" .
1192 "** The prohibition_message option no longer exists. The facility is\n" .
1193 "   provided in a different way in Exim 4, via the \"message\" keyword\n" .
1194 "   in Access Control Lists. It isn't possible to do an automatic conversion,\n" .
1195 "   so the value of prohibition_message has been ignored. You will have to\n" .
1196 "   modify the ACLs if you want to reinstate the feature.\n";
1197     }
1198
1199   # auth_always_advertise gets converted to auth_advertise_hosts
1200
1201   elsif ($name eq "auth_always_advertise")
1202     {
1203     print STDOUT "#!!# auth_always_advertise converted to auth_advertise_hosts\n";
1204     if (&bool("auth_always_advertise"))
1205       {
1206       print STDOUT "auth_advertise_hosts = *\n";
1207       }
1208     else
1209       {
1210       $sep = "";
1211       print STDOUT "auth_advertise_hosts =";
1212       if (defined $main{"auth_hosts"})
1213         {
1214         print STDOUT "$sep +auth_hosts";
1215         $sep = " :";
1216         }
1217       if (defined $main{"host_accept_relay"})
1218         {
1219         print STDOUT "$sep !+relay_hosts";
1220         $sep = " :";
1221         }
1222       if (defined $main{"host_auth_accept_relay"})
1223         {
1224         print STDOUT "$sep +auth_relay_hosts";
1225         }
1226       print STDOUT "\n";
1227       }
1228     }
1229
1230   # Deal with main options that have to be rewritten
1231
1232   elsif ($name eq "accept_timeout")
1233     {
1234     print STDOUT "#!!# accept_timeout renamed receive_timeout\n";
1235     print STDOUT "receive_timeout = $rest\n";
1236     }
1237
1238   elsif ($name eq "collapse_source_routes")
1239     {
1240     print STDOUT "#!!# collapse_source_routes removed\n";
1241     print STDOUT "#!!# It has been a no-op since 3.10.\n";
1242     }
1243
1244   elsif ($name eq "daemon_smtp_service")
1245     {
1246     print STDOUT "#!!# daemon_smtp_service renamed daemon_smtp_port\n";
1247     print STDOUT "daemon_smtp_port = $rest\n";
1248     }
1249
1250   elsif ($name eq "dns_check_names" || $name eq "dns_check_names_pattern")
1251     {
1252     if (!$done_dns_check_names)
1253       {
1254       if (&bool("dns_check_names"))
1255         {
1256         if (defined $main{"dns_check_names_pattern"})
1257           {
1258           &outopt(\%main, "dns_check_names_pattern", 0);
1259           }
1260         }
1261
1262       else
1263         {
1264         print STDOUT "#!!# dns_check_names has been abolished\n";
1265         print STDOUT "#!!# setting dns_check_pattern empty to turn off check\n";
1266         print STDOUT "dns_check_names_pattern =\n";
1267         }
1268
1269       $done_dns_check_names = 1;
1270       }
1271     }
1272
1273   elsif ($name eq "deliver_load_max")
1274     {
1275     print STDOUT "deliver_queue_load_max = $main{'deliver_queue_load_max'}\n"
1276       if !$deliver_queue_load_max_was_present;
1277     print STDOUT "queue_only_load = $main{'queue_only_load'}\n"
1278       if !$queue_only_load_was_present;
1279     }
1280
1281   elsif ($name eq "errmsg_file")
1282     {
1283     print STDOUT "#!!# errmsg_file renamed bounce_message_file\n";
1284     print STDOUT "bounce_message_file = $rest\n";
1285     }
1286
1287   elsif ($name eq "errmsg_text")
1288     {
1289     print STDOUT "#!!# errmsg_text renamed bounce_message_text\n";
1290     print STDOUT "bounce_message_text = $rest\n";
1291     }
1292
1293   elsif ($name eq "forbid_domain_literals")
1294     {
1295     print STDOUT "#!!# forbid_domain_literals replaced by allow_domain_literals\n";
1296     print STDOUT "allow_domain_literals = ",
1297           &bool("forbid_domain_literals")? "false" : "true", "\n";
1298     }
1299
1300   elsif ($name eq "freeze_tell_mailmaster")
1301     {
1302     print STDOUT "#!!# freeze_tell_mailmaster replaced by freeze_tell\n";
1303     if (&bool("freeze_tell_mailmaster"))
1304       {
1305       print STDOUT "freeze_tell = ",
1306         ((defined $main{"errors_address"})?
1307           $main{"errors_address"} : "postmaster"), "\n";
1308       }
1309     else
1310       {
1311       print STDOUT "#!!# freeze_tell is unset by default\n";
1312       }
1313     }
1314
1315   elsif ($name eq "helo_verify")
1316     {
1317     print STDOUT "#!!# helo_verify renamed helo_verify_hosts\n";
1318     printf STDOUT ("helo_verify_hosts = %s\n", &no_expand_regex($rest));
1319     }
1320
1321   elsif ($name eq "ignore_errmsg_errors")
1322     {
1323     print STDOUT "ignore_bounce_errors_after = 0s\n";
1324     }
1325
1326   elsif ($name eq "ignore_errmsg_errors_after")
1327     {
1328     print STDOUT "#!!# ignore_errmsg_errors_after renamed ignore_bounce_errors_after\n";
1329     print STDOUT "ignore_bounce_errors_after = $rest\n";
1330     }
1331
1332   elsif ($name eq "ipv4_address_lookup" || $name eq "dns_ipv4_lookup")
1333     {
1334     print STDOUT "#!!# $name changed to dns_ipv4_lookup\n"
1335       if $name eq "ipv4_address_lookup";
1336     print STDOUT "#!!# dns_ipv4_lookup is now a domain list\n";
1337     if (&bool($name))
1338       {
1339       print STDOUT "dns_ipv4_lookup = *\n";
1340       }
1341     else
1342       {
1343       print STDOUT "#!!# default for dns_ipv4_lookup is unset\n";
1344       }
1345     }
1346
1347   elsif ($name eq "locally_caseless")
1348     {
1349     print STDOUT "#!!# locally_caseless removed\n";
1350     print STDOUT "#!!# caseful_local_part will be added to ex-directors\n";
1351     $add_caseful_local_part = 1;
1352     }
1353
1354   elsif ($name eq "message_filter_directory2_transport")
1355     {
1356     print STDOUT "#!!# message_filter_directory2_transport removed\n";
1357     }
1358
1359   elsif ($name =~ /^message_filter(.*)/)
1360     {
1361     print STDOUT "#!!# $name renamed system_filter$1\n";
1362     print STDOUT "system_filter$1 = $rest\n";
1363     }
1364
1365   elsif ($name eq "queue_remote_domains")
1366     {
1367     print STDOUT "#!!# queue_remote_domains renamed queue_domains\n";
1368     printf STDOUT ("queue_domains = %s\n", &no_expand_regex($rest));
1369     }
1370
1371   elsif ($name eq "receiver_unqualified_hosts")
1372     {
1373     print STDOUT "#!!# receiver_unqualified_hosts renamed recipient_unqualified_hosts\n";
1374     printf STDOUT ("recipient_unqualified_hosts = %s\n",
1375       &no_expand_regex($rest));
1376     }
1377
1378   elsif ($name eq "remote_sort")
1379     {
1380     print STDOUT "#!!# remote_sort renamed remote_sort_domains\n";
1381     printf STDOUT ("remote_sort_domains = %s\n", &no_expand_regex($rest));
1382     }
1383
1384   elsif ($name eq "security")
1385     {
1386     if ($rest eq "unprivileged")
1387       {
1388       print STDOUT "#!!# security=unprivileged changed to deliver_drop_privilege\n";
1389       print STDOUT "deliver_drop_privilege\n";
1390       }
1391     else
1392       {
1393       &rubric();
1394       print STDERR "\n" .
1395 "** The 'security' option no longer exists.\n";
1396       }
1397     }
1398
1399   elsif ($name eq "timestamps_utc")
1400     {
1401     print STDOUT "#!!# timestamps_utc changed to use timezone\n";
1402     print STDOUT "timezone = utc\n";
1403     }
1404
1405   elsif ($name eq "untrusted_set_sender")
1406     {
1407     print STDOUT "#!!# untrusted_set_sender is now a list of what can be set\n";
1408     print STDOUT "#!!# The default is an empty list.\n";
1409     if (&bool("untrusted_set_sender"))
1410       {
1411       print STDOUT "untrusted_set_sender = *\n";
1412       }
1413     }
1414
1415   elsif ($name eq "warnmsg_file")
1416     {
1417     print STDOUT "#!!# warnmsg_file renamed warn_message_file\n";
1418     print STDOUT "warn_message_file = $rest\n";
1419     }
1420
1421   # Remaining options just get copied unless they are one of those that's
1422   # a list where any regular expressions have to be escaped.
1423
1424   else
1425     {
1426     my($no_expand) = 0;
1427     foreach $o (@list_options)
1428       {
1429       if ($name eq $o)
1430         {
1431         $no_expand = 1;
1432         last;
1433         }
1434       }
1435     &outopt(\%main, $name, $no_expand);
1436     }
1437   }
1438
1439
1440 # -------- The ACL configuration --------
1441
1442 print STDOUT "\n";
1443 print STDOUT "#!!#######################################################!!#\n";
1444 print STDOUT "#!!# This new section of the configuration contains ACLs #!!#\n";
1445 print STDOUT "#!!# (Access Control Lists) derived from the Exim 3      #!!#\n";
1446 print STDOUT "#!!# policy control options.                             #!!#\n";
1447 print STDOUT "#!!#######################################################!!#\n";
1448
1449 print STDOUT "\n";
1450 print STDOUT "#!!# These ACLs are crudely constructed from Exim 3 options.\n";
1451 print STDOUT "#!!# They are almost certainly not optimal. You should study\n";
1452 print STDOUT "#!!# them and rewrite as necessary.\n";
1453
1454 print STDOUT "\nbegin acl\n\n";
1455
1456
1457 # Output an ACL for use after the RCPT command. This combines all the previous
1458 # policy checking options.
1459
1460 print STDOUT "#!!# ACL that is used after the RCPT command\n";
1461 print STDOUT "check_recipient:\n";
1462
1463 print STDOUT "  # Exim 3 had no checking on -bs messages, so for compatibility\n";
1464 print STDOUT "  # we accept if the source is local SMTP (i.e. not over TCP/IP).\n";
1465 print STDOUT "  # We do this by testing for an empty sending host field.\n";
1466 print STDOUT "  accept  hosts = :\n";
1467
1468 if (defined $main{"tls_verify_ciphers"})
1469   {
1470   print STDOUT "  deny    ";
1471   print STDOUT "hosts = $main{'tls_verify_hosts'}\n         "
1472     if defined $main{"tls_verify_hosts"};
1473   print STDOUT " encrypted = *\n         ";
1474   print STDOUT "!encrypted = $main{'tls_verify_ciphers'}\n";
1475   }
1476
1477 print STDOUT "  deny    hosts = +auth_hosts\n" .
1478              "          message = authentication required\n" .
1479              "         !authenticated = *\n"
1480   if defined $main{"auth_hosts"};
1481
1482 print STDOUT "  deny    hosts = +tls_hosts\n" .
1483              "          message = encryption required\n" .
1484              "         !encrypted = *\n"
1485   if defined $main{"tls_hosts"};
1486
1487 printf STDOUT ("  accept  recipients = %s\n",
1488   &acl_quote(&sort_address_list($main{"recipients_reject_except"},
1489     "recipients_reject_except")))
1490       if defined $main{"recipients_reject_except"};
1491
1492 printf STDOUT ("  accept  senders = %s\n",
1493   &acl_quote(&sort_address_list($main{"recipients_reject_except_senders"},
1494     "recipients_reject_except_senders")))
1495       if defined $main{"recipients_reject_except_senders"};
1496
1497 printf STDOUT ("  deny    hosts = %s\n", &acl_quote($main{"host_reject"}))
1498   if defined $main{"host_reject"};
1499
1500 printf STDOUT ("  deny    hosts = %s\n",
1501   &acl_quote($main{"host_reject_recipients"}))
1502     if defined $main{"host_reject_recipients"};
1503
1504 if (defined $main{"rbl_domains"})
1505   {
1506   my($msg) = "message = host is listed in \$dnslist_domain\n          ";
1507   my($hlist) = (defined $main{"rbl_hosts"})?
1508     "hosts = +rbl_hosts\n          " : "";
1509
1510   print STDOUT "  accept  ${hlist}dnslists = $rbl_accept_domains\n"
1511     if defined $rbl_accept_domains;
1512   print STDOUT "  deny    ${hlist}${msg}dnslists = $rbl_reject_domains\n"
1513     if defined $rbl_reject_domains;
1514   print STDOUT "  warn    ${hlist}" .
1515     "message = X-Warning: \$sender_host_address is listed at \$dnslist_domain\n" .
1516     "          dnslists = $rbl_warn_domains\n"
1517       if defined $rbl_warn_domains;
1518
1519   if (defined $main{"host_accept_relay"})
1520     {
1521     $hlist .= "hosts = !+relay_hosts\n          ";
1522     print STDOUT "  accept  ${hlist}dnslists = $rbl_accept_skiprelay\n"
1523       if defined $rbl_accept_skiprelay;
1524     print STDOUT "  deny    ${hlist}${msg}dnslists = $rbl_reject_skiprelay\n"
1525       if defined $rbl_reject_skiprelay;
1526     print STDOUT "  warn    ${hlist}" .
1527       "message = X-Warning: \$sender_host_address is listed at \$dnslist_domain\n" .
1528       "          dnslists = $rbl_warn_skiprelay\n"
1529         if defined $rbl_warn_skiprelay;
1530     }
1531   }
1532
1533 printf STDOUT ("  deny    senders = %s\n",
1534   &acl_quote(&sort_address_list($main{"sender_reject"}, "sender_reject")))
1535     if defined $main{"sender_reject"};
1536
1537 printf STDOUT ("  deny    senders = %s\n",
1538   &acl_quote(&sort_address_list($main{"sender_reject_recipients"},
1539     "sender_reject_recipients")))
1540       if defined $main{"sender_reject_recipients"};
1541
1542 if (&bool("sender_verify"))
1543   {
1544   if (defined $main{"sender_verify_hosts_callback"} &&
1545       defined $main{"sender_verify_callback_domains"})
1546     {
1547     printf STDOUT ("  deny    hosts = %s\n",
1548       &acl_quote($main{"sender_verify_hosts_callback"}));
1549     printf STDOUT ("          sender_domains = %s\n",
1550       &acl_quote($main{"sender_verify_callback_domains"}));
1551     print  STDOUT  "         !verify = sender/callout";
1552     print  STDOUT  "=$main{\"sender_verify_callback_timeout\"}"
1553       if defined $main{"sender_verify_callback_timeout"};
1554     print  STDOUT  "\n";
1555     }
1556
1557   if (defined $main{"sender_verify_hosts"})
1558     {
1559     printf STDOUT ("  deny    hosts = %s\n",
1560       &acl_quote($main{"sender_verify_hosts"}));
1561     print  STDOUT  "         !verify = sender\n";
1562     }
1563   else
1564     {
1565     print STDOUT "  require verify = sender\n";
1566     }
1567   }
1568
1569 if (&bool("receiver_verify"))
1570   {
1571   print  STDOUT  "  deny    message = unrouteable address\n";
1572   printf STDOUT ("          recipients = %s\n",
1573     &acl_quote(&sort_address_list($main{"receiver_verify_addresses"},
1574       "receiver_verify_addresses")))
1575         if defined $main{"receiver_verify_addresses"};
1576   printf STDOUT ("          hosts = %s\n",
1577     &acl_quote($main{"receiver_verify_hosts"}))
1578       if defined $main{"receiver_verify_hosts"};
1579   printf STDOUT ("          senders = %s\n",
1580     &acl_quote(&sort_address_list($main{"receiver_verify_senders"},
1581       "receiver_verify_senders")))
1582         if defined $main{"receiver_verify_senders"};
1583   print  STDOUT  "         !verify = recipient\n";
1584   }
1585
1586 print STDOUT "  accept  domains = +local_domains\n"
1587   if $local_domains !~ /^\s*$/;
1588
1589 print STDOUT "  accept  domains = +relay_domains\n"
1590   if $relay_domains !~ /^\s*$/;
1591
1592 if (defined $main{"host_accept_relay"})
1593   {
1594   if (defined $main{"sender_address_relay"})
1595     {
1596     if (defined $main{"sender_address_relay_hosts"})
1597       {
1598       printf STDOUT ("  accept  hosts = %s\n",
1599         &acl_quote($main{"sender_address_relay_hosts"}));
1600       print  STDOUT  "          endpass\n";
1601       print  STDOUT  "          message = invalid sender\n";
1602       printf STDOUT ("          senders = %s\n",
1603         &acl_quote(&sort_address_list($main{"sender_address_relay"},
1604           "sender_address_relay")));
1605       print  STDOUT  "  accept  hosts = +relay_hosts\n";
1606       }
1607     else
1608       {
1609       print  STDOUT  "  accept  hosts = +relay_hosts\n";
1610       print  STDOUT  "          endpass\n";
1611       print  STDOUT  "          message = invalid sender\n";
1612       printf STDOUT ("          senders = %s\n",
1613         &acl_quote(&sort_address_list($main{"sender_address_relay"},
1614           "sender_address_relay")));
1615       }
1616     }
1617   else
1618     {
1619     print STDOUT "  accept  hosts = +relay_hosts\n";
1620     }
1621   }
1622
1623 print STDOUT "  accept  hosts = +auth_relay_hosts\n" .
1624              "          endpass\n" .
1625              "          message = authentication required\n" .
1626              "          authenticated = *\n"
1627   if defined $main{"host_auth_accept_relay"};
1628
1629 print STDOUT "  accept  hosts = +tls_relay_hosts\n" .
1630              "          endpass\n" .
1631              "          message = encryption required\n" .
1632              "          encrypted = *\n"
1633   if defined $main{"tls_host_accept_relay"};
1634
1635 print STDOUT "  deny    message = relay not permitted\n\n";
1636
1637
1638 # Output an ACL for use after the DATA command. This is concerned with
1639 # header checking.
1640
1641 print STDOUT "#!!# ACL that is used after the DATA command\n";
1642 print STDOUT "check_message:\n";
1643
1644 # Default for headers_checks_fail is true
1645
1646 if (!defined $main{"headers_checks_fail"} ||
1647     $main{"headers_checks_fail"} eq "true")
1648   {
1649   print STDOUT "  require verify = header_syntax\n"
1650     if &bool("headers_check_syntax");
1651   print STDOUT "  require verify = header_sender\n"
1652     if &bool("headers_sender_verify");
1653   print STDOUT "  accept  senders = !:\n  require verify = header_sender\n"
1654     if &bool("headers_sender_verify_errmsg");
1655   }
1656 else
1657   {
1658   print STDOUT "  warn    !verify = header_syntax\n"
1659     if &bool("headers_check_syntax");
1660   print STDOUT "  warn    !verify = header_sender\n"
1661     if &bool("headers_sender_verify");
1662   print STDOUT "  accept  senders = !:\n  warn    !verify = header_sender\n"
1663     if &bool("headers_sender_verify_errmsg");
1664   }
1665
1666 print STDOUT "  accept\n\n";
1667
1668
1669 # Output an ACL for AUTH if required
1670
1671 if (defined $main{"auth_over_tls_hosts"})
1672   {
1673   print STDOUT "#!!# ACL that is used after the AUTH command\n" .
1674                "check_auth:\n" .
1675                "  accept  hosts = +auth_over_tls_hosts\n" .
1676                "          endpass\n" .
1677                "          message = STARTTLS required before AUTH\n" .
1678                "          encrypted = *\n" .
1679                "  accept\n";
1680   }
1681
1682
1683 # Output ACLs for ETRN, EXPN, and VRFY if required
1684
1685 if (defined $main{"smtp_etrn_hosts"})
1686   {
1687   print STDOUT "#!!# ACL that is used after the ETRN command\n" .
1688                "check_etrn:\n";
1689   print STDOUT "  deny    hosts = +auth_hosts\n" .
1690                "          message = authentication required\n" .
1691                "         !authenticated = *\n"
1692     if defined $main{"auth_hosts"};
1693   print STDOUT "  accept  hosts = $main{\"smtp_etrn_hosts\"}\n\n";
1694   }
1695
1696 if (defined $main{"smtp_expn_hosts"})
1697   {
1698   print STDOUT "#!!# ACL that is used after the EXPN command\n" .
1699                "check_expn:\n";
1700   print STDOUT "  deny    hosts = +auth_hosts\n" .
1701                "          message = authentication required\n" .
1702                "         !authenticated = *\n"
1703     if defined $main{"auth_hosts"};
1704   print STDOUT "  accept  hosts = $main{\"smtp_expn_hosts\"}\n\n";
1705   }
1706
1707 if (&bool("smtp_verify"))
1708   {
1709   print STDOUT "#!!# ACL that is used after the VRFY command\n" .
1710                "check_vrfy:\n";
1711   print STDOUT "  deny    hosts = +auth_hosts\n" .
1712                "          message = authentication required\n" .
1713                "         !authenticated = *\n"
1714     if defined $main{"auth_hosts"};
1715   print STDOUT "  accept\n\n";
1716   }
1717
1718 # -------- The authenticators --------
1719
1720 $started = 0;
1721 for ($i = $auth_start; $i < $clen; $i++)
1722   {
1723   if (!$started)
1724     {
1725     if ($c[$i] !~ /^\s*(#|$)/)
1726       {
1727       print STDOUT "\nbegin authenticators\n\n";
1728       $started = 1;
1729       }
1730     }
1731   print STDOUT "$c[$i]\n";
1732   }
1733
1734
1735 # -------- Rewrite section --------
1736
1737 $started = 0;
1738 for ($i = $rewrite_start; $i < $clen && $i < $auth_start - 1; $i++)
1739   {
1740   if (!$started)
1741     {
1742     if ($c[$i] !~ /^\s*(#|$)/)
1743       {
1744       print STDOUT "\nbegin rewrite\n\n";
1745       $started = 1;
1746       }
1747     }
1748   &print_no_expand($c[$i]);
1749   }
1750
1751
1752 # -------- The routers configuration --------
1753
1754 # The new routers configuration is created out of the old directors and routers
1755 # configuration. We put the old routers first, adding a "domains" option to
1756 # any that don't have one, to make them select the domains that do not match
1757 # the original local_domains. The routers get modified as necessary, and the
1758 # final one has "no_more" set, unless it has conditions. In that case we have
1759 # to add an extra router to be sure of failing all non-local addresses that
1760 # fall through. We do this also if there are no routers at all. The old
1761 # directors follow, modified as required.
1762
1763 $prefix = "r.";
1764 undef @comments;
1765
1766 print STDOUT "\n";
1767 print STDOUT "#!!#######################################################!!#\n";
1768 print STDOUT "#!!# Here follow routers created from the old routers,   #!!#\n";
1769 print STDOUT "#!!# for handling non-local domains.                     #!!#\n";
1770 print STDOUT "#!!#######################################################!!#\n";
1771
1772 print STDOUT "\nbegin routers\n\n";
1773
1774 for ($i = $router_start; $i < $clen; $i++)
1775   {
1776   $type = &checkline($c[$i]);
1777   last if $type eq "end";
1778
1779   if ($type eq "comment") { push(@comments, "$c[$i]\n"); next; }
1780
1781   # When we hit the start of a driver, modify its options as necessary,
1782   # and then output it from the stored option settings, having first output
1783   # and previous comments.
1784
1785   if ($type eq "driver")
1786     {
1787     print STDOUT shift @comments while scalar(@comments) > 0;
1788
1789     $hash = $driverlist{"$prefix$name"};
1790     $driver = $$hash{"driver"};
1791     print STDOUT "$name:\n";
1792
1793     $add_no_more =
1794       ! defined $$hash{"domains"} &&
1795       ! defined $$hash{"local_parts"} &&
1796       ! defined $$hash{"senders"} &&
1797       ! defined $$hash{"condition"} &&
1798       ! defined $$hash{"require_files"} &&
1799       (!defined $$hash{"verify_only"} || $$hash{"verify_only"} eq "false") &&
1800       (!defined $$hash{"verify"} || $$hash{"verify"} eq "true");
1801
1802     # Create a "domains" setting if there isn't one, unless local domains
1803     # was explicitly empty.
1804
1805     $$hash{"domains"} = "! +local_domains"
1806       if !defined $$hash{"domains"} && $local_domains !~ /^\s*$/;
1807
1808     # If the router had a local_parts setting, add caseful_local_part
1809
1810     $$hash{"caseful_local_part"} = "true" if defined $$hash{"local_parts"};
1811
1812     # If the router has "self=local" set, change it to "self=pass", and
1813     # set pass_router to the router that was the first director. Change the
1814     # obsolete self settings of "fail_hard" and "fail_soft" to "fail" and
1815     # "pass".
1816
1817     if (defined $$hash{"self"})
1818       {
1819       if ($$hash{"self"} eq "local")
1820         {
1821         $$hash{"self"} = "pass";
1822         $$hash{"pass_router"} = $first_director;
1823         }
1824       elsif ($$hash{"self"} eq "fail_hard")
1825         {
1826         $$hash{"self"} = "fail";
1827         }
1828       elsif ($$hash{"self"} eq "fail_soft")
1829         {
1830         $$hash{"self"} = "pass";
1831         }
1832       }
1833
1834     # If the router had a require_files setting, check it for user names
1835     # and colons that are part of expansion items
1836
1837     if (defined $$hash{"require_files"})
1838       {
1839       &check_require($$hash{"require_files"}, "'$name' router");
1840       if (($$hash{"require_files"} =~ s/(\$\{\w+):/$1::/g) > 0 ||
1841           ($$hash{"require_files"} =~ s/ldap:/ldap::/g) > 0)
1842         {
1843         &rubric();
1844         print STDERR "\n" .
1845 "*** A setting of require_files in the $name router contains\n" .
1846 "    a colon in what appears to be an expansion item. In Exim 3, the\n" .
1847 "    whole string was expanded before splitting the list, but in Exim 4\n" .
1848 "    each item is expanded separately, so colons that are not list\n" .
1849 "    item separators have to be doubled. One or more such colons in this\n" .
1850 "    list have been doubled as a precaution. Please check the result.\n";
1851         }
1852       }
1853
1854     # If the router had a "senders" setting, munge the address list
1855
1856     $$hash{"senders"} = &sort_address_list($$hash{"senders"}, "senders")
1857       if defined $$hash{"senders"};
1858
1859     # ---- Changes to domainlist router ----
1860
1861     if ($driver eq "domainlist")
1862       {
1863       &abolished($hash, "A domainlist router",
1864         "modemask", "owners", "owngroups",
1865         "qualify_single", "search_parents");
1866
1867       # The name has changed
1868
1869       $$hash{"driver"} = "manualroute";
1870
1871       # Turn "route_file", "route_query" and "route_queries" into lookups for
1872       # route_data.
1873
1874       if (defined $$hash{"route_file"})
1875         {
1876         $$hash{"route_data"} = "\${lookup\{\$domain\}$$hash{'search_type'}" .
1877                          "\{$$hash{'route_file'}\}\}";
1878         }
1879       elsif (defined $$hash{"route_query"})
1880         {
1881         $$hash{"route_data"} = "\${lookup $$hash{'search_type'}" .
1882                                "\{" . &unquote($$hash{'route_query'}) . "\}\}";
1883         }
1884       elsif (defined $$hash{"route_queries"})
1885         {
1886         $endkets = 0;
1887         $$hash{"route_data"} = "";
1888         $route_queries = $$hash{'route_queries'};
1889         $route_queries =~ s/^"(.*)"$/$1/s;
1890         $route_queries =~ s/::/++colons++/g;
1891         @qq = split(/:/, $route_queries);
1892
1893         foreach $q (@qq)
1894           {
1895           $q =~ s/\+\+colons\+\+/:/g;
1896           $q =~ s/^\s+//;
1897           $q =~ s/\s+$//;
1898           if ($endkets > 0)
1899             {
1900             $$hash{"route_data"} .= "\\\n    {";
1901             $endkets++;
1902             }
1903           $$hash{"route_data"} .= "\${lookup $$hash{'search_type'} \{$q\}\{\$value\}";
1904           $endkets++;
1905           }
1906
1907         $$hash{"route_data"} .= "}" x $endkets;
1908         }
1909
1910       delete $$hash{"route_file"};
1911       delete $$hash{"route_query"};
1912       delete $$hash{"route_queries"};
1913       delete $$hash{"search_type"};
1914
1915       # But we can't allow both route_data and route_list
1916
1917       if (defined $$hash{"route_data"} && defined $$hash{"route_list"})
1918         {
1919         &rubric();
1920         print STDERR "\n" .
1921 "** An Exim 3 'domainlist' router called '$name' contained a 'route_list'\n" .
1922 "   option as well as a setting of 'route_file', 'route_query', or\n" .
1923 "   'route_queries'. The latter has been turned into a 'route_data' setting,\n".
1924 "   but in Exim 4 you can't have both 'route_data' and 'route_list'. You'll\n" .
1925 "   have to rewrite this router; in the meantime, 'route_list' has been\n" .
1926 "   omitted.\n";
1927         print STDOUT "#!!# route_list option removed\n";
1928         delete $$hash{"route_list"};
1929         }
1930
1931       # Change bydns_a into bydns in a route_list; also bydns_mx, but that
1932       # works differently.
1933
1934       if (defined $$hash{"route_list"})
1935         {
1936         $$hash{"route_list"} =~ s/bydns_a/bydns/g;
1937         if ($$hash{"route_list"} =~ /bydns_mx/)
1938           {
1939           $$hash{"route_list"} =~ s/bydns_mx/bydns/g;
1940           &rubric();
1941           print STDERR "\n" .
1942 "*** An Exim 3 'domainlist' router called '$name' contained a 'route_list'\n" .
1943 "    option which used 'bydns_mx'. This feature no longer exists in Exim 4.\n" .
1944 "    It has been changed to 'bydns', but it won't have the same effect,\n" .
1945 "    because it will look for A rather than MX records. Use the 'dnslookup'\n" .
1946 "    router to do MX lookups - if you want to override the hosts found from\n" .
1947 "    MX records, you should route to a special 'smtp' transport which has\n" .
1948 "    both 'hosts' and 'hosts_override' set.\n";
1949           }
1950         }
1951
1952       # Arrange to not expand regex
1953
1954       $$hash{"route_list"} = &no_expand_regex($$hash{"route_list"}, ";")
1955         if (defined $$hash{"route_list"})
1956       }
1957
1958
1959     # ---- Changes to iplookup router ----
1960
1961     elsif ($driver eq "iplookup")
1962       {
1963       &renamed($hash, "service", "port");
1964       }
1965
1966
1967     # ---- Changes to lookuphost router ----
1968
1969     elsif ($driver eq "lookuphost")
1970       {
1971       $$hash{"driver"} = "dnslookup";
1972
1973       if (defined $$hash{"gethostbyname"})
1974         {
1975         &rubric();
1976         print STDERR "\n" .
1977 "** An Exim 3 'lookuphost' router called '$name' used the 'gethostbyname'\n" .
1978 "   option, which no longer exists. You will have to rewrite it.\n";
1979         print STDOUT "#!!# gethostbyname option removed\n";
1980         delete $$hash{"gethostbyname"};
1981         }
1982
1983       $$hash{"mx_domains"} = &no_expand_regex($$hash{"mx_domains"})
1984         if defined $$hash{"mx_domains"};
1985       }
1986
1987
1988     # ---- Changes to the queryprogram router ----
1989
1990     elsif ($driver eq "queryprogram")
1991       {
1992       &rubric();
1993       print STDERR "\n" .
1994 "** The configuration contains a 'queryprogram' router. Please note that\n" .
1995 "   the specification for the text that is returned by the program run\n" .
1996 "   by this router has changed in Exim 4. You will need to modify your\n" .
1997 "   program.\n";
1998
1999       if (!defined $$hash{'command_user'})
2000         {
2001         &rubric();
2002         print STDERR "\n" .
2003 "** The 'queryprogram' router called '$name' does not have a setting for\n" .
2004 "   the 'command_user' option. This is mandatory in Exim 4. A setting of\n" .
2005 "   'nobody' has been created.\n";
2006         $$hash{"command_user"} = "nobody";
2007         }
2008       }
2009
2010
2011     # -------------------------------------
2012
2013     # Output the router's option settings
2014
2015     &outdriver($hash);
2016     next;
2017     }
2018
2019   # Skip past any continuation lines for an option setting
2020   while ($c[$i] =~ /\\\s*$/s && $i < $clen - 1)
2021     {
2022     $i++;
2023     $i++ while ($c[$i] =~ /^\s*#/);
2024     }
2025   }
2026
2027 # Add "no_more" to the final driver from the old routers, provided it had no
2028 # conditions. Otherwise, or if there were no routers, make up one to fail all
2029 # non-local domains.
2030
2031 if ($add_no_more)
2032   {
2033   print STDOUT "  no_more\n";
2034   print STDOUT shift @comments while scalar(@comments) > 0;
2035   }
2036 else
2037   {
2038   print STDOUT shift @comments while scalar(@comments) > 0;
2039   print STDOUT "\n#!!# This new router is put here to fail all domains that\n";
2040   print STDOUT "#!!# were not in local_domains in the Exim 3 configuration.\n\n";
2041   print STDOUT "fail_remote_domains:\n";
2042   print STDOUT "  driver = redirect\n";
2043   print STDOUT "  domains = ! +local_domains\n";
2044   print STDOUT "  allow_fail\n";
2045   print STDOUT "  data = :fail: unrouteable mail domain \"\$domain\"\n\n";
2046   }
2047
2048 # Now copy the directors, making appropriate changes
2049
2050 print STDOUT "\n";
2051 print STDOUT "#!!#######################################################!!#\n";
2052 print STDOUT "#!!# Here follow routers created from the old directors, #!!#\n";
2053 print STDOUT "#!!# for handling local domains.                         #!!#\n";
2054 print STDOUT "#!!#######################################################!!#\n";
2055
2056 $prefix = "d.";
2057 for ($i = $director_start; $i < $clen; $i++)
2058   {
2059   $type = &checkline($c[$i]);
2060   last if $type eq "end";
2061
2062   if ($type eq "comment") { print STDOUT "$c[$i]\n"; next; }
2063
2064   undef $second_router;
2065
2066   if ($type eq "driver")
2067     {
2068     $hash = $driverlist{"$prefix$name"};
2069     $driver = $$hash{"driver"};
2070     print STDOUT "$name:\n";
2071
2072     $$hash{"caseful_local_part"} = "true" if $add_caseful_local_part;
2073
2074     if (defined $$hash{"local_parts"} &&
2075         (defined $$hash{"prefix"} || defined $hash{"suffix"}))
2076       {
2077       &rubric();
2078       print STDERR "\n" .
2079 "** The Exim 3 configuration contains a director called '$name' which has\n" .
2080 "   'local_parts' set, together with either or both of 'prefix' and 'suffix'\n".
2081 "   This combination has a different effect in Exim 4, where the affix\n" .
2082 "   is removed *before* 'local_parts' is tested. You will probably need\n" .
2083 "   to make changes to this driver.\n";
2084       }
2085
2086     &renamed($hash, "prefix", "local_part_prefix");
2087     &renamed($hash, "prefix_optional", "local_part_prefix_optional");
2088     &renamed($hash, "suffix", "local_part_suffix");
2089     &renamed($hash, "suffix_optional", "local_part_suffix_optional");
2090     &renamed($hash, "new_director", "redirect_router");
2091
2092     &handle_current_and_home_directory($hash, $driver, $name);
2093
2094     # If the director had a require_files setting, check it for user names
2095     # and colons that are part of expansion items
2096
2097     if (defined $$hash{"require_files"})
2098       {
2099       &check_require($$hash{"require_files"}, "'$name' director");
2100       if (($$hash{"require_files"} =~ s/(\$\{\w+):/$1::/g) > 0 ||
2101           ($$hash{"require_files"} =~ s/ldap:/ldap::/g) > 0)
2102         {
2103         &rubric();
2104         print STDERR "\n" .
2105 "*** A setting of require_files in the $name director contains\n" .
2106 "    a colon in what appears to be an expansion item. In Exim 3, the\n" .
2107 "    whole string was expanded before splitting the list, but in Exim 4\n" .
2108 "    each item is expanded separately, so colons that are not list\n" .
2109 "    item separators have to be doubled. One or more such colons in this\n" .
2110 "    list have been doubled as a precaution. Please check the result.\n";
2111         }
2112       }
2113
2114     # If the director had a "senders" setting, munge the address list
2115
2116     $$hash{"senders"} = &sort_address_list($$hash{"senders"}, "senders")
2117       if defined $$hash{"senders"};
2118
2119     # ---- Changes to aliasfile director ----
2120
2121     if ($driver eq "aliasfile")
2122       {
2123       &abolished($hash, "An aliasfile director",
2124         "directory2_transport", "freeze_missing_include",
2125         "modemask", "owners", "owngroups");
2126
2127       $$hash{"driver"} = "redirect";
2128
2129       $key = "\$local_part";
2130       $key = "\$local_part\@\$domain"
2131         if defined $$hash{"include_domain"} &&
2132           $$hash{"include_domain"} eq "true";
2133       delete $$hash{"include_domain"};
2134
2135       if (defined $$hash{"forbid_special"} && $$hash{"forbid_special"} eq "true")
2136         {
2137         $$hash{"forbid_blackhole"} = "true";
2138         }
2139       else
2140         {
2141         $$hash{"allow_defer"} = "true";
2142         $$hash{"allow_fail"} = "true";
2143         }
2144       delete $$hash{"forbid_special"};
2145
2146       # Deal with "file", "query", or "queries"
2147
2148       if (defined $$hash{"file"})
2149         {
2150         $$hash{"data"} =
2151           "\$\{lookup\{$key\}$$hash{'search_type'}\{$$hash{'file'}\}\}";
2152         if (defined $$hash{"optional"} && $$hash{"optional"} eq "true")
2153           {
2154           $$hash{"data"} =
2155             "\$\{if exists\{$$hash{'file'}\}\{$$hash{'data'}\}\}";
2156           }
2157         delete $$hash{"optional"};
2158         }
2159       elsif (defined $$hash{"query"})
2160         {
2161         &abolished($hash, "An aliasfile director", "optional");
2162         $$hash{"data"} = "\${lookup $$hash{'search_type'} " .
2163                          "\{" . &unquote($$hash{'query'}) . "\}\}";
2164         }
2165       else   # Must be queries
2166         {
2167         &abolished($hash, "An aliasfile director", "optional");
2168         $endkets = 0;
2169         $$hash{"data"} = "";
2170         $queries = $$hash{'queries'};
2171         $queries =~ s/^"(.*)"$/$1/s;
2172         $queries =~ s/::/++colons++/g;
2173         @qq = split(/:/, $queries);
2174
2175         foreach $q (@qq)
2176           {
2177           $q =~ s/\+\+colons\+\+/:/g;
2178           $q =~ s/^\s+//;
2179           $q =~ s/\s+$//;
2180           if ($endkets > 0)
2181             {
2182             $$hash{"data"} .= "\\\n    {";
2183             $endkets++;
2184             }
2185           $$hash{"data"} .= "\${lookup $$hash{'search_type'} \{$q\}\{\$value\}";
2186           $endkets++;
2187           }
2188
2189         $$hash{"data"} .= "}" x $endkets;
2190         }
2191
2192       $$hash{"data"} = "\${expand:$$hash{'data'}\}"
2193         if (defined $$hash{"expand"} && $$hash{"expand"} eq "true");
2194
2195       delete $$hash{"expand"};
2196       delete $$hash{"file"};
2197       delete $$hash{"query"};
2198       delete $$hash{"queries"};
2199       delete $$hash{"search_type"};
2200
2201       # Turn aliasfile + transport into accept + condition
2202
2203       if (defined $$hash{'transport'})
2204         {
2205         &rubric();
2206         if (!defined $$hash{'condition'})
2207           {
2208           print STDERR "\n" .
2209 "** The Exim 3 configuration contains an aliasfile director called '$name',\n".
2210 "   which has 'transport' set. This has been turned into an 'accept' router\n".
2211 "   with a 'condition' setting, but should be carefully checked.\n";
2212           $$hash{'driver'} = "accept";
2213           $$hash{'condition'} =
2214             "\$\{if eq \{\}\{$$hash{'data'}\}\{no\}\{yes\}\}";
2215           delete $$hash{'data'};
2216           delete $$hash{'allow_defer'};
2217           delete $$hash{'allow_fail'};
2218           }
2219         else
2220           {
2221           print STDERR "\n" .
2222 "** The Exim 3 configuration contains an aliasfile director called '$name',\n".
2223 "   which has 'transport' set. This cannot be turned into an 'accept' router\n".
2224 "   with a 'condition' setting, because there is already a 'condition'\n" .
2225 "   setting. It has been left as 'redirect' with a transport, which is\n" .
2226 "   invalid - you must sort this one out.\n";
2227           }
2228         }
2229       }
2230
2231
2232     # ---- Changes to forwardfile director ----
2233
2234     elsif ($driver eq "forwardfile")
2235       {
2236       &abolished($hash, "A forwardfile director",
2237         "check_group", "directory2_transport",
2238         "freeze_missing_include", "match_directory",
2239         "seteuid");
2240
2241       &renamed($hash, "filter", "allow_filter");
2242
2243       $$hash{"driver"} = "redirect";
2244       $$hash{"check_local_user"} = "true"
2245         if !defined $$hash{"check_local_user"};
2246
2247       if (defined $$hash{"forbid_pipe"} && $$hash{"forbid_pipe"} eq "true")
2248         {
2249         print STDOUT "#!!# forbid_filter_run added because forbid_pipe is set\n";
2250         $$hash{"forbid_filter_run"} = "true";
2251         }
2252
2253       if (defined $$hash{'allow_system_actions'} &&
2254           $$hash{'allow_system_actions'} eq 'true')
2255         {
2256         $$hash{'allow_freeze'} = "true";
2257         }
2258       delete $$hash{'allow_system_actions'};
2259
2260       # If file_directory is defined, use it to qualify relative paths; if not,
2261       # and check_local_user is defined, use $home. Remove file_directory from
2262       # the output.
2263
2264       $dir = "";
2265       if (defined $$hash{"file_directory"})
2266         {
2267         $dir = $$hash{"file_directory"} . "/";
2268         delete $$hash{"file_directory"};
2269         }
2270       elsif ($$hash{"check_local_user"} eq "true")
2271         {
2272         $dir = "\$home/";
2273         }
2274
2275       # If it begins with an upper case letter, guess that this is really
2276       # a macro.
2277
2278       if (defined $$hash{"file"} && $$hash{"file"} !~ /^[\/A-Z]/)
2279         {
2280         $$hash{"file"} = $dir . $$hash{"file"};
2281         }
2282       }
2283
2284
2285     # ---- Changes to localuser director ----
2286
2287     elsif ($driver eq "localuser")
2288       {
2289       &abolished($hash, "A localuser director", "match_directory");
2290       $$hash{"driver"} = "accept";
2291       $$hash{"check_local_user"} = "true";
2292       }
2293
2294
2295     # ---- Changes to smartuser director ----
2296
2297     elsif ($driver eq "smartuser")
2298       {
2299       &abolished($hash, "A smartuser director", "panic_expansion_fail");
2300
2301       $transport = $$hash{"transport"};
2302       $new_address = $$hash{"new_address"};
2303
2304       if (defined $transport && defined $new_address)
2305         {
2306         &rubric();
2307         print STDERR "\n" .
2308 "** The Exim 3 configuration contains a smartuser director called '$name',\n".
2309 "   which has both 'transport' and 'new_address' set. This has been turned\n".
2310 "   into two routers for Exim 4. However, if the new address contains a\n" .
2311 "   reference to \$local_part, this won't work correctly. In any case, you\n".
2312 "   may be able to make it tidier by rewriting.\n";
2313         $$hash{"driver"} = "redirect";
2314         $$hash{"data"} = $new_address;
2315         $$hash{"redirect_router"} = "${name}_part2";
2316
2317         $second_router = "\n".
2318           "#!!# This router is invented to go with the previous one because\n".
2319           "#!!# in Exim 4 you can't have a change of address and a transport\n".
2320           "#!!# setting in the same router as you could in Exim 3.\n\n" .
2321           "${name}_part2:\n".
2322           "  driver = accept\n".
2323           "  condition = \$\{if eq\{\$local_part@\$domain\}" .
2324           "\{$new_address\}\{yes\}\{no\}\}\n".
2325           "  transport = $$hash{'transport'}\n";
2326
2327         delete $$hash{"new_address"};
2328         delete $$hash{"transport"};
2329         }
2330       elsif (defined $new_address)
2331         {
2332         $$hash{"driver"} = "redirect";
2333         $$hash{"data"} = $new_address;
2334         $$hash{"allow_defer"} = "true";
2335         $$hash{"allow_fail"} = "true";
2336         delete $$hash{"new_address"};
2337         }
2338       else     # Includes the case of neither set (verify_only)
2339         {
2340         $$hash{"driver"} = "accept";
2341         if (defined $$hash{"rewrite"})
2342           {
2343           &rubric();
2344           print STDERR "\n" .
2345 "** The Exim 3 configuration contains a setting of the 'rewrite' option on\n".
2346 "   a smartuser director called '$name', but this director does not have\n".
2347 "   a setting of 'new_address', so 'rewrite' has no effect. The director\n".
2348 "   has been turned into an 'accept' router, and 'rewrite' has been discarded.";
2349           delete $$hash{"rewrite"};
2350           }
2351         }
2352       }
2353
2354
2355     # -------------------------------------
2356
2357     # For ex-directors that don't have check_local_user set, add
2358     # retry_use_local_part to imitate what Exim 3 would have done.
2359
2360     $$hash{"retry_use_local_part"} = "true"
2361       if (!defined $$hash{"check_local_user"} ||
2362           $$hash{"check_local_user"} eq "false") ;
2363
2364     # Output the router's option settings
2365
2366     &outdriver($hash);
2367
2368     # Output an auxiliary router if one is needed
2369
2370     print STDOUT $second_router if defined $second_router;
2371
2372     next;
2373     }
2374
2375   # Skip past any continuation lines for an option setting
2376   while ($c[$i] =~ /\\\s*$/s)
2377     {
2378     $i++;
2379     $i++ while ($c[$i] =~ /^\s*#/);
2380     }
2381   }
2382
2383
2384
2385 # -------- The transports configuration --------
2386
2387 $started = 0;
2388 $prefix = "t.";
2389 for ($i = $transport_start; $i < $clen; $i++)
2390   {
2391   $type = &checkline($c[$i]);
2392   last if $type eq "end";
2393
2394   if ($type eq "comment") { print STDOUT "$c[$i]\n"; next; }
2395
2396   if (!$started)
2397     {
2398     print STDOUT "begin transports\n\n";
2399     $started = 1;
2400     }
2401
2402   if ($type eq "driver")
2403     {
2404     $hash = $driverlist{"$prefix$name"};
2405     $driver = $$hash{"driver"};
2406     print STDOUT "$name:\n";
2407
2408     # ---- Changes to the appendfile transport ----
2409
2410     if ($driver eq "appendfile")
2411       {
2412       &renamed($hash, "prefix", "message_prefix");
2413       &renamed($hash, "suffix", "message_suffix");
2414       &abolished($hash, "An appendfile transport",
2415         "require_lockfile");
2416       &handle_batch_and_bsmtp($hash);
2417       if (defined $$hash{"from_hack"} && $$hash{"from_hack"} eq "false")
2418         {
2419         print STDOUT "#!!# no_from_hack replaced by check_string\n";
2420         $$hash{"check_string"} = "";
2421         }
2422       delete $$hash{"from_hack"};
2423       }
2424
2425     # ---- Changes to the lmtp transport ----
2426
2427     elsif ($driver eq "lmtp")
2428       {
2429       if (defined $$hash{"batch"} && $$hash{"batch"} ne "none")
2430         {
2431         $$hash{"batch_max"} = "100" if !defined $$hash{"batch_max"};
2432         $$hash{"batch_id"} = "\$domain" if $$hash{"batch"} eq "domain";
2433         }
2434       else
2435         {
2436         $$hash{"batch_max"} = "1" if defined $$hash{"batch_max"};
2437         }
2438       delete $$hash{"batch"};
2439       }
2440
2441     # ---- Changes to the pipe transport ----
2442
2443     elsif ($driver eq "pipe")
2444       {
2445       &renamed($hash, "prefix", "message_prefix");
2446       &renamed($hash, "suffix", "message_suffix");
2447       &handle_batch_and_bsmtp($hash);
2448       if (defined $$hash{"from_hack"} && $$hash{"from_hack"} eq "false")
2449         {
2450         print STDOUT "#!!# no_from_hack replaced by check_string\n";
2451         $$hash{"check_string"} = "";
2452         }
2453       delete $$hash{"from_hack"};
2454       }
2455
2456     # ---- Changes to the smtp transport ----
2457
2458     elsif ($driver eq "smtp")
2459       {
2460       &abolished($hash, "An smtp transport", "mx_domains");
2461       &renamed($hash, "service", "port");
2462       &renamed($hash, "tls_verify_ciphers", "tls_require_ciphers");
2463       &renamed($hash, "authenticate_hosts", "hosts_try_auth");
2464
2465       if (defined $$hash{"batch_max"})
2466         {
2467         print STDOUT "#!!# batch_max renamed connection_max_messages\n";
2468         $$hash{"connection_max_messages"} = $$hash{"batch_max"};
2469         delete $$hash{"batch_max"};
2470         }
2471
2472       foreach $o ("hosts_try_auth", "hosts_avoid_tls", "hosts_require_tls",
2473                   "mx_domains", "serialize_hosts")
2474         {
2475         $$hash{$o} = &no_expand_regex($$hash{$o}) if defined $$hash{$o};
2476         }
2477       }
2478
2479     &outdriver($driverlist{"$prefix$name"});
2480     next;
2481     }
2482
2483   # Skip past any continuation lines for an option setting
2484   while ($c[$i] =~ /\\\s*$/s)
2485     {
2486     $i++;
2487     $i++ while ($c[$i] =~ /^\s*#/);
2488     }
2489   }
2490
2491
2492 # -------- The retry configuration --------
2493
2494 $started = 0;
2495 for ($i = $retry_start; $i < $clen && $i < $rewrite_start - 1; $i++)
2496   {
2497   if (!$started)
2498     {
2499     if ($c[$i] !~ /^\s*(#|$)/)
2500       {
2501       print STDOUT "\nbegin retry\n\n";
2502       $started = 1;
2503       }
2504     }
2505   &print_no_expand($c[$i]);
2506   }
2507
2508 print STDOUT "\n# End of Exim 4 configuration\n";
2509
2510 print STDERR "\n*******************************************************\n";
2511 print STDERR   "***** Please review the generated file carefully. *****\n";
2512 print STDERR   "*******************************************************\n\n";
2513
2514 # End of convert4r4
2515