Home


pager

#!/usr/local/bin/perl5 -w
#
#	pager
#
#	Page somebody when they have e-mail.
#
#	Put this into your cron script running at times that you
#	are willing to receive pages.
#

#	Configuration
$User	= "joe.cool";
$Phone	= "555 1212";
$TTY	= "ttyS3";
$Port	= "/dev/$TTY";
$Lock	= "/usr/spool/uucp/LCK..$TTY";

#	See if he has mail to read
chdir("/users1/$User");
print scalar(localtime()), "\n";
#	Perl has a number of operators which test various
#	attributes of files.  This is very useful for automated
#	tasks.  You can check for the existence of files (-e),
#	if the file is zero length (-z), the modification date
#	of a file (-M), as well as file ownership, if the file
#	is a directory or regular file, as well as about any
#	attribute about a file.  These tests don't deal
#	with the contents of the file, just the "meta"
#	information.
exit 0 if (! -e "/usr/spool/mail/$User" ||
			-z "/usr/spool/mail/$User");

#	There is mail.
#	Only page if we haven't paged since the last time we logged in.
if (-f ".paged")
    {
    #	The -M returns the age of the file in days since the
    #	file was last modified.  Note that this number is
    #	typically not an integer.  This bit of code attempts
    #	to page the recipient when they get new mail since the
    #	last time they logged in (and presumably read their mail),
    #	but also repeat the page periodically in case they are
    #	out of range of the paging site.
    if (-M ".paged" < 0.1666)
	{
	exit 0 if (-M ".paged" < -M ".lastlogin");
	}
    }

#	There is mail, and he doesn't know about it yet.
#	Time to page him

#	Get the lock file.
#	The following ugly code deals with lock files which in
#	this case Unix systems use to keep multiple programs
#	from interfering with each other getting to the modem.
die "Can't get lock file" if -e $Lock;
open(LOCK,"+>$Lock") || die "Can't get lock file: $!";
#	The "$$" variable is the current process ID which gets
#	written into the lock file.
printf(LOCK "%10d\n", $$);
close(LOCK);

#	Perl lets the programmer catch certain signals.  In this case
#	I want the Perl script to give up the modem after a short period
#	of time, even if something unexpected goes wrong.  So I set an
#	alarm to go off in 60 seconds, and tell Perl if the timer goes
#	off to call the death subroutine.
alarm 60;		# Panic timer
$SIG{'ALRM'} = &death;
$SIG{'INT'} = &death;

#	The other examples so far deal with only the console.  In this
#	example we needed to get to various files such as the lock
#	file and the modem.  The open function is used to describe
#	which file to use.  The line containing the select function
#	is used to ensure that characters written to the modem go out
#	immediately instead of waiting for a complete line or buffer of
#	text.  This is important for interactive devices, and not needed
#	for disk files.
open(TTY, "+>$Port") || die "Can't open modem";
select(TTY); $| = 1; select(STDOUT); $| = 1;

#	The following commands talk to the modem while putting in
#	pauses to let the modem and phone system respond as needed.
print "Send the paging\n";
sleep 1;
print TTY "\r";
sleep 1;
print TTY "atz\r";
sleep 4;
print "Dial string is: atm0dt$Phone,,,,,,,,,,*39\n\n";
print TTY "atm0dt$Phone,,*39#\r";
sleep 10;
print TTY "\r";
print TTY "atz\r";

#	Release the lock file
`touch .paged`;
death();

###
###	Death does the clean up processing
###
#	Subroutines are declared like this.  This particular subroutine
#	does not take parameters.  In another example we will show how
#	parameters are handled.  The other thing of note is that all
#	variables are global variables unless you use the local
#	statement.  More on that later as well.
sub death
    {
    print TTY "\ratz\r";
    close(TTY);
    unlink($Lock);
    exit(0);
    }

PEAK


Last modified 27 May 2006
Dave Regan
http://www.peak.org/~regan/
Resume / Biography