STACKマクロによるTSOコマンド出力のトラップ
STACKマクロによるTSOコマンド出力のトラップ
z/OS(MVS、OS/390)のTSOでは、CLIST内で発行したTSOコマンドの出力メッセージは、システム変数「SYSOUTTRAP」と「SYSOUTLINE」によって簡単にトラップすることができます。これらの変数を使えば、コマンドからの出力メッセージはシステム変数SYSOUTLINEnnに保管され、後でその内容を参照したり取り出したりすることができます。しかし「SYSOUTTRAP」と「SYSOUTLINE」の機能は、z/OSでしか利用できません。このサイトでも紹介しているライセンス・フリーで使用できるMVS3.8あるいはMSPやVOS3では利用できません。これらのOSではシステム変数ではなく、アセンブラー・プログラムによってTSOコマンド出力の宛先を変えることで代替することができます。
TSOコマンドの出力メッセージの宛先を変更するには、STACKマクロを使います。そのサンプルとして@CMDプログラムを紹介します。@CMDプログラムは、STACKマクロによってメッセージの宛先をデータセットに変更して、指定されたTSOコマンド・プログラムを呼び出し、変更したメッセージの宛先を元に戻して終了します。CLIST内で直接TSOコマンドを発行する代わりに@CMDを発行することで、指定したTSOコマンドの出力メッセージをデータセットに書き出すことができます。後はCLISTの中でそのデータセットにアクセスすれば、コマンドから出力されたメッセージを取得することができます。
@CMDプログラム
// JOB (ACCT),NAME,CLASS=A,MSGCLASS=C,MSGLEVEL=(1,1) //********************************************************************* //ASMCLG PROC N=TEMPNAME,AOPT=RLD,APARM=,LOPT=,NCAL=NCAL, // MAC1='SYS1.MACLIB', // MAC2='SYS1.MACLIB', // MAC3='SYS1.AMODGEN', // LLIB='load module library' //ASM EXEC PGM=IFOX00,REGION=4096K, // PARM=('OBJ,NODECK,XREF(SHORT),TERM,RLD,&AOPT', // 'SYSPARM(&APARM)') //SYSLIB DD DSN=&MAC1,DISP=SHR,DCB=BLKSIZE=32720 // DD DSN=&MAC2,DISP=SHR // DD DSN=&MAC3,DISP=SHR //SYSUT1 DD UNIT=SYSALLDA,SPACE=(TRK,(50,20)) //SYSUT2 DD UNIT=SYSALLDA,SPACE=(TRK,(50,20)) //SYSUT3 DD UNIT=SYSALLDA,SPACE=(TRK,(50,20)) //SYSGO DD DISP=(,PASS), // UNIT=SYSALLDA,SPACE=(TRK,(30,15),RLSE), // DCB=(RECFM=FB,BLKSIZE=3120,LRECL=80) //SYSPRINT DD SYSOUT=* //SYSTERM DD SYSOUT=* //LKD EXEC PGM=IEWL,COND=(5,LT,ASM), // PARM=('LIST,LET,&NCAL,XREF,&LOPT') //SYSPRINT DD SYSOUT=* //SYSUT1 DD UNIT=SYSALLDA,SPACE=(TRK,(80,20)) //SYSLIN DD DSN=*.ASM.SYSGO,DISP=(OLD,DELETE) // DD DDNAME=SYSIN //SYSLIB DD DSN=&LLIB,DISP=SHR //SYSLMOD DD DSN=&LLIB(&N),DISP=SHR // PEND //********************************************************************* //@CMD EXEC ASMCLG,N=@CMD //ASM.SYSIN DD * @CMD TITLE 'TSO COMMAND ISSUER PROGRAM' *********************************************************************** *---------------------------------------------------------------------* * HOUSE KEEPING * *---------------------------------------------------------------------* @CMD CSECT , DEFINE CODE SECTION B 4+68+28+156(,15) AROUND PROGRAM HEADER DC 17F'-1' OUR REGISTER SAVEAREA DC AL1(8) MODULE NAME LENGTH DC CL8'@CMD' MODULE NAME DC CL6'R1.00' MODULE VERSION DC CL8'&SYSDATE' ASSEMBLY DATE DC CL5'&SYSTIME' ASSEMBLY TIME DC 156X'FF' ZAP SPACE USING @CMD,RD DEFINE OUR BASE REGISTERS STM RE,RC,12(RD) SAVE CALLER REGISTERS ST RD,4(,RF) SAVE CALLER SAVEAREA POINTER LA RE,0(,RD) SAVE CALLER SAVEAREA ADDRESS LA RD,0(,RF) LOAD OUR 1ST BASE ADDRESS ST RD,8(,RE) SET BACK CHAIN FOR LINK TRACE B MAINPROC GO TO MAIN PROCESSING SPACE , *---------------------------------------------------------------------* * EXIT PROCESSING * *---------------------------------------------------------------------* EXITPROC DS 0H L RD,4(,RD) LOAD CALLER SAVEAREA ST RF,16(,RD) PASS RETURN CODE TO CALLER LM RE,RC,12(RD) RESTORE CALLER REGISTERS BR RE RETURN TO CALLER EJECT , *********************************************************************** * MAIN PROCESSING * * GR1 -- EXEC PARAMETER PLIST * * GR13 - BASE REGISTER AND OUR REGISTER SAVEAREA * *---------------------------------------------------------------------* * OPERATION: * * ALLOC DD(MSGPRINT) DA(output dataset) SHR * * ENTER '@CMD' ON TSO/TMP SCREEN. ==> @CMD tso command string * * * * INPUTS: * * GR1 --- TSO CPPL * * GR1 --> +-+---------+-+---------+-+---------+-+---------+ * * I0I A(CBUF) I0I A(UPT) I0I A(PSCB) I0I A(ECT) I * * +-+---------+-+---------+-+---------+-+---------+ * * CBUF STRUCTURE * * +-----------------+-------------------+ * * I H(TOTAL LENGTH) I H(OFFSET TO PARM) I * * +-----------------+-------------------+---------+ * * I CL???'VERB+PARAMETER STRINGS' I * * +-----------------------------------------------+ * *********************************************************************** MAINPROC DS 0H *********************************************************************** * EXTRACT COMMAND PARAMETER STRING * * ===================================================== * * GR0 ----> N/A * * GR1 ----> TSO/CPPL * *********************************************************************** LR R2,R1 LOAD OUR CPPL ADDRESS USING CPPL,R2 ADDRESS IT L R1,CPPLCBUF LOAD COMMAND BUFFER AREA LH RF,0(,R1) LOAD TOTAL STRING LENGTH SH RF,2(,R1) SUBTRACT CMD VERB LENGTH CH RF,=H'4' CALLED WITH ANY PARMS ? BNH EXITPROC NO, ABORT PROCESSING WITH RC=4 SPACE , LH RF,2(,R1) LOAD COMMAND VERB LENGTH + (WITH TRAILING BLANK) LH R4,0(,R1) LOAD TOTAL STRING LENGTH SH R4,=H'4' SUBTRACT HDR LENGTH SR R4,RF GR4 --> LNGTH OF PARM STRING LA R3,0(RF,R1) LOCATE TO NEW HDR FIELD LA R0,4(,R4) LOAD CALLED CMD VERB+PARM LNG STH R0,0(,R3) WITH HDR AND SET IT LA R3,4(,R3) GR3 --> BEGIN OF PARM STRING SPACE , LA R1,CMDNAME LOAD CALLED CMD NAME FIELD FOR + LINK/ATTACH EPLOC LR RE,R3 SET BEGIN OF CALLED CMD VERB LR R0,R4 SET NUM OF MAXIMUM LOOPS CLI 0(RE),C' ' SEARCH END OF CMD VERB BNH *+4+6+4+4+4+4 I TO BE CALLED MVC 0(1,R1),0(RE) I LA RE,1(,RE) I LA R1,1(,R1) I BCT R0,*-4-4-6-4-4 V B *+4+4 IN CASE OF NO PARAMETER LA RE,1(,RE) SKIP BLANK BETWEEN VERB & PARM SLR RE,R3 LOAD CALLED CMD VERB LENGTH SH R3,=H'4' LOCATE TO NEW HDR FIELD STH RE,2(,R3) SET CALLED CMD VERB LENGTH SPACE , * *----------------------------------* * * BUILD PSEUDO CPPL FOR CALLED * * * TSO COMMAND. * * * ============================== * * *----------------------------------* ST R3,PSEUCPPL+0 SET FAKED CMD BUFFER ADDR TO + PSEUDO CPPL MVC PSEUCPPL+4(4),CPPLUPT MOVE OUR UPT TO PSEUDO CPPL MVC PSEUCPPL+8(4),CPPLPSCB MOVE OUR PSCB TO PSEUDO CPPL MVC PSEUCPPL+12(4),CPPLECT MOVE OUR ECT TO PSEUDO CPPL SPACE , * *----------------------------------* * * CHANGE STDOUT TO OUR LOCAL * * * DATASET.(DDNAME=MSGPRINT) * * * ============================== * * *----------------------------------* LA R3,IOPLAREA LOAD IOPL AREA ADDRESS USING IOPL,R3 ADDRESS IT L R4,CPPLUPT LOAD OUR UPT ADDRESS L R5,CPPLECT LOAD OUR ECT ADDRESS STACK MF=(E,IOPL),PARM=STPB, ISSUE STACK TO CHANGE STD + ECB=ECB, OUTPUT DEVICE. + DATASET=(OUTDD=OUTDDNAM), + UPT=(4),ECT=(5) SPACE , * *----------------------------------* * * CALL TSO COMMAND * * * ============================== * * * * * *----------------------------------* LA R1,PSEUCPPL LOAD PSEUDO CPPL ADDRESS LINK EPLOC=CMDNAME EXECUTE TSO COMMAND LR RA,RF GR10 -> RETCD FROM TSO CMD SPACE , * *----------------------------------* * * RESTORE STDOUT DEVICE TO TSO * * * ORIGIN. * * * ============================== * * *----------------------------------* STACK MF=(E,IOPL),PARM=STPB, ISSUE STACK TO RESTORE ORIGIN + ECB=ECB, STD OUTPUT DEVICE. + DELETE=TOP SPACE , LR RF,RA GR15 -> RETCD FROM TSO CMD B EXITPROC PROCESSING DONE... EJECT , *********************************************************************** * I N T E R N A L S U B R O U T I N E S * *********************************************************************** EJECT , *********************************************************************** * DATA AREA (CONSTANTS) * *********************************************************************** DS 0D * *----------------------------------* * * MISCELLANEOUS * * * ============================== * * *----------------------------------* SPACE , *********************************************************************** * DATA AREA * *********************************************************************** * *----------------------------------* * * MISCELLANEOUS * * * ============================== * * *----------------------------------* CMDNAME DC CL8' ' CMD NAME TO BE CALLED IOPLAREA DC 4A(0) TSO I/O SERVICE PLIST ECB DC F'0' ECB FOR STACK WORK STPB STACK MF=L STACK MACRO LIST FORM OUTDDNAM DC CL8'MSGPRINT' MSGPRINT DDNAME PSEUCPPL CALL ,(0,0,0,0),MF=L PSEUDO CPPL FOR CALLED CMD SPACE , *---------------------------------------------------------------------* DROP , FORGET ALL BASE REGISTER *********************************************************************** * DATA AREA (OUTSIDE OUR BASE) * *********************************************************************** *---------------------------------------------------------------------* * LOCAL WORKAREA * *---------------------------------------------------------------------* *---------------------------------------------------------------------* * LOCAL DSECTS * *---------------------------------------------------------------------* *---------------------------------------------------------------------* * GLOBAL DSECTS * *---------------------------------------------------------------------* *---------------------------------------------------------------------* * S/370, ESA/390 REGISTER EQUATES * *---------------------------------------------------------------------* *------- YREGS , OS: REGISTER EQUATES R0 EQU 0 GENERAL REGISTER 0 R1 EQU 1 GENERAL REGISTER 1 R2 EQU 2 GENERAL REGISTER 2 R3 EQU 3 GENERAL REGISTER 3 R4 EQU 4 GENERAL REGISTER 4 R5 EQU 5 GENERAL REGISTER 5 R6 EQU 6 GENERAL REGISTER 6 R7 EQU 7 GENERAL REGISTER 7 R8 EQU 8 GENERAL REGISTER 8 R9 EQU 9 GENERAL REGISTER 9 RA EQU 10 GENERAL REGISTER 10 RB EQU 11 GENERAL REGISTER 11 RC EQU 12 GENERAL REGISTER 12 RD EQU 13 GENERAL REGISTER 13 RE EQU 14 GENERAL REGISTER 14 RF EQU 15 GENERAL REGISTER 15 *---------------------------------------------------------------------* * OS CONTROL BLOCKS * *---------------------------------------------------------------------* PRINT NOGEN IKJTSB , TSO TSB IKJCPPL , TSO CPPL IKJPSCB , TSO PSCB IKJPPL , TSO IKJPARS PLIST IKJIOPL , TSO I/O SERVICE PLIST END // //
これはMVS3.8用ですが、冒頭のアセンブルとリンクエディットのJCL部分を変更すればMSPとVOS3でも使えると思います。必要はありませんが、OS/390やz/OSでも動かすことができます。
ロードモジュールは、TSOコマンド・プログラムとなるので、TSOのコマンド・ライブラリーもしくはTSOログオン・プロシージャーのSTEPLIBデータセットに格納します。
TSOコマンドを発行するプログラムはTMPの代わりをすればよいのです。
MSPの場合は、マニュアルTSS/Eコマンド開発手引書の1.2ターミナルモニタプログラムを参考にできます。VOS3の場合は、システムプログラマの手引-TSS編- 1.2 TSSコマンドの作成と組み込み、あたりが参考にできます。
メッセージ格納データセットの割り振り
//ALLOC EXEC PGM=IEFBR14 //MSGPRINT DD DISP=(,CATLG),DSN=userid.MSGPRINT, // UNIT=SYSDA,SPACE=(TRK,(1,1)),DCB=(DSORG=PS) //
TSOコマンドからの出力メッセージを格納するデータセットを割り振ります。DCB情報は実際の書き出し時にシステムによって設定されるのでPSデータセットであることだけを指定します。
@CMDプログラムの実行
@CMD tso command and parameter
@CMDに続き、実際に発行したいTSOコマンドとそのパラメーターを指定します。呼び出したTSOコマンドからの出力メッセージはDD名MSGPRINTで定義されたデータセットに書き出されます。コマンドを使用する前にALLOCコマンド等で割り振っておく必要があります。
以下は、CLIST内で使用する例です。最初にMSGPRINTを割り振ります。最初のLISTDSコマンドはそのまま発行しているのでメッセージはトラップされず画面にそのまま出力されます。次の@CMDによってLISTALCコマンドが呼び出され、その出力はMSGPRINTデータセットに出力されます。画面には出力されません。
ALLOC DD(MSGPRINT) DA('TK.MSGPRINT') SHR REUSE LISTDS 'TK.MSGPRINT' STATUS HISTORY @CMD LISTALC STATUS