home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Telecom
/
1996-04-telecom-walnutcreek.iso
/
technical
/
ixo.program.scripts
/
tpaged.pl
< prev
Wrap
Perl Script
|
1993-02-14
|
12KB
|
420 lines
#! /usr/local/bin/perl4.019
# tpaged -- back-end to tpage system.
# by Tom Limoncelli, tal@warren.mentorg.com
# Copyright (c) 1992, Tom Limoncelli
# The sources can be freely copied for non-commercial use only
# and only if they are unmodified.
# Version 2.0 -- See file HISTORY for details.
####################################################################
#
# Parameters that the user can set:
#
####################################################################
$debug = 0;
# $| = 1; open( STDOUT, ">/home/adm/lib/tpage/log.txt" ) if $debug; $| = 1;
$QUEUE_DIR = '/home/adm/lib/tpage/pqueue/'; # same as in tpage.pl
#$IXOCICO = '/home/tal/work/beep2/ixocico'; # where is ixocico?
$IXOCICO = '/home/adm/lib/tpage/ixocico'; # where is ixocico?
$MAIL = '/usr/ucb/mail'; # which
mail to use?
# Recommended mailers: SunOS & BSD's: /usr/ucb/mail, AT&T Unix's xmail
# Not recommended mailers: /bin/mail
# list of devices to rotate through.
@DEVICES = ( "/dev/ttyz4" ); # currently they are all spoken
# to at the same speed and same parameters. Some day I'll set up
# a modemtab system, but I don't think more than one modem is
# really needed for this system.
# amount of time to sleep between scans of the queue
$SLEEP_TIME = 150; # 2.5 minutes
$SLEEP_TIME = 10 if $debug; # smaller when I'm debugging
# Small amount of time to wait between finding anything in the queue
# and doing a real scan of the queue.
$MULT_SLEEP_TIME = 10;
####################################################################
# QUEUE FILES FORMAT:
#
# Files in the queue have the name of the format in the
# first line. Currently there is only one format and it
# is named "A". The first line marks it as the "A" format.
# a subroutine called read_format_A reads this format. Other
# formats can be written (see comments by read_format_A)
#
# The "A" format:
# line contents
# 1: A\n
# 2: number to dial\n
# 3: pin\n
# 4: entire message\n
# 5: X\n
# read_format_* -- modules that read various data formats.
# Currently implemented: The "A" format.
# do_proto_* -- modules that do various beeper protocols.
# Currently implmented: the ixo protocol.
# Future protocols: numeric-only pagers.
####################################################################
# Here's the actual program
# define some globals
local(%protocols);
while (1) {
local ($first, @allfiles, @anyfiles);
# We could scoop up all the files and process them, but chances
# are if one file is found, more are on the way. So, instead
# we scoop, if any are found we sleep 5 seconds and re-scoop.
# wait for any files to appear.
while (1) {
@anyfiles = &scan_queue;
print "DEBUG: anyfiles= ", join(' ', @anyfiles), "\n" if $debug;
if ($#anyfiles!=-1) { # files? take a rest and then process.
sleep $MULT_SLEEP_TIME unless $debug;
last;
} else { # no files? hibernate.
sleep $SLEEP_TIME;
next;
}
}
# re-get the files in the queue
@allfiles = &scan_queue;
print "DEBUG: allfiles= ", join(' ', @allfiles), "\n" if $debug;
# get all the data out of the queue'd files.
foreach $file (@allfiles) {
print "DEBUG: Doing $file\n" if $debug;
open(DATA, "<" . $QUEUE_DIR . $file) || print "Can't open $file:
$!";
chop( $first = <DATA> );
print "DEBUG: first=$first\n" if $debug;
eval "do read_format_$first()";
}
# process all the extracted data (do_protocol_* should delete the files)
foreach $proto (keys %protocols) {
eval "do do_protocol_$proto()";
delete $protocols{ $proto };
sleep $SLEEP_TIME;
}
}
# scan the queue for entries (avoid "blacklisted" files)
sub scan_queue {
local(@files);
# scan the directory for "P files (pager files)
opendir(QDIR, $QUEUE_DIR) || die "$0: Can't open $QUEUE_DIR: $!";
@files = grep( /^P/, readdir(QDIR) );
closedir(QDIR);
print "DEBUG: filescan= ", join(' ', @files), "\n" if $debug;
# remove the blacklisted files
@files = grep( ! defined $blacklist_data{ $_ }, @files);
print "DEBUG: goodfiles= ", join(' ', @files), "\n" if $debug;
# return the files
@files;
}
# blacklist a file in the queue (couldn't delete it for some reason
# and we don't want to repeat it)
sub blacklist {
local($file) = @_;
$blacklist_data{ $file } = 1;
}
# Each read_format_ must:
# read from <DATA> and then close(DATA).
# %protocols{ protocol name } = 1 (for the protocol to use)
# and stuff the right data into the right variables for that protocol
# to use.
sub read_format_A
{
local($dial,$pin,$error,$mess,$X); # $file is by sideeffect
print "DEBUG: reading format A\n" if $debug;
chop( $dial = <DATA> );
chop( $pin = <DATA> );
chop( $error = <DATA> );
chop( $mess = <DATA> );
chop( $X = <DATA> );
return if $X ne "X"; # file isn't in correct format or isn't done.
return if $dial eq "";
return if $pin eq "";
return if $mess eq "";
$protocols{ 'ixo' } = 1;
&ixo_mesg_append( $dial, $pin, $error, $mess, $file );
}
# Each do_protocol_ must:
# delete files out of the queue that are successful.
# delete files out of the queue that are aged.
# clean up so that the routine can be called again.
sub do_protocol_ixo {
print "DEBUG: doing protocol IXO\n" if $debug;
local($pin, $error, $mess, $file, $cmd, $status, $index);
local($general_reject, $general_error_message);
# build the temp file and the command line
local($tmpfile) = "/tmp/tpaged.$$";
foreach $dial ( &ixo_listphones ) {
print "DEBUG: Number to dial is $dial\n" if $debug;
# fill the data file
open(IX, ">$tmpfile" ) || die "$0: Can't create $tmpfile: $!";
foreach $index ( &ixo_listindexes( $dial ) ) {
($pin, $error, $mess, $file) = &ixo_mesg_get( $dial, $index
);
# put it in the file for ixocico to use
print IX "$pin\n$mess\n";
}
close IX;
print "DEBUG: messages to send", &ixo_listindexes( $dial ), "\n" if
$debug;
$general_reject = 1; # when done, 1=cancel remaining; 0=retry
remaining
$general_error_message = "SHOULD NOT HAPPEN"; # if all messages
are cancelled
$cmd = $IXOCICO . " <" . $tmpfile . " "
. push(@DEVICES, shift @DEVICES) . " " . $dial;
print "DEBUG: About to execute: $cmd\n" if $debug;
open(IX, $cmd . "|") || die "$0: Can't execute ixocico: $!";
while (<IX>) {
print if $debug;
next unless /^#/;
print unless $debug;
/^#WRONGARGS / &&
die("$0: Major program bug: $!");
/^#NOCONN / && do {
printf("$0: Nobody answered the phone!\n") if
$debug;
$general_reject = 0;
last;
};
/^#UNKNOWNPROTO / && do {
print "$0: Uhhh, are you sure that's a pager
service?\n" if $debug;
$general_reject = 1;
$general_error_message = "other end using different
protocol";
last;
};
/^\#MESOK (\d) / && do {
$index = $1;
print "DEBUG: message $index done.\n" if $debug;
($pin, $error, $mess, $file) = &ixo_mesg_get(
$dial, $index );
print "DEBUG: ERROR=$error; FILE=$file\n" if
$debug;
print "DEBUG: unlinking " . $QUEUE_DIR . $file .
"\n" if $debug;
$status = unlink $QUEUE_DIR . $file;
print "DEBUG: unlink status=$status; $!\n" if
$debug;
&blacklist( $file) unless $status;
# remove from queue
&ixo_mesg_delete( $dial, $index );
};
/^#MESREJECT (\d) / && do { # very similar to
#MESOK
$index = $1;
print "DEBUG: message $index rejected.\n" if
$debug;
($pin, $error, $mess, $file) = &ixo_mesg_get(
$dial, $index );
print "DEBUG: ERROR=$error; FILE=$file\n" if
$debug;
# notify anyone that wants to know about failures
if ($error + 0) {
$cmd = "$MAIL <"
. $QUEUE_DIR . $file
. " -s 'TPAGE_MESSAGE: request rejected by service' "
. $error;
print "DEBUG: About to execute $cmd\n" if
$debug;
system $cmd;
}
print "DEBUG: unlinking " . $QUEUE_DIR . $file .
"\n" if $debug;
$status = unlink $QUEUE_DIR . $file;
print "DEBUG: unlink status=$status; $!\n" if
$debug;
&blacklist( $file) unless $status;
# remove from queue
&ixo_mesg_delete( $dial, $index );
};
/^#FORDIS / && do {
print "Forced disconnect from server.\n" if $debug;
$general_reject = 1;
$general_error_message = "other end requesting
disconnect";
last;
};
/^#PROTERR / && do {
print "Server not following protocol.\n" if $debug;
$general_reject = 1;
$general_error_message = "other end having a
protocol error";
last;
};
( /^#DONE / || /#BYE / ) && do {
print "Done with sending batch. Waiting BYE.\n" if
$debug;
$general_reject = 0;
$general_error_message = "been told we're done but
weren't".
next;
};
/^#WRONGANY / && do {
print "We've been notified that one of the batch
may have been not xmited.\n(great protocol, eh?)\n" if $debug;
next;
};
/^#BADQUEUE / && do {
die "$0: Programmer error. Data in queue is bad:
$_\n";
};
/^#MODOPEN / && do {
print "Modem can't be opened\n" if $debug;
$general_reject = 0;
last;
};
/^#PACKLEN / && do {
die "$0: Protocol error. Should never happen:
$_\n";
};
/^#GOTMESSEQ / && do {
print "MESSAGE: $_\n" if $debug;
};
/^#LONELY / && do {
print "Hello? Hello? Either I'm getting the
silent treatment or the server is dead." if $debug;
$general_reject = 0;
last;
};
}
close IX;
unlink $tmpfile;
print "DEBUG: rejecting remaining messages\n" if $debug;
# now reject remaining messages
foreach $index ( &ixo_listindexes( $dial) ) {
# if general_reject then we have work to do
if ($general_reject) {
print "DEBUG: removing $dial:$index\n" if $debug;
($pin, $error, $mess, $file) = &ixo_mesg_get(
$dial, $index );
###### mail a warning
if ($error + 0) {
$cmd = "$MAIL <"
. $QUEUE_DIR . $file
. " -s 'TPAGE_MESSAGE: unprocessed message deleted due to "
. $general_error_message . "' "
. $error;
print "DEBUG: About to execute $cmd\n" if
$debug;
system $cmd;
}
###### make sure it gets deleted
print "DEBUG: unlinking (leftover) " . $QUEUE_DIR .
$file . "\n" if $debug;
$status = unlink $QUEUE_DIR . $file;
print "DEBUG: unlink status=$status; $!\n" if
$debug;
&blacklist( $file) unless $status;
}
print "DEBUG: deleting from memory $dial:$index\n" if
$debug;
# delete it from the ixo list
&ixo_mesg_delete( $dial, $index );
}
# at this point %ixo_data should be empty
&ixo_end_asserts;
# now do the next phone number
}
}
sub ixo_end_asserts {
# test a couple assertions
print "DEBUG: testing assertions\n" if $debug;
# $ixo_count{ $dial } should be zero
die "$0: bug1\n" if $ixo_count{ $dial };
# %ixo_data should be empty at this point
die "$0: bug2\n" if grep(1,keys %ixo_data); # fast key counter
}
sub ixo_mesg_append {
local($dial, $pin, $error, $mess, $file, $count) = @_;
print "APPEND: dial=$dial pin=$pin error=$error file=$file mess=$mess\n" if
$debug;
$count = 0 + $ixo_count{ $dial }++;
$ixo_data{ "$dial:$count" } = "$pin\n$error\n$mess\n$file";
print "APPEND: data=", $ixo_data{ "$dial:$count" }, "\n" if $debug;
}
sub ixo_mesg_get {
local($dial, $index) = @_;
local($pin, $error, $mess, $file, @list);
print "GET: dial=$dial index=$index\n" if $debug;
@list = split( '\n', $ixo_data{ "$dial:$index" } );
($pin, $error, $mess, $file) = @list;
print "GET: pin=$pin error=$error file=$file mess=$mess\n" if $debug;
@list;
}
sub ixo_mesg_delete {
local($dial, $index) = @_;
print "DELETE: dial=$dial, index=$index\n" if $debug;
delete $ixo_data{ "$dial:$index" };
$ixo_count{ $dial }--;
}
sub ixo_listindexes {
local($dial) = @_;
# gather and sort the second field
sort grep( s/^$dial:(.+)/$1/, keys %ixo_data );
}
sub ixo_listphones {
local(@list);
local($l) = undef;
# gather and sort the first field.
@list = sort grep( s/^(.+):.+$/$1/, keys %ixo_data );
# uniq them
@list = grep (!($_ eq $l || ($l = $_, 0)), @list );
# return them
@list;
}