The Computer Journal, Issue 45

Z-System Corner

© Jay Sage

Reproduced with permission of author and publisher.

A Mex-Plus Script for Using PC-Pursuit

Last time we gave you a pretty thorough presentation of the script language from the MEX-Plus telecommunications program. However, as necessary as such documentation is, it does not really teach one how to make effective use of the language. So this time we will present as a teaching example significant portions of the script suite that I use for almost all my telecommunication work. It is the most complex script that I have ever written, illustrates many techniques, and might be very useful to many of you as well.

This script is far from perfect. Every time I work with MEX-Plus I learn something more about it, and that was a large part of my motivation for writing these two columns. As usual, I hope that some astute readers will notice ways to improve on my script.

More MEX Commands

Before getting into the script itself, I have a few items to add to the discussion from last time. First, I forgot to mention one extremely important MEX command; second, just today I discovered some more undocumented commands that appear to be quite interesting.

The WAIT Command

The WAIT command is one of MEX's most important commands. It allows MEX to monitor the character stream coming back from the remote system and to take various actions depending on what it sees. There are four variants of the command: WAIT DATE, WAIT TIME, WAIT SILENCE, and WAIT STRING.

The first two forms cause the script to pause until a specified date or time arrives. Obviously, you must have a real-time clock and a MEX clock module installed for these commands to work. The command forms are:


These commands would be useful for a script to automatically place a call during the middle of the night when phone rates are lower.

The WAIT SILENCE command waits until no characters have been received from the modem for a specified time interval. This is one way to infer that the remote system has finished what it was doing and is ready for a command from you. The syntax is:


The most powerful of the WAIT commands is WAIT STRING, whose full syntax is:

WAIT STRING [time] string1 [string2 string3 string4]

This command takes from one to four string expressions and an optional wait time, which otherwise defaults to values set by STAT parameters. The command terminates as soon as one of the strings is detected or the time limit expires. The VALUE variable tells you the result. It will be 0 if the time limit was reached or 1, 2, 3, or 4 depending on which string was matched. You will see a number of examples of the use of this command in my PC-Pursuit script.

Undocumented Commands

MEX has quite a number of undocumented commands. These can be discovered by doing a memory dump of MEX.COM and looking for the command dispatch table. Scanning programs' command tables to see what goodies might have been built into them that the authors - for one reason or another - decided not to tell you about is a great sport. I will mention only a few of the MEX commands I discovered this way.

First, there are some commands that are just alternate names for documented functions. For example, there is a RENAME command that vectors to the same code that the REN command does.

Since, as I mentioned last time, there seemed to be a paucity of ways to get out of MEX (only about six commands!), I was quite relieved to discover the command ABORTMEX, which appears to offer yet another way! Actually, I have a recollection of having seen that command somewhere in the documentation, but it is not listed in the index and I cannot find it again. From examining the dispatch vectors, I can tell that ABORTMEX is not the same thing as CPM, EXIT, QUIT, and so on, but it seems to do the same thing.

One command that I think will prove quite useful is the PAUSE command. Its syntax appears to be like that of the undocumented PRINT. Whatever text comes after it is echoed to the screen, and the script then pauses until any key is pressed.

The MEM command looked as though it was going to be quite useful, as it displays the status of MEX's memory buffer. The trouble is, I have not been able to figure out what buffer this is! I started a capture buffer, and MEM still showed the same values and reported that none of the buffer was in use. Then I put the command in a script file, thinking it might report the status of the script buffer. Alas, the report was still the same. Perhaps this is just a command that was never fully coded. All I can say is that the buffer size reported does depend on the size of one's TPA.

Another very interesting command is WIN. Its name suggested that it created some kind of window, and indeed it does. It is probably not documented because it does not seem to work completely correctly. I entered the command

WIN 5 5 12 75

and MEX drew a partial box of the sort that "BOX 5 5 12 75" would have and then put its prompt at the upper left corner of the window. After that, screen output was restricted to the lines in the window, but the lateral limits of the window were not observed; text still ran across the full width of the screen. The STAT command would fill just the window and then wait for a keypress to continue. Of course, I did my tests from the command line, and WIN may act differently if invoked from a script file.

The "@" command cursor addressing could still take one anywhere on the screen. Thus, it looks as though the WIN command might be useful in some special cases where one wants to keep certain status information on the screen. The window could be set to the last 20 lines on the screen, and status information could be written using "@ SAY" to the regions outside the window.

Another command whose function I thought I could guess was FLUSH. I assumed that it flushes the contents of a buffer, perhaps the capture buffer. However, I tried it with a capture buffer, and nothing seemed to happen. There must be something more subtle about it.

Finally, there are the commands DUPE, RESTORE, TRAP, LIB, EXEC, OVRINIT and probably a few others.

A Challenge

I will offer an unspecified prize to the user who does some detective work and sends me the most complete documentation on these undocumented commands. A free copy of the Mex-Pack terminal emulation and remote operation modules might be a fitting prize. Or perhaps a copy of the new ZMATE macro text editor.

I also have some recollection that someone once figured out a way to use either the strings assigned to keys or the names in the phone directory as string variables. So far, however, I have not been able to figure out how to do it. We'll include that and any other undocumented information about MEX-Plus within the framework of this challenge.

Now let's begin the look at the PCP script.

The PC-Pursuit Script

The Purpose

The purpose of this suite of MEX scripts is to make life with PC-Pursuit easier. Before the recent changes in policy, using PCP was an enormously frustrating experience. The outdial modems were almost always busy, and it sometimes took dozens or even hundreds of tries to get connected to a desired city - each try requiring one to enter one's user ID and password. Today, with the 30-hour limit on free access, things are much, much better, but it is still handy to have a script take care of the operation automatically.

Here is basically what my script does. It calls up the local Telenet access point and issues the commands to set up the proper terminal mode. Then it negotiates a connection to the city where the selected remote access system (RAS) is located. If all the modems in that city are busy, the script can keep trying. If all the 2400 bps modems are busy, it can even automatically step down and try the 1200 bps modems. Today, one rarely fails to connect on the first try at 2400, but in the past the multiple tries and automatic stepdown were lifesavers.

Once the connection to the city has been established, the script issues the commands to put the remote modem into Racal Vadic mode and then dials the number for the RAS. In Vadic mode, the modem issues call status reports, so you know when the modem is dialing, when the phone is ringing, when the line is busy, and when the call has simply failed. The MEX script monitors these reports and responds appropriately.

Once the remote system has been reached, a very short script is initiated so that a maximum amount of memory will be free for MEX to use for its capture and file transfer buffers. The script also programs several function keys to make logging onto the RAS easier.

It would be quite easy to have the PCP script chain to a script to perform the complete login operation, but I generally prefer to do this manually. That gives me a chance to notice if there are any new bulletins or other changes in the system.

Design Philosophy

Two main principles guided the design of the script suite. First, as I mentioned last time, I made it highly modular. This makes writing the script easier and clearer but, more importantly, it overcomes memory limitations. By chaining from one script to another, only one script has to be in memory at one time. By making the last script a very small one, almost no buffer space is lost during the time the user is working on the remote system, even though a script is still in operation.

The second principle is to provide as much error checking as possible. For example, at the very beginning, the script checks to make sure that the local modem is connected, turned on, and responding. I learned to do this after trying many times to run this and other scripts with the modem turned off.

In its present form, when an error is detected, the script normally issues an explanatory message and then terminates. It would be better to provide error recovery wherever possible. For example, having discovered the PAUSE command, I might now improve the script by making it pause until the user turns the modem on and presses a key. Then the script would loop back and try again.

There are quite a few places in the script where it will retry a failed operation several times before it gives up. Sometimes PC-Pursuit just seems to go out to lunch, and I have been unable to get any response from it even with manually entered commands. In such cases, of course, there is nothing more that the script can do.


Before talking about the detailed functions of each module in the script, I would like to describe the architecture. There are 6 modules, and their relationships are shown in Fig. 1.

    +------------->   PCPMENU.MEX  <----------+
    |                /     |     \            |
    |               /      v      \           |
    |              /      CPM      \          |
    |             v                 v         |
    |         PCPDATA.MEX       PCPMAN.MEX -->+
    |               \             /           |
    |                 \         /             |
    |                   v     v               |
    |                   PCPCALL ------------->+
    |                      |
    |                      |
    |                      v
    +-----------------  PCPCONN

    Figure 1.
    This shows the architectural organization of the suite of script files

    that comprise the complete the PCP script.

The central script is in the file PCPMENU.MEX. The invocation script, PCP.MEX, performs some one-time operations and then transfers control to PCPMENU. After that, control branches to other scripts but eventually returns to the menu script. It is only from PCPMENU that the script can be terminated and control returned to CP/M in a graceful fashion.

The data needed to connect to a remote system can be supplied in two ways. First, the menu displayed by PCPMENU lists many commonly called systems. When one of these is selected, control branches to PCPDATA, which loads the required data into MEX numerical and string variables and function keys.

Alternatively, there is a choice for contacting a RAS that is not on the menu. In this case, the script PCPMAN (short for PCPMANUAL) provides for step-by-step, menu-driven entry of the required information. If the user decides against making that call, control can be returned to PCPMENU. Normally, however, control from either PCPDATA or PCPMAN flows to PCPCALL.

PCPCALL carries out the operations required to make PC-Pursuit connect to the requested city and then dial the requested local telephone number. When either the PCP or RAS modems is busy, the script allows the user to decide whether to continue trying and how many times. If the call cannot be completed and the user does not want to continue trying, control returns to PCPMENU.

If the remote system is reached, control is passed to the small script PCPCONN (short for PCPCONNECTED). We showed this script in the previous column. It puts the user into terminal mode for login. Whenever the user exits back to MEX command mode, a prompt is put up. Entering the command "M" returns control to PCPMENU. Other MEX commands can be entered as usual for transferring files, opening capture buffers, changing STAT parameters, and so on.

This script suite does not make use of any subroutine scripts invoked using the DO command. In all cases, control is transferred permanently to another script using the READ command. There are some subroutine command blocks defined by the PROC and ENDP commands. These subroutines are contained within the script file because they execute faster that way and because there was no reason in most cases to implement them as separate files.

We will now make a few comments about details of the individual script files. Because the code is quite lengthy, we are unable to print it all here. Many whole sections have been removed, and some comments have been cut out. However, there are several ways to obtain the complete scripts. First, they will probably be included on the ZSUS (Z-System Software Update Service) subscription disk that is released at about the time this issue appears. Second, the files will be posted on RASs. Finally, Art Carlson has offered to make them available to subsribers who send him a formatted, labeled diskette with return postage and mailer.

Script PCP.MEX

This script (Listing 1) initializes a number of variables. Note that variables that the user is likely to want to change are placed at the beginning of the script. Also note that certain values that could have been hard coded into the script, such as the default number of tries to connect to a city, are stored instead in numerical variables. This is like using EQU parameters in assembly code and is a highly recommended practice. It is not a bad maxim never to use actual numerical constants in any program; always use symbolic constants.

Table 1 shows how variables are used in the scripts. I'll have to confess that I prepared much of this list after the fact. That was a mistake. I would have made many fewer coding errors had I meticulously documented the use of variables from the very beginning. In fact, the comments next to each variable should be more extensive than what I show here. Some of the information is incomplete; some may even be wrong.

Note the way command line parameters are handled in PCP.MEX. The full syntax for invocation of the script is:

READ PCP [menu choice] [city tries] [RAS tries]

There are three optional parameters. The first is a menu choice. If you know that you want to place a call to RAS number 1 on the menu, you can use the command "READ PCP 1" to do so directly. In case you think that it is too hard to remember the numbers, you are right; that's where ARUNZ aliases come in! My LADERA alias becomes "MEX READ PCP 1". The other two parameters are the default number of times to connect to a city's outdial modem and the destination modem, respectively.

The parameter values are carefully validated in the script. If the values are illegal, then the built-in defaults are used. Validating user input is something that none of us does enough of.

In the part of the script that checks the local modem, there is the command:


This makes the script wait for up to 2 seconds for the modem to respond with either "OK" (which it will do in normal verbose mode) or "0" (which it will do if it was left in terse mode). It is always a good idea to have code anticipate and deal with all possible situations.

I have an MNP level-4 modem, and Telenet supports MNP error correction at the indial port that I use. Therefore, I put the modem into MNP mode at the beginning of the PCP script and set it back to normal mode on normal exit. I have omitted this code from the listing. If you do not have an MNP modem, you would, of course, remove (comment out) this part of the script.

The script is pretty carefully written to make sure that everything is proceeding correctly. After connecting to Telenet, up to two attempts are made to establish the required synchronization. This same technique of looping with a max-tries count in variable %z is used in many places throughout the scripts. Note the use of the SLEEP command to introduce delays when the system you are communicating with does not always respond immediately.


The menu in this script (Listing 2) is drawn inside a box and has the RAS selections displayed in three columns. Free entries are filled in with a row of dots. We have included only enough entries to show how they are generated. It is important that free entries be trapped later in the script.

The menu is adaptive. If one is currently connected to a city, the city code and data rate are shown in the menu header, and the menu selections for changing the data rate that otherwise appear at the bottom are omitted.

Another example of robust coding is provided by the ABORT routine at the end. Whenever this script is running, we should be connected to PC-Pursuit. Therefore, the script attempts to disconnect by sending the HANGUP command that PCP likes to see. If several attempts to disconnect in this way fail, however, we simply drop carrier.


This script (Listing 3) is quite straightforward. It sets some default key definitions that apply to many systems. Then it branches to the entry for the RAS selected from the menu in PCPMENU. Here the variables necessary to place the call are set and any other function key definitions are made. Then control is transferred to PCPCALL. In the listing we show the entry for only one RAS.


This is the second most complex module in the series (Listing 4). I used to have a much simpler and less agreeable version; in honor of this column I just rewrote it. It used to require manual entry of all information, and it provided no checking. Now it puts up a menu of all PCP cities and allows selection by number. It also keeps track of the area codes covered by each city. When there is a second area code, a menu lets the user choose. The script is even smart enough to include the area code as part of the local number when needed and to insert the "1" prefix for those phone systems that require it.

There are two major subroutines in this module. Routine CITYNAME takes the city number and produces the name of the city and state in a string variable. Routine PCPCODE generates the PCP outdial code and the telephone area codes for the city. The same CITYNAME subroutine is also included in module PCPCALL.

The menu of PCP cities is drawn by calling the CITYNAME routine from inside a loop. This is much slower than drawing the menu directly. I put the code for the CITYNAME subroutine at the beginning of the script, since I think it executes a little faster from there.

I wrote the script this way for two reasons. First, it illustrates some interesting techniques, such as iterated loops and computed coordinates for the "@" command. Second, it keeps information about the city names in one place. If they are kept in more than one place, then when changes are made in the future they might not be made everywhere. As it is, this danger exists in several places in these scripts. For example, the menu of RASs is drawn in PCPMENU, but the data for each RAS are stored in PCPDATA. When changes are made, the user must be sure to keep the information synchronized.


Now we come to the most complex module in the script (Listing 5). This one has to perform a lot of housekeeping and tricky operations. It has to know if we are already connected to a city and if so which one. It then has to decide how to go about connecting to the requested city. This may require disconnecting from the current city and then connecting to the new city.

The script has to allow for things not always going right, at least not the first time. You should particularly note the pains it takes to reset and test the PCP outdial modem and to put it into Racal-Vadic mode.

If the outdial modem is busy or if the RAS is busy, the script will ask the user whether to make additional attempts and if so how many. The script is very careful to keep the user informed of exactly what is going on.

If all works out, we eventually end up connected to the remote system. PCPCALL then chains to PCPCONN (Listing 6), which drops one into terminal mode with the function keys programmed to ease logging in. It would not be hard to have the script first call a subroutine script to perform the login operation automatically. The easiest way would be to store a number in a numerical variable as a flag and the name of the login script file in a string variable. Unfortunately, it's not clear that we have a free string variable to use. One possibility would be to use the system name in variable F. One could run it using the command "DO {F}".


I hope this extended example will give you a better idea of how and to what extent MEX script commands can be used to automate telecommunications tasks. Please let me know if you have some ideas to improve these scripts.


Listing 1.
Script PCP.MEX.

.. PCP.MEX: MAIN PCP SCRIPT (04/15/90)
.. This is the main entry point to the script for automating
.. calls via the PC-Pursuit network.  This part of the script
.. handles initialization of MEX and the modem and establishes
.. the connection to the local access number.

.. Two things we have to take care of right away

screen off
stat sep ";"

.. ------------------------------------------------------------
..      Configuration Information
.. ------------------------------------------------------------

phone pcp.0-0000 2400;.  local access number and baud rate
A="Your Town -Class B";.   type of Telenet access for msg later
key i="PCP_USERID";.       key for entering user ID
key w="PCP_PW";.           key for entering password

%m=100;.                   default menu (100 -> display it)
%t=5;.                     default attempts to reach city
%s=1;.                     default attempts to reach BBS
%b=2400;.                  default baud rate value for outdial
B="24"                     default baud rate as a string
%n=2;.                     automatic stepdown mode
key 0="read pcpmenu/r";    key for reinvoking script

.. ------------------------------------------------------------
..      Initialization
.. ------------------------------------------------------------

.. Initialize data from command line.  There are three optional
.. parameters.  The first is a menu selection number to call
.. immediately.  The second is the number of attempts that
.. should be made to connect to the destination city.  The third
.. is the number of times to attempt to connect to the local
.. number in that city.  In all cases, we check to make sure that
.. we have an acceptable value.

.. menu selection (variable %m)

%d={1:0};.           read parameter 1 with default value of 0
if %d<1 GOTO BAD1;.  ignore if illegal value
if %d>100 GOTO BAD1
%m=%d;.              if value in range 1..100, use it

.. similar code for other parameters omitted.

.. Initialize various variables and MEX parameters

%a=0;.               no area code requested
.. etc.
D=" ";.              no PCP outdial (city) code
.. etc.

stat filter on       turn filter on
stat trigger "";.    do sendouts immediately
stat sodelay on;.    ..but at a slow rate
stat reply 0;.       do not wait for response to a sendout
stat case on;.       ignore case
.. etc.

.. ------------------------------------------------------------
..      Initialize the Modem
.. ------------------------------------------------------------

.. Make sure the modem is connected and responding.

sendout "AT/r"
wait string 2 "OK" "0";.     allow verbose or terse responses
if value=0 A="No response from local modem";GOTO ABORT
.. etc.

.. ----------------------------------------------------------------------
..      Establish Connection to Local Access to Telenet
.. ----------------------------------------------------------------------

screen on;.                   tell user what we are doing
say "/n/nDialing Telenet (",A,") . . . ";.
screen off

.. place call to Telenet

dial pcp
if value=0 A="No connection to Telenet:";GOTO ABORT
screen on

.. initialize PCP session

%z=2;.                       max tries
if %z<1 A="Telenet not responding";GOTO ABORT
screen on;say "  sync... ";screen off
sendout "@";sleep 1;sendout "D/r"
wait string 1 "TERMINAL"
if value=0 sleep 1;goto LOGIN
screen on;say "terminal ID... ";screen off
sendout "D1/r"

read PCPMENU;.               chain to PCPMENU script

.. ------------------------------------------------------------
..      Subroutines
.. ------------------------------------------------------------

screen on
say "/n/n",A,"; session aborted./n/n"

Table 1
A list showing how the string and numerical variables are used in the scripts.

A       error message string, temporary string
B       baud rate
C       temporary city code in PCPMAN
D       PCP outdial city code
E       RAS phone number
F       RAS system name, scratch sometimes

%a      area code of city currently connected to (or 0 if none)
%b      maximum baud rate
%c      current city selection (see PCPMAN.MEX menu)
%d      temporary variable
%e      max number of tries
%f      main area code
%g      alternate area code (or 0 if none)
%h      flag for "1" prefix requirement (0 if not required)
%m      menu selection
%n      stepdown mode ( 0 = manual, >0 = automatic )
%o      flag used to indicate current stepdown status (0 = no
        ..stepdown yet)
%p      number of city actually connected to
%r      count of number of rings detected
%s      default tries to connect to RAS
%t      default tries to connect to city
%u      flag to show intial attempt to connect to a city or RAS
%v      flag to show Vadic status ( >0 if modem in Vadic mode )
%w      cursor row
%x      loop index
%y      cursor column
%z      dummy counter


Listing 2


.. PCPMENU.MEX  (04/15/90)

if %m<100 GOTO PROCESS;.  if selection already made, process it

.. ------------------------------------------------------------
..      Main Re-entry Point and Display of BBS Menu
.. ------------------------------------------------------------


screen on
box 1 1 20 79
@ 2 32 say "PC-PURSUIT MENU"

@  6 3 say "1. Al Hawley (ZN02)"
.. etc.
@ 14 3 say "9. Vanhorn (ZN66)"

@  6 27 say "10. Roger Warren (ZN09)"
.. etc.
@ 14 27 say "18. ...................."

@  6 52 say "19. Terry Pinto"
@ 11 52 say "24. ...................."
.. etc.
@ 12 52 say "25. ...................."
@ 14 52 say "27. WLA PCBoard"

@ 16 12 say "  0. RESET"
@ 17 12 say " 99. QUIT"
@ 18 12 say "100. MANUAL ENTRY MENU"

.. The following baud-rate-selection choices are allowed only if
.. not presently connected to a city.

if %a=0
  @ 16 45 say "200. 2400 BAUD AUTO"
  @ 17 45 say "201. 1200 BAUD FIXED"
  @ 18 45 say "202. 2400 BAUD FIXED"

.. ------------------------------------------------------------
..      Baud Rate / City Connection Status Display
.. ------------------------------------------------------------


if %a=0
  if %n>0
    @ 4 20 say "  Set to max ",%b," bps (auto stepdown)      "
    @ 4 20 say "            Set to ",%b," bps          "
  @ 4 20 say "Connected to Citycode ",D," at ",B,"00 bps"

.. ------------------------------------------------------------
..      Get / Process Selection
.. ------------------------------------------------------------


@ 22 12 say "Enter Selection:       "
@ 22 29


.. ---------- special selections

if %m=0   GOTO RESET
if %m=99  A="User termination";GOTO ABORT
if %m=100 READ PCPMAN;.     manual entry of city and phone #

.. if already connected to a city, do not allow baud rate changes
.. by resetting the choice to 9999

if %p<>0
  if %m> 0 %m=9999

.. handle baud mode selections

if %m 0 %n=2;%b=2400;B="24";GOTO DRAWBAUD
if %m 1 %n=0;%b=1200;B="12";GOTO DRAWBAUD
if %m 2 %n=0;%b=2400:B="24";GOTO DRAWBAUD


.. ---------- calling selections

.. reject unassigned menu choices

.. etc.

READ PCPDATA;.              chain to data fetch routine


bell 1

.. significant part of script omitted

.. ------------------------------------------------------------
..      Subroutines
.. ------------------------------------------------------------


screen on
@ 5 0 say A,"; session ended."

%z=3;.                      max tries

if %z<1 dsc;GOTO ABORT2;.   if soft disconnect fails, hang up
screen on
sendout "/r@/r";.           send disconnect commands to Telenet
wait string 1 "@"
if value<>1 GOTO ABORT1
sendout "hangup/r"
wait string 10 "NO CARRIER"
if value <>1 GOTO ABORT1

sendout "AT\N1/r"
say "/n/nModem MNP mode turned off/n"


Listing 3


.. PCPDATA.MEX  (04/14/90))
.. This routine contains all the data for the systems in the
.. menu.  Each entry sets the following variables:
..      B               actual baud rate code ("12" or "24")
..      D               outdial code
..      E               phone number
..      F               name of system called
..      %a              area code
..      %c              city number (see PCPMAN menu)
.. In addition, function keys are set up (where the defaults are
.. not correct) with the login names and/or passwords.

key 1="Your Name/r";.       default key definitions
key 2="Your-Usual-PW/r"

if %b=1200 B="12"
if %b=2400 B="24"

.. dispatch table

if %m=1  GOTO BBS01
.. etc.
if %m=27 GOTO BBS27

.. ------------------------------------------------------------
..      Data on Remote Access Systems from Menu
.. ------------------------------------------------------------

F="Al Hawley (ZN2)"
key 1="###CCCCCCC/r";.      login id/password combination
READ PCPCALL;.              chain to place the call

.. entries for other systems omitted


Listing 4


.. PCPMAN.MEX  (04/14/90)

.. This subroutine script handles the manual entry of data for a
.. destination RAS.

.. See if there is usable call data already defined.  If so, the
.. user will be given the option of using it (in case this is a
.. second attempt to make the same manual call).  Otherwise, we
.. will skip that menu and go directly to the data input menus.


.. ------------------------------------------------------------
..      Subroutines (placed at beginning for speed)
.. ------------------------------------------------------------

.. This subroutine is passed the city number in scratch variable
.. %d and returns the name of the city in string variable A.

if %d=1 A="Atlanta, GA";ENDP
.. etc.
if %d=34 A="Washington, DC";ENDP
A="Unknown City"

.. ------------------------------------------------------------

.. This subroutine takes the city number in %d and sets the PCP
.. city code into string variable C, the main area code into
.. variable %f, and any additional area code into %g.  Variable
.. %h is set to 1 if a "1" prefix is required.


.. initialize

%f=0;.          no main area code
%g=0;.          no alternate area code
%h=0;.          no "1" prefix needed
C=" ";.         no city code

if %d=1  C="GAATL";%f=404;ENDP
if %d=2  C="MABOS";%f=617;ENDP
if %d=3  C="ILCHI";%f=312;%g*5;%h=1;F="815";ENDP
.. etc.
if %d=29 C="CASJO";%f=408;%g=415;F="415";ENDP
.. etc.
if %d=34 C="DCWAS";%f 2


.. ------------------------------------------------------------
..      Main Code
.. ------------------------------------------------------------


C=D;.           set temporary city code to current value
comp C " ";if value=1 GOTO SETCITY
comp E " ";if value=1 GOTO SETCITY

screen on

.. ------------------------------------------------------------
..      Ask About Entering New RAS Data
.. ------------------------------------------------------------


%d=%c;.         convert city code into city name in A

box 1 5 15 50
@  3 19 say "Manual Call Entry"
@  5 10 say "1. use current data"
@  6 15 say "System Name:    ",F
@  7 15 say "City:           ",A
@  8 15 say "PCP City Code:  ",C
@  9 15 say "Data Rate:      ",%b
if %n>0 say " AUTO"
@ 10 15 say "Area Code:      ",%a
@ 11 15 say "Phone Number:   ",E
@ 13 10 say "2. enter new RAS data"

@ 17 1 say "Enter selection (or 0 to return to main menu):"


@ 17 48 say "       "
@ 17 48

if value=3 %m=100;READ PCPMENU
if value=1 GOTO MAKECALL
if value<>2 bell 1;GOTO ASKMODE

.. ------------------------------------------------------------
..      Get PCP Outdial City Code
.. ------------------------------------------------------------


box 1 1 18 79

if %p=0
  @ 3 28 say "PC-Pursuit City Choices"
  GOSUB CITYNAME;.          get current city name into A
  @ 3 10 say "PC-Pursuit Cities (Currently Connected to ",A,")"

%x=1;.                          starting city number
if %x<10 %y=5
if %x>12 %y=28;%w=%x-8
if %x>24 %y=52;%w=%x-20
@ %w %y say %x,". ",A
if %x<35 GOTO COLUMN

@ 20 5 say "City code selection (or 0 to return to main menu):"


@ 20 56 say "       "
@ 20 56

if %c=0 %m=100;READ PCPMENU;.   return to main menu
%d=%c;GOSUB PCPCODE;.           set PCP code and area code data
if %c=%p GOTO SETPHONE;.  if already connected, skip baud query

.. ------------------------------------------------------------
..      Get baud rate to use if a new city is specified.
.. ------------------------------------------------------------


box 5 5 13 54
@  7 10 say "Data rate to use for new city (",C,"):"
@  9 15 say "1.  2400 AUTO"
@ 10 15 say "2.  1200 FIXED"
@ 11 15 say "3.  2400 FIXED"
@ 15 1 say "Enter selection (or 0 to return to main menu):"

@ 15 48 say "        "
@ 15 48

if value=1 %b=2400;B="24";%n=2;GOTO SETPHONE
if value=2 %b=1200;B="12";%n=0;GOTO SETPHONE
if value=3 %b=2400;B="24";%n=0;GOTO SETPHONE

.. if bad answer, ring bell and get another answer

bell 1

.. ------------------------------------------------------------



if %g=0 %a=%f;GOTO SETNUMB

box 5 5 12 50
@  7 10 say "Area Codes for PCP City Code ",C
@  9 15 say "1. main area code:      ",%f
@ 10 15 say "2. alternate area code: ",%g

@ 14 10 say "Area code selection: "


@ 14 32 say "       "
@ 14 32

if value=1 %a=%f;%h=0;GOTO SETNUMB
if value=2 %a=%g;GOTO SETNUMB

.. if invalid response, ring bell and ask again

bell 1

.. ------------------------------------------------------------


say "/n/nArea code is ",%a

say "/n/nEnter phone number (###-####): "
accept E,8

if %a=%g E="{F}-{E}";.  prefix the area code to the number
if %h>0  E="1-{E}";.    if required, prefix "1-" to number

say "/nEnter system name (optional): "
accept F


say "/n/nReady to place the following call:/n"
say "/n   System Name:    ",F
say "/n   City:           ",A
say "/n   PCP City Code:  ",C
say "/n   Data Rate:      ",%b
if %n>0 say " AUTO"
say "/n   Area Code:      ",%a
say "/n   Phone Number:   ",E

say "/n/nData Correct (Y//n)? "
accept A,1

comp ".{A}" ".";if value=1 GOTO MAKECALL1
comp A "Y";if value=1 GOTO MAKECALL1
GOTO SETCITY;.                          start over again


D=C;.                           set PCP city code
READ PCPCALL;.                  chain to PCPCALL script


Listing 5


.. PCPCALL.MEX  (04/16/90)

.. This script performs the steps necessary to connect to the
.. designated city and remote system.

%m=100;.        clear menu selection
%u=0;.          flag to show initial run thru script

.. *** section omitted here ***

.. Branch depending on whether we are presently connected to no
.. city, to the requested city, or to a different city.

if %p=0  GOTO NEWCITY;.     no city connected presently
if %c=%p GOTO LOCAL;.       already connected to desired city

.. ------------------------------------------------------------
..      Disconnect from wrong city
.. ------------------------------------------------------------

%d=%p;GOSUB CITYNAME;.    get name of currently connected city
say "/n/nDisconnecting from ",A," . . . "

%z=3;.                    max number of tries


screen off
sendout "/r@/r";.         try to return to PCP command mode
wait string 2 "@";.       we should get '@' prompt
if value>0 GOTO DROP1;.   if we do, continue below
%z=%z-1;.                 else decrement count
.. abort if count expired
if %z<1 A="Cannot quit current city";GOTO ABORT
GOTO DROPCITY;.           try again

screen off
sendout "D/r";.           tell PCP to disconnect from city
%p=0;.                    show no city connected
%v=0;.                    show not in Vadic mode
screen on
say "OK";.                tell user that it worked

.. ------------------------------------------------------------
..      Connect to new city
.. ------------------------------------------------------------


screen on

.. We do different things depending on whether or not we have
.. exhausted the first set of attempts.

if %u=0
  say "/n";.              end any line of screen output
  %u=1;.                  show no longer first time
  %e=%t;.                 number of tries into variable 'e'
  A=" city code"
  gosub GETD;.            gets number of times to try
  say "/nCalling ",F,"/n";.tell user whom we are trying to reach

say "/nDialing city code ",D," (",A,")";.report the city code we are dialing

%z=1;.                    count of tries
%o=1;.                    indicate no auto stepdown yet


if %z>%d goto MORETRIES
sleep 1
screen on;say "/n  try #",%z," of ",%e," at ",B,"00 bps...";screen off
sendout "C D//";sendout D;.         city code
sendout "//";sendout B;.            baud code
sendout ",";sendout "PCP_USERID";.  user id
sendout ",";sendout "PCP_PW";.      user password
sendout "/r"

wait string 4 "CONNECTED" "BUSY" "FAIL"

.. If we connected, set %p to show new city connected and %u to
.. indicate the first pass at connecting to the specified RAS.

if value=1 %u=0;%p=%c;GOTO LOCAL

screen on
if value=3 say "Failed Call";goto MORETR1
if value=2 say "Busy"
if value=0 say "No Response"

if %n=0 goto MORETR1;.    no auto step down
if %o=0 goto MORETR1;.    already stepped down

%o=0;.                    show now stepped down
if %b=2400 B="12";%z=1;GOTO CITYCODE;.  reset trial count %z


A=" city code"
if value=1 GOTO NEWCITY;. try again to reach new city

READ PCPMENU;.            else chain back to main menu

.. ------------------------------------------------------------
..      In right city; try connecting to specified system
.. ------------------------------------------------------------

screen on
say "/n/nConnected to city code ",D," (",A,")"

.. initialize destination modem to make sure it is still alive

if %v=2;.                 if in Vadic mode, reinitialize modem
  sendout "I/r";.         exit from it
  %v=0;.                  show initialized modem
  sleep 1

%z=3;.                    max attempts to initialize modem
if %z<1 A="Remote modem failure";goto ABORT
screen on;say "/n  initialize remote modem... ";screen off
sleep 1
sendout "ATZ/r"
wait string 3 "OK"
if value=0 goto REINIT1

.. Call destination system


.. *** section omitted ***


sendout "^E/r";.          enter Vadic mode
wait string 3 "*"
screen on
if value=0 say "/nVadic Mode Failed/n";goto REINIT

say "/nRemote modem now in Vadic Mode"
%v=2;.                    show Vadic mode


%r=0;.                    initialize ring count
screen on;say "/n/nTry #",%z," of ",%e," (at ",B,"00 bps)/n"
sendout "D";sendout E;sendout "/r"

screen on
wait string 25 "ANSWER" "BUSY" "DIAL TONE" "RINGING..."
if value=1  goto SUCCESS
if value=2  goto BUSY
if value=3  goto DIALTONE
if value<>4 goto BADCODE

.. *** many routines omitted ***

screen on
READ PCPCONN;.            chain to short script to free memory

.. ---------- Subroutines

.. Ask user for the number of times to connect and put answer is
.. %e.  If the answer is less than 1, then use a value of 1.

say "/nTry how many times to connect to",A,"? "
if %e<1 %e=1

.. Ask if user wants to continue trying to connect.  Return with
.. the answer in VALUE, 1 if YES, 0 if NO.

screen on
say "/n/nTry",A," some more (Y//N)? "
bell 1
accept C,1
screen off
comp C "Y"
if value=1 ENDP
comp C "N"
if value=1 value=0;ENDP
bell 1

.. *** remaining routines omitted ***


Listing 6


.. PCPCONN.MEX  (02/08/90)

.. This short script is run once the destination system has been
.. reached.

screen on
say "Connected to ",F," at ",B,"00 bps/n/n"
t;.                                enter terminal mode

say "/nEnter a single MEX command (or M for menu): "
accept A
comp A "M"
if value=1 READ PCPMENU


[This article was originally published in issue 45 of The Computer Journal, P.O. Box 12, South Plainfield, NJ 07080-0012 and is reproduced with the permission of the author and the publisher. Further reproduction for non-commercial purposes is authorized. This copyright notice must be retained. (c) Copyright 1990, 1991 Socrates Press and respective authors]