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 */
<erm, /* (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);
}