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