#! /usr/bin/perl
#line 2
use 5.010;
use strict;
use warnings;
use if $ENV{DEBUG}//'' eq 'vidns' => 'Smart::Comments';
use File::Temp;
use Getopt::Long;
use Pod::Usage;

use blib;
use DNS::Vi;

sub main {
    my %o = (
        key    => undef,
        server => undef,
	debug => undef,
    );

    GetOptions(
        'k|key=s'    => \$o{key},
        's|server=s' => \$o{server},
	'd|debug!'  => \$o{debug},
      )
      && @ARGV == 1
      or pod2usage();

    my @dig = (
        dig => 'AXFR',
        defined $o{key} ? (-k => $o{key}) : (),
        defined $o{server} ? ("\@$o{server}") : (),
        $ARGV[0]
    );

    my @zone1 = grep {
        not $_->{rrset}{rrtype} ~~
          [qw(RRSIG NSEC3 NSEC3PARAM NSEC DNSKEY TSIG)]
    } parse($_ = `@dig`) or die $_;

    my $tmp = File::Temp->new();
    $tmp->print(nice @zone1);
    $tmp->flush();
    system $ENV{EDITOR} // 'vi' => $tmp->filename;
    $tmp->seek(0, 0);
    my @zone2 = parse(<$tmp>);
    my ($add, $del) = delta(\@zone1, \@zone2);

    my @cmds = ((map { "update add $_" } @$add),
	       (map { "update delete $_" } @$del));

    print <<_EOF, join "\n" => @cmds, '';
# The following commands are about to be sent via nsupdate
# to the master server:
_EOF
print '# Please confirm (yes/no): ';
return 1 if <STDIN> ne "yes\n";

    my @nsupdate = ('nsupdate', defined $o{debug} ? ('-d') : (), defined $o{key} ? (-k => $o{key}) : ());
    open(my $nsupdate, '|-') or do {
	exec @nsupdate;
	die "Can't exec @nsupdate: $!\n";
    };
    print $nsupdate join "\n", @cmds, 'send', '';
    close($nsupdate);
    say "nsupdate returned $?";
    return 0;
}

exit main(@ARGV) if not caller;

__END__

=head1 NAME

 vidns -- editor for dynamically maintained zones

=head1 SYNOPSIS

 vidns [-k key] [-s server] [-d] <zone>

=head1 DESCRIPTION

=head1 PREREQUISITES

We need some tools to be installed:

=over

=item B<dig>

The domain information grabber is used for the zone transfer currently.

=item B<nsupdate>

The nsupdate tool is used to send the updates back to the server.

=back

=cut
