Chapter Contents

Previous

Next
iucvsevr

An Example of IUCV Communication

The following example illustrates how two virtual machines can communicate with each other by sending IUCV messages. The first example program is called SENDER. This program prompts for a message string to be input from the terminal and sends the string to the second example program, RECEIVER. RECEIVER displays the message and prompts for a reply string. The reply string is sent back to SENDER. SENDER displays the reply, and the cycle repeats until a zero-length line is entered in response to SENDER's prompt.


The SENDER Program

This program has only two functions. The main function initializes signal processing and IUCV. It uses fgets to read message strings and printf to display reply strings. The sigpause function makes the program wait until a reply is sent. The sigblock function blocks SIGIUCV signals until the program is ready to handle them.

The iucvtrap function is the SIGIUCV signal handler. Only two IUCV interrupt types are expected: a CONNECTION COMPLETE interrupt in response to the IUCV CONNECT and an INCOMING REPLY in response to each IUCV SEND.

The source code for these examples is provided with the compiler and library. Ask your SAS Software Representative for SAS/C software products for information about obtaining copies of these programs.

                 /* SENDER */

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

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

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

int rep_len = 0;
short pathid = 0;

main()
{
   struct iucv_path_plist path;    /* IUCV plist for CONNECT, SEVER  */
   struct iucv_msg_plist msg;      /* IUCV plist for SEND            */

      /* maximum number of IUCV connections for this virtual machine */
   int maxconns;
   int rc;                         /* return code from IUCV functions*/
   char message[120],              /* message buffer                 */
   reply[120];                     /* reply buffer                   */

      /* Initialize IUCV signal processing and establish a handler.  */
      /* Block IUCV signals until we're ready to handle them.        */
   signal(SIGIUCV,&iucvtrap);
   sigblock(1 << (SIGIUCV-1));

      /* Identify this program as SENDER. */
   if ((rc = iucvset("SENDER",&maxconns)) != 0) {
      printf("Return code from iucvset was %d\n",rc);
      exit(4);
   }
   printf("Maximum IUCV connections: %d\n",maxconns);
     /* Fill in the IUCV "path" parameter list with the target      */
     /* userid and the name of the target program. All of the other */
     /* parameters are superfluous in this program.                 */
   memset((void *) &path,0,sizeof(path));
   memcpy(path.vmid,"SASCUSER",8);
   memcpy(path.pgm,"RECEIVER",8);

     /* Request an IUCV CONNECT to the userid/program pair named    */
     /* in the parameter list.  Check for an IUCV error (return     */
     /* code of 1)and print the IUCV error code.                    */
   rc = iucvconn("SENDER",&path);
   if (rc != 0) {
      printf("Return code from iucvconn was %d\n",rc);
      if (rc == 1)
         printf("IPRCODE = %d\n",path.ip.rcode);
      exit(8);
   }

     /* Now we are ready. The first interrupt we receive is the     */
     /* CONNECTION COMPLETE interrupt that occurs when RECEIVER     */
     /* issues an IUCV ACCEPT.                                      */
   sigpause(0);

     /* Initialize the SEND parameter list with the pathid and      */
     /* buffer addresses and the length of the reply buffer.        */
   memset((void *) &msg,'\0',sizeof(msg));
   path.pathid = msg.pathid = pathid;
   msg.msg.bf1.adr = message;
   msg.bf2.adr = reply;
   msg.bf2.ln = sizeof(reply);

     /* Prompt for input messages and send until EOF.               */
   fgets(message,sizeof(message),stdin);
   while (!feof(stdin)) {
        /* Put message length in the SEND parameter list.           */
      msg.msg.bf1.ln = strlen(message) - 1;
        /* 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.                            */
      iucvsend(&msg);
      sigpause(0);
      rep_len = sizeof(reply) - rep_len;
      printf("RECEIVER replies "%.*s"\n",
              rep_len,reply);
      fgets(message,sizeof(message),stdin);
   }
      /* We are ready to quit. SEVER the IUCV path.  Check for IUCV   */
      /* errors as before.                                            */
   if ((rc = iucvsevr("SENDER",&path,"ONE")) != 0) {
      printf("Return code from iucvsever = %d\n",rc);
      if (rc == 1)
         printf("IPRCODE = %d\n",path.ip.rcode);
      exit(10);
   }

      /* Terminate IUCV communications for SENDER. */
   iucvclr("SENDER");
   exit(0);
}

   /* The SIGIUCV signal handler. Signals are blocked until return.   */
void iucvtrap(void)
{
      /* Pointer to external interrupt data returned by siginfo. The  */
      /* type is arbitrary since it can point to any of the IUCV      */
      /* structures.                                                  */
   iucv_path_data *XID;

      /* Get a pointer to the external interrupt data.  Use the       */
      /* interrupt type to determine what to do.                      */
   XID = (iucv_path_data *) siginfo();
   switch (XID->ip.type) {
      case CONNECTION_COMPLETE:          /* Save the pathid for SEND. */
         pathid = XID->pathid;
         break;

         /* Extract the number of unused characters in the buffer.    */
      case INCOMING_REPLY:
         rep_len = ((iucv_msg_data *)XID)->bf2.ln;
         break;

         /* Handle unexpected termination of RECEIVER.                */
      case PATH_SEVERED:
         puts("Unexpected SEVER!");
         exit(20);

         /* Handle unexpected type of IUCV signal.                    */
      default:
         printf("Unexpected interrupt type %d\n",XID->ip.type);
         fflush(stdout);
         abort();
   }
      /* Reestablish this function as the SIGIUCV signal handler.     */
   signal(SIGIUCV,&iucvtrap);
   return;
}


The RECEIVER Program

This program defines three functions. The main function, again, initializes signal processing and IUCV. main calls sigpause to wait for the initial CONNECTION PENDING interrupt once and then repeatedly (until all connections are severed) for incoming messages.

The iucvtrap function is again the SIGIUCV signal handler. Three types of IUCV interrupts are expected: a CONNECTION PENDING for each sending program, a PATH SEVERED as each sending program finishes, and an INCOMING MSG interrupt for each message sent by a sending program.

Finally, the rcvrply function issues an IUCV RECEIVE for each incoming message and prompts for a reply string. It then sends the reply string via an IUCV REPLY.

                  /* RECEIVER */

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

void iucvtrap(void);                  /* SIGIUCV signal handler      */

                                      /* stdin prompt string         */
char *_stdiamp = "prompt=What do I reply to SENDER?";
int connects = 0;                     /* number of connections made  */
static void rcvrply(iucv_msg_data *); /* Declare internal functions. */

void main()
{
   int maxconns;               /* number of IUCV connections allowed */
   int rc;                     /* return code from IUCV functions    */

      /* Initialize IUCV signal processing and establish a handler.  */
      /* Block IUCV signals until we are ready to handle them.       */
   signal(SIGIUCV,&iucvtrap);
   sigblock(1 << (SIGIUCV-1));

      /* Identify this program as RECEIVER. */
   if ((rc = iucvset("RECEIVER",&maxconns)) != 0) {
      printf("Return code from iucvset was %d\n",rc);
      exit(4);
   }
   printf("Maximum IUCV connections: %d\n",maxconns);

      /* This call waits for the initial                             */
      /* CONNECTION PENDING interrupt.                               */
   sigpause(0);

      /* As long as some SENDER is connected,                        */
      /* wait for incoming messages.                                 */
   while (connects > 0) sigpause(0);
      /* All paths have been terminated. Terminate IUCV processing.  */
   iucvclr("RECEIVER");
   exit(0);
}

   /* SIGIUCV signal handler. Signals are blocked until return.      */
void iucvtrap(void) {
      /* Pointer to external interrupt data returned by siginfo. The */
      /* type is arbitrary because it can point to any of the IUCV   */
      /* structures.                                                 */
   iucv_path_data *XID;
   int rc;                               /* Return code from iucvacc.*/

      /* Get a pointer to the external interrupt data. Use the       */
      /* interrupt type to determine what to do.                     */
   XID = (iucv_path_data *) siginfo();
   switch (XID->ip.type) {
      case CONNECTION_PENDING:           /* Issue ACCEPT.            */
         XID->ip.type = 0;
         if ((rc = iucvacc("RECEIVER",XID)) != 0) {
            printf("Return code from iucvacc = %d\n",rc);
            if (rc == 1)
               printf("IPRCODE = %d\n",XID->ip.rcode);
            exit(8);
         }
            /* Keep track of the number of connections made.         */
         connects++;
         break;

         /* Call function to get message and send reply. */
      case INCOMING_MSG:

         rcvrply((iucv_msg_data *)XID);
         break;

      case PATH_SEVERED:             /* SENDER decided to stop.      */
         if ((rc = iucvsevr("RECEIVER",XID,"ONE")) != 0) {
            printf("Return code from iucvsevr = %d\n",rc);
            exit(8);
         }
         connects--;                 /* Update number of connections.*/
         break;

      default:                       /* Handle other interrupt types.*/
         printf("Unexpected interrupt type %d\n",XID->ip.type);
         fflush(stdout);
         abort();
   }

      /* Re-establish this function as the SIGIUCV signal handler.   */
   signal(SIGIUCV,&iucvtrap);
   return;
}

      /* Function to issue IUCV RECEIVE and print the message.       */
static void rcvrply(m_data)
iucv_msg_data *m_data;
{
   int msg_len;                           /* incoming message length */
   char msg_buffer[120];                  /* message buffer          */

      /* Create IUCV RECEIVE parameter list using the external       */
      /* interrupt data area.  Issue the IUCV RECEIVE.               */
   m_data->msg.bf1.adr = msg_buffer;
   m_data->msg.bf1.ln = sizeof(msg_buffer);
   iucvrecv(m_data);

      /* Upon return, m_data->msg.bf1.ln contains the number of      */
      /* unused bytes in the message buffer.  Print the message.     */
   msg_len = sizeof(msg_buffer) - m_data->msg.bf1.ln;
   printf("SENDER says "%.*s"\n",
        msg_len,msg_buffer);

      /* Prompt for a reply message.  If EOF, quit.                  */
   fgets(msg_buffer,sizeof(msg_buffer),stdin);
   if (feof(stdin)) {
      puts("Terminating due to end-of-file.");
      exit(12);
   }

      /* Fill in IUCV REPLY parameter list with buffer               */
      /* address/length and send REPLY.                              */
   m_data->bf2.adr = msg_buffer;
   m_data->bf2.ln = strlen(msg_buffer) - 1;
   iucvrply(m_data);
}


Chapter Contents

Previous

Next

Top of Page

Copyright © 2001 by SAS Institute Inc., Cary, NC, USA. All rights reserved.