Cool Things: Retrieving Program Information

CL
Typography
  • Smaller Small Medium Big Bigger
  • Default Helvetica Segoe Georgia Times

 

Who writes the commands that IBM forgot to write?

 

Every now and then, I think that there are functions that IBM simply forgot to provide. One example is the inability to do a command like DSPPGM for all programs in a given library. I recently had a need for exactly this functionality. It seemed like a perfect opportunity to create a new utility. In this tip, I'll show you the GETPGMINFO utility.

The GETPGMINFO Command

The GETPGMINFO command is what will allow us to display program information for all programs in a library. This command accepts four parameters as shown below:

 

GETPGMINFO    PGMNAME(library/program) 
                   OUTTYPE(output-type
                   OUTFILE(output-library/output-file)
                   OUTMBR(output-member)

 

The PGMNAME parameter is used to supply the qualified library/program for the command. Note that *ALL can be used for the program name to show all programs in the supplied library. The OUTTYPE parameter is used to identify where the output should be sent. Valid options are * to send the output to the screen, *PRINT to generate a printer file with the results, and *OUTFILE to send the output to the physical file/member identified on the OUTFILE and OUTMBR parameters.

The Code

The key to this utility is the QCLRPGMI API. This API allows us to retrieve the same type of program information that can be displayed using the DSPPGM command. The difference here is that instead of being restricted to a single program, our command will call this API multiple times and send the output to a printer file, a physical file, or the display. The code for this tip is made up of a command, a CL program, an RPGLE program, and a physical file. The source for the CL program is shown below.

 

 

PGM       PARM(&QUALPGM &OUTTYPE &OUTFILE &OUTMBR)

 

 

 

DCL       VAR(&QUALPGM) TYPE(*CHAR) LEN(20)

 

DCL       VAR(&OUTTYPE) TYPE(*CHAR) LEN(8)

 

DCL       VAR(&OUTFILE) TYPE(*CHAR) LEN(20)

 

DCL       VAR(&OUTMBR) TYPE(*CHAR) LEN(10)

 

DCL       VAR(&OUTFLE) TYPE(*CHAR) LEN(10)

 

DCL       VAR(&OUTLIB) TYPE(*CHAR) LEN(10)

 

DCL       VAR(&PGMNAME) TYPE(*CHAR) LEN(10)

 

DCL       VAR(&PGMLIBR) TYPE(*CHAR) LEN(10)

 

 

 

CHGVAR VAR(&PGMNAME) VALUE(%SST(&QUALPGM 1 10))

 

CHGVAR VAR(&PGMLIBR) VALUE(%SST(&QUALPGM 11 10))

 

DSPOBJD   OBJ(&PGMLIBR/&PGMNAME) OBJTYPE(*PGM) +

 

          OUTPUT(*OUTFILE) OUTFILE(QTEMP/PGMS)

 

 

 

IF         COND(&OUTTYPE *EQ '*OUTFILE') THEN(DO)

 

   CHGVAR VAR(&OUTFLE) VALUE(%SST(&OUTFILE 1 10))

 

   CHGVAR VAR(&OUTLIB) VALUE(%SST(&OUTFILE 11 10))

 

ENDDO

 

ELSE CMD(DO)

 

   CHGVAR VAR(&OUTFLE) VALUE('PGMINFO')

 

   CHGVAR VAR(&OUTLIB) VALUE('QTEMP')

 

ENDDO

 

CRTDUPOBJ OBJ(PGMINFO) FROMLIB(*LIBL) OBJTYPE(*FILE) +

 

            TOLIB(&OUTLIB) NEWOBJ(&OUTFLE)

 

MONMSG     MSGID(CPD2104 CPF2130) EXEC(CLRPFM +

 

             FILE(&OUTLIB/&OUTFLE))

 

 

 

CHGPF     FILE(&OUTLIB/&OUTFLE) MAXMBRS(*NOMAX)

 

ADDPFM     FILE(&OUTLIB/&OUTFLE) MBR(&OUTMBR)

 

MONMSG     MSGID(CPF5812 CPF7306) EXEC(CLRPFM +

 

            FILE(&OUTLIB/&OUTFLE) MBR(&OUTMBR))

 

 

 

OVRDBF     FILE(PGMINFO) TOFILE(&OUTLIB/&OUTFLE) +

 

              MBR(&OUTMBR) OVRSCOPE(*JOB)

 

OVRDBF     FILE(QADSPOBJ) TOFILE(QTEMP/PGMS) +

 

             OVRSCOPE(*JOB)

 

 

 

CALL       PGM(GETPGMINFO)

 

 

 

IF COND(&OUTTYPE *EQ '*PRINT') THEN(DO)

 

   RUNQRY QRYFILE((QTEMP/PGMINFO *FIRST)) +

 

            OUTTYPE(*PRINTER)

 

ENDDO

 

IF COND(&OUTTYPE *EQ '*DISPLAY') THEN(DO)

 

RUNQRY     QRYFILE((QTEMP/PGMINFO *FIRST)) +

 

            OUTTYPE(*DISPLAY)

 

ENDDO

 

ENDPGM

 

 

This CL program performs all of the control functions for the command. It first generates a list of program objects matching what was supplied on the PGMNAME parameter. Note that this value can be a single program, a wildcard, or *ALL. Next, the program determines if it needs to create an output file based on the output type identified on the OUTTYPE parameter. Next, the GETPGMINFO RPGLE is used to extract the program information. This program reads through the output of the DSPOBJD command, which uses the format of the IBM file QADSPOBJ. That command was used to extract a list of program objects within the CL program described above. After that, our RPGLE program calls the IBM QCLRPGMI API to extract program information. This API returns a data structure containing the same information that is displayed by the DSPPGM command. The resulting data is written to the PGMINFO file. The layout for that file is shown in the table below.

 

File Layout for the File PGMINFO

Field Name

Type

Length

Description

PINNAME

Char

10

Program Name

PINLIBRARY

Char

10

Program Library

PINOWNER

Char

10

Object Owner

PINATTR

Char

10

Program Attribute (type)

PINCRTDTTM

Char

13

Date/Time Created

PINSRCFILE

Char

10

Source File

PINSRCFLLB

Char

10

Source Library

PINSRCMBR

Char

10

Source Member

PINSRCUPDT

Char

13

Source Update Date/Time

PINOBSRVBL

Char

1

Observable Flag

PINUSRPROP

Char

6

User Profile

PINUSEADAU

Char

1

Use Adopted Authority

 

A few notes on the values in this table: ILE programs do not show any of the source information because of the fact that they are created from a module. The link exists between the source and the module, not the source and the program. The RPGLE program GETPGMINFO is used to repeatedly call the QCLRPGMI API for each program in the list generated by the DSPOBJD command in our CL program.

 

     //------------------------------------------------------------------------

     // Program: GetPgmInfo

     //

      // Description: Retrieve program information using the QCLRPGMI API

     //

     // Copyright 2012 Mike Faust

     //------------------------------------------------------------------------

     FQADSPOBJ if   e             DISK

     Fpgminfo   o a e             DISK

 

     dpep             pr                 EXTPGM('GETPGMINFO')

     d parpgm                       10a

     d parlibr                       10a

 

     dpep             pi

     d parpgm                       10a

     d parlibr                      10a

 

     dRtvPgmInfo       pr                 ExtPgm('QCLRPGMI')

     d OutputData                 32767a   Options(*varsize)

     d Len                           10i 0 Const

     d Format                         8a   Const

     d PgmName                       20a   Const

     d ErrorCode                           LikeDS(ErrorDS)

 

     dPGMI0100         ds                 Qualified

     d BytesReturned                 10i 0

     d BytesAvailable               10i 0

     d Name                          10a

     d Library                       10a

     d Owner                         10a

     d Attribute                     10a

     d CrtDateTime                   13a

     d SrcFile                       10a

     d SrcFileLib                    10a

     d SrcMbr                       10a

     d SrcUpdDateTime               13a

     d Observable                     1a

     d UsrPrfOption                   1a

     d UseAdpAut                     1a

     d LogCmd                         1a

   d AlwRTVCLSRC                   1a

     d FixDec                         1a

     d Text                         50a

     d PgmType                       1a

     d TeraspaceEnabled...

     d                               1a

     d                              58a

     d MinParms                     10i 0

     d MaxParms                     10i 0

     d Size                         10i 0

     d AssocSpcSize                 10i 0

     d StaticStgSize                 10i 0

     d AutoStgSize                  10i 0

     d MICount                       10i 0

     d MIODTCount                   10i 0

     d State                         1a

     d CompilerID                   14a

     d OSCanRunOn                     6a

     d SrtSeqTbl                    10a

     d SrtSeqTblLib                 10a

     d LangID                       10a

     d Domain                         1a

     d ConvRequired                   1a

     d                               20a

     d Optimized                     1a

     d PagingPool                     1a

     d UpdPASA                       1a

     d ClrPASA                       1a

     d PagingAmt                     1a

     d                               18a

     d PEPMod                       10a

     d PEPModLib                     10a

     d ActGrpAttr                   30a

     d ObservInfoCompressed...

     d                               1a

     d RuntimeInfoCompressed...

     d                               1a

     d OSCrtOn                       6a

     d SharedActGrp                   1a

     d AlwUpd                         1a

     d CCSID                         10i 0

     d ModCount                     10i 0

     d SrvPgmCount                   10i 0

     d CopyrightCount               10i 0

     d UnresolveRefCount...

     d                               10i 0

     d OSCrtFor                       6a

     d AlwStaticReinit...

     d                               1a

     d CrtDta                         1a

     d AlwBndSrvPgmLibUpd...

     d                               1a

     d ProfilingData                 10a

     d TeraspaceEnabledModules...

     d                               1a

     d StgMdl                         1a

     d                               87a

 

     dErrorDS        ds                 Qualified

     d BytesProvided                 10i 0 Inz(%Size(ErrorDS))

     d BytesAvailable               10i 0

     d MsgID                         7a

     d                               1a

     d Text                         500a   Varying

 

     dwrkQualPgm       s             20a

 

     /free

 

       read QLIDOBJD;

       dow not %eof();

         wrkQualPgm = ODOBNM + ODLBNM;

         RtvPgmInfo (pgmi0100: 540: 'PGMI0100': wrkQualPgm: ErrorDS);

         if ErrorDS.BytesAvailable = 0;

             clear pgminfor;

             pinNAME = PGMI0100.Name;

             pinLIBRARY = PGMI0100.Library;

             pinOWNER = PGMI0100.Owner;

             pinATTR = PGMI0100.Attribute;

             pinCRTDTTM = PGMI0100.CrtDateTime;

           pinSRCFILE = PGMI0100.SrcFile;

             pinSRCFLLB = PGMI0100.SrcFileLib;

             pinSRCMBR = PGMI0100.SrcMbr;

             pinSRCUPDT = PGMI0100.SrcUpdDateTime;

             pinOBSRVBL = PGMI0100.Observable;

             select;

              when PGMI0100.UsrPrfOption = 'U';

                   pinUSRPROP = '*USER';

               when PGMI0100.UsrPrfOption = 'O';

                   pinUSRPROP = '*OWNER';

             endsl;

             pinUSEADAU = PGMI0100.UseAdpAut;

             write pgminfor;

         endif;

         read QLIDOBJD;

       enddo;

       *inlr = *on;

       return;

 

As you can see, the code here simply loops through the file, calling QCLRPGMI and writing the results to the PGMINFO file. That file is then used to generate either the printed report, physical file, or display output. Figure 1 below shows a sample of the output as generated using *DISPLAY output type.

 

 

Figure 1: This is the output generated by the GETPGMINFO command.

 

This was generated for all programs in the QSYS library. Below is the command that was called to generate this sample:

 

GETPGMINFO PGMNAME(QSYS/*ALL) OUTTYPE(*DISPLAY)  

The "Why"

The reasons why you might want this command are numerous. It may simply be that you want to identify all of the programs in a given library that are owned by a specific user. Possibly, you might want to find every program that uses adopted authority. Whatever your reason, I hope this utility helps to make your job a little easier.

 

 

 

 

BLOG COMMENTS POWERED BY DISQUS

LATEST COMMENTS

Support MC Press Online

$0.00 Raised:
$