MAINFRAME COMMUNICATION

        So you want to talk to a mainframe...  Most likely you will
        need to transfer files and/or run a mainframe session. If
        file transfer is all you need, you could just "RUN Send" or
        "RUN Receive"; but given the amount of memory the terminal
        emulator takes up, you may need to obtain one of the
        available Clipper memory swappers so your program will work
        even if there isn't enough memory to RUN Send or Receive.

        If you want to communicate with a mainframe through a
        terminal session, you'll need to use some kind of an
        interface between your Clipper application and the 3270
        emulator. The two of which I'm aware are IBM's Entry
        Emulator High Level Language Application Programming
        Interface (HLLAPI) and Steve Straley's CLIRMA Library.

        The HLLAPI interface comes with the IBM PC 3270 Emulation
        Program and the EXTRA! 3270 emulation software from
        Attachmate.

        The reason that Clipper can talk to a mainframe session
        through the HLLAPI interface is because the 3270 emulation
        allows for a concurent DOS session in which you can run a
        Clipper program. Since the session runs concurently the
        Clipper program may call the HLLAPI interface which then
        passes the request off to the 3270 session and gets the
        answer and returns it to your program. Either your program
        or the 3270 session may be in the foreground, I tended to
        switch back and forth depending on what information I wanted
        to see at any given instant. One last interesting feature is
        the ability to use @ SAYs in your Clipper program and have
        it's output bleed through onto the 3270 screen allowing you
        to post informative messages to help with troubleshooting.

    Starting out

        Before you get too far along you will need to find out the
        interface you are going to use for your connection and the
        tools you are going to need to talk to that interface. If it
        happens to be IBM or Attachmate HLLAPI I've included the
        necessary Language Interface Modules along with some sample
        code on the Conference disks.  If you are talking directly
        to an IRMA or compatible card, you will need to obtain a
        copy of CLIRMA or the services of someone to interface the
        IRMA libraries to Clipper.  If you are using the HLLAPI
        interface I'd also recommend you get a copy of the IBM
        HLLAPI programmer's guide, see the bibliography for the part
        number. Not only does it seem to be the best reference
        manual for the actual functions calls but it's quite
        reasonably priced at about $18.

    Planning the project

        Well, now that you have been assigned the task and gathered
        the requisite tools where do you start? When I started my
        first project I had never seen HLLAPI before nor had I ever
        played with an IBM mainframe, so I found someone in the MIS
        department to teach me the basic things--how to get an ID
        and password, how to get my ID unlocked after too many
        failed attempts at signing on, how to sign on, and, most
        importantly, how to navigate by hand completely through the
        session I needed to automate. In order to make this process
        easier I recommend you find a way to locate the current
        cursor position when navigating through a mainframe session.
        I did this by using a HLLAPI function in a Clipper program
        running in the background which constantly put the current
        mainframe cursor location on the screen. A program to do
        this using the HLLAPI interface is included on the
        Conference disk. After you've figured out how to get where
        you need to go, it's time to start coding. On the Conference
        disk are some Clipper functions I've used to ease getting
        information on and off the screen. One of the things you
        might notice when reading this code is the rather constantly
        occurring long waits. Mainframes are not PCs and operations
        tend to take anywhere from a few seconds to a minute. I've
        included the text of two of the error messages from the IBM
        PC 3270 Emulation manual to show the kinds of things that
        you might expect when dealing with mainframes.

     1 Wait

        Cause: You sent information to the host computer and it has
        not yet responded or is in the process of responding, or the
        host computer is sending information to your IBM PC and IBM
        PC 3270 Emulation has not finished processing the
        information sent by the host computer.

        Action: Wait one minute, then retry your operation. If the
        problem persists, contact your network coordinator or host
        personnel; or refer to your IBM PC Local Area Network User's
        Guide.

     2: Wait or RESET - system

        Cause: You sent information to the host computer while it
        was sending information to you.

        Action: Wait 5 minutes for the host computer to complete
        processing both tasks, or press the RESET key and retry the
        operation

        The thing I find most interesting about these messages is
        the amount of time they indicate that you should wait, much
        longer than I would ever put up with on a PC-based system.
        One thing to watch for when you are writing the program is
        that you wait long enough for the mainframe to finish. The
        HLLAPI command "Wait" is useful for this because it waits
        either one minute or until the mainframe finishes its
        current task and then tells you how it ended so you'll know
        whether to continue or try the current step again.  Another
        thing to ask about when you are learning about this is if
        there is an Escape key. On the system on which I work the
        PF24 key will always take me back to the very first log-on
        screen--a very useful piece of knowledge if your program
        finds something wrong and needs to start over.

    Memory considerations

        Clipper, as we all know, is a memory hog. Many of you who
        are requested to communicate with a mainframe will discover
        that the network shell and terminal emulator with the HLLAPI
        extensions leaves only a small amount of memory for a
        Clipper application. In my shop, the average 286 workstation
        running the Starlan or Vines network driver and the
        Attachmate EXTRA! 3270 emulation software with the HLLAPI
        extension leave you less than 400K and sometimes as little
        as 250K to play in. That is enough to write a reasonably
        sized application, but it's likely to be a tight fit if you
        want to have lots of fancy options and use lots of add-on
        libraries. If you can convince management to let you have
        386 or SX machines for your workstations, you can gain up to
        an additional 100K by clever use of the ability of 386MAX
        V5.0 or QEMM 5.0 to load TSRs above the 640K barrier.
        Figuring out how to load programs high, which ones it's OK
        to load high, where your network adaptor's memory window is,
        and whether it's OK to use the video memory between 640K and
        704K or 736K for DOS can be enough to drive one to drink.
        The thing to remember is that it can take a hundred tries
        and 20 of them might lock the machine, so make sure to have
        a boot floppy around. It will be a lot easier if you can get
        all the information from the hardware types about what sorts
        of things are in the machines that take up space in the high
        memory area and easier still if you can convince them to do
        it. Sadly enough it's often undocumented and mysterious. At
        work now, my machine has 556K at the DOS prompt when logged
        onto our Starlan network. It took me about 8 hours to gather
        all the relevant information and reboot the machine 50
        times, but now I have 70K more than any other machine on the
        network. The best way I've found to figure out what to load
        high is to use your memory manager to show you all of the
        TSRs on your machine and then one at a time try adding the
        command to load them high and see if the machine  continues
        to work. When you are done, have the memory manager show you
        a map of high memory and juggle the programs you can put
        high so that you can fit the most things up there. The art
        is in figuring out where and in what order to load things
        high so you save the most space. Sometimes you will need to
        leave a 6K program low in order to put a 40K program high,
        but notice that that choice gains you 34K.

    Pretending to be an operator

        One of the first things you need to understand is that your
        Clipper application and the mainframe can run simultaneously
        and that either one can be in the foreground. This means
        that a Clipper application can be accepting and validating
        information from an operator while an active mainframe
        session runs in the background.

        This is probably be the reason most of you are here today:
        someone wants you to access a mainframe and automatically
        run a job and input a bunch of data or get a bunch of data
        and print some sort of custom report. You might want to
        write a data validating front end for a mainframe
        application to reduce the load on the mainframe. You could
        validate things like all fields which must contain data,
        does the zip code match the city and state, and does the
        title field contain valid data--all things which are better
        done in an interactive environment where the corrections can
        often be suggested by pop up lists and other user-friendly
        means (as opposed to the mainframe way of fill out the
        screen, send the screen, wait, fix any problems, send the
        screen again, wait, fix any problems, etc...).

        In order to write a Clipper program that will successfully
        conduct a mainframe session, you are first going to have to
        find out how to conduct that mainframe session yourself. The
        best way to do this is to start out with a pencil and paper
        and write down all the keystrokes needed to get where you're
        going and things to look for along the way to make sure you
        are not lost. When I was doing this, I wrote a small
        Clipper/HLLAPI program which constantly querries the
        mainframe cursor position and writes it to the screen so I
        could copy it down for later use. Another thing about
        mainframe cursors is that you can move them anywhere on some
        screens using the cursor keys, allowing you to figure out
        the location of identifing marks while navigating your way
        through your session. When you know all of the places you
        need to go and all of the keys to input and where to input
        them, it is time to start coding. If your program does not
        work correctly at first, I'd suggest putting in the debugger
        and stepping through slowly to see where you get lost.  If
        you don't have enough memory to run the debugger than add @
        SAYs everywhere so you know where your Clipper program is at
        any time in the host session. The first time I ever tried
        this it took many tries to figure out the correct way
        through.

    Security considerations

        The following are a couple of things to consider when you
        start talking to mainframe sessions from completely
        automated Clipper sessions. It is important to talk to the
        people in charge of security for your site to make sure that
        what you are doing corresponds with their mainframe
        guidelines. I've found that their ideas of security and mine
        differ widely and we get along better if I try to meet their
        needs.

    Availability of password to anyone with dBASE

        A stand alone Clipper program tends to be an easy target for
        someone looking for a password. Sincs passwords must be
        changed occasionally, they would normally be stored in a
        database or .mem file and be accessible to anyone with a
        knowledge of dBASE. There are some precautions which should
        be taken to minimize this risk. If possible, encrypt the
        password when it is stored on disk or (even better) keep it
        encrypted except when it is passed to the function that
        passes it to the mainframe session. Secondly, make sure that
        the program has its own account and that the people in
        charge of mainframe security realize that this account
        belongs to a machine and should have its access restricted
        as much as is practical.

    Constantly changing password

        Another way to improve security is to change the program's
        password constantly. It is not hard to set up a program so
        that the password is changed every time the system is logged
        onto. Set it up so that only the old invalid password from
        which the new password was generated from is ever saved to
        disk. That way a valid password never exists and the only
        way for someone to crack it would be to grab 2 or more
        consecutive password and try to figure out the method used
        to generate one from the other.

    Things you can do to keep the mainframe guys happy

        Mainframes seem to like to do batch things. You give them a
        whole screen of data and they operate on it and either
        accept it or reject it with all of the problems marked. In a
        Clipper application, it's real easy to do things one at a
        time, especially in input screens, by using WHEN and VALID
        clauses on a GET. Not only is this easy, but it tends to
        improve the users' productivity and their mental outlook.
        These kinds of things not only improve the users lives, but
        they lessen the load on the mainframe because it has to
        spend less time dealing with bad input. Another place you
        can help the mainframe guys is with the TSR concept. In the
        last application I wrote, I needed some information from the
        mainframe which showed up at random times. Due to the
        overhead involved, the mainframe programmers were unwilling
        to write a program which constantly checked for new
        information, but my Clipper program was able to inquire
        every 3 minutes whether the idle mainframe program if it had
        anything. If it did I got it; otherwise it told me try again
        later and put itself back to sleep. Any situation where you
        can reduce the load on the mainframe will be appreciated.

    Uploading and downloading files

        Uploading and downloading files is about the fastest way of
        transferring information between the PC and the mainframe
        there is, but it means you need cooperation with the
        mainframe programmers. In order to download information, you
        will need them to create files which contain the information
        you need in a format that is useable by your program. And if
        you want to batch upload information to the mainframe you
        will need them to help define a file format that they are
        willing to process.

        Most files transmitted between a PC and a mainframe will be
        in System Delimited Format, so called SDF files. Luckily,
        Clipper can directly read and write SDF files by using the
        SDF keyword with the COPY TO and APPEND FROM commands. An
        SDF file is a flat file with all records being one line of a
        fixed length ended with a CR LF pair. SDF files are viewable
        in most word processors if you can set the page width wide
        enough or by using the shareware program List. Fields are
        just a substring of a record starting at some offset and
        continuing for some length. The following is an example of
        what an SDF file looks like. The first line of numbers is
        just to make talking about the file easier.

        FILE mainfram

        123456789012345678901234567890123456
        Roger RabbitMale  2134561234
        Ellie Mae   Female8181235678
        Dick  Tracy Male  5431235465
        Bugsy MaloneMale  1232344444
        BreathlessMahoney   Female2134562345

        As you can see the fields just run together, but each field
        always starts at the same place on a line. In this example
        the First Name field starts at position one and runs for 10
        characters, the Last Name field starts at position 11 for 10
        characters, the Sex field starts at position 21 for 6
        characters and the Phone field starts at position 27 for 10
        characters. The following DBF file would correctly import
        the mainframe file and export files in a matching format.

        FILE phonlist
        NAME  TYPE  SIZE  DECIMAL
        LNAME C 10
        FNAME C 10
        SEX   C  6
        PHONE C 10

        To import a downloaded mainframe SDF format file you would
        use the following commands.

        USE phonlist
        APPEND FROM mainfram SDF

        And to export a file to upload the mainframe you would use
        the following commands.

        USE phonlist
        COPY TO mainfram SDF

        You will need to talk to your mainframe contact to find out
        exactly what method you will be using to transfer files back
        and forth, but the most common way seems to be to use the
        SEND.COM and RECEIVE.COM which should have been included
        with your 3270 Terminal emulation software. In order to
        complete the transfers you will need to run the appropriate
        file with the correct parameters. You can either RUN them
        from within your Clipper application, from a batch file, or
        use one of the memory swapping add-ons for Clipper to swap
        the Clipper application out to disk so that there will be
        sufficient memory to run SEND and RECEIVE. The general
        syntax for SEND and RECEIVE is shown below. It is probably
        necessary to talk to your mainframe operator to find out the
        correct syntax for your particular situation. You will note
        that there is a Send File and Receive File function in the
        list of HLLAPI functions. I would recommend not using these
        as all they effectively do is just RUN the command and if
        you do that from Clipper, you will have more control over
        what goes on and how much memory is available. Also note
        that before you attempt a file transfer, your program must
        be sure to disconnect itself from the host session.

        SEND pcfile datasetname filetype [filemode] [options]


        RECEIVE pcfile datasetname [filetype] [filemode] [options]

     HLLAPI commands

        The following are the commands documented in the IBM HLLAPI
        Version 1.21 programmers guide. I will list them here along
        with a brief description of what they do. I think you will
        see that with these commands and Clipper you can automate
        almost any routine mainframe task. Please notice when using
        the HLLAPI interface, that most of the return values are
        just an indicator of success or failure of the function
        call, and that the values you are looking for are usually
        returned in parameters that you are required to pass by
        reference. You'll see this indicated often in the IBM HLLAPI
        manual when you look at the Values Returned section for a
        function and see the word "Length". This means that the
        value you are looking for is returned in the Length
        parameter. Be especially careful when passing strings by
        reference that you make the strings long enough to contain
        the value to be returned, otherwise memory will be corrupted
        and your program will probably just crash, though a worse
        possibility is that it will continue to run and will start
        getting bad data. The first parameter should always be
        passed by reference as most of the time useful information
        will be returned in it

    1 - Connect presentation space

        Tries to establish a connection between your program and a
        specified presentation space.

      PARAMETERS
        1 - 1 character short name of presentation space
        2 - N/A
        3 - N/A

    2 - Disconnect presentation space

        Disconnect your program from a connected presentation space.

      PARAMETERS
        1 - N/A
        2 - N/A
        3 - N/A

    3 - Send key

        Send a keystroke to the current presentation space as if an
        operator typed it in at their console. The string of
        keystrokes may be up to 256 characters long. The following
        strings are interpreted specially and send the indicated
        special keystroke.

        @B - @B - Backtab
        @C - Clear
        @D - @D - Delete
        @E - Enter
        @F - Erase EOF
        @I - Insert
        @L - Cursor Left
        @N - New Line
        @P - Print
        @R - Reset
        @T - Tab
        @U - Cursor Up
        @V - Cursor Down
        @Z - Cursor Right
        @0 - Home
        @1-@24 - PF1-PF24
        @PA1 - PA1
        @PA2 - PA2
        @A@C - Test
        @A@D - Word Delete
        @A@F - Erase Input
        @A@H - System Request
        @A@I - Alt+Insert
        @A@J - Cursor Select
        @A@P - Ident
        @A@Q - Attention
        @A@R - Device Cancel
        @A@d - Doc Mode
        @A@e - Wrap
        @A@f - Change Format
        @A@m - Cursor Position
        @S@x - DUP
        @S@y - Field Mark

      PARAMETERS
        1 - a string of keystrokes of max length 255 characters
        2 - length of string
        3 - N/A

    4 - Wait

        Check to see if the system is waiting for the host, if so
        wait up to one minute for condition to clear. This function
        should be called after every call which leaves you waiting
        for the mainframe to respond. The following return codes let
        you know what happened.

        0 - Successful completion
        1 - You are not connected to a host session
        4 - Timeout, host not ready
        5 - The keyboard is locked
        9 - System error

      PARAMETERS
        1 - N/A
        2 - N/A
        3 - N/A

    5 - Copy presentation space

        Copies the complete presentation space, 80 columns x 24
        rows, to a character variable.

      PARAMETERS
        1 - a string containing space(255)
        2 - N/A
        3 - N/A

    6 - Search presentation space

        Search the presentation space for a matching string. Returns
        the location of the first occurrence or 0 if not found.
        Function 9, Set Session parameters, may be used to allow the
        specification of a starting position which will allow
        finding the second and later occurrences of the string. It
        also allows you to specify the search direction, forward or
        backward.

      PARAMETERS
        1 - string to search for
        2 - length of string
        3 - position to start search (see function 9)

    7 - Query cursor position

        Get the current location of the cursor. Returns a number
        from 1 to 2000.

      PARAMETERS
        1 - N/A
        2 - N/A
        3 - N/A

    8 - Copy presentation space to string

        Copy a piece of the presentation space to a character
        variable. Takes as parameters the starting position and
        length. Note that empty space is often returned as strings
        of chr(0) and not spaces so you might want to run
        strtran(string,chr(0)," ") against all copied strings before
        doing anything with them.

      PARAMETERS
        1 - string of space(length+1)
        2 - length
        3 - starting position to copy from

    9 - Set session parameters

        Define some defaults that the HLLAPI interface will obey. In
        all of my work with mainframes I've always left this alone
        and used all of the default settings. Calls to this function
        let you change the behavior of the following functions.
        Before changing any of these parameters make sure you
        understand all of the ramifications of making the change.

        All Copy functions
        Send key
        Search
        Trace
        Wait
        Disconnect presentation space
        Pause
        Send and Receive

      PARAMETERS
        1 - string containing settings
        2 - length of string
        3 - N/A

    10 - Query sessions

        Get information on the currently active session.

      PARAMETERS
        1 - space(144)
        2 - 144
        3 - N/A

    11 - Reserve (Lock the presentation space)

        Prevents the operator from entering data via the console.
        This function can prevent someone from wandering by, hitting
        some mainframe keys and crashing your current session.

      PARAMETERS
        1 - N/A
        2 - N/A
        3 - N/A

    12 - Release (Unlock the presentation space)

        Allows the operator to enter data at the keyboard. Undoes
        function 12, Reserve.

      PARAMETERS
        1 - N/A
        2 - N/A
        3 - N/A

    13 - Copy Operator Information Area

        Returns a 103 character string containing information on the
        status of the current session. Positions 1 - 80 contains an
        image of the 25the row of the terminal screen.

      PARAMETERS
        1 - a sring of space(104)
        2 - 103
        3 - N/A

    14 - Query field attributes

        Returns the attribute byte of the specified field.

      PARAMETERS
        1 - N/A
        2 - N/A
        3 - Position in the presentation space to query

    15 - Copy string to presentation space

        Place a string at a specified position on the current
        screen. I used this for all of my data input on the
        application I worked on. If you only know the position on
        the screen where to put data this function will work fine.
        Had I been working in a more complicated application. I
        would probably have used Copy String to Field, Function 33.

      PARAMETERS
        1 - Data to copy to presentation space
        2 - length of string
        3 - position to place string

    17 - Storage manager

        Allocates and deallocates memory, probably useless for
        Clipper programmers.

    18 - Pause

        Waits approximately n/2 seconds or until the host releases
        it depending on settings in function 9, set session
        parameters. This function requires that function 23, Start
        host notification be called first if you want the host to be
        able to release the pause. This is useful while waiting for
        a long host request to finish. All of the HLLAPI manuals
        I've seen recommend strongly not asking for pauses longer
        than about 20 minutes. The Attachmate manual lists 7200 as
        an absolute maximum value to use. Both the IBM and
        Attachmate recommend not using it for pauses over 20 minutes
        or for things which require accurate timings. Depending on
        the settings in Function 9, Set Session Parameters, the host
        can be given the capability of ending the wait when it is
        ready for more input.

      PARAMETERS
        1 - N/A
        2 - pause duration in seconds*2
        3 - N/A

    20 - Query system

        Returns HLLAPI version and revision levels.

      PARAMETERS
        1 - space(35)
        2 - N/A
        3 - N/A

    21 - Reset system

        Resets all settings in the interface software to the default
        condition and disconnects the presentation space.

      PARAMETERS
        1 - N/A
        2 - N/A
        3 - N/A

    22 - Query session status

        Returns the type of connection and the number of rows and
        columns on the current screen

      PARAMETERS
        1 - short name of presentation space + space(18)
        2 - 18
        3 - N/A

    23 - Start host notification

        Turns on the ability to use Query host update and Pause.

    24 - Query host update

        Tells you if the Operator Information Area or presentation
        space has been updated since you last checked this function.

    25 - Stop host notification

        Turns off the ability to use Query host update and Pause.

    30 - Search field

        Search within fields for a string. Returns 0 or the location
        of the first occurrence of the string. Function 9, Set
        Session Parameters, may be used to allow the specification
        of a starting position which will allow finding the second
        and later occurrences of the string. It also allows you to
        specify the search direction, forward or backward.

      PARAMETERS
        1 - string to search for
        2 - length of string
        3 - position to start search from (see function 9)

    31 - Find field position

        Find the location of the current, next or previous field.
        This will return the starting position of the current,
        previous or next field. You may set a filter so that it only
        looks for protected or unprotected fields.

      PARAMETERS
        1 -
             "T " - this field
             "P " - previous field
             "N " - next field
             "NP" - next protected field
             "NU" - next unprotected field
             "PP" - previous protected field
             "PU" - previous unprotected field
        2 - N/A
        3 - position from which to start the find

    32 - Find field length

        Find the length of the current, next or previous field. This
        will return the length of the current, previous or next
        field. You may set a filter so that it only looks for
        protected or unprotected fields.

      PARAMETERS
        1 -
             "T " - this field
             "P " - previous field
             "N " - next field
             "NP" - next protected field
             "NU" - next unprotected field
             "PP" - previous protected field
             "PU" - previous unprotected field
        2 - N/A
        3 - position from which to start the find

    33 - Copy string to field

        Place a string in a specified field.

      PARAMETERS
        1 - String containig data to transfer
        2 - length of the string
        3 - position of the field to copy to.

    34 - Copy field to string

        Get the contents of a specified field.

      PARAMETERS
        1 - string of space(length +1)
        2 - length
        3 - position of the field to copy from

    90 - Send file

        Upload a file to the mainframe using Send. Since this just
        calls a second copy of command.com to run Send, I'd
        recommend using one of the Clipper memory swappers to RUN
        Send.exe to make sure that Send has enough memory to run.

    91 - Receive file

        Download a file to the mainframe using Receive. Since this
        just calls a second copy of command.com to run Receive, I'd
        recommend using one of the Clipper memory swappers to RUN
        Receive.exe to make sure that Receive has enough memory to
        run.

    99 - Convert position or Row Col

        Converts back and forth between the mainframe 1-1920 cursor
        positioning convention and the PC 0-24 x 0-79 cursor
        positioning convention. I'd suggest using the following
        Clipper functions instead. Please notice that the maintopc
        function requires that you pass the parameter by reference
        as the column number will be returned via that parameter.

        FUNCTION pctomain ( row, col )
           RETURN INT( ( row * 80 ) + col + 1 )

        FUNCTION maintopc ( location )
           LOCAL row, col
           row := INT( --location / 80 )
           col := ( location  % 80 )
           location := col
           RETURN row

    Attachmate only HLLAPI commands

        The following 8 commands are extensions to the IBM HLLAPI
        specification which are available to those of you who will
        be using Attachmate's EXTRA! 3270 terminal emulation
        software.

    0 - Attachmate query system

        Returns the Attachmate software version number and
        connection type.

      PARAMETERS
        1 - space(32)
        2 - 32
        3 - N/A

    16 - WS control

        Allows direct calls to Attachmate's Workstation control
        commands.

      PARAMETERS
        1 - a string of commands
        2 - length of the string
        3 - N/A

    50 - Start keystroke intercept

        Allows your program to intercept any operator input.

      PARAMETERS
        1 - data string
        2 - 256
        3 - N/A

    51 - Get key

        Get operator input from the session on which Function 50 put
        an interrupt.

      PARAMETERS
        1 - data string
        2 - N/A
        3 - N/A

    52 - Post intercept status

        Tell EXTRA! whether to accept or reject the keystroke
        obtained with Get Key.

      PARAMETERS
        1 - data string
        2 - N/A
        3 - N/A

    53 - Stop keystroke intercept

        Turn off keystroke intercept.

      PARAMETERS
        1 - name of presentation space
        2 - N/A
        3 - N/A

    92 - Invoke DOS program

        RUN a program. This will not work on internal DOS functions,
        see DOS redirect.  This does not look like a function I'd
        recommend you use, use RUN instead.

    93 - DOS redirect

        Allows calling DOS internal functions like Copy. This does
        not look like a function I'd recommend you use, use RUN
        instead.

    CLIRMA

        CLIRMA, which stands for Clipper-IRMA is a library for
        CLipper which allows a Clipper application to talk to a
        mainframe terminal session in a computer which contains and
        DCA IRMA or compatible 3270 terminal emulation card. The
        CLIRMA library contains all of the commands you are likely
        to need to automate a mainframe session or transfer files.

    Bibliography

        IBM PC 3270 Emulation Program Version 3.0, P/N 59X9969.

        IBM PC 3270 Emulation Program Entry Level Version 1.21, High
        Level Language Application Program Interface Programmers
        Guide, P/N 74X9881.

        IBM PC 3270 Emulation Program Entry Level Version 1.21, High
        Level Language Application Program Interface Quick Reference
        Card, P/N 74X9879.

        Attachmate EXTRA! Programmer's Tool Kit Volume I, HLLAPI,
        SRPI.

        Steve Straley's CLIRMA Library
        Four Seasons Publishing Co., Inc.
        P.O. Box 20025
        N.Y., NY  10017-0001

    Clipper memory swappers.

        In the limited memory situation which occurs when using a
        3270 emulation product, ability to maximize memory for
        running external programs might make the difference between
        success and failure. Clipper's Summer '87 and 5.0 versions
        manage memory differently.  Both the size of Clipper's
        working memory and the proportion it can give to an external
        program differ between versions. But for both versions there
        may be cases where a progam to swap the entire Clipper
        application to disk is useful. The following two programs
        have that ability. Both products are expected to work under
        Clipper 5.0, according to their representatives. Their
        authors and users actively participate on Nanforum.

        Dr. Switch
        Black & White International, Inc.
        P.O. Box 1040
        Planetarium Station
        New York, NY  10024-1040
        (212) 787-6633

        Overlay()
        Market Service Associates
        P.O. Box 986
        Coeur d'Aline, ID  83814
        (208) 765-9439
