Fix cert-try-verify when denied by event action
[exim.git] / src / src / convert4r3.src
1 #! PERL_COMMAND -w
2
3 # This is a Perl script that reads an Exim run-time configuration file and
4 # checks for settings that were valid prior to release 3.00 but which were
5 # obsoleted by that release. It writes a new file with suggested changes to
6 # the standard output, and commentary about what it has done to stderr.
7
8 # It is assumed that the input is a valid Exim configuration file.
9
10
11 ##################################################
12 # Analyse one line #
13 ##################################################
14
15 # This is called for the main and the driver sections, not for retry
16 # or rewrite sections (which are unmodified).
17
18 sub checkline{
19 my($line) = $_[0];
20
21 return "comment" if $line =~ /^\s*(#|$)/;
22 return "end" if $line =~ /^\s*end\s*$/;
23
24 # Macros are recognized only in the first section of the file.
25
26 return "macro" if $prefix eq "" && $line =~ /^\s*[A-Z]/;
27
28 # Pick out the name at the start and the rest of the line (into global
29 # variables) and return whether the start of a driver or not.
30
31 ($i1,$name,$i2,$rest) = $line =~ /^(\s*)([a-z0-9_]+)(\s*)(.*?)\s*$/;
32 return ($rest =~ /^:/)? "driver" : "option";
33 }
34
35
36
37
38 ##################################################
39 # Add transport setting to a director #
40 ##################################################
41
42 # This function adds a transport setting to an aliasfile or forwardfile
43 # director if a global setting exists and a local one does not. If neither
44 # exist, it adds file/pipe/reply, but not the directory ones.
45
46 sub add_transport{
47 my($option) = @_;
48
49 my($key) = "$prefix$driver.${option}_transport";
50 if (!exists $o{$key})
51 {
52 if (exists $o{"address_${option}_transport"})
53 {
54 print STDOUT "# >> Option added by convert4r3\n";
55 printf STDOUT "${i1}${option}_transport = %s\n",
56 $o{"address_${option}_transport"};
57 printf STDERR
58 "\n%03d ${option}_transport added to $driver director.\n",
59 ++$count;
60 }
61 else
62 {
63 if ($option eq "pipe" || $option eq "file" || $option eq "reply")
64 {
65 print STDOUT "# >> Option added by convert4r3\n";
66 printf STDOUT "${i1}${option}_transport = address_${option}\n";
67 printf STDERR
68 "\n%03d ${option}_transport added to $driver director.\n",
69 ++$count;
70 }
71 }
72 }
73 }
74
75
76
77
78 ##################################################
79 # Negate a list of things #
80 ##################################################
81
82 sub negate {
83 my($list) = $_[0];
84
85 return $list if ! defined $list;
86
87 ($list) = $list =~ /^"?(.*?)"?\s*$/s;
88
89 # Under Perl 5.005 we can split very nicely at colons, ignoring double
90 # colons, like this:
91 #
92 # @split = split /\s*(?<!:):(?!:)\s*(?:\\\s*)?/s, $list;
93 #
94 # However, we'd better make this work under Perl 5.004, since there is
95 # a lot of that about.
96
97 $list =~ s/::/>%%%%</g;
98 @split = split /\s*:\s*(?:\\\s*)?/s, $list;
99 foreach $item (@split)
100 {
101 $item =~ s/>%%%%</::/g;
102 }
103
104 $" = " : \\\n ! ";
105 return "! @split";
106 }
107
108
109
110
111
112 ##################################################
113 # Skip blank lines #
114 ##################################################
115
116 # This function is called after we have generated no output for an option;
117 # it skips subsequent blank lines if the previous line was blank.
118
119 sub skipblanks {
120 my($i) = $_[0];
121 if ($last_was_blank)
122 {
123 $i++ while $c[$i+1] =~ /^\s*$/;
124 }
125 return $i;
126 }
127
128
129
130
131
132 ##################################################
133 # Get base name of data key #
134 ##################################################
135
136 sub base {
137 return "$_[0]" if $_[0] !~ /^(?:d|r|t)\.[^.]+\.(.*)/;
138 return $1;
139 }
140
141
142
143 ##################################################
144 # Amalgamate accept/reject/reject_except #
145 ##################################################
146
147 # This function amalgamates the three previous kinds of
148 # option into a single list, using negation for the middle one if
149 # the final argument is "+", or for the outer two if the final
150 # argument is "-".
151
152 sub amalgamate {
153 my($accept,$reject,$reject_except,$name);
154 my($last_was_negated) = 0;
155 my($join) = "";
156
157 $accept = $o{$_[0]};
158 $reject = $o{$_[1]};
159 $reject_except = $o{$_[2]};
160 $name = $_[3];
161
162 if ($_[4] eq "+")
163 {
164 ($accept) = $accept =~ /^"?(.*?)"?\s*$/s if defined $accept;
165 $reject = &negate($reject) if defined $reject;
166 ($reject_except) = $reject_except =~ /^"?(.*?)"?\s*$/s if defined $reject_except;
167 }
168 else
169 {
170 $accept = &negate($accept) if defined $accept;
171 ($reject) = $reject =~ /^"?(.*?)"?\s*$/s if defined $reject;
172 $reject_except = &negate($reject_except) if defined $reject_except;
173 }
174
175 print STDOUT "# >> Option rewritten by convert4r3\n";
176 print STDOUT "${i1}$name = \"";
177
178 if (defined $reject_except)
179 {
180 print STDOUT "$reject_except";
181 $join = " : \\\n ";
182 $last_was_negated = ($_[4] ne "+");
183 }
184 if (defined $reject)
185 {
186 print STDOUT "$join$reject";
187 $join = " : \\\n ";
188 $last_was_negated = ($_[4] eq "+");
189 }
190 if (defined $accept)
191 {
192 print STDOUT "$join$accept";
193 $last_was_negated = ($_[4] ne "+");
194 $join = " : \\\n ";
195 }
196
197 print STDOUT "$join*" if $last_was_negated;
198
199 print STDOUT "\"\n";
200
201 my($driver_name);
202 my($driver_type) = "";
203
204 if ($_[0] =~ /^(d|r|t)\.([^.]+)\./ ||
205 $_[1] =~ /^(d|r|t)\.([^.]+)\./ ||
206 $_[2] =~ /^(d|r|t)\.([^.]+)\./)
207 {
208 $driver_type = ($1 eq 'd')? "director" : ($1 eq 'r')? "router" : "transport";
209 $driver_name = $2;
210 }
211
212 my($x) = ($driver_type ne "")? " in \"$driver_name\" $driver_type" : "";
213
214 my($l0) = &base($_[0]);
215 my($l1) = &base($_[1]);
216 my($l2) = &base($_[2]);
217
218
219 if ($l2 eq "")
220 {
221 if ($l0 eq "")
222 {
223 printf STDERR "\n%03d $l1 converted to $name$x.\n", ++$count;
224 }
225 else
226 {
227 printf STDERR "\n%03d $l0 and $l1\n amalgamated into $name$x.\n",
228 ++$count;
229 }
230 }
231 else
232 {
233 if ($l1 eq "")
234 {
235 printf STDERR "\n%03d $l0 and $l2\n amalgamated into $name$x.\n",
236 ++$count;
237 }
238 else
239 {
240 printf STDERR "\n%03d $l0, $l1 and $l2\n amalgamated into " .
241 "$name$x.\n", ++$count;
242 }
243 }
244 }
245
246
247
248
249 ##################################################
250 # Join two lists, if they exist #
251 ##################################################
252
253 sub pair{
254 my($l1) = $o{"$_[0]"};
255 my($l2) = $o{"$_[1]"};
256
257 return $l2 if (!defined $l1);
258 return $l1 if (!defined $l2);
259
260 ($l1) = $l1 =~ /^"?(.*?)"?\s*$/s;
261 ($l2) = $l2 =~ /^"?(.*?)"?\s*$/s;
262
263 return "$l1 : $l2";
264 }
265
266
267
268
269 ##################################################
270 # Amalgamate accept/reject/reject_except pairs #
271 ##################################################
272
273 # This is like amalgamate, but it combines pairs of arguments, and
274 # doesn't output commentary (easier to write a generic one for the few
275 # cases).
276
277 sub amalgamatepairs {
278 my($accept) = &pair($_[0], $_[1]);
279 my($reject) = &pair($_[2], $_[3]);
280 my($reject_except) = &pair($_[4], $_[5]);
281 my($last_was_negated) = 0;
282 my($join) = "";
283
284 if ($_[7] eq "+")
285 {
286 ($accept) = $accept =~ /^"?(.*?)"?\s*$/s if defined $accept;
287 $reject = &negate($reject) if defined $reject;
288 ($reject_except) = $reject_except =~ /^"?(.*?)"?\s*$/s if defined $reject_except;
289 }
290 else
291 {
292 $accept = &negate($accept) if defined $accept;
293 ($reject) = $reject =~ /^"?(.*?)"?$/s if defined $reject;
294 $reject_except = &negate($reject_except) if defined $reject_except;
295 }
296
297 print STDOUT "# >> Option rewritten by convert4r3\n";
298 print STDOUT "${i1}$_[6] = \"";
299
300 if (defined $reject_except)
301 {
302 print STDOUT "$reject_except";
303 $join = " : \\\n ";
304 $last_was_negated = ($_[7] ne "+");
305 }
306 if (defined $reject)
307 {
308 print STDOUT "$join$reject";
309 $join = " : \\\n ";
310 $last_was_negated = ($_[7] eq "+");
311 }
312 if (defined $accept)
313 {
314 print STDOUT "$join$accept";
315 $last_was_negated = ($_[7] ne "+");
316 $join = " : \\\n ";
317 }
318
319 print STDOUT "$join*" if $last_was_negated;
320 print STDOUT "\"\n";
321 }
322
323
324
325 ##################################################
326 # Amalgamate boolean and exception list(s) #
327 ##################################################
328
329 sub amalgboolandlist {
330 my($name,$bool,$e1,$e2) = @_;
331
332 print STDOUT "# >> Option rewritten by convert4r3\n";
333 if ($bool eq "false")
334 {
335 printf STDOUT "$i1$name =\n";
336 }
337 else
338 {
339 printf STDOUT "$i1$name = ";
340 my($n1) = &negate($o{$e1});
341 my($n2) = &negate($o{$e2});
342 if (!defined $n1 && !defined $n2)
343 {
344 print STDOUT "*\n";
345 }
346 elsif (!defined $n1)
347 {
348 print STDOUT "\"$n2 : \\\n *\"\n";
349 }
350 elsif (!defined $n2)
351 {
352 print STDOUT "\"$n1 : \\\n *\"\n";
353 }
354 else
355 {
356 print STDOUT "\"$n1 : \\\n $n2 : \\\n *\"\n";
357 }
358 }
359 }
360
361
362
363 ##################################################
364 # Convert mask format #
365 ##################################################
366
367 # This function converts an address and mask in old-fashioned dotted-quad
368 # format into an address plus a new format mask.
369
370 @byte_list = (0, 128, 192, 224, 240, 248, 252, 254, 255);
371
372 sub mask {
373 my($address,$mask) = @_;
374 my($length) = 0;
375 my($i, $j);
376
377 my(@bytes) = split /\./, $mask;
378
379 for ($i = 0; $i < 4; $i++)
380 {
381 for ($j = 0; $j <= 8; $j++)
382 {
383 if ($bytes[$i] == $byte_list[$j])
384 {
385 $length += $j;
386 if ($j != 8)
387 {
388 for ($i++; $i < 4; $i++)
389 {
390 $j = 9 if ($bytes[$i] != 0);
391 }
392 }
393 last;
394 }
395 }
396
397 if ($j > 8)
398 {
399 print STDERR "*** IP mask $mask cannot be converted to /n format. ***\n";
400 return "$address/$mask";
401 }
402 }
403
404 if (!defined $masks{$mask})
405 {
406 printf STDERR "\n%03d IP address mask $mask converted to /$length\n",
407 ++$count, $mask, $length;
408 $masks{$mask} = 1;
409 }
410
411 return sprintf "$address/%d", $length;
412 }
413
414
415
416
417
418 ##################################################
419 # Main program #
420 ##################################################
421
422 print STDERR "Exim pre-release 3.00 configuration file converter.\n";
423
424 $count = 0;
425 $seen_helo_accept_junk = 0;
426 $seen_hold_domains = 0;
427 $seen_receiver_unqualified = 0;
428 $seen_receiver_verify_except = 0;
429 $seen_receiver_verify_senders = 0;
430 $seen_rfc1413_except = 0;
431 $seen_sender_accept = 0;
432 $seen_sender_accept_recipients = 0;
433 $seen_sender_host_accept = 0;
434 $seen_sender_host_accept_recipients = 0;
435 $seen_sender_host_accept_relay = 0;
436 $seen_sender_unqualified = 0;
437 $seen_sender_verify_except_hosts = 0;
438 $seen_smtp_etrn = 0;
439 $seen_smtp_expn = 0;
440 $seen_smtp_reserve = 0;
441 $semicomma = 0;
442
443 # Read the entire file into an array
444
445 chomp(@c = <STDIN>);
446
447 # First, go through the input and covert any net masks in the old dotted-quad
448 # style into the new /n style.
449
450 for ($i = 0; $i < scalar(@c); $i++)
451 {
452 $c[$i] =~
453 s"((?:\d{1,3}\.){3}\d{1,3})/((?:\d{1,3}\.){3}\d{1,3})"&mask($1,$2)"eg;
454 }
455
456 # We now make two more passes over the input. In the first pass, we place all
457 # the option values into an associative array. Main options are keyed by their
458 # names; options for drivers are keyed by a driver type letter, the driver
459 # name, and the option name, dot-separated. In the second pass we modify
460 # the options if necessary, and write the output file.
461
462 for ($pass = 1; $pass < 3; $pass++)
463 {
464 $prefix = "";
465 $driver = "";
466 $last_was_blank = 0;
467
468 for ($i = 0; $i < scalar(@c); $i++)
469 {
470 # Everything after the router section is just copied in pass 2 and
471 # ignored in pass 1.
472
473 if ($prefix eq "end")
474 {
475 print STDOUT "$c[$i]\n" if $pass == 2;
476 next;
477 }
478
479 # Analyze the line
480
481 $type = &checkline($c[$i]);
482
483 # Skip comments in pass 1; copy in pass 2
484
485 if ($type eq "comment")
486 {
487 $last_was_blank = ($c[$i] =~ /^\s*$/)? 1 : 0;
488 print STDOUT "$c[$i]\n" if $pass == 2;
489 next;
490 }
491
492 # Skip/copy macro definitions, but must handle continuations
493
494 if ($type eq "macro")
495 {
496 print STDOUT "$c[$i]\n" if $pass == 2;
497 while ($c[$i] =~ /\\\s*$/)
498 {
499 $i++;
500 print STDOUT "$c[$i]\n" if $pass == 2;
501 }
502 $last_was_blank = 0;
503 next;
504 }
505
506 # Handle end of section
507
508 if ($type eq "end")
509 {
510 $prefix = "end"if $prefix eq "r.";
511 $prefix = "r." if $prefix eq "d.";
512 $prefix = "d." if $prefix eq "t.";
513 $prefix = "t." if $prefix eq "";
514 print STDOUT "$c[$i]\n" if $pass == 2;
515 $last_was_blank = 0;
516 next;
517 }
518
519 # Handle start of a new driver
520
521 if ($type eq "driver")
522 {
523 $driver = $name;
524 print STDOUT "$c[$i]\n" if $pass == 2;
525 $last_was_blank = 0;
526 $seen_domains = 0;
527 $seen_local_parts = 0;
528 $seen_senders = 0;
529 $seen_mx_domains = 0;
530 $seen_serialize = 0;
531 next;
532 }
533
534 # Handle definition of an option
535
536 if ($type eq "option")
537 {
538 # Handle continued strings
539
540 if ($rest =~ /^=\s*".*\\$/)
541 {
542 for (;;)
543 {
544 $rest .= "\n$c[++$i]";
545 last unless $c[$i] =~ /(\\\s*$|^\s*#)/;
546 }
547 }
548
549 # Remove any terminating commas and semicolons in pass 2
550
551 if ($pass == 2 && $rest =~ /[;,]\s*$/)
552 {
553 $rest =~ s/\s*[;,]\s*$//;
554 if (!$semicomma)
555 {
556 printf STDERR
557 "\n%03d Terminating semicolons and commas removed from driver " .
558 "options.\n", ++$count;
559 $semicomma = 1;
560 }
561 }
562
563 # Convert all booleans to "x = true/false" format, but save the
564 # original so that it can be reproduced unchanged for options that
565 # are not of interest.
566
567 $origname = $name;
568 $origrest = $rest;
569
570 if ($name =~ /^not?_(.*)/)
571 {
572 $name = $1;
573 $rest = "= false";
574 }
575 elsif ($rest !~ /^=/)
576 {
577 $rest = "= true";
578 }
579
580 # Set up the associative array key, and get rid of the = on the data
581
582 $key = ($prefix eq "")? "$name" : "$prefix$driver.$name";
583 ($rest) = $rest =~ /^=\s*(.*)/s;
584
585 # Create the associative array of values in pass 1
586
587 if ($pass == 1)
588 {
589 $o{$key} = $rest;
590 }
591
592 # In pass 2, test for interesting options and do the necessary; copy
593 # all the rest.
594
595 else
596 {
597 ########## Global configuration ##########
598
599 # These global options are abolished
600
601 if ($name eq "address_directory_transport" ||
602 $name eq "address_directory2_transport" ||
603 $name eq "address_file_transport" ||
604 $name eq "address_pipe_transport" ||
605 $name eq "address_reply_transport")
606 {
607 ($n2) = $name =~ /^address_(.*)/;
608 printf STDERR "\n%03d $name option deleted.\n", ++$count;
609 printf STDERR " $n2 will be added to appropriate directors.\n";
610 $i = &skipblanks($i);
611 next;
612 }
613
614 # This debugging option is abolished
615
616 elsif ($name eq "sender_verify_log_details")
617 {
618 printf STDERR "\n%03d $name option deleted.\n", ++$count;
619 printf STDERR " (Little used facility abolished.)\n";
620 }
621
622 # This option has been renamed
623
624 elsif ($name eq "check_dns_names")
625 {
626 $origname =~ s/check_dns/dns_check/;
627 print STDOUT "# >> Option rewritten by convert4r3\n";
628 print STDOUT "$i1$origname$i2$origrest\n";
629 printf STDERR "\n%03d check_dns_names renamed as dns_check_names.\n",
630 ++$count;
631 }
632
633 # helo_accept_junk_nets is abolished
634
635 elsif ($name eq "helo_accept_junk_nets" ||
636 $name eq "helo_accept_junk_hosts")
637 {
638 if (!$seen_helo_accept_junk)
639 {
640 &amalgamate("helo_accept_junk_nets", "",
641 "helo_accept_junk_hosts", "helo_accept_junk_hosts", "+");
642 $seen_helo_accept_junk = 1;
643 }
644 else
645 {
646 $i = &skipblanks($i);
647 next;
648 }
649 }
650
651 # helo_verify_except_{hosts,nets} are abolished, and helo_verify
652 # is now a host list instead of a boolean.
653
654 elsif ($name eq "helo_verify")
655 {
656 &amalgboolandlist("helo_verify", $rest, "helo_verify_except_hosts",
657 "helo_verify_except_nets");
658 printf STDERR "\n%03d helo_verify converted to host list.\n",
659 ++$count;
660 }
661 elsif ($name eq "helo_verify_except_hosts" ||
662 $name eq "helo_verify_except_nets")
663 {
664 $i = &skipblanks($i);
665 next;
666 }
667
668 # helo_verify_nets was an old synonym for host_lookup_nets; only
669 # one of them will be encountered. Change to a new name.
670
671 elsif ($name eq "helo_verify_nets" ||
672 $name eq "host_lookup_nets")
673 {
674 print STDOUT "# >> Option rewritten by convert4r3\n";
675 print STDOUT "${i1}host_lookup$i2$origrest\n";
676 printf STDERR "\n%03d $name renamed as host_lookup.\n", ++$count;
677 }
678
679 # hold_domains_except is abolished; add as negated items to
680 # hold_domains.
681
682 elsif ($name eq "hold_domains_except" ||
683 $name eq "hold_domains")
684 {
685 if ($seen_hold_domains) # If already done with these
686 { # omit, and following blanks.
687 $i = &skipblanks($i);
688 next;
689 }
690 $seen_hold_domains = 1;
691
692 if (exists $o{"hold_domains_except"})
693 {
694 &amalgamate("hold_domains", "hold_domains_except", "",
695 "hold_domains", "+");
696 }
697 else
698 {
699 print STDOUT "$i1$origname$i2$origrest\n";
700 }
701 }
702
703 # ignore_fromline_nets is renamed as ignore_fromline_hosts
704
705 elsif ($name eq "ignore_fromline_nets")
706 {
707 $origname =~ s/_nets/_hosts/;
708 print STDOUT "# >> Option rewritten by convert4r3\n";
709 print STDOUT "$i1$origname$i2$origrest\n";
710 printf STDERR
711 "\n%03d ignore_fromline_nets renamed as ignore_fromline_hosts.\n",
712 ++$count;
713 }
714
715 # Output a warning for message filters with no transports set
716
717 elsif ($name eq "message_filter")
718 {
719 print STDOUT "$i1$origname$i2$origrest\n";
720
721 if (!exists $o{"message_filter_directory_transport"} &&
722 !exists $o{"message_filter_directory2_transport"} &&
723 !exists $o{"message_filter_file_transport"} &&
724 !exists $o{"message_filter_pipe_transport"} &&
725 !exists $o{"message_filter_reply_transport"})
726 {
727 printf STDERR
728 "\n%03d message_filter is set, but no message_filter transports "
729 . "are defined.\n"
730 . " If your filter generates file or pipe deliveries, or "
731 . "auto-replies,\n"
732 . " you will need to define "
733 . "message_filter_{file,pipe,reply}_transport\n"
734 . " options, as required.\n", ++$count;
735 }
736 }
737
738 # queue_remote_except is abolished, and queue_remote is replaced by
739 # queue_remote_domains, which is a host list.
740
741 elsif ($name eq "queue_remote")
742 {
743 &amalgboolandlist("queue_remote_domains", $rest,
744 "queue_remote_except", "");
745 printf STDERR
746 "\n%03d queue_remote converted to domain list queue_remote_domains.\n",
747 ++$count;
748 }
749 elsif ($name eq "queue_remote_except")
750 {
751 $i = &skipblanks($i);
752 next;
753 }
754
755 # queue_smtp_except is abolished, and queue_smtp is replaced by
756 # queue_smtp_domains, which is a host list.
757
758 elsif ($name eq "queue_smtp")
759 {
760 &amalgboolandlist("queue_smtp_domains", $rest,
761 "queue_smtp_except", "");
762 printf STDERR
763 "\n%03d queue_smtp converted to domain list queue_smtp_domains.\n",
764 ++$count;
765 }
766 elsif ($name eq "queue_smtp_except")
767 {
768 $i = &skipblanks($i);
769 next;
770 }
771
772 # rbl_except_nets is replaced by rbl_hosts
773
774 elsif ($name eq "rbl_except_nets")
775 {
776 &amalgamate("", "rbl_except_nets", "", "rbl_hosts", "+");
777 }
778
779 # receiver_unqualified_nets is abolished
780
781 elsif ($name eq "receiver_unqualified_nets" ||
782 $name eq "receiver_unqualified_hosts")
783 {
784 if (!$seen_receiver_unqualified)
785 {
786 &amalgamate("receiver_unqualified_nets", "",
787 "receiver_unqualified_hosts", "receiver_unqualified_hosts", "+");
788 $seen_receiver_unqualified = 1;
789 }
790 else
791 {
792 $i = &skipblanks($i);
793 next;
794 }
795 }
796
797 # receiver_verify_except_{hosts,nets} are replaced by
798 # receiver_verify_hosts.
799
800 elsif ($name eq "receiver_verify_except_hosts" ||
801 $name eq "receiver_verify_except_nets")
802 {
803 if (!$seen_receiver_verify_except)
804 {
805 &amalgboolandlist("receiver_verify_hosts", "true",
806 "receiver_verify_except_hosts", "receiver_verify_except_nets");
807 printf STDERR
808 "\n%03d receiver_verify_except_{hosts,nets} converted to " .
809 "receiver_verify_hosts.\n",
810 ++$count;
811 $seen_receiver_verify_except = 1;
812 }
813 else
814 {
815 $i = &skipblanks($i);
816 next;
817 }
818 }
819
820 # receiver_verify_senders_except is abolished
821
822 elsif ($name eq "receiver_verify_senders" ||
823 $name eq "receiver_verify_senders_except")
824 {
825 if (defined $o{"receiver_verify_senders_except"})
826 {
827 if (!$seen_receiver_verify_senders)
828 {
829 &amalgamate("receiver_verify_senders",
830 "receiver_verify_senders_except", "",
831 "receiver_verify_senders", "+");
832 $seen_receiver_verify_senders = 1;
833 }
834 else
835 {
836 $i = &skipblanks($i);
837 next;
838 }
839 }
840 else
841 {
842 print STDOUT "$i1$origname$i2$origrest\n";
843 }
844 }
845
846 # rfc1413_except_{hosts,nets} are replaced by rfc1413_hosts.
847
848 elsif ($name eq "rfc1413_except_hosts" ||
849 $name eq "rfc1413_except_nets")
850 {
851 if (!$seen_rfc1413_except)
852 {
853 &amalgboolandlist("rfc1413_hosts", "true",
854 "rfc1413_except_hosts", "rfc1413_except_nets");
855 printf STDERR
856 "\n%03d rfc1413_except_{hosts,nets} converted to rfc1413_hosts.\n",
857 ++$count;
858 $seen_rfc1413_except = 1;
859 }
860 else
861 {
862 $i = &skipblanks($i);
863 next;
864 }
865 }
866
867 # sender_accept and sender_reject_except are abolished
868
869 elsif ($name eq "sender_accept" ||
870 $name eq "sender_reject")
871 {
872 if (!$seen_sender_accept)
873 {
874 &amalgamate("sender_accept", "sender_reject",
875 "sender_reject_except", "sender_reject", "-");
876 $seen_sender_accept = 1;
877 }
878 else
879 {
880 $i = &skipblanks($i);
881 next;
882 }
883 }
884
885 # sender_accept_recipients is also abolished; sender_reject_except
886 # also used to apply to this, so we include it here as well.
887
888 elsif ($name eq "sender_accept_recipients" ||
889 $name eq "sender_reject_recipients")
890 {
891 if (!$seen_sender_accept_recipients)
892 {
893 &amalgamate("sender_accept_recipients", "sender_reject_recipients",
894 "sender_reject_except", "sender_reject_recipients", "-");
895 $seen_sender_accept_recipients = 1;
896 }
897 else
898 {
899 $i = &skipblanks($i);
900 next;
901 }
902 }
903
904 # sender_reject_except must be removed
905
906 elsif ($name eq "sender_reject_except")
907 {
908 $i = &skipblanks($i);
909 next;
910 }
911
912 # sender_{host,net}_{accept,reject}[_except] all collapse into
913 # host_reject.
914
915 elsif ($name eq "sender_host_accept" ||
916 $name eq "sender_net_accept" ||
917 $name eq "sender_host_reject" ||
918 $name eq "sender_net_reject")
919 {
920 if (!$seen_sender_host_accept)
921 {
922 &amalgamatepairs("sender_host_accept", "sender_net_accept",
923 "sender_host_reject", "sender_net_reject",
924 "sender_host_reject_except", "sender_net_reject_except",
925 "host_reject", "-");
926 printf STDERR "\n%03d sender_{host,net}_{accept,reject} and " .
927 "sender_{host_net}_reject_except\n" .
928 " amalgamated into host_reject.\n", ++$count;
929 $seen_sender_host_accept = 1;
930 }
931 else
932 {
933 $i = &skipblanks($i);
934 next;
935 }
936 }
937
938 # sender_{host,net}_{accept,reject}_recipients all collapse into
939 # host_reject_recipients.
940
941 elsif ($name eq "sender_host_accept_recipients" ||
942 $name eq "sender_net_accept_recipients" ||
943 $name eq "sender_host_reject_recipients" ||
944 $name eq "sender_net_reject_recipients")
945 {
946 if (!$seen_sender_host_accept_recipients)
947 {
948 &amalgamatepairs("sender_host_accept_recipients",
949 "sender_net_accept_recipients",
950 "sender_host_reject_recipients",
951 "sender_net_reject_recipients",
952 "sender_host_reject_except", "sender_net_reject_except",
953 "host_reject_recipients", "-");
954 printf STDERR "\n%03d sender_{host,net}_{accept,reject}_recipients"
955 . "\n and sender_{host_net}_reject_except"
956 . "\n amalgamated into host_reject_recipients.\n", ++$count;
957 $seen_sender_host_accept_recipients = 1;
958 }
959 else
960 {
961 $i = &skipblanks($i);
962 next;
963 }
964 }
965
966 # sender_{host,net}_reject_except must be removed
967
968 elsif ($name eq "sender_host_reject_except" ||
969 $name eq "sender_net_reject_except")
970 {
971 $i = &skipblanks($i);
972 next;
973 }
974
975 # sender_{host,net}_{accept,reject}_relay all collapse into
976 # host_accept_relay.
977
978 elsif ($name eq "sender_host_accept_relay" ||
979 $name eq "sender_net_accept_relay" ||
980 $name eq "sender_host_reject_relay" ||
981 $name eq "sender_net_reject_relay")
982 {
983 if (!$seen_sender_host_accept_relay)
984 {
985 &amalgamatepairs("sender_host_accept_relay",
986 "sender_net_accept_relay",
987 "sender_host_reject_relay",
988 "sender_net_reject_relay",
989 "sender_host_reject_relay_except",
990 "sender_net_reject_relay_except",
991 "host_accept_relay", "+");
992 printf STDERR "\n%03d sender_{host,net}_{accept,reject}_relay"
993 . "\n and sender_{host_net}_reject_relay_except"
994 . "\n amalgamated into host_accept_relay.\n", ++$count;
995 $seen_sender_host_accept_relay = 1;
996 }
997 else
998 {
999 $i = &skipblanks($i);
1000 next;
1001 }
1002 }
1003
1004 # sender_{host,net}_reject_relay_except must be removed
1005
1006 elsif ($name eq "sender_host_reject_relay_except" ||
1007 $name eq "sender_net_reject_relay_except")
1008 {
1009 $i = &skipblanks($i);
1010 next;
1011 }
1012
1013
1014 # sender_unqualified_nets is abolished
1015
1016 elsif ($name eq "sender_unqualified_nets" ||
1017 $name eq "sender_unqualified_hosts")
1018 {
1019 if (!$seen_sender_unqualified)
1020 {
1021 &amalgamate("sender_unqualified_nets", "",
1022 "sender_unqualified_hosts", "sender_unqualified_hosts", "+");
1023 $seen_sender_unqualified = 1;
1024 }
1025 else
1026 {
1027 $i = &skipblanks($i);
1028 next;
1029 }
1030 }
1031
1032 # sender_verify_except_{hosts,nets} are replaced by sender_verify_hosts.
1033
1034 elsif ($name eq "sender_verify_except_hosts" ||
1035 $name eq "sender_verify_except_nets")
1036 {
1037 if (!$seen_sender_verify_except_hosts)
1038 {
1039 &amalgboolandlist("sender_verify_hosts", "true",
1040 "sender_verify_except_hosts", "sender_verify_except_nets");
1041 printf STDERR
1042 "\n%03d sender_verify_except_{hosts,nets} converted to " .
1043 "sender_verify_hosts.\n",
1044 ++$count;
1045 $seen_sender_verify_except_hosts = 1;
1046 }
1047 else
1048 {
1049 $i = &skipblanks($i);
1050 next;
1051 }
1052 }
1053
1054 # smtp_etrn_nets is abolished
1055
1056 elsif ($name eq "smtp_etrn_nets" ||
1057 $name eq "smtp_etrn_hosts")
1058 {
1059 if (!$seen_smtp_etrn)
1060 {
1061 &amalgamate("smtp_etrn_nets", "",
1062 "smtp_etrn_hosts", "smtp_etrn_hosts", "+");
1063 $seen_smtp_etrn = 1;
1064 }
1065 else
1066 {
1067 $i = &skipblanks($i);
1068 next;
1069 }
1070 }
1071
1072 # smtp_expn_nets is abolished
1073
1074 elsif ($name eq "smtp_expn_nets" ||
1075 $name eq "smtp_expn_hosts")
1076 {
1077 if (!$seen_smtp_expn)
1078 {
1079 &amalgamate("smtp_expn_nets", "",
1080 "smtp_expn_hosts", "smtp_expn_hosts", "+");
1081 $seen_smtp_expn = 1;
1082 }
1083 else
1084 {
1085 $i = &skipblanks($i);
1086 next;
1087 }
1088 }
1089
1090 # This option has been renamed
1091
1092 elsif ($name eq "smtp_log_connections")
1093 {
1094 $origname =~ s/smtp_log/log_smtp/;
1095 print STDOUT "# >> Option rewritten by convert4r3\n";
1096 print STDOUT "$i1$origname$i2$origrest\n";
1097 printf STDERR "\n%03d smtp_log_connections renamed as " .
1098 "log_smtp_connections.\n",
1099 ++$count;
1100 }
1101
1102 # smtp_reserve_nets is abolished
1103
1104 elsif ($name eq "smtp_reserve_nets" ||
1105 $name eq "smtp_reserve_hosts")
1106 {
1107 if (!$seen_smtp_reserve)
1108 {
1109 &amalgamate("smtp_reserve_nets", "",
1110 "smtp_reserve_hosts", "smtp_reserve_hosts", "+");
1111 $seen_smtp_reserve = 1;
1112 }
1113 else
1114 {
1115 $i = &skipblanks($i);
1116 next;
1117 }
1118 }
1119
1120 ########### Driver configurations ##########
1121
1122 # For aliasfile and forwardfile directors, add file, pipe, and
1123 # reply transports - copying from the globals if they are set.
1124
1125 elsif ($name eq "driver")
1126 {
1127 $driver_type = $rest;
1128 print STDOUT "$i1$origname$i2$origrest\n";
1129 if ($rest eq "aliasfile" || $rest eq "forwardfile")
1130 {
1131 &add_transport("directory");
1132 &add_transport("directory2");
1133 &add_transport("file");
1134 &add_transport("pipe");
1135 &add_transport("reply") if $rest eq "forwardfile";
1136 }
1137 }
1138
1139 # except_domains is abolished; add as negated items to domains.
1140
1141 elsif ($name eq "except_domains" ||
1142 $name eq "domains")
1143 {
1144 if ($seen_domains) # If already done with these
1145 { # omit, and following blanks.
1146 $i = &skipblanks($i);
1147 next;
1148 }
1149 $seen_domains = 1;
1150
1151 if (exists $o{"$prefix$driver.except_domains"})
1152 {
1153 &amalgamate("$prefix$driver.domains",
1154 "$prefix$driver.except_domains", "",
1155 "domains", "+");
1156 }
1157 else
1158 {
1159 print STDOUT "$i1$origname$i2$origrest\n";
1160 }
1161 }
1162
1163 # except_local_parts is abolished; add as negated items to
1164 # local_parts.
1165
1166 elsif ($name eq "except_local_parts" ||
1167 $name eq "local_parts")
1168 {
1169 if ($seen_local_parts) # If already done with these
1170 { # omit, and following blanks.
1171 $i = &skipblanks($i);
1172 next;
1173 }
1174 $seen_local_parts = 1;
1175
1176 if (exists $o{"$prefix$driver.except_local_parts"})
1177 {
1178 &amalgamate("$prefix$driver.local_parts",
1179 "$prefix$driver.except_local_parts", "",
1180 "local_parts", "+");
1181 }
1182 else
1183 {
1184 print STDOUT "$i1$origname$i2$origrest\n";
1185 }
1186 }
1187
1188 # except_senders is abolished; add as negated items to senders
1189
1190 elsif ($name eq "except_senders" ||
1191 $name eq "senders")
1192 {
1193 if ($seen_senders) # If already done with these
1194 { # omit, and following blanks.
1195 $i = &skipblanks($i);
1196 next;
1197 }
1198 $seen_senders = 1;
1199
1200 if (exists $o{"$prefix$driver.except_senders"})
1201 {
1202 &amalgamate("$prefix$driver.senders",
1203 "$prefix$driver.except_senders", "",
1204 "senders", "+");
1205 }
1206 else
1207 {
1208 print STDOUT "$i1$origname$i2$origrest\n";
1209 }
1210 }
1211
1212 # This option has been renamed
1213
1214 elsif ($name eq "directory" && $driver_type eq "aliasfile")
1215 {
1216 $origname =~ s/directory/home_directory/;
1217 print STDOUT "# >> Option rewritten by convert4r3\n";
1218 print STDOUT "$i1$origname$i2$origrest\n";
1219 printf STDERR "\n%03d directory renamed as " .
1220 "home_directory in \"$driver\" director.\n",
1221 ++$count;
1222 }
1223
1224 # This option has been renamed
1225
1226 elsif ($name eq "directory" && $driver_type eq "forwardfile")
1227 {
1228 $origname =~ s/directory/file_directory/;
1229 print STDOUT "# >> Option rewritten by convert4r3\n";
1230 print STDOUT "$i1$origname$i2$origrest\n";
1231 printf STDERR "\n%03d directory renamed as " .
1232 "file_directory in \"$driver\" director.\n",
1233 ++$count;
1234 }
1235
1236 # This option has been renamed
1237
1238 elsif ($name eq "forbid_filter_log" && $driver_type eq "forwardfile")
1239 {
1240 $origname =~ s/log/logwrite/;
1241 print STDOUT "# >> Option rewritten by convert4r3\n";
1242 print STDOUT "$i1$origname$i2$origrest\n";
1243 printf STDERR "\n%03d forbid_filter_log renamed as " .
1244 "forbid_filter_logwrite in \"$driver\" director.\n",
1245 ++$count;
1246 }
1247
1248 # This option has been renamed
1249
1250 elsif ($name eq "directory" && $driver_type eq "localuser")
1251 {
1252 $origname =~ s/directory/match_directory/;
1253 print STDOUT "# >> Option rewritten by convert4r3\n";
1254 print STDOUT "$i1$origname$i2$origrest\n";
1255 printf STDERR "\n%03d directory renamed as " .
1256 "match_directory in \"$driver\" director.\n",
1257 ++$count;
1258 }
1259
1260 # mx_domains_except (and old synonym non_mx_domains) are abolished
1261 # (both lookuphost router and smtp transport)
1262
1263 elsif ($name eq "mx_domains" ||
1264 $name eq "mx_domains_except" ||
1265 $name eq "non_mx_domains")
1266 {
1267 if ($seen_mx_domains) # If already done with these
1268 { # omit, and following blanks.
1269 $i = &skipblanks($i);
1270 next;
1271 }
1272 $seen_mx_domains = 1;
1273
1274 if (exists $o{"$prefix$driver.mx_domains_except"} ||
1275 exists $o{"$prefix$driver.non_mx_domains"})
1276 {
1277 $o{"$prefix$driver.mx_domains_except"} =
1278 &pair("$prefix$driver.mx_domains_except",
1279 "$prefix$driver.non_mx_domains");
1280
1281 &amalgamate("$prefix$driver.mx_domains",
1282 "$prefix$driver.mx_domains_except", "",
1283 "mx_domains", "+");
1284 }
1285 else
1286 {
1287 print STDOUT "$i1$origname$i2$origrest\n";
1288 }
1289 }
1290
1291 # This option has been renamed
1292
1293 elsif ($name eq "directory" && $driver_type eq "pipe")
1294 {
1295 $origname =~ s/directory/home_directory/;
1296 print STDOUT "# >> Option rewritten by convert4r3\n";
1297 print STDOUT "$i1$origname$i2$origrest\n";
1298 printf STDERR "\n%03d directory renamed as " .
1299 "home_directory in \"$driver\" director.\n",
1300 ++$count;
1301 }
1302
1303 # serialize_nets is abolished
1304
1305 elsif ($name eq "serialize_nets" ||
1306 $name eq "serialize_hosts")
1307 {
1308 if (!$seen_serialize)
1309 {
1310 &amalgamate("$prefix$driver.serialize_nets", "",
1311 "$prefix$driver.serialize_hosts", "serialize_hosts", "+");
1312 $seen_serialize = 1;
1313 }
1314 else
1315 {
1316 $i = &skipblanks($i);
1317 next;
1318 }
1319 }
1320
1321
1322 # Option not of interest; reproduce verbatim
1323
1324 else
1325 {
1326 print STDOUT "$i1$origname$i2$origrest\n";
1327 }
1328
1329
1330 $last_was_blank = 0;
1331 }
1332 }
1333 }
1334
1335 }
1336
1337 # Debugging: show the associative array
1338 # foreach $key (sort keys %o) { print STDERR "$key = $o{$key}\n"; }
1339
1340 print STDERR "\nEnd of configuration file conversion.\n";
1341 print STDERR "\n*******************************************************\n";
1342 print STDERR "***** Please review the generated file carefully. *****\n";
1343 print STDERR "*******************************************************\n\n";
1344
1345 print STDERR "In particular:\n\n";
1346
1347 print STDERR "(1) If you use regular expressions in any options that have\n";
1348 print STDERR " been rewritten by this script, they might have been put\n";
1349 print STDERR " inside quotes, when then were not previously quoted. This\n";
1350 print STDERR " means that any backslashes in them must now be escaped.\n\n";
1351
1352 print STDERR "(2) If your configuration refers to any external files that\n";
1353 print STDERR " contain lists of network addresses, check that the masks\n";
1354 print STDERR " are specified as single numbers, e.g. /24 and NOT as dotted\n";
1355 print STDERR " quads (e.g. 255.255.255.0) because Exim release 3.00 does\n";
1356 print STDERR " not recognize the dotted quad form.\n\n";
1357
1358 print STDERR "(3) If your configuration uses macros for lists of domains or\n";
1359 print STDERR " hosts or addresses, check to see if any of the references\n";
1360 print STDERR " have been negated. If so, you will have to rework things,\n";
1361 print STDERR " because the negation will apply only to the first item in\n";
1362 print STDERR " the macro-generated list.\n\n";
1363
1364 print STDERR "(4) If you do not generate deliveries to pipes, files, or\n";
1365 print STDERR " auto-replies in your aliasfile and forwardfile directors,\n";
1366 print STDERR " you can remove the added transport settings.\n\n";
1367
1368 # End of convert4r3