#!FOOPERL

#
# Copyright (c) Xerox Corporation 1997, 1998. All rights reserved.
#
# License is granted to copy, to use, and to make and to use derivative
# works, provided that Xerox is acknowledged in all documentation
# pertaining to any such copy or derivative work. Xerox grants no other
# licenses expressed or implied. The Xerox trade name should not be used
# in any advertising without its written permission.
#
# XEROX CORPORATION MAKES NO REPRESENTATIONS CONCERNING EITHER THE
# MERCHANTABILITY OF THIS SOFTWARE OR THE SUITABILITY OF THIS SOFTWARE
# FOR ANY PARTICULAR PURPOSE.  The software is provided "as is" without
# express or implied warranty of any kind.
#
# These notices must be retained in any copies of any part of this software.
#



#----- default directory names and executable paths ----------
# users can override these values using the command line options listed
# the output directory for the route monitor program, command line opt -d
$rtemondir = "FOORTEMONDIR";
# the executable for the route monitor program, command line opt -E
$rtemon = "FOORTEEXEC";
# the output directory for the as lookup program, command line opt -l
$aslookupdir = "FOOHMKRDIR";
# the executable for the as lookup program, command line opt -L
$aslookup = "FOOASLEXEC";
# the output directory for this program, command line opt -h
$hmakerdir =  "FOOHMKRDIR";
# the directory to put new web pages, command line opt -w
$webdir = "FOOWEBDIR";
# the directory to archive any route table or route stats, command line opt -a
$archivedir = "FOOARDIR";
# the complete href to the associated cgi search script, command line opt -s
$search_cgi = "FOOCGISEARCH";
# no modifications should occur below this point

#-----------------------------------------------
# command line options
# option: -r rtr
#   action: instruct route monitor to only accept route updates from rtr
#   default: route monitor accepts updates from all neighboring routers
# option: -x
#   action:  instruct route monitor to always dump the route table on exit
#   default: route monitor only dumps the route table only when signaled
# option: -d directory
#   action: instruct route monitor to use the output directory for all output
#   default: route monitor uses its default directory for all output
# option: -e executable
#   action: instruct route monitor to run the routewatch program executable
#   default: route monitor runs its default routewatch program
# option: -E executable
#   action:  run route monitor program executable
#   default: run the route monitor program $rtemon defined above
# option: -l directory
#   action: instruct aslookup to use the output directory for all output
#   default: aslookup uses its default directory for all output
# option: -L executable
#   action:  run as lookup program executable
#   default: run the as lookup program $aslookup defined above
# option: -h directory
#   action: write pid file and error log to directory
#   default: write pid file and error log to $hmakerdir defined above
# option: -w directory
#   action: write the html files generated to directory
#   default: write the html files generated to $webdir defined above
# option: -s href
#   action: use href as the hyper link to the cgi search script
#   default: use $search_cgi above as the href (used in week/month html files)
# option: -a directory
#   action: write any route tables or route stats archived to directory
#   default: write any route tables or stats archived $archivedir defined above
# option: -W
#   action: archive the route statistics each week
#   default: do not archive route statistics weekly
# option: -M
#   action: archive the route statistics each month
#   default: do not archive route statistics monthly
# option: -T
#   action: archive each route table generated by route monitor
#   default: do not archive any route tables generated by route monitor
# option: -R script
#   action: run script to copy the html files generated to a remote web server
#   default: web server directories are locally accessible
#  NOTE: this option should be used by sites where this program can not
#  directly write to a web server area.  The script specified with -R
#  should use rcp or ftp or any other method to copy all the files from
#  $webdir onto the web server.  The script will be run by this program
#  each time new files are generated in $webdir




use Getopt::Std;


if (!getopts('xr:x:e:l:L:h:w:a:TWME:R:s:')  || (@ARGV > 0)) {
    print "usage: htmlmaker [-xTWM] [-e rtewatch] [-E rtemon] [-r rtr]\n";
    print "                 [-d rtemondir] [-h hmakerdir] [-w webdir]\n";
    print "                 [-a archivedir] [-R remote_cp_script] [-s href]\n";
    print "                 [-l aslookupdir] [-L aslookup]\n";
    exit(-1);
}
if (defined($opt_h)) {
    $hmakerdir = $opt_h;
}

$pidfile = "$hmakerdir/html_maker.pid";
open(PIDFILE, ">$pidfile") || &log_quit(pid,$pidfile);
print PIDFILE "$$\n";
close(PIDFILE);   
$errorfile = "$hmakerdir/html_maker.err";
log_error(start,none);
&declare_fields;
&init_routemonitor;
&init_update;
&init_archive;
&init_as;
&init_html;
&read_current_stats;
$SIG{USR1} = 'trigger_stats_update';
$need_update = "no";
$SIG{ALRM} = 'get_table';
$curtime = time;
$exacthour = int($curtime/3600) * 3600 + 3600;
$nextalarm = $exacthour - $curtime;
alarm ($nextalarm);
while(1) {
    sleep;
}

sub get_table {
    $curtime = time;
    $exacthour = int($curtime/3600) * 3600 + 3600;
    $nextalarm = $exacthour - $curtime;
    alarm ($nextalarm);
    if ($need_update eq "yes") {
	&read_stats_update;
	$need_update = "no";
    }
    if (&signal_routemonitor == -1) {
	return(-1);
    }
    if (&update_stats ==  -1) {
	return(-1);
    }
    &archive_data;
    &write_current_stats;
    if ($web_copy ne "no") {
	my($ret) = system("$web_copy > /dev/null");
	if ($ret !=0) {
	    &log_error(webcopy,$web_copy);
	}
    }
    return(1);
}

sub trigger_stats_update {
   $need_update = "yes";
   &log_error(updatesignal, none);
} 


sub init_routemonitor {
    if (defined($opt_d)) {
	$rtemondir = $opt_d;
    }
    $rtemonpid = "$rtemondir/route_monitor.pid";
    $rtemontable = "$rtemondir/route_table";
    if (defined($opt_E)) {
	$rtemon = $opt_E;
    }
    if (defined($opt_e)) {
	$rtemon = "$rtemon -e $opt_e";
    }
    if (defined($opt_x)) {
	$rtemon = "$rtemon -e $opt_e -x";
    }
    $rtemon = "$rtemon -d $rtemondir";
    my($rtepid) = &check_routemonitor;
    if ($rtepid == -1) {
	&start_routemonitor;
    } else {
	kill USR1, $rtepid;
    }
}

sub start_routemonitor {
    system("nohup $rtemon > /dev/null &");
    sleep 10;
    my($rtepid) = &check_routemonitor;
    if ($rtepid == -1 ) {
	&log_quit(start,$rtemon);
    }
}

sub check_routemonitor {
    open(RTEPID, "$rtemonpid") || return (-1);
    my($rtepid) = <RTEPID>;
    chop($rtepid);
    close(RTEPID);
    if (kill(0,$rtepid) != 1) {
	return(-1);
    } else {
    	return($rtepid);
    }
}

sub signal_routemonitor{
    my($rtepid) = &check_routemonitor;
    if ($rtepid == -1) {
	&log_error(nortemon, none);
	&start_routemonitor;
	return(-1);
    } else {
	kill(USR1,$rtepid);
	sleep(120);
	return(1);
    }
    
}


sub read_current_stats {
    my($src, $a, $line);
    if (!(-f $statsfile)) {
	&log_error(nofile,none);
	$totalw = 0; $totalm = 0; $stime = time;
	return(-1);
    }
    open(STATSFILE, "$statsfile") || &log_quit(statsopen,$statsfile);
    $line = <STATSFILE>;
    my($Route,$Data,$From, $Time);
    ($Route,$Data,$From, $stime, $Time, $totalw, $totalm) = split(" ",$line);
    if (($Route ne "Route") || (split(" ",$line) != 7)) {
	&log_error(startline,$line);
	system("mv $statsfile $statsfile.bak");
	$totalw = 0; $totalm = 0; $stime = time;
	return(-1);
    }
    while($line = <STATSFILE>) {
       chop($line);
       if (split(" ",$line) != $fieldtotal) {
	   &log_error(statsline,$line); 
       } else {
	   @array = split(" ",$line);
	   $a = &field_num("addr");
    	   if ($a != -1) {
	       $stats{$array[$a]} = $line;
	       $active{$array[$a]} = "no";
	   }
       }
   }
   close(STATSFILE);
}

sub write_current_stats {
    open(STATSFILE, "> $statsfile") || &log_quit(statswrite,$statsfile);
    $stime = $dtime;
    my($sc,$mn,$hr,$dy,$mo,$yr,$wd,$yd,$isd) = gmtime($stime);
    $mo = $mo + 1;
    if ($yr < 100) { 
        $yr = "19$yr"; 
    } else {
        $yr = $yr -100;
        $yr = "20$yr";
    }
    if ($hr < 10) { $hr = "0$hr"; }
    if ($mn < 10) { $mn = "0$mn"; }
    if ($sc < 10) { $sc = "0$sc"; }
    my($Time) = "$mo/$dy/$yr,$hr:$mn:$sc-GMT";
    print STATSFILE "Route Data From $stime ($Time) $totalw $totalm\n";
    my($src);
    foreach $src (keys %stats) {
	print STATSFILE "$stats{$src}\n";
    }
    close(STATSFILE);
}

sub read_stats_update {
    &log_error(updatebegin,none);
    my($src, $a, $line);
    if (!(-f $updatefile)) {
	&log_error(noupdate,$updatefile);
	return(-1);
    }
    open(UPDATEFILE, "$updatefile") || &log_error(updateopen,$updatefile);
    $line = <UPDATEFILE>;
    my($Route,$Stats,$Update);
    ($Route,$Stats,$Update) = split(" ",$line);
    if (($Route ne "Route") || (split(" ",$line) != 3)) {
	&log_error(updatestart,$line);
	return(-1);
    }
    while($line = <UPDATEFILE>) {
       chop($line);
       if (split(" ",$line) != $fieldtotal) {
	   &log_error(updateline,$line); 
       } else {
	   @uparray = split(" ",$line);
	   $a = &field_num("addr");
    	   if ($a != -1) {
	       $src = $uparray[$a];
	       @array = split(" ",$stats{$src});
	       for($i=0; $i<$fieldtotal; $i++) {
		   if ($uparray[$i] ne "*") {
		       $array[$i] = $uparray[$i];
		   }
	       }
	       &save_src;
	       $active{$array[$a]} = "no";
	   }
       }
   }
    close(UPDATEFILE);
    &log_error(updateend, none);
}




sub init_update {
    $rpt_interval = 60;
    $interval_diff = 5;
    $table_diff = 600;
    $expire = 5184000;
}
 
sub update_stats {
    if (&valid_table == -1) {
	return(-1);
    }
    &reset_hourly_stats;
    &reset_weekly_stats;
    &reset_monthly_stats;
    &reset_as_stats;
    my($line);
    while($line = <NEWTABLE>) {
	($src,$first,$metric,$flaps,$updates,$tree) = split(" ",$line);
	if (!defined($stats{$src})) { &new_src; }
	$active{$src} = "yes";
	@array = split(" ",$stats{$src});
	&update_hourly_stats;
	&update_weekly_stats;
	&update_monthly_stats;
	&update_as_stats;
	&save_src;
    }
    close(NEWTABLE);
    foreach $src (keys %stats) {
	if ($active{$src} eq "no") {
	    @array = split(" ",$stats{$src});
	    if (&expire_src == -1) {
		&inactive_hourly_stats;
		&inactive_weekly_stats;
		&inactive_monthly_stats;
		&inactive_as_stats;
		$active{$src} = "no";
		&save_src;
	    }
	} else {
	    $active{$src} = "no";
	}
    }
    &compute_worst;
    &write_hourly_html;
    if ($new_week == 1) {
	&write_lweek_html;
    }
    &write_weekly_html;
    &write_monthly_html;
    &as_lookup;
}

sub valid_table {
    my($difftime,$diffint,$line);
    open(NEWTABLE, "$rtemontable") || &log_error(newtable,$rtemontable);
    $line = <NEWTABLE>;
    my($Route,$Table,$Dumped,$At,$Time,$Total,$Routes,$In,$Table2);
    ($Route,$Table,$Dumped,$At,$dtime,$Time,$Total,$Routes,$In,$Table2) = 
	split(" ",$line);
    if (($Route ne "Route") || (split(" ",$line) != 10)) {
	&log_error(tablestart,$line);
	$dtime = time;
	return(-1);
    }
    $line = <NEWTABLE>;
    my($Report,$Interval, $Is, $Minutes, $Table3, $Last, $Reset, $At1, $Ltime,
     $Time2);
    ($Report,$Interval,$Is,$rptint,$Minutes, $Table3,$Last,$Reset,$At1,$Ltime, 
     $Time2) = split(" ",$line);
    if (($Report ne "Report") || (split(" ",$line) != 11)) {
	&log_error(tablestart,$line);
	$dtime = time;
	return(-1);
    }
    $difftime = abs($dtime - time);
    if ($difftime > $table_diff) {
	&log_error(oldtable,$difftime);
	return(-1);
    }
    $diffint = abs($rptint - $rpt_interval);
    if ($diffint > $interval_diff) {
	&log_error(interval,$rptint);
	return(-1);
    }
    return(1);
}

sub expire_src {
    my($s,$c,$downtime);
    $s = &field_num("state"); $c = &field_num("change"); 
    if (($s == -1) || ($c == -1)) {
	return(-1);
    }
    $downtime = $dtime - $array[$c];
    if (($downtime > $expire) && ($array[$s] eq "down")) {
	delete $stats{$src};
	delete $active{$src};
	return(1);
    }
    return(-1);
}


	    
	





sub init_archive {
    if (defined($opt_a)) {
	$archivedir = $opt_a;
    }
    if (defined($opt_W)) {
	$weekarchive = "$archivedir/weekly_stats";
    } else {
	$weekarchive = "none";
    }
    if (defined($opt_M)) {
	$montharchive = "$archivedir/monthly_stats";
    } else {
	$montharchive = "none";
    }
    if (defined($opt_T)) {
	$tablearchive = "$archivedir/route_table";
    } else {
	$tablearchive = "none";
    }
}

sub archive_data {
    my($ret);
    my($sc,$mn,$hr,$dy,$mo,$yr,$wd,$yd,$isd) = gmtime($stime);
    $mo = $mo + 1;
    if ($yr < 100) { 
        $yr = "19$yr"; 
    } else {
        $yr = $yr -100;
        $yr = "20$yr";
    }
    if ($new_month == 1) {
	if ($montharchive ne "none") {
	    if ($mo < 10) {$mo = "0$mo";}
	    $ret = system("cp $statsfile $montharchive.$yr.$mo");
	    if ($ret != 0) {
		&log_error(copy,$montharchive.$yr.$mo);
	    }
	}
    }
    if ($new_week == 1) {
	if ($weekarchive ne "none") {
	    my($myweek) = int($yd/7) + 1;
	    if ($myweek < 10) {$myweek = "0$myweek";}
	    $ret = system("cp $statsfile $weekarchive.$yr.$myweek");
	    if ($ret != 0) {
		&log_error(copy,$weekarchive.$yr.$myweek);
	    }
	}
    }
    if ($tablearchive ne "none") {
	($sc,$mn,$hr,$dy,$mo,$yr,$wd,$yd,$isd) = gmtime($dtime);
	if ($hr < 10) { $hr = "0$hr"; }
	$yd = $yd + 1;
	if ($yd < 10) { 
	    $yd = "00$yd"; 
	} elsif ($yd < 100) {
	    $yd = "0$yd";
	}
	if ($yr < 100) {
	    $yr = "19$yr";
	} else {
	    $yr = $yr -100;
	    $yr = "20$yr";
	}
	$ret = system("cp $rtemontable $tablearchive.$yr.$yd.$hr"); 
	if ($ret != 0) {
	    &log_error(copy,$tablearchive.$yr.$yd.$hr);
	}
    }
    return(1);
}


sub reset_hourly_stats {
    $routes = 0; $stable = 0; $noreach = 0;
    $max = -1; $maxsrc = "0.0.0.0";
    $cameup = 0; $wentdown = 0; $newup =0;
}

sub update_hourly_stats {
    $routes++;
    if ($metric == 32) { $noreach++; }
    if ($flaps == 0) { $stable++; }
    if ($flaps > $max) {
	$max = $flaps;
	$maxsrc = $src;
    }
    my($s,$c,$m,$f,$u);
    $s = &field_num("state"); $c = &field_num("change"); 
    $m = &field_num("metric"); $f = &field_num("flaps");
    $u = &field_num("updates");
    if (($s == -1) || ($c == -1) || ($m == -1) || ($f == -1) || ($u == -1)) {
	return(-1);
    }
    if ($array[$s] eq "down") {
	$cameup++;
	$array[$s] = "up";
	$array[$c] = $dtime;
    }
    $array[$m] = $metric;
    $array[$f] = $flaps;
    $array[$u] = $updates;
}

sub inactive_hourly_stats {
    my($s,$c,$m,$f,$u);
    $s = &field_num("state"); $c = &field_num("change"); 
    $m = &field_num("metric"); $f = &field_num("flaps");
    $u = &field_num("updates");
    if (($s == -1) || ($c == -1) || ($m == -1) || ($f == -1) || ($u == -1)) {
	return(-1);
    }
    if ($array[$s] eq "up") {
	$array[$s] = "down";
	$array[$c] = $dtime;
	$wentdown++;
    }
    $array[$m] = 32;
    $array[$f] = 0;
    $array[$u] = 0;
}


sub reset_weekly_stats {
    my($ssc,$smn,$shr,$sdy,$smo,$syr,$swd,$syd,$sisd) = gmtime($stime);
    $smo = $smo + 1;
    my($dsc,$dmn,$dhr,$ddy,$dmo,$dyr,$dwd,$dyd,$disd) = gmtime($dtime);
    $dmo = $dmo + 1;
    if (($dwd < $swd) || (($dyd - $syd) > 7 )) {
	$totalw = 1;
	$new_week = 1;
    } else {
	$totalw++;
	$new_week = 0;
    }
}

sub update_weekly_stats {
    my($f,$c,$p,$n,$p,$s);
    $f = &field_num("wflaps"); $c = &field_num("change"); 
    $p = &field_num("whour"); $n = &field_num("wcount");
    $s = &field_num("wstates");
    if (($f == -1) || ($c == -1) || ($p == -1) || ($n == -1) || ($s == -1)) {
	return(-1);
    }
    if ($new_week == 1) {
	my($lf,$lp,$ln,$ls);
	$lf = &field_num("lflaps"); $lp = &field_num("lhour"); 
	$ln = &field_num("lcount"); $ls = &field_num("lstates");
	if (($lf == -1) || ($lp == -1) || ($ln == -1) || ($ls == -1)) {
	    return(-1);
	}
	$array[$lf] = $array[$f];
	$array[$lp] = $array[$p];
	$array[$ln] = $array[$n];
	$array[$ls] = $array[$s];
	$array[$f] = $flaps;
       	$array[$n] = 1;
	$array[$s] = 0;
    } else {
	$array[$f] = (($array[$n] * $array[$f]) + $flaps) / ($array[$n] + 1);
	$array[$n] = $array[$n] + 1;
    }
    if ($array[$c] == $dtime) {
	$array[$s] = $array[$s] + 1;
    }
    $array[$p] = int(100*($array[$n]/$totalw));
}

sub inactive_weekly_stats {
    my($f,$c,$p,$n,$s);
    $f = &field_num("wflaps"); $c = &field_num("change"); 
    $p = &field_num("whour"); $n = &field_num("wcount");
    $s = &field_num("wstates");
    if (($f == -1) || ($c == -1) || ($p == -1) || ($n == -1) || ($s == -1)) {
	return(-1);
    }
    if ($new_week == 1) {
	my($lf,$lp,$ln,$ls);
	$lf = &field_num("lflaps"); $lp = &field_num("lhour"); 
	$ln = &field_num("lcount"); $ls = &field_num("lstates");
	if (($lf == -1) || ($lp == -1) || ($ln == -1) || ($ls == -1)) {
	    return(-1);
	}
	$array[$lf] = $array[$f];
	$array[$lp] = $array[$p];
	$array[$ln] = $array[$n];
	$array[$ls] = $array[$s];
	$array[$f] = 0;
       	$array[$n] = 0;
	$array[$s] = 0;
    } 
    if ($array[$c] == $dtime) {
	$array[$s] = $array[$s] + 1;
    }
    $array[$p] = int(100*($array[$n]/$totalw));
}





sub reset_monthly_stats {
    my($ssc,$smn,$shr,$sdy,$smo,$syr,$swd,$syd,$sisd) = gmtime($stime);
    $smo = $smo + 1;
    my($dsc,$dmn,$dhr,$ddy,$dmo,$dyr,$dwd,$dyd,$disd) = gmtime($dtime);
    $dmo = $dmo +1;
    if ($smo != $dmo ) {
	$totalm = 1;
	$new_month = 1;
    } else {
	$totalm++;
	$new_month = 0;
    }  
}

sub update_monthly_stats {
    my($f, $c,$p,$n,$s);
    $f = &field_num("mflaps"); $c = &field_num("change"); 
    $p = &field_num("mhour"); $n = &field_num("mcount");
    $s = &field_num("mstates");
    if (($f == -1) || ($c == -1) || ($p == -1) || ($n == -1) || ($s == -1)) {
	return(-1);
    }
    if ($new_month == 1) {
	$array[$f] = $flaps;
       	$array[$n] = 1;
	$array[$s] = 0;
    } else {
	$array[$f] = (($array[$n] * $array[$f]) + $flaps) / ($array[$n] + 1);
	$array[$n] = $array[$n] + 1;
    }
    if ($array[$c] == $dtime) {
	$array[$s] = $array[$s] + 1;
    }
    $array[$p] = int(100*($array[$n]/$totalm));

}

sub inactive_monthly_stats {
    my($f,$c,$p,$n,$s);
    $f = &field_num("mflaps"); $c = &field_num("change"); 
    $p = &field_num("mhour"); $n = &field_num("mcount");
    $s = &field_num("mstates");
    if (($f == -1) || ($c == -1) || ($p == -1) || ($n == -1) || ($s == -1)) {
	return(-1);
    }
    if ($new_month == 1) {
	$array[$f] = 0;
       	$array[$n] = 0;
	$array[$s] = 0;
    } 
    if ($array[$c] == $dtime) {
	$array[$s] = $array[$s] + 1;
    }
    $array[$p] = int(100*($array[$n]/$totalm));
}





sub init_as {
    if (defined($opt_l)) {
	$aslookupdir = $opt_l;
    }
    if (defined($opt_L)) {
	$asscript = "$opt_L -h $aslookupdir -d";
    } else {
	$asscript = "$aslookup -h $aslookupdir -d";
    }
    $asinfile = "$aslookupdir/find_as_for";
    $asoutfile = "$aslookupdir/found_as_for";
    $aspidfile = "$aslookupdir/as_lookup.pid";
    $looking_up_as = "no";
    $asdata{-3} = "-3 0 0 0 0.0.0.0 0 0 0.0.0.0 0";
}

sub reset_as_stats {
    my($num,$size,$down,$wflap,$wsrc,$wmax,$mflap,$msrc,$mmax);
    $size = 0; $down = 0; $wflap =0; $wsrc = "0.0.0.0"; $wmax = 0;
    $mflap = 0; $msrc = "0.0.0.0"; $mmax = 0;
    foreach $num (keys %asdata) {
	$asdata{$num} = 
	    "$num $size $down $wflap $wsrc $wmax $mflap $msrc $mmax";
    }
    if ($looking_up_as ne "yes") {
	return(1);
    }
    $looking_up_as = "no";
    open(ASPID, "$aspidfile") || &log_error(aspidfile,$aspidfile);
    my($aspid) = <ASPID>;
    chop($aspid);
    close(ASPID);
    if (kill(0,$aspid) == 1) {
	$looking_up_as = "yes";
	return(1); 
    }
    my($a) = &field_num("asnum");
    if ($a == -1) { return(-1); }
    open(ASOUT, "$asoutfile") || &log_error(asout,$asoutfile);
    my($aline,$asrc, $anum);
    while($aline = <ASOUT>) {
	if (split(" ",$aline) != 2) {
	    &log_error(asline,$aline);
	} else {
	    ($asrc,$anum) = split(" ",$aline);
	    if (!defined($stats{$asrc})) {
		&log_error(assrc,$asrc);
	    } else {
		@array = split(" ",$stats{$asrc});
		$array[$a] = $anum;
		&save_src;
	    }
	    delete $need_as{$asrc}; 
	}
    }
    close(ASOUT);
}

sub update_as_stats {
    my($num,$size,$down,$wflap,$wsrc,$wmax,$mflap,$msrc,$mmax);
    my($a,$w,$m,$mywflap,$mymflap);
    $a = &field_num("asnum"); 
    $w = &field_num("wflaps"); $m = &field_num("mflaps"); 
    if (($a == -1) || ($w == -1) || ($m == -1)) {
	return(-1);
    }
    $num = $array[$a]; $mywflap = $array[$w]; $mymflap = $array[$m];
    if (!defined($asdata{$num})) {
	$size = 0; $down = 0; 
	$wflap = 0; $wsrc = "0.0.0.0"; $wmax = 0;
	$mflap = 0; $msrc = "0.0.0.0"; $mmax = 0;
    } else {
	($num,$size,$down,$wflap,$wsrc,$wmax,$mflap,$msrc,$mmax) = 
	    split(" ",$asdata{$num});
    }
    if ($num == -2) {
	if (!defined($need_as{$src}) || ($need_lookup ne "yes")) {
	    $need_as{$src} = "yes";
	    $need_lookup = "yes";
	}
    }
    if ($mywflap >= $wmax) {
	$wmax = $mywflap;
	$wsrc = $src;
    }
    if ($mymflap >= $mmax) {
	$mmax = $mymflap;
	$msrc = $src;
    }
    if (int($mywflap) > 0) {
	$wflap++;
    }
    if (int($mymflap) > 0) {
	$mflap++;
    }
    $size++;
    $asdata{$num} = "$num $size $down $wflap $wsrc $wmax $mflap $msrc $mmax";
}

sub inactive_as_stats {
    &update_as_stats;
    my($num,$size,$down,$wflap,$wsrc,$wmax,$mflap,$msrc,$mmax);
    $a = &field_num("asnum");
    if ($a == -1) { return(-1); }
    $num = $array[$a];
    ($num,$size,$down,$wflap,$wsrc,$wmax,$mflap,$msrc,$mmax) = 
	split(" ",$asdata{$num});
    $down++;
    $asdata{$num} = "$num $size $down $wflap $wsrc $wmax $mflap $msrc $mmax";
}

sub as_lookup {
    if (($looking_up_as eq "yes") || ($need_lookup eq "no")) {
	return(1);
    }
    open(ASIN,">$asinfile") || &log_error(asin,$asinfile);
    my($asrc);
    foreach $asrc (keys %need_as) { print ASIN "$asrc\n"; }
    close(ASIN);
    my($myscript) = "$asscript -i $asinfile -o $asoutfile";
    my($ret) = system("$myscript > /dev/null &");
    if ($ret != 0) { &log_error(asstart,$myscript); }
    $need_lookup = "no";
    $looking_up_as = "yes";
}







sub init_html {
    if (defined($opt_w)) {
	$webdir = $opt_w;
    }
    $statsfile = "$webdir/route_stats";
    $updatefile = "$webdir/route_stats.update";
    $backhtml = "./stone.gif";
    $linehtml = "./hline.gif";
    $sumhtml = "$webdir/summary.html";
    $weekhtml = "$webdir/week.html";
    $monthhtml = "$webdir/month.html";
    $lweekhtml = "$webdir/last.html";
    $printmonth = 50;
    $printweek = 50;
    if (defined $opt_s) {
	$search_cgi = $opt_s;
    }
    if (defined($opt_R)) {
	$web_copy = $opt_R;
    } else {
	$web_copy = "no";
    }
}

sub compute_worst {
    my($wrank,$mrank);
    for($i =0; $i < $printweek; $i++) {
	$weekworst[$i] = -2;
	$wrank[$i] = 0;
    }
    for($i =0; $i < $printmonth; $i++) {
	$monthworst[$i] = -2;
	$mrank[$i] = 0;
    }
    my($newas,$newrank,$prev,$i);
    my($num,$size,$down,$wflap,$wsrc,$wmax,$mflap,$msrc,$mmax);
    foreach $newas (keys %asdata) {
	($num,$size,$down,$wflap,$wsrc,$wmax,$mflap,$msrc,$mmax) = 
	    split(" ",$asdata{$newas});
	if ($wmax >= $wrank[$printweek]) {
	    $newrank = $printweek -1;
	    while(($newrank >=0) && ($wmax >= $wrank[$newrank])) {
		$newrank = $newrank  -1;
	    }
	    $newrank++;
	    for($i=$printweek; $i > $newrank; $i--) {
		$prev = $i -1;
		$weekworst[$i] = $weekworst[$prev];
		$wrank[$i] = $wrank[$prev];
	    }
	    $weekworst[$newrank] = $newas;
	    $wrank[$newrank] = $wmax;
	}
	if ($mmax >= $mrank[$printmonth]) {
	    $newrank = $printmonth -1;
	    while(($newrank >=0) && ($mmax >= $mrank[$newrank])) {
		$newrank = $newrank  -1;
	    }
	    $newrank++;
	    for($i=$printmonth; $i > $newrank; $i--) {
		$prev = $i -1;
		$monthworst[$i] = $monthworst[$prev];
		$mrank[$i] = $mrank[$prev];
	    }
	    $monthworst[$newrank] = $newas;
	    $mrank[$newrank] = $mmax;
	}
    }
}
	
sub write_hourly_html {
    my($prct);
    my($sc,$mn,$hr,$dy,$mo,$yr,$wd,$yd,$isd) = gmtime($dtime);
    $mo = $mo + 1;
    if ($hr < 10) { $hr = "0$hr"; }
    if ($mn < 10) { $mn = "0$mn"; }
    if ($sc < 10) { $sc = "0$sc"; }
    if ($yr < 100) { 
	$yr = "19$yr"; 
    } else {
	$yr = $yr -100;
	$yr = "20$yr";
    }
    my($day) = "$mo/$dy/$yr";
    my($hour) = "$hr:$mn:$sc GMT";
    open(SUMHTML, ">$sumhtml") || &log_error(sumhtml,$sumhtml);
    print SUMHTML "<html> <head> <title>Route Report Summary</title> \n";
    print SUMHTML '<meta http-equiv="Refresh" content="3600"> </head>';
    print SUMHTML '<body background="';
    print SUMHTML "$backhtml";
    print SUMHTML '" text="#000000">';
    print SUMHTML "<center><h1>Multicast Routing Summary Report</h1></center>\n";
    print SUMHTML "<font size=4> \n";
    print SUMHTML "<ul> \n";
    if ($routes == 0) {
	$prct = 0;
    } else {
	$prct = int($stable/$routes * 100);
    }
    print SUMHTML "<li>Report for a $rptint minute period, dated $hour $day\n";
    print SUMHTML "<li> $stable routes did not change during report time\n";
    print SUMHTML "<font size=4 color=red>($prct%)</font> \n";
    print SUMHTML "<li> Max number of flaps was \n";
    print SUMHTML "<font size=4 color=red> $max </font> for route $maxsrc\n";
    print SUMHTML "<li> $routes Routes Advertised in Total \n";
    print SUMHTML "<li> $noreach routes listed unreachable at end of report period \n";
    print SUMHTML "<li> $cameup routes changed state to up this period \n";
    print SUMHTML "<li> $newup of routes which came up are new sources\n";
    print SUMHTML "<li> $wentdown routes changed state to down this period\n";
    print SUMHTML "</ul> </body> </html> \n";
    close(SUMHTML);
}

sub write_weekly_html {
    open(HTML, ">$weekhtml") || &log_error(weekhtml,$weekhtml);
    &start_worst(week);
    my($num,$size,$down,$wflap,$wsrc,$wmax,$mflap,$msrc,$mmax);
    my($i);
    for($i = 0; $i < $printweek; $i++) {
	($num,$size,$down,$wflap,$wsrc,$wmax,$mflap,$msrc,$mmax) =
	    split(" ",$asdata{$weekworst[$i]});
	$wmax = int($wmax);
	print HTML "      <tr>\n";
	print HTML "         <td align=left> $wsrc </td>\n";
	print HTML "         <td align=right>$wmax</td>\n";
	print HTML "         <td align=right>\n";
	print HTML '<a href="';
	print HTML "$search_cgi";
	print HTML "?use=state&use=change&use=asnum&use=wflaps&use=whour";
	print HTML "&care=state&use=wstates&asnum=$num&sortnum=wflaps";
	print HTML '">';
	print HTML "$num </a> </td>\n";
	print HTML "         <td align=right>$size</td>\n";
	print HTML "         <td align=right>$wflap</td>\n";
	print HTML "         <td align=right>$down</td>\n";
	print HTML "      </tr>\n";
    }
    &finish_worst;
    close(HTML);
}

sub write_monthly_html {
    open(HTML, ">$monthhtml") || &log_error(monthhtml,$monthhtml);
    &start_worst(month);
    my($num,$size,$down,$wflap,$wsrc,$wmax,$mflap,$msrc,$mmax);
    my($i);
    for($i=0; $i < $printmonth; $i++) {
	($num,$size,$down,$wflap,$wsrc,$wmax,$mflap,$msrc,$mmax) =
	    split(" ",$asdata{$monthworst[$i]});
	$mmax = int($mmax);
	print HTML "      <tr>\n";
	print HTML "         <td align=left> $msrc </td>\n";
	print HTML "         <td align=right>$mmax</td>\n";
	print HTML "         <td align=right>\n";
	print HTML '<a href="';
	print HTML "$search_cgi";
	print HTML "?use=state&use=change&use=asnum&use=mflaps&use=mhour";
	print HTML "&care=state&use=mstates&asnum=$num&sortnum=mflaps";
	print HTML '">';
	print HTML "$num </a> </td>\n";
	print HTML "         <td align=right>$size</td>\n";
	print HTML "         <td align=right>$mflap</td>\n";
	print HTML "         <td align=right>$down</td>\n";
	print HTML "      </tr>\n";
    }
    &finish_worst;
    close(HTML);
}

sub start_worst {
    my($sc,$mn,$hr,$dy,$mo,$yr,$wd,$yd,$isd) = gmtime($dtime);
    $mo = $mo + 1;
    if ($hr < 10) { $hr = "0$hr"; }
    if ($mn < 10) { $mn = "0$mn"; }
    if ($sc < 10) { $sc = "0$sc"; }
    if ($yr < 100) { 
        $yr = "19$yr"; 
    } else {
        $yr = $yr - 100;
        $yr = "20$yr";
    }
    my($day) = "$mo/$dy/$yr";
    my($hour) = "$hr:$mn:$sc GMT";
    my($Capital,$normal);
    if ($_[0] eq "week") { 
	$Capital = "Week";
	$normal = "week";
    } else {
	$Capital = "Month";
	$normal = "month";
    }
    print HTML "<html>\n\n";
    print HTML "<head>\n";
    print HTML "   <title> This ${Capital}'s Worst Routes </title>\n";
    print HTML '   <meta http-equiv="Refresh" content="3600">';
    print HTML "\n";
    print HTML "</head>\n\n";
    print HTML "<body>\n";
    print HTML "   <center> <h1> This ${Capital}'s Worst Routes </h1> </center>\n\n";
    print HTML '   <br> <img src="';
    print HTML "$linehtml";
    print HTML '" width="100%"'; 
    print HTML "\n    alt=";
    print HTML '"----------------------------------------------------------">';
    print HTML "   <br>\n\n";
    print HTML "   <p> The table lists this ${normal}'s most unstable routes.\n";
    print HTML "   Our monitoring tool tracks the distance\n";
    print HTML "   to each source in the MBone.  A change in distance\n";
    print HTML "   indicates a change in the route to the source, ie a flap\n";
    print HTML "   Using this data, we calculate the <b>average number of\n";
    print HTML "   flaps per hour</b>.  This page reports the most unstable\n";
    print HTML "   routes observed during the current $normal.  This page is\n";
    print HTML "   updated hourly.  <b>Only one route per Autonomous System\n";
    print HTML "   is listed</b>.\n\n";
    print HTML "  <p>The cause of this instability is often one of the bugs\n";
    print HTML "   listed in the \n";
    print HTML ' <a href="http://ganef.cs.ucla.edu/~masseyd/Route/bugs.html">';
    print HTML "  \n";
    print HTML "   Current Bugs</a> page.  Note Autonomous Systems listed \n";
    print HTML "   here typically advertise many unstable routes, but only \n";
    print HTML "   the worst route for the AS is reported.  For a full \n";
    print HTML "   report on the AS, click on the AS number. \n\n"; 
    print HTML '   <br> <img src="';
    print HTML "$linehtml";
    print HTML '" width="100%"'; 
    print HTML "   \n    alt=";
    print HTML '"----------------------------------------------------------">';
    print HTML "   <br>\n\n";
    print HTML "   <font size=4>";
    print HTML "   <p> Data last updated at $day $hour <br> \n";
    print HTML "   <table border=2 cellpadding=2 cellspacing=4> \n";
    print HTML "      <tr>\n";
    print HTML "         <th align=center> Source</th>\n";
    print HTML "         <th align=center> Avg. Flaps/Hour </th> \n";
    print HTML "         <th align=center>AS Number</th> \n";
    print HTML "         <th align=center> Sources in AS </th> \n";
    print HTML "         <th align=center> Sources Flapping </th> \n";
    print HTML "         <th align=center> Sources Down </th> \n";
    print HTML "      </tr> \n";
}

sub finish_worst {
    print HTML "   </table>\n";
    print HTML "   <br>\n";
    print HTML "</body>\n\n";
    print HTML "</html>\n";
}

sub write_lweek_html {
    open(WEEK, "$weekhtml") || &log_error(weekopen,$weekhtml);
    open(LAST, ">$lweekhtml") || &log_error(lweekhtml,$lweekhtml);
    my($line);
    while($line = <WEEK>) {
	$line =~ s/This Week/Last Week/g;
	$line =~ s/this week/last week/g;
	$line =~ s/current week/previous week/g;
	$line =~ s/wflaps/lflaps/g;
	$line =~ s/whour/lhour/g;
	$line =~ s/wcount/lcount/g;
	$line =~ s/wstates/lstates/g;
   	print LAST $line;
    }
    close(WEEK);
    close(LAST);
}

sub declare_fields{
    my($time, $header,$i);
    $data[0]="addr";     $header[0]="CIDR addr"; $time[0]="none";
    $data[1]="asnum";    $header[1]="AS Number"; $time[1]="none";
    $data[2]="state";    $header[2]="State";     $time[2]="none";
    $data[3]="change";   $header[3]="Change";    $time[3]="none";
    $data[4]="age";      $header[4]="Appeared";  $time[4]="none";
    $data[5]="metric";   $header[5]="Metric";    $time[5]="hour";
    $data[6]="flaps";    $header[6]="Flaps";     $time[6]="hour";
    $data[7]="updates";  $header[7]="Updates";   $time[7]="hour";
    $data[8]="wflaps";   $header[8]="Flaps";     $time[8]="week";
    $data[9]="whour";    $header[9]="Uptime(%)"; $time[9]="week";
    $data[10]="wcount";  $header[10]="Hours #";  $time[10]="week";
    $data[11]="wstates"; $header[11]="Changes";  $time[11]="week";
    $data[12]="mflaps";  $header[12]="Flaps";    $time[12]="month";
    $data[13]="mhour";   $header[13]="Uptime(%)"; $time[13]="month";
    $data[14]="mcount";  $header[14]="Hours #";  $time[14]="month";
    $data[15]="mstates"; $header[15]="Changes";  $time[15]="month";
    $data[16]="lflaps";  $header[16]="Flaps";    $time[16]="lweek";
    $data[17]="lhour";   $header[17]="Uptime(%)"; $time[17]="lweek";
    $data[18]="lcount";  $header[18]="Hours #";  $time[18]="lweek";
    $data[19]="lstates"; $header[19]="Changes";  $time[19]="lweek";
    $fieldtotal = 20;         # total number of fields
    $special = 5;        # fields < this number are not max/min type fields
    for($i=0; $i < $fieldtotal; $i++) {
	$fndata{$data[$i]} = $i;
    }
}

sub field_num{
   my($name) = @_[0];
   if (defined($fndata{$name})) {
       return ($fndata{$name});
   } else {
       &log_error(field,$name);
       return (-1);
   }
}

sub save_src {
    my($a) = &field_num("addr");
    if ($a == -1) { return(-1); }
    my($src) = $array[$a];
    my($save) = $src;
    for($i = 1; $i < $fieldtotal; $i++) {
	$save = "$save $array[$i]";
    }
    $stats{$src} = $save;
}

sub new_src {
    $stats{$src} = "error -1 down 0 0 32 0 0 0 0 0 0 0 0 0 0 0 0 0 0";
    $active{$src} = "yes";
    my($a,$n,$s,$c,$m,$f,$u,$p,$s,$d);
    $a = &field_num("addr"); $n = &field_num("asnum");
    if (($a == -1) || ($n == -1)) { 
	return(-1); 
    }
    $array[$a] = $src;
    $array[$n] = "-2";
    $s = &field_num("state"); $c = &field_num("change"); 
    $d = &field_num("age"); 
    $m = &field_num("metric"); $f = &field_num("flaps");
    $u = &field_num("updates");
    if (($s==-1) || ($c==-1) || ($m==-1) || ($f==-1) || ($u==-1) || ($d==-1)) {
	return(-1);
    }
    $array[$s] = "down";
    $array[$c] = $dtime;
    $array[$d] = $dtime;
    $array[$m] = 32;
    $array[$f] = 0;
    $array[$u] = 0;
    $f = &field_num("wflaps");  $p = &field_num("whour"); 
    $n = &field_num("wcount");  $s = &field_num("wstates");
    if (($f == -1) || ($p == -1) || ($n == -1) || ($s == -1)) {
      	return(-1);
    }
    $array[$f] = 0;
    $array[$p] = 0;
    $array[$n] = 0;
    $array[$s] = 0; 
    $f = &field_num("mflaps");  $p = &field_num("mhour"); 
    $n = &field_num("mcount");  $s = &field_num("mstates");
    if (($f == -1) || ($p == -1) || ($n == -1) || ($s == -1)) {
	return(-1);
    }
    $array[$f] = 0;
    $array[$p] = 0;
    $array[$n] = 0;
    $array[$s] = 0;
    $f = &field_num("lflaps");  $p = &field_num("lhour"); 
    $n = &field_num("lcount");  $s = &field_num("lstates");
    if (($f == -1) || ($p == -1) || ($n == -1) || ($s == -1)) {
	return(-1);
    }
    $array[$f] = 0;
    $array[$p] = 0;
    $array[$n] = 0;
    $array[$s] = 0;
    &save_src;
    $newup++;
}

sub log_error {
    my($errname) = $_[0];
    my($errmesg) = $_[1];
    my($sc,$mn,$hr,$dy,$mo,$yr,$wd,$yd,$isd) = gmtime();
    $mo = $mo +1;
    if ($yr < 100) { 
        $yr = "19$yr"; 
    } else {
        $yr = $yr -100;
        $yr = "20$yr";
    }
    if ($hr < 10) { $hr = "0$hr"; }
    if ($mn < 10) { $mn = "0$mn"; }
    if ($sc < 10) { $sc = "0$sc"; }
    my($errdate) = "$mo/$dy/$yr $hr:$mn:$sc GMT";
    open(ERRORFILE, ">>$errorfile") ||
        die "Html Maker unable to open error log $errorfile\n";
    if ($errname eq "start") {
	print ERRORFILE "$errdate START: htmlmaker started\n";
    } elsif ($errname eq "webcopy") {
	print ERRORFILE "$errdate ERROR: copy to web server failed\n";
	print ERRORFILE "web copy script is: $errmesg\n";
	print ERRORFILE "DATA NOT COPIED TO WEB SERVER, RESUMING...\n";
    } elsif ($errname eq "nortemon") {
	print ERRORFILE "$errdate ERROR: route monitor has died\n";
	print ERRORFILE "LAUNCHING A NEW ROUTE MONITOR...\n";
    } elsif ($errname eq "copy") {
	print ERRORFILE "$errdate ERROR: unable to copy file to archives\n";
	print ERRORFILE "archive filename was: $errmesg \n";
	print ERRORFILE "DATA NOT ARCHIVED, RESUMING...\n";
    } elsif ($errname eq "nofile") {
	print ERRORFILE "$errdate ERROR: no route stats file exists\n";
	print ERRORFILE "CREATING NEW ROUTE STATS FILE...\n";
    } elsif ($errname eq "noupdate") {
	print ERRORFILE "$errdate ERROR: update triggered but no update file\n";
	print ERRORFILE "update file expected is: $errmesg\n";
	print ERRORFILE "UPDATE TRIGGER IGNORED, RESUMING...\n";
    } elsif ($errname eq "updatebegin") {
	print ERRORFILE "$errdate UPDATE: route stats update started\n";
    } elsif ($errname eq "updateend") {
	print ERRORFILE "$errdate UPDATE: route stats update completed\n";
    } elsif ($errname eq "updateend") {
	print ERRORFILE "$errdate UPDATE: route stats update signal recvd\n";
    } elsif ($errname eq "updateopen") {
	print ERRORFILE "$errdate ERROR: unable to open stats update file\n";
	print ERRORFILE "update file: $errmesg\n";
	print ERRORFILE "UPDATE TRIGGER IGNORED, RESUMING...\n";
    } elsif ($errname eq "updatestart") {
	print ERRORFILE "$errdate ERROR: wrong first update stats line:\n";
	print ERRORFILE "line is: $errmesg";
	print ERRORFILE "UPDATE TRIGGER IGNORED, RESUMING...\n";
    } elsif ($errname eq "updateline") {
	print ERRORFILE "$errdate ERROR: invalid update stats line:\n";
	print ERRORFILE "$errmesg";
	print ERRORFILE "LINE IGNORED, RESUMING...\n";
    } elsif ($errname eq "startline") {
	print ERRORFILE "$errdate ERROR: wrong first route stats line:\n";
	print ERRORFILE "line is: $errmesg";
	print ERRORFILE "invalid route stats file renamed .bak";
	print ERRORFILE "CREATING NEW ROUTE STATS FILE...\n";
    } elsif ($errname eq "statsline") {
	print ERRORFILE "$errdate ERROR: invalid route stats line:\n";
	print ERRORFILE "$errmesg\n";
	print ERRORFILE "LINE IGNORED, RESUMING...\n";
    } elsif ($errname eq "field") {
	print ERRORFILE "$errdate ERROR: unable to look up field $errmesg\n";
	print ERRORFILE "ATTEMPTING TO IGNORE FIELD, RESUMING...\n";
    } elsif ($errname eq "newtable") {
	print ERRORFILE "$errdate ERROR: unable to open new route table\n";
	print ERRORFILE "route monitor table in $errmesg \n"; 
    } elsif ($errname eq "tablestart") {
	print ERRORFILE "$errdate ERROR: wrong initial route table lines:\n";
	print ERRORFILE "line is: $errmesg";
	print ERRORFILE "NEW ROUTE TABLE IGNORED, RESUMING...\n";
    } elsif ($errname eq "oldtable") {
	print ERRORFILE "$errdate ERROR: route table age is too old\n";
	print ERRORFILE "table is $errmesg seconds old \n";
	print ERRORFILE "NEW ROUTE TABLE IGNORED, RESUMING...\n";
    } elsif ($errname eq "interval") {
	print ERRORFILE "$errdate ERROR: route table interval is incorrect\n";
	print ERRORFILE "route table interval was $errmesg minutes \n";
	print ERRORFILE "NEW ROUTE TABLE IGNORED, RESUMING...\n";
    } elsif ($errname eq "sumhtml") {
	print ERRORFILE "$errdate ERROR: unable to generate html summary\n";
	print ERRORFILE "html summary file is: $errmesg \n";
	print ERRORFILE "HTML PAGE NOT UPDATED, RESUMING...\n";
    } elsif ($errname eq "weekhtml") {
	print ERRORFILE "$errdate ERROR: unable to generate week html file\n";
	print ERRORFILE "html weekly worst file is: $errmesg \n";
	print ERRORFILE "HTML PAGE NOT UPDATED, RESUMING...\n";
    } elsif ($errname eq "monthhtml") {
	print ERRORFILE "$errdate ERROR: unable to generate month html file\n";
	print ERRORFILE "html monthly worst file is: $errmesg \n";
	print ERRORFILE "HTML PAGE NOT UPDATED, RESUMING...\n";
    } elsif ($errname eq "weekopen") {
	print ERRORFILE "$errdate ERROR: unable to open  week html file\n";
	print ERRORFILE "html weekly worst file is: $errmesg \n";
	print ERRORFILE "unable to copy current week into last week file\n";
	print ERRORFILE "HTML PAGE NOT UPDATED, RESUMING...\n";
    } elsif ($errname eq "lweekhtml") {
	print ERRORFILE "$errdate ERROR: unable to generate last week file\n";
	print ERRORFILE "html last week  worst file is: $errmesg \n";
	print ERRORFILE "HTML PAGE NOT UPDATED, RESUMING...\n";	
    } elsif ($errname eq "aspidfile") {
	print ERRORFILE "$errdate ERROR: unable to open as lookup pid file\n";
	print ERRORFILE "as lookup pid file is: $errmesg \n";
	print ERRORFILE "UNABLE TO UPDATE AS NUMBERS, RESUMING...\n";
    } elsif ($errname eq "asout") {
	print ERRORFILE "$errdate ERROR: unable to open as lookup results\n";
	print ERRORFILE "as lookup output file is: $errmesg \n";
	print ERRORFILE "UNABLE TO UPDATE AS NUMBERS, RESUMING...\n";
    } elsif ($errname eq "asline") {
	print ERRORFILE "$errdate ERROR: invalid line in as lookup results\n";
	print ERRORFILE "line is: $errmesg";
	print ERRORFILE "AS RESULTS LINE IGNORED, RESUMING...\n";
    } elsif ($errname eq "assrc") {
	print ERRORFILE "$errdate ERROR: as lookup result for unknown src\n";
	print ERRORFILE "source is $errmesg \n";
	print ERRORFILE "AS RESULTS FOR SOURCE IGNORED, RESUMING...\n";
    } elsif ($errname eq "asin") {
	print ERRORFILE "$errdate ERROR: unable to write as lookup requests\n";
	print ERRORFILE "as lookup input file is: $errmesg \n";
	print ERRORFILE "UNABLE TO UPDATE AS NUMBERS, RESUMING...\n";
    } elsif ($errname eq "asstart") {
	print ERRORFILE "$errdate ERROR: unable to launch aslookup\n";
	print ERRORFILE "$errmesg\n";
	print ERRORFILE "AS LOOKUP WILL RETRY NEXT HOUR, RESUMING...\n";
    } else {
        print ERRORFILE "$errdate ERROR: unidentified error code $errname:\n";
        print ERRORFILE "ERROR CODE IGNORED, RESUMING...\n";
    }
    close(ERRORFILE);
}

sub log_quit {
    my($errname) = $_[0];
    my($errmesg) = $_[1];
    my($sc,$mn,$hr,$dy,$mo,$yr,$wd,$yd,$isd) = gmtime();
    $mo = $mo + 1;
    if ($yr < 100) { 
        $yr = "19$yr"; 
    } else {
        $yr = $yr -100;
        $yr = "20$yr";
    }
    if ($hr < 10) { $hr = "0$hr"; }
    if ($mn < 10) { $mn = "0$mn"; }
    if ($sc < 10) { $sc = "0$sc"; }
    my($errdate) = "$mo/$dy/$yr $hr:$mn:$sc GMT";
    open(ERRORFILE, ">>$errorfile") ||
        die "Html Maker unable to open error log $errorfile\n";
    if ($errname eq "pid") {
	print ERRORFILE "$errdate ERROR: unable to write pid file $errmesg\n";
    } elsif ($errname eq "start") {
	print ERRORFILE "$errdate ERROR: unable to start route monitor\n";
	print ERRORFILE "route monitor executable is $errmesg\n";
    } elsif ($errname eq "statsfile") {
	print ERRORFILE "$errdate ERROR: unable to open existing stats file\n";
	print ERRORFILE "statsfile is $errmesg\n";
    } elsif ($errname eq "statwrite") {
	print ERRORFILE "$errdate ERROR: unable to write new stats file\n";
	print ERRORFILE "statsfile is $errmesg\n";
    } else {
        print ERRORFILE "$errdate ERROR: unidentified error code $errname:\n";
    }
    print ERRORFILE "FATAL ERROR, EXITING.\n";
    close(ERRORFILE);
    exit(-1);
}

