# -*- perl -*-
#
# $Revision: 1.3 $
#/s/nagios/bin/nagioscmd service post <host> <service> \
# <result_code> <service_message>


package timctest;

require Exporter;
@ISA = qw(Exporter);
@EXPORT_OK = qw(&print_usage &print_version &service_test);

use FileHandle;
use Data::Dumper;
use IPC::Open3;
use Sys::Hostname;
use Time::ParseDate;

use CSL::What;
use What::Data;

use lib $main::runtimedir;
use csl_utils qw($TIMEOUT %ERRORS);

use strict;

# This will need to change if the location of the stashed tickets ever changes
use constant CCPROTO => '/var/adm/krb5/tmp/stash/krb5cc_%d.stash';
# klist is /usr/bin/klist on rhel6
my $KLIST;
if ( -e '/usr/bin/klist') {
	$KLIST = '/usr/bin/klist';
} else {
	$KLIST = '/s/std/bin/klist';
}

my ($return_code);

sub print_usage ();
sub print_version ();
sub service_test (%);

sub print_usage () {

    print "
Usage:  Check status of stashed tickets
manOptions:
    [--verbose]
    [--help]
    [--version]
    [--usage]
    --hours <hours>
";
    return $ERRORS{'OK'};
}

sub print_version () {
    my $version = '$Revision: 1.3 $';
    $version =~ s/^\$Revision: //;
    $version =~ s/ \$\s*$//;

    print "stashticket.pm - $version\n";
    return $ERRORS{'OK'};
}

sub service_test (%) {
    my %options = @_;

    my $delta_time;
    $return_code = $ERRORS{'OK'};

    if (!defined $options{opt_hours}) {
      critical ("--hours option required and not specified!");
      return $return_code;
    }

    if ($options{"verbose"}) {
        foreach my $opt (sort keys(%options)) {
            if ($options{$opt}) {
                print "$opt - $options{$opt}\n";
            }
        }
    }

    # Find out who's supposed to have stashed tickets here
    my $host = $options{"opt_H"};

    if ((!$host) || ($host eq "")) {
      $host = hostname;
    }
    if ((!$host) || ($host eq "")) {
      return critical ("Host name not specified.");
    }

    my $dh = new What::Data;
    if (!defined $dh) {
      return critical ("Failed to connect to What data!");
    }

    # Array context required...
    ($host) = gethostbyname ($host);

    my $data = $dh->find ($host);
    if (!defined ($data) || !defined ($data->{Data}->{StashTickets})) {
      return critical ("No data found for $host\n");
    }
    my ($d) = $data->{Data}->{StashTickets};
    my ($luser);
    foreach $luser (keys %$d) {
      next unless $d->{$luser}->{stash};
      check_ticket ($luser, $options{opt_hours});
    }

    #print STDERR "# All tickets OK" if ($return_code == $ERRORS{OK});
    print "# All tickets OK" if ($return_code == $ERRORS{OK});

    print "\n";
    return $return_code;
}


sub check_ticket {
  my $luser = shift;
  my $hours = shift;

  my $luid = getpwnam ($luser);
  if (!defined $luid) {
    critical ("getpwnam failed for $luser!");
    return;
  }
  my $ccfile = sprintf (CCPROTO, $luid);
  if (! -e $ccfile) {
    critical ("Stashed ticket FILE:$ccfile for $luser doesn't exist!");
    return;
  }

  # Read the klist output and parse, parse, parse
  my ($pid, $cin, $cout, $line, $date, $hoursleft);
	#where the hell is $KLIST
  $pid = open3 ($cin, $cout, undef, $KLIST ." FILE:$ccfile");
  close $cin;
  if (defined $cout) {
    while (defined ($line=<$cout>)) {
      if ($line =~ m;^\S+\s+\S+\s+(\S+\s+\S+)\s+krbtgt/;) {
	$date = parsedate ($1);
	if (!defined $date) {
	  critical ("Failed to parse ticket cache for $luser!");
	  return;
	}
	$hoursleft = ($date - time)/3600;
	if ($hoursleft < $hours) {
	  my $foo = sprintf "%6.2f", $hoursleft;
	  critical ("Ticket for $luser has $foo (<$hours) hours remaining!");
	  return;
	}
      }
    }
  }
}

# Report a warning
sub warning {
  my $warning = shift;
  #print STDERR "$warning ";
  print "$warning ";
  $return_code = $ERRORS{WARNING};
}

# Report a critical error
sub critical {
  my $error = shift;
  #print STDERR "$error ";
  print "$error ";
  $return_code = $ERRORS{CRITICAL};
}

1;
