REXX Scripts for MVS 3.8j

December 2020

 

Now that REXX is available for MVS 3.8j, I thought I would create a page to host some useful REXX scripts.  Some information available directly from system APIs on later IBM Operating Systems was only available on MVS 3.8j through REXX scripts.  REXX allows you to access, both for reading and updating information, many of the MVS control blocks.  A REXX script can allocate datasets and call external programs, capturing the output from the programs for later processing by the REXX script.  There are many examples of REXX scripts on the CBT tape, as well as other places on the Internet, but many of them are designed to function on later IBM Operating Systems and will fail if you attempt to execute them on MVS 3.8j.  Some of the available scripts may be modified to execute properly on MVS 3.8j, but most will simply fail with a REXX error code.  All of the scripts I post here have been tested and will execute on MVS 3.8j as built using my MVS 3.8j Installation tutorial.  A prerequisite to using REXX on MVS 3.8j is the installation of BREXX/370.  The version I have installed is V2R3M0 [November 2020] and some of the scripts I write utilize facilities that may not be present in earlier versions of BREXX/370.

 

Script Name

Function
astemtmp Allocates a temporary dataset (RECFM=FB,LRECL=150,BLKSIZE=9300), usable for saving stem variable contents and other data that might be passed between scripts/functions.
dasdonl Step through Unit Control Blocks table and verify passed VOLume SERial number is currently online.
dasducb Steps through Unit Control Blocks table and returns information fields from all mounted DASD devices.
dstemtmp Unallocates and deletes temporary dataset allocated/created with astemtmp script.
getvtoc Calls SUPERLST to retrieve VTOC information for given VOLume SERial number, then extracts and returns fields for datasets to calling REXX script.

 

ASTEMTMP Allocate STEM TeMPorary dataset

Download the jobstream install_astemtmp.jcl which uses PDSLOAD to put the REXX exec into your EXEC library (you may need to edit the SYSUT2 DD to point to your library).

Prerequisite(s): BREXX/370 including RXLIB

Some of the scripts I write pass information from the main script to secondary scripts, or from a secondary script back to the main script.  In some implementations of REXX it is possible to pass stem variables between scripts/functions, but not BREXX370, at least not reliably and not when calling scripts from a different library, so this is a convenient way to pass the contents of stem variables or other fields.  Call this function prior to a function requiring the dataset.  If the dataset is already allocated to your TSO session under the DD name STEMTMP, the function will simply return.  If the dataset <userid>.TEMPSTEM exists, it will be allocated to the DD name STEMTMP.  If the dataset does not exist, it will be created and allocated to the DD name STEMTMP.

At the conclusion of your script, or series of scripts, you may call the script DSTEMTMP to deallocate the dataset and delete the dataset.  It is not really necessary to either unallocate or delete the dataset, as it is a small dataset and may be reused by other scripts.  The dataset allocated has the characteristics:  RECFM=FB,LRECL=150,BLKSIZE=9300.

 

DASDUCB return DASD information for all online disk drives using UCB table entries

Download the jobstream install_dasducb.jcl which uses PDSLOAD to put the REXX exec into your EXEC library (you may need to edit the SYSUT2 DD to point to your library).

Prerequisite(s): BREXX/370 including RXLIB, astemtmp

The address of a table containing the Unit Control Blocks for all the devices specified for MVS 3.8j is pointed to by an address held at the address of the Communication Vector Table (CVT) plus x'64' (or decimal 16).  The CVT address is at absolute address x'10' (or decimal 16), so the UCB table is found by loading the address for the CVT and then loading the address at that address plus x'64'.  The table at that address is a list of half-word addresses for each of the Unit Control Blocks.  So it is just a matter of stepping through this table and processing the UCBs to extract the fields for each device.

If the address is zero, there is no UCB block present to process.  If the address is non-zero, the data in storage at that address is loaded and, for each UCB, if it is a normal UCB (x'FF' at offset 3), is for a direct access device (x'20' at offset 19), and online (x'80' at offset 4), then the fields for Channel and Unit (the address of the device), the DASD device type, the Volume Serial Number, and the Storage Class for the volume are extracted/interpreted and returned to the calling REXX script.

This script builds a record with the fields to return in a stem variable; each field is delimited by a tilde (~) character, then writes the stem variable contents to a temporary dataset that may be processed by the calling REXX script.  Here is a simple REXX script to call dasducb, parse the fields, and print the information returned:

/* testing dasducb                                */                    
                                                                        
ADDRESS TSO 'RX SYS2.EXEC(DASDUCB)';  /* retrieve dasd information */   
                                                                        
'EXECIO * DISKR STEMTMP (STEM cuu.'                                     
                                                                        
DO ix=1 BY 1 TO cuu.0                                                   
  PARSE VAR cuu.ix WITH cuu_addr'~'cuu_volser'~'cuu_type'~'cuu_class'~';
  SAY 'CUU:   ' cuu_addr ,                                              
      'Volume:' cuu_volser ,                                            
      'Type:  ' cuu_type ,                                              
      'Class: ' cuu_class;                                              
END;                                                                    
                                                                        
ADDRESS TSO 'RX SYS2.EXEC(DSTEMTMP)'                                    
                                                                        
EXIT;                                                                   

Here is the first screen of output from the script above:

 

DASDONL verify that DASD matching passed volume serial number is ONLine 

Download the jobstream install_dasdonl.jcl which uses PDSLOAD to put the REXX exec into your EXEC library (you may need to edit the SYSUT2 DD to point to your library).

Prerequisite(s): BREXX/370 

Requires a single argument: six character Volume Serial Number.  Scans the Unit Control Block table testing each online DASD device against passed Volume Serial Number.  If matching number is found, returns 0; if no matching number is found, returns -1.

 

DSTEMTMP Deallocate and delete STEM TeMPorary dataset

Download the jobstream install_dstemtmp.jcl which uses PDSLOAD to put the REXX exec into your EXEC library (you may need to edit the SYSUT2 DD to point to your library).

Prerequisite(s): BREXX/370 including RXLIB

If you have called the script ASTEMTMP to create and allocate the dataset <userid>.TEMPSTEM, when you are finished with the dataset, call this function to deallocate and delete the dataset.  

 

GETVTOC calls SUPERLST utility to read and format VTOC, then extracts fields for datasets for return to caller

Download the jobstream install_getvtoc.jcl which uses PDSLOAD to put the REXX exec into your EXEC library (you may need to edit the SYSUT2 DD to point to your library).

Prerequisite(s): BREXX/370 including RXLIB, dasdonl, astemtmp, SUPERLST (batch utility)

This script utilizes the batch utility SUPERLST (is contained in SYSC.LINKLIB on SYSCPK) to retrieve and format the DASD Volume Table of Contents with the PDS option to include information about Partitioned Datasets.  The script allocates the datasets required by the utility and calls it.  The script then extracts the information about each dataset, builds a record with the fields to return in a stem variable; each field is delimited by a tilde (~) character.  The stem variable contents are written to a temporary dataset that may be processed by the calling REXX script.  Here is a simple REXX script to call getvtoc, parse the fields, and print the information returned:

/* testing getvtoc                             */

cmdline = 'RX ' || QUOTE('SYS2.EXEC(GETVTOC)') || ' ' || ARG(1);
ADDRESS TSO cmdline;

IF rc \= 0 THEN EXIT;

'EXECIO * DISKR STEMTMP (STEM vtoc.'

SAY LEFT('Dataset',20) ,
    LEFT('DSORG',5) ,
    LEFT('RECFM',5) ,
    LEFT('BLKSZ',5) ,
    LEFT('LRECL',5) ,
    LEFT('TRKAL',5) ,
    LEFT('MEM',3) ,
    LEFT('DIRSZ',5);

DO ix=1 BY 1 TO vtoc.0
  PARSE VAR vtoc.ix WITH dsn'~'dsorg'~'recfm'~'blksize'~'lrecl'~'trkal'~'members
  SAY LEFT(dsn,20) ,
      CENTER(dsorg,5) ,
      CENTER(recfm,5) ,
      RIGHT(blksize,5) ,
      RIGHT(lrecl,5) ,
      RIGHT(trkal,5) ,
      RIGHT(members,3),
      RIGHT(dirblks,5);
END;

ADDRESS TSO 'RX SYS2.EXEC(DSTEMTMP)'

Here is the output from the script above:


I hope that you have found my instructions useful.  If you have questions that I can answer to help expand upon my explanations and examples shown here, please don't hesitate to send them to me:


Return to Site Home Page Frequently Asked Questions


This page was last updated on December 04, 2020 .