package App::Mangemanche; use strict; use warnings; use Getopt::Long qw(:config gnu_getopt no_ignore_case require_order); use Pod::Man; use Pod::Usage; use Pod::Find qw(pod_where); use Net::Ping903; use App::Mangemanche::Command ':exit_codes'; use File::Basename; our $VERSION = '0.8'; my $DEFAULT_URL = 'http://localhost:8080'; my $LICENSE = <<'EOT' Copyright (C) 2020 Sergey Poznyakoff License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. EOT ; sub new { my $class = shift; my $config_file; my $url; my $config = {}; GetOptions( 'shorthelp|?' => sub { pod2usage(-input => pod_where({-inc => 1}, $class), -verbose => 99, -sections => [qw(NAME SYNOPSIS COMMANDS)], -exitstatus => 'NOEXIT'); $class->list_commands; exit(EX_OK); }, 'help' => sub { App::Mangemanche::Command::mandoc($class, basename($0)), }, 'usage' => sub { pod2usage(-exitstatus => EX_OK, -input => pod_where({-inc => 1}, $class), -verbose => 0) }, 'version' => sub { print "$0 version $VERSION\n"; print $LICENSE,"\n"; exit(EX_OK); }, 'config|c=s' => \$config_file, 'url|u=s' => \$url ) or exit(EX_USAGE); if ($config_file) { if (-f $config_file) { $config = $class->readconfig($config_file); } else { die "configuration file $config_file does not exists\n"; } } else { $config_file = '/etc/ping903.conf'; if (-f $config_file) { $config = $class->readconfig($config_file); } } if ($url) { $config->{baseurl} = $url; } elsif (!$config->{baseurl}) { $config->{baseurl} = $DEFAULT_URL; } unless ($config->{baseurl} =~ m{^https?://}) { $config->{baseurl} = "http://$url"; } my $agent = new Net::Ping903($config->{baseurl}); my $com = shift @ARGV; die "no command name\n" unless $com; my $modname = __PACKAGE__ . '::Command::' . $com; my $modpath = $modname; $modpath =~ s{::}{/}g; $modpath .= '.pm'; my $cmd; eval { require $modpath; $cmd = $modname->new($com, $agent); }; if ($@) { if ($@ =~ /Can't locate $modpath/) { die "unknown command: $com\n" } die $@; } return $cmd; } sub readconfig { my ($class, $file) = @_; my $config = {}; if (open(my $fh, '<', $file)) { while (<$fh>) { chomp; s/^\s+//; s/\s+$//; next if /^(#.*)?$/; if (m{^listen\s+(.+)$}) { $config->{baseurl} = $1; last; } } close $fh; } else { die "$file: file doesn't exist\n"; } return $config; } sub list_commands { my $class = shift; my @classpath = (split(/::/, $class), 'Command'); print "\nAvailable commands are:\n"; foreach my $mod (sort map { my $name = basename($_); my $filename = File::Spec->catfile(@classpath,$name); if (exists($INC{$filename})) { () } else { eval { require $filename; }; $name =~ s/\.pm$//; $@ ? () : [$name, $_]; } } map { glob File::Spec->catfile($_, @classpath, '*.pm') } @INC) { my $s; open(my $fh, '>', \$s); pod2usage(-input => $mod->[1], -output => $fh, -verbose => 99, -sections => ['NAME'], -exitstatus => 'NOEXIT'); close $fh; my (undef, $descr) = split("\n", $s||''); unless ($descr) { $descr = ' ' . $mod->[0] } print "$descr\n"; } } 1; =head1 NAME mangemanche - remote management interface to B daemon. =head1 SYNOPSIS B [B<-c> I] [B<-u> I] [B<--config=>I] [B<--url=>I] I I... B [B<-?>] [B<--help>] [B<--usage>] [B<--version>] =head1 DESCRIPTION Mangemanche provides remote management facilities for the running B daemon. First non-optional argument specifies the name of the I to run. Arguments following it supply options and arguments to that command. Mangemanche reads the IP address and port number of the B management socket from its configuration file, F. If the file does not exist, the default port (B) is used. The location of both can be overridden in the command line. If the server requests HTTP authorization, the program will look up the authorization credentials in the B<.ping903.cred> file located in the home directory. Refer to L(5) for a detailed description. =head1 OPTIONS =over 4 =item B<-c>, B<--config=>I Specifies alternative configuration file to use instead of F. =item B<-u>, B<--url=>I Sets the URL of the B management socket. =back =head2 Informative options Each of these options causes the program to display a particular piece of information and exit with the zero status. Any other options and arguments are ignored. =over 4 =item B<-?> Displays a short option reminder and lists the available commands with their short descriptions. =item B<--help> Displays this manual page. =item B<--usage> Displays a terse command line usage summary. =item B<--version> Displays the program version and copyright information. =back =head1 COMMANDS This section summarizes the basic B commands. Your installation may provide more. Use B to obtain the list of available command. To see the manual for each particular command, run mangemanche COMMAND --help =head2 ident Displays B server identification: package name, version number, and main process PID. =head2 inspect Displays the actual B server configuration. =head2 ipadd Adds a single IP to the mutable list of monitored IP addresses. =head2 ipdel Deletes a single IP from the mutable list of monitored IP addresses. =head2 nagios Extracts the list of monitored IP addresses from the Nagios configuration and installs them in B. =head2 dbload Load IP addresses from SQL database into B. =head1 SEE ALSO L(1), L(5), L(5). =cut