From 27e6a28ece206e74212d4f688291a48f5829c493 Mon Sep 17 00:00:00 2001 From: "Lionel B. Dyck" <42328411+lbdyck@users.noreply.github.com> Date: Fri, 9 Oct 2020 06:00:09 -0500 Subject: [PATCH 1/3] Create .gitattributes --- .gitattributes | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..6d2e61c --- /dev/null +++ b/.gitattributes @@ -0,0 +1,4 @@ +# This .gitattributes file is autogenerated with ZIGI v3r02 +* git-encoding=iso8859-1 zos-working-tree-encoding=ibm-1047 +.gitattributes git-encoding=iso8859-1 zos-working-tree-encoding=iso8859-1 +.gitignore git-encoding=IBM-1047 zos-working-tree-encoding=IBM-1047 From 4f2265630ad80423a4397445dfbe11a298c48047 Mon Sep 17 00:00:00 2001 From: "Lionel B. Dyck" <42328411+lbdyck@users.noreply.github.com> Date: Fri, 9 Oct 2020 06:00:59 -0500 Subject: [PATCH 2/3] Create dsn --- .zigi/dsn | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .zigi/dsn diff --git a/.zigi/dsn b/.zigi/dsn new file mode 100644 index 0000000..3a386f6 --- /dev/null +++ b/.zigi/dsn @@ -0,0 +1,23 @@ +# ZIGI dsn-file +# This file needs to be here. +# Don't edit unless you know what you're doing :) +# +# record format is (case insensitive): +# +# Position - description +# +# 1 - directory name which will be prefixed by the +# defined HLQ to create the z/OS dataset +# (* defines the default) +# 2 - PS or PO (dataset organization) +# PS for a flat file +# PO for a directory and thus a partitioned dataset +# 3 - record format (FB or VB) +# 4 - lrecl +# 5 - blksize +# 0 is allowed if system determined blksize is enabled +# 6 - extension (optional - if used then no period) +# file extension to be used for PDS members in USS +# +# Default DSORG and DCB info +* PO FB 80 32720 From 561c615ddafeaa8c2cfefb83dcf78cdd32d6739c Mon Sep 17 00:00:00 2001 From: "Lionel.Dyck" Date: Fri, 9 Oct 2020 06:42:37 -0500 Subject: [PATCH 3/3] Convert repository to ZIGI format --------------------------------- Converted the repository to ZIGI format: 1. created partitioned datasets for ASM, C, and EXEC 2. moved appropriate elements into (2) 3. added ZIGI standalone repository OMVS to z/OS utilities 4. renamed README.MD to README.md so it isn't copied to z/OS 5. renamed LICENSE to License so it isn't copied to z/OS --- .zigi/ACCESS | 0 .zigi/APFCHECK | 0 .zigi/ASM | 2 + .zigi/C | 1 + .zigi/ENUM | 0 .zigi/EXEC | 6 + .zigi/LICENSE | 0 .zigi/PSSF | 0 .zigi/README.MD | 0 .zigi/SEARCHRX.REXX | 0 .zigi/SYS0WN | 0 .zigi/dsn | 3 + ACCESS => ASM/ACCESS | 0 APFCHECK => ASM/APFCHECK | 0 checkp.c => C/CHECKUP | 30 +- catmap => EXEC/CATMAP | 0 ENUM => EXEC/ENUM | 318 +++---- PSSF => EXEC/PSSF | 2 +- SEARCHRX.REXX => EXEC/SEARCHRX | 0 startmap => EXEC/STARTMAP | 60 +- EXEC/SYS0WN | 171 ++++ LICENSE => License | 0 README.MD => README.md | 54 +- SYS0WN | 161 ---- zginstall.readme | 22 + zginstall.rex | 1421 ++++++++++++++++++++++++++++++++ 26 files changed, 1858 insertions(+), 393 deletions(-) create mode 100644 .zigi/ACCESS create mode 100644 .zigi/APFCHECK create mode 100644 .zigi/ASM create mode 100644 .zigi/C create mode 100644 .zigi/ENUM create mode 100644 .zigi/EXEC create mode 100644 .zigi/LICENSE create mode 100644 .zigi/PSSF create mode 100644 .zigi/README.MD create mode 100644 .zigi/SEARCHRX.REXX create mode 100644 .zigi/SYS0WN rename ACCESS => ASM/ACCESS (100%) rename APFCHECK => ASM/APFCHECK (100%) rename checkp.c => C/CHECKUP (92%) rename catmap => EXEC/CATMAP (100%) rename ENUM => EXEC/ENUM (88%) rename PSSF => EXEC/PSSF (99%) rename SEARCHRX.REXX => EXEC/SEARCHRX (100%) rename startmap => EXEC/STARTMAP (94%) create mode 100644 EXEC/SYS0WN rename LICENSE => License (100%) rename README.MD => README.md (81%) delete mode 100644 SYS0WN create mode 100644 zginstall.readme create mode 100755 zginstall.rex diff --git a/.zigi/ACCESS b/.zigi/ACCESS new file mode 100644 index 0000000..e69de29 diff --git a/.zigi/APFCHECK b/.zigi/APFCHECK new file mode 100644 index 0000000..e69de29 diff --git a/.zigi/ASM b/.zigi/ASM new file mode 100644 index 0000000..13d141d --- /dev/null +++ b/.zigi/ASM @@ -0,0 +1,2 @@ +ACCESS 20/10/09 20/10/09 1 0 06:14:14 97 97 0 ENUM +APFCHECK 20/10/09 20/10/09 1 0 06:14:14 218 218 0 ENUM diff --git a/.zigi/C b/.zigi/C new file mode 100644 index 0000000..cec6c1d --- /dev/null +++ b/.zigi/C @@ -0,0 +1 @@ +CHECKUP 20/10/09 20/10/09 1 0 06:14:16 96 96 0 ENUM diff --git a/.zigi/ENUM b/.zigi/ENUM new file mode 100644 index 0000000..e69de29 diff --git a/.zigi/EXEC b/.zigi/EXEC new file mode 100644 index 0000000..784602c --- /dev/null +++ b/.zigi/EXEC @@ -0,0 +1,6 @@ +CATMAP 20/10/09 20/10/09 1 0 06:14:19 498 498 0 ENUM +ENUM 20/10/09 20/10/09 1 0 06:14:19 1053 1053 0 ENUM +PSSF 20/10/09 20/10/09 1 0 06:14:19 1320 1320 0 ENUM +SEARCHRX 20/10/09 20/10/09 1 0 06:14:19 24 24 0 ENUM +STARTMAP 20/10/09 20/10/09 1 0 06:14:19 396 396 0 ENUM +SYS0WN 20/10/09 20/10/09 1 1 06:24:10 171 161 0 ENUM diff --git a/.zigi/LICENSE b/.zigi/LICENSE new file mode 100644 index 0000000..e69de29 diff --git a/.zigi/PSSF b/.zigi/PSSF new file mode 100644 index 0000000..e69de29 diff --git a/.zigi/README.MD b/.zigi/README.MD new file mode 100644 index 0000000..e69de29 diff --git a/.zigi/SEARCHRX.REXX b/.zigi/SEARCHRX.REXX new file mode 100644 index 0000000..e69de29 diff --git a/.zigi/SYS0WN b/.zigi/SYS0WN new file mode 100644 index 0000000..e69de29 diff --git a/.zigi/dsn b/.zigi/dsn index 3a386f6..37dac48 100644 --- a/.zigi/dsn +++ b/.zigi/dsn @@ -21,3 +21,6 @@ # # Default DSORG and DCB info * PO FB 80 32720 +ASM PO FB 80 32720 +C PO VB 255 32720 +EXEC PO FB 80 27920 diff --git a/ACCESS b/ASM/ACCESS similarity index 100% rename from ACCESS rename to ASM/ACCESS diff --git a/APFCHECK b/ASM/APFCHECK similarity index 100% rename from APFCHECK rename to ASM/APFCHECK diff --git a/checkp.c b/C/CHECKUP similarity index 92% rename from checkp.c rename to C/CHECKUP index 780f077..372350e 100644 --- a/checkp.c +++ b/C/CHECKUP @@ -3,25 +3,25 @@ To use in TSO (after compile in Unix): /bin/tsocmd "ALLOCATE DATASET(PDSE) NEW VOLUME(DEV) SPACE(10,10) BLOCK(200) BLKSIZE(6144) RECFM(U) LRECL(0) DSNTYPE(LIBRARY) DSORG(PO)" cp -X ./checkp "//'.PDSE(CHECKP)'" - + in TSO: call '.PDSE(CHECKP)' '/-a' - + License GPL Copyright Soldier of FORTRAN - + Purpose: If you don't have access to netstat this will print a list of potential open ports or checks on a single port. The output is comma sperated to be copied to Nmap. - + */ - + #include #include #include #include #include - + int checkp(int); int checkp(int port) { @@ -29,7 +29,7 @@ int checkp(int port) struct sockaddr_in server; /* server address information */ int s; /* socket for accepting connections */ int result = 0; /* 1 open 0 closed */ - if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) + if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf("[!] ERROR Cannot open a socket! Are you sure you have permission?"); exit(2); @@ -40,18 +40,18 @@ int checkp(int port) if (bind(s, (struct sockaddr *)&server, sizeof(server)) < 0) { result = 1; - } + } close(s); return result; } - + main(argc, argv) int argc; char **argv; { unsigned short port; /* port server binds to */ int results; /* We got em */ - int i; /* for loop */ + int i; /* for loop */ char* logo = "\n" " _______ __ __ _______ \n" "| _ | |--.-----.----| |--. | _ |\n" @@ -60,16 +60,16 @@ char **argv; "|: 1 | |: | \n" "|::.. . | |::.| \n" "`-------' `---' \n\n"; - printf("%s", logo); - + printf("%s", logo); + if (argc != 2) { fprintf(stderr, "Usage:\n Check one port: %s \n Check all ports: %s -a\n\n", argv[0], argv[0]); exit(1); } - + /* First check the arguments */ - + if (0 == strcmp(argv[1], "-a")) { printf("*** You're in the butter zone now baby!\n"); printf("*** Checking ports 1 through 65535\n"); @@ -90,7 +90,7 @@ char **argv; printf("*** %d is not in use\n", port); } } - + printf("*** Done\n\n"); exit(0); } diff --git a/catmap b/EXEC/CATMAP similarity index 100% rename from catmap rename to EXEC/CATMAP diff --git a/ENUM b/EXEC/ENUM similarity index 88% rename from ENUM rename to EXEC/ENUM index 9dac341..a084a09 100644 --- a/ENUM +++ b/EXEC/ENUM @@ -54,7 +54,7 @@ |* USS/OMVS user details list by Davide Girardi (@nogonosa) *| |* *| \*--------------------------------------------------------------------*/ - + PARSE SOURCE s1 s2 prg s3 name s4 s5 space . @@ -119,10 +119,10 @@ SELECT say '' x = SVC() say '-----------------------------------------' - say '' + say '' x = TSTA() say '-----------------------------------------' - say '' + say '' call USSU say '-----------------------------------------' say '' @@ -140,7 +140,7 @@ say " _qQ$Qp_ . . WHO, TSTA" say " . $$$$$$$ . : .: ." say " I$$$$$$$$$$L `?jlj7' j$l$l$$il$$I" say " :$$$$$$$$$i$b. .d$$$$$$$$$$$:" -say " ?$$$$$I$$%'~ ` ~*$$$$$$$$$7" +say " ?$$$$$I$$%'~ ` ~*$$$$$$$$$7" say " ?$$$$\'~ `. ~#$$$$$7" say " `7'~ `. ` ~#7'" say " `. ." @@ -167,7 +167,7 @@ say "---z-o-s---e-n-u-m-e-r-a-t-i-o-n-------------------------------------" exit 8 END END - + return 0 @@ -183,10 +183,10 @@ return 0 USERS: numeric digits 10 -cvt=ptr(16) /* Get CVT */ -asvt=ptr(cvt+556)+512 /* Get asvt */ +cvt=ptr(16) /* Get CVT */ +asvt=ptr(cvt+556)+512 /* Get asvt */ -tso_users.0 = 0 +tso_users.0 = 0 tasks.0 = 0 tasks_users.0 = 0 omvs.0 = 0 @@ -195,58 +195,58 @@ jobs.0 = 0 jobs_users.0 = 0 system.0 = 0 -asvtmaxu=ptr(asvt+4) /* Get max asvt entries */ -Do a = 0 to asvtmaxu - 1 - ascb=stg(asvt+16+a*4,4) /* Get ptr to ascb (Skip master) */ - - If bitand(ascb,'80000000'x) = '00000000'x Then /* If in use */ - Do - ascb=c2d(ascb) /* Get ascb address */ - cscb=ptr(ascb+56) /* Get CSCB address */ - chtrkid=stg(cscb+28,1) /* Check addr space type */ - ascbjbni=ptr(ascb+172) /* Get ascbjbni */ - ascbjbns=ptr(ascb+176) /* Get ascbjbns */ +asvtmaxu=ptr(asvt+4) /* Get max asvt entries */ +Do a = 0 to asvtmaxu - 1 + ascb=stg(asvt+16+a*4,4) /* Get ptr to ascb (Skip master) */ + + If bitand(ascb,'80000000'x) = '00000000'x Then /* If in use */ + Do + ascb=c2d(ascb) /* Get ascb address */ + cscb=ptr(ascb+56) /* Get CSCB address */ + chtrkid=stg(cscb+28,1) /* Check addr space type */ + ascbjbni=ptr(ascb+172) /* Get ascbjbni */ + ascbjbns=ptr(ascb+176) /* Get ascbjbns */ asxb = ptr(ascb+108) - - acee = ptr(asxb+200) - + + acee = ptr(asxb+200) + ftcb = ptr(asxb+4) ltcb = ptr(asxb+8) - + ascboucb = ptr(ascb+144,4) oucbsubn = stg(ascboucb+176,4) oucbtrxn = stg(ascboucb+200,8) /* transaction name */ oucbusrd = stg(ascboucb+208,8) /* userid */ - + If ascbjbns<>0 & chtrkid = '02'x Then /* started task */ - Do + Do assb = ptr(ascb+336) jsab = ptr(assb+168) if jsab = 0 then usid = "" else usid = stg(jsab+44,8) - + tmp = tasks.0 + 1 tasks.tmp = stg(ascbjbns,8) tasks_users.tmp = usid - tasks.0 = tmp - - + tasks.0 = tmp + + End If ascbjbns<>0 & chtrkid = '01'x Then /* TSO user */ - Do + Do tmp = tso_users.0 + 1 tso_users.tmp = stg(ascbjbns,8) tso_users.0 = tmp - + End If ascbjbns<>0 & chtrkid = '04'x Then /* System */ - Do + Do tmp = system.0 + 1 system.tmp = stg(ascbjbns,8) system.0 = tmp - + End If strip(oucbsubn) = 'OMVS' Then /* OMVS user */ Do @@ -254,38 +254,38 @@ Do a = 0 to asvtmaxu - 1 omvs.tmp = oucbtrxn omvs_users.tmp = oucbusrd omvs.0 = tmp - End + End If ascbjbni<>0 & chtrkid = '03'x Then /* JOBS */ - Do + Do If strip(oucbsubn) = 'OMVS' Then iterate assb = ptr(ascb+336) jsab = ptr(assb+168) usid = stg(jsab+44,8) - + if jsab = 0 then usid = "" else usid = stg(jsab+44,8) - + tmp = jobs.0 + 1 jobs.tmp = stg(ascbjbni,8) jobs_users.tmp = usid jobs.0 = tmp - - + + End - End + End End say "**** Started Task - Owner *****" DO i = 1 to tasks.0 - say tasks.i " - " tasks_users.i -END + say tasks.i " - " tasks_users.i +END say "" say "**** TSO Users - Owner ****" DO i = 1 to tso_users.0 - say tso_users.i " - " tso_users.i + say tso_users.i " - " tso_users.i END say "" @@ -297,10 +297,10 @@ END say "" say "**** Jobs - Owner ****" DO i = 1 to jobs.0 - say jobs.i " - " jobs_users.i + say jobs.i " - " jobs_users.i END -return 0 +return 0 SECURITY: say 'External Security Manager:' @@ -309,11 +309,11 @@ say 'External Security Manager:' numeric digits 20 CVT = C2D(STORAGE(10,4)) /* CVT Pointer */ CVTRAC = C2D(STORAGE(D2X(CVT + 992),4)) -ID = STORAGE(D2X(CVTRAC),4) +ID = STORAGE(D2X(CVTRAC),4) If ID = 'RCVT' THEN DO /* RACF */ - RACFVRM = Storage(D2x(CVTRAC + 616),4) + RACFVRM = Storage(D2x(CVTRAC + 616),4) RCVTDSDT = C2d(Storage(D2x(CVTRAC + 224),4)) - DSDTNUM = C2d(Storage(D2x(RCVTDSDT+4),4)) + DSDTNUM = C2d(Storage(D2x(RCVTDSDT+4),4)) DSDTPRIM = STRIP(Storage(D2x(RCVTDSDT+177),44),'T') DSDTBACK = STRIP(Storage(D2x(RCVTDSDT+353),44),'T') SAY 'Product: RACF' @@ -327,10 +327,10 @@ If ID = 'RCVT' THEN DO /* RACF */ OFFSET = 0 DB = '' DO i = 1 TO DSDTNUM - DSDTPRIM = STRIP(Storage(D2x(RCVTDSDT+177+OFFSET),44),'T') + DSDTPRIM = STRIP(Storage(D2x(RCVTDSDT+177+OFFSET),44),'T') DSDTBACK = STRIP(Storage(D2x(RCVTDSDT+353+OFFSET),44),'T') OFFSET = OFFSET + 352 - SAY ' ('i') Primary:' DSDTPRIM + SAY ' ('i') Primary:' DSDTPRIM SAY ' ('i') Backup: ' DSDTBACK END END @@ -347,29 +347,29 @@ ELSE DO /* ACF2 */ /* All credit to Mark */ CVTJESCT = C2D(STORAGE(D2X(CVT + 296),4)) SSCVT = C2D(STORAGE(D2X(CVTJESCT + 24),4)) - Do while SSCVT <> 0 - SSCTSNAM = Storage(D2x(SSCVT+8),4) /* subsystem name */ - If SSCTSNAM = 'ACF2' then do - ACCVT = C2d(Storage(D2x(SSCVT + 20),4)) /* ACF2 CVT */ - ACCPFXP = C2d(Storage(D2x(ACCVT - 4),4)) /* ACCVT prefix */ - ACCPIDL = C2d(Storage(D2x(ACCPFXP + 8),2)) /* Len ident area */ - LEN_ID = ACCPIDL-4 /* don't count ACCPIDL and ACCPIDO in len */ - ACCPIDS = Strip(Storage(D2x(ACCPFXP + 12),LEN_ID)) /*sys ident*/ - ACF2DSNS = C2d(Storage(D2x(ACCVT + 252) ,4)) /* ACF2 DSNs */ - ACF2DNUM = C2d(Storage(D2x(ACF2DSNS + 16),2)) /* # OF DSNs */ - Leave - End - SSCVT = C2d(Storage(D2x(SSCVT+4),4)) /* next sscvt or zero */ + Do while SSCVT <> 0 + SSCTSNAM = Storage(D2x(SSCVT+8),4) /* subsystem name */ + If SSCTSNAM = 'ACF2' then do + ACCVT = C2d(Storage(D2x(SSCVT + 20),4)) /* ACF2 CVT */ + ACCPFXP = C2d(Storage(D2x(ACCVT - 4),4)) /* ACCVT prefix */ + ACCPIDL = C2d(Storage(D2x(ACCPFXP + 8),2)) /* Len ident area */ + LEN_ID = ACCPIDL-4 /* don't count ACCPIDL and ACCPIDO in len */ + ACCPIDS = Strip(Storage(D2x(ACCPFXP + 12),LEN_ID)) /*sys ident*/ + ACF2DSNS = C2d(Storage(D2x(ACCVT + 252) ,4)) /* ACF2 DSNs */ + ACF2DNUM = C2d(Storage(D2x(ACF2DSNS + 16),2)) /* # OF DSNs */ + Leave + End + SSCVT = C2d(Storage(D2x(SSCVT+4),4)) /* next sscvt or zero */ End SAY 'Product: ACF2' SAY 'Version:' ACCPIDS SAY 'Dataset(s):' - Do ADSNS = 1 to ACF2DNUM - ADSOFF = ACF2DSNS + 24 + (ADSNS-1)*64 - ACF2TYPE = Storage(D2x(ADSOFF) , 8) - ACF2DSN = Storage(D2x(ADSOFF + 16),44) - SAY ' ' ACF2TYPE '-' ACF2DSN - End + Do ADSNS = 1 to ACF2DNUM + ADSOFF = ACF2DSNS + 24 + (ADSNS-1)*64 + ACF2TYPE = Storage(D2x(ADSOFF) , 8) + ACF2DSN = Storage(D2x(ADSOFF + 16),44) + SAY ' ' ACF2TYPE '-' ACF2DSN + End END return 0 @@ -392,13 +392,13 @@ RETCODE = 0 numeric digits 20 /* need this for D2X/C2D */ CVT = C2D(STORAGE(10,4)) /* CVT Pointer */ CVTAUTHL = C2D(STORAGE(D2X(CVT + 484),4)) -IF CVTAUTHL = C2D('7FFFF001'x) THEN DO +IF CVTAUTHL = C2D('7FFFF001'x) THEN DO /* The APF Table is Dynamic, not Static */ CVTECVT = C2D(STORAGE(D2X(CVT + 140),4)) ECVTCSVT = C2D(STORAGE(D2X(CVTECVT + 228),4)) APF_PTR = c2d(storage(d2x(ECVTCSVT+12),4)) - CUR = c2d(storage(d2x(APF_PTR+8),4)) - LAST = c2d(storage(d2x(APF_PTR+12),4)) + CUR = c2d(storage(d2x(APF_PTR+8),4)) + LAST = c2d(storage(d2x(APF_PTR+12),4)) DO FOREVER DATASET = storage(d2x(CUR+24),44) MISSING = ' Yes ' @@ -427,21 +427,21 @@ IF CVTAUTHL = C2D('7FFFF001'x) THEN DO com.ibm.zos.v2r1.ikja300/ldsi.htm#ldsi__ldrs */ END /* Here we list the found items */ - SAY strip(VOLUME) "|" MISSING "|" STRIP(DATASET) + SAY strip(VOLUME) "|" MISSING "|" STRIP(DATASET) END IF CUR = LAST THEN LEAVE ELSE CUR = C2D(STORAGE(D2X(CUR+8),4)) END /* Do */ END /* End of Dynamic */ ELSE DO /* It's Static instead */ - NUMAPF = C2D(STORAGE(D2X(CVTAUTHL),2)) - LEN = C2D(STORAGE(D2X(CVTAUTHL+2),1)) - CUR = CVTAUTHL + 3 - DO I = 1 TO NUMAPF - VOLUME = STORAGE(D2X(CUR),6) + NUMAPF = C2D(STORAGE(D2X(CVTAUTHL),2)) + LEN = C2D(STORAGE(D2X(CVTAUTHL+2),1)) + CUR = CVTAUTHL + 3 + DO I = 1 TO NUMAPF + VOLUME = STORAGE(D2X(CUR),6) DATASET = STORAGE(D2X(CUR + 7),LEN) - CUR = CUR + LEN + 1 - LEN = C2D(STORAGE(D2X(CUR-1),1)) + CUR = CUR + LEN + 1 + LEN = C2D(STORAGE(D2X(CUR-1),1)) SAY STRIP(VOLUME) "|" STRIP(DATASET) END END @@ -460,24 +460,24 @@ CVTVERID = STORAGE(D2X(CVT - 24),16) ECVT = C2d(Storage(D2x(CVT + 140),4)) /* OS */ PRODNAME = Storage(D2x(CVT - 40),7) -PRODNAM2 = Storage(D2x(ECVT+496),16) /* point to product name*/ -PRODNAM2 = Strip(PRODNAM2,'T') /* del trailing blanks */ -VER = Storage(D2x(ECVT+512),2) /* point to version */ -REL = Storage(D2x(ECVT+514),2) /* point to release */ -MOD = Storage(D2x(ECVT+516),2) /* point to mod level */ -VRM = VER'.'REL'.'MOD -FMIDNUM = Storage(D2x(CVT - 32),7) /* point to fmid */ -SAY 'The OS version is 'PRODNAM2 VRM' - FMID' , - FMIDNUM' ('PRODNAME').' +PRODNAM2 = Storage(D2x(ECVT+496),16) /* point to product name*/ +PRODNAM2 = Strip(PRODNAM2,'T') /* del trailing blanks */ +VER = Storage(D2x(ECVT+512),2) /* point to version */ +REL = Storage(D2x(ECVT+514),2) /* point to release */ +MOD = Storage(D2x(ECVT+516),2) /* point to mod level */ +VRM = VER'.'REL'.'MOD +FMIDNUM = Storage(D2x(CVT - 32),7) /* point to fmid */ +SAY 'The OS version is 'PRODNAM2 VRM' - FMID' , + FMIDNUM' ('PRODNAME').' -/* Job Entry */ +/* Job Entry */ JESSSCT = C2D(STORAGE(D2X(CVTJESCT + 24),4)) JESPJESN = STORAGE(D2X(CVTJESCT + 28),4) SSCTSNAM = STORAGE(D2X(JESSSCT + 8),4) DO UNTIL JESSSCT = 0 IF JESPJESN = SSCTSNAM THEN DO - SSCTSSVT = C2D(Storage(D2X(JESSSCT+16),4)) - SSCTSUSE = C2D(Storage(D2X(JESSSCT+20),4)) + SSCTSSVT = C2D(Storage(D2X(JESSSCT+16),4)) + SSCTSUSE = C2D(Storage(D2X(JESSSCT+20),4)) SSCTSUS2 = C2D(Storage(D2X(JESSSCT+28),4)) LEAVE END @@ -485,12 +485,12 @@ DO UNTIL JESSSCT = 0 END IF JESPJESN = 'JES3' THEN DO - JESVERS = SYSVAR('SYSJES') + JESVERS = SYSVAR('SYSJES') JESNODE = SYSVAR('SYSNODE') END ELSE IF JESPJESN = 'JES2' THEN DO JESVERS = Strip(Storage(D2x(SSCTSUSE),8)) - Select + Select When Substr(JESVERS,1,8) == 'z/OS 2.2' then , /* z/OS 2.2 */ JESNODE = Strip(Storage(D2x(SSCTSUS2+664),8)) /* JES2 NODE */ When Substr(JESVERS,1,8) == 'z/OS 2.1' | , /* z/OS 2.1 */ @@ -518,69 +518,69 @@ ELSE IF JESPJESN = 'JES2' THEN DO Substr(JESVERS,1,5) == 'OS 2.' then, /* through OS/390 2.9 */ JESNODE = Strip(Storage(D2x(SSCTSUS2+372),8)) /* JES2 NODE */ Otherwise , /* Lower than ESA V5 */ - If ENV = 'OMVS' then JESNODE = '*not_avail*' + If ENV = 'OMVS' then JESNODE = '*not_avail*' else JESNODE = SYSVAR('SYSNODE') /* TSO/E VAR for JESNODE*/ - End /* select */ + End /* select */ END /* DF */ /* From IPLINFO */ -CVTDFA = C2d(Storage(D2x(CVT + 1216),4)) +CVTDFA = C2d(Storage(D2x(CVT + 1216),4)) DFAPROD = C2d(Storage(D2x(CVTDFA +16),1)) -If DFAPROD = 0 then do /* DFP not DF/SMS */ - DFAREL = C2x(Storage(D2x(CVTDFA+2),2)) /* point to DFP release */ - DFPVER = Substr(DFAREL,1,1) /* DFP Version */ - DFPREL = Substr(DFAREL,2,1) /* DFP Release */ - DFPMOD = Substr(DFAREL,3,1) /* DFP Mod Lvl */ - DFPRD = 'DFP' /* product is DFP */ - DFLEV = DFPVER || '.' || DFPREL || '.' || DFPMOD -End -Else do /* DFSMS not DFP */ - DFARELS = C2x(Storage(D2x(CVTDFA+16),4)) /* point to DF/SMS rel */ - DFAVER = X2d(Substr(DFARELS,3,2)) /* DF/SMS Version */ - DFAREL = X2d(Substr(DFARELS,5,2)) /* DF/SMS Release */ - DFAMOD = X2d(Substr(DFARELS,7,2)) /* DF/SMS Mod Lvl */ - DFPRD = 'DFSMS' /* product is DF/SMS */ - DFLEV = DFAVER || '.' || DFAREL || '.' || DFAMOD - If DFAPROD = 2 then DFLEV = 'OS/390' DFLEV - If DFAPROD = 3 then do - DFLEV = 'z/OS' DFLEV - /* Next section of code doesn't work because CRT is in key 5 */ - /* - CVTCBSP = C2d(Storage(D2x(CVT + 256),4)) /* point to AMCBS */ - CRT = C2d(Storage(D2x(CVTCBSP + 124),4)) /* point to CRT */ - CRTFMID = Storage(D2x(CRT + 472),7) /* DFSMS FMID */ - */ - End /* if DFAPROD = 3 */ -End +If DFAPROD = 0 then do /* DFP not DF/SMS */ + DFAREL = C2x(Storage(D2x(CVTDFA+2),2)) /* point to DFP release */ + DFPVER = Substr(DFAREL,1,1) /* DFP Version */ + DFPREL = Substr(DFAREL,2,1) /* DFP Release */ + DFPMOD = Substr(DFAREL,3,1) /* DFP Mod Lvl */ + DFPRD = 'DFP' /* product is DFP */ + DFLEV = DFPVER || '.' || DFPREL || '.' || DFPMOD +End +Else do /* DFSMS not DFP */ + DFARELS = C2x(Storage(D2x(CVTDFA+16),4)) /* point to DF/SMS rel */ + DFAVER = X2d(Substr(DFARELS,3,2)) /* DF/SMS Version */ + DFAREL = X2d(Substr(DFARELS,5,2)) /* DF/SMS Release */ + DFAMOD = X2d(Substr(DFARELS,7,2)) /* DF/SMS Mod Lvl */ + DFPRD = 'DFSMS' /* product is DF/SMS */ + DFLEV = DFAVER || '.' || DFAREL || '.' || DFAMOD + If DFAPROD = 2 then DFLEV = 'OS/390' DFLEV + If DFAPROD = 3 then do + DFLEV = 'z/OS' DFLEV + /* Next section of code doesn't work because CRT is in key 5 */ + /* + CVTCBSP = C2d(Storage(D2x(CVT + 256),4)) /* point to AMCBS */ + CRT = C2d(Storage(D2x(CVTCBSP + 124),4)) /* point to CRT */ + CRTFMID = Storage(D2x(CRT + 472),7) /* DFSMS FMID */ + */ + End /* if DFAPROD = 3 */ +End /* TSO */ -CVTTVT = C2d(Storage(D2x(CVT + 156),4)) /* point to TSO vect tbl*/ -TSVTLVER = Storage(D2x(CVTTVT+100),1) /* point to TSO Version */ -TSVTLREL = Storage(D2x(CVTTVT+101),2) /* point to TSO Release */ -TSVTLREL = Format(TSVTLREL) /* Remove leading 0 */ -TSVTLMOD = Storage(D2x(CVTTVT+103),1) /* point to TSO Mod Lvl */ -TSOLEV = TSVTLVER || '.' || TSVTLREL || '.' || TSVTLMOD +CVTTVT = C2d(Storage(D2x(CVT + 156),4)) /* point to TSO vect tbl*/ +TSVTLVER = Storage(D2x(CVTTVT+100),1) /* point to TSO Version */ +TSVTLREL = Storage(D2x(CVTTVT+101),2) /* point to TSO Release */ +TSVTLREL = Format(TSVTLREL) /* Remove leading 0 */ +TSVTLMOD = Storage(D2x(CVTTVT+103),1) /* point to TSO Mod Lvl */ +TSOLEV = TSVTLVER || '.' || TSVTLREL || '.' || TSVTLMOD /* VTAM */ -CHKVTACT = Storage(D2x(CVTEXT2+64),1) /* VTAM active flag */ -If bitand(CHKVTACT,'80'x) = '80'x then do /* vtam is active */ - CVTATCVT = C2d(Storage(D2x(CVTEXT2 + 65),3)) /* point to VTAM AVT */ - ISTATCVT = C2d(Storage(D2x(CVTATCVT + 0),4)) /* point to VTAM CVT */ - ATCVTLVL = Storage(D2x(ISTATCVT + 0),8) /* VTAM Rel Lvl VOVRP */ - VTAMVER = Substr(ATCVTLVL,3,1) /* VTAM Version V */ - VTAMREL = Substr(ATCVTLVL,4,1) /* VTAM Release R */ - VTAMMOD = Substr(ATCVTLVL,5,1) /* VTAM Mod Lvl P */ - If VTAMMOD = ' ' then VTAMLEV = VTAMVER || '.' || VTAMREL - else VTAMLEV = VTAMVER || '.' || VTAMREL || '.' || VTAMMOD -/* */ - ATCNETID = Strip(Storage(D2x(ISTATCVT + 2080),8)) /* VTAM NETID */ - ATCNQNAM = Strip(Storage(D2x(ISTATCVT + 2412),17)) /* VTAM SSCPNAME*/ - VTAM_ACTIVE = 'YES' -End /* if bitand (vtam is active) */ -Else VTAM_ACTIVE = 'NO' +CHKVTACT = Storage(D2x(CVTEXT2+64),1) /* VTAM active flag */ +If bitand(CHKVTACT,'80'x) = '80'x then do /* vtam is active */ + CVTATCVT = C2d(Storage(D2x(CVTEXT2 + 65),3)) /* point to VTAM AVT */ + ISTATCVT = C2d(Storage(D2x(CVTATCVT + 0),4)) /* point to VTAM CVT */ + ATCVTLVL = Storage(D2x(ISTATCVT + 0),8) /* VTAM Rel Lvl VOVRP */ + VTAMVER = Substr(ATCVTLVL,3,1) /* VTAM Version V */ + VTAMREL = Substr(ATCVTLVL,4,1) /* VTAM Release R */ + VTAMMOD = Substr(ATCVTLVL,5,1) /* VTAM Mod Lvl P */ + If VTAMMOD = ' ' then VTAMLEV = VTAMVER || '.' || VTAMREL + else VTAMLEV = VTAMVER || '.' || VTAMREL || '.' || VTAMMOD +/* */ + ATCNETID = Strip(Storage(D2x(ISTATCVT + 2080),8)) /* VTAM NETID */ + ATCNQNAM = Strip(Storage(D2x(ISTATCVT + 2412),17)) /* VTAM SSCPNAME*/ + VTAM_ACTIVE = 'YES' +End /* if bitand (vtam is active) */ +Else VTAM_ACTIVE = 'NO' SAY 'TSO:' TSOLEV SAY 'JES:' JESPJESN JESVERS 'Node:' JESNODE -IF VTAM_ACTIVE = 'YES' THEN +IF VTAM_ACTIVE = 'YES' THEN SAY 'VTAM:' VTAMLEV '(NETID:' ATCNETID') (SSCPNAME:' ATCNQNAM')' return 0 @@ -589,10 +589,10 @@ SVC: /* and #NUCLKUP */ numeric digits 20 /* need this for D2X/C2D */ -/* from: +/* from: https://groups.google.com/forum/#!topic/ bit.listserv.ibm-main/XmgU5suwx9c -CVT : CVTABEND ---> SCVTSECT : +CVT : CVTABEND ---> SCVTSECT : SCVTSVCT ---> SVC table (mapped by IHASVC) */ say 'Installed SVCs:' @@ -630,7 +630,7 @@ Do i = 0 to 255 ELSE APF = "N" IF BITAND(SVCTYPE,'04'x) = '04'x THEN ESR = 'Y' ELSE ESR = "N" - + SAY C2X(STORAGE(D2X(SCVTSVCT+(i*8)),4)) "|", RIGHT(i,3,0) "|" RIGHT(D2X(i),2,0) "| ", TYPE " | " APF " | " ESR @@ -652,7 +652,7 @@ TCBTIO = C2D(STORAGE(D2X(PSALCCAV + 12), 4)) /* Points to TIOT PAGE 338 */ TIOT = TCBTIO + 24 TIOELNGH = 0 DD = '' -IF lvl < 1 THEN DO +IF lvl < 1 THEN DO say 'Non-Verbose. Only displaying SYSPROC/SYSEXEC' say 'DD | DATASET Name' say '---------|-------------' @@ -675,18 +675,18 @@ DO FOREVER SAY DD "|" DATASET END ELSE - SAY DD "|" VOLUME "|" DATASET + SAY DD "|" VOLUME "|" DATASET END -RETURN 0 +RETURN 0 CAT: /* Master Catalog routing from IPLINFO */ CVT = C2d(Storage(10,4)) ECVT = C2d(Storage(D2x(CVT + 140),4)) -ECVTIPA = C2d(Storage(D2x(ECVT + 392),4)) /* point to IPA */ +ECVTIPA = C2d(Storage(D2x(ECVT + 392),4)) /* point to IPA */ IPASCAT = Storage(D2x(ECVTIPA + 224),63) -MCATDSN = Strip(Substr(IPASCAT,11,44)) /* master catalog dsn */ -MCATVOL = Substr(IPASCAT,1,6) +MCATDSN = Strip(Substr(IPASCAT,11,44)) /* master catalog dsn */ +MCATVOL = Substr(IPASCAT,1,6) say 'Master Catalog:' MCATDSN 'Volume:' MCATVOL return 0 @@ -1022,10 +1022,10 @@ END IF LENGTH(ARG(1)) // 8 /= 0 THEN SAY HEXOUT "|" SUBSTR(ARG(1),j,LENGTH(ARG(1))) RETURN 0 -/*-------------------------------------------------------------------*/ -ptr: Return c2d(storage(d2x(Arg(1)),4)) /* Return a pointer */ -/*-------------------------------------------------------------------*/ -stg: Return storage(d2x(Arg(1)),Arg(2)) /* Return storage */ +/*-------------------------------------------------------------------*/ +ptr: Return c2d(storage(d2x(Arg(1)),4)) /* Return a pointer */ +/*-------------------------------------------------------------------*/ +stg: Return storage(d2x(Arg(1)),Arg(2)) /* Return storage */ USSU: PROCEDURE call syscalls 'ON' diff --git a/PSSF b/EXEC/PSSF similarity index 99% rename from PSSF rename to EXEC/PSSF index 50747fd..fda0152 100644 --- a/PSSF +++ b/EXEC/PSSF @@ -134,7 +134,7 @@ DO FOREVER /* */ /* The status of a port if "filtered" by default */ /* The next code detects the real status of a port */ - + /* Now we check the sockets */ /* READ/WRITE means an open socket */ /* Exception means closed */ diff --git a/SEARCHRX.REXX b/EXEC/SEARCHRX similarity index 100% rename from SEARCHRX.REXX rename to EXEC/SEARCHRX diff --git a/startmap b/EXEC/STARTMAP similarity index 94% rename from startmap rename to EXEC/STARTMAP index 3cffbd4..f1b82cc 100644 --- a/startmap +++ b/EXEC/STARTMAP @@ -28,22 +28,22 @@ IPL_MEMBER = LOAD || Substr(IPLPARM,5,2) DO I = 0 TO 9 IF SYSDSN("'SYS"||I||".IPLPARM("|| IPL_MEMBER ||")'") == "OK" THEN DO IPL_DATASET = "SYS"||I||".IPLPARM" - LEAVE + LEAVE END END IPL_DSN = IPL_DATASET ||"("||IPL_MEMBER||")" SAY " + IPL Dataset:" IPL_DSN SAY " + VOLUME:" IPL_VOLUME /* Step 2 Find SYSPARM, Symbols and concatenation */ -/* The system uses the definitions in all IEASYMxx members for which - suffixes are specified. If the system finds duplicate definitions, the +/* The system uses the definitions in all IEASYMxx members for which + suffixes are specified. If the system finds duplicate definitions, the last definition overrides any previous definitions */ -ADDRESS TSO +ADDRESS TSO "ALLOC F(INFILE) DSN('"||IPL_DSN||"') SHR REU" "EXECIO * DISKR INFILE ( FINIS STEM IPLPARM." "FREE F(INFILE)" PARMNUM = 0 -DO I = 1 TO IPLPARM.0 +DO I = 1 TO IPLPARM.0 IF INDEX(IPLPARM.I,"SYSPARM") >0 THEN DO PARSE VAR IPLPARM.I . PARM . SPARM = strip(PARM) @@ -64,7 +64,7 @@ DO I = 1 TO IPLPARM.0 PARMLIB.PARMNUM = strip(PARM) SAY " + PARMLIB #"||PARMNUM "is" PARMLIB.PARMNUM END -END +END PARMLIB.0 = PARMNUM /* Getting symbols, courtesy of IPLINFO */ SAY "> System Symbols" @@ -82,7 +82,7 @@ Do I = 1 to NUMSYMBS NAMED = substr(SYMNAME, 2, max(0, length(SYMNAME) -2)) interpret NAMED||'="'||VALNAME||'"' SAY " + " NAMED "=" VALNAME -End +End /* Now lets parse out these values. Starting with SYSPARM */ /* We do this because SYM/SYS could look like */ /* this: (00,21,56,L) but we've already removed the () */ @@ -122,7 +122,7 @@ END SAY " + ORDER | EXISTS | DATASET" DO i = 1 TO SYSPARM.0 DO j = 1 to PARMLIB.0 - IF SYSDSN("'"||PARMLIB.j||"(IEASYS"|| SYSPARM.i||")'") == "OK" THEN + IF SYSDSN("'"||PARMLIB.j||"(IEASYS"|| SYSPARM.i||")'") == "OK" THEN SAY " "|| right(j,2,0) || " | YES | " ||, PARMLIB.j||"(IEASYS"|| SYSPARM.i||")" ELSE @@ -146,7 +146,7 @@ END SAY " + ORDER | EXISTS | DATASET" DO i = 1 TO IEASYM.0 DO j = 1 to PARMLIB.0 - IF SYSDSN("'"||PARMLIB.j||"(IEASYM"|| IEASYM.i||")'") == "OK" THEN + IF SYSDSN("'"||PARMLIB.j||"(IEASYM"|| IEASYM.i||")'") == "OK" THEN SAY " "|| right(j,2,0) || " | YES | " ||, PARMLIB.j||"(IEASYM"|| IEASYM.i||")" ELSE @@ -159,7 +159,7 @@ END /* https://www.ibm.com/support/knowledgecenter/en/ SSLTBW_2.3.0/com.ibm.zos.v2r3.ieae200/ieae200266.htm */ SAY "> Parsing" SYSPARM -ADDRESS TSO +ADDRESS TSO "ALLOC F(INFILE) DSN('"||IEASYSxx||"') SHR REU" "EXECIO * DISKR INFILE ( FINIS STEM IEASYS." "FREE F(INFILE)" @@ -175,7 +175,7 @@ do ix = 1 While Length(SEARCH_ITEMS) > 0 Parse Var SEARCH_ITEMS ITEMS.ix SEARCH_ITEMS end ITEMS.0 = ix - 1 -DO I = 1 TO IEASYS.0 +DO I = 1 TO IEASYS.0 DO J = 1 TO ITEMS.0 IF INDEX(IEASYS.I,ITEMS.J||"=") == 1 THEN DO SAY " +" ITEMS.J "Found" @@ -199,9 +199,9 @@ DO J = 1 to ITEMS.0 /* So we change them here */ IF ITEMS.j == "CMD" THEN DSN = "'"||PARMLIB.i||"(COMMND"||PDS||")'" - ELSE IF ITEMS.j == "OMVS" THEN + ELSE IF ITEMS.j == "OMVS" THEN DSN = "'"||PARMLIB.i||"(BPXPRM"||PDS||")'" - ELSE IF ITEMS.j == "MSTRJCL" THEN + ELSE IF ITEMS.j == "MSTRJCL" THEN DSN = "'"||PARMLIB.i||"(MSTJCL"||PDS||")'" ELSE IF ITEMS.j == "LPA" THEN DSN = "'"||PARMLIB.i||"(LPALST"||PDS||")'" @@ -219,9 +219,9 @@ DO J = 1 to ITEMS.0 END END -Say "> Parsing MSTJCL (Master JCL File)" +Say "> Parsing MSTJCL (Master JCL File)" Say " + using:" MSTRJCL.dsn1 -ADDRESS TSO +ADDRESS TSO "ALLOC F(INFILE) DSN('"||MSTRJCL.dsn1||"') SHR REU" "EXECIO * DISKR INFILE ( FINIS STEM MSTJCL." "FREE F(INFILE)" @@ -258,7 +258,7 @@ DO i = 1 TO procs.0 END Say "> Parsing COMMNDxx (commands automatically issued at initialization)" Say " + Using:" CMD.dsn1 -ADDRESS TSO +ADDRESS TSO "ALLOC F(INFILE) DSN('"||CMD.dsn1||"') SHR REU" "EXECIO * DISKR INFILE ( FINIS STEM COMMND." "FREE F(INFILE)" @@ -270,14 +270,14 @@ DO i = 1 to COMMND.0 command = strip(COMMND.i) if substr(command,1,6) == "COM='S" THEN DO say ' + Parsing Command:' substr(command,5) - if pos(",",command,6) > 0 THEN + if pos(",",command,6) > 0 THEN sproc = symbols(substr(command,8,pos(",",command,6)-8)) - else + else sproc = symbols(strip(substr(command,8),,"'")) say " + Searching for proc:" sproc do j = 1 to procs.0 IF SYSDSN("'"||procs.j ||"("sproc||")'") == "OK" THEN - say " Found" procs.j ||"("sproc||")" + say " Found" procs.j ||"("sproc||")" end end end @@ -287,7 +287,7 @@ do i = 1 to OMVS.0 DSN = "'"||PARMLIB.j||"(BPXPRM"||OMVS.i||")'" if SYSDSN(DSN) == "OK" THEN DO SAY " + Dataset:" DSN - ADDRESS TSO + ADDRESS TSO "ALLOC F(INFILE) DSN("||DSN||") SHR REU" "EXECIO * DISKR INFILE ( FINIS STEM BPXPRM." "FREE F(INFILE)" @@ -330,7 +330,7 @@ return -1 /* REPLACE SYMBOLS */ /* Symbols look like &SYM */ /* This function finds all symbols in a string and replaces them */ -SYMBOLS: +SYMBOLS: parse arg text totals = FINDALL(text) l = length(strip(text)) @@ -371,17 +371,17 @@ return count LISTMEMBERS: procedure parse arg pdsname say "+ Listing Members of:" pdsname -X=OUTTRAP("RES.") -ADDRESS TSO "LISTDS ('"pdsname"') MEMBERS" -X=OUTTRAP("OFF") -DO I = 7 TO RES.0 - RES.I = STRIP(RES.I) - DS = pdsname || "(" || RES.I || ")" +X=OUTTRAP("RES.") +ADDRESS TSO "LISTDS ('"pdsname"') MEMBERS" +X=OUTTRAP("OFF") +DO I = 7 TO RES.0 + RES.I = STRIP(RES.I) + DS = pdsname || "(" || RES.I || ")" SAY " + " DS -END +END return -smallest: procedure +smallest: procedure parse arg barf do i = 1 by 1 while barf <> '' parse var barf sortme.i ' ' barf @@ -389,7 +389,7 @@ smallest: procedure sortme.0 = i-1 tmp = 10000 do i = 1 to sortme.0 - if tmp > sortme.i & sortme.i /= 0 then + if tmp > sortme.i & sortme.i /= 0 then tmp = sortme.i end if tmp == 10000 then tmp = 0 diff --git a/EXEC/SYS0WN b/EXEC/SYS0WN new file mode 100644 index 0000000..c2c33fc --- /dev/null +++ b/EXEC/SYS0WN @@ -0,0 +1,171 @@ +/* REXX */ +/* This script was designed to list out all the SYSPROC/SYSEXEC */ +/* datasets, their creation date, last access date and your access */ +/* Created by SoF */ + + + say '';say '';say ''; /* the cheapest ISPF screen clear */ + SAY 'Script to check SYSPROC/SYSEXEC permissions' + ADDRESS TSO + CALL PATH + + exit + +PATH: +/* Identify DDNAME Allocated Datasets */ +/* from CBT FILE 496 */ +/* Like the $PATH in UNIX */ + Numeric Digits 10 +/*address TSO*/ + PSALCCAV = C2D(STORAGE(21C, 4)) + TCBTIO = C2D(STORAGE(D2X(PSALCCAV + 12), 4)) /* Points to TIOT PAGE 338 */ + TIOT = TCBTIO + 24 + TIOELNGH = 0 + longest = 0 + DD = '' + j = 0 + DO FOREVER + TIOT = TIOT + TIOELNGH + TIOELNGH = C2D(STORAGE(D2X(TIOT))) /* STORAGE returns one byte by default */ + IF TIOELNGH = 0 THEN LEAVE /* We've hit the end */ + TIOEDDNM = STORAGE(D2X(TIOT+4),8) + IF TIOEDDNM \= ' ' THEN DD = TIOEDDNM + DSNADDR = D2X(SWAREQ(Storage(d2x(TIOT + 12),3))) + DATASET = STRIP(STORAGE(DSNADDR, 44)) + VOLUME = STORAGE(D2X(X2D(DSNADDR)+118),6) + IF DD ='SYSPROC ' | DD ='SYSEXEC ' THEN DO + j = j + 1 + x = listdsi("'"dataset"'") + type.j = DD + dsn.j = dataset + vol.j = VOLUME + racf.j = SYSRACFA + create.j = DATE_GOOD(SYSCREATE) + ref.j = DATE_GOOD(SYSREFDATE) + if length(DATASET) > longest then longest = length(DATASET) + END + END + type.0 = j + dsn.0 = j + vol.0 = j + racf.0 = j + create.0 = j + ref.0 = j + + SYSPROC.0 = 0 + SYSEXEC.0 = 0 + DO i = 1 to j + ACCESS = 'NONE' + if racf.i == "GENERIC" THEN DO + OUTG = OUTTRAP('OUTG.') + "LD DA('"dsn.i"') GEN" + IF OUTG.0>1 THEN DO + ACCESS = WORD(OUTG.17,1) + END + end + else if racf.i == 'DISCRETE' THEN DO + OUTG = OUTTRAP('OUTG.') + "LD DA('"dsn.i"')" + IF OUTG.0>1 THEN DO + ACCESS = WORD(OUTG.17,1) + END + end + if type.i == 'SYSPROC ' then do + SYSPROC.0 = SYSPROC.0 + 1 + x = SYSPROC.0 + SYSPROC.x = "| "||LEFT(dsn.i,longest+1)||" | "||vol.i||" | " , + ||center(create.i,12)||" | "||center(ref.i,14)||" | "||LEFT(ACCESS,7)||"|" + end + else do + SYSEXEC.0 = SYSEXEC.0 + 1 + x = SYSEXEC.0 + SYSEXEC.x = "| "||LEFT(dsn.i,longest+1)||" | "||vol.i||" | " , + ||center(create.i,12)||" | "||center(ref.i,14)||" | "||LEFT(ACCESS,7)||"|" + end + end + Say 'SYSPROC:' + say "+-"||left('',longest+1,'-') , + ||"---------------------------------------------------+" + SAY "|" LEFT("Sysproc DSN",longest+1), + ||" | Volume | Created Date | Reference Date | Access |" + say "|-"||left('',longest+1,'-') , + ||"-|--------|--------------|----------------|--------|" + do i = 1 to SYSPROC.0 + say SYSPROC.i + end + say "+-"||left('',longest+1,'-') , + ||"---------------------------------------------------+" + SAY 'SYSEXEC:' + say "+-"||left('',longest+1,'-') , + ||"---------------------------------------------------+" + SAY "|" LEFT("Sysexec DSN",longest+1), + ||" | Volume | Created Date | Reference Date | Access |" + say "|-"||left('',longest+1,'-'), + ||"-|--------|--------------|----------------|--------|" + do i = 1 to SYSEXEC.0 + say SYSEXEC.i + end + say "+-"||left('',longest+1,'-'), + ||"---------------------------------------------------+" + + RETURN 0 + + +date_good: + /* parses the date */ + parse arg YEAR '/' DAY + return DATE('E',SUBSTR(YEAR,3,2)RIGHT(DAY,3,'0'),'J') + + +/*--------------------------------------------------------------------*\ +|* *| +|* MODULE NAME = SWAREQ *| +|* *| +|* DESCRIPTIVE NAME = Convert an SVA to a 31-bit address *| +|* *| +|* STATUS = R200 *| +|* *| +|* FUNCTION = The SWAREQ function simulates the SWAREQ macro to *| +|* convert an SWA Virtual Address (SVA) to a full 31-bit *| +|* address which can be used to access SWA control blocks *| +|* in the SWA=ABOVE environment. The input is a 3-byte *| +|* SVA; the output value is a 10-digit decimal number. *| +|* *| +|* AUTHOR = Gilbert Saint-Flour *| +|* *| +|* DEPENDENCIES = TSO/E V2 *| +|* *| +|* SYNTAX = SWAREQ(sva) *| +|* *| +|* sva must contain a 3-byte SVA. *| +|* *| +\*--------------------------------------------------------------------*/ +SWAREQ: PROCEDURE + NUMERIC DIGITS 20 /* allow up to 2**64 */ + sva=C2D(ARG(1)) /* convert to decimal */ + tcb = C2D(STORAGE(21C,4)) /* TCB PSATOLD */ + jscb = C2D(STORAGE(D2X(tcb+180),4)) /* JSCB TCBJSCB */ + qmpl = C2D(STORAGE(D2X(jscb+244),4)) /* QMPL JSCBQMPI */ +/* See if qmat can be above the bar */ + qmsta= C2X(STORAGE(D2X(qmpl+16),1)) /* JOB STATUS BYTE */ + if SUBSTR(X2B(qmsta),6,1) then /* is QMQMAT64 bit on? */ + do /* yes, qmat can be ATB */ + IF RIGHT(X2B(C2X(ARG(1))),1) \= '1' THEN/* SWA=BELOW ? */ + RETURN C2D(ARG(1))+16 /* yes, return sva+16 */ + qmat=C2D(STORAGE(D2X(qmpl+10),2))*(2**48) +,/* QMAT+0 QMADD01 */ + C2D(STORAGE(D2X(qmpl+18),2))*(2**32) +,/* QMAT+2 QMADD23 */ + C2D(STORAGE(D2X(qmpl+24),4)) /* QMAT+4 QMADD */ + RETURN C2D(STORAGE(D2X(qmat+(sva*12)+64),4))+16 + end + else + do /* no, qmat is BTB */ + IF RIGHT(C2X(ARG(1)),1) \= 'F' THEN /* SWA=BELOW ? */ + RETURN C2D(ARG(1))+16 /* yes, return sva+16 */ + qmat = C2D(STORAGE(D2X(qmpl+24),4)) /* QMAT QMADD */ + DO WHILE sva>65536 + qmat = C2D(STORAGE(D2X(qmat+12),4)) /* next QMAT QMAT+12 */ + sva=sva-65536 /* 010006F -> 000006F */ + END + RETURN C2D(STORAGE(D2X(qmat+sva+1),4))+16 + end +/*-------------------------------------------------------------------*/ diff --git a/LICENSE b/License similarity index 100% rename from LICENSE rename to License diff --git a/README.MD b/README.md similarity index 81% rename from README.MD rename to README.md index 5726a2a..4218795 100644 --- a/README.MD +++ b/README.md @@ -2,7 +2,7 @@ ## ENUM -This script is a proof of concept REXX script built to aide in system enumeration of z/OS. The purpose of this script is to help identify other areas of interest to look in to during a penetration test. It work in both TSO and OMVS (UNIX). When you run it for the first time it displays this screen: +This script is a proof of concept REXX script built to aide in system enumeratio ``` $ ./ENUM @@ -38,7 +38,7 @@ Example: ./ENUM WHO ``` -So that it doesn't cause too many alarms or alerts the script tries to gather all information using storage (memory) calls. For example, to get the JOB Name (i.e. the name of the process executing this script) we look at a few storage areas that return pointers: +So that it doesn't cause too many alarms or alerts the script tries to gather al ```REXX CVT = STORAGE(10,4) /* FLCCVT-PSA DATA AREA */ @@ -56,7 +56,7 @@ Displays information from all of the argument areas outlined below. ### APF -Displays APF authorized libraries either dynamically allocated or declared statically. This script will then check to see if the dataset declared for the APF authorized actually exists. +Displays APF authorized libraries either dynamically allocated or declared stati ### CAT @@ -68,11 +68,11 @@ Displays the name of the executing JOB ### PATH -Displays information about the dataset concatenation (if in TSO). This is basically the 'path' which is searched for executables. When this function is called with the 'ALL' argument it attempts to display all DDNAMEs. When called specifically it will only show SYSPROC/SYSEXEC. +Displays information about the dataset concatenation (if in TSO). This is basica ### SEC -Information about the security product installed. RACF gives a lot of information. ACF2 less, TopSecret, so secretive it only tells if you're running TopSecret or not. +Information about the security product installed. RACF gives a lot of informatio ### SVC @@ -80,11 +80,11 @@ Displays information about the installed SVCs ### VERS -Displays version information about the operating system and some other components. +Displays version information about the operating system and some other component ### WHO -Displays a list of who is currently logged on to the mainframe either in TSO or OMVS (UNIX). +Displays a list of who is currently logged on to the mainframe either in TSO or ### TSTA @@ -92,23 +92,23 @@ Displays authorization status for TESTAUTH program. ### Sources -Big thanks goes out to the following for information which I used to build this script: +Big thanks goes out to the following for information which I used to build this * Mark Zelden's IPLINFO Rexx: http://www.mzelden.com/mvsfiles/iplinfo.txt * Jay Taylor's SETRRCVT: https://github.com/jaytay79/zos -* z/OS MVS Data Areas Volumes 1 through 6: https://www-03.ibm.com/systems/z/os/zos/library/bkserv/v2r2pdf/#IEA -* File # 221 EDP Auditor REXX tools updated from Lee Conyers: http://www.cbttape.org/ftp/cbt/CBT221.zip -* File # 496 REXX exec to do LISTA (display allocations): http://www.cbttape.org/ftp/cbt/CBT496.zip +* z/OS MVS Data Areas Volumes 1 through 6: https://www-03.ibm.com/systems/z/os/z +* File # 221 EDP Auditor REXX tools updated from Lee Conyers: http://www.cbttape +* File # 496 REXX exec to do LISTA (display allocations): http://www.cbttape.org ## STARTMAP -This REXX script was designed to map out mainframe startup (IPL) settings, files, proclibs, etc. Simply call the -program with `ex 'HLQ.STARTMAP'` or `ex 'HLQ.DATASET(STARTMAP)'` and read the results. +This REXX script was designed to map out mainframe startup (IPL) settings, files +program with `ex 'HLQ.STARTMAP'` or `ex 'HLQ.DATASET(STARTMAP)'` and read the re -There's a lot of results to part here so recording your output might be a good idea. +There's a lot of results to part here so recording your output might be a good i ``` - + .dP"Y8 8888888 d8b 88"""Yb 8888888 "Ybo." 888 dP8Yb 88___dP 888 o."Y8b 888 dP___Yb 88""Yb 888 @@ -121,8 +121,8 @@ There's a lot of results to part here so recording your output might be a good i |: NNN NNNN N ,NNN' :NNN, NNNNNN :::::::| ------------,NNN',NNNNNNNN,-------------- M A I N F R A M E I P L M A P P E R - - + + > Identifying Load Parameters in storage + IPL Dataset: SYS1.IPLPARM(LOADCS) + VOLUME: 0A82 @@ -136,7 +136,7 @@ There's a lot of results to part here so recording your output might be a good i ## CATMAP -This tool was developed to help identify all (nonvsam) datasets (and their members) on z/OS. +This tool was developed to help identify all (nonvsam) datasets (and their membe ``` @@ -167,13 +167,13 @@ Arguments: (-vol ) Volume for dataset - optional (-space <# cylinders>) size of dataset in cylinders 100 cyls = 59 MB - optional - + Defaults: Verbose Mode: Disabled Brutal Mode: Disabled Space: 59MB Volume: System Default - + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! !! !! WARNING: Brutal mode may create thousands of access !! @@ -186,9 +186,9 @@ Examples usage: ``` ex 'h4cked.catmap' '-b' - - - + + + Starting BRUTAL MODE ADCD.DYNISPF.ISPPLIB(IBMPRODS) ADCD.DYNISPF.ISPPLIB(IPC@PRIM) @@ -209,13 +209,13 @@ ex 'h4cked.catmap' '-b' # SYS0WN -A rexx script to check on the permissions, create and reference dates for the SYSPROC and SYSEXEC datasets. SYSPROC (CLISTs) and SYSEXEC (REXX execs) are basically your `$PATH` variable in TSO. The order displayed is the search order in TSO. +A rexx script to check on the permissions, create and reference dates for the SY Usage: ex 'user.SYS0WN' ``` -Script to check SYSPROC/SYSEXEC permissions -SYSPROC: +Script to check SYSPROC/SYSEXEC permissions +SYSPROC: +----------------------------------------------------------------------+ | Sysproc DSN | Volume | Created Date | Reference Date | Access | |--------------------|--------|--------------|----------------|--------| @@ -232,4 +232,4 @@ SYSPROC: | IOE.SIOEEXEC | PROD0A | 19/09/13 | 05/06/18 | READ | | USER.PROCLIB | DEV2C2 | 13/03/16 | 05/06/18 | ALTER | +----------------------------------------------------------------------+ -``` +``` diff --git a/SYS0WN b/SYS0WN deleted file mode 100644 index f35a5bc..0000000 --- a/SYS0WN +++ /dev/null @@ -1,161 +0,0 @@ -/* REXX */ -/* This script was designed to list out all the SYSPROC/SYSEXEC */ -/* datasets, their creation date, last access date and your access */ -/* Created by SoF */ - - -say '';say '';say ''; /* the cheapest ISPF screen clear */ -SAY 'Script to check SYSPROC/SYSEXEC permissions' -ADDRESS TSO -CALL PATH - -exit - -PATH: -/* Identify DDNAME Allocated Datasets */ -/* from CBT FILE 496 */ -/* Like the $PATH in UNIX */ -Numeric Digits 10 -/*address TSO*/ -PSALCCAV = C2D(STORAGE(21C, 4)) -TCBTIO = C2D(STORAGE(D2X(PSALCCAV + 12), 4)) /* Points to TIOT PAGE 338 */ -TIOT = TCBTIO + 24 -TIOELNGH = 0 -longest = 0 -DD = '' -j = 0 -DO FOREVER - TIOT = TIOT + TIOELNGH - TIOELNGH = C2D(STORAGE(D2X(TIOT))) /* STORAGE returns one byte by default */ - IF TIOELNGH = 0 THEN LEAVE /* We've hit the end */ - TIOEDDNM = STORAGE(D2X(TIOT+4),8) - IF TIOEDDNM \= ' ' THEN DD = TIOEDDNM - DSNADDR = D2X(SWAREQ(Storage(d2x(TIOT + 12),3))) - DATASET = STRIP(STORAGE(DSNADDR, 44)) - VOLUME = STORAGE(D2X(X2D(DSNADDR)+118),6) - IF DD ='SYSPROC ' | DD ='SYSEXEC ' THEN DO - j = j + 1 - x = listdsi("'"dataset"'") - type.j = DD - dsn.j = dataset - vol.j = VOLUME - racf.j = SYSRACFA - create.j = DATE_GOOD(SYSCREATE) - ref.j = DATE_GOOD(SYSREFDATE) - if length(DATASET) > longest then longest = length(DATASET) - END -END -type.0 = j -dsn.0 = j -vol.0 = j -racf.0 = j -create.0 = j -ref.0 = j - -SYSPROC.0 = 0 -SYSEXEC.0 = 0 -DO i = 1 to j - ACCESS = 'NONE' - if racf.i == "GENERIC" THEN DO - OUTG = OUTTRAP('OUTG.') - "LD DA('"dsn.i"') GEN" - IF OUTG.0>1 THEN DO - ACCESS = WORD(OUTG.17,1) - END - end - else if racf.i == 'DISCRETE' THEN DO - OUTG = OUTTRAP('OUTG.') - "LD DA('"dsn.i"')" - IF OUTG.0>1 THEN DO - ACCESS = WORD(OUTG.17,1) - END - end - if type.i == 'SYSPROC ' then do - SYSPROC.0 = SYSPROC.0 + 1 - x = SYSPROC.0 - SYSPROC.x = "| "||LEFT(dsn.i,longest+1)||" | "||vol.i||" | "||center(create.i,12)||" | "||center(ref.i,14)||" | "||LEFT(ACCESS,7)||"|" - end - else do - SYSEXEC.0 = SYSEXEC.0 + 1 - x = SYSEXEC.0 - SYSEXEC.x = "| "||LEFT(dsn.i,longest+1)||" | "||vol.i||" | "||center(create.i,12)||" | "||center(ref.i,14)||" | "||LEFT(ACCESS,7)||"|" - end -end -Say 'SYSPROC:' -say "+-"||left('',longest+1,'-') ||"---------------------------------------------------+" -SAY "|" LEFT("Sysproc DSN",longest+1) ||" | Volume | Created Date | Reference Date | Access |" -say "|-"||left('',longest+1,'-') ||"-|--------|--------------|----------------|--------|" -do i = 1 to SYSPROC.0 - say SYSPROC.i -end -say "+-"||left('',longest+1,'-') ||"---------------------------------------------------+" -SAY 'SYSEXEC:' -say "+-"||left('',longest+1,'-') ||"---------------------------------------------------+" -SAY "|" LEFT("Sysexec DSN",longest+1) ||" | Volume | Created Date | Reference Date | Access |" -say "|-"||left('',longest+1,'-') ||"-|--------|--------------|----------------|--------|" -do i = 1 to SYSEXEC.0 - say SYSEXEC.i -end -say "+-"||left('',longest+1,'-') ||"---------------------------------------------------+" - -RETURN 0 - - -date_good: - /* parses the date */ - parse arg YEAR '/' DAY -return DATE('E',SUBSTR(YEAR,3,2)RIGHT(DAY,3,'0'),'J') - - -/*--------------------------------------------------------------------*\ -|* *| -|* MODULE NAME = SWAREQ *| -|* *| -|* DESCRIPTIVE NAME = Convert an SVA to a 31-bit address *| -|* *| -|* STATUS = R200 *| -|* *| -|* FUNCTION = The SWAREQ function simulates the SWAREQ macro to *| -|* convert an SWA Virtual Address (SVA) to a full 31-bit *| -|* address which can be used to access SWA control blocks *| -|* in the SWA=ABOVE environment. The input is a 3-byte *| -|* SVA; the output value is a 10-digit decimal number. *| -|* *| -|* AUTHOR = Gilbert Saint-Flour *| -|* *| -|* DEPENDENCIES = TSO/E V2 *| -|* *| -|* SYNTAX = SWAREQ(sva) *| -|* *| -|* sva must contain a 3-byte SVA. *| -|* *| -\*--------------------------------------------------------------------*/ -SWAREQ: PROCEDURE -NUMERIC DIGITS 20 /* allow up to 2**64 */ -sva=C2D(ARG(1)) /* convert to decimal */ -tcb = C2D(STORAGE(21C,4)) /* TCB PSATOLD */ -jscb = C2D(STORAGE(D2X(tcb+180),4)) /* JSCB TCBJSCB */ -qmpl = C2D(STORAGE(D2X(jscb+244),4)) /* QMPL JSCBQMPI */ -/* See if qmat can be above the bar */ -qmsta= C2X(STORAGE(D2X(qmpl+16),1)) /* JOB STATUS BYTE */ -if SUBSTR(X2B(qmsta),6,1) then /* is QMQMAT64 bit on? */ -do /* yes, qmat can be ATB */ - IF RIGHT(X2B(C2X(ARG(1))),1) \= '1' THEN/* SWA=BELOW ? */ - RETURN C2D(ARG(1))+16 /* yes, return sva+16 */ - qmat=C2D(STORAGE(D2X(qmpl+10),2))*(2**48) +,/* QMAT+0 QMADD01 */ - C2D(STORAGE(D2X(qmpl+18),2))*(2**32) +,/* QMAT+2 QMADD23 */ - C2D(STORAGE(D2X(qmpl+24),4)) /* QMAT+4 QMADD */ - RETURN C2D(STORAGE(D2X(qmat+(sva*12)+64),4))+16 -end -else -do /* no, qmat is BTB */ - IF RIGHT(C2X(ARG(1)),1) \= 'F' THEN /* SWA=BELOW ? */ - RETURN C2D(ARG(1))+16 /* yes, return sva+16 */ - qmat = C2D(STORAGE(D2X(qmpl+24),4)) /* QMAT QMADD */ - DO WHILE sva>65536 - qmat = C2D(STORAGE(D2X(qmat+12),4)) /* next QMAT QMAT+12 */ - sva=sva-65536 /* 010006F -> 000006F */ - END - RETURN C2D(STORAGE(D2X(qmat+sva+1),4))+16 -end -/*-------------------------------------------------------------------*/ diff --git a/zginstall.readme b/zginstall.readme new file mode 100644 index 0000000..aa216d0 --- /dev/null +++ b/zginstall.readme @@ -0,0 +1,22 @@ +ZIGI Managed Repository Generalized Installation Tool + +The zginstall.rex is the ZIGI generalized installation tool and it is +used by this repository, when the ZIGI ISPF dialog is not used, to +install the repositories z/OS datasets from the Git OMVS repository. + +To use zginstall.rex: + + 1. Enter OMVS + 2. At the OMVS prompt change to the OMVS directory where the Git + repository is located + 3. Enter at the OMVS prompt ./zginstall.rex + 4. Enter when prompted the z/OS dataset high level qualifier to be + used for the z/OS datasets to be created from this Git repository + 5. When zginstall.rex completes all of the z/OS datasets that are + part of the Git repository will have been copied into newly + allocated z/OS datasets. + 6. Next return to TSO/ISPF and execute the ZGSTAT command that is + documented by the zginstall.rex installation report. This will + apply the ISPF statistics to all of the partitioned datasets, + something that ZIGI supports because neither Git or OMVS + understand what ISPF statistics are. diff --git a/zginstall.rex b/zginstall.rex new file mode 100755 index 0000000..e9077f9 --- /dev/null +++ b/zginstall.rex @@ -0,0 +1,1421 @@ +/* REXX - must start in column 1 */ + /* --------------------------------------------------------- * + | Name: zginstall.rex | + | | + | Function: ZIGI Package Installation Script | + | | + | Syntax: ./zginstall.rex hlq \ option | + | | + | Usage: If hlq is not provided it will be prompted for | + | and used for the z/OS dataset hlq. | + | | + | \ - delimeter | + | | + | x - any non-blank will cause zginstall to | + | copy individual files into the PDS instead | + | of all at once.. | + | | + | Installation: This script should be installed in the root | + | OMVS directory for the ZIGI managed Git | + | repository. | + | | + | It is included in this library so that it | + | can be accessed by ZIGI to prime a new, or | + | existing, repository. | + | | + | Usage Notes: | + | 1. Prompt for | + | - default HLQ to be used | + | 2. Sequential files that have no lowercase | + | will be processed. | + | 3. Directories that are all uppercase will | + | be assumed to be PDS directories | + | 4. Upon completing the upload of all z/OS | + | datasets the hlq.ZGSTAT.EXEC dataset will | + | be generated. It will be pre-configured for | + | the uploaded datasets and when executed will | + | apply the ISPF statistics to all partitioned | + | dataset members from the ISPF statistics | + | files found in the .zigi directory. | + | | + | Author: Lionel B. Dyck | + | | + | History: (most recent on top) | + | 08/08/20 LBD - Generalize get_binfiles | + | 07/29/20 LBD - Add _EDC_ZERO_RECLEN=Y to env. | + | 07/24/20 LBD - Adjust Popup Panel Location | + | - Prompt to Proceed after display | + | of target datasets | + | 07/12/20 LBD - Define OMVS env stem | + | 07/04/20 LBD - Use Clear to clear screen | + | 06/29/20 LBD - Add generic installer prose | + | 06/28/20 LBD - Add text graphics | + | - Add prose about INPUT state | + | 06/27/20 LBD - Use a single cp if the pds is | + | not mixed (text & binary) | + | 06/26/20 LBD - Fixup zgstat.exec dsname quotes | + | 06/11/20 LBD - Redesign self contained exec | + | 06/10/20 LBD - Tweak for zgstat.exec dsn | + | 06/09/20 LBD - Creation from zigickot | + | ---------------------------------------------------------- | + | zigi - the z/OS ISPF Git Interface | + | Copyright (C) 2020 - Henri Kuiper and Lionel Dyck | + | | + | This program is free software: you can redistribute it | + | and/or modify it under the terms of the GNU General | + | Public License as published by the Free Software | + | Foundation, either version 3 of the License, or (at | + | your option) any later version. | + | | + | This program is distributed in the hope that it will be | + | useful, but WITHOUT ANY WARRANTY; without even the | + | implied warranty of MERCHANTABILITY or FITNESS FOR A | + | PARTICULAR PURPOSE. See the GNU General Public License | + | for more details. | + | | + | You should have received a copy of the GNU General | + | Public License along with this program. If not, see | + | . | + * ---------------------------------------------------------- */ + + arg options + + parse value options with ckothlq'/'opt + + ckothlq = strip(ckothlq) + + x = bpxwunix('clear') + say copies('-',73) + say " .zZ. Zz " + say " ZZZZZZZZ ZZZZZZZ " + say " ZZZZZZZZZZZZZZZZZZZZZZ ZZ ZZZ zZ " + say " ZZZZZZZZZZZZZZZZZZZZZZZZZZZZ ZZZ .zZZ ZZ " + say " ZZZZZZZZZZZZZZZZ ZZZZZZZ ZZ ZZZ ..zZZZ Zz " + say " ZZZZZZZZZZ, ZZZZZZZZZ ZZZ ZzZ ZZ ZZ ZZZZZZZ" + say " ZZZZ ZZZZZZZZ ZZZ ZZZZZZZZZZZ ZZZZZZZZZZZ " + say " ZZZZZZZZ ZZZZ ZZZZZZ ZZZZZZZZZg " + say " ZZZZZZZZ ZZZ ZZZZZZZZZ " + say " ZZZZZZZ zZZZZZZZZZZZZZZ Common" + say " ZZZZZZZ ZZZZZZZZZZZZZZ Installation" + say " .ZZZZZZZ ZZZZZZZZZZZZZZ Tool" + say " ZZZZZZZZZZZZZZZZZZZZZZ " + say " ZZZZZZZZZZZZZZZZZ zOS ISPF Git Interface " + say " ZZZZZZZZZZZZ " + say " ZZZZZZZZZg The git interface for the rest of us" + say " ZZZZZZig " + say " ZZZZZZi Henri Kuiper & Lionel Dyck " + say copies('-',73) + + + /* --------------------- * + | Set Default Env and | + | Get current directory | + * --------------------- */ + env.1 = '_BPX_SHAREAS=YES' + env.2 = '_BPX_SPAWN_SCRIPT=YES' + env.3 = '_EDC_ZERO_RECLEN=Y' + env.0 = 3 + cmd = 'pwd' + x = bpxwunix(cmd,,so.,se.,env.) + ckotdir = strip(so.1) + +Restart: + /* ------------------- * + | Prompt for z/OS HLQ | + * ------------------- */ + if ckothlq = '' then do + say 'Enter the z/OS High Level Qualifier to use:' + pull ckothlq + if ckothlq = '' then do + say 'no qualifier entered - exiting for now.' + exit 8 + end + ckothlq = translate(strip(ckothlq)) + end + + /* -------------------------------------------------------- * + | Issue the ls command to get file names and sizes for all | + | files in the current directory and sub-directories. | + * -------------------------------------------------------- */ + cmd = 'ls -laRk' ckotdir + rc = bpxwunix(cmd,,stdout.,stderr.,env.) + + /* ---------------------------------------------- * + | Display any error messages and if so then exit | + * ---------------------------------------------- */ + if stderr.0 > 0 then do + do i = 1 to stderr.0 + say stderr.i + end + exit 8 + end + + /* ------------------------- * + | Define our work variables | + * ------------------------- */ + parse value '' with subs files null + mgen = 0 + hit = 0 + filec = 0 + +/* -------------------------------------------------------------- * + | Inform the user that if there are directories with a lot of | + | members to be copied into a PDS tht the OMVS shell may enter | + | an INPUT state and to just press F10 - meanwhile the copy (cp) | + | is proceeding. | + * -------------------------------------------------------------- */ + if opt = null then do + call zmsg ' ' + call zmsg 'If the repository being installed has partitioned datasets' + call zmsg 'with a large number of members, the copy operation will take' + call zmsg 'longer than the TN3270 polling expects. This will cause' + call zmsg 'the OMVS Shell to change from RUNNING to INPUT.' + call zmsg 'Just press the F10 key to return to a RUNNING state. ' + call zmsg ' ' + call zmsg 'Do not worry, however, as the copy operation is still running' + call zmsg 'and will report out when it completes (but only if the shell' + call zmsg 'is in a RUNNING state.' + call zmsg ' ' + end + + /* ------------------------------------ * + | Read in ../.zigi/dsn to get dcb info | + * ------------------------------------ */ + cmd = 'cd' ckotdir '&& ls -la .zigi' + x = bpxwunix(cmd,,co.,ce.,env.) + if x > 0 then do + def_recfm = 'FB' + def_lrecl = 80 + def_blksize = 32720 + def. = null + end + else do + ckdd = 'ck'time('s') + x = bpxwunix("cat '"ckotdir"/.zigi/dsn'",,ck.) + def. = null + zdsn. = null + do i = 1 to ck.0 + if left(ck.i,1) = '#' then iterate + if word(ck.i,1) = '*' then do + parse value ck.i with . def_dsorg def_recfm def_lrecl def_blksize . + end + else do + dsn = word(ck.i,1) /* dataset name less hlq */ + def.dsn = subword(ck.i,2) /* dataset dsorg */ + zdsn.dsn = word(ck.i,6) /* file extension */ + end + end + end + + Address TSO + + /* ------------------------------- * + | Get the list of Binary Datasets | + * ------------------------------- */ + call get_binfiles + + /* ---------------------------------------------------- * + | Process the results of the ls command to: | + | 1. collect number of members per sub-directory | + | 2. collect bytes count (in k) for each sub-directory | + | 3. collect info on sequential files | + * ---------------------------------------------------- */ + if stdout.0 > 0 then + do i = 1 to stdout.0 + select + when pos(ckotdir,stdout.i) > 0 then do + parse value stdout.i with (ckotdir)sub':' + if left(sub,1) = '/' then sub = substr(sub,2) + if strip(sub) /= '' then do + size.sub = 0 + dir.sub = 0 + si = 0 + if left(sub,1) /= '.' then do + subs = subs sub + end + end + end + when word(stdout.i,1) = 'total' then do + hit = hit + 1 + end + when hit > 1 & left(stdout.i,1) = '-' then + if strip(sub) /= '' then do + size.sub = size.sub + word(stdout.i,5) + dir.sub = dir.sub + 1 + end + when hit = 1 & left(stdout.i,1) = '-' then do + file = word(stdout.i,9) + if left(file,1) = '.' then iterate + fx = translate(file,'??????????????????????????', , + 'abcdefghijklmnopqrstuvwxyz') + if pos('?',fx) > 0 then iterate + size.file = word(stdout.i,5) + files = files file + end + otherwise nop + end + end + + call zmsg 'The following Datasets will be Created or Recreated:' + if words(files) > 0 then + do fi = 1 to words(files) + wdsn = "'"ckothlq"."word(files,fi)"'" + call zmsg wdsn + if check_file(wdsn) > 0 + then call zmsg '--- Dataset exists and will be recreated.' + end + do fi = 1 to words(subs) + wdsn = "'"ckothlq"."word(subs,fi)"'" + call zmsg wdsn + if check_file(wdsn) > 0 + then call zmsg '--- Dataset exists and will be recreated.' + end + call zmsg ' ' + say ' ' + say 'Enter Y to Proceed or anything to Retry:' + pull zgans + if translate(zgans) /= 'Y' then do + ckothlq = null + signal ReStart + end + + /* -------------------------------------------- * + | Process the individual files, if any | + | Allocation and Copy | + * -------------------------------------------- */ + do i = 1 to words(files) + parse value '' with zs1 zs2 zs3 zs4 zs5 zs6 zs7 zs8 zs9 + sub = word(files,i) + fileg = "'"ckothlq"."sub"'" + odir = "'"ckotdir"/"sub"'" + bin = is_binfile(sub) + if bin = 1 then type = 'Binary' + else type = 'Text' + say 'Copying' odir 'to' fileg 'as' type + filec = filec + 1 + zfile.filec = fileg + x = check_file(fileg) + if x = 0 then do + call outtrap 'x.' + 'delete' fileg + call outtrap 'off' + end + tracks = (size.sub%50000 + 1) * 2 + call get_dcb + 'alloc ds('fileg') new spa('tracks','tracks') tr dsorg(ps)' , + 'recfm('recfm') lrecl('lrecl') blksize('blksize')' + 'free ds('fileg')' + 'oget' odir fileg type + end + + /* -------------------------------------------- * + | Process the sub-directories and initiate the | + | Allocation and Copy | + | Ignore subdirectories | + * -------------------------------------------- */ + do isub = 1 to words(subs) + parse value '' with zs1 zs2 zs3 zs4 zs5 zs6 zs7 zs8 zs9 + sub = word(subs,isub) + bin = is_binfile(sub) + if bin = 1 then type = 'Binary' + else type = 'Text' + fx = translate(sub,'??????????????????????????', , + 'abcdefghijklmnopqrstuvwxyz') + if pos('?',fx) > 0 then iterate + tracks = (size.sub%50000 + 1) * 2 + call alloc_copy_pds + end + + /* ------------------------------------------ * + | Now update and create the zgstat.exec file | + * ------------------------------------------ */ + c = 0 + hit = 0 + last = sourceline() + do i = 1 to last + card = sourceline(i) + if left(card,8) = '>ZGSTATE' then leave + if hit = 0 then + if left(card,8) = '>ZGSTAT ' then do + hit = 1 + iterate + end + else iterate + if pos('$$$$$$',card) > 0 then do + parse value card with var '=' . + if translate(var) = 'REPODIR' then + card = " repodir ='"ckotdir"'" + if translate(var) = 'HLQ' then + card = " hlq ='"ckothlq"'" + end + c = c + 1 + zg.c = card + end + zg.0 = c + + Address syscall + path = ckotdir'/lrhg.rex' + 'open' path O_rdwr+O_creat+O_trunc 660 + if retval = -1 then do + say 'Unable to open the output file for ZGSTAT.EXEC' + say 'so ISPF statistics will not be able to be recreated.' + exit 8 + end + fd = retval + do i = 1 to zg.0 + rec = zg.i ESC_N + 'write' fd 'rec' length(rec) + end + 'close' fd + Address TSO + + zgstat_dsn = "'"ckothlq".ZGSTAT.EXEC'" + cmd = 'cp -v lrhg.rex "//'zgstat_dsn '"' + cmd = cmd '&& rm lrhg.rex' + x = bpxwunix(cmd,,so.,se.,env.) + if so.0 > 0 then + do i = 1 to so.0;say so.i;end + if se.0 > 0 then + do i = 1 to se.0;say se.i;end + + /* -------------------- * + | Done with everything | + * -------------------- */ + say ' ' + say 'Completed - z/OS datasets created:' + say ' ' + do i = 1 to filec + say zfile.i + end + say ' ' + say 'Note that using this installation path does not allow the ISPF' + say 'statistics to be recreated. Other than the missing ISPF statistics' + say 'everything has been successfully installed on z/OS.' + say ' ' + say 'To recreate the ISPF statistics execute the following command' + say 'after returning to TSO/ISPF:' + say ' ' + say 'TSO EX' zgstat_dsn 'EX' + say ' ' + say 'After it completes successfully it can be deleted.' + + Exit + +zmsg: + parse arg message + if strip(message) = null then + message = copies('-',63) + say '* 'left(message,63)' *' + return + + /* ----------------------------------------------------- */ + /* number format code thanks to Doug Nadel */ + /* ----------------------------------------------------- */ +fix_num: procedure + arg bytes + str=strip(translate('0,123,456,789,abc,def', , + right(bytes,16,','), , + '0123456789abcdef'),'L',',') + bytes = strip(str) + return bytes + + /* ----------------------------------------------------------------- * + | Allocate the PDS and perform the copy using cp | + | - if the target PDS exists as a PDS, delete and realloc as a PDSE | + | - if the target is a PDSE then it will NOT be reallocated | + | - The target PDS will be allocated as a PDSE version 2. | + | - if maxgen (mgen) is provided then member generations will | + | also be defined at allocation | + | - Uppercase and remove defined extension for members | + * ----------------------------------------------------------------- */ +Alloc_Copy_PDS: + pds = "'"ckothlq"."sub"'" + odir = "'"ckotdir"/"sub"/'" + filec = filec + 1 + zfile.filec = pds + x = check_file(pds) + if x = 0 then do + call outtrap 'x.' + Address TSO , + 'delete' pds + call outtrap 'off' + end + call get_dcb + if recfm = 'U' then do + type = 'Load module' + end + say 'Copying' odir 'to' pds + if mgen > 0 then gens = 'maxgens('mgen')' + else gens = null + 'Alloc new spa('tracks','tracks') recfm('recfm') lrecl('lrecl')' , + 'Blksize('blksize') Dsntype(Library,2) dsorg(po) dir(1)' , + 'dsn('pds')' gens + 'Free ds('pds')' + + /* ---------------------------------------------------- * + | Read directory to get all member file names and then | + | adjust according and then do individual cp | + * ---------------------------------------------------- */ + target = strip(pds,'B',"'") + address syscall + rdir = strip(odir,'B',"'") + rdir = strip(rdir,'T','/') + 'readdir' rdir 'mems.' + tcount = mems.0 - 2 + + if opt /= null then + mixed = check_mixed_bintext(sub) + else mixed = 0 + + if mixed = 0 then do + bin = is_binfile(sub) + if bin = 1 then binopt = '-B' + else binopt = null + if recfm = 'U' then binopt = '-X -I' + if binopt = null then type = 'Text' + else if binopt = '-B' then type = 'Binary' + else if recfm = 'U' then type = 'Load module' + zos = usssafe("//'"target"'") + say 'Copying' tcount 'members as' type + cmd = 'cp -A -U -v' binopt usssafe(rdir'/*') '"'zos'"' + x = docmd(cmd) + if x > 0 then do + say ' ' + say 'Copy command:' cmd + say ' ' + say 'Standard messages:' + say ' ' + do vs = 1 to so.0;say so.vs;end + say ' ' + say 'Error messages:' + say ' ' + do vs = 1 to se.0;say se.vs;end + end + end + else do /* mixed text and binary in same PDS */ + mcount = 0 + do ii = 1 to mems.0 + if mems.ii = "." | mems.ii = ".." then do + /* skip the . and .. things */ + iterate + end + m = mems.ii /* ignore the translation */ + if zdsn.sub /= null then + if right(m,length(zdsn.sub)) = zdsn.sub then do + parse value m with m'.'. + m = translate(m) + end + src = rdir'/'mems.ii + bin = is_binfile(sub'/'mems.ii) + if bin = 1 then binopt = '-B' + else binopt = null + if recfm = 'U' then binopt = '-X -I' + src = usssafe(mems.ii) + if left(src,1) = '#' then src = '\'src + zos = usssafe("//'"target"("m")'") + mcount = mcount + 1 + if binopt = null then type = 'Text' + else if binopt = '-B' then type = 'Binary' + else if recfm = 'U' then type = 'Load module' + say left('Copying' mcount 'of' tcount,24) 'Member:' m 'as' type + cmd = 'cd' usssafe(rdir) + cmd = cmd '&& cp -U -v' binopt src '"'zos'"' + x = docmd(cmd) + if x > 0 then do + say ' ' + say 'Standard messages:' + say ' ' + do vs = 1 to so.0;say so.vs;end + say ' ' + say 'Error messages:' + say ' ' + do vs = 1 to se.0;say se.vs;end + end + end + end + return + +get_dcb: + if def.sub /= null then do + parse value def.sub with dsorg recfm lrecl blksize . + recfm = left(recfm,1) substr(recfm,2,1) substr(recfm,3,1) + end + else do + recfm = left(def_recfm,1) substr(def_recfm,2,1) substr(def_recfm,3,1) + lrecl = def_lrecl + blksize = def_blksize + end + return + +Check_File: Procedure + arg dsn + call outtrap 'x.' + Address TSO 'Listd' dsn + call outtrap 'off' + if x.0 > 3 then return 8 + else return 0 + + /* ---------------------------------------- * + | Check if a PDS has mixed binary and text | + | 0 = not mixed 1 = mixed | + * ---------------------------------------- */ +Check_Mixed_BinText: + parse arg checkForBinFile + cmbtRC = 0 + if datatype(binfiles.0) /= 'NUM' then return 0 + do bi = 1 to binfiles.0 + parse value binfiles.bi with cmbtfile'/'cmbtmbr + parse value checkForBinFile with checkFile'/'checkmbr + if cmbtfile = checkFile then + if cmbtmbr = '*' then cmbtRC = 0 + else return 1 + if binfiles.bi = checkForBinFile then return 1 + end + return cmbtRC + +usssafe: procedure + parse arg dsn + if pos('$',dsn) = 0 then return dsn + /* Let's not usssafe it twice :) */ + if pos('\$',dsn) > 0 then return dsn + dsn = strreplace(dsn, '$', '\$') + return dsn + +strreplace: Procedure + string = arg(1) + strfrom = arg(2) + strto = arg(3) + null = '' + if pos(strfrom,string) = 0 then return string + newString = null + do i = 1 to length(string) + if substr(string,i,1) /= strfrom + then newstring = newstring''substr(string,i,1) + else newstring = newstring''strto + end + return newstring + +get_binfiles: + /* ---------------------------------------------------------\ + | Name: binfiles | + | | + | Function: Fills the global binfiles. stem with all | + | current repo files that are added as binary. | + \---------------------------------------------------------- */ + cmd = 'cd' ckotdir'/ &&' + cmd = 'cat -W filecodeset=UTF-8,pgmcodeset=IBM-1047' ckotdir'/.gitattributes' + cmd = cmd ' | grep BINARY' + cmd = cmd '| cut -d" " -f1' + x = docmd(cmd) + if so.0 = 0 then do + binfiles.0 = 0 + return 0 + end + do b = 1 to so.0 + binfiles.b = so.b + end + binfiles.0 = so.0 + return 0 + +is_binfile: procedure expose binfiles. + /* ---------------------------------------------------------\ + | Name: is_binfile | + | | + | Function: Checks the global binfiles. stem for the | + | provided dataset or dataset/member | + \---------------------------------------------------------- */ + parse arg file + if datatype(binfiles.0) /= 'NUM' then return 0 + do bi = 1 to binfiles.0 + if right(binfiles.bi,1) = '*' then do + parse value file with test'/'. + if left(binfiles.bi,length(binfiles.bi)-2) = test + then return 1 + end + if binfiles.bi = file then return 1 + end + return 0 + +docmd: + parse arg cmd + drop so. se. + x = bpxwunix(cmd,,so.,se.,env.) + return x + +/* +>ZGSTAT *** Inline ZGSTAT that will be updated and uploaded */ + /*--------------------- rexx procedure -------------------- * + | Name: ZGSTAT | + | | + | Function: To work with the ZIGI Generic Installation | + | tool to add the ISPF statistics to the ZIGI | + | managed partitioned datasets after they have | + | been created by the ZGINSTALL. | + | | + | Syntax: ex zgstat ex | + | | + | Dependencies: Uses a modified copy of the ZIGI zigistat | + | exec | + | | + | Author: Lionel B. Dyck | + | | + | History: (most recent on top) | + | 06/11/20 LBD - Put inline in zginstall.rex | + | 06/10/20 LBD - Usability enhancements | + | 06/09/20 LBD - Creation | + | | + | ---------------------------------------------------------- | + | ZIGI - the z/OS ISPF Git Interface | + | Copyright (C) 2020 - Henri Kuiper and Lionel Dyck | + | | + | This program is free software: you can redistribute it | + | and/or modify it under the terms of the GNU General | + | Public License as published by the Free Software | + | Foundation, either version 3 of the License, or (at | + | your option) any later version. | + | | + | This program is distributed in the hope that it will be | + | useful, but WITHOUT ANY WARRANTY; without even the | + | implied warranty of MERCHANTABILITY or FITNESS FOR A | + | PARTICULAR PURPOSE. See the GNU General Public License | + | for more details. | + | | + | You should have received a copy of the GNU General | + | Public License along with this program. If not, see | + | . | + * ---------------------------------------------------------- */ + +/* ------------------------------------------------ * + | These variables will be updated by zginstall.rex | + * ------------------------------------------------ */ + repodir = '$$$$$$' + hlq = '$$$$$$' + + Address ISPExec + load_info = loadispf() + + address syscall , + 'readdir' repodir 'files.' + + if files.0 = 0 then do + zedsmsg = 'Error' + zedlmsg = 'The directory specified is not the correct directory.' + 'setmsg msg(isrz001)' + exit 8 + end + + do i = 1 to files.0 + file = files.i + if left(file,1) = '.' then iterate + /* check for lower case so ignore these */ + fx = translate(file,'??????????????????????????', , + 'abcdefghijklmnopqrstuvwxyz') + if pos('?',fx) > 0 then iterate + dsname = "'"hlq"."file"'" + x = listdsi(dsname) + if sysdsorg /= 'PO' then iterate + msg1 = 'Applying ISPF Statistics to:' + msg2 = dsname + call pfshow 'off' /* make sure pfshow is off */ + 'Control Display Lock' + 'Addpop row(8) column(11)' + 'Display Panel(zgpop)' + 'Rempop' + call pfshow 'reset' /* restore pfshow setting */ + x = zigistat(dsname repodir'/.zigi/'file 'U') + end + +Done: + x = dropispf(load_info) + zedsmsg = 'Completed.' + zedlmsg = 'ZGSTAT completed ISPF statistics updates.' + 'setmsg msg(isrz001)' + exit 0 + +Cancel: + x = dropispf(load_info) + Say 'ZGSTAT utility canceled.' + exit 8 + + /* ------------------------------------------------------ * + | The pfshow routine will: | + | 1. check to see the passed option | + | 2. if Off then it will save the current pfshow setting | + | - save the current setting | + | - turn off pfshow | + | 3. if the option is Reset then it will | + | - test if pfshow was on and turn it back on | + * ------------------------------------------------------ */ +pfshow: + if zpfshow = 'OFF' then return + arg pfkopt + if pfkopt = 'RESET' then do + if pfkeys = 'ON' then + 'select pgm(ispopf) parm(FKA,ON)' + end + if pfkopt = 'OFF' then do + 'vget (zpfshow)' + pfkeys = zpfshow + if pfkeys /= 'OFF' then + 'select pgm(ispopf) parm(FKA,OFF)' + end + return + + /* Inline ISPF Elements - must remain within a comment +>Start +>Panel zgstat +)Attr + _ type(input) caps(on) hilite(uscore) + $ type(input) caps(off) hilite(uscore) +)Body Window(65,7) ++ ++Enter the z/OS Dataset HLQ (Prefix): +_hlq + ++ ++Enter the OMVS Directory for the Repository: +$repodir + ++ +)Init + &zwinttl = 'ZIGI Statistics Apply Utility' +)Proc + ver (&hlq,nb,dsname) + ver (&repodir,nb) +)End +>Panel zgpop +)Attr + @ type(output) caps(off) intens(low) +)Body Window(46,4) ++ +@msg1 +@msg2 ++ +)Init + &zwinttl = 'ZIGI Statistics Apply Utility' +)Proc + ver (&hlq,nb,dsname) + ver (&repodir,nb) +)End +>End */ + + /* -------------------- rexx procedure -------------------- * + | Name: zigistat | + | | + | Function: Collect or Compare the ISPF Stats for all | + | members in a PDS | + | | + | Syntax: x=zigistat(dsname filepath option) | + | | + | dsname is the z/OS dataset name to work with | + | | + | filepath is the OMVS file where the stats are | + | stored and consists of: | + | localdir/repodir/.ZIGI/filename | + | filename is the OMVS file that represents | + | the z/OS PDS dataset name | + | | + | Options: C - compare stats | + | S - save stats | + | U - update stats to those saved | + | used when creating/refreshing datasets | + | | + | Vars: statmems ispf variable for selective update | + | | + | Usage | + | Notes: Subroutine of ZIGI | + | Returns string of members changed | + | | + | Dependencies: | + | ISPF services | + | | + | Return: | + | 0 - stats saved or stats applied | + | 8 - no dsname provided | + | 12 - no filepath provided | + | 16 - no option provided | + | 20 - stats file in /.zigi missing | + | string - string of members with different stats | + | | + | Author: Lionel B. Dyck | + | | + | History: (most recent on top) | + | 06/09/20 LBD - Modified and included here | + | 06/09/20 LBD - Bypass stat update for lmod | + | 05/08/20 LBD - Support Load Libraries | + | 01/08/20 LBD - Selecitve stat update if statmems| + | 01/05/20 LBD - Correct special chars in filepath| + | using usssafe routine | + | 11/22/19 LBD - If a member has no stats - add | + | 11/18/19 LBD - Many fixes and add Debug | + | 11/15/19 LBD - Creation | + | | + | ---------------------------------------------------------- | + | ZIGI - the z/OS ISPF Git Interface | + | Copyright (C) 2020 - Henri Kuiper and Lionel Dyck | + | | + | This program is free software: you can redistribute it | + | and/or modify it under the terms of the GNU General | + | Public License as published by the Free Software | + | Foundation, either version 3 of the License, or (at | + | your option) any later version. | + | | + | This program is distributed in the hope that it will be | + | useful, but WITHOUT ANY WARRANTY; without even the | + | implied warranty of MERCHANTABILITY or FITNESS FOR A | + | PARTICULAR PURPOSE. See the GNU General Public License | + | for more details. | + | | + | You should have received a copy of the GNU General | + | Public License along with this program. If not, see | + | . | + * ---------------------------------------------------------- */ +zigistat: Procedure + + /* --------------------------------- * + | Define OMVS Environment Variables | + * --------------------------------- */ + env.1 = '_BPX_SHAREAS=YES' + env.2 = '_BPX_SPAWN_SCRIPT=YES' + env.0 = 2 + + /* --------------- * + | Define defaults | + * --------------- */ + parse value '' with null string m. rx allmems + zdd = 'ZS'time('s') + + /* --------------------------------- * + | Check for parms and return if not | + * --------------------------------- */ + parse arg dsn filepath opt + if dsn = null then return 8 + if filepath = null then return 12 + if opt = null then return 16 + opt = translate(opt) /* make upper case */ + + /* --------------------------------------- * + | If option C or U then read in the stats | + | - check if stats member exists rc=16 | + | - read into stem stats. | + * --------------------------------------- */ + if pos(opt,'C U') > 0 then do + x = check_stats_file(filepath) + rc = x + if rc > 0 then return x + drop stats. + cmd = 'cat' usssafe(filepath) + x = bpxwunix(cmd,,stats.,se.,env.) + do i = 1 to stats.0 + stats.i = translate(stats.i,' ','0D'x) + end + end + + /* ------------------ * + * Define ISPF Dataid * + * ------------------ */ + Address ISPExec + "LMINIT DATAID(STATUS) DATASET("dsn")" + "LMOPEN DATAID("STATUS") OPTION(INPUT)" + + /* ---------------------------------- * + | Get dataset recfm (check for lmod) | + * ---------------------------------- */ + x = listdsi(dsn) + + /* ------------ * + * Set defaults * + * ------------ */ + parse value null with member mem. , + ZLCDATE ZLMDATE ZLVERS ZLMOD ZLMTIME ZLCNORC, + ZLINORC ZLMNORC ZLUSER , + zlcnorce zlinorce zlmnorce , + zlsize zlamod zlrmode zlattr zlalias zlssi + mem.0 = 0 + + /* ----------------------- * + * Now process all members * + * ----------------------- */ + do forever + "LMMLIST Dataid("status") OPTION(LIST) MEMBER(MEMBER)" , + "STATS(YES)" + /* --------------------------------- * + * If RC 4 or more leave the do loop * + * --------------------------------- */ + if rc > 3 then leave + /* -------------------------------- * + | Check if no stats then add them. | + * -------------------------------- */ + if sysrecfm /= 'U' then + if zlcdate = null then do + 'LMMSTATS DATAID('status') Member('member') user('sysvar(sysuid)')' + "LMMFind DATAID("status") Member("member") STATS(YES)" + end + /* ------------------------------ * + * Add each member info to a stem * + * ------------------------------ */ + c = mem.0 + 1 + if sysrecfm /= 'U' + then mem.c = strip(member , + ZLCDATE ZLMDATE ZLVERS ZLMOD ZLMTIME ZLCNORC , + ZLINORC ZLMNORC ZLUSER , + zlcnorce zlinorce zlmnorce) + else mem.c = strip(member , + zlsize zlamod zlrmode zlattr zlalias zlssi) + mem.0 = c + if opt = 'C' then allmems = allmems member + end + + /* ------------------------- * + * Close and Free the Dataid * + * ------------------------- */ + "LMClose Dataid("status")" + "LMFree Dataid("status")" + + /* ----------------------------------------------- * + | Process the data based on the provided options: | + | | + | C - compare stats | + | S - save stats | + | U - update stats to those saved | + | used when creating/refreshing datasets | + * ----------------------------------------------- */ + Select + /* ---------------------------------------------------------- * + | Update ISPF Stats: | + | - all members in the ZIGI stats member will have their | + | ispf stats updated to reflect the saved stats | + | - Use statmems ispf var for selective stat updates | + | - new members will not be updated as we don't know about | + | them | + | - members with no stats will have stats added if they are | + | in the saved stats member | + * ---------------------------------------------------------- */ + When opt = 'U' then + if sysrecfm /= 'U' then do + 'vget (statmems)' + if statmems /= null then do + end + "LMINIT DATAID(zstats) DATASET("dsn")" + "LMOPEN DATAID("zstats") OPTION(INPUT)" + do i = 1 to stats.0 + parse value stats.i with member ZLCDATE ZLMDATE ZLVERS ZLMOD , + ZLMTIME ZLCNORC ZLINORC ZLMNORC ZLUSER ZLCNORCE , + ZLINORCE ZLMNORCE . + if statmems /= null then + if wordpos(member,statmems) = 0 then iterate + if zlcdate = null then , + 'LMMSTATS DATAID('zstats') Member('member') user('sysvar(sysuid)')' + else , + 'LMMSTATS DATAID('zstats') MEMBER('member') VERSION('zlvers')' , + 'MODLEVEL('zlmod') CREATED('zlcdate') MODDATE('zlmdate')' , + 'MODTIME('zlmtime') INITSIZE('zlinorc')' , + 'MODRECS('zlmnorc') USER('zluser')' + end + "LMClose Dataid("zstats")" + "LMFree Dataid("zstats")" + return 0 + end + /* ----------------------------------------------------------- * + | Compare ISPF stats. | + | | + | Comparison will be from the active datasets ISPF stats with | + | the saved stats found in ISPF stats file in /.zigi | + | | + | If a member is in the active but not in the saved list then | + | it will be added to the returned string. | + | | + | If a members saved stats do not match the active stats then | + | it will be added to the returned string. | + * ----------------------------------------------------------- */ + When opt = 'C' then do + /* 1st setup the saved stem for easy comparison */ + do i = 1 to stats.0 + parse value stats.i with savedmem data + m.savedmem = strip(data) + end + /* now compare active to saved */ + do i = 1 to mem.0 + parse value mem.i with actmem data + data = strip(data) + if m.actmem = null then string = string actmem + else if data /= m.actmem then string = string actmem + end + 'vput (allmems)' + return string + end + Otherwise nop /* should never get here */ + end + + /* -------------------------------------------- * + | Check to see if the provided filepath exists | + | rc 0 it does | + | rc 20 it does not | + * -------------------------------------------- */ +Check_Stats_File: + save_address = address() + address syscall 'lstat' filepath 'file.' + if file.0 = 0 then do + ADDRESS value(save_address) + return 20 + end + else return 0 + +docmd: + parse arg cmd + drop so. se. + x = bpxwunix(cmd,,so.,se.,env.) + return x + + /* ---------------------------------- * + | Make the z/OS dsname safe for OMVS | + * ---------------------------------- */ +usssafe: procedure + parse arg dsn + if pos('$',dsn) = 0 then return dsn + /* Let's not usssafe it twice :) */ + if pos('\$',dsn) > 0 then return dsn + dsn = strreplace(dsn, '$', '\$') + return dsn + +STRREPLACE: + ORIGINAL = ARG(1) + OLDTXT = ARG(2) + NEWTXT = ARG(3) + /* YOU CAN CHANGE THE BELOW KEY (TMPTXT), WHICH IS USED AS A TEMPORARY + POINTER TO IDENTIFY THE TEXT TO BE REPLACED */ + TMPTXT = '6A53CD2EW1F' + NEWSTR = ORIGINAL + DO WHILE POS(OLDTXT,NEWSTR) > 0 + NEWSTR = SUBSTR(NEWSTR, 1 , POS(OLDTXT,NEWSTR)-1) ||, + TMPTXT || SUBSTR(NEWSTR, POS(OLDTXT,NEWSTR) + LENGTH(OLDTXT)) + END + DO WHILE POS(TMPTXT,NEWSTR) > 0 + NEWSTR = SUBSTR(NEWSTR, 1 , POS(TMPTXT,NEWSTR)-1) ||, + NEWTXT || SUBSTR(NEWSTR, POS(TMPTXT,NEWSTR) + LENGTH(TMPTXT)) + END + RETURN NEWSTR + + /* -------------------- rexx procedure -------------------- * + * Name: LoadISPF * + * * + * Function: Load ISPF elements that are inline in the * + * REXX source code. * + * * + * Syntax: load_info = loadispf() * + * rc = dropispf(load_info) * + * * + * The inline ISPF resources are limited to * + * ISPF Messages, Panels, and Skeletons, * + * CLISTs and EXECs are also supported. * + * * + * The inline resources must start in column 1 * + * and use the following syntax: * + * * + * >START used to indicate the start of the * + * inline data * + * * + * >END - used to indicate the end of the * + * inline data * + * * + * Each resource begins with a type record: * + * >type name * + * where type is CLIST, EXEC, MSG, PANEL, SKEL * + * name is the name of the element * + * * + * Sample usage: * + * -* rexx *- * + * load_info = loadispf() * + * ... magic code happens here (your code) ... * + * rc = dropispf(load_info) * + * exit * + * >Start inline elements * + * >Panel panel1 * + * ... * + * >Msg msg1 * + * ... * + * >End of inline elements * + * * + * Returns: the list of ddnames allocated for use along * + * with the libdef's performed or altlib * + * * + * format is ddname libdef ddname libdef ... * + * libdef may be altlibc or altlibe * + * for altlib clist or altlib exec * + * * + * Notes: Entire routine must be included with REXX * + * exec - inline with the code. * + * * + * Comments: The entire rexx program is processed from the * + * last record to the first to find the >START * + * record at which point all records from that * + * point on are processed until the >END * + * statement or the end of the program is found. * + * * + * It is *strongly* suggested that the inline * + * elements be at the very end of your code so * + * that the search for them is faster. * + * * + * Inline ISPTLIB or ISPLLIB were not supported * + * because the values for these would have to be * + * in hex. * + * * + * Author: Lionel B. Dyck * + * * + * History: * + * 01/09/19 - Include DROPISPF routine * + * 08/29/17 - Fixup static values that were vars * + * 05/31/17 - Change default directory count * + * 12/09/16 - update for add_it routine * + * 05/10/16 - correction for clist and exec * + * 04/19/16 - bug correction * + * 06/04/04 - Enhancements for speed * + * 08/05/02 - Creation * + * * + * ---------------------------------------------------------- * + * Disclaimer: There is no warranty, either explicit or * + * implied with this code. Use it at your own risk as there * + * is no recourse from either the author or his employeer. * + * ---------------------------------------------------------- */ +LoadISPF: Procedure + + parse value "" with null kmsg kpanel kskel first returns , + kclist kexec + /* ------------------------------------------------------- * + * Find the InLine ISPF Elements and load them into a stem * + * variable. * + * * + * Elements keyword syntax: * + * >START - start of inline data * + * >CLIST name * + * >EXEC name * + * >MSG name * + * >PANEL name * + * >SKEL name * + * >END - end of all inline data (optional if last) * + * ------------------------------------------------------- */ + last_line = sourceline() + do i = last_line to 1 by -1 + line = sourceline(i) + if translate(left(line,6)) = ">START " then leave + end + rec = 0 + /* --------------------------------------------------- * + * Flag types of ISPF resources by testing each record * + * then add each record to the data. stem variable. * + * --------------------------------------------------- */ + do j = i+1 to last_line + line = sourceline(j) + if translate(left(line,5)) = ">END " then leave + if translate(left(line,7)) = ">CLIST " then kclist = 1 + if translate(left(line,6)) = ">EXEC " then kexec = 1 + if translate(left(line,5)) = ">MSG " then kmsg = 1 + if translate(left(line,7)) = ">PANEL " then kpanel = 1 + if translate(left(line,6)) = ">SKEL " then kskel = 1 + rec = rec + 1 + data.rec = line + end + + /* ----------------------------------------------------- * + * Now create the Library and Load the Member(s) * + * ----------------------------------------------------- */ + Address ISPExec + /* ----------------------------- * + * Assign dynamic random ddnames * + * ----------------------------- */ + clistdd = "lc"random(999) + execdd = "le"random(999) + msgdd = "lm"random(999) + paneldd = "lp"random(999) + skeldd = "ls"random(999) + + /* ---------------------------------------- * + * LmInit and LmOpen each resource library * + * ---------------------------------------- */ + if kclist <> null then do + call alloc_dd clistdd + "Lminit dataid(clist) ddname("clistdd")" + "LmOpen dataid("clist") Option(Output)" + returns = strip(returns clistdd 'ALTLIBC') + end + if kexec <> null then do + call alloc_dd execdd + "Lminit dataid(exec) ddname("execdd")" + "LmOpen dataid("exec") Option(Output)" + returns = strip(returns execdd 'ALTLIBE') + end + if kmsg <> null then do + call alloc_dd msgdd + "Lminit dataid(msg) ddname("msgdd")" + "LmOpen dataid("msg") Option(Output)" + returns = strip(returns msgdd 'ISPMLIB') + end + if kpanel <> null then do + call alloc_dd paneldd + "Lminit dataid(panel) ddname("paneldd")" + "LmOpen dataid("panel") Option(Output)" + returns = strip(returns paneldd 'ISPPLIB') + end + if kskel <> null then do + call alloc_dd skeldd + "Lminit dataid(skel) ddname("skeldd")" + "LmOpen dataid("skel") Option(Output)" + returns = strip(returns skeldd 'ISPSLIB') + end + + /* ----------------------------------------------- * + * Process all records in the data. stem variable. * + * ----------------------------------------------- */ + do i = 1 to rec + record = data.i + recordu = translate(record) + if left(recordu,5) = ">END " then leave + if left(recordu,7) = ">CLIST " then do + if first = 1 then call add_it + type = "Clist" + first = 1 + parse value record with x name + iterate + end + if left(recordu,6) = ">EXEC " then do + if first = 1 then call add_it + type = "Exec" + first = 1 + parse value record with x name + iterate + end + if left(recordu,5) = ">MSG " then do + if first = 1 then call add_it + type = "Msg" + first = 1 + parse value record with x name + iterate + end + if left(recordu,7) = ">PANEL " then do + if first = 1 then call add_it + type = "Panel" + first = 1 + parse value record with x name + iterate + end + if left(recordu,6) = ">SKEL " then do + if first = 1 then call add_it + type = "Skel" + first = 1 + parse value record with x name + iterate + end + /* --------------------------------------------* + * Put the record into the appropriate library * + * based on the record type. * + * ------------------------------------------- */ + Select + When type = "Clist" then + "LmPut dataid("clist") MODE(INVAR)" , + "DataLoc(record) DataLen(255)" + When type = "Exec" then + "LmPut dataid("exec") MODE(INVAR)" , + "DataLoc(record) DataLen(255)" + When type = "Msg" then + "LmPut dataid("msg") MODE(INVAR)" , + "DataLoc(record) DataLen(80)" + When type = "Panel" then + "LmPut dataid("panel") MODE(INVAR)" , + "DataLoc(record) DataLen(80)" + When type = "Skel" then + "LmPut dataid("skel") MODE(INVAR)" , + "DataLoc(record) DataLen(80)" + Otherwise nop + end + end + if type <> null then call add_it + /* ---------------------------------------------------- * + * Processing completed - now lmfree the allocation and * + * Libdef the library. * + * ---------------------------------------------------- */ + if kclist <> null then do + Address TSO, + "Altlib Act Application(Clist) File("clistdd")" + "LmFree dataid("clist")" + end + if kexec <> null then do + Address TSO, + "Altlib Act Application(Exec) File("execdd")" + "LmFree dataid("exec")" + end + if kmsg <> null then do + "LmFree dataid("msg")" + "Libdef ISPMlib Library ID("msgdd") Stack" + end + if kpanel <> null then do + "Libdef ISPPlib Library ID("paneldd") Stack" + "LmFree dataid("panel")" + end + if kskel <> null then do + "Libdef ISPSlib Library ID("skeldd") Stack" + "LmFree dataid("skel")" + end + return returns + + /* --------------------------- * + * Add the Member using LmmAdd * + * based upon type of resource * + * --------------------------- */ +Add_It: + Select + When type = "Clist" then + "LmmAdd dataid("clist") Member("name")" + When type = "Exec" then + "LmmAdd dataid("exec") Member("name")" + When type = "Msg" then + "LmmAdd dataid("msg") Member("name")" + When type = "Panel" then + "LmmAdd dataid("panel") Member("name")" + When type = "Skel" then + "LmmAdd dataid("skel") Member("name")" + Otherwise nop + end + type = null + return + + /* ------------------------------ * + * ALlocate the temp ispf library * + * ------------------------------ */ +Alloc_DD: + arg dd + Address TSO + if pos(left(dd,2),"lc le") > 0 then + "Alloc f("dd") unit(sysda) spa(5,5) dir(5)", + "recfm(v b) lrecl(255) blksize(32760)" + else + "Alloc f("dd") unit(sysda) spa(5,5) dir(5)", + "recfm(f b) lrecl(80) blksize(23440)" + return + + /* -------------------- rexx procedure -------------------- * + * Name: DropISPF * + * * + * Function: Remove ISPF LIBDEF's and deactivate ALTLIB's * + * that were created by the LoadISPF function. * + * * + * Syntax: rc = dropispf(load_info) * + * * + * Author: Janko * + * * + * History: * + * 12/05/18 - Creation * + * ---------------------------------------------------------- */ +DropISPF: Procedure + arg load_info + Address ISPEXEC + do until length(load_info) = 0 + parse value load_info with dd libd load_info + if left(libd,6) = "ALTLIB" then do + if libd = "ALTLIBC" then lib = "CLIST" + else lib = "EXEC" + Address TSO, + "Altlib Deact Application("lib")" + end + else "libdef" libd + address tso "free f("dd")" + end + return 0 + >ZGSTATE *** End of the ZGSTAT inline code