Difference between revisions of "Submit Recurring Job"
From MidrangeWiki
(Created page with "==Background== If you do not have access to the Advanced Job Scheduler on the IBM i servers, this program can help you to submit a job a recurring number of times. The sourc...") |
|||
Line 46: | Line 46: | ||
:- Allow Duplicate Jobs = *YES - Delay will be between submissions. If the delay is 60 seconds, every 60 seconds a submission will take place | :- Allow Duplicate Jobs = *YES - Delay will be between submissions. If the delay is 60 seconds, every 60 seconds a submission will take place | ||
:- Allow Duplicate Jobs = *NO - Delay will be xx number of seconds after the one job ended and the next one is submitted again | :- Allow Duplicate Jobs = *NO - Delay will be xx number of seconds after the one job ended and the next one is submitted again | ||
+ | |||
+ | ==Source Code - SBMRECJOB== | ||
+ | |||
+ | CMD PROMPT('Submit Recurring Job') | ||
+ | PARM KWD(SBMCMD) TYPE(*CMDSTR) LEN(5000) MIN(1) + | ||
+ | PROMPT('Command to submit') | ||
+ | PARM KWD(SBMJOB) TYPE(*CHAR) LEN(10) MIN(1) + | ||
+ | PROMPT('Submitted Job Name') | ||
+ | PARM KWD(SBMUSR) TYPE(*CHAR) LEN(10) + | ||
+ | DFT(*CURRENT) SPCVAL((*CURRENT)) + | ||
+ | PROMPT('Submitted Job User Profile') | ||
+ | PARM KWD(SBMJOBQ) TYPE(QUAL1) PROMPT('Submitted + | ||
+ | Job Queue to use') | ||
+ | PARM KWD(SBMDUP) TYPE(*CHAR) LEN(4) RSTD(*YES) + | ||
+ | DFT(*YES) VALUES(*YES *NO) PROMPT('Allow + | ||
+ | duplicate jobs?') | ||
+ | PARM KWD(ITERATION) TYPE(*DEC) LEN(3 0) DFT(2) + | ||
+ | RANGE(1 999) PROMPT('Number of recurring + | ||
+ | iterations') | ||
+ | PARM KWD(DELAY) TYPE(*DEC) LEN(5) DFT(60) RANGE(1 + | ||
+ | 86400) CHOICE('Delay in seconds (up to 24 + | ||
+ | hr)') PROMPT('Delay between iterations') | ||
+ | hr)') PROMPT('Delay between iterations') | ||
+ | QUAL1: QUAL TYPE(*NAME) LEN(10) DFT(*JOBD) SPCVAL((*JOBD)) | ||
+ | QUAL TYPE(*CHAR) LEN(10) DFT(*LIBL) + | ||
+ | SPCVAL((*LIBL)) PROMPT('Library Name') | ||
+ | |||
+ | * Compile with | ||
+ | CRTCMD ??CMD(SBMRECJOB) | ||
+ | ??PGM(*LIBL/SBMRECJB#C) | ||
+ | ?*SRCFILE(ZOPSLIB/QCMDSRC) | ||
+ | ?*SRCMBR(SBMRECJOB) | ||
+ | ALLOW(*BATCH *BPGM *BREXX *EXEC *BMOD) | ||
+ | ??REPLACE(*NO) | ||
+ | |||
+ | ==Source Code - SBMRECJB#C== | ||
+ | BEGIN: PGM PARM(&SBMCMD &SBMJOB &SBMUSR &SBMJOBQ + | ||
+ | &SBMDUP &SBMITER &DELAY) | ||
+ | |||
+ | /*-------------------------------------------------------------------*/ | ||
+ | /* PASSED Variables */ | ||
+ | /*------------------- */ | ||
+ | /* */ | ||
+ | DCL VAR(&SBMCMD) TYPE(*CHAR) LEN(5000) | ||
+ | DCL VAR(&SBMJOB) TYPE(*CHAR) LEN(10) | ||
+ | DCL VAR(&SBMUSR) TYPE(*CHAR) LEN(10) | ||
+ | DCL VAR(&SBMJOBQ) TYPE(*CHAR) LEN(20) | ||
+ | DCL VAR(&SBMDUP) TYPE(*CHAR) LEN(4) | ||
+ | DCL VAR(&SBMITER) TYPE(*DEC) LEN(3 0) | ||
+ | DCL VAR(&DELAY) TYPE(*DEC) LEN(5 0) | ||
+ | |||
+ | /* */ | ||
+ | /* PROGRAM Variables */ | ||
+ | /*-------------------- */ | ||
+ | /* */ | ||
+ | DCL VAR(&COUNTER) TYPE(*INT) | ||
+ | DCL VAR(&JOBCOUNT) TYPE(*DEC) LEN(8 0) | ||
+ | DCL VAR(&SBMSTRING) TYPE(*CHAR) LEN(6000) | ||
+ | DCL VAR(&ITERATION) TYPE(*INT) | ||
+ | DCL VAR(&JOBQ) TYPE(*CHAR) LEN(10) | ||
+ | DCL VAR(&JOBQLIB) TYPE(*CHAR) LEN(10) | ||
+ | DCL VAR(&JOBQVAL) TYPE(*CHAR) LEN(22) | ||
+ | /* */ | ||
+ | /* Settings for input parameters */ | ||
+ | /* */ | ||
+ | /* */ | ||
+ | /* Standard Error Handling variables */ | ||
+ | /*------------------------------------ */ | ||
+ | /* */ | ||
+ | |||
+ | DCL VAR(&MSGID) TYPE(*CHAR) LEN(7) /* Error + | ||
+ | Message Identifier */ | ||
+ | DCL VAR(&MSGDTA) TYPE(*CHAR) LEN(256) /* Error + | ||
+ | Message Data */ | ||
+ | DCL VAR(&MSGFILNAM) TYPE(*CHAR) LEN(10) /* Error + | ||
+ | Message File Name */ | ||
+ | DCL VAR(&MSGFILLIB) TYPE(*CHAR) LEN(10) /* Error + | ||
+ | Message File Name */ | ||
+ | /* ----------------------------------------------------------------- */ | ||
+ | /* Program Code Starts Here */ | ||
+ | /* ------------------------ */ | ||
+ | /* */ | ||
+ | |||
+ | /* MONITOR FOR UNEXPECTED ERROR MESSAGES */ | ||
+ | |||
+ | MONMSG MSGID(CPF0000) EXEC(GOTO CMDLBL(ERROR)) | ||
+ | /* */ | ||
+ | /* */ | ||
+ | /* Reset counters first */ | ||
+ | /*------------------------------------------------------------ */ | ||
+ | /* */ | ||
+ | CHGVAR VAR(&COUNTER) VALUE(0) | ||
+ | CHGVAR VAR(&JOBCOUNT) VALUE(0) | ||
+ | CHGVAR VAR(&ITERATION) VALUE(&SBMITER) | ||
+ | /* */ | ||
+ | /* */ | ||
+ | /* Check if the user exist, if not, retrieve current user profile */ | ||
+ | /*------------------------------------------------------------ */ | ||
+ | /* */ | ||
+ | IF COND(&SBMUSR *EQ '*CURRENT') THEN(RTVJOBA + | ||
+ | USER(&SBMUSR)) | ||
+ | CHKOBJ OBJ(&SBMUSR) OBJTYPE(*USRPRF) | ||
+ | MONMSG MSGID(CPF0000) EXEC(DO) | ||
+ | RTVJOBA USER(&SBMUSR) | ||
+ | ENDDO | ||
+ | /* */ | ||
+ | /* */ | ||
+ | /* Check if the job queue exist. If not, set JOBQ to *JOBD */ | ||
+ | /*------------------------------------------------------------ */ | ||
+ | /* */ | ||
+ | CHGVAR VAR(&JOBQ) VALUE(%SST(&SBMJOBQ 1 10)) | ||
+ | CHGVAR VAR(&JOBQLIB) VALUE(%SST(&SBMJOBQ 11 10)) | ||
+ | SELECT | ||
+ | WHEN COND(&JOBQ *EQ '*JOBD') THEN(DO) | ||
+ | CHGVAR VAR(&JOBQVAL) VALUE('*JOBD') | ||
+ | ENDDO | ||
+ | /**/ | ||
+ | WHEN COND(&JOBQ *NE '*JOBD') THEN(DO) | ||
+ | CHGVAR VAR(&JOBQVAL) VALUE(&JOBQLIB *TCAT '/' *TCAT + | ||
+ | &JOBQ) | ||
+ | CHKOBJ OBJ(&JOBQLIB/&JOBQ) OBJTYPE(*JOBQ) | ||
+ | MONMSG MSGID(CPF0000) EXEC(DO) | ||
+ | CHGVAR VAR(&JOBQVAL) VALUE('*JOBD') | ||
+ | ENDDO | ||
+ | ENDDO | ||
+ | ENDSELECT | ||
+ | /* */ | ||
+ | /* */ | ||
+ | /* Setup the command now, write entries to the joblog */ | ||
+ | /*------------------------------------------------------------ */ | ||
+ | /* */ | ||
+ | CHGVAR VAR(&SBMSTRING) VALUE('SBMJOB CMD(' *TCAT + | ||
+ | &SBMCMD *TCAT ') JOB(' *TCAT &SBMJOB + | ||
+ | *TCAT ') USER(' *TCAT &SBMUSR *TCAT ') + | ||
+ | CURLIB(*USRPRF) INLLIBL(*JOBD) JOBQ(' + | ||
+ | *TCAT &JOBQVAL *TCAT ')') | ||
+ | SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA('Cmd to + | ||
+ | submit -' *BCAT %TRIM(&SBMCMD)) | ||
+ | SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA('Delay + | ||
+ | time in seconds - ' *TCAT %CHAR(&DELAY)) | ||
+ | SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA('Submit + | ||
+ | user - ' *BCAT &SBMUSR) | ||
+ | SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA('Submit + | ||
+ | job name - ' *BCAT &SBMJOB) | ||
+ | |||
+ | /* */ | ||
+ | /* */ | ||
+ | /* Go into the for loop here. */ | ||
+ | /*------------------------------------------------------------ */ | ||
+ | /* */ | ||
+ | DOFOR VAR(&COUNTER) FROM(1) TO(&ITERATION) | ||
+ | SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) + | ||
+ | MSGDTA('Iteration - ' *BCAT + | ||
+ | %CHAR(&COUNTER) *BCAT 'of' *BCAT + | ||
+ | %CHAR(&ITERATION)) | ||
+ | /* */ | ||
+ | /* Check if job is already running. */ | ||
+ | /*------------------------------------------------------------ */ | ||
+ | /* */ | ||
+ | RTVJOBCNT JOB(&SBMJOB) USER(&SBMUSR) + | ||
+ | COUNT(&JOBCOUNT) | ||
+ | MONMSG MSGID(CPF0000) | ||
+ | SELECT | ||
+ | /* If job is not active, or Submit Duplicates is yes, submit it */ | ||
+ | WHEN COND(&JOBCOUNT = 0 *OR &SBMDUP = '*YES') + | ||
+ | THEN(DO) | ||
+ | SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) + | ||
+ | MSGDTA('-- Submitting job ' *BCAT &SBMJOB + | ||
+ | *BCAT ' for user ' *BCAT &SBMUSR) | ||
+ | CALL PGM(QCMDEXC) PARM(&SBMSTRING 6000) | ||
+ | ENDDO | ||
+ | OTHERWISE CMD(DO) | ||
+ | SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA('-- Job + | ||
+ | ' *BCAT &SBMJOB *BCAT ' NOT submitted for + | ||
+ | user ' *BCAT &SBMUSR) | ||
+ | ENDDO | ||
+ | ENDSELECT | ||
+ | /* */ | ||
+ | /* */ | ||
+ | /* Delay the job now for the specified number of minutes */ | ||
+ | /*------------------------------------------------------------ */ | ||
+ | /* */ | ||
+ | DLYJOB DLY(&DELAY) | ||
+ | ENDDO | ||
+ | |||
+ | /* */ | ||
+ | /* GO TO NORMAL PROGRAM END */ | ||
+ | /* ------------------------------------------- */ | ||
+ | /* */ | ||
+ | |||
+ | GOTO CMDLBL(EXIT) | ||
+ | /* */ | ||
+ | /* ----------------------------------------------------------------- */ | ||
+ | /* UNEXPECTED ERROR ROUTINE */ | ||
+ | /* ------------------------ */ | ||
+ | /* */ | ||
+ | ERROR: | ||
+ | RCVMSG MSGTYPE(*EXCP) MSGDTA(&MSGDTA) MSGID(&MSGID) + | ||
+ | MSGF(&MSGFILNAM) MSGFLIB(&MSGFILLIB) | ||
+ | SNDPGMMSG MSGID(&MSGID) MSGF(&MSGFILLIB/&MSGFILNAM) + | ||
+ | MSGDTA(&MSGDTA) MSGTYPE(*ESCAPE) | ||
+ | /* */ | ||
+ | /* ----------------------------------------------------------------- */ | ||
+ | /* ALL ROADS LEAD TO EXIT */ | ||
+ | /* ---------------------- */ | ||
+ | /* */ | ||
+ | EXIT: | ||
+ | RETURN | ||
+ | ENDPGM |
Revision as of 09:00, 19 November 2020
Background
If you do not have access to the Advanced Job Scheduler on the IBM i servers, this program can help you to submit a job a recurring number of times. The source consists of the following
RTVJOBCNT - CMD - Retrieve Job Count RTVJOBCN#C - CLLE - Retrieve Job Count CL Program SBMRECJOB - CMD - Submit Recurring Job SBMRECJ#C - CLLE - Submit recurring Job CL PRogram
Using the program
If you issue the command SBMRECJOB, you have to provide the following fields:
Submit Recurring Job (SBMRECJOB) Type choices, press Enter. Command to submit . . . . . . . _____________________________________________ _______________________________________________________________________________ _______________________________________________________________________________ _________________ ...
Submitted Job Name . . . . . . . ____________ Character value Submitted Job User Profile . . . *CURRENT Character value, *CURRENT Submitted Job Queue to use . . . *JOBD Name, *JOBD Library Name . . . . . . . . . *LIBL Character value, *LIBL Allow duplicate jobs? . . . . . *YES *YES, *NO Number of recurring iterations 2 1-999 Delay between iterations . . . . 60 Delay in seconds (up to 24 hr) Bottom F3=Exit F4=Prompt F5=Refresh F12=Cancel F13=How to use this display F24=More keys
- Command to submit: Specify the command here. You can also prompt the command to give the correct values and parameters
- Submitted Job name: The command specified will be submitted using the specified job name.
- Submitted Job User Profile: Under which profile should the submitted job run. Can also specify *CURRENT for the user running the current job.
- Submitted Job queue to use: Specify a jobq to use for the submission. Can also specify *JOBD to use the JOBD from the user profile
- Allow Duplicate Jobs: If there should always be only one job with this name running, use *NO here. If you do not care whether the previous job ended or not, you can ignore duplicate jobs and specify *YES here
- Number of recurring iterations: Specify how many times this job will be submitted
- Delay between iterations: Specify here how may seconds delay should take place between submissions. This behaviour is also governed by the "Allow Duplicate Jobs" parameter:
- - Allow Duplicate Jobs = *YES - Delay will be between submissions. If the delay is 60 seconds, every 60 seconds a submission will take place
- - Allow Duplicate Jobs = *NO - Delay will be xx number of seconds after the one job ended and the next one is submitted again
Source Code - SBMRECJOB
CMD PROMPT('Submit Recurring Job') PARM KWD(SBMCMD) TYPE(*CMDSTR) LEN(5000) MIN(1) + PROMPT('Command to submit') PARM KWD(SBMJOB) TYPE(*CHAR) LEN(10) MIN(1) + PROMPT('Submitted Job Name') PARM KWD(SBMUSR) TYPE(*CHAR) LEN(10) + DFT(*CURRENT) SPCVAL((*CURRENT)) + PROMPT('Submitted Job User Profile') PARM KWD(SBMJOBQ) TYPE(QUAL1) PROMPT('Submitted + Job Queue to use') PARM KWD(SBMDUP) TYPE(*CHAR) LEN(4) RSTD(*YES) + DFT(*YES) VALUES(*YES *NO) PROMPT('Allow + duplicate jobs?') PARM KWD(ITERATION) TYPE(*DEC) LEN(3 0) DFT(2) + RANGE(1 999) PROMPT('Number of recurring + iterations') PARM KWD(DELAY) TYPE(*DEC) LEN(5) DFT(60) RANGE(1 + 86400) CHOICE('Delay in seconds (up to 24 + hr)') PROMPT('Delay between iterations') hr)') PROMPT('Delay between iterations') QUAL1: QUAL TYPE(*NAME) LEN(10) DFT(*JOBD) SPCVAL((*JOBD)) QUAL TYPE(*CHAR) LEN(10) DFT(*LIBL) + SPCVAL((*LIBL)) PROMPT('Library Name')
- Compile with
CRTCMD ??CMD(SBMRECJOB) ??PGM(*LIBL/SBMRECJB#C) ?*SRCFILE(ZOPSLIB/QCMDSRC) ?*SRCMBR(SBMRECJOB) ALLOW(*BATCH *BPGM *BREXX *EXEC *BMOD) ??REPLACE(*NO)
Source Code - SBMRECJB#C
BEGIN: PGM PARM(&SBMCMD &SBMJOB &SBMUSR &SBMJOBQ + &SBMDUP &SBMITER &DELAY) /*-------------------------------------------------------------------*/ /* PASSED Variables */ /*------------------- */ /* */ DCL VAR(&SBMCMD) TYPE(*CHAR) LEN(5000) DCL VAR(&SBMJOB) TYPE(*CHAR) LEN(10) DCL VAR(&SBMUSR) TYPE(*CHAR) LEN(10) DCL VAR(&SBMJOBQ) TYPE(*CHAR) LEN(20) DCL VAR(&SBMDUP) TYPE(*CHAR) LEN(4) DCL VAR(&SBMITER) TYPE(*DEC) LEN(3 0) DCL VAR(&DELAY) TYPE(*DEC) LEN(5 0) /* */ /* PROGRAM Variables */ /*-------------------- */ /* */ DCL VAR(&COUNTER) TYPE(*INT) DCL VAR(&JOBCOUNT) TYPE(*DEC) LEN(8 0) DCL VAR(&SBMSTRING) TYPE(*CHAR) LEN(6000) DCL VAR(&ITERATION) TYPE(*INT) DCL VAR(&JOBQ) TYPE(*CHAR) LEN(10) DCL VAR(&JOBQLIB) TYPE(*CHAR) LEN(10) DCL VAR(&JOBQVAL) TYPE(*CHAR) LEN(22) /* */ /* Settings for input parameters */ /* */ /* */ /* Standard Error Handling variables */ /*------------------------------------ */ /* */ DCL VAR(&MSGID) TYPE(*CHAR) LEN(7) /* Error + Message Identifier */ DCL VAR(&MSGDTA) TYPE(*CHAR) LEN(256) /* Error + Message Data */ DCL VAR(&MSGFILNAM) TYPE(*CHAR) LEN(10) /* Error + Message File Name */ DCL VAR(&MSGFILLIB) TYPE(*CHAR) LEN(10) /* Error + Message File Name */ /* ----------------------------------------------------------------- */ /* Program Code Starts Here */ /* ------------------------ */ /* */ /* MONITOR FOR UNEXPECTED ERROR MESSAGES */ MONMSG MSGID(CPF0000) EXEC(GOTO CMDLBL(ERROR)) /* */ /* */ /* Reset counters first */ /*------------------------------------------------------------ */ /* */ CHGVAR VAR(&COUNTER) VALUE(0) CHGVAR VAR(&JOBCOUNT) VALUE(0) CHGVAR VAR(&ITERATION) VALUE(&SBMITER) /* */ /* */ /* Check if the user exist, if not, retrieve current user profile */ /*------------------------------------------------------------ */ /* */ IF COND(&SBMUSR *EQ '*CURRENT') THEN(RTVJOBA + USER(&SBMUSR)) CHKOBJ OBJ(&SBMUSR) OBJTYPE(*USRPRF) MONMSG MSGID(CPF0000) EXEC(DO) RTVJOBA USER(&SBMUSR) ENDDO /* */ /* */ /* Check if the job queue exist. If not, set JOBQ to *JOBD */ /*------------------------------------------------------------ */ /* */ CHGVAR VAR(&JOBQ) VALUE(%SST(&SBMJOBQ 1 10)) CHGVAR VAR(&JOBQLIB) VALUE(%SST(&SBMJOBQ 11 10)) SELECT WHEN COND(&JOBQ *EQ '*JOBD') THEN(DO) CHGVAR VAR(&JOBQVAL) VALUE('*JOBD') ENDDO /**/ WHEN COND(&JOBQ *NE '*JOBD') THEN(DO) CHGVAR VAR(&JOBQVAL) VALUE(&JOBQLIB *TCAT '/' *TCAT + &JOBQ) CHKOBJ OBJ(&JOBQLIB/&JOBQ) OBJTYPE(*JOBQ) MONMSG MSGID(CPF0000) EXEC(DO) CHGVAR VAR(&JOBQVAL) VALUE('*JOBD') ENDDO ENDDO ENDSELECT /* */ /* */ /* Setup the command now, write entries to the joblog */ /*------------------------------------------------------------ */ /* */ CHGVAR VAR(&SBMSTRING) VALUE('SBMJOB CMD(' *TCAT + &SBMCMD *TCAT ') JOB(' *TCAT &SBMJOB + *TCAT ') USER(' *TCAT &SBMUSR *TCAT ') + CURLIB(*USRPRF) INLLIBL(*JOBD) JOBQ(' + *TCAT &JOBQVAL *TCAT ')') SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA('Cmd to + submit -' *BCAT %TRIM(&SBMCMD)) SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA('Delay + time in seconds - ' *TCAT %CHAR(&DELAY)) SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA('Submit + user - ' *BCAT &SBMUSR) SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA('Submit + job name - ' *BCAT &SBMJOB) /* */ /* */ /* Go into the for loop here. */ /*------------------------------------------------------------ */ /* */ DOFOR VAR(&COUNTER) FROM(1) TO(&ITERATION) SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) + MSGDTA('Iteration - ' *BCAT + %CHAR(&COUNTER) *BCAT 'of' *BCAT + %CHAR(&ITERATION)) /* */ /* Check if job is already running. */ /*------------------------------------------------------------ */ /* */ RTVJOBCNT JOB(&SBMJOB) USER(&SBMUSR) + COUNT(&JOBCOUNT) MONMSG MSGID(CPF0000) SELECT /* If job is not active, or Submit Duplicates is yes, submit it */ WHEN COND(&JOBCOUNT = 0 *OR &SBMDUP = '*YES') + THEN(DO) SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) + MSGDTA('-- Submitting job ' *BCAT &SBMJOB + *BCAT ' for user ' *BCAT &SBMUSR) CALL PGM(QCMDEXC) PARM(&SBMSTRING 6000) ENDDO OTHERWISE CMD(DO) SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA('-- Job + ' *BCAT &SBMJOB *BCAT ' NOT submitted for + user ' *BCAT &SBMUSR) ENDDO ENDSELECT /* */ /* */ /* Delay the job now for the specified number of minutes */ /*------------------------------------------------------------ */ /* */ DLYJOB DLY(&DELAY) ENDDO /* */ /* GO TO NORMAL PROGRAM END */ /* ------------------------------------------- */ /* */ GOTO CMDLBL(EXIT) /* */ /* ----------------------------------------------------------------- */ /* UNEXPECTED ERROR ROUTINE */ /* ------------------------ */ /* */ ERROR: RCVMSG MSGTYPE(*EXCP) MSGDTA(&MSGDTA) MSGID(&MSGID) + MSGF(&MSGFILNAM) MSGFLIB(&MSGFILLIB) SNDPGMMSG MSGID(&MSGID) MSGF(&MSGFILLIB/&MSGFILNAM) + MSGDTA(&MSGDTA) MSGTYPE(*ESCAPE) /* */ /* ----------------------------------------------------------------- */ /* ALL ROADS LEAD TO EXIT */ /* ---------------------- */ /* */ EXIT: RETURN ENDPGM