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