#!/usr/local/bin/perl 
# show_service_output
#
# list plugin output for each host/service
#
# by Doke Scott, doke at udel dot edu
#
# $Id: show_service_output,v 1.1 2017/07/28 17:44:58 doke Exp $
#



use strict;   
use warnings;   
use Getopt::Long;


my $status_file = "/usr/local/nagios/var/status.dat";  

my $pending_state = 9;  # fake state for pending services

my $min_host_importance = 200;
my $min_service_importance = 200;

my $pattern = '';
my $verbose = 0;
my $help = 0;


sub usage { 
    my( $rc ) = @_;
    print "Usage: $0 [-vh] -p <pattern> 
    -p pattern   search for hosts or services matching perl regular expression
		 examples: 'copland', 'sw-ne37-.*', 'mahler.*prtdiag', 
    -v           verbose
    -h           this help
\n";
    exit $rc;
    }


Getopt::Long::Configure ("bundling");
GetOptions(
    'p=s' => \$pattern,
    'v+' => \$verbose,
    'h' => \$help,
    );
&usage( 0 ) if ( $help );
&usage( 1 ) if ( ! $pattern );

my( %hosts, %services );

read_statusfile();
show_services();

exit 0;



##########################





sub read_statusfile { 
    open( fH, $status_file ) || die "can't read-open $status_file: $!\n";

    my $in_servicestatus = 0;
    my $in_hoststatus = 0;
    my $in_servicecomment = 0;
    my $in_hostdowntime = 0;
    my $in_servicedowntime = 0;

    my $host = undef;
    my $service = undef;
    my $current_state = 0;
    my $acked = 0;
    my $state_type = 0;
    my $current_attempt = 0;
    my $max_attempts = 0;
    my $last_state_change = 0;
    my $last_hard_state_change = 0;
    my $last_check = 0;
    my $plugin_output = '';
    my $current_notification_number = 0;
    my $has_been_checked = 0;
    my $should_be_scheduled = 0;
    my $comment_id = 0;
    my $comment = '';
    my $author = '';
    my $downtime_id = 0;
    my $entry_time = 0;
    my $start_time = 0;
    my $end_time = 0;
    my $is_in_effect = 0;

    my $nservices = 0;

    while ( <fH> ) { 
	if ( $in_servicestatus || $in_hoststatus || $in_servicecomment 
		|| $in_hostdowntime || $in_servicedowntime ) {

	    # end of the block?
	    if ( m/^\s*(?#{)}\s*$/ ) { 

		if ( $in_servicestatus ) {   
		    $verbose && print "host $host, service $service, ", 
			"current_state $current_state, state_type $state_type, ",
			"acked $acked\n";
		    if ( $host && $service ) { 
			$services{ "$host/$service" }{ 'host' } = $host;
			$services{ "$host/$service" }{ 'service' } = $service;
			$services{ "$host/$service" }{ 'current_state' } = $current_state;
			$services{ "$host/$service" }{ 'acked' } = $acked;
			$services{ "$host/$service" }{ 'state_type' } = $state_type;
			$services{ "$host/$service" }{ 'current_attempt' } = $current_attempt;
			$services{ "$host/$service" }{ 'max_attempts' } = $max_attempts;
			$services{ "$host/$service" }{ 'last_state_change' } = $last_state_change;
			$services{ "$host/$service" }{ 'last_hard_state_change' } = $last_hard_state_change;
			$services{ "$host/$service" }{ 'last_check' } = $last_check;
			$services{ "$host/$service" }{ 'plugin_output' } = $plugin_output;
			$services{ "$host/$service" }{ 'current_notification_number' } = $current_notification_number;
			$services{ "$host/$service" }{ 'has_been_checked' } = $has_been_checked;
			$services{ "$host/$service" }{ 'should_be_scheduled' } = $should_be_scheduled;
			$nservices ++;
			}
		    }

		elsif ( $in_hoststatus ) {   
		    $verbose && print "host $host, ", 
			"current_state $current_state, state_type $state_type, ",
			"acked $acked\n";
		    if ( $host ) { 
			$hosts{ $host }{ 'current_state' } = $current_state;
			$hosts{ $host }{ 'acked' } = $acked;
			$hosts{ $host }{ 'state_type' } = $state_type;
			$hosts{ $host }{ 'current_attempt' } = $current_attempt;
			$hosts{ $host }{ 'max_attempts' } = $max_attempts;
			$hosts{ $host }{ 'last_state_change' } = $last_state_change;
			$hosts{ $host }{ 'last_hard_state_change' } = $last_hard_state_change;
			$hosts{ $host }{ 'last_check' } = $last_check;
			$hosts{ $host }{ 'plugin_output' } = $plugin_output;
			}
		    }

		elsif ( $in_servicecomment ) {   
		    $verbose && print "host $host, service $service, ", 
			"comment_id $comment_id, comment $comment, ",
			"author $author\n";
		    if ( $host && $service && $comment_id && $comment ) { 
			$services{ "$host/$service" }{ 'comments' }{ $comment_id }{ 'entry_time' } = $entry_time;
			$services{ "$host/$service" }{ 'comments' }{ $comment_id }{ 'author' } = $author;
			$services{ "$host/$service" }{ 'comments' }{ $comment_id }{ 'comment' } = $comment;
			}
		    }

		elsif ( $in_hostdowntime ) {   
		    $verbose && print "host $host, ", 
			"downtime_id $downtime_id, is_in_effect $is_in_effect, ",
			"downtime start $start_time, end $end_time, ",
			"comment $comment, author $author\n";
		    if ( $host && $downtime_id ) { 
			$hosts{ $host }{ 'downtime' }{ $downtime_id }{ 'entry_time' } = $entry_time;
			$hosts{ $host }{ 'downtime' }{ $downtime_id }{ 'start_time' } = $start_time;
			$hosts{ $host }{ 'downtime' }{ $downtime_id }{ 'end_time' } = $end_time;
			$hosts{ $host }{ 'downtime' }{ $downtime_id }{ 'is_in_effect' } = $is_in_effect;
			$hosts{ $host }{ 'downtime' }{ $downtime_id }{ 'author' } = $author;
			$hosts{ $host }{ 'downtime' }{ $downtime_id }{ 'comment' } = $comment;
			}
		    }

		elsif ( $in_servicedowntime ) {   
		    $verbose && print "host $host, service $service, ", 
			"downtime_id $downtime_id, is_in_effect $is_in_effect, ",
			"downtime start $start_time, end $end_time, ",
			"comment $comment, author $author\n";
		    if ( $host && $service && $downtime_id ) { 
			$services{ "$host/$service" }{ 'downtime' }{ $downtime_id }{ 'entry_time' } = $entry_time;
			$services{ "$host/$service" }{ 'downtime' }{ $downtime_id }{ 'start_time' } = $start_time;
			$services{ "$host/$service" }{ 'downtime' }{ $downtime_id }{ 'end_time' } = $end_time;
			$services{ "$host/$service" }{ 'downtime' }{ $downtime_id }{ 'is_in_effect' } = $is_in_effect;
			$services{ "$host/$service" }{ 'downtime' }{ $downtime_id }{ 'author' } = $author;
			$services{ "$host/$service" }{ 'downtime' }{ $downtime_id }{ 'comment' } = $comment;
			}
		    }

		$in_servicestatus = 0;
		$in_hoststatus = 0;
		$in_servicecomment = 0;
		$in_hostdowntime = 0;
		$in_servicedowntime = 0;

		$host = undef;
		$service = undef;
		$current_state = 0;
		$acked = 0;
		$state_type = 0;
		$current_attempt = 0;
		$max_attempts = 0;
		$last_state_change = 0;
		$last_hard_state_change = 0;
		$last_check = 0;
		$plugin_output = '';
		$current_notification_number = 0;
		$has_been_checked = 0;
		$should_be_scheduled = 0;
		$comment_id = 0;
		$comment = '';
		$author = '';
		$downtime_id = 0;
		$start_time = 0;
		$end_time = 0;
		$is_in_effect = 0;
		}

	    # host stuff
	    elsif ( m/^\s*host_name=(.*)/ ) { 
		$host = $1;
		}

	    # service status stuff
	    elsif ( m/^\s*service_description=(.*)/ ) { 
		$service = $1;
		}
	    elsif ( m/^\s*current_state=(\d+)/ ) { 
		$current_state = $1;
		}
	    elsif ( m/^\s*problem_has_been_acknowledged=(\d+)/ ) { 
		$acked = $1;
		}
	    elsif ( m/^\s*state_type=(\d+)/ ) { 
		$state_type = $1;
		}
	    elsif ( m/^\s*current_attempt=(\d+)/ ) { 
		$current_attempt = $1;
		}
	    elsif ( m/^\s*max_attempts=(\d+)/ ) { 
		$max_attempts = $1;
		}
	    elsif ( m/^\s*last_state_change=(\d+)/ ) { 
		$last_state_change = $1;
		}
	    elsif ( m/^\s*last_hard_state_change=(\d+)/ ) { 
		$last_hard_state_change = $1;
		}
	    elsif ( m/^\s*last_check=(\d+)/ ) { 
		$last_check = $1;
		}
	    elsif ( m/^\s*plugin_output=(.+)/ ) { 
		$plugin_output = $1;
		}
	    elsif ( m/^\s*current_notification_number=(.+)/ ) { 
		$current_notification_number = $1;
		}
	    elsif ( m/^\s*has_been_checked=(.+)/ ) { 
		$has_been_checked = $1;
		}
	    elsif ( m/^\s*should_be_scheduled=(.+)/ ) { 
		$should_be_scheduled = $1;
		}

	    # comment stuff
	    elsif ( m/^\s*author=(.+)/ ) { 
		$author = $1;
		}
	    elsif ( m/^\s*comment_id=(\d+)/ ) { 
		$comment_id = $1;
		}
	    elsif ( m/^\s*(?:comment|comment_data)=(.+)/ ) { 
		$comment = $1;
		}
	    elsif ( m/^\s*entry_time=(\d+)/ ) { 
		$entry_time = $1;
		}

	    # downtime stuff
	    elsif ( m/^\s*downtime_id=(\d+)/ ) { 
		$downtime_id = $1;
		}
	    elsif ( m/^\s*start_time=(\d+)/ ) { 
		$start_time = $1;
		}
	    elsif ( m/^\s*end_time=(\d+)/ ) { 
		$end_time = $1;
		}
	    elsif ( m/^\s*is_in_effect=(\d+)/ ) { 
		$is_in_effect = $1;
		}
	    }

	elsif ( m/^servicestatus\s*{(?#})/ )  { 
	    $in_servicestatus = 1;
	    }
	elsif ( m/^hoststatus\s*{(?#})/ )  {
	    $in_hoststatus = 1;
	    }
	elsif ( m/^servicecomment\s*{(?#})/ )  {
	    $in_servicecomment = 1;
	    }
	elsif ( m/^hostdowntime\s*{(?#})/ )  {
	    $in_hostdowntime = 1;
	    }
	elsif ( m/^servicedowntime\s*{(?#})/ )  {
	    $in_servicedowntime = 1;
	    }
	}

    if ( $verbose ) { 
	print "read $. status lines\n";
	printf "found %d host statuses\n", scalar( keys %hosts );
	printf "found %d service statuses\n", $nservices;
	}

    close fH;
    }







sub show_services { 
    my( $hostservice, $plugin_output );

    foreach $hostservice ( keys %services ) { 
	if ( $hostservice =~ m/$pattern/i ) { 
	    $plugin_output = $services{ $hostservice }{ 'plugin_output' };

	    printf "%s: %s\n", $hostservice, $plugin_output; 
	    }
	}
    }



