/* REXX */
/* CLS2REXXed by UMLA01S on 1 Mar 2019 at 14:58:51  */
/*trace ?r*/
Signal On NoValue
Call On Error
Signal On Failure
Signal On Syntax
Parse source opsys . exec_name .
Address ISREDIT
 
"MACRO"               /* CACM0014 EDIT PROCLIB(FTPD) */
/*********************************************************************/
/* This EDIT MACRO provides the finding details for IFTP0020.        */
/*********************************************************************/
/* 08/05/2004 JL.NELSON ADDED EXIT CODE.                             */
/* 08/10/2004 JL.NELSON ADDED check for continuation JCL and EOF.    */
/* 08/13/2004 JL.NELSON ADDED comments for PDI checks.               */
/* 02/11/2005 JL.NELSON Changed constants to variables before        */
/*            rename.                                                */
/* 03/09/2005 JL.NELSON Changed LMMREP to LMMADD/LMMREP to avoid     */
/*            errors.                                                */
/* 06/09/2005 JL.NELSON Pass MAXCC in ZISPFRC variable.              */
/* 06/29/2005 JL.NELSON Changed undefined &LP to &RP for numbered    */
/*            msgs.                                                  */
/* 07/08/2005 JL.NELSON Fixed FIND for INACTIVE & ANONYMOUS.         */
/* 07/11/2005 JL.NELSON Drop all comments in JCL.                    */
/* 07/14/2005 JL.NELSON Changed for SYSFTPD/SYSTCPD not found.       */
/* 10/24/2005 JL.NELSON Modified for v511 PDI name changes.          */
/* 03/02/2006 JL.NELSON Modified RESOLVER_CONFIG multiple            */
/*            delimiters.                                            */
/* 03/02/2006 JL.NELSON Changed to correct variable substitution.    */
/* 03/20/2006 JL.NELSON Use NRSTR avoid abend 900 if ampersand in    */
/*            data.                                                  */
/* 03/29/2006 JL.NELSON Test for empty member LINENUM Rcode = 4.     */
/* 04/11/2006 JL.NELSON Added code for SYMDEF variable in JCL.       */
/* 04/12/2006 JL.NELSON Replace & with ? if varible not found.       */
/* 05/09/2006 JL.NELSON Avoid RC 20 on ISREDIT LINE when " or ' in   */
/*            data.                                                  */
/* 03/01/2019 CL.FENTON Converted script from CLIST to REXX.         */
/*                                                                   */
/*                                                                   */
/*                                                                   */
/*                                                                   */
/*********************************************************************/
pgmname = "CACM0014 03/01/19"
sysprompt = "OFF"                /* CONTROL NOPROMPT          */
sysflush  = "OFF"                /* CONTROL NOFLUSH           */
sysasis   = "ON"                 /* CONTROL ASIS - caps off   */
return_code = 0
maxcc = 0
max_rc = 0
Address ISPEXEC "CONTROL NONDISPL ENTER"
Address ISPEXEC "CONTROL ERRORS RETURN"
/*******************************************/
/* VARIABLES ARE PASSED TO THIS MACRO      */
/* CONSLIST                                */
/* COMLIST                                 */
/* SYMLIST                                 */
/* TERMMSGS                                */
/*******************************************/
return_code = 0
zerrsm = ""
Address ISPEXEC "VGET (CONSLIST COMLIST SYMLIST TERMMSGS",
  "PDIDD ACP) ASIS"
cm14vget = return_code
If return_code <> 0 then do
  Say pgmname "VGET RC =" return_code zerrsm
  Say pgmname "CONSLIST/"conslist "COMLIST/"comlist "SYMLIST/"symlist,
    "TERMMSGS/"termmsgs
  Say pgmname "PDIDD/"pdidd "ACP/"acp
  return_code = return_code + 16
  SIGNAL ERR_EXIT
  End
 
If CONSLIST = "ON" | COMLIST = "ON" | SYMLIST = "ON" ,
  then Trace r
 
return_code = 0
/*******************************************/
/* TURN ON MESSAGES                        */
/*******************************************/
syssymlist = symlist          /* CONTROL SYMLIST/NOSYMLIST */
sysconlist = conslist         /* CONTROL CONLIST/NOCONLIST */
syslist    = comlist          /* CONTROL LIST/NOLIST       */
sysmsg     = termmsgs         /* CONTROL MSG/NOMSG         */
/*******************************************/
/* MAIN PROCESS                            */
/*******************************************/
"(MEMBER) = MEMBER"
"(DSNAME) = DATASET"
return_code = 0
"(LASTLINE) = LINENUM .ZLAST"
 
If return_code > 0 then do
  If lastline = 0 then,
    Say pgmname "Empty file RCode =" return_code "DSN="dsname,
      "MEMBER="member zerrsm
  Else
    Say pgmname "LINENUM Error RCode =" return_code "DSN="dsname,
      "MEMBER="member zerrsm
  SIGNAL ERR_EXIT
  end
 
find_sysftpd = 12
find_systcpd = 12
find_anonymous = 12
find_inactive = 12
lp = "("
rp = ")"
pfdsn = ""
sfdsn = ""
a = "*"
"EXCLUDE ALL '//*' 1"
"EXCLUDE ALL '/*' 1"
"EXCLUDE ALL '*' 1"
"DELETE ALL X"
return_code = 0
"(LASTLINE) = LINENUM .ZLAST"
If return_code > 0 then do
  If lastline = 0 then,
    Say pgmname "Empty file RCode =" return_code "DSN="dsname,
      "MEMBER="member zerrsm
  Else
    Say pgmname "LINENUM Error RCode =" return_code "DSN="dsname,
      "MEMBER="member zerrsm
  SIGNAL ERR_EXIT
  end
 
return_code = 0
row = 1
col = 0
"CHANGE ALL X'50' X'6C'"             /* CHANGE ALL '&' '%'*/
 
 
PRE_LOOP:
do until return_code <> 0
  return_code = 0
  "CURSOR =" row col
  "FIND X'6C'"                          /* FIND '%'*/
  If return_code > 0 then leave
 
  "(ROW,COL) = CURSOR"
  "(DATA) = LINE" row
  scol = col + 1
  endx = length(data)
  ecol = pos(" ",data,col)-1
  ecol = pos(" ",data,col)
  If ecol = col then iterate
  If ecol <= 0 then,
    ecol = endx
  parse var data . =(scol) temp =(ecol) .
 
  If pos(",",temp) > 2 then,
    parse var temp temp "," .
  If pos("'",temp) > 2 then,
    parse var temp temp "'" .
  If pos('"',temp) > 2 then,
    parse var temp temp '"' .
  If pos('.',temp) > 2 then,
    parse var temp temp '.' .
  If pos('%',temp) > 2 then,
    parse var temp temp '%' .
  If pos("(",temp) > 2 then,
    parse var temp temp '(' .
  If pos(")",temp) > 2 then,
    parse var temp temp ')' .
  ecol = scol + length(temp)
  If temp <> " " then do
    name = temp
    Say pgmname "Variable" name "found in JCL."
    If substr(data,ecol,1) = "." then,
      ecol = ecol+1
    return_code = 0
    "FIND FIRST ' "name"='"
    If return_code <> 0 then do
      return_code = 0
      "FIND FIRST '"name"='"
      end
    If return_code = 0 then do
      "(ROW1,COL1) = CURSOR"
      If row1 >= row then,
        return_code = 4
      end
    If return_code <> 0 & length(name) < 9 then do
      return_code = 0
      save_maxcc = maxcc
      name2 = mvsvar("symdef",name)
      maxcc = save_maxcc
      If return_code = 0 & name2 <> " " then do
        Call NAME2_FOUND
        iterate
        end
      Else
        return_code = 4
      end
    If return_code <> 0 then do
      name2 = "?"name
      Call NAME2_FOUND
      iterate
      end
    "(DATA1) = LINE" row1
    x = pos("=",data1,col1)
    If x = 0 then iterate
    name2 = substr(data1,x+1)
    name2 = strip(name2,"B")
/*    parse var name2 name2 .*/
    If left(name2,1) = "'" then do
      parse var name2 . "'" name2 "'" .
      if name2 = "" then,
        name2 = "Null"
      end
    Else do
      parse var name2 name2 .
      If pos(",",name2) > 0 then do
        parse var name2 name2 "," .
        end
      end
    Call NAME2_FOUND
    end
  "LINE" row "= (DATA)"
  end
 
 
NEXT_1:
pfdsn = " "
return_code = 0
"FIND FIRST '//SYSFTPD ' 1 10"
find_sysftpd = return_code
b = 0
If find_sysftpd = 0 then,
  "(ROW,COL) = CURSOR"
 
 
SYSFTPD_CHK:
do row = row to lastline
  If find_sysftpd <> 0 then,
    leave
  "(DATA) = LINE" row
  If left(data,3) <> "// " &,
     left(data,10) <> "//SYSFTPD " then,
    leave
  return_code = 0
  a = pos("DSN=",data)
  If a > 0 then,
    a = a+4
  Else do
    a = pos("DSNAME=",data)
    If a > 0 then,
      a = a+7
    end
 
  If a > 1 then,
    b = pos(",",data,a)
  If a > 1 & a > b then,
    b = pos(" ",data,a)
  If a > 1 & a < b then do
    parse var data . =(a) pfdsn =(b) .
    leave
    end
  end
 
 
SYSFTPD_CHK_END:
return_code = 0
 
If pfdsn = " " then do
  find_sysftpd = 8
  stigtxt2 = "The SYSFTPD DD statement does not specify the FTP",
    "Data configuration file."
  end
Else,
  stigtxt2 = "The SYSFTPD DD statement does specify the FTP Data",
    "configuration file."  pfdsn
 
sfdsn = " "
return_code = 0
"FIND FIRST '//SYSTCPD ' 1 10"
find_systcpd = return_code
If find_systcpd = 0 then,
  "(ROW,COL) = CURSOR"
"(DATA) = LINE" row
 
 
SYSTCPD_CHK:
return_code = 0
b = 0
do row = row to lastline
  If find_systcpd <> 0 then,
    leave
  "(DATA) = LINE" row
  If left(data,3) <> "// " &,
     left(data,10) <> "//SYSTCPD " then,
    leave
  a = pos("DSN=",data)
  If a > 0 then,
    a = a+4
  Else do
    a = pos("DSNAME=",data)
    If a > 0 then,
      a = a+7
  end
  If a > 1 then,
    b = pos(",",data,a)
  If a > 1 & a > b then,
    b = pos(" ",data,a)-1
  If a > 1 & a < b then do
    parse var data . =(a) sfdsn =(b) .
    leave
    end
  end
 
 
SYSTCPD_CHK_END:
return_code = 0
 
If sfdsn = " " then do
  find_systcpd = 8
  stigtxt1 = "The SYSTCPD DD statement does not specify the",
    "TCP/IP Data configuration file."
  end
Else,
  stigtxt1 = "The SYSTCPD DD statement does specify the TCP/IP",
    "Data configuration file."   sfdsn
 
return_code = 0
/*"FIND ' PROC ' FIRST"
If return_code <> 0 then do*/
  return_code = 0
  "FIND ' EXEC ' FIRST"
/*  end    */
If return_code = 0 then,
  "(ROW,COL) = CURSOR"
Else,
  row = 1
 
"LABEL" row "= .X"
anonymous_data = " "
return_code = 0
"FIND 'ANONYMOUS' .X .ZL"
find_anonymous = return_code
If find_anonymous <> 0 then do
  stigtxt3 = "The ANONYMOUS startup parameter is not in use to",
    "enable the FTP server to accept anonymous logins."
  stigtxt4 = "The ANONYMOUS=acid startup parameter is not in use",
    "to enable the FTP server to accept anonymous logins."
/*SIGNAL INACTIVE_CHK*/
  end
Else do
  "(ROW,COL) = CURSOR"
  "(DATA) = LINE" row
  If pos("ANONYMOUS=",data,col) > 0 then do
    x = pos(" ",data,col)
    If x = 0 then,
      x = pos("'",data,col)
    If x = 0 then,
      x = pos(",",data,col)
    If col < x then do
      ecol = x
      parse var data . =(col) anonymous_data =(ecol) .
      end
    Else,
      parse var data . =(col) anonymous_data .
/*  If col < x-1 then do
      ecol = x - 1
      parse var data . =(col) anonymous_data =(ecol) .
      anonymous_data = substrc(col,x-1,data)
      end
    Else,
      parse var data . =(col) anonymous_data .
      anonymous_data = substrc(col,length(data),data) */
    stigtxt3 = "The ANONYMOUS startup parameter is not in use to",
      "enable the FTP server to accept anonymous logins."
    stigtxt4 = "The ANONYMOUS=acid startup parameter is in use",
      "enabling the FTP server to accept anonymous logins."
    end
  Else do
    stigtxt3 = "The ANONYMOUS startup parameter is in use enabling",
      "the FTP server to accept anonymous logins."
    stigtxt4 = "The ANONYMOUS=acid startup parameter is not in use",
      "to enable the FTP server to accept anonymous logins."
    end
  end
 
 
INACTIVE_CHK:
return_code = 0
"FIND 'INACTIVE' .X .ZL"
find_inactive = return_code
If find_inactive = 0 then,
  stigtxt5 = "The INACTIVE startup parameter is in use."
Else,
  stigtxt5 = "The INACTIVE startup parameter is not in use."
 
zftp0020_sw = 0
If find_sysftpd > 0 then,
  zftp0020_sw = zftp0020_sw + 1
If find_systcpd > 0 then,
  zftp0020_sw = zftp0020_sw + 1
If find_anonymous = 0 then,
  zftp0020_sw = zftp0020_sw + 1
If find_inactive = 0 then,
  zftp0020_sw = zftp0020_sw + 1
 
If zftp0020_sw > 0 then,
  call Process_zftp0020
Else do
  ac = "Not a Finding"
  Address ISPEXEC "LMPUT DATAID("pdidd") MODE(INVAR) DATALOC(AC)",
    "DATALEN("length(ac)") MEMBER(IFTP0020)"
  ac = " "
  Address ISPEXEC "LMPUT DATAID("pdidd") MODE(INVAR) DATALOC(AC)",
    "DATALEN("length(ac)") MEMBER(IFTP0020)"
  ac = "1) "stigtxt1
  Address ISPEXEC "LMPUT DATAID("pdidd") MODE(INVAR) DATALOC(AC)",
    "DATALEN("length(ac)") MEMBER(IFTP0020)"
  ac = "2) "stigtxt2
  Address ISPEXEC "LMPUT DATAID("pdidd") MODE(INVAR) DATALOC(AC)",
    "DATALEN("length(ac)") MEMBER(IFTP0020)"
  ac = "3) "stigtxt3
  Address ISPEXEC "LMPUT DATAID("pdidd") MODE(INVAR) DATALOC(AC)",
    "DATALEN("length(ac)") MEMBER(IFTP0020)"
  ac = "4) "stigtxt4
  Address ISPEXEC "LMPUT DATAID("pdidd") MODE(INVAR) DATALOC(AC)",
    "DATALEN("length(ac)") MEMBER(IFTP0020)"
  ac = "5) "stigtxt5
  Address ISPEXEC "LMPUT DATAID("pdidd") MODE(INVAR) DATALOC(AC)",
    "DATALEN("length(ac)") MEMBER(IFTP0020)"
  end
 
 
REP_ZFTP0020:
return_code = 0
mbr = "IFTP0020"
Address ISPEXEC "LMMADD DATAID("pdidd") MEMBER("mbr")"
If return_code = 4 then do
  return_code = 0
  Address ISPEXEC "LMMREP DATAID("pdidd") MEMBER("mbr")"
  If return_code <> 0 then,
    Say pgmname "LMMREP_PDIDD_RCODE =" return_code mbr zerrsm
  end
Else do
  If return_code <> 0 then,
    Say pgmname "LMMADD_PDIDD_RCODE =" return_code mbr zerrsm
  end
 
 
END_EXIT:
return_code = 0
 
 
ERR_EXIT:
If maxcc >= 16 | return_code > 0 then do
  Address ISPEXEC "VGET (ZISPFRC) SHARED"
  If maxcc > zispfrc then,
    zispfrc = maxcc
  Else,
    zispfrc = return_code
  Address ISPEXEC "VPUT (ZISPFRC) SHARED"
  Say pgmname "ZISPFRC =" zispfrc
  end
cm014rc = return_code
Address ISPEXEC "VPUT (PFDSN SFDSN CM14VGET CM014RC) ASIS"
"END"
Exit (0)
 
 
/*******************************************/
/*  SYSCALL SUBROUTINES                    */
/*******************************************/
 
 
NAME2_FOUND:
Say pgmname "Variable" name "replaced with" name2
If name2 = "Null" then,
  name2 = ""
data = strip(left(data,col-1)name2""substr(data,ecol),"T")
"LINE" row "= (DATA)"
return
 
 
Process_zftp0020:
ac = "The JCL for the FTP daemon's started task is coded",
  "improperly."
Address ISPEXEC "LMPUT DATAID("pdidd") MODE(INVAR) DATALOC(AC)",
  "DATALEN("length(ac)") MEMBER(IFTP0020)"
ac = " "
Address ISPEXEC "LMPUT DATAID("pdidd") MODE(INVAR) DATALOC(AC)",
  "DATALEN("length(ac)") MEMBER(IFTP0020)"
a = 1
If zftp0020_sw > 1 then,
  pd = a") "
Else
  pd = ""
 
If find_systcpd > 0 then do
  ac = pd"The SYSTCPD DD statement does not specify the TCP/IP",
    "Data configuration file."
  Address ISPEXEC "LMPUT DATAID("pdidd") MODE(INVAR) DATALOC(AC)",
    "DATALEN("length(ac)") MEMBER(IFTP0020)"
  a = a + 1
  If zftp0020_sw > 1 then,
    pd = a") "
  end
 
If find_sysftpd > 0 then do
  ac = pd"The SYSFTPD DD statement does not specify the FTP Data",
    "configuration file."
  Address ISPEXEC "LMPUT DATAID("pdidd") MODE(INVAR) DATALOC(AC)",
    "DATALEN("length(ac)") MEMBER(IFTP0020)"
  a = a + 1
  If zftp0020_sw > 1 then,
    pd = a") "
  end
 
If find_anonymous = 0 & anonymous_data = " " then do
  ac = pd""stigtxt3
  Address ISPEXEC "LMPUT DATAID("pdidd") MODE(INVAR) DATALOC(AC)",
    "DATALEN("length(ac)") MEMBER(IFTP0020)"
  a = a + 1
  If zftp0020_sw > 1 then,
    pd = a") "
  end
 
If anonymous_data <> " " then do
  ac = pd""stigtxt4
  Address ISPEXEC "LMPUT DATAID("pdidd") MODE(INVAR) DATALOC(AC)",
    "DATALEN("length(ac)") MEMBER(IFTP0020)"
  ac = "     "anonymous_data
  Address ISPEXEC "LMPUT DATAID("pdidd") MODE(INVAR) DATALOC(AC)",
    "DATALEN("length(ac)") MEMBER(IFTP0020)"
  a = a + 1
  If zftp0020_sw > 1 then,
    pd = a""rp" "
  end
 
If find_inactive = 0 then do
  ac = pd""stigtxt5
  Address ISPEXEC "LMPUT DATAID("pdidd") MODE(INVAR) DATALOC(AC)",
    "DATALEN("length(ac)") MEMBER(IFTP0020)"
  a = a + 1
  If zftp0020_sw > 1 then,
    pd = a") "
  end
return
 
 
substrc: Procedure
 If arg(3) = ''
   Then
     Do
     s = Arg(1)
     l = 1
     v = arg(2)
     End
   Else
     Do
     s = arg(1)
     l = arg(2)-arg(1)+1
     v = arg(3)
     End
  Return substr(v,s,l)
 
 
NoValue:
Failure:
Syntax:
say pgmname "REXX error" rc "in line" sigl":" strip(ERRORTEXT(rc))
say SOURCELINE(sigl)
SIGNAL ERR_EXIT
 
 
Error:
return_code = RC
if RC >= 16 then do
  say pgmname "LASTCC =" RC strip(zerrlm)
  say pgmname "REXX error" rc "in line" sigl":" ERRORTEXT(rc)
  say SOURCELINE(sigl)
  end
if return_code > maxcc then
  maxcc = return_code
return
 
 
