Page 1 of 2

Change a variable in a member, then execute through CLIST?

PostPosted: Thu Oct 17, 2013 10:15 pm
by NoSleep319
Hi there,

My team has a fairly wide range of jobcards that have very specific tasks, but within the jobcard, there are editing instructions with xxxx and yyyy variables, generally where xxxx needs to be changed to your sysuid and yyyy to the uid you're trying to create/alter/delete. My task is to get these jobs to be closer to automated. I'm going to use the built-in &sysuid to pull the admin's uid, but what I can't figure out is how to modify the jobcard without VISUALLY opening it. It has to be behind the scenes. I've been playing with &SUBSTR, and i've gotten it to work, but if there are spaces, it craps with the EOF error.

My ultimate question is, How do I modifiy connection/permit/ALU/AU statements and change the needed uid and execute it?

This is what I've been working with:

CLIST: (TESTPRM)

PROC 0                                                     
 allocate file(testprm) da('aaaa.jcl.lib(testprm)') shr reu
 OPENFILE testprm UPDATE /* Open file for updating */     
 GETFILE testprm /* Read first record */                   
 DO WHILE &SUBSTR(1:4,&testprm)?=xxxx
 GETFILE testprm /* Read another record */                 
 END                                                       
 SET testprm = yyyy /* Set new value */                   
 PUTFILE testprm /* Write new value to data set */         
 CLOSFILE testprm /* Close the file */                     
END                     


JCL: ('aaaa.jcl.lib(testprm)')

CO   xxxx GROUP($9AOUNEW) OWNER($9AOUNEW) 
PE   'xxxx.**' ID(blah) ACCESS(ALTER) GEN 
PE   'KATM.**' ID(xxxx) ACCESS(ALTER) GEN 
PE   'QCG1X1.**' ID(xxxx) ACCESS(ALTER) GEN
SETROPTS GENERIC (DATASET ) REFRESH


The odd thing is that I can get it to work if there are no spaces...I have no idea how to begin to fix this though. Any ideas? Any help would be greatly appreciated!

Once I can get these variables to be changed/saved, I can get them saved to a temp pds instead, and execute from there so I don't modify the original, then I can change the PROC 0 to PROC 1 UID so noone has to go into the pds at all!

Re: Change a variable in a member, then execute through CLIS

PostPosted: Thu Oct 17, 2013 10:53 pm
by Akatsukami
  • If this is not code that has been in existence for decades, I recommend that you use Rexx instead of CLIST. Even if it has been around for decades, I recommend converting it to Rexx if that is possible.
  • Have you considered using ISPF file-tailoring services?

Re: Change a variable in a member, then execute through CLIS

PostPosted: Fri Oct 18, 2013 7:22 pm
by NoSleep319
Thanks for your response! RIght now, I have a little experience with CLISTs, but none with REXX. I will definitely look into ISPF file-tailoring services. So are you saying it's not possible, or are you just not sure how to do it?

Re: Change a variable in a member, then execute through CLIS

PostPosted: Fri Oct 18, 2013 7:38 pm
by Akatsukami
It is possible, however Rexx is by far the preferred scripting language, as unlike CLIST it is portable between many systems. Likewise, you can certainly edit JCL, but where a fixed set of tasks are to be done, writing a skeleton and then tailoring is again the preferable solution.

Re: Change a variable in a member, then execute through CLIS

PostPosted: Fri Oct 18, 2013 10:14 pm
by NoSleep319
So it looks like File Tailoring would be modifying a 'skeleton', instead of just a jobcard, correct? (still learning...always) I've moved what I had from my jcl.lib to my ispslib ('xxxx.ISPSLIB(TESTREXX)'). I've changed the alias I want to change to &ALIAS and my alias to &ADMIN.

//&ADMINCDV@ JOB MSGCLASS=F,CLASS=B,REGION=0M
//*ROUTE XEQ DEV
//&ADMINCDV@ NJB (733730860000607P0,
// 'UTILITY JOB'),
// SCHENV=JOB@SY0,
// REGION=1000K,MSGLEVEL=1,CLASS=9,MSGCLASS=F
//VRABATCH EXEC PGM=IKJEFT01,DYNAMNBR=25
//OUTRPT OUTPUT DEST=DEV,CLASS=*
//SYSPROC DD DSN=SYS1.SYSSOFT.CLISTLIB,DISP=SHR
//VIPOPTS DD DSN=SYS1.VANGUARD.VANOPTS,DISP=SHR
//SYSTSPRT DD SYSOUT=*,OUTPUT=(*.OUTRPT)
//SYSTSIN DD *
LU &ALIAS
CO &ALIAS GROUP(TESTGRP) OWNER(TESTGRP)
AD 'C02059.TEST.**' GEN FROM('C02059.**') FGEN UACC(NONE) OW(C02059)
PE 'C02059.TEST.**' ID(&ALIAS) AC(R) G
SETR REF GENERIC(DATASET)
/*

I want to change &ADMIN to &SYSUID, but I'll work on that later. for now, I want to get the file-tailoring to work for changing &ALIAS to the ID of my choice without any visual interaction with the jcl. Now that the skeleton is in place (please let me know if I did this correctly...) What would my REXX look like?

Re: Change a variable in a member, then execute through CLIS

PostPosted: Fri Oct 18, 2013 10:54 pm
by Akatsukami
What you show is almost suitable as a skeleton; you just have to separate the the variables (e.g., &ADMIN) from following characters that are valid in variable names with a dot (.) so that the tailoring process can differentiate &ADMIN from &ADMINCDV@. The modified skeleton looks like
//&ADMIN.CDV@ JOB MSGCLASS=F,CLASS=B,REGION=0M,TYPRUN=SCAN         
//*ROUTE XEQ DEV                                                   
//&ADMIN.CDV@ NJB (733730860000607P0,                               
// 'UTILITY JOB'),                                                 
// SCHENV=JOB@SY0,                                                 
// REGION=1000K,MSGLEVEL=1,CLASS=9,MSGCLASS=F                       
//VRABATCH EXEC PGM=IKJEFT01,DYNAMNBR=25                           
//OUTRPT OUTPUT DEST=DEV,CLASS=*                                   
//SYSPROC DD DSN=SYS1.SYSSOFT.CLISTLIB,DISP=SHR                     
//VIPOPTS DD DSN=SYS1.VANGUARD.VANOPTS,DISP=SHR                     
//SYSTSPRT DD SYSOUT=*,OUTPUT=(*.OUTRPT)                           
//SYSTSIN DD *                                                     
LU &ALIAS                                                           
CO &ALIAS GROUP(TESTGRP) OWNER(TESTGRP)                             
AD 'C02059.TEST.**' GEN FROM('C02059.**') FGEN UACC(NONE) OW(C02059)
PE 'C02059.TEST.**' ID(&ALIAS) AC(R) G                             
SETR REF GENERIC(DATASET)                                           

I have placed it in a member named SAF in my sandbox skeleton library. Then the Rexx script to tailor and submit it looks like:
/* REXX */                                                     
/* Written Heisei 25.10.18 by Akatsukami-sama */               
  trace o                                                     
  arg alias .                                                 
  sig = x2c("E69989A3A3859540C88589A2858940F2F54BF1F04BF1F840")
  sig = sig || x2c("82A840C19281A3A2A49281948960A2819481")     
  admin = userid()                                             
  address ispexec "LIBDEF ISPSLIB DATASET ID(WORK.SKELS) STACK"
  address ispexec "FTOPEN TEMP"                               
  address ispexec "FTINCL SAF"                                 
  address ispexec "FTCLOSE"                                   
  address ispexec "VGET ZTEMPF"                               
  "SUBMIT '"ztempf"'"                                         
  address ispexec "LIBDEF ISPSLIB"                             

Let this exec be saved in a member of a suitable PDS(E) (RECFM=VB, LRECL=255). Then the command
EX 'rexx-library(FOO)'  'alias'

will tailor and submit the skeleton; &ADMIN is set to the ID of the person running it, and &ALIAS to whatever you enter as an argument.

Re: Change a variable in a member, then execute through CLIS

PostPosted: Sat Oct 19, 2013 12:08 am
by NoSleep319
ok, so just to make sure I understand this, I throw the EX 'rexx-library(FOO)' 'alias' statement in a CLIST so I can TSO 'blah', then that will kick off the ISPSLIB SAF, which changes and subs the WORK.SKELS dataset, correct?

If I'm correct, I like it! Was I correct? I am new to REXX, and only recently started to understand the simple CLISTs I've done so far.

Re: Change a variable in a member, then execute through CLIS

PostPosted: Sat Oct 19, 2013 12:31 am
by Akatsukami
If rexx-library is allocated to SYSPROC or SYSEXEC, then you can execute the exec by "TSO FOO" (or whatever you choose to name it). My sandbox libraries contain so much WIP, proof-of-concept material, and sheer junk that I almost never allocate them to those filenames, as I want to be able to run the production version of an exec and the test version(s) in different logical screens.

The SAF skeleton in WORK.SKELS (or, again, whatever you choose to name the library) won't be changed itself; rather it'll be read into memory, edited, and written to a sequential data set, the name of which is stored in profile variable ztempf. That variable is retrieved with the VGET service, and the tailored JCL is submitted.

Re: Change a variable in a member, then execute through CLIS

PostPosted: Sat Oct 19, 2013 2:03 am
by NoSleep319
ok...you've been a GREAT help, and I'm going to save what you've given me for testing on my own. I just got off the phone with one of our developers, and they sent me what they've actually been using, and they want me to modify it to work for my needs. if the word comes down to jump...so this is what they gave me, with some of my modifications:

location: RJYW.CLISTLIB(TESTRUN)
/* REXX */                                   
ADDRESS 'ISPEXEC' 'CONTROL ERRORS RETURN'   
ID = R7RR
WRKDSN = 'RJYW.ISPSLIB(TESTREXX)'           
ADDRESS "ISPEXEC" "EDIT DATASET('"WRKDSN"')",
        " MACRO("TESTPRM") PARM(ID)"         
RETURN         


location: RJYW.CLISTLIB(TESTPRM)'
/*REXX*/                                   
/* TO CHANGE XXXX TO BP ALIAS FROM INPUT */
ADDRESS 'ISPEXEC' 'CONTROL ERRORS CANCEL' 
ADDRESS ISREDIT "MACRO (ID)"               
UPPER ID                                   
ALIAS = USERID()                           
ADDRESS ISREDIT "RESET"                   
ADDRESS ISREDIT "CHANGE XXXX " ID "ALL"   
ADDRESS ISREDIT "CHANGE AAAA " ALIAS "ALL"
ADDRESS ISREDIT "SAVE"                     
ADDRESS ISREDIT "END"                     
RETURN     


location: RJYW.ISPSLIB(TESTREXX)'
//AAAACDV@ JOB MSGCLASS=F,CLASS=B,REGION=0M,TYPRUN=SCAN             
//*ROUTE XEQ DEV                                                   
//AAAACDV@ NJB (733730860000607P0,                                 
//             'UTILITY JOB'),                                     
//             SCHENV=JOB@SY0,                                     
//             REGION=1000K,MSGLEVEL=1,CLASS=9,MSGCLASS=F           
//VRABATCH EXEC PGM=IKJEFT01,DYNAMNBR=25                           
//OUTRPT  OUTPUT DEST=DEV,CLASS=*                                   
//SYSPROC  DD  DSN=SYS1.SYSSOFT.CLISTLIB,DISP=SHR                   
//VIPOPTS  DD  DSN=SYS1.VANGUARD.VANOPTS,DISP=SHR                   
//SYSTSPRT DD SYSOUT=*,OUTPUT=(*.OUTRPT)                           
//SYSTSIN  DD *                                                     
LU XXXX                                                             
CO XXXX GROUP(TESTGRP) OWNER(TESTGRP)                               
AD 'C02059.TEST.**' GEN FROM('C02059.**') FGEN UACC(NONE) OW(C02059)
PE 'C02059.TEST.**' ID(XXXX) AC(R) G                               
SETR REF GENERIC(DATASET)                                           
/*                                         


So this works by making ID = R7RR, but we need it to take a variable upon request. So like above, TESTRUN alias. I feel bad asking after you put the effort into explaining how to use the skeletons, but any help with modifying this as well?

Re: Change a variable in a member, then execute through CLIS

PostPosted: Sat Oct 19, 2013 3:46 pm
by NicC
It helps if you put your code in code tags - I have done it for you. If you do not know how then just click the "Quote" button on the post that I coded for you.

I am new to REXX, and only recently started to understand the simple CLIST

Rexx programs are NOT clists. Clists are written in the Clist language. Rexx programs are commonly referred to as "execs"