safer coding of router toplevel
[exim.git] / src / util / mkcdb.pl
1 #!/usr/bin/perl -wT
2 # Copyright (c) The Exim Maintainers 2022
3 # SPDX-License-Identifier: GPL-2.0-or-later
4 #
5 # Create cdb file from flat alias file. DPC: 15/10/98.
6 # Args:      source  (may be relative or absolute)
7 #            target  (may be relative or absolute. Default = source)
8 # Generates: target.cdb
9 #            target.tmp
10 #
11 # Little Perl script to convert flat file into CDB file. Two advantages over
12 # cdbmake-12 awk script that is distributed with CDB:
13 #  1) Handles 'dpc22:dpc22@hermes' as well as 'dpc22 dpc22@hermes'
14 #  2) Perl works with arbitrary length strings: awk chokes at 1,024 chars
15 #
16 # Cambridge: hermes/src/admin/mkcdb,v 1.9 2005/02/15 18:14:12 fanf2 Exp
17
18 use strict;
19
20 BEGIN { pop @INC if $INC[-1] eq '.' };
21 $ENV{'PATH'} = "";
22 umask(022);
23
24 my $CDB = '/opt/cdb/bin/cdbmake';
25
26 my $prog = $0;
27 $prog =~ s|(.*/)?([^/]+)|$2|;
28
29 my $source;
30 my $target;
31 if (@ARGV == 1) {
32     $source = shift(@ARGV);
33     $target = $source;
34 } elsif (@ARGV == 2) {
35     $source = shift(@ARGV);
36     $target = shift(@ARGV);
37 } else {
38     die("$prog: usage: <source> [<target>]\n");
39 }
40 # trust the invoker ?!
41 $source =~ /(.*)/;
42 $source = $1;
43 $target =~ /(.*)/;
44 $target = $1;
45
46 open(SOURCE, "< ${source}")
47     or die("$prog: open < $source: $!\n");
48
49 open(PIPE, "| $CDB $target.cdb $target.tmp")
50     or die("$prog: open | $CDB $target: $!\n");
51
52 sub add_item ($$) {
53     my $key = shift;
54     my $val = shift;
55     printf PIPE ("+%d,%d:%s->%s\n", length($key), length($val), $key, $val);
56 }
57
58 sub add_line ($) {
59     my $line = shift;
60     if ($line =~ /^([^\s:]+)\s*:\s*(.*)$/s) {   # key : values
61         add_item($1,$2);
62         return;
63     }
64     if ($line =~ /^(\S+)\s+(.*)$/s) {       # key: values
65         add_item($1,$2);
66         return;
67     }
68     if ($line =~ /^(\S+)$/s) {              # key (empty value)
69         add_item($1,'');
70         return;
71     }
72     warn "$prog: unrecognized item: $line";
73 }
74
75 my $data;
76 while(<SOURCE>) {
77     next if /^#/ or /^\s*$/;
78     m/^(\s*)(\S.*)\s+$/s;
79     if (length($1) == 0) {
80             add_line($data) if defined $data;
81             $data = $2;
82     } else {
83             $data .= " $2";
84     }
85 }
86 add_line($data) if defined $data;
87 print PIPE "\n";
88
89 close(SOURCE)
90     or die("$prog: close < $source: $!\n");
91 close(PIPE)
92     or die($! ? "$prog: close | $CDB $target: $!\n"
93            : "$prog: close | $CDB $target: exited $?\n");
94
95 exit 0;