The List Data Areas (LSTDTAARA) command produces a list of all data areas in a library, revealing their contents. Optionally, it can list only those data areas that contain a given character string.
The other day, while rereading Now What? What to Do When a Programmer Leaves (MC, January 1998), I saw a potential security risk. Suppose a programmer hardcodes his user profile name within a CL program so that only he can access certain privileged functions of the program. Or perhaps the programmer is clever and softcodes his name within a data area.
If the name is hardcoded, a simple run of the Find String with PDM (FNDSTRPDM) command can pinpoint the source code of the programs in question. But if the name is softcoded, you dont have a prayer of finding outunless you have something like my List Data Areas (LSTDTAARA) command. Or suppose you know that a data area in QSYS contains the string V04R02M00, but you cant remember its name. LSTDTAARA can help you there, too. Just download the code from the MC Web site (http://www.midrangecomputing.com/mc/98/11), and youre on your way.
LSTDTAARA prints a list of all character data areas in a given library. Besides printing the name of the data area, LSTDTAARA lists the data areas entire contents, up to the last nonblank character. But thats not all LSTDTAARA can do; you can supply an optional character string for LSTDTAARA to find. In that case, the report lists only those character data areas that contain the string you specified.
For instance, lets say you suspect a programmer has softcoded his user profile name, HERVE, in some data area of library ACCTG. To find out if thats indeed the case, run the following command:
LSTDTAARA LIB(ACCTG) STRING(HERVE)
The LSTDTAARA command has rather simple code. Its CPP, CL program DTA002CL, simply produces a database file with one data area per record, courtesy of the Display Object Description (DSPOBJD) command. The outfile is named DTAARA and placed in QTEMP. Then, it calls RPG III program DTA002RG to generate the listing.
Since the outfile produced by DSPOBJD is defined using QSYS/QADSPOBJ as a model, I coded the RPG III program with QADSPOBJ in the F-spec. Consequently, the CL program needs a way to tie QADSPOBJ (in the RPG III program) to the QTEMP/DTAARA file (they are, actually, one and the same thing). Thats done by using the Override with Database File (OVRDBF) command before calling the RPG program and the Delete Override (DLTOVR) command afterward.
The RPG program begins by calculating the length of the character string you have supplied, and it places that length in field LEN. To calculate the length, it uses the CHEKR op code with a single blank character in Factor 1. Then, it enters a loop in which it reads one record from QADSPOBJ (i.e., one data area name) and calls CL program DTA003CL to retrieve the value of the data area. If DTA003CL cannot retrieve the value, field RTNCDE has a value of *ON. This error condition may occur if the data area is not of type character, for example, or if it was deleted between the moment DSPOBJD generated the outfile and the moment the RPG program reached the record in QADSPOBJ containing the name of the data area.
If the retrieval is successful, the program prints the data area name and contents if
(a) you specified no string to scan, or (b) you did and the string is contained anywhere within the data area.
The actual printing is performed in subroutine PRINT. The subroutine begins by printing a NEWDA record, which writes the name of the data area to the printer and does not advance the paper. Next, it enters a loop, extracting 100 characters at a time and printing that, this time advancing the paper. The result is that only the first 100 characters of the data area value are printed on the same physical line as the data area name. After printing each 100-character chunk, the subroutine finds out if the rest of the data area is all blanks. If it is, the subroutine exits the loop. It also exits the loop whenever the next 100 characters are beyond the 2,000-character mark, which is the maximum length of a character data area.
DTA002RG has one more trick you may want to use in your RPG III programs. You know that RPG IV has the D-specs in which you can define every single field, data structure, array, and table of your program. In an RPG IV program, therefore, you can gather all field definitions and put them in the same place so they arent scattered all over the C-specs as definitions of result fields. RPG III doesnt have D-specs or anything like that, but you can fake them with a subroutine that does nothing but define the fields.
That subroutine is named DCLVAR (for declare variables) in my RPG III programs. Within that subroutine, I code a Z-ADD for numeric fields and a MOVE for alpha fields, initializing the fields to zeros or blanks, respectively. Furthermore, the lines within DCLVAR are sorted alphabetically by field name. And if too many fields share the same characteristics (for instance, many fields represent object names), first I define a pseudo-data-type field such as NAME (as 10 bytes), and then I define all the actual fields by referencing NAME, using the *LIKE DEFN op code. It works like a charm.
Code for this article on the Web at http://www.midrangecomputing.com/mc/98/11
LATEST COMMENTS
MC Press Online