#!/usr/bin/perl
#
# Action module for Ant monitoring system
#
# Sends mail with report to admin.
# Aggregates several reports in one mail, and send message in specified time
#
# Agruments:
#      - e-mail(s) via comma where to send mails to.
#      - scedule in format: wd.hh:mm|hh:mm|mm, where wd=1-7, hh=00-23, mm=00-59
#        fields can be intervals (a-b) and enumerated (1,3,5)
#        fields hh and mm can be * or */N (N=number), field wd can be *
#
#        NOTE: format M/N (e.g. 3/15) IS NOT SUPPORTED!
#
#      e.g. root@localhost 1-5.00,06,12,18:*/15

use Fcntl;
use IO::File;

sub send_n_exit( $ );
sub sendit( );


$ENV{PATH}="/usr/sbin";

$SIG{USR1}=sub { sendit();};
$SIG{HUP} =sub { sendit();};
$SIG{TERM}=sub { send_n_exit("TERM");};
$SIG{QUIT}=sub { send_n_exit("QUIT");};
$SIG{PIPE}=sub { send_n_exit("PIPE");};

$|=1;

$,=' ';

my $line;
my %tosend;
my $counter=0;
my ($p,$p2,$i,$j,$h,$m,$d,%scedule,%hours,%days,%mins);

chomp @ARGV;
my $to=shift @ARGV;

fcntl(STDIN,F_SETFL,fcntl(STDIN,F_GETFL,0)|O_NONBLOCK);

sub action();
sub sendit();

## add scedules

foreach $i (@ARGV){
  my ($min,$day,$hour,@x,$j);
  $i =~ /(.*\.)?(.*:)?(.*)/ or next;
  ($day,$hour,$min)=($1,$2,$3);

  %days=();
  if($day ne ''){
    substr($day,-1,1)='';
    if($day eq '*'){
      $days{1}=$days{2}=$days{3}=$days{4}=$days{5}=$days{6}=$days{0}=1;
    }
    else{
      @x=split(/,/,$day);
      foreach $j (@x){$days{$j}=1;}
      $days{0}=1 if exists $days{7};
    }
  }
  else{
      $days{1}=$days{2}=$days{3}=$days{4}=$days{5}=$days{6}=$days{0}=1;
  }

  @x=();
  if($hour ne ''){
    substr($hour,-1,1)='';
    if($hour eq '*'){
      @x=0..23;
    }
    elsif($hour =~ m{^\*/(\d+)}){
      foreach $j (0..23){
        push @x, $j if($j%$1==0);
      }
    }
    else{
      @x=split(/,/,$hour);
    }
  }

  @y=();
  if($min eq '*'){
    @y=0..59;
  }
  elsif($min =~ m{^\*/(\d+)}){
    foreach $j (0..59){
      push @y, $j if($j%$1==0);
    }
  }
  else{
    @y=split(/,/,$min);
  }
  foreach $h (@x){
    foreach $m (@y){
      foreach $d (keys(%days)){
        $scedule{"$d:$h:$m"}=1;
      }
    }
  }

}


shift while $#ARGV>=0;
$0='action-restrictmail: nothing to send yet';

$counter=6;

for(;;){
  $line='';
INNER_LOOP:
  for(;;){
    while(read(STDIN,$p,1)>0){
      $line.=$p;
      last INNER_LOOP if $p eq "\n" and $p2 eq "\n";
      $p2=$p;
    }
    if(--$counter==0){
      $counter=6;
      (undef,$min,$hour,undef,undef,undef,$wday)=localtime(time);
      if(exists($scedule{"$wday:$hour:$min"})){
        sendit();
        %tosend=();
      }
      select(undef,undef,undef,0.15);
    }
  }
  action();
}

sub action( ){
  $line =~ /^([^\n]*)\n(.*)/s;

  $tosend{$1}.=$2;
  $counter=50 if($counter==0);
  ##print "push it ($1) $counter ...\n";
  $0='action-restrictmail: some messages to send!';
}


sub sendit(){
  my $i;
  foreach $i (keys(%tosend)){
    ## print "Send it ($i)!!!\n$tosend{$i}\n";
    open MAIL,"|sendmail '$to'" or die "Cannot run sendmail!";
    print MAIL <<MAIL_BODY;
To: $to
Subject: $i

$tosend{$i}
MAIL_BODY

    close MAIL;
  }
  %tosend=();
  $0='action-restrictmail: nothing to send yet';
}

sub send_n_exit( $ ){
  print "Signal: $_[0]\n";
  STDOUT->flush();
  exit 0;
}
