#!/usr/bin/perl -w

=head1 NAME

octo_pusher - Octopussy Pusher program

=head1 SYNOPSIS

octo_pusher

=head1 DESCRIPTION

octo_pusher is the program used by the Octopussy Project to parse 'no-syslog' Logs for 'no-syslog' Devices

=cut

use strict;
use File::Copy;
use File::Path;
use AAT;
use Octopussy;

my $PROG_NAME = "octo_pusher";
my $FTP_DIR= "/var/lib/octopussy/logs/_FTP_/";

my %conf;
my %device_dir;

my %month = ( Jan => "01", Feb => "02", Mar => "03", Apr => "04", 
	May => "05", Jun => "06", Jul => "07", Aug => "08", 
	Sep => "09", Oct => "10", Nov => "11", Dec => "12"  );

my @months = (undef, "Jan", "Feb", "Mar", "Apr", "May", "Jun", 
	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec");

=head1 FUNCTIONS

=head2 Init()

Inits Pusher

=cut
sub Init()
{
	%device_dir = ();
	AAT::Syslog($PROG_NAME, "Load Devices Configuration");
	my $storage = Octopussy::Storage::Default();
	foreach my $d (Octopussy::Device::Configurations("name"))
	{
		if ((defined $d->{logtype}) && ($d->{logtype} eq "asynchronous")
				&& (defined $d->{async}))
		{
			foreach my $as (@{$d->{async}})
			{
				push(@{$conf{$d->{name}}},
					{ regexp => qr/$as->{regexp}/, output => $as->{output} });
			}
			$device_dir{$d->{name}} = 
				Octopussy::Storage::Directory_Incoming($d->{name});
		}
	}		
}

=head2 Handle_Dir($device, $day, $month, $year)

Handles Directory ($device/$year/$month/$day)

=cut
sub Handle_Dir($$$$)
{
	my ($device, $day, $month, $year) = @_;

	if (!defined $device_dir{$device})
	{
  	if (!-f Octopussy::Device::Filename($device))
  	{
    	Octopussy::Device::New({ name => $device, address => $device,
      	description => "New Device !" });
			my $storage = Octopussy::Storage::Default();
    	$device_dir{$device} = Octopussy::Storage::Directory_Incoming($device);
  	}
	}
	$day = ($day < 10 ? "0" . $day : $day);
  my $dir_incoming =
    "$device_dir{$device}/$device/Incoming/$year/$month/$day";
	Octopussy::Create_Directory($dir_incoming);

	return ($dir_incoming);
}

=head2 Convert_To_Syslog($line, $device)

Converts line $line to a syslog line

=cut
sub Convert_To_Syslog($$)
{
	my ($line, $device) = @_;
	chomp($line);
	my $syslog = $line;
	foreach my $as (AAT::ARRAY($conf{$device}))
	{
		if (AAT::NOT_NULL($as->{output}))
		{
  		$syslog = $as->{output};
 			if (my @var = $line =~ /$as->{regexp}/)
 			{
				if ($syslog =~ /__localtime\((\d+)\)__/)
				{
					my ($sec, $min, $hour, $mday, $mon, $year) = localtime($var[$1-1]);
					$hour = ($hour < 10 ? "0$hour" : $hour);
					$min = ($min < 10 ? "0$min" : $min);
					$sec = ($sec < 10 ? "0$sec" : $sec);
					$mday = ($mday < 10 ? " $mday" : $mday);
					my $substitution = "$months[$mon] $mday $hour:$min:$sec";
					$syslog =~ s/__localtime\(\d+\)__/$substitution/g;
				}
  			$syslog =~ s/__(\d+)__/$var[$1-1]/g;
   			$syslog =~ s/__device__/$device/g;
				last;
			}
 		}
	}

	return ($syslog);	
}

=head2 Write_To_Incoming($dev, $year, $month, $mday, $hour, $min, @lines)

Writes to Incoming Directory

=cut
sub Write_To_Incoming
{
	my ($dev, $year, $month, $mday, $hour, $min, @lines) = @_;

	if ($#lines >= 0)
	{
		my $dir = Handle_Dir($dev, $mday, $month, $year);
 		my $file = "$dir/msg_$hour" . "h$min.log";
 		if (defined open(INCOMING, ">> $file"))
		{
 			foreach my $l (@lines)
  			{ print INCOMING "$l\n"; }
 			close(INCOMING);
 			Octopussy::Chown($file);
		}
		else
		{
     	print "Unable to open file '$file'\n";
     	AAT::Syslog("octo_pusher", "UNABLE_OPEN_FILE", $file);
    }
	}
}

#
# MAIN
#

my $device = undef;

my ($year, $month, $mday, $hour, $min) = AAT::Datetime::Now();
my ($n_year, $n_month, $n_mday, $n_hour, $n_min) = AAT::Datetime::Now();

$SIG{HUP} = \&Init;
Octopussy::PID_File($PROG_NAME);
AAT::Syslog($PROG_NAME, "Started !");

while (1)
{
	Init();
	opendir(DIR, $FTP_DIR);
	my @dirs = grep !/^\./, readdir(DIR);
	closedir(DIR);
	foreach my $d (@dirs)
	{
		if ((-d "$FTP_DIR$d") && (defined $conf{$d}))
 		{
   		opendir(DIR2, "$FTP_DIR/$d/");
    	my @files = grep !/^\./, readdir(DIR2);	
			foreach my $f (@files)
    	{
     		if (defined open(FILE, "$FTP_DIR/$d/$f"))
				{
					my @lines = ();
					while (<FILE>)
					{
						my $syslog = Convert_To_Syslog($_, $d);
						if ($syslog =~ /^(\w{3}) \s?(\d{1,2}) (\d\d):(\d\d):\d\d (\S+)/)
						{
							$device = $5;
							($n_min, $n_hour, $n_mday, $n_month, $n_year) = 
								($4, $3, $2, $month{$1}, ($month{$1} > $n_month ? $n_year - 1 : $n_year));
							if (($n_min ne $min) || ($n_hour ne $hour) || ($n_mday ne $mday) 
								|| ($n_month ne $month))
							{
								Write_To_Incoming($device, $year, $month, $mday, $hour, $min, @lines);
								($year, $month, $mday, $hour, $min) = 
									($n_year, $n_month, $n_mday, $n_hour, $n_min);
								@lines = ();
							}
							push(@lines, $syslog);  
						}
					}
					close(FILE);
					unlink("$FTP_DIR/$d/$f")	if (($#lines >= 0) || (-z "$FTP_DIR/$d/$f"));
					Write_To_Incoming($device, $year, $month, $mday, $hour, $min, @lines)	
						if (defined $device);	
				}
				else
      	{
        	print "Unable to open file '$f'\n";
        	AAT::Syslog("octo_pusher", "UNABLE_OPEN_FILE", $f);
      	}
  		}
    	closedir(DIR2);
		}
	}
	sleep(300);
}
