OTMA C/I sample program for asynchronous processing

The following program illustrates how to use OTMA C/I for asynchronous (unsolicited) processing.

In this sample program, one otma_send_asynch and one otma_receive_asynch call is issued per loop.

Recommendation: If you will be using synchronous (one in-one out) processing exclusively, use the otma_send_receive API. The otma_send_receiveAPI provides the most efficient means of synchronous processing.
#pragma langlvl(extended)       
                                                
/*********************************************************************/
/*                                                                   */
/* Callable Interface sample program using asynchronous APIs         */ 
/*                                                                   */ 
/* Parameters:                                                       */ 
/*         Server Name                                               */ 
/*         Client Name                                               */
/*         Transaction                                               */
/*         User Name                                                 */
/*         User Group                                                */
/*         Lterm                                                     */ 
/*         Mod Name                                                  */
/*         OTMA Data                                                 */
/*         Iterations                                                */
/*                                                                   */
/* Note:  The send buffer is sent as a file with a ddname of         */        
/*        SENDBUFn in the invoking JCL.                              */        
/*                                                                   */        
/* Example:  //SENDBUF0 DD *,DLM=$$                                  */        
/*           SEND OTMA TO SKS1                                       */        
/*           $$                                                      */        
/*                                                                   */        
/* Note: COMPAR1 is the DDNAME of an input file used to compare      */        
/*       actual output with expected output. '?' is used to delimit  */        
/*       the compare string and '|' is used to ignore a char compare */       
/*                                                                   */        
/* Example:  //COMPAR0  DD *,DLM=$$                                  */        
/*           SEND OTMA TO SKS1?                                      */        
/*           $$                                                      */        
/*                                                                   */        
/* Note: TPIPBUFn is the DDNAME of an input file used to specify     */        
/*       the tpipe name to be used for each iteration.               */        
/*                                                                   */        
/* Example:  //TPIPEBUF0  DD *,DLM=$$                                */        
/*           TPIPE001                                                */        
/*           $$                                                      */        
/*                                                                   */        
/*********************************************************************/         

/********************************************************************/
/*   Entry...                                                       */
/*                                                                  */
/*     This test program is callable from JCL                       */
/*                                                                  */
/* //NA1OTMA  JOB CLASS=A,MSGLEVEL=(1,1),MSGCLASS=H,REGION=2M       */
/* //************************************************************** */
/* //* PARM=server_member_name client_member_name transaction       */
/* //*      user_name group_name lterm_name ModName OTMA_Data       */
/* //*      iterations                                              */
/* //************************************************************** */
/* //MINISAMP EXEC PGM=NA1OTMA,                                     */
/* // PARM='TRAP(OFF)/IMS61CR1 IMSTESR G214992 /DISP user01 groupid */
/* //       Lterm ModName OTMAData 1'                               */
/* //STEPLIB  DD DISP=SHR,DSN=OTMA.TEST.LOAD                        */
/* //SYSUDUMP DD SYSOUT=*                                           */
/* //STDOUT   DD SYSOUT=*                                           */
/* //STDERR   DD SYSOUT=*                                           */
/* //CEEDUMP  DD SYSOUT=*                                           */
/* //COMPAR1  DD *,DLM=$$                                           */
/* EXPECTED OUTPUT GOES HERE                                        */
/* $$                                                               */
/* //SENDBUF0 DD *,DLM=$$                                           */
/* SEND DATA GOES HERE                                              */
/* $$                                                               */
/* //TPIPBUF0 DD *,DLM=$$                                           */
/* TPIPE NAME GOES HERE                                             */
/* $$                                                               */
/*                                                                  */
/* Note: TRAP(OFF)/ Passes LE run-time option TRAP(OFF) which turns */
/*       off LE condition handling. To get a LE dump on abend set   */
/*       TRAP ON and provide a CEEDUMP DDNAME.                      */
/*                                                                  */
/* Note: COMPAR1 is the DDNAME of an input file used to compare     */
/*       actual output with expected output. '?' is used to delimit */
/*       the compare string and '|' is used to ignore a char compare*/
/*                                                                  */
/********************************************************************/ 
                                                   
/*********************************************************************/         
/* An example for using the OTMA Client API in C lang.               */         
/*   This program is broken into the following parts:                */         
/*      Declarations for special support                             */         
/*      Process invocation parameters                                */         
/*      Setup for C signal handling                                  */         
/*      Do XCF open processing and analysis                          */         
/*      Execute an API to send data per invocation parm              */         
/*      Execute an API to receive data per invocation parm           */         
/*      Do close                                                     */         
/*      End                                                          */         
/*********************************************************************/         
                                                                                
/*********************************************************************/         
/* Header Definitions.                                               */         
/*********************************************************************/         
#include "dfsyc0.h"              /* Non-authorized OTMA API's        */         
#include <stdlib.h>              /* Standard C Header file           */         
#include <stddef.h>              /* Standard C Header file           */         
#include <stdio.h>               /* Standard C Header file           */         
                                                                                
/*********************************************************************/         
/* Internal functions                                                */         
/*********************************************************************/         
/* memory comparison macro.                                          */
/* int  memc(char *comp_buf, char *rec_buf1 );                       */
/*                                                                   */
/*                                                                   */
/* macro to move string to blank filled left justified char field    */ 
/* #define splat(t,s) \                                              */
/* {\                                                                */
/* memset((char*)&(t),' ',sizeof(t));\                               */
/* strncpy((char*)&(t), s ,strlen(s));}                              */
/*                                                                   */
/* standard math routines                                            */
/* #define   min(a,b)        ((a)<(b)?(a):(b))                       */
/* #define   max(a,b)        ((a)>(b)?(a):(b))                       */
                                                                                
/*********************************************************************/          
/*                                                                   */          
/*     This OTMA C/I Program                                         */          
/*                                                                   */          
/* Note: TRAP(OFF)/ Passes LE run-time option TRAP(OFF) which turns  */          
/*       off LE condition handling. To get a LE dump on abend set    */          
/*       TRAP ON and provide a CEEDUMP DDNAME.                       */          
/*                                                                   */          
/* Note: COMPAR1 is the DDNAME of an input file used to compare      */          
/*       actual output with expected output. '?' is used to delimit  */          
/*       the compare string and '|' is used to ignore a char compare */          
/*                                                                   */          
/*********************************************************************/          
main(int argc,char *argv[])                                                     
{                                                                               
                                                                                
/*********************************************************************/         
/*  Fields used by OTMA C/I APIs.                                    */         
/*********************************************************************/         

/* The following fields used by all the OTMA C/I API's.              */         
                                                                                
 otma_anchor_t    anchor;         /* Handle returned by create       */         
                                  /* and used by all others.         */         
 otma_retrsn_t    retrsn;         /* Return code returned by all.    */
                                                                     */
/* The following fields are used by the otma_create and              */
/* otma_open API's.                                                  */

otma_grp_name_t   grp_name;      /* API XCF Group Member Name.      */         
 otma_clt_name_t   clt_name;      /* API XCF Client Member Name.     */         
 otma_srv_name_t   srv_name;      /* API XCF Server Member Name.     */         
                                  /*   (IMS's XCF member name).      */         
 signed long       sessions;      /* number of sessions to support   */         
 tpipe_prfx_t      tpipe_prefix;  /* first part of tpipe NAME        */           
   /* The following fields are used by otma_send_async API.          */         

 tpipe_name_t      tpipe;         /* User tpipe Name.                */
 tran_name_t       trans;         /* IMS Trancode or CMD.            */         
 racf_uid_t        user_name;     /* RACF UserID.                    */         
 racf_prf_t        user_prf;      /* RACF Groupname.                 */         
 lterm_name_t      lterm;         /* Input Lterm.                    */
 mod_name_t        modname;       /* Input Modname.                  */  
 otma_user_t       otma_data;     /* OTMA Userdata.                  */         
 char             send_buf[BUFFER_LEN];
int long          buffer_length = 0;     /* Send Buffer length.        */
unsigned char error_message_text[120]; /*  IMS error msg field -     */
                                    /* A place to receive any IMS      */         
                                  /* DFS error messages.             */         
 unsigned char *error_message = (unsigned char*)&error_message_text;            
                                  /* a pointer to which is parameter */         
                                  /* on send_receive.                */         
 otma_profile2_t   send_options;  /* Send Special Options.           */         

   /* The following fields are used by otma_receive_async API.       */         

 lterm_name_t      rec_lterm;     /* Output Lterm.                   */        
 mod_name_t        rec_modname;   /* Output Modname.                 */         
 otma_user_t       rec_otma_data; /* OTMA Userdata.                  */         
 char          rec_buf[BUFFER_LEN];                                             
 int long      rec_buffer_len = BUFFER_LEN;                                     
 long int      rec_data_len = 0;                                                
 otma_profile3_t   rec_options;   /* Receive Special Options.        */         

/*********************************************************************/         
/*  The callable interface makes use of z/OS Event Control Blocks.   */         
/*  Any language which call the interface must deal with this.       */         
/*********************************************************************/         
                                                                                
 unsigned long  *(ecb_list[2]);        /* z/OS pause ecb list        */
 unsigned long **pecb_list;                                                     
                                                                                
 ecb_t         ecbOPEN   = 0L;     /* ecb to be posted by OTMA API   */         
 ecb_t         ecbIO     = 0L;     /* ecb to be posted by OTMA API   */         
 ecb_t         signal    = 0L;     /* ecb to be posted by C runtime  */         

 ecb_list[0] = (unsigned long *) &(signal); /* post by C signal      */       
 ecb_list[1] = (unsigned long *)            /* post by OTMA          */ 
               ((unsigned long)&(ecbOPEN) |                                  
               (unsigned long)0x80000000);  /* end of list           */         
 pecb_list   = &ecb_list[0];                /* pointer to list       */
                                            /* define callable I/F   */         

/*********************************************************************/         
/*  Local Variables                                                  */         
/*********************************************************************/         

 long int         retsave;        /* Return code save area           */         
int           iterations;     /* Number of iterations to use     */
int           loop_count;     /* Number of iterations used       */
int            compare_result; /* Return Code result of the      */
                               /* comparison for buffers.         */  
                                                                                
/*********************************************************************/         
/*  Local Constants                                                  */         
/*********************************************************************/         
                                                                                
 #define BUFFER_LEN  4096          /* Set our buffer sizes          */           
 #define NUM_BUFFER  80            /* Set the number of buffers     */
 #define GROUP_NAME  "HARRY"       /* Set XCF group name to join    */           
 char    temp_buf[NUM_BUFFER];     /* Swapping buffer               */
 char    compare_buf[NUM_BUFFER + 1]; /* Compare buffer             */                                                                                            
 FILE * stream;                                                                 
 int num;       /* number of characters read from stream */                 
                                                                               
/*******************************************************************/         
/* To support test functions - names of parms in order to pring   */
/* the parms out for documentation.                                 */        
/*******************************************************************/         
                                                                                
char * argdefs[10]={"Program Name",  /* 1                   */                 
                     "Server Name",   /* 2                   */                 
                     "Client Name",   /* 3                   */                 
                     "Transaction",   /* 4                   */                 
                     "User Name  ",   /* 5                   */                 
                     "User Group ",   /* 6                   */                 
                     "Lterm      ",   /* 7                   */                 
                     "Mod Name   ",   /* 8                   */                 
                     "OTMA Data  ",   /* 9                   */                 
                     "Iterations ",   /* 10                  */                 
                     };                                                         
                                                                                
/*******************************************************************/         
/*  Declare an array of compare file ddnames to                    */         
/*  compare actual output received with expected output.           */         
/*******************************************************************/         
                                                                                
 char * infiledd[4]={"DD:COMPAR0",        /* 1                 */
                       "DD:COMPAR1" ,        /* 2                  */            
                     "DD:COMPAR2" ,       /* 3                 */  
                        "DD:COMPAR3" ,         /* 4                   */             
                     };                                                         
                                                                                
/*******************************************************************/         
/*  Declare an array of send file ddnames to                       */         
/*  send application data to OTMA.                                 */         
/*******************************************************************/         
                                                                                
 char * sndfiledd[4]= {"DD:SENDBUF0",       /* 1                   */
                       "DD:SENDBUF1" ,      /* 2                   */
                       "DD:SENDBUF2" ,      /* 3                   */
                          "DD:SENDBUF3" ,       /* 4                    */          
                      };                                                        
                                                                                
                                                                                
/*******************************************************************/         
/*  Declare an array of tpipe names ddnames for the                */         
/*  otma_send_async API.                                           */         
/*******************************************************************/         
                                                                                
 char * tpipefiledd[4]= {"DD:TPIPBUF0",    /* 1                   */            
                         "DD:TPIPBUF1" ,   /* 2                   */            
                         "DD:TPIPBUF2" ,   /* 3                   */            
                         "DD:TPIPBUF3" ,   /* 4                   */            
                      };                                                        
                                                                                
/*******************************************************************/          
/* Begin Test Case...                                              */          
/* Anounce the startup of the test program.                        */         
/*******************************************************************/          
   printf("OTMCI02 Run Date: %s Run Time: %s\n" ,__DATE__,__TIME__ );           
                                                                                
/*******************************************************************/
/* Process parms/command line arguments.                           */
/*                                                                 */
/* Note:  If not a parameter is not used, then "NONE" is used in   */
/*        its place.                                               */
/*                                                                 */
/*******************************************************************/         
                                                                                
  /* First, print the parameters. */                                                          
  printf("Invocation parameters = \n");                                         
   for (i=1 ; i<(min(11,argc));i++)                                             
   {                                                                            
     printf("%d   %s = ", i, argdefs[i]);                                       
     printf("%s.\n", argv[i]);                                                  
   }                                                                            
                                                                                
   printf("\n");                                                                
  
   if (argc>1 && strcmp(argv[1],"NONE") != 0) 
     splat( srv_name, argv[1])             /* Server Name.       */            
   else                                                                         
     splat( srv_name, "IMS61CR1");         /* Hard coded default */             
   if (argc>2 && strcmp(argv[2],"NONE") != 0)                                   
     splat( clt_name, argv[2])             /* Client name        */             
   else                                                                         
     splat( clt_name, "XCFTEST"  );        /* Hard coded default */             
   if (argc>3 && strcmp(argv[3],"NONE") != 0)                                   
     splat( trans, argv[3])                /* IMS Tran/Cmd to use*/
   else                                                                         
     splat( trans, "");                    /* Hard coded default */             
   if (argc>4 && strcmp(argv[4],"NONE") != 0)                                   
     splat( user_name, argv[4])            /* RACF Username      */             
   else                                                                         
     splat( user_name, "");                /* Hard coded default */             
   if (argc>5 && strcmp(argv[5],"NONE") != 0)                                   
     splat( user_prf, argv[5])             /* RACF Group ID      */             
   else                                                                         
     splat( user_prf, "" );                /* Hard coded default */             
   if (argc>6 && strcmp(argv[6],"NONE") != 0)                                   
     splat( lterm , argv[6])               /* Lterm to use       */             
   else                                                                         
     splat( lterm , "" );                  /* Hard coded default */             
   if (argc>7 && strcmp(argv[7],"NONE") != 0)                                   
     splat( modname , argv[7])             /* ModName to use     */             
   else                                                                         
     splat( modname , "" );                /* Hard coded default */             
   if (argc>8 && strcmp(argv[8],"NONE") != 0)                                   
     splat( otma_data, argv[8])            /* OTMAData to use    */             
   else                                                                         
     splat( otma_data, "" );               /* Hard coded default */             
   if (argc>9 && strcmp(argv[9],"NONE") != 0)                                   
     iterations = atoi(argv[9]);           /* Loop count         */              
   else                                                                         
     iterations = 1;                       /* Hard coded default */             
                                                                                
   /* -----------------------------------------------------------*/             
   /* Open the file with the ddname SENDBUF0 supplied in the     */             
   /* JCL which invoked this C driver.  Then read the file into  */             
   /* temp_buf.                                                  */             
   /* -----------------------------------------------------------*/             
                                                                                
   if (( stream = fopen("DD:SENDBUF0","rb")) != NULL )                          
   {                                                                            
     num = fread( temp_buf, sizeof( char ), NUM_BUFFER, stream );               
     if (num == NUM_BUFFER) {                                                   
       printf( "Number of characters read = %i\n", num );                       
       fclose( stream );                                                        
     }                                                                          
     else {                                                                     
       if ( ferror(stream) )                                                    
         printf( "Error reading DDNAME sendbuf0/n");                            
       else if ( feof(stream)) {                                                
         printf( "EOF found\n" );                                               
         printf( "Number of characters read %d\n", num );                       
         printf( "temp_buf = %.*s\n", num, temp_buf);                           
         fclose( stream );                                                      
       }                                                                        
     }                                                                          
   }                                                                            
   else                                                                         
     printf( "ERROR opening DDNAME sendbuf0/n" );                               
                                                                                
   /*-----------------------------------------------------------*/             
   /* Initialize parameters for the otma_create and otma_open   */             
   /* APIs.                                                     */             
   /*-----------------------------------------------------------*/             
                                                                                
   splat( grp_name,GROUP_NAME );               /* XCF Group Name     */         
   splat( tpipe_prefix,"TPAS" );               /* XCF Group Name     */         
   strcat(send_buf, temp_buf );       /* Copy temp_buf into send_buf */         
   strcat(send_buf, " " );            /* add a blank for strlen      */         
   buffer_length = strlen(send_buf);                                            
                                                                                
  /*******************************************************************/         
  /* Example of setting up parms to Open the XCF Link                */         
  /*******************************************************************/         
                                                                                
    retrsn.ret    = -1;                                                         
    retrsn.rsn[0] = -1;                                                         
    retrsn.rsn[1] = -1;                                                         
    retrsn.rsn[2] = -1;                                                         
    retrsn.rsn[3] = -1;                                                         
    r             =  0;                                                         
    sessions      = 10;    /* OTMA supports multiple parallel        */         
                           /* sessions (TPIPES) How many do you want?*/         
                                                                                
  /*******************************************************************/         
  /*BEGIN:                                                           */         
  /* We have a CREATE function to set up storage and                 */         
  /* an OPEN function to start the protocol.                         */         
  /* If you don't need to customize the environment you can start    */         
  /* with the OPEN function, the CREATE will be done by OPEN.        */         
  /*******************************************************************/         
                                                                                
    otma_create(&anchor,      /* (out) ptr to addr to receive ancho*/           
           &retrsn,           /* (out) return code                 */           
           (ecb_t *) &ecbOPEN,/* not posted by create but stored   */           
                                                                                
           &grp_name,         /* (in) ptr to valid groupname       */           
           &clt_name,         /* (in) Our member name              */           
           &srv_name,         /* (in) Our server name              */           
                                                                                
           &sessions,         /* (in) number of sessions to support*/           
           &tpipe_prefix      /* (in) first part of tpipe name     */           
           );                                                                   
                                                                                
     printf("OTMA_CREATE issued. ret = %d rsn = %.8x,%.8x,%.8x,%.8x\n"          
            "  anchor is at %.8x.\n",                                           
            retrsn.ret,                                                         
            retrsn.rsn[0],                                                      
            retrsn.rsn[1],                                                      
            retrsn.rsn[2],                                                      
            retrsn.rsn[3],                                                      
            anchor);                                                            
                                                                                
                                                                                
   printf("-\n");                                                               
                                                                                
                                                                                
  /*******************************************************************/         
  /*  Time to try to connect to IMS                                  */         
  /*******************************************************************/         
                                                                                
   /* ___start XCF connection_____________________________ */                   
                                                                                
    otma_open(&anchor,        /* out ptr to addr to receive anchor */           
           &retrsn,           /* out return code                   */           
           (ecb_t *)&ecbOPEN, /* out posted by open if failure     */           
                              /*     else posted by exit pgm       */           
           &grp_name,         /* in ptr to valid XCF groupname     */           
           &clt_name,         /* in Our member name                */           
           &srv_name,         /* in Our server name                */           
                                                                                
           &sessions,         /* in number of sessions to support  */           
           &tpipe_prefix      /* in first part of tpipe name       */           
           );                                                                   
                                                                                
     printf("OTMA_OPEN issued. ret = %.8x rsn = %.8x,%.8x,%.8x,%.8x\n"          
            " Waiting for ecb at %.8x.=%.8x.\n",                                
            retrsn.ret,                                                         
            retrsn.rsn[1],                                                      
            retrsn.rsn[2],                                                      
            retrsn.rsn[3],                                                      
            ecb_list[1],                                                        
            *ecb_list[1]                                                        
            );                                                                  
                                                                                
   printf("-\n");                                                               
                                                                                
 /* ---------------------------------------------------------------- */         
 /* Here we wait for Open to signal complete                         */         
 /* ---------------------------------------------------------------- */         
     DFSYCWAT(ecb_list[1]);   /* WAIT on ecb                 */                 
                                                                                
      printf("OTMA_OPEN done. ret = %.8x rsn = %.8x,%.8x,%.8x,%.8x \n"          
             "\nEcb at %.8x.= %.8x.\n",                                         
             retrsn.ret,                                                        
             retrsn.rsn[0],                                                     
             retrsn.rsn[1],                                                     
             retrsn.rsn[2],                                                     
             retrsn.rsn[3],                                                     
             ecb_list[1], *ecb_list[1]                                          
             );                                                                 
                                                                                
      printf("Local Area Anchor at %8.8X = %8.8X\n",                            
                  &anchor, anchor);                                             
                                                                                
                                                                                
   /* -----------------------------------------------------------*/             
   /* The post code from open indicates success or failure       */             
   /* -----------------------------------------------------------*/             
      if (0!=(0x00ffffff & ecbOPEN))                                            
        {                                                                       
          printf("OPEN_OTMA ecb is posted failure.\n");                         
          return(retrsn.rsn[0]);                                                
        }                                                                       
                                                                                
   /**************************************************************/             
   /* This is the loop that sends and receives data.             */             
   /*                                                            */             
   /* This test program can iterate with multiple calls here.    */             
   /**************************************************************/             
                                                                                
  for (loop_count = 0 ; loop_count<iterations ; loop_count++)                   
  {                                                                             

   /* Change the environment to wait for ecbIO                */
   ecbIO = 0;                            /* clear ecb for reuse  */         
   ecb_list[1] = (unsigned long *)       /* posted by OTMA       */             
                 ((unsigned long)&(ecbIO) |                                  
                 (unsigned long)0x80000000);  /* end of list     */         
                                                                                
    if (loop_count != 0)                                                        
     {                                                                          
                                                                                
      /* -----------------------------------------------------------*/          
      /* If looping more than once open the next file to send       */          
      /* and read it into the send_buf.                             */          
      /* -----------------------------------------------------------*/          
                                                                                
      if (( stream = fopen(sndfiledd[loop_count],"rb")) != NULL )               
       {                                                                        
        num = fread( temp_buf, sizeof( char ), NUM_BUFFER, stream );            
        if (num == NUM_BUFFER) {                                                
          fclose( stream );                                                     
        }                                                                       
        else {                                                                  
         if ( ferror(stream) )                                                  
          printf( "Error opening file              
          else if ( feof(stream)) {                                             
            printf( "EOF found\n" );                                            
            printf( "Number of characters read %d\n", num );                    
            printf( "temp_buf = %.*s\n", temp_buf);                             
            fclose( stream );                                                   
          }                                                                     
        }                                                                       
       }                                                                        
      else                                                                      
       printf( "Error opening file %s\n", sndfiledd[loop_count]);               
                                                                                
                                                                                
      /*  Put data in to Send Buffer.  */                                  
      memset(error_message_text ,0, sizeof(error_message_text));                
      memset(send_buf ,0, sizeof(send_buf));                                    
      strcat(send_buf, temp_buf );                                              
      strcat(send_buf, " " );                                                   
      buffer_length = strlen(send_buf);                                         
                                                                                
     }  /* end if loop_count != 0    */                                         
                                                                                
      /* -----------------------------------------------------------*/          
      /* If looping more than once open the next tpipe to use       */          
      /* and read it into the tpipe.                                */          
      /* -----------------------------------------------------------*/          
                                                                                
      if (( stream = fopen(tpipefiledd[loop_count],"rb")) != NULL )             
       {                                                                        
        num = fread( temp_buf, sizeof( char ), NUM_BUFFER, stream );            
        if (num == NUM_BUFFER) {                                                
          fclose( stream );                                                     
        }                                                                       
        else {                                                                  
         if ( ferror(stream) )                                                  
          printf( "Error opening file              
          else if ( feof(stream)) {                                             
            printf( "EOF found\n" );                                            
            printf( "Number of characters read %d\n", num );                    
            printf( "temp_buf = %.*s\n", temp_buf);                             
            fclose( stream );                                                   
          }                                                                     
        }                                                                       
       }                                                                        
      else                                                                      
       printf( "Error opening file %s\n", sndfiledd[loop_count]);               
                                                                                
      memcpy(tpipe, temp_buf, 8);                                               
                                                                                
                                                                                
    /* Print announcement of send API.    */                                    
    printf("-\n-\n- Iteration #%d  Send API ---------------\n-\n",              
            loop_count+1);                                                      
    printf("tpipe Name = %.8s.\n", tpipe);                                      
    printf("Transaction = %.8s.\n", trans);                                     
    printf("RACF UserID = %.8s.\n", user_name);                                 
    printf("RACF Group = %.8s.\n", user_prf);                                   
    printf("Lterm = %.8s.\n", lterm );                                          
    printf("Modname = %.8s.\n", modname );                                      
    printf("OTMA Data = %.50s.\n", otma_data );                                 
    printf("Send buf = %s.\n", send_buf);                                       
    printf("Send buf at %.8x.\n", &send_buf);                                   
    printf ("Buffer length = %d.\n", buffer_length);                            
    printf ("Waiting for ecb at %.8x.=%.8x.\n", ecb_list[1],                    
            *ecb_list[1]);                                                      
                                                                                
      otma_send_async(                                                          
                     &anchor,          /* (in)  anchor block         */         
                     &retrsn,          /* (out) return status        */         
                     &ecbIO,           /* (out) ecb address          */         
                                                                                
                     &tpipe,           /* (in)  user tpipe name      */         
                     &trans,           /* (in)  IMS trancode or cmd  */         
                     &user_name,       /* (in)  RACF userid          */         
                     &user_prf,        /* (in)  RACF group name      */         
                     &lterm,           /* (in)  logical terminal     */         
                     &modname,         /* (in)  module name          */         
                     &otma_data,       /* (in)  OTMA user data       */         
                                                                                
   (unsigned char *) &send_buf,        /* (in)  send buffer          */         
                     &buffer_length,   /* (in)  size of send buffer  */         
                     0,                /* (in)  send_segment_list    */         
                     &error_message,   /* (out) IMS Error msg.       */         
                    &send_options);    /* (in)  send special options */          
                                                                                
   DFSYCWAT(ecb_list[1]);              /* WAIT on ecb                */          

   /* Print results of send API.    */                                         
  printf("OTMA_SEND_ASYNC done. ret = %.8x rsn = %.8x,%.8x,%.8x,%.8x\n"         
         "Ecb at %.8x.=%.8x.\n",                                                
             retrsn.ret,                                                        
             retrsn.rsn[0],                                                     
             retrsn.rsn[1],                                                     
             retrsn.rsn[2],                                                     
             retrsn.rsn[3],                                                     
             ecb_list[1],                                                       
             *ecb_list[1]                                                       
            );                                                                  
                                                                                
    retsave = retrsn.ret;    /*  Save otma_send_async Return Code.  */          
                                                                                
                                                                                
    /* Error Processing for OTMA_SEND_ASYNC API.          */                    
     if (retrsn.ret != 0)                                                       
     {                                                                          
                                                                                
      /* ___Error path Free allocated session _____________________ */          
      printf("-Error send_async API retrsn.ret=               
      printf( "Error message = %s\n", error_message );                          
                                                                                
  if (( stream = fopen(infiledd[loop_count],"rb")) != NULL )                    
  {                                                                             
    num = fread( compare_buf, sizeof( char ), NUM_BUFFER, stream );             
    if (num == NUM_BUFFER) {  /* fread success */                               
      printf( "Compare_buf = %.80s.\n", compare_buf );                          
      printf( "Error_buf   = %.80s.\n", error_message );                        
      fclose( stream );                                                         
      compare_result = memc( compare_buf, error_message );                      
      printf( "compare_result =                           
  if (compare_result != 0)                                                      
    return(compare_result);        /* Exit if NO COMPARE    */                  
    }                                                                           
    else {  /* fread() failed */                                                
      if ( ferror(stream) )         /* possibility 1 */                         
        printf( "Error reading file %s\n", infiledd[loop_count]);               
      else if ( feof(stream)) {     /* possibility 2 */                         
        printf( "EOF found\n" );                                                
        printf( "Number of characters read %d\n", num );                        
        printf( "Receive compare_buf = %.*s\n", num, compare_buf);              
      }                                                                         
    }                                                                           
  }                                                                             
  else                                                                          
    printf( "Error opening file %s\n", infiledd[loop_count]);                   
                                                                                
      printf("-\n");                                                            
                                                                                
      /* ___Sever IMS connection ____________________________ */                
      printf("-\n");                                                            
      otma_close(                                                               
                     & anchor,        /* (in,out) tr to otma anchor */          
                     & retrsn         /* (out) rc,reason (1-4)      */          
              );                                                                
                                                                                
      printf("OTMA_CLOSE done. ret = %.8x rsn = %.8x,%.8x,%.8x,%.8x\n",         
             retrsn.ret,                                                        
             retrsn.rsn[0],                                                     
             retrsn.rsn[1],                                                     
             retrsn.rsn[2],                                                     
             retrsn.rsn[3]                                                      
             );                                                                 
                                                                                
      return (retsave);      /* EXIT with receive API return code */            
     }                                                                          
                                                                                
  /* Initialize otma_receive_async parameters.            */
   splat( rec_lterm , "" );                                                   
   splat( rec_modname , "" );                                                 
   splat( rec_otma_data , "" );                                               
   ecbIO = 0;                            /* clear ecb for reuse      */
   ecb_list[1] = (unsigned long *)       /* posted by OTMA           */
   ((unsigned long)&(ecbIO) |                                  
                     (unsigned long)0x80000000);  /* end of list     */         
                                                                                
    /* Print announcement of receive API.    */                                 
    printf("-\n-\n- Iteration #%d  Receive API ---------------\n-\n",           
            loop_count+1);                                                      
    printf("tpipe Name = %.8s.\n", tpipe);                                      
    printf("Waiting for ecb at %.8x=%.8x.\n", ecb_list[1],                      
            *ecb_list[1]);                                                      
                                                                                
     otma_receive_async(                                                        
                      &anchor,          /* (in)  anchor block         */        
                      &retrsn,          /* (out) return status        */        
                      &ecbIO,           /* (out) ecb address          */        
                                                                                
                      &tpipe,           /* (in)  user tpipe name      */        
                      &rec_lterm,       /* (in)  logical terminal     */        
                      &rec_modname,     /* (in)  module name          */        
                      &rec_otma_data,   /* (in)  OTMA user data       */        
                                                                                
    (unsigned char *) &rec_buf,         /* (out) Receive buffer       */        
                      &rec_buffer_len,  /* (in)  size of rec buffer   */        
                      &rec_data_len,    /* (in)  send_segment_list    */        
                      0,                /* (in/out) rec multiple seg  */        
                      &rec_options);    /* (in)  rec special options  */        
                                                                                
 DFSYCWAT(ecb_list[1]);                 /* WAIT on ecb                */                                                                                  
    /* Print results of receive API.    */                                      
   printf("OTMA_REC_ASYNC done. ret = %.8x rsn = %.8x,%.8x,%.8x,%.8x\n"         
            "Ecb at %.8x.=%.8x.\n",                                             
              retrsn.ret,                                                       
              retrsn.rsn[0],                                                    
              retrsn.rsn[1],                                                    
              retrsn.rsn[2],                                                    
              retrsn.rsn[3],                                                    
              ecb_list[1],                                                      
              *ecb_list[1]);                                                    
    printf("Lterm = %.8s.\n", rec_lterm );                                      
    printf("Modname = %.8s.\n", rec_modname );                                  
    printf("OTMA Data = %.50s.\n", rec_otma_data );                             
    printf("Receive buf = %.80s.\n", rec_buf);                                  
    printf("Receive buf at %.8x.\n", &rec_buf);                                 
    printf("Data length = %d.\n", rec_data_len);                                
    printf("Buffer length = %d.\n", rec_buffer_len);                            
                                                                                
                                                                                
    retsave = retrsn.ret;    /* Save otma_receive_async Return Code.  */        
                                                                                
    /* Error Processing for OTMA_RECEIVE_ASYNC API.          */                 
     if (retrsn.ret != 0)                                                       
     {                                                                          
                                                                                
      /* ___Error path Free allocated session _____________________ */          
      printf("-error path retrsn.ret=                         
      printf("-\n");                                                            
                                                                                
      /* ___Sever IMS connection ____________________________ */                
      printf("-\n");                                                            
      otma_close(                                                               
                     & anchor,        /* (in,out) tr to otma anchor */          
                     & retrsn         /* (out) rc,reason (1-4)      */          
              );                                                                
                                                                                
      printf("OTMA_CLOSE done. ret = %.8x rsn = %.8x,%.8x,%.8x,%.8x\n",         
             retrsn.ret,                                                        
             retrsn.rsn[0],                                                     
             retrsn.rsn[1],                                                     
             retrsn.rsn[2],                                                     
             retrsn.rsn[3]                                                      
             );                                                                 
                                                                                
      return (retsave);      /* EXIT with receive API return code */            
     }                                                                          
                                                                                
                                                                                
   /* -----------------------------------------------------------*/             
   /*  Open the compare file containing the expected output      */             
   /*  of the receive buffer.  Compare the expected output       */             
   /*  with the actual output and return the result.             */             
   /* -----------------------------------------------------------*/             
                                                                                
    printf("-\n-\n- Iteration #%d  Data Validation -----------\n-\n",           
            loop_count+1);                                                      
                                                                                
  if (( stream = fopen(infiledd[loop_count],"rb")) != NULL )                    
  {                                                                             
    num = fread( compare_buf, sizeof( char ), NUM_BUFFER, stream );             
    if (num == NUM_BUFFER) {  /* fread success */                               
      printf( "compare_buf = %.80s.\n", compare_buf );                          
      printf( "    rec_buf = %.80s.\n", rec_buf );                              
      fclose( stream );                                                         
      compare_result = memc( compare_buf, rec_buf );                            
      printf( "compare_result =                           
  if (compare_result != 0)                                                      
    return(compare_result);        /* Exit if NO COMPARE    */                  
    }                                                                           
    else {  /* fread() failed */                                                
      if ( ferror(stream) )         /* possibility 1 */                         
        printf( "Error reading file %s\n", infiledd[loop_count]);               
      else if ( feof(stream)) {     /* possibility 2 */                         
        printf( "EOF found\n" );                                                
        printf( "Number of characters read %d\n", num );                        
        printf( "Receive compare_buf = %.*s\n", num, compare_buf);              
      }                                                                         
    }                                                                           
  }                                                                             
  else                                                                          
    printf( "Error opening file %s\n", infiledd[loop_count]);                   
                                                                                
   memset(rec_buf ,' ', sizeof(rec_buf));                                       
                                                                                
  printf( "End of loop \n" );                                                   
}      /* end of loop */                                                       
                                                                                
                                                                                
    printf("-\n");                                                              
                                                                                
   /*****************************************************************/          
   /* Finally, CLOSE severs the connection with IMS and frees the   */          
   /* Storage used by the OTMA API.                                 */          
   /* This will be done at job-step termination but its untidy.     */          
   /*****************************************************************/          
                                                                                
    otma_close(                                                                 
                     & anchor,        /* (in,out) ptr to otma anchor */         
                     & retrsn         /* (out)  rc,reason (1-4)      */         
              );                                                                
    printf("OTMA_CLOSE done. ret = %.8x rsn = %.8x,%.8x,%.8x,%.8x \n",          
            retrsn.ret,                                                         
            retrsn.rsn[0],                                                      
            retrsn.rsn[1],                                                      
            retrsn.rsn[2],                                                      
            retrsn.rsn[3]                                                       
            );                                                                  
                                                                                
    return (compare_result);      /* We're done */                              
} /* end of main */                                                             
                                                                                
/*===================================================================*/         
/*      Subroutine to compare expected results(compare_buf)          */         
/*      with actual results(err_msg) the "|" is used to signify      */         
/*      an ignore compare and "?" is used to mark the end of string. */         
/* Note: Compare starts using an index i=1 ie. the 2nd character     */         
/*       because the 1st character was blanked out. ( NL x'15' )     */         
/*===================================================================*/         
                                                                                
                                                                                
int memc(char *comp_buf, char *rec_buf1)                                        
{                                                                               
                                                                                
 int j;                                                                         
 int i;                                                                         
                                                                                
  j = 0;                                                                        
                                                                                
  for (i=1;                                                                     
      ( (j==0) && (comp_buf[i] != '?') );                                       
       i++ )                                                                    
    {                                                                           
      if( comp_buf[i] != '|' )                   /* Ignore compare  */
      {                                                                         
        if( comp_buf[i] != rec_buf1[i])          /* compare ok ?    */
        {                                                                       
          j++;                                   /* No              */          
          printf( "MISCOMPARE !!!   \n" );                                      
          printf( "comp_buf[%d] = %c\n", i, comp_buf[i] );                      
          printf( "rec_buf1[%d] = %c\n", i, rec_buf1[i] );                      
        }                                                                       
        else                                                                    
          ;                                                                     
      }                                                                         
      else                                                                      
        ;                                       /* Else null        */   
    }                                                                           
                                                                                
 return (j);                                                                    
}