#!/usr/local/bin/perl
#
# modified to customize for this webmin module of MON-dt 09th sept 2001
# monshow - concise, user view-based opstatus summary
#
# Jim Trocki, trockij@transmeta.com
#
# $Id: monshow 1.1 Sat, 26 Aug 2000 12:22:34 -0700 trockij $
#
# Copyright (C) 1998, Jim Trocki
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
require './mon-lib.pl';
&init_config();
&ui_print_header(undef, $text{'mon_status_title'}, "","monshow");
print "
\n";
use strict "vars";
use Getopt::Long;
use English;
use CGI;
use Text::Wrap;
use Mon::Client;
use Data::Dumper;
#
# forward declarations
#
sub usage;
sub get_auth;
sub read_cf;
sub err_die;
sub expand_watch;
sub secs_to_hms;
sub display_allok;
sub compose_detail;
sub compose_header;
sub compose_disabled;
sub compose_table;
sub compose_trailer;
sub get_client_status;
sub opstatus_color;
sub tdiff_string;
#
# set this to the path of your view configuration files
#
my $VIEWPATH = "/etc/mon/monshow";
#my $VIEWPATH = "/home/trockij/monshow";
my %OPSTAT = %Mon::Client::OPSTAT;
my $WORD = '[a-zA-Z0-9_-]+';
my $OUT_BUF = "";
my $e;
$= = 1000;
$SIG{INT} = \&handle_sig;
$SIG{TERM} = \&handle_sig;
my ($DEP, $GROUP, $SERVICE, $STATUS, $TIME, $NEXT, $ALERTS, $SUMMARY, $DESC);
my %opt;
GetOptions (\%opt, "showall", "auth", "help", "full", "disabled",
"rcfile=s", "login=s", "server=s", "port=i", "prot=s",
"detail=s", "view=s");
my $CGI;
my %QUERY_ARGS;
if (defined $ENV{"REQUEST_METHOD"})
{
$CGI = new CGI;
}
if (!$CGI && $opt{"help"})
{
usage;
exit 1;
}
if ($CGI)
{
foreach my $e (split (/\?/, $ENV{"QUERY_STRING"}))
{
next if ($e !~ /=/);
my ($var, $val) = split (/=/, $e);
$QUERY_ARGS{$var} = $val;
}
}
my $CF = {
"full" => 0,
"show-disabled" => 0,
"bg" => "d5d5d5",
"bg-ok" => "a0d0a0",
"bg-fail" => "FF66FF",
"bg-disabled" => "FAEBD7",
"bg-untested" => "e0e0e0",
"table-color" => "cccccc",
};
my $GLOBAL = {
"view-name" => undef,
};
#
# read config file
#
my ($e, $what) = read_cf ($CF);
if ($e ne "")
{
err_die ("while reading config file, $e");
}
#
# cmdline args override config file
#
if (!$CGI)
{
$CF->{"all"} = 1 if ($opt{"showall"});
$CF->{"full"} = 1 if ($opt{"full"});
$CF->{"detail"} = $opt{"detail"} if ($opt{"detail"} ne "");
$CF->{"host"} = $opt{"server"} if ($opt{"server"});
$CF->{"port"} = $opt{"port"} if ($opt{"port"});
$CF->{"prot"} = $opt{"prot"} if ($opt{"prot"});
}
#
# retrieve client status
#
my ($e, $st) = get_client_status ($what);
if ($e ne "")
{
err_die ($e);
}
expand_watch ($what, $st);
my $rows = select_table ($what, $st);
compose_header ($st->{"state"});
#
# CGI invocation
#
if ($CGI)
{
if ($QUERY_ARGS{"disabled"})
{
compose_disabled ($st->{"disabled"});
}
elsif (!$QUERY_ARGS{"detail"})
{
compose_table ($rows, $st);
compose_disabled ($st->{"disabled"}) if ($CF->{"show-disabled"});
}
elsif ($QUERY_ARGS{"detail"})
{
compose_detail ($QUERY_ARGS{"detail"}, $st);
}
}
#
# cmdline invocation
#
else
{
if ($opt{"disabled"})
{
compose_disabled ($st->{"disabled"});
}
elsif ($CF->{"detail"} ne "")
{
compose_detail ($CF->{"detail"}, $st);
}
else
{
compose_table ($rows, $st);
compose_disabled ($st->{"disabled"}) if ($CF->{"show-disabled"});
}
}
compose_trailer;
if ($CGI)
{
#Content-type: text/html
print <
EOF
&footer("./","MON Index page");
}
else
{
print "\n";
}
exit;
#-----------------------------------------------------------------------------
format STDOUT_TOP =
GROUP SERVICE STATUS LAST NEXT ALERTS SUMMARY
.
#
# usage
#
sub usage
{
print <query ("login");
$pass = $CGI->query ("password");
}
else
{
if ($opt{"login"})
{
$login = $opt{"login"};
}
else
{
return "could not determine username"
if (!defined ($login = getpwuid($EUID)));
}
if (-t STDIN)
{
system "stty -echo";
print "Password: ";
chop ($pass = );
print "\n";
system "stty echo";
return "invalid password" if ($pass =~ /^\s*$/);
}
else
{
my $cmd;
while (defined ($cmd = <>))
{
chomp $cmd;
if ($cmd =~ /^user=(\S+)$/i)
{
$login = $1;
}
elsif ($cmd =~ /^pass=(\S+)$/i)
{
$pass = $1;
}
last if (defined ($login) && defined ($pass));
}
}
}
return "inadequate authentication information supplied"
if ($login eq "" || $pass eq "");
return ("", $login, $pass);
}
#
# config file
#
sub read_cf
{
my $CF = shift;
my ($group, $service);
my @RC;
my $view = 0;
my $RC = "/webmin-0.87/mon/monshowrc";
if ($CGI)
{
if ($ENV{"PATH_INFO"} =~ /^\/\S+/)
{
my $p=$ENV{"PATH_INFO"};
$p =~ s/^[.\/]*//;
$p =~ s/\/*$//;
$p =~ s/\.\.//g;
$RC = "$VIEWPATH/$p";
$GLOBAL->{"view-name"} = $p;
$view = 1;
}
elsif ($QUERY_ARGS{"view"} ne "")
{
$QUERY_ARGS{"view"} =~ s/^[.\/]*//;
$QUERY_ARGS{"view"} =~ s/\.\.//g;
$GLOBAL->{"view-name"} = $QUERY_ARGS{"view"};
$RC = "$VIEWPATH/$QUERY_ARGS{view}";
$view = 1;
}
elsif (-f ".monshowrc")
{
$RC = ".monshowrc";
}
}
else
{
if ($opt{"rcfile"})
{
$RC = $opt{"rcfile"};
}
elsif ($opt{"view"} ne "")
{
$RC = "$VIEWPATH/$opt{view}";
$GLOBAL->{"view-name"} = $opt{"view"};
$view = 1;
}
elsif (-f "$ENV{HOME}/.monshowrc")
{
$RC = "$ENV{HOME}/.monshowrc";
}
}
if ($opt{"old"})
{
$CF->{"prot"} = "0.37.0";
$CF->{"port"} = 32777;
}
if (-f $RC)
{
open (IN, $RC) || return "could not read $RC: $!";
my $html_header = 0;
my $link_text = 0;
my $link_group = "";
my $link_service = "";
while ()
{
next if (/^\s*#/ || /^\s*$/);
if ($html_header)
{
if (/^END\s*$/)
{
$html_header = 0;
next;
}
else
{
$CF->{"html-header"} .= $_;
next;
}
}
elsif ($link_text)
{
if (/^END\s*$/)
{
$link_text = 0;
next;
}
else
{
$CF->{"links"}->{$link_group}->{$link_service}->{"link-text"} .= $_;
next;
}
}
else
{
chomp;
s/^\s*//;
s/\s*$//;
}
if (/^set \s+ (\S+) \s* (\S+)?/ix)
{
my $cmd = $1;
my $arg = $2;
if ($cmd eq "show-disabled") { }
elsif ($cmd eq "host") { }
elsif ($cmd eq "prot") { }
elsif ($cmd eq "port") { }
elsif ($cmd eq "full") { }
elsif ($cmd eq "bg") { }
elsif ($cmd eq "bg-ok") { }
elsif ($cmd eq "bg-fail") { }
elsif ($cmd eq "bg-disabled") { }
elsif ($cmd eq "bg-untested") { }
elsif ($cmd eq "table-color") { }
elsif ($cmd eq "html-header") { $html_header = 1; next; }
elsif ($cmd eq "refresh") { }
else
{
print STDERR "unknown set, line $.\n";
next;
}
if ($arg ne "")
{
$CF->{$cmd} = $arg;
}
else
{
$CF->{$cmd} = 1;
}
}
elsif (/^watch \s+ (\S+)/x)
{
push (@RC, [$1]);
}
elsif (/^service \s+ (\S+) \s+ (\S+)/x)
{
push (@RC, [$1, $2]);
}
elsif (/^link \s+ (\S+) \s+ (\S+) \s+ (.*)\s*/ix)
{
$CF->{"links"}->{$1}->{$2}->{"link"} = $3;
}
elsif (/^link-text \s+ (\S+) \s+ (\S+)/ix)
{
$link_text = 1;
$link_group = $1;
$link_service = $2;
next;
}
else
{
my $lnum = $.;
close (IN);
err_die ("error in config file, line $.");
}
}
close (IN);
}
elsif (! -f $RC && $view)
{
err_die ("no view found");
}
return ("", \@RC);
}
sub secs_to_hms
{
my ($s) = @_;
my ($dd, $hh, $mm, $ss);
$dd = int ($s / 86400);
$s -= $dd * 86400;
$hh = int ($s / 3600);
$s -= $hh * 3600;
$mm = int ($s / 60);
$s -= $mm * 60;
$ss = $s;
if ($dd == 0)
{
sprintf("%02d:%02d", $hh, $mm);
}
else
{
sprintf("%d days, %02d:%02d", $dd, $hh, $mm);
}
}
#
# exit displaying error in appropriate output format
#
sub err_die
{
my $msg = shift;
if ($CGI)
{
print <
Error
Error
$msg