#!/usr/local/bin/perl5
# $Id: upserial,v 1.5 1998/02/19 11:47:44 martin Exp martin $

die "upserial <zone.filename>" if ! @ARGV;

@lt=localtime(time);
$lt[4]+=1;
if ($lt[4]<10) {$lt[4]="0".$lt[4];}
if ($lt[3]<10) {$lt[3]="0".$lt[3];}
$newserial=(1900+$lt[5]).$lt[4].$lt[3];

$zonefile=$ARGV[0];
$zonetmp=$zonefile.".$$.tmp";
$zonebak=$zonefile.".bak";

open ZONE, $zonefile or die "Cant open $zonefile";
open ZONETMP, ">".$zonetmp or die "Cant open $zonefile.$$.tmp";
while(<ZONE>) {
  chomp;
  next if /^#/;  		# remove comments
				# pass through comments and $ directives
  print(ZONETMP"$_\n") and next if ((/^;/)||(/\$/));
  s/;.*//g; 		# deal with bracketed lines:
            		# concat them into one long line
  if (/\(/) {
     $sofar=$_;
     while(<ZONE>) {
        chomp;
        s/;.*//g;
        $sofar.=$_;
        last if ($sofar=~/\)/);
        }
     $_=$sofar; 		# remove the backets
     s/[\(\)]//g;
     }
			# at this stage we have a full RR line in $_
  if (/\sMX\s/) {$rtype="MX";}
  elsif (/\sNS\s/) {$rtype="NS";}
  elsif (/\sA\s/) {$rtype="A";}
  elsif (/\sCNAME\s/) {$rtype="CNAME";}
  elsif (/\sHINFO\s/) {$rtype="HINFO";}
  elsif (/\sPTR\s/) {$rtype="PTR";}
  elsif (/\sSOA\s/) {$rtype="SOA";}
  else {$rtype="none";}
  @rr=split; 
  @rdata="";
  $ttl="";
  $owner="";
  $rowner="";
			# pop off the rdata into an array
  while ($rtype ne "none") {
     $_=pop @rr;
     if ($rtype ne $_) {push @rdata,$_} 
     else {last;}
     }
		# now the tricky bit... I dont like this loose format
		# it blows. and as far as I'm concerned its ambiguous.
  while ($#rr>=0) {
     $_=pop @rr;
     next if ($_ eq "IN");
     if ((/\A\d+\Z/)&&($#rr>0)) {
        $ttl=$_;
        next;
        } 
     $owner=$_;
     }
$rowner=$owner;
if ($rowner eq "") {$rowner=$lastowner;}
if ($rtype eq "SOA") {
   print(ZONETMP"$rowner\tIN\tSOA\t$rdata[$#rdata]\t$rdata[$#rdata-1] (\n");
   pop @rdata;
   pop @rdata;
   $_=pop @rdata;
   if (substr($_,0,8) eq $newserial) {
     $_++;
     }
   else {
     $_=$newserial."00";
     }
   print(ZONETMP"\t\t\t\t$_ ;Serial\n");
   $_=pop @rdata;
   print(ZONETMP"\t\t\t\t$_\t;Refresh\n");
   $_=pop @rdata;
   print(ZONETMP"\t\t\t\t$_\t;Retry\n");
   $_=pop @rdata;
   print(ZONETMP"\t\t\t\t$_\t;Expire\n");
   $_=pop @rdata;
   print(ZONETMP"\t\t\t\t$_ )\t;TTL\n");
   }
elsif ($rtype eq "none") {print(ZONETMP";\n");}
else {
   print(ZONETMP"$owner\t$ttl\tIN\t$rtype");
   while ($#rdata) {
      $_=pop @rdata;
      print(ZONETMP"\t$_");
      }
   print(ZONETMP"\n");
   }
$lastowner=$rowner;
}
close ZONE;
close ZONETMP;
rename $zonefile,$zonebak;
rename $zonetmp,$zonefile;
