iSeries i5/OS: Top 10 Q&As
Ken Graap, iSeries i5/OS expert, has been answering Search400.com's member questions for over five years. Ken has seen many of the same issues and concerns asked over and over. Therefore, we've compiled the top 10 questions asked about iSeries i5/OS for you. Do you have a question that's not listed here?
![]() |
|
![]() |
![]() |
Ken Graap | ![]() |
![]() |
Ken Graap, iSeries i5/OS expert, has been answering Search400.com's member questions for over five years. Ken has seen many of the same issues and concerns asked over and over. Therefore, we've compiled the top 10 questions asked about iSeries i5/OS for you. Do you have a question that's not listed here? Ask Ken your i5/OS questions.
TABLE OF CONTENTS
1. Creating a command shortcut for WRKOUTQ PRT03
2. Moving a spool files from one system to another
3. Editing a word document stored in an IFS shared directory
4. Setting up Remote Journaling between two i5 servers
5. Control the creation of job logs on your system
6. Distribute copies of spool files to several different printers
7. Set up you i5 system to forward email to a corporate email system
8. Secure production data from PUBLIC access
9. Run as another user without having to sign on as that user
10. Set up secure access to a command line from an interactive job
![]() |
![]() |
I need to create a command shortcut for WRKOUTQ PRT03. How do you recommend I do this?
I would suggest that you create a simple command using the QCMDEXC API and then passing it a "constant" value, like this:
/* */ /* CRTCMD CMD(QGPL/WQ3) PGM(QSYS/QCMDEXC) */ /* SRCFILE(Your_Srclib/QCMDSRC) */ /* */ CMD PROMPT('WRKOUTQ PRT03') PARM KWD(CMD) TYPE(*CHAR) LEN(20) CONSTANT('wrkoutq outq(prt03)') PARM KWD(LEN) TYPE(*DEC) LEN(15 5) CONSTANT(20)
Have any other "shortcuts" you would like to create? Consider using this technique instead of creating duplicate system commands.
![]() |
![]() |
I need to move spool files from one system (V4R4) to another (V5R3). Is there an easy way to do this?
Let's assume that your two systems are connected via TCP/IP. Then all you would have to do is create a remote *OUTQ on the V4R4 system pointing to an *OUTQ on the V5R3 system. Any spool file placed on this remote *OUTQ would then be sent to the V5R3 system.
Here is and example for creating a remote *OUTQ:
CRTOUTQ OUTQ(mylib/remoteoutq) -- The *OUTQ on the V4R4 system.
RMTSYS(v5r3sys) -- The DNS name for the V5R3 system.
RMTPRTQ('mylib/v5r3outq') -- The *OUTQ on the V5R3 system.
AUOSTRWTR(1)
CNNTYPE(*IP)
DESTTYPE(*OS400)
Note: If the writer associated with this remote *OUTQ needs to be restarted for any reason, you would have to use the STRRMTWTR command instead of the STRPRTWTR command.
![]() |
![]() |
When I edit a Word document stored in an IFS shared directory, the Word program's temporary files aren't being deleted after I save the document. Why can't Word clean up after itself when using the IFS?
What I believe is happening is that the authority to the IFS directory you are creating your documents in is insufficient.
When a user creates a new file in an IFS directory they become the owner of the file and therefore have all data rights, but the OBJECT authority assigned to the file is based on the authority of the directory it is placed in. Here are the rules:
The owner for the new object has the same object authorities that the owner of the parent directory has to the parent directory.
The primary group for the new object has the same object authorities that the primary group of the parent directory has to the parent directory.
*PUBLIC has the same object authorities to the new object that it has to the parent directory.
In your word processing example, the word processing program creates a temporary file when a file is created or opened for edit. When the user finally saves the document and exits, the PC program attempts to rename the most current temporary file to the original file name. If the user's objects didn't get sufficient private authority from the parent directory (which I suspect they aren't) then this operation can't be completed.
So, check to see whom the OWNER of the parent directory is and what authority they have to it because this will be the authority assigned to any new object created in that directory.
If the OWNER of the directory is different than the user creating the object in the directory (which is probably the case) then the *PUBLIC authority setting comes into play.
The simplest fix to your problem may be to assign *PUBLIC authority, such as:
Data --Object Authorities-- User Authority Exist Mgt Alter Ref *PUBLIC *RX X
Oh, by the way, here is IBM's explanation of "mgt object authority":
The object authorities that the user has to the object. An "X" in the column indicates that the user has the specified object authority to the object named. The specific object authorities are: Mgt Object management authority provides authority to specify security, to move or rename the object, and to add members if the object is a database file.
![]() |
![]() |
How can I set up Remote Journaling between two i5 servers?
This is easier that you might think.
First of all, you will need to establish a TCP/IP connection between the two machines. This could just be an Internet connection. My guess is that you have already done this.
To enable Remote Journaling you would do the following:
1. Define Journaling on the SOURCE system.
For Example:
a. Create a message queue to receive journal messages:
CRTMSGQ MSGQ(QGPL/LAWJRN) TEXT('Lawson journal messages')
b. Create a journal receiver in the proper journal receiver library:
CRTJRNRCV JRNRCV(JRNRCVLAW/LAW2JR0001) THRESHOLD(1000000)
c. Create a journal referencing the receiver just created:
CRTJRN JRN(LAWP1FILES/LAWP1JRN)
JRNRCV(JRNRCVLAW/LAW2JR0001)+
MSGQ(QGPL/LAWJRN) MNGRCV(*SYSTEM) DLTRCV(*NO) +
RCVSIZOPT(*RMVINTENT *MAXOPT2)
2. Create a Relational Database entry to identify the DB on the system you wish to journal to.
For Example:
ADDRDBDIRE RDB(REMOTESYS)
RMTLOCNAME('10.10.10.110' *IP)
TEXT('My Remote system')
3. Create a Remote Journal.
For Example:
ADDRMTJRN RDB(REMOTESYS) SRCJRN(LAWP1FILES/LAWP1JRN) TGTJRN(RMTJRN/LAWP1JRN) RMTRCVLIB(RMTJRN) TEXT('Remote journal for LAWP1FILES')
4. Decide what objects you want to journal and start journaling them.
5. Manage your remote journaling environment.
![]() |
![]() |
How can I control the creation of job logs on my system?
There are several components to how job logs are created on a the system.
The message logging parameters determine what kind of information will be collected:
Message logging: LOG Level . . . . . . . . . . . . 4 Severity . . . . . . . . . . . 00 Text . . . . . . . . . . . . . *NOLIST Log CL program commands . . . . LOGCLPGM *NO
I won't go into all the specifics related to these values, but if the message logging 'TEXT' parameter is set to *NOLIST a job log will only be created if the job ends abnormally. If the job completes normally, no job log will be created.
This is the same whether the job is an interactive or batch job.
If any value other than *NOLIST is specified for the message logging 'TEXT' parameter in a batch job, a job log will always be produced, whether the job ends normally or abnormally.
This works differently for interactive jobs though. In order to conserve disk space the SIGNOFF command has been defined as:
Sign Off (SIGNOFF) Type choices, press Enter. Job log . . . . . . . . . . . . LOG *NOLIST Drop line . . . . . . . . . . . DROP *DEVD End connection . . . . . . . . . ENDCNN *NO
So, by default, when an interactive job is ended normally, no joblog will be produced.
However, if the interactive job ends abnormally a joblog and most likely a program dump, will be produced.
If you want to force the creation of a job log from an interactive job you can do it in one of two ways.
1. When you sign off enter SIGNOFF LOG(*LIST).
2. Prior to signing off enter DSPJOBLOG OUTPUT(*PRINT).
When one of these options is used a job log is created.
On V5R4 of OS400 the job log creation process has been enhanced. To review the changes, following this link.
![]() |
![]() |
I need to distribute copies of spool files to several different printers. Is there an easy way to do this without having to purchase additional software for my system?
Yes, I think there is a "simple" process for distributing copies of spool files to different printers using just basic OS/400 commands and definitions.
With just a few simple user profiles, distribution entries and the SNDNETSPLF command you can create a spool file distribution system.
You'll find the pieces in a past tip of mine"Distribute spool files to printers easily."
![]() |
![]() |
How would I set up my i5 system to forward email to my corporate email system?
To enable email forwarding from your i5 server requires that you do a couple of things.
First, you need to change the System directory Attributes via the CHGSYSDIRA command:
CHGSYSDIRA USRDFNFLD((FORWARDING *NONE *ADD *ADDRESS 256) (FWDSRVLVL *NONE *ADD *MSFSRVLVL 1))
This sets up the User defined fields like this:
Change System Dir Attributes (CHGSYSDIRA)
Type choices, press Enter.
User-defined fields: USRDFNFLD Field name . . . . . . . . . . FORWARDING Product ID . . . . . . . . . . *NONE Function . . . . . . . . . . . *KEEP Field type . . . . . . . . . . *ADDRESS Maximum field length . . . . . 256 Field name . . . . . . . . . . FWDSRVLVL Product ID . . . . . . . . . . *NONE Function . . . . . . . . . . . *KEEP Field type . . . . . . . . . . *MSFSRVLVL Maximum field length . . . . . 001
Next you need to define where to forward email to for each user's directory entry. In this example, I will define that any email delivered to i5 user KEG to be forwarded to their internet email address: keg@nwnatural.com
CHGDIRE USRID(KEG S02) USRDFNFLD((FORWARDING *NONE KEG@NWNATURAL.COM))
MSFSRVLVL(FWDSRVLVL *NONE) PREFADR(FORWARDING *NONE MIME)
This change can be verified from the DSPDIRE USRID(KEG S02) screen via the F20 key:
Display User-Defined Fields User ID/Address . . . . : KEG S02 FORWARDING : KEG@nwnatural.com With these configurations changes in place, any email sent to keg.s02@s02.gasco.com will be automatically forwarded to keg@nwnatural.com. This can be verified by reviewing the entries in the QZMF journal: Message ID Job User Number Program ID 10E844A0605111113150000002142 QTSMTPSRVP QTCP 429585 QZMFXLOG Date Time Data Comment 5/11/06 11:13:15 9 99 MSGID: 11:13:15 9 9T MSG SIZE 3326 11:13:15 9 94 LIN TO SRVR 198.5.59.26 11:13:15 9 91 O keg@NWNATURAL.COM 11:13:15 9 92 R11:13:15 9 97 SRVR TO QTMSINQ 11:13:15 7 7A QTMSINQ TO BRSR 11:13:15 7 7H BRSR TO MSF 11:13:15 7 71 O keg@NWNATURAL.COM 11:13:15 7 72 R 11:13:15 1 MSF message create 11:13:16 P P2 R chg to SNADS, can parse ... 11:13:16 H H1 01A1 KEG S02 01B... 11:13:16 5 00001 00001 11:13:16 P P2 R SMTP MsgFwd KEG@nwnatural.com 11:13:17 C C6 FWD TO QTMSOUTQ 11:13:17 C C1 O keg@NWNATURAL.COM 11:13:17 C C2 R 11:13:17 8 8B QTMSOUTQ TO CLNT 11:13:17 2 000010000100000 11:13:17 8 88 DLVED 198.5.59.26 Successful delivery 11:13:17 8 82 R
That's all there is to it.
![]() |
![]() |
How can I secure production data from PUBLIC access, on a system used for both production and development work?
One solution would be to set up two partitions on your system, production and development. However, sometimes this isn't possible for a number of reasons.
Another solution is to utilize OS/400 security to create separate application environments within a single partition.
This can be done using Adopted Authority and Application Access programs.
Environment:
1. Access to the production environment is denied to the public by default (*PUBLIC *EXCLUDE)
2. The change management profile (CHANGEMGT) will have *ALL access to production objects… Source, Data and Programs.
3. Development users will be able to READ production source.
4. All users can EXECUTE production programs to allow for testing with development data.
5. CHANGE access to production data, will be granted to authorized production users through a Production Application Access program set to adopt authority.
Implementation:
Production source files will be owned by user profile PRODSRC
The libraries and objects within the source libraries, will have *PUBLIC *AUTL authority defined and be secured by an authority list named PRDSRC
Authority granted through authority list PRDSRC will be:
*PUBLIC *EXCLUDE DEVELOPMENT *USE CHANGEMGT *ALL
This prevents general users from accessing production source files, but allows development users READ access. Of course the CHANGEMGT profile has all authority so it can be used to maintain the application.
Production application data will be owned by user profile PRODDATA
The libraries and objects within the libraries, will have *PUBLIC *AUTL authority defined and be secured by authority list PRDDATA
Authority granted through authority list PRDDATA will be:
PRODAAP *CHANGE *PUBLIC *EXCLUDE CHANGEMGT *ALL
This insures that production data is excluded from all but PRODAAP. Production uses will adopt this authority to access the data.
Production application programs will be owned by user profile PRODAPP
The libraries and objects within the application program libraries, will have *PUBLIC *AUTL authority defined and be secured by authority list PRDAPP
Authority granted through authority list PRDAPP will be:
*PUBLIC *USE CHANGEMGT *ALL
This provides access to the application code for all users. This is OK because they can only use these programs to access data they own (test data) unless they adopt authority from a Production Application Access program, and only production users have access to Production Application Access programs. CHANGEMGT has all authority so it can be used to maintain the application.
All production user profiles will have an initial program of PRDAAP defined.
Program PRDAAP will be owned by user profile PRODAPP and defined to adopt the program owner's authority - CHGPGM PGM(PRDAAP) USRPRF(*OWNER).
Authority to program PRDAAP will be:
*PUBLIC *EXCLUDE PRODUSER *USE
This is the KEY to the whole configuration. Only members of the PRODUSER group will be able to execute this Application Access program and adopt the authority necessary to access production data! Development and test users would have Application Access Programs that don't adopt authority and therefore they could not access production data even if they could modify their library lists.
Production Application Access programs will need to be created for each type of access, Interactive, Batch, ODBC etc… These programs will need to be set to adopt the authority for user PRODAAP too.
When a Production Application Access program is used, authority to production data is allowed via program adoption.
The following graphic illustrates this whole process.
![]() |
![]() |
![]() |
How can I run as another user without having to sign on as that user?
OS/400 does have API's that allow you to swap to another user profile within your current job. These programs are usually used to swap profiles within a server program, but you can use them to swap within your programs, too.
To maintain secure access to user profiles there are a few requirements that need to be met before you can perform a user swap.
First of all, the source and target user profiles will need to have *USE authority to the swapping API programs, QWTSETP & QSYGETPH. Both programs will need to have *USE access to each other before swapping can occur, too.
Once these requirements are satisfied, the following program could be used to swap to another program without having to supply a password:
Note: This program code is enhanced to monitor for errors and notify the System Administrator when they occur. These enhancements are optional to the swapping process, but it isn't a bad idea to monitor the use of a program like this.
PGM PARM(&NEWUSER) /* ************************************************************** */ /* */ /* DECLARE PROGRAM VARIABLES */ /* */ /* ************************************************************** */ DCL VAR(&USRPRF) TYPE(*CHAR) LEN(10) DCL VAR(&NEWUSER) TYPE(*CHAR) LEN(10) DCL VAR(&PRFHDL) TYPE(*CHAR) LEN(12) DCL VAR(&PRFHDLCUR) TYPE(*CHAR) LEN(12) DCL &ERRORSW *LGL /* Std err */ DCL &MSGID *CHAR LEN(7) /* Std err */ DCL &MSGDTA *CHAR LEN(100) /* Std err */ DCL &MSGF *CHAR LEN(10) /* Std err */ DCL &MSGFLIB *CHAR LEN(10) /* Std err */ /* ************************************************************** */ /* */ /* GLOBAL MESSAGE MONITOR */ /* */ /* ************************************************************** */ MONMSG MSGID(CPF6801) /* Monitor for F3 from + command Prompt */ MONMSG MSGID(CPF0000) EXEC(GOTO CMDLBL(STDERR1)) RTVJOBA USER(&USRPRF) SNDPGMMSG MSG('User: "' *TCAT &USRPRF *TCAT '" is using + RUNAS to swap to USRPRF: "' *TCAT + &NEWUSER *TCAT '"') TOMSGQ(CRITMSG) CALL PGM(QSYGETPH) PARM(*CURRENT '*NOPWD ' + &PRFHDLCUR) /* Needed to swap back .... */ CALL PGM(QSYGETPH) PARM(&NEWUSER '*NOPWD ' + &PRFHDL) MONMSG MSGID(CPF22E9) EXEC(DO) /* Not enough + authority to SWAP. */ SNDSTSMSG MSG('You don''t have authority to swap to + USRPRF: "' *TCAT &NEWUSER *TCAT '"') DLY(3) DLYJOB DLY(3) SNDSTSMSG MSG('Contact the System Administrator - KEG + or KKH...') DLY(5) DLYJOB DLY(5) SNDCOMPMSG MSG('Contact the System Administrator - KEG + or KKH...') SNDPGMMSG MSG('User: "' *TCAT &USRPRF *TCAT '" tried + using RUNAS to swap to USRPRF: "' *TCAT + &NEWUSER *TCAT '". They were unable to + SWAP due to an authority issue.') + TOMSGQ(CRITMSG) GOTO CMDLBL(END) ENDDO MONMSG MSGID(CPF22E4) EXEC(DO) /* Password expired */ SNDSTSMSG MSG('The password is expired for USRPRF: "' + *TCAT &NEWUSER *TCAT '"') DLY(3) DLYJOB DLY(3) SNDSTSMSG MSG('Contact the System Administrator - KEG + or KKH...') DLY(5) DLYJOB DLY(5) SNDCOMPMSG MSG('Contact the System Administrator - KEG + or KKH...') SNDPGMMSG MSG('User: "' *TCAT &USRPRF *TCAT '" tried + using RUNAS to swap to USRPRF: "' *TCAT + &NEWUSER *TCAT '". They were unable to + SWAP because the password is expired.') + TOMSGQ(CRITMSG) GOTO CMDLBL(END) ENDDO SNDSTSMSG MSG('Here we go, ready... set... SWAP + profiles!!!!') DLY(5) DLYJOB DLY(5) CALL PGM(QWTSETP) PARM(&PRFHDL) CALL PGM(GRTCMDAUD) /* Make sure commands are + being audited. */ SNDSTSMSG MSG('You are now running as user profile : + "' *TCAT &NEWUSER *TCAT '"') + DLY(5) DLYJOB DLY(5) SNDSTSMSG MSG('You will now be prompted to change some + Job/User Profile values.') DLY(5) DLYJOB DLY(5) ? CHGJOB ?-JOB(*) ?-JOBPTY(*SAME) + ?-OUTPTY(*SAME) ?-PRTDEV(*SAME) + ??OUTQ(*SAME) ?-RUNPTY(*SAME) + ?-JOBQ(*SAME) ?-PRTTXT(*SAME) ?-LOG(*SAME + *SAME *SAME) ?-LOGCLPGM(*SAME) + ?-INQMSGRPY(*SAME) ?-BRKMSG(*SAME) + ?-STSMSG(*SAME) ?-DDMCNV(*SAME) + ?-SCDDATE(*SAME) ?-SCDTIME(*SAME) + ?-DATE(*SAME) ?-DATFMT(*SAME) + ?-DATSEP(*SAME) ?-TIMSEP(*SAME) + ?-SWS(*SAME) ?-TIMESLICE(*SAME) + ?-PURGE(*SAME) ?-DFTWAIT(*SAME) + ?-DEVRCYACN(*SAME) ?-TSEPOOL(*SAME) + ?-PRTKEYFMT(*SAME) ?-SRTSEQ(*SAME) + ?-LANGID(*SAME) ?-CNTRYID(*SAME) + ?-CCSID(*SAME) ?-JOBMSGQFL(*SAME) + ?-DUPJOBOPT(*SELECT) ? CHGPRF ?-ASTLVL(*SAME) ?-CURLIB(*SAME) + ?-INLPGM(*SAME) ?-INLMNU(*SAME) + ?-TEXT(*SAME) ?-KBDBUF(*SAME) + ?-JOBD(*SAME) ?-DOCPWD(*SAME) + ?-MSGQ(*SAME) ?-DLVRY(*SAME) ?-SEV(*SAME) + ?-PRTDEV(*SAME) ??OUTQ(*SAME) + ?-ATNPGM(*SAME) ?-SRTSEQ(*SAME) + ?-LANGID(*SAME) ?-CNTRYID(*SAME) + ?-CCSID(*SAME) ?-CHRIDCTL(*SAME) + ?-SETJOBATR(*SAME) ?-LOCALE(*SAME) + ?-USROPT(*SAME) ?-HOMEDIR(*SAME) ? CHGLIBL OVRPRTF FILE(*PRTF) SPLFOWN(*JOB) /* Keep spool + files with this job. */ SNDSTSMSG MSG('I'll now give you a command entry + screen. Have fun!') DLY(5) DLYJOB DLY(5) SNDSTSMSG MSG('When finished, use F3 to return to your + original user profile.') DLY(5) DLYJOB DLY(5) CALL PGM(QCMD) /* Present a command screen while + running as the NEW user... */ DSPJOBLOG OUTPUT(*PRINT) /* Generate a joblog */ CALL PGM(QWTSETP) PARM(&PRFHDLCUR) SNDSTSMSG MSG('You are now returning to user profile : + "' *TCAT &USRPRF *TCAT '"') DLY(5) DLYJOB DLY(5) SNDSTSMSG MSG('You will now be allowed to reset some + Job/User Profile values, if you want + to.') DLY(5) DLYJOB DLY(5) ? CHGJOB ?-JOB(*) ?-JOBPTY(*SAME) + ?-OUTPTY(*SAME) ?-PRTDEV(*SAME) + ??OUTQ(*SAME) ?-RUNPTY(*SAME) + ?-JOBQ(*SAME) ?-PRTTXT(*SAME) ?-LOG(*SAME + *SAME *SAME) ?-LOGCLPGM(*SAME) + ?-INQMSGRPY(*SAME) ?-BRKMSG(*SAME) + ?-STSMSG(*SAME) ?-DDMCNV(*SAME) + ?-SCDDATE(*SAME) ?-SCDTIME(*SAME) + ?-DATE(*SAME) ?-DATFMT(*SAME) + ?-DATSEP(*SAME) ?-TIMSEP(*SAME) + ?-SWS(*SAME) ?-TIMESLICE(*SAME) + ?-PURGE(*SAME) ?-DFTWAIT(*SAME) + ?-DEVRCYACN(*SAME) ?-TSEPOOL(*SAME) + ?-PRTKEYFMT(*SAME) ?-SRTSEQ(*SAME) + ?-LANGID(*SAME) ?-CNTRYID(*SAME) + ?-CCSID(*SAME) ?-JOBMSGQFL(*SAME) + ?-DUPJOBOPT(*SELECT) ? CHGLIBL SNDSTSMSG MSG('Welcome back!') DLY(3) DLYJOB DLY(3) SNDSTSMSG MSG(*REMOVE) SNDCOMPMSG MSG('Welcome back!') SNDPGMMSG MSG('User: "' *TCAT &USRPRF *TCAT '" has + finished using RUNAS to swap to USRPRF: + "' *TCAT &NEWUSER *TCAT '"') TOMSGQ(CRITMSG) /* ************************************************************** */ /* */ /* NORMAL END OF PROGRAM */ /* */ /* ************************************************************** */ END: RETURN /* ************************************************************** */ /* */ /* STANDARD ERROR PROCESSING */ /* */ /* ************************************************************** */ STDERR1: /* Standard error handling routine */ IF &ERRORSW SNDPGMMSG MSGID(CPF9999) + MSGF(QCPFMSG) MSGTYPE(*ESCAPE) /* Func chk */ CHGVAR &ERRORSW '1' /* Set to fail ir error occurs */ STDERR2: RCVMSG MSGTYPE(*DIAG) MSGDTA(&MSGDTA) MSGID(&MSGID) + MSGF(&MSGF) MSGFLIB(&MSGFLIB) IF (&MSGID *EQ ' ') GOTO STDERR3 SNDPGMMSG MSGID(&MSGID) MSGF(&MSGFLIB/&MSGF) + MSGDTA(&MSGDTA) MSGTYPE(*DIAG) GOTO STDERR2 /* Loop back for addl diagnostics */ STDERR3: RCVMSG MSGTYPE(*EXCP) MSGDTA(&MSGDTA) MSGID(&MSGID) + MSGF(&MSGF) MSGFLIB(&MSGFLIB) SNDPGMMSG MSGID(&MSGID) MSGF(&MSGFLIB/&MSGF) + MSGDTA(&MSGDTA) MSGTYPE(*ESCAPE) ENDPGM
![]() |
![]() |
How can I set up secure access to a command line from an interactive job?
One way to do this is to modify how the System Request menu works.
By default the System Request 90 option will execute the SIGNOFF command.
This option is defined by the contents of Message Description CPX2313, which can be found in message file QSYS/QCPFMSG:
Message file . . . . . . . : QCPFMSG Library . . . . .. . . . .: QSYS Message IDs: CPX2313 CPX2313 Message . . . . : ENDRQS DSPJOB DSPMSG SNDMSG SIGNOFF DSPMSG DSCJOB DSPWSUSR ENDRDBRQS Severity . . . . . . . . . . . . . . . . . : SEV 0 Message level . . . . . . . . . . . . . . : LVL 04/10/99 65 Modification level . . . . . . . . . . . : 07/02/05 66 Alert option . . . . . . . . . . . . . . . : ALROPT *NO Log problem . . . . . . . . . . . . . . . : LOGPRB *NO Coded character set ID . . . . . . . . . . : CCSID 65535 • * * * * E N D O F L I S T I N G * * * * *
A simple command can be written that will check an authority list and call the command line API (QUSRCMDLN) if a user is authorized or just sign off the user if they aren't authorized to get a command line.
To implement this process do the following:
First define an authority list named SYSRQ90. Add the names of any individual user or group profiles you would like to give command line access via System Request 90, using the following commands:
For individual users: ADDAUTLE AUTL(SYSRQ90) USER(xxx) AUT(*USE)
For group profiles: ADDAUTLE AUTL(SYSRQ90) USER(xxx) AUT(*USE *AUTLMGT)
Next modify the CPX2313 message replacing SIGNOFF with SYSRQ90:
Do WRKMSGD CPX2313 and then use Option 2 to get the following prompt of the CHGMSGD command:
Change Message Description (CHGMSGD) Type choices, press Enter. Message identifier . . . . . . . MSGID > CPX2313 Message file . . . . . . . . . . MSGF > QCPFMSG Library . . . . . . . . . . . > QSYS First-level message text . . . . MSG 'ENDRQS DSPJOB DSPMSG SNDMSG SYSRQ90 DSPMSG DSCJOB DSPWSUSR ENDRDBRQS '
Make sure you don't change the spacing between the commands in this list. They have to be entered exactly as shown or System Request will not function correctly!
Create the following program and command:
CRTCLPGM PGM(QGPL/SYSRQ90)
Here is the program source: /* ************************************************************** */ /* PROGRAM DESCRIPTION : WHEN A USER ENTERS SYSRQ 90 THIS PROGRAM */ /* IS CALLED. MESSAGE DESCRIPTION CPX2313 */ /* WAS UPDATED TO CALL THIS PROGRAM INSTEAD */ /* OF SIGNOFF */ /* */ /* */ /* SPECIAL COMPILE OPTIONS: DON'T ALLOW ADOPTED AUTHORITY */ /* */ /* */ /* WRITTEN BY: KEN GRAAP 07/14/94 */ /* UPDATED BY: */ /* */ /* ************************************************************** */ PGM /* ************************************************************** */ /* */ /* DECLARE PROGRAM VARIABLES */ /* */ /* ************************************************************** */ DCL VAR(&USER) TYPE(*CHAR) LEN(10) DCL VAR(&GROUP) TYPE(*CHAR) LEN(10) DCL VAR(&READ) TYPE(*CHAR) LEN(10) DCL &ERRORSW *LGL /* Std err */ DCL &MSGID *CHAR LEN(7) /* Std err */ DCL &MSGDTA *CHAR LEN(100) /* Std err */ DCL &MSGF *CHAR LEN(10) /* Std err */ DCL &MSGFLIB *CHAR LEN(10) /* Std err */ /* ************************************************************** */ /* */ /* GLOBAL MESSAGE MONITOR */ /* */ /* ************************************************************** */ MONMSG MSGID(CPF0000) EXEC(GOTO CMDLBL(STDERR1)) /* ************************************************************** */ /* */ /* CALL QUSCMDLN IF THE USER IS AUTHORIZED TO USE THIS FUNCTION */ /* */ /* ************************************************************** */ RTVUSRPRF RTNUSRPRF(&USER) GRPPRF(&GROUP) USER: RTVAUTLE AUTL(SYSRQ90) USER(&USER) READ(&READ) MONMSG MSGID(CPF22A7 CPF22A8) EXEC(GOTO CMDLBL(GROUP)) IF COND(&READ *EQ *READ) THEN(DO) CALL PGM(QSYS/QUSCMDLN) GOTO CMDLBL(END) ENDDO GOTO CMDLBL(SIGNOFF) GROUP: IF COND(&GROUP *EQ *NONE) THEN(GOTO + CMDLBL(SIGNOFF)) RTVAUTLE AUTL(SYSRQ90) USER(&GROUP) READ(&READ) MONMSG MSGID(CPF22A7 CPF22A8) EXEC(GOTO + CMDLBL(SIGNOFF)) IF COND(&READ *EQ *READ) THEN(DO) CALL PGM(QSYS/QUSCMDLN) GOTO CMDLBL(END) ENDDO SIGNOFF: SIGNOFF LOG(*LIST) /* ************************************************************** */ /* */ /* NORMAL END OF PROGRAM */ /* */ /* ************************************************************** */ END: RETURN /* ************************************************************** */ /* */ /* STANDARD ERROR PROCESSING */ /* */ /* ************************************************************** */ STDERR1: /* Standard error handling routine */ IF &ERRORSW SNDPGMMSG MSGID(CPF9999) + MSGF(QCPFMSG) MSGTYPE(*ESCAPE) /* Func chk */ CHGVAR &ERRORSW '1' /* Set to fail ir error occurs */ STDERR2: RCVMSG MSGTYPE(*DIAG) MSGDTA(&MSGDTA) MSGID(&MSGID) + MSGF(&MSGF) MSGFLIB(&MSGFLIB) IF (&MSGID *EQ ' ') GOTO STDERR3 SNDPGMMSG MSGID(&MSGID) MSGF(&MSGFLIB/&MSGF) + MSGDTA(&MSGDTA) MSGTYPE(*DIAG) GOTO STDERR2 /* Loop back for addl diagnostics */ STDERR3: RCVMSG MSGTYPE(*EXCP) MSGDTA(&MSGDTA) MSGID(&MSGID) + MSGF(&MSGF) MSGFLIB(&MSGFLIB) SNDPGMMSG MSGID(&MSGID) MSGF(&MSGFLIB/&MSGF) + MSGDTA(&MSGDTA) MSGTYPE(*ESCAPE) ENDPGM
CRTCMD CMD(QGPL/SYSRQ90) PGM(QGPL/SYSRQ90)
Here is the command source:
CMD PROMPT('System Request 90')
That's all there is to it. The next time a user does a SYSTEM REQUEST 90 option they will either be signed off, or they will get a command line, depending on if they are on the SYSRQ90 Authority List or not.
Start the conversation
0 comments