DSN8ED2
Use the Instrumentation Facility Interface (IFI) to process a Db2 command which has been passed from DSN8ED1, the requester program.
/******************************************************************** 00010000
* Module name = DSN8ED2 (sample program) * 00020000
* * 00030000
* Descriptive name = Stored procedure result set server program * 00040000
* * 00050000
* LICENSED MATERIALS - PROPERTY OF IBM * 00060000
* 5675-DB2 * 00070000
* (C) COPYRIGHT 1997, 2000 IBM CORP. ALL RIGHTS RESERVED. * 00080000
* * 00090000
* STATUS = VERSION 7 * 00100000
* * 00110000
* Function: * 00120000
* Use the Instrumentation Facility Interface (IFI) to process * 00130000
* a DB2 command which has been passed from DSN8ED1, the * 00140000
* requester program. Load the responses to a temporary DB2 * 00150000
* table and return them as a result set. * 00160000
* * 00170000
* Notes: * 00180000
* Dependencies = * 00190000
* 1. Must be linked and run under LE/370 * 00200000
* 2. Requires global temporary table DSN8.DSN8ED2_RS_TBL * 00202990
* (created by sample job DSNTEJ6T) * 00205980
* * 00210000
* Restrictions = * 00220000
* 1. The Instrumentation Facility Communication Area * 00230000
* (IFCA) contains information regarding the success * 00240000
* of the call and provides feedback. * 00250000
* This area must be maintained to include any changes * 00260000
* to the mapping macro DSNDIFCA. * 00270000
* * 00280000
* 2. A command may be no more than 4096 bytes. * 00290000
* * 00300000
* Module type = C program * 00310000
* Processor = * 00320000
* ADMF precompiler * 00330000
* C/370 * 00340000
* Module size = See linkedit output * 00350000
* Attributes = Not re-entrant nor re-usable * 00360000
* * 00370000
* Entry Point = CEESTART (LE/370) * 00380000
* Purpose = See function * 00390000
* Linkage = SIMPLE WITH NULLS * 00400000
* Invoked via EXEC SQL call * 00410000
* Input = Parameters explicitly passed to this function: * 00420000
* Symbolic label/name = ARGV[1] (puts inputcmd) * 00430000
* Description = DB2 command to be processed by IFI. * 00440000
* Input statements from this parameter * 00450000
* will be passed to the text_or_command * 00460000
* field of the output_area of the IFI * 00470000
* utility for processing. * 00480000
* * 00490000
* Output = Parameters explicitly returned: * 00500000
* Symbolic label/name = ARGV[2] (gets ifca_ret_hex) * 00510000
* - IFI return code, in hex * 00520000
* Symbolic label/name = ARGV[3] (gets ifca_res_hex) * 00530000
* - IFI reason code, in hex * 00540000
* Symbolic label/name = ARGV[4] (gets xs_bytes_hex) * 00550000
* - Excess bytes not returned, in hex * 00560000
* Symbolic label/name = ARGV[5] (gets errmsg_buf) * 00570000
* - Formatted SQL error messages * 00580000
* Symbolic label/name = ARGV[6] (gets indvar) * 00590000
* - DB2 indicator variables * 00600000
* * 00610000
* Output = Result set returned: * 00620000
* Result set cursor name = DSN8ED2_RS_CSR * 00630000
* - Formatted responses from IFI for input command * 00640000
* * 00650000
* Exit normal = * 00660000
* No errors were found in the passed DB2 command and no * 00670000
* errors occurred during processing. * 00680000
* * 00690000
* Normal messages = * 00700000
* * 00710000
* Exit-error = * 00720000
* Errors were found in the passed DB2 command or occurred * 00730000
* during processing. * 00740000
* * 00750000
* Return codes: n/a * 00760000
* * 00770000
* Error messages = see under output * 00780000
* * 00790000
* External references = * 00800000
* Routines/services = none * 00810000
* Data areas = none * 00820000
* Control blocks = none * 00830000
* * 00840000
* Pseudocode = * 00850000
* DSN8ED2: Main * 00860000
* - get the passed DB2 command. * 00870000
* - calculate the return area size for command requests. * 00880000
* - allocate the requested return area. * 00890000
* - format the output area with the requested command. * 00900000
* - issue the command request to IFI. * 00910000
* - create the temporary table to hold the result set. * 00920000
* - call sql_error if an unexpected SQLCODE is encountered * 00930000
* - extract the responses from the IFI return buffer and * 00940000
* insert them to the result set table. * 00950000
* - call sql_error if an unexpected SQLCODE is encountered * 00960000
* - open the cursor to the result set table and exit. * 00970000
* - call sql_error if an unexpected SQLCODE is encountered * 00980000
* End DSN8ED2 * 00990000
* * 01000000
* sql_error * 01010000
* - invoke DSNTIAR to format the current SQL code and put the * 01020000
* messages to output parameter ARGV[5]. * 01030000
* - if DSNTIAR cannot detail the code, put the SQLCODE and the * 01040000
* SQLERRM to output parameter ARGV[5]. * 01050000
* End sql_error * 01060000
********************************************************************/ 01070000
01080000
01090000
/********************** C library definitions ***********************/ 01100000
#pragma runopts( plist(mvs) ) 01110000
#include <stdio.h> 01120000
#include <stdlib.h> 01130000
#include <string.h> 01140000
#pragma linkage( dsnwli,OS ) 01150000
01160000
/**************************** Constants *****************************/ 01170000
#define BLANK ' ' /* Buffer padding */ 01180000
#define BUFROWLN 80 /* Length of a report line */ 01190000
#define DATA_DIM 10 /* Number of message lines */ 01200000
#define HYPHEN '-' /* Hyphen */ 01210000
#define LINEFEED '\n' /* Linefeed character */ 01220000
#define NULLCHAR '\0' /* Null character */ 01230000
#define RETSEV 12 /* Severe error return code */ 01240000
#define RETURN_LEN 8320 /* Length of IFI return buffer*/ 01250000
01260000
/********************** Program Argument List ***********************/ 01270000
struct inp { /* Arg1 (in): Command stmt */ 01280000
short int incmlen; /* - Input stmt length */ 01290000
char incmtxt[4096]; /* - Input stmt text */ 01300000
} inputcmd; /* */ 01310000
struct inp *inpptr; /* Pointer to input struct */ 01320000
01330000
long int ifca_ret_hex; /* Arg2 (out): IFI return code*/ 01340000
long int ifca_res_hex; /* Arg3 (out): IFI reason code*/ 01350000
01360000
long int xs_bytes_hex; /* Arg4 (out): # records lost */ 01370000
01380000
char errmsg[DATA_DIM+1][BUFROWLN]; 01390000
/* Arg5 (out): error messages */ 01400000
01410000
short int locind[5]; /* Arg6 (out): indicator vars */ 01420000
01430000
/************************ Working variables *************************/ 01440000
char *parg1[]; /* Pointer to argument 1 */ 01450000
int *parg2; /* Pointer to argument 2 */ 01460000
int *parg3; /* Pointer to argument 3 */ 01470000
int *parg4; /* Pointer to argument 4 */ 01480000
char *parg5[][BUFROWLN]; /* Pointer to argument 5 */ 01490000
short int *parg6; /* Pointer to argument 6 */ 01500000
01510000
long int rc, lastrc; /* Return codes */ 01520000
01530000
/************************ DB2 Host Variables ************************/ 01540000
EXEC SQL BEGIN DECLARE SECTION; 01550000
long int rs_sequence; /* Result set data sequence */ 01560000
char rs_data[81]; /* Result set data buffer */ 01570000
/* - length is BUFROWLN+1 for */ 01580000
/* C NUL-terminator byte) */ 01590000
EXEC SQL END DECLARE SECTION; 01600000
01610000
/******************** DB2 SQL Communication Area ********************/ 01620000
EXEC SQL INCLUDE SQLCA; 01630000
01640000
/******************** DB2 SQL Cursor Declarations *******************/ 01650000
EXEC SQL DECLARE DSN8ED2_RS_CSR 01660000
CURSOR WITH RETURN WITH HOLD FOR 01670000
SELECT RS_SEQUENCE, RS_DATA 01680000
FROM DSN8.DSN8ED2_RS_TBL /* <- Created in job DSNTEJ6T */ 01690000
ORDER BY RS_SEQUENCE; 01700000
01710000
/********************************************************************/ 01720000
/*************************** main routine ***************************/ 01730000
/********************************************************************/ 01740000
int main( int argc, char *argv[] ) /* Argument count and list */ 01750000
{ 01760000
/*************************** Constants ****************************/ 01770000
01780000
char eye[4] /* Const for IFI eye catcher */ 01790000
= {'I','F','C','A'}; 01800000
char loc[4] /* Const for IFI location */ 01810000
= {'L','O','C','2'}; 01820000
01830000
/*********************** Working variables ************************/ 01840000
01850000
short int numfull; /* No. of lines in area passed*/ 01860000
/* from IFI that have BUFROWLN*/ 01870000
/* or more bytes */ 01880000
short int partrow; /* No. of lines in area passed*/ 01890000
/* from IFI that have less */ 01900000
/* than BUFROWLN bytes */ 01910000
01920000
short int i, j, k; /* Loop control vars */ 01930000
01940000
char *curbyte; /* Pointer to current byte in */ 01950000
/* return area */ 01960000
01970000
short int len_bin; /* Length of buffer, in binary*/ 01980000
char lenbyt1; /* 1st byte of length */ 01990000
char lenbyt2; /* 2nd byte of length */ 02000000
02010000
02020000
/*********************** IFI Argument List ************************/ 02030000
02040000
char function[9]; /* First parm for IFI call */ 02050000
02060000
/******************************************************************* 02070000
* IFCA - (Instrumentation Facility Communication Area) contains * 02080000
* information regarding the success of the call to IFI and * 02090000
* provides feedback information to the application program. * 02100000
* * 02110000
* WARNING: This area must be maintained to include any changes to * 02120000
* the mapping macro DSNDIFCA. * 02130000
*******************************************************************/ 02140000
02150000
typedef struct { /* Second parm for IFI call */ 02160000
short int lngth; /* Length of the IFCA, */ 02170000
/* including length field */ 02180000
short int unused1; /* Reserved */ 02190000
char eye_catcher[4]; /* Valid eye catcher of IFCA */ 02200000
/* used to verify IFCA block */ 02210000
char owner_id[4]; /* Used to establish ownership*/ 02220000
/* of an OPN destination */ 02230000
long int ifcarc1; /* Rtrn code for IFC API call */ 02240000
long int ifcarc2; /* Reason cd for IFC API call */ 02250000
long int bytes_moved; /* Bytes of recrd rtrnd by IFI*/ 02260000
long int excess_bytes; /* Bytes that did not fit */ 02270000
long int opn_writ_seq_num; /* Last OPN writer sequ numbr */ 02280000
/* rtrnd for a READA function*/ 02290000
long int num_recds_lost; /* Records lost indicator */ 02300000
char opn_name_for_reada[4];/* OPN nm used for READA requ */ 02310000
struct { /* Area with up to 8 OPN names*/ 02320000
short int opn_lngth; /* Length+4 of OPN names rtrnd*/ 02330000
short int unused2; /* Reserved */ 02340000
char array_opn_names[4][8]; 02350000
/* Area for OPN names returned*/ 02360000
} opn_names_area; 02370000
struct { /* Area with up to 8 trace nos*/ 02380000
short int trace_lngth; /* Length+4 of trace nos rtrnd*/ 02390000
short int unused3; /* Reserved */ 02400000
char array_trace_nos[2][8]; 02410000
/* Area for trace nos returned*/ 02420000
} trace_nos_area; 02430000
struct { /* Diagnosticd area */ 02440000
short int diagnos_lngth; /* Diagnostics length */ 02450000
short int unused4; /* Reserved */ 02460000
char diagnos_data[80]; /* Diagnostics data */ 02470000
} diagnos_area; 02480000
} ifca; /****** end IFCA typedef ******/ 02490000
02500000
ifca *pi; /* Pointer to IFCA structure */ 02510000
02520000
typedef struct { /* Third parm for IFI call */ 02530000
short int lngth; /* Length+4 of text or command*/ 02540000
short int unused; /* Reserved */ 02550000
char text_or_command[254]; /* Actual cmd or record text */ 02560000
} output_area; 02570000
02580000
output_area *po; /* Pointer to IFI output area */ 02590000
02600000
typedef struct { /* Fourth parm for IFI call */ 02610000
long int lngth; /* Length+4 of IFI return area*/ 02620000
char rtrn_buff[RETURN_LEN];/* IFI return area */ 02630000
} return_area; 02640000
02650000
return_area *pr; /* Pointer to IFI return area */ 02660000
02670000
/******************************************************************* 02680000
* initialize working variables * 02690000
*******************************************************************/ 02700000
rc = 0; /* Initialize return code */ 02710000
lastrc = 0; /* Initialize return code */ 02720000
02730000
for( i=0; i<DATA_DIM+1; i++ ) /* clear error message buffer */ 02740000
for( j=0; j<BUFROWLN; j++ ) 02750000
errmsg[i][j] = BLANK; 02760000
02770000
/******************************************************************* 02780000
* get input parameter (command for IFI) from caller * 02790000
*******************************************************************/ 02800000
parg1[1] = argv[1]; /* Command text from caller */ 02810000
curbyte = parg1[1]; /* Get pointer to input struct*/ 02820000
02830000
/******************************************************************* 02840000
* determine the length of the command text * 02850000
*******************************************************************/ 02860000
inputcmd.incmlen = 0; 02870000
i = 0; 02880000
while( *(curbyte) != NULLCHAR && i < 4096 ) 02890000
{ 02900000
inputcmd.incmtxt[i] = *curbyte; 02910000
i++; 02920000
curbyte++; 02930000
inputcmd.incmlen++; 02940000
} 02950000
02960000
/******************************************************************* 02970000
* initialize the IFI parameters * 02980000
*******************************************************************/ 02990000
strncpy( function,"COMMAND \0",9 ); /* Set constant */ 03000000
03010000
pi = malloc( sizeof(ifca) ); /* Point to IFCA structure */ 03020000
pi->lngth = sizeof(ifca); /* Note length of IFCA area */ 03030000
for(i=0; i<4; i++ ) 03040000
{ 03050000
pi->eye_catcher[i] = eye[i]; /* Initialize eye catcher */ 03060000
pi->owner_id[i] = loc[i]; /* DB2 Loc: 1=Local, 2=Remote */ 03070000
} 03080000
03090000
pr = malloc( sizeof(return_area) ); /* Point to IFI return area */ 03100000
for( i=0; i<RETURN_LEN; i++ ) 03110000
pr->rtrn_buff[i] = BLANK; /* Clear the return buffer */ 03120000
pr->lngth = RETURN_LEN; /* Length of return buffer */ 03130000
03140000
po = malloc( sizeof(output_area) ); /* Point to IFI command area */ 03150000
po->lngth = inputcmd.incmlen+4; /* Note length of command text*/ 03160000
for( i=0; i<254; i++ ) /* Copy in command */ 03170000
po->text_or_command[i] = inputcmd.incmtxt[i]; 03180000
03190000
/******************************************************************* 03200000
* make the IFI call via the DSNWLI macro * 03210000
*******************************************************************/ 03220000
dsnwli( function,pi,pr,po ); 03230000
03240000
/******************************************************************* 03250000
* copy IFI command status codes to output parms * 03260000
*******************************************************************/ 03270000
ifca_ret_hex = pi->ifcarc1; /* IFI Return code in binary */ 03280000
ifca_res_hex = pi->ifcarc2; /* IFI Reason code in binary */ 03290000
xs_bytes_hex = pi->excess_bytes; /* Bytes that did not fit */ 03300000
03310000
/******************************************************************* 03320000
* Extract records from the IFI return area and place them in a * 03330000
* table for transmission to the caller via a result set * 03340000
*******************************************************************/ 03350000
if( pi->bytes_moved != 0 ) /* If data was returned by IFI*/ 03360000
{ 03370000
/***************************************************************** 03380000
* First, clear any residue from the result set table * 03390000
*****************************************************************/ 03400000
EXEC SQL DELETE 03439990
FROM DSN8.DSN8ED2_RS_TBL; 03469980
if( SQLCODE != 0 /* 0 because everything is ok */ 03499970
& SQLCODE != +88 ) /* +88 because all rows del'd */ 03529960
sql_error( "*** SQL error when clearing temp table ..." ); 03559950
03620000
rs_sequence = 0; /* Init result set sequence no*/ 03630000
for( k=0; k<BUFROWLN; k++ ) /* Clear result set data var */ 03640000
rs_data[k] = BLANK; 03650000
03660000
/***************************************************************** 03670000
* The IFI return buffer contains one or more variable length * 03680000
* records. Each record consists of a 4-byte length component * 03690000
* followed by a text component. The length component contains * 03700000
* the length of the text component plus 4 to account for its * 03710000
* own length. * 03720000
****************************************************************** 03730000
* Extract the length of the 1st record in the buffer and sub- * 03740000
* tract 4 bytes to obtain the length of just the text portion. * 03750000
*****************************************************************/ 03760000
curbyte = &( pr->rtrn_buff[0] ); /* Point to 1st byte in buffer*/ 03770000
lenbyt1 = *(curbyte); /* Set 1st byte of length */ 03780000
lenbyt2 = *(curbyte+1); /* Set 2nd byte of length */ 03790000
03800000
len_bin = ( (short int)lenbyt1 ) * 10 + ( (short int)lenbyt2 ); 03810000
len_bin = len_bin - 4; /* Discount size of length fld*/ 03820000
03830000
/***************************************************************** 03840000
* For each IFI record returned, create one or more records of * 03850000
* length BUFROWLN and insert them to the result set table * 03860000
*****************************************************************/ 03870000
while( ( rc < RETSEV ) && (pi->bytes_moved - len_bin) > 2 ) 03880000
{ 03890000
curbyte = curbyte + 4; /* Update position in buffer */ 03900000
03910000
if( ((short int)( curbyte - &(pr->rtrn_buff[0]) ) + len_bin - 1) 03920000
> pi->bytes_moved ) 03930000
break; /* At end of buffer */ 03940000
03950000
numfull = len_bin / BUFROWLN; /* No. rows of BUFROWLN bytes */ 03960000
partrow = len_bin % BUFROWLN; /* No. of bytes leftover */ 03970000
03980000
/*************************************************************** 03990000
* Move all complete lines * 04000000
***************************************************************/ 04010000
if( numfull > 0 ) 04020000
for( j=0; j<numfull; j++ ) 04030000
{ 04040000
for( i=0; i<BUFROWLN; i++ ) /* Clear result set tbl buffer*/ 04050000
rs_data[i] = BLANK; 04060000
for( i=0; i<BUFROWLN; i++ ) 04070000
{ 04080000
rs_data[i] = *curbyte; /* Build result set table rec */ 04090000
curbyte++; /* Bump ptr into IFI rtrn buff*/ 04100000
} 04110000
04120000
rs_sequence++; /* Bump result set tbl sequ no*/ 04130000
EXEC SQL INSERT /* Insert to the table */ 04140000
INTO DSN8.DSN8ED2_RS_TBL 04150000
( RS_SEQUENCE,RS_DATA ) 04160000
VALUES(:rs_sequence,:rs_data ); 04170000
if( SQLCODE != 0 ) 04180000
sql_error( "*** SQL error when inserting full line ..." ); 04190000
} 04200000
04210000
/*************************************************************** 04220000
* Move leftover bytes to one last result set table record * 04230000
***************************************************************/ 04240000
if( rc < RETSEV && partrow > 0 ) 04250000
{ 04260000
for( i=0; i<BUFROWLN; i++ ) /* Clear result set tbl buffer*/ 04270000
rs_data[i] = BLANK; 04280000
for( i=0; i<partrow; i++ ) 04290000
{ 04300000
rs_data[i] = *curbyte; /* Build result set table rec */ 04310000
curbyte++; /* Bump ptr into IFI rtrn buff*/ 04320000
} 04330000
rs_data[i-1] = BLANK; /* Discard linefeed char */ 04340000
04350000
rs_sequence++; /* Bump result set tbl sequ no*/ 04360000
04370000
EXEC SQL INSERT /* Insert to the table */ 04380000
INTO DSN8.DSN8ED2_RS_TBL 04390000
( RS_SEQUENCE,RS_DATA ) 04400000
VALUES(:rs_sequence,:rs_data ); 04410000
if( SQLCODE != 0 ) 04420000
sql_error( "*** SQL error when inserting partial line ..." );04430000
} /* End-move partial line */ 04440000
04450000
/*************************************************************** 04460000
* Advance to next record in the IFI buffer, extract its length,* 04470000
* and subtract 4 bytes to get length of text portion * 04480000
***************************************************************/ 04490000
lenbyt1 = *(curbyte); /* Set 1st byte of length */ 04500000
lenbyt2 = *(curbyte+1); /* Set 2nd byte of length */ 04510000
04520000
len_bin = ( (short int)lenbyt1) * 10 + ((short int)lenbyt2 ); 04530000
len_bin = len_bin - 4; /* Discount for length field */ 04540000
04550000
} /* End of copying IFI return text to result set table */ 04560000
04570000
/***************************************************************** 04580000
* Open the cursor to the result set table on the way out * 04590000
*****************************************************************/ 04600000
if( rc < RETSEV ) 04610000
{ 04620000
EXEC SQL OPEN DSN8ED2_RS_CSR; 04630000
if( SQLCODE != 0 ) 04640000
sql_error( "*** SQL error when opening result set cursor ...");04650000
} 04660000
04670000
} /* End of if data was returned by IFI */ 04680000
04690000
/******************************************************************* 04700000
* Set output arguments and DB2 locator variables * 04710000
*******************************************************************/ 04720000
parg2 = (int *)argv[2]; /* locate and recast 2nd arg */ 04730000
*parg2 = ifca_ret_hex; /* assign it ifca return cd */ 04740000
locind[1] = 0; /* tell DB2 to transmit it */ 04750000
04760000
parg3 = (int *)argv[3]; /* locate and recast 3rd arg */ 04770000
*parg3 = ifca_res_hex; /* assign it ifca reason cd */ 04780000
locind[2] = 0; /* tell DB2 to transmit it */ 04790000
04800000
parg4 = (int *)argv[4]; /* locate and recast 4th arg */ 04810000
*parg4 = xs_bytes_hex; /* and assign it bytes lost */ 04820000
locind[3] = 0; /* tell DB2 to transmit it */ 04830000
04840000
if( errmsg[0][0] == BLANK ) /* if no error message exists*/ 04850000
locind[4] = -1; /* -tell DB2 not to send one */ 04860000
else /* otherwise copy it over and*/ 04870000
{ /* tell DB2 to transmit it */ 04880000
parg5[0][0] = argv[5]; /* -locate the 5th func arg */ 04890000
curbyte = parg5[0][0]; /* -set helper pointer */ 04900000
for( i=0; i<DATA_DIM+1; i++ ) /* -parse a row, looking for */ 04910000
{ /* the end of its msg text */ 04920000
j = 0; 04930000
while( errmsg[i][j] != NULLCHAR && j < BUFROWLN ) 04940000
{ 04950000
*curbyte = errmsg[i][j++]; /* -copy nonnull bytes */ 04960000
curbyte++; 04970000
} 04980000
errmsg[i][j] = LINEFEED; /* -add linefd to end of row */ 04990000
} /* End of for( i=0; i<DATA_DIM+1; i++ ) */ 05000000
05010000
*curbyte = NULLCHAR; /* -null-terminate the buffer*/ 05020000
locind[4] = 0; /* -tell DB2 to transmit it */ 05030000
} /* End of if( errmsg[0][0] != BLANK ) */ 05040000
05050000
parg6 = (short int *)argv[6]; /* locate and recast 6th arg */ 05060000
for( j=0; j<5; j++ ) /* copy over null-ind array */ 05070000
{ 05080000
*parg6 = locind[j]; 05090000
parg6++; 05100000
} /* return control to caller */ 05110000
05120000
} /* end of main */ 05130000
05140000
/********************************************************************* 05150000
* SQL error handler * 05160000
*********************************************************************/ 05170000
#pragma linkage(dsntiar, OS) 05180000
05190000
sql_error( char locmsg[] ) 05200000
{ 05210000
05220000
/* DSNTIAR message structure */ 05230000
struct error_struct { 05240000
short int error_len; 05250000
char error_text[DATA_DIM][BUFROWLN]; 05260000
} error_message = {DATA_DIM * BUFROWLN}; 05270000
05280000
extern short int dsntiar( struct sqlca *sqlca, 05290000
struct error_struct *msg, 05300000
int *len ); 05310000
05320000
char *curbyte; /* Pointer to current byte in */ 05330000
/* error_message */ 05340000
05350000
short int tiar_rc; /* DSNTIAR Return code */ 05360000
int i; /* Loop control */ 05370000
static int lrecl = BUFROWLN; /* Width of message lines */ 05380000
05390000
/******************************************************************* 05400000
* indicate that a fatal error has occurred * 05410000
*******************************************************************/ 05420000
rc = RETSEV; 05430000
05440000
/******************************************************************* 05450000
* copy locator message to the error message return buffer * 05460000
*******************************************************************/ 05470000
strcpy( errmsg[0],locmsg ); 05480000
05490000
/******************************************************************* 05500000
* format the SQL message and move it to the err msg rtn buffer * 05510000
*******************************************************************/ 05520000
tiar_rc = dsntiar( &sqlca, &error_message, &lrecl ); 05530000
05540000
if( tiar_rc == 0 ) 05550000
for( i=0; i<DATA_DIM; i++ ) 05560000
{ 05570000
strncpy( errmsg[i+1],error_message.error_text[i],BUFROWLN ); 05580000
} 05590000
else 05600000
{ 05610000
strcpy( errmsg[1],"DSNTIAR could not detail the SQL error" ); 05620000
strcpy( errmsg[2],"*** SQLCODE is " ); 05630000
strcat( errmsg[3],(char *)SQLCODE ); 05640000
strcpy( errmsg[4],"*** SQLERRM is " ); 05650000
for( i=0; i<sqlca.sqlerrml; i++ ) 05660000
errmsg[5][i],sqlca.sqlerrmc[i]; 05670000
} 05680000
05690000
} /* end of sql_error */ 05700000