#!/usr/local/bin/perl 
# 
# send mail to a pager
# escape url in body
# limit how often anything is sent to a given pager

## 'notify-by-epager' command definition
#define command{
#    command_name	notify-by-epager
#    ;command_line	/usr/bin/printf "%b" "Service: $SERVICEDESC$\nHost: $HOSTNAME$\nAddress: $HOSTADDRESS$\nState: $SERVICESTATE$\nInfo: $SERVICEOUTPUT$\nDate: $LONGDATETIME$" | /bin/mail -s "$NOTIFICATIONTYPE$: $HOSTALIAS$/$SERVICEDESC$ is $SERVICESTATE$" $CONTACTPAGER$
#    ;command_line	/usr/bin/printf "%b" "Service: $SERVICEDESC$\nHost: $HOSTNAME$\nAddress: $HOSTADDRESS$\nState: $SERVICESTATE$\nInfo: $SERVICEOUTPUT$\nDate: $LONGDATETIME$" | /usr/ucb/mail -s "$NOTIFICATIONTYPE$: $HOSTALIAS$/$SERVICEDESC$ is $SERVICESTATE$" $CONTACTPAGER$
#    command_line	/usr/bin/printf "%b" "Service: $SERVICEDESC$\nHost: $HOSTNAME$\nAddress: $HOSTADDRESS$\nState: $SERVICESTATE$\nInfo: $SERVICEOUTPUT$\nDate: $LONGDATETIME$" | /usr/local/nagios/libexec/notify_by_epager -s "$NOTIFICATIONTYPE$: $HOSTALIAS$/$SERVICEDESC$ is $SERVICESTATE$" $CONTACTPAGER$
#    }


use strict;
use warnings;
no warnings 'uninitialized';
no warnings 'redefine';
use Getopt::Long;
use NDBM_File;
use POSIX qw( :fcntl_h );
use URI::Escape;
use Time::HiRes qw( usleep );


use vars qw( $subject $emailaddr $verbose $help $body $now $historydb 
    $last_paged $holddown $logfile %hist $emailcmd $tied $i );

$holddown = 600;   # only page each person once this many seconds
$historydb = "/usr/local/nagios/var/notify_by_epager_history";  
$logfile = "/usr/local/nagios/var/nagios.log";  
$emailcmd = "/bin/mail";
$verbose = 0;
$help = 0;

sub usage {
    my( $rc ) = @_;
    print "Usage: $0 [options] -s <subject> emailaddr
    -v    verbose
    -h    help
";
    exit $rc;
    }

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

$emailaddr = shift;
&usage( 1 ) if ( ! $emailaddr );

# Just in case of problems, let's not hang Nagios
$SIG{'ALRM'} = sub {
    exit 3;
    };
alarm( 60 );

$/ = undef;
$body = <>; 

$now = time();

$tied = 0; 
$i = 9; 
while ( --$i >= 0 ) { 
    # 0664 = permissions on dbm files, group writable to nagios
    # O_CREAT doesn't work?
    if ( tie( %hist, 'NDBM_File', $historydb, O_RDWR | O_CREAT, 0664 ) )  { 
	$tied = 1;
	last;
	}

    if ( ! -f "$historydb.dir" ) { 
	open( hH, '>', "$historydb.dir" );
	close fH;
	chmod 0664, "$historydb.dir";
	}
    if ( ! -f "$historydb.dir" ) { 
	open( hH, '>', "$historydb.pag" );
	close fH;
	chmod 0664, "$historydb.pag";
	}

    usleep( 500000 );
    };

if ( ! $tied ) { 
    print "internal error, can't tie pager history dbm: $!\n"; 
    if ( open( lH, '>>', $logfile ) ) {
	print lH "[$now] notify_by_epager can't tie history dbm\n";
	close lH;
	}
    exit 3;  
    }

$last_paged = $hist{ $emailaddr };
$last_paged = 0 if ( ! defined $last_paged );
$verbose && printf "last_paged for $emailaddr = $last_paged, %s\n", 
    scalar( localtime( $last_paged ) );

if ( $last_paged > ( $now - $holddown ) ) {  
    # too soon, don't page
    $verbose && printf "too soon, %d s, supressing page\n", $now - $last_paged;
    untie( %hist );
    if ( open( lH, '>>', $logfile ) ) {
	printf lH "[$now] notify_by_epager supressing page to $emailaddr, last page was %d sec ago\n", $now - $last_paged;
	close lH;
	}
    exit 0;
    }


$hist{ $emailaddr } = $now;
untie( %hist );

if ( open( lH, '>>', $logfile ) ) {
    print lH "[$now] notify_by_epager forwarding page to $emailaddr\n";
    close lH;
    }

# spaces and stuff in url confuse some mail readers
$body =~ s!<(https?)://([^>]*/)([^>]*)>! "<$1://$2" . uri_escape($3) .'>' !eg;

if ( ! open( pH, '|-', "$emailcmd -s '$subject' '$emailaddr'"  ) ) { 
    # Uh, now what?  This IS the error notification script....
    $verbose && print "can't run $emailcmd: $!\n";
    if ( open( lH, '>>', $logfile ) ) { 
	print lH "[$now] notify_by_epager can't run $emailcmd: $!\n";
	close lH;
	}
    exit 2;
    }

print pH $body;
close pH; 

$verbose && print "success, normal exit\n";
exit 0;


