I've had a similar need when helping to debug application code. See the
pasted "REXXBACK EXEC" below, which can show the whole path back the
original caller (along with the userid/mdisk|directory where each exec was
located).
Mike Walter
Hewitt Associates
The opinions expressed herein are mine alone, not my employer's.
---<snip>---
/* Prolog; See Epilog for additional information ********************
* Exec Name - REXXBACK EXEC *
* Unit Support - OSS/VM *
* Status - Version 1, Release 1.0 *
********************************************************************/
address COMMAND
parse source xos xct xfn xft xfm xcmd xenvir .
parse upper arg parms 0 operands '(' options ')' parmrest
?function=(xct='FUNCTION')
If parms='?' then Signal Explain
If ?function then
Do
operands=arg(1)
options =arg(2)
End
upper operands options
backchain=''
fmhit=''
operands=strip(operands,'B')
If operands<>'*' & verify(operands,0123456789)>0 then
Do
say xfn'; Operand must be a single number, found: "'operands'"'
say 'For more help, enter:' xfn '?'
Call Exit 20
End
If operands='' then operands='*'
?owner=0
invopts=''
If options<>'' then
Do while options<>''
parse var options opt options
If opt<>'OWNER' then invopts=invopts opt
else ?owner=1
End
If invopts<>'' then
say xfn'; Invalid options ignored:' space(invopts)
If operands='*' | operands=''
then backlvl=4E4 /* I.e. For_E_For, or forever*/
else backlvl=operands+1
Do ix=1 to backlvl
drop c.
'PIPE (NAME' xfn')' ,
'| REXXVARS' ix 'NOMESSAGE233' , /* Get caller's variables */
'| STRFIND /s/' , /* Keep just Source vars */
'| TAKE 1' , /* Only 1st one */
'| VAR clrsource' /* Save for use */
If rc<>0 then Leave ix /* Get rc=233 at chain head */
parse var clrsource c.cpfx c.cxos c.cxct c.cxfn c.cxft c.cxfm ,
c.cxcmd c.cxenvir .
backchain=backchain',' c.cxfn c.cxft c.cxfm
If \?owner then Iterate
parse var c.cxfm fm 2 .
If fm<>'*' & pos(fm,fmhit)>0 then Iterate /* Diff. EXECLoads? */
fmhit=fmhit fm
If fm='*' then
'PIPE (NAME' xfn'2)' ,
'| COMMAND EXECMAP' c.cxfn c.cxft ,
'| DROP 1' , /* Drop title */
'| TAKE 1' , /* Only first appearance */
'| SPECS W -1;-1 1' , /* Last word */
'| VAR owner'
Else
Do /* Get Owner info */
/* Examples: */
/* q accessed a */
/* Mode Stat Files Vdev Label/Directory */
/* A R/W 2291 191 JQPUBLIC */
/* q accessed z */
/* Mode Stat Files Vdev Label/Directory */
/* Z R/W 3316 DIR PPS01:SYSPROG.TOOLS */
'PIPE (NAME MDorSFS)' ,
'| COMMAND QUERY ACCESSED' fm ,
'| DROP 1' ,
'| VAR qacc'
parse var qacc . . . vdev owner .
If vdev<>'DIR' then
'PIPE (NAME MDowner)' ,
'| CP QUERY MDISK' vdev 'LOCATION',
'| DROP 1' ,
'| SPECS W3.2 1' , /* Owner/vdev in CP DRCT */
'W6.2 NW' , /* Real volser and rdev */
'| VAR owner'
End
backchain=backchain'('owner')'
End
backlvl=backlvl-1
backchain=strip(backchain,'L',',')
backchain=strip(backchain,'L',' ')
If ?function then Return operands'=' backchain
else say 'REXXback' operands'="'backchain'".'
Call Exit 0
/********************************************************************/
/* Sub-Routines below this point */
/********************************************************************/
Exit:
parse arg exitrc .
If verify(exitrc,'-0123456789')=0 then Exit exitrc
else Exit 999999
Explain:
'PIPE (NAME RexxBackExplain)' ,
'| <' xfn xft xfm ,
'| INSIDE ANYCASE /ExplainBegin/ /ExplainEnd/' ,
'| CONSOLE'
Call Exit 4
/*
ExplainBegin:
REXXBACK provides the names (and optionally minidisk owner and address)
of all the calling rexx programs, back to the beginning of the calling
chain of REXX EXECs.
The command format is:
+-*-----+
>>-REXXBACK-+-------+---------------+-------------------------------+-->
+-n-----+ +--(----| Options |---+-----+---+
+--)--+
Options:
|--+-------+-----------------------------------------------------------|
+-OWNER-+
Where:
n
limits the number of calling execs to search back. For example
'0' would display only the current exec running REXXBACK, '1'
would display the current exec and go back only 1 level.
Default: '*' - meaning to go back to the beginning of the chain.
OWNER
includes the userid and minidisk address within parenthesis the
first time each filemode is encountered in the chain.
Usage note:
The displayed rexx exec chain is for REXX execs only. And imbedded
EXEC or EXEC2 execs will not be displayed.
Examples from within a REXX program:
say rexxback()
*= E EXEC A1, D EXEC A1, C EXEC A1, B EXEC A1, A EXEC A1
say rexxback(0,OWNER)
0= E EXEC A1(JQPUBLIC 0191)
say rexxback(1,OWNER)
1= E EXEC A1(JMDOE 0191), D EXEC A1
say rexxback(4,OWNER)
4= E EXEC A1(DWJONES 0191), D EXEC A1, C EXEC A1, B EXEC A1, A EXEC A1
EXEC REXXBACK 4 (OWNER
REXXback 4="E EXEC A1(ABSMITH 0191), D EXEC A1, C EXEC A1, B EXEC
D1(ONMOORE 02
00), A EXEC A1".
EXEC REXXBACK (OWNER
REXXback *="E EXEC A1(LSONE 0191), D EXEC A1, C EXEC C1(YKNOT 0192), B
EXEC A1, A EXEC A1".
EXEC REXXBACK
REXXback *="E EXEC A1, D EXEC A1, C EXEC A1, B EXEC A1, A EXEC A1".
ExplainEnd:
*/
Call Exit 4
/* Epilog ***********************************************************
* Function - Provide means of tracing back calling rexx *
* program chain to start. *
* Component of - N/A *
* Command format- See 'Explain' subroutine, above. *
* Called by - Misc. rexx programs *
* Dependencies - CMS Pipelines. *
* Program Lang. - CMS REXX *
* Date Written - 20000316 *
* Author - Michael R. Walter *
* Changed | By | Description of Change *
* --------+-----+------------------------------------------------- *
* 20000918 mrw - Replace RUNPIPE with REXXVARS "NOMESSAGE233" oper*
* 20080709 mrw - Display EXECLOADed locations. *
* 20100923 mrw - Remove reliance on external QOWNER EXEC. *
* *
********************************************************************/
---<snip>---
"Colin Allinson" <[email protected]>
Sent by: "CMSTSO Pipelines Discussion List" <[email protected]>
09/23/2010 08:42 AM
Please respond to
"CMSTSO Pipelines Discussion List" <[email protected]>
To
[email protected]
cc
Subject
Invocation Question
I have a REXX EXEC (that will run as a compiled module) that needs to know
how it was called and where from.
It could be called but, more likely, it will just be executed from an
EXEC.
I can certainly include a PIPE REXXVARS 1 in the routine to find the
caller.
The problem is that the other possibility is that it may be called
directly from the call line. In this case any invocation level other than
0 gives a pipe error.
I don't think there is anything on PARSE SOURCE that can help me because I
am normally not called as a subroutine.
Is there any way I can tell what is the maximum valid invocation level? I
am sure there is something obvious but I can't think of it at the moment.
Just to explain what I am trying to do. I want to put a wrapper around a
standard command module so that I can log it's use (where from etc.).
Colin Allinson
VM Systems Support
Amadeus Data Processing GmbH
IMPORTANT - CONFIDENTIALITY NOTICE - This e-mail is intended only for
the use of the individual or entity shown above as addressees. It may
contain information which is privileged, confidential or otherwise
protected from disclosure under applicable laws. If the reader of this
transmission is not the intended recipient, you are hereby notified that
any dissemination, printing, distribution, copying, disclosure or the
taking of any action in reliance on the contents of this information is
strictly prohibited. If you have received this transmission in error,
please immediately notify us by reply e-mail or using the address below
and delete the message and any attachments from your system.
Amadeus Data Processing GmbH
Geschäftsführer: Eberhard Haag
Sitz der Gesellschaft: Erding
HR München 48 199
Berghamer Strasse 6
85435 Erding
Germany
The information contained in this e-mail and any accompanying documents may
contain information that is confidential or otherwise protected from
disclosure. If you are not the intended recipient of this message, or if this
message has been addressed to you in error, please immediately alert the sender
by reply e-mail and then delete this message, including any attachments. Any
dissemination, distribution or other use of the contents of this message by
anyone other than the intended recipient is strictly prohibited. All messages
sent to and from this e-mail address may be monitored as permitted by
applicable law and regulations to ensure compliance with our internal policies
and to protect our business. E-mails are not secure and cannot be guaranteed to
be error free as they can be intercepted, amended, lost or destroyed, or
contain viruses. You are deemed to have accepted these risks if you communicate
with us by e-mail.