05
Tue, Nov
5 New Articles

The API Corner: Finding Modules in a *SRVPGM

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

Are you aware of what you can do with the QBNLSPGM API?

 

In the last article, "Module, Module, Who's Got My Module?", we wrote an application to find all *SRVPGMs that had a given *MODULE bound into them. We saw the first version of our program, MODUSAGE, but didn't have the opportunity to examine it. We'll do so now. For space reasons, the program is not being repeated in this article, so you may want to review the previous article.

 

After first verifying that the two required parameters, ModNam and SrchLib, were passed, MODUSAGE runs the Setup procedure. Setup performs several functions in order to set the appropriate environment for MODUSAGE.

 

First, the Bytes Provided field of the API error code structure QUSEC is initialized to 0. This structure was previously copied into MODUSAGE with the /copy qsysinc/qrpglesrc,qusec statement in the main procedure. By setting Bytes Provided (QUSBPRV) to 0, we are telling any API we call that we want exception messages returned to the program when an error is encountered. In a subsequent version of MODUSAGE, we will use another instance of the error code structure for when we want to handle specific error conditions and not go through the overhead of actually receiving, and monitoring for, an exception message. Because several procedures within MODUSAGE will use the QUSEC error code structure, we declare the structure within the main procedure.

 

Second, Setup sets the ObjLib subfield of the ObjLibNam data structure to the value of the SrchLib parameter (the library name, or special value, that was passed as the second parameter of MODUSAGE). The ObjLibNam data structure is later used when calling the QBNLSPGM API in order to identify what *SRVPGMs in the specified library are to be returned to MODUSAGE. The first 10 bytes of ObjLibNam, which represent the name of the *SRVPGM, are initialized to the special value *ALL.

 

Following this, Setup creates the *USRSPC MODLUSRSPC (Module List User Space) in library QTEMP. The prototype for calling the Create User Space (QUSCRTUS) API is defined in Setup. The *USRSPC is created with the following characteristics:

 

•·         No extended attribute--We have no need for one.

•·         An initial size of 1 byte--We could try to guess a size, but there isn't any need. List APIs will automatically extend a *USRSPC up to a maximum of approximately16MB if that's what's needed to accommodate the data being returned. The initial size parameter is more for other uses of *USRSPCs, users who are not using list APIs.

•·         An initial value of x'00' for the storage associated with the *USRSPC--This is, per the API documentation, the best-performing value.

•·         A public authority of *CHANGE--This doesn't mean a whole lot as the *USRSPC is being created in QTEMP.

•·         No text description--As with an extended attribute, we just don't have a need for one. If we were creating the *USRSPC into a permanent library, such as QGPL, a text description could be more valuable.

•·         An option to replace any existing *USRSPC by the same name in the same library--Due to the overhead of creating an object, this is one option we may revisit later (though not today).

 

The QUSEC error code structure is used when calling the QUSCRTUS API so that any errors will cause an exception message to be returned to the program. The documentation for the QUSCRTUS API can be found here.

 

After successfully creating the *USRSPC, Setup then sets the pointer variable ModLstSpcPtr (Module List Space Pointer), defined in the main procedure, to the first byte of the *USRSPC MODLUSRSPC. This is done by calling the Retrieve Pointer to User Space (QUSPTRUS) API. The prototype for calling QUSPTRUS is defined in Setup, and the documentation for the API can be found here.

 

Setup then returns to the main procedure, where the ChkSrvPgmMod (Check Service Program Modules) procedure is run. ChkSrvPgmMod first calls the List Service Program Information (QBNLSPGM) API. The first parameter value, ModLstSpc, tells the API to return the requested data in the MODLUSRSPC *USRSPC previously created in Setup. The second parameter value, SPGL0100, identifies the type of information to be returned; format SPGL0100 indicates that information about bound *MODULEs is being requested. The third parameter, ObjLibNam, identifies what *SRVPGMs we're interested in. As a reminder, this variable was previously set in Setup and specifies that *ALL *SRVPGMs in the library previously passed to MODUSAGE should be returned. The fourth parameter is the QUSEC error code structure.

 

Now things get a little more interesting!

 

With list-type APIs, there is a common header, often called the generic header, which the API provides at the start of the *USRSPC. The documentation for this generic header can be found here. In the main procedure of MODUSAGE, we included the IBM-supplied definition for this generic header with the statement /copy qsysinc/qrpglesrc,qusgen. While there are many fields of interest in this generic header, the five of primary concern to us today are shown below:

 

DQUSH0100         DS                                             

D*                                             Qus Generic Header

...

D QUSIS                 104    104                               

D*                                             Information Status

...

D QUSOLD                125    128B 0                           

D*                                             Offset List Data 

...

D QUSNBRLE              133    136B 0                            

D*                                             Number List Entries

D QUSSEE                137    140B 0                            

D*                                             Size Each Entry   

 

The first field of interest is the name of the data structure, QUSH0100. In MODUSAGE, we referenced this data structure when defining our own data structure GenHdr, like so:

 

dGenHdr           ds                  likeds(QUSH0100)             

d                                     based(ModLstSpcPtr)          

 

As GenHdr is based on the ModLstSpcPtr, ModLstSpcPtr is addressing the first byte of the *USRSPC (this was done in the Setup procedure), and the QBNLSPGM API stores the generic header starting at the first byte of the *USRSPC, we're ready to start using the subfields of the generic header as soon as the QBNLSPGM API returns to our application.

 

The next statement, following the call to QBNLSPGM, is to determine if the generic header Information status subfield, QUSIS, has the value 'C'. QUSIS provides the status of the information within the returned list. A value of 'C' indicates the list is complete and accurate, 'P' that the list is incomplete (there may be more list entries than could fit in one *USRSPC) but accurate in terms of what is returned, and 'I' that the returned information is incomplete--essentially, do not process any list entries. This status field should be examined prior to using any other generic header field that is related to the returned list.

 

With some list-type APIs, though not QBNLSPGM, there is the capability to call the API multiple times with an option for the API to resume where it left off, on the previous call, in terms of returning list entries to the *USRSPC. In these cases, a QUSIS value of 'P' indicates that you need to call the API one or more additional times in order to access all available information. The List Save File (QSRLSAVF) API documented here, with its Continuation handle parameter, is an example of such an API. QBNLSPGM does not provide this "continuation" capability, so MODUSAGE simply checks for a QUSIS value of 'C'. If only partial information can be returned by the API due to *USRSPC size considerations, then QBNLSPGM will send the escape message CPF3CAA (List is too large for user space MODLUSRSPC), and because the QUSEC error code structure is set for exceptions (and MODUSAGE isn't written to handle exceptions: no monitor, etc.), this error message would cause MODUSAGE to end without ever getting to the compare.

 

If GenHdr.QUSIS is 'C', then ChkSrvPgmMod accesses the first module entry in the list with this statement:

 

SrvPgmEPtr = ModLstSpcPtr + GenHdr.QUSOLD;

 

The field GenHdr.QUSOLD represents the Offset to List Data that is provided within the generic header. By adding this offset value to the starting address of the *USRSPC, ModLstSpcPtr, we determine the address of the first list entry that was returned by the API. Within the ChkSrvPgmMod procedure, we included the IBM-supplied definitions for the QBNLSPGM API formats with the statement /copy qsysinc/qrpglesrc,qbnlspgm and, similar to how we defined GenHdr, we define our own data structure SrvPgmE (Service Program Entry) using the IBM-supplied data structure QBNL010000.

 

dSrvPgmE          ds                  likeds(QBNL010000)            

d                                     based(SrvPgmEPtr)       

 

As SrvPgmE is based on the Service Program Entry Pointer (SrvPgmEPtr) and we just set SrvPgmEPtr to the address of the first list entry, we're ready to start processing the first list entry. For the purposes of MODUSAGE, the subfields of the QBNL010000 data structure that we're interested in are these:

 

DQBNL010000       DS                                             

D*                                             Qbn LSPGM SPGL0100

D QBNSN00                 1     10                               

D*                                             Srvpgm Name       

D QBNSLIBN               11     20                               

D*                                             Srvpgm Library Name

D QBNBMN00               21     30                               

D*                                             Bound Module Name

D QBNBMLN00              31     40                               

D*                                             Bound Module Library 

...

D QBNSFILM00             61     70                                

D*                                             Source File Member      

 

In order to control when to stop processing list entries, ChkSrvPgmMod enters into a FOR loop conditioned by the Number of List Entries returned, GenHdr.QUSNBRLE. Within the FOR loop, we determine if the *SRVPGMs bound module name, SrvPgmE.QBNBMN00, is equal to the *MODULE name passed to MODUSAGE, ModNam. If so, the program displays the qualified *SRVPGM name and increments a counter, Hits, which will be used at the end of the program to indicate how many occurrences of the *MODULE were found.

 

Note that this comparison of the bound module name, SrvPgmE.QNBMN00, and the module name passed in as the first parameter to MODUSAGE, ModNam, is making the assumption that you do not have different modules in different libraries sharing the same name. This assumption may or may not be valid, depending on your development environment. If this assumption is not valid, it's easy enough to correct. Simply add another parameter to MODUSAGE, or extend the ModNam parameter, to include the *MODULE library name. In ChkSrvPgmMod, then compare both SrvPgmE.QNBMN00 and SrvPgmE.QBNBMLN00 (the Bound Module Library Name) to the module name and module library you have passed to MODUSAGE. In a later article, we'll make such a change when we provide a command interface to MODUSAGE. The command will support a qualified module name to search for, along with the special value *ALL for the module library name.

 

ChkSrvPgmMod then accesses the next list entry by adding the Size of Each Entry, GenHdr.QUSSEE, to the pointer SrvPgmEPtr and re-entering the FOR loop.

 

When the loop is finished, so is the program. MODUSAGE displays the total number of *SRVPGMs found that have module ModNam bound into them and then ends.

 

Note that this processing within ChkSrvPgmMod represents the heart and soul of how to work with list-type APIs. Once you master checking the list information status field QUSIS, accessing the first list entry with the offset to list data field QUSOLD, and processing the number of list entries, QUSNBRLE, by advancing through each entry incrementing your list pointer by the size of each entry, QUSSEE, then you're ready to take on virtually any list API. I'm confident, for instance, that you could now code the equivalent search of ILE programs using the List ILE Program Information (QBNLPGMI) API documented here.

 

Some list APIs will have the additional nuance of having variable list entry sizes, but even then you simply increment your list pointer by the size of each individual entry (which is always provided by the current list entry) rather than the fixed QUSSEE value (which will generally be set to 0 for formats with variable-length size entries).

 

Just remember that if you're using based and likeds defined structures, as we are in MODUSAGE, you must always qualify your generic header field variables with the name of your based structure. That is, GenHdr.QUSIS, GenHdr.QUSOLD, etc. rather than QUSIS, QUSOLD, etc. QUSIS, QUSOLD, and the other fields from QUSH0100 are still valid names; they'll just always be set to their initial values as they aren't being used other than for the likeds definition of our based structures.

 

This version of MODUSAGE isn't bad, but it isn't the greatest either. One problem is that we are making the assumption that the information associated with all modules bound into all *SRVPGMs that are analyzed per API call can fit into one *USRSPC. With the maximum size of a *USRSPC being roughly 16MB and the size of each module list entry being 3995 bytes (at least in V5R4), we're making the assumption that we will not have more than roughly 4,000 modules bound into the *SRVPGMs on our system--most likely not a good assumption.

 

We could try to work around this by running QBNLSPGM against each library on the system one by one, as opposed to multiple libraries when using a special value such as *ALLUSR. But we may still run into a library with more than 4,000 bound modules. As an example, IBM has over 10,000 modules bound into various QSYS *SRVPGMs in V5R4. We could start using generic *SRVPGM names (A*, B*, C*, QA*, QB*, etc.) by individual library to order to try to keep the number of modules per API call under 4,000, but there has to be a better way!   And of course there is a better way.

 

In our next column, we'll look at an Open List API that can be used to return a list of all the *SRVPGMs on our system and that is not constrained by a size limitation of 16MB in which to return the list. Given this list of *SRVPGMs, we'll then use QBNLSPGM to list the bound modules of each *SRVPGM and analyze each *SRVPGM one by one. In this way, we can handle virtually any number of *SRVPGMs and, as long as no *SRVPGM has more than 4,000 modules bound into it (in which case I think you may have some other problems), we can find all occurrences of a *MODULE across all *SRVPGMs.

 

Meanwhile, if you have other API questions, send them to me at This email address is being protected from spambots. You need JavaScript enabled to view it.. I'll see what I can do about answering your burning questions in future columns.

 

                       

Bruce Vining

Bruce Vining is president and co-founder of Bruce Vining Services, LLC, a firm providing contract programming and consulting services to the System i community. He began his career in 1979 as an IBM Systems Engineer in St. Louis, Missouri, and then transferred to Rochester, Minnesota, in 1985, where he continues to reside. From 1992 until leaving IBM in 2007, Bruce was a member of the System Design Control Group responsible for OS/400 and i5/OS areas such as System APIs, Globalization, and Software Serviceability. He is also the designer of Control Language for Files (CLF).A frequent speaker and writer, Bruce can be reached at This email address is being protected from spambots. You need JavaScript enabled to view it.. 


MC Press books written by Bruce Vining available now on the MC Press Bookstore.

IBM System i APIs at Work IBM System i APIs at Work
Leverage the power of APIs with this definitive resource.
List Price $89.95

Now On Sale

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: