#!/usr/bin/perl
require "./preferences.pl";

$email = $Email;
if (eval "use Mail::Mailer") {
    $email = "";
}

if ($DEMO) { print "Auto Recheck not available in DEMO mode.\n"; exit; }

($pidfile, $interval, $iip, $portmask, $discover) = @ARGV;
$iip =~ s/\*$/1-254/ if $discover;

exit unless $pidfile;
$interval *= 60;

$pid = fork if $interval > 0;

if ($interval > 0) {
  exit if $pid;
  die "Couldn't fork: $!" unless defined($pid);
}

sub CreateDir {
    my $filename = shift || die "Unable to create a null directory.";
    my @dirs = split(/\//, $filename);
    pop @dirs;     #Filename part
    unshift @dirs; #Root part
    my $dir = "";
    foreach (@dirs) {
      $dir .= "/" . $_;
      mkdir($dir,0775) unless -d $dir;
      die("Unable to create directory: $dir") unless -d $dir;
    }
    return 1;
}

sub ip2file {
    return $Basedir . '/' . join('/', split(/\./, shift));
}

sub SendMail {
    my($status, $ip, $email) = @_;
    return unless ($ip and $email);
    $mail = new Mail::Mailer;
    eval "use Sys::Hostname; $hostname = hostname();";
    my $from = $myName.' <'.($< || 'root').'@'.($hostname || $ENV{'HOSTNAME'} || 'localhost').'>'; 
    my $type = ($status == $Stat_fail) ? "Failure" : "Recovery";
    $mail->open( { From => $from,
                   To   => $email,
                   Subject => "nPULSE Status Message (Site $type) from $ip" } ) || die $!;
    print $mail "Status message from $from\nSite $type reported for $ip\n";
    close($mail);
}

sub ReadConfigfile {
    local(*F);
    my(@out) = ();
    open(F, "<$Configfile") || exit;
    @out = <F>;
    close(F);
    chomp @out;
    return wantarray ? @out : join("\n",@out);
}

sub signal_handler {
    $time_to_die = 1;
}

$SIG{INT} = $SIG{TERM} = $SIG{HUP} = \&signal_handler;

open(F, ">$pidfile") || die "Unable to open $pidfile";
print F $$;
close(F);

until ($time_to_die) {

  undef @cmds;
  if ($discover)    { push(@cmds, $Nmapcmd." --min_rtt_timeout 100 -v -oM - -sT '".$iip."' 2>/dev/null | grep \"Host: \""); }
  elsif ($portmask) { push(@cmds, $Nmapcmd." --min_rtt_timeout 100 -v -oM - -sT -p '".$portmask."' '".$iip."' 2>/dev/null | grep \"Host: \""); } 
  elsif (!$ip)      { foreach (&ReadConfigfile()) { ($ipmask, $portmask) = split / /; push(@cmds, $Nmapcmd." --min_rtt_timeout 100 -v -oM - -sT -p '".$portmask."' '".$ipmask."' 2>/dev/null | grep \"Host: \""); } }
  else              { push(@cmds, $Nmapcmd." --min_rtt_timeout 100 -v -oM - -sT '".$iip."' 2>/dev/null | grep \"Host: \""); }
  
  undef @output;
  foreach $cmd (@cmds) {
    @out = `$cmd`;
    chomp @out;
    push(@output, @out);
  }

  if ($discover) {
    open(F, ">$Configfile") || die $!;
    $interval = 0;
    $email = "";
  } else {
    open(F, ">$Currentfile") || die $!;
  }

  foreach (@output) {
    ($host, @rest) = split /\t/;
    $host =~ s/^Host: //;
    ($ip, $name) = split(/ /, $host);
    $name =~ s/\(|\)//g;
    unless ($ip) { $ip = $name; $name = ""; }

    if ($discover) {
      $ports = $rest[0];
      next unless $ports =~ /^Ports/;
      $ports =~ s/^Ports: //;
      $portmask = "";
      foreach (split(/,\s*/, $ports)) { $portmask .= (split(/\//,$_))[0].","; }
      chop $portmask;
      print F $ip," ",$portmask,"\n";

    } else {
      $filename = $Basedir . '/' . join('/', split(/\./, $ip)) . ".hist";
      &CreateDir($filename) unless -f $filename;
      open(G, ">>$filename") || die $!;
      print G time,"\tHost: ",$ip," (",$name,")\t",join("\t",@rest),"\n";
      close(G);
      print F "Host: ",$ip," (",$name,")\t",join("\t",@rest),"\n";
      if ($email) {
        $efilename = $Basedir . '/' . join('/', split(/\./, $ip)) . ".email";
        if ($rest[0] =~ /^Status: Down/) {
          unless (-f $efilename) {
            &SendMail($Stat_fail, $ip, $email);
            open(E, ">$efilename"); print E time," Down"; close(E);
          }
        } elsif (-f $efilename) {
          &SendMail($Stat_ok, $ip, $email);
          unlink($efilename);
        }
      }
    }
  }
  close(F);

  if ($interval > 0) { sleep($interval); } else { $time_to_die = 1; }
}

unlink($pidfile);
exit;
