DSN8ED4

Demonstrates how to use an application program to call DSNTPSMP, the Db2 SQL Procedures Processor.

 /********************************************************************* 00010000
 * Module name = DSN8ED4 (sample program)                             * 00020000
 *                                                                    * 00030000
 * DESCRIPTIVE NAME: Sample client for:                               * 00040000
 *                   DSNTPSMP (DB2 SQL Procedures Processor)          * 00050000
 *                                                                    * 00060000
 *     LICENSED MATERIALS - PROPERTY OF IBM                           * 00070000
 *     5625-DB2                                                       * 00080000
 *     (C) COPYRIGHT 1982, 2003 IBM CORP.  ALL RIGHTS RESERVED.       * 00090000
 *                                                                    * 00100000
 *     STATUS = VERSION 8                                             * 00110000
 *                                                                    * 00120000
 * Function: Demonstrates how to use an application program to call   * 00130000
 *           DSNTPSMP, the DB2 SQL Procedures Processor.  DSN8ED4     * 00140000
 *           collects and passes user-provided SQL Procedure source   * 00150000
 *           code and prep options to DSNTPSMP, and outputs the       * 00160000
 *           report(s), if any, returned from DSNTPSMP by result set. * 00170000
 *                                                                    * 00180000
 * Notes:                                                             * 00190000
 *   Dependencies: Requires SYSPROC.DSNTPSMP                          * 00200000
 *                                                                    * 00210000
 *   Restrictions:                                                    * 00220000
 *                                                                    * 00230000
 * Module type: C program                                             * 00240000
 *   Processor: DB2 Precompiler                                       * 00250000
 *              IBM C/C++ for OS/390 V1R3 or higher                   * 00260000
 * Module size: See linkedit output                                   * 00270000
 *  Attributes: Reentrant and reusable                                * 00280000
 *                                                                    * 00290000
 * Entry point: DSN8ED4                                               * 00300000
 *     Purpose: See Function                                          * 00310000
 *     Linkage: Standard MVS program invocation, three parameters.    * 00320000
 *                                                                    * 00330000
 *  Parameters: DSN8ED4 uses the C "main" argument convention of      * 00340000
 *              argv (argument vector) and argc (argument count).     * 00350000
 *                                                                    * 00360000
 *              - ARGV[0]: (input) pointer to a char[9],              * 00370000
 *                         null-terminated string having the name of  * 00380000
 *                         this program (DSN8ED4)                     * 00390000
 *              - ARGV[1]: (input) pointer to a char[21],             * 00400000
 *                         null-terminated string having the action   * 00410000
 *                         that DSNTPSMP is to perform:               * 00420000
 *                         - BUILD: Prepare a new SQL Procedure       * 00430000
 *                         - REBUILD: Prepare an existing SQL         * 00440000
 *                         - QUERYLEVEL: Verify DSNTPSMP level     @05* 00450004
 *                         - DESTROY: Remove an SQL Procedure         * 00460000
 *                         - REBIND: Rebind the package of an exist-  * 00470000
 *                             ing SQL Procedure                      * 00480000
 *              - ARGV[2]: (input) pointer to a char[262],            * 00490000
 *                         null-terminated string having the schema   * 00500000
 *                         and name of the SQL Procedure to be        * 00510000
 *                         processed by DSNTPSMP (e.g. DSN8.DSN8ES2)  * 00520000
 *              - ARGV[3]: (input) pointer to a char[9],              * 00530000
 *                         null-terminated string having the author-  * 00540000
 *                         ization id to be used for BUILDOWNER and   * 00550003
 *                         for calling DSNTPSMP.                      * 00560003
 *              - ARGV[4]: (input) pointer to a char[17],             * 00570000
 *                         null-terminated string having the name of  * 00580000
 *                         the server where DSNTPSMP is to be run.    * 00590000
 *                         This is an optional parameter; the local   * 00600000
 *                         server is used if no argument is provided. * 00610000
 *                                                                    * 00620000
 *      Inputs: DSN8ED4 allocates these input DDs:                    * 00630000
 *              - PCOPTS  : Options for the DB2 precompiler           * 00640000
 *              - COPTS   : Options for the C compiler                * 00650000
 *              - PLKDOPTS: Options for the pre-link editor           * 00660000
 *              - LKEDOPTS: Options for the link editor               * 00670000
 *              - BINDOPTS: Options for the DB2 BIND                  * 00680000
 *              - SQLIN   : Source code for the SQL Procedure         * 00690000
 *                                                                    * 00700000
 *     Outputs: DSN8ED4 allocates these output DD                     * 00710000
 *              - REPORT01: First report data set from DSNTPSMP       * 00720000
 *              - REPORT02: Second report data set from DSNTPSMP      * 00730000
 *              - REPORT03: Third report data set from DSNTPSMP       * 00740000
 *                                                                    * 00750000
 * Normal Exit: Return Code: 0000                                     * 00760000
 *              - Message: DSNTPSMP has completed with return code 0  * 00770000
 *              - Message: SQL changes have been committed         @04* 00780000
 *                                                                    * 00790000
 * Normal with Warnings Exit: Return Code: 0004                   +@04* 00800000
 *              - Message: DSNTPSMP has completed with return code 4  * 00810000
 *              - Message: SQL changes have been committed        -@04* 00820000
 *                                                                    * 00830000
 *  Error Exit: Return Code: 0012                                     * 00840000
 *              - Message: DSNTPSMP has completed with return code <n>* 00850000
 *              - Message: The length of the argument specified for   * 00860000
 *                         the <parameter-name> does not fall within  * 00870000
 *                         the required bounds of <minimum-length>    * 00880000
 *                         and <maximum-length>                       * 00890000
 *              - Message: The argument specified for the action      * 00900000
 *                         parameter is invalid                       * 00910000
 *              - Message: Invalid sequence number <sequence-number>  * 00920000
 *                         specified for REPORTnn DD                  * 00930000
 *              - Message: DSN8ED4 was invoked with <parameter-count> * 00940000
 *                         parameters.  At least 3 parameters are     * 00950000
 *                         required                                   * 00960000
 *              - Message: Unable to open <DD-name>                   * 00970000
 *              - Message: Unable to close <DD-name>                  * 00980000
 *              - Message: <formatted SQL text from DSNTIAR>          * 00990000
 *              - Message: SQL changes have been rolled back       @04* 01000000
 *                                                                    * 01010000
 * External References:                                               * 01020000
 *              - Routines/Services: DSNTIAR: DB2 msg text formatter  * 01030000
 *              - Data areas       : None                             * 01040000
 *              - Control blocks   : None                             * 01050000
 *                                                                    * 01060000
 *                                                                    * 01070000
 * Pseudocode:                                                        * 01080000
 *   DSN8ED4:                                                         * 01090000
 *     - call getCallParms to receive and validate call parm arguments* 01100000
 *     - case action                                                  * 01110000
 *       - when BUILD, call getReBuildData                            * 01120000
 *       - when DESTROY, call getDestroyData                          * 01130000
 *       - when REBUILD, call getReBuildData                          * 01140000
 *       - when REBIND, call getRebindData                            * 01150000
 *       - when QUERYLEVEL, call getLevelData                         * 01160003
 *       - otherwise call issueInvalidActionError                     * 01170000
 *     - call connectToLocation                                       * 01180000
 *     - call setAuthID to set the current authorization id  @pq53353 * 01190003
 *     - call callDSNTPSMP to invoke the DB2 SQL Procedures Processor * 01200000
 *     - call processDSNTPSMPresultSet to write reports from DSNTPSMP * 01210000
 *     - If no errors, call processSqlCommit to commit work       @04 * 01220000
 *       Else call processSqlRollback to undo work                @04 * 01230000
 *   End DSN8ED4                                                      * 01240000
 *                                                                    * 01250000
 *                                                                    * 01260000
 *  Change activity =                                                 * 01270000
 *    PQ46962 03/28/2001 changed line feed character to hex 25    @01 * 01280000
 *    PQ43444 04/12/2001 Disable LEOPTS DD (LE options are not    @02 * 01290000
 *                       processed by DSNTPSMP).  Remission the   @02 * 01300000
 *                       leOptions hostvar as alterStmt.          @02 * 01310000
 *    PQ56601 03/06/2002 Trim +/- continuation characters from    @03 * 01320000
 *                       BIND options to prevent BIND errors.     @03 * 01330000
 *                       These characters are often used to con-  @03 * 01340000
 *                       tinue BIND statements being processed    @03 * 01350000
 *                       by the DB2 DSN command processor (which  @03 * 01360000
 *                       uses TSO i/o services that recognize     @03 * 01370000
 *                       them as continuation characters) but     @03 * 01380000
 *                       they are not otherwise valid in DB2      @03 * 01390000
 *                       commands.                                @03 * 01400000
 *    PQ61782 07/16/2002 Distinguish between DSNTPSMP return code @04 * 01410000
 *                       and DSN8ED4 return code; Issue SQL COMMIT@04 * 01420000
 *                       when DSNTPSMP returns rc = 0 or rc = 4;  @04 * 01430000
 *                       Otherwise issue SQL ROLLBACK             @04 * 01440000
 *    D55199  12/08/2003 Adjust to use DSNTPSMP 1.2x interface    @05 * 01450004
 *    D56462  02/12/2004 Allocate maximum of 6 output reports     @06 * 01460005
 *********************************************************************/ 01470000
                                                                        01480000
 /********************** C library definitions ***********************/ 01490000
 #include        <errno.h>                                              01500000
 #include        <stdio.h>                                              01510000
 #include        <stdlib.h>                                             01520000
 #include        <string.h>                                             01530000
                                                                        01540000
 /**************************** Constants *****************************/ 01550000
 #define         NULLCHAR         '\0' /* Null character             */ 01560000
 #define         RETNRM             0  /* Normal  return code     @04*/ 01570000
 #define         RETWRN             4  /* Warning return code        */ 01580000
 #define         RETERR             8  /* Error return code          */ 01590000
 #define         RETSEV            12  /* Severe error return code   */ 01600000
 #define         INTERFACE       "1.2" /* DSNTPSMP innterface level  */ 01610003
                                                                        01620000
 enum flag                  {No, Yes}; /* Settings for flags         */ 01630000
                                                                        01640000
                                                                        01650000
 /***************** Input: SQL Procedure Source Code *****************/ 01660000
 FILE            *sqlInFile;           /* Pointer to SQL source DD   */ 01670000
                                                                        01680000
                                                                        01690000
 /*********** Output: DB2 SQL Procedures Processor Reports ***********/ 01700000
 FILE            *reportDD;            /* Pointer to curr report DD  */ 01710000
 char            reportDDName[12];     /* For generated DD name      */ 01720000
 unsigned short  reportLRECL;          /* length req'd for output rec*/ 01730000
                                                                        01740000
                                                                        01750000
 /************************ Working variables *************************/ 01760000
 unsigned short  resultSetReturned = 0;/* DSNTPSMP result set stat@04*/ 01770000
 long int        DSNTPSMP_rc     = -1; /* DSNTPSMP return code    @04*/ 01780000
 long int        rc               = 0; /* program return code        */ 01790000
 char            levelquery      ='N'; /* Is this a level check?  @05*/ 01800004
                                                                        01810000
                                                                        01820000
 /******************** DB2 SQL Communication Area ********************/ 01830000
 EXEC SQL INCLUDE SQLCA;                                                01840000
                                                                        01850000
                                                                        01860000
 /************************ DB2 Host Variables ************************/ 01870000
 EXEC SQL BEGIN DECLARE SECTION;                                        01880000
                                                                        01890000
   char            authID[9];          /* Authorization id-BUILDOWNER*/ 01900000
                                                                        01910000
   char            locationName[17];   /* Server location name       */ 01920000
                                                                        01930000
   char            action[21];         /* Command for PSM processor  */ 01940000
   char            routineName[262];   /* SQL Procedure schema.name  */ 01950000
   SQL TYPE IS CLOB(2M) sqlSource;     /* SQL Procedure source    @05*/ 01960004
                                                                        01970000
   char            precompOptions[256];/* precompiler options        */ 01980000
   char            compileOptions[256];/* compilation parameters     */ 01990000
   char            prelinkOptions[256];/* prelink options            */ 02000000
   char            linkOptions[256];   /* link-edit options          */ 02010000
   char            bindOptions[1025];  /* DB2 bind options           */ 02020000
   char            alterStmt[32672];   /* ALTER PROC text         @02*/ 02030000
                                                                        02040000
   char            sqlSourceDsn[81];   /* Source data set name       */ 02050000
   char            outputString[256];  /* DSNTPSMP status area       */ 02060000
                                                                        02070000
   char            DSNTPSMP_pname[19]  /* DSNTPSMP procedure-name    */ 02080000
                   = "SYSPROC.DSNTPSMP\0";                              02090000
                                                                        02100000
   char            stepName[17];       /* DSNTPSMP stepname          */ 02110000
   char            fileName[9];        /* DSNTPSMP output DD name    */ 02120000
   long int        reportLineNumber;   /* DSNTPSMP report line no.   */ 02130000
   char            reportLine[256];    /* DSNTPSMP report line       */ 02140000
                                                                        02150000
 EXEC SQL END DECLARE SECTION;                                          02160000
                                                                        02170000
                                                                        02180000
 /*************** DB2 Result Set Locator Host Variables **************/ 02190000
 EXEC SQL BEGIN DECLARE SECTION;                                        02200000
   static volatile SQL TYPE IS RESULT_SET_LOCATOR *DSNTPSMP_rs_loc1;    02210000
 EXEC SQL END DECLARE SECTION;                                          02220000
                                                                        02230000
                                                                        02240000
 /********************** DSN8ED4 Function Models *********************/ 02250000
 int main                              /* DSN8ED4 driver             */ 02260000
   ( int argc,                         /* - Input argument count     */ 02270000
     char *argv[]                      /* - Input argument vector    */ 02280000
   );                                                                   02290000
 void getCallParms                     /* Process args to call parms */ 02300000
   ( int argc,                         /* - Input argument count     */ 02310000
     char *argv[]                      /* - Input argument vector    */ 02320000
   );                                                                   02330000
 void getReBuildData( void );          /* Get SQL Proc re/build data */ 02340000
 void getDestroyData( void );          /* Get SQL Proc destroy data  */ 02350000
 void getRebindData( void );           /* Get SQL Proc rebind data   */ 02360000
 void getLevelData( void );            /* Get DSNTPSMP level data    */ 02370003
 void getOptions                       /* Read specified options file*/ 02380000
   ( char *options,                    /* -out: list of options read */ 02390000
     int maxBytes,                     /* - in: max size of list     */ 02400000
     char *optionsDDname               /* - in: name of DD to read   */ 02410000
   );                                                                   02420000
 void getSqlSource( void );            /* Read SQL Procedure Source  */ 02430000
 void setAuthID( void );               /* Set the current DB2 auth id*/ 02440003
 void connectToLocation( void );       /* Connect to DB2 location    */ 02450000
 void callDSNTPSMP( void );            /* Run SQL Procedure Processor*/ 02460000
 void listDSNTPSMPcallParms( void );   /* List parms sent to DSNTPSMP*/ 02470000
 void processDSNTPSMPresultSet( void );/* Process DSNTPSMP rslt sets */ 02480000
 void associateResultSetLocator(void); /* Assoc DSNTPSMP RS locator  */ 02490000
 void allocateResultSetCursor( void ); /* Alloc DSNTPSMP RS cursor   */ 02500000
 void writeDSNTPSMPreports( void );    /* Output a DSNTPSMP report   */ 02510000
 void fetchFromResultSetCursor( void );/* Read DSNTSPMP RS cursor    */ 02520000
 void openReportDataSet                /* Alloc DD for a report      */ 02530000
   ( short int reportNumber            /* - in: Seqeunce number      */ 02540000
   );                                                                   02550000
 void closeReportDataSet( void );      /* Dealloc DD for a report    */ 02560000
 void trimTrailingBlanks               /* Strip off trailing blanks  */ 02570000
   ( char            *string           /* - in: string to be trimmed */ 02580000
   );                                                                   02590000
 void stripContinuationCharacter       /* Strip off trailing - or +  */ 02600000
   ( char            *string           /* - in: string to be trimmed */ 02610000
   );                                                           /*@03*/ 02620000
 void processSqlCommit( void );        /* Commit SQL changes      @04*/ 02630000
 void processSqlRollback( void );      /* Rollback SQL changes    @04*/ 02640000
 void issueDataSetClosingError         /* Handler for ds close error */ 02650000
   ( char            *DDname,          /* - in: name of errant DD    */ 02660000
     int             LEerrno           /* - in: LE diagnostic errno  */ 02670000
   );                                                                   02680000
 void issueDataSetOpeningError         /* Handler for ds open error  */ 02690000
   ( char            *DDname,          /* - in: name of errant DD    */ 02700000
     int             LEerrno           /* - in: LE diagnostic errno  */ 02710000
   );                                                                   02720000
 void issueDataSetReadingError         /* Handler for ds read error  */ 02730000
   ( char            *DDname,          /* - in: name of errant DD    */ 02740000
     int             LEerrno           /* - in: LE diagnostic errno  */ 02750000
   );                                                                   02760000
 void issueInvalidCallParmCountError   /* Handler for parm count err */ 02770000
   ( int argc                          /* - in: no. parms received   */ 02780000
   );                                                                   02790000
 void issueInvalidActionError          /* Handler for unknown action */ 02800000
   ( char *action                      /* - in: action specified     */ 02810000
   );                                                                   02820000
 void issueInvalidLevelError           /* Handler for wrong DSNTPSMP */ 02830003
   ( char *level                       /* - in: level encountered    */ 02840003
   );                                                                   02850003
 void issueInvalidDDnumError           /* Handler for unknown DD seq */ 02860000
   ( short          invalidDDnum       /* - in: invalid DD sequ. no. */ 02870000
   );                                                                   02880000
 void issueInvalidParmLengthError      /* Handler for parm len error */ 02890000
   ( char *parmName,                   /* - in: identify of parm     */ 02900000
     int minLength,                    /* - in: min valid length     */ 02910000
     int maxLength                     /* - in: max valid length     */ 02920000
   );                                                                   02930000
 void issueSqlError                    /* Handler for SQL error      */ 02940000
   ( char *locMsg                      /* - in: Call location        */ 02950000
   );                                                                   02960000
                                                                        02970000
                                                                        02980000
 int main                              /* DSN8ED4 driver             */ 02990000
   ( int argc,                         /* - Input argument count     */ 03000000
     char *argv[]                      /* - Input argument vector    */ 03010000
   )                                                                    03020000
   /******************************************************************* 03030000
   * Main Driver:                                                     * 03040000
   * - Gets arguments for call parms                                  * 03050000
   * - Gets processing options and data                               * 03060000
   * - Connects to remote location, if one was specified              * 03070000
   * - Calls the DB2 SQL Procedure Processor, DSNTSPMP                * 03080000
   * - Processes any result set(s) returned from DSNTPSMP             * 03090000
   *                                                                  * 03100000
   *******************************************************************/ 03110000
   { /***************************************************************** 03120000
     * Extract the following information from the call parms:         * 03130000
     * (1) DB2 location name where where SQL Procedure is to be built,* 03140000
     *     destroyed, rebuilt, rebound, etc.)                         * 03150000
     * (2) DB2 SQL Procedure Processor action (Build,Destroy,...)     * 03160000
     * (3) Name of SQL Procedure to be built, destroyed, rebound, etc.* 03170000
     *****************************************************************/ 03180000
     getCallParms( argc,argv );                                         03190000
                                                                        03200000
     /***************************************************************** 03210000
     * Collect DSNTPSMP parms appropriate for the user-passed action  * 03220000
     *****************************************************************/ 03230000
     if( rc < RETSEV )                                                  03240000
       { if( memcmp( action,"BUILD",5 ) == 0 )                          03250000
           { getReBuildData();                                          03260000
           }                                                            03270000
         else if( memcmp( action,"DESTROY",7 ) == 0 )                   03280000
           { getDestroyData();                                          03290000
           }                                                            03300000
         else if( memcmp( action,"REBUILD",7 ) == 0 )                   03310000
           { getReBuildData();                                          03320000
           }                                                            03330000
         else if( memcmp( action,"REBIND",6 ) == 0 )                    03340000
           { getRebindData();                                           03350000
           }                                                            03360000
         else if( memcmp( action,"QUERYLEVEL",10 ) == 0 )               03370003
           { getLevelData();                                            03380003
             levelquery='Y';                                            03390003
           }                                                            03400003
         else                                                           03410000
           { issueInvalidActionError( action );                         03420000
           }                                                            03430000
       }                                                                03440000
                                                                        03450000
     /***************************************************************** 03460000
     * Connect to location where the SQL Procedure is to be processed * 03470000
     *****************************************************************/ 03480000
     if( rc < RETSEV  &&  strlen(locationName) > 0 )                    03490000
       connectToLocation();                                             03500000
                                                                        03510003
     /***************************************************************** 03520003
     * Set current DB2 authorization id to use when calling DSNTPSMP  * 03530003
     *****************************************************************/ 03540003
     if( rc < RETSEV )                                     /*@pq53353*/ 03550003
       setAuthID();                                                     03560003
                                                                        03570000
     /***************************************************************** 03580000
     * Call the PSM processor                                         * 03590000
     *****************************************************************/ 03600000
     if( rc < RETSEV )                                                  03610000
       callDSNTPSMP();                                                  03620000
                                                                        03630000
     /***************************************************************** 03640000
     * Process the result set, if any, from DSNTPSMP                  * 03650000
     *****************************************************************/ 03660000
     if( resultSetReturned )                                    /*@04*/ 03670000
       processDSNTPSMPresultSet();                                      03680000
                                                                        03690000
     /***********************************************************+@04** 03700000
     * If DSNTPSMP returns either 0 (normal) or 4 (warnings), commit  * 03710000
     * the SQL changes; Otherwise, rollback the SQL changes           * 03720000
     *****************************************************************/ 03730000
     if( DSNTPSMP_rc == RETNRM || DSNTPSMP_rc == RETWRN )               03740000
       { processSqlCommit();                                            03750000
         if( rc < DSNTPSMP_rc )                                         03760000
           rc = DSNTPSMP_rc;                                            03770000
       }                                                                03780000
     else                                                               03790000
       { processSqlRollback();                                          03800000
         if( rc < RETSEV )                                              03810000
           rc = RETSEV;                                                 03820000
       }                                                       /*-@04*/ 03830000
                                                                        03840000
     /***************************************************************** 03850000
     * Return highest completion code                                 * 03860000
     *****************************************************************/ 03870000
     return( rc );                                                      03880000
                                                                        03890000
   } /* end of main */                                                  03900000
                                                                        03910000
                                                                        03920000
 void getCallParms                     /* Process args to call parms */ 03930000
   ( int argc,                         /* - Input argument count     */ 03940000
     char *argv[]                      /* - Input argument vector    */ 03950000
   )                                                                    03960000
   /******************************************************************* 03970000
   * Verifies that correct call parms have been passed in:            * 03980000
   * - Three parameters (action, routine name, and authorization id)  * 03990000
   *   require arguments                                              * 04000000
   * - The fourth parameter (location name) is optional               * 04010000
   *******************************************************************/ 04020000
   { if( argc < 4  || argc > 5 )                                        04030000
       { issueInvalidCallParmCountError( argc );                        04040000
       }                                                                04050000
     else if( strlen( argv[1] ) < 1  ||  strlen( argv[1] ) > 20 )       04060000
       { issueInvalidParmLengthError("DSNTPSMP Action",1,20);           04070000
       }                                                                04080000
     else if( strlen( argv[2] ) < 1  ||  strlen( argv[2] ) > 261 )      04090000
       { issueInvalidParmLengthError("SQL Procedure schema.name",1,261);04100000
       }                                                                04110000
     else if( strlen( argv[3] ) < 1  ||  strlen( argv[3] ) > 8 )        04120000
       { issueInvalidParmLengthError("Authorization ID",1,8);           04130000
       }                                                                04140000
     else                                                               04150000
       { strcpy( action,      argv[1] );                                04160000
         strcpy( routineName, argv[2] );                                04170000
         strcpy( authID, argv[3] );                                     04180000
       }                                                                04190000
                                                                        04200000
     if( argc > 4 )                                                     04210000
       if( strlen( argv[4] ) < 1  ||  strlen( argv[4] ) > 16 )          04220000
         { issueInvalidParmLengthError("Server Location Name",1,16);    04230000
         }                                                              04240000
       else                                                             04250000
         strcpy( locationName,argv[4] );                                04260000
     else                                                               04270000
       locationName[0] = NULLCHAR;                                      04280000
                                                                        04290000
   } /* end of getCallParms */                                          04300000
                                                                        04310000
                                                                        04320000
 void getReBuildData( void )           /* Get SQL Proc re/build data */ 04330000
   /******************************************************************* 04340000
   * Collects the prep options and source data needed by DSNTPSMP to  * 04350000
   * perform a BUILD or REBUILD operation.                            * 04360000
   *******************************************************************/ 04370000
   {                                                                    04380000
     /***************************************************************** 04390000
     * Get program prep, bind, and runtime options                    * 04400000
     *****************************************************************/ 04410000
     getOptions( precompOptions,255,"PCOPTS" );                         04420000
     if( rc < RETSEV )                                                  04430000
       getOptions( compileOptions,255,"COPTS" );                        04440000
     if( rc < RETSEV )                                                  04450000
       getOptions( prelinkOptions,255,"PLKDOPTS" );                     04460000
     if( rc < RETSEV )                                                  04470000
       getOptions( linkOptions,255,"LKEDOPTS" );                        04480000
     if( rc < RETSEV )                                                  04490000
       getOptions( bindOptions,1024,"BINDOPTS" );                       04500000
     /* if( rc < RETSEV )                                         @02*/ 04510000
     /*   getOptions( LeOptions,254,"LEOPTS" );                   @02*/ 04520000
                                                                        04530000
     /***************************************************************** 04540000
     * Get the source for the SQL procedure to be prepared            * 04550000
     *****************************************************************/ 04560000
     if( rc < RETSEV )                                                  04570000
       getSqlSource();                                                  04580000
   } /* end of getReBuildData */                                        04590000
                                                                        04600000
                                                                        04610000
 void getDestroyData( void )           /* Get SQL Proc destroy data  */ 04620000
   /******************************************************************* 04630000
   * Gets the name of the package to be freed by DSNTPSMP during a    * 04640000
   * DESTROY operation.                                               * 04650000
   *******************************************************************/ 04660000
   {                                                                    04670000
     /***************************************************************** 04680000
     * Set program prep and runtime options to NULLCHAR               * 04690000
     *****************************************************************/ 04700000
     sqlSource.length      = 0;                                 /*@05*/ 04710004
     sqlSource.data[0]     = NULLCHAR;                          /*@05*/ 04720004
     precompOptions[0]     = NULLCHAR;                                  04730000
     compileOptions[0]     = NULLCHAR;                                  04740000
     prelinkOptions[0]     = NULLCHAR;                                  04750000
     linkOptions[0]        = NULLCHAR;                                  04760000
     alterStmt[0]          = NULLCHAR;                          /*@02*/ 04770000
     sqlSourceDsn[0]       = NULLCHAR;                                  04780000
     outputString[0]       = NULLCHAR;                                  04790000
                                                                        04800000
     /***************************************************************** 04810000
     * Get name of package to free                                    * 04820000
     *****************************************************************/ 04830000
     getOptions( bindOptions,1024,"BINDOPTS" );                         04840000
                                                                        04850000
   } /* end of getDestroyData */                                        04860000
                                                                        04870000
                                                                        04880000
 void getRebindData( void )            /* Rebind an SQL Procedure    */ 04890000
   /******************************************************************* 04900000
   * Gets the name of the package to be rebound by DSNTPSMP during a  * 04910000
   * REBIND operation.                                                * 04920000
   *******************************************************************/ 04930000
   {                                                                    04940000
     /***************************************************************** 04950000
     * Set program prep and runtime options to NULLCHAR               * 04960000
     *****************************************************************/ 04970000
     sqlSource.length      = 0;                                 /*@05*/ 04980004
     sqlSource.data[0]     = NULLCHAR;                          /*@05*/ 04990004
     precompOptions[0]     = NULLCHAR;                                  05000000
     compileOptions[0]     = NULLCHAR;                                  05010000
     prelinkOptions[0]     = NULLCHAR;                                  05020000
     linkOptions[0]        = NULLCHAR;                                  05030000
     alterStmt[0]          = NULLCHAR;                          /*@02*/ 05040000
     sqlSourceDsn[0]       = NULLCHAR;                                  05050000
     outputString[0]       = NULLCHAR;                                  05060000
                                                                        05070000
     /***************************************************************** 05080000
     * Get parameters to pass for rebind                              * 05090000
     *****************************************************************/ 05100000
     getOptions( bindOptions,1024,"BINDOPTS" );                         05110000
                                                                        05120000
   } /* end of getRebindData */                                         05130000
                                                                        05140000
                                                                        05150000
 void getLevelData( void )             /* QueryLevel of DSNTPSMP     */ 05160003
   /******************************************************************* 05170003
   * Prepare for a DSNTPSMP QUERYLEVEL operation.                     * 05180003
   *******************************************************************/ 05190003
   {                                                                    05200003
     /***************************************************************** 05210003
     * Set program prep and runtime options to NULLCHAR               * 05220003
     *****************************************************************/ 05230003
     sqlSource.length      = 0;                                 /*@05*/ 05240004
     sqlSource.data[0]     = NULLCHAR;                          /*@05*/ 05250004
     precompOptions[0]     = NULLCHAR;                                  05260003
     compileOptions[0]     = NULLCHAR;                                  05270003
     prelinkOptions[0]     = NULLCHAR;                                  05280003
     linkOptions[0]        = NULLCHAR;                                  05290003
     alterStmt[0]          = NULLCHAR;                          /*@02*/ 05300003
     sqlSourceDsn[0]       = NULLCHAR;                                  05310003
     outputString[0]       = NULLCHAR;                                  05320003
                                                                        05330003
   } /* end of getLevelData */                                          05340003
                                                                        05350003
                                                                        05360003
 void getOptions                       /* Read processing options    */ 05370000
   ( char *options,                    /* -out: list of options read */ 05380000
     int maxBytes,                     /* - in: max size of list     */ 05390000
     char *optionsDDname               /* - in: nameof DD to read    */ 05400000
   )                                                                    05410000
   /******************************************************************* 05420000
   * Reads up to maxBytes bytes of data from optionsDDname into the   * 05430000
   * options buffer.                                                  * 05440000
   *******************************************************************/ 05450000
   { FILE           *optionsFile;      /* Ptr to specified options DD*/ 05460000
     char           optionsDD[12];     /* DD handle                  */ 05470000
     char           optionsRec[80];    /* Options file input record  */ 05480000
     short int      recordLength  = 0; /* Length of record           */ 05490000
     unsigned short moreRecords = Yes; /* EOF indicator              */ 05500000
                                                                        05510000
     sprintf( optionsDD,                                                05520000
              "DD:%s\0",                                                05530000
              optionsDDname );                                          05540000
                                                                        05550000
     errno = 0;                        /* clear LE errno             */ 05560000
     optionsFile = fopen( optionsDD,                                    05570000
                         "rb,lrecl=80,type=record" );                   05580000
     if( optionsFile == NULL )                                          05590000
       issueDataSetOpeningError( optionsDD,errno );                     05600000
                                                                        05610000
     while( moreRecords == Yes  &&  rc < RETSEV )                       05620000
       { recordLength                                                   05630000
           = fread( optionsRec,        /* Read into options rec area */ 05640000
                    1,                 /* ..1 record                 */ 05650000
                    80,                /* ..of 80 bytes              */ 05660000
                    optionsFile );     /* ..from current options file*/ 05670000
                                                                        05680000
         if( ferror(optionsFile) )     /* Handle IO errors           */ 05690000
            issueDataSetReadingError( optionsDD,errno );                05700000
                                                                        05710000
         else if( feof(optionsFile) )  /* Handle EOF                 */ 05720000
            moreRecords = No;                                           05730000
                                       /* Discard bytes 73-80 and    */ 05740000
         else                          /* strip off trailing blanks  */ 05750000
           { strncat( options,optionsRec,72 );                          05760000
             trimTrailingBlanks( options );                             05770000
             /* Remove +/- continuation chars from BIND input     @03*/ 05780000
             if( memcmp( optionsDDname,"BINDOPTS",8 ) == 0 )    /*@03*/ 05790000
               stripContinuationCharacter( options );           /*@03*/ 05800000
           }                                                            05810000
                                       /* Don't overfill return area */ 05820000
         if( rc < RETSEV  &&  strlen(options) > maxBytes )              05830000
           issueInvalidParmLengthError( optionsDD,0,maxBytes );         05840000
       }                                                                05850000
                                                                        05860000
     if( rc < RETSEV )                                                  05870000
       if( fclose( optionsFile ) != 0 )                                 05880000
         issueDataSetClosingError( optionsDD,errno );                   05890000
                                                                        05900000
   } /* end of getOptions */                                            05910000
                                                                        05920000
                                                                        05930000
 void getSqlSource( void )             /* Read SQL Procedure Source  */ 05940000
   /******************************************************************* 05950000
   * Reads up to 2M bytes of SQL Procedure source code from the       * 05960000
   * SQLIN DD.                                                        * 05970000
   *******************************************************************/ 05980000
   { char           sourceRec[80];     /* Source file input record   */ 05990000
     short int      recordLength  = 0; /* Length of record           */ 06000000
     unsigned short moreRecords = Yes; /* EOF indicator              */ 06010000
                                                                        06020000
     /***************************************************************** 06030000
     * Open the data set having the source for the SQL Procedure      * 06040000
     *****************************************************************/ 06050000
     errno = 0;                        /* clear LE errno             */ 06060000
     sqlInFile = fopen( "DD:SQLIN",                                     06070000
                        "rb,lrecl=80,type=record" );                    06080000
     if( sqlInFile == NULL )                                            06090000
        issueDataSetOpeningError( "DD:SQLIN",errno );                   06100000
                                                                        06110000
     while( moreRecords == Yes  &&  rc < RETSEV )                       06120000
       { recordLength                                                   06130000
           = fread( sourceRec,         /* Read into source rec area  */ 06140000
                    1,                 /* ..1 record                 */ 06150000
                    80,                /* ..of 80 bytes              */ 06160000
                    sqlInFile );       /* ..from SQL Proc source file*/ 06170000
                                                                        06180000
         if( ferror(sqlInFile) )       /* Handle IO errors           */ 06190000
            issueDataSetReadingError( "DD:SQLIN",errno );               06200000
                                                                        06210000
         else if( feof(sqlInFile) )    /* Handle EOF                 */ 06220000
            moreRecords = No;                                           06230000
                                       /* Discard bytes 73-80, strip */ 06240000
         else                          /* trailing blanks,add NL char*/ 06250000
           { sourceRec[72] = NULLCHAR;                                  06260000
             trimTrailingBlanks( sourceRec );                           06270000
             strncat( sourceRec,"\x25",1 );                             06280000
             strcat( sqlSource.data, sourceRec );                       06290000
             sqlSource.length = strlen(sqlSource.data);                 06300003
           }                                                            06310000
       /* Throw exception if not enough room for next record ...     */ 06320003
       if( moreRecords == Yes && sqlSource.length >((2*1048576)-72) )   06330003
         issueInvalidParmLengthError( "DD:SQLIN",0,((2*1048576)-72) );  06340000
       }                                                                06350000
                                                                        06360000
     if( rc < RETSEV )                                                  06370000
       if( fclose( sqlInFile ) != 0 )                                   06380000
         issueDataSetClosingError( "DD:SQLIN",errno );                  06390000
                                                                        06400000
   } /* end of getSQLsource */                                          06410000
                                                                        06420000
                                                                        06430000
 void connectToLocation( void )        /* Connect to DB2 location    */ 06440000
   /******************************************************************* 06450000
   * Connects to the DB2 location specified in call parm number 4     * 06460000
   *******************************************************************/ 06470000
   { EXEC SQL                                                           06480000
       CONNECT TO :locationName;                                        06490000
                                                                        06500000
     if( SQLCODE != 0 )                                                 06510000
       { issueSqlError( "Connect to location failed" );                 06520000
       }                                                                06530000
   } /* end of connectToLocation */                                     06540000
                                                                        06550000
                                                                        06560003
 void setAuthID( void )                /* Set the current DB2 auth id*/ 06570003
   /******************************************************************* 06580003
   * Changes the current authorization id to the one specified in     * 06590003
   * call parm number 3                                               * 06600003
   *******************************************************************/ 06610003
   { EXEC SQL                                                           06620003
       SET CURRENT SQLID = :authID;                                     06630003
                                                                        06640003
     if( SQLCODE != 0 )                                                 06650003
       { issueSqlError( "Set current SQLID failed" );                   06660003
       }                                                                06670003
   } /* end of setAuthID */                                             06680003
                                                                        06690003
                                                                        06700000
 void callDSNTPSMP( void )             /* Run SQL Procedure Processor*/ 06710000
   /******************************************************************* 06720000
   * Calls the DSNTPSMP (DB2 SQL Procedures Processor)                * 06730000
   *******************************************************************/ 06740000
   { listDSNTPSMPcallParms();                                           06750000
                                                                        06760000
     EXEC SQL                                                           06770000
       CALL SYSPROC.DSNTPSMP( :action,                                  06780000
                              :routineName,                             06790000
                              :sqlSource,                               06800000
                              :bindOptions,                             06810000
                              :compileOptions,                          06820000
                              :precompOptions,                          06830000
                              :prelinkOptions,                          06840000
                              :linkOptions,                             06850000
                              :alterStmt,                       /*@02*/ 06860000
                              :sqlSourceDsn,                            06870000
                              :authID,                          /*@05*/ 06880004
                              :DSNTPSMP_pname,                  /*@05*/ 06890004
                              :outputString );                          06900000
                                                                        06910000
     /***************************************************************** 06920000
     * Analyze status codes from DSNTPSMP                             * 06930000
     *****************************************************************/ 06940000
     printf( "* DSNTPSMP has completed with return code %s\n",          06950000
                outputString );                                         06960000
     if( SQLCODE != 0  &&  SQLCODE != 466 )                    /*+@04*/ 06970000
       { issueSqlError( "Call to DSNTPSMP failed" );                    06980000
       }                                                                06990000
     else if( levelquery != 'Y' )                                       07000000
       { DSNTPSMP_rc = atoi( outputString );                            07010000
         if( SQLCODE == 466 )                                           07020000
           resultSetReturned = Yes;                                     07030000
         else /* SQLCODE == 0 */                                        07040000
           resultSetReturned = No;                                      07050000
       }                                                       /*-@04*/ 07060000
     else /* levelquery == 'Y' */                                       07070003
       { DSNTPSMP_rc=0;                            /* not applicable */ 07080003
         if( SQLCODE == 466 )                                           07090003
           resultSetReturned = Yes;                                     07100003
         else /* SQLCODE == 0 */                                        07110003
           resultSetReturned = No;                                      07120003
         /* Check that level returned matches to the TENTHS digit.   */ 07130003
         if( memcmp( outputString,INTERFACE,3 ) != 0 )                  07140003
           issueInvalidLevelError( outputString );                      07150003
       }                                                                07160003
                                                                        07170000
   } /* end of callDSNTPSMP */                                          07180000
                                                                        07190000
                                                                        07200000
 void listDSNTPSMPcallParms( void )    /* List parms sent to DSNTPSMP*/ 07210000
   /******************************************************************* 07220000
   * Displays the arguments of parameters being passed to DSNTPSMP    * 07230000
   *******************************************************************/ 07240000
   { printf( "****************************************"                 07250000
             "****************************************\n" );            07260000
     printf( "* DSN8ED4 is now invoking the DB2 SQL Procedures "        07270000
             "Processor (SYSPROC.DSNTPSMP)\n" );                        07280000
     printf( "*\n" );                                                   07290000
     printf( "* Location name: %s\n", locationName );                   07300000
     printf( "*\n" );                                                   07310000
     printf( "* Action specified: %s\n", action );                      07320000
     printf( "*\n" );                                                   07330000
     printf( "* SQL Procedure name: %s\n", routineName );               07340000
     printf( "*\n" );                                                   07350000
     printf( "* DB2 Precompiler Options:\n* %s\n", precompOptions );    07360000
     printf( "*\n" );                                                   07370000
     printf( "* Compiler Options:\n* %s\n", compileOptions );           07380000
     printf( "*\n" );                                                   07390000
     printf( "* Prelink Editor Options:\n* %s\n", prelinkOptions );     07400000
     printf( "*\n" );                                                   07410000
     printf( "* Link Editor Options:\n* %s\n", linkOptions );           07420000
     printf( "*\n" );                                                   07430000
     printf( "* DB2 Bind Options:\n* %s\n", bindOptions );              07440000
     printf( "*\n" );                                                   07450000
     if( strlen(alterStmt) > 0 )                                /*@02*/ 07460000
       {                                                        /*@02*/ 07470000
         printf( "* ALTER statement:\n* %s\n", alterStmt );     /*@02*/ 07480000
         printf( "*\n" );                                               07490000
       }                                                        /*@02*/ 07500000
                                                                        07510000
   } /* end of listDSNTPSMPcallParms */                                 07520000
                                                                        07530000
                                                                        07540000
 void processDSNTPSMPresultSet( void ) /* Handle DSNTPSMP result sets*/ 07550000
   /******************************************************************* 07560000
   * Outputs data from the result set returned by DSNTPSMP            * 07570000
   *******************************************************************/ 07580000
   {                                                                    07590000
     /***************************************************************** 07600000
     * Associate a locator with the result set from DSNTPSMP          * 07610000
     *****************************************************************/ 07620000
     associateResultSetLocator();                                       07630000
                                                                        07640000
     /***************************************************************** 07650000
     * Allocate a cursor for the result set                           * 07660000
     *****************************************************************/ 07670000
     if( rc < RETSEV )                                                  07680000
       allocateResultSetCursor();                                       07690000
                                                                        07700000
     /***************************************************************** 07710000
     * Output reports returned in the result set                      * 07720000
     *****************************************************************/ 07730000
     if( rc < RETSEV )                                                  07740000
       writeDSNTPSMPreports();                                          07750000
                                                                        07760000
   } /* end of processDSNTPSMPresultSet */                              07770000
                                                                        07780000
                                                                        07790000
 void associateResultSetLocator(void)  /* Assoc DSNTPSMP RS locator  */ 07800000
   /******************************************************************* 07810000
   * Associates the result set from DSNTPSMP with a result set locator* 07820000
   *******************************************************************/ 07830000
   { EXEC SQL                                                           07840000
       ASSOCIATE                                                        07850000
         LOCATORS( :DSNTPSMP_rs_loc1 )                                  07860000
       WITH PROCEDURE SYSPROC.DSNTPSMP;                                 07870000
                                                                        07880000
     if( SQLCODE != 0 )                                                 07890000
       { issueSqlError( "Associate locator call failed" );              07900000
       }                                                                07910000
                                                                        07920000
   } /* end of associateResultSetLocator */                             07930000
                                                                        07940000
                                                                        07950000
 void allocateResultSetCursor( void )  /* Alloc DSNTPSMP RS cursor   */ 07960000
   /******************************************************************* 07970000
   * Allocates a cursor to the locator for the DSNTPSMP result set    * 07980000
   *******************************************************************/ 07990000
   { EXEC SQL                                                           08000000
       ALLOCATE DSNTPSMP_RS_CSR1                                        08010000
         CURSOR FOR RESULT SET :DSNTPSMP_rs_loc1;                       08020000
                                                                        08030000
     if( SQLCODE != 0 )                                                 08040000
       { issueSqlError( "Allocate result set cursor "                   08050000
                                 "call failed" );                       08060000
       }                                                                08070000
                                                                        08080000
   } /* end of allocateResultSetCursor */                               08090000
                                                                        08100000
                                                                        08110000
 void writeDSNTPSMPreports( void )     /* Print DSNTPSMP report      */ 08120000
   /******************************************************************* 08130000
   * Outputs the reports returned in the result set from DSNTPSMP     * 08140000
   ******************************************************************** 08150000
   * The result set returned by DSNTPSMP contains one or more reports.* 08160000
   *                                                                  * 08170000
   * Within the result set, reports are distinguished from one anoth- * 08180000
   * er by the STEP and FILE columns:                                 * 08190000
   * - STEP refers to the phase (e.g. precompile, compile, bind, etc.)* 08200000
   *   of DSNTPSMP that generated the report.                         * 08210000
   * - FILE distinguishes reports that are generated by the same STEP.* 08220000
   *                                                                  * 08230000
   * Report line data are stored in the LINE column, and arranged ac- * 08240000
   * cording to the sequence number in the SEQN column.               * 08250000
   *                                                                  * 08260000
   * In summary, STEPs contain FILEs, FILEs contain LINEs, and LINEs  * 08270000
   * are ordered according to SEQN (sequence).                        * 08280000
   *******************************************************************/ 08290000
   { short int reportNumber = 1;       /* Sequence number of report  */ 08300000
     char      prevStepName[17];       /* Track step name changes    */ 08310000
     char      prevFileName[9];        /* Track file name changes    */ 08320000
     short int recordLength = 0;       /* Length of record           */ 08330000
                                                                        08340000
     /***************************************************************** 08350000
     * Get the first entry in the result set                          * 08360000
     *****************************************************************/ 08370000
     fetchFromResultSetCursor();                                        08380000
                                                                        08390000
     /***************************************************************** 08400000
     * Allocate an outout DD for the first report                     * 08410000
     *****************************************************************/ 08420000
     if( rc < RETSEV )                                                  08430000
       openReportDataSet( reportNumber );                               08440000
                                                                        08450000
     /***************************************************************** 08460000
     * Save step and file, to monitor for when they change            * 08470000
     *****************************************************************/ 08480000
     if( rc < RETSEV )                                                  08490000
       { strncpy( prevStepName,stepName,17 );                           08500000
         strncpy( prevFileName,fileName,9 );                            08510000
       }                                                                08520000
                                                                        08530000
     /***************************************************************** 08540000
     * Process all rows in the result set                             * 08550000
     *****************************************************************/ 08560000
     while( SQLCODE == 0  &&  rc < RETSEV )                             08570000
       { if( ( strcmp( prevStepName,stepName ) != 0                     08580005
            || strcmp( prevFileName,fileName ) != 0 )                   08590005
         && reportNumber < 6 )                                 /*@06*/  08600005
           /*********************************************************** 08610000
           * If the step or file changes, allocate next report DD     * 08620000
           * up to and including report no. 6                      @06* 08630005
           ***********************************************************/ 08640000
           { closeReportDataSet();                                      08650000
             if( rc < RETSEV )                                          08660000
               openReportDataSet( ++reportNumber );                     08670000
             if( rc < RETSEV )                                          08680000
               { strncpy( prevStepName,stepName,17 );                   08690000
                 strncpy( prevFileName,fileName,9 );                    08700000
               }                                                        08710000
           }                                                            08720000
         /************************************************************* 08730000
         * Write the current report line to the current report DD     * 08740000
         *************************************************************/ 08750000
         if( rc < RETSEV )                                              08760000
           { recordLength                                               08770000
               = fwrite( reportLine,   /* write from reportLine      */ 08780000
                         1,            /* ..a record                 */ 08790000
                         sizeof( reportLine ),                          08800000
                         reportDD );   /* ..into the report data set */ 08810000
           }                                                            08820000
         if( rc < RETSEV )                                              08830000
           { fetchFromResultSetCursor();                                08840000
           }                                                            08850000
       }                                                                08860000
                                                                        08870000
     if( rc < RETSEV )                                                  08880000
       { closeReportDataSet();                                          08890000
       }                                                                08900000
                                                                        08910000
   } /* end of writeDSNTPSMPreports */                                  08920000
                                                                        08930000
                                                                        08940000
 void fetchFromResultSetCursor( void ) /* Read DSNTSPMP RS cursor    */ 08950000
   /******************************************************************* 08960000
   * Reads the cursor for the DSNTPSMP result set                     * 08970000
   *******************************************************************/ 08980000
   { memset( reportLine,' ',256 );                                      08990000
                                                                        09000000
     EXEC SQL                                                           09010000
       FETCH DSNTPSMP_RS_CSR1                                           09020000
       INTO  :stepName,                                                 09030000
             :fileName,                                                 09040000
             :reportLineNumber,                                         09050000
             :reportLine;                                               09060000
                                                                        09070000
     if( SQLCODE != 0  &&  SQLCODE != 100  &&  rc < RETSEV )            09080000
       { issueSqlError( "*** Fetch from "                               09090000
                                 "result set cursor failed" );          09100000
       }                                                                09110000
   } /* end of fetchFromResultSetCursor */                              09120000
                                                                        09130000
                                                                        09140000
 void openReportDataSet                /* Alloc DD for a report      */ 09150000
   ( short int reportNumber            /* - in: Seqeunce number      */ 09160000
   )                                                                    09170000
   /******************************************************************* 09180000
   * Opens the DD REPORTnn, where "nn" is the report number passed in * 09190000
   * and associates it with the file handler reportDD.                * 09200000
   *******************************************************************/ 09210000
   { char          reportDDdcb[36];    /* for generated DCB          */ 09220000
                                                                        09230000
     if( reportNumber < 1 || reportNumber > 99 )                        09240000
        issueInvalidDDnumError( reportNumber );                         09250000
                                                                        09260000
     else                                                               09270000
       { sprintf( reportDDName,        /* Generate DD name REPORTnn  */ 09280000
                  "DD:REPORT%2.2i\0",  /* ..where nn is the sequence */ 09290000
                  reportNumber );      /* ..number of the report     */ 09300000
                                                                        09310000
         if( reportLine[0] == '1' )    /* Does this look like FBA?   */ 09320000
           sprintf( reportDDdcb,       /* Yes: Specify               */ 09330000
                    "wb,recfm=FBA,"    /* ..record output, recfm=fba */ 09340000
                    "lrecl=256" );     /* ..and lrecl 255            */ 09350000
         else                                                           09360000
           sprintf( reportDDdcb,       /* No: Specify                */ 09370000
                    "wb,recfm=FB,"     /* ..record output, recfm=fb  */ 09380000
                    "lrecl=256" );     /* ..and lrecl 255            */ 09390000
                                                                        09400000
         errno = 0;                    /* clear LE errno             */ 09410000
         reportDD = fopen( reportDDName,reportDDdcb );                  09420000
                                                                        09430000
         if( reportDD == NULL )        /* If unable to open data set */ 09440000
           issueDataSetOpeningError( reportDDName,errno );              09450000
       }                                                                09460000
   } /* end of openReportDataSet */                                     09470000
                                                                        09480000
                                                                        09490000
 void closeReportDataSet( void )       /* Dealloc DD for a report    */ 09500000
   /******************************************************************* 09510000
   * Closes the DD associated with the file handler reportDD.         * 09520000
   *******************************************************************/ 09530000
   { if( fclose(reportDD) != 0 )                                        09540000
       issueDataSetClosingError( reportDDName,errno );                  09550000
   } /* end of closeReportDataSet */                                    09560000
                                                                        09570000
                                                                        09580000
 void trimTrailingBlanks               /* Strip off trailing blanks  */ 09590000
   ( char            *string           /* - in: string to be trimmed */ 09600000
   )                                                                    09610000
   /******************************************************************* 09620000
   * Strips trailing blanks from a string                             * 09630000
   *******************************************************************/ 09640000
   { int             i;                                                 09650000
     for( i = strlen(string) - 1; string[i] == ' '; i-- );              09660000
     string[++i] = '\0';                                                09670000
   } /* end of trimTrailingBlanks */                                    09680000
                                                                        09690000
                                                          /*begin @03*/ 09700000
 void stripContinuationCharacter       /* Strip off trailing - or +  */ 09710000
   ( char            *string           /* - in: string to be trimmed */ 09720000
   )                                                                    09730000
   /******************************************************************* 09740000
   * Strips trailing '+' or '-' from a blank-trimmed string           * 09750000
   *******************************************************************/ 09760000
   { int             i;                                                 09770000
     i = strlen(string) - 1;                                            09780000
     if( string[i] == '+' || string[i] == '-' )                         09790000
       string[i] = '\0';                                                09800000
     trimTrailingBlanks( string );                                      09810000
   } /* end of trimstripContinuationCharacter */                        09820000
                                                            /*end @03*/ 09830000
                                                                        09840000
                                                          /*begin @04*/ 09850000
 void processSqlCommit( void )         /* Commit SQL changes         */ 09860000
   /******************************************************************* 09870000
   * Commits the current unit of SQL work                             * 09880000
   *******************************************************************/ 09890000
   { EXEC SQL                                                           09900000
       COMMIT;                                                          09910000
                                                                        09920000
     if( SQLCODE != 0 )                                                 09930000
       { issueSqlError( "*** Commit failed " );                         09940000
       }                                                                09950000
     else                                                               09960000
       { printf( "* SQL changes have been committed\n" );               09970000
       }                                                                09980000
                                                                        09990000
   } /* end of processSqlCommit */                                      10000000
                                                                        10010000
                                                                        10020000
 void processSqlRollback( void )       /* Rollback SQL changes       */ 10030000
   /******************************************************************* 10040000
   * Rolls back the current unit of SQL work                          * 10050000
   *******************************************************************/ 10060000
   { EXEC SQL                                                           10070000
       ROLLBACK;                                                        10080000
                                                                        10090000
     if( SQLCODE != 0 )                                                 10100000
       { issueSqlError( "*** Rollback failed " );                       10110000
       }                                                                10120000
     else                                                               10130000
       { printf( "* SQL changes have been rolled back\n" );             10140000
       }                                                                10150000
                                                                        10160000
   } /* end of processSqlRollback */                                    10170000
                                                            /*end @04*/ 10180000
                                                                        10190000
 void issueDataSetClosingError         /* Handler for ds close error */ 10200000
   ( char            *DDname,          /* - in: name of errant DD    */ 10210000
     int             LEerrno           /* - in: LE diagnostic errno  */ 10220000
   )                                                                    10230000
   /******************************************************************* 10240000
   * Called when a TSO data set cannot be closed                      * 10250000
   *******************************************************************/ 10260000
   { printf( "ERROR: Unable to close %s\n", DDname );                   10270000
     printf( "%s \n",strerror(LEerrno) );                               10280000
     printf( "-----> Processing halted\n" );                            10290000
     rc = RETSEV;                                                       10300000
   } /* end of issueDataSetClosingError */                              10310000
                                                                        10320000
                                                                        10330000
 void issueDataSetOpeningError         /* Handler for ds open error  */ 10340000
   ( char            *DDname,          /* - in: name of errant DD    */ 10350000
     int             LEerrno           /* - in: LE diagnostic errno  */ 10360000
   )                                                                    10370000
   /******************************************************************* 10380000
   * Called when a TSO data set cannot be opened                      * 10390000
   *******************************************************************/ 10400000
   { printf( "ERROR: Unable to open %s\n", DDname );                    10410000
     printf( "%s \n",strerror(LEerrno) );                               10420000
     printf( "-----> Processing halted\n" );                            10430000
     rc = RETSEV;                                                       10440000
   } /* end of issueDataSetOpeningError */                              10450000
                                                                        10460000
                                                                        10470000
 void issueDataSetReadingError         /* Handler for ds read error  */ 10480000
   ( char            *DDname,          /* - in: name of errant DD    */ 10490000
     int             LEerrno           /* - in: LE diagnostic errno  */ 10500000
   )                                                                    10510000
   /******************************************************************* 10520000
   * Called when a TSO data set cannot be read                        * 10530000
   *******************************************************************/ 10540000
   { printf( "ERROR: Unable to read %s\n", DDname );                    10550000
     printf( "%s \n",strerror(LEerrno) );                               10560000
     printf( "-----> Processing halted\n" );                            10570000
     rc = RETSEV;                                                       10580000
   } /* end of issueDataSetReadingError */                              10590000
                                                                        10600000
                                                                        10610000
 void issueInvalidCallParmCountError   /* Handler for parm count err */ 10620000
   ( int argc                          /* - in: no. parms received   */ 10630000
   )                                                                    10640000
   /******************************************************************* 10650000
   * Called when this program is invoked with an inappropriate number * 10660000
   * of call parms.                                                   * 10670000
   *******************************************************************/ 10680000
   { printf( "ERROR: DSN8ED4 was invoked with %i parameters\n",--argc );10690000
     printf( "       - The first three parms (action, routine "         10700000
                      "name, and authid) are required\n" );             10710000
     printf( "       - The fourth parm (location name) "                10720000
                      "is optional\n" );                                10730000
     printf( "-----> Processing halted\n" );                            10740000
     rc = RETSEV;                                                       10750000
   } /* end of issueInvalidCallParmCountError */                        10760000
                                                                        10770000
                                                                        10780000
 void issueInvalidDDnumError           /* Handler for unknown DD seq */ 10790000
   ( short          invalidDDnum       /* - in: invalid DD sequ. no. */ 10800000
   )                                                                    10810000
   /******************************************************************* 10820000
   * Called when the sequence number for a report DD (REPORTnn, where * 10830000
   * "nn" is the sequence number" is less than 1 or greater 99.       * 10840000
   *******************************************************************/ 10850000
   { printf( "ERROR: Invalid sequence "/* Issue error messages       */ 10860000
             "number <%i> specified "  /* ..for DD REPORTnn          */ 10870000
             "for REPORTnn DD\n",      /* ..where nn is the sequence */ 10880000
             invalidDDnum );           /* ..number of the result set */ 10890000
     printf( "-----> Processing halted\n" );                            10900000
     rc = RETSEV;                                                       10910000
   } /* end of issueInvalidDDnumError */                                10920000
                                                                        10930000
                                                                        10940000
 void issueInvalidActionError          /* Handler for unknown action */ 10950000
   ( char *action                      /* - in: action specified     */ 10960000
   )                                                                    10970000
   /******************************************************************* 10980000
   * Called when an unexpected argument is specified for the DB2 SQL  * 10990000
   * Procedures Processor action                                      * 11000000
   *******************************************************************/ 11010000
   { printf( "ERROR: The argument specified for the action "            11020000
                    "parameter is invalid\n",action );                  11030000
     printf( "-----> Processing halted\n" );                            11040000
     rc = RETSEV;                                                       11050000
   } /* end of issueInvalidActionError */                               11060000
                                                                        11070000
                                                                        11080000
 void issueInvalidParmLengthError      /* Handler for parm len error */ 11090000
   ( char *parmName,                   /* - in: identify of parm     */ 11100000
     int minLength,                    /* - in: min valid length     */ 11110000
     int maxLength                     /* - in: max valid length     */ 11120000
   )                                                                    11130000
   /******************************************************************* 11140000
   * Called when the length of an argument specified for a DSNTPSMP   * 11150000
   * parameter (parmName) does not fall within the valid bounds for   * 11160000
   * size (minLength and maxLength) for that parameter                * 11170000
   *******************************************************************/ 11180000
   { printf( "ERROR: The length of the argument specified for the %s "  11190000
                    "parameter\n",parmName );                           11200000
     printf( "       does not fall within the required bounds of %i "   11210000
                    "and %i\n",minLength,maxLength );                   11220000
     printf( "-----> Processing halted\n" );                            11230000
     rc = RETSEV;                                                       11240000
   } /* end of issueInvalidParmLengthError */                           11250000
                                                                        11260003
                                                                        11270003
 void issueInvalidLevelError           /* Handler for wrong DSNTPSMP */ 11280003
   ( char *level                       /* - in: level encountered    */ 11290003
   )                                                                    11300003
   /******************************************************************* 11310003
   * Called when a DSNTPSMP QUERYLEVEL request returns a level not    * 11320003
   * handled by this sample client.                                   * 11330003
   *******************************************************************/ 11340003
   { printf( "ERROR: The DSNTPSMP interface level %s is not "           11350003
                    "supported by this client\n",level );               11360003
     printf( "-----> Processing halted\n" );                            11370003
     rc = RETSEV;                                                       11380003
   } /* end of issueInvalidLevelError */                                11390003
                                                                        11400000
                                                                        11410000
 #pragma linkage(dsntiar, OS)                                           11420000
 void issueSqlError                    /* Handler for SQL error      */ 11430000
   ( char *locMsg                      /* - in: Call location        */ 11440000
   )                                                                    11450000
   /******************************************************************* 11460000
   * Called when an unexpected SQLCODE is returned from a DB2 call    * 11470000
   *******************************************************************/ 11480000
   { struct      error_struct {        /* DSNTIAR message structure  */ 11490000
       short int   error_len;                                           11500000
       char        error_text[10][80];                                  11510000
       }         error_message = {10 * 80};                             11520000
                                                                        11530000
     extern short int dsntiar( struct      sqlca         *sqlca,        11540000
                               struct      error_struct  *msg,          11550000
                               int                       *len );        11560000
                                                                        11570000
     short int   DSNTIARrc;            /* DSNTIAR Return code        */ 11580000
     int         j;                    /* Loop control               */ 11590000
     static int  lrecl = 80;           /* Width of message lines     */ 11600000
                                                                        11610000
     /***************************************************************** 11620000
     * print the locator message                                      * 11630000
     *****************************************************************/ 11640000
     printf( "ERROR: %-80s\n", locMsg );                                11650000
     printf( "-----> Processing halted\n" );                            11660000
                                                                        11670000
     /***************************************************************** 11680000
     * format and print the SQL message                               * 11690000
     *****************************************************************/ 11700000
     DSNTIARrc = dsntiar( &sqlca, &error_message, &lrecl );             11710000
     if( DSNTIARrc == 0 )                                               11720000
       for( j = 0; j <= 10; j++ )                                       11730000
         printf( " %.80s\n", error_message.error_text[j] );             11740000
     else                                                               11750000
       {                                                                11760000
         printf( " *** ERROR: DSNTIAR could not format the message\n" );11770000
         printf( " ***        SQLCODE is %d\n",SQLCODE );               11780000
         printf( " ***        SQLERRM is \n" );                         11790000
         for( j=0; j<sqlca.sqlerrml; j++ )                              11800000
           printf( "%c", sqlca.sqlerrmc[j] );                           11810000
         printf( "\n" );                                                11820000
       }                                                                11830000
                                                                        11840000
     /***************************************************************** 11850000
     * set severe error code                                          * 11860000
     *****************************************************************/ 11870000
     rc = RETSEV;                                                       11880000
                                                                        11890000
   } /* end of issueSqlError */                                         11900000