#!/usr/bin/perl -w
use strict; # $Id: monm 136 2022-09-09 15:37:03Z abalama $

=encoding utf8

=head1 NAME

monm - simple monitoring tool

=head1 SYNOPSIS

    monm [options] [commands [args]]

    monm [-dltUvI]

    monm [-c CONFIG_FILE] [-d DATADIR]
         [ configure | checkit [NAMEs] | report [Emails] 
           | info | remind | show ]

    monm configure [/tmp/testconf]

    monm checkit foo bar baz

    monm report -o /tmp/report.msg
    monm report foo@example.com bar@example.com

    monm remind

    monm info
    monm -D info

    monm show
    monm -D 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 (/tmp/monm)

=item B<-D, --daemondir>

Use sharedstatedir (/var/lib/monm) directory of daemon process

=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<-o OUTPUTFILE, --outfile=OUTPUTFILE>

Sets path to file for output (for reports, eg.)

=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

    monm configure /root/monm

This example shows how to extract configuration into NON system directory /root/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

=item B<info>

Shows statistic data, tests config file

=item B<remind>

Retries sending notifies

=back

=head1 DESCRIPTION

Simple monitoring tool

=head1 AUTHOR

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

=head1 COPYRIGHT

Copyright (C) 1998-2022 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/],
};

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
    # p P q Q r R s S t 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
    "verbose|v",            # Verbose mode
    "log|l",                # Log mode

    # CTK Application
    "config|conf|c=s",      # Config file
    "datadir|dir|d=s",      # DataDir
    "daemondir|D",          # Daemon dir (/var/lib/monm) as datadir

    # MonM Application
    "outfile|o=s",          # Output file

) || 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 = App::MonM->new(
        project => PROJECTNAME,
        prefix  => PREFIX,
        ($options->{config} && -e $options->{config} ? (configfile => $options->{config}) : ()),
        ($options->{datadir} ? (datadir => $options->{datadir}) : ()),
        options => $options,
        verbose => $options->{verbose},
        log     => $options->{log},
    );
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 = CTK::FilePid->new({
        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__
