The system supports the capability (as of V4R5) to retrieve a command
that is about to be run or to change a command that is about to be
run. This function provides significant capability, but there are
important considerations. The exit program cannot be used to
guarantee all command usage will be changed and you can expose
yourself to errors by using an exit program.
This tool is a documentation member plus sample source in a CL member
on how to do an Exit program. The code shown handles the case where
you want to ensure that a parameter value is not used.
You can provide an Exit program for most commands with the major
** Any 'CL compiler only' command (such as DCL, ENDDO, RCVF) and
any RTV command that returns a value (such as RTVJOBA).
** The CALL command.
There are a few significant considerations when you use an Exit
** If the user specified a command with a library qualifier, you
cannot change it. For example, CRTxxx can be changed, but
QSYS/CRTxxx cannot. The intent of this is to allow system
code that uses CL commands to run without modification, but it
also allows a 'back door' for users who want to bypass your
change function. In addition to system commands, you cannot
change a user command if it is library qualified.
** When you change the operation of a command, you are exposed to
problems caused by running code written by other individuals
that are not aware of any potential changes. The system
protects against this by library qualifying all command use in
its CL programs. TAA Tool commands do not always use library
qualifiers within CL programs. Other products and code that
you have written yourself or picked up from outside sources
will also not be aware of your changes.
** Your exit program will only be called once. If the command is
prompted for, your exit program will gain control and should
change and protect the prompted version. If you don't protect
the parameter (prevent it from being changed by the ?*
function), the user could overkey and defeat your intention.
Your exit program is not called again when the command is run.
The example code shows how to provide this protection.
** You cannot send an escape message and get the command to fail.
The system monitors for any escape messages sent and ignores
them. Consequently, if you are attempting to use the function
to prevent the use of a certain command or parameter, you can
only change a parameter or change to a different command. For
example, you could run the TAA NOOP command.
If you want to send an escape message and prevent the use of
the command, see the later discussion of the SNDESCMSG4
In order to have the system invoke your Exit program, you must
'register' the request with the ADDEXITPGM command. See the later
The 'Retrieve' function allows you to determine that a command is
being run. This function may not seem very exciting, but you could
use it to:
** Prevent the use of a command or prevent the use by a specific
** Log the fact that a specific command occurred. This is the
same function you can get with object level auditing which
only requires commands to invoke (not writing a program).
** Log a command if a particular parameter value was used. You
could also do this using object level auditing plus a program
that scanned for the parameter use.
** Notify someone immediately that a command or parameter was
being used. Note that it is too late to stop the command from
If you want to write a Retrieve Exit, follow the example provided
with this tool for the Change Exit along with the system
documentation for the 'Command Analyzer Retrieve Exit Program'.
The 'Change' function is where the real meat is. For example, you
could add or change a parameter value, or use a totally different
command. Remember, however, that there are exceptions and
considerations as described earlier. The Exit program is not a 'fail
safe' form or protection.
Reading about the details
You can read about the Exit programs by using the Info Center CD and
successively clicking on:
- CL and APIs
- APIs by Category
- Program and CL Command
Then roll to the section on 'Exit Programs'. Look at the details of:
- Command Analyzer Change
- Command Analyzer Retrieve
Registering the Exit
If you want to use a Change Exit, you probably want to practice on a
command that is unlikely to be used until you get familiar with the
process. For this reason, the example code uses the CRTDKTF command
and prevents the user from using FILETYPE(*DATA) which is the
default. Instead, the example exit program changes all CRTDKTF
commands to FILETYPE(*SRC). While this is an 'academic example', it
is typical of what many users may want to do.
You need to register your Exit program for the command you want to
Because you can have multiple Exit programs, the system uses the
PGMNBR parameter to provide a unique ID. To allow for inserting a
later exit, you might assign a value such as 50 to begin with.
As QSECOFR (or a user with security rights), enter the ADDEXITPGM
command. The name of your exit program goes in the PGM parameter.
The example requests the program be called whenever the CRTDKTF
command in QSYS is used.
ADDEXITPGM EXITPNT(QIBM_QCA_CHG_COMMAND) FORMAT(CHGC0100)
PGMDTA(*JOB 20 'CRTDKTF QSYS ')
If you want to remove an Exit, use the RMVEXITPGM command such as:
RMVEXITPGM EXITPNT(QIBM_QCA_CHG_COMMAND) FORMAT(CHGC0100)
You can only have one change exit per command.
There is also a WRKREGINF command that will let you see what is
registered. You will find lots of system function is already
registered. In fact, the Exit points for CHG and RTV are already in
the list, but may not have any programs.
Use Option 8 to 'Work with exit programs'. A list of the programs is
displayed along with the unique PGMNBR value you assigned. Removing
is easy here, but adding is more difficult because you cannot
re-prompt the command in case of errors. You may prefer to use
command entry when you want to do an Add.
Writing the Exit program
The 'Change Exit' documentation (on the Info CD) describes the
details of how to code the exit.
The exit program gets called in the following situations:
** Prompting the command
** Performing interparmeter checks
** Calling the validity checker program
** Transferring control to the command processing program (CPP)
but the program is only called once. This means if the command is
prompted, has a validity checker, and is run, your program will only
get one shot at changing the command. Since prompting would occur
first, that is when your exit program will gain control. If the
command is prompted, you can insert your value before the prompter
displays the value, but you will want to make sure that the operator
cannot change your value. The example code provides for this.
The exit program receives a standard parameter list that includes the
command name and any parameters along with the keyword names. A
return parameter is used for the command to be run.
If you want to send an escape message from the exit, a discussion
exists in the example as well as a 'commented out' line of code. See
the later discussion on SNDESCMSG4.
The example code is fairly standard if you have the same requirement
of forcing the use of a command parameter value. The example assumes
that you always want CRTDKTF to use FILETYPE(*SRC) instead of the
default of FILETYPE(*DATA).
Note that CHGCMDDFT will allow you to change the default of a
command, but you cannot enforce its use. The sample Change Exit will
enforce the use of *SRC (unless the command is qualified as
QSYS/CRTDKTF as described earlier).
Your requirements could be different in which case you will need to
make several changes to the example code.
You can view the example code with the command:
You can copy this code to your source file and member by specifying:
CPYTAA TAAARCMBR(TAACMEMC) TOMBR(xxx)
SNDESCMSG4 for sending an escape message
The system monitors for any escape messages sent from the Command
Exit program and ignores them. Consequently, you cannot use
SNDPGMMSG or a TAA command like SNDESCMSG to cause an escape message
that will prevent the use of the original command. You cannot return
with a different command that is a CALL to a program that will send
an escape message because CALL is prevented as a return command.
You can however, use a different command from what was entered that
invokes a CPP that sends an escape message to cause the original
command to fail.
This is the purpose of the TAA command SNDESCMSG4. You must build up
this command as a string and then use it as the replaced command.
The function exists in the example code, but the branch to the
function is 'commented out'.
SNDESCMSG4 sends the TAA1020 message from TAAMSGF in TAATOOL. The
second level text identifies it as coming from SNDESCMSG4.
None, but the following TAA Tools are used in the example.
SCNVAR Scan variable
SCNVARRGT Scan variable from the right
SNDAUDE Send audit entry
SNDESCMSG4 Send escape message 4
None, this is only a documentation tool.
Objects used by the tool
Object Type Attribute Src member Src file
------ ---- --------- ---------- ----------
Only source is provided for the example.