29
Fri, Nov
0 New Articles

JWSPLF: A Better WRKSPLF Utility

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

Are you looking for a particular spool file? Do you want to find, archive, and delete a group of reports? Do you need a shortcut to your spool commands? The JWSPLF command, a utility much like IBM’s Work with Spooled Files (WRKSPLF) command, can meet all these needs and more. JWSPLF does everything that the standard WRKSPLF command does and gives you a whole host of additional useful features:

• You can filter spool files by user name and/or by output queue.
• You can limit the list of spool files to those with data values (spool file name, job name, date, user, and user data) that match a value you enter.

• You can reposition the list of spool files by spool file name.
• You can use options not found in WRKSPLF, such as duplicate, copy into database, and archive.

• You can create additional user options with PDM-like runtime parameter insertion.
• You can repeat a single option from a selected file to the end of the list. JWSPLF is a powerful replacement for IBM’s WRKSPLF command and, as Figure 1 shows, features the same user interface.

There is a lot of code to this utility, far too much to print here. You can download the source code from the Midrange Computing Web site at www.midrangecomputing.com/mc/. However, I’d like to briefly describe a few of the techniques I used to build JWSPLF.

Faster Insert and Retrieve Operations with User Indexes

JWSPLF makes heavy use of an object type with which you may not be familiar—the user index. In the past, these objects were only available to system programs. They were designed to give the best performances in insert and retrieve operations and use less of the system’s resources. Now application programs can use user indexes as well.

User indexes allow data storage and search functions based on a key but differ from database keyed files in that they have only one unformatted data field, rather than externally described fields. The first portion of this field is the key, whose length you determine when you create the index. The remaining part contains the data. The maximum length of each index entry is now 2,000 bytes (it was 120 bytes in earlier releases).

There are two ways to access user indexes. The first is to use a set of APIs, as documented in the manual OS/400 Object APIs. The second way is to use machine interface (MI) instructions (shown in Figure 2), which can be referenced as functions in ILE languages. In addition, you can use one user index CL command—Delete User Index (DLTUSRIDX)—as well as any CL commands that work with objects of any type, such as Create Duplicate Object (CRTDUPOBJ). For more information about user indexes, see
“Putting User Indexes into Practice” (MC, October 1998) and “Applying User Index APIs” (MC, February 1996).

Since JWSPLF relies heavily on user indexes, I wrote procedure JWUSIDX, which performs every function needed. This same standard procedure can then be used in many other applications.

Figure 3 contains the code needed to retrieve index entries. The technique used for the other index operations is similar. As seen in Section A, I’ve prototyped the Find Index Entries (_FNDINXEN) MI function. Note that all parameters are pointers. The first parameter references the area in the calling program where the retrieved entries will be stored. This can be either a field or an array that contains up to 4,095 entries; the actual number of entries that must be retrieved by the instruction must be indicated in another parameter, as I will explain.

The second parameter is a system pointer that references the user index. The system pointer to an object can be located with one of the available ILE functions, which is derived from the basic MI instruction called Resolve System Pointer (RSLVSP). These functions receive object name, object type, and (by option) the system pointer to the library; the functions then return the pointer to the requested object. This pointer stores the virtual address of the object and must be used as is. If you try to manipulate it, the pointer will be invalidated by the machine and will become inoperative. If you want to resolve a pointer for a user index located in a specific library other than QTEMP, you must pass to the function a system pointer for the library, as I will show you. If you are using the QTEMP library, you can retrieve the pointer and use it.

A QTEMP library, as we know, is automatically created for each job when the job starts and deleted when it ends. However, the operating system gives the QTEMP library an internal, unique name that can be referenced directly by using a pointer stored in a system work area known as Process Communication Object (PCO). That way the ILE programmer can use a built-in function called _PCOPTR to get the pointers to QTEMP and *CURLIB directly from PCO. You can use the Dump System Object (DMPSYSOBJ *PCS) command and see the location of the pointers to QTEMP and *CURLIB within the PCO at offsets x’000040’ and x’000070’. Figure 3, Section B, contains the sample code needed to get these pointers using the _PCOPTR function. The returned part of the PCO pointer is redefined in RPG as an array of 16-byte pointers so that QTEMP is the fifth element and *CURLIB is the eighth. After __PCOPTR executes, the Ctx@ pointer is evaluated to address QTEMP or the current library.

If the user index is in a specific library, you must first resolve the library’s pointer. Figure 3, Section C, shows the code for this function. Note that the object’s type must be indicated in hexadecimal (for example, the hex code for a library is x’0401’). Use the QLICVTTP API to convert symbolic names (if they are unknown) to hex MI names or simply dump the object with the Dump Object (DMPOBJ) command. Because no special authority can be set with this instruction, the ObjAuth parameter should be initialized with x’0000’. When the function is complete, the Ctx@ field will contain the resolved pointer for the requested library. At this point, you can resolve the pointer for the user index (type x’0E0A’) into Idx@ and pass the pointer to the _FNDINXEN function (see Figure 3, Section D).

The third parameter, Inx_opt@, references a data structure with the find options. This structure has four subfields. The first (inx_opt_rule) indicates how entries should be retrieved; for sequential access, retrieval may begin with the first or last entry; keyed access, however, allows random retrieval. The second (inx_opt_argl) contains the key

length, while the third (inx_opt_occc) contains the number of entries to retrieve (up to 4,095 at a time). After any successful execution, the number of entries actually retrieved is returned into the fourth subfield (inx_opt_rtnc).

The fourth parameter, Inx_arg@, references the field that contains the search key. The keyed access method always requires a key.

Here Comes the JWSPLF Utility

The JWSPLF command calls the command processing program (CPP) JWSPLF, which is built from modules JWSPLFB, JWSPLFC, JWSPLFK, JWSPLFQ, JWSPLFR, JWSPLFU, JWSPLFX, and JWUSIDX. Each module is designed to perform one specific action, so most of the code can be reused, with little or no editing, for any other Work with application.

The entry point of the program is the module JWSPLFB. This module retrieves the spool files, creates a temporary user index, and loads the spool entries into it. The spool file entries are retrieved with the QUSLSPL API within the SPLF0200 format. The SPLF0200 returns all the names and attributes of the requested files by passing an array of keys to the API. This array contains one key for each attribute—e.g., 201=File name or 202=Job. The API places spool entries into a user space in order of timestamp. Each entry, with the attributes selected here, is 400 bytes long: A user space, then, can hold approximately 40,000 entries. Each spool entry is formatted into a 120-byte line that includes a unique 20-byte key with the spool name, job, and number. The entry is then moved into an array of 4,095 elements (the maximum number allowed for each insert operation). When the array is full, the entries are written into the user index, and the array is reloaded with more data.

The array is loaded directly via a pointer that references the 120-byte line. The array is used as a row area to store the file attributes. The first data structure, splf@l, is initially mapped to the first spool entry in the user space. The second data structure, splf@x, is mapped to the first element of the array. Use the eval op code to copy all the spool attributes from the user space to the array. To move to the next elements in the user space and the array, increase the value of the pointer with the appropriate offset. The first offset is retrieved from the user space header (set by the spool API); the second offset is evaluated as %len(splf@x), or 120 bytes.

If an error occurs in the spool API, the standard error structure returns the CPF message identifier and its message data. These are passed to the QMHSNDPM API to send an *ESCAPE message. The *PSSR routine, which is automatically invoked, resends the error with QMHRSNEM and terminates by resignalling, with the *CANCL option, the originating error. When all the entries have been loaded into the index, control passes to the module JWSPLFR, which displays the list of the selected spool files.

As I’ve explained, I designed JWSPLF to look like the standard WRKSPLF panel group. But instead of panel groups, I used a single display for each view and a display for confirming delete requests. The scrollable area, which lists up to nine spool files, is defined by the program as a group of arrays, rather than a subfile. Because there is no subfile that keeps the selected options, I created a second user index that stores only the entries for which the user has entered an option. This second user index makes it easy to know immediately if there are options to execute.

If there are options to execute, a simple CL program is called that reads the entries from this second index and runs the appropriate command for each option. When writing the code, I paid particularly close attention to minor details—e.g., list and cursor positioning (based on whether the user selected one or more options), whether errors were encountered while executing commands, whether entries were removed, and whether any functional key had been pressed.

When the user presses Enter or a roll key, the program saves the current lowest and highest keys. The program uses these stored keys to scroll the list forward and backward

and to reposition the list after it has been reloaded with F5=refresh. If the user has entered any line options, the selected spool file entries are written into the second user index; however, if the user deletes an option that was previously inserted, the corresponding entry is removed from the index.

When the F9 key is pressed, the program calls the Retrieve Messages API, QMHRTVRQ. This API returns, one at a time, the old request messages that are in the job log. Note that the first call must be done with the option initialized to *LAST. If the user presses F9 again, this option should be changed to the value *PRV. The retrieved command (up to 73 bytes) is put into the command line for later execution. If the user presses F13, the first option on the current page is repeated until the last entry is reached; all the entries that are in this range are put into the second user index.

If the user presses Enter, the program queries the second user index to determine if there are line options to be executed. If there are, the program calls the procedure JWSPLFX with the optional parameters in the command line; otherwise, the JWSPLFQ procedure is called. So that the system help is available on any message, errors are displayed at line 24 by means of an error subfile associated with the program queue.

Execute All the Options with a Simple CL Module

The procedure that executes the options is a CL module. The module receives a character string containing any command parameters the user keyed on the command line as well as the F4 indicator; the module then reads all the entries from the second user index. If the option entered was not 4, to delete a spool file, the program calls the well-known QCMDEXC API, passing to it the command built from the spool parameters retrieved from the second user index and the optional parameters.

JWSPLF includes the most common WRKSPLF options, but you can easily add other options. I changed the standard option 7 to duplicate spool files instead of display messages. The option to display messages is still available by calling API QSPDSPFM, but only if your system is at security level 30. The source code for the program contains code for both options.

The procedure builds the command depending on the user’s choices (based on F4 being pressed and whether or not the user entered any parameters on the command line). Notice the “?” before the command that forces prompting and the “?*” string, which protects some parameters (like file name) from being changed before the command is executed. If any parameters are keyed on the command line, they are appended at the bottom of the command.

If the user enters option 4 to delete a spool file, the spool entries are read twice. The first time, they are passed to function JWSPLFC, which writes the entries into a subfile. When all the entries have been read once, the JWSPLFC is called again to show the list with all the files ready to be deleted. If the user confirms the list by pressing Enter, the second user index is read again, spool files are deleted from the system, and entries are removed from both indexes.

Customized user options, like predefined ones, are handled by QCMDEXC. Module JWSPLFU builds the command, replacing any “&” variables with the corresponding spool file values. When the user option is complete, the QUSRSPLA API is called to retrieve the new status of the file. (For example, the user could have cancelled a spool with a user-defined option instead of the standard option 4.) Now, consider the QWCRTVCA and QWCCCJOB APIs: The first API traps whether the F3 or F12 key is pressed from any system or user screen; if the user pressed one of these keys (e.g., while displaying many spool files) the multiple-entry processing task stops, and control passes back to the list display. The second API resets the F-key flags. The procedure has one error branchpoint that transforms any escape message received into an information message and moves the message back to the calling program with the QMHMOVPM API. These messages will be displayed in the subfile line 24.

Module JWSPLFQ directly executes a command from the command line. The module uses the QCAPCMD API to execute or prompt for commands. QCAPCMD provides some additions to QCMDEXDC and QCMDCHK, such as limited user checking and generic command search. Executed commands are written in the job log as request messages and then received so they are not executed again. The user can retrieve these logged commands by pressing F9.

Add All the Options You Need

JWSPLF, like PDM, allows you to define options. The program used to manage the user options stores nonstandard options in a database file. User options have an option code and a command string that usually contains all the substitution variables needed to identify each spool file. The variables that can be put into a command are &SF (Spool file name), &J (Job name), &U (User name), &N (Job number), &SN (Spool file number), and &FJ (Full job name). To replace these variables with values, I call QCAPCMD, specifying a value of 8 in the first subfield of the options control block parameter. See Figure 4 for examples of user-defined options.

Archive Your Spool Files

The JWSPLF utility includes option A=Archive. This option uses the JSPLGET command (included in the tool) to download a spool file with its attributes into a user space. This space can be saved or moved to another system using save and restore CL commands. The spool file with its attributes can be reprinted at any time directly from the user space by using the JSPLPUT command (included in the tool as well). These archival functions use the spool API QSPOPNSP to open the requested spool file, QSPGETSP, to put the data into the user space, and QSPCLOSP to close the spool. The user space can be up to 16 MB, which allows you to store a report of approximately 3,000 to 4,000 pages (archiving bigger reports is the programmer’s responsibility). My procedure creates as many user spaces as needed to store all the pages of the report. Each space is chained to the next one by writing a space_id in the first 10 bytes of the 64 bytes of user area not used by the spool APIs. At the end of the chain, the value *NONE indicates that this is the last space used. When the spool has to be reprinted, the QSPPUTSP API is called for each user space in the chain until the *NONE indicator is found. The space_id is in the form Snnnnnnnnn, in which n is a number retrieved from the SPCNR data area. The JPLARC *pf contains a list (with chain specifications, attributes, and download elapsed time) of the spool files that have been copied to user spaces. All the APIs described in this paragraph are shipped with the authority *EXCLUDE. (Consider granting *USE authority to all APIs that will run the JSPLPUT and JSPLGET commands.)

If You Need More Information

Hopefully, the information I’ve provided will help enhance your everyday use of WRKSPLF. I hope that you find JWSPLF useful in dealing with spool files, as well as in programming Work with applications. The source code provides you with many comments that will help you better understand the techniques used.

References and Related Materials

• “Applying User Index APIs,” Doug Pence and Ron Hawkins, MC, February 1996
• MI Library Reference (SC09-2418, CD-ROM QBJADR00)
• OS/400 Message Handling APIs (SC41-5862, CD-ROM QB3AMN03)
• OS/400 Object APIs (SC41-5865, CD-ROM QB3AMQ03)
• “Putting User Indexes into Practice,” Bruce Guetzkow, MC, October 1998




Figure 1: The JWSPLF utility looks very much like IBM’s WRKSPLF.


MI Instruction Description ILE/MI Built-in Function INSINXEN Insert index entries _INSINXEN
FNDINXEN Find index entries _FNDINXEN
RMVINXEN Remove index entries _RMVINXEN1
MATINXAT Materialize index attributes _MATINXAT

Figure 2: OS/400 includes powerful MI instructions for manipulating user indexes.



JWSPLF-_A_Better_WRKSPLF_Utility06-00.png 595x447

d*d* FNDINXEN - Find index entry
d*d FndInxEn PR ExtProc(‘_FNDINXEN’)
d Inx_receiver@ * value
d Inx@ *
d Inx_opt@ * value
d Inx_arg@ * value

c *entry plist
c parm p_entry
c eval inx_receiver@ = %addr(p_entry)

d*d* MATPCO - Materialize Process Communication Object
d*d MatPco PR * ExtProc(‘_PCOPTR’)
d*
d Pco s *
d Pco@ s * dim(8) based(Pco)
c** retrieve the qtemp or *curlib system pointer
c select
c** ... qtemp
c when idxlibr = ‘QTEMP’
c eval Pco = Matpco
c eval Ctx@ = Pco@(5)
c** ... *curlib
c when idxlibr = ‘*CURLIB’
c eval Pco = Matpco
c eval Ctx@ = Pco@(8) d*d* RSLVSP - Resolve system pointer
d*d Rslvsp6 PR ExtProc(‘_RSLVSP6’)
d SysPtr *
d Objname 34A
d ObjAuth 2A
d Rslvsp8 PR ExtProc(‘_RSLVSP8’)
d SysPtr *
d Objname 34A
d ObjCtx *
d ObjAuth 2A
d ObjName ds
d Objtype 2A
d ObjId 30A
d ObjAuth 2A inz(x’0000’)

c** resolve the library system pointer
c eval ObjType = x’0401’
c eval ObjId = idxlibr
c CallP RslvSp6(Ctx@:ObjName:Objauth)

c** resolve the user index system pointer
c eval ObjType = x’0E0A’
c eval ObjId = idxname
c if idxlibr = ‘*LIBL’ or idxlibr = *blanks
c CallP RslvSp6(Idx@:ObjName:Objauth)
c else
c CallP RslvSp8(Idx@:ObjName:Ctx@:Objauth)
c endif

A

B

C

D

Figure 3: Procedure prototypes simplify the task of accessing user indexes from RPG programs.

Figure 4: JWSPLF allows you to add PDM-like options to the Work with Spooled Files panel.





JWSPLF-_A_Better_WRKSPLF_Utility07-00.png 610x458

Giuseppe Costagliola is a programmer in Turin, Italy. You can reach him atThis email address is being protected from spambots. You need JavaScript enabled to view it.

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: