CLP に対しては RTVCLSRC(*YES) でコンパイルしておくと、RTVCLSRC によって元のCLPソースを
生成できることは良く知られているが コマンドに対する RTVCMDSRC なるものはこれまでなかった。
コマンドを自作するときに OS400 のコマンドはどのようにして作成されているのかを
知りたいと思ったことはないだろうか ?
そこで禁断のコマンド・ソースを検索する RTVCMDSRC を紹介しよう。
RTVCMDSRC は、どのようなコマンドに対しても元のソースを生成するリバース・エンジニアリング機能を
提供する。そんなことができるとは大抵の人は思っていないだろう。
もちろん System i で提供されている OS400 のコマンドであっても、弊社製品のコマンドであっても
コマンド・オブジェクトから元のソースを生成することができる。
今回、紹介する手法はあくまでも学習用にして頂くためのものと考えて欲しい。
コマンド・ソースを検索したからといってオブジェクトのプロバイダーにとって大きな問題となることは
ないだろうと判断して紹介することにした。
----------------------------------------------------------------------------------------
0001.00 CMD PROMPT(' コマンド・ソース検索 ')
0002.00 PARM KWD(CMD) TYPE(CMD) MIN(1) PROMPT(' コマンド ')
0003.00 PARM KWD(SRCFILE) TYPE(SRC) +
0004.00 PROMPT(' ソース・ファイル ')
0005.00 PARM KWD(SRCMBR) TYPE(*NAME) DFT(*CMD) +
0006.00 SPCVAL((*CMD)) PROMPT(' ソース・メンバー ')
0007.00 PARM KWD(PROMPT) TYPE(*CHAR) LEN(5) RSTD(*YES) +
0008.00 DFT(*TEXT) SPCVAL((*TEXT) (*MSG)) +
0009.00 PROMPT(' プロンプト・テキスト OR MSGID')
0010.00 CMD: QUAL TYPE(*NAME) LEN(10)
0011.00 QUAL TYPE(*NAME) LEN(10) DFT(*LIBL) +
0012.00 SPCVAL((*LIBL) (*CURLIB)) +
0013.00 PROMPT(' ライブラリー ')
0014.00 SRC: QUAL TYPE(*NAME) LEN(10) +
0015.00 DFT(QCMDSRC)
0016.00 QUAL TYPE(*NAME) LEN(10) DFT(*LIBL) +
0017.00 SPCVAL((*LIBL) (*CURLIB)) +
0018.00 PROMPT(' ライブラリー ')
0019.00 PARM KWD(COMPILE) TYPE(*CHAR) LEN(4) RSTD(*YES) +
0020.00 DFT(*NO) VALUES(*YES *NO) PMTCTL(*PMTRQS) +
0021.00 PROMPT(' コンパイル・テキスト ')
----------------------------------------------------------------------------------------
CRTCMD CMD(MYLIB/RTVCMDSRC) PGM(MYLIB/RTVCMDSRCC) SRCFILE(MYSRCLIB/QCMDSR) AUT(*ALL)
--------------------------------------------------------------------------------------
0001.00 PGM PARM(&CMDLIB &OFILLIB &OMBR &TXT &COMPILE)
0002.00 /*---------------------------------------------------------*/
0003.00 /* RTVCMDSRCC : コマンド・ソース検索 */
0004.00 /*---------------------------------------------------------*/
0005.00 DCL VAR(&CMDLIB) TYPE(*CHAR) LEN(20)
0006.00 DCL VAR(&OFILLIB) TYPE(*CHAR) LEN(20)
0007.00 DCL VAR(&OMBR) TYPE(*CHAR) LEN(10)
0008.00 DCL VAR(&TXT) TYPE(*CHAR) LEN(5)
0009.00 DCL VAR(&COMPILE) TYPE(*CHAR) LEN(4)
0010.00
0011.00 DCL VAR(&CMDNM) TYPE(*CHAR) LEN(10)
0012.00 DCL VAR(&CMDLI) TYPE(*CHAR) LEN(10)
0013.00 DCL VAR(&MCMDLIB) TYPE(*CHAR) LEN(20)
0014.00 DCL VAR(&OFILE) TYPE(*CHAR) LEN(10)
0015.00 DCL VAR(&OLIBR) TYPE(*CHAR) LEN(10)
0016.00 DCL VAR(&CURLIB) TYPE(*CHAR) LEN(10)
0017.00 DCL VAR(&MSGORTXT) TYPE(*CHAR) LEN(2) VALUE('-M')
0018.00 DCL VAR(&CMDTEXT) TYPE(*CHAR) LEN(50)
0019.00 DCL VAR(&LIN) TYPE(*CHAR) LEN(132)
0020.00 DCL VAR(&USNAMLIB) TYPE(*CHAR) LEN(20)
0021.00 DCL VAR(&PROTOS) TYPE(*CHAR) LEN(10) +
0022.00 VALUE('RTVCMDS')
0023.00 DCL VAR(&USRSPC) TYPE(*CHAR) LEN(10) +
0024.00 VALUE('RTVCMDSPC')
0025.00
0026.00 DCL VAR(&ERRORSW) TYPE(*LGL)
0027.00 DCL VAR(&EMSGID) TYPE(*CHAR) LEN(7)
0028.00 DCL VAR(&EMSGDTA) TYPE(*CHAR) LEN(100)
0029.00 DCL VAR(&EMSGF) TYPE(*CHAR) LEN(10)
0030.00 DCL VAR(&EMSGFLIB) TYPE(*CHAR) LEN(10)
0031.00 DCL VAR(&OS400) TYPE(*CHAR) LEN(6)
0032.00 DCL VAR(&APIERR) TYPE(*CHAR) LEN(4) +
0033.00 VALUE(X'00000000') /* 2 進数 */
0034.00 DCL VAR(&INZSIZ) TYPE(*CHAR) LEN(4)
0035.00 MONMSG MSGID(CPF0000) EXEC(GOTO CMDLBL(ERROR))
0036.00
0037.00 RTVDTAARA DTAARA(QGPL/QSS1MRI (1 6)) RTNVAR(&OS400)
0038.00 RTVJOBA CURLIB(&CURLIB)
0039.00 CHGVAR VAR(&CMDNM) VALUE(%SST(&CMDLIB 1 10))
0040.00 CHGVAR VAR(&CMDLI) VALUE(%SST(&CMDLIB 11 10))
0041.00 CHGVAR VAR(&OFILE) VALUE(%SST(&OFILLIB 1 10))
0042.00 CHGVAR VAR(&OLIBR) VALUE(%SST(&OFILLIB 11 10))
0043.00
0044.00 /*------------------------------------------------*/
0045.00 IF (&OMBR = *DUMPCMD) THEN(GOTO DUMPCMD)
0046.00 /*------------------------------------------------*/
0047.00
0048.00 IF COND(&TXT = *TEXT) THEN(CHGVAR VAR(&MSGORTXT) VALUE('-T'))
0049.00 IF COND(&OMBR = *CMD) THEN(CHGVAR VAR(&OMBR) VALUE(&CMDNM))
0050.00
0051.00 IF COND(&CMDLI *EQ *CURLIB) THEN(DO)
0052.00 IF COND(&CURLIB *EQ *NONE) THEN(CHGVAR VAR(&CMDLI) VALUE(QGPL))
0053.00 ELSE CMD(CHGVAR VAR(&CMDLI) VALUE(&CURLIB))
0054.00 ENDDO
0055.00
0056.00 CHGVAR VAR(%SST(&MCMDLIB 1 10)) VALUE(&CMDNM)
0057.00 CHGVAR VAR(%SST(&MCMDLIB 11 10)) VALUE(&CMDLI)
0058.00
0059.00 IF COND(&OLIBR *EQ *CURLIB) THEN(DO)
0060.00 IF COND(&CURLIB *EQ *NONE) THEN(CHGVAR VAR(&OLIBR) VALUE(QGPL))
0061.00 ELSE CMD(CHGVAR VAR(&OLIBR) VALUE(&CURLIB))
0062.00 ENDDO
0063.00
0064.00 /* コマンドの権限を検査 */
0065.00 CHKOBJ OBJ(&CMDLI/&CMDNM) OBJTYPE(*CMD) AUT(*USE)
0066.00 RTVOBJD OBJ(&CMDLI/&CMDNM) OBJTYPE(*CMD) TEXT(&CMDTEXT)
0067.00
0068.00 /* ソース・ファイルの使用権限を検査 */
0069.00 CHKOBJ OBJ(&OLIBR/&OFILE) OBJTYPE(*FILE) AUT(*CHANGE)
0070.00
0071.00 /* ソース・タイプ CMD をコピー */
0072.00 RMVM FILE(&OLIBR/&OFILE) MBR(&OMBR)
0073.00 MONMSG MSGID(CPF0000)
0074.00 CPYF FROMFILE(ASNET.COM/&PROTOS) +
0075.00 TOFILE(&OLIBR/&OFILE) FROMMBR(CMD) +
0076.00 TOMBR(&OMBR) MBROPT(*REPLACE) FMTOPT(*NOCHK)
0077.00 MONMSG MSGID(CPF0000)
0078.00 CLRPFM FILE(&OLIBR/&OFILE) MBR(&OMBR)
0079.00 MONMSG MSGID(CPF0000)
0080.00 CHGPFM FILE(&OLIBR/&OFILE) MBR(&OMBR) TEXT(&CMDTEXT)
0081.00
0082.00 /* ユーザー・スペースにコピー */
0083.00 DLTUSRSPC USRSPC(QTEMP/&USRSPC)
0084.00 MONMSG MSGID(CPF0000)
0085.00 IF COND(&OS400 *GE 'V5R3M0') THEN(DO) /* +
0086.00 V5R3M0 以上ダンプ */
0087.00 CHGVAR VAR(%BIN(&INZSIZ)) VALUE(32767)
0088.00 CALL PGM(QUSCRTUS) PARM('RTVCMDSPC QTEMP ' +
0089.00 'PF ' &INZSIZ X'00' '*ALL ' +
0090.00 'RTVCMDSRC 用ユーザー空間 ' '*YES ' +
0091.00 &APIERR)
0092.00 MONMSG CPF9870
0093.00 CALL PGM(ASNET.COM/RTVCMDSRCC) PARM(&CMDLIB +
0094.00 &OFILLIB *DUMPCMD &TXT &COMPILE)
0095.00 ENDDO /* V5R3M0 以上ダンプ */
0096.00 ELSE CMD(DO) /* V5R2M0 以下は MI */
0097.00 CALL PGM(ASNET.COM/RTVCMDM) PARM(&MCMDLIB)
0098.00 ENDDO /* V5R2M0 以下は MI */
0099.00
0100.00 /* コマンド・ソースの検索 */
0101.00 OVRDBF FILE(SRC) TOFILE(&OLIBR/&OFILE) MBR(&OMBR) +
0102.00 SECURE(*YES) OVRSCOPE(*JOB)
0103.00 CALL PGM(ASNET.COM/RTVCMD) PARM( +
0104.00 '-N' &CMDNM +
0105.00 '-L' &CMDLI +
0106.00 '-SF' &OFILE +
0107.00 '-SL' &OLIBR +
0108.00 '-SM' &OMBR +
0109.00 '-X' &CMDTEXT +
0110.00 '-C' &COMPILE +
0111.00 &MSGORTXT)
0112.00
0113.00 /* CALL PGM(ASNET.COM/ADDLBL) ラベルを訂正 */
0114.00 DLTOVR FILE(SRC) LVL(*JOB)
0115.00 DLTUSRSPC USRSPC(QTEMP/&USRSPC)
0116.00 MONMSG MSGID(CPF0000)
0117.00 DLTF FILE(QTEMP/RTVCMDSF)
0118.00 MONMSG MSGID(CPF0000)
0119.00 RCLRSC
0120.00 MONMSG MSGID(CPF0000)
0121.00 RMVMSG PGMQ(*ALLINACT) CLEAR(*ALL)
0122.00 RMVMSG CLEAR(*ALL)
0123.00 SNDPGMMSG MSG(' コマンド ' *CAT &CMDLI *TCAT '/' +
0124.00 *CAT &CMDNM *TCAT +
0125.00 ' のソースを検索しました ') MSGTYPE(*DIAG)
0126.00 GOTO CMDLBL(ENDPGM)
0127.00 /*------------------------------------*/
0128.00 /* コマンド・オブジェクトのダンプ */
0129.00 /*------------------------------------*/
0130.00 DUMPCMD:
0131.00 CRTPF FILE(QTEMP/RTVCMDSF) RCDLEN(132) +
0132.00 IGCDTA(*YES) SIZE(*NOMAX)
0133.00 MONMSG MSGID(CPF7302) EXEC(DO)
0134.00 CLRPFM FILE(QTEMP/RTVCMDSF)
0135.00 ENDDO
0136.00 OVRPRTF FILE(QPSRVDMP) HOLD(*YES) LVLCHK(*NO) +
0137.00 SECURE(*YES) OVRSCOPE(*JOB)
0138.00 DMPOBJ OBJ(&CMDLI/&CMDNM) OBJTYPE(*CMD)
0139.00 DLTOVR FILE(QPSRVDMP) LVL(*JOB)
0140.00 CPYSPLF FILE(QPSRVDMP) TOFILE(QTEMP/RTVCMDSF) +
0141.00 SPLNBR(*LAST)
0142.00 DLTSPLF FILE(QPSRVDMP) SPLNBR(*LAST)
0143.00
0144.00 /* スプールをユーザー・スペースへコピー */
0145.00 CHGVAR VAR(&USNAMLIB) VALUE(&OFILLIB)
0146.00 CHGVAR VAR(&USNAMLIB) VALUE('RTVCMDSPC QTEMP ') +
0147.00 /* QTR */
0148.00 OVRDBF FILE(RTVCMDSF) TOFILE(QTEMP/RTVCMDSF) +
0149.00 SECURE(*YES) OVRSCOPE(*JOB) SEQONLY(*YES 25)
0150.00 CALL PGM(ASNET.COM/RTVCMDR) PARM(&LIN &USNAMLIB +
0151.00 'COPYSPLF')
0152.00 DLTOVR FILE(RTVCMDSF) LVL(*JOB)
0153.00 GOTO CMDLBL(ENDPGM)
0154.00 /*-----------------------------------------------------------------*/
0155.00 ERROR:
0156.00 IF COND(&ERRORSW) THEN(SNDPGMMSG MSGID(CPF9999) +
0157.00 MSGF(QCPFMSG) MSGTYPE(*ESCAPE))
0158.00 CHGVAR &ERRORSW '1' /* Set to fail if error occurs */
0159.00 RCVMSG: RCVMSG MSGTYPE(*DIAG) MSGDTA(&EMSGDTA) MSGID(&EMSGID) +
0160.00 MSGF(&EMSGF) MSGFLIB(&EMSGFLIB)
0161.00 IF (&EMSGID *EQ ' ') GOTO NXTMSG
0162.00 SNDPGMMSG MSGID(&EMSGID) MSGF(&EMSGFLIB/&EMSGF) +
0163.00 MSGDTA(&EMSGDTA) TOPGMQ(*PRV *) +
0164.00 MSGTYPE(*DIAG)
0165.00 GOTO CMDLBL(RCVMSG)
0166.00 NXTMSG: RCVMSG MSGTYPE(*EXCP) MSGDTA(&EMSGDTA) MSGID(&EMSGID) +
0167.00 MSGF(&EMSGF) MSGFLIB(&EMSGFLIB)
0168.00 SNDPGMMSG MSGID(&EMSGID) MSGF(&EMSGFLIB/&EMSGF) +
0169.00 MSGDTA(&EMSGDTA) TOPGMQ(*PRV *) +
0170.00 MSGTYPE(*ESCAPE)
0171.00 /*-----------------------------------------------------------------*/
0172.00 ENDPGM:
0173.00 ENDPGM
--------------------------------------------------------------------------------------
CRTCLPGM PGM(MYLIB/RTVCMDSRCC) SRCFILE(MYSRCLIB/QCLSRC) AUT(*ALL)
------------------------------------------------------------------------------
0001.00 ENTRY EXENTRY(EXENTOL) EXT;
0002.00 DCL SPCPTR PARM1P PARM;
0003.00 DCL OL EXENTOL (PARM1P) EXT PARM MIN(1);
0004.00
0005.00 /* パラメータ */
0006.00 DCL SPC $PARMS BAS(PARM1P);
0007.00 DCL DD $CMDNM CHAR(10) DEF($PARMS) POS( 1);
0008.00 DCL DD $CMDLI CHAR(10) DEF($PARMS) POS(11);
0009.00
0010.00 DCL CON CUSPNAME CHAR(10) INIT('RTVCMDSPC');
0011.00 DCL CON CUSPLIBR CHAR(10) INIT('QTEMP');
0012.00 DCL CON SKIP CHAR(2) INIT(X'3000');
0013.00 DCL CON HANDLE CHAR(2) INIT(X'B000');
0014.00 DCL CON OP2ISCON CHAR(1) INIT(X'01');
0015.00
0016.00 DCL SYSPTR QTEMPPTR BASPCO POS(65);
0017.00 DCL SYSPTR WORKSYP AUTO;
0018.00 DCL SYSPTR CMDLSYP AUTO;
0019.00 DCL SYSPTR CMDSYP AUTO;
0020.00 DCL SPCPTR USPSPP AUTO;
0021.00
0022.00 DCL DD UCMDLI CHAR(10) AUTO;
0023.00 DCL DD CMDSIZE BIN(4) AUTO BDRY(4) INIT(0);
0024.00
0025.00 /* RSLVSP テンプレート */
0026.00 DCL DD OBJDESC CHAR(34) AUTO;
0027.00 DCL DD TYPESUB CHAR(2) DEF(OBJDESC) POS(1);
0028.00 DCL DD OBJNAM CHAR(30) DEF(OBJDESC) POS(3);
0029.00 DCL DD * CHAR(2) DEF(OBJDESC) POS(33) INIT(X'0000');
0030.00
0031.00 /* MATPTR 用出力テンプレート */
0032.00 DCL SPCPTR MTPTRPTR AUTO INIT(MTPTR);
0033.00 DCL DD MTPTR CHAR(84) AUTO;
0034.00 DCL DD MTPPROV BIN(4) DEF(MTPTR) POS(1) INIT(84);
0035.00 DCL DD MTPTYPE CHAR(1) DEF(MTPTR) POS(9) INIT(X'01') /* syp*/
0036.00 DCL DD MTPSPEC CHAR(75) DEF(MTPTR) POS(10);
0037.00 DCL DD MTSYCTXN CHAR(30) DEF(MTPSPEC) POS(3);
0038.00
0039.00 /* MATS 用出力テンプレート */
0040.00 DCL SPCPTR MATSTMPP AUTO INIT(MATSTMP);
0041.00 DCL DD MATSTMP CHAR(96) AUTO BDRY(16);
0042.00 DCL DD MATSPRV BIN(4) DEF(MATSTMP) POS( 1) INIT(96);
0043.00 DCL DD MATSSIZ BIN(4) DEF(MATSTMP) POS(49);
0044.00
0045.00 DCL DD ERRCODE CHAR( 96) AUTO BDRY(4);
0046.00 DCL DD ERRPROV BIN( 4) DEF(ERRCODE) POS( 1) INIT(96);
0047.00 DCL DD ERRAVAL BIN( 4) DEF(ERRCODE) POS( 5);
:
(省略)
:
------------------------------------------------------------------------------
CRTMI PGM(MYLIB/RTVCMDM) SRCFILE(MYSRCLIB/QMISRC)
※CRTMI というコマンドは存在していないので、この Tools にある「MIコンパイラー」によって作成すること。
ソースを検索する原理はコマンドのダンプ・リストをスプールに出力して
それを MI (マシンインターフェース ) によって解析してソースを抽出している。
下記に RTVCMDSRC の実行の様子を紹介する。