IBM Mainframe Forum Index
 
Log In
 
IBM Mainframe Forum Index Mainframe: Search IBM Mainframe Forum: FAQ Register
 

Passing Parameters to Programs Invoked with IKJEFTSR


IBM Mainframe Forums -> PL/I & Assembler
Post new topic   Reply to topic
View previous topic :: View next topic  
Author Message
Alex Gassem

New User


Joined: 28 Mar 2023
Posts: 9
Location: United Kingdom

PostPosted: Thu Jul 27, 2023 9:22 pm
Reply with quote

Hi,

I am looking into how to use the TSO/E Service Facility Routine to invoke other programs in an assembly program. I've been successful in invoking another program without passing any parameters, however, I can't seem to figure out how to pass parameters.

I am aware that IKJEFTSR parameter 7 can be used to specify parameters that would usually be passed in the PARM field. However, I want to try to pass an argument that the program consumes.

This is what I've come up with for IDCAMS (I know you're not meant to put IDCAMS in AUTHTSF, but this is just for me to test temporarily).

Code:

IDCAMASM CSECT                      # Mark as executable.
         STM   14,12,12(13)         # Store stack contents.
         BALR    12,0               # Establish addressability by
         USING   *,12               # storing base addr in base reg.
         ST    13,SAVE+4            # save the CALLER save area
         LA    13,SAVE              # load pointer to THIS save area
*
* invoke IKJEFTSR which has been passed IDCAMS as an arg (PGM/PGMLEN)
*
         L     15,=V(IKJEFTSR)      # GET ADDRESS OF IKJEFTSR
    CALL (15),(IKJPARM1,PGM,PGMLEN,RETCODE,REASONC,ABENDCD,PARMLST),VL
         LTR   15,15                 # check TSR return code
         BNZ   ERRORRTN              # bad TSR return
         CLC   RETCODE,ZERO          # check for IDCAMS error
         BH    ERRORPGM              # bad IDCAMD program error
         B     CLEANUP               # run cleanup code and return
*
* TSR SERVICE FACILITY ERROR BRANCH
*
ERRORRTN DS    0H
         B     CLEANUP
*
* IDCAMS ERROR BRANCH
*
ERRORPGM DS    0H
         B     CLEANUP
*
* COMMON CLEANUP CODE
*
CLEANUP  DS    0H
         L     13,4(,13)           # restore CALLER save area
         LM    14,12,12(13)        # restore register contents
         SLR   15,15
         BR    14                  # branch back to caller
*
* CUSTOM SUBROUTINE
*
IOROUTE  STM 14,12,12(13)
         BALR  12,0
         USING *,12
*
* RETURN
*
         L     13,SAVETWO+4
         LM    14,12,12(13)
         BR    14
*
* declarations
*
ZERO     DC    F'0'                  # zero constant
SAVE     DS    18F                   # define save area storage
SAVETWO  DS    18F                   # save area for subroutine
PGM      DC    C'IDCAMS'             # name of program
PGMLEN   DC    F'6'                  # length of program name
RETCODE  DS    F                     # data area for return code
REASONC  DS    F                     # data area for abend reason code
ABENDCD  DS    F                     # ABEND code
IKJPARM1 DS    0F                    # align
         DC    XL2'0000'             # invoke from unauth program
         DC    X'01'                 # take dump if abend
         DC    X'02'                 # invoke program
IDCMARG  DS    1F                    # one full word
         DC    H'2'                  # OPTIONS param len
         DC    X'0000'               # OPTIONS param content
OPTIONS  DC    H'0'                  # no basic parms for IDCAMS
DNAMES   DC    H'0'                  # no alt ddnames
PGNO     DC    H'0'                  # length of field
DDNAME   DC    C'DDINPUTDS '         # left-justified DD for IO
IOLIST   DC    F'1'                  # one I/O list entry
         DC    A(DDNAME)             # address of DDNAME
         DC    A(IOROUTE)            # address of subroutine
         DC    A(DDNAME)             # required arg for subroutine
PARMLST  CALL  ,(IDCMARG,DNAMES,PGNO,IOLIST),VL,MF=L  # set up PARMLIST
IDCAMASM AMODE 31
         END


Here is how I am compiling and running the program:

Code:

//IDCAMIKJ JOB NOTIFY=&SYSUID,MSGLEVEL=(1,1),TIME=(0,20)
//*
//*       COMPILE WITH REQUIRED LIBS
//*
//COMPILE    EXEC PROC=ASMACL
//C.SYSPRINT   DD SYSOUT=*
//C.SYSIN      DD DSN=ALEXGAS.SOURCE.ASM(IDCAMASM),DISP=SHR
//C.SYSLIB     DD DSN=SYS1.SISTMAC1,DISP=SHR
//             DD DSN=SYS1.MODGEN,DISP=SHR
//             DD DSN=SYS1.MACLIB,DISP=SHR
//L.SYSPRINT   DD SYSOUT=*
//L.SYSLMOD    DD DSN=ALEXGAS.MYLIBS.NOAPFLIB(IDCAMASM),DISP=SHR
//L.IKJDD      DD DSN=SYS1.LPALIB,DISP=SHR
//L.SYSIN      DD *
  MODE AMODE(31)
  INCLUDE IKJDD(IKJEFTSR)
/*
//*
//*       RUN THE PROGRAM
//*
//RUNSTEP    EXEC PGM=IDCAMASM
//STEPLIB    DD DSN=ALEXGAS.MYLIBS.NOAPFLIB,DISP=SHR
//SYSPRINT   DD SYSOUT=*
//AMSDUMP    DD SYSOUT=*
//INPUTDS    DD DSN=ALEXGAS.TEMP.PDS(TEST),DISP=SHR
//SYSIN      DD *
 PRINT INFILE(INPUTDS)
/*


But I don't get any output from the IDCAMS PRINT statement like I do when I run this with the same parameters with a CALL directly. There are no abends or anything, and I can't find documentation on passing arguments in the way I want to -- any tips?
Back to top
View user's profile Send private message
sergeyken

Senior Member


Joined: 29 Apr 2008
Posts: 2023
Location: USA

PostPosted: Thu Jul 27, 2023 10:18 pm
Reply with quote

At least, it should be
Code:
DDNAME   DC    CL8'INPUTDS'
not
Code:
DDNAME   DC    C'DDINPUTDS '


When nothing is clear enough, the DETAILED LOGS OF EVERY STEP are required. Otherwise it would be only blah-blah-blah...
Back to top
View user's profile Send private message
Pedro

Global Moderator


Joined: 01 Sep 2006
Posts: 2547
Location: Silicon Valley

PostPosted: Fri Jul 28, 2023 3:07 am
Reply with quote

Code:
IOLIST   DC    F'1'                  # one I/O list entry
         DC    A(DDNAME)             # address of DDNAME
         DC    A(IOROUTE)            # address of subroutine
         DC    A(DDNAME)             # required arg for subroutine


I have never called IDCAMS in this way...

I think the use of DDINPUTDS is correct, but you use the same parameter, DDNAME, both for the first and third parameters in the group. The third parameter is USER DATA and it seems to have a very specific format. (but your IOROUTE routine does not seem to do anything, so perhaps it does not matter now. It might matter in the future.)

See figure 1 here: www.ibm.com/docs/en/zos/2.3.0?topic=instructions-invocation-from-pli-program#da6i2317__arglist
Though the section title is about PLI, I think the control block structure still applies.
Back to top
View user's profile Send private message
Pedro

Global Moderator


Joined: 01 Sep 2006
Posts: 2547
Location: Silicon Valley

PostPosted: Fri Jul 28, 2023 4:09 am
Reply with quote

re: DDINPUTDS

You use DS if what follows is a data set name. I saw it earlier, but I cannot find the reference anymore.
Back to top
View user's profile Send private message
Alex Gassem

New User


Joined: 28 Mar 2023
Posts: 9
Location: United Kingdom

PostPosted: Fri Jul 28, 2023 3:48 pm
Reply with quote

Thanks for the responses!

So the above way of calling IDCAMS worked well enough for me if I called it directly; it outputs the dataset to SYSPRINT. See the below output for the non-IKJEFTSR code.

Assembler that is basically the same as the above but calls IDCAMS directly rather than through IKJEFTSR:

Code:

IDCAMTST CSECT                      # Mark as executable.
         STM   14,12,12(13)         # Store stack contents.
         BALR    12,0               # Establish addressability by
         USING   *,12               # storing base addr in base reg.
         ST    13,SAVE+4            # save the CALLER save area
         LA    13,SAVE              # load pointer to THIS save area
*
* invoke IKJEFTSR which has been passed IDCAMS as an arg (PGM/PGMLEN)
*
         LOAD  EP=IDCAMS             # Load IDCAMS into R0
         LR    15,0                  # Copy R0 to R15
    CALL (15),(OPTIONS,DNAMES,PGNO,IOLIST),VL
         LTR   15,15                 # check TSR return code
         BNZ   ERRORRTN              # bad IDCAMS error
         B     CLEANUP               # run cleanup code and return
*
* IDCAMS ERROR BRANCH
*
ERRORRTN DS    0H
         B     CLEANUP
*
* OTHER ERROR BRANCH
*
* ERRORPGM DS    0H
*          B     CLEANUP
*
* COMMON CLEANUP CODE
*
CLEANUP  DS    0H
         L     13,4(,13)           # restore CALLER save area
         LM    14,12,12(13)        # restore register contents
         SLR   15,15
         BR    14                  # branch back to caller
*
* CUSTOM SUBROUTINE
*
IOROUTE  STM 14,12,12(13)
         BALR  12,0
         USING *,12
         ST    13,SAVETWO+4
         LA    13,SAVETWO
*
* RETURN
*
         L     13,SAVETWO+4
         LM    14,12,12(13)
         BR    14
*
* declarations
*
ZERO     DC    F'0'                  # zero constant
SAVE     DS    18F                   # define save area storage
SAVETWO  DS    18F                   # second save area
* PGM      DC    C'IDCAMS'             # name of program
* PGMLEN   DC    F'6'                  # length of program name
* RETCODE  DS    F                     # data area for return code
* REASONC  DS    F                     # data area for abend reason code
* ABENDCD  DS    F                     # ABEND code
* IKJPARM1 DS    0F                    # align
*         DC    XL2'0000'             # invoke from unauth program
*         DC    X'01'                 # take dump if abend
*         DC    X'02'                 # invoke program
*IDCMARG  DS    1F                    # one full word
*         DC    H'2'                  # OPTIONS param len
*         DC    X'0000'               # OPTIONS param content
OPTIONS  DC    H'0'                  # no basic parms for IDCAMS
DNAMES   DC    H'0'                  # no alt ddnames
PGNO     DC    H'0'                  # length of field
DDNAME   DC    CL8'INPUTDS'          # left-justified DD for IO
IOLIST   DC    F'1'                  # one I/O list entry
         DC    A(DDNAME)             # address of DDNAME
         DC    A(IOROUTE)            # address of subroutine
         DC    A(DDNAME)             # required arg for subroutine
* PARMLST  CALL  ,(IDCMARG,DNAMES,PGNO,IOLIST),VL,MF=L # set up PARM
IDCAMASM AMODE 31
         END


SYSPRINT in RUNSTEP:

Code:

1IDCAMS  SYSTEM SERVICES                                           TIME: 05:08:12        07/28/23     PAGE      1         
0                                                                               
  PRINT INFILE(INPUTDS)                                                         
1IDCAMS  SYSTEM SERVICES                                           TIME: 05:08:12        07/28/23     PAGE      2         
-LISTING OF DATA SET -ALEXGAS.TEMP.PDS                                         
0RECORD SEQUENCE NUMBER - 1                                                     
 000000  E3C8C9E2 40C9E240 C140E3C5 E2E340C9   C4C3C1D4 E240D9C5 C3D6D9C4            *THIS IS A TEST IDCAMS RECORD    *   
                                                                               
0IDC0005I NUMBER OF RECORDS PROCESSED WAS 1                                     
0IDC0001I FUNCTION COMPLETED, HIGHEST CONDITION CODE WAS 0                     
1IDCAMS  SYSTEM SERVICES                                           TIME: 05:08:12        07/28/23     PAGE      3       
0                                                                               
0IDC0002I IDCAMS PROCESSING COMPLETE. MAXIMUM CONDITION CODE WAS 0             


But when I use IKJEFTSR, it doesn't seem to process the IDCAMS command I provide to print the dataset, which means that my custom subroutine isn't called.

Perhaps the more accurate question is: how can I pass commands to the program that IKJEFTSR invoked? (or is this even possible?)

I feel like there must be a way as it would be incredibly limiting to not allow such functionality, but perhaps this use-case is too niche...

Sidenote: I am happy to try and get some logs -- would the link-edit output be of use? I don't think we have the z/OS Debugger though icon_sad.gif
Back to top
View user's profile Send private message
Pedro

Global Moderator


Joined: 01 Sep 2006
Posts: 2547
Location: Silicon Valley

PostPosted: Fri Jul 28, 2023 6:16 pm
Reply with quote

re: "how can I pass commands"

Consider an IDCAMS job:
Code:
//STEP2    EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//SYSIN    DD *
 DELETE PEDRO.DATA.VSAM CLUSTER
/*


In your code, you are using the parameters to use INPUTDS instead of SYSIN. I agree that you should prefer not to use SYSIN to avoid collisions with other processes... but IMHO, the simplest way is to default to use SYSIN.
Back to top
View user's profile Send private message
View previous topic :: :: View next topic  
Post new topic   Reply to topic View Bookmarks
All times are GMT + 6 Hours
Forum Index -> PL/I & Assembler

 


Similar Topics
Topic Forum Replies
No new posts Fetch data from programs execute (dat... DB2 3
No new posts Passing SYSPRINT to Invoked Program PL/I & Assembler 9
No new posts Finding Assembler programs PL/I & Assembler 5
No new posts Injecting HTTPHEADER parameters in th... PL/I & Assembler 0
No new posts Passing parm from JCL to Assembler, b... PL/I & Assembler 2
Search our Forums:

Back to Top