#!/usr/bin/perl

open (STDERR, ">&STDOUT");
select ((select(STDOUT), $| = 1)[0]); # Synchronize STDOUT
select ((select(STDERR), $| = 1)[0]); # with STDERR

($dns_lib = $0) =~ s:(^|/)[^/]*$::;
($script=$0) =~ s:^.*/([^/]*)$:$1:;	# Get the simple name of this script.

push (@INC, $dns_lib);

require 5.0;
require 'dns_lib.perl';

umask 0007;

use Getopt::Long;
$Getopt::Long::autoabbrev=1;    # Allow keyword abbreviations (to uniqueness).
$Getopt::Long::getopt_compat=1; # Allow both "--foo=bar" and "+foo=bar" style.
#$Getopt::Long::option_start='(--|-|\+)';       # [Use the defaults]
#$Getopt::Long::order=$Getopt::Long::REQUIRE_ORDER; # Options can't intermingle
$Getopt::Long::order=$Getopt::Long::PERMUTE;    # or options may intermingle.
$Getopt::Long::ignorecase=1;    # Don't consider case in options.
$Getopt::Long::debug=0;         ### Debug ###

$opt_help = ($#ARGV < 0);

&GetOptions ('help', 'f', 'soa!', 'zone=s') || die "Try $script --help for more information.\n";

if (($opt_help) || ($#ARGV >= 0)) { 
 
    print <<"EndOfHelp";
Usage: $script [OPTION]
 
  --help      This info
  --f         Force the action
  --nosoa     No new SOA record for this zone
  --soa       New SOA record for this zone
  --zone=x    Zone to be primary for
 
You must set zone and eiter soa or nosoa.

EndOfHelp
    
    exit;

} # End if - help

die "\nNot enough arguments.\n\nTry: $script --help for more information.\n\n" unless (defined ($opt_zone) && defined ($opt_soa));

$zone = $opt_zone;

if ($zone =~ m/^(\d+\.)*\d+(\.in-addr\.arpa\.?)?$/o) {

    $zone = &verify_subnet ($zone, '');
    $zone = &reverse_ip ($zone) unless $zone =~ m/\.in-addr\.arpa\.?$/o;

} else {

    $zone = &verify_name ($zone, '');

}
 
($old_host, $old_zone) = split ('\.', $zone, 2);

if ((($x = &verify_zone ($old_zone)) eq 'PRIMARY') || ($x eq 'SEC_W_GLUE')) {
    
    @file = &read_file ($old_zone, '.primary');
    @recs = &find_record (&build_record ($old_host, '', '', ''), @file);

    if (($#recs >= 0) && (! defined ($opt_f))) {

	die "\nError: Existing data for $old_host in $old_zone\n\nUse the --f option to move the data to the new .primary file\n\n";

    }
    
}

@dirs = reverse (split ('\.', lc($zone)));
$path = '/';
$rebuild = 0;

&rcs_co ('', '.zoneinfo');
open (ZONEINFO, ">>$tree_root/.zoneinfo") || die "Can't open $tree_root/.zoneinfo: $!\n";

foreach $dir (@dirs) {

    $path .= "$dir/";
    
    if (-e $tree_root.$path) {
	
	if (! -d _) {

	    die "$tree_root$path is not a directory.\n";

	}

    } elsif (mkdir ($tree_root.$path, 0770)) {

	mkdir ($tree_root.$path.'RCS', 0770) || warn "Couldn't create RCS directory in $dir.  $!\n";
	print ZONEINFO join ('.', reverse (split ('/', $path))),"\n";
	$rebuild = 1;

    } else {

	die "$tree_root$path is not a directory and could not be created.\n";
   
    }

}

close (ZONEINFO);
$path = $tree_root.$path;
system "$build_class" if $rebuild;
&rcs_ci ('', '.zoneinfo', "Script $script: added $zone");
open (ZONEINFO, "$tree_root/.zoneinfo") || die "Can't open $tree_root/.zoneinfo: $!\n";

while (<ZONEINFO>) {

    if (m/^$zone\.*\s+(\S+)/o) {

	$class = $1;
	last;

    }

}

close ZONEINFO;

if (! defined ($class)) {

    die "Couldn't get class associated with $zone\n";

}


if ((-e "$path.secondary") && (! defined ($opt_f))){

    die "We are currently secondary for $zone\n\nUse the --f option to remove the .secondary file and become primary for $zone\nUse --f --nosoa to add a .primary file for glue purposes\n" if $opt_soa == 1;
    die "We are currently secondary for $zone\n\nUse the --f option to add a .primary file for glue purposes\n" if $opt_soa == 0;

} elsif (-e "$path.soa") {

    die "We are already primary for $zone.\n";

} elsif (-e "$path.primary") {

    die "We are already primary for $zone (SOA is in a parent zone).\n";

} else {

    if ((-e "$path.secondary") && (defined ($opt_f)) && ($opt_soa == 1)) {

	print "Trashing .secondary (RCS backup will remain)...\n\n";
	unlink "$path.secondary";

    }

    open (PRIMARY, ">$path.primary") || die "Cannot create $path.primary: $!\n";

    if ($opt_soa == 1) {

	if ($class eq 'campus') {

	    print PRIMARY &build_record ('@', 'NS', $campus_ns_1, '');
	    print PRIMARY &build_record ('@', 'NS', $campus_ns_2, '');

	} else {

	    print PRIMARY &build_record ('@', 'NS', $default_ns_1, '');
	    print PRIMARY &build_record ('@', 'NS', $default_ns_2, '');

	}

    }

    if ($#recs >= 0) {

	&rcs_co ($old_zone, '.primary');

	print "Moving $old_host RRs to new .primary file... ";
	foreach (@recs) {

	    ($result, @file) = &remove_record ($_, @file);
	    s/$old_host/@/;
	    print PRIMARY $_;

	}

	&write_file ($old_zone, '.primary', @file);
	&rcs_ci ($old_zone, '.primary', "Script $script: Moved $old_host RRs to $zone");

	print "Done.\n";

    }

    close PRIMARY;
    rcs_new_ci ("$path.primary", "Script $script: Primary data for $zone");

    if ($opt_soa == 1) {

	open (SOA, ">$path.soa") || die "Cannot create $path.soa: $!\n";
	print SOA "@\t\tIN\tSOA\t$soa_creation_host $soa_email (\n\t\t\t\t$soa_serial\t\t; $soa_serial_comment\n\t\t\t\t$soa_refresh\t\t; $soa_refresh_comment\n\t\t\t\t$soa_retry\t\t; $soa_retry_comment\n\t\t\t\t$soa_expire\t\t; $soa_expire_comment\n\t\t\t\t$soa_ttl )\t; $soa_ttl_comment\n";
	close SOA;
	rcs_new_ci ("$path.soa", "SOA record for $zone");
	open (REBUILD, ">$tree_root/.rebuild") || die "Cannot create .rebuild file: $!\n";
	close (REBUILD);
	
    }

    print "We are now primary for $zone\n";
    print "\nNOTE: No new SOA record was created.\nMake sure there is an SOA record in a parent zone or the data will not be served.\n\n" if $opt_soa == 0;

}

exit;
