Professional Documents
Culture Documents
Introduction
Just imagine, you have IPLed your brand-new MVT system (or MVS, if and
when it becomes available for Hercules). Now you decide to change some
parameters in SYS1.PARMLIB. Of course, you want to play it safe, like
Wear a belt
Wear suspenders
Keep your hands in your pockets
With other words, before you change a crucial member (let's say
LNKLST00) you will want to make a safe copy, or backup, of this member.
Very simple, you say:
You fire up explorer, click with the mouse, drag the member.... Oooops -
wrong timeframe, wrong system, restarting.....
What you really do is: You call up a little helper and tell him to do the
copying for you. IBM has provided a lot of little helpers in MVT, and they
are called UTILITIES. We will discuss a few of the more useful ones here.
SYSPRINT
With the SYSPRINT DD statement you tell MVT into which output queue
you want the utility to place its messages and report. Usually you would
code
//SYSPRINT DD SYSOUT=A
The SYSIN DD statement specifies the dataset that contains the commands
you want to give to the utility program. In most cases this is an instream
data set, i.e.:
//SYSIN DD *
or
//SYSIN DD DATA
If you do not want to issue any specific commands (but rely on some default
action the utility will take), you code:
//SYSIN DD DUMMY
Whenever you code commands for the utility (they are called Utility Control
Statements), some special rules apply:
Utility Programs
The following utility program will be discussed in this article (eventually)
IEFBR14
A Dummy Program. Does Nothing. Really. Nothing. Nada. Ne Riens.
Inge Ting. Nix.
IEBGENER
Copies sequential data sets
IEBCOPY
Copies partitoned data sets
IEHDASDR
Doing weird things to a DASD (...aka disk)
IEBPTPCH
Prints (or punches) partitioned or sequential datsets or members of
partitioned data sets
IEHLIST
Prints datasets and VTOC information
IEHPROGM
Maintains the catalog. Can delete and uncatalog datasets
IEFBR14
A program that REALLY does nothing. Zilch. Why do we need such a
thing? Well, look at the following JCL:
//MYJOB JOB CLASS=A,MSGCLASS=A,REGION=256K,MSGLEVEL=(1,1)
//NEWFILE DD DISP=(NEW,CATLG),DSN=MY.NEW.FILE,
// UNIT=3330,VOL=SER=WORK01,
// SPACE=(CYL,(10,10,10)),DCB=SYS1.PARMLIB
//
From the NEWFILE DD statement it is clearly seen that this job tries to
make a new file. Unfortunately, it will fail with a JCL error!!! Can you see
the error in the JCL statement?
It is not really obvious, but the error is in the EXEC statement! Which
EXEC statement? Well, THAT exec statement, the one that has not been
coded. The JCL error message is
JOB HAS NO STEPS
And here is where IEFBR14 comes in: A program that just doesn't do
anything - but keeps the MVT JCL parser happy:
//MYJOB JOB CLASS=A,MSGCLASS=A,REGION=256K,MSGLEVEL=(1,1)
//ALLOC EXEC PGM=IEFBR14
//NEWFILE DD DISP=(NEW,CATLG),DSN=MY.NEW.FILE,
// UNIT=3330,VOL=SER=WORK01,
// SPACE=(CYL,(10,10,10)),DCB=SYS1.PARMLIB
//
This is nice, of course, but what if the file to be deleted doesn't exist? Your
job will fail with
JCL ERROR, DATASET NOT FOUND
and none of the subsequent steps will execute. Therefore it might be better
to code sometimes:
//MYJOB JOB CLASS=A,MSGCLASS=A,REGION=256K,MSGLEVEL=(1,1)
//DELETE EXEC PGM=IEFBR14
//GETRID DD DISP=(MOD,DELETE,DELETE),DSN=NOT.NEEDED.ANY.MORE,
// UNIT=SYSDA,SPACE=(TRK,(0))
If the file exists, it will be deleted, and if it does not exist, it will be created
at step beginning and deleted at step end
By the way, do not try to delete a member of a PDS with IEFBR14 - grown
men have been known to cry because of this. What would the following JCL
do:
//DONTRUN JOB (REALLY,DONT),'RUN THIS!!',CLASS=Z,MSGCLASS=A
//ALLOC EXEC PGM=IEFBR14
//GETRID DD
DISP=(OLD,DELETE,DELETE),DSN=VERY.IMPORTNT.FILE(OBSOLETE)
IEBGENER
IEBGENER is basically a copy program that copies sequential file to
another sequential file. It can also be used to read a sequential file and place
parts of it into different members of a partitioned dataset.
Required DD statements
SYSUT1
SYSUT2
SYSIN
SYSPRINT
IEBCOPY
IEBCOPY is a utility program used to copy partitioned datasets (aka
libraries)
Required DD statements
SYSUT1
SYSUT2
SYSIN
SYSPRINT
The first step deletes a preexisting SYS2.LINKLIB. In the second step all
the members of SYS1.LINKLIB will we copied to a newly created
SYS2.LINKLIB. Finito. Simple.
Now, sometimes you might want to use more than one pair of datasets for
copying. You could achieve this with multiple IEBCOPY steps, of course.
But a more elegant way can be chosen:
//MYJOB JOB CLASS=A,MSGCLASS=A,REGION=256K,MSGLEVEL=(1,1)
//BACKUP EXEC PGM=IEBCOPY
//SYSPRINT DD SYSOUT=A
//SOURCE DD DISP=SHR,DSN=SYS1.LINKLIB
//TARGET DD DISP=SHR,DSN=SYS2.LINKLIB
//PARMLIB DD DISP=SHR,DSN=SYS1.PARMLIB
//PARMSAVE DD DISP=SHR,DSN=SYS2.PARMLIB
//SYSIN DD *
COPY INDD=SOURCE,OUTDD=TARGET
C I=PARMLIB,O=PARMSAVE
What has changed? We added Utility Control Statements. The first one tells
IEBCOPY to copy from INput DDname SOURCE to the OUTput DDname
TARGET, i.e. we tell IEBCOPY to use different DDnames than the default
ones, SYSUT1 and SYSUT2. The second control statement looks a bit more
crypric, but actually, it isn't. Commands and keywords can be abbreviated to
one character codes. The second command therefore tells IEBCOPY to copy
all members from SYS1.PARMLIB to SYS2.PARMLIB.
We can also copy several datasets into one target file. There are two
possibilities, one using concatenation (see JCL in the N.U.D.E.). The other
one by using a list of DDames
//MYJOB JOB CLASS=A,MSGCLASS=A,REGION=256K,MSGLEVEL=(1,1)
//BACKUP EXEC PGM=IEBCOPY
//SYSPRINT DD SYSOUT=A
//PROCLIB DD DISP=SHR,DSN=SYS1.PROCLIB
//PARMLIB DD DISP=SHR,DSN=SYS2.PARMLIB
//PARMPROC DD DISP=SHR,DSN=SYS1.PARMPROC
//SYSIN DD *
COPY INDD=(PROCLIB,PARMLIB),OUTDD=PARMPROC
Very good. So far you know how to copy complete libraries. Obviously, you
would also want to jsu copy a few member, or only one. Don't even think
about wildcards, they do not exist!! The correct way to copy just a few
members is
//MYJOB JOB CLASS=A,MSGCLASS=A,REGION=256K,MSGLEVEL=(1,1)
//BACKUP EXEC PGM=IEBCOPY
//SYSPRINT DD SYSOUT=A
//PROCLIB DD DISP=SHR,DSN=SYS1.PROCLIB
//PARMPROC DD DISP=SHR,DSN=SYS1.PARMPROC
//SYSIN DD *
COPY INDD=PROCLIB,OUTDD=PARMPROC
SELECT MEMBER=(ONEMEMBR)
S M=(MEMBERA,MEMBERB,MEMBERC)
with other words, you add another utility control statement where you tell
IEBCOPY which members you want selected. Keywords can be abbreviated
again. Also, you can copy a full library except for selected members. Look
at the next example:
//MYJOB JOB CLASS=A,MSGCLASS=A,REGION=256K,MSGLEVEL=(1,1)
//BACKUP EXEC PGM=IEBCOPY
//SYSPRINT DD SYSOUT=A
//PROCLIB DD DISP=SHR,DSN=SYS1.PROCLIB
//PARMPROC DD DISP=SHR,DSN=SYS1.PARMPROC
//SYSIN DD *
C I=PROCLIB,O=PARMPROC
EXCLUDE MEMBER=(ONEMEMBR)
Again, existing members in the target dataset will not be overwritten. If you
really want to do this, code
//MYJOB JOB CLASS=A,MSGCLASS=A,REGION=256K,MSGLEVEL=(1,1)
//BACKUP EXEC PGM=IEBCOPY
//SYSPRINT DD SYSOUT=A
//PROCLIB DD DISP=SHR,DSN=SYS1.PROCLIB
//PARMPROC DD DISP=SHR,DSN=SYS1.PARMPROC
//SYSIN DD *
C I=PROCLIB,O=PARMPROC
SELECT MEMBER=((MEMBERA,,R))
Note the double brackets again. This command will take MEMBERA from
SYS1.PROCLIB and will copy it to SYS1.PARMPROC, and will overwrite
any existing MEMBERA in the process. You might wonder what the pair of
brackets commas is all about...they indicate that a parameter has been
omitted. The omitted parameter specifies the new name of a member in the
target dataset:
//MYJOB JOB CLASS=A,MSGCLASS=A,REGION=256K,MSGLEVEL=(1,1)
//BACKUP EXEC PGM=IEBCOPY
//SYSPRINT DD SYSOUT=A
//PROCLIB DD DISP=SHR,DSN=SYS1.PROCLIB
//PARMPROC DD DISP=SHR,DSN=SYS1.PARMPROC
//SYSIN DD *
C I=PROCLIB,O=PARMPROC
SELECT MEMBER=((MEMBERA,MEMBERB,R))
This will take MEMBERA, and will store it as MEMBERB in the target
dataset, overwriting an existing MEMBERB.
Compress
Every so often (and more often than you like) a PDS fills up with garbage.
Actually, every time you change or overwrite an existing member, this
member is still part of the dataset, even if it cannot easily be accessed. When
your datset fills up this way, a COMPRESS is required for garbage
collection. This is done using IEBCOPY again. A compress (=garbage
collection) is performed if and only if the input and the output dataset of
IEBCOPY are identical:
//MYJOB JOB CLASS=A,MSGCLASS=A,REGION=256K,MSGLEVEL=(1,1)
//BACKUP EXEC PGM=IEBCOPY
//SYSPRINT DD SYSOUT=A
//PROCLIB DD DISP=SHR,DSN=SYS1.PROCLIB
//SYSIN DD *
COPY INDD=PROCLIB,OUTDD=PROCLIB
IEHLIST
provided by Kevin Shelly
Required DD statements
anyname
SYSIN
SYSPRINT
This will print a list of the datasets on that volume along with some of their
attributes. There are two choices for the type of report generated. The
FORMAT option is formatted for easy reading. The DUMP format shows
each record of the VTOC in a dump-like format.
To list the contents of the catalog on a particular volume, you can code:
//MYJOB JOB CLASS=A,MSGCLASS=A,REGION=256K,MSGLEVEL=(1,1)
//LISTCTLG EXEC PGM=IEHLIST
//SYSPRINT DD SYSOUT=A
//VOLDD DD UNIT=SYSDA,VOL=SER=IPL001,DISP=OLD
//SYSIN DD *
LISTCTLG VOL=3330=IPL001
/*
//
Like the LISTVTOC control card, the LISTPDS control card accepts either
a FORMAT option or a DUMP option. The FORMAT option is for PDS
members created by the linkage editor (load modules).
instead.
IEHDASDR
Sorry, didn't het around to writing this chapter yet. If you have a write-up
on IEHDASDR, why don't you send it to me?