23
Sat, Nov
1 New Articles

Library List: Asset or Liability?

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

Virtually all OS/400 commands that manipulate objects can use the library list. Or let me put that even better: Virtually all command parameters that reference objects let you qualify the object in such a way that the object is searched within the library list. The library list is, of course, that facility built into OS/400 that allows you to remove library name qualifiers every time you reference an object. Instead of looking for the object in a given library, the library list searches all libraries within the job’s library list until it finds the object or until it exhausts the library list, whichever happens first.

Figure 1 illustrates the structure of the library list. It has four portions: system, product, current, and user, totaling a maximum of 43 library names. Of these portions, the system is the most important because it houses QSYS, the library in which the operating system lives. In fact, QSYS is so important that you cannot remove it from the system portion of the library list.

I don’t want to go into excessive detail describing what the library list is, does, and cannot do. Rather, I’d like to focus on a particular problem: the potential multiplicity of objects in two or more libraries, when such libraries are in the library list at the same time.

For instance, suppose you call a program named INV657RG whose purpose is to print invoices. INV657RG is supposed to reside in library ACCTG, but a duplicate of the same program is in library DEVELOP, which you use as a “scratch” library while doing code maintenance. Both ACCTG and DEVELOP are in your library list. Which of the two INV657RG programs is executed when you call the program without a library qualifier?

The answer depends on the order in which the library names have been placed in the library list: The system will always pick up the program from the library whose name occurs first in the library list. Since the library list has a vertical organization, “first” means “higher.” Therefore, if you have placed DEVELOP higher than ACCTG within the library list, it will be DEVELOP’s copy of the program that will be executed, not ACCTG’s.

This behavior can be an asset, actually. During the development, maintenance, or debugging stages of your work, you’ll want to execute the copy in DEVELOP. Once the program is ready to be placed into production, you only have to move it from DEVELOP to ACCTG. But you know how it is—even the best policies are ignored or broken, usually by an oversight. This means that sometimes the wrong object may be accessed through the library list. The Find Object in the Library List (FNDOBJLIBL) command can help you determine if that’s the case for a given object.

Figure 2 shows a typical panel presented by FNDOBJLIBL. As you can see, the command determined that INV657RG existed in both ACCTG and DEVELOP, as indicated by the library names highlighted with reverse image.

The standard Work with Objects (WRKOBJ) and Work with Objects using PDM (WRKOBJPDM) commands can perform the same service, but FNDOBJLIBL does something else: It gives you an image of the library list structure.

How It Works

The command (see Figure 3) has no parameters, since all work is performed interactively. When you execute it, ILE program OBJ022@ runs automatically. This program is comprised of two CL modules OBJ022CL (Figure 4) and OBJ023CL (Figure
5). The first thing OJB022CL does is retrieve the job’s library list. There are several ways to do so:

• With the Retrieve Job Attributes (RTVJOBA) command, using parameters SYSLIBL, CURLIB, and USRLIBL

• With the Display Library List (DSPLIBL) command
• With the Display Job (DSPJOB) command, specifying TYPE(*LIBL) I used none of these. RTVJOBA cannot give me the name of the product libraries (if any are present); and DSPLIBL and DSPJOB cannot place their output in CL variables or an outfile—only on the screen or printer—so they are not very reliable after a release upgrade. Instead of these approaches, I created my own command, Retrieve Library List (RTVLIBL), which is described in full in the sidebar, “Retrieving the Library List.” For now, just accept the fact that RTVLIBL retrieves all libraries in the library list in four CL variables—one per portion.

Next, OBJ022CL extracts the names of each individual library from the four strings returned by RTVLIBL. I’ve named the variables &SYSnn (system portion), &PRDnn (product portion), &CURLIB (current library), and &USRnn (user portion). The program then stops to present the panel, waiting for the user to enter an object name and type.

For each of the possible 43 library names, OBJ022CL calls OBJ023CL. This new procedure determines whether the object exists in the given library and returns a display attribute byte—either a hexadecimal 20 (normal video) if the object was not found or a hexadecimal 21 (reverse image) if the object was found. Then it goes back to label AGAIN to redisplay the panel.

Procedure OBJ023CL (see Figure 5) is not very complicated. Essentially, it runs the Check Object (CHKOBJ) command. If the command fails (either the object doesn’t exist or the library doesn’t exist), it returns a hexadecimal 20 (normal video). If the object does exist, it returns a hexadecimal 21. Of course, you may be wondering why I have gone to the trouble of creating this additional procedure. The answer is that I have to perform the same task 43 times in a language that does not support subroutines. Calling an ILE procedure, bound by copy, is the most viable alternative.

The display file OBJ022DF (shown in Figure 6) defines quite a few fields; among them are 43 single-byte fields and 43 ten-byte fields, one of each for each library in the

library list. To avoid defining fields incorrectly, I’ve defined two hidden fields, BYTE and NAME, as hidden fields. They are 1 and 10 bytes long, respectively. Then I define the actual working fields by reference, pointing to either BYTE or NAME as necessary. Notice the use of *SRC within the REFFLD keyword; *SRC means that the referenced field is contained in the same display file.

The display file potentially needs to highlight 43 output fields. I could have done it using indicators, but I feel that would have been too complicated and error-prone, because there’s no direct relationship between an indicator number and the corresponding field name whose display attributes it controls. For instance, I could have assigned indicator 01 to highlight field SYS01 and 02 for SYS02, thereby creating a pretty correspondence (the two digits). But as soon as I reached the product libraries, I’d end up with indicator 16 controlling the attribute of PRD01 and 17 for PRD02. And 18 for the current library. The pretty correspondence would be pretty no more. It’s much easier to control the attributes via 1-byte fields that have names similar to those of the data fields they control, such as SYS01A controlling SYS01.

So, instead, I decided to highlight the output fields using a one-byte program-to- system field, which is to contain the appropriate hexadecimal display attribute value. For example, if you examine the DSPATR keyword for field SYS01 (the output field containing the first library name within the system portion of the library list), you’ll see that, instead of showing RI for reverse image, it shows &SYS01A, the one-byte program- to-system field I have already defined for that purpose. If I want to show SYS01 in reverse image, I assign hexadecimal 21 to SYS01A; conversely, to show it in normal video, I assign hexadecimal 20 to SYS01A.

We have covered a lot of ground examining some coding techniques, and now you have new CL and DDS skills, plus two utility commands you can start using immediately. I hope FNDOBJLIBL helps you realize that the library list is not a foe, but a friend—an old, dear friend indeed.

Reference System API Reference: OS/400 Work Management APIs (SC41-4878-01, QBKAM701)

System portion (15 libraries maximum) Defined by system value QSYSLIBL.

Product portion (2 libraries maximum) In existence while menu or command is active.

Current portion (1 library maximum) Defined by user profile.

User portion (25 libraries maximum) Defined by system value QUSRLIBL or job description.

Figure 1: Structure of the Library List

Phew!




Figure 2: Sample Display of FNDOBJLIBL



Library_List-_Asset_or_Liability-04-00.png 900x589

/*===================================================================*/

/* To compile: */
/* */

/* CRTCMD CMD(XXX/FNDOBJLIBL) PGM(XXX/OBJ022@) + */
/* SRCFILE(XXX/QCMDSRC) TEXT('Find Object in +*/
/* *LIBL') ALLOW(*IPGM *IMOD *INTERACT *EXEC) */
/* */

/* CRTDSPF FILE(XXX/OBJ022DF) SRCFILE(XXX/QDDSSRC) + */
/* TEXT('Display file for FNDOBJLIBL') */
/* */

/* CRTCLMOD MODULE(XXX/OBJ022CL) SRCFILE(XXX/QCLSRC) + */
/* TEXT('PEP for OBJ022@') */
/* */

/* CRTCLMOD MODULE(XXX/OBJ023CL) SRCFILE(XXX/QCLSRC) + */
/* TEXT('Called from OBJ022CL') */
/* */

/* CRTPGM PGM(XXX/OBJ022@) MODULE(XXX/OBJ022CL + */
/* XXX/OBJ023CL) TEXT('CPP for FNDOBJLIBL + */
/* command') */
/* */

/*prerequisite: */
/* */

/* Utility command FWDPGMMSG (see January 1998 issue). */
/* */

/*===================================================================*/

CMD PROMPT('Find Object in *LIBL')

Figure 3: Command FNDOBJLIBL

PGM

DCLF FILE(OBJ022DF)

DCL VAR(&CURLIBL) TYPE(*CHAR) LEN(11)

DCL VAR(&PRDLIBL) TYPE(*CHAR) LEN(22)

DCL VAR(&SYSLIBL) TYPE(*CHAR) LEN(165)

DCL VAR(&USRLIBL) TYPE(*CHAR) LEN(275)

MONMSG MSGID(CPF0000 MCH0000) EXEC(GOTO CMDLBL(ERROR))

/* Retrieve the job's library list */

RTVLIBL JOB(*) SYSLIBL(&SYSLIBL) PRDLIBL(&PRDLIBL) +

CURLIBL(&CURLIBL) USRLIBL(&USRLIBL)

CHGVAR VAR(&SYS01) VALUE(%SST(&SYSLIBL 1 10))

CHGVAR VAR(&SYS02) VALUE(%SST(&SYSLIBL 12 10))

CHGVAR VAR(&SYS03) VALUE(%SST(&SYSLIBL 23 10))

CHGVAR VAR(&SYS04) VALUE(%SST(&SYSLIBL 34 10))

CHGVAR VAR(&SYS05) VALUE(%SST(&SYSLIBL 45 10))

CHGVAR VAR(&SYS06) VALUE(%SST(&SYSLIBL 56 10))

CHGVAR VAR(&SYS07) VALUE(%SST(&SYSLIBL 67 10))

CHGVAR VAR(&SYS08) VALUE(%SST(&SYSLIBL 78 10))

CHGVAR VAR(&SYS09) VALUE(%SST(&SYSLIBL 89 10))

CHGVAR VAR(&SYS10) VALUE(%SST(&SYSLIBL 100 10))

CHGVAR VAR(&SYS11) VALUE(%SST(&SYSLIBL 111 10))

CHGVAR VAR(&SYS12) VALUE(%SST(&SYSLIBL 122 10))

CHGVAR VAR(&SYS13) VALUE(%SST(&SYSLIBL 133 10))

CHGVAR VAR(&SYS14) VALUE(%SST(&SYSLIBL 144 10))

CHGVAR VAR(&SYS15) VALUE(%SST(&SYSLIBL 155 10))

CHGVAR VAR(&PRD01) VALUE(%SST(&PRDLIBL 1 10))

CHGVAR VAR(&PRD02) VALUE(%SST(&PRDLIBL 11 10))

CHGVAR VAR(&CURLIB) VALUE(%SST(&CURLIBL 1 10))

CHGVAR VAR(&USR01) VALUE(%SST(&USRLIBL 1 10))

CHGVAR VAR(&USR02) VALUE(%SST(&USRLIBL 12 10))

CHGVAR VAR(&USR03) VALUE(%SST(&USRLIBL 23 10))

CHGVAR VAR(&USR04) VALUE(%SST(&USRLIBL 34 10))

CHGVAR VAR(&USR05) VALUE(%SST(&USRLIBL 45 10))

CHGVAR VAR(&USR06) VALUE(%SST(&USRLIBL 56 10))

CHGVAR VAR(&USR07) VALUE(%SST(&USRLIBL 67 10))

CHGVAR VAR(&USR08) VALUE(%SST(&USRLIBL 78 10))

CHGVAR VAR(&USR09) VALUE(%SST(&USRLIBL 89 10))

CHGVAR VAR(&USR10) VALUE(%SST(&USRLIBL 100 10))

CHGVAR VAR(&USR11) VALUE(%SST(&USRLIBL 111 10))

CHGVAR VAR(&USR12) VALUE(%SST(&USRLIBL 122 10))

CHGVAR VAR(&USR13) VALUE(%SST(&USRLIBL 133 10))

CHGVAR VAR(&USR14) VALUE(%SST(&USRLIBL 144 10))

CHGVAR VAR(&USR15) VALUE(%SST(&USRLIBL 155 10))

CHGVAR VAR(&USR16) VALUE(%SST(&USRLIBL 166 10))

CHGVAR VAR(&USR17) VALUE(%SST(&USRLIBL 177 10))

CHGVAR VAR(&USR18) VALUE(%SST(&USRLIBL 188 10))

CHGVAR VAR(&USR19) VALUE(%SST(&USRLIBL 199 10))

CHGVAR VAR(&USR20) VALUE(%SST(&USRLIBL 210 10))

CHGVAR VAR(&USR21) VALUE(%SST(&USRLIBL 221 10))

CHGVAR VAR(&USR22) VALUE(%SST(&USRLIBL 232 10))

CHGVAR VAR(&USR23) VALUE(%SST(&USRLIBL 243 10))

CHGVAR VAR(&USR24) VALUE(%SST(&USRLIBL 254 10))

CHGVAR VAR(&USR25) VALUE(%SST(&USRLIBL 265 10))

/* Present panel */
AGAIN:

SNDRCVF RCDFMT(PANEL)

IF COND(&IN03 *OR &IN12) THEN(GOTO +

CMDLBL(END_EXEC))

/* Highlight library where found */

CALLPRC PRC(OBJ023CL) PARM(&OBJ &SYS01 &OBJTYPE &SYS01A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &SYS02 &OBJTYPE &SYS02A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &SYS03 &OBJTYPE &SYS03A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &SYS04 &OBJTYPE &SYS04A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &SYS05 &OBJTYPE &SYS05A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &SYS06 &OBJTYPE &SYS06A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &SYS07 &OBJTYPE &SYS07A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &SYS08 &OBJTYPE &SYS08A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &SYS09 &OBJTYPE &SYS09A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &SYS10 &OBJTYPE &SYS10A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &SYS11 &OBJTYPE &SYS11A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &SYS12 &OBJTYPE &SYS12A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &SYS13 &OBJTYPE &SYS13A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &SYS14 &OBJTYPE &SYS14A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &SYS15 &OBJTYPE &SYS15A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &PRD01 &OBJTYPE &PRD01A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &PRD02 &OBJTYPE &PRD02A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &CURLIB &OBJTYPE &CURLIBA)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &USR01 &OBJTYPE &USR01A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &USR02 &OBJTYPE &USR02A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &USR03 &OBJTYPE &USR03A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &USR04 &OBJTYPE &USR04A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &USR05 &OBJTYPE &USR05A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &USR06 &OBJTYPE &USR06A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &USR07 &OBJTYPE &USR07A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &USR08 &OBJTYPE &USR08A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &USR09 &OBJTYPE &USR09A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &USR10 &OBJTYPE &USR10A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &USR11 &OBJTYPE &USR11A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &USR12 &OBJTYPE &USR12A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &USR13 &OBJTYPE &USR13A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &USR14 &OBJTYPE &USR14A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &USR15 &OBJTYPE &USR15A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &USR16 &OBJTYPE &USR16A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &USR17 &OBJTYPE &USR17A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &USR18 &OBJTYPE &USR18A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &USR19 &OBJTYPE &USR19A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &USR20 &OBJTYPE &USR20A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &USR21 &OBJTYPE &USR21A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &USR22 &OBJTYPE &USR22A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &USR23 &OBJTYPE &USR23A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &USR24 &OBJTYPE &USR24A)

CALLPRC PRC(OBJ023CL) PARM(&OBJ &USR25 &OBJTYPE &USR25A)

GOTO CMDLBL(AGAIN)

END_EXEC:

RETURN

ERROR:

FWDPGMMSG

MONMSG MSGID(CPF0000)

ENDPGM PGM PARM(&OBJ &OBJLIB &OBJTYPE &ATTR)

DCL VAR(&ATTR) TYPE(*CHAR) LEN(1)

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

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

DCL VAR(&OBJTYPE) TYPE(*CHAR) LEN(7)

IF COND(&OBJLIB *EQ ' ') THEN(DO)

CHGVAR VAR(&ATTR) VALUE(X'20')

ENDDO

ELSE CMD(DO)

CHGVAR VAR(&ATTR) VALUE(X'21')

CHKOBJ OBJ(&OBJLIB/&OBJ) OBJTYPE(&OBJTYPE)

MONMSG MSGID(CPF0000) EXEC(DO)

CHGVAR VAR(&ATTR) VALUE(X'20')

ENDDO

ENDDO

ENDPGM A DSPSIZ(24 80 *DS3)
A CA03(03 'Exit')
A CA12(12 'Cancel')
A PRINT

*======================================================================

*

* Define data types.
A R PANEL
A BYTE 1A H
A NAME 10A H

*

* Define display attribute fields.
A CURLIBA R P REFFLD(BYTE *SRC)
A PRD01A R P REFFLD(BYTE *SRC)
A PRD02A R P REFFLD(BYTE *SRC)
A SYS01A R P REFFLD(BYTE *SRC)
A SYS02A R P REFFLD(BYTE *SRC)
A SYS03A R P REFFLD(BYTE *SRC)
A SYS04A R P REFFLD(BYTE *SRC)
A SYS05A R P REFFLD(BYTE *SRC)
A SYS06A R P REFFLD(BYTE *SRC)

Figure 4: CL Program OBJ022CL

Figure 5: CL Program OBJ023CL

A SYS07A R P REFFLD(BYTE *SRC)
A SYS08A R P REFFLD(BYTE *SRC)
A SYS09A R P REFFLD(BYTE *SRC)
A SYS10A R P REFFLD(BYTE *SRC)
A SYS11A R P REFFLD(BYTE *SRC)
A SYS12A R P REFFLD(BYTE *SRC)
A SYS13A R P REFFLD(BYTE *SRC)
A SYS14A R P REFFLD(BYTE *SRC)
A SYS15A R P REFFLD(BYTE *SRC)
A USR01A R P REFFLD(BYTE *SRC)
A USR02A R P REFFLD(BYTE *SRC)
A USR03A R P REFFLD(BYTE *SRC)
A USR04A R P REFFLD(BYTE *SRC)
A USR05A R P REFFLD(BYTE *SRC)
A USR06A R P REFFLD(BYTE *SRC)
A USR07A R P REFFLD(BYTE *SRC)
A USR08A R P REFFLD(BYTE *SRC)
A USR09A R P REFFLD(BYTE *SRC)
A USR10A R P REFFLD(BYTE *SRC)
A USR11A R P REFFLD(BYTE *SRC)
A USR12A R P REFFLD(BYTE *SRC)
A USR13A R P REFFLD(BYTE *SRC)
A USR14A R P REFFLD(BYTE *SRC)
A USR15A R P REFFLD(BYTE *SRC)
A USR16A R P REFFLD(BYTE *SRC)
A USR17A R P REFFLD(BYTE *SRC)
A USR18A R P REFFLD(BYTE *SRC)
A USR19A R P REFFLD(BYTE *SRC)
A USR20A R P REFFLD(BYTE *SRC)
A USR21A R P REFFLD(BYTE *SRC)
A USR22A R P REFFLD(BYTE *SRC)
A USR23A R P REFFLD(BYTE *SRC)
A USR24A R P REFFLD(BYTE *SRC)
A USR25A R P REFFLD(BYTE *SRC) *

* Define panel fields.
A 1 31'Find Object in *LIBL'
A DSPATR(HI)
A 3 2'The library list is as follows:'
A COLOR(BLU)
A 4 2'System:'
A SYS01 R O 4 12REFFLD(NAME *SRC) DSPATR(&SYS01A)
A SYS02 R O 4 23REFFLD(NAME *SRC) DSPATR(&SYS02A)
A SYS03 R O 4 34REFFLD(NAME *SRC) DSPATR(&SYS03A)
A SYS04 R O 4 45REFFLD(NAME *SRC) DSPATR(&SYS04A)
A SYS05 R O 4 56REFFLD(NAME *SRC) DSPATR(&SYS05A)
A SYS06 R O 5 12REFFLD(NAME *SRC) DSPATR(&SYS06A)
A SYS07 R O 5 23REFFLD(NAME *SRC) DSPATR(&SYS07A)
A SYS08 R O 5 34REFFLD(NAME *SRC) DSPATR(&SYS08A)
A SYS09 R O 5 45REFFLD(NAME *SRC) DSPATR(&SYS09A)
A SYS10 R O 5 56REFFLD(NAME *SRC) DSPATR(&SYS10A)
A SYS11 R O 6 12REFFLD(NAME *SRC) DSPATR(&SYS11A)
A SYS12 R O 6 23REFFLD(NAME *SRC) DSPATR(&SYS12A)
A SYS13 R O 6 34REFFLD(NAME *SRC) DSPATR(&SYS13A)
A SYS14 R O 6 45REFFLD(NAME *SRC) DSPATR(&SYS14A)
A SYS15 R O 6 56REFFLD(NAME *SRC) DSPATR(&SYS15A)
A 8 2'Product:'
A PRD01 R O 8 12REFFLD(NAME *SRC) DSPATR(&PRD01A)
A PRD02 R O 8 23REFFLD(NAME *SRC) DSPATR(&PRD02A)
A 10 2'Current:'
A CURLIB R O 10 12REFFLD(NAME *SRC) DSPATR(&CURLIBA)
A 12 2'User:'
A USR01 R O 12 12REFFLD(NAME *SRC) DSPATR(&USR01A)
A USR02 R O 12 23REFFLD(NAME *SRC) DSPATR(&USR02A)
A USR03 R O 12 34REFFLD(NAME *SRC) DSPATR(&USR03A)
A USR04 R O 12 45REFFLD(NAME *SRC) DSPATR(&USR04A)
A USR05 R O 12 56REFFLD(NAME *SRC) DSPATR(&USR05A)
A USR06 R O 13 12REFFLD(NAME *SRC) DSPATR(&USR06A)
A USR07 R O 13 23REFFLD(NAME *SRC) DSPATR(&USR07A)
A USR08 R O 13 34REFFLD(NAME *SRC) DSPATR(&USR08A)
A USR09 R O 13 45REFFLD(NAME *SRC) DSPATR(&USR09A)
A USR10 R O 13 56REFFLD(NAME *SRC) DSPATR(&USR10A)
A USR11 R O 14 12REFFLD(NAME *SRC) DSPATR(&USR11A)
A USR12 R O 14 23REFFLD(NAME *SRC) DSPATR(&USR12A)
A USR13 R O 14 34REFFLD(NAME *SRC) DSPATR(&USR13A)
A USR14 R O 14 45REFFLD(NAME *SRC) DSPATR(&USR14A)
A USR15 R O 14 56REFFLD(NAME *SRC) DSPATR(&USR15A)
A USR16 R O 15 12REFFLD(NAME *SRC) DSPATR(&USR16A)
A USR17 R O 15 23REFFLD(NAME *SRC) DSPATR(&USR17A)
A USR18 R O 15 34REFFLD(NAME *SRC) DSPATR(&USR18A)
A USR19 R O 15 45REFFLD(NAME *SRC) DSPATR(&USR19A)

A USR20 R O 15 56REFFLD(NAME *SRC) DSPATR(&USR20A)
A USR21 R O 16 12REFFLD(NAME *SRC) DSPATR(&USR21A)
A USR22 R O 16 23REFFLD(NAME *SRC) DSPATR(&USR22A)
A USR23 R O 16 34REFFLD(NAME *SRC) DSPATR(&USR23A)
A USR24 R O 16 45REFFLD(NAME *SRC) DSPATR(&USR24A)
A USR25 R O 16 56REFFLD(NAME *SRC) DSPATR(&USR25A)
A 17 2'AA '
A DSPATR(UL) COLOR(BLU)
A 19 2'Enter options, press Enter.'
A COLOR(BLU)
A 21 2'Object:'
A OBJ R B 21 12REFFLD(NAME *SRC) DSPATR(HI)
A 22 2'Type:'
A OBJTYPE 7A B 22 12DSPATR(HI)
A 24 2'F3=Exit F12=Cancel'
A COLOR(BLU)

Figure 6: Display File OBJ022DF

Retrieving the Library List

As the main article explains, none of the three “classical” methods of retrieving the library list works well enough. There is another method, however, which involves the use of an API named QUSRJOBI. This API provides job-related information in a variable (not a user space), but it is a bit difficult to use, as most APIs are. That’s what prompted me to make up a user command as a front-end to the API. The result was RTVLIBL (see Figure A1).

Its parameters are as follows:

JOB: This parameter identifies the job whose library list is to be retrieved. The job name can be fully qualified. It defaults to *, which retrieves the library list of the current job.

SYSLIBL: This parameter returns the system portion of the library list. The program that uses RTVLIBL must use a 165-byte character variable to receive this information.

PRDLIBL: This parameter moves the names of the product libraries into a 22-byte character variable.

CURLIBL: This parameter moves the names of the current library into an 11-byte character variable.

USRLIBL: This parameter moves the names of the user portion of the library list into a 275-byte character variable.

These parameters are not required. If JOB is not specified, you get the library list of the current job. If you don’t use a variable for some of the four return variable parameters, you won’t get that information. For example, you can use RTVLIBL with only the SYSLIBL parameter if you’re interested only in the system portion of the library list.

All four return variable parameters return the library names in a continuous stream, at 11-byte intervals: a 10-byte library name, and a one-byte display attribute. This means that the first library name begins on byte 1, the second library name begins on byte 12 (1 + 11), the third on byte 23 (12 + 11), and so on.

How It Works

The command’s processing program, LIBL006CL (Figure A2) calls API QUSRJOBI. This API is rather complicated, however, and I won’t explain it all. Instead, you may want to look up its description in the System API Reference: OS/400 Work Management APIs referenced at the end of the article. Still, I have used some important coding techniques, which I’d like to show you.

To begin with, QUSRJOBI can use a number of different data formats depending on the kind of information you want to retrieve. For my purposes, I used format JOBI0700, which includes the library list and other information items. This format, however, doesn’t have a

fixed size. Its size depends on the number of library names contained in each of the four portions of the library list being retrieved. Since CL doesn’t support variable-length variables, I placed myself in the worst-case scenario and decided to assume that the library list would have all 43 library names. That turns out to be 473 bytes for the library list, so I rounded it up to 500 before calling the API.

The API error code parameter (the last parameter of this API) returns a message ID and message data if the API ended in error. That may happen, for example, if the job specified does not exist. Therefore, program LIBL006CL finds out if the API returned any data in the error code parameter by examining bytes 5 to 8 of the error code. If they contain anything but hexadecimal zeros, there was an error. In that case, I merely forward the error as an escape message, extracting the message ID from bytes 9 to 15 and the message data from bytes 17 to 96.

If no error was found, I determine how many library names are in each portion, extracting binary values from the receiving variable (&RCVVAR). To retrieve the system portion of the library list, I initialize the offset to 81 and the length to 11 times the number of libraries in the system portion before extracting the library names with a substring (%SST) function. This operation may yield escape message CPF3601 if the user did not use the SYSLIBL parameter of the RTVLIBL command, so I monitor for it in order to ignore it.

The rest of the library list portions are retrieved the same way. Now that I have the offset of the system portion in &OFFSET and its length in &LENGTH, I can calculate the offset of the next portion (product) by adding both, and I can calculate the new length by multiplication. And so on.

One obvious advantage of RTVLIBL (and, implicitly, of QUSRJOBI) is that you can retrieve the library list of any job on the system.

/*===================================================================*/

/* To compile: */
/* */

/* CRTCMD CMD(XXX/RTVLIBL) PGM(XXX/LIBL006CL) + */
/* SRCFILE(XXX/QCMDSRC) TEXT(‘Retrieve + */
/* Library List’) ALLOW(*IPGM *IMOD + */
/* *BPGM *BMOD) */
/* */

/*===================================================================*/

CMD PROMPT(‘Retrieve Library List’)

PARM KWD(JOB) TYPE(Q1) DFT(*) SNGVAL((*)) +

PROMPT(‘Job name’)

Q1: QUAL TYPE(*NAME) LEN(10) EXPR(*YES)

QUAL TYPE(*NAME) LEN(10) EXPR(*YES) PROMPT(‘User +

name’)

QUAL TYPE(*CHAR) LEN(6) RANGE(000000 999999) +

EXPR(*YES) PROMPT(‘Job number’)

PARM KWD(SYSLIBL) TYPE(*CHAR) LEN(165) +

RTNVAL(*YES) PROMPT(‘System portion (165A)’)

PARM KWD(PRDLIBL) TYPE(*CHAR) LEN(22) +

RTNVAL(*YES) PROMPT(‘Product libraries +

(22A)’)

PARM KWD(CURLIBL) TYPE(*CHAR) LEN(11) +

RTNVAL(*YES) PROMPT(‘Current library (11A)’)

PARM KWD(USRLIBL) TYPE(*CHAR) LEN(275) +

RTNVAL(*YES) PROMPT(‘User portion (275A)’) /*===================================================================*/

/* To compile: */
/* */

/* CRTCLPGM PGM(XXX/LIBL006CL) SRCFILE(XXX/QCLSRC) + */
/* TEXT(‘CPP for RTVLIBL command’) */

Figure A1: Command RTVLIBL

/* */

/* Prerequisite: */
/* FWDPGMMSG command, published in the January 1998 issue. */
/* */

/*===================================================================*/

PGM PARM(&QJOBNAM &SYSLIBL &PRDLIBL &CURLIBL +

&USRLIBL)

DCL VAR(&APIERR) TYPE(*CHAR) LEN(96) VALUE(X’00000060’)

DCL VAR(&CURLIBL) TYPE(*CHAR) LEN(11)

DCL VAR(&DTAFMT) TYPE(*CHAR) LEN(8) VALUE(‘JOBI0700’)

DCL VAR(&INTJOBID) TYPE(*CHAR) LEN(16) VALUE(‘ ‘)

DCL VAR(&LENGTH) TYPE(*DEC) LEN(9)

DCL VAR(&MSGDTA) TYPE(*CHAR) LEN(256)

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

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

DCL VAR(&MSGID) TYPE(*CHAR) LEN(7)

DCL VAR(&NBRCURLIB) TYPE(*DEC) LEN(9)

DCL VAR(&NBRPRDLIB) TYPE(*DEC) LEN(9)

DCL VAR(&NBRSYSLIB) TYPE(*DEC) LEN(9)

DCL VAR(&NBRUSRLIB) TYPE(*DEC) LEN(9)

DCL VAR(&OFFSET) TYPE(*DEC) LEN(9)

DCL VAR(&PRDLIBL) TYPE(*CHAR) LEN(22)

DCL VAR(&QJOBNAM) TYPE(*CHAR) LEN(26)

DCL VAR(&RCVVAR) TYPE(*CHAR) LEN(500)

DCL VAR(&RCVVARLEN) TYPE(*CHAR) LEN(4)

DCL VAR(&SYSLIBL) TYPE(*CHAR) LEN(165)

DCL VAR(&USRLIBL) TYPE(*CHAR) LEN(275)

MONMSG MSGID(CPF0000 MCH0000) EXEC(GOTO CMDLBL(ERROR))

/* Retrieve library list */

CHGVAR VAR(%BIN(&RCVVARLEN)) VALUE(500)

CALL PGM(QUSRJOBI) PARM(&RCVVAR &RCVVARLEN +

&DTAFMT &QJOBNAM &INTJOBID &APIERR)

/* If API ends in error, forward to caller */

IF COND(%BIN(&APIERR 5 4) *GT 0) THEN(DO)

SNDPGMMSG MSGID(%SST(&APIERR 9 7)) MSGF(QCPFMSG) +

MSGDTA(%SST(&APIERR 17 80)) MSGTYPE(*ESCAPE)

ENDDO

CHGVAR VAR(&NBRSYSLIB) VALUE(%BIN(&RCVVAR 65 4))

CHGVAR VAR(&NBRPRDLIB) VALUE(%BIN(&RCVVAR 69 4))

CHGVAR VAR(&NBRCURLIB) VALUE(%BIN(&RCVVAR 73 4))

CHGVAR VAR(&NBRUSRLIB) VALUE(%BIN(&RCVVAR 77 4))

/* Extract system portion of library list */

CHGVAR VAR(&OFFSET) VALUE(81)

CHGVAR VAR(&LENGTH) VALUE(&NBRSYSLIB * 11)

IF COND(&LENGTH *GT 0) THEN(DO)

CHGVAR VAR(&SYSLIBL) VALUE(%SST(&RCVVAR &OFFSET &LENGTH))

MONMSG MSGID(CPF3601)

ENDDO

/* Extract product libraries */

CHGVAR VAR(&OFFSET) VALUE(&OFFSET + &LENGTH)

CHGVAR VAR(&LENGTH) VALUE(&NBRPRDLIB * 11)

IF COND(&LENGTH *GT 0) THEN(DO)

CHGVAR VAR(&PRDLIBL) VALUE(%SST(&RCVVAR &OFFSET &LENGTH))

MONMSG MSGID(CPF3601)

ENDDO

/* Extract current library */

CHGVAR VAR(&OFFSET) VALUE(&OFFSET + &LENGTH)

CHGVAR VAR(&LENGTH) VALUE(&NBRCURLIB * 11)

IF COND(&LENGTH *GT 0) THEN(DO)

CHGVAR VAR(&CURLIBL) VALUE(%SST(&RCVVAR &OFFSET &LENGTH))

MONMSG MSGID(CPF3601)

ENDDO

/* Extract user portion of library list */

CHGVAR VAR(&OFFSET) VALUE(&OFFSET + &LENGTH)

CHGVAR VAR(&LENGTH) VALUE(&NBRUSRLIB * 11)

IF COND(&LENGTH *GT 0) THEN(DO)

CHGVAR VAR(&USRLIBL) VALUE(%SST(&RCVVAR &OFFSET &LENGTH))

MONMSG MSGID(CPF3601)

ENDDO

RETURN

ERROR:

FWDPGMMSG

MONMSG MSGID(CPF0000)

ENDPGM

Figure A2: CL Program LIBL006CL

BLOG COMMENTS POWERED BY DISQUS

LATEST COMMENTS

Support MC Press Online

$

Book Reviews

Resource Center

  • SB Profound WC 5536 Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application. You can find Part 1 here. In Part 2 of our free Node.js Webinar Series, Brian May teaches you the different tooling options available for writing code, debugging, and using Git for version control. Brian will briefly discuss the different tools available, and demonstrate his preferred setup for Node development on IBM i or any platform. Attend this webinar to learn:

  • SB Profound WP 5539More than ever, there is a demand for IT to deliver innovation. Your IBM i has been an essential part of your business operations for years. However, your organization may struggle to maintain the current system and implement new projects. The thousands of customers we've worked with and surveyed state that expectations regarding the digital footprint and vision of the company are not aligned with the current IT environment.

  • SB HelpSystems ROBOT Generic IBM announced the E1080 servers using the latest Power10 processor in September 2021. The most powerful processor from IBM to date, Power10 is designed to handle the demands of doing business in today’s high-tech atmosphere, including running cloud applications, supporting big data, and managing AI workloads. But what does Power10 mean for your data center? In this recorded webinar, IBMers Dan Sundt and Dylan Boday join IBM Power Champion Tom Huntington for a discussion on why Power10 technology is the right strategic investment if you run IBM i, AIX, or Linux. In this action-packed hour, Tom will share trends from the IBM i and AIX user communities while Dan and Dylan dive into the tech specs for key hardware, including:

  • Magic MarkTRY the one package that solves all your document design and printing challenges on all your platforms. Produce bar code labels, electronic forms, ad hoc reports, and RFID tags – without programming! MarkMagic is the only document design and print solution that combines report writing, WYSIWYG label and forms design, and conditional printing in one integrated product. Make sure your data survives when catastrophe hits. Request your trial now!  Request Now.

  • SB HelpSystems ROBOT GenericForms of ransomware has been around for over 30 years, and with more and more organizations suffering attacks each year, it continues to endure. What has made ransomware such a durable threat and what is the best way to combat it? In order to prevent ransomware, organizations must first understand how it works.

  • SB HelpSystems ROBOT GenericIT security is a top priority for businesses around the world, but most IBM i pros don’t know where to begin—and most cybersecurity experts don’t know IBM i. In this session, Robin Tatam explores the business impact of lax IBM i security, the top vulnerabilities putting IBM i at risk, and the steps you can take to protect your organization. If you’re looking to avoid unexpected downtime or corrupted data, you don’t want to miss this session.

  • SB HelpSystems ROBOT GenericCan you trust all of your users all of the time? A typical end user receives 16 malicious emails each month, but only 17 percent of these phishing campaigns are reported to IT. Once an attack is underway, most organizations won’t discover the breach until six months later. A staggering amount of damage can occur in that time. Despite these risks, 93 percent of organizations are leaving their IBM i systems vulnerable to cybercrime. In this on-demand webinar, IBM i security experts Robin Tatam and Sandi Moore will reveal:

  • FORTRA Disaster protection is vital to every business. Yet, it often consists of patched together procedures that are prone to error. From automatic backups to data encryption to media management, Robot automates the routine (yet often complex) tasks of iSeries backup and recovery, saving you time and money and making the process safer and more reliable. Automate your backups with the Robot Backup and Recovery Solution. Key features include:

  • FORTRAManaging messages on your IBM i can be more than a full-time job if you have to do it manually. Messages need a response and resources must be monitored—often over multiple systems and across platforms. How can you be sure you won’t miss important system events? Automate your message center with the Robot Message Management Solution. Key features include:

  • FORTRAThe thought of printing, distributing, and storing iSeries reports manually may reduce you to tears. Paper and labor costs associated with report generation can spiral out of control. Mountains of paper threaten to swamp your files. Robot automates report bursting, distribution, bundling, and archiving, and offers secure, selective online report viewing. Manage your reports with the Robot Report Management Solution. Key features include:

  • FORTRAFor over 30 years, Robot has been a leader in systems management for IBM i. With batch job creation and scheduling at its core, the Robot Job Scheduling Solution reduces the opportunity for human error and helps you maintain service levels, automating even the biggest, most complex runbooks. Manage your job schedule with the Robot Job Scheduling Solution. Key features include:

  • LANSA Business users want new applications now. Market and regulatory pressures require faster application updates and delivery into production. Your IBM i developers may be approaching retirement, and you see no sure way to fill their positions with experienced developers. In addition, you may be caught between maintaining your existing applications and the uncertainty of moving to something new.

  • LANSAWhen it comes to creating your business applications, there are hundreds of coding platforms and programming languages to choose from. These options range from very complex traditional programming languages to Low-Code platforms where sometimes no traditional coding experience is needed. Download our whitepaper, The Power of Writing Code in a Low-Code Solution, and:

  • LANSASupply Chain is becoming increasingly complex and unpredictable. From raw materials for manufacturing to food supply chains, the journey from source to production to delivery to consumers is marred with inefficiencies, manual processes, shortages, recalls, counterfeits, and scandals. In this webinar, we discuss how:

  • The MC Resource Centers bring you the widest selection of white papers, trial software, and on-demand webcasts for you to choose from. >> Review the list of White Papers, Trial Software or On-Demand Webcast at the MC Press Resource Center. >> Add the items to yru Cart and complet he checkout process and submit

  • Profound Logic Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application.

  • SB Profound WC 5536Join us for this hour-long webcast that will explore:

  • Fortra IT managers hoping to find new IBM i talent are discovering that the pool of experienced RPG programmers and operators or administrators with intimate knowledge of the operating system and the applications that run on it is small. This begs the question: How will you manage the platform that supports such a big part of your business? This guide offers strategies and software suggestions to help you plan IT staffing and resources and smooth the transition after your AS/400 talent retires. Read on to learn: