#!/usr/bin/perl

eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
    if 0; # not running under some shell
#
#   Vispan - VIrus and SPam ANalyser
#	This program analyses the mail log file entries created by the 
#	MailScanner program written by Julian Field. It is available at
#	http://www.mailscanner.info
#
#   Copyright (C) 2002  David While
#
#   $Id: Vispan,v 1.26 2004/12/17 11:04:35 dwhile Exp $
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 2 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program; if not, write to the Free Software
#   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
#   The author, David While, can be contacted by email at
#      david.while@uce.ac.uk
#   or by paper mail at
#      David While
#      School of Computing
#      University of Central England
#      Birmingham
#      B42 2SU
#      United Kingdom
#

use POSIX qw(strftime);
use POSIX qw(printf);

use Vispan::Setup;
use Vispan::Config;
use Vispan::Stats;
use Vispan::ProcessLog;
use Vispan::Sendmail;
use Vispan::Postfix;
use Vispan::Mailscanner;
use Vispan::Print;
use FileHandle;
use Getopt::Std;

#use strict;


# You should not need to change anything below here.
$VERSION="2.0.2";

sub usage {
   print "Usage is: $0 [-r IP] [-f file]\n";
   exit;
}

main: {
   my ($Workdir, $Line);
   # Find the Vispan.conf file, with a default just in case.

   my $opt_string = 'hr:f:';
   getopts("$opt_string", \%opt ) or usage();

   if (defined $opt{f} ) {
      $ConfFile = $opt{f};
      }

   $ConfFile = '/etc/Vispan.conf' unless $ConfFile;
   die "Can't find Configuration file at: $ConfFile" if(! -e $ConfFile);
	   
   # Read the configuration values from the file
   Config::ReadConfFile($ConfFile);

   $WorkDir = Config::Value(WorkDir);

   # Read the existing stats into the has arrays.
   Stats::ReadWorkFile($WorkDir);

   if (defined $opt{r} ) {
      if( Stats::CommandRemove($opt{r}) == 1 ) {
         while( check_lock() ) {
            sleep(1);
            }
         Stats::WriteWorkFile($WorkDir);
         }
      exit;
      }

   if (defined $opt{h} ) {
      usage();
      }

   my $AutoUpdateSeen = 0;

   $Debug = Config::Value(Debug) || 0;
   # Check to see if the working directory exists - if not create it.
   Setup::BuildWorkingEnvironment("$WorkDir") if ( ! -e "$WorkDir" );
   Setup::BuildHTMLEnvironment("$HTMLDir") if ( ! -e "$HTMLDir" );

   # First check to see if mailstats is already running - if so exit
   if ( check_lock() ) {
      exit 1;
      }

   open (PID, ">$WorkDir/mailstats.lck");
   print PID "$$";
   close PID;

   # Create the temporary log file to process
   ProcessLog::CreateTmpLog();

   # Work through the temporary file building up the stats.
   $file = Config::Value(tmpfile);
   open(LOG, "<$file");
   while($Line = <LOG>) {
      chomp($Line);
	  # Check to see if we want to look at this servers logs
	  $servers_to_lookat_list = Config::Value(ServersToLookAt);
	  
	  print "$servers_to_lookat_list\n" if($Debug);
	  @servers_to_lookat = split(/\s+/, $servers_to_lookat_list);
	  if($servers_to_lookat[0] ne ''){
		 $found_server = 0;
		 foreach $server (@servers_to_lookat){
			 @parsed_line = split(/\s+/, $Line);
			 $found_server = 1 if($parsed_line[3] eq $server);
			 print "Server to Look at: $server\n" if($Debug);
		 }
		 print "$parsed_line[3] is" if($Debug);
		 print " not" if((! $found_server) && ($Debug));
		 print " on the list\n" if($Debug);
		 next if(! $found_server);
	  }
	  print "Running Line: $Line\n" if($Debug);
      # Check the date of the last virus definition update
      if ( $Line =~ /.*autoupdate\[.* updated/i) {
         ($VirUpdate, $Scanner) = ($Line =~ /^(...... ..:..:..) .* (.*).autoupdate\[.*updated/);
         Stats::AddVirDate($VirUpdate, $Scanner);
         $AutoUpdateSeen = 1;
         }

      # We are only interested in the mailscanner log entries.
      if ( $Line =~ /MailScanner\[/i) {
         Mailscanner::ProcessLine($Line);
         }

      # Not a mailscanner line so lets find the number of messages sent.
      $SMString = Config::Value(SMLogString);
      if ($Line =~ /$SMString/i) {
         Sendmail::ProcessLine($Line);
         }

      # Check for Postfix entries
      if ( $Line =~ /postfix/) {
         Postfix::ProcessLine($Line);
         }
      }

   Mailscanner::printScannerNames() if($Debug);

   Mailscanner::GetLocalVerNums if ($AutoUpdateSeen);

   close LOG;

   Stats::SortData;

   Stats::MoveStats;

   Stats::WriteWorkFile($WorkDir);

   system("rm $WorkDir/mailstats.lck");
}

sub check_lock {
   my $PID;
   my $WorkDir = Config::Value(WorkDir);

   if( open(PID, "$WorkDir/mailstats.lck") ) {
      $PID = <PID>;
      close PID;

      if( kill 0 => $PID ) {
         # There is another Vispan running
         return 1;
         }
      else {
         # This is a stale lock file
         system("rm $WorkDir/mailstats.lck");
         return 0;
         }
      }
   else {
      # no lock file exists
      return 0;
      }
}

