#!/usr/local/bin/perl

$exit = 0;
$status = 0;

&set_date;

$dir_base = "/var/named";
$dir_bin = "$dir_base/bin";
$dir_temp = "$dir_base/namedb-temp";
$dir_roots = "$dir_base/namedb-root";
$dir_real = "$dir_base/namedb";

$file_opennic_serial = "$dir_bin/opennic.serial";

&set_serial;

$token_serial = "#SERIAL#";

$file_tlds = "$dir_bin/opennic.tlds";
$file_opennic_header = "$dir_bin/opennic.header";
$file_opennic_servers = "$dir_bin/opennic.servers";
$file_alternic_tlds = "$dir_bin/alternic.tlds";
$file_alternic_servers = "$dir_bin/alternic.servers";
$file_pacroot_tlds = "$dir_bin/pacroot.tlds";
$file_pacroot_servers = "$dir_bin/pacroot.servers";

$file_rootzone = "root.zone";
$file_download = "$dir_temp/$file_rootzone.gz";

$file_in = sprintf("$dir_temp/tld-root-%s", $serial);
$file_out = sprintf("$dir_roots/tld-root-%s", $serial);
$file_final = "$dir_real/tld-root";


$url_zone = "ftp://rs.internic.net/domain/root.zone.gz";

$cmd_transfer = "/usr/local/bin/wget -q --output-document=$file_download $url_zone";
$cmd_gunzip = "/usr/bin/gunzip";
$cmd_mv = "/bin/mv";
$cmd_cp = "/bin/cp";
$cmd_test = "/bin/ps -ax | /usr/bin/grep \"/usr/sbin/named\" | /usr/bin/grep -v \"grep\" | /usr/bin/awk '{print \$1, \$5}'";
$cmd_hup = "kill -HUP";

%exists =
{
	-18 , "could not open PacRoot TLD file",
	-17 , "could not open PacRoot data file",
	-16 , "could not open AlterNIC TLD file",
	-15 , "could not open AlterNIC data file",
	-14 , "could not move ICANN root.zone file",
	-13 , "could not gunzip ICANN root.zone file",
	-12 , "could not open OpenNIC serial file",
	-11 , "found OpenNIC TLD in INCANN data",
	-10 , "could not open OpenNIC TLD file",
	-9 , "failed to install final file",
	-8 , "failed to \"kill -HUP\" named process",
	-7 , "too many \"/usr/sbin/named\" processes",
	-6 , "could not open OpenNIC data file",
	-5 , "could not open OpenNIC header file",
	-4 , "could not open input file",
	-3 , "could not open output file",
	-2 , "test command failed",
	-1 , "could not transfer",
	0 , "success",
};

if(open(OPENNIC, "<$file_tlds"))
{
	$index = 0;
	while($txtline = <OPENNIC>)
	{
		if("" ne $txtline)
		{
			$txtline =~ s/\n$//;
			$tlds_opennic[$index] = $txtline;
			$index ++;
		}
	}
	
	close(OPENNIC);
}
else
{
	$exit = -10;
	print "ERROR($exit:$status): $exits{$exit}: $!\n";
	die $exit;
}

$status = (system "$cmd_transfer");

if(0 == $status)
{
	$status = (system "$cmd_gunzip $file_download");
	
	if(0 == $status)
	{
		$status = (system "$cmd_mv $dir_temp/$file_rootzone $file_in");
	
		if(0 != $status)
		{
			$exit = -14;
			print "ERROR($exit:$status): $exits{$exit}: $!\n";
			die $exit;
		}
	}
	else
	{
		$exit = -13;
		print "ERROR($exit:$status): $exits{$exit}: $!\n";
		die $exit;
	}
}
else
{
	$exit = -1;
	print "ERROR($exit:$status): $exits{$exit}: $!\n";
	die $exit;
}

if(open(OUTFILE, ">$file_out"))
{
	$insoa = "false";
	$first_RR = 0;
	$first_norm = 0;
	print OUTFILE ";begin ICANN header\n";

	if(open(INFILE, "<$file_in"))
	{
		while($txtline = <INFILE>)
		{
			#check for attempts to overwrite our TLDs
			foreach $thing (@tlds_opennic)
			{
				if($txtline =~ m/$thing\./)
				{
					$exit = -11;
					print "ERROR($exit:$status): $exits{$exit}: $!\n";
					die $exit;
				}
			}
		
			@txtline_split = split(//, $txtline);
			
			if(";" eq $txtline_split[0])
			{
				#it's just a comment line
				print OUTFILE $txtline;
			}
			elsif("true" eq $insoa)
			{
				if(-1 != (index($txtline, ")")))
				{
					#it's the SOA record last line
					print OUTFILE "; $txtline";
					$insoa = "false";
					
					print OUTFILE "\n;end ICANN header\n\n";
					
					&print_opennic_header;
				}
				else
				{
					#it's a normal SOA record line
					print OUTFILE "; $txtline";
				}
			}
			elsif($txtline_split[0] =~ m/^\s/)
			{
				#it's just an empty line
				print OUTFILE $txtline;
			}
			else
			{
				if(-1 != (index($txtline, "(")))
				{
					#it's the SOA record first line
					print OUTFILE "; $txtline";
					$insoa = "true";
				}
				elsif($txtline_split[0] =~ m/^\./)
				{
					#it's an RR NS line
					if(0 == $first_RR)
					{
						print OUTFILE ";begin ICANN root pointers\n\n";
						print OUTFILE "; $txtline";
						
						$first_RR ++;
					}
					else
					{
						#it's an ICANN RR NS line
						print OUTFILE "; $txtline";
					}
				}
				else
				{
					#it's an ICANN data line
					if(0 == $first_norm)
					{
						print OUTFILE "\n;end ICANN root pointers\n\n";
						
						&print_opennic_rootrr;
						
						&print_opennic_data;
						&print_alternic_data;
						&print_pacroot_data;
						
						print OUTFILE ";begin ICANN data\n\n";
						print OUTFILE $txtline;
						
						$first_norm ++;
					}
					else
					{
						#it's an ICANN data line
						print OUTFILE $txtline;
					}
				}
			}
		}
		
		close(INFILE);
	}
	else
	{
		$exit = -4;
		print "ERROR($exit:$status): $exits{$exit}: $!\n";
		die $exit;
	}
	
	print OUTFILE "\n;end ICANN data\n";
	
	close(OUTFILE);
}
else
{
	$exit = -3;
	print "ERROR($exit:$status): $exits{$exit}: $!\n";
	die $exit;
}

if(0 != (system "$cmd_cp $file_out $file_final"))
	{
		$exit = -9;
		print "ERROR($exit:$status): $exits{$exit}: $!\n";
		die $exit;
	}

if(open(PSTEST, "$cmd_test|"))
{
	$loops = 0;
	while($txtline = <PSTEST>)
	{
		@temp = split(/\s/, $txtline);
		$loops ++;
	}
	close(PSTEST);
	
	if(1 != $loops)
	{
		$exit = -7;
		print "ERROR($exit:$status): $exits{$exit}: $!\n";
		die $exit;
	}
	
	if(0 != (system "$cmd_hup $temp[0]"))
	{
		$exit = -8;
		print "ERROR($exit:$status): $exits{$exit}: $!\n";
		die $exit;
	}
}
else
{
	$exit = -2;
	print "ERROR($exit:$status): $exits{$exit}: $!\n";
	die $exit;
}

sub set_date
{
	#(49, 52, 22, 27, 1, 100, 0, 57, 0)
	($second, $minute, $hour, $mday, $month, $year, $wday, $yday, $isdst) = localtime(time);
	$year = ($year + 1900);
	$month = ($month + 1);
	
	if(10 > $month)
	{
		$month = sprintf("0%d", $month);
	}
	if(10 > $mday)
	{
		$mday = sprintf("0%d", $mday);
	}
	$date = "$year-$month-$mday";
	
	if(10 > $hour)
	{
		$hour = sprintf("0%d", hour);
	}
	if(10 > $minute)
	{
		$minute = sprintf("0%d", $minute);
	}
	if(10 > $second)
	{
		$second = sprintf("0%d", $second);
	}
	$time = "$hour-$minute-$second";
}

sub set_serial
{
	if(open(OPENNIC, "<$file_opennic_serial"))
	{
		$txtline = <OPENNIC>;
		$txtline =~ s/\n$//;
		
		close(OPENNIC);
		
		@temp_serial = split(//, $txtline);
		
		$temp_date0 = sprintf("%s%s%s", $year, $month, $mday);
		$temp_date1 = sprintf("%s%s%s%s%s%s%s%s", $temp_serial[0], $temp_serial[1], $temp_serial[2], $temp_serial[3], $temp_serial[4], $temp_serial[5], $temp_serial[6], $temp_serial[7]);

		if($temp_date0 ne $temp_date1)
		{
			$serial = sprintf("%s%s%s%s01", $year, $month, $mday);
		}
		else
		{
			$serial_in = sprintf("%s%s", $temp_serial[8], $temp_serial[9]);
			$serial_in ++;
			if(10 > $serial_in)
			{
				$serial_in = sprintf("0%d", $serial_in);
			}
		
			$serial = sprintf("%s%s%s%s", $year, $month, $mday, $serial_in);
		}

		if(open(OPENNIC, ">$file_opennic_serial"))
		{
			print OPENNIC "$serial\n";
			
			close(OPENNIC);
		}
		else
		{
			$exit = -12;
			print "ERROR($exit:$status): $exits{$exit}: $!\n";
			die $exit;
		}
	}
	else
	{
		$exit = -12;
		print "ERROR($exit:$status): $exits{$exit}: $!\n";
		die $exit;
	}
}

sub print_opennic_header
{
	if(open(OPENNIC, "<$file_opennic_header"))
	{
		while($txtline = <OPENNIC>)
		{
			$txtline =~ s/$token_serial/$serial/g;
			print OUTFILE $txtline;
		}
		print OUTFILE "\n";
		
		close(OPENNIC);
	}
	else
	{
		$exit = -5;
		print "ERROR($exit:$status): $exits{$exit}: $!\n";
		die $exit;
	}
}

sub print_opennic_rootrr
{
	print OUTFILE ";begin OpenNIC root pointers\n\n";
	
	if(open(OPENNIC, "<$file_opennic_servers"))
	{
		while($txtline = <OPENNIC>)
		{
			$txtline =~ s/\n$//;
			@temp_servers = split(/\s/, $txtline);
			$servers_opennic{$temp_servers[0]} = $temp_servers[1];
		}
		
		close(OPENNIC);
	}
	else
	{
		$exit = -6;
		print "ERROR($exit:$status): $exits{$exit}: $!\n";
		die $exit;
	}
	
	foreach $thing (sort(keys(%servers_opennic)))
	{
		print OUTFILE ".\t518400\tIN\tNS\t$thing.\n";
	}
	
	print OUTFILE "\n;end OpenNIC root pointers\n\n";
}


sub print_opennic_data
{
	print OUTFILE ";begin OpenNIC TLDs\n\n";
	
	foreach $thing (sort(@tlds_opennic))
	{
		foreach $thing0 (sort(keys(%servers_opennic)))
		{
			print OUTFILE "$thing.\t172800\tIN\tNS\t$thing0.\n";
		}
	}
	
	print OUTFILE "\n;end OpenNIC TLDs\n";
	print OUTFILE "\n;begin OpenNIC.glue\n\n";
	
	foreach $thing0 (sort(keys(%servers_opennic)))
	{
		print OUTFILE "opennic.glue.\t172800\tIN\tNS\t$thing0.\n";
	}
	
	
	print OUTFILE "\n;end OpenNIC.glue\n\n";
	print OUTFILE "\n;begin OpenNIC servers\n\n";
	
	foreach $thing0 (sort(keys(%servers_opennic)))
	{
		print OUTFILE "$thing0.\t172800\tIN\tA\t$servers_opennic{$thing0}\n";
	}
	
	print OUTFILE "\n;end OpenNIC servers\n";
	print OUTFILE "\n";
}

sub print_alternic_data
{
	if(open(ALTERNIC, "<$file_alternic_tlds"))
	{
		$index = 0;
		while($txtline = <ALTERNIC>)
		{
			if("" ne $txtline)
			{
				$txtline =~ s/\n$//;
				$tlds_alternic[$index] = $txtline;
				$index ++;
			}
		}
		
		close(ALTERNIC);
	}
	else
	{
		$exit = -16;
		print "ERROR($exit:$status): $exits{$exit}: $!\n";
		die $exit;
	}
	
	print OUTFILE ";begin AlterNIC TLDs\n";
	
	if(open(ALTERNIC, "<$file_alternic_servers"))
	{
		while($txtline = <ALTERNIC>)
		{
			$txtline =~ s/\n$//;
			@temp_servers = split(/\s/, $txtline);
			$servers_alternic{$temp_servers[0]} = $temp_servers[1];
		}
		
		close(ALTERNIC);
	}
	else
	{
		$exit = -15;
		print "ERROR($exit:$status): $exits{$exit}: $!\n";
		die $exit;
	}
	
	print OUTFILE "\n";
	
	foreach $thing (sort(@tlds_alternic))
	{
		foreach $thing0 (sort(keys(%servers_alternic)))
		{
			print OUTFILE "$thing.\t172800\tIN\tNS\t$thing0.\n";
		}
	}
	
	print OUTFILE "\n;end AlterNIC TLDs\n";
	print OUTFILE "\n;begin AlterNIC.glue\n\n";
	
	foreach $thing0 (sort(keys(%servers_alternic)))
	{
		print OUTFILE "alternic.glue.\t172800\tIN\tNS\t$thing0.\n";
	}
	
	
	print OUTFILE "\n;end AlterNIC.glue\n\n";
	print OUTFILE "\n;begin AlterNIC servers\n\n";
	
	foreach $thing0 (sort(keys(%servers_alternic)))
	{
		print OUTFILE "$thing0.\t172800\tIN\tA\t$servers_alternic{$thing0}\n";
	}
	
	print OUTFILE "\n;end AlterNIC servers\n";
	print OUTFILE "\n";
}

sub print_pacroot_data
{
	if(open(PACROOT, "<$file_pacroot_tlds"))
	{
		$index = 0;
		while($txtline = <PACROOT>)
		{
			if("" ne $txtline)
			{
				$txtline =~ s/\n$//;
				$tlds_pacroot[$index] = $txtline;
				$index ++;
			}
		}
		
		close(PACROOT);
	}
	else
	{
		$exit = -18;
		print "ERROR($exit:$status): $exits{$exit}: $!\n";
		die $exit;
	}
	
	print OUTFILE ";begin PacRoot TLDs\n";
	
	if(open(PACROOT, "<$file_pacroot_servers"))
	{
		while($txtline = <PACROOT>)
		{
			$txtline =~ s/\n$//;
			@temp_servers = split(/\s/, $txtline);
			$servers_pacroot{$temp_servers[0]} = $temp_servers[1];
		}
		
		close(PACROOT);
	}
	else
	{
		$exit = -17;
		print "ERROR($exit:$status): $exits{$exit}: $!\n";
		die $exit;
	}
	
	print OUTFILE "\n";
	
	foreach $thing (sort(@tlds_pacroot))
	{
		foreach $thing0 (sort(keys(%servers_pacroot)))
		{
			print OUTFILE "$thing.\t172800\tIN\tNS\t$thing0.\n";
		}
	}
	
	print OUTFILE "\n;end PacRoot TLDs\n";
	print OUTFILE "\n;begin PacRoot.glue\n\n";
	
	foreach $thing0 (sort(keys(%servers_pacroot)))
	{
		print OUTFILE "pacroot.glue.\t172800\tIN\tNS\t$thing0.\n";
	}
	
	
	print OUTFILE "\n;end PacRoot.glue\n\n";
	print OUTFILE "\n;begin PacRoot servers\n\n";
	
	foreach $thing0 (sort(keys(%servers_pacroot)))
	{
		print OUTFILE "$thing0.\t172800\tIN\tA\t$servers_pacroot{$thing0}\n";
	}
	
	print OUTFILE "\n;end PacRoot servers\n";
	print OUTFILE "\n";
}
