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. 

Reply via email to