Modifying OS/400 Commands

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

OS/400 provides hundreds of commands for almost every task imaginable. Despite this wealth of tools, every AS/400 shop has a few, customized commands it just can't live without. Some of these commands perform functions related to a specific application. Others add to the repertoire of system functions supplied with OS/400. Still others are designed to restrict the functions of an existing command for a specific group of users. It's this last group that this article addresses. By taking advantage of the techniques illustrated in this article, you can create customized versions of OS/400 commands without creating a second copy of the command.

The most common way to customize commands is to write your version of the command and restrict access to specific parameters or parameter values. A more versatile method uses a validity checking program (VCP) to prevent use of some options. A VCP can be implemented for almost any command-both OS/400 commands and those you write yourself. The only restrictions are commands such as IF, ELSE, DO, ENDDO, and CHGVAR.

In this article, I'll illustrate how to write a VCP by creating a VCP to customize the Change Job (CHGJOB) command. If changing this command happens to be a requirement in your shop, this article will give you all the information you need, and the code included with it can be downloaded and put to work without modification. However, the main point of this article is to show you the research required to add a VCP to any OS/400 command. Because each command is different, each one will require a certain amount of detective work. I can only provide guidelines for organizing your investigation. Modifying the sample programs to work with commands other than CHGJOB will require RPG programming skills and investigation of the specific command you want to modify. Since each OS/400 command is different the process may be quite complex.

Why Write a VCP

Before we get into how to write a VCP, consider why this method may be better than creating your own version of the command. When you create a second copy of a command, it is typically stored in a library that is above QSYS in the system portion of the library list. Some weaknesses of this technique are:

o Programmers who use this method will confirm that processing the input from a character string is not trivial. This is particularly true if any parameter allows a list of values or if the user has a choice between a qualified object and a single value.

o Supplying a prompt screen for your version of an IBM command is possible but tedious. When the command retrieves default information from job or system values, this becomes even more difficult.

o A clever programmer may explicitly qualify the command with library QSYS and bypass the customized version.

o Some installations solve the problem noted in the previous item by renaming the IBM command, moving it to another library, or restricting access to the command. However, this creates a new problem. If you have renamed or moved IBM commands, then changes need to be repeated immediately after each release is installed. Renaming or moving IBM commands can create problems if system menus explicitly specify library QSYS.

A VCP offers several advantages over the traditional approach. A VCP supports full prompting and current value retrieval without any special coding. Users cannot bypass the VCP by specifying the library, and the VCP is automatically used when menu options issue IBM commands. However this approach has some shortcomings of its own:

o Determining the data values passed from IBM commands is not easy. IBM does not provide the command definition source for IBM commands. That is where this article will be of assistance.

o You need to add the VCPs to the commands each time a new release of OS/400 is installed.

o IBM sometimes adds parameters to an existing command for a new release. In that case, the VCP will need to be modified to handle the additional parameters.

Command Structure

1 illustrates the general structure of AS/400 commands, whether supplied by IBM or written in-house. Each command names a command processing program (CPP) and can optionally name a VCP.

Figure 1 illustrates the general structure of AS/400 commands, whether supplied by IBM or written in-house. Each command names a command processing program (CPP) and can optionally name a VCP.

The VCP is called before the CPP. A VCP verifies the command parameters and determines if the command execution will continue. It does not modify any data-the parameters passed to the VCP and CPP are the same.

If the VCP returns normally, the command analyzer calls the CPP that will execute the command. To prevent command execution, the VCP should send diagnostic message CPF0006 to describe why the command is not being executed. The VCP should then send escape message, CPF0002, to indicate not to execute the command. 2 shows the framework for a VCP.

If the VCP returns normally, the command analyzer calls the CPP that will execute the command. To prevent command execution, the VCP should send diagnostic message CPF0006 to describe why the command is not being executed. The VCP should then send escape message, CPF0002, to indicate not to execute the command. Figure 2 shows the framework for a VCP.

In theory, if you wanted to add a VCP to one of your commands, you could look at the source code for either the command definition or the CPP to determine the number, order, and value of command parameters. Unfortunately, IBM does not supply source code for the command definition or the CPP, so you must determine the command parameters yourself.

This task is complicated for many reasons. The order in which the command parameters are passed may be different from the order shown by the prompter. The command definition may include some constant parameters that the prompter does not show-IBM often uses hidden constants so the same CPP can be used for multiple operations. For example, create and change commands frequently use the same CPP, taking advantage of a constant to distinguish the functions.

Because IBM does not supply the command definition source you need to follow the steps outlined in this article. The next section describes a step-by-step procedure you can use to determine the command parameters.

Determining the Command Parameters

STEP 1: Display the command definition

Use Display Command (DSPCMD) to determine if a command already has a VCP. The output shown in 3 indicates there is no VCP for the CHGJOB command. Most IBM commands do not have a VCP making it easy to add a VCP. If the command already has a VCP, you can still use the techniques in this article unless you are running security level 40 or 50. Your VCP can perform checks and then call the original VCP.

Use Display Command (DSPCMD) to determine if a command already has a VCP. The output shown in Figure 3 indicates there is no VCP for the CHGJOB command. Most IBM commands do not have a VCP making it easy to add a VCP. If the command already has a VCP, you can still use the techniques in this article unless you are running security level 40 or 50. Your VCP can perform checks and then call the original VCP.

Step 2: Make a copy of the IBM command

Copy the IBM command definition from QSYS into your library. Do not modify the IBM command until you have tested your VCP thoroughly. Working with a copy allows users to run the IBM command without disruption while you make the changes to your version of the command. You will need to have *ALL authority to the CHGJOB command for this step. The following command duplicates the CHGJOB command in your library.

 CRTDUPOBJ OBJ(CHGJOB) + FROMLIB(QSYS) OBJTYPE(*CMD) + TOLIB(MYLIB) 

Step 3: Dump the command

The command definition determines the names and order of the keywords. Since you don't have the command definition source, you'll have to use the command object. Use the following command to dump the contents of the command object to a spooled file.

 DMPOBJ OBJ(MYLIB/CHGJOB) + OBJTYPE(*CMD) 

4 illustrates what the object dump looks like. Notice the interpreted part of the object that appears in red on the right of the dump. The dump of the command object will show all parameters including hidden parameters in the order they are passed to the VCP. This is not necessarily the same order as the prompt. As you scan the printed output, you will begin to recognize the names of the keywords in the interpreted text portion. You can use this information to determine the sequence of the parameters.

Figure 4 illustrates what the object dump looks like. Notice the interpreted part of the object that appears in red on the right of the dump. The dump of the command object will show all parameters including hidden parameters in the order they are passed to the VCP. This is not necessarily the same order as the prompt. As you scan the printed output, you will begin to recognize the names of the keywords in the interpreted text portion. You can use this information to determine the sequence of the parameters.

The command analyzer passes data to the VCP in the order shown in the command dump. 5 shows how you can assign relative parameter numbers to the parameters found in the interpreted portion of the dump. The relative parameter number appears in the right column. You can see that the CHGJOB command for V2R3 has 34 parameters.

The command analyzer passes data to the VCP in the order shown in the command dump. Figure 5 shows how you can assign relative parameter numbers to the parameters found in the interpreted portion of the dump. The relative parameter number appears in the right column. You can see that the CHGJOB command for V2R3 has 34 parameters.

For this example, we are interested in the RUNPTY parameter. The dump shows that RUNPTY is passed as parameter 22. Before you write a VCP, you need to determine the format of the data for this parameter.

Step 4: Determine the format of data passed

The RPG program, DMP001RG (shown in 6), dumps the parameters passed to the VCP. This lets you determine the number and value of the parameters passed to the VCP. To accomplish this, you need to temporarily add the DMP001RG program as a VCP for your copy of the command. This Change Command (CHGCMD) command adds the VCP, DMP001RG, to the test version of the CHGJOB command in MYLIB.

The RPG program, DMP001RG (shown in Figure 6), dumps the parameters passed to the VCP. This lets you determine the number and value of the parameters passed to the VCP. To accomplish this, you need to temporarily add the DMP001RG program as a VCP for your copy of the command. This Change Command (CHGCMD) command adds the VCP, DMP001RG, to the test version of the CHGJOB command in MYLIB.

 CHGCMD CMD(MYLIB/CHGJOB) + VLDCKR(DMP001RG) 

The DMP001RG program is generic so that you can use it for any command you plan to modify.

STEP 5: Enter sample data in the test version of the command

Enter sample data to determine how the values are passed to the CPP. This is where you need to experiment and collect several copies of the data. Be sure to test all possible values for the parameters you want to check. The specific data you'll need to use will vary from one command to another. As a general guideline, you should run tests with the highest valid value, the lowest valid value, a valid value that is neither highest or lowest, no entry (zero or blank), invalid values both above and below the valid range, and a default value. You should also test all of the special values allowed by the command parameter. These values may get mapped to other values.

STEP 6: Analyze the output from DMP001RG

Analyze the output from DMP001RG program to determine the values passed to the VCP. The DMP001RG program shows ten characters of data. The ten characters may contain information from two or more parameters if the current parameter is less than ten characters. This is where your investigative work will be important. I can offer some guidelines about how data is passed, but I cannot be certain that they will apply to the particular command you plan to modify. The following pointers may help you to interpret the data you see when you run DMP001RG.

o The numeric data in IBM commands tends to be passed in binary fields of two or four bytes.

o Character strings are sometimes mapped to a single character. For example, in some commands, OUTPUT(*PRINT) is mapped to the single character "L"-a carry over from the S/38 when the output parameter specified *LIST.

o Some IBM commands use null pointers for the omitted parameters. The use of null pointers intro-duces some complications that I will discuss later.

7 illustrates a sample of the output from DMP001RG obtained by running the following CHGJOB command.

Figure 7 illustrates a sample of the output from DMP001RG obtained by running the following CHGJOB command.

 CHGJOB JOBPTY(7) OUTPTY(8) + RUNPTY(45) JOBQ(TESTJOBQ) + PRTTXT(TEXT) 

I added the keyword names to the left of the dump output using the keyword order determined in Step 3 to help you follow the analysis.

CHGJOB is one of the commands that uses null pointers. 8 eliminates parameters that have null pointers, making it easier to analyze the values passed to the VCP. 9 provides examples to show you how to extract the information you need.

CHGJOB is one of the commands that uses null pointers. Figure 8 eliminates parameters that have null pointers, making it easier to analyze the values passed to the VCP. Figure 9 provides examples to show you how to extract the information you need.

PARM22 is the RUNPTY parameter we are interested in for this example. The value shown for PARM22 is:

'002D000000005C000000'X

The X designates that this parameter is displayed in hexadecimal format.

The value of 45 was specified for the RUNPTY parameter. If you converted 45 to hex, you would get the value 2D. The RUNPTY is passed as a BINARY number of length 2.

Adding the VCP to CHGJOB

Let's review what we discovered so far.

o The number of parameters. CHGJOB has 34 for V2R3.

o The relative number of the parameter we want to restrict. RUNPTY is parameter 22.

o The format of the data passed. RUNPTY is passed as a 2-byte, binary value or a null pointer.

The detective work is over. Now we have enough information to write the VCP.

I first started with a simple CL program as the VCP. Typical of most programming projects, the simple way is not the way that works. This program fails because of the null pointers that are passed when a parameter is not specified. Therefore a CL program cannot be used.

I am not an expert on RPG, so I contacted one of my associates, Russell Popeil, and described my problem of null pointers. Russell was kind enough to provide the program shown in 10. Study this program because it demonstrates clever techniques on how to handle null pointers and send messages from an RPG program.

I am not an expert on RPG, so I contacted one of my associates, Russell Popeil, and described my problem of null pointers. Russell was kind enough to provide the program shown in Figure 10. Study this program because it demonstrates clever techniques on how to handle null pointers and send messages from an RPG program.

The next section explains how to add a VCP for the IBM CHGJOB command. The VCP can detect when a user has entered a run priority of less than 20. The program issues an error message and prevents changing the priority to less than 20. The technique demonstrated can be used to add a VCP to any IBM command.

STEP 1: Add the VCP to the test version of command

Change your test version of the command to add the VCP as shown.

CHGCMD CMD(MYLIB/CHGJOB) +

VLDCKR(MYLIB/VCP001RG)

STEP 2: Test the VCP

Before moving the command to QSYS you should run extensive tests and make sure that you have a backup copy of the original, IBM-supplied command.

STEP 3: Change the QSYS version of the command

Now that all the tests are complete, you can put the modified CHGJOB command into production. To do this:

1. Move the VCP (VCP001RG in this example) to a production library that is part of the library list for all users.

 MOVOBJ OBJ(MYLIB/VCP001RG) + OBJTYPE(*PGM) + TOLIB(production) 

2. Change the QSYS version of the command to add the validity checking program. You should record the way you run CHGCMD so that you can repeat the change when you install a new release.

 CHGCMD CMD(QSYS/CHGJOB) + VLDCKR(production/VCP001RG) 

STEP 3: Change the QSYS38 version of the command

Some commands also exist in the QSYS38 library, and you need to make a similar change to the CHGJOB command in the QSYS38 library. You can usually assume that the parameter list for the QSYS38 version of the command is the same as the QSYS version, but you need to check. One quick test is to display the QSYS38 version of the command and check the name of the CPP for the QSYS and QSYS38 versions. If both the QSYS and QSYS38 versions of the command use the same CPP, you can use the same VCP.

Additional Comments

You should keep track of any changes you make to IBM commands. When you install a new release, the VCP changes will need to be added to the IBM commands. The recommended method is to store all of the CHGCMD commands in a source member that can be run when the new release is installed. When you install a new release, the command may have additional parameters. If the new version of the command has more parameters than your VCP, you will get an error and need to add more parameters to the RPG program and recompile it.

Limited Access Achieved

The techniques presented in this article were developed as a result of questions I received from AS/400 customers. Standard security functions control access to a command, but it is an all-or-nothing access. AS/400 security does not work at the parameter level. A VCP can limit access at the parameter level. The requirement to restrict access to CHGJOB occurs frequently and cannot be resolved easily with AS/400 security. The methods used in this article for the CHGJOB command can be extended to most OS/400 commands.

For more information on VCPs, consult the CL Programmer's Guide (SC41-8077, CD- ROM QBKA7102), "Writing AS/400 Commands (part 3)," MC, March 1993 or the "Validity-Checking Programs" sidebar in "Message Queue Housekeeper," MC, August 1994.

Wayne O. Evans is an AS/400 security consultant and a frequent speaker on security topics. During his 27 years with IBM Corporation, he was involved with AS/400 security design issues. Prior to working on security, Wayne was the team leader and designer for the command definition and CL language on the S/38.

Russell Popeil is an EDP Manager at Banca Commerciale Italiana in New York.


Modifying OS/400 Commands

Figure 1 AS/400 Command STructure

 UNABLE TO REPRODUCE GRAPHICS 
Modifying OS/400 Commands

Figure 2 Framework of a VCP

 PGM PARM(&P1 &P2 ... &Pn) DCL VAR(&P1) TYPE(type) LEN(length) DCL VAR(&P2) TYPE(type) LEN(length) . . . DCL VAR(&Pn) TYPE(type) LEN(length) /* Determine if the command should be allowed */ IF COND(&OK) THEN(RETURN) SNDPGMMSG MSGID(CPF0006) MSGF(QCPFMSG) MSGDTA('Tell + user why command not allowed') + MSGTYPE(*DIAG) SNDPGMMSG MSGID(CPF0002) MSGF(QCPFMSG) MSGTYPE(*ESCAPE) ENDPGM 
Modifying OS/400 Commands

Figure 3 Display of the CHGJOB Command

 Display Command Information Command . . . . . . . : CHGJOB Library . . . . . . . : QSYS Program to process command . . . . . . : QWTCCCHJ Library . . . . . . . . . . . . . . : QSYS State used to call program . . . . . : *SYSTEM Source file . . . . . . . . . . . . . : Library . . . . . . . . . . . . . . : Source file member . . . . . . . . . . : Validity checking program . . . . . . : *NONE Mode(s) in which valid . . . . . . . . : *PROD *DEBUG *SERVICE Where allowed to run . . . . . . . . . : *IMOD *BMOD *IREXX *BREXX *BPGM *IPGM *EXEC *INTERACT *BATCH Allow limited user . . . . . . . . . . : *NO Maximum positional parameters . . . . : 1 More... Press Enter to continue. F3=Exit F12=Cancel 
Modifying OS/400 Commands

Figure 4 DMPOBJ Output for the CHGJOB Command

 5738SS1 V2R2M0 920925 AS/400 DUMP 422912/DEVWOE/BPPAF222S1 02/07/94 18:38:02 PAGE 1 DMPOBJ PARAMETERS OBJ- CHGJOB CONTEXT- QSYS OBJTYPE- *CMD OBJECT TYPE- SPACE *CMD * 000040 00000000 00000000 00010002 32000400 00000000 00000000 00000000 00000000 * NAME- CHGJOB TYPE- 19 SUBTYPE- 05 LIBRARY- MYLIB TYPE- 04 SUBTYPE- 01 CREATION- 04/18/94 12:51:19 SIZE- 0000001800 OWNER- VMG TYPE- 08 SUBTYPE- 01 ATTRIBUTES- 0800 ADDRESS- 00149400 0000 SPACE ATTRIBUTES- 000000 00000080 00000060 1905C3C8 C7D1D6C2 40404040 40404040 40404040 40404040 * - CHGJOB * 000020 40404040 40404040 A0000000 00000000 00001700 00030000 00000000 00000000 * * SPACE- 000000 0000D8E6 E3C3C3C3 C8D14040 D8E2E8E2 40404040 40400000 5C404040 40404040 * QWTCCCHJ QSYS * 000700 00000000 00010000 41080013 A0000000 00D9E4D5 D7E3E840 40404000 16083601 * _ µ RUNPTY * 000720 0006050D 7802000C 00010000 A10D780D 9E04000B 0002030D 46060DA0 06000820 * _ ~ _ ? µ * 000740 000113B9 FF079400 00006C00 03000400 00000000 01000041 280017F2 00000000 * _ m % _ 2 * 
Modifying OS/400 Commands

Figure 5 Assigning Relative Parameter Numbers

 Interpreted Portion of Command Dump Relative Name of Parameter Number Parameter * - CHGJOB * * µ * * * * TQWTCCCHJ QSYS * * * a q pQCPFMSG *L* *IBL _ * * 4µ T 0 s a * * E ! - _ JOB * 1 JOB * _ g _ _ * * U - _ _ * *JOBQ x _ e _ _* 2 JOBQ * 4 ? % _ ?* * JOBPTY ? _ g* 3 JOBPTY * _ _ " b % x % * * _ c OUTPTY * 4 OUTPTY *, _ g _ _ e b * * z 5 + _ * * PRTTXT 5 _ e _* 5 PRTTXT * _e h he _ _ µ * * _ M LOG * 6 LOG *_ + ? 0 LOGCLP* 7 LOGCLPGM *GM _ _ g _ _o C Io* * { { + ?* * INQMSGRPY { _ * 8 INQMSGRPY * g _ _- J P- _ - T _ * * + ? # BRKMS* 9 BRKMSG *G _ e _ _e 0 0* *e 9 9e ? , + * * ? E STSMSG * 10 STSMSG * _ e _ _e e _ _e e 0* * 0 n * * { SBRKMSG n Y + * 11 SBRKMSG * _ PRTDEV Y * 12 PRTDEV * _ e _ _e e _ _e * * W U - _ ) * * OUTQ 6 _ e * 13 OUTQ *_ _e e e + i * * ? DATFMT Z _ * 18 DATFMT * £ _ _~ _ ?~ 0 ~ 6 ~ _ ~ s* * & + ? * * DATSEP & _ g* 19 DATSEP * _ _- _ PE h E E E E * * E ? o + * * ? - TIMSEP o _ * 20 TIMSEP * g _ _- _ PE h E E E* * E _ 6 + * * A _ SWS * 21 SWS *_ E _ _ % * * _ µ RUNPTY * 22 RUNPTY * _ ~ _ ? µ * * _ m % _ 2 * *TIMESLICE m _ ~ _ * 23 TIMESLICE * S + * * ? PURGE S * 24 PURGE * _ g _ _o C Io { * * % _ DFT* 25 DFTWAIT *WAIT - _ ~ _ £ * * c - * * J ACGCDE E * 26 ACGCDE * {o M _o _ Y + * * * DUPJOBOPT * 34 DUPJOBOPT * _ e _ _e s s ' * * S % * * *_ g _ _ " r * * % * % * 
Modifying OS/400 Commands

Figure 6 RPG Program to Dump VCP Parameters

 *=============================================================== * To compile: * * CRTRPGPGM PGM(XXX/DMP001RG) SRCFILE(XXX/QRPGSRC) * *=============================================================== *. 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 H 1 C *ENTRY PLIST C PARM PARM01 10 C PARM PARM02 10 * Parameters 03-48 are the same -- omitted to save space C PARM PARM49 10 C PARM PARM50 10 * C DUMP * C MOVE *ON *INLR *. 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 
Modifying OS/400 Commands

Figure 7 Dump of CHGJOB Values

 Parameter Output from RPG Dump JOB PARM01 NOT ADDRESSABLE PARM01.P 000000 POINTER(SPP) NULL JOBQ PARM02 00064A CHAR(10) 'TESTJOBQ ' PARM02.P 000010 POINTER(SPP) SPACE OFFSET 1610 '0000064A'X OBJECT QCAWRKAREA JOBPTY PARM03 00065E CHAR(10) '87TEXT ' PARM03.P 000020 POINTER(SPP) SPACE OFFSET 1630 '0000065E'X OBJECT QCAWRKAREA OUTPTY PARM04 00065F CHAR(10) '7TEXT ' PARM04.P 000030 POINTER(SPP) SPACE OFFSET 1631 '0000065F'X OBJECT QCAWRKAREA PRTTXT PARM05 000660 CHAR(10) 'TEXT ' PARM05.P 000040 POINTER(SPP) SPACE OFFSET 1632 '00000660'X OBJECT QCAWRKAREA LOG PARM06 NOT ADDRESSABLE PARM06.P 000050 POINTER(SPP) NULL . . . SWS PARM21 NOT ADDRESSABLE PARM21.P 000140 POINTER(SPP) NULL RUNPTY PARM22 0006D3 CHAR(10) '002D000000005C000000'X PARM22.P 000150 POINTER(SPP) SPACE OFFSET 1747 '000006D3'X OBJECT QCAWRKAREA TIMESLICE PARM23 NOT ADDRESSABLE PARM23.P 000160 POINTER(SPP) NULL 
Modifying OS/400 Commands

Figure 8 Selected Data from DMP001RG of CHGJOB Command

 PARM02 00064A CHAR(10) 'TESTJOBQ ' PARM02.P 000010 POINTER(SPP) SPACE OFFSET 1610 PARM03 00065E CHAR(10) '87TEXT ' PARM03.P 000020 POINTER(SPP) PARM04 00065F CHAR(10) '7TEXT ' PARM04.P 000030 POINTER(SPP) SPACE OFFSET 1631 PARM05 000660 CHAR(10) 'TEXT ' PARM05.P 000040 POINTER(SPP) SPACE OFFSET 1632 PARM22 0006D3 CHAR(10) '002D000000005C000000'X PARM22.P 000150 POINTER(SPP) SPACE OFFSET 1747 
Modifying OS/400 Commands

Figure 9 Extracting Parameter Information from the Program

 1. The value shown for PARM02 is TESTJOBQ, but experience tells us that this is a qualified name. Where is the library name? Although the library name is passed immediately after the object name, we only dumped ten characters so the library name was not shown. Had the DMP001RG program been modified to dump 20 characters, you would have seen the default library name *LIBL. You can determine that the length of PARM02 is 20 by subtracting the space offset of PARM02 from the next parameter PARM03 as follows: PARM03 SPACE OFFSET 1630 PARM02 SPACE OFFSET 1610 Difference 20 2. PARM03 is one character long and currently has a value of 8. You can calculate the length to be one character by subtracting the space offset of the next parameter. Although the value shown for PARM03 is '87TEXT ', the remainder of the ten characters is data for other parameters. 3. The value shown for PARM04 is '7TEXT ' but using what we have learned about determining, the length this field is also a single character long with a value of 7. 4. The value shown for PARM05 is 'TEXT ' but if you calculate the length, you can determine that this field is actually 30 characters long and the dump only shows the first 10. 
Modifying OS/400 Commands

Figure 10 Change Job Validity Checking Program

 *=============================================================== * To compile: * * CRTRPGPGM PGM(XXX/VCP001RG) SRCFILE(XXX/QRPGSRC) * *=============================================================== * * PURPOSE * Valitity check program for the CHGJOB command * The RUNPTY (run priority parameter) is checked * to prevent any priority less that 20. * * IMPLEMENTATION * If the RUNPTY is not specified on the CHGJOB command * a null parameter is passed. When the program * attempts to reference a null pointer, an exception * is detected which is handled by the program status * data structure. * *=============================================================== *. 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 * Error code data structure for API's IERR IDS I I 16 B 1 40BIN1 I B 5 80BIN2 I 9 15 MSGID I 16 16 FILLER * Call stacker counter I IDS I B 1 40STKCTR I B 5 80DTALEN * Qualified Message IMSGFLB IDS I I 'QCPFMSG' 1 10 MSGF I I '*LIBL' 11 20 MSGFL * Named Constant I '0000Runpty Cannot b- C TEXT I 'e Changed' * BINARY TO DECIMAL CONVERSION IXDS IDS I B 1 20X I 2 2 XX * Program status data structure I SDS I* Exception number I 43 46 ENUM I* CPF message text I 91 170 CPFMSG *=============================================================== C *ENTRY PLIST C PARM PARM01 10 C PARM PARM02 10 * Parameters 03-20 are the same -- omitted to save space C PARM PARM21 10 C PARM PARM22 2 Runpty C PARM PARM23 10 * Parameters 24-33 are the same -- omitted to save space C PARM PARM34 10 * * Convert character to binary thru data structure C CLEARXDS C MOVE PARM22 XX * * If program gets here then the program status subroutine was * not evoked, because a RUNPTY was passed to the validity * checking program * * The Following line will test to see if RUNPTY of less than 20 * was passed. C X IFLT 20 * * Send CPD0006 to command prompter C Z-ADD28 DTALEN C MOVELTEXT MSGDTA P C MOVEL'*DIAG' MSGTYP P C MOVEL'*' TPGMQ P C MOVE 'CPD0006' ERRMSG 7 C EXSR SNDMSG * * Follow by CPF0002 to force prompter to display CPD0006 text C Z-ADD0 DTALEN C Z-ADD1 STKCTR C MOVE *BLANKS MSGDTA C MOVEL'*ESCAPE' MSGTYP P C MOVEL'*' TPGMQ P C MOVE 'CPF0002' ERRMSG C EXSR SNDMSG C ENDIF * C MOVE *ON *INLR *=============================================================== C SNDMSG BEGSR * * Call Send Program Message API C CALL 'QMHSNDPM' C PARM ERRMSG C PARM MSGFLB C PARM MSGDTA 28 C PARM DTALEN C PARM MSGTYP 10 C PARM TPGMQ 10 C PARM STKCTR C PARM MSGKEY 4 C PARM ERR * C ENDSR *=============================================================== C *PSSR BEGSR * C PSRFLG IFEQ '1' * If *PSSR is already handling error and then receives another * set on H1 and return. C MOVE *ON *INH1 C RETRN C ELSE C MOVE '1' PSRFLG 1 C ENUM IFEQ '3601' C MOVE *ON *INLR C RETRN C ENDIF C ENDIF * Reset *PSSR error flag at exit of routine C MOVE '0' PSRFLG * C ENDSR * *. 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 
BLOG COMMENTS POWERED BY DISQUS