chiark / gitweb /
Bugfixes. foreign group.
[chiark-utils.git] / scripts / named-conf
index 39bee7f9ae35c2e949077549ae752c91845b5221..50b7945fb67965fa406df33cd5622322799c4198 100755 (executable)
@@ -6,7 +6,7 @@ use Data::Dumper;
 use POSIX;
 use Fcntl qw(:DEFAULT :flock);
 
-use vars qw($quis
+use vars qw($quis $stdout_fh $stderr_fh
            $mode $doall $domail
            $etcfile $where
            $debug $needglue $localonly $repeat $verbosity
@@ -27,10 +27,14 @@ $verbosity= 2;
 $admin=''; $mail_state_dir=''; $mail_max_warnfreq= 50;
 $repeat= 0;
 $domail= '';
-$progress_fh= 'STDOUT';
-$warn_fh= 'STDERR';
 $modifiers= '';
+$group2modcmd{'foreign'}= '*$!@?';
+$group2used{'foreign'}= 1;
 
+($progress_fh= $stdout_fh= new_from_fd IO::Handle(1,'w') and
+ $warn_fh= $stderr_fh = new_from_fd IO::Handle(2,'w'))
+    or die "$quis: setup standard filehandles: $!\n";
+    
 use vars qw($dig_owner $dig_type $dig_rdata);
 
 while (@ARGV && $ARGV[0] =~ m/^\-/) {
@@ -39,7 +43,7 @@ while (@ARGV && $ARGV[0] =~ m/^\-/) {
        last if m/^$/;
        if (m/^(yes|no|force)$/) { m/^./; $mode= $&; $domail=''; }
        elsif (m/^nothing$/) { $mode= 'x'; $domail=''; }
-       elsif (m/^mail\-(first|middle|final|final-test)/) {
+       elsif (m/^mail\-(first|middle|final|final\-test)$/) {
            $mode='n';
            $domail=$1;
        }
@@ -81,7 +85,7 @@ usageerr("-q may be specified at most twice") if $verbosity<0;
 usageerr("-v may be specified at most once") if $verbosity>3;
 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;
+    if !!$mode == !!@ARGV && !$domail;
 
 sub usageerr ($) {
     die <<END;
@@ -141,10 +145,12 @@ $install= $mode =~ m/^[yf]/;
 
 read_config($etcfile);
 debug_dump('@zone_cfg_list %zone_cfg');
-process_zones($mode ? @zone_cfg_list : @ARGV);
+process_zones($mode && !$domail ? @zone_cfg_list : @ARGV);
 debug_dump('%output_contents');
 output_files() if $install;
 
+$stdout_fh->close or die "$quis: write messages to stdout: $!\n";
+$stderr_fh->close or die "$quis: write messages to stderr: $!\n";
 exit 0;
 
 #-------------------- configuration reading
@@ -270,7 +276,7 @@ sub bad_modifiers ($) {
     local ($_) = @_;
     if (!eval {
        die "bad modifier $&" if m/[^!*\$\@~?]/;
-       die "repeated modifier $1" if m/(.).*$1/;
+       die "repeated modifier $1" if m/(.).*\1/;
        1;
     }) {
        $@ =~ s/\n//;
@@ -314,7 +320,7 @@ sub zone_conf ($$$$$@) {
        $zone_cfg{$zone}{$sfx}= $aref;
     }
     foreach $sfx (qw(self_soa self_ns)) {
-       $zone_cfg{$zone}{$sfx} =~ s/\*$/$zone/;
+       map { s/\*$/$zone/ } @{ $zone_cfg{$zone}{$sfx} };
     }
     $zone_cfg{$zone}{'output'}= $output;
     push @zone_cfg_list, $zone;
@@ -346,11 +352,12 @@ sub process_zones (@) {
     foreach $zone (@zones) {
        $cfg= $zone_cfg{$zone} || {
            'style_p' => 'foreign',
-           's' => 'f',
+           's' => "f $group2modcmd{'foreign'}",
            'servers' => [ ],
            };
 
-       mail_zone_before() if $domail;
+       mail_zone_before() or next
+           if $domail;
        zone_reset();
        progress(1, sprintf "%-20s %s", $zone, $$cfg{'style_p'});
        if ($check && ($doall || !zone_style('?',0))) {
@@ -700,14 +707,14 @@ sub mail_zone_before () {
 
     for (;;) {
        $m_lock= new IO::File "${m_base}_lock", O_RDWR|O_CREAT, 0600
-           or die "$quis: create lockfile ${m_base}_lock";
+           or die "$quis: create lockfile ${m_base}_lock: $!\n";
        if (!flock($m_lock, LOCK_EX|LOCK_NB)) {
            <$m_lock> =~ m/^\d+ /;
            die "$quis: $zone: concurrrency? - flock $&$!\n";
            $m_lock->close;
-           next;
+           return 0;
        }
-       (@s1= $m_lock->fstat) or die "$quis: fstat ${m_base}_lock: $!\n";
+       (@s1= $m_lock->stat) or die "$quis: fstat ${m_base}_lock: $!\n";
        (@s2= stat "${m_base}_lock") or
            die "$quis: stat ${m_base}_lock: $!\n";
        last if ($s1[0] eq $s2[0] && $s1[1] eq $s2[1]);
@@ -726,17 +733,17 @@ sub mail_zone_before () {
            if ($2 eq ':' && $3 eq ':') {
                warn "$quis: $zone: mid/last run, but last".
                    "run already done, ignoring zone\n";
-               next;
+               return 0;
            }
            @m_ok= split /\:/, $2;
            @m_fail= split /\:/, $3;
        }
     } elsif ($! != &ENOENT) {
        die "$quis: open ${m_base}_info: $!\n";
-    } elsif ($domail eq 'first') {
+    } elsif ($domail ne 'first') {
        warn "$quis: $zone: first run, but not --mail-first,".
            " ignoring zone\n";
-       next;
+       return 0;
     }
     if ($domail eq 'first') {
        remove "${m_base}_history" or $!==&ENOENT
@@ -749,6 +756,7 @@ sub mail_zone_before () {
 
     $m_time= time;
     progress(-1, "\n".('-'x70)."\n".ptime($m_time)."\n");
+    return 1;
 }
 
 sub mail_zone_after () {
@@ -761,13 +769,13 @@ sub mail_zone_after () {
        progress(-1,"everything is fine");
     }
     close $progress_fh or die "$quis: close ${m_base}_history: $!\n";
-    $progress_fh= $warn_fh= 'STDERR';
+    $progress_fh= $warn_fh= $stderr_fh;
 
     if ($domail =~ m/^final/) {
        if (100*@m_fail <= $$cfg{'mailmwarn'}*(@m_fail + @m_ok)) {
-           printf " %-40s ok\n" or die "$quis: mail ok report: $!\n";
+           printf " %-40s ok\n", $zone or die "$quis: mail ok report: $!\n";
        } elsif (zone_style('@',0)) {
-           printf " %-40s mail suppressed\n"
+           printf " %-40s mail suppressed\n", $zone
                or die "$quis: mail suppress report: $!\n";
        } else {
            mail_zone_mail();
@@ -797,15 +805,15 @@ sub ptime ($) {
 }
 
 sub mail_zone_mail () {
-    my ($log, $zone_to, $zterr, $c, $r, $t);
+    my ($log, $zone_to, $zterr, $c, $r, $t, @soas);
     $m_m= new IO::File "${m_base}_mail", 'w', 0666
        or die "$quis: create ${m_base}_mail: $!\n";
     $zone_to=''; $zterr='';
-    if (!zone_style("\$",$$cfg{'s'} =~ m/u/)) {
+    if (!zone_style("\$", $$cfg{'s'} !~ m/[ps]/)) {
        eval {
-           $_= lookup($zone,'soa','0','problem-addr');
-           m/\n\n/ and die "multiple soas\n";
-           m/^\S+ (\S.*\@\S+) [0-9 ]+$/ or
+           ($r,@soas)= lookup($zone,'soa','0','problem-addr');
+           @soas==1 or die "multiple soas\n";
+           $soas[0] =~ m/^\S+ (\S.*\@\S+) [0-9 ]+$/ or
                die "bad soa \`$_'\n";
            $zone_to= $1;
        };
@@ -813,7 +821,7 @@ sub mail_zone_mail () {
        $zterr =~ s/\n$//;
     }
     pmail <<END
-From: zone check system <$$cfg{'admin'}>
+From: zone checker <$$cfg{'admin'}>
 Subject: $zone - configuration problems report
 END
 ;
@@ -842,7 +850,7 @@ if length $zterr;
 The zone has had configuration errors or persistent operational
 problems during recent checks.  See the logs below for details.
 
-Check history for $zone:
+Recent check history for $zone:
 END
 ;
     if ($m_lastok ne '-') {
@@ -851,7 +859,7 @@ END
        pmail(" No record of this zone ever being fine.\n");
     }
     for $t (@m_fail) {
-       pmail(" Errors/warnings at: ".ptime($t)."\n");
+       pmail(" Zone had problems at: ".ptime($t)."\n");
     }
     for $t (@m_ok) {
        pmail(" Everything in order at: ".ptime($t)."\n");
@@ -860,18 +868,20 @@ END
     $log= new IO::File "${m_base}_history",'r'
        or die "$quis: reopen ${m_base}_history: $!";
     undef $/;
-    pmail($log);
+    pmail($log->getline);
     $/= "\n";
-    $log->error && $log->close
-       or die "$quis: reread or close ${m_base}_log: $!";
+    (!$log->error and $log->close)
+       or die "$quis: reread or close ${m_base}_log: $!\n";
+    $log->eof or die;
     $m_m->close or die "$quis: close ${m_base}_mail: $!\n";
     $m_m= new IO::File "${m_base}_mail"
        or die "$quis: reopen ${m_base}_mail: $!";
 
     defined($c= fork) or die "$quis: fork for mail: $!\n";
     if (!$c) {
-       open STDIN, "<& ${m_m}" or die "$quis - sendmail: dup for stdin: $!\n";
-       exec (qw(/usr/sbin/sendmail -odq -oee -oi),
+       defined dup2($m_m->fileno, 0)
+           or die "$quis - sendmail: dup for stdin: $!\n";
+       exec (qw(/usr/sbin/sendmail -odb -oee -oi),
              ($domail eq 'final' ? '-t' : $$cfg{'admin'}));
        die "$quis - sendmail: exec: $!\n";
     }