Submitting jobs from within IBM i Control Language programs is EASY
But sometimes we want to know the job name, or job queue, that the job was submitted with.
This is easy to do in CL, and since my colleague John ShhhItsAsecret “who’s surname can’t be mentioned or else it will give him an internet presence alerting the FBI, NSA and YAKUZA who are all hunting him for various crimes committing during the 80’s” asked me how to do it
RCVMSG Example for SBMJOB
So, here is a example written in my favorite template layout, using IBM i Control Language:
/* Capture SUBMIT JOB information and send to joblog */
/* ----------------------------------------------------------- */
/* Program.......... SBMJOBMSG */
/* Author........... nick@nicklitten.com */
/* Calling Program.. *NONE */
/* Calling Command.. *NONE */
/* User Profile..... *USER */
/* Object Owner..... QPGMR */
/* Compiler Options. This is a CLLE *MODULE bound into *PGM */
/* Module: CRTBNDCL PGM(NICKLITTEN/SBMJOBMSG) */
/* SRCSTMF('/home/nicklitten/source-cl/sbmjobmsg.clle') */
/* OPTIMIZE(*NONE) */
/* DBGVIEW(*SOURCE) */
/* ILEPGM: CRTPGM PGM('library'/TEMPLATE) MODULE(TEMPLATE*) */
/* ----------------------------------------------------------- */
/* Modification History: */
/* Author Date Description */
/* NJL01 10/17/2017 Created */
/* NJL02 10/01/2024 Minor Code Tidyup and comment refresh */
/* ----------------------------------------------------------- */
PGM
DCLPRCOPT LOG(*NO) DFTACTGRP(*NO) ACTGRP(*CALLER)
DCL VAR(&PGMNAME) TYPE(*CHAR) LEN(10)
DCL VAR(&CRASHED) TYPE(*LGL) VALUE('0')
DCL VAR(&MSGID) TYPE(*CHAR) LEN(7)
DCL VAR(&MSGDTA) TYPE(*CHAR) LEN(256)
DCL VAR(&MSGFIL) TYPE(*CHAR) LEN(10)
DCL VAR(&MSGFLIB) TYPE(*CHAR) LEN(10)
DCL VAR(&MSGKEY) TYPE(*CHAR) LEN(4)
DCL VAR(&RTNTYPE) TYPE(*CHAR) LEN(2)
DCL VAR(&SENDER) TYPE(*CHAR) LEN(80)
DCL VAR(&SBMJOB) TYPE(*CHAR) LEN(10)
DCL VAR(&SBMJOBUSR) TYPE(*CHAR) LEN(10)
DCL VAR(&SBMJOBNBR) TYPE(*CHAR) LEN(6)
DCL VAR(&SBMJOBQ) TYPE(*CHAR) LEN(10)
DCL VAR(&SBMJOBQLB) TYPE(*CHAR) LEN(10)
COPYRIGHT TEXT('SBMJOBMSG Ver:002 Show submitted job info')
/* Global monitor for any error messages */
MONMSG MSGID(CPF0000) EXEC(GOTO CMDLBL(CRASH))
/* a little initialization subroutine to do pre-run gubbins */
CALLSUBR SUBR(INZSR)
/* begin regular program logic here */
CALLSUBR SUBR(MAINLINE)
SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) +
MSGDTA('Program' *BCAT &PGMNAME *BCAT 'completed normally') MSGTYPE(*COMP)
END: RETURN
CRASH: CALLSUBR SUBR(CRASH)
/* ------------------------------------------------------------ */
/* SUBROUTINE SECTION */
/* Initialization Routine - lets use it to get the pgm name */
/* ------------------------------------------------------------ */
SUBR SUBR(INZSR)
SNDPGMMSG MSG('What is this program name?') TOPGMQ(*SAME) +
MSGTYPE(*INFO) KEYVAR(&MSGKEY)
RCVMSG PGMQ(*SAME) WAIT(0) RMV(*YES) SENDER(&SENDER) SENDERFMT(*SHORT)
CHGVAR VAR(&PGMNAME) VALUE(%SST(&SENDER 56 10))
ENDSUBR
/* ------------------------------------------------------------ */
/* MAINLINE - You could use this for your mainline */
/* ------------------------------------------------------------ */
SUBR SUBR(MAINLINE)
/* We need to send this message just find the MSGKEY Value */
SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) +
MSGDTA('Submitting Job...') TOPGMQ(*SAME) +
KEYVAR(&MSGKEY)
/* submit a silly job that will do nothing */
SBMJOB CMD(DLYJOB DLY(1)) JOB(SOMETHING) LOG(4 0 *SECLVL)
MONMSG MSGID(CPF0000) EXEC(DO)
SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA('ERROR Unable to submit job') +
TOPGMQ(*PRV) MSGTYPE(*COMP)
RTNSUBR
ENDDO
/* retrieve 'sbmjob' message from msg queue */
RCVMSG PGMQ(*SAME) MSGQ(*PGMQ) MSGTYPE(*NEXT) +
MSGKEY(&MSGKEY) RMV(*NO) MSGDTA(&MSGDTA)
CHGVAR VAR(&SBMJOB) VALUE(%SST(&MSGDTA 1 10))
CHGVAR VAR(&SBMJOBUSR) VALUE(%SST(&MSGDTA 11 10))
CHGVAR VAR(&SBMJOBNBR) VALUE(%SST(&MSGDTA 21 6))
CHGVAR VAR(&SBMJOBQ) VALUE(%SST(&MSGDTA 27 10))
CHGVAR VAR(&SBMJOBQLB) VALUE(%SST(&MSGDTA 37 10))
SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) +
MSGDTA('Submitted job was' *BCAT &SBMJOBNBR *TCAT '/' +
*TCAT &SBMJOBUSR *TCAT '/' *TCAT &SBMJOB *TCAT +
', and it submitted using jobq(' *TCAT &SBMJOBQLB *TCAT +
'/' *TCAT &SBMJOBQ *TCAT ')') +
TOPGMQ(*PRV) MSGTYPE(*COMP)
RTNSUBR
ENDSUBR
/* ------------------------------------------------------------ */
/* CRASH : Routine to handle unexpected errors */
/* ------------------------------------------------------------ */
SUBR SUBR(CRASH)
IF COND(&CRASHED) THEN(RETURN)
CHGVAR VAR(&CRASHED) VALUE('1')
/* This subroutine will read back through this programs joblog */
/* and pump out messages to your joblog based on the status */
/* codes returned from RCVMSG. RTNTYPE values include: */
/* - 01 Completion */
/* - 02 Diagnostic */
/* - 04 Information */
/* - 05 Inquiry */
/* - 06 Copy */
/* - 08 Request */
/* - 10 Request with prompting */
/* - 14 Notify (exception already handled at time of RCVMSG) */
/* - 15 Escape (exception already handled at time of RCVMSG) */
/* - 16 Notify (exception not handled at time of RCVMSG) */
/* - 17 Escape (exception not handled at time of RCVMSG) */
/* - 21 Reply, not checked for validity */
/* - 22 Reply, already checked for validity */
/* - 23 Reply, message default used */
/* - 24 Reply, system default used */
/* - 25 Reply, from System Reply List */
/* - 26 Reply, from exit program */
RCVMSG MSGTYPE(*LAST) MSGDTA(&MSGDTA) MSGID(&MSGID) +
RTNTYPE(&RTNTYPE) MSGF(&MSGFIL) SNDMSGFLIB(&MSGFLIB)
IF COND(&RTNTYPE *EQ '15' *OR &RTNTYPE *EQ '17') THEN(DO)
SNDPGMMSG MSGID(&MSGID) MSGF(&MSGFIL) MSGDTA(&MSGDTA) MSGTYPE(*DIAG)
ENDDO
SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) +
MSGDTA('* Program' *BCAT &PGMNAME *BCAT 'ended abnormally') +
MSGTYPE(*ESCAPE)
ENDSUBR
ENDPGM: ENDPGM
So, when we run this little program, it submits a job (that does nothing other than delay for 1 second before gracefully ending) and then reads the last program message so it can snag the job details.

Simples!!
I hope that is what you are looking for.
If you want to download the source code, or even suffer through a video of my walking through the code, explaining what it is up to and generally waffling about Control Language you can watch that here
What is IBM CL?
IBM i Control Language (CL) is a powerful scripting language for the IBM AS/400, IBM iSeries and IBM i Systems. It's got roots in the older IBM Job Control Language, and it works as a simple way to script commands, instructions and other functions into an easy-to-understand programs.
The code is missing “*” for *PRV, *COMP, *SAME, etc…
Thanks Ken – using WordPress for the website CMS, it will cut special characters when I paste code samples in. Nice catch – I’ve updated 😉