See
this topic.
In concept, a program should not care, or even know, if it is called from JCL or another program. There are no 100% certain methods for a program to determine if it is called by JCL or another program. Some possibilities:
- Compare the save area address used when your program is entered with the address in TCBFSA in the current TCB. If they match, AND the current TCB address matches the address in TCBJSTA in the current TCB, your program probably - though not certainly - was called from JCL. It still could have been called from another program using the XCTL macro, but ...
- Obtain the current request block address from TCBRBP in the current TCB. Compare the 24-bit "next" RB address with the address of the current TCB. If they are equal, your program was probably called from JCL.
I wrote the following program to test these ideas
TESTJCL CSECT DEFINE PROGRAM CSECT
PUSH PRINT
PRINT NOGEN
CVT DSECT=YES DEFINE CVT DATA AREA
IKJTCB , DEFINE TVB DATA AREA
IHARB DSECT=YES DEFINE RB DATA AREA
POP PRINT
TESTJCL CSECT RETURN TO PROGRAM CSECT
USING *,12 ESTASBLISH ADDRESSABILITY
SAVE (14,12),,* SAVE REGISTERS
LR 12,15 COPY ENTRY POINT ADDRESS TO REG 12
* WE DO NOT HAVE TO OBTAIN A NEW SAVE AREA
L 2,CVTPTR LOAD CVT ADDRESS
L 2,CVTTCBP-CVTMAP(,2) LOAD ADDR OF THE TCB POINTER WORDS
L 2,4(,2) LOAD ADDR OF THE CURRENT TCB
N 2,=A(X'FFFFFF') ISOLATE THE 24-BIT TCB ADDRESS
L 3,TCBRBP-TCB(,2) LOAD ADDR OF THE CURRENT RB
N 3,=A(X'FFFFFF') ISOLATE THE 24-BIT RB ADDRESS
L 4,TCBFSA-TCB(,2) LOAD ADDR OF THE FIRST SAVE AREA
N 4,=A(X'FFFFFF') ISOLATE THE 24-BITE ADDRESS
L 5,TCBJSTCB-TCB(,2) LOAD ADDR OF THE JOB STEP TCB
N 5,=A(X'FFFFFF') ISOLATE THE 24-BIT TCB ADDRESS
CR 2,5 TEST IF CURRENT TCB = THE JOB STEP ->
TCB
BNE NOTJCL BR IF NOT
WTO 'CURRENT TCB IS THE JOBSTEP TCB',ROUTCDE=11,DESC=7
CR 4,13 TEST IF SAVE AREA = FIRST SAVE AREA
BNE FSAERR BR IF NOT
WTO 'SAVE AREA PONTER = TCBFSA',ROUTCDE=11,DESC=7
B FSAOK
FSAERR WTO 'SAVE AREA POINTER ¬= TCBFSA',ROUTCDE=11,DESC=7
FSAOK CLM 2,B'0111',RBLINK-RBBASIC+1(3) TEST RBLINK
BNE RBERROR BR IF NOT
WTO 'RBLINK POINTS TO TCB',ROUTCDE=11,DESC=7
B EXIT
RBERROR WTO 'RBLINK DOES NOT POINT TO TCB',ROUTCDE=11,DESC=7
B EXIT
NOTJCL WTO 'TCB IS NOT THE JOB STEP TCB',ROUTCDE=11,DESC=7
EXIT RETURN (14,12),T,RC=0
DC 0D'0'
LTORG ,
DC 0D'0'
END TESTJCL
I assembled the program, then used this JCL to run it.
//A EXEC PGM=LOADER,PARM='MAP'
//SYSLOUT DD SYSOUT=*
//SYSLIN DD DISP=(SHR,PASS),DSN=&SYSUID..TESTJCL.OBJ
//B EXEC PGM=IEWL,PARM=MAP
//SYSPRINT DD SYSOUT=*
//SYSLMOD DD DISP=(,PASS),UNIT=SYSDA,SPACE=(TRK,(1,1,1)),DSN=&&G(G)
//SYSLIN DD DISP=(SHR,PASS),DSN=&SYSUID..TESTJCL.OBJ
//C EXEC PGM=*.B.SYSLMOD
The LOADER program loads the object deck directly into storage and then runs it as a subtask, so it should not be considered as called from JCL. Step B prepares a load module from the object deck, and step C runs the program from JCL.