× The internal search function is temporarily non-functional. The current search engine is no longer viable and we are researching alternatives.
As a stop gap measure, we are using Google's custom search engine service.
If you know of an easy to use, open source, search engine ... please contact support@midrange.com.



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:

1) STRJOBCMD - CLLE
2) SNDJOBCMD - CLLE
3) ENDJOBCMD - CLLE
4) EXITTRC - CLLE
5) STRJOBCMD - CMD
6) SNDJOBCMD - CMD
7) ENDJOBCMD - CMD

1) 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

2) 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

3) 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

4) 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

5) 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 . . . . . . . . . . . .')
****************** End of data ****************************************

6) SNDJOBCMD - CMD
            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 . . . . . . . . . . . .')

7) ENDJOBCMD - CMD
*************** Beginning of data *************************************
            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 . . . . . . . . . . . .')



As an Amazon Associate we earn from qualifying purchases.

This thread ...

Follow-Ups:

Follow On AppleNews
Return to Archive home page | Return to MIDRANGE.COM home page

This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].

Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.