Wondering what REXX is? First off, it has nothing to do with those big green lizards that ran around angrily eating other lizards (presumably because their pathetically small arms gave them some kind of appendage envy) REXX is a kinda cool interpretive language — a bit like Control language (CLP).
The neat thing about it is that you just enter the commands in a source member and then use STRREXPRC to run them. No need to compile.
I haven’t used REXX for years. Not since my early days working on the old System38. But, last week I was writing a little upload script to make emailing/upload/installing a *SAVF a little easier and I had this thought of “Wouldnt it be nice if I could just write an install script to run automatically? Then I could send it to another IBM I system in text form to let them run it with a simple copy/paste“. Rexx lets us do exactly that!
Caveat Emptor – I ended up discarding this idea and doing things a completely different way but… but… I did write and test these very simple scripts and thought maybe it’s worth stuffing a blog in case it helps someone else out?
So here is a very basic REXX scrptin that you could copy/paste into a source member and then run using STREXPRC from the IBM i Command line:
/* -------------------------------------------------------- */
/* REXX PROCEDURE FOR HOTFIX INSTALL */
/* -------------------------------------------------------- */
say 'starting HOTFIX install'
cmd = 'dltf TSTFIXNEW/MYSAVF'
cmd
select
when rc = 0 then
say 'previous version of *SAVF(TSTFIXNEW/MYSAVF) deleted'
otherwise
say '*** debug: TSTFIXNEW/MYSAVF did not delete'
end
cmd = 'crtsavf file(TSTFIXNEW/MYSAVF) text(hotfix_installer_from_NickLitten)'
cmd
select
when rc = 0 then
say 'savefile created OK'
otherwise
say '*** debug: *SAVF did not create'
end
So, logic is really basic here and the code is self-explanatory right?
But, I started thinking about – would it be nice if I could prompt for library and save file name as a parameter? Perhaps I could add subroutines to do multiple logic chunks in the same script?
The answer is YES and during a few hours tinkering I discovered that REX is a lot more powerful than I remembered.
Here is a bit more evolved version of the same code:
/* REXX PROCEDURE FOR LIBRARY INSTALL */
/* Parameters passed: */
/* (1) function - 3Char - values("CRT"/"RST"/"RUN") */
/* (2) library - 10Char - library name ie: "HOTFIXNEW" */
/* (3) savefile - 10Char - Name of *SAVF being installed */
/* Returns: '0' SUCCESS */
/* '1' FAIL */
/* ------------------------------------------------------------ */
/* Author: nick@nicklitten.com */
/* Date: Sep 18 2017 */
/* Reason: created. */
/* ------------------------------------------------------------ */
/* Setup ERROR,FAILURE & SYNTAX condition traps.*/
SIGNAL on NOVALUE
SIGNAL ON SYNTAX
PARSE ARG 'FUNCTION(' function ')'
PARSE ARG 'LIBRARY(' library ')'
PARSE ARG 'SAVEFILE(' savefile ')'
say "+-------------------------------+"
say "| HOTFIX INSTALL PROCESS |"
say "+-------------------------------+"
if function = " " then
do
say "Enter function CRT/RST/RUN?"
pull function
end
say 'INSTALLING using Function 'function
if library = " " then
do
say "Library Name?"
pull library
end
say 'Using Library 'library
if savefile = " " then
do
say "Save File Name?"
pull savefile
end
say 'Save File 'savefile
/* Does the library exist ? */
'CHKOBJ OBJ(QSYS/'library') OBJTYPE(*LIB)'
if POS('CPF98',rc) ¬= 0 then do
msg = '** Library 'library' not found.'
'SNDPGMMSG MSG(&msg)'
exit(rc)
end
select
when function = "CRT" then CALL proc_create
when function = "RST" then CALL proc_restore
when function = "RUN" then CALL proc_run
end
EXIT(0)
/* ------------------------------------------------------------ */
/* subprocedures for CRT - CREATE */
/* ------------------------------------------------------------ */
proc_create:
say 'HOTFIX REXX - starting CREATE process'
'DLTF 'library'/'savefile
if rc = 0 then
say 'previous version of *SAVF('library'/'savefile') deleted'
'crtsavf file('library'/'savefile') text(hotfix_installer)'
if rc = 0 then say 'Savefile created OK'
return
/* ------------------------------------------------------------ */
/* subprocedures for RST - RESTORE */
/* ------------------------------------------------------------ */
proc_restore:
'RSTLIB SAVLIB('library') RSTLIB('library') DEV(SAVF) SAVF('library'/'savefile')'
if rc = 0 then say library ' has been restored'
else say '*** debug: RSTLIB did not work'
return
/* ------------------------------------------------------------ */
/* subprocedures for RUN - POSTRUN OPTIONS */
/* ------------------------------------------------------------ */
proc_run:
say 'placeholder for some POST RUN logic to add later. Add some logic here'
return
return
Self explanatory code really; Nowt much else I am going to say about this…
So lets run this version.
Simply copy/paste it into a source member (in this case I pasted it into a member called REXXTEST in LITTENN/QRPGLESRC) and then run it like this:
Thank you!
REXX is used in IBM Z mainframe very often. Advantage of learning REXX: 1/ Very easy to master, 2/Useful and powerful, 3/portability (IBM i and IBM Z)
Nice!! I was looking for something a user (None programmer) could manipulate his/her own entry criteria (via RPGLE) which doesn’t have to be compiled. This fits perfectly. Thanks
Thank you!
REXX is used in IBM Z mainframe very often. Advantage of learning REXX: 1/ Very easy to master, 2/Useful and powerful, 3/portability (IBM i and IBM Z)
Nice!! I was looking for something a user (None programmer) could manipulate his/her own entry criteria (via RPGLE) which doesn’t have to be compiled. This fits perfectly. Thanks