Avoid using "-w" option in perl script shebang lines, being incompatible with "env...
[exim.git] / src / src / convert4r4.src
CommitLineData
8c4f17b3 1#! PERL_COMMAND
059ec3d9
PH
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
8c4f17b3 9use warnings;
059ec3d9
PH
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
120sub rubric {
121return if $rubric_output;
122$rubric_output = 1;
123print 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
134sub checkline{
135my($line) = $_[0];
136
137return "comment" if $line =~ /^\s*(#|$)/;
138return "end" if $line =~ /^\s*end\s*$/i;
139
140# Macros are recognized only in the first section of the file.
141
142return "macro" if $prefix eq "" && $line =~ /^\s*[A-Z]/;
143
144# In retry and rewrite sections, the type is always "other"
145
146return "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
155return "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
160if ($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
169else
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
182return "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
194sub negate {
195my($list) = $_[0];
196my($delim) = ":";
197my($leadin) = "";
198
199return $list if ! defined $list;
200
201($list) = $list =~ /^"?(.*?)"?\s*$/s; # Remove surrounding quotes
202$list =~ s/\\\s*\n\s*//g; # Remove continuation markers
203
204if ($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
215foreach $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)$/;
235return "$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
247sub no_expand_regex {
248my($list) = $_[0];
249my($delim) = ":";
250my($leadin) = "";
251
252return $list if ! defined $list;
253
254$delim = $_[1] if (defined $_[1]);
255
256my($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
261if ($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
272my($changed) = 0;
273foreach $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 }
291print STDOUT
292 "#!!# Regular expressions enclosed in \\N...\\N to avoid expansion\n"
293 if $changed;
294
295$" = " $delim \\\n ";
296$leadin .= " " if $leadin !~ /(^|\s)$/;
297return "$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
309sub sort_address_list {
310my($list) = $_[0];
311my($name) = $_[1];
312my($delim) = ":";
313my($leadin) = "";
314my($quoted) = 0;
315
316return $list if ! defined $list;
317
318if ($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
326if ($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
337foreach $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
364return $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
375sub expquote {
376my($s) = $_[0];
377$s =~ s/\$/\\\$/sg;
378$s =~ s/\\(?!\s*\n)/\\\\/sg;
379return $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
391sub unquote {
392my($s) = $_[0];
393$s =~ s/^"(.*)"$/$1/s;
394return $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
406sub acl_quote {
407my($s) = $_[0];
408$s = ($s =~ /^"(.*)"$/s)? $1 : &expquote($s);
409$s =~ s/\n/\n /g;
410$s =~ s/\n\s{11,}/\n /g;
411return $s;
412}
413
414
415##################################################
416# Handle abolished driver options #
417##################################################
418
419sub abolished {
420my($hash) = shift @_;
421my($name) = shift @_;
422for $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
442sub renamed {
443my($hash,$old,$new) = @_;
444if (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
458sub check_require {
459my($string, $name) = @_;
460
461$string =~ s/::/[[[]]]/g;
462my(@list) = split /:/, $string;
463my($item);
464
465for $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
486sub handle_current_and_home_directory {
487my($hash,$driver,$name) = @_;
488
489for ("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
516sub handle_batch_and_bsmtp{
517my($hash) = @_;
518
519if (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
541if (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 }
546else
547 {
548 $$hash{"batch_max"} = "1" if defined $$hash{"batch_max"};
549 }
550delete $$hash{"batch"};
551}
552
553
554
555##################################################
556# Output one option #
557##################################################
558
559sub outopt {
560my($hash, $key, $no_expand) = @_;
561my($data) = $$hash{$key};
562
563print STDOUT "hide " if defined $$hash{"$key-hide"};
564
565# Output booleans in the form that doesn't use "="
566
567if ($data eq "true")
568 {
569 print STDOUT "$key\n";
570 }
571elsif ($data eq "false")
572 {
573 print STDOUT "no_$key\n";
574 }
575else
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
596sub outdriver {
597my($hash) = $_[0];
598print STDOUT " driver = $$hash{'driver'}\n";
599foreach $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
616sub print_no_expand {
617my($s) = $_[0];
618if ($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 }
633print 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
644sub bool {
645return defined $main{$_[0]} && $main{$_[0]} eq "true";
646}
647
648
649
650##################################################
651# Main program #
652##################################################
653
654print 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
674chomp(@c = <STDIN>);
675$clen = scalar @c;
676
677# Remove the standard comment that appears at the end of the default
678
679if ($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
693for ($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
825print STDOUT "#!!# This file is output from the convert4r4 script, which tries\n";
826print STDOUT "#!!# to convert Exim 3 configurations into Exim 4 configurations.\n";
827print STDOUT "#!!# However, it is not perfect, especially with non-simple\n";
828print STDOUT "#!!# configurations. You must check it before running it.\n";
829print STDOUT "\n\n";
830
831# Output the macro definitions
832
833if ($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
843print STDOUT "#!!# These options specify the Access Control Lists (ACLs) that\n";
844print STDOUT "#!!# are used for incoming SMTP messages - after the RCPT and DATA\n";
845print STDOUT "#!!# commands, respectively.\n\n";
846
847print STDOUT "acl_smtp_rcpt = check_recipient\n";
848print STDOUT "acl_smtp_data = check_message\n\n";
849
850if (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
857if (&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 = ":";
877if ($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
895if ($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 = ":";
910if ($relay_domains =~ /^\s*<(.)\s*(.*)/s)
911 {
912 $ldsep = $1;
913 }
914
915if (defined $main{"relay_domains_include_local_mx"})
916 {
917 $relay_domains .= ($relay_domains =~ /^\s*$/)? "\@mx_any" :
918 " $ldsep \@mx_any";
919 }
920
921printf 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
929push @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
938if (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
998printf STDOUT ("hostlist auth_hosts = %s\n",
999 &no_expand_regex($main{"auth_hosts"}))
1000 if defined $main{"auth_hosts"};
1001printf STDOUT ("hostlist rbl_hosts = %s\n",
1002 &no_expand_regex($main{"rbl_hosts"}))
1003 if defined $main{"rbl_hosts"};
1004printf STDOUT ("hostlist relay_hosts = %s\n",
1005 &no_expand_regex($main{"host_accept_relay"}))
1006 if defined $main{"host_accept_relay"};
1007printf 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
1011printf 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"};
1014printf STDOUT ("hostlist tls_hosts = %s\n",
1015 &no_expand_regex($main{"tls_hosts"}))
1016 if defined $main{"tls_hosts"};
1017printf 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
1021print STDOUT "\n";
1022
1023
1024# Convert various logging options
1025
1026$log_selector = "";
1027$sep = " \\\n ";
1028
1029if (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
1059if ($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
1071if (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 = "";
1119MainLine: 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
1441print STDOUT "\n";
1442print STDOUT "#!!#######################################################!!#\n";
1443print STDOUT "#!!# This new section of the configuration contains ACLs #!!#\n";
1444print STDOUT "#!!# (Access Control Lists) derived from the Exim 3 #!!#\n";
1445print STDOUT "#!!# policy control options. #!!#\n";
1446print STDOUT "#!!#######################################################!!#\n";
1447
1448print STDOUT "\n";
1449print STDOUT "#!!# These ACLs are crudely constructed from Exim 3 options.\n";
1450print STDOUT "#!!# They are almost certainly not optimal. You should study\n";
1451print STDOUT "#!!# them and rewrite as necessary.\n";
1452
1453print 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
1459print STDOUT "#!!# ACL that is used after the RCPT command\n";
1460print STDOUT "check_recipient:\n";
1461
1462print STDOUT " # Exim 3 had no checking on -bs messages, so for compatibility\n";
1463print STDOUT " # we accept if the source is local SMTP (i.e. not over TCP/IP).\n";
1464print STDOUT " # We do this by testing for an empty sending host field.\n";
1465print STDOUT " accept hosts = :\n";
1466
1467if (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
1476print STDOUT " deny hosts = +auth_hosts\n" .
1477 " message = authentication required\n" .
1478 " !authenticated = *\n"
1479 if defined $main{"auth_hosts"};
1480
1481print STDOUT " deny hosts = +tls_hosts\n" .
1482 " message = encryption required\n" .
1483 " !encrypted = *\n"
1484 if defined $main{"tls_hosts"};
1485
1486printf 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
1491printf 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
1496printf STDOUT (" deny hosts = %s\n", &acl_quote($main{"host_reject"}))
1497 if defined $main{"host_reject"};
1498
1499printf STDOUT (" deny hosts = %s\n",
1500 &acl_quote($main{"host_reject_recipients"}))
1501 if defined $main{"host_reject_recipients"};
1502
1503if (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
1532printf STDOUT (" deny senders = %s\n",
1533 &acl_quote(&sort_address_list($main{"sender_reject"}, "sender_reject")))
1534 if defined $main{"sender_reject"};
1535
1536printf 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
1541if (&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
1568if (&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
1585print STDOUT " accept domains = +local_domains\n"
1586 if $local_domains !~ /^\s*$/;
1587
1588print STDOUT " accept domains = +relay_domains\n"
1589 if $relay_domains !~ /^\s*$/;
1590
1591if (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
1622print 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
1628print 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
1634print 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
1640print STDOUT "#!!# ACL that is used after the DATA command\n";
1641print STDOUT "check_message:\n";
1642
1643# Default for headers_checks_fail is true
1644
1645if (!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 }
1655else
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
1665print STDOUT " accept\n\n";
1666
1667
1668# Output an ACL for AUTH if required
1669
1670if (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
1684if (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
1695if (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
1706if (&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;
1720for ($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;
1737for ($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.";
1763undef @comments;
1764
1765print STDOUT "\n";
1766print STDOUT "#!!#######################################################!!#\n";
1767print STDOUT "#!!# Here follow routers created from the old routers, #!!#\n";
1768print STDOUT "#!!# for handling non-local domains. #!!#\n";
1769print STDOUT "#!!#######################################################!!#\n";
1770
1771print STDOUT "\nbegin routers\n\n";
1772
1773for ($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
2030if ($add_no_more)
2031 {
2032 print STDOUT " no_more\n";
2033 print STDOUT shift @comments while scalar(@comments) > 0;
2034 }
2035else
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
2049print STDOUT "\n";
2050print STDOUT "#!!#######################################################!!#\n";
2051print STDOUT "#!!# Here follow routers created from the old directors, #!!#\n";
2052print STDOUT "#!!# for handling local domains. #!!#\n";
2053print STDOUT "#!!#######################################################!!#\n";
2054
2055$prefix = "d.";
2056for ($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.";
2388for ($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;
2494for ($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
2507print STDOUT "\n# End of Exim 4 configuration\n";
2508
2509print STDERR "\n*******************************************************\n";
2510print STDERR "***** Please review the generated file carefully. *****\n";
2511print STDERR "*******************************************************\n\n";
2512
2513# End of convert4r4
2514