Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Control Block Navigation in REXX

581 views
Skip to first unread message

Robert Zenuk

unread,
Mar 14, 2001, 12:48:13 PM3/14/01
to
I was hoping someone could let me know if I have reached a limitation of REXX
under IKJEFT01 being a non-authorized program or if there is another REXX
approach to accomplishing what I am after.

With the help of "borrowed" code from here and other places I have created
some subroutines that have been very helpful. From one perspective I can get
all the information I want when starting in my address space (or the current
TSO batch address space) and when staying within certain control blocks, but
when trying to run chains beyond the ASCB I get lost. I have "snippetized"
the code for brevity (hopefully I didn't break anything doing this).

My first routine is a JOBINFO routine (recently improved with some nifty ptr:
and stg: subroutines found here - sorry I can't remember who posted this to
give the appropriate credit). This gathers information I commonly use from
the currently running address space.

/* rexx */
sysid = mvsvar(sysname)
jobname = mvsvar('SYMDEF',JOBNAME)
tcb = ptr(540)
ascb = ptr(548)
tiot = ptr(tcb+12)
jscb = ptr(tcb+180)
ssib = ptr(jscb+316)
asid = c2d(stg(ascb+36,2))
jobtype = stg(ssib+12,3)
jobnum = strip(stg(ssib+15,5),l,0)
stepname = stg(tiot+8,8)
procstep = stg(tiot+16,8)
program = stg(jscb+360,8)
say jobname sysid asid jobtype jobnum stepname procstep program
exit(0)
ptr: return c2d(storage(d2x(arg(1)),4))
stg: return storage(d2x(arg(1)),arg(2))

This next routine is called ISITUP. This will check to see if a known
address space name is currently running.

/* REXX */
arg asname
if asname = '' then asname = userid()
/* Chain from the psa to the asvt and run the ascb chain */
psa = ptr(16)
asvt = ptr(psa+556)+512
asvtmaxu = ptr(asvt+4)
/* Using asvtmaxu loop through all active address spaces */
do i=0 to asvtmaxu - 1
ascb = stg(asvt+16+i*4,4)
/* Is this an active ascb? */
if bitand(ascb,'80000000'x) = '00000000'x then
do
ascb = c2d(ascb)
job = stg(ptr(ascb+172),8)
stc = stg(ptr(ascb+176),8)
/* if we find the desired address space name exit with RC=0 */
if stc = asname | job = asname then
exit(0)
end
end
/* We did not find the desired address space name RC=12 */
exit(12)
ptr: return c2d(storage(d2x(arg(1)),4))
stg: return storage(d2x(arg(1)),arg(2))

The last correctly working routine is call WHATSUP and will simply list all
active address spaces.

/* REXX */
psa = ptr(16)
asvt = ptr(psa+556)+512
asvtmaxu = ptr(asvt+4)
/* Using asvtmaxu loop through all active address spaces */
do i=0 to asvtmaxu - 1
ascb = stg(asvt+16+i*4,4)
/* Is this an active ascb? */
if bitand(ascb,'80000000'x) = '00000000'x then
do
ascb = c2d(ascb)
job = stg(ptr(ascb+172),8)
stc = stg(ptr(ascb+176),8)
/* Display the address space name and job if this is an initiator */
if datatype(substr(job,1,1),'U') = 1 then
say stc job
else
/* Filter out inactive initiators */
if stc <> 'INIT' & stc <> 'BPXAS' &,
datatype(substr(stc,1,1),'U') = 1 then
say stc
end
end
exit
ptr: return c2d(storage(d2x(arg(1)),4))
stg: return storage(d2x(arg(1)),arg(2))

Now what I really need is a routine that can find all the currently executing
versions of a particular program name. We have a 16-way Production SYSPLEX
and are constantly adding new STC's and in some cases moving STC's from one
CEC to another. Just to make things interesting, another challenge is the
introduction of some new naming conventions. This routine will be used to
find all executing copies of CICS (DFHSIP), DB2 (DSNYASCP), MQ (CSQYASCP) and
other various critical STC's within each CEC. The ultimate goal is to remove
hard coded names and locations of "loved" applications from an existing
"health check" application. This "health check" application has also been
requested on 3 other SYSPLEX's and I don't want to get into a maintenance
nightmare. So any words of wisdom would be greatly appreciated. This is not
a traditional monitor application like Omegamon, it is more application and
implementation detail oriented.

My initial unsuccessful attempt looks like this:

/* REXX */
arg pgmname
if pgmname = '' then exit(20)
/* Chain from the psa to the asvt and run the ascb chain */
psa = ptr(16)
asvt = ptr(psa+556)+512
asvtmaxu = ptr(asvt+4)
/* Using asvtmaxu loop through all active address spaces */
do i=0 to asvtmaxu - 1
ascb = stg(asvt+16+i*4,4)
/* Is this an active ascb? */
if bitand(ascb,'80000000'x) = '00000000'x then
do
/* If so, ascb->asxb->tcb->jscb->jscbpgmn */
ascb = c2d(ascb)
asxb = ptr(ascb+108)
tcb = ptr(asxb+4)
/* tcb = ptr(ascb+12) didn't work either... */
jscb = ptr(tcb+180)
jscbpgmn = stg(jscb+360,8)
ascbjbni = stg(ptr(ascb+172),8)
ascbjbns = stg(ptr(ascb+176),8)
asid = c2d(stg(ascb+36,2))
/* Exclude initiators */
if ascbjbns <> 'INIT' then
say ascbjbns ascbjbni asid jscbpgmn /* xascb xtcb xjscb */
/* if we find the desired program name exit with RC=0 */
if jscbpgmn = pgmname then exit(0)
end
end
/* We did not find the desired program name */
exit(12)
ptr: return c2d(storage(d2x(arg(1)),4))
stg: return storage(d2x(arg(1)),arg(2))

With this code, I get all address spaces listed but the program name of the
*MASTER* address space only. When I use the last TCB from the AXSB, I get my
TSO user's program name (IKJEFT01).

Is this possible (or some other approach to get the same results) in REXX or
do I have to go to an authorized assembler program to get by the storage
protection issue?

Like many large shops we have a lot of products installed. If someone is
aware of some product that has a TSO or REXX interface (or even batch for
that matter) that can provide me with this information, I'm not tied to the
direct control block access approach (I'll be happy to parse through someone
else's output).

Thanks,
Robert Zenuk
robz...@aol.com

----------------------------------------------------------------------
For TSO-REXX subscribe / signoff / archive access instructions,
send email to LIST...@VM.MARIST.EDU with the message: GET TSO-REXX INFO

One Hand Clapping

unread,
Mar 14, 2001, 2:02:08 PM3/14/01
to
one of your problems is due to some of the information being in lsqa storage
(part of the jobs private region). you may be able to code an asm routine to do
what you need, but if your auditors or legal hear about it you may have a hard
time explaining it... (something to do with data privacy issues I think).


exclusivly from within rexx the only thing that comes to mind is to abandon the
mvs control chain method you are using, and go after the jes2 checkpoint
instead. A copy of the checkpoint is supposed to live in ecsa now.... all you
have to do is decode its internal structure, and you have all jobs on every queue
in every Jes2 member including start/mount/logon. The JQE may even have the job
name (but not every PRB or CDE entry)

Robert Zenuk wrote:

> I was hoping someone could let me know if I have reached a limitation of REXX
> under IKJEFT01 being a non-authorized program or if there is another REXX

> approach to accomplishing what I am after.<snip>

One Hand Clapping

unread,
Mar 14, 2001, 2:08:45 PM3/14/01
to
make that read "The JQE may even have the program name...."

One Hand Clapping wrote while not reading what was written:

> <snip> The JQE may even have the job name (but not every PRB or CDE entry)

<snip>

Robin Ryerse

unread,
Mar 14, 2001, 2:31:50 PM3/14/01
to
.

Although my suggestion doesn't solve your problem, I would like to
suggest to all those Rexx programmers who chase storage control blocks
that you might find my post on "Exploiting Parse Source" worthwhile.
By using member aliases & parse source you can centralize the control
block addressing into one or two members.


On 14 Mar 2001 09:48:13 -0800, Robz...@AOL.COM (Robert Zenuk) wrote:

<snip>


>My first routine is a JOBINFO routine (recently improved with some nifty ptr:
>and stg: subroutines found here - sorry I can't remember who posted this to
>give the appropriate credit). This gathers information I commonly use from
>the currently running address space.

<snip>

Jeremy C B Nicoll

unread,
Mar 14, 2001, 5:57:20 PM3/14/01
to
On 14 Mar, Robert Zenuk <Robz...@AOL.COM> wrote:
> I was hoping someone could let me know if I have reached a limitation
> of REXX

Why are you not using your shop's automation tool? - eg to issue
sysplex-wide D A,CIC* type commands to see what is present?


Using interpreted rexx to scan ASCBs is slow.

Your execs will need to run on all images; better to collect the data
some other way - eg batch SDSF DA displays with suitable filtering will
show active tasks, address space ids etc.

If you must run ASCBs yourself write it in assembler - there must be
plenty of samples on CBT etc that do this; ideally you'd want to be able
to filter on address space type, name etc. It's dead easy code...

--
Jeremy C B Nicoll - my opinions are my own.

Robert Zenuk

unread,
Mar 14, 2001, 8:37:03 PM3/14/01
to
Thanks everyone for the feedback. Basically it is what I thought, I was
hoping someone might have another idea on how to approach this.

Regarding the comments about automation tools, ROUTE commands and SDSF:

I already use several ROUTE commands to collect a lot of information. I also
already use SDSF in batch to issue commands so I can parse and reuse the
results in batch REXX within stem variables and/or temporary ISPF tables.
ROUTE *ALL,D A,XXX* is useful when you have a good, common naming convention
for what you are looking for. I actually already use this technique for
tasks with "easy" names. With CICS, we (like many shops) have functional
prefixes and suffixes for TOR's, AOR's, FOR's, QOR's, ROR's, E-I-E-I-OR's,
etc. Some of the older names have a common prefix others have the &SYSCLONE
value imbedded in the name starting in the 2nd character. Some region types
don't exist on certain CEC's... I could go on for hours...

I do run jobs on each member of the SYSPLEX to get the results I need. I
have one routine (GETPLEX - uses the output from D XCF,S,ALL) that queues all
the active &SYSNAME's in a PLEX. I use this from another routine called
SUB@PLEX where I load an ISPF table with the names and generate jobs using a
skeleton that I submit with "/*JOBPARM SYSAFF=xxxx" to each CEC and "/*ROUTE
PRINT yyyy" back to a specific spool for viewing (unfortunately we have more
than 1 JES MAS in our big SYSPLEX).

I also have a routine called GETCDRMS that can find all the active VTAM
domains in our network (across all 6 PLEX's). It issues a D
NET,CDRMS,SCOPE=ACTONLY and queues the results. I also have a SUB@CDRM that
uses this to load an ISPF table. Naming conventions here allow me to reason
out NJE node names. Here I also use an ISPF skeleton to generate jobs that
use a

/*ROUTE XEQ xxxx to send a job to each NJE Node
/*JOBPARM SYSAFF=yyyy to "fan-out" to all CEC's once it hits the target PLEX
/*ROUTE PRINT zzzz to return the output back to a specific spool

Doing basic stuff has always been easy. Our naming conventions for CICS's,
DB2's and MQ QMGR's (especially on Development systems) presents the biggest
challenges. As Seymour says "The devil is in the details".

I figured if I could resolve the jobnames (sometimes these seem to be
randomly named) after finding the program name from the EXEC card from the
JSCB (a firm constant), I could dynamically deal with the situation presented
to me today. Tomorrow, I'm sure someone will figure out a way to trip me up
again...

FYI, 2 of the 3 routines I posted earlier ISITUP and WHATSUP all chase ASCB's
and run very quickly (usually under .1 second - but then again its running on
a ZZ7).

Thanks for the help,
Robert Zenuk
robz...@aol.com

0 new messages