Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Capturing JES2 Variables in Batch REXX

Status
Not open for further replies.

ks01

MIS
Aug 11, 2002
110
US
Hi everyone …

I know almost 0% about REXX, but am using an exec written about 16 years ago by a predecessor at my shop.

The function of the exec is used in a batch job to send data in a file created by a previous step in the same job to an SMTP gateway on one of the MVS communication server running an SMTP gateway.

This exec has worked fine all these years, but our users have requested that we include a few variables with the passing of the data that I do not believe are system variables (e.g. mvsvar('symdef','jobname')). The variables that are being requested are the JES2 job number and the job's condition code.

I was hoping that someone may have a suggestion on something relatively easy I could implement to grab the data from JES2 about the job that is creating this data using the existing exec I have. Here is the exec we're using today.

Thanks in advance for any suggestions!

Code:
/* THIS COMMENT IS REQUIRED TO DENOTE THAT THIS IS A REXX EXEC */

PARSE UPPER ARG RECIPDSN BODYDSN
RECIPDSN = STRIP(RECIPDSN)
BODYDSN = STRIP(BODYDSN)

CALL INIT

CALL GET_RECIPIENTS

CALL GET_BODY_OF_NOTE

CALL BUILD_HEADER

CALL BUILD_BODY

CALL BUILD_TRAILER

CALL DISPLAY_IT

CALL MAIL_IT

EXIT
/*--------------------------------------------------------------------*/

INIT:

SYSID   = mvsvar('sysname')
Sysplex = mvsvar('sysplex')
Jobname = mvsvar('symdef','jobname')
Userid  = userid()

Jobname = translate(Jobname,'________________________________',  ,
                            '~!@#$%¬&*()_+{}|:"<>?`-=¢¦\;'',./')

MAILTIME = Date('Normal') /* dd mon yyyy */ ,
           Time('Normal') /* hh:mm:ss 24 hour */

SMTPTASK = 'TCPSMTP'
SMTPSYSID = SYSID

Select
  When Sysplex = 'MVS1PLEX' Then SMTPSYSID =    'MVS1'
  When Sysplex = 'MVS3PLEX' Then SMTPSYSID = /* 'MVS3' */ 'MVS5'
  When Sysplex = 'MVS4PLEX' Then SMTPSYSID = /* 'MVS9' */ 'MVS5'
  When Sysplex = 'MVS5PLEX' Then SMTPSYSID =    'MVS5'
  When Sysplex = 'MVS7PLEX' Then SMTPSYSID = /* 'MVS7' */ 'MVS5'
  When Sysid   = 'MVS8'     Then SMTPSYSID = /* 'MVS8' */ 'MVS5'
  When Sysplex = 'Y2KPLEX'  Then SMTPSYSID = /* 'MT2K' */ 'MVS5'
  Otherwise
      SMTPSYSID = 'MVS5'
end; /* select */

RETURN
/*--------------------------------------------------------------------*/

GET_RECIPIENTS:

/* Read the recipient file into array "RECIP." */
ADDRESS TSO "ALLOCATE DD(RECIPDD) DATASET('"RECIPDSN"') SHR"
"EXECIO * DISKR RECIPDD (STEM RECIP. FINIS)"
ADDRESS TSO "FREE DD(RECIPDD)"
SAY RECIP.0 'RECIPIENTS READ'

/* Clean up recipients ID's */
DO I = 1 TO RECIP.0
   RECIP.I = STRIP(RECIP.I)

   PARSE UPPER VAR RECIP.I NODE.I '.' NAME.I

   If index(RECIP.I,'RSCS1.') Then Do
      RECIP.I = Substr(RECIP.I,7,80)
   End

   If index(RECIP.I,'OCWVM.') Then Do
      RECIP.I = Substr(RECIP.I,7,80)
   End

   If index(RECIP.I,'OCBVM.') Then Do
      RECIP.I = Substr(RECIP.I,7,80)
   End

   If index(RECIP.I,'N14.') Then Do
      RECIP.I = Substr(RECIP.I,5,80)
   End

   If index(RECIP.I,'N15.') Then Do
      RECIP.I = Substr(RECIP.I,5,80)
   End

   If index(RECIP.I,'VM4.') Then Do
      RECIP.I = Substr(RECIP.I,5,80)
   End

   If index(RECIP.I,'VM5.') Then Do
      RECIP.I = Substr(RECIP.I,5,80)
   End

   RECIP.I = strip(RECIP.I)

   /* If ID doesn't have an '@' then default recipients to DOMAIN.com */
   If index(RECIP.I,'@') = 0 Then Do
      RECIP.I = RECIP.I||'@DOMAIN.Com'
   End
END

RETURN
/*--------------------------------------------------------------------*/

GET_BODY_OF_NOTE:

ADDRESS TSO "ALLOCATE DD(BODYDD) DATASET('"BODYDSN"') SHR"
"EXECIO * DISKR BODYDD (STEM BODY. FINIS)"
ADDRESS TSO "FREE DD(BODYDD)"
SAY BODY.0 'LINES OF TEXT BODY READ'

If BODY.1 = 'BODY.1' Then BODY.1 = ' '

If BODY.2 = 'BODY.2' Then BODY.2 = ' '

RETURN
/*--------------------------------------------------------------------*/

BUILD_HEADER:

WORK.1 = 'HELO' SMTPSYSID||'.DOMAIN.COM'  /* no space */
WORKSUB = 2 /* subscript for work arry */

WORK.WORKSUB = 'MAIL FROM: <'||sysid||'.'||jobname||'@DOMAIN.com>'
WORKSUB = WORKSUB + 1

DO I = 1 TO RECIP.0
   WORK.WORKSUB = 'RCPT TO: <'||RECIP.I||'>'
   WORKSUB = WORKSUB + 1
END

WORK.WORKSUB = 'DATA'  /* end of SMTP commands */
WORKSUB = WORKSUB + 1

WORK.WORKSUB = 'Date:' MAILTIME 'GMT'
WORKSUB = WORKSUB + 1

WORK.WORKSUB = 'From:' sysid||'.'||jobname strip(BODY.1)
WORKSUB = WORKSUB + 1

DO I = 1 TO RECIP.0
   WORK.WORKSUB = 'TO:' RECIP.I
   WORKSUB = WORKSUB + 1
END

WORK.WORKSUB = 'SUBJECT:' strip(BODY.2)
WORKSUB = WORKSUB + 1

RETURN
/*--------------------------------------------------------------------*/

BUILD_BODY:


If index(BODY.3,':') > 0 then do
   WORK.WORKSUB = ' '
   WORKSUB = WORKSUB + 1
end

DO I = 3 TO BODY.0

   If BODY.I = '.' Then Do
      BODY.I = ' ' || BODY.I
   End
   WORK.WORKSUB = BODY.I
   WORKSUB = WORKSUB + 1
END

RETURN
/*--------------------------------------------------------------------*/

BUILD_TRAILER:

WORK.WORKSUB = '_____' /* '' caused note to terminate ' ' is ok */
WORKSUB = WORKSUB + 1

WORK.WORKSUB = '.'
/*  WORKSUB = WORKSUB + 1  not for last line */

RETURN
/*--------------------------------------------------------------------*/

DISPLAY_IT:

SAY('The following note is about to be sent:')
SAY('')
DO I = 1 TO WORKSUB
   SAY(WORK.I)
END
SAY('')

RETURN
/*--------------------------------------------------------------------*/

MAIL_IT:

SAY('About to mail to:' SMTPSYSID||'.'||SMTPTASK)
ADDRESS TSO "ALLOCATE DD(PROFSDD) SYSOUT(B) ,
             DEST("SMTPSYSID") WRITER("SMTPTASK")"
"EXECIO * DISKW PROFSDD (STEM WORK. FINIS"
ADDRESS TSO "FREE DD(PROFSDD)"

RETURN
 
There is a way to get jobname and jobnumber from a running job:
Code:
@ascb    = Right(c2x(Storage(224,4)),7) /* ASCBaddr is at X'224'     */
@cvt     = Right(c2x(Storage(10,4)),7) /* CVTaddr is at X'10'        */
sysname  = Storage(d2x(x2d(@cvt) + x2d('154')),8)
                             /* SYSNAME is X'154' bytes into the CVT */

@smca    = Right(c2x(Storage(d2x(x2d(@cvt) + x2d('c4')),4)),7)
                             /* SMCAaddr is X'C4' bytes into the CVT */
cpuid    = Storage(d2x(x2d(@smca) + x2d('10')),4)
                       /* DW92, e.g.; located 16 bytes into the SMCA */

@tcb     = Right(c2x(Storage(21c,4)),7)  /* TCBaddr is at X'21C'     */
@tct     = Right(c2x(Storage(d2x(x2d(@tcb) + x2d('a4')),4)),7)
                              /* TCTaddr is X'A4' bytes into the TCB */
@jscb    = Right(c2x(Storage(d2x(x2d(@tcb) + x2d('b4')),4)),7)
                             /* JSCBaddr is X'B4' bytes into the TCB */
@ssib    = Right(c2x(Storage(d2x(x2d(@jscb) + x2d('13c')),4)),7)
                           /* SSIBaddr is X'13C' bytes into the JSCB */
jobnum   = Storage(d2x(x2d(@ssib) + x2d('0c')),8)
                           /* JOBnumber is X'0C' bytes into the SSIB */

@tiot    = Right(c2x(Storage(d2x(x2d(@tcb) + x2d('c')),4)),7)
                                /* TIOTaddr is 12 bytes into the TCB */
jobname  = Storage(@tiot,8)
                         /* JOBname is the first 8 bytes of the TIOT */

text = "JN="jobname " J#="jobnum "  CPU="cpuid "  Sysn="sysname
This isn't my original work. I got it from somebody else, probably Doug Nadel.

There is also a method (I've seen it) to get all the step-return codes from prior steps in the job, but I don't have a copy of that. Keep looking.


Frank Clarke
--America's source for adverse opinions since 1943.
 
Thanks Frank, I will try this out and see how it works!

Do you have any suggestions on a good documentation/reference point for a total REXX newbie that I could add to my favorites that I could read up on other helpful things such as this?

Thanks again!
 
Well, you could look at my REXX site at to see some examples of utility software. Some of it is pretty elaborate so it might be over your head, but lots of people have told me they learned a great deal from the routines there.


Frank Clarke
--America's source for adverse opinions since 1943.
 
Hi Frank ...

My job ended with a return code 0012 for the step that executed the exec.

Here is the update I made to my code:

Code:
INIT:                                                           
                                                                
SYSID   = mvsvar('sysname')                                     
Sysplex = mvsvar('sysplex')                                     
Jobname = mvsvar('symdef','jobname')                            
Jobnum  = Storage(d2x(x2d(@ssib) + x2d('0c')),8)
Userid  = userid()

Here is the error message I received:

Code:
READY                                                       
 %DRPROFSX PCX.CPSR.LIST.LOAD.TEST PCX.RPT.STA147A.OUT      
    87 +++  Jobnum  = Storage(d2x(x2d(@ssib) + x2d('0c')),8)
    62 +++ CALL INIT                                        
Error running DRPROFSX, line 87: Incorrect call to routine

Any suggestions?

Thank you again in advance ...
 

You need ALL of the code I gave you, not just one line.

Frank Clarke
--America's source for adverse opinions since 1943.
 
Thanks Frank, this worked perfectly and gave me exactly what I needed. I spent a few hours yesterday reading through the REXX manuals on the IBM web site so this has been a good learning experience for me as well.

One final question, any suggestion on where I might be able to find the job's final condition code?

Thanks again!

 
Each step has a condition code.

I'm not aware of any "final condition code" for a job.
 
Perhaps I should have worded that better ... the highest return code?
 

As I said: there is a REXX routine which pokes through various system control blocks to discover ALL of the step return codes. I've been looking for it -- I know we use it in one of our applications -- but haven't been able to find it. There might be a reference on mvshelp.net and I'll look there later.


Frank Clarke
--America's source for adverse opinions since 1943.
 
Have a look at this thread: thread277-827693

I think it contains what you are after.

Marc
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top