chiark / gitweb /
Fix bugs.
[chiark-utils.git] / scripts / named-conf
index 5fafeec..b6d0c0c 100755 (executable)
@@ -4,15 +4,17 @@ use strict;
 use IO::File;
 use Data::Dumper;
 
-use vars qw($mode
+use vars qw($quis $mode
            $etcfile $where
            $debug $needglue $localonly $verbosity);
 
+$quis= $0; $quis =~ s,.*/,,;
+
 $mode= '';
 $etcfile= "/etc/bind/chiark-conf-gen.zones";
 $where= '<built-in>';
 $debug= 0;
-$needglue= 1;
+$needglue= 2;
 $localonly= 0;
 $verbosity= 1;
 
@@ -24,7 +26,7 @@ while (@ARGV && $ARGV[0] =~ m/^\-/) {
        last if m/^$/;
        if (m/^(yes|no|force)$/) { m/^./; $mode= $&; }
        elsif (m/^config$/) { $etcfile= loarg(); $where= '--config option'; }
-       elsif (m/^glueless$/) { $needglue=0; }
+       elsif (m/^glueless$/) { $needglue--; }
        elsif (m/^localonly$/) { $localonly=1; }
        elsif (m/^quiet$/) { $verbosity=0; }
        elsif (m/^verbose$/) { $verbosity=2; }
@@ -36,7 +38,7 @@ while (@ARGV && $ARGV[0] =~ m/^\-/) {
            if (s/^[ynf]//) { $mode=$&; }
            elsif (s/^C//) { $etcfile= soarg(); $where= '-C option'; }
            elsif (s/^D//) { $debug++; }
-           elsif (s/^g//) { $needglue=0; }
+           elsif (s/^g//) { $needglue--; }
            elsif (s/^l//) { $localonly=1; }
            elsif (s/^q//) { $verbosity=0; }
            elsif (s/^v//) { $verbosity=2; }
@@ -48,6 +50,8 @@ while (@ARGV && $ARGV[0] =~ m/^\-/) {
 sub loarg() { usageerr("missing option value") if !@ARGV; return shift @ARGV; }
 sub soarg() { my ($rv); $rv=$_; $_=''; return length $rv ? $rv : loarg(); }
 
+usageerr("-g may be specified at most twice") if $needglue<0;
+usageerr("-D may be specified at most twice") if $debug>2;
 usageerr("must specify either -f|-y|-n or zones (and not both)")
     if !!$mode == !!@ARGV;
 
@@ -97,10 +101,11 @@ debug_dump('@zone_cfg_list %zone_cfg');
 process_zones($mode ? @zone_cfg_list : @ARGV);
 debug_dump('%output_contents');
 
+exit 0;
 
 #-------------------- configuration reading
 
-sub cfg_fail ($) { die "$0: $where:\n $_[0]\n"; }
+sub cfg_fail ($) { die "$quis: $where:\n $_[0]\n"; }
 
 sub read_config ($) {
     my ($if) = @_;
@@ -122,12 +127,13 @@ sub read_config ($) {
            @self= split /\s+/, $2;
            @self_ns= @self if $1 ne '-soa';
            @self_soa= @self if $1 ne '-ns';
-       } elsif (m/^primary\-dir\s+(\S+)((?:\s+(\S+))??:\s+(\S+))?$/) {
+       } elsif (m/^primary\-dir\s+(\S+)((?:\s+(\S+))?:\s+(\S+))?$/) {
            ($dir, $prefix, $suffix) = (qualify($1),$2,$3);
-           $suffix= '_db' if !length $suffix;
+           $suffix= '_db' if !defined $suffix;
+           $prefix= '' if !defined $prefix;
            opendir D, $dir or cfg_fail("open primary-dir $dir:\n $!");
            $lprefix= length $prefix; $lsuffix= length $suffix;
-           while ($!=0, $_= readdir D) {
+           while (defined($_= readdir D)) {
                next if m/^\./ && !$lprefix;
                next unless length > $lprefix+$lsuffix;
                next unless substr($_,0,$lprefix) eq $prefix;
@@ -135,7 +141,6 @@ sub read_config ($) {
                $z= substr($_,$lprefix,length($_)-($lprefix+$lsuffix));
                zone_conf($z,'primary',"$dir/$_");
            }
-           $! and cfg_fail("read primary-dir $dir:\n $!");
            closedir D or cfg_fail("close primary-dir $dir:\n $!");
        } elsif (m/^primary\s+(\S+)\s+(\S+)$/) {
            zone_conf($1,'primary',qualify($2));
@@ -143,7 +148,7 @@ sub read_config ($) {
            zone_conf($1,'secondary','',$2);
        } elsif (m/^stealth\s+(\S+)\s+([0-9. \t]+)$/) {
            zone_conf($1,'stealth','',split /\s+/, $2);
-       } elsif (m/^slave\-dir\s+(\S+)((?:\s+(\S+))??:\s+(\S+))?$/) {
+       } elsif (m/^slave\-dir\s+(\S+)((?:\s+(\S+))?:\s+(\S+))?$/) {
            ($slave_dir, $slave_prefix, $slave_suffix) = (qualify($1),$2,$3);
        } elsif (m/^output\s+bind8\+(\S+)$/) {
            cfg_fail("default output may not apply to only some zones")
@@ -162,6 +167,7 @@ sub read_config ($) {
 sub qualify ($) {
     my ($i) = @_;
     $i= "$default_dir/$i" unless $i =~ m,^/,;
+    return $i;
 }
 
 sub zone_conf ($$@) {
@@ -229,6 +235,8 @@ sub process_zones (@) {
        }
        zone_output() if $install;
     }
+    print STDERR "$quis: $warnings warnings\n" or die $!
+       if $warnings;
 }
 
 sub zone_warning ($) {
@@ -247,7 +255,7 @@ use vars qw(%delgs); # $delgs{$nameserver_list} = [ $whosaidandwhy ]
 use vars qw(%auths); # $auths{$nameserver_list} = [ $whosaidandwhy ]
 use vars qw(%glue);  # $glue{$name}{$addr_list} = [ $whosaidandwhy ]
 use vars qw(%soas);  # $soa{"$origin $serial"} = [ $whosaidandwhy ]
-use vars qw(%addr_is_ok);
+use vars qw(%addr_is_ok %gluelesswarned);
 use vars qw(@to_check); # ($addr,$whyask,$is_auth,$glueless_ok, ...)
 use vars qw(@to_check_soa); # ($addr,$whyask, ...)
 
@@ -259,7 +267,7 @@ sub zone_check_full () {
 }
 
 sub zone_reset() {
-    %delgs= %auths= %glue= %soas= %addr_is_ok= ();
+    %delgs= %auths= %glue= %soas= %gluelesswarned= %addr_is_ok= ();
     @to_check= @to_check_soa= ();
 }
 
@@ -329,8 +337,11 @@ sub zone_check_nsrrset ($$$$) {
     foreach $s (@s) {
        @glue= @{ $s2g{$s} };
        if (!@glue) {
-           zone_warning("glueless NS $s, from $ww")
-               unless $glueless_ok || !$needglue;
+           zone_warning("glueless NS $s,".
+                        ($needglue<=1 ? " (eg)" : "").
+                        " from $ww")
+               unless $glueless_ok || !$needglue ||
+                      ($needglue<=1 && $gluelesswarned{$s}++);
            next;
        }
        $glue= join ' ', sort @glue;
@@ -479,17 +490,17 @@ sub lookup ($$$) {
     debug_trace("lookup ==> (->$okrcodes) $domain $type");
     $h= new IO::Handle;
 
-    defined($c= open $h, "-|") or die "$0: fork adnshost:\n $!\n";
+    defined($c= open $h, "-|") or die "$quis: fork adnshost:\n $!\n";
     if (!$c) {
        exec 'adnshost','-Fi','+Do','+Dt','+Dc','-Cf',"-t$type",
             '-',"$domain.";
-       die "$0: exec adnshost:\n $!\n";
+       die "$quis: exec adnshost:\n $!\n";
     }
     @result= $h->getlines();
-    $h->error and die "$0: read from adnshost:\n $!\n";
+    $h->error and die "$quis: read from adnshost:\n $!\n";
     chomp @result;
     $!=0; $h->close;
-    die "$0: lookup -t$type $domain $okrcodes failed $? $!\n"
+    die "$quis: lookup -t$type $domain $okrcodes failed $? $!\n"
        if $! or $?>6 or index($okrcodes,$?)<0;
     debug_trace("lookup <== $? @result");
     return ($?,@result);
@@ -505,18 +516,18 @@ sub dig (&$$$) {
     debug_trace("dig ==> \@$qaddr $qowner $qtype");
 
     $h= new IO::Handle;
-    defined($c= open $h, "-|") or die "$0: fork dig:\n $!\n";
+    defined($c= open $h, "-|") or die "$quis: fork dig:\n $!\n";
     if (!$c) {
        open STDERR, ">&STDOUT" or die $!;
        exec ('dig',
              '+nodef','+nosea','+nodebug','+norecurse',
              "\@$qaddr",'-t',$qtype,$qowner);
-       die "$0: exec dig:\n $!\n";
+       die "$quis: exec dig:\n $!\n";
     }
     $inmid='';
     for (;;) {
        if (!defined($_= $h->getline())) {
-           $h->error() and die "$0: read from dig:\n $!\n";
+           $h->error() and die "$quis: read from dig:\n $!\n";
            last;
        }
        chomp;
@@ -575,7 +586,7 @@ __DATA__
 sub lookup1 ($$) {
     my ($type,$domain) = @_;
     my (@result)= lookup($type,$domain);
-    @result==1 or die "$0: lookup -t$type $domain gave more than one RR\n";
+    @result==1 or die "$quis: lookup -t$type $domain gave more than one RR\n";
     return $result[0];
 }
 
@@ -624,7 +635,7 @@ sub check () {
        for $super_ns (@super_ns) {
            @deleg_ns= ();
            open DIG, "dig @$super_ns. -t ns +norecurse $zone."
-               or die "$0: fork for dig:\n $!\n";
+               or die "$quis: fork for dig:\n $!\n";
            while (<DIG>) {
                
 
@@ -700,7 +711,7 @@ done
 endfile
 
     
-chdir "$base/primary" or die "$0: chdir $base/primary:\n $!";
+chdir "$base/primary" or die "$quis: chdir $base/primary:\n $!";
 beginfile('primary.zones');
 
 for $f (<*_db>) {
@@ -719,19 +730,19 @@ endfile
 sub beginfile ($) {
     $currentfile= $_[0];
     $currentfile_opened= $install ? "$conf/$currentfile.new" : "/dev/null";
-    open CFF, "> $toopen" or die "$0: begin $currentfile_opened:\n $!\n";
+    open CFF, "> $toopen" or die "$quis: begin $currentfile_opened:\n $!\n";
 }
 
 endfile () {
-    close CFF or die "$0: close $currentfile_opened:\n $!\n";
+    close CFF or die "$quis: close $currentfile_opened:\n $!\n";
     push @files, $currentfile;
 }
 
 sub installfiles () {
     return unless $install;
-    chdir $conf or die "$0: chdir $conf:\n $!\n";
+    chdir $conf or die "$quis: chdir $conf:\n $!\n";
     for $f (@files) {
-       rename "$f.new", $f or die "$0: install new $f:\n $!\n";
+       rename "$f.new", $f or die "$quis: install new $f:\n $!\n";
     }
 }