From limbic!gil Thu Mar 15 13:25:46 EST 1990
Article 584 of unix-pc.sources:
Path: icus!limbic!gil
>From: gil@limbic.UUCP (Gil Kloepfer Jr.)
Newsgroups: unix-pc.sources
Subject: Answering Machine using Voice Power (V1.0)
Message-ID: <651@limbic.UUCP>
Date: 15 Mar 90 03:14:06 GMT
Distribution: unix-pc
Organization: ICUS Software Systems, Islip, NY
Lines: 1683

Here is an answering machine program for use with the UNIX-pc version of
the AT&T Voice Power board that so many of you purchased through the deal
that Lenny Tropiano arranged.

Please note that I am restricting the distribution initially to the unix-pc
hierarchy for the following reasons:

	1.  AT&T does still manufacture a product called Voice Power,
	    which does the same thing as the one for the UNIX-pc, except
	    that the one for the UNIX-pc has *more* features (yes!!).
	    Since I use some of these features, I felt that there would
	    be possible confusion in the cross-post.

	2.  I'm sure that there are some small bugs in the README
	    file, and things in the program itself which should be
	    cleaned-up.  I would rather get suggestions back from a
	    small subset of users first, then go with a larger
	    distribution.

Also note that I would like to remain the coordinator of any modifications
to this software - this means that in posting this, I ask that you please
lend me the courtesy of sending all patches to *me first*, at which time
I will merge them into the source and post them in a sane manner to the
net.  This is the kind of program where a number of conflicting versions
would eventually make the program unusable.

Lastly, this program requires two libraries which are part of a certain
Voice Power package (I don't remember which).  These are the 'voice'
and 'tts' libraries.  If you don't have them, please drop me a message.
As long as no copyrights prevent me, I will attempt to make these
available for public digestion.

I will respond to ALL users donating patches via e-mail.  If you don't
receive an e-mail message in response to a patch you sent me, please
contact me via voice.

I hope this contribution to the net helps start some more interesting
experimentation into the uses of Voice Power.  My thanks to Lenny for
catching a few spelling errors before the final posting.

Gil Kloepfer, Jr.  ...!ames!limbic!gil  |  gil%limbic@ames.arc.nasa.gov

=======
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  README ansmach.c anscheck.c
# Wrapped by gil@limbic on Wed Mar 14 21:55:08 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f README -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"README\"
else
echo shar: Extracting \"README\" \(21207 characters\)
sed "s/^X//" >README <<'END_OF_README'
XREADME file for 'ansmach' version 1.* -- 3/12/90
XBy Gil Kloepfer, Jr   ICUS Software Systems
X(c) Copyright 1990 Gil Kloepfer, Jr.  (NOTE: Please read the full copyright
Xand disclaimer at the end of this file)
X
X
XIntroduction
X------------
X
XThe answering machine program provided in this distribution is a simple
Xanswering machine with some interesting extended capability.  However,
Xit currently is really a little more than a hack at the current time,
Xand could probably be more appropriately called "a UNIX programmer's
Xvoice mail system."
X
XIn order to get the system running the way you'll want, there are
Xseveral source code parameters and files you need to set-up.  They
Xare described below.
X
XNote that you may hack on this program to make it do other things,
Xbut please e-mail the changes back to me (unless you plan to keep them
Xlocalized) because I would like to maintain some sort of order to the
Xprogram even if it starts as madness.  I will respond personally to
Xall mailings, so if you don't get an e-mail response, please get in
Xvoice contact with me at the number below.
X
XPlease also note that there are yet some 'unimplemented features' of
Xthe program.  These will be described below also.  You are forewarned
Xto read this whole text before using the program.
X
X
XFeatures & Bugs
X---------------
X
XThis answering machine program has the following features:
X
X	1.	Fully-electronic message playback and recording -- no
X		tapes to break or stretch or motors to wear-out
X
X	2.	Time/date stamping on each message
X
X	3.	Ability to distinguish between new and old messages
X
X	4.	Ability to check the number of e-mail messages in a
X		specified user's mailbox
X
X	5.	Password protection of sensitive functions
X
X	6.	Touch-tone(tm) command-driven menus allow access to
X		messages from virtually any tone-dialing phone.  No
X		'long-tones' are necessary to make the system work.
X
X	7.	Software control allows a programmer to add functions
X		as necessary to perform other miscellaneous action
X
X	8.	Toll-saver makes the answering machine pick-up in
X		4 rings on the first recorded call, and 1 ring on all
X		subsequent calls
X
X	9.	All answering machine activity is logged to a file
X
X
Xand with all feature-filled programs, there are bugs:
X
X	1.	Message length is fixed due to some bugs in the voice
X		library's handling of silence detection
X
X	2.	There is no ability to delete messages remotely.  This
X		is actually a security feature, except there is currently
X		no way to enable such a feature
X
X	3.	Messages are kept in numbered files which have no real
X		meaning except to the program.  Skips in numbered files
X		show up as 'unavailable messages' until the control.dat
X		file is recreated
X
X	4.	Program could probably be more easily written as a
X		shell-script at a minor decrease in performance, but
X		with better ease of modification
X
X	5.	The e-mail check feature is a kludge
X
X	6.	There is a provision for the password to be kept in
X		control.dat, but it isn't implemented
X
X	7.	There is a provision for the answering machine to be
X		'shut off', but it isn't implemented either.  In fact,
X		I don't know how I planned to implement it!
X
X	8.	The outgoing message cannot be changed remotely
X
X	9.	No checks are performed to assure that sufficient disk
X		space exists to record the incoming messages
X
XIn many cases, the bugs noted here don't significantly affect the operation
Xof the program, and are necessary only as personal taste dictates.  The
Xprogram itself actually performs pretty well in most real-world situations.
X
X
X
XVoice response files
X--------------------
X
XThe following are voice 'scripts' to be loaded into the voice response
Xfiles (they are located in what would be called the 'vocab' directory).
XThey are created using the voice editor, as follows:
X
X		$ ve -l 3 -24 file
X		$ mv file:e:v file
X
XThe "-l 3" means to disconnect the phone line from the voice board and
Xuse the local telephone to record the messages.  The "-24" means to
Xrecord the messages in 24kb sub-band mode.  I've found that although
Xthis tends to make the messages a bit big (byte-wise), the clarity is
Xmore pleasing to the caller.
X
X** File: admenu
X** Purpose: administration menu
X
X"Touch one to retrieve the new messages.  Touch two to retrieve all
X messages.  Touch three to toggle toll-saver on or off.  Touch four
X to check e-mail.  Touch five to exit system.  Enter now."
X
XThere are actually two other 'hidden' commands which probably won't
Xwork on your system, but could be easily hacked to make work.  Command
X6 resets the getty on my /dev/tty001 which is the modem.  If the modem
Xever locks-up, I can reset it by making a telephone call.  Command 7,
Xif entered twice, initiates an unattended reboot of my system.  I don't
Xannounce these in the administration menu 'just in case.'
X
X
X** File: beep
X** Purpose: announce start of recording to caller
X
XRecord a suitable one-second beep.  I got mine by putting my VT100 in
Xcontinuous beep mode, and recording it.  It sounds sick.  I would welcome
Xsome more interesting 'tone's.
X
X
X** File: bye
X** Purpose: Tell a caller good-bye
X
X"Good bye."
X
XThis file is played if the caller records a message longer than the
Xspecified length, and when the '5' command is entered in administration
Xmode.
X
X
X** File: entpassw
X** Purpose: prompt for password
X
X"Please enter the password."
X
X
X** File: holdon
X** Purpose: tell caller to hold on (in admin mode)
X
X"Please hold on."
X
X
X** File: modreset
X** Purpose: announce that the modem reset has been performed
X
X"The modem on <your-port-name> has now been reset."
X
X
X** File: nonew
X** Purpose: announce that there are no new messages waiting
X
X"There are no new messages waiting at this time."
X
X
X** File: outgoing
X** Purpose: your outgoing message
X
XRecord the same kind of message that you would record as an outgoing
Xmessage on a conventional answering machine.
X
X
X** File: reboot
X** Purpose: announce system reboot
X
X"The system will now be rebooted.  Please hang up now."
X
X
X** File: thankyou
X** Purpose: thank the caller for something
X
X"Thank you."
X
X
XConfiguration
X-------------
X
XBefore you can get the answering machine going, you will need to configure
Xit to your system.  The following are recommended directory structures.
XYou don't have to adhere to them, but they tend to make life a little
Xeasier:
X
X	/usr/ansmach	- Directory where answering machine binaries and
X			source/vocab directories are kept.  Keep protected
X			so that you and root can read/write/execute, and
X			world has no access.
X
X	/usr/ansmach/src - Directory where the source and things like this
X			README file are kept
X
X	/usr/ansmach/vocab - Directory where all voice response messages
X			are kept
X
X	/usr/spool/ansmach - Directory where all log files, data files,
X			and messages are kept.  Should be 'rwx' for
X			yourself and root, '---' for world.
X
XAll these may be configured by changing the #define's at the top of the
Xsource code.  It is obvious when looking at the list of defines which
Xones define the files.  I won't bother explaining these.
X
XThe following other #define's allow some customization of the program:
X
XSYSPASSW	This is defined as a character string of numeric
X		digits which is the 'password' to get to administration
X		mode.  Although the comments refer to this as the
X		'initial' password, in reality this is the ONLY password.
X
XMAXFLEN		This is the maximum length of a filename/path combination.
X		It is currently set for 50, and one should not find it
X		necessary to mess with it unless large pathnames are
X		used.
X
XMBUFSIZ		This is the input buffer size used when reading the
X		user's mail file.  It is currently set for 132 characters,
X		which is more than ample when reading the mail header.
X
XRECTIME		This is the amount of time (seconds) that an incoming
X		message is recorded.  It is currently set for 60 seconds,
X		which appears to be a relatively acceptable value.
X		Remember that for every second of recording time using
X		the 24K sub-band, 4000 bytes of data is recorded.
X
XTSVRING		This is the number of rings the answering machine will
X		answer the phone on the first message using toll saver.
X		It is currently set for 4 rings, and should not be
X		changed unless you really have strong feelings otherwise.
X
XCARDID		Voice card slot ID.  This is currently set for slot 0,
X		but could be set to slot -1 so the floating card would
X		be used (floating card means the first available card).
X
XAUTO_ON		This is the number of rings that the answering machine
X		will automatically turn itself on.  Since this feature
X		is not fully implemented in this version, it should
X		be left at 10 rings.
X
XSUBPROC		When this symbol is defined, the answering machine will
X		fork a child of itself and put a 'setpgrp'd version of
X		itself in the background, while the parent will immediately
X		return to the shell.  This is the normal mode of operation
X		so that the program may be started at boot time using a
X		shell-script in /etc/daemons.
X
X		For those who wish to start the answering machine from
X		the /etc/inittab file, this symbol should be #undef'd
X		so that the program doesn't continuously respawn.
X
XCARSALE		This was a grand idea of mine when I thought of selling
X		my car.  The intent was that the outgoing message would
X		direct a user to press '1' for more information on the
X		car-for-sale.  After hearing the advertisement, one could
X		leave a normal answering machine message if desired.
X		Defining this symbol will enable this function, and the
X		vocabulary file 'carinfo' will be played.  This feature
X		will be disabled by default.
X
X
XPASSIVE		This VERY IMPORTANT symbol defines whether the answering
X		machine controls the connected phone and phone line in
X		passive or active mode.
X
X		In ACTIVE MODE (#undef PASSIVE) - the phone connected to the
X		SET jack on the voice power board can ONLY be used for the
X		answering machine while the answering machine is running.
X		The only way for the phone to be used for normal telephone
X		conversations is to stop the answering machine program.
X		Answering functions on the LINE jack (ie. ringing) are
X		handled normally, but the attached phone will neither
X		ring nor will it allow normal conversation.
X
X		In PASSIVE MODE (#define PASSIVE) - the phone connected
X		to the SET jack is passed to the LINE jack so that the
X		connected telephone may be used for normal conversations
X		and will perform all the normal functions of a normal
X		phone so long as the answering machine has not answered
X		the phone.  The answering machine program is accessed
X		by the attached phone by "FLASHING" the phone (ie. lifting
X		the receiver, waiting for telco dial-tone, then pressing
X		the switch-hook down for 1 second, then lifting the
X		switch-hook again).  The connected phone(s) are then
X		connected to the answering machine until the receiver
X		is placed on the hook, at which time the system will
X		become passive again.
X
X		The default mode is PASSIVE mode, which will probably
X		be the mode of choice for most users.  It takes a little
X		experimentation to see just WHY this mode is such a neat
X		thing.  Let it be said that in PASSIVE mode, all phones
X		in the home can be connected to the SET jack, the main
X		phone line can be connected to the LINE jack, which will
X		allow any phone in the house to access the answering
X		machine by simply flashing the switch-hook.
X
X		Two things to note:  One is that the flash threshold
X		is about 10 seconds.  For you mistake-ridden dialers,
X		or for people who repeatedly speed-dial this might be
X		a problem since the system will interpret the hang-up
X		within 10 seconds to be a flash.  Again, experimentation
X		is best to find this out.  Second is that if you enter
X		the answering machine while in PASSIVE mode, an incoming
X		call could arrive while you're checking your messages.
X		In this case, the attached phone(s) will not ring and the
X		caller will receive no signal that you are using your
X		answering machine.  For this reason, and for safety
X		reasons, it is recommended that at least one phone be
X		tied directly to the phone line so that phone calls
X		can be made in an emergency should the voice power board
X		fail for some unknown reason.
X
XSYSFUNCS	Defining this symbol enables the invisible functions 6
X		and 7 as noted above in the admin mode dialogue.  This
X		is disabled by default, and should only be enabled and
X		implemented by experienced programmers.
X
XAdditionally, there is a 'static char' variable called 'mailfile' which
Xcontains the text 'YOUR-NAME'.  You should change 'YOUR-NAME' to your
Xlogin-id on the system.  This also assumes that you are running the
Xanswering machine suid to that ID so it can read the mail file.  It
Xneeds to in order to determine the number of messages you have.  Don't
Xsacrifice your mail file's security to make the answering machine work.
X
X
XChecking Your Messages
X----------------------
X
XMessages may be checked by entering admin mode and waiting for the
Xelectronic voice to tell you how many messages you have waiting.  Old
Xmessages are considered messages that have been listened-to in their
Xentirety or skipped with the '*' key.
X
XAdditionally, there is a hack-program called 'anscheck.c' which may
Xbe compiled and run from your .profile (or .login, for csh users) which
Xwill inform you of any voice messages upon login.  Be sure that you modify
Xthis program if you intend to use it and have modified the pathnames
Xin the answering machine program.
X
X
XListening To Your Messages
X--------------------------
X
XAs implied above, messages that have been left and have not been listened-
Xto before are considered 'new' messages.
X
XNew messages may be heard by using the '1' option from the admin menu.
XBefore a message is played, the date and time that the message was
Xleft is growled-at the operator in an electronic voice.  At any time
Xwhile the message is being played, the remainder of the message may
Xbe skipped by pressing the '*' key, while the retrieval mode can be
Xaborted in its entirety by pressing the '#' key.
X
XMessages skipped with '*' are no longer new, and may only be listened-to
Xagain by using the '2' option (listen to old messages).  The above
Xoptions '*' and '#' may be used when listening to old messages also.
X
X
XGetting To Admin Mode Remotely
X------------------------------
X
XOne normally needs to get to admin mode remotely in order to remotely
Xlisten to messages.  The admin mode is accessed by pressing the '#'
Xkey while the outgoing message is playing.  A prompt for the password
Xwill be played, at which time the password defined in the SYSPASSW
Xoption above should be entered, followed by another '#' key.  If
Xall goes well, the system should thank you for correctly entering the
Xpassword, and continue to enter admin mode.  If you incorrectly enter
Xthe password, the system will immediately hang-up on you.  This is to
Xkeep intruders from gaining feedback about your system from its prompts.
X
XNote that in ACTIVE mode, the local phone will operate in the same manner
Xas the remote phone (ie. you will need to enter the remote sequence
Xabove).  PASSIVE mode does not require a password.
X
XNOTE!!  When calling your answering machine from a coin telephone using
Xa long-distance calling card, you will have a problem with conflicting
Xfunctions of the '#' and '*' keys (some phones use them to indicate
X'new call').  One can usually struggle through the procedure in this
Xcase by following the following steps:
X
X		1.  Wait until your outgoing message has played
X		halfway-through.
X
X		2.  Hit the '#' key followed by the FIRST DIGIT of
X		your password code quickly.  This usually fools the
X		phone company's computers into thinking you really
X		didn't mean 'new call.'
X
X		3.  Enter the remainder of your password, then
X		press '#' followed by '1' quickly as before.  This
X		will complete your password and start getting the
X		first message.  One could substitute a '9' for the
X		'1' if desired, so no function is initially performed.
X
XIn future versions of the program, a digit will be designated the 'enter
Xdigit' and won't be allowed anywhere in the password.  This will solve
Xthe problem with '*' and '#'.
X
X
XDeleting Messages
X-----------------
X
XCurrently, for security reasons, there is no way to delete a message from
Xthe answering machine admin mode.  It is recommended that all messages
Xbe deleted at once from the system, using the following procedure:
X
X	1.  Stop (kill -2) the answering machine
X
X	2.  Remove the file /usr/spool/ansmach/control.dat.  This is
X	the file which contains the last recorded message information
X	and toll saver.  You will need to reset toll saver to 'OFF'
X	if that's the way you like it normally.
X
X	3.  'mv' any of the incoming message files (*.in) you wish to
X	keep to a name other than something with a '.in' suffix.
X
X	4.  Remove (rm) '*.in'
X
X	5.  Restart the answering machine
X
XOptionally, you may just remove blank messages or those you wish to
Ximmediately discard.  When the system comes upon a message you removed,
Xit will say "Message 'n' is not available."  
X
XIf you fail to remove 'control.dat' at the time you delete the incoming
Xmessage files, you will get a whole lot of blurb telling you that all
Xthe messages you deleted are not available.  Note this will only happen
Xwhen you use the '2' command from the admin mode.
X
X
XConnecting To The Phone Line
X----------------------------
X
XThe simplest way to connect the system to the phone line is to connect
Xthe voice power board as follows:
X
X     -----+
X    \     |
X    /     |Line
X    \     |---------------------------------------To Phone Wall Jack
X    /     |
X    \     |Set
X    /     |-----------To Telephone(s)
X    \     |
X    /     |
X    \     |
X     -----+
X
XThere are others who might wish to connect the AT&T Phone Manager to
Xthe system in addition to the voice board.  In this case, LINE1 on the
XUNIX-pc should be connected to SET, and the telephone(s) should be
Xconnected to PHONE on the UNIX-pc.  Wiring things this way will
Xenable the UNIX-pc to be used to get the answering machine messages (you
Xcould even program the flash sequences and commands, I believe, in the
Xphone manager!!).  This sure beats a speaker/amp connected to OUT
Xon the voice power board, like I have!
X
X
XCompilation
X-----------
X
XThe program is compiled as follows:
X
X	$ cc -v -O -o ansmach ansmach.c -lvoice -ltts -s
X	$ cc -v -O -o anscheck anscheck.c -s
X
XNote that those with the 'shared library' compiler commands can happily
Xsubstitute those for 'cc'.
X
XIf you are missing any of the libraries above, please let me know.  I've
Xbeen informed that not everyone has them.  Queries for this information
Xwill likely be answered by a form message which states where you can
Xget it, or states why you can't.  I see no problem right now with
Xgetting the libraries to those who need them.
X
X
XProblems
X--------
X
XThis should get most of you started using the answering machine.  I know
XI left some stuff out, and I'm counting on you to send me any additions
Xyou have so that I can incorporate them into this text file (or the
Xprogram, whichever is appropriate).  If you're REALLY STUCK -- and I
Xmean REALLY STUCK, I can be reached at home between 6PM and 10PM eastern
Xtime at (516) 794-6501.  If you get my answering machine, please (!!)
Xleave your name, phone number, and a good time to call you back, and
XI will.  I prefer queries by e-mail, and these are welcome anytime.
XOne of the following net-addresses should work:
X
X	gil%limbic@ames.arc.nasa.gov		(Sites on the Internet)
X	...!ames!limbic!gil			(UUCP sites)
X	gil@limbic.UUCP				(UUCP sites with smart mailers)
X
X
X
XCopyright & Disclaimer
X----------------------
X
XUnfortunately, due to the nature of this software, there is a specific
Xcopyright and a most specific disclaimer attached to this file and
Xany files or software associated with this answering machine.
X
XFirst, all software and accompanying text, unless otherwise copyrighted
Xby AT&T, is copyright (c) 1990, Gil Kloepfer, Jr.  All rights reserved.
XYou may use the software for your own personal uses or in your business,
Xbut you can't sell it or any part of it or otherwise try to gain profit
Xfrom the software itself (on the other hand, if using the software and
Xgetting your calls answered helps you gain profit, all the power to you!).
XAs part of this copyright, I request that all modifications be sent to
Xme so that I can properly maintain the program and text files, and can
Xkeep the network with a good, current copy.  I'm not out to keep anyone
Xfrom making mods to it, I just want credit for the work I did, and I
Xwant others' work to be distributed and credited in an orderly way.
XIf you have a totally new idea which you took a part of my program
Xto make, please give me appropriate credit.  I would do the same for
Xyou.
X
XSecond, I take NO RESPONSIBILITY for any ill-effects you may obtain
Xfrom this program, including, but not limited to, inability to use
Xyour phone, repair bills resulting from or related-to the use of
Xthis program, inability to use the phone in an emergency situation,
Xacts of God (I'm not God, so how could I be responsible?!), etc.
XIf you use this program and like it, and it works for you, fantastic.
XIf it doesn't, tough.  It didn't cost you anything, and it shouldn't
Xcost me anything if you couldn't use it properly (or even if you
Xcould or couldn't use it at all).
X
X[End of README file]
END_OF_README
if test 21207 -ne `wc -c <README`; then
    echo shar: \"README\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f ansmach.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"ansmach.c\"
else
echo shar: Extracting \"ansmach.c\" \(24059 characters\)
sed "s/^X//" >ansmach.c <<'END_OF_ansmach.c'
X/***************************************************************************\
X *
X * File name:		ansmach.c
X *
X * Purpose:		Provide answering machine service functions using
X *			the AT&T Voice Power board
X *
X * Programmer:		Gil Kloepfer, Jr.  ICUS Software Systems
X *
X * Revision history:
X *
X *	1.0  3/23/89	Program created
X *	1.1  3/30/89	Corrected/enhanced/added the following:
X *			  1)  Log is now in a separate file and is
X *			      date/time stamped
X *			  2)  Toll saver mode proposed
X *			  3)  Ability to modify password proposed
X *	1.2  4/3/89	Allowed options to skip new message, skip
X *			old messages, and quit.
X *			AGC enabled on recording inbound messages
X *	1.3  4/16/89	Automatically fork and go to background
X *	1.4  4/28/89	Added '1' command for information about the
X *			car for sale.
X *      1.5  5/22/89	Added optional code which allows the answering
X *			machine to connect to all phones in the house,
X *			using flash to obtain control of the answering
X *			machine functions.
X *			Answering machine can now be "shut off" and will
X *			turn itself on automatically if phone rings 10
X *			times.  Undefine AUTO_ON to disable this function.
X *      1.6  12/19/89	All ESRs set mode back to 24Ksb, and this is
X *			initialized before the v_fplay at the wait_call
X *			loop.  This fixes a bug that sometimes allows the
X *			answering machine to be left in TTS mode.
X *	1.7  1/90	Performed some code cleanup in preparation for
X *			the USENIX UNIX-pc BOF
X *	1.8  3/12/90	Cleaned-up #define comments
X *
X *
X * Comments:
X *
X *	This program is based on the hotline example program accompanying
X *	the voice power software, although most of the routines have been
X *	significantly cleaned-up or enhanced for this application.
X *
X *	Mail check code borrowed almost verbatim (I added the tts stuff)
X *	from Lenny Tropiano's "logininit" program.  Thanks much Lenny!
X *
X * Compiled by:		$ cc -v -O -o ansmach ansmach.c -lvoice -ltts -s
X *
X * Copyright/		(C) 1989 Gil Kloepfer, Jr., ICUS Software Systems
X * Disclaimer:		All Rights Reserved
X *			[See full copyright in accompanying README file]
X *
X *			Permission is granted to use, copy, or redistribute
X *			this software provided that this header in its
X *			entirety is kept in the source code, that all
X *			copyright notices are left intact, and that it is
X *			not distributed or used for monetary gain of any
X *			kind without the express, written permission of
X *			the copyright holder(s).  Furthermore, if this
X *			software is modified, all changes should be mailed
X *			to ames!limbic!gil or gil%limbic@ames.arc.nasa.gov
X *
X\***************************************************************************/
X
X
X/*
X * System include files
X */
X
X#include <sys/types.h>
X#include <sys/v2.h>
X#include <sys/vl.h>
X#include <sys/tts.h>
X#include <stdio.h>
X#include <fcntl.h>
X#include <setjmp.h>
X#include <signal.h>
X#include <sys/stat.h>
X#include <time.h>
X
X/*
X * Program parameter definitions
X */
X
X#define	TRUE	1		/* Used in flags to denote boolean TRUE */
X#define	FALSE	0		/* Used in flags to denote boolean FALSE */
X#define	SYSPASSW "123"		/* Initial password for admin mode */
X#define	MAXFLEN	50		/* Maximum file/path name length */
X#define	MBUFSIZ 132		/* Mail check buffer size */
X#define	RECTIME	60		/* Time allowed to leave a message (secs) */
X#define	TSVRING	4		/* Answer on 4th ring for toll saver */
X#define	CARDID	0		/* Voice card ID */
X#define	AUTO_ON	10		/* Turn on automatically in 10 rings */
X#define	SUBPROC			/* Defined for automatic background exec. */
X#undef	CARSALE			/* Defined for 'car for sale' message */
X#define	PASSIVE			/* Defined to execute in passive mode */
X#undef	SYSFUNCS		/* Undefine if system functions should be disabled */
X
X/*
X * Files which contain voice response messages
X */
X
Xstatic char *m_beep = "/usr/ansmach/vocab/beep";	/* Beep */
Xstatic char *m_bye = "/usr/ansmach/vocab/bye";		/* Good Bye */
Xstatic char *m_entpassw = "/usr/ansmach/vocab/entpassw"; /* Enter the password */
Xstatic char *m_outgoing = "/usr/ansmach/vocab/outgoing"; /* (outgoing message) */
Xstatic char *m_thankyou = "/usr/ansmach/vocab/thankyou"; /* Thank you */
Xstatic char *m_holdon = "/usr/ansmach/vocab/holdon";	/* Please hold on */
Xstatic char *m_admenu = "/usr/ansmach/vocab/admenu";	/* (admin menu) */
Xstatic char *m_nonew = "/usr/ansmach/vocab/nonew";	/* No new messages */
Xstatic char *m_carinfo = "/usr/ansmach/vocab/carinfo";	/* (car for sale info) */
X#ifdef SYSFUNCS
Xstatic char *m_mdreset = "/usr/ansmach/vocab/modreset";	/* The modem has been reset */
Xstatic char *m_reboot = "/usr/ansmach/vocab/reboot";	/* The system will be rebooted */
X#endif
X
X/*
X * Other file definitions
X */
X
Xstatic char *controlf = "/usr/spool/ansmach/control.dat"; /* control file */
Xstatic char *messdir = "/usr/spool/ansmach";		/* messages dir */
Xstatic char *logfile = "/usr/spool/ansmach/ansmach.log"; /* log file */
Xstatic char *mailfile = "/usr/mail/YOUR-NAME";		/* mail file to check */
X#ifdef SYSFUNCS
Xstatic char *resetmodem = "/usr/lib/uucp/tbreset 001";	/* reset modem script */
Xstatic char *sysreboot = "/usr/lbin/sudo -r /etc/init 3"; /* reboot command */
X#endif
X
X/*
X * Structure which defines the system control file
X */
X
Xstruct sysctl {
X	int	lastread;		/* Last message retrieved */
X	int	lastmsgf;		/* Last message filed */
X	char	syspassw[20];		/* System password code */
X	int	tollsaver;		/* Toll saver enabled flag */
X	int	systemon;		/* Answering machine "ON" */
X};
X
X/*
X * Definition of the months of the year for saying the date.  NOTE: These
X * months are spelled phonetically in some cases to make the tts
X * algorithim say the words properly.  Do not use these months for
X * PRINTING the date!
X */
X
Xstatic char *ttsmonths[] = {
X	"january","february","mmarch","april","mmay","june","july",
X	"august","sehptember","october","nohvember","deecember" };
X
X/*
X * Global variables
X */
X
Xchar *progname;		/* Pointer to name of program (argv[0]) */
XFILE *logfp;		/* Logfile file pointer */
X
Xlong timebuf;		/* Miscellaneous buffer for time operations */
X
Xjmp_buf restart_buf;	/* Setjmp address for restarting system */
Xint card = CARDID;	/* voice card number */
X
X/***************************************************************************/
X
X/*
X * MAIN ROUTINE
X */
X
Xmain(argc,argv)
Xint argc;
Xchar *argv[];
X{
X	int	ans_esr(), sigint(), fork();
X	FILE	*fopen();
X	v_card_data cdp;
X	struct tts_parms ttsparms;
X
X	/* Fork and run as a background process if enabled */
X
X#ifdef SUBPROC
X	close(0);
X	close(1);
X	close(2);
X	if (fork() != 0)
X		exit(0);
X	setpgrp(0);
X#endif
X
X	/* Open the answering machine log file */
X
X	if ((logfp=fopen(logfile,"a")) == NULL) {
X		perror(logfile);
X		exit(2);
X	}
X
X	/* Set the name of the program to argv[0] for error routines */
X
X	progname=argv[0];
X
X	signal(SIGINT, sigint);       		/* Catch interrupts */
X
X	/* Initialize the voice card.  If the control-all functions are
X	 * enabled, then make the answering machine passive and monitor
X	 * ring & hook status for flash & ring.  Otherwise take complete
X	 * control of the connected phone.
X	 */
X
X#ifdef PASSIVE
X	cdp=v_init(progname,card,V2P_ONHOOK);
X#else
X	cdp=v_init(progname,card,V2P_SET);
X#endif
X
X	if (cdp == (v_card_data)VL_DENY) {
X		log_message("busy with higher priority application",0);
X		exit(2);
X	}
X
X	if (cdp == (v_card_data)VL_NOCARD) {
X		log_message("can't find voice card",0);
X		exit(2);
X	}
X
X	v_s_esr(ans_esr);	/* Set event service routine */
X
X	log_message("answering machine started",0);  /* Log startup */
X
X	/*
X	 * Set the amplitude and inflection of the TTS stuff to
X	 * something reasonable
X	 */
X
X	v_tts_init();
X	v_tts_tune(0,&ttsparms);  /* Get the tts params */
X	ttsparms.pitch_contour[0]=240;
X	ttsparms.pitch_contour[1]=200;
X	ttsparms.pitch_contour[2]=150;
X	ttsparms.pitch_contour[3]=100;
X	ttsparms.duration_scaling_factor=70;
X	ttsparms.amplitude=4;
X	v_tts_tune(1,&ttsparms);  /* Set the tts params */
X
X	wait_call();		/* Await calls */
X}
X
X
X/***************************************************************************/
X
X/*
X * This v_error routine replaces the default v_error(3Voice) routine which
X * formats a voice routine error message
X */
X
Xvoid v_error(message,val)
Xchar *message;
Xint val;
X{
X	log_message(message,val);
X	exit(2);
X}
X
X
X/***************************************************************************/
X
X/*
X * This is the event service routine which is called asynchronously by
X * the voice power software when a voice/line event occurs.
X */
X
Xint ans_esr(v2_nstatus,cdp)
Xstruct v2_nstatus *v2_nstatus;
Xv_card_data cdp;
X{
X	switch (v2_nstatus->event) {
X	case VE_TIMEOUT: 
X	case VE_ONHOOK:
X		log_message("timeout or receiver back on hook",0);
X		v_ipstop();
X		v_irstop();
X		v_f_touch();
X		v_s_format(V2T_24K);
X		longjmp(restart_buf,1);
X
X	case VE_BUZZOFF:
X		log_message("suspended by higher priority proc",0);
X		v_buzzoff();
X		log_message("resumed",0);
X		return VESR_BUZZ;
X	}
X
X	return VESR_STOP;
X}
X
X
X/***************************************************************************/
X
X/*
X * This function is called asynchronously when the program is interrupted
X * by a SIGINT
X */
X
Xint sigint()
X{
X	log_message("interrupted by a SIGINT",0);
X
X	/* Don't just close() vcc channel as it may block if data    *
X	 * in buffer until buffer is empty.  Just soft reset driver. */
X	v_sreset();
X
X	exit(1);
X}
X
X
X/***************************************************************************/
X
Xlog_message(message,value)
Xchar *message;
Xint value;
X{
X	long	timebuf;
X	char	*ctime(),timestr[25];
X
X	time(&timebuf);
X	strncpy(timestr,ctime(&timebuf),24);
X	timestr[24]='\0';
X	fprintf(logfp,"%s/CID %d: [%s] ",progname,card,timestr);
X	fprintf(logfp,message,value);
X	fprintf(logfp,"\n");
X	fflush(logfp);
X}
X
X
X/***************************************************************************/
X
Xget_newfile(filename)
Xchar *filename;
X{
X	struct sysctl control;
X
X	get_control(&control);
X	make_messfile(++control.lastmsgf,filename);
X	set_control(&control);
X}
X
X
X/***************************************************************************/
X
Xmake_messfile(messno,filename)
Xint messno;
Xchar *filename;
X{
X	sprintf(filename,"%s/%d.in",messdir,messno);
X}
X
X
X/***************************************************************************/
X
Xget_control(ctlstr)
Xstruct sysctl *ctlstr;
X{
X	int	fd;
X
X	if ((fd=open(controlf,O_RDWR)) < 0) {
X		/* New file .. set defaults */
X		ctlstr->lastread=0;
X		ctlstr->lastmsgf=0;
X		ctlstr->tollsaver=TRUE;
X		ctlstr->systemon=TRUE;
X		if ((fd=creat(controlf,0660)) < 0) {
X			perror(controlf);
X			exit(2);
X		}
X		write(fd,ctlstr,sizeof(struct sysctl));
X	} else
X		read(fd,ctlstr,sizeof(struct sysctl));
X	close(fd);
X}
X
X
X/***************************************************************************/
X
Xset_control(ctlstr)
Xstruct sysctl *ctlstr;
X{
X	int	fd;
X
X	if ((fd=open(controlf,O_RDWR)) < 0) {
X		if ((fd=creat(controlf,0660)) < 0) {
X			perror(controlf);
X			exit(2);
X		}
X	}
X	lseek(fd,0L,0);
X	write(fd,ctlstr,sizeof(struct sysctl));
X	close(fd);
X}
X
X
X/***************************************************************************/
X
Xwait_call()
X{
X	int	event, ringcount, checkcount, ansrings;
X	int	test_flash();
X	struct sysctl control;
X
X	/* Main loop to wait for a call */
X
X	while (TRUE) {
X		/* Restart here if an trapped condition occurs */
X
X		/* Decide which mode to keep an idle line in.  See
X		 * comments in main() for a tutorial about this
X		 * functionality.
X		 */
X
X#ifdef PASSIVE
X		if (setjmp(restart_buf))
X			v_s_line(V2P_ONHOOK);
X#else
X		if (setjmp(restart_buf))
X			v_s_line(V2P_SET);
X#endif
X
X		/* Compute number of rings to answer on based on new messages
X		 * and whether the answering machine is "on" or not.  Only
X		 * turn on automatically if AUTO_ON is set...
X		 */
X
X		get_control(&control);
X		if (control.systemon) {
X			/* If machine on, determine ring count based on
X			 * toll saver function & # of messages */
X			if (control.tollsaver)
X				if (control.lastread != control.lastmsgf)
X					ansrings=1;
X				else
X					ansrings=TSVRING;
X			else
X				ansrings=1;
X		} else {
X			/* Otherwise base on AUTO_ON function */
X#ifdef AUTO_ON
X			ansrings=AUTO_ON;
X#else
X			ansrings=9999;  /* if someone is able to ring
X					 * THIS many times.... */
X#endif
X		}
X
X		/* Wait for an event */
X
X		ringcount=0;
X		event=v_wait(V2M_LRING | V2M_OFFHOOK, 0);
X
X		/* Handle toll saver ring count */
X
X		if (event == VE_LRING) {
X			checkcount=TRUE;
X			while ((++ringcount < ansrings) && checkcount) {
X				event=v_wait(V2M_LRING | V2M_OFFHOOK | V2M_CLOCK, 10);
X				if (event != VE_LRING) checkcount=FALSE;
X			}
X		}
X
X		/* Handle all events obtained from monitoring line status */
X
X		switch (event) {
X		case VE_LRING:  /* Telephone line ring detected */
X			v_s_line(V2P_LINESET | V2P_GAIN); /* answer call */
X			log_message("outside call received",0);
X			outgoing_msg();
X#ifdef PASSIVE
X			v_s_line(V2P_ONHOOK);  /* Hangup & return to passive */
X#else
X			v_s_line(V2P_SET);  /* Hangup & return to abs ctl */
X#endif
X			break;
X
X		case VE_OFFHOOK:  /* Local telephone is off hook */
X#ifdef PASSIVE
X			/* Control-all mode will wait 10 seconds for a
X			 * switch-hook flash, after which it will return
X			 * to passive mode and wait for an idle line.
X			 * Note that this routine is also called if someone
X			 * answers a ringing telephone.
X			 */
X			log_message("telephone off hook/answered",0);
X			if (test_flash()) {
X				sleep(2);  /* settle line */
X				admin_mode();
X				v_s_line(V2P_ONHOOK);
X				v_f_touch();
X			} else
X				idle_wait();
X#else
X			log_message("local handset used",0);
X			outgoing_msg();
X#endif
X			break;
X
X		case VE_CLOCK:  /* Timeout from toll saver */
X			log_message("toll saver timeout used",0);
X			break;
X
X		default:  /* Any other event (unexpected) */
X			v_f_touch();
X			log_message("unexpected event %d in wait_call",event);
X			break;
X		}
X	} /* END: while(TRUE) */
X}
X
X
X/**************************************************************************/
X
Xoutgoing_msg()
X{
X	/* char v_g_dtouch(); */
X	int event;
X	char touchcode;
X
X	while (TRUE) {
X		v_s_format(V2T_24K);
X		event=v_fplay(m_outgoing,0L,V2M_TOUCH | V2M_ONHOOK);
X		switch (event) {
X		case VE_TOUCH:  /* Touch-tone entered */
X			touchcode=v_g_dtouch();
X			if (touchcode == '#') {
X				admin_passw();
X				return;
X			}
X#ifdef CARSALE
X			if (touchcode == '1') {
X				log_message("caller wanted to know about car",0);
X				event=v_fplay(m_carinfo,0L,V2M_ONHOOK);
X				break;
X			}
X#endif
X			get_incoming();
X			return;
X
X		case VL_OK:  /* outgoing message complete */
X			sleep(2);
X			get_incoming();
X			return;
X
X		default:
X			v_f_touch();
X			log_message("unexpected event %d in outgoing_msg",event);
X			break;
X		}
X	}
X}
X
X
X/***************************************************************************/
X
Xadmin_passw()
X{
X	int	event;
X	char	passbuf[10];
X
X	(void) v_fplay(m_entpassw,0L,V2M_TOUCH | V2M_ONHOOK);
X
X	event=v_g_touch(passbuf,9,'#',10,V2M_ONHOOK);
X
X	switch (event) {
X	case VE_TOUCH:  /* Touch tones were entered (normal) */
X		if (strcmp(SYSPASSW,passbuf) == 0) {
X			(void) v_fplay(m_thankyou,0L,V2M_TOUCH | V2M_ONHOOK);
X			admin_mode();
X		} else 
X			log_message("incorrect password given",0);
X		break;
X
X	default:  /* Something unusual happened */
X		log_message("unexpected event %d in admin_passw",event);
X		break;
X
X	}
X}
X
X
X/***************************************************************************/
X
Xadmin_mode()
X{
X	int	run_flag = TRUE;
X	int	event, rebcount;
X	char	cmdbuf[2];
X
X	log_message("entered administration mode",0);
X
X	report_msg();
X	
X	rebcount=0;	/* Reboot must be done twice to confirm */
X	while (run_flag) {
X		(void) v_fplay(m_admenu,0L,V2M_TOUCH | V2M_ONHOOK);
X		event = v_g_touch(cmdbuf, 1, 0, 10, V2M_ONHOOK);
X
X		switch (event) {
X		case VE_TOUCH:  /* A touch tone was entered */
X			switch (cmdbuf[0]) {
X			case '1':  /* Retrieve new messages */
X				retrieve_new();
X				break;
X
X			case '2':  /* Retrieve all messages */
X				retrieve_all();
X				break;
X
X			case '3':  /* Toll saver toggle on/off */
X				tollsv_toggle();
X				break;
X
X			case '4':  /* Check my e-mail */
X				check_email();
X				break;
X
X			case '5':  /* Good bye */
X				(void) v_fplay(m_bye,0L,V2M_ONHOOK);
X				run_flag=FALSE;	
X				break;
X
X#ifdef SYSFUNCS
X			case '6':  /* Reset modem */
X				(void) v_fplay(m_holdon,0L,V2M_ONHOOK);
X				(void)system(resetmodem);
X				(void) v_fplay(m_mdreset,0L,V2M_ONHOOK);
X				break;
X
X			case '7':  /* Reboot machine */
X				if (++rebcount >= 2) {
X					log_message("reboot requested",0);
X					(void) v_fplay(m_holdon,0L,V2M_ONHOOK);
X					(void)system(sysreboot);
X					(void) v_fplay(m_reboot,0L,V2M_ONHOOK);
X				}
X#endif
X			}
X			break;
X
X		default:
X			v_f_touch();
X			log_message("unexpected event %d in admin_mode",event);
X			break;
X		}
X
X	} /* END: while(run_flag) */
X}
X
X
X/***************************************************************************/
X
Xget_incoming()
X{
X	int	retcod;
X	char	msgfile[MAXFLEN];
X
X	get_newfile(msgfile);
X	(void) v_fplay(m_beep,0L,V2M_TOUCH | V2M_ONHOOK);
X	v_s_format(V2T_24K);
X	retcod=v_frecord(msgfile,
X	    (long)(RECTIME * V2_SEC2BYTES),
X	    0,
X	    O_TRUNC,
X	    V2M_TOUCH);
X	v_f_touch();            /* in case record was touch terminated */
X	(void) v_fplay(m_bye,0L,V2M_TOUCH | V2M_ONHOOK);
X	log_message("message was taken  Event=%d",retcod);
X}
X
X
X/***************************************************************************/
X
Xreport_msg()
X{
X	char	messbuf[128];
X	struct sysctl control;
X
X	get_control(&control);
X	sprintf(messbuf,
X		"you have %d new messages and %d old messages waiting..",
X		control.lastmsgf-control.lastread,control.lastread);
X
X	v_s_format(V2T_TTS);
X	(void) v_stts(messbuf,V2M_TOUCH | V2M_ONHOOK);
X	v_s_format(V2T_24K);
X}
X
X
X/***************************************************************************/
X
Xretrieve_new()
X{
X	int	event,msgno,play_message();
X	struct sysctl control;
X
X	(void) v_fplay(m_holdon,0L,V2M_TOUCH | V2M_ONHOOK);
X	get_control(&control);
X
X	if ((control.lastmsgf-control.lastread) == 0) {
X		(void) v_fplay(m_nonew,0L,V2M_TOUCH | V2M_ONHOOK);
X		return;
X	}
X
X	for (msgno=control.lastread+1; msgno<=control.lastmsgf; msgno++) {
X		event=play_message(msgno);
X		if (event == VE_TOUCH)
X			switch(v_g_dtouch()) {
X			case '#':  /* Abort */
X				v_f_touch();
X				return;
X
X			case '*':  /* Next */
X 				v_f_touch();
X				break;
X
X			default:  /* anything else... */
X 				v_f_touch();
X				return;
X			}
X		control.lastread=msgno;
X		set_control(&control);
X	}
X}
X
X
X
X/***************************************************************************/
X
Xretrieve_all()
X{
X	int	event,msgno,play_message();
X	struct sysctl control;
X
X	(void) v_fplay(m_holdon,0L,V2M_TOUCH | V2M_ONHOOK);
X	get_control(&control);
X
X	if (control.lastmsgf == 0) {
X		(void) v_fplay(m_nonew,0L,V2M_TOUCH | V2M_ONHOOK);
X		return;
X	}
X
X	for (msgno=1; msgno<=control.lastmsgf; msgno++) {
X		event=play_message(msgno);
X		if (event == VE_TOUCH)
X			switch(v_g_dtouch()) {
X			case '#':  /* Abort */
X				v_f_touch();
X				return;
X
X			case '*':  /* Next */
X 				v_f_touch();
X				break;
X
X			default:  /* anything else... */
X 				v_f_touch();
X				return;
X			}
X	}
X}
X
X
X/***************************************************************************/
X
Xint play_message(messno)
Xint messno;
X{
X	int	event,shorthour;
X	char	messfile[MAXFLEN], ttsbuf[200];
X	struct stat statbuf;
X	struct tm *timep, *localtime();
X
X	/* Make the message file name from its number */
X	make_messfile(messno,messfile);
X
X	/* Stat the file to see assure it exists and to get its time */
X	if (stat(messfile,&statbuf) < 0) {
X		sprintf(ttsbuf,"message %d, is not available",messno);
X		v_s_format(V2T_TTS);
X		event=v_stts(ttsbuf,V2M_TOUCH | V2M_ONHOOK);
X		v_s_format(V2T_24K);
X		return(event);
X	}
X
X	/* Get the localtime for this file in the time structure */
X	timep=localtime(&statbuf.st_ctime);
X
X	/* Convert the time to something we can say */
X	if (timep->tm_hour > 12)
X		shorthour=timep->tm_hour-12;
X	else
X		if (timep->tm_hour == 0)
X			shorthour=12;
X		else
X			shorthour=timep->tm_hour;
X
X	sprintf(ttsbuf,"mmessage was taken on, %s, %d, at, %d %d, %s...",
X		ttsmonths[timep->tm_mon], timep->tm_mday,
X		shorthour,timep->tm_min,
X		timep->tm_hour < 12 ? "ay m":"p m");
X
X	/* Say that this is a message and when we took it */
X	v_s_format(V2T_TTS);
X	event=v_stts(ttsbuf,V2M_TOUCH | V2M_ONHOOK);
X	v_s_format(V2T_24K);
X
X	/* If some event happened, return it */
X	if (event != VL_OK) return(event);
X
X	/* play the message */
X	event=v_fplay(messfile,0L,V2M_TOUCH | V2M_ONHOOK);
X	return(event);
X}
X
X
X/***************************************************************************/
X
Xcheck_email()
X{
X	FILE	*fp;
X	char	buffer[MBUFSIZ], ttsbuf[132], *strrchr();
X	int	msgs = 0, forward = 0, line = 0;
X
X	/* Tell the caller to hold on a second */
X	(void) v_fplay(m_holdon,0L,V2M_TOUCH | V2M_ONHOOK);
X
X	/* Check the mailbox here */
X	if (access(mailfile,4) == 0) {
X		msgs = 0;
X		if ((fp = fopen(mailfile,"r")) != NULL) {
X			while (fgets(buffer, MBUFSIZ, fp) != NULL) {
X				line++;
X				if (line == 1 &&
X				    strncmp(buffer,"Forward",7) == 0) {
X					forward = 1;
X					break;
X				}
X				if (strncmp(buffer,"From ",5) == 0)
X					msgs++;
X			}
X		}
X		fclose(fp);
X	} else  msgs = 0;
X
X	/* Use the information gathered to make a description of our mail */
X	if (forward)
X		sprintf(ttsbuf,"your ee mail is being forwarded to%s",
X			strrchr(buffer,' '));
X	else if (msgs != 0)
X		sprintf(ttsbuf,"you have %d, ee mail message%s in your mailbox",
X			msgs, (msgs == 1) ? "" : "s");
X	else
X		sprintf(ttsbuf,"you have no ee mail");
X
X	/* Now say the status of our mail file */
X	v_s_format(V2T_TTS);
X	(void) v_stts(ttsbuf,V2M_TOUCH | V2M_ONHOOK);
X	v_s_format(V2T_24K);
X
X	sleep(1);
X	v_f_touch();	/* in case touch tones aborted the input */
X}
X
X
X
X/***************************************************************************/
X
Xtollsv_toggle()
X{
X	char	messbuf[128];
X	struct sysctl control;
X
X	get_control(&control);
X	control.tollsaver= control.tollsaver ? FALSE:TRUE;
X	set_control(&control);
X
X	sprintf(messbuf,
X		"tole saver is now, %s...", control.tollsaver ? "on":"awf");
X
X	v_s_format(V2T_TTS);
X	(void) v_stts(messbuf,V2M_TOUCH | V2M_ONHOOK);
X	v_s_format(V2T_24K);
X}
X
X
X/***************************************************************************/
X
Xint test_flash()
X{
X	int event, ans_esr(), dummy_esr();
X
X	v_s_esr(dummy_esr); /* Temp cancel all esr's */
X
X	sleep(1);	/* Give the line a chance to settle */
X
X	event=v_wait(V2M_ONHOOK | V2M_CLOCK, 10);
X	switch(event) {  /* Check this event */
X	case VE_ONHOOK:  /* When phone is on hook (maybe for flash?) */
X		break;		/* Exit loop and check for OFFHOOK again */
X
X	case VE_CLOCK:   /* Possible flash time has elapsed */
X	case VE_TIMEOUT:  /* The expired time seems to use this though... */
X		goto fail;  /* no flash detected */
X
X	default:         /* If anything else happens, forget flash */
X		log_message("Unusual event in wait 1 test_flash %d", event);
X		goto fail;
X	}
X
X	/* Wait for offhook in 2 seconds for flash */
X
X	event=v_wait(V2M_OFFHOOK | V2M_CLOCK, 2);
X	switch(event) {  /* check this event */
X	case VE_OFFHOOK:  /* we went off hook, capture line, hangup call,
X			   * and notify of valid flash */
X		v_s_line(V2P_SET);
X		goto pass;
X
X	case VE_CLOCK:  /* Time expired .. invalid flash */
X	case VE_TIMEOUT:  /* The expired time seems to use this though... */
X		goto fail;
X
X	default:         /* Unknown event, ignore flash */
X		log_message("Unusual event in wait 2 test_flash %d", event);
X		goto fail;
X	}
X
X	/* All pass/fail status codes are done here to assure
X	 * restoration of the ESR functions (very important)
X	 */
X
Xfail:
X	v_s_esr(ans_esr);   /* restore ESR function */
X	return(0);
X
Xpass:
X	v_s_esr(ans_esr);   /* restore ESR function */
X	return(1);
X}
X
X
X/***************************************************************************/
X
Xint dummy_esr(v2_nstatus,cdp)
Xstruct v2_nstatus *v2_nstatus;
Xv_card_data cdp;
X{
X	switch (v2_nstatus->event) {
X	case VE_BUZZOFF:
X		log_message("suspended by higher priority proc",0);
X		v_buzzoff();
X		log_message("resumed",0);
X		return VESR_BUZZ;
X	}
X
X	return VESR_STOP;
X}
X
X
X/***************************************************************************/
X
Xidle_wait()
X{
X	int	events;
X	struct v2_pstat pstat;
X
X	log_message("waiting for call to be completed",0);
X	events=VE_NULL;
X	while((events & V2M_ONHOOK) == 0) {
X		sleep(2);
X		v_gs_pstat(&pstat);
X		events=(int)pstat.psstat;
X	}
X	log_message("call completed",0);
X}
END_OF_ansmach.c
if test 24059 -ne `wc -c <ansmach.c`; then
    echo shar: \"ansmach.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f anscheck.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"anscheck.c\"
else
echo shar: Extracting \"anscheck.c\" \(1242 characters\)
sed "s/^X//" >anscheck.c <<'END_OF_anscheck.c'
X#include <stdio.h>
X#include <fcntl.h>
X
X#define	TRUE	1
X
Xstatic char *controlf = "/usr/spool/ansmach/control.dat"; /* control file */
X
X/*
X * Structure which defines the system control file
X */
X
Xstruct sysctl {
X	int	lastread;		/* Last message retrieved */
X	int	lastmsgf;		/* Last message filed */
X	char	syspassw[20];		/* System password code */
X	int	tollsaver;		/* Toll saver enabled flag */
X};
X
X
Xmain(argc,argv)
Xint argc;
Xchar *argv[];
X{
X	struct sysctl ctlblk;
X
X	fprintf(stdout,"Ans Mach:  ");
X
X	get_control(&ctlblk);
X	if (ctlblk.lastread == ctlblk.lastmsgf)
X		fprintf(stdout,"No new messages   ");
X	else
X		fprintf(stdout,"%d new messages   ",
X			ctlblk.lastmsgf-ctlblk.lastread);
X
X	if (ctlblk.tollsaver)
X		fprintf(stdout,"TollSaver On  ");
X
X	fprintf(stdout,"\n");
X
X	fflush(stdout);
X}
X
X
X/***************************************************************************/
X
Xget_control(ctlstr)
Xstruct sysctl *ctlstr;
X{
X	int	fd;
X
X	if ((fd=open(controlf,O_RDWR)) < 0) {
X		/* New file .. set defaults */
X		ctlstr->lastread=0;
X		ctlstr->lastmsgf=0;
X		ctlstr->tollsaver=TRUE;
X		if ((fd=creat(controlf,0660)) < 0) {
X			perror(controlf);
X			exit(2);
X		}
X		write(fd,ctlstr,sizeof(struct sysctl));
X	} else
X		read(fd,ctlstr,sizeof(struct sysctl));
X	close(fd);
X}
END_OF_anscheck.c
if test 1242 -ne `wc -c <anscheck.c`; then
    echo shar: \"anscheck.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of shell archive.
exit 0
-- 
Gil Kloepfer, Jr.  ...!ames!limbic!gil  |  gil%limbic@ames.arc.nasa.gov
ICUS Software Systems -- Western Development Center
P.O. Box 1    Islip Terrace, NY  11752



