home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / viscobv6.zip / vac22os2 / ibmcobol / samples / sdu / dfmacall.c < prev    next >
Text File  |  1997-03-19  |  61KB  |  1,253 lines

  1.  
  2. /**************************************************************************
  3. ****************************  DFMACALL.C  *********************************
  4. ***************************************************************************
  5. *
  6. *                         DFM DataAgent Sample
  7. *
  8. * Module Name: DFMACALL.C
  9. *   This module demonstrates the ability to invoke DFM DataAgent
  10. *   functions from C applications on workstations running SdU.
  11. *
  12. *   If modified, rename and compile it on a workstation using the header
  13. *   files distributed with SdU.
  14. *
  15. * SdU (program no. 5648-02011)
  16. *
  17. * Version: 1.0
  18. * Release: 1.0
  19. *
  20. * Copyright (C)
  21. * International Business Machines Corporation 1997
  22. *
  23. * DISCLAIMER OF WARRANTIES: The following (enclosed) code is sample code
  24. * created by the IBM Corporation.  This sample code is not a part of any
  25. * IBM product and is provided to you solely for the purpose of assisting
  26. * you in the development of your applications.  The code is provided
  27. * "AS IS", without warranty of any kind.  IBM shall not be liable for any
  28. * damages arising out of your use of the sample code, even if they have
  29. * been advised of the possibility of such damages.
  30. *
  31. * The sample program does the following:
  32. *
  33. * 1) Construct a filename and filename suffix from the input parameters.
  34. * 2) Do a DDMOpen for the file or directory to trigger MVS suffix
  35. *    processing.
  36. * 3) Do a DDMClose for the file or directory to terminate processing.
  37. * 4) Do a DDMUnLoadFileFirst and DDMUnLoadFileNext to display a server
  38. *    system file.
  39. *
  40. * COMMAND LINE INVOCATION:
  41. *
  42. *   Note:
  43. *     1. References to "driverletter" represents a driver letter that
  44. *        has been defined to be associated with a server system and optionally, 
  45. *        a logon userid of IBMUSER via the dfmdrive command. In the examples that
  46. *        follow, drive letters r: and s: have been defined by issuing the
  47. *        following dfmdrive commands.
  48. *        dfmdrive assign r: //MVS
  49. *
  50. *        dfmdrive assign s: IBMUSER //MVS
  51. *
  52. *        In this case, MVS is the remote server system, and IBMUSER is
  53. *        the logon userid to MVS. References to MVS and IBMUSER will be
  54. *        used in the following examples.
  55. *
  56. *     2. When the DISPLAY option is specified, the records of a server system
  57. *        file is displayed on the console. To ensure that the data to display
  58. *        is in ASCII format, a FILE_DESCRIPTOR_MAP statement for the server
  59. *        system file to display should be defined. For example, if the
  60. *        possible server system files to display are IBMUSER.DFMXTSO.SYSTSPRT
  61. *        and IBMUSER.DFMQTSO.SYSTSPRT, the following FILE_DESCRIPTOR_MAP
  62. *        statement may be created to ensure that data from these files are
  63. *        converted from EBCDIC to ASCII.
  64. *
  65. *                 FILE_DESCRIPTOR_MAP (
  66. *                      TARGET_SYSTEM (MVS)
  67. *                      TARGET_FILENAME (IBMUSER.DFM*.*)
  68. *                      BASE_DDF(base.ddf)
  69. *                      VIEW_DDF(view.ddf)
  70. *                      )
  71. *
  72. *        The last splat '*' character of the TARGET_FILENAME parameter
  73. *        ensures that the stream of data which represents a DataAgent
  74. *        request (ie. IBMUSER.DFMQTSO.SYSTSPRT,(dfmqtso,u=userID,pgm(dfmqtso),
  75. *        parm()) does not prevent DFM for Windows from converting the
  76. *        server system file data from EBCDIC to ASCII.
  77. *
  78. *        The view.adl and base.adl files are defined as follows:
  79. *
  80. *        view.adl
  81. *        ========  
  82. *            DECLARE
  83. *             BEGIN;
  84. *               ViewRec:
  85. *               SEQUENCE
  86. *                 BEGIN;
  87. *                   Localtxt: CHAR LENGTH (80) CCSID (437);
  88. *                 END;
  89. *             END;
  90. *
  91. *        base.adl
  92. *        ======== 
  93. *            DECLARE
  94. *             BEGIN;
  95. *               BaseRec:
  96. *               SEQUENCE
  97. *                 BEGIN;
  98. *                    Remotetxt: CHAR LENGTH (80) CCSID(500);
  99. *                 END;
  100. *             END;
  101. *
  102. *
  103. *     3. When issuing the TSO requests from dfmacall, data set IBMUSER.DFMXTSO.SYSTSPRT
  104. *        and IBMUSER.DFMXTSO.SYSTSIN should be predefined. Similarly, when issuing
  105. *        a QTSO request, IBMUSER.DFMQTSO.SYSTSPRT should be predefined. These
  106. *        datasets should be defined to have a logical record length of 80 to match
  107. *        the view and base adl record format descriptions examples described above. 
  108. *        Note: a record length mismatch condition between the base/view adl file
  109. *        record format description and the remote/local files may lead to a Translation
  110. *        Error (ie. XLATERM reply message).
  111. *
  112. *   This sample can be invoked in the following formats:
  113. *
  114. *  DFMACALL QTSO  driveletter:         TSOcommandline  [DISPLAY]
  115. *  DFMACALL TSO   driveletter:         [TSOcommandline]  [DISPLAY]
  116. *  DFMACALL AGENT driveletter:[filename]  MVSprocedure[,procedural_parameters]
  117. *         [PGM program_name] [PARM program-parameters] [DISPLAY]
  118. *  DFMACALL START driveletter:         MVSprocedure[,procedural_parameters]
  119. *  DFMACALL       driveletter:filename[,filename_suffix]  [DISPLAY]
  120. *
  121. * The last format is free-form in which MVS parameters can be specified
  122. * in the filename suffix.  Parameters that are relevant to DFM
  123. * DataAgent processing are the following:
  124. *   AGENT(agentname) - Specifies the name of a procedure in SYS1.PROCLIB
  125. *         that provides the JCL for agent processing and, if PGM is
  126. *         omitted, the name of the DataAgent routine (program) to run.
  127. *         Note that procedural parameters can also be specifed.  For
  128. *         example, AGENT(agentname,USER=userID,DSNAME=DS1,...).  If
  129. *         you use the free-form format, remember to specify PARM also.
  130. *   PGM(programname) - Specifies the name of the DataAgent routine.
  131. *   PARM(program_name) - Specifies input parameters to the DataAgent
  132. *                        routine.
  133. *   START(procedurename,procedure parameters) - Specifies the name of an
  134. *         MVS procedure to be started asynchronously.
  135. *   DISPLAY - Displays the result of the call to DFM DataAgent.  In the case of
  136. *         QTSO or TSO the result is the SYSTSPRT file.  In the case of other
  137. *         DataAgents it is the output name returned by the DataAgent routine
  138. *         after successful invocation.  See DFMXSORT for an example.
  139. *         (Note that DISPLAY can be used as a DataAgent name with DFMACALL
  140. *         but not as a TSO command.)
  141. *
  142. *   Examples:
  143. *
  144. *     dfmacall r:ibmuser.a.b
  145. *        ==> Opens and closes MVS file ibmuser.a.b on remote drive r.
  146. *
  147. *     dfmacall r:ibmuser.a.b,agent(dfmxagnt)
  148. *        ==> Opens and closes MVS file ibmuser.a.b invoking agent dfmxagnt.
  149. *
  150. *     dfmacall r:ibmuser.a.b,agent(dfmx0001),pgm(dfmxagnt)
  151. *        ==> Opens and closes MVS file ibmuser.a.b invoking agent dfmx0001
  152. *        ==> with program dfmxagnt.
  153. *
  154. *     dfmacall agent r:ibmuser.a.b dfmxagnt
  155. *        ==> Opens and closes MVS file ibmuser.a.b invoking agent dfmxagnt
  156. *        ==> with default program dfmxagnt and null parameters implied.
  157. *
  158. *     dfmacall agent r:ibmuser.a.b dfmxtso pgm ikjeft01
  159. *        ==> Opens and closes MVS file ibmuser.a.b invoking agent dfmxtso
  160. *        ==> with (APF-authorized) program ikjeft01.  (Equivalent to
  161. *        ==> DFMACALL TSO.)
  162. *
  163. *     dfmacall start s: dfmx0001,dfminit=iefbr14
  164. *        ==> Asynchronously starts procedure dfmx0001 with parameter
  165. *        ==> dfminit set to iefbr14.
  166. *
  167. *     dfmacall qtso   s:  listc   display
  168. *        ==> Calls TSO to list catalog entries and place the results
  169. *        ==> in IBMUSER.DFMQTSO.SYSTSPRT.  No SYSTSIN input file is
  170. *        ==> expected.  The SYSTSPRT file is displayed.
  171. *
  172. *     dfmacall tso   s:
  173. *        ==> Calls TSO to process input file IBMUSER.DFMXTSO.SYSTSIN
  174. *        ==> and put the results in IBMUSER.DFMXTSO.SYSTSPRT.
  175. *
  176. *     dfmacall tso   s:    "profile prefix(ibmuser)"  display
  177. *        ==> After running the command passed it (in this case "profile")
  178. *        ==> it calls TSO to process input file IBMUSER.DFMXTSO.SYSTSIN
  179. *        ==> and put the results in IBMUSER.DFMXTSO.SYSTSPRT. Display the
  180. *        ==> output file.
  181. *
  182. *
  183. * Change Summary:
  184. *  $L0,960724,SJPLMMR: Initial code for SdU support of DFM/MVS DataAgent
  185. *  $P1,970303,SJPLWBN: Increase buffer parameter size from 100 to 255
  186. *                      (PARMLEN).
  187. *  $P2,970314,SJPLTML: DataAgent request is nolonger suppressed when the
  188. *                      DISPLAY option is specified.
  189. *  $P3=970319,SJPLTML: Add missing RM table entries.
  190. *
  191. ***************************************************************************/
  192.  
  193.  
  194. #include  <os2.h>                       /* required for RLIO applications */
  195. #include  <stdio.h>
  196. #include  <string.h>
  197. #include  <memory.h>
  198. #include  <malloc.h>
  199. #include  "dub.h"        /* required master include for RLIO applications */
  200.  
  201. /*-------------------------------------------------------------------------
  202. --                       SYMBOLIC CONSTANTS
  203. --------------------------------------------------------------------------*/
  204. #define FILCLS_SIZE sizeof(OBJLENGTH) + (2 * sizeof(CODEPOINT))
  205. #define FILCLS_NAME ".DDM_FILCLS"
  206. #define RECDATALEN  100
  207. #define RPYMSBFLN   546                    /* reply message buffer length   */
  208. #define PATHLEN     300                    /* path with 45 extra bytes      */
  209. #define PARMLEN     255                    /* arbitrary maximum parm len@P1C*/
  210. #define USPARMLEN   255                    /* arbitrary max user parm len   */
  211. #define MINPQTSO    4                      /* minimum parameters for QTSO   */
  212. #define MAXPQTSO    5                      /* maximum parameters for QTSO   */
  213. #define MINPTSO     3                      /* minimum parameters for TSO    */
  214. #define MAXPTSO     5                      /* maximum parameters for TSO    */
  215. #define MINPAGENT   4                      /* minimum parameters for AGENT  */
  216. #define MAXPAGENT   9                      /* maximum parameters for AGENT  */
  217. #define MINPSTART   4                      /* minimum parameters for START  */
  218. #define MAXPSTART   4                      /* maximum parameters for START  */
  219. #define MINPFF      2                      /* minimum parameters for FF     */
  220. #define MAXPFF      3                      /* maximum parameters for FF     */
  221.  
  222. /*-------------------------------------------------------------------------
  223. --                     LOCAL FUNCTION DECLARATIONS
  224. --------------------------------------------------------------------------*/
  225. int  SpecialOptions(int index, int argc, char* argv[]);
  226. int  CheckRange(int min, int max, int argc, char uarg[PARMLEN]);
  227. VOID DumpBuffer(PDDMOBJECT pAttribute, USHORT Count);
  228. CODEPOINT  ReplyMsg(VOID);
  229. VOID OmitError(VOID);
  230. VOID GeneralError(VOID);
  231. VOID ValueError(char *value);
  232. VOID ParmLenError(char *value);
  233. int  strupper(char *out, char *in, int bufflen);
  234. VOID DisplayBuffer(ULONG count, PDDMRECORD pRcdarea);
  235. VOID DuplicateError(VOID);
  236. VOID HasFileNameError(VOID);
  237. VOID NoFileNameError(VOID);
  238. VOID TooManyError(VOID);
  239. VOID NotEnoughError(VOID);
  240. VOID DisplayHelp(char *helpflag);
  241.  
  242.  
  243. /*-------------------------------------------------------------------------
  244. --                             DFMACALL
  245. --------------------------------------------------------------------------*/
  246.  
  247.     int dummy_filename = 0;      /* Dummy filename flag               */
  248.     int display_filename = 0;    /* Display filename flag             */
  249.     int TSO_retry = 0;           /* TSO error retry flag              */
  250.     int debug = 1;               /* Debug flag: 0 = nothing displayed,*/
  251.                                  /* 1 = filename display, 2 = all of  */
  252.                                  /* the above plus major functions,   */
  253.                                  /* 5 = all the above plus data.      */
  254.     int display_counter = 0;     /* Record display counter            */
  255.     int intrc;                   /* internal return code              */
  256.  
  257.  
  258. main(int argc, char* argv[])
  259. {
  260.     int i;                       /* Loop counter                      */
  261.     int fnlen = 0;               /* Filename length                   */
  262.     int pgmcnt = 0;              /* Number of PGM parm occurrences    */
  263.     int parmcnt = 0;             /* Number of PARM parm occurrences   */
  264.     int data_follows;            /* Data follows in next arg          */
  265.     APIRET SevCode;              /* Severity code (see DUBDEFS.H)     */
  266.     CODEPOINT  LCodePoint;       /* Local Code Point for reply msg    */
  267.  
  268.  
  269.     PDDMRECORD pRecord;
  270.     RECLENGTH  RecordSize;
  271.     PDDMRECAL  pRecAL;
  272.     PDDMRECALK pRecALK;
  273.     RECLENGTH  RecALSize;
  274.     PBYTE      pData;
  275.     HDDMLOAD   UnLoad;            /* File handle for unload           */
  276.     ULONG      RecCount;
  277.     ULONG      DDMMoreDataFlag;
  278.     int        minparms;          /* minimum parameters current cmd   */
  279.     int        maxparms;          /* maximum parameters current cmd   */
  280.  
  281.  
  282.     HDDMFILE FileHandle;
  283.  
  284.  
  285.     /* Filename to be operated on                                     */
  286.     CHAR MVSFilename[PATHLEN];
  287.     CHAR RootName[PATHLEN];        /* Root name for TSO retry         */
  288.     CHAR dummy_name[9] = "NULLFILE";
  289.     CHAR display_name[PATHLEN];
  290.  
  291.     CHAR uarg[PARMLEN];            /* Upper case argument             */
  292.     CHAR usparg[USPARMLEN];        /* Upper case subparameter         */
  293.  
  294.     /******************************************************************/
  295.     /* Determine which command format was used and build the MVS      */
  296.     /* filename and filename suffix accordingly.                      */
  297.     /******************************************************************/
  298.  
  299.  
  300.     RootName[0] = 0;               /* Set TSO root name to null string*/
  301.     switch (argc)
  302.     {  case 1: /* no user arguments */
  303.           NotEnoughError();
  304.           DisplayHelp("N");
  305.           return(SC_SEVERE);
  306.        default:
  307.          /*************************************************************/
  308.          /* 1 or more user arguments--check further                   */
  309.          /*************************************************************/
  310.          /* Convert current user argument to upper case.              */
  311.          if (intrc = strupper(uarg, argv[1], PATHLEN))
  312.            return intrc;
  313.  
  314.  
  315.          if (strcmp(uarg,"QTSO") == 0 |
  316.              strcmp(uarg,"TSO") == 0 ) {
  317.              if (strcmp(uarg,"QTSO") == 0) {
  318.                 /******************************************************/
  319.                 /* QTSO format                                        */
  320.                 /******************************************************/
  321.                 minparms = MINPQTSO;
  322.                 maxparms = MAXPQTSO;
  323.               }
  324.               else {
  325.                 /******************************************************/
  326.                 /* TSO format                                         */
  327.                 /******************************************************/
  328.                 minparms = MINPTSO;
  329.                 maxparms = MAXPTSO;
  330.               }
  331.               if (intrc = CheckRange(minparms,maxparms,argc, uarg) > 0)
  332.                 return(intrc);
  333.  
  334.               /********************************************************/
  335.               /* Set special processing flags                         */
  336.               /********************************************************/
  337.               for (i=minparms; i < argc; i++) {
  338.                     if (intrc = SpecialOptions(i, argc, argv) > 0)
  339.                   return(intrc);
  340.               }
  341.  
  342.               /********************************************************/
  343.               /* Build filename in the format of                      */
  344.               /*  x:fn,agent(dfmqtso,u=userID),pgm(dfmqtso),          */
  345.               /*         parm(...)                                    */
  346.               /*                  -- OR --                            */
  347.               /*  x:fn,agent(dfmxtso,u=userID),pgm(ikjeft01),         */
  348.               /*         parm(...)                                    */
  349.               /* (Note that MVS will append u=userid)                 */
  350.               /********************************************************/
  351.               if (intrc = strupper(MVSFilename,argv[2],PATHLEN))
  352.                 return(intrc);
  353.               fnlen = strlen(MVSFilename);  /* Save true filename len */
  354.               if ( fnlen > 2 | strncmp(&MVSFilename[1],":",1) != 0  ) {
  355.                  HasFileNameError();
  356.                  DisplayHelp(&uarg[0]);
  357.                  return(SC_SEVERE);
  358.               }
  359.               /********************************************************/
  360.               /* Build root filename.                                 */
  361.               /********************************************************/
  362.               if (display_filename) {
  363.                 if (strcmp(uarg,"QTSO") == 0)
  364.                   strcat(MVSFilename,"DFMQTSO.SYSTSPRT");
  365.                 else
  366.                   strcat(MVSFilename,"DFMXTSO.SYSTSPRT");
  367.                 strcpy(RootName,MVSFilename);
  368.               } else {
  369.                 dummy_filename = 1;
  370.                 strcat(MVSFilename,dummy_name);
  371.               } /* endif */
  372.  
  373.               /********************************************************/
  374.               /* Attach filename suffix.                              */
  375.               /********************************************************/
  376.               if (strcmp(uarg,"QTSO") == 0)
  377.                 strcat(MVSFilename,",agent(dfmqtso),parm(");
  378.               else
  379.                 strcat(MVSFilename,",agent(dfmxtso),pgm(ikjeft01),parm(");
  380.  
  381.               /********************************************************/
  382.               /* Concatenate parm field                               */
  383.               /********************************************************/
  384.               if (argc >= 4 ) {
  385.                 if (intrc = strupper(usparg, argv[3], USPARMLEN))
  386.                   return (intrc);
  387.                 if (strcmp(usparg,"DISPLAY") != 0)
  388.                   strcat(MVSFilename,argv[3]);
  389.                 else if (strcmp(uarg,"QTSO") == 0) {
  390.                   /* DFMQTSO requires a parameter field               */
  391.                   OmitError();
  392.                   DisplayHelp(&uarg[0]);
  393.                   return(SC_SEVERE);
  394.                 }
  395.               }
  396.               strcat(MVSFilename,")");   /* Terminate parameter field */
  397.  
  398.          }                                /* End of QTSO/TSO case     */
  399.           else if (strcmp(uarg,"AGENT") == 0) {
  400.               /********************************************************/
  401.               /* AGENT format                                         */
  402.               /********************************************************/
  403.               minparms = MINPAGENT;
  404.               maxparms = MAXPAGENT;
  405.               if (intrc = CheckRange(minparms,maxparms,argc, uarg) > 0)
  406.                 return(intrc);
  407.  
  408.               /********************************************************/
  409.               /* Set special processing flags                         */
  410.               /********************************************************/
  411.               for (i=minparms; i < argc; i++) {
  412.                     if (intrc = SpecialOptions(i, argc, argv) > 0)
  413.                   return(intrc);
  414.               }
  415.  
  416.               /********************************************************/
  417.               /* Build filename in the format of                      */
  418.               /*  x:fn,agent(agentname),pgm(program_name),parm(parms) */
  419.               /********************************************************/
  420.               if (intrc = strupper(MVSFilename,argv[2], PATHLEN))
  421.                 return(intrc);
  422.               fnlen = strlen(MVSFilename);  /* Save true filename len */
  423.               /* Add dummy filename if one wasn't specified           */
  424.               if ( fnlen == 2  & strncmp(&MVSFilename[1],":",1) == 0  ) {
  425.                 dummy_filename = 1;
  426.                 strcat(MVSFilename,dummy_name);
  427.               }
  428.  
  429.               /* Check the filename format for obvious errors.        */
  430.               fnlen = strlen(MVSFilename);  /* Save true filename len */
  431.               if (fnlen < 3 ) {
  432.                 NoFileNameError();
  433.                 DisplayHelp(&uarg[0]);
  434.                 return(SC_SEVERE);
  435.                }
  436.  
  437.               strcat(MVSFilename,",agent(");
  438.               strcat(MVSFilename,argv[3]);
  439.               strcat(MVSFilename,")");
  440.               /********************************************************/
  441.               /* Concatenate optional fields                          */
  442.               /********************************************************/
  443.               if (argc > 4) {
  444.                 /******************************************************/
  445.                 /* Optional parameters are present                    */
  446.                 /******************************************************/
  447.  
  448.                 /******************************************************/
  449.                 /* All but DISPLAY are in format of keyword + value.  */
  450.                 /******************************************************/
  451.                 data_follows = 0;
  452.                 for (i=4; i < argc; i++) {
  453.                   if (!data_follows) {
  454.                     /* Not data object -- process the keyword.        */
  455.                     data_follows = 1;
  456.                     if (intrc = strupper(usparg, argv[i], USPARMLEN))
  457.                       return (intrc);
  458.                     if (strcmp(usparg,"PGM") == 0) {
  459.                          pgmcnt++;
  460.                          strcat(MVSFilename,",pgm(");
  461.                     }
  462.                     else if (strcmp(usparg,"PARM") == 0) {
  463.                          parmcnt++;
  464.                          strcat(MVSFilename,",parm(");
  465.                     }
  466.                     else {                    /* Unidentified keyword?*/
  467.                       /* Make sure it's not a display option          */
  468.                        if (strcmp(usparg,"DISPLAY") != 0 ) {
  469.                          GeneralError();
  470.                          DisplayHelp(&uarg[0]);
  471.                          return(SC_SEVERE);
  472.                        }
  473.                        else
  474.                          data_follows = 0;    /* No following data    */
  475.                     }                         /* End, unidentified kwd*/
  476.                   }                           /* End, even number     */
  477.                   else  {
  478.                     /* Process the keyword's data.                    */
  479.                     data_follows = 0;
  480.                     strcat(MVSFilename,argv[i]);
  481.                     strcat(MVSFilename,")");
  482.                   }                           /* End, data field      */
  483.                 }    /* End of for loop                               */
  484.               }
  485.               /********************************************************/
  486.               /* Ensure no duplicate parameters                       */
  487.               /********************************************************/
  488.               if ( pgmcnt > 1 | parmcnt > 1 ) {
  489.                 DuplicateError();
  490.                 DisplayHelp(&uarg[0]);
  491.                 return(SC_SEVERE);
  492.               }
  493.               /********************************************************/
  494.               /* Ensure AGENT is invoked with a PARM                  */
  495.               /********************************************************/
  496.               if (parmcnt == 0)
  497.                 strcat(MVSFilename,",parm()");
  498.          }                               /* End of AGENT              */
  499.  
  500.          else if (strcmp(uarg,"START") == 0) {
  501.               /********************************************************/
  502.               /* START format                                         */
  503.               /********************************************************/
  504.               minparms = MINPSTART;
  505.               maxparms = MAXPSTART;
  506.               if (intrc = CheckRange(minparms,maxparms,argc, uarg) > 0)
  507.                 return(intrc);
  508.  
  509.               /********************************************************/
  510.               /* Build filename in the format of                      */
  511.               /*     x:fn,start(proc,parms)                           */
  512.               /********************************************************/
  513.               if (intrc = strupper(MVSFilename,argv[2],PATHLEN))
  514.                 return(intrc);
  515.               fnlen = strlen(MVSFilename);
  516.               if ( (fnlen > 2) | (strncmp(&MVSFilename[1],":",1) != 0)  ) {
  517.                 HasFileNameError();
  518.                 DisplayHelp(&uarg[0]);
  519.                 return(SC_SEVERE);
  520.                }
  521.               dummy_filename = 1;
  522.               strcat(MVSFilename,dummy_name);
  523.               strcat(MVSFilename,",start(");
  524.               strcat(MVSFilename,argv[3]);
  525.               strcat(MVSFilename,")");
  526.          }                           /* End of START parameter        */
  527.          else {                      /* None of the above             */
  528.               /********************************************************/
  529.               /* Free-form command otherwise                          */
  530.               /********************************************************/
  531.               /********************************************************/
  532.               /* Check for help request.                              */
  533.               /********************************************************/
  534.               if (strncmp(uarg, "?",1) == 0) {
  535.                 DisplayHelp(&uarg[0]);
  536.                 return(SC_WARNING);
  537.                }
  538.  
  539.               minparms = MINPFF;
  540.               maxparms = MAXPFF;
  541.               if (intrc = CheckRange(minparms,maxparms,argc, uarg) > 0)
  542.                 return(intrc);
  543.               /********************************************************/
  544.               /* Set special processing flags                         */
  545.               /********************************************************/
  546.               for (i=minparms; i < argc; i++) {
  547.                     if (intrc = SpecialOptions(i, argc, argv) > 0)
  548.                   return(intrc);
  549.               }
  550.  
  551.  
  552.               if (intrc = strupper(MVSFilename,argv[1], PATHLEN))
  553.                 return(intrc);
  554.               fnlen = strlen(MVSFilename);  /* Save true filename len */
  555.               if (fnlen < 3) {
  556.                 NoFileNameError();
  557.                 DisplayHelp(&uarg[0]);
  558.                 return(SC_SEVERE);
  559.                }
  560.  
  561.          }                           /* End of free form parameters   */
  562.     }
  563.  
  564.     /******************************************************************/
  565.     /* Begin processing the MVS file                              @P2M*/
  566.     /******************************************************************/
  567.  
  568.     if (debug >= 1)  printf
  569.       ("DFMACALL: Processing filename and filename suffix of %s.\n",
  570.                  MVSFilename);
  571.  
  572.     /****************************************************************/
  573.     /* Open the file                                            @P2M*/
  574.     /****************************************************************/
  575.     SevCode = DDMOpen
  576.             (MVSFilename,                     /* FileName       @P2M*/
  577.              &FileHandle,                     /* FileHandle     @P2M*/
  578.              RELRNBAM,                        /* AccessMethod   @P2M*/
  579.              DDM_GETAI,                       /* AccIntList     @P2M*/
  580.              DDM_UPDATERS,                    /* FileShare      @P2M*/
  581.              NULL,                            /* EABuf          @P2M*/
  582.              NULL                             /* reserved       @P2M*/
  583.             );                                               /* @P2M*/
  584.  
  585.     if (SevCode != SC_NO_ERROR)                              /* @P2M*/
  586.     {                                                        /* @P2M*/
  587.        if (dummy_filename == 0)                              /* @P2M*/
  588.        {                                                     /* @P2M*/
  589.        printf("Error opening file %s\n",MVSFilename);        /* @P2M*/
  590.        printf("Severity code = %u\n",SevCode);               /* @P2M*/
  591.        }                                                     /* @P2M*/
  592.        ReplyMsg();                                           /* @P2M*/
  593.        return(SevCode);                                      /* @P2M*/
  594.  
  595.     }                                                        /* @P2M*/
  596.  
  597.  
  598.     /****************************************************************/
  599.     /* Close the file                                           @P2M*/
  600.     /****************************************************************/
  601.     SevCode = DDMClose                                       /* @P2M*/
  602.             (FileHandle                         /* FileHandle   @P2M*/
  603.             );                                               /* @P2M*/
  604.  
  605.     if (SevCode != SC_NO_ERROR)                              /* @P2M*/
  606.     {                                                        /* @P2M*/
  607.        if (dummy_filename == 0)                              /* @P2M*/
  608.        {                                                     /* @P2M*/
  609.        printf("Error closing file %s\n",MVSFilename);        /* @P2M*/
  610.        printf("Severity code = %u\n",SevCode);               /* @P2M*/
  611.        }                                                     /* @P2M*/
  612.        ReplyMsg();                                           /* @P2M*/
  613.        return(SevCode);                                      /* @P2M*/
  614.     }                                                        /* @P2M*/
  615.  
  616.  
  617.     if (display_filename) {
  618.       /****************************************************************/
  619.       /* Perform unload of records to satisfy display request         */
  620.       /****************************************************************/
  621.  
  622.       /****************************************************************/
  623.       /* Allocate a record buffer                                     */
  624.       /****************************************************************/
  625.       RecALSize = 64000;        /* Try to use a 64K Buffer for records*/
  626.       if ((pRecord = (PDDMRECORD)malloc(RecALSize)) == NULL) {
  627.          /* Not enough storage--make one last try for 32K             */
  628.          RecALSize = RecALSize / 2;                /* Try 32K Buffer  */
  629.          if ((pRecord = (PDDMRECORD)malloc(RecALSize)) == NULL) {
  630.            printf("DFMACALL: Out of memory\n");
  631.            return(SC_SEVERE);
  632.          }
  633.       }
  634.       /****************************************************************/
  635.       /* Unload the first batch of records in rcd number order        */
  636.       /****************************************************************/
  637.       SevCode = 1;
  638.       while (SevCode) {
  639.         SevCode = DDMUnLoadFileFirst
  640.                (MVSFilename,                /* FileName               */
  641.                 &UnLoad,                    /* UnLoadHandle           */
  642.                 0UL,                        /* AccessFlags            */
  643.                 &DDMMoreDataFlag,           /* Flags                  */
  644.                 pRecord,                    /* RecordBuf              */
  645.                 RecALSize,                  /* RecordBufLen           */
  646.                 (CODEPOINT) RECSEQ,         /* UnloadOrder=rcd number */
  647.                 &RecCount                   /* RecCount               */
  648.                );
  649.         if (SevCode > SC_WARNING) {
  650.            printf("DFMACALL: Error on DDMUnLoadFileFirst for %s.\n",
  651.                     MVSFilename);
  652.            printf("Severity code = %u\n",SevCode);
  653.            LCodePoint = ReplyMsg();
  654.            /* Retry TSO unload output file if not tried already.      */
  655.            if (strcmp(MVSFilename,RootName) != 0  &
  656.                LCodePoint == VALNSPRM ) {
  657.              TSO_retry = 1;
  658.              strcpy(MVSFilename,RootName);
  659.            }                                /* End, TSO retry         */
  660.            else {                           /* Permanent error        */
  661.              free(pRecord);
  662.              return(SevCode);
  663.            }                                /* End, permanent error   */
  664.         }     /* End of error from unload file first.                 */
  665.       }       /* End of while no error.                               */
  666.  
  667.       if (SevCode > SC_WARNING) {
  668.         free(pRecord);
  669.         return(SevCode);
  670.       }                                      /* End, unload first err */
  671.  
  672.       if (debug >= 2 )
  673.          printf ("DDMUnLoadFileFirst: %d records in buffer.\n",
  674.                   RecCount);
  675.       if (TSO_retry > 0 ) {
  676.          printf ("\n** The TSO Output File associated with the error is\
  677.  as follows: **\n");
  678.          printf ("**    (Note that its contents may be from a previou\
  679. s run.)      **\n");
  680.       }
  681.  
  682.       DisplayBuffer(RecCount,pRecord);
  683.  
  684.       /****************************************************************/
  685.       /* Unload remaining records in record number order.             */
  686.       /* When DDMMoreDataFlag is 0x00UL then the file handle is       */
  687.       /* invalid and the file will be closed.                         */
  688.       /****************************************************************/
  689.       while (DDMMoreDataFlag == 0x01UL)
  690.         {
  691.            SevCode = DDMUnLoadFileNext
  692.               (UnLoad,                          /* UnLoadHandle       */
  693.                0x0000UL,                        /* Flags              */
  694.                &DDMMoreDataFlag,                /* UnloadFlags        */
  695.                pRecord,                         /* RecordBuf          */
  696.                RecALSize,                       /* RecordBufLen       */
  697.                &RecCount                        /* RecCount           */
  698.               );
  699.           if (SevCode > SC_WARNING) {
  700.              printf("DFMACALL: Error on DDMUnLoadFileNext for %s.\n",
  701.                       MVSFilename);
  702.              printf("Severity code = %u\n",SevCode);
  703.              ReplyMsg();
  704.              free(pRecord);
  705.              return(SevCode);
  706.           }
  707.           if (debug >= 2)
  708.             printf ("DDMUnLoadFileNext: %d records in buffer.\n",
  709.               RecCount);
  710.           DisplayBuffer(RecCount,pRecord);
  711.  
  712.       }                                         /* End of WHILE loop  */
  713.    free(pRecord);
  714.  
  715.     } else {
  716.       /****************************************************************/
  717.       /* No display--just open to trigger DataAgent and then close    */
  718.       /****************************************************************/
  719.  
  720.  
  721.     }
  722.  
  723.  
  724.     return(SC_NO_ERROR);
  725.  
  726. } /* End--sample main */
  727.  
  728.  
  729. /**************************************************************************
  730. ****************************  ReplyMsg  ***********************************
  731. ***************************************************************************
  732. *   Process the reply message if there is a Severity Code other than
  733. *   SC_NO_ERROR;
  734. *
  735. ***************************************************************************/
  736. CODEPOINT   ReplyMsg(VOID)
  737. {
  738.     static BYTE pRpyMsgBuf[RPYMSBFLN];
  739.  
  740.     APIRET     rc;
  741.     CODEPOINT  CodePoint;
  742.     PDDMOBJECT pReplyObject;
  743.     USHORT     index;
  744.  
  745.     /*---------------------------------------------------------------------
  746.     --  The following table contains the count for the number of parameters
  747.     --  expected for each reply message (1st column), and it also contains
  748.     --  the expanded error messages
  749.     --
  750.     -- The first message in the table, KEYUDIRM, has the lowest
  751.     -- code point value.  It is also the first message in a block of
  752.     -- message code points that ends with RECNAVRM.
  753.     --
  754.     -- The next block of message code points (in ascending code point order)
  755.     -- begins with OS2ERRRM and ends with FILERRRM.
  756.     -- The low-order byte is used as the index into this block.
  757.     ----------------------------------------------------------------------*/
  758.     static struct
  759.     {  USHORT   Count;
  760.        BYTE     msg[52];
  761.     } ErrorMsgBuffer[] =
  762.       { 6, "Key Update Not Allowed by Different Index         \0",
  763.         0, "                                                  \0",
  764.         3, "System Command Reply Message                      \0",   /* SYSCMDRM */ /*@P3C*/
  765.         0, "Default Record Error                              \0",
  766.         5, "Cursor Not Selecting a Record Position            \0",
  767.         7, "Invalid Data Record                               \0",
  768.         3, "Duplicate File Name                               \0",
  769.         8, "Duplicate Key Different Index                     \0",
  770.         7, "Duplicate Key Same Index                          \0",
  771.         7, "Duplicate Record Number                           \0",
  772.         3, "End of File                                       \0",
  773.         7, "File is Full                                      \0",
  774.         4, "File in Use                                       \0",
  775.         3, "File Not Found                                    \0",
  776.         6, "File Space Not Available                          \0",
  777.         3, "Manager Level Conflict                            \0",   /* MGRLVLRM */ /*@P3C*/
  778.         4, "File Not Opened                                   \0",   /* FILNOPRM */ /*@P3C*/
  779.         3, "Invalid File Name                                 \0",
  780.         0, "                                                  \0",
  781.         3, "Shadow Exists                                     \0",   /* SHDEXSRM */ /*@P3C*/
  782.         7, "Record Length Mismatch                            \0",
  783.         3, "Storage Class Not Found                           \0",   /* STGNFNRM */ /*@P3C*/
  784.         3, "Management Class Not Found                        \0",   /* MGMNFNRM */ /*@P3C*/
  785.         4, "Manager Dependency Error                          \0",   /* MGRDEPRM */ /*@P3C*/
  786.         0, "                                                  \0",
  787.         3, "Not Authorized to Storage Class                   \0",   /* STGATHRM */ /*@P3C*/
  788.         3, "Not Authorized to Management Class                \0",   /* MGMATHRM */ /*@P3C*/
  789.         2, "Not Authorized to Function                        \0",
  790.         4, "File Open Lock Option Changed                     \0",   /* FILOLORM */ /*@P3C*/
  791.         4, "File Temporarily Not Available                    \0",
  792.         0, "                                                  \0",
  793.         2, "Declare Conflict                                  \0",   /* DCLCNFRM */ /*@P3C*/
  794.         3, "Directory is Temporarily Not Available            \0",   /* DRCTNARM */ /*@P3C*/
  795.         0, "                                                  \0",
  796.         0, "                                                  \0",
  797.         7, "Record Number Out of Bounds                       \0",
  798.         5, "Record Not Found                                  \0",
  799.         0, "                                                  \0",
  800.         0, "                                                  \0",
  801.         0, "                                                  \0",
  802.         0, "                                                  \0",
  803.         0, "                                                  \0",
  804.         0, "                                                  \0",
  805.         3, "Data Class Not Found                              \0",   /* DTANFNRM */ /*@P3C*/
  806.         3, "Invalid Key Length                                \0",
  807.         0, "                                                  \0",
  808.         0, "                                                  \0",
  809.         3, "Not Authorized to Access Method                   \0",
  810.         0, "Invalid Access Method                             \0",
  811.         3, "Permanent Agent Error                             \0",
  812.         6, "Resource Limits Reached on Target System          \0",
  813.         3, "Invalid Base File Name                            \0",
  814.         0, "                                                  \0",
  815.         0, "                                                  \0",
  816.         2, "Not Authorized to Directory                       \0",
  817.         0, "Management Class Conflict                         \0",
  818.         0, "Storage Class Conflict                            \0",
  819.         3, "Existing Condition                                \0",
  820.         4, "Not Authorized to File                            \0",
  821.         6, "Invalid Request                                   \0",
  822.         4, "Invalid Key Definition                            \0",
  823.         0, "                                                  \0",
  824.         5, "Key Update Not Allowed by Same Index              \0",
  825.         8, "Invalid Key Value                                 \0",
  826.         3, "Invalid User                                      \0",   /* INVUSRRM */ /*@P3C*/
  827.         3, "Open Conflict Error                               \0",   /* OPNCNFRM */ /*@P3C*/
  828.         3, "Open Exclusive by Same User                       \0",
  829.         4, "Concurrent Open Exceeds Maximum                   \0",
  830.         4, "Conversational Protocol Error                     \0",
  831.         0, "                                                  \0",
  832.         0, "                                                  \0",
  833.         0, "                                                  \0",
  834.         7, "Record Damaged                                    \0",
  835.         7, "Record in Use                                     \0",
  836.         2, "Command Processing Completed                      \0",   /* CMDCMPRM */ /*@P3C*/
  837.         5, "Data Stream Syntax Error                          \0",
  838.         7, "Update Cursor Error                               \0",
  839.         5, "No Update Intent on Record                        \0",
  840.         3, "Invalid New File Name                             \0",
  841.         3, "Function Not Supported                            \0",
  842.         3, "Parameter Not Supported                           \0",
  843.         4, "Parameter Value Not Supported                     \0",
  844.         4, "Object Not Supported                              \0",
  845.         5, "Command Check                                     \0",
  846.         2, "Duplicate Declared Name                           \0",   /* DUPDCLRM */ /*@P3C*/
  847.         2, "Invalid Declared Name                             \0",   /* DCLNAMRM */ /*@P3C*/
  848.         2, "File Handle Not Found                             \0",
  849.         3, "Directory Full                                    \0",
  850.         3, "Record Inactive                                   \0",
  851.         7, "File Damaged                                      \0",
  852.         4, "Load Records Count Mismatch                       \0",
  853.         3, "Not Authorized to Open Intent for Named File      \0",
  854.         5, "User Attribute Error                              \0",   /* USRATTRM */ /*@P3C*/
  855.         3, "File Closed with Damage                           \0",
  856.         2, "Target Not Supported                              \0",
  857.         5, "Key Value Modified after Cursor was Last Set      \0",
  858.         4, "Change File Attributes Rejected                   \0",   /* CHGFATRM */ /*@P3C*/
  859.         3, "Invalid Directory Name                            \0",   /* DRCNAMRM */ /*@P3C*/
  860.         3, "Directory Not Found                               \0",   /* DRCNFNRM */ /*@P3C*/
  861.         5, "Stream In Use Error                               \0",   /* STRIUSRM */ /*@P3C*/
  862.         7, "Invalid Substream                                 \0",   /* SUBSTRRM */ /*@P3C*/
  863.         0, "Access Intent List Error                          \0",
  864.         3, "Directory In Use                                  \0",   /* DRCIUSRM */ /*@P3C*/
  865.         7, "Stream Damaged                                    \0",   /* STRDMGRM */ /*@P3C*/
  866.         3, "Invalid Directory Entry                           \0",   /* DRCENTRM */ /*@P3C*/
  867.         3, "Duplicate Directory Name                          \0",   /* DUPDRCRM */ /*@P3C*/
  868.         3, "Directory Space Not Available                     \0",   /* DRCSNARM */ /*@P3C*/
  869.         7, "Data Mapping Error                                \0",   /* DTAMAPRM */ /*@P3C*/
  870.         0, "                                                  \0",
  871.         4, "Load Stream Count Mismatch                        \0",   /* LODSTRRM */ /*@P3C*/
  872.         5, "Record Not Available                              \0",
  873.  
  874.      /************ START OF SECOND CODE POINT RANGE *************/
  875.         0, "OS/2 Error                                        \0",
  876.         0, "Data Description File Not Found                   \0",
  877.         0, "Conversion Table Not Found                        \0",
  878.         2, "Translation Error                                 \0",
  879.         0, "                                                  \0",
  880.         2, "Invalid Flag                                      \0",
  881.         0, "                                                  \0",
  882.         2, "Communications Error                              \0",
  883.         0, "                                                  \0",
  884.         0, "                                                  \0",
  885.         0, "                                                  \0",
  886.         0, "                                                  \0",
  887.         0, "                                                  \0",
  888.         0, "                                                  \0",
  889.         0, "                                                  \0",
  890.         0, "                                                  \0",
  891.         2, "Resource Limit Reached in OS/2 V2.0 Source System \0",
  892.         2, "Field Length Error                                \0",
  893.         2, "Address Error                                     \0",
  894.         0, "                                                  \0",
  895.         2, "Function Continuation Error                       \0",
  896.         0, "                                                  \0",
  897.         2, "File Error                                        \0"
  898.       };
  899.  
  900.     /*---------------------------------------------------------------------
  901.     -- For each reply message available, retrieve and display it.
  902.     ----------------------------------------------------------------------*/
  903.     do
  904.     {  /*------------------------------------------------------------------
  905.        -- Get the reply message
  906.        -------------------------------------------------------------------*/
  907.        rc = DDMGetReplyMessage(pRpyMsgBuf, (ULONG)RPYMSBFLN, (ULONG)1);
  908.  
  909.        switch (rc)
  910.        {  case SC_NO_ERROR:      /* All reply messages have been received */
  911.           case SC_WARNING: /* There are more reply messages to be received*/
  912.              break;
  913.           case SC_ERROR:
  914.              printf("   ReplyMsg: reply message buffer is too small -\n");
  915.              printf("              enlarge and recompile ...\n");
  916.              return(rc);
  917.              break;
  918.           case SC_SEVERE:
  919.              printf("   ReplyMsg: Warning: A reply message was requested,\n");
  920.              printf("              but there are none available ...\n");
  921.              return(rc);
  922.              break;
  923.           case SC_ACCESSDAMAGE:
  924.              printf("   ReplyMsg: Error: An invalid reply message buffer\n");
  925.              printf("              address was specified ...\n");
  926.              return(rc);
  927.              break;
  928.           case SC_PERMDAMAGE:
  929.              printf("   ReplyMsg: Severe Error: An unarchitected reply message\n");
  930.              printf("              object was encountered ...\n");
  931.              return(rc);
  932.              break;
  933.           default:
  934.              printf("   ReplyMsg: Unknown return code from DDMGetReplyMessage\n");
  935.              return(rc);
  936.              break;
  937.        } /* endswitch */
  938.  
  939.        /*------------------------------------------------------------------
  940.        -- Get the reply message
  941.        -------------------------------------------------------------------*/
  942.        pReplyObject = (PDDMOBJECT)pRpyMsgBuf;
  943.  
  944.        CodePoint = pReplyObject->cpObject;              /* get code point */
  945.  
  946.  
  947.        /* reset pointer to first parm base */
  948.        pReplyObject = (PDDMOBJECT)((PBYTE)pReplyObject
  949.                                    + (sizeof(CODEPOINT)
  950.                                       + sizeof(OBJLENGTH))
  951.                                   );
  952.  
  953.        /*------------------------------------------------------------------
  954.        -- Calculate the index into the parameter/msg table based on
  955.        -- the codepoint.
  956.        -------------------------------------------------------------------*/
  957.        if (CodePoint <= RECNAVRM)         /* if code point in first block */
  958.           index = (USHORT)(CodePoint - KEYUDIRM);
  959.        else                               /* code point in second block */
  960.           index = (USHORT)
  961.                   ((RECNAVRM - KEYUDIRM + 1) /* number of entries in
  962.                                                 first block */
  963.                    + (CodePoint % 0x0100UL) /* index into second block */
  964.                   );
  965.  
  966.        /* If the index indicates "file not found" and a dummy filename    */
  967.        /* is being used, ignore the error.                                */
  968.        if (index == 13 & dummy_filename == 1 )
  969.          return(SC_NO_ERROR);
  970.  
  971.        /*------------------------------------------------------------------
  972.        -- Begin dissecting the reply message buffer
  973.        -------------------------------------------------------------------*/
  974.        if (ErrorMsgBuffer[index].Count > 0)
  975.        {  printf("RPYMSG: %s\n",ErrorMsgBuffer[index].msg);
  976.           DumpBuffer(pReplyObject, ErrorMsgBuffer[index].Count);
  977.           printf("\n");
  978.        }
  979.  
  980.     } while (rc == SC_WARNING); /* enddo */
  981.   return(CodePoint);
  982.  
  983. } /* ReplyMsg */
  984.  
  985. /**************************************************************************
  986. **************************  DumpBuffer  ***********************************
  987. ***************************************************************************
  988. *
  989. *   For each object in the reply message buffer, print out its contents.
  990. *
  991. ***************************************************************************/
  992. VOID DumpBuffer(PDDMOBJECT  pAttribute,
  993.                 USHORT      Count)
  994. {
  995.     int i;                                  /* Local loop counter  */
  996.     do
  997.     {  if (pAttribute->cbObject == (sizeof(CODEPOINT) + sizeof(OBJLENGTH)))
  998.        {  printf("Null object returned = %x\n",pAttribute->cbObject);
  999.           pAttribute->cpObject = 0;
  1000.        }
  1001.        else
  1002.        {  switch(pAttribute->cpObject)
  1003.           {  case ACCMTHCL:                 /* Access Method Class */
  1004.                 printf("ACCMTHCL = 0x%X\n", *(PCODEPOINT)(pAttribute->pData));
  1005.                 break;
  1006.              case BASFILNM:                 /* Base File Name */
  1007.                printf("BASFILNM = %s\n", pAttribute->pData);
  1008.                 break;
  1009.              case CODPNT:                   /* Code Point */
  1010.                 printf("CODPNT = 0x%X\n", *(PCODEPOINT)(pAttribute->pData));
  1011.                 break;
  1012.              case CSRPOSST:                 /* Cursor Position Status */
  1013.                 printf("CSRPOSST = 0x%hX\n", *(PBYTE)(pAttribute->pData));
  1014.                 break;
  1015.              case DTALCKST:                 /* Data Lock Status */
  1016.                 printf("DTALCKST = 0x%hX\n", *(PBYTE)(pAttribute->pData));
  1017.                 break;
  1018.              case ERRFILNM:                 /* Error File Name */
  1019.                 printf("ERRFILNM = %s\n", pAttribute->pData);
  1020.                 break;
  1021.              case FILNAM:                   /* File Name */
  1022.                 printf("FILNAM = %s\n", pAttribute->pData);
  1023.                 break;
  1024.              case KEYDEFCD:                 /* Key Definition Error Code */
  1025.                 printf("KEYDEFCD = 0x%hX\n", *(PBYTE)(pAttribute->pData));
  1026.                 break;
  1027.              case MAXOPN:                   /* Maximum Number of File Extents
  1028.                                                 Concurrent Opens Allowed */
  1029.                 printf("MAXOPN = %d\n", *(PUSHORT)(pAttribute->pData));
  1030.                 break;
  1031.              case NEWFILNM:                 /* New File Name */
  1032.                 printf("NEWFILNM = %s\n", pAttribute->pData);
  1033.                 break;
  1034.              case PRCCNVCD:         /* Conversational Protocol Error Code */
  1035.                 printf("PRCCNVCD = 0x%hX\n", *(PBYTE)(pAttribute->pData));
  1036.                 break;
  1037.              case RECCNT:                   /* Record Count */
  1038.                 printf("RECCNT = %ld\n", *(PULONG)(pAttribute->pData));
  1039.                 break;
  1040.              case RECNBR:                   /* Record Number */
  1041.                 printf("RECNBR = %ld\n", *(PRECNUM)(pAttribute->pData));
  1042.                 break;
  1043.              case SRVDGN:      {            /* Server Diagnostic Information */
  1044.                 printf("SRVDGN = 0x\n");
  1045.                 for (i=1; i < (pAttribute->cbObject-5); i++) /* 2 byte len, 2 byte codept*/
  1046.                     { if (i % 16 ==0)
  1047.                                   printf("%02X\n", *(PBYTE)(pAttribute->pData+i-1));
  1048.                        else
  1049.                        if (i % 4 ==0)
  1050.                                   printf("%02X ", *(PBYTE)(pAttribute->pData+i-1));
  1051.                        else
  1052.                            printf("%02X", *(PBYTE)(pAttribute->pData+i-1));
  1053.                      }
  1054.                }
  1055.                 break;
  1056.              case SVRCOD:                   /* Severity Code */
  1057.                 printf("SVRCOD = 0x%X\n", *(PCODEPOINT)(pAttribute->pData));
  1058.                 break;
  1059.              case SYNERRCD:                 /* Syntax Error Code */
  1060.                 printf("SYNERRCD = 0x%hX\n", *(PBYTE)(pAttribute->pData));
  1061.                 break;
  1062.              default:
  1063.                 printf("Unknown code point - 0x%X\n",
  1064.                        *(PCODEPOINT)(pAttribute->pData));
  1065.                 break;
  1066.           } /* endswitch */
  1067.        } /* endif */
  1068.  
  1069.        /* go to next object */
  1070.        pAttribute = (PDDMOBJECT)((PBYTE)pAttribute + pAttribute->cbObject);
  1071.  
  1072.     } while(--Count > 0);
  1073.  
  1074. } /* DumpBuffer */
  1075.  
  1076. /**************************************************************************
  1077. ****************************  Error Routines ******************************
  1078. **************************************************************************/
  1079. VOID GeneralError()
  1080. {
  1081.   printf("DFMACALL: Incorrect command line syntax.\n");
  1082. } /* GeneralError */
  1083.  
  1084. VOID OmitError()
  1085. {
  1086.   printf("DFMACALL: A required parameter was omitted.\n");
  1087. }
  1088.  
  1089. VOID TooManyError()
  1090. {
  1091.   printf("DFMACALL: Too many parameters were on the command line.\n");
  1092. }
  1093.  
  1094. VOID NotEnoughError()
  1095. {
  1096.  printf("DFMACALL: Not enough parameters were on the command line.\n");
  1097. }
  1098.  
  1099. VOID HasFileNameError()
  1100. {
  1101.  printf("DFMACALL: Filename is not allowed for QTSO, TSO, or START.\n");
  1102. }
  1103.  
  1104. VOID NoFileNameError()
  1105. {
  1106.  printf("DFMACALL: A filename must be specified.\n");
  1107. }
  1108.  
  1109. VOID ValueError(char *value)
  1110. {
  1111.  printf("DFMACALL: Incorrect parameter value %s.\n",value);
  1112. }
  1113.  
  1114. VOID ParmLenError(char *value)
  1115. {
  1116.  printf("DFMACALL: Parameter %s is too long.\n",value);
  1117. }
  1118.  
  1119. int strupper(char *oarg, char *iarg, int bufflen)
  1120. {
  1121.  /* Convert string to upper case.                                     */
  1122.  int i;
  1123.  if (strlen(iarg) > bufflen) {
  1124.    ParmLenError(iarg);
  1125.    return(SC_SEVERE);
  1126.  }
  1127.  
  1128.  for (i=0; i < strlen(iarg); i++) {
  1129.     oarg[i] = toupper(iarg[i]);
  1130.  }
  1131.  oarg[i] = 0;
  1132.  return (0);
  1133.  
  1134. }
  1135.  
  1136. VOID DuplicateError()
  1137. {
  1138.  printf("DFMACALL: One or more parameters were duplicated.\n");
  1139. }
  1140.  
  1141. VOID  DisplayBuffer(ULONG count, PDDMRECORD pCurrentRecord)
  1142. {
  1143.     /* Display a buffer full of records                                       */
  1144.     ULONG i;                            /* record counter                     */
  1145.     int j;                              /* index to character in record       */
  1146.     int cRecLen;                        /* current record length              */
  1147.     UCHAR c;                            /* current converted character        */
  1148.     UCHAR savechar;                     /* savearea for trailing character    */
  1149.  
  1150.  
  1151.          for (i=1; i <= count; i++) {
  1152.            cRecLen = pCurrentRecord->cbRecord - sizeof(pCurrentRecord->cbRecord)
  1153.                           - sizeof(pCurrentRecord->cpRecord);
  1154.            /*******************************************************************/
  1155.            /* Replace all instances of non-printable characters,              */
  1156.            /*******************************************************************/
  1157.            /* Make sure the string is printable and                           */
  1158.            /* make sure that there is no 0 in the middle of string.           */
  1159.            for (j=0; j < cRecLen; j++) {
  1160.              if (!(c = pCurrentRecord->pRecord[j]))
  1161.                pCurrentRecord->pRecord[j] = ' ';  /* Replace x00 with blank   */
  1162.              else if (!isprint(c))
  1163.                pCurrentRecord->pRecord[j] = '.';  /* Make nonprintable a "."  */
  1164.            }                                      /* End of for j= loop       */
  1165.            savechar = pCurrentRecord->pRecord[cRecLen]; /* save trailing char */
  1166.            pCurrentRecord->pRecord[cRecLen] = '\0';
  1167.  
  1168.            if (debug >= 5) {
  1169.              display_counter++;
  1170.              printf ("Displaying record %d with length %d:\n",
  1171.                       display_counter,cRecLen);
  1172.            }
  1173.            printf ("%s\n",pCurrentRecord->pRecord);
  1174.            pCurrentRecord->pRecord[cRecLen] = savechar;  /* restore trailing   */
  1175.            pCurrentRecord = (PDDMRECORD)  (pCurrentRecord->pRecord + cRecLen);
  1176.          }
  1177.  
  1178. }
  1179.  
  1180.  
  1181.      SpecialOptions(int index, int argc, char  *argv[])
  1182. {
  1183.  CHAR uarg[PARMLEN];            /* Upper case argument               */
  1184.   /* Check for special processing options.                           */
  1185.   if (intrc = strupper(uarg, argv[index], PARMLEN))
  1186.     return(intrc);
  1187.   if (strcmp(uarg,"DISPLAY") == 0)
  1188.     display_filename = 1;
  1189.  
  1190.  return(0);
  1191. }         /* End of SpecialOptions  */
  1192.  
  1193.      CheckRange(int minparms, int maxparms, int argc, char uarg[PARMLEN])
  1194. {
  1195.  /* Ensure number of parameters is reasonable for the command   */
  1196.  
  1197.     /********************************************************/
  1198.     /* Ensure enough parameters                             */
  1199.     /********************************************************/
  1200.     if (argc < minparms) {
  1201.       NotEnoughError();
  1202.       DisplayHelp(&uarg[0]);
  1203.       return(SC_SEVERE);
  1204.     }
  1205.  
  1206.     /********************************************************/
  1207.     /* Ensure no leftover parameters                        */
  1208.     /********************************************************/
  1209.     if (argc > maxparms) {
  1210.       TooManyError();
  1211.       DisplayHelp(&uarg[0]);
  1212.       return(SC_SEVERE);
  1213.     }
  1214.  
  1215. return(0);
  1216.  
  1217. }
  1218.  
  1219.  
  1220. /**********************************************************************
  1221. ****************************  DisplayHelp *****************************
  1222. ***********************************************************************
  1223. *   Display the correct syntax for invoking this function.
  1224. *
  1225. **********************************************************************/
  1226. VOID DisplayHelp(char *fullhelp)
  1227. {
  1228. if (strncmp(fullhelp,"?",1) == 0) {
  1229.   /* Print full help text.                                           */
  1230.   printf("Correct syntax:                                             \n\n");
  1231.   printf("  DFMACALL QTSO  driveletter:  TSOcommandline  [DISPLAY]      \n");
  1232.   printf("  DFMACALL TSO   driveletter:  [TSOcommandline] [DISPLAY]     \n");
  1233.   printf("  DFMACALL AGENT driveletter:[filename] MVSproc[,proc_parms]  \n");
  1234.   printf("     [PGM prog_name] [PARM prog_parms] [DISPLAY]              \n");
  1235.   printf("  DFMACALL START driveletter:    MVSproc[,proc_parms]         \n");
  1236.   printf("  DFMACALL driveletter:filename[,filename_suffix] [DISPLAY] \n\n");
  1237.   printf(" Examples:                                             \n\n");
  1238.   printf("   dfmacall qtso  s: listc  display                      \n");
  1239.   printf("   dfmacall tso   s:        display                      \n");
  1240.   printf("   dfmacall agent r:ibmuser.a.b  dfmxagnt                \n");
  1241.   printf("   dfmacall agent r:ibmuser.a.b  dfmxtso                 \n");
  1242.   printf("           pgm ikjeft01 parm listc                       \n");
  1243.   printf("   dfmacall start s:          dfmx0001,dfminit=iefbr14   \n");
  1244.   printf("   dfmacall r:ibmuser.a.b,agent(dfmxagnt),parm(hello)    \n");
  1245.   printf("   dfmacall r:ibmuser.a.b,agent(dfmx0001),pgm(dfmxagnt)\n\n");
  1246. }
  1247. else {
  1248.   /* Print clue for getting correct help text.                          */
  1249.   printf("DFMACALL: Enter DFMACALL ? to get the correct command syntax. \n\n");
  1250. }
  1251. }
  1252.