WTO directly from Rexx

  • Post category:Rexx
  • Reading time:1 mins read

There are probably more ways do write a message in the system log – “Write to Operator” from a Rexx script.

This is a very straightforward one I found some time ago somewhere on the Interweb.

/* rexx */                                           
trace r                                              
call syscalls 'ON'                                   
address syscall                                      
path='/dev/console'                                  
'open' path O_wronly 666                             
if retval=-1 then                                    
do                                                    
say 'file not opened, error codes' errno errnojr     
return                                               
end                                                  
fd=retval                                            
rec= 'This is my message text to appear in the system log.' || esc_n                            
'write' fd 'rec' length(rec)                         
if retval=-1 then                                    
say 'record not written, error codes' errno errnojr  
'close' fd                                           
 

Have more solutions? Or remarks? Please let me know below.

Running a MVS or TSO Rexx program from the z/OS Unix environment

  • Post category:Rexx
  • Reading time:2 mins read

You probably know that you can use Rexx programs in z/OS Unix.

What you may not know is that you can also run a TSO or MVS Rexx program from the z/OS Unix environment.

There is a unix command called tso for this. It works as simple as this:

tso –t “exec ‘YOUR.MVS.REXXPDS(TESTREXX)’ EXEC”

will execute your TESTREXX program.

You may want or need to allocate TSO datasets or other datasets in order to execute the Rexx.

You can simply allocate these through the export command.

export ddname=YOUR.MVS.DATASET

You can add these exports to you shell script, or add them to your .profile.

Executing operator command froms batch – using Rexx and SDSF

  • Post category:JCLRexxSDSF
  • Reading time:2 mins read

One of the many way to execute an operator command from a batch rexx program.

With this solution here, with Rexx and SDSF, you can embed the commands in more complex business logic, and use Rexx variables to dynamically establish values for the commands to be issued.

By the way I have started a repository on GitHub on which I will share assets in the future.

https://github.com/execpgm/execpgm-assets

I have added this tool here:

https://github.com/execpgm/execpgm-assets/tree/master/Tools

Direct link:

https://github.com/execpgm/execpgm-assets/blob/master/Tools/OperatorCommandSDSFbatch.txt

//GENER   EXEC PGM=IEBGENER 
//SYSPRINT DD SYSOUT=* 
//SYSIN DD ,BLKSIZE=800,LRECL=80 
 GENERATE 
 LABELS DATA=ALL 
/*
//SYSUT1  DD *  
/* REXX /  
RC=ISFCALLS('ON')  
YOURSTC = "MYSTC"  
ADDRESS SDSF "ISFEXEC '/P "YOURSTC"'"  
ISFDELAY="5"  /* REPLY IS IN STEM ISFULOG. */ 
/*
//SYSUT2  DD  DSNAME=&&DS1(CMD),DISP=(NEW,PASS), 
//       UNIT=SYSDA,SPACE=(TRK,(5,,2)) 
//* 
//RDWRJ    EXEC PGM=IKJEFT01 
//SYSPRINT DD SYSOUT=* 
//SYSPROC  DD DISP=SHR,DSN=&&DS1 
//SYSTSPRT DD SYSOUT=* 
//SYSTSIN DD * 
 CMD 
/* 
//

Ways get utc / gmt time zone (offset) versus local time in Rexx on z/OS

  • Post category:Rexx
  • Reading time:2 mins read

Regularly we need to compare local time to absolute time UTC (or GMT) programmatically.

This can be done in various ways.

The cleanest way is to use the static system symbols that z/OS defines. See also section “Static System Symbols” in the z/OS Initialization and Tuning Reference.You can easily use this in a Rexx program. For example: 

/* Rexx */  
/* Display UTC Time elements */
say  mvsvar('SYMDEF','HR')      
say  mvsvar('SYMDEF','MIN')     
say  mvsvar('SYMDEF','SEC')     
say  mvsvar('SYMDEF','HHMMSS')  
say  mvsvar('SYMDEF','LHHMMSS') 

It is also possible through Unix System Services date command to obtain UTC:

date -u
Wed Aug 21 15:20:42 GMT 2019 

A more complex way (old fashioned) to achieve the same is addressing the CVT extension block:

                   
cvt = c2d(storage(d2x(16),4))                                
cvtext2 = c2d(storage(d2x(cvt + 328 ),4))
offset  = ((c2d(storage(d2x(cvtext2+56+2),4))) * 16) /3600000000 
timezone = "+0"||offset||"00"                   

Thanks to Henk for the latter two solution alternatives.

— Niek de Greef

Compare Disk contents with Catalogs – a custom Rexx and JCL solution

  • Post category:Rexx
  • Reading time:2 mins read

This one is untested since 1997. A little warning, though I believe it will still work.

During a z/OS migration (probably still MVS/ESA or maybe OS/390) we needed to restructure the catalog layout. The client did not have a good catalog structure in place and almost everything had ended up in the master catalog. A small nightmare, especially for a smooth upgrade. BEtter worded: they made a mess of their catalogs. (The company does not exist anymore.)

I created some custom programs to compare catalog contents with contents on disks.

The job in CMPLCLVJ does the following:

CMPLCLVJ

  • Step INTRPOLD – Interpret an existing LISTCAT result for easier handling during the compare
  • Step LIST: Create LISTVTOC of desired volumes
  • Step INTRPLV – Interpret the LISTVTOC output for easier handling during the compare
  • Step COMPLCLV – Compare the Listcat and LISTVTOC

The following Rexx programs are used in this job:

INTLISTC – interprets the LISTCAT output.

INTLISTV – interprets the LISTVTOC results

CMPLCLV – compares the interpreted (transformed) listcat and listvtoc results and reports the results.

// Judd Froam

A simple Rexx program to find matches / unmatches in file contents

  • Post category:Rexx
  • Reading time:3 mins read

The problem were are solving here:

You have 2 files, one has records (lines) with “key” values in the first word, the second has records (lines) “key” values in the second word. (A Word here is defined as a string delimited by blanks – similar to the definition in Rexx – See Rexx Reference)

For all of the key entries in file1 you want to know if key entries exist in file2. If the key entry does not exist the record in file2 is written to the output file.

The solution in Rexx below works as follows:

Build a simple hash table of key entries in file1. For each record in file2, check if the key value has an entry in the hash table. If not, write the record to the outfile file.

BTW in Rexx programs for files that are not excessively large, I have the habit of reading them fully into a stem variable before processing. Similarly I use a stem variable to capture the output data, and write that in one go after processing is complete. Not sure if that is a good habit, but it makes programming easy.

/* Rexx */
trace off
/* Fill InpRec1. and InpRec2. */
Call ReadInput
/* Fill filter.     */
Drop filter.Do N = 1 To InpRec1.0  
entryname = Word(InpRec1.N,1)  
   filter.entryname = 1
End /* Do */
/* Compare old file with new and write output */
Drop OutRec1.OutRec1.0 = 0
Do N = 1 To InpRec2.0  
   entryname = Word(InpRec2.N,2)  
   If filter.entryname = 1  
   Then Do
      NOP /* This entry exists in both, that's ok */      
      Say 'To be skipped : ' entryname    
      End  
    Else Do /* Write this line, this entry has to be processed */
       help = OutRec1.0 + 1      
       OutRec1.help = InpRec2.N      
       OutRec1.0 = help    
       End
End /* Do */
 Call WriteOutput
Exit
/*******************************************************************/
/* Routines ********************************************************/
/*******************************************************************/
/*******************************************************************/
ReadInput:
Address Tso
'EXECIO * DISKR FILTER  (Stem InpRec1. Finis'
If RC <> 0
Then Do
    Say 'Error reading input file FILTER, Rc = ' RC
    Exit 69  
End
'EXECIO * DISKR INPLIST (Stem InpRec2. Finis'
If RC <> 0
Then Do
    Say 'Error reading input file INPLIST, Rc = ' RC
    Exit 69  End
Return /* ReadInput */
/*******************************************************************/
WriteOutput:
Address Tso
'EXECIO * DISKW OUTLIST (Stem OutRec1. Finis'
If RC <> 0
Then Do
    Say 'Error writing output file OUTLIST, Rc = ' RC
    Exit 69
  End
Return /* WriteOutput */