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

IBM Integration Bus / Message Broker operations with IBM Integration API aka CMP

  • Post category:IBM Integration Bus
  • Reading time:11 mins read

IBM provides the IBM Integration API, also known under the less accurate and descriptive name Configuration Manager Proxy (CPM), through which you can write your applications to control IBM Integration Bus components.

The Java code below provices a working example of this API. The code presented revolves around a BrokerManager class. In the code below only one method on this class has been implemented, but it can easily be extended with other methods. 

The code uses a z/OS specific way to connect to a broker. On z/OS we do not connect through the network but locally. This needs a slightly different approach using the getLocalInstance method on the Broker Proxy API.

The main() method in this sample implements the instantiation and invocation of the BrokerManager, implementing a command line solution, but the same code could be used in different contexts seamlessly.

The documentation of the API can be found in the IBM Integration Bus Knowledge Center.

Information for the App Connect enterprise version can be found through this link. I have not tried that version.

package com.your.company.package.broker;
import com.ibm.broker.config.proxy.AdministeredObject;
import com.ibm.broker.config.proxy.AdministeredObjectListener;
import com.ibm.broker.config.proxy.ApplicationProxy;
import com.ibm.broker.config.proxy.AttributeConstants;
import com.ibm.broker.config.proxy.BrokerConnectionParameters;
import com.ibm.broker.config.proxy.BrokerProxy;
import com.ibm.broker.config.proxy.CompletionCodeType;
import com.ibm.broker.config.proxy.ConfigManagerProxyException;
import com.ibm.broker.config.proxy.ConfigManagerProxyLoggedException;
import com.ibm.broker.config.proxy.ConfigManagerProxyPropertyNotInitializedException;
import com.ibm.broker.config.proxy.ExecutionGroupProxy;
import com.ibm.broker.config.proxy.LogEntry;
import com.ibm.broker.config.proxy.MQBrokerConnectionParameters;
import com.ibm.broker.config.proxy.MQPropertyFileBrokerConnectionParameters;
import com.ibm.broker.config.proxy.MessageFlowProxy;
import com.ibm.mq.MQException;
import java.util.Enumeration;


public class BrokerManager {


    private BrokerProxy bp;
    private String bn;
    private String qm;
    private String hn;
    private int port;


    BrokerManager(String broker, String host, String qmgr, int port) {
        this.bn = broker;
        this.qm = qmgr;
        this.hn = host;
        this.port = port;
        System.out.println("Creating Broker Manager " + this.bn);
    }


    public boolean connect() {
        BrokerConnectionParameters bcp;
        boolean brokerIsResponding = false;
        // bcp = new MQBrokerConnectionParameters(this.hn, this.port, this.qm);
        // Not for z/OS
        // bcp = new MQBrokerConnectionParameters("", this.port, this.qm); but we will use
        // getLocalInstance for z/OS below
        try {
            this.bp = BrokerProxy.getLocalInstance(this.bn);
            // alternative this.bp = BrokerProxy.getInstance(bcp);
            // Ensure the broker is actually talking to us.
            brokerIsResponding = bp.hasBeenPopulatedByBroker(true);
            if (brokerIsResponding) {
                System.out.println("Broker" + this.hn + " broker " + this.bn + "is responding");
            } else {
                System.err.println("Broker" + this.bn + "is not responding");
                this.bp.disconnect();
                this.bp = null;
            }


        } catch (ConfigManagerProxyLoggedException e) {
            System.err.println("Broker" + this.bn + " CONNECT failed" + e.toString());
        }
        return brokerIsResponding;
    }


    public boolean setStartMode(String exg, String sm) {
        // Set startmode for all flows in given execution group
        //
        // AttributeConstants.STARTMODE_MAINTAINED which means at deploy time or
        // restart the message flow will start based on its isRunEnabled value.
        // AttributeConstants.STARTMODE_MANUAL which means at deploy time or
        // restart the message flow will be stopped.
        // AttributeConstants.STARTMODE_AUTOMATIC
        this.bp.setSynchronous(15000);
        boolean result = false;
        try {
            Enumeration<ExecutionGroupProxy> listEG = this.bp.getExecutionGroups(null);
            while (listEG.hasMoreElements()) {
                ExecutionGroupProxy eg = listEG.nextElement();
                if (eg.getName().equalsIgnoreCase(exg)) {
                    System.out.println("Connected to execution group " + exg );
                    Enumeration<MessageFlowProxy> listMsgFlow = eg.getMessageFlows(null);
                    while (listMsgFlow.hasMoreElements()) {
                        MessageFlowProxy flow = listMsgFlow.nextElement();
                        if (sm.equalsIgnoreCase("maintained")) {
                            flow.setStartMode(AttributeConstants.STARTMODE_MAINTAINED);
                        } else if (sm.equalsIgnoreCase("manual")) {
                            flow.setStartMode(AttributeConstants.STARTMODE_MANUAL);
                        } else if (sm.equalsIgnoreCase("automatic")) {
                            flow.setStartMode(AttributeConstants.STARTMODE_AUTOMATIC);
                        }
                        System.out.println(flow.getName() + " startmode set to " + sm);
                    }
                }
            }
        } catch (Exception e) {
            System.err.println("Error " + e.toString() + " during getExecutionGroup");
        }
        return result;
    }


    public static void main(String[] args) {
        // Variables, initialised
        String action = "";
        String startmode = "";
        String brokername = "";
        String exgname = "";
        String qmgr = "";
        String hostname = "";
        int brokerport = 0;
        
        // Parse the command line arguments
        // We currently only need these, so we do not make parsing of arguments more complex than this
        if (args.length < 4) {
            System.out.println("Error in input. Please provide: Brokername, Executiongroupname, Action, parametervalue");
        } else {
            brokername = args[0];
            exgname = args[1];
            action = args[2];
            startmode = args[3];
            
            // Create brokermanager and connect
            BrokerManager b = new BrokerManager(brokername, hostname, qmgr, brokerport);
            b.connect();
            // Perform given action, currently only
            if (action.equalsIgnoreCase("setstartmode")) {
                b.setStartMode(exgname, startmode);
            } else {
                System.out.println("You gave action: " + action + " Specify valid action: setstartmode.");
            }
        }
    }
}

Hope this works for you. Let me know if you have comments.

// Niek de Greef

Linkfest

  • Post category:Links
  • Reading time:9 mins read

Introductory learning materials

Start here: Here’s What Happens When an 18 Year Old Buys a Mainframe. Great video.

z/OS introductory video course

http://www.redbooks.ibm.com/redbooks.nsf/redbookabstracts/crse0304.html?Open

Master the Mainframe

https://www.ibm.com/it-infrastructure/z/education/master-the-mainframe

The ABCs of System Programming redbooks

http://www.redbooks.ibm.com/abstracts/sg246981.html?Open

IBM z/OS Basic Skills page in Knowledge Center. 

https://www.ibm.com/support/knowledgecenter/en/zosbasics/com.ibm.zos.zbasics/lcmain.html

Introduction to the new mainframe

http://www.redbooks.ibm.com/abstracts/sg246366.html?Open

Introduction to CICS

http://www.redbooks.ibm.com/abstracts/crse0303.html?Open

Db2

DB2 for z/OS: Data Sharing in a Nutshell

Mq on z/os concepts

https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_8.0.0/com.ibm.mq.pro.doc/q003590_.htm

http://share.confex.com/data/handout/share/131/Session_23611_handout_11867_0.pdf

RelevantZ site

http://relevantz.ibmsystemsmag.com/ibm-systems-relevant-z

IBM Z Youtube

IBM Z YouTube channel

Introduction to CICS from IBM

http://www.redbooks.ibm.com/redbooks.nsf/redbookabstracts/crse0303.html?Open

Introduction to the (new) mainframe)

http://www.redbooks.ibm.com/abstracts/sg246366.html?Open

Books (search for 2nd hand versions)

Teach Yourself COBOL In 21 Days

Murarch’s Mainframe COBOL

Assembler training

Assembler training

IBM System z Tech

IBM System z tech zone

Love mainframe site

https://lovemainframe.com/

Relevant Z

http://relevantz.ibmsystemsmag.com/

Zowe

https://www.openmainframeproject.org/

Free training offers

IBM z/OS Introduction and Workshop for the IT Professional – 5 Day Edition (Next Offering: November 11th to 15th – USA CDT)

https://www-01.ibm.com/events/wwe/ast/mtm/zlearn.nsf/enrollall?openform

Free training at HPI

https://open.hpi.de/courses/mainframes2018

Many tutorials on Mainframetechhelp

https://www.mainframestechhelp.com/

Tutorialspoint on mainframe

https://www.tutorialspoint.com/mainframe_tutorials.htm

Mainframe Playground 

https://mainframeplayground.neocities.org/

JCL course

https://www.tutorialspoint.com/jcl/jcl_job_statement.htm

Free COBOL course from CSIS

http://www.csis.ul.ie/cobol/course/

z/OS Introduction and Workshop

http://dtsc.dfw.ibm.com/MVSDS/’HTTPD2.APPS.ZOSCLASS.SHTML(ZOSCLASS)’

Mainframe playground on COBOL

https://mainframeplayground.neocities.org/COBOL.html

Access to real mainframe

Community mainframe

Unfortunately there is no Community open source mainframe yet. How cool would that be – a z/OS system on real Z hardware not owned by our boss.

zD&T

There is the emulator solution zD&T on which you can run z/OS legitimately. If you can afford it and like tinkering with an Intel machine an dLinux.

IBM Z trials – only 3 days

https://www.ibm.com/it-infrastructure/z/resources/trial

Only available for 3 days

Master the mainframe – free

https://www.ibm.com/it-infrastructure/z/education/master-the-mainframe

Remote development programme on Dallas System z

When you have a software development company, or if you are rich.

http://dtsc.dfw.ibm.com/MVSDS/’HTTPD2.ENROL.PUBLIC.SHTML(ZOSRDP)’

Will start at something like $550 USD per month.

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 */

Copy members from one PDS(E) to another using the IEBCOPY utility

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

This JCL script shows how to copy members from one PDS library to another. 

I have retained the input file being tape in the original JCL script for nostalgic reasons only; you will unlike ever use this nowadays. As unlikely, you will be allocating the output dataset on a specific volume, so normally you could omit the VOL=SER= clause as well.

If you omit the S M= (SELECT MEMBER=) clauses, the entire content of the INDD input PDS will be copied to the OuTDD output PDS.

//STEP01   EXEC PGM=IEBCOPY                  
//SYSPRINT DD SYSOUT=*                        
//*INDOC     DD DISP=SHR,DSN=SYS1.ST006868.DOCLIB,LABEL=(06,SL),
//*         VOL=SER=R6868A,UNIT=CTAPE                    
//INDOC     DD DISP=SHR,DSN=YOUR.INPUT.LIBRARY
//OUTDOC     DD DISP=(NEW,CATLG,DELETE),DSN=YOUR.OUTPUT.PDSLIB, 
//         VOL=SER=DASD1A,UNIT=SYSDA,SPACE=(9600,(240,30,20))
//SYSIN    DD *                                    
COPY INDD=INDOC,OUTDD=OUTDOC                       
S M=MEMBER1                                         
S M=MEMBER2                                        
S M=OTHERMEM                                       
S M=MEM4          

THe IEBCOPY is a simple copy utility but it has many many options, of which you will only practically use a fraction. The application above I think is the one you will use in 99% of occasions. The DFDMDdfp Utilities manual sums all the options up.

How to authenticate to the z/OSMF API with a certificate

  • Post category:z/OSMF
  • Reading time:2 mins read

This is a brief description of how to use the z/OSMF API with certificate authentication, from a PHP application.

Create a certificate.For example with openSSL:

openssl req -newkey rsa:2048 -nodes -keyout yourdomain.key
 -out yourdomain.csr

Send the certificate to a certificate authority to get it signed.

Add the signed certificate to RACF:

RACDCERT CHECKCERT(CERT)RACDCERT ADD(CERT) TRUST WITHLABEL('yourlabel-client-ssl') ID(your RACF userID) SETROPTS REFRESH RACLIST(DIGTCERT, DIGTRING)

When authentication, the userID in the ID field will be mapped to, and the z/OSMF tasks will run under this userID.

Save the signed certificate on the PHP server in a directory accessible for the PHP server.
The following PHP code will then issue a request with client certificate authentication: 

curl_setopt($curl, CURLOPT_SSLCERT, '/<server>/htdocs/<somesubdir>yourdomain.csr');
curl_setopt($curl, CURLOPT_SSLCERTTYPE, 'PEM');
curl_setopt($curl, CURLOPT_VERBOSE, 1);
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
// this is the basic auth commented out: 'authorization: Basic ' . base64_encode($this->userid . ":" . $this->password),
etc for the reast of the header

Compile and run a COBOL program on z/OS – A mini-tutorial

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

With this mini-tutorial you may get a quick start with COBOL on z/OS. It gives you a handson overview of the process to get a COBOL program running on z/OS.

The tutorial will show you how to create a Hello World COBOL program on z/OS, compile it and then run in. You can find the program itseld and the JCL scripts for the compilation and run attached below to this post.

The following video describes the process

The following assets are used in this mini-tutorial.

The Hello World COBOL program

COBPROG

The JCL to compile the program

COBCOMP

The JCL to run the program

COBPROGJ

/* Niek de Greef