#!/usr/bin/perl

eval 'exec /usr/bin/perl  -S $0 ${1+"$@"}'
    if 0; # not running under some shell
#
# quick script for sending SNPP messages
#
# $Id: snpp 316 2008-01-03 20:21:19Z keescook $
#
# Copyright (C) 2000-2004 Kees Cook
# kees@outflux.net, http://outflux.net/
#
# 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.
# http://www.gnu.org/copyleft/gpl.html

=head1 NAME

snpp - send pages via SNPP

=head1 SYNOPSIS

snpp [OPTIONS] recipient...

=head1 OPTIONS

=over 4

=item -s SERVER[:PORT]

Connect to the specified SERVER (and PORT, if given).  Default is
"localhost:444".

=item -f USER

Show that the sent page is coming from USER.  Default is the current user.

=item -m MESSAGE

Send the given MESSAGE instead of reading text from stdin.

=item -n

Do not notify the 'from' user about the status of the page.

=item -d

Display SNPP session debugging.

=item -C CONF

Read CONF instead of /etc/snpp.conf for server default.

=item -h

Display a summary of all the available command line options.

=back

=head1 DESCRIPTION

This tool is used to send a page via the Simple Network Paging Protocol
(level 2).  It is designed to be used with 'sendpage', but should work
with any other SNPP servers as well.

The /etc/snpp.conf file can contain a single line in the form of

	server:ADDRESS[:PORT]

where ADDRESS and PORT are the defaults for snpp.

=head1 AUTHOR

Kees Cook <kees@outflux.net>

=head1 BUGS

Not much happening in this tool, but I bet the use of "CALLer id" is
not standard, and other SNPP server may require this tool run with
the '-n' option all the time.

=head1 COPYRIGHT

snpp is free software; it can be used under the terms of the GNU General
Public License.

=head1 SEE ALSO

perl(1), sendpage(1), Net::SNPP(3)

=cut

use Getopt::Std;
use Net::SNPP;
use Sys::Hostname;
use IO::File;

my %opts;
my $VERSION="0.1";

sub Usage {
        die "Usage: $0 [OPTIONS] pin1 [pin2 [...]]

version $VERSION

-s SERVER[:PORT]  SNPP server to use (default is 'localhost')
-f USER           force page to be from user USER (default is current user)
-m MESSAGE	  message to send (reads from stdin by default)
-n                no email carboning to 'from'
-d                turn debug on
-C CONF		  read CONF instead of /etc/snpp.conf
-h                you're reading it.  :)

";
}


# get our options
if (!getopts('hdns:f:m:C:',\%opts) || $opts{h} || !@ARGV) {
        Usage();
}

### DEFAULTS
# set config file
$opts{C}="/etc/snpp.conf" unless ($opts{C});
# set server
my $server="localhost";


my $fh = new IO::File $opts{C}, "r";
if (!defined($fh)) {
        warn "Cannot read '$opts{C}' file (using defaults): $!\n";
}
else {
	my $num=0;
	my $line;

	foreach $line (<$fh>) {
	        chomp($line);
	        $num++;

	        # skip comments and blanks
	        next if ($line =~ /^\s*#/ || $line =~ /^\s*$/);

	        ($cmd,$arg)=split(/:/,$line,2);

	        if ($cmd eq "server") {
			$server=$arg;
       		}
        	else {
               		warn "unknown command '$cmd' in '$opts{C}', line ".
				"$num\n";
        	}
	}
	undef $fh;
}

# override config file and defaults
$opts{s}=$server unless ($opts{s});

# verify that there is a "SNPP" service (weakness in Net::SNPP...)
$proto=getprotobyname("tcp");
if (!defined($proto))
{
	die "Could not resolve 'tcp' protocol into a protocol number!\nPlease check /etc/protocols\n";
}
else
{
	warn "'tcp' is proto $proto\n" if ($opts{d});	
}
$port=getservbyname("snpp","tcp");
if (!defined($port))
{
	die "Could not resolve 'snpp' service into a port number!\nPlease check /etc/services\n";
}
else
{
	warn "'snpp' is service $port\n" if ($opts{d});	
}
$snpp = Net::SNPP->new($opts{s}, Debug => $opts{d} );
if (!defined($snpp)) {
	die "Could not connect to SNPP server '$opts{s}'\n";
}

# get the pins
my @pins = @ARGV;

# get the page text
undef $/;
my $text = $opts{m} ? $opts{m} : <STDIN>;
$/="\n";

# who is it from?
if (!defined($opts{f}) && !$opts{n}) {
	$opts{f}=scalar(getpwuid($<))."\@";
	$opts{f}.=hostname;
}

# send pins
foreach $pin (@pins) {
	if (!$snpp->pager_id($pin)) {
		warn $snpp->message();
		if ($snpp->status()==4) {
			exit($snpp->code()-400);
		}
	}
}

# send 'caller id', if we need to
if (!$opts{n}) {
	if (!$snpp->caller_id($opts{f})) {
		warn $snpp->message();
		if ($snpp->status()==4) {
			exit($snpp->code()-400);
		}
	}
}

# send text
if (!$snpp->data($text)) {
	warn $snpp->message();
	if ($snpp->status()==4) {
		exit($snpp->code()-400);
	}
}

# issue the send
if (!$snpp->send()) {
	warn $snpp->message();
	exit($snpp->code()%100);
}

$snpp->quit;

undef $snpp;
