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