
/*@@file***********************************************************************
 *
 * DESCRIPTION:
 *  This is the IS/2 sample client program with for use in a CS/2 (non-APPC)
 *  environment. 
 *  **** This sample is distributed "As Is" and without warranty. 
 *  It is intended to be used only as an example of how the functions 
 *  of IS/2 can be invoked in a CS/2 network on an OS/2 system.
 *
 ****************************************************************************/
#ifdef  DOCUMENT

    This file contains all the information needed to build and execute the IS/2
    sample client program using CS/2 on an OS/2 system. When used in conjunction
    with the Interface Services/2 Programmer's Guide, SC28-8258, the sample
    program will help you to understand an IS/2 program running on a CS/2
    network.

FUNCTION:

    The function of CS2SAMP is to send three IS/2 transactions to the
    IS/2 Server, EA_AUTHORIZE, EA_SYMLOOK, and EA_EXIT.  This is accomplished
    by using the CS/2 SEND and RECEIVE functions. For each transaction CS2SAMP
    waits for the IS/2 response message and displays it on the console. At the
    end of this sequence, the program terminates. The program can be re-executed
    as many times as desired.

COMPONENTS PROVIDED (as separate files):

    IS/2 Server Side:

      The PlantWorks executive node is already defined to CS/2 so no new
      requirements exist.

    Client Side:

      cs2samp.txt  Sample documentation and the sample listing (this file)
      eaclnt2.cbs  Sample CS/2 configuration description file for client side


COMPONENTS RELATIONSHIP & INTERFACES:

      NODE5:   the server node
      CS2NODE: the client node


RELATED REQUIREMENTS:

    Run Time Environment Network Hardware requirements
    --------------------------------------------------

    o   No network is required if the server and client are the same node.
    o   Token Ring or other NETBIOS devices network is required if we run 
        this in the seperated node.

    Run Time Environment Network Software requirements
    --------------------------------------------------

    o   The system which runs IS/2 is designated the 'server node'.
        The system running the user program is designated the 'client node'.

    o   The 'server node' has to have the following software:
        1.  OS/2 Extended Edition Version 1.2 or later
        2.  CS/2 Version 1.1 or later
        3.  PlantWorks Build Services/2 and Execution Services/2 (Exec Node)
        4.  PlantWorks IS/2 1.0

    o   The 'client node' has to have the following software:
        1.  OS/2 Extended Edition Version 1.2 or later
        2.  CS/2 Version 1.1 or later

        NOTE: The 'client node' can be the same as the 'server node' if desired

    Run Time Environment CS/2 Configuration requirements
    ----------------------------------------------------

    o   See "eaclnt2.cbs".

EXECUTION SEQUENCE:

        Before the sample program can be executed some PW variables must be
        defined. The sample assumes that a user ID and password and a PW item
        have been defined as described below:

    o   PlantWorks user identification

        1. User Name ID:  EAPIDEMO
        2. User Password: EAPIDEMO
           NOTE: This user ID should have 'full access'. See page the
           IS/2 Programmer's Guide for a description of how to do this.

    o   PlantWorks Item

        1. Item Name:     APP:VAR1

	This item must be defined as a floating point variable, or you should
        change the sample program.

        Once these two tasks have been accomplished you are now ready to run
        the sample program. The following describes this process:

    o   Build the IS/2 Sample CS/2 Client Program with IBM C/2 compiler

        1. Copy cs2samp.txt and rename it to cs2samp.c
        2. The program is set up assuming that it is being executed on a single
           node. If you want to execute it on the remote node that IS/2 is
           installed on, enable the define for REMOTE.
        3. The program is also set up assuming that it is being started by CMD.
           If you want to start the program by CS/2, enable the define for
           START_BY_CS2.
        4. Compile and link the program with these parameters:

           cl /AL /G2 /W1 /Zp  /F 4000 cs2samp.c /link cs2calls.lib

    o   Startup the IS/2 Server Node

        1. Start the CS/2 System Software
        2. Start the PlantWorks Software
        3. Start and Verify the IS/2 Server

    o   Startup the Sample program (except when it is started by CS/2)

        1. Execute the program by keying "cs2samp" on the 'client node'.

#endif  /* DOCUMENT */


/****************************************************************************
 *----- Beginning of C program
 ****************************************************************************
 */

/*      CS2SAMP.TXT is a sample IS/2 client application program running on a CS2
 *      system. It can be run as a CS/2 application program by having CS/2 start
 *      it or it can be run as an external CS2 application by starting it
 *      independently. It also can be run on the same node on which IS/2 is
 *      installed or on a different node. Values are set in the program to
 *      determine this.
 *
 *      You must set up and verify that the CS2 environment is operational
 *      before the sample program will execute correctly.
 *
 *      This sample program does the following:
 *
 *      . Registers the program to an ACB, named EAPI0001.CS2NODE, as the
 *        originating resource
 *      . Registers the program to an ACB, named EAPI.NODE5, as the
 *        destination resource
 *      . Sends an EA_AUTHORIZE transaction request to set up the IS/2
 *        connection
 *      . Receives an EA_AUTHORIZE status code back
 *      . Sends an EA_SYMLOOKUP transaction request to look up a variable
 *      . Receives the EA_SYMLOOKUP information back
 *      . Sends an EA_EXIT request to disconnect the IS/2 connection
 *      . Receives an EA_EXIT status
 *      . Unregisters the program from "EAPI0001.CS2NODE" and "EAPI.NODE5",
 *        so the sample can run again.
*/
#include <stdio.h>
#include <cs2apcal.h>
#include <cs2coerr.h>
#include <eapimsg.h>


/*
 *      Message data definitions for SEND
 */
#define ACK             1       /* Acknowledge on msg arrival    */
#define PRIORITY        100     /* message priority              */
#define TIMEOUT         2000    /* synchronous request with
                                 * timeout before return         */
#define SNDMSGL sizeof (sndmsg) /* send msg size                 */
/* #define START_BY_CS2    1       program started by CS2        */
/* #define REMOTE          1       program on different node     */

struct  ear_authorize sndmsg = {/* authorize msg contents to send*/
        EA_AUTHORIZE,           /* transaction type              */
        0,                      /* msg_id =0                     */
        EA_CS2,                 /* CS2 based client program      */
        0,                      /* reserved                      */
        "EAPIDEMO",             /* User ID - 32 byte field       */
        "EAPIDEMO"              /* User Password - 32 byte field */
        };

struct CS2AP_SND_S mysend = {   /* send msg pointer              */
        (unsigned long )SNDMSGL,/* msg length                    */
        (char far *)&sndmsg};   /* address of the message        */

struct  ear_symlookup symmsg = {/* authorize msg contents to send*/
        EA_SYMLOOKUP,           /* transaction type              */
        1,                      /* u_msg_id                      */
        "APP:VAR1                       ",/* symbol name - 32 byte field*/
        };

struct CS2AP_SND_S symsend = {  /* send msg pointer              */
        sizeof (symmsg),        /* msg length                    */
        (char far *)&symmsg};   /* address of the message        */

struct CS2AP_RSN_S origin = {   /* msg source header             */
        0,                      /* reserved                      */
        "EAPI0001.CS2NODE"      /* IS/2 client program ACB name  */
        };
struct CS2AP_RSN_S dest = {     /* msg destination header        */
        0,                      /* reserved                      */
#ifdef  REMOTE
        "EAPI.NODE5"};          /* client/server not on same node */
#else
        "EAPI.CS2NODE"};        /* client/server on same node    */
#endif

struct CS2AP_RDS_S myrds = {    /* CS/2 Request Data Structure   */
        &origin,                /* pointer to CS2_RSN_S structure*/
                                /* CS2_RSN_S which represents the*/
                                /* originating resource for the  */
                                /* request.                      */
        &dest,                  /* pointer to CS2_RSN_S structure*/
                                /* CS2_RSN_S which represents the*/
                                /* destination resource for the  */
                                /* request.                      */
        0,                      /* no acknowledgement parameter  */
                                /* acknowledge when message arrived*/
        TIMEOUT,                /* timeout value in milliseconds */
        PRIORITY ,              /* priority of request           */
        0,                      /* CS/2 return code              */
        0,                      /* operating system return code  */
        0,                      /* reserved area                 */
        0,                      /* command code                  */
        0,                      /* length of message received    */
        0,0,0,0,0,0,0           /* CS/2 Reserved                 */
};


/*
 *      Message data definitions for RECEIVE
 */
#define RCVMSGL         sizeof (rcvmsg)
#define PURGE           1       /* purge the msg after receive   */
char rcvmsg[512];               /* receiving msg buffer          */
struct CS2AP_PFX_S prefix;      /* buffer for the msg header     */
                                /* msg receiver data structure   */
struct CS2AP_REC_S myrecv = {
        (unsigned long )RCVMSGL, /* length of buffer to receive  */
        (char far *)rcvmsg,      /* buffer for receive data      */
        &prefix,                 /* buffer for receive header    */
        PURGE,                   /* purg after receive           */
        NULL,                    /* accept any sending resource  */
        0,0
        };
/*
 *      Main program
 */

main()
{

        CS2_INIT(&myrds);        /* initialization               */
        if (myrds.cnretcd){      /* check error return code      */
                printf("error: CS2_INIT failed: %d\n",myrds.cnretcd);
                exit(4);
        }
#ifndef START_BY_CS2
        /*
         * IF     this program is not started by CS2
         * THEN   we find the IS/2 Client's ACB and initialize
         * ENDIF
         */
        myrds.orig = &origin;
        CS2_INITIALIZE_RES(&myrds); /* Register this program with */
                                    /* the ACB or ANCB resource   */
        if (myrds.cnretcd){
                printf("error: CS2_INITIALIZE_RES failed: %d\n",myrds.cnretcd);
                process_error(&myrds);
                }
#endif
        myrds.dest = &dest;         /* set destination resource name*/
        CS2_SEND(&myrds, &mysend);  /* send EA_AUTHORIZE request    */
        if (myrds.cnretcd != 0)     /* error on send                */
                process_error(&myrds);
        myrds.dest = &origin;       /* set receiving resource name  */
        CS2_RECEIVE(&myrds, &myrecv); /* receive EA_AUTHORIZE status*/
        if ( (myrds.cnretcd != 0) ||  /* check all error flag       */
           (((struct eas_authorize far *) myrecv.buf)->status != 0) )
                process_error(&myrds);

        myrds.dest = &dest;         /* set destination resource name*/
        CS2_SEND(&myrds, &symsend); /* send EA_SYMLOOKUP request    */
        if (myrds.cnretcd != 0)
                process_error(&myrds);
        myrds.dest = &origin;       /* set receiving resource name  */
        CS2_RECEIVE(&myrds, &myrecv); /* receive SYMBOL data        */
        if ( (myrds.cnretcd != 0) ||
           (((struct eas_symlookup far *) myrecv.buf)->status != 0) )
                process_error(&myrds);
/*
 *      Exit from IS/2 Transaction
 */
        sndmsg.tid = EA_EXIT;       /* change transaction ID        */
        mysend.msglen = sizeof (struct ear_exit);
        myrds.dest = &dest;         /* set destination resource name*/
        CS2_SEND(&myrds, &mysend);  /* send EA_EXIT request         */
        if (myrds.cnretcd != 0)
                process_error(&myrds);

        myrds.dest = &origin;       /* set receiving resource name  */
        CS2_RECEIVE(&myrds, &myrecv); /* receive EA_EXIT status     */
        if ( (myrds.cnretcd != 0) ||
           (((struct eas_exit far *) myrecv.buf)->status != 0) )
                process_error(&myrds);

        myrds.dest = &origin;       /* set receiving resource name  */
        CS2_STOP_RES (&myrds);      /* stop the the orig. ACB resource*/
        CS2_PURGE_RES (&myrds);     /* purge the the ACB resource   */
        exit(0);
}

/*
 *      Error handling
 */
process_error(rds)
struct CS2AP_RDS_S far *rds;
{
                                    /* set the ACB to purge         */
        rds->dest= &origin;
        CS2_STOP_RES (rds);         /* stop the the orig. ACB resource*/
        CS2_PURGE_RES (rds);        /* purge the the ACB resource   */
        exit(4);
}

/*
 *------------------------- End of C program --------------------------------
 */
