www.sas.com > Service and Support > Technical Support
 
Technical Support SAS - The power to know(tm)
  TS Home | Intro to Services | News and Info | Contact TS | Site Map | FAQ | Feedback


/*--------------------------------------------------------------------+
|                                                                     |
|              Copyright 1996 (c), SAS Institute Inc.                  |
|                Unpublished - All Rights Reserved                    |
|                                                                     |
|                     S A S / C  S A M P L E                          |
|                                                                     |
|       Name: APPCSEND                                                |
|                                                                     |
|   Language: C                                                       |
|                                                                     |
| EntryPoint: MAIN                                                    |
|                                                                     |
| EntryType : OS Entry Linkage                                        |
|                                                                     |
| Files Note: 'prefix' is the installation defined high level         |
|             qualifier for the SAS/C product.                        |
|                                                                     |
|    Purpose: Demonstrate SAS/C APPC/VM support.                      |
|                                                                     |
| MVS -  Not Supported for MVS                                        |
|                                                                     |
|     Source: prefix.SAMPLE.C(APPSEND)                                |
|                                                                     |
| CMS -                                                               |
|     Source: SAMPLC   MACLIB (APPCSEND)                              |
|                                                                     |
|    Compile: global maclib lc370                                     |
|             lc370 appcsend                                          |
|                                                                     |
|       Link: global txtlib lc370bas lc370std                         |
|             load (appcsend                                          |
|             genmod appcsend(from @main                              |
|                                                                     |
|    Execute:  See the SAS/C Language Reference Vol 2,                |
|              chapter 'APPC/VM Functions' for details.               |
|                                                                     |
|      Notes:                                                         |
|            - This sample for CMS only.                              |
|            - See sample APPCSERV for setup information.             |
|                                                                     |
+--------------------------------------------------------------------*/
#eject

#include <lcsignal.h>
#include <lcstring.h>
#include <cmsappc.h>
#include <lcio.h>

void appctrap(void);              /* Declare SIGIUCV handler.       */

                                  /* Set up stdin amparms.          */
char *_stdiamp = "prompt=What message do I send?\n,eof=";

static int rep_len = 0;
static short pathid = 0;
static short ident_pathid = 0;

void main()

   {
   struct appc_conn_plist conn;   /* APPC plist for CONNECT, SEVER  */
   struct appc_send_plist send;   /* APPC plist for SENDDATA,       */
                                  /*    SENDCNFD                    */
   int maxconns,                  /* Maximum number of IUCV connec- */
                                  /*  tions for this virtual machine*/
       rc;                        /* Return code from APPC functions*/

   struct senddata {
      unsigned short length;      /* length of data to send          */
      char message(|120+2|);      /* Message buffer.                */
      } logrec, reply;            /* Log record and reply buffers   */

   /*----------------------------------------------------------------+
   | Initialize IUCV signal processing and establish a handler.      |
   | Block IUCV signals until we're ready to handle them.            |
   +----------------------------------------------------------------*/

   signal(SIGIUCV,&appctrap);
   sigblock(1 << (SIGIUCV-1));

   /*----------------------------------------------------------------+
   | Identify this program as APPCSEND.                              |
   +----------------------------------------------------------------*/

   if ((rc = iucvset("APPCSEND",&maxconns)) != 0) {
      printf("Return code from iucvset was %d\n",rc);
      exit(4);
      }
   printf("Maximum IUCV connections: %d\n",maxconns);

   /*----------------------------------------------------------------+
   | Fill in the APPC "conn" parameter list with the target resource |
   | id, "APPCSERV".                                                 |
   |                                                                 |
   | Note that the resource name in IPRESID must be eight bytes      |
   | long, padded on the right with blanks if necessary.             |
   +----------------------------------------------------------------*/

   memset(&conn, 0, sizeof(conn));
   conn.ip2.flags2 = IPLVLCF + IPMAPPED;
   memcpy(conn.resid, "APPCSERV",8);

   /*----------------------------------------------------------------+
   | Request an APPC CONNECT to the resource named in the            |
   | parameter list.  Check for an IUCV error (return code != 0) and |
   | print the APPC error code.                                      |
   +----------------------------------------------------------------*/

   rc = appcconn("APPCSEND",&conn, 0);
   if (rc != 0) {
      printf("Return code from appcconn was %d\n",rc);
      if (rc == 1)
         printf("IPRCODE = x'%X'\n",conn.ip1.rcode);
      exit(8);
      }

   /*----------------------------------------------------------------+
   | Now we're ready.  The first interrupt we will receive is the    |
   | CONNECTION COMPLETE interrupt that occurs when APPCSERV         |
   | issues an APPC ACCEPT.                                          |
   +----------------------------------------------------------------*/

   sigpause(0);

   /*----------------------------------------------------------------+
   | Initialize the SEND parameter list with the pathid and buffer   |
   | addresses, and the length of the reply buffer.                  |
   +----------------------------------------------------------------*/

   memset(&send, 0,sizeof(send));
   send.pathid = pathid;
   send.sendop = IPSNDRCV;
   send.bf1.adr  = (char *) &logrec;
   send.bf2.adr  = (char *) &reply;
   send.bf2.ln  = sizeof(reply);

   /*----------------------------------------------------------------+
   | Prompt for input messages and send until EOF.                   |
   +----------------------------------------------------------------*/

   fgets(logrec.message, sizeof(logrec.message), stdin);
   while (!feof(stdin))
      {

      /*-------------------------------------------------------------+
      | Put message length in the SEND parameter list.               |
      +-------------------------------------------------------------*/

      logrec.length = strlen(logrec.message) + 1;
      send.bf1.ln = logrec.length;


      /*-------------------------------------------------------------+
      | Send message.  Wait (via sigpause) for reply.  Upon receipt  |
      | of reply, 'rep_len' contains the number of unused bytes in   |
      | the reply buffer.  Print the reply and prompt for a new      |
      | message.                                                     |
      +-------------------------------------------------------------*/

      appcsdta(&send);
      sigpause(0);
      rep_len = reply.length - sizeof(reply.length);
      printf("APPCSERV replies \"%.*s\"\n",rep_len,reply.message);
      fgets(logrec.message, sizeof(logrec.message), stdin);
      }

   /*----------------------------------------------------------------+
   | We're ready to quit.  Ask the server if it's OK to sever.  If   |
   | so, then sever.                                                 |
   +----------------------------------------------------------------*/

   memset(&send, 0, sizeof(send));
   send.pathid = pathid;
   send.ip2.flags2 = IPWAIT;      /* Specify WAIT=YES               */
   send.sendop = IPCNFSEV;

   if ((rc = appcsdta(&send)) != 2) {
      printf("Return code from appcsdta = %d\n",rc);
      if (rc == 1)
         printf("IPRCODE = x'%X'\n",send.ip1.rcode);
      exit(12);
      }

   memset(&conn, 0, sizeof(conn));
   conn.pathid = pathid;
   conn.ip2.flags2 = IPWAIT;      /* Specify WAIT=YES               */
   conn.sendop = IPSNORM;

   if ((rc = appcsevr("APPCSEND",&conn,"ONE")) != 2) {
      printf("Return code from appcsever = %d\n",rc);
      if (rc == 1)
         printf("IPRCODE = x'%X'\n",conn.ip1.rcode);
      exit(16);
      }

   /*----------------------------------------------------------------+
   | Terminate APPC communications for APPCSEND.                     |
   +----------------------------------------------------------------*/

   iucvclr("APPCSEND");

   exit(0);

   }

#pragma eject
/*-------------------------------------------------------------------+
| The SIGIUCV signal handler.  Signals are blocked until return.     |
+-------------------------------------------------------------------*/

void appctrap()

   {
   appc_conn_data *XID;           /* Pointer to external interrupt  */
                                  /* data returned by siginfo.      */
   int rc;

   /*----------------------------------------------------------------+
   | Get a pointer to the external interrupt data.  Use the interrupt|
   | type to determine what to do.                                   |
   +----------------------------------------------------------------*/

   XID = (appc_conn_data *) siginfo();
   switch (XID->ip1.type)
      {
      case APPC_CONNECTION_COMPLETE:
         pathid = XID->pathid;    /* Save the pathid                */
         break;

      case APPC_FUNCTION_COMPLETE:
                                  /* See if it's for CONFIRM         */
         if (XID->pathid == pathid && XID->ip2.whatrc == IPSNDCNF) {
            struct appc_send_plist *send = (struct appc_send_plist *)XID;
            send->sendop = IPCNFRMD;
            rc = appcscfd(send);
            if (rc != 2) {
               printf("Error %d confirming request to recv\n", rc);
               printf("IPRCODE = x'%X'\n", XID->ip1.rcode);
               exit(20);
               }
            }
         break;

      case APPC_SEVER_INTERRUPT:  /* Handle unexpected termination  */
                                  /* of APPCSERV.                   */
         puts("Unexpected SEVER!");
         exit(24);

      default:                    /* Handle unexpected signal type  */
         printf("Unexpected interrupt type x'%X'\n",XID->ip1.type);
         fflush(stdout);
         abort();
      }

   /*----------------------------------------------------------------+
   | Re-establish this function as the SIGIUCV signal handler.       |
   +----------------------------------------------------------------*/

   signal(SIGIUCV,&appctrap);
   return;
   }

Copyright (c) 2000 SAS Institute Inc. All Rights Reserved.
Terms of Use & Legal Information | Privacy Statement