Access another jobs QTEMP

From MidrangeWiki
Revision as of 17:05, 25 May 2005 by David (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

From an email by Larry Ducie available in the rpg400 archives at: http://archive.midrange.com/rpg400-l/200505/msg00297.html

Chaps,

I've just reviewed the code and it's more simple than I remembered - 4 CLLE programs and three commands. They're all very small so I'll post all 7 at the foot of this mail. (I hope you don't mind David - and apologies to all, but there's nothing worse than looking for something in the archives and all you find are references of source passed off-list)

First - an overview of how it works: To get started quickly all objects must be compiled into library JOBCMDLIB. This is because it's hard-coded. But as you now have the source, you can do what you want. :-)

Basically, it works by starting a job trace on the job you are investigating. When starting a trace you can specify an exit program. As this exit program is invoked WITHIN the environment of the job being traced it can be used as a hook within the job. Every time a traceable event occurs within the job it will call this program. By default this program marks the trace as processed and discards it - so an actual trace is not generated. You can optionally specify whether you wish to service this job - good for debugging.

When you issue command STRJOBCMD it starts a trace, and registers program EXITTRC. It also creates a message queue in library JOBCMDLIB that uniquely references that job. Every time the exit program is called it looks for entries on that mesage queue and passes the command on it directly to QCMDEXC. This allows you to run commands within that job - using the job's user profile!

When you issue command SNDJOBCMD it lets you create a command string and then passes it to the message queue created for the job you're tracing. Next time it generates a traceable event it executes your command. It's as simple as that!

When you issue command ENDJOBCMD it ends the trace. You can specify whether you wish to end the service of the job too - good if you're servicing and debugging the job and wish to keep debugging.

That's it.

To create the commands:

  1. create a library called JOBCMDLIB
  2. compile the four CLLE programs into library JOBCMDLIB.
  3. compile the three commands into library JOBCMDLIB, specify the CLLE of the same name as the processing program.

You will also need to create a message queue called CMDLOG in library JOBCMDLIB. This will log all commands sent to jobs via this route. This is important as there is practically no way of knowing somebody is doing this. You can piggyback one job after another and then it'd be almost impossible to trace the fact that actions invoked within one job was actually caused by another user running another job.

Finally, here's a good test:

  1. Start two sessions.
  2. Leave session 1 on a command line.
  3. Add JOBCMDLIB to the library list of session 2 and issue command STRJOBCMD - enter the job details of session 1, and opt to service the job.
  4. In session 2 issue command SNDJOBCMD and place the job details of session 1 again. This time type a call command to your favourite interactive screen program.
  5. Simply press Enter in session 1.

The program should be called, and the screen should appear.

Have fun! (I've copy 'n' pasted the source into the mail so I hope it formats OK).

I'll try and set up a savf to download on my website.

Cheers

Larry Ducie

Source:

STRJOBCMD - CLLE

/* **************************************************************** */
             PGM        PARM(&JOB &SRVJOB)

             DCL        VAR(&JOB)    TYPE(*CHAR) LEN(26)
             DCL        VAR(&NAME)   TYPE(*CHAR) LEN(10)
             DCL        VAR(&USER)   TYPE(*CHAR) LEN(10)
             DCL        VAR(&NUMBER) TYPE(*CHAR) LEN(6)
             DCL        VAR(&SRVJOB) TYPE(*CHAR) LEN(1)
             DCL        VAR(&MSGQ)   TYPE(*CHAR) LEN(10)

/* Extract job details...                                           */
             CHGVAR     VAR(&NAME)   VALUE(%SST(&JOB  1 10))
             CHGVAR     VAR(&USER)   VALUE(%SST(&JOB 11 10))
             CHGVAR     VAR(&NUMBER) VALUE(%SST(&JOB 21 6))

/* Service job..?                                                   */
             IF         COND(&SRVJOB *EQ 'Y') THEN(DO)
             STRSRVJOB  JOB(&NUMBER/&USER/&NAME)

/* Job does not exist...                                            */
             MONMSG     MSGID(CPF3520) EXEC(DO)
             SNDPGMMSG  MSG('The job you are trying to send a +
                          command to does not exist') TOPGMQ(*PRV)
             GOTO       CMDLBL(END)
             ENDDO

/* Job already being serviced...                                    */
             MONMSG     MSGID(CPF3501) EXEC(DO)
             SNDPGMMSG  MSG('Job is already being serviced, traced +
                          or debugged') TOPGMQ(*PRV)
             GOTO       CMDLBL(END)
             ENDDO


/* Already servicing another job...                                 */
             MONMSG     MSGID(CPF3938) EXEC(DO)
             SNDPGMMSG  MSG('You are already servicing another job') +
                          TOPGMQ(*PRV)
             GOTO       CMDLBL(END)
             ENDDO

/* General errors...                                                */
             MONMSG     MSGID(CPF3500) EXEC(DO)
             SNDPGMMSG  MSG('An error occurred when trying to +
                          service the job. See joblog for +
                          details.') TOPGMQ(*PRV)
             GOTO       CMDLBL(END)
             ENDDO
             ENDDO

/* Create message queue...                                           */
             CHGVAR     VAR(&MSGQ) VALUE('SRVJ' *CAT &NUMBER)
             CRTMSGQ    MSGQ(JOBCMDLIB/&MSGQ)
             MONMSG     CPF9999

/* Set trace...                                                     */
             TRCJOB     EXITPGM(JOBCMDLIB/EXITTRC)
             MONMSG     CPF9999 EXEC(DO)
             SNDPGMMSG  MSG('An error occurred when trying to +
                          trace the job. See joblog for +
                          details.') TOPGMQ(*PRV)
             IF         COND(&SRVJOB *EQ 'Y') THEN(DO)
             ENDSRVJOB
             MONMSG     MSGID(CPF9999)
             ENDDO
             DLTMSGQ    MSGQ(JOBCMDLIB/&MSGQ)
             MONMSG     CPF9999
             GOTO       CMDLBL(END)
             ENDDO

END:      ENDPGM

SNDJOBCMD - CLLE

/* **************************************************************** */
             PGM        PARM(&JOB &CMD)

             DCL        VAR(&JOB)    TYPE(*CHAR) LEN(26)
             DCL        VAR(&NAME)   TYPE(*CHAR) LEN(10)
             DCL        VAR(&USER)   TYPE(*CHAR) LEN(10)
             DCL        VAR(&NUMBER) TYPE(*CHAR) LEN(6)
             DCL        VAR(&CMD)    TYPE(*CHAR) LEN(512)
             DCL        VAR(&MSGQ)   TYPE(*CHAR) LEN(10)

/* Extract job details...                                           */
             CHGVAR     VAR(&NAME)   VALUE(%SST(&JOB  1 10))
             CHGVAR     VAR(&USER)   VALUE(%SST(&JOB 11 10))
             CHGVAR     VAR(&NUMBER) VALUE(%SST(&JOB 21 6))

/* Send command to message queue...                                 */
             CHGVAR     VAR(&MSGQ) VALUE('SRVJ' *CAT &NUMBER)
             SNDPGMMSG  MSG(&CMD) TOMSGQ(JOBCMDLIB/&MSGQ)
             MONMSG     MSGID(CPF2469) EXEC(DO)
             SNDPGMMSG  MSG('An error occured while sending the +
                          command. Please re-enter the details.')
             GOTO       CMDLBL(END)
             ENDDO

END:         ENDPGM

ENDJOBCMD - CLLE

/* **************************************************************** */
             PGM        PARM(&JOB &SRVJOB)

             DCL        VAR(&JOB)    TYPE(*CHAR) LEN(26)
             DCL        VAR(&NAME)   TYPE(*CHAR) LEN(10)
             DCL        VAR(&USER)   TYPE(*CHAR) LEN(10)
             DCL        VAR(&NUMBER) TYPE(*CHAR) LEN(6)
             DCL        VAR(&SRVJOB) TYPE(*CHAR) LEN(1)
             DCL        VAR(&MSGQ)   TYPE(*CHAR) LEN(10)

/* Extract job details...                                           */
             CHGVAR     VAR(&NAME)   VALUE(%SST(&JOB  1 10))
             CHGVAR     VAR(&USER)   VALUE(%SST(&JOB 11 10))
             CHGVAR     VAR(&NUMBER) VALUE(%SST(&JOB 21 6))

/* End trace...                                                     */
             TRCJOB     SET(*END)
             MONMSG     CPF9999

/* End service job...                                                */
             IF         COND(&SRVJOB *EQ 'Y') THEN(DO)
             ENDSRVJOB
             MONMSG     CPF9999
             ENDDO


/* Delete message queue...                                           */
             CHGVAR     VAR(&MSGQ) VALUE('SRVJ' *CAT &NUMBER)
             DLTMSGQ    MSGQ(JOBCMDLIB/&MSGQ)
             MONMSG     CPF9999

             ENDPGM

EXITTRC - CLLE

             PGM        PARM(&TRCDTA)

             DCL        VAR(&TRCDTA) TYPE(*CHAR) LEN(1024)
             DCL        VAR(&CMD)    TYPE(*CHAR) LEN(1024)
             DCL        VAR(&LEN)    TYPE(*DEC)  LEN(15 5) VALUE(512)
             DCL        VAR(&MSGTXT) TYPE(*CHAR) LEN(512)
             DCL        VAR(&NAME)   TYPE(*CHAR) LEN(10)
             DCL        VAR(&USER)   TYPE(*CHAR) LEN(10)
             DCL        VAR(&NUMBER) TYPE(*CHAR) LEN(6)
             DCL        VAR(&MSGQ)   TYPE(*CHAR) LEN(10)
             DCL        VAR(&SENDER) TYPE(*CHAR) LEN(80)
             DCL        VAR(&LOG)    TYPE(*CHAR) LEN(512)

/* Set trace record as processed...                                  */
             CHGVAR     VAR(&TRCDTA) VALUE('  ')


/* Retrieve job attributes...                                        */
             RTVJOBA    JOB(&NAME) USER(&USER) NBR(&NUMBER)

/* Receive message from queue...                                     */
             CHGVAR     VAR(&MSGQ) VALUE('SRVJ' *CAT &NUMBER)
             RCVMSG     MSGQ(JOBCMDLIB/&MSGQ) MSG(&MSGTXT) +
                          SENDER(&SENDER)
             MONMSG     MSGID(CPF9999) EXEC(GOTO CMDLBL(END))

/* Set command...                                                    */
             CHGVAR     %SST(&CMD 1 1024) %SST(&MSGTXT 1 &LEN)

/* Send log messages, if message received...                         */
             IF         COND(&MSGTXT *NE ' ') THEN(DO)
             CHGVAR     VAR(&LOG) VALUE(&SENDER *CAT &NAME *CAT +
                          &USER *CAT &NUMBER)
             SNDPGMMSG  MSG(&LOG) TOMSGQ(JOBCMDLIB/CMDLOG)
             CHGVAR     VAR(&LOG) VALUE(&CMD)
             SNDPGMMSG  MSG(&LOG) TOMSGQ(JOBCMDLIB/CMDLOG)
             MONMSG     CPF0000

/* Call QCMDEXC to process command...                                */
             CALL       PGM(QCMDEXC) PARM(&CMD &LEN)
             MONMSG     CPF0000
             ENDDO

END:         ENDPGM

STRJOBCMD - CMD

             CMD        PROMPT('Start Job Command Processing')

             PARM       KWD(JOB) TYPE(Q1) MIN(1) PROMPT('Job name . +
                          . . . . . . . . . .')

             PARM       KWD(SRVJOB) TYPE(*CHAR) LEN(1) RSTD(*YES) +
                          DFT(Y) VALUES(Y N) CHOICE('(Y/N)') +
                          PROMPT('Service Job  . . . . . . . . .')
/*********************************************************************/
Q1:          QUAL       TYPE(*NAME) LEN(10) MIN(1) CHOICE('Name')
             QUAL       TYPE(*NAME) LEN(10) MIN(1) CHOICE('User') +
                          PROMPT('User . . . . . . . . . . . . .')
             QUAL       TYPE(*CHAR) LEN(6) RANGE(000000 999999) +
                          MIN(1) CHOICE('000000-999999') +
                          PROMPT('Number . . . . . . . . . . . .')
</pre
==SNDJOBCMD - CMD==
<pre>
             CMD        PROMPT('Send Job Command')

             PARM       KWD(JOB) TYPE(Q1) MIN(1) PROMPT('Job name . +
                          . . . . . . . . . .')

             PARM       KWD(CMD) TYPE(*CMDSTR) LEN(512) MIN(1) +
                          CHOICE('Command') +
                          PROMPT('Command  . . . . . . . . . . .')

/*********************************************************************/
Q1:          QUAL       TYPE(*NAME) LEN(10) MIN(1) CHOICE('Name')
             QUAL       TYPE(*NAME) LEN(10) MIN(1) CHOICE('Name') +
                          PROMPT('User . . . . . . . . . . . . .')
             QUAL       TYPE(*CHAR) LEN(6) RANGE(000000 999999) +
                          MIN(1) CHOICE('000000-999999') +
                          PROMPT('Number . . . . . . . . . . . .')

ENDJOBCMD - CMD

             CMD        PROMPT('End Job Command Processing')

             PARM       KWD(JOB) TYPE(Q1) MIN(1) PROMPT('Job name . +
                          . . . . . . . . . .')

             PARM       KWD(SRVJOB) TYPE(*CHAR) LEN(1) RSTD(*YES) +
                          DFT(Y) VALUES(Y N) CHOICE('(Y/N)') +
                          PROMPT('End service job  . . . . . . .')

/*********************************************************************/
Q1:          QUAL       TYPE(*NAME) LEN(10) MIN(1) CHOICE('Name')
             QUAL       TYPE(*NAME) LEN(10) MIN(1) CHOICE('User') +
                          PROMPT('User . . . . . . . . . . . . .')
             QUAL       TYPE(*CHAR) LEN(6) RANGE(000000 999999) +
                          MIN(1) CHOICE('000000-999999') +
                          PROMPT('Number . . . . . . . . . . . .')