#!/usr/bin/env perl

# Use mandatory external modules
use strict;
use Cwd;
use File::Basename;
use Data::Dumper;
use POSIX;
use Config;
use Getopt::Long;
use IO::Socket;
use Proc::Daemon;
use Time::HiRes;

# Determine installation dir name
our $SELF_DIR = dirname(dirname(Cwd::abs_path(__FILE__)));

# Include parts of the system
require $SELF_DIR . '/lib/version.pm';
require $SELF_DIR . '/lib/config.pm';
require $SELF_DIR . '/lib/log.pm';

#-----------------------------------------------------------------
# Say hello
PrintVersion();

#-----------------------------------------------------------------
# Read config file
my $cfg_file = "mmm_angel.conf";
our $config = ReadConfig($cfg_file);

my $shutdown = 0;

# Go to background
Proc::Daemon::Init if ($config->{debug} =~ /^(off|no|0)$/i);
CreatePidFile();

# Catch signals
$SIG{INT} = \&SignalHandler;
$SIG{TERM} = \&SignalHandler;

# Call main function
DaemonMain();

exit(0);

#-----------------------------------------------------------------
sub DaemonMain() {
    while (!$shutdown) {
        foreach my $service (keys(%{$config->{service}})) {
            my $s = $config->{service}->{$service};
            next if ($s->{disabled});
            
            CheckService($s);
        }

        # sleep before next check
        sleep($config->{check_period});
    }
}

#-----------------------------------------------------------------
sub CheckService($) {
    my $service = shift;
    
    LogDebug("Checking service: $service->{description}");
    
    my $pid = $service->{pid};
    my $cmd = $service->{command};
    
    if (CheckPid($pid)) {
        LogDebug("Service '$service->{description}' is OK");
        return 1;
    }
    
    LogTrap("Warning: Service '$service->{description}' is dead! Restarting it...");
    my $res = system("nohup $cmd &> /dev/null &");
    if ($res) {
        LogError("Error: Can't execute command: '$cmd'");
        SendEmailNotice("'$service->{description}' is dead! Restart try failed!");
        return 1;
    }
    
    sleep(5);

    if (CheckPid($pid)) {
        LogTrap("Notice: Service '$service->{description}' has been restarted successfully");
        SendEmailNotice("'$service->{description}' was dead! Restarted successfully!");
        return 1;
    }

    LogTrap("Error: Service '$service->{description}' could not be restarted");
    SendEmailNotice("'$service->{description}' is dead! Restart failed!");
}

#-----------------------------------------------------------------
sub CheckPid($) {
    my $pid_file = shift;

    open(PID, $pid_file) || return 0;
    chomp(my $pid = <PID>);
    close(PID);
    
    return 0 unless ($pid);
    return 0 unless (kill(0, $pid));

    return 1;
}

#-----------------------------------------------------------------
sub SignalHandler() {
    LogDebug("Core: Signal received: exiting...");
    $shutdown = 1;
}

#-----------------------------------------------------------------
sub SendEmailNotice($) {
    my $msg = shift;
    my $now = strftime("%Y-%m-%d %H:%M:%S", localtime);
    
    my $sendmail = "/usr/sbin/sendmail -t";
    my $res = open(SENDMAIL, "|$sendmail");
    unless ($res) { 
        LogError("Error: Cannot open $sendmail: $!");
        return 1;
    }
    print SENDMAIL "From: mmm_mon\@kovyrin.net\n";
    print SENDMAIL "Subject: [$now] MMM Service failure\n";
    print SENDMAIL "To: $config->{admin_email}\n\n";
    print SENDMAIL "$now: $msg\n";
    close(SENDMAIL);
}
