Menu Bar

OPSWEB: Tools and Samples for web-enabling OPS/MVS


MVS now ships with the UNIX System Services-based HTTPD server, and CA-OPS/MVS®  II contains UNIX System Services support, so you can now web-enable OPS/MVS, using REXX programs which adhere to the Common Gateway Interface (CGI) standard. However, as usual, there are some tricks necessary, especially since OPS/REXX does not support all of the UNIX interfaces that TSO/E REXX does (details further below).

Code samples:

  • CGIDemo1.html - Source code for the web page that drives the CGIDemo1.rex program, which demonstrates the basics of how data is passed from a web browser to a CGI program, via both the POST and GET methods.. You can view the completed page here.

  • CGIDemo2.html - Source code for the web page that drives the CGIDemo2.rex program. This example builds onto CGIDemo1.rex (above), adding a REXX SIGNAL ON ERROR Handler, using the CGIParse() function to extract the form data into a stem variable, and demonstrating how to handle processing for an imagemap (it determines if you clicked on the sun, moon, or star). You can view the completed page here.

  • CGIDemo3.rex - Source code for the CGIDemo3.rex program, which does not have a matching html page; instead, it detects when it was invoked without any form data, and dynamically generates the initial web form page.

  • env.sh - Source code for the a very simple Bourne shell script which can run as a CGI program. You can run it here.

  • glvtest1.rex - Source code for an MVS USS (UNIX System Services) REXX program that demonstrates how to call the CA-OPS/MVS OPSDELV(), OPSGETV(), OPSGETVL(), and OPSSETV() functions from the OMVS shell prompt. When run, the output looks like this.

  • USS REXX execs can use the OI() OPS/REXX function to call OPS/REXX execs. Here is an example of opadoper.rex using OI() to call OPS/REXX exec adoper() as a function. adoper uses the CA-OPS/MVS ADDRESS OPER feature to issue a command, retrieve, and display the response. When you run opadoper.rex from the OMVS shell prompt, the output looks like this. Note that the technique used by ADOPER (allowing the calling program to pass in an MVS command as an argument) is NOT SECURE; it is merely used as a simple example to illustrate the power of what can be accomplished. It is preferable for the caller to request a service, and have the calling program translate that service into the appropriate MVS command.

Utility functions:

  • OPSADDR - The OPS/REXX ADDRESS environments (such as ADDRESS OPER, ADDRESS WTO, etc.) are not available to TSO/E or USS REXX programs. OPSADDR() is an external REXX function that is callable from a TSO/E or USS REXX exec that provides access to these OPS/MVS features. Internally it is rather tricky; you call it in USS REXX, then it calls itself in OPS/REXX, performs the function, then returns the data to the USS side. Because of this, you must copy it to a DSNAME in your SYSEXEC concatenation and also to a location in the HFS that is on your UNIX $PATH environment variable (I suggest creating a /usr/local/bin/ directory for such tools). OPSADDRQ is a QA test routine to go with OPSADDR, so that I can easily re-run the original tests after fixing bugs. OPS/REXX execs require SYSEXEC to be allocated, and it doesn't generally stay allocated for long in the USS environment, so OPSADDR() calls the external OPSALLOC() function to perform these allocations. You customize OPSALLOC for your installation by hard-coding your REXX dataset names into it; being an external routine, you customize it once, rather than having dataset names hard-coded into a lot of other REXX execs.

  • OPSFUNC - OPS/REXX functions (such as OPSINFO(), OPSTATUS(), OPSJES2(), etc.) are not available to TSO/E or USS REXX programs. OPSFUNC() is an external REXX function that is callable from a TSO/E or USS REXX exec that provides access to these OPS/MVS features. It uses similar trickery to OPSADDR discussed above, and also requires that you copy it to a DSNAME in your SYSEXEC concatenation and also to a location in the HFS that is on your UNIX $PATH environment variable. OPSFUNCQ is a QA test routine to go with OPSFUNC, so that I can easily re-run the original tests after fixing bugs; it also provides some examples of how to call OPSFUNC(). Like OPSADDR(), OPSFUNC() calls the external OPSALLOC() function to allocate SYSEXEC.

  • There are bits of code that you'll write over and over again in CGI programs, which make good canned tools. Here are a few, all designed to work as internal REXX functions:
    CGIParse() parses HTML form data passed from the web server to CGI programs directly into stem variables, as well as decoding "+" and "%nn" values. It runs in MVS and in Windows.
    RxGetEnv() returns the value of an environment variable in MVS USS, and in Windows under Object REXX and Regina REXX. It could easily be enhanced to support other UNIX platforms, too, I just haven't needed that yet.
    RxHtml() takes the grunt work out of coding HTML tables; It will generate an entire table using input from a stem variable. It is a bit of a work in progress, but it has enough features to get you started, and it is cross-platform between MVS and windows. It also has RxHtmlQ, which is a QA test routine for it.

Installation tools:

The installation of OPS/MVS commands under USS is documented in the "Using OPS/REXX" chapter of the OPS/MVS User Guide manual, but it doesn't give you specific commands to issue, and some additional OPS/MVS commands and functions will run under USS that are not documented. Two installation techniques are mentioned, each with advantages and disadvantages; 

  • opsetup.jcl implements the first installation technique, which places copies of certain OPS/MVS modules into the HFS. This generally works best, except that you must re-run the installation after applying OPS/MVS maintenance (which is easily done with this batch job). 

  • opsetup.sh is a Bourne shell script that implements the second installation technique, where null files are placed in the HFS with the UNIX "sticky bit" activated. I've had mixed success with this technique, sometimes the commands run but don't do anything, and no errors are generated. Hmmm.



Download zipped version of all of the above files
These files should be uploaded to a working directory in your USS HFS, and then dealt with from there. If the file has no extension, it is a REXX EXEC that will go into your SYSEXEC DSNAME, or it is an internal REXX exec that you paste into another REXX program. Anything named *.JCL is, of course, MVS JCL, and should be stored in a *.CNTL or *.JCL library. The *.html files will generally go into your web servers pub/ directory, see your MVS webmaster for details. The *.rex files wil go into the web server's cgi-bin/ directory, or in a system wide directory such as /usr/local/bin/.


Issues using OPS/REXX with CGI:

  • OPS/REXX runs rexx EXECS stored in MVS PDS datasets via the OI and OX commands:
    OI execname
    OX "'fully.qualified.exec.name(member)'"
    But the webserver invokes REXX execs stored in the HFS implicitly, as:
    execname

  • The web server passes environment variables:
    But OPS/REXX cannot access environment variables

  • The web server passes form data via stdin:
    But OPS/REXX cannot PULL or read STDIN

  • First web page output must be <HTML>
    But SAY '<HTML>' in OPS/REXX produces:
    OPX0996I <HTML>


Note: This sample is provided "as-is", and no warranty is provided by ProTech. Use at your own risk! However, feedback on this sample is welcomed by the author! E-mail address: bstark@protechpts.com

 

Google
WWW ProTech