/runcheck
#!/usr/bin/perl
use File::Basename;
use strict;


my $dir = shift;
unless (-d $dir) {
	print "Arg is not a directory";
	exit 1;
}
my $me = basename $dir;
my ($status, $details);

sub do_command {
	my $command = shift;
	$command =~ /^(\w+)(\s+(.*))?$/;
	my ($do, $args) = ($1, $3);
	if ($do eq 'mail') {
		open MAIL, '|-', qq!mail -s "$me $status" $args! or die "Could not mail";
		print MAIL $details,"\n";
		close MAIL;
	} elsif ($do eq 'exec') {
		system($args);
	} elsif ($do eq 'pipe') {
		open PIPE, '|-', $args;
		print PIPE "$status\n";
		print PIPE $details;
		close PIPE;
	}
}


my ($checkcommand, $every, %on);
$on{success} = [];
$on{failure} = [];
$on{change} = [];

open CONFIG, "$dir/check";
while (<CONFIG>) {
	my @words = split(/\s+/);
	my $command = shift @words;
	if ($command eq 'check') {
		$checkcommand = join(' ', @words);
	} elsif ($command eq 'on') {
		my $when = shift @words;
		if ($when eq 'failure') {
			push @{$on{failure}}, join(' ', @words);
		} elsif ($when eq 'success') {
			push @{$on{success}}, join(' ', @words);
		} elsif ($when eq 'change') {
			push @{$on{change}}, join(' ', @words);
		} else {
			print "Unknown event in 'on', $dir/check line $.\n";
		}
	} elsif ($command eq 'every') {
		$every = $words[0];
	} else {
		print "Unknown command '$command', $dir/check line $.\n";
	}
}
close CONFIG;

unless ($checkcommand) {
	print "Check command not specified in $dir/check\n";
	exit 1;
}
unless (@{$on{failure}} || @{$on{success}} || @{$on{change}}) {
	print "No actions specified in $dir/check. This is probably a mistake.\n";
}

open STATUS, "$dir/checkstatus";
chomp(my $oldstatus = <STATUS>);
my $oldtime = (stat(STATUS))[9];
close STATUS;

my $td = time() - $oldtime;
if ($td < $every) {
	# Not time to recheck yet
	#print "Not rechecking; ", $every - $td, " seconds to go.\n";
	exit $oldstatus;
}

my ($pid, $hung, $exitstatus);
$SIG{ALRM} = sub {
	kill 9, $pid;
	$hung = 1;
};
alarm 10;

$pid = open CHECK, '-|', $checkcommand;
$status = <CHECK>;
$details = join('', <CHECK>);
close CHECK;
if ($hung) {
	$status = 'TIMEOUT';
	$details = 'Check did not complete within ten seconds';
	$exitstatus = -1;
} else {
	$exitstatus = $? >> 8;
}

if ($exitstatus == 0 && $oldstatus != 0) {
	do_command($_) foreach @{$on{success}};
}
if ($exitstatus != 0 && $oldstatus == 0) {
	do_command($_) foreach @{$on{failure}};
}
if ($exitstatus != $oldstatus) {
	do_command($_) foreach @{$on{change}};
}

open STATUS, ">$dir/checkstatus";
print STATUS "$exitstatus\n";
print STATUS "$status\n";
print STATUS "$details\n";
close STATUS;

exit $exitstatus;