顯示具有 Work Management 標籤的文章。 顯示所有文章
顯示具有 Work Management 標籤的文章。 顯示所有文章

星期五, 12月 22, 2023

2023-12-22 Get top cpu usage percentage job (TOPCPUPCT)

2023-12-22 Get top cpu usage percentage job (TOPCPUPCT)

File  : QRPGLESRC
Member: TOPCPUPCT
Type  : RPGLE

     **
     **  Program . . : TopCpuPct
     **  Description : Finds CPU Top  and notifies caller
     **  Author  . . : Vengoal Chang
     **  Published . : AS400 ePaper
     **  Date  . . . : November 21, 2023
     **
     **
     **  Program summary
     **  ---------------
     **
     **  Work management APIs:
     **    QGYOLJOB      Open list of jobs     Lists jobs on the system based on
     **                                        the specified selection criteria.
     **
     **                                        Optionally a sort order for the
     **                                        returned jobs can be specified -
     **                                        in this case the processor unit
     **                                        time percentage in descending
     **                                        order - listing the jobs having
     **                                        the highest CPU usage first.
     **
     **                                        The CPU processor time is measured
     **                                        for an interval of 10 seconds in
     **                                        this example.
     **
     **                                        The QGYOLJOB API is found in the
     **                                        QGY library as are all other open
     **                                        list APIs.
     **
     **    QWVRCSTK      Retrieve Call Stack   Lists the program call stack for
     **                                        the specified job or thread.
     **                                        The current invocation level is
     **                                        returned first.
     **
     **  Message handling API:
     **    QMHSNDM       Send message          Sends a message to the specified
     **                                        non-program message queue - here
     **                                        an informational message is sent
     **                                        to the current user running this
     **                                        program.
     **
     **  Open list APIs:
     **    QGYGTLE       Get list entries      To retrieve open lists entries
     **                                        from an already open list the
     **                                        QGYGTLE (Get List Entries) API
     **                                        is available.
     **
     **    QGYCLST       Close list            This API closes the previously
     **                                        opened list identified by the
     **                                        request handle parameter.
     **                                        Storage allocated is freed.
     **
     **  MI builtins:
     **    _MEMMOVE      Copy memory           Copies a string from one pointer
     **                                        specified location to another.
     **
     **  Unix Type - Signal APIs:
     **    Sleep                               Suspends program processing for
     **                                        the specified number of seconds.
     **
     **
     **  Sequence of events:
     **    1. The act jobs processor time limit percentage is retrieved
     **
     **    2. The list jobs API input parameters are initialized
     **
     **    3. The open list of jobs API is called to reset the job
     **       statistics.
     **
     **    4. Program is suspended for some seconds
     **
     **    5. The open list of jobs API is called to list the interactive
     **       jobs on the system returning the most CPU intensive jobs
     **       for the elapsed period first.
     **
     **    6. For each top cpu percent job a message is sent to the
     **       message queue.
     **
     **    7. The job list resources are cleaned up.
     **
     **    8. The program will loop 1 to 7, until manual job.
     **
     **  Programmer's notes:
     **
     **    As mentioned above library QGY must be in the job library list
     **    to succesfully run this program.
     **
     **    To retrieve another job's call stack *JOBCTL special authority is
     **    required.
     **
     **
     **  Compile options:
     **
     **    CrtRpgMod Module( TOPCPUPCT )  DbgView( *LIST )
     **
     **    CrtPgm    Pgm( TOPCPUPCT )
     **              Module( TOPCPUPCT )
     **
     **  Usage sample:
     **    Get top first CPU% job per 60 secs with following:
     **     SBMJOB
     **       CMD(TOPCPUPCT TOPCOUNT(001) INTERVAL(00060)
     **                     TOMSGQ(*SYSOPR))
     **       Job(TOPPCTPCT)
     **
     **    Get top 5     CPU% job per 60 secs with following:
     **     SBMJOB
     **       CMD(TOPCPUPCT TOPCOUNT(005) INTERVAL(00060)
     **                     TOMSGQ(*SYSOPR))
     **       Job(TOPPCTPCT)
     **
     **-- Control spec:  -----------------------------------------------------**
     H Option( *SrcStmt )  DecEdit( *JobRun )  BndDir( 'QC2LE' )
     H DftActGrp(*NO)
     **-- System information:  -----------------------------------------------**
     D PgmSts         SDs
     D  PsPgmNam         *Proc
     D  PsSts                         5a   Overlay( PgmSts:  11 )
     D  PsCurJob                     10a   Overlay( PgmSts: 244 )
     D  PsUsrPrf                     10a   Overlay( PgmSts: 254 )
     D  PsJobNbr                      6a   Overlay( PgmSts: 264 )
     D  PsCurUsr                     10a   Overlay( PgmSts: 358 )
     **-- API error data structure:  -----------------------------------------**
     D ApiError        Ds
     D  AeBytPrv                     10i 0 Inz( %Size( ApiError ))
     D  AeBytAvl                     10i 0
     D  AeExcpId                      7a
     D                                1a
     D  AeExcpDta                   128a
     **-- API parameters:  ---------------------------------------------------**
     D JlRtnRcdNbr     s             10i 0 Inz( 1 )
     D JlNbrFldRtn     s             10i 0 Inz( %Elem( JlKeyFld ))
     D JlKeyFld        s             10i 0 Dim( 3 )
     **-- Job information:
     D JlJobInf        Ds           512
     D  JbJobId                      26a
     D   JbJobUsd                    10a   Overlay( JbJobId: 1 )
     D   JbUsrUsd                    10a   Overlay( JbJobId: *Next )
     D   JbNbrUsd                     6a   Overlay( JbJobId: *Next )
     D  JbActSts                      4a
     D  JbJobTyp                      1a
     D  JbJobSubTyp                   1a
     D  JbDtaLen                     10i 0
     D                                4a
     D  JbDta                       256a
     **-- Key information:
     D JlKeyInf        Ds
     D  KiFldNbrRtn                  10i 0
     D  KiKeyInf                     20a   Dim( %Elem( JlKeyFld ))
     D   KiFldInfLen                 10i 0 Overlay( KiKeyInf :  1 )
     D   KiKeyFld                    10i 0 Overlay( KiKeyInf :  5 )
     D   KiDtaTyp                     1a   Overlay( KiKeyInf :  9 )
     D                                3a   Overlay( KiKeyInf : 10 )
     D   KiDtaLen                    10i 0 Overlay( KiKeyInf : 13 )
     D   KiDtaOfs                    10i 0 Overlay( KiKeyInf : 17 )
     **-- Sort information:
     D JlSrtInf        Ds
     D  SiNbrKeys                    10i 0 Inz( 1 )
     D  SiSrtInf                     12a   Dim( 10 )
     D   SiKeyFldOfs                 10i 0 Overlay( SiSrtInf :  1 )
     D   SiKeyFldLen                 10i 0 Overlay( SiSrtInf :  5 )
     D   SiKeyFldTyp                  5i 0 Overlay( SiSrtInf :  9 )
     D   SiSrtOrd                     1a   Overlay( SiSrtInf : 11 )
     D   SiRsv                        1a   Overlay( SiSrtInf : 12 )
     **-- List information:
     D JlLstInf        Ds
     D  LiRcdNbrTot                  10i 0
     D  LiRcdNbrRtn                  10i 0
     D  LiHandle                      4a
     D  LiRcdLen                     10i 0
     D  LiInfSts                      1a
     D  LiDts                        13a
     D  LiLstSts                      1a
     D                                1a
     D  LiInfLen                     10i 0
     D  LiRcd1                       10i 0
     D                               40a
     **-- Selection information:
     D JlSltInf        Ds
     D  SiJobNam                     10a   Inz( '*ALL' )
     D  SiUsrNam                     10a   Inz( '*ALL' )
     D  SiJobNbr                      6a   Inz( '*ALL' )
     D  SiJobTyp                      1a   Inz( '*' )
     D                                1a
     D  SiOfsPriSts                  10i 0 Inz( 60 )
     D  SiNbrPriSts                  10i 0 Inz( 0 )
     D  SiOfsActSts                  10i 0 Inz( 70 )
     D  SiNbrActSts                  10i 0 Inz( 0 )
     D  SiOfsJbqSts                  10i 0 Inz( 78 )
     D  SiNbrJbqSts                  10i 0 Inz( 0 )
     D  SiOfsJbqNam                  10i 0 Inz( 88 )
     D  SiNbrJbqNam                  10i 0 Inz( 0 )
     **
     D  SiPriSts                     10a   Dim( 1 )
     D  SiActSts                      4a   Dim( 2 )
     D  SiJbqSts                     10a   Dim( 1 )
     D  SiJbqNam                     20a   Dim( 1 )
     **-- Job information key fields:
     D JbKeyDta        Ds
     D  JbPrcUniTim                  20u 0
     D  JbPrcUniPct                   9b 1
     D  JbPrcUniTimE                 20u 0
     **-- General return data:
     D JlGenDta        Ds
     D  GdBytRtn                     10i 0
     D  GdBytAvl                     10i 0
     D  GdElpTim                     20u 0
     D                               16a
     **-- MatRmd parameters:  ------------------------------------------------**
     D MatRscMgDt      Ds
     D  RdBytPrv                     10i 0 Inz( %Size( MatRscMgDt ))
     D  RdBytAvl                     10i 0
     D  RdTimDay                      8a
     D  RdData
     D   RdPrcTimIpl                 20u 0 Overlay( RdData: 1 )
     D   RdPrcTimScWl                20u 0 Overlay( RdData: *Next )
     D   RdPrcTimDb                  20u 0 Overlay( RdData: *Next )
     D   RdPrcTimDbTh                 5u 0 Overlay( RdData: *Next )
     D   RdPrcTimDbLm                 5u 0 Overlay( RdData: *Next )
     D   RdRsv1                      10u 0 Inz( x'00' )
     D                                     Overlay( RdData: *Next )
     D   RdPrcTimInt                 20u 0 Overlay( RdData: *Next )
     D   RdPrcTimIntT                 4b 1 Overlay( RdData: *Next )
     D   RdPrcTimIntL                 4b 1 Overlay( RdData: *Next )
     D   RdRsv2                      10u 0 Inz( x'00' )
     D                                     Overlay( RdData: *Next )
     **
     D MatCtlDta       Ds
     D  CdSltOpt                      1a   Inz( x'01' )
     D  CdRsv                         7a   Inz( *Allx'00' )
     **-- Global variables:  -------------------------------------------------**
     D Ix              s              5i 0
     D Count           s              5i 0
     D Interval        s             10u 0
     D TopCount        s              3S 0
     D PgmNam          s             10a
     D MsgDta          s            256a   Varying
     D MsgKey          s              4a
     D SysTime         s               z   inz(*sys)
     **-- API constants:  ----------------------------------------------------**
     D JOB_RESET_STAT  c                   '1'
     D JOB_KEEP_STAT   c                   '0'
     **-- Open list of jobs:  ------------------------------------------------**
     D LstJobs         Pr                  ExtPgm( 'QGYOLJOB' )
     D  LjRcvVar                  65535a          Options( *VarSize )
     D  LjRcvVarLen                  10i 0 Const
     D  LjFmtNam                      8a   Const
     D  LjRcvVarDfn               65535a          Options( *VarSize )
     D  LjRcvDfnLen                  10i 0 Const
     D  LjLstInf                     80a
     D  LjNbrRcdRtn                  10i 0 Const
     D  LjSrtInf                   1024a   Const  Options( *VarSize )
     D  LjJobSltInf                1024a   Const  Options( *VarSize )
     D  LjJobSltLen                  10i 0 Const
     D  LjNbrFldRtn                  10i 0 Const
     D  LjKeyFldRtn                  10i 0 Const  Options( *VarSize )  Dim( 32 )
     D  LjError                    1024a          Options( *VarSize )
     **
     D  LjJobSltFmt                   8a   Const  Options( *NoPass )
     **
     D  LjResStc                      1a   Const  Options( *NoPass )
     D  LjGenRtnDta                  32a          Options( *NoPass: *VarSize )
     D  LjGenRtnDtaLn                10i 0 Const  Options( *NoPass )
     **-- Get list entry:  ---------------------------------------------------**
     D GetLstEnt       Pr                  ExtPgm( 'QGYGTLE' )
     D  GlRcvVar                  65535a          Options( *VarSize )
     D  GlRcvVarLen                  10i 0 Const
     D  GlHandle                      4a   Const
     D  GlLstInf                     80a
     D  GlNbrRcdRtn                  10i 0 Const
     D  GlRtnRcdNbr                  10i 0 Const
     D  GlError                    1024a          Options( *VarSize )
     **-- Close list:  -------------------------------------------------------**
     D CloseLst        Pr                  ExtPgm( 'QGYCLST' )
     D  ClHandle                      4a   Const
     D  ClError                    1024a          Options( *VarSize )
     **-- Send message:  -----------------------------------------------------**
     D SndMsg          Pr                  ExtPgm( 'QMHSNDM' )
     D  SmMsgId                       7a   Const
     D  SmMsgFq                      20a   Const
     D  SmMsgDta                    512a   Const Options( *VarSize )
     D  SmMsgDtaLen                  10i 0 Const
     D  SmMsgTyp                     10a   Const
     D  SmMsgQq                    1000a   Const Options( *VarSize )
     D  SmMsgQnbr                    10i 0 Const
     D  SmMsgQrpy                    20a   Const
     D  SmMsgKey                      4a
     D  SmError                      10i 0 Const
     **
     D  SmCcsId                      10i 0 Const Options( *NoPass )
     **-- Copy memory:  ------------------------------------------------------**
     D memcpy          Pr              *   ExtProc( '_MEMMOVE' )
     D  outmem                         *   Value
     D  inpmem                         *   Value
     D  memsiz                       10u 0 Value
     **-- Delay job:  --------------------------------------------------------**
     D sleep           Pr            10i 0 ExtProc( 'sleep' )
     D  seconds                      10u 0 Value
     **-- Get top stack entry:  ----------------------------------------------**
     D GetTopStkE      Pr            20a
     D  GtJobId                      26a   Const
     **-- Materialize resource management data:  -----------------------------**
     D MatRmd          Pr                  ExtProc( '_MATRMD' )
     D  Rcv                                Like( MatRscMgDt )
     D  Ctl                                Like( MatCtlDta )
     **
     **-- Mainline:  ---------------------------------------------------------**
     **
     C     *Entry        Plist
     C                   Parm                    TopCount_p        3
     C                   Parm                    Interval_p        5
     C                   Parm                    ToMsgQ           10
     **
     C                   Eval      TopCount    = %Int(TopCount_p)
     C                   Eval      Interval    = %Int(Interval_p)

     C                   Select
     C                   When      ToMsgQ      =  '*SYSOPR'
     C                   Eval      ToMsgQ      =  'QSYSOPR'
     C                   When      ToMsgQ      =  '*CURUSR'
     C                   Eval      ToMsgQ      =  PsCurUsr
     C                   EndSl
     **
     **-- Job information return fields:
     C                   Eval      JlKeyFld(1) = 312
     C                   Eval      JlKeyFld(2) = 314
     C                   Eval      JlKeyFld(3) = 315
     **
     **-- Sort field specification:
     C                   Eval      SiNbrKeys      = 1
     C                   Eval      SiKeyFldOfs(1) = 49
     C                   Eval      SiKeyFldLen(1) = 4
     C                   Eval      SiKeyFldTyp(1) = 0
     C                   Eval      SiSrtOrd(1)    = '2'
     C                   Eval      SiRsv(1)       = x'00'
     **
     **-- Initialize job CPU measurement:
     **-- NOTE: Statistics only reset if return records are requested
     **
     C                   DoW       1 = 1
     C                   CallP     LstJobs( JlJobInf
     C                                    : %Size( JlJobInf )
     C                                    : 'OLJB0300'
     C                                    : JlKeyInf
     C                                    : %Size( JlKeyInf )
     C                                    : JlLstInf
     C                                    : 1
     C                                    : JlSrtInf
     C                                    : JlSltInf
     C                                    : %Size( JlSltInf )
     C                                    : JlNbrFldRtn
     C                                    : JlKeyFld
     C                                    : ApiError
     C                                    : 'OLJS0100'
     C                                    : JOB_RESET_STAT
     C                                    : JlGenDta
     C                                    : %Size( JlGenDta )
     C                                    )
     **
     **-- Wait 10 seconds:
     C                   CallP     sleep( Interval )
     **
     **-- Retrieve job list:
     C                   CallP     LstJobs( JlJobInf
     C                                    : %Size( JlJobInf )
     C                                    : 'OLJB0300'
     C                                    : JlKeyInf
     C                                    : %Size( JlKeyInf )
     C                                    : JlLstInf
     C                                    : 1
     C                                    : JlSrtInf
     C                                    : JlSltInf
     C                                    : %Size( JlSltInf )
     C                                    : JlNbrFldRtn
     C                                    : JlKeyFld
     C                                    : ApiError
     C                                    : 'OLJS0100'
     C                                    : JOB_KEEP_STAT
     C                                    : JlGenDta
     C                                    : %Size( JlGenDta )
     C                                    )
     **
     C                   If        AeBytAvl    =  *Zero
     **
     C                   Eval      Count       = 0
     C                   DoW       LiLstSts    <> '2'           Or
     C                             LiRcdNbrTot >  JlRtnRcdNbr
     **
     C                   ExSr      GetCpuDta
     C                   ExSr      ChkCpuPct
     **
     C*                  ExSr      SndCmpMsg
     **
     C                   If        Count      >= TopCount
     C                   Leave
     C                   EndIf
     **
     C                   Eval      JlRtnRcdNbr = JlRtnRcdNbr + 1
     **
     C                   CallP     GetLstEnt( JlJobInf
     C                                      : %Size( JlJobInf )
     C                                      : LiHandle
     C                                      : JlLstInf
     C                                      : 1
     C                                      : JlRtnRcdNbr
     C                                      : ApiError
     C                                      )
     **
     C                   If        AeBytAvl    > *Zero
     C                   Leave
     C                   EndIf
     **
     C                   EndDo
     **
     C                   CallP     CloseLst( LiHandle
     C                                     : ApiError
     C                                     )
     **
     C                   EndIf
     **
     C                   EndDo
     **
     C                   Eval      *InLr       = *On
     **
     C                   Return
     **
     **-- Get CPU data:  -----------------------------------------------------**
     C     GetCpuDta     BegSr
     **
     C                   Clear                   JbKeyDta
     **
     C                   For       Ix = 1  To KiFldNbrRtn
     **
     C                   Select
     C                   When      KiKeyFld(Ix) = 312
     C                   CallP     memcpy( %Addr( JbPrcUniTim )
     C                                   : %Addr( JlJobInf ) +
     C                                     KiDtaOfs(Ix)
     C                                   : KiDtaLen(Ix)
     C                                   )
     **
     C                   When      KiKeyFld(Ix) = 314
     C                   CallP     memcpy( %Addr( JbPrcUniPct )
     C                                   : %Addr( JlJobInf ) +
     C                                     KiDtaOfs(Ix)
     C                                   : KiDtaLen(Ix)
     C                                   )
     **
     C                   When      KiKeyFld(Ix) = 315
     C                   CallP     memcpy( %Addr( JbPrcUniTimE )
     C                                   : %Addr( JlJobInf ) +
     C                                     KiDtaOfs(Ix)
     C                                   : KiDtaLen(Ix)
     C                                   )
     C                   EndSl
     C                   EndFor
     **
     C                   EndSr
     **-- Check CPU percent:  ------------------------------------------------**
     C     ChkCpuPct     BegSr
     **
     C                   Eval      Count = Count + 1
     C                   Eval      PgmNam      = GetTopStkE( JbJobId )
     **
     C                   Eval      SysTime     = %Timestamp()
     C                   Eval      MsgDta      =
     C                                '{ "CPUPCTMSG": { '                     +
     C                                     '"QDATETIME" : "'                  +
     C                                       %Char(%Timestamp():*ISO) + '", ' +
     C                                     '"JobNam" : "'                     +
     C                                       %Trim(JbJobUsd) + '", '          +
     C                                     '"JobUsr" : "'                     +
     C                                       %Trim(JbUsrUsd) + '", '          +
     C                                     '"JobNbr" : "'                     +
     C                                       %Trim(JbNbrUsd) + '", '          +
     C                                     '"CpuPct" : "'                     +
     C                                       %Char( JbPrcUniPct ) + '", '     +
     C                                     '"PgmNam" : "'                     +
     C                                       %Trim( PgmNam ) + '"  '          +
     C                                '}  }'
     **
     C                   CallP(e)  SndMsg( *Blanks
     C                                   : *Blanks
     C                                   : MsgDta
     C                                   : %Len( MsgDta )
     C                                   : '*INFO'
     C                                   : ToMsgQ   + '*LIBL'
     C                                   : 1
     C                                   : *Blanks
     C                                   : MsgKey
     C                                   : 0
     C                                   )
     **
     C                   EndSr
     **-- Get top stack entry:  ----------------------------------------------**
     P GetTopStkE      B                   Export
     D                 Pi            20a
     D  GtJobId                      26a   Const
     **-- API parameters:
     D CsRcvVar        Ds
     D  CsBytRtn                     10i 0
     D  CsBytAvl                     10i 0
     D  CsNbrStkE                    10i 0
     D  CsOfsStkE                    10i 0
     D  CsNbrEntRtn                  10i 0
     D  CsThrId                       8a
     D  CsInfSts                      1a
     D  CsCalStk                  32767a
     **
     D CsCalStkE       Ds                  Based( pCalStkE )
     D  CsStkEntLen                  10i 0
     D  CsOfsStmIds                  10i 0
     D  CsNbrStmIds                  10i 0
     D  CsOfsPrcNam                  10i 0
     D  CsLenPrcNam                  10i 0
     D  CsRqsLvl                     10i 0
     D  CsPgmNam                     10a
     D  CsPgmLib                     10a
     D  CsMiInst                     10i 0
     D  CsModNam                     10a
     D  CsModLib                     10a
     D  CsCtlBdy                      1a
     D  CsRsv                         3a
     D  CsActGrpNbr                  10u 0
     D  CsActGrpNam                  10a
     D  CsAddInf                   4096a
     **
     D  CsStmIds                     10a   Dim( 16 )
     D  CsPrcNam                    512a
     **
     D CsJobId         Ds
     D  JiJobId                      26a
     D   JiJobNam                    10a   Overlay( JiJobId: 1 )
     D   JiUsrNam                    10a   Overlay( JiJobId: *Next )
     D   JiJobNbr                     6a   Overlay( JiJobId: *Next )
     D  JiIntId                      16a
     D  JiRsv                         2a   Inz( *Allx'00' )
     D  JiThrInd                     10i 0 Inz( 2 )
     D  JiThrId                       8a   Inz( *Allx'00' )
     **-- Retrieve call stack:
     D RtvCalStk       Pr                  ExtPgm( 'QWVRCSTK' )
     D  RcRcvVar                  32767a
     D  RcRcvVarLen                  10i 0 Const
     D  RcRcvInfFmt                   8a   Const
     D  RcJobId                      56a   Const
     D  RcJobIdFmt                    8a   Const
     D  RcError                   32767a          Options( *VarSize )
     **
     D EntNbr          s              5u 0
     **-- Get stack entries:  ------------------------------------------------**
     **
     C                   Eval      JiJobId     =  GtJobId
     **
     C                   CallP     RtvCalStk( CsRcvVar
     C                                      : %Size( CsRcvVar )
     C                                      : 'CSTK0100'
     C                                      : CsJobId
     C                                      : 'JIDF0100'
     C                                      : ApiError
     C                                      )
     **
     C                   If        AeBytAvl    = *Zero
     C                   Eval      pCalStkE    = %Addr( CsRcvVar ) + CsOfsStkE
     **
     C                   For       EntNbr = 1  to CsNbrEntRtn
     **
     C                   If        EntNbr      = 1
     **
     C                   Eval      CsStmIds    = *Blanks
     C                   Eval      CsPrcNam    = *Blanks
     **
     C                   If        CsOfsStmIds > *Zero
     C                   CallP     MemCpy( %Addr( CsStmIds )
     C                                   : %Addr( CsCalStkE ) +
     C                                     CsOfsStmIds
     C                                   : CsNbrStmIds * %Size( CsStmIds )
     C                                   )
     C                   EndIf
     **
     C                   If        CsOfsPrcNam > *Zero
     C                   CallP     MemCpy( %Addr( CsPrcNam )
     C                                   : %Addr( CsCalStkE ) +
     C                                     CsOfsPrcNam
     C                                   : CsLenPrcNam
     C                                   )
     C                   EndIf
     **
     C                   Leave
     C                   EndIf
     **
     C                   If        EntNbr      < CsNbrEntRtn
     C                   Eval      pCalStkE    = PCalStkE    + CsStkEntLen
     C                   EndIf
     C                   EndFor
     **
     C                   Return    CsPgmNam + CsPgmLib
     **
     C                   Else
     C                   Return    *Blanks
     C                   EndIf
     **
     P GetTopStkE      E


File  : QCMDSRC
Member: TOPCPUPCT
Type  : CMD

/*  ===============================================================  */
/*  = Command....... TopCpuPct                                    =  */
/*  = CPP........... TopCpuPct RPGLE                              =  */
/*  = Description... Send WRKACTJOB CPUPCT top to user            =  */
/*  =                                                             =  */
/*  =                                                             =  */
/*  = CrtCmd      Cmd( TopCpuPct )                                =  */
/*  =             Pgm( TopCpuPct  )                               =  */
/*  =             SrcFile( YourSourceFile )                       =  */
/*  ===============================================================  */
/*  = Date  : 2023/11/21                                          =  */
/*  = Author: Vengoal Chang                                       =  */
/*  ===============================================================  */
             CMD        PROMPT('Top Cpu Percent Job')

             PARM       KWD(TOPCOUNT) TYPE(*CHAR) LEN(3)             +
                          RANGE('001' '999')                         +
                          FULL(*YES)                                 +
                          PROMPT('TOP CPU JOB COUNT')

             PARM       KWD(INTERVAL) TYPE(*CHAR) LEN(5)             +
                          RANGE('00001' '99999')                     +
                          FULL(*YES)                                 +
                          PROMPT('Interval second')

             PARM       KWD(TOMSGQ) TYPE(*CHAR) LEN(10)              +
                          DFT(*SYSOPR)                               +
                          SPCVAL((*SYSOPR) (*CURUSR))                +
                          PROMPT('Message To MsgQ')


Program to capture CPU usage over time (with SQL)

星期一, 11月 06, 2023

2003-06-11 如何於程式執行時知道 Savf File 的內容(API QSRLSAVF) ?


2003-06-11 如何於程式執行時知道 Savf File 的內容(API QSRLSAVF) ?

有時候系統管理員需要控管哪些程式,檔案或程式原始檔成員可以 Restore 到系統中,
所以需要作確認,系統中提供 DSPSAVF 指令可以顯示 SAVF 內容,但無法於程式中直接
檢核,所以我利用 API QSRLSAVF 來達成這個目的,此範例僅顯示 SAVF 內容,並未提
供自動 Restore 物件功能,若有需要你可以於程式中自行建立 RSTOBJ 指令字串於程式
中,並加入所選取的物件字串,再執行整個 RSTOBJ 指令即可。


File  : QDDSSRC
Member: RSTOBJD
Type  : DSPF
Usage : CRTDSPF RSTOBJD

      *===============================================================
      *
      * To compile:
      *
      *      CRTDSPF  FILE(XXX/RSTOBJD) SRCFILE(XXX/QDDSSRC)
      *
      *===============================================================
     A*
     A*%%EC
     A                                      DSPSIZ(24 80 *DS3)
     A                                      PRINT
     A                                      ERRSFL
     A                                      CA03
     A                                      CA12
     A*
     A          R SFL1                      SFL
     A*
     A            SELECT         1   B  6  2
     A            OBJNAM        10   O  6  4
     A            OBJTYP        10   O  6 15
     A            OBJATR        10   O  6 26
     A            MBRNAM        10   O  6 37
     A*
     A*
     A          R SF1CTL                    SFLCTL(SFL1)
     A                                      SFLSIZ(0017)
     A                                      SFLPAG(0016)
     A                                      OVERLAY
     A N32                                  SFLDSP
     A N31                                  SFLDSPCTL
     A  31                                  SFLCLR
     A  90                                  SFLEND(*MORE)
     A                                      SFLCSRRRN(&CSRRRN1)
     A            RRN1           4S 0H      SFLRCDNBR
     A            CSRRRN1        5S 0H
     A                                  1  2'RSTOBJR '
     A                                  1 28'DISPLAY SAVF FILE CONTENTS'
     A                                      COLOR(WHT)
     A                                  1 71DATE
     A                                      EDTCDE(Y)
     A                                  2 29'API QSRLSAVF SAMPLE'
     A                                      COLOR(WHT)
     A                                  2 71TIME
     A                                  4  1'INPUT X TO SELECT'
     A                                  3  2'LIBRARY SAVED:'
     A            SAVLIB        10   O  3 17
     A                                  3 29'SAVE COMMAND:'
     A            SAVCMD        10   O  3 43
     A                                  3 54'RELEASE:'
     A            SAVRLS         6   O  3 63
     A                                  4 54'SAVED DATE:'
     A            SAVDAT         8   O  4 66
     A                                  5  4'OBJECT'
     A                                      COLOR(WHT)
     A                                  5 15'OBJ TYPE'
     A                                      COLOR(WHT)
     A                                  5 26'OBJ ATTR'
     A                                      COLOR(WHT)
     A                                  5 37'MEMBER'
     A                                      COLOR(WHT)
     A*
     A          R SFL3                      SFL
     A            OBJNAM        10   O  6  4
     A            OBJTYP        10   O  6 15
     A            MBRNAM        10   O  6 26
      *
     A          R SF3CTL                    SFLCTL(SFL3)
     A                                      SFLSIZ(0017)
     A                                      SFLPAG(0016)
     A                                      OVERLAY
     A N32                                  SFLDSP
     A N31                                  SFLDSPCTL
     A  31                                  SFLCLR
     A  90                                  SFLEND(*MORE)
     A            RRN3           4S 0H
     A                                  1  2'TFROBJR '
     A                                  1 28'DISPLAY SAVF FILE CONTENTS'
     A                                      COLOR(WHT)
     A                                  1 71DATE
     A                                      EDTCDE(Y)
     A                                  2 29'API QSRLSAVF SAMPLE'
     A                                  2 71TIME
     A                                  3  1'PRESS ENTER TO CONFIRM'
     A                                  4  2'LIBRARY SAVED:'
     A            SAVLIB        10   O  4 17
     A                                  4 29'SAVE COMMAND:'
     A            SAVCMD        10   O  4 43
     A                                  5  4'OBJECT'
     A                                      COLOR(WHT)
     A                                  5 15'OBJ TYPE'
     A                                      COLOR(WHT)
     A                                  5 26'MEMBER'
     A                                      COLOR(WHT)
     A          R FKEY1
     A*
     A                                 23  2'F3=Exit'
     A                                      COLOR(BLU)
     A                                 23 12'F12=Cancel'
     A                                      COLOR(BLU)



File  : QDRPGLESRC
Member: RSTOBJR
Type  : RPGLE
Usage : CRTBNDRPG RSTOBJR


      *===============================================================
      * To compile:
      *
      *      CRTRPGPGM  PGM(XXX/WRKSAVOBJR) SRCFILE(XXX/QRPGLESRC)
      *
      *===============================================================
      *. 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7
     H DEBUG  OPTION(*SRCSTMT:*NODEBUGIO)
     H DftActGrp(*NO) ActGrp(*CALLER)

     FRSTOBJD   cf   e             workstn
     F                                     sfile(sfl1:rrn1)
     F                                     sfile(sfl3:rrn3)
     F                                     infds(info)
      * Information data structure to hold attention indicator (AID) byte.
      * AID byte contains a code identifying the function
      * key used to return control to the program from the display file.
      * For more information see the DATA MANAGEMENT GUIDE.

     Dinfo             ds
     D cfkey                 369    369

      * Constants to compare to AID - F3, F12, F6, and ENTER keys.
      * Other values documented in DATA MANAGEMENT GUIDE.

     Dexit             C                   const(X'33')
     Dcancel           C                   const(X'3C')
     Dadd              C                   const(X'36')
     Denter            C                   const(X'F1')

     D savrrn          S              5S 0
     D confirm         S              1

     D GENDS           DS
     D  OFFLST               125    128B 0
     D  NUMLST               133    136B 0
     D  SIZENT               137    140B 0
     D LIBINF          DS            72
     D  SAVLIB                 1     10
     D  SAVCMD                11     20
     D  SAVCM6                11     16
      * The time at which the objects were saved in system time-stamp format
     D  SAVDAT                21     28
     D  SAVRLS                55     60
     D OBJINF          DS           204
     D  OBJNAM                 1     10
     D  OBJTYP                21     30
     D  OBJATR                31     40
     D  OBJTXT               155    194
     D MBRINF          DS            40
     D  FILNAM                 1     10
     D  FILLIB                11     20
     D  MBRNAM                21     30
     D                 DS                  INZ
     D  USRSPC                 1     20    INZ('DSPSAVF   QTEMP     ')
     D  STRPOS                41     44B 0
     D  STRLEN                45     48B 0
     D  LENSPC                49     52B 0
     D  STKCNT                53     56B 0
     D  APPSCP                57     60B 0
     D  EXTPRM                61     64B 0
     D  ERRCOD                65     68B 0
     D  FKEY                  69     72B 0
     D  VARLEN                73     76B 0
      * Parameters for Create User Space used
     D ExtendAttr      S             10    INZ('USRSPC    ')
     D InitialSiz      S             10I 0 INZ(1024)
     D InitialVal      S              1    INZ(X'00')
     D PublicAut       S             10    INZ('*ALL      ')
     D ReplaceSpc      S             10    INZ('*YES      ')
     D TextDescrp      S             50    INZ('User space for SAVF ListAPI')
      *
     D DTS             s             16a
     D LongJul         s             17a
     D YYMD            s             17a

      **-- Convert date & time:  -------------------------------------------
     D CvtDtf          Pr                  ExtPgm( 'QWCCVTDT' )
     D  CdInpFmt                     10a   Const
     D  CdInpVar                     17a   Const  Options( *VarSize )
     D  CdOutFmt                     10a   Const  Options( *VarSize )
     D  CdOutVar                     17a          Options( *VarSize )
     D  CdError                   32767a          Options( *VarSize )
      **
**********************************************************************************************
      *  Standard error code DS for API error handling
     D Error_Code      DS
     D  BytesProvd                   10I 0 INZ( %Size( Error_Code ))
     D  BytesAvail                   10I 0 INZ(0)
     D  Except_ID                     7
     D  Reserved                      1
     D  Exception                   256
      *===============================================================
     C     *ENTRY        PLIST
     C                   PARM                    SAVF             20
     C                   PARM                    OBJFLT           10
     C                   PARM                    TYPFLT           10
      *
      * Create User Space
     C                   EXSR      CRTUSRSPC
      *
      * Load user space with library level information
     C                   MOVEL     'SAVF0100'    FMTNAM            8
     C                   EXSR      LODSPC
      *
      * Get library level information from user space
     C                   CALL      'QUSRTVUS'
     C                   PARM                    USRSPC
     C                   PARM                    STRPOS
     C                   PARM                    STRLEN
     C                   PARM                    LIBINF
      *
      * Perform error checking selection
     C                   SELECT
      *
      * If no data issue message
     C     SAVLIB        WHENEQ    *BLANKS
     C                   MOVEL     '*EMPTY'      ERRDTA           10
      *
      * If unsupported save command issue message
     C     SAVCM6        WHENNE    'SAVLIB'
     C     SAVCM6        ANDNE     'SAVOBJ'
     C     SAVCM6        ANDNE     'SAVCHG'
     C                   MOVEL     SAVCMD        ERRDTA
      *
      * Otherwise process data
     C                   OTHER
      * Convert Save Date & time to *MDY format
     C                   CallP     CvtDtf( '*DTS'
     C                                   : SAVDAT
     C                                   : '*MDY'
     C                                   : DTS
     C                                   : Error_Code
     C                                   )
     C                   EVAL      SAVDAT = %subst(DTS:2:6)
     C                   EXSR      PROCES
     C                   ENDSL
      *
     C                   MOVE      *ON           *INLR

      *===============================================================
     C     CRTUSRSPC     BEGSR
      * Create a user space to hold savf list entries
     C                   CALL      'QUSCRTUS'
     C                   PARM                    USRSPC
     C                   PARM                    ExtendAttr
     C                   PARM                    InitialSiz
     C                   PARM                    InitialVal
     C                   PARM                    PublicAut
     C                   PARM                    TextDescrp
     C                   PARM                    ReplaceSpc
     C                   PARM                    Error_Code

     C                   ENDSR
      *===============================================================
     C     LODSPC        BEGSR
      *
      * Call the list save file API
     C                   CALL      'QSRLSAVF'
     C                   PARM                    USRSPC
     C                   PARM                    FMTNAM
     C                   PARM                    SAVF
     C                   PARM                    OBJFLT
     C                   PARM                    TYPFLT
     C                   PARM      *BLANKS       CNTHND           36
     C                   PARM      0             ERRCOD
      *
      * Retrieve the generic header
     C                   Z-ADD     1             STRPOS
     C                   Z-ADD     140           STRLEN
      *
     C                   CALL      'QUSRTVUS'
     C                   PARM                    USRSPC
     C                   PARM                    STRPOS
     C                   PARM                    STRLEN
     C                   PARM                    GENDS
      *
      * Calculate starting position and length
     C     OFFLST        ADD       1             STRPOS
     C                   Z-ADD     SIZENT        STRLEN
      *
     C                   ENDSR
      *===============================================================
     C     PROCES        BEGSR
      *
      * Load user space with object level information
     C                   MOVEL     'SAVF0200'    FMTNAM
     C                   EXSR      LODSPC
      *
     C                   ExSr      clrsfl

      * Get object level information from user space
     C                   DO        NUMLST
     C                   CALL      'QUSRTVUS'
     C                   PARM                    USRSPC
     C                   PARM                    STRPOS
     C                   PARM                    STRLEN
     C                   PARM                    OBJINF
      *
      * Exclude library objects from list
     C     OBJTYP        IFNE      '*LIB'
     C                   move      ' '           select
     C                   MOVE      *Blanks       MBRNAM
      *
      * Add a OBJINF list entry to the screen
     C                   Eval      rrn1 = rrn1 + 1
     C                   Write     sfl1
     C                   ENDIF
      *
      * Calculate position of next entry
     C                   ADD       SIZENT        STRPOS
     C                   ENDDO

      * Load user space with member level information
     C                   MOVEL     'SAVF0300'    FMTNAM
     C                   EXSR      LODSPC
      *
      * Get object level information from user space
     C                   DO        NUMLST
     C                   CALL      'QUSRTVUS'
     C                   PARM                    USRSPC
     C                   PARM                    STRPOS
     C                   PARM                    STRLEN
     C                   PARM                    MBRINF
      *
     C                   move      ' '           select
     C                   MOVEL     FILNAM        OBJNAM
     C                   MOVE      *Blanks       OBJTYP
      *
      * Add a list entry to the screen
     C                   Eval      rrn1 = rrn1 + 1
     C                   Write     sfl1
     C*                  ENDIF
      *
      * Calculate position of next entry
     C                   ADD       SIZENT        STRPOS
     C                   ENDDO
      *
      * Display Screen
     C                   Eval      savrrn = rrn1
     C                   Eval      rrn1 = 1
      *
     C                   Eval      *In90 = *on
     C                   If        rrn1 = 0
     C                   Eval      *in32 = *on
     C                   EndIf

      * Simply redisplay subfile until user hits Exit or Cancel

     C                   DoU       (cfkey = exit) or (cfkey = cancel)
     C                   Write     fkey1
     C                   ExFmt     sf1ctl
     C                   Exsr      procesSlt
     C                   If        confirm = '1'
     C                   leave
     C                   EndIf
     C                   EndDo
     C
     C                   ENDSR
      *===============================================================
     C     procesSlt     BEGSR
      *
      * clear sfl3
     C                   Eval      *in31 = *on
     C                   Eval      rrn3 = 0
     c                   Write     sf3ctl
     C                   Eval      *in31 = *off
      *
     C                   z-add     1             idx               5 0
     C                   Eval      confirm = '0'
     C                   DoW       idx <= savrrn

     C     idx           Chain     sfl1

     C                   If        select = 'X'
     C                   Z-add     idx           strrrn            4 0
     C                   Eval      rrn3 = rrn3 + 1
     C                   Write     sfl3
     C                   Eval      select = ' '
     C                   update    sfl1
     C                   EndIf

     C                   Eval      idx = idx + 1
     C                   EndDo
     C
     C                   If        rrn3 > 0
     C                   z-add     rrn3          savrrn3           4 0
     C                   Write     fkey1
     C                   ExFmt     sf3ctl
     C                   If        (cfkey <> exit) and (cfkey <> cancel)
     C                   Eval      confirm = '1'
     C                   Eval      idx = 1
     C                   DoW       idx <= savrrn3
     C     idx           Chain     sfl3

      * write your process select obj or member step under here.

     C                   Eval      idx = idx + 1
     C                   EndDo
     C                   EndIf
     C                   If        cfkey = cancel
     C                   Eval      cfkey = ' '
     C                   EndIf
     C                   EndIf
     C                   If        strrrn > 0
     C                   Z-add     strrrn        rrn1
     C                   Else
     C                   Z-add     csrrrn1       rrn1
     C                   EndIf
      *
     C                   ENDSR
      *********************************************************************
     C     ClrSfl        BegSr

      * Clear the subfile by activating SFLCLR and writing the subfile control
      * format.  Reset the subfile relative record number.

     C                   Eval      *in31 = *on
     C                   Eval      rrn1 = 0
     C                   Write     sf1ctl
     C                   Eval      *in31 = *off
      *
     C                   EndSr




2003-06-10 如何動態選取要儲存的物件或原始檔成員(TFROBJ) ?


如何動態選取要儲存的物件或原始檔成員(TFROBJ) ?

有時候由於檔案或原始檔某些成員需要傳至另一個 AS/400(iSeries) 系統,
所以需要使用 SAVOBJ 的方式儲存,但是又須麻煩的一個一個輸入指定物件或原
始檔成員,所以我寫一個程式針對同一個 Library 中的物件或原始檔中
成員讓使用者選取,並將所選儲存至同一 Library SAVF 中,然後你可以
使用此 SAVF 利用 FTP 或 SNDNETF 或 SAVRSTOBJ 傳輸至另一系統中。

此程式中使用 Source-Library -> 欲儲存的 Library
             Targrt-Library -> 欲 Restored 到目的地 Library,目前未使用,若需要將傳輸及自動 Restored 時,你可以利用此參數。

二個參數,並將選取的物件存至 Source-Library 中以同 Source-Library 為名的 SAVF。


File  : QCLSRC
Member: TFROBJC
Type  : CLP
Usage : CRTCLPGM TFROBJC


             PGM  (&SRCLIB &TOLIB)

             DCL        VAR(&SRCLIB) TYPE(*CHAR) LEN(10)
             DCL        VAR(&TOLIB)  TYPE(*CHAR) LEN(10)
             DCL        VAR(&SAVOBJTYP) TYPE(*CHAR) LEN(10)
             DCL        VAR(&CURRCD) TYPE(*DEC) LEN(10 0)

             DCLF       QAFDBASI
/* OUTPUT OBJ DESCRIPTION TO OUTFILE */
             DSPOBJD    OBJ(&SRCLIB/*ALL) OBJTYPE(*ALL) +
                          OUTPUT(*OUTFILE) OUTFILE(QTEMP/DSPOBJ)

/* OUTPUT FILE DESCRIPTION TO OUTFILE */
             DSPFD      FILE(&SRCLIB/*ALL) TYPE(*BASATR) +
                          OUTPUT(*OUTFILE) OUTFILE(QTEMP/DSPFD)
             OVRDBF     FILE(QAFDBASI) TOFILE(QTEMP/DSPFD)

             DLTF       DSPMBRLIST
             MONMSG     CPF0000
 NEXT:
             RCVF
             MONMSG  CPF0864 EXEC(GOTO MBRLISTEND)
             IF    (&ATDTAT = 'S') +
             DSPFD      FILE(&ATLIB/&ATFILE) TYPE(*MBRLIST) +
                          OUTPUT(*OUTFILE) +
                          OUTFILE(QTEMP/DSPMBRLIST) OUTMBR(*FIRST *ADD)
             GOTO NEXT

 MBRLISTEND:
             DLTF QTEMP/SAVMBRLIST
             MONMSG CPF0000
             /* CREATE TEMP FILE TO SAVE SAVED MEMBER NAME AND OBJ */
             CRTDUPOBJ  OBJ(QAFDMBRL) FROMLIB(*LIBL) OBJTYPE(*FILE) +
                          TOLIB(QTEMP) NEWOBJ(SAVMBRLIST)
             ADDPFM     FILE(QTEMP/SAVMBRLIST) MBR(SAVMBRLIST)

 /* SELECT OBJECT TO SAVED */
             CALL TFROBJR
 /* CONSTRUCT SAVRST COMMAND */
             RTVMBRD    FILE(QTEMP/SAVMBRLIST) NBRCURRCD(&CURRCD)
             IF (&CURRCD  > 0) +
                 CALL TFROBJC1 (&SRCLIB &TOLIB)

             ENDPGM


File  : QCLSRC
Member: TFROBJC1
Type  : CLP
Usage : CRTCLPGM TFROBJC1


             PGM  (&SRCLIB &TOLIB)

             DCL        VAR(&SRCLIB) TYPE(*CHAR) LEN(10)
             DCL        VAR(&TOLIB)  TYPE(*CHAR) LEN(10)
             DCL        VAR(&SAVOBJTYP) TYPE(*CHAR) LEN(10)
             DCL        VAR(&CMDSTR) TYPE(*CHAR) LEN(3000) +
                          VALUE('SAVOBJ OBJ(')
             DCL        VAR(&MLFILES) TYPE(*CHAR) LEN(10) +
                          VALUE('          ')
             DCL        VAR(&SAVFILE) TYPE(*CHAR) LEN(10)
             DCL        VAR(&SAVOBJS) TYPE(*CHAR) LEN(7) +
                          VALUE('SAVOBJ ')
             DCL        VAR(&OBJS) TYPE(*CHAR) LEN(4) VALUE('OBJ(')
             DCL        VAR(&OBJSS) TYPE(*CHAR) LEN(150)
             DCL        VAR(&LIBS) TYPE(*CHAR) LEN(4) VALUE('LIB(')
             DCL        VAR(&DEVS) TYPE(*CHAR) LEN(11) +
                          VALUE('DEV(*SAVF) ')
             DCL        VAR(&OBJTYPS) TYPE(*CHAR) LEN(14) +
                          VALUE('OBJTYPE(*ALL) ')
             DCL        VAR(&SAVFS) TYPE(*CHAR) LEN(15) VALUE('SAVF(')
             DCL        VAR(&FILEMBRS) TYPE(*CHAR) LEN(15) +
                          VALUE('FILEMBR(')
             DCL        VAR(&LEFT) TYPE(*CHAR) LEN(1) VALUE('(')
             DCL        VAR(&RIGHT) TYPE(*CHAR) LEN(2) VALUE(') ')
             DCL        VAR(&SLASH) TYPE(*CHAR) LEN(1) VALUE('/')
             DCL        VAR(&MBRS) TYPE(*CHAR) LEN(300)
             DCL        VAR(&WITHMBRS) TYPE(*CHAR) LEN(1)

             DCLF       QAFDMBRL

             CHGVAR     &SAVFILE &SRCLIB
             DLTF       &SRCLIB/&SAVFILE
             MONMSG     CPF0000
             CRTSAVF    FILE(&SRCLIB/&SAVFILE)

             OVRDBF     FILE(QAFDMBRL) TOFILE(QTEMP/SAVMBRLIST)

 NEXT:
             RCVF
             MONMSG  CPF0864 EXEC(GOTO MBRLISTEND)
             IF         (&MLFILES *NE &MLFILE) DO
 /*                     SAVOBJ +
                          OBJ(FILE) LIB(SRCLIB) DEV(*SAVF) +
                          OBJTYPE(*FILE) SAVF(SRCLIB/SAVF) +
                          FILEMBR((FILE1 (MBR1 MBR2)) (FILE2 (MBR1 +
                          MBR2)))  */
             IF         (&MLFILES *NE '          '  *AND +
                         &MLNAME  *NE '          ') DO
             CHGVAR  &MBRS +
                       (&MBRS *TCAT &RIGHT *TCAT &RIGHT)
             ENDDO

             CHGVAR &MLFILES &MLFILE
             CHGVAR &OBJSS (&OBJSS *BCAT &MLFILE)

             IF (&MLNAME *NE '          ') DO
              CHGVAR  &MBRS +
                      (&MBRS *BCAT &LEFT *CAT &MLFILE *BCAT &LEFT)
              CHGVAR  &WITHMBRS '1'
             ENDDO

             ENDDO

             IF (&MLNAME *NE '          ') +
                CHGVAR  &MBRS +
                        (&MBRS *BCAT &MLNAME)

             GOTO NEXT
 MBRLISTEND:

             DLTOVR     FILE(*ALL)
             CHGVAR  &CMDSTR +
                    (&SAVOBJS *CAT +
                     &OBJS *TCAT &OBJSS *TCAT &RIGHT *CAT +
                     &LIBS *TCAT &MLLIB  *TCAT &RIGHT *CAT +
                     &DEVS *CAT +
                     &OBJTYPS *CAT +
                     &SAVFS *TCAT &SRCLIB *TCAT &SLASH *CAT +
                                 &SAVFILE *TCAT &RIGHT)

             CHGVAR  &MBRS +
                       (&MBRS *TCAT &RIGHT *TCAT &RIGHT *TCAT &RIGHT)
             IF (&WITHMBRS = '1') DO
             CHGVAR &CMDSTR +
                    (&CMDSTR *BCAT &FILEMBRS *CAT &MBRS)
             ENDDO

             CALL QCMDEXC (&CMDSTR 3000)
             SNDPGMMSG  MSG('SAVF' *BCAT &SAVFILE *BCAT 'created in' +
                          *BCAT &SRCLIB *TCAT '.') TOPGMQ(*PRV +
                          (TFROBJC))

             ENDPGM


File  : QDDSSRC
Member: TFROBJD
Type  : DSPF
Usage : CRTDSPF TFROBJD


      *===============================================================
      *
      * To compile:
      *
      *      CRTDSPF  FILE(XXX/TFROBJD) SRCFILE(XXX/QDDSSRC)
      *
      *===============================================================
     A*
     A*%%EC
     A                                      DSPSIZ(24 80 *DS3)
     A                                      PRINT
     A                                      ERRSFL
     A                                      CA03
     A                                      CA12
     A*
     A          R SFL1                      SFL
     A*
     A            SELECT         1   B  6  2
     A            MLFILE        10   O  6  4
     A            MLNAME        10   O  6 15
     A            MLCDAT         6   O  6 26
     A            MLCHGD         6   O  6 33
     A            ODOBNM        10   O  6 40
     A            ODOBTP         8   O  6 51
     A            ODOBOW        10   O  6 60
     A            ODLDAT         6   O  6 71
     A            ODCDAT         6   H
     A*
     A*
     A          R SF1CTL                    SFLCTL(SFL1)
     A                                      SFLSIZ(0017)
     A                                      SFLPAG(0016)
     A                                      OVERLAY
     A N32                                  SFLDSP
     A N31                                  SFLDSPCTL
     A  31                                  SFLCLR
     A  90                                  SFLEND(*MORE)
     A                                      SFLCSRRRN(&CSRRRN1)
     A            RRN1           4S 0H      SFLRCDNBR
     A            CSRRRN1        5S 0H
     A                                  1  2'TFROBJR '
     A                                  1 28'Your Company name'
     A                                      COLOR(WHT)
     A                                  1 71DATE
     A                                      EDTCDE(Y)
     A                                  2 29'Select Object or SRC Member to save'
     A                                      COLOR(WHT)
     A                                  2 71TIME
     A                                  3  1'X'
     A                                  4  3'LIBRARY:'
     A            SAVLIB        10   O  4 12
     A                                  5  4'FILE'
     A                                      COLOR(WHT)
     A                                  5 15'MEMBER'
     A                                      COLOR(WHT)
     A                                  4 26'CRT'
     A                                      COLOR(WHT)
     A                                  5 26'DATE'
     A                                      COLOR(WHT)
     A                                  3 33'LAST'
     A                                      COLOR(WHT)
     A                                  4 33'CHANGE'
     A                                      COLOR(WHT)
     A                                  5 33'DATE'
     A                                      COLOR(WHT)
     A                                  5 40'OBJECT'
     A                                      COLOR(WHT)
     A                                  5 51'TYPE'
     A                                      COLOR(WHT)
     A                                  5 60'OWNER'
     A                                      COLOR(WHT)
     A                                  3 71'LAST'
     A                                      COLOR(WHT)
     A                                  4 71'CHANGED'
     A                                      COLOR(WHT)
     A                                  5 71'DATE'
     A                                      COLOR(WHT)
     A*
     A          R SFL2                      SFL
     A*
     A            SELECT         1   B  6  2
     A            ODLBNM        10   O  6  4
     A            ODOBNM        10   O  6 15
     A            ODOBTP         8   O  6 26
     A            ODOBAT        10   O  6 37
     A            ODCDAT         6   O  6 48
     A            ODLDAT         6   O  6 55
     A            ODOBOW        10   O  6 62
     A          R SF2CTL                    SFLCTL(SFL2)
     A                                      SFLSIZ(0017)
     A                                      SFLPAG(0016)
     A                                      OVERLAY
     A N32                                  SFLDSP
     A N31                                  SFLDSPCTL
     A  31                                  SFLCLR
     A  90                                  SFLEND(*MORE)
     A            RRN2           4S 0H
     A                                  1  2'TFROBJR '
     A                                  1 28'Your Company name'
     A                                      COLOR(WHT)
     A                                  1 71DATE
     A                                      EDTCDE(Y)
     A                                  2 34''
     A                                      COLOR(WHT)
     A                                  2 71TIME
     A                                  3  1'X'
     A                                  5  4'LIBRARY'
     A                                      COLOR(WHT)
     A                                  5 15'OBJECT '
     A                                      COLOR(WHT)
     A                                  5 26'OBJTYPE'
     A                                      COLOR(WHT)
     A                                  5 37'ATTR'
     A                                      COLOR(WHT)
     A                                  4 48'CRT'
     A                                      COLOR(WHT)
     A                                  5 48'DATE'
     A                                      COLOR(WHT)
     A                                  4 48'CHG'
     A                                      COLOR(WHT)
     A                                  5 55'DATE'
     A                                      COLOR(WHT)
     A                                  5 62'OWNER'
     A                                      COLOR(WHT)
     A          R SFL3                      SFL
     A            SAVOBJ        10   O  6  4
     A            SAVMBR        10   O  6 15
     A            MLCDAT         6   O  6 27
     A            MLCHGD         6   O  6 34
     A            ODOBOW        10   O  6 41
      *
     A          R SF3CTL                    SFLCTL(SFL3)
     A                                      SFLSIZ(0017)
     A                                      SFLPAG(0016)
     A                                      OVERLAY
     A N32                                  SFLDSP
     A N31                                  SFLDSPCTL
     A  31                                  SFLCLR
     A  90                                  SFLEND(*MORE)
     A            RRN3           4S 0H
     A                                  1  2'TFROBJR '
     A                                  1 28'Your Company Name'
     A                                      COLOR(WHT)
     A                                  1 71DATE
     A                                      EDTCDE(Y)
     A                                  2 34'Confirm Selection'
     A                                  2 71TIME
     A                                  3  1'Please press Enter to confirm'
     A                                  4  3'LIBRARY:'
     A            SAVLIB        10   O  4 12
     A                                  5  4'OBJECT     MEMBER'
     A                                      COLOR(WHT)
     A                                  4 27'CRT'
     A                                      COLOR(WHT)
     A                                  5 27'DATE'
     A                                      COLOR(WHT)
     A                                  3 34'LAST'
     A                                      COLOR(WHT)
     A                                  4 34'CHG'
     A                                      COLOR(WHT)
     A                                  5 34'DATE'
     A                                      COLOR(WHT)
     A                                  5 41'OWNER'
     A                                      COLOR(WHT)
     A          R FKEY1
     A*
     A                                 23  2'F3=Exit'
     A                                      COLOR(BLU)
     A                                 23 12'F12=Cancel'
     A                                      COLOR(BLU)


File  : QRPGLESRC
Member: TFROBJR
Type  : RPGLE
Usage : CRTBNDRPG TFROBJR


      *===============================================================
      *
      * To compile:
      *
      *      CRTBNDRPG  PGM(XXX/TFROBJR) SRCFILE(XXX/QRPGLESRC)
      *
      *===============================================================

     H DEBUG  OPTION(*SRCSTMT:*NODEBUGIO)
     H DftActGrp(*NO) ActGrp(*CALLER)

     FTFROBJD   cf   e             workstn
     F                                     sfile(sfl1:rrn1)
     F                                     sfile(sfl2:rrn2)
     F                                     sfile(sfl3:rrn3)
     F                                     infds(info)

     FDSPOBJ    if   e             disk
     FDSPMBRLISTif   e             disk
     FSAVMBRLISTO    e             disk    rename(QWHFDML : SAVMBRR)

      * Information data structure to hold attention indicator (AID) byte.
      * AID byte contains a code identifying the function
      * key used to return control to the program from the display file.
      * For more information see the DATA MANAGEMENT GUIDE.

     Dinfo             ds
     D cfkey                 369    369

      * Constants to compare to AID - F3, F12, F6, and ENTER keys.
      * Other values documented in DATA MANAGEMENT GUIDE.

     Dexit             C                   const(X'33')
     Dcancel           C                   const(X'3C')
     Dadd              C                   const(X'36')
     Denter            C                   const(X'F1')

      * Input parameter: Source Type or not

     D savrrn          S              5S 0
     D confirm         S              1

      * Clear the subfile, then call the recursive NextLevel procedure
     C                   ExSr      clrsfl
     C                   Exsr      loadsfl
     C                   Eval      *In90 = *on
     C                   If        rrn1 = 0
     C                   Eval      *in32 = *on
     C                   EndIf

     C*                  Eval      csrrrn1 = 1

      * Simply redisplay subfile until user hits Exit or Cancel

     C                   DoU       (cfkey = exit) or (cfkey = cancel)
     C                   Write     fkey1
     C                   ExFmt     sf1ctl
     C                   Exsr      prcsfl
     C                   If        confirm = '1'
     C                   leave
     C                   EndIf
     C                   EndDo

      * Close files and terminate.

     C                   Eval      *inlr = *on

      *********************************************************************
     C     ClrSfl        BegSr

      * Clear the subfile by activating SFLCLR and writing the subfile control
      * format.  Reset the subfile relative record number.

     C                   Eval      *in31 = *on
     C                   Eval      rrn1 = 0
     C                   Write     sf1ctl
     C                   Eval      *in31 = *off
      *
     C                   EndSr

      *********************************************************************
     C     Loadsfl       Begsr

      * Loop until EOF is encountered.
      * read DSPMBRLIST
     C                   Read      DSPMBRLIST
     C                   DoW       not %eof

     C                   Eval      select = ' '

      * Update the global RRN counter, and write the new subfile record.

     C                   Eval      rrn1 = rrn1 + 1
     C                   Write     sfl1
     C                   Read      DSPMBRLIST
     C                   EndDo
     C                   Eval      SAVLIB = MLLIB

      * read DSPOBJ
     C                   Reset                   SFL1
     C                   Read      DSPOBJ
     C                   DoW       not %eof

     C                   Eval      select = ' '

      * Update the global RRN counter, and write the new subfile record.

     C                   Eval      rrn1 = rrn1 + 1
     C                   Write     sfl1
     C                   Read      DSPOBJ
     C                   EndDo

     C                   Eval      savrrn = rrn1
     C                   Eval      rrn1 = 1

     C                   EndSr
      *********************************************************************
     C     PrcSfl        Begsr
      * clear sfl3
     C                   Eval      *in31 = *on
     C                   Eval      rrn3 = 0
     c                   Write     sf3ctl

     C                   Eval      *in31 = *off
     C                   z-add     1             idx               5 0
     C                   Eval      confirm = '0'
     C                   DoW       idx < savrrn

     C     idx           Chain     sfl1

     C                   If        select = 'X'

     C                   If        MLFILE <> *blanks
     C                   Eval      SavLIB  = SAVLIB
     C                   Eval      SavOBJ  = MLFILE
     C                   Eval      SavMBR  = MLNAME
     C                   Else
     C                   Eval      SavLIB  = SAVLIB
     C                   Eval      SavOBJ  = ODOBNM
     C                   Eval      SavMBR  = *BLANKS
     C                   Eval      MLCDAT  = ODCDAT
     C                   Eval      MLCHGD  = ODLDAT
     C                   EndIf

     C                   Z-add     idx           strrrn            4 0
     C                   Eval      rrn3 = rrn3 + 1
     C                   Write     sfl3
     C                   Eval      select = ' '
     C                   update    sfl1
     C                   EndIf

     C                   Eval      idx = idx + 1
     C                   EndDo
     C
     C                   If        rrn3 > 0
     C                   z-add     rrn3          savrrn3           4 0
     C                   Write     fkey1
     C                   ExFmt     sf3ctl
     C                   If        (cfkey <> exit) and (cfkey <> cancel)
     C                   Eval      confirm = '1'
     C                   Eval      idx = 1
     C                   Reset                   SAVMBRR
     C                   DoW       idx <= savrrn3
     C     idx           Chain     sfl3
     C                   Eval      MLLIB = SAVLIB
     C                   Eval      MLFILE= SAVOBJ
     C                   EVAL      MLNAME= SAVMBR
     C                   EVAL      MLSEU2= ODOBOW
     C                   Write     SAVMBRR
     C                   Eval      idx = idx + 1
     C                   EndDo
     C                   EndIf
     C                   EndIf
     C                   If        strrrn > 0
     C                   Z-add     strrrn        rrn1
     C                   Else
     C                   Z-add     csrrrn1       rrn1
     C                   EndIf
     C                   EndSr

            

由於此程式利用 QTEMP 暫存檔處理,所以安裝程序須照下列方式,否則無法編譯完成:
1. 將 TFROBJC 程式後段修改如下:
 /* SELECT OBJECT TO SAVED */
 /*            CALL TFROBJR */
 /* CONSTRUCT SAVRST COMMAND */
 /*            RTVMBRD    FILE(QTEMP/SAVMBRLIST) NBRCURRCD(&CURRCD)  */
/*             IF (&CURRCD  > 0) +     */
/*                 CALL TFROBJC1 (&SRCLIB &TOLIB) */

儲存,執行編譯 CRTCLPGM TFROBJC完成後,
執行 CALL TFROBJC ('QGPL' 'QGPL' '*ALL')產生暫存檔 QTEMP/SAVMBRLIST 供 TFROBJR 使用。

2. CRTDSPF TFROBJD 

3. CRTBNDRPG TFROBJR

4. CRTCLPGM TFROBJC1

5. 回復 TFROBJC 後段為:
 /* SELECT OBJECT TO SAVED */
             CALL TFROBJR
 /* CONSTRUCT SAVRST COMMAND */
             RTVMBRD    FILE(QTEMP/SAVMBRLIST) NBRCURRCD(&CURRCD)
             IF (&CURRCD  > 0) +
                 CALL TFROBJC1 (&SRCLIB &TOLIB)

儲存,執行編譯 CRTCLPGM TFROBJC 完成安裝。

執行程式語法:
CALL TFROBJC ('source-library' 'target-library')
            




2003-04-28 如何快速得知 IFS 目錄下的檔案大小?


如何快速得知 IFS 目錄下的檔案大小?

IBM 提供 V5R1 PTF SI05156 (superseded by SI05856) 及 V5R2 PTF SI05155 
可以執行程式指定目錄及可以快速得知該目錄下檔案大小。

For the full report:
  call qsrsrv parm("METRICS" '/')

To omit QNTC, QNETWARE, QLANSRV use the following.
  call qsrsrv parm("METRICS" '/' "EPFS")

Or for a specific directory.
  call qsrsrv parm("METRICS" '/mydir/mysubdir') 
            



2003-01-06 報表安全系列五:如何限制指令 CHGSPLFA 的使用, 防止使用者更改其他人報表的屬性?


報表安全系列五:如何限制指令 CHGSPLFA 的使用, 防止使用者更改其他人報表的屬性?

有鑑於 報表的安全性管理,iSeries(AS/400) 作業系統並未提供完善的保護,我將建議使用 VCP 命令
語法檢核程式來做安全空管,

報表安全系列一 :如何限制指令 WRKSPLF 的使用, 防止使用者察看全系統的報表 ?

報表安全系列二 :如何限制指令 DSPSPLF 的使用, 防止使用者於 WRKSPLF 畫面中瀏覽全系統的報表 ?

報表安全系列三 :如何限制指令 DLTSPLF  的使用, 防止使用者刪除其他人的報表 ?

報表安全系列四 :如何限制指令 CPYSPLF  的使用, 防止使用者複製其他人的報表 ?

報表安全系列五 :如何限制指令 CHGSPLFA  的使用, 防止使用者更改其他人報表的屬性? 

有 *SPLCTL 權限的人可以更改系統上任何報表的屬性,如印表機,Outq 輸出佇列..等屬性,
要如何防止非授權使用者更改機密敏感的報表資料屬性,為了要防止這種情形發生,只能從命
令檢核程式著手,此範例與其他相關報表命令
(WRKSPLF, DSPSPLF, DLTSPLF, CPYSPLF)的檢核程式一樣,限制除了 QSECOFR, QSYSOPR
之外,使用者僅能刪除自己的報表,同樣也分 OS V5R1(含)以前及OS V5R2(含)以後的版本。

CHGSPLFAVC 命令語法檢核程式 for V5R1

File  : QCLSRC
Member: CHGSPLFAVC
Type  : CLP
OS version: V5R1 以前
Usage : CRTCLPGM mylib/CHGSPLFAVC
        CHGCMD CMD(CHGSPLFA) VLDCKR(mylib/CHGSPLFAVC) 
        若執行有問題或不使用命令語法檢核程式時,執行
        CHGCMD CMD(CHGSPLFA) VLDCKR(*NONE) 


  /*  Program : CHGSPLFVAVC                                     */
  /*  System  : iSeries 400                                     */
  /*                                                            */
  /*  Validity Checking program for command CHGSPLFA            */
  /*                                                            */
  /*  Example :   protecting an OUTQ from a USER                */
  /*                                                            */
  /*      CHGCMD CMD(CHGSPLFA) VLDCKR(MYLIB/CHGSPLFVAL)         */
  /*  To reset (in case you made errors) :                      */
  /*      CHGCMD CMD(CHGSPLFA) VLDCKR(*NONE)                    */

 CHGSPLFVAL: PGM        PARM(&P1 &P2 &P3 &P4 &P5 &P6 &P7 &P8 &P9 +
                          &P10 &P11 &P12 &P13 &P14 &P15 &P16 &P17 +
                          &P18 &P19 &P20 &P21 &P22 &P23 &P24 &P25 +
                          &P26 &P27 &P28 &P29 &P30 &P31 &P32 &P33 +
                          &P34 &P35 &P36 &P37 &P38 &P39)

             DCL        VAR(&P1) TYPE(*CHAR) LEN(1)
             DCL        VAR(&P2) TYPE(*CHAR) LEN(10) /* FILE    */
             DCL        VAR(&P3) TYPE(*CHAR) LEN(26) /* JOB     */
             DCL        VAR(&P4) TYPE(*CHAR) LEN(1)
             DCL        VAR(&P5) TYPE(*CHAR) LEN(44) /* SELECT  */
             DCL        VAR(&P6) TYPE(*CHAR) LEN(10) /* PRINTER */
             DCL        VAR(&P7) TYPE(*CHAR) LEN(1)
             DCL        VAR(&P8) TYPE(*CHAR) LEN(20)  /* OUTQ       */
             DCL        VAR(&P9) TYPE(*CHAR) LEN(10)  /* OUTQ LIB   */
             DCL        VAR(&P10) TYPE(*CHAR) LEN(1)
             DCL        VAR(&P11) TYPE(*CHAR) LEN(1)
             DCL        VAR(&P12) TYPE(*CHAR) LEN(1)
             DCL        VAR(&P13) TYPE(*CHAR) LEN(1)
             DCL        VAR(&P14) TYPE(*CHAR) LEN(1)
             DCL        VAR(&P15) TYPE(*CHAR) LEN(1)
             DCL        VAR(&P16) TYPE(*CHAR) LEN(1)
             DCL        VAR(&P17) TYPE(*CHAR) LEN(1)
             DCL        VAR(&P18) TYPE(*CHAR) LEN(1)
             DCL        VAR(&P19) TYPE(*CHAR) LEN(1)
             DCL        VAR(&P20) TYPE(*CHAR) LEN(1)
             DCL        VAR(&P21) TYPE(*CHAR) LEN(1)
             DCL        VAR(&P22) TYPE(*CHAR) LEN(1)
             DCL        VAR(&P23) TYPE(*CHAR) LEN(1)
             DCL        VAR(&P24) TYPE(*CHAR) LEN(1)
             DCL        VAR(&P25) TYPE(*CHAR) LEN(1)
             DCL        VAR(&P26) TYPE(*CHAR) LEN(1)
             DCL        VAR(&P27) TYPE(*CHAR) LEN(1)
             DCL        VAR(&P28) TYPE(*CHAR) LEN(1)
             DCL        VAR(&P29) TYPE(*CHAR) LEN(1)
             DCL        VAR(&P30) TYPE(*CHAR) LEN(1)
             DCL        VAR(&P31) TYPE(*CHAR) LEN(1)
             DCL        VAR(&P32) TYPE(*CHAR) LEN(1)
             DCL        VAR(&P33) TYPE(*CHAR) LEN(1)
             DCL        VAR(&P34) TYPE(*CHAR) LEN(1)
             DCL        VAR(&P35) TYPE(*CHAR) LEN(1)
             DCL        VAR(&P36) TYPE(*CHAR) LEN(1)
             DCL        VAR(&P37) TYPE(*CHAR) LEN(1)
             DCL        VAR(&P38) TYPE(*CHAR) LEN(1)
             DCL        VAR(&P39) TYPE(*CHAR) LEN(1)
             DCL        VAR(&OUTQ) TYPE(*CHAR) LEN(10)
             DCL        VAR(&SPLUSR) TYPE(*CHAR) LEN(10)
             DCL        VAR(&USER) TYPE(*CHAR) LEN(10)
             DCL        VAR(&JOBNAME) TYPE(*CHAR) LEN(10)
             DCL        VAR(&JOBNBR) TYPE(*CHAR) LEN(6)

             RTVJOBA    JOB(&JOBNAME) USER(&USER) NBR(&JOBNBR)
             CHGVAR     &OUTQ      %SST(&P8 1 10)
             IF         (%SST(&P3 1 1) *EQ '*')  DO
                        CHGVAR     &SPLUSR &USER
                        CHGVAR     %SST(&P3  1  10) &JOBNAME
                        CHGVAR     %SST(&P3 11  10) &USER
                        CHGVAR     %SST(&P3 21   6) &JOBNBR
                 ENDDO
             ELSE                                +
                        CHGVAR     &SPLUSR %SST(&P3 11 10)

  /*  Check here your criteria.                                */
  /*  (f.e. Userprofile ...                                    */

  /*  If a user is authorized based on your criteria, then     */
  /*  RETURN.                                                  */
  /*  If he is not authorized then goto NOT_OK.                */
  /*  In that case an escape message is send.                  */

 /* USER QSECOFR, QSYSOPR UNLIMIT ACCESS SPOOLED FILE */
             IF         ((&USER *EQ 'QSECOFR') *OR +
                         (&USER *EQ 'QSYSOPR'))    +
                          THEN(GOTO OK)

 /* LIMIT ONLY SPOOLED CREATION USER CAN BROWSE OWN'S SPOOLED FILE */
             IF         COND(&USER *NE &SPLUSR) +
                          THEN(GOTO NOT_OK)
 /* LIMIT OUTQ FOR SPECIFIED USER */
             IF         COND(&USER *EQ 'JOE' *AND &P8 *EQ 'MYOUTQ') +
                          THEN(GOTO NOT_OK)

 OK:
             RETURN

 NOT_OK:     SNDPGMMSG  MSGID(CPD0006) MSGF(QCPFMSG) +
                          MSGDTA('0000' *CAT 'You are not +
                          authorized to output queue MYOUTQ') +
                          MSGTYPE(*DIAG)

             SNDPGMMSG  MSGID( CPF0002 )                          +
                        MSGF( QSYS/QCPFMSG )                      +
                        MSGTYPE( *ESCAPE )

 END:        ENDPGM

            
            
CPYSPLF 命令語法檢核程式 for V5R2

因為 CHGSPLFA 命令於 OS V5R2 中的參數個數增加至 42 個,而 CLP 的 PARM 參數僅能
接收 40 個參數,所以我改用 RPGLE 來撰寫命令語法檢核程式。

File  : QRPGLESRC
Member: CHGSPLFAVR
Type  : RPGLE
OS version: V5R2 以後
Usage : CRTBNDRPG mylib/CHGSPLFAVR
        CHGCMD CMD(CHGSPLFA) VLDCKR(mylib/CHGSPLFAVR) 
        若執行有問題或不使用命令語法檢核程式時,執行
        CHGCMD CMD(CHGSPLFA) VLDCKR(*NONE) 


      ****************************************************************************************
      * CHGSPLFA VCP for iSeries V5R2
      *
  /*  * Validity Checking program for command CHGSPLFA
  /*
  /*  * Example :   protecting an SPOOL From a USER
  /*  *
  /*  *   CHGCMD CMD(CHGSPLFA) VLDCKR(MYLIB/CHGSPLFAVR)
  /*  * To reset (in case you made errors) :
  /*  *    CHGCMD CMD(CHGSPLFA) VLDCKR(*NONE)
      ****************************************************************************************

      ****************************************************************************************
      *       D E F I N I T I O N     S P E C I F I C A T I O N      *
      ****************************************************************
      *
      *  Program Status Data Structure
      *
     D PGMDS          SDS
     D  Pgmq##           *PROC
     D  ErrorSts         *STATUS
     D  PrvStatus             16     20S 0
     D  SrcLinNum             21     28
     D  Routine          *ROUTINE
     D  NumParms         *PARMS
     D  ExcpType              40     42
     D  ExcpNum               43     46
      *
     D  PgmLib                81     90
     D  ExcpData              91    170
     D  ExcpId               171    174
     D  LastFile             201    208
     D  FileErr              209    243
     D  JobName              244    253
     D  User                 254    263
     D  JobNumA              264    269
     D  JobNum               264    269S 0
     D  JobDate              270    275S 0
     D  RunDate              276    281S 0
     D  RunTime              282    287S 0
     D  PgmCrtDt             288    293
     D  PgmCrtTm             294    299
     D  CmplrLvl             300    303
     D  SrcFile              304    313
     D  SrcLib               314    323
     D  SrcMbr               324    333
     D  ProcPgm              334    343
     D  ProcMod              344    353

     D  cmd_str        S           1024    INZ
     D  cmd_len        S             15P 5 INZ(1024)
     D  msg_str        S            256

     D vApiErrDs       ds
     D  vbytpv                       10i 0 inz(%size(vApiErrDs))                bytes provided
     D  vbytav                       10i 0 inz(0)                               bytes returned
     D  vmsgid                        7a                                        error msgid
     D  vresvd                        1a                                        reserved
     D  vrpldta                      50a                                        replacement data

     D qmhsndpm        PR                  ExtPgm('QMHSNDPM')                   SEND MESSAGES
     D                                7    const                                ID
     D                               20    const                                FILE
     D                               73    const                                TEXT
     D                               10i 0 const                                LENGTH
     D                               10    const                                TYPE
     D                               10    const                                QUEUE
     D                               10i 0 const                                STACK ENTRY
     D                                4    const                                KEY
     Db                                    like(vApiErrDS)

      * QCMDEXC - Prototyped Call

     D qcmdexc         PR                  EXTPGM('QCMDEXC')
     D  cmd_str                    1024    OPTIONS(*VARSIZE) CONST
     D  cmd_len                      15P 5 CONST

     C     *entry        Plist
     C                   Parm                    P1                1
     C                   Parm                    P2               10            File
     C                   Parm                    P3               26            Job
     C                   Parm                    P4                4            Splnbr
     C                   Parm                    P5                8            Sysname
     C                   Parm                    P6                6
     C                   Parm                    P7               44
     C                   Parm                    P8               10            Device
     C                   Parm                    P9                1
     C                   Parm                    P10              20
     C                   Parm                    P11               1
     C                   Parm                    P12               1
     C                   Parm                    P13               1
     C                   Parm                    P14               1
     C                   Parm                    P15               1
     C                   Parm                    P16               1
     C                   Parm                    P17               1            Outq
     C                   Parm                    P18               1
     C                   Parm                    P19               1
     C                   Parm                    P21               1
     C                   Parm                    P22               1
     C                   Parm                    P23               1
     C                   Parm                    P24               1
     C                   Parm                    P25               1
     C                   Parm                    P26               1
     C                   Parm                    P27               1
     C                   Parm                    P28               1
     C                   Parm                    P29               1
     C                   Parm                    P30               1
     C                   Parm                    P31               1
     C                   Parm                    P32               1
     C                   Parm                    P33               1
     C                   Parm                    P34               1
     C                   Parm                    P35               1
     C                   Parm                    P36               1
     C                   Parm                    P37               1
     C                   Parm                    P38               1
     C                   Parm                    P39               1
     C                   Parm                    P40               1
     C                   Parm                    P41               1
     C                   Parm                    P42               1
     C

     C                   If        %Subst(P3:1:1) = '*'
     C                   Eval      %Subst(P3: 1:10)= JobName
     C                   Eval      %Subst(P3:11:10)= User
     C                   Eval      %Subst(P3:21: 6)= JobNumA
     C                   EndIf
      * Exclude highest authority user
     C                   If        User <> 'QSECOFR' and
     C                             User <> 'QSYSOPR'

      * Limit user can chgsplfa on their own spooled
     C                   If        %Subst(P3:11:10)<> User
     C                   Eval      msg_str =
     C                             '0000 You are not authorized to ' +
     C                             'spooled file ' + P2
      * Send diag message
     C                   callp     QMHSNDPM(
     C                             'CPD0006':'QCPFMSG   *LIBL     ':
     C                             msg_str:
     C                             256:'*DIAG  ':'*CTLBDY ': 1:'    ':
     C                             vApiErrDS)
     C

      * Send Excape message
     C                   callp     QMHSNDPM(
     C                             'CPF0002':'QCPFMSG   *LIBL     ':
     C                             '    ' :
     C                             0  :'*ESCAPE':'*CTLBDY ': 1:'    ':
     C                             vApiErrDS)

     C                   EndIf

     C                   EndIf
     C
     C                   Eval      *InLr = *On





2003-01-05 報表安全系列四:如何限制指令 CPYSPLF 的使用, 防止使用者複製其他人的報表 ?


如何限制指令 CPYSPLF 的使用, 防止使用者複製其他人的報表 ?

有鑑於 報表的安全性管理,iSeries(AS/400) 作業系統並未提供完善的保護,我將建議使用 VCP 命令
語法檢核程式來做安全空管,

報表安全系列一 :如何限制指令 WRKSPLF 的使用, 防止使用者察看全系統的報表 ?

報表安全系列二 :如何限制指令 DSPSPLF 的使用, 防止使用者於 WRKSPLF 畫面中瀏覽全系統的報表 ?

報表安全系列三 :如何限制指令 DLTSPLF  的使用, 防止使用者刪除其他人的報表 ?

報表安全系列四 :如何限制指令 CPYSPLF  的使用, 防止使用者複製其他人的報表 ? 

有 *SPLCTL 權限的人可以複製系統上任何報表,要如何防止非授權使用者複製機密敏感
的報表資料,為了要防止這種情形發生,只能從命令檢核程式著手,此範例與其他相關報
表命令(WRKSPLF, DSPSPLF, DLTSPLF)的檢核程式一樣,限制除了 QSECOFR, QSYSOPR 之外,
使用者僅能刪除自己的報表,同樣也分 OS V5R1(含)以前及OS V5R2(含)以後的版本。

CPYSPLF 命令語法檢核程式 for V5R1

File  : QCLSRC
Member: CPYSPLFVC
Type  : CLP
OS version: V5R1 以前
Usage : CRTCLPGM mylib/CPYSPLFVC
        CHGCMD CMD(CPYSPLF) VLDCKR(mylib/CPYSPLFVC) 
        若執行有問題或不使用命令語法檢核程式時,執行
        CHGCMD CMD(DSPSPLF) VLDCKR(*NONE) 


  /*  Program : CPYSPLFVC                                       */
  /*  System  : iSeries 400  FOR V5R1                           */
  /*                                                            */
  /*  Validity Checking program for command CPYSPLF             */
  /*                                                            */
  /*  Example :   protecting an SPOOL From a USER               */
  /*                                                            */
  /*      CHGCMD CMD(CPYSPLF) VLDCKR(MYLIB/CPYSPLFVC)           */
  /*  To reset (in case you made errors) :                      */
  /*      CHGCMD CMD(CPYSPLF) VLDCKR(*NONE)                     */

 DSPSPLFVC:  PGM        PARM(&P1 &P2 &P3 &P4 &P5 +
                             &P6 &P7 &P8 &P9 &P10)

             DCL        VAR(&P1) TYPE(*CHAR) LEN(10)  /* FILE   */
             DCL        VAR(&P2) TYPE(*CHAR) LEN(20)  /* TOFILE */
             DCL        VAR(&P3) TYPE(*CHAR) LEN(26)  /* JOB    */
             DCL        VAR(&P4) TYPE(*CHAR) LEN(4)   /* SPLNBR */
             DCL        VAR(&P5) TYPE(*CHAR) LEN(10)  /* MEMBER */
             DCL        VAR(&P6) TYPE(*CHAR) LEN(1)   /* MBR OPTION */
             DCL        VAR(&P7) TYPE(*CHAR) LEN(1)   /* CTLCHAR */
             DCL        VAR(&P8) TYPE(*CHAR) LEN(1)
             DCL        VAR(&P9) TYPE(*CHAR) LEN(1)
             DCL        VAR(&P10) TYPE(*CHAR) LEN(1)
             DCL        VAR(&SPLUSR) TYPE(*CHAR) LEN(10)
             DCL        VAR(&USER) TYPE(*CHAR) LEN(10)
             DCL        VAR(&JOBNAME) TYPE(*CHAR) LEN(10)
             DCL        VAR(&JOBNBR) TYPE(*CHAR) LEN(6)

             RTVJOBA    JOB(&JOBNAME) USER(&USER) NBR(&JOBNBR)
             IF         (%SST(&P3 1 1) *EQ '*')  DO
                        CHGVAR     &SPLUSR &USER
                        CHGVAR     %SST(&P3  1  10) &JOBNAME
                        CHGVAR     %SST(&P3 11  10) &USER
                        CHGVAR     %SST(&P3 21   6) &JOBNBR
                 ENDDO
             ELSE                                +
                        CHGVAR     &SPLUSR %SST(&P3 11 10)

 /* QSECOFR, QSYSOPR CAN BROWSE ALL SPOOLED FILE */
             IF         COND((&USER *EQ 'QSECOFR') *OR +
                             (&USER *EQ 'QSYSOPR'))    +
                          THEN(GOTO CMDLBL(OK))

 /* LIMIT ONLY SPOOLED CREATION USER CAN BROWSE OWN'S SPOOLED FILE */
             IF         COND(&USER *NE &SPLUSR) +
                          THEN(GOTO NOT_OK)
 OK:
             RETURN

 NOT_OK:     SNDPGMMSG  MSGID(CPD0006) MSGF(QCPFMSG) MSGDTA('0000' +
                          *CAT 'You are not authorized to spooled +
                          file' *BCAT &P1) MSGTYPE(*DIAG)

             SNDPGMMSG  MSGID( CPF0002 )                          +
                        MSGF( QSYS/QCPFMSG )                      +
                        MSGTYPE( *ESCAPE )

             ENDPGM


CPYSPLF 命令語法檢核程式 for V5R2

File  : QCLSRC
Member: CPYSPLFVC
Type  : CLP
OS version: V5R2 以後
Usage : CRTCLPGM mylib/CPYSPLFVC
        CHGCMD CMD(CPYSPLF) VLDCKR(mylib/CPYSPLFVC) 
        若執行有問題或不使用命令語法檢核程式時,執行
        CHGCMD CMD(DSPSPLF) VLDCKR(*NONE) 


  /*  Program : CPYSPLFVC                                       */
  /*  System  : iSeries 400  FOR V5R2                           */
  /*                                                            */
  /*  Validity Checking program for command CPYSPLF             */
  /*                                                            */
  /*  Example :   protecting an SPOOL From a USER               */
  /*                                                            */
  /*      CHGCMD CMD(CPYSPLF) VLDCKR(MYLIB/CPYSPLFVC)           */
  /*  To reset (in case you made errors) :                      */
  /*      CHGCMD CMD(CPYSPLF) VLDCKR(*NONE)                     */

 DSPSPLFVC:  PGM        PARM(&P1 &P2 &P3 &P4 &P5 &P6 +
                             &P7 &P8 &P9 &P10 &P11 &P12)

             DCL        VAR(&P1) TYPE(*CHAR) LEN(10)  /* FILE   */
             DCL        VAR(&P2) TYPE(*CHAR) LEN(20)  /* TOFILE */
             DCL        VAR(&P3) TYPE(*CHAR) LEN(26)  /* JOB    */
             DCL        VAR(&P4) TYPE(*CHAR) LEN(4)   /* SPLNBR */
             DCL        VAR(&P5) TYPE(*CHAR) LEN(8)   /* SYSNAME*/
             DCL        VAR(&P6) TYPE(*CHAR) LEN(6)   /* CRTDATE    */
             DCL        VAR(&P7) TYPE(*CHAR) LEN(10)  /* MEMBER */
             DCL        VAR(&P8) TYPE(*CHAR) LEN(1)   /* MBR OPTION */
             DCL        VAR(&P9) TYPE(*CHAR) LEN(1)   /* CTLCHAR */
             DCL        VAR(&P10) TYPE(*CHAR) LEN(1)
             DCL        VAR(&P11) TYPE(*CHAR) LEN(1)
             DCL        VAR(&P12) TYPE(*CHAR) LEN(1)
             DCL        VAR(&SPLUSR) TYPE(*CHAR) LEN(10)
             DCL        VAR(&USER) TYPE(*CHAR) LEN(10)
             DCL        VAR(&JOBNAME) TYPE(*CHAR) LEN(10)
             DCL        VAR(&JOBNBR) TYPE(*CHAR) LEN(6)

             RTVJOBA    JOB(&JOBNAME) USER(&USER) NBR(&JOBNBR)
             IF         (%SST(&P3 1 1) *EQ '*')  DO
                        CHGVAR     &SPLUSR &USER
                        CHGVAR     %SST(&P3  1  10) &JOBNAME
                        CHGVAR     %SST(&P3 11  10) &USER
                        CHGVAR     %SST(&P3 21   6) &JOBNBR
                 ENDDO
             ELSE                                +
                        CHGVAR     &SPLUSR %SST(&P3 11 10)

 /* QSECOFR, QSYSOPR CAN BROWSE ALL SPOOLED FILE */
             IF         COND((&USER *EQ 'QSECOFR') *OR +
                             (&USER *EQ 'QSYSOPR'))    +
                          THEN(GOTO CMDLBL(OK))

 /* LIMIT ONLY SPOOLED CREATION USER CAN BROWSE OWN'S SPOOLED FILE */
             IF         COND(&USER *NE &SPLUSR) +
                          THEN(GOTO NOT_OK)
 OK:
             RETURN

 NOT_OK:     SNDPGMMSG  MSGID(CPD0006) MSGF(QCPFMSG) MSGDTA('0000' +
                          *CAT 'You are not authorized to spooled +
                          file' *BCAT &P1) MSGTYPE(*DIAG)

             SNDPGMMSG  MSGID( CPF0002 )                          +
                        MSGF( QSYS/QCPFMSG )                      +
                        MSGTYPE( *ESCAPE )

             ENDPGM




2003-01-04 報表安全列三:如何限制指令 DLTSPLF 的使用, 防止使用者刪除其他人的報表 ?


報表安全列三:如何限制指令 DLTSPLF 的使用, 防止使用者刪除其他人的報表 ?

有鑑於 報表的安全性管理,iSeries(AS/400) 作業系統並未提供完善的保護,我將建議使用 VCP 命令語
法檢核程式來做安全空管,

報表安全系列一 :如何限制指令 WRKSPLF 的使用, 防止使用者察看全系統的報表 ?

報表安全系列二 :如何限制指令 DSPSPLF 的使用, 防止使用者於 WRKSPLF 畫面中瀏覽全系統的報表 ?

報表安全系列三 :如何限制指令 DLTSPLF  的使用, 防止使用者刪除其他人的報表 ? 

你是否常會遇到使用者反應他的報表不見了,有可能被其他有 *SPLCTL 權限的人刪除,
為了要防止這種情形發生,只能從命令檢核程式著手,此範例與其他相關報表命令
(WRKSPLF, DSPSPLF)的檢核程式一樣,限制除了 QSECOFR, QSYSOPR 之外,使
用者僅能刪除自己的報表,同樣也分 OS V5R1(含)以前及OS V5R2(含)以後的版本。

DLTSPLF 命令語法檢核程式 for V5R1

File  : QCLSRC
Member: DLTSPLFVC
Type  : CLP
OS version: V5R1 以前
Usage : CRTCLPGM mylib/DLTSPLFVC
        CHGCMD CMD(DLTSPLF) VLDCKR(mylib/DLTSPLFVC) 
        若執行有問題或不使用命令語法檢核程式時,執行
        CHGCMD CMD(DSPSPLF) VLDCKR(*NONE) 


  /*  Program : DLTSPLFVC                                       */
  /*  System  : iSeries 400 FOR V5R1                            */
  /*                                                            */
  /*  Validity Checking program for command DLTSPLF             */
  /*                                                            */
  /*  Example :   protecting an SPOOL From a USER               */
  /*                                                            */
  /*      CHGCMD CMD(DLTSPLF) VLDCKR(MYLIB/DLTSPLFVC)           */
  /*  To reset (in case you made errors) :                      */
  /*      CHGCMD CMD(DLTSPLF) VLDCKR(*NONE)                     */

 DSPSPLFVC:  PGM        PARM(&P1 &P2 &P3 &P4 &P5)

             DCL        VAR(&P1) TYPE(*CHAR) LEN(10)  /* FUNC    */
             DCL        VAR(&P2) TYPE(*CHAR) LEN(10)  /* FILE    */
             DCL        VAR(&P3) TYPE(*CHAR) LEN(26)  /* JOB     */
             DCL        VAR(&P4) TYPE(*CHAR) LEN(4)   /* SPLNBR  */
             DCL        VAR(&P5) TYPE(*CHAR) LEN(40)  /* SELECT  */
             DCL        VAR(&SPLUSR) TYPE(*CHAR) LEN(10)
             DCL        VAR(&USER) TYPE(*CHAR) LEN(10)
             DCL        VAR(&JOBNAME) TYPE(*CHAR) LEN(10)
             DCL        VAR(&JOBNBR) TYPE(*CHAR) LEN(6)

             RTVJOBA    JOB(&JOBNAME) USER(&USER) NBR(&JOBNBR)
             IF         (%SST(&P3 1 1) *EQ '*')  DO
                        CHGVAR     &SPLUSR &USER
                        CHGVAR     %SST(&P3  1  10) &JOBNAME
                        CHGVAR     %SST(&P3 11  10) &USER
                        CHGVAR     %SST(&P3 21   6) &JOBNBR
                 ENDDO
             ELSE                                +
                        CHGVAR     &SPLUSR %SST(&P3 11 10)

 /* USER QSECOFR, QSYSOPR UNLIMIT ACCESS SPOOLED FILE */
             IF         ((&USER *EQ 'QSECOFR') *OR +
                         (&USER *EQ 'QSYSOPR'))    +
                          THEN(GOTO OK)

 /* LIMIT ONLY SPOOLED CREATION USER CAN BROWSE OWN'S SPOOLED FILE */
             IF         COND(&USER *NE &SPLUSR) +
                          THEN(GOTO NOT_OK)

 OK:
             RETURN

 NOT_OK:     SNDPGMMSG  MSGID(CPD0006) MSGF(QCPFMSG) MSGDTA('0000' +
                          *CAT 'You are not authorized to spooled +
                          file' *BCAT &P2) MSGTYPE(*DIAG)

             SNDPGMMSG  MSGID( CPF0002 )                          +
                        MSGF( QSYS/QCPFMSG )                      +
                        MSGTYPE( *ESCAPE )

             ENDPGM



DLTSPLF 命令語法檢核程式 for V5R2

File  : QCLSRC
Member: DLTSPLFVC
Type  : CLP
OS version: V5R2 以後
Usage : CRTCLPGM mylib/DLTSPLFVC
        CHGCMD CMD(DLTSPLF) VLDCKR(mylib/DLTSPLFVC) 
        若執行有問題或不使用命令語法檢核程式時,執行
        CHGCMD CMD(DSPSPLF) VLDCKR(*NONE) 


  /*  Program : DLTSPLFVC                                       */
  /*  System  : iSeries 400 FOR V5R2                            */
  /*                                                            */
  /*  Validity Checking program for command DLTSPLF             */
  /*                                                            */
  /*  Example :   protecting an SPOOL From a USER               */
  /*                                                            */
  /*      CHGCMD CMD(DLTSPLF) VLDCKR(MYLIB/DLTSPLFVC)           */
  /*  To reset (in case you made errors) :                      */
  /*      CHGCMD CMD(DLTSPLF) VLDCKR(*NONE)                     */

 DSPSPLFVC:  PGM        PARM(&P1 &P2 &P3 &P4 &P5 &P6 &P7)

             DCL        VAR(&P1) TYPE(*CHAR) LEN(1)   /* FUNC    */
             DCL        VAR(&P2) TYPE(*CHAR) LEN(10)  /* FILE    */
             DCL        VAR(&P3) TYPE(*CHAR) LEN(26)  /* JOB     */
             DCL        VAR(&P4) TYPE(*CHAR) LEN(4)   /* SPLNBR  */
             DCL        VAR(&P5) TYPE(*CHAR) LEN(8)   /* SYSNAME */
             DCL        VAR(&P6) TYPE(*CHAR) LEN(6)   /* CRTDATE */
             DCL        VAR(&P7) TYPE(*CHAR) LEN(40)  /* SELECT  */
             DCL        VAR(&SPLUSR) TYPE(*CHAR) LEN(10)
             DCL        VAR(&USER) TYPE(*CHAR) LEN(10)

             DCL        VAR(&JOBNAME) TYPE(*CHAR) LEN(10)
             DCL        VAR(&JOBNBR) TYPE(*CHAR) LEN(6)

             RTVJOBA    JOB(&JOBNAME) USER(&USER) NBR(&JOBNBR)
             IF         (%SST(&P3 1 1) *EQ '*')  DO
                        CHGVAR     &SPLUSR &USER
                        CHGVAR     %SST(&P3  1  10) &JOBNAME
                        CHGVAR     %SST(&P3 11  10) &USER
                        CHGVAR     %SST(&P3 21   6) &JOBNBR
                 ENDDO
             ELSE                                +
                        CHGVAR     &SPLUSR %SST(&P3 11 10)

 /* USER QSECOFR, QSYSOPR UNLIMIT ACCESS SPOOLED FILE */
             IF      ((&USER *EQ 'QSECOFR') *OR +
                      (&USER *EQ 'QSYSOPR'))    +
                          THEN(GOTO OK)

 /* LIMIT ONLY SPOOLED CREATION USER CAN BROWSE OWN'S SPOOLED FILE */
             IF         COND(&USER *NE &SPLUSR) +
                          THEN(GOTO NOT_OK)

 OK:
             RETURN

 NOT_OK:     SNDPGMMSG  MSGID(CPD0006) MSGF(QCPFMSG) MSGDTA('0000' +
                          *CAT 'You are not authorized to spooled +
                          file' *BCAT &P2) MSGTYPE(*DIAG)

             SNDPGMMSG  MSGID( CPF0002 )                          +
                        MSGF( QSYS/QCPFMSG )                      +
                        MSGTYPE( *ESCAPE )

             ENDPGM