/* This RSP returns takes an office code passed in positional format, and returns records from a KSDS VSAM file with that office code as the key in a DB2-format output pipe. Ex. USE PROCEDURE SAMP04X 00200 Written in SAS/C V5R0. Used the SAS/C digraphs "(³" and "³)" for square brackets. */ #define TRUE 1 /* Boolean value */ #define FALSE 0 /* Boolean value */ #define NUMCOLS 5 /* Number of columns returned */ #define CHAR 452 /* SQLTYPE for CHAR */ #define SMALLINT 500 /* SQLTYPE for SMALLINT */ #define DECIMAL 484 /* SQLTYPE for DECIMAL */ #define SYS_CICS /* This is a CICS program */ #define NO_IO /* Don't include I/O routines */ #define NO_WARNING /* Don't include warning rtns. */ #define NO_ABEND /* Don't include ABEND rtns. */ #include /* Make this all-resident */ #include /* Needed for NULL definition */ #include "sparea.h" /* Stored Procedure Comm Area */ /* Record definition for the EMPSAMP VSAM file. */ struct { char office(³5³); char ssno(³11³); char name(³30³); short exemptions; char hourlyWage(³3³); /* Actually IBM packed decimal */ char filler(³29³); } empRow; char holdOff(³5³); /* Save of original search key */ /* SQLDA for DB2-format output pipe. */ struct SQLDA { unsigned char sqldaid(³8³); long sqldabc; short sqln; short sqld; struct SQLVAR { short sqltype; union SQLLENGTH { short sqllen; struct SQLDECIMAL { unsigned char precision; unsigned char scale; } sqldecimal; } sqllength; void *sqldata; short *sqlind; struct SQLNAME { short length; unsigned char name(³30³); } sqlname; } sqlvar(³NUMCOLS³); }; /* Instantiate SQLDA and initialize its header. */ struct SQLDA sqlda = {"SQLDA ", 16 + (NUMCOLS * 44), NUMCOLS, NUMCOLS}; long cicsRC; /* Response code from CICS */ int findOff(struct SPAREA *); /* Find passed office parm */ void initPipe(struct SPAREA *); /* Initialize SQLDA for pipe */ int openOut(struct SPAREA *); /* Open DB2-format output pipe */ int fetchRow(void); /* Fetch next VSAM record */ void endBr(void); /* End the VSAM BROWSE */ void openpipe(struct SPAREA *); /* RSP openpipe routine */ void putpipe(struct SPAREA *); /* RSP putpipe routine */ void clospipe(struct SPAREA *); /* RSP clospipe routine */ void main(struct EIBLK *eib_pointer, struct SPAREA *spPointer) { /* Initialize SQLDA for DB2-format output pipe. */ initPipe( spPointer ); /* If they sent us a positional parameter, and the DB2-format output pipe open OK, process request, otherwise issue error message. */ if (findOff( spPointer ) && openOut( spPointer )) { /* As long as there are rows, put them to the output pipe. */ while (fetchRow()) { putpipe( spPointer ); if (memcmp( spPointer->sprc, "000", sizeof(spPointer->sprc) )) break; } /* Everything went OK. */ memcpy( spPointer->spstatus, "OK", sizeof(spPointer->spstatus) ); strcpy( spPointer->spmsg, "Request processed OK" ); clospipe( spPointer ); endBr(); } else memcpy( spPointer->spstatus, "E ", sizeof(spPointer->spstatus) ); /* Issue whatever message has been built, and then the required status command. */ message( spPointer ); status( spPointer ); } /* Find passed date parm. */ int findOff(struct SPAREA *spPointer) { /* If there is no passed parm, issue error message. Otherwise, initialize the VSAM key field with the parm and start the VSAM BROWSE. */ if (spPointer->spvartxt) { memcpy( empRow.office, spPointer->spvartxt, sizeof(empRow.office) ); memcpy( holdOff, spPointer->spvartxt, sizeof(holdOff) ); EXEC CICS STARTBR DATASET("EMPSAMP") RIDFLD(empRow.office) KEYLENGTH(sizeof(empRow.office)) GENERIC EQUAL RESP(cicsRC); switch (cicsRC) { case DFHRESP(NORMAL) : /* Ready to start reading */ return TRUE; break; case DFHRESP(NOTFND) : /* Key was not found */ strcpy( spPointer->spmsg, "Key not found"); break; default : /* Something else went wrong */ strcpy( spPointer->spmsg, "STARTBR on EMPSAMP file failed" ); break; } } else strcpy( spPointer->spmsg, "No office code passed"); return FALSE; } /* Initialize SQLDA for DB2-format output pipe. */ void initPipe(struct SPAREA *spPointer) { int i; /* Initialize all column name fields to blanks and all null indicator pointers to NULL. */ for (i = 0; i < NUMCOLS; i++) { memset( sqlda.sqlvar(³i³).sqlname.name, ' ', sizeof(sqlda.sqlvar(³i³).sqlname.name) ); sqlda.sqlvar(³i³).sqlind = NULL; } /* Initialize OFFICE_CODE column. */ sqlda.sqlvar(³0³).sqltype = CHAR; sqlda.sqlvar(³0³).sqllength.sqllen = sizeof(empRow.office); sqlda.sqlvar(³0³).sqldata = (char *)&empRow.office; sqlda.sqlvar(³0³).sqlname.length = strlen( "OFFICE_CODE" ); memcpy( sqlda.sqlvar(³0³).sqlname.name, "OFFICE_CODE", strlen( "OFFICE_CODE" ) ); /* Initialize SSNO column. */ sqlda.sqlvar(³1³).sqltype = CHAR; sqlda.sqlvar(³1³).sqllength.sqllen = sizeof(empRow.ssno); sqlda.sqlvar(³1³).sqldata = (char *)&empRow.ssno; sqlda.sqlvar(³1³).sqlname.length = strlen( "SSNO" ); memcpy( sqlda.sqlvar(³1³).sqlname.name, "SSNO", strlen( "SSNO" ) ); /* Initialize NAME column. */ sqlda.sqlvar(³2³).sqltype = CHAR; sqlda.sqlvar(³2³).sqllength.sqllen = sizeof(empRow.name); sqlda.sqlvar(³2³).sqldata = (struct name *)&empRow.name; sqlda.sqlvar(³2³).sqlname.length = strlen( "NAME" ); memcpy( sqlda.sqlvar(³2³).sqlname.name, "NAME", strlen( "NAME" ) ); /* Initialize EXEMPTIONS column. */ sqlda.sqlvar(³3³).sqltype = SMALLINT; sqlda.sqlvar(³3³).sqllength.sqllen = sizeof(empRow.exemptions); sqlda.sqlvar(³3³).sqldata = (short *)&empRow.exemptions; sqlda.sqlvar(³3³).sqlname.length = strlen( "EXEMPTIONS" ); memcpy( sqlda.sqlvar(³3³).sqlname.name, "EXEMPTIONS", strlen( "EXEMPTIONS" ) ); /* Initialize HOURLY_WAGE column. */ sqlda.sqlvar(³4³).sqltype = DECIMAL; sqlda.sqlvar(³4³).sqllength.sqldecimal.precision = 5; sqlda.sqlvar(³4³).sqllength.sqldecimal.scale = 2; sqlda.sqlvar(³4³).sqldata = (char *)&empRow.hourlyWage; sqlda.sqlvar(³4³).sqlname.length = strlen( "HOURLY_WAGE" ); memcpy( sqlda.sqlvar(³4³).sqlname.name, "HOURLY_WAGE", strlen( "HOURLY_WAGE" ) ); } /* Open DB2-format output pipe. */ int openOut(struct SPAREA *spPointer) { memcpy( spPointer->spformat, "DB2", sizeof(spPointer->spformat) ); memcpy( spPointer->spmode, "OUTPUT", sizeof(spPointer->spmode) ); spPointer->spsqlda = (struct SQLDA *)&sqlda; openpipe( spPointer ); if (memcmp( spPointer->sprc, "000", sizeof(spPointer->sprc) )) { strcpy( spPointer->spmsg, "Output pipe did not open" ); return FALSE; } else return TRUE; } /* Get next record in VSAM file. Return FALSE when key returned is not equal to the original search key, or a non-normal response is returned from the READNEXT (ie. EOF). */ int fetchRow(void) { EXEC CICS READNEXT DATASET("EMPSAMP") RIDFLD(empRow.office) INTO(empRow) LENGTH(sizeof(empRow)) RESP(cicsRC); if (memcmp( empRow.office, holdOff, sizeof(holdOff) ) ³³ cicsRC != DFHRESP(NORMAL)) return FALSE; else return TRUE; } /* End the VSAM BROWSE. */ void endBr(void) { EXEC CICS ENDBR DATASET("EMPSAMP"); }