Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 20 Aug 1996 04:01:47 -0400 (EDT)
From:      hoek@freenet.hamilton.on.ca
To:        Leonard@pacbell.net
Cc:        questions@freebsd.org
Subject:   Re: Pager Program?
Message-ID:  <199608200801.EAA14857@james.freenet.hamilton.on.ca>

Next in thread | Raw E-Mail | Index | Archive | Help
In Email, Leonard Chung <Leonard@pacbell.net> wrote:
> At 05:10 PM 8/19/96 -0400, hoek@freenet.hamilton.on.ca wrote:
> script after running chmod +x on it, but FBSD refused to run the script

Actually, it was the shell that refused to run the script. :) FBSD didn't
even get to find out about the whole thing. 

> saying that it isn't a valid command.  Am I doing something wrong here?

Yes.


> If you could add some comments, that'd be great.  Also, I tried to run the

Ok, here's a commented version, in addition to a bit of documentation. 
Like I said before, though, it hasn't been "real-world" tested, since I
don't have a pager.  All I know is that it dials my phone number whenever
the modem sends a RING. :)


The basic idea is as follows,

Your modem is attached to a com port.

For every com port you have, there is a file in your /dev directory 
which, when read from, returns data from the com port, and, when written 
to, sends data to the com port.

(Incidentally, this file has associated with information regarding the
baud rate, cr->nl mapping, and just about everything else.  man 1 stty if
such unimportant details are interesting.  man 3 tcgetattr is even more
interesting, actually.  This `struct termios' stuff is associated with,
for example, stdin, stderr, and /dev/mouse)

We want a shell script that will, when it reads a `RING', print
`atdt 5557399'.  It must not just print `atdt 5557399', however.  It 
must, after the `RING', wait about 10 minutes so that the person can 
leave their message.  Because it's possible for the attempted `atdt 
5557399' to fail, it must also somehow know that the pager was 
successfully dialed.

Because the reading (from the com port) will BLOCK (or wait) until a 
whole line is read, the script will have to fork one process to read for 
a succesful "CONNECTED" message, and another to dial in the meantime.

Depending on your specific modem some changes may be necessary.  
Hopefully they wouldn't/won't be too hard to make.

This script expects to have data from the modem sent to it as (stdin) 
and data printed to (stdout) is expected to go to the modem.

Therefore, it must be started like this,

./pager < /dev/cuaa? > /dev/cuaa?

So that it can read/write to /dev/cuaa? it must be run as root.  Where 
the `?' is, you should put the com port number of the modem - 1.  For 
example, if you modem is on com1, you would use

./pager < /dev/cuaa0 > /dev/cuaa0

We need to specify the `./' in front of `pager' because the pager program 
is not in one of the directories specified in your PATH.  Alternatively, 
if it is, you may have to type `rehash' to make csh know that it is in 
one of the directories specified in your PATH.

There!  Lotsa comments!  :)  Any other (fairly specific questions, I 
trust) will be entertained, too.  :)


#! /bin/sh
 # This line makes the system use the /bin/sh program to interpret the
 # file.  It also means that making this a setuid program will not make
 # it a setuid program.

 # If there is already an environment variable by the name of LOGFILE,
 # then we'll leave LOGFILE as that.  Otherwise, we'll make LOGFILE 
 # equal to `/dev/null'.  LOGFILE=~/.junk ./pager < /dev/cuaa1 > /dev/cuaa1
 # would set LOGFILE to ~/.junk.
LOGFILE=${LOGFILE:-/dev/null}

 # Later we fork another process.  Because it's a different process it
 # will have a different process id.  However, it needs to know what 
 # the pid of it's parent is, so we'll store it here.  (It needs to 
 # know because the two communicate via files named after the pid).
MYPID=$$ export MYPID

 # These are the afore-mentioned files.  $$ expands to the pid.  We
 # could have used DIALINGPAGER.${MYPID}, too.
rm -f /tmp/DIALINGPAGER.$$
rm -f /tmp/CONNECTED.$$

 # Turn echoing off.  Standard hayes command.  We use the `printf' 
 # program so that we have translation of \r and \n (for example.  
 # Some (most, all?) modems expect lines to be terminated in the 
 # DOS fashion of \r\n instead of just \n.
printf 'ate0\r\n'
printf 'atx3\r\n'

 # equivelant to C's  while (1) {
while [ ! ]
do
         # Read one line of input into the variable ${l}.
	read l
         # Remove any \r and \n 's from ${l}.
	l=`echo ${l} | perl -pe 's/\r|\n//g'`
         # `man 1 [' for more info on the `[' expression syntax.
	 # We put an `x' in front of RING and ${l} since it's possible
	 # for ${l} to be empty, which would result in `[ = xRING ]'
	 # which, of course, is a syntax error.
	if [ x"${l}" = xRING ]
	then
		 # Print a dated message into the logfile.  `>>'
		 # specifies that we concatanate to the logfile. 
		 # a simple `>' would overwrite it (unless some NOCLOBBER
		 # screw-up variable is defined).  man 1 date
		date '+%m/%d %H:%M Caught a `RING'\''!' >> ${LOGFILE}
		 # True if the file does not exist.
		 # Obviously we don't want to be trying to dial the
		 # pager if we are already trying to dial the pager.
		if [ ! -e /tmp/DIALINGPAGER.$$ ]
		then
 # Fork a second copy of `sh' and run it in the background.  Pass to it
 # the following commends, upto the `EOF'.  Do not perform any 
 # interpretation on the text between here and the EOF before passing
 # it to the forked shell.  `man 1 sh' and then text-search for the
 # string `here-document'.
sh << "EOF" &
		 # Defines a shell function called redial.  I really
		 # don't know why I made this a function.  In retrospect,
		 # it's kind of silly.  Oh well, at least I don't make
		 # a gratouitous (sp?) use of `cat' anywhere... :)
		redial () {
			 # Append dated message to logfile.
			date '+%m/%d %H:%M Dialing pager.' >> ${LOGFILE}
			 # Can you find the hidden message? ;)
			printf 'atdt 5557399\r\n'
		}
		 # NOTE that we have not yet executed any of the commands
		 # in the redial function.
		 #
		 # Goto sleep for ten minutes to allow the person ample
		 # time to finish their message. 
		sleep 600
		 # Loop until the file /tmp/CONNECTED.#### exists.
		while [ ! -e /tmp/CONNECTED.$MYPID ]
		do
			 # Call the redial function.
			redial
			 # Allow time for the modem to actually dial
			sleep 30
		done
		 # We're out of the loop.  That means that the
		 # file /tmp/CONNECTED.#### exists.  That means we
		 # connected.  Yea!  Let's make a dated logfile entry.
		date '+%m/%d %H:%M Successfully dialed pager.' >> ${LOGFILE}
		 # Remove these two files.  And do so silently.
		rm -f /tmp/DIALINGPAGER.$MYPID
		rm -f /tmp/CONNECTED.$MYPID
 # This signifies the end of the commands passed to the second, forked,
 # backgroud shell.  Try to envision the flow of commands.  This section
 # was really just one command it executed in the background.  To the 
 # shell it executed in the background, this section was a number of
 # commands.  The foreground shell has already continued executing 
 # commands far far beyond this one.  The background shell, however,
 # stops here (since this is all that is passed to it).
EOF
		 # Create the file to show that we currently have 
		 # a shell in the background dialing the pager.  That
		 # background shell will delete the file when it is 
		 # no longer dialing the pager.
		touch /tmp/DIALINGPAGER.$$
		 # ENDIF, in BASIC terminology.  This endif goes with 
		 # the original test to see if there was already 
		 # a process dialing the pager.  For some reason I didn't
		 # intend between hither and thither.  Shucks Darn.
		fi
	 # else if.
	 # My modem seems to send either `BUSY' or `NO CARRIER'
	 # when it connects to a voice line.  If ${l} equals this
	 # then we must have connected.  Your modem may be different.
	elif [ x"${l}" = xBUSY -o x"${l}" = x"NO CARRIER" ]
	then
		 # Create the file to let the spawned background shell
		 # know that we have connected.
		touch /tmp/CONNECTED.$$
		 # Log It!
		date '+%m/%d %H:%M Connected!' >> ${LOGFILE}
	 # Else if ${l} has equaled nieither RING, nor BUSY, nor 
	 # NO CARRIER, then do this.
	else
		 # Okay, only do this if ${l} actually equals something
		 # and is not just an empty line.  (Your modem probably
		 # sends an empty line along with every interesting
		 # line).
		if [ ! x"${l}" = x ]
		then
			 # Log It!
			date '+%m/%d %H:%M Caught a `'"${l}"\' >> ${LOGFILE}
		fi
	fi
 # end of the intermniable while loop.
done

 # Try doing that with a DOS batch file!  ;)

-- 
--
tIM...HOEk
Outnumbered?  Maybe.  Outspoken?  NEVER!



Want to link to this message? Use this URL: <http://docs.FreeBSD.org/cgi/mid.cgi?199608200801.EAA14857>