04
Mon, Nov
5 New Articles

No Reason to Fear User Spaces

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

There are several kinds of APIs out there. One kind performs a useful system function, such as executing a command or changing some job attribute. Another retrieves a short piece of information, such as the description of an object. And among the other kinds, there’s one that produces a list of items into a user space. It’s this last one that usually turns the stomach of the beginner, and justifiably so. This article briefly explains how list APIs work and how to retrieve from user spaces the information they produce.

Of course, you may be wondering why you should bother. After all, outfiles have been doing the job wonderfully since the S/38 days. But outfiles are slower than list APIs. And some APIs have no corresponding outfiles.

What Are User Spaces?

User spaces are objects (type *USRSPC) that store information, much like physical files and data areas. Like physical files, they can store an enormous amount of data; like data areas, however, they have no internal structure of any kind—they’re just big containers in which you can dump anything. It’s up to you to organize their contents when you write into them.

User spaces are the output medium for list APIs. Take, for example, the List Objects API (QUSLOBJ). It has four required parameters and three optional parameters. Let’s look at the required parameters and one optional parameter:

• The qualified name of a user space. You have to supply the name of a user space into which the API is to write the list of objects you want to create.
• A data format name. There are seven to choose from, but the simplest is OBJL0100. The data format is actually a data structure. In the case of OBJL0100, there are three fields only: the object name, library name, and object type—each of which is 10 bytes long.
• The qualified names of the objects you want listed. You will no doubt want to use

a generic object name (or even *ALL). The library name can be specific, or it can be a special value; you have *LIBL, *USRLIBL, *ALL, *ALLUSR, and *CURLIB to choose from.
• The type of object to be listed. The object type would be a value such as *FILE, *PGM, or *ALL.
• An error code, in which the API returns information if an error occurs. The error code parameter is another data structure, as you can see in Figure 1. The first subfield tells the API how long the data structure is; I usually initialize this subfield to 96 and replace the asterisk (*) in the last subfield with a 96. When you call QUSLOBJ, the API writes the list of objects to the user space you identified in the first parameter. If the API runs without trouble, the error code parameter will show zero in the second subfield (bytes provided) and blanks in both the error message ID and message data subfields.

Accessing the Data in a User Space

The real challenge comes in reading the information contained in the user space. But before you can read it, you have to retrieve it. To do so, you need another API: the Retrieve User Space (QUSRTVUS) API. Before explaining how QUSRTVUS works, let’s digress a bit to explain how the list APIs organize data in the user space. See Figure 2.

At the beginning of the user space, the API writes offsets and lengths to the useful information contained therein. Both are written in binary format (4 bytes for each binary field), but there’s no reason to fear them; an offset of 0 merely means the first byte of something. An offset of 573 means the 574th byte of the same something. In fact, the offset just tells you how many bytes you have to add to the first byte in order to reach another.

The Input Section contains a copy of the input parameters you gave the API to do its work. For example, if you called QUSLOBJ to list all objects in QGPL, the Input Section contains *ALL, QGPL, and object type *ALL. Never mind how this is organized, because it is seldom needed.

The Header Section contains information that applies to all the list entries. For example, if you were listing the members of a database file, the Header Section might contain general information about the database file. Again, this information, although useful, is not what you’ll be after in most cases. Let’s skip it.

The List Section is, by far, the most useful one. It contains entries, each one describing a separate item in the list produced by the API just called. For instance, running QUSLOBJ makes each entry an object—which would be a record in an outfile.

As you can see in Figure 2, you have to read bytes 125 to 128 to find out on which byte the List Section begins (remember to add 1 to whatever number you obtain from 125 to 128). Bytes 133 to 136 tell you how many entries (“objects”) are in the list, while bytes 137 to 140 provide the length of each entry.

Armed with this information, you can easily retrieve the list of objects contained in the user space by using the QUSRTVUS API. QUSRTVUS requires the name of the user space from which it is to retrieve data, the beginning byte number, and the number of bytes; it returns the data you requested. In fact, QUSRTVUS works very much like the Retrieve Data Area (RTVDTAARA) command, since RTVDTAARA also requires a name (of the data area, in this case), a beginning byte number, and a number of bytes. And it returns the information you requested.

You can see, then, that the algorithm you should use to read one entry after another is as follows:

1. Read the first 140 bytes in the user space. Store the offset to the List Section in OFFSTL, the number of entries in LSENTQ, and the length of each entry in LSENTS (all binary, 4 bytes long).

2. Read the first entry at byte number OFFSTL + 1, for the number of bytes specified by LSENTS. The information retrieved is placed in a data structure that matches the data format of the list API (such as OBJL0100 for QUSLOBJ).

3. Process that entry. For instance, print the information, or write it to a subfile.
4. Repeat the process for all other entries. The starting byte number for each following entry is equal to the offset to the current entry plus LSENTS. You have to repeat the process a total of LSENTQ times.

Easier Than Subfiles

Actually, processing a user space can be easier than writing a typical subfile program. I have written a generic list API processor program in RPG III. You can see it in Figure 3. It contains the algorithm and data structures mentioned above, ready for use. Before using it, however, you must make changes to adapt the program for the particular list API you’ll be calling. Let’s look at what you’d have to do to use the generic processor (GENLSTAPI) to list objects using QUSLOBJ.

There are three externally described data structures: USINPS, USHDRS, and USLSTS, which describe the Input, Header, and List Sections, respectively. Since these data structures change according to the list API you’re going to use, you must supply the data structures yourself. One easy way to do so is by defining each one previously as a physical file; as you can see in Figure 4, I have described the List Section’s OBJL0100 data format. (You could define the data structures in source members and bring them in with /COPY, but I favor the physical file method, because I can use it with equal ease in any language. The /COPY method doesn’t have that flexibility.)

The three data structures are defined in the I-specs and contain a token, (in which x can be I, H, or L), that you have to change to an actual value using SEU. For example, needs to be changed to OBJL0100 in this case. Since I won’t be using either the Input Section or the Header Section, I can simply delete those lines from the I-specs. I also have to delete subroutines RTVHS and RTVIS and the EXSR op codes that invoke them.

Two other tokens, and , have to be changed to reflect the actual name of the user space and its library, respectively. For instance, to use a user space name of LIST and put it in QTEMP, change to LIST (followed by four blanks, for a total length of 8 characters), and change to QTEMP (followed by three blanks).

Write appropriate code for the PRCLSE subroutine. This subroutine is called to process each List Section entry, so if you want your program to print the list of objects, code an EXCPT or a WRITE op code there, in addition to whatever code you need to ensure printer overflow conditions.

Write the code for the WRTUS subroutine. This subroutine is meant to be the one that produces the list in the user space. To list objects, for instance, code a call to QUSLOBJ within this subroutine.

Now, you can compile the program. It should be ready for use.

Implementation Notes

To fully implement the generic list processor, you have to define the externally described data structures for the list data formats you’re going to use (such as OBJL0100 for QUSLOBJ). I recommend using the list data format name as the file name to keep things simple. Obviously, you don’t have to create a physical file for every list data format

contained in the API manuals—only those you’ll need—and you can create them as you go. To save disk space, create each physical file with MBR(*NONE) so the system won’t add a member to the file. And create the file in a library that is sure to be in your library list. Instead of creating physical files, you can also create /COPY source members to define the data structures you need. Some words of caution, however: First, the copy member, if written in RPG III, can’t be used in an RPG IV program—or a COBOL program. Second, you may end up creating copy members that have duplicate field names, something that will produce errors at compile time. If this happened to you when using the externally described method, however, you could rename some of the fields within the program. Third, and last, the /COPY directive itself can give you grief, as it forces you to code a source file name (and perhaps a library) if you use anything other than QRPGSRC.

As you can see, using the list APIs with user spaces is not the nightmare you thought it was. In fact, they may become as easy to use as outfiles, and they certainly show better performance. Using outfiles entails coding a CL program to run the command that produces the outfile, and you may have to issue a file override before you call your RPG program. Besides, the outfile already contains the field names, as chosen by IBM, and those field names (which may not make much sense to you) would result in a less understandable program.

On the other hand, you can take advantage of the generic list processor to quickly clone RPG code, and you need no CL program because you can call all APIs directly from the RPG program. Besides, whatever field names you use depends entirely on you, since it is you who designs the externally described data structures for the list data formats. You can even have two or more list data formats of the same type (e.g., two OBJL0100 data structures) if the application requires it, each using a slightly different externally described data structure, thereby avoiding field name conflicts. Try that using outfiles!

From To Data Type Description
--

1 4 Binary Bytes available.
5 8 Binary Bytes provided.
9 15 Character Error message ID.

16 16 Character (Reserved)

17 * Character Error message data.

From To Data Type Description
--

1 108 Character This information is rarely useful.

109 112 Binary Offset to the Input Section.

113 116 Binary Length of the Input Section.

117 120 Binary Offset to the Header Section.

121 124 Binary Length of the Header Section.

125 128 Binary Offset to the List Section.

129 132 Binary Length of the List Section.

133 136 Binary Number of entries in the List Section.

137 140 Binary Length of each entry in the List Section.

* * Structure Input Section.

* * Structure Header Section.

* * Structure List Section. *****************************************************************

*

* GENLSTAPI = Generic List API Processor.

*

* Instructions:

*

* 1. Copy this source member before making any changes.

Figure 1: Error code parameter

Figure 2: Organization of a user space

* Give the new source member a more suitable name.

* Use option 3 of WRKMBRPDM or the CPYSRCF command.

*

* 2. Edit the _copy_ to make your changes:

*

* a. Replace all variable tokens with the right names:

* with the name of a physical file object

* in which you’ve described the fields

* contained in the User Space Input Section.

*

* with the name of a physical file object

* in which you’ve described the fields

* contained in the User Space Header Section.

*

* with the name of a physical file object

* in which you’ve described the fields

* contained in the User Space List Section

* (the API’s “data format”).

*

* with the name of the user space.

*

* with the name of the user space library.

*

* b. Code in the PRCLSE subroutine whatever you want

* done with each list entry. Field names come from

* the physical file.

*

* c. Code in the WRTUS subroutine whatever code is

* necessary to list something into a user space.

* Typically, what it takes is calling a list API

* passing suitable parameter values.

*

* 3. If necessary, write additional code. For example,

* if you intend to show the output in a printed list,

* you’ll have to add a PRINTER file, C-specs to write

* to the file (EXCPT or WRITE), and O-specs if the

* printer file is program-described.

*

* 4. Compile the copy of the source member using the

* CRTRPGPGM command.

*

*****************************************************************

* API error code.

*

IAPIERR DS

I I 96 B 1 40BYTAVL

I B 5 80BYTPRV

I 9 15 EXCPID

I 17 96 EXCPDT

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

* User space header.

*

IUSHDR DS

I B 109 1120OFFSTI

I B 113 1160SIZEI

I B 117 1200OFFSTH

I B 121 1240SIZEH

I B 125 1280OFFSTL

I B 129 1320SIZEL

I B 133 1360LSENTQ

I B 137 1400LSENTS

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

* API data formats: Input, header, and list sections.

*

IUSINPS E DS

IUSHDRS E DS

IUSLSTS E DS

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

* Binary variables.

*

IBINARY DS

I B 1 40STRPOS

I B 5 80DTALEN

I B 9 120OFFSET

I B 13 160USSIZE

*****************************************************************

* Mainline.

*

C MOVEL’’USNAME P

C MOVEL’’USLIBR P

C USNAME CAT USLIBR QUSNAM P

*

C EXSR CRTUS

C EXSR WRTUS

C EXSR RTVUS

C EXSR DLTUS

*

C MOVE *ON *INLR

C RETRN

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

* CRTUS: Create user space.

*

C CRTUS BEGSR

C CALL ‘QUSCRTUS’

C PARM QUSNAM

C PARM USXATR

C PARM 1000000 USSIZE

C PARM *BLANK USVAL

C PARM ‘*USE’ PUBAUT

C PARM *BLANK USTEXT

C PARM ‘*YES’ USRPLC

C PARM APIERR

C ENDSR

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

* DCLVAR: Declare program variables.

*

C DCLVAR BEGSR

C MOVE *BLANK BYTE 1

C MOVE *BLANK CHR050 50

C Z-ADD0 LNGINT 150

C MOVE *BLANK NAME 10

C MOVE *BLANK QNAME 20

*

C *LIKE DEFN LNGINT N

C *LIKE DEFN NAME PUBAUT

C *LIKE DEFN QNAME QUSNAM

C *LIKE DEFN NAME USLIBR

C *LIKE DEFN NAME USNAME

C *LIKE DEFN NAME USRPLC

C *LIKE DEFN CHR050 USTEXT

C *LIKE DEFN BYTE USVAL

C *LIKE DEFN NAME USXATR

C ENDSR

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

* DLTUS: Delete user space.

*

C DLTUS BEGSR

C CALL ‘QUSDLTUS’

C PARM QUSNAM

C PARM APIERR

C ENDSR

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

* PRCLSE: Process list section entry.

*

C PRCLSE BEGSR

C ENDSR

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

* RTVHS: Retrieve header section.

*

C RTVHS BEGSR

C OFFSTH ADD 1 STRPOS

C CALL ‘QUSRTVUS’

C PARM QUSNAM

C PARM STRPOS

C PARM SIZEH DTALEN

C PARM USHDRS

C ENDSR

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

* RTVIS: Retrieve input section.

*

C RTVIS BEGSR

C OFFSTI ADD 1 STRPOS

C CALL ‘QUSRTVUS’

C PARM QUSNAM

C PARM STRPOS

C PARM SIZEI DTALEN

C PARM USINPS

C ENDSR

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

* RTVLS: Retrieve list entries.

*

C RTVLS BEGSR

C OFFSTL ADD 1 OFFSET

*

C 1 DO LSENTQ N

C CALL ‘QUSRTVUS’

C PARM QUSNAM

C PARM OFFSET STRPOS

C PARM LSENTS DTALEN

C PARM USLSTS

C ADD LSENTS OFFSET

* Process list section entry.

C EXSR PRCLSE

C ENDDO

C ENDSR

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

* RTVUS: Retrieve information from user space.

*

C RTVUS BEGSR

C EXSR RTVUSH

C EXSR RTVIS

C EXSR RTVHS

C EXSR RTVLS

C ENDSR

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

* RTVUSH: Retrieve user space header.

*

C RTVUSH BEGSR

C CALL ‘QUSRTVUS’

C PARM QUSNAM

C PARM 1 STRPOS

C PARM 140 DTALEN

C PARM USHDR

C ENDSR

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

* WRTUS: Produce output to user space.

*

C WRTUS BEGSR

C ENDSR

Figure 3: Generic list API processor

A R OBJL010R

A OBJNAM 10A

A OBJLIB 10A

A OBJTYP 10A

Figure 4: API data format OBJL0100

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: