24
Tue, Dec
1 New Articles

The CL Corner: Understanding the CHKKILL Program, Continued

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

Change commands with the Command Analyzer Change exit point.

 

This article is the fourth in a series that discusses how to use proxy commands and the Command Analyzer Change exit point. In the last article, we reviewed the validation-checking that an exit program should perform prior to processing command-related data passed to the program. In this article, we will look at the actual processing of this command-related data.

 

Before reading this article, you may find it beneficial to review the three prior articles:

 

 

For space reasons, the source for program CHKKILL is not being repeated in this article, so you may want to refer to the previous article, "Overriding Commands and Their Parameter Values."

 

Having verified that the exit program was called by the QIBM_QCA_CHG_COMMAND exit point, that the format of the data passed conforms to format CHGC0100, and that the command being processed is ENDJOB, CHKKILL then determines if any proxy commands were used. If the number of proxy commands in the proxy chain, field &Nbr_Prx, is equal to 0 then CHKKILL can simply return as the KILL proxy was clearly not used.

 

Having determined that one or more proxy commands were used in reaching the ENDJOB command, the CHKKILL program now accesses the proxy chain passed by the exit point in the &Chg_Info parameter. To do this, CHKKILL sets the pointer variable &Ptr_Prx to the address of the &Chg_Info structure and then adds the offset to the first proxy command entry, &Off_Prx, to &Ptr_Prx. As the structure &Prx_Struct defines one proxy command entry and is declared as being *BASED on the pointer &Ptr_Prx, the &Prx_Name and &Prx_Lib subfields of the &Prx_Struct structure now contain the values of the first proxy entry's proxy command name and proxy command library, respectively.

 

But prior to examining these values, CHKKILL first determines the size of each proxy command entry by using the RTVVARSIZ command. This is done because we need to know the size of each entry to step from the first entry to the second, third, etc. The size of each proxy command entry is determined by using the RTVVARSIZ command and is stored in the variable &Size_PrxID.

 

CHKKILL then enters into a DoFor loop to process all of the proxy entries (&Nbr_Prx). If the proxy command name is not KILL, CHKKILL adds the size of one entry (&Size_PrxID) to the pointer &Ptr_Prx and simply moves to the next proxy command entry in the chain. If all proxy entries in the proxy chain have been examined and the KILL proxy was not found, CHKKILL simply returns to the exit point. If the proxy command name is KILL, CHKKILL looks to see if the keyword OPTION was specified with the command. If OPTION was specified by the user, we do not want CHKKILL to override the user-provided value. We only want CHKKILL to use OPTION(*IMMED) as a default.

 

To perform this check, CHKKILL uses the Scan for String Pattern (QCLSCAN) API, which is documented here. This API has a restriction that the string to be searched (in our case, the initial command string) cannot be greater than 999 bytes in length. We could work around this limitation, but I elected not to in the sample program as 999 bytes is sufficient for the vast majority of command strings you are likely to run into. If the initial command string is greater than 999 bytes in length (field &Len_InlCmd of the &Chg_Info structure), CHKKILL sends message PRX1004 using the SndErrMsg subroutine. PRX1004 does return the actual command string length as a replacement variable.

 

If the initial command string length is less than or equal to 999 bytes, CHKKILL accesses the initial command string. To do this, CHKKILL sets the pointer variable &Ptr_InlCmd to the address of the &Chg_Info structure and then adds the offset to the initial command string, &Off_InlCmd, to &Ptr_InlCmd. As the variable &Inl_Cmd is declared as being *BASED on the pointer &Ptr_InlCmd, &Inl_Cmd now contains the value of the initial command string in the first &Len_InlCmd bytes of &Inl_Cmd.

 

CHKKILL now calls the QCLSCAN API, searching for the pattern 'OPTION('. If the pattern 'OPTION(' is found within the initial string, indicated by a &Result value greater than 0, CHKKILL simply returns as we do not want to override the user-specified OPTION value.

 

If the pattern 'OPTION(' is not found, indicated by a &Result value of 0, or the initial command string isn't long enough to even hold the value 'OPTION(', indicated by a &Result value of -1, CHKKILL then determines if the command string can be modified. The ability to change the initial command string is controlled by the variable &Alw_Chg. There are certain conditions, discussed in the Command Analyzer Change exit documentation, where the exit program is not allowed to modify the initial command string. If CHKKILL has determined that it should add OPTION(*IMMED) to the initial command string but is not allowed to, then message PRX1005 is sent using SndErrMsg.

 

If a change to the initial command string is permitted, CHKKILL then copies the initial command string &Inl_Cmd to the &New_Cmd parameter and concatenates the value 'OPTION(*IMMED)' to this copied value. CHKKILL then updates the &Len_NewCmd parameter. This parameter, which reflects the length of the new command string, is set to the length of the initial command string, &Len_InlCmd, plus the length of the 'OPTION(*IMMED)' literal, plus a separating blank as we used *BCat for the concatenation, a total of 15 bytes. When the exit program CHKKILL returns to the Command Analyzer Change exit point, it is this &New_Cmd that will be run rather than the initial command passed to CHKKILL.

 

While the logic used for setting &Len_NewCmd works, there is a better approach. The problem with the shown solution is that we now have hard-coded dependencies that span two lines of CL source code. In one line, we are concatenating the literal value 'OPTIONS(*IMMED)', and in a separate line, setting the length of this literal value (14 + 1 separating blank). If a developer a year from now were to change the literal 'OPTIONS(*IMMED)' to the literal 'OPTIONS(*IMMED) LOGLMT(0)', the developer would need to know that the ChgVar updating &Len_NewCmd must also be updated, in this case changing the '15' to '25'. This is something that can be easily overlooked.

 

A better approach would be to calculate at run time the actual length of the new &New_Cmd command string. To do this, we can create a new command: Retrieve Variable Length (RTVVARLEN). The ability to create this type of command was alluded to in the article "Just How Big Is That Variable?"

 

To create the RTVVARLEN command, we should add three more messages to the USERMSGF message file created in the article "Overriding Commands and Their Parameter Values." The following commands will accomplish this:

 

ADDMSGD MSGID(MSG0201) MSGF(USERMSGF) MSG('Retrieve Variable Length')

ADDMSGD MSGID(MSG0202) MSGF(USERMSGF) MSG('Variable name')

ADDMSGD MSGID(MSG0203) MSGF(USERMSGF) MSG('Variable length')

 

This is the command definition for the RTVVARLEN command:

 

             Cmd        Prompt(MSG0201)                              

             Parm       KWD(Var) Type(*Char) Len(5000) Min(1) +     

                          Vary(*Yes *Int4) Prompt(MSG0202)           

             Parm       KWD(Length) Type(*Int4) RtnVal(*Yes) Min(1) +

                          Prompt(MSG0203)                             

 

And this is the RTVVARLEN command processing program (CPP) source:

 

             Pgm        Parm(&Var &Length)                         

             Dcl        Var(&Var) Type(*Char) Len(5000)            

             Dcl        Var(&VarLength) Type(*Int) Stg(*Defined) + 

                          Len(4) DefVar(&Var)                      

             Dcl        Var(&Length) Type(*Int)                    

                                                                   

             ChgVar     Var(&Length) Value(&VarLength)             

             EndPgm                                                

 

To compile the CPP and command use this:

 

CRTBNDCL RTVVARLEN

CRTCMD CMD(RTVVARLEN) PGM(RTVVARLEN) ALLOW(*IPGM *BPGM *IMOD *BMOD)

     PMTFILE(USERMSGF)

 

With the addition of the RTVVARLEN command, you can now replace this line...

 

                                  ChgVar Var(&Len_NewCmd) +     

                                    Value(&Len_InlCmd + 15)     

 

...with this line:

                                  RtvVarLen Var(&New_Cmd) +  

                                    Length(&Len_NewCmd)      

 

Using the RTVVARLEN command, you no longer have to worry about keeping the value for variable &New_Cmd in sync with the value assigned to variable &Len_NewCmd. With one consideration, you can add new keywords without the need to count characters or update a dependent source line in the program. The one consideration is that commands do not allow a *CHAR parameter to exceed 5000 bytes in size after performing blank truncation. If you try to pass a parameter exceeding 5000 bytes in length to RTVVARLEN, you will receive a run-time error of CPD0074 - Value &1 for VAR exceeds 5000 characters. For this situation, other solutions, which I will not cover in this article, exist.

 

Returning back to CHKKILL, the last check after calling the QCLSCAN API is to determine if an error occurred when calling the API, indicated by a &Result value of less than -1. In this situation, CHKKILL sends the error message PRX1006 using the SndErrMsg subroutine. PRX1006 does include the actual &Result value that was returned so that the developer has a starting point for further investigation.

 

And that's it. In this series of articles, you have seen how to...

 

  • Create proxy commands
  • Use the Command Analyzer Change exit point to customize command options based on the proxy command used
  • Send messages containing replacement data values
  •  Use the MATPGMNM MI instruction to determine the currently running program name
  • Use the PROPB MI instruction to propagate a character value across a variable
  • Determine the length of a character string using the RTVVARLEN command

 

Hopefully, you will be able to put some of this knowledge to good use in future development efforts.

More CL Questions?              

Wondering how to accomplish a function in CL? Send your CL-related questions to me at This email address is being protected from spambots. You need JavaScript enabled to view it.. I'll try to answer your burning questions in future columns.

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: