#!/usr/bin/perl -w
use strict; # $Id: monm 84 2019-07-10 15:13:28Z abalama $

=head1 NAME

monm - simple monitoring tool

=head1 SYNOPSIS

    monm [options] [commands [args]] 

    monm [-dltUvI] 

    monm [--debug] [--log] [--testmode] [--config=CONFIG_FILE] [--datadir=DATADIR]
         [ configure | checkit [NAMEs] | report [NAMEs] ]

    monm checkit www.example.com ftp.example.com

    monm report www.example.com ftp.example.com

    monm show

=head1 OPTIONS

=over 4

=item B<-c CONFIG_FILE, --config=CONFIG_FILE>

Full path of the configuration file. The configuration file allows determine the 
basic default settings, which will use the system if it fails to specify additional 
configuration files in $CONFDIR directory. The default system 
path /etc/monm/monm.conf

=item B<-D DATADIR, --datadir=DATADIR, --dir=DATADIR>

The directory of temporary files.

Default: system temp directory

=item B<-d, --debug>

Enable debug mode. In this mode, debug messages are displayed on the screen

=item B<-h, --help>

Show short help information and quit

=item B<-H, --longhelp>

Show long help information and quit

=item B<-l, --log>

Enabling write debug information to syslog or user log file.

Do not confuse the debug logging from regular logging to a file monm.log.
Regular logging allows you to store information in monm.log on the progress of the processes 
module, whereas debug logging for debugging of the internal components 
of the module.

To control the level of debugging see parameter LogEnable and LogLevel.

=item B<-t, --testmode>

Enabling test mode. This key allows force sending notification while checking

=item B<-v, --verbose>

Enabling at which displays information about the progress on the screen

=item B<-V, --version>

Print the version number of the program and quit

=back

=head1 COMMANDS

=over 4

=item B<configure>

Configure (initializing) of the App::MonM. This command should be performed
after the first installation of the module App::MonM

=item B<checkit>

Checking the status of services with the possibility of informing about the change of these states

=item B<report>

Creating a report on the checks

=item B<show>

Shows current table data of the checkit DB

If -v flag is specified - shows table as dump

=back

=head1 DESCRIPTION

Simple monitoring tool

=head1 AUTHOR

Serz Minus (Sergey Lepenkov) L<http://www.serzik.com> E<lt>abalama@cpan.orgE<gt>

=head1 COPYRIGHT

Copyright (C) 1998-2019 D&D Corporation. All Rights Reserved

=head1 LICENSE

This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

See L<https://dev.perl.org/licenses/>

=cut

use Getopt::Long;
use Pod::Usage;

use Cwd qw/getcwd/;
use File::Spec;

use CTK::FilePid;

use App::MonM;
use App::MonM::Const;

use constant {
    PIDMASK     => '%s.%s.pid',
    PIDREQS     => [qw/checkit report/],
};

$| = 1;  # autoflush

my $options = {};
Getopt::Long::Configure("bundling");
GetOptions($options,
    # NoUsed keys map:
    #
    # a A b B   C     e E
    # f F g G     i I j J
    # k K   L m M n N o O
    # p P q Q r R s S   T
    # u U     w W x X y Y
    # z Z

    # Information and debug
    "help|usage|h",         # Show help page
    "longhelp|H|?",         # Show long help page
    "version|vers|ver|V",   # Print VERSION of the App::MonM
    "debug|d",              # Debug mode
    "verbose|v",            # Verbose mode
    "log|l",                # Log mode
    "test|testmode|t",      # Test mode

    # CTK Application
    "config|conf|c=s",      # Config file
    "datadir|dir|D=s",      # DataDir

) || pod2usage(-exitval => 1, -verbose => 0, -output => \*STDERR);
pod2usage(-exitval => 0, -verbose => 1) if $options->{help};
pod2usage(-exitval => 0, -verbose => 2) if $options->{longhelp};
printf("Version: %s\n", App::MonM->VERSION) && exit(0) if $options->{version};

# VARS
my $command = shift(@ARGV) || '';
my @arguments = @ARGV;

my ($pidfile, $pidstat);
$SIG{INT} = sub {
    print STDERR "Trying interrupt...\n";
    $ENV{SIG_INT} = $ENV{SIG_INT} ? ($ENV{SIG_INT}+1) : 1;
    $pidfile->remove if $pidfile;
    die "Abnormally interrupted\n" if $ENV{SIG_INT} >= 2;
};

# App::MonM instance
my $app = new App::MonM(
        project => PROJECTNAME,
        prefix  => PREFIX,
        ($options->{config} && -e $options->{config} ? (configfile => $options->{config}) : ()),
        ($options->{datadir} ? (datadir => $options->{datadir}) : ()),
        options => $options,
        debug   => $options->{debug},
        verbose => $options->{verbose},
        log     => $options->{log},
        test    => $options->{test},
    );
pod2usage(-exitval => 1, -verbose => 99, -sections => 'SYNOPSIS|OPTIONS|COMMANDS', -output => \*STDERR)
    unless $command && grep {$_ eq $command} ($app->list_handlers());

if (grep {$_ eq $command} @{(PIDREQS())}) {
    $pidfile = new CTK::FilePid({
        file => File::Spec->catfile($app->tempdir(), sprintf(PIDMASK, PREFIX, $command))
    });
    $pidstat = $pidfile->running || 0;
}

if ($pidfile) {
    die(sprintf("Already running (%s, PID=%s)", $pidfile->file(), $pidstat)) if $pidstat;
    $pidfile->write;
}

# Run
my $exitval = $app->run($command, @arguments) ? 0 : 1;
printf STDERR "%s\n", $app->error if $exitval && $app->error;

$pidfile->remove if $pidfile;

exit $exitval;

1;

__END__
