プログラムがコンソール・オペレーターと通信(対話)を行うには2つの方法があります。1つは、メッセージを出力してそのメッセージに対する応答を受け取る方法です。もう1つは、メッセージとは無関係にオペレーターがMODIFYコマンドやSTOPコマンドによってプログラムに指示を与える方法です。
前者は、プログラムでオペレーターの判断を必要とする何らかの事態が起きたときに利用されます。例えば、DASDボリュームを初期化することがパラメーターで指定された時に、本当にクリアーしてもいいのかを再確認するような機能を持たせる場合や、誤った入力データを見つけたような時に処理不能で異常終了するのか、誤ったデータを無視して処理を続けるのかなどを選択させるような場合に、その旨のメッセージをコンソールに出してこの後どう動くかをオペレーターに判断してもらうようなプログラムを作ることができます。
後者は、システム運用などの都合によって、プログラムに特定の動作を行わせたり動きを変える場合などに利用されます。バッチ処理のように入力データが終わったらプログラムの処理も終わるのではなく、一定時間あるいはオペレーターが指示するまで動き続ける常駐型のプログラムを作る際に必要となる機能です。MODIFYコマンドでプログラムの動作や機能を変更し、STOPコマンドでプログラムを終了させるのが一般的です。
メッセージに対するオペレーター応答を受け取る
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ----+----1----+----2----+----3----+----4----+----5----+----6----+----7--          MVI   WTORECB,0                CLEAR WTOR ECB          WTOR  'MYP003D INVALID INPUT DATA FOUND, REPLY ''GO'' TO CONTI+                NUE OR ''CANCEL''',                                     +                RPLYAREA,L'RPLYAREA,WTORECB          WAIT  ECB=WTORECB              WAIT UNTIL REPLIED BY OPERATOR          :          :          : WTORECB  DC    F'0'                     ECB OF WTOR SERVICE RPLYAREA DC    CL6' '                   ENTERED REPLY COMMAND AREA          MVI   WTORECB,0                CLEAR WTOR ECB          WTOR  TEXT=(MSGLENG,RPLYAREA,L'RPLYAREA,WTORECB)          WAIT  ECB=WTORECB              WAIT UNTIL REPLIED BY OPERATOR          :          :          : WTORECB  DC    F'0'                     ECB OF WTOR SERVICE RPLYAREA DC    CL6' '                   ENTERED REPLY COMMAND AREA MSGLENG  DC    AL2(L'MSGTEXT) MSGTEXT  DC    C'MYP004A ENTER EXECUTE OPTIONS OR U' | 
WTORマクロは、コンソールにメッセージを表示してオペレーターからの応答を受け取ります。出力するメッセージの指定方法はWTOマクロと同じですが、オペレーターからの応答を受け取る領域とその長さ及び待ち受けのためのECBアドレスを追加で指定します。
WTORマクロの完了は、オペレーターが応答を入力したときではありません。コンソールへのメッセージ出力がスケジュールされたら完了してプログラムに戻ってきます。この時、返答領域にオペレーターからの応答が入力されているかはわかりません(殆どの場合未だ入力されてません)。オペレーターからの応答を待ち受けるには、WTORマクロで指定したECBでWAITマクロを発行しなければなりません。オペレーターが応答すればWAITマクロが完了します。
バッチ処理のプログラムではあまり必要ありませんが、WTORマクロの後ですぐにWAITを出さず、オペレーターが入力するまでの間も止まることなく別の処理を行うこともできます。なお、WTORでもマクロ完了時にGR1にメッセージ識別番号が返ります。必要なら応答を待たずにメッセージを取り消すことも可能です。
最初の例は、古典的なWTORマクロのコーディングです。2番目は、後から追加されたTEXTパラメーターによって利用可能なメッセージ・テキストをマクロの外に記述する方法です。
オペレーター・コマンドを受け取る
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | ----+----1----+----2----+----3----+----4----+----5----+----6----+----7-- MAINENTR CSECT ,                        DEFINE CONTROL SECTION          USING *,RC                     DEFINE BASE REGISTER          STM   14,12,12(13)             SAVE CALLER REGISTERS          LA    12,0(,15)                GR12 -> OUR 1ST BASE ADDRESS          LR    15,13                    SAVE CALLER SAVEAREA          CNOP  0,4                      INSURE FULL WORD BOUNDARY          BAS   13,*+4+72                AROUND OUR SAVEAREA          DC    18F'-1'                  OUR GPR SAVEAREA          ST    15,4(,13)                SAVE CALLER SAVEAREA POINTER          ST    13,8(,15)                SET BACK CHAIN FOR LINK TRACE *---------------------------------------------------------------------* 初期設定の処理          USING DCOM,2                   ADDRESS TO COMM AREA(IEZCOM)          USING DCIB,3                   ADDRESS TO CIB          EXTRACT ACOMLIST,FIELDS=COMM   ISSUE EXTRACT COMM          L     R2,ACOMLIST              LOAD COMLIST ADDRESS          ICM   R3,B'1111',COMCIBPT      LOAD START COMMAND CIB          BZ    *+4+4+4+4+4              IF WE ARE NOT STC TASK          LH    R0,CIBDATLN              LOAD COMMAND LENGTH          LA    R1,CIBDATA               LOCATE TO COMMAND AREA          STM   R0,R1,LCMDPARM           SAVE START COMMAND PARAMETER          BAS   RA,FREECIB               FREE START COMMAND CIB          SPACE ,          QEDIT ORIGIN=COMCIBPT,         SET AVAILABLE COMMAND QUEUES   +                CIBCTR=10          DROP  R2,R3                    FORGET COMM-AREA AND CIB *---------------------------------------------------------------------*          :          :          :          :          :          :          : *---------------------------------------------------------------------* オペレーターコマンドの待ち合わせと受け取りの処理          USING DCOM,2                   ADDRESS TO COMM AREA(IEZCOM)          USING DCIB,3                   ADDRESS TO CIB CMNDWAIT DS    0H          L     R2,ACOMLIST              LOAD COMLIST ADDRESS          L     R1,COMECBPT              LOAD OP-COMMAND ECB ADDRESS          WAIT  ECB=(1)                  WAIT ANY OP-COMMAND CMNDNEXT DS    0H          ICM   R3,B'1111',COMCIBPT      LOAD NEXT CIB          BZ    CMNDWAIT                 IF NOT, WAIT AGAIN          CLI   CIBVERB,CIBSTOP          STOP COMMAND ?          BE    CMNDSTOP                 YES, PROGRAM DONE          LH    RF,CIBDATLN              LOAD ENTERED OP-COMMAND LENGTH          BAS   RA,ECHOCMD               ECHO ENTERED OP-COMMAND          SPACE ,          ここに入力されたコマンドの処理を入れる。          SPACE ,          BAS   RA,FREECIB               FREE CURRENT CIB          B     CMNDNEXT                 PICKUP NEXT CIB          DROP  R2,R3                    FORGET COMM-AREA AND CIB          SPACE , *---------------------------------------------------------------------* STOPコマンドの処理 CMNDSTOP DS    0H          WTO   'SAMPLE STC PROCESSOR, STOP COMMAND ACCEPTED.'          SLR   RF,RF                    SET CC=0          L     RD,4(,RD)                LOAD CALLER SAVEAREA          L     RE,12(,RD)               RESTORE CALLER GPR14          LM    R0,RC,20(RD)             RESTORE CALLER GPR0-12          BR    RE                       PROGRAM END          SPACE , *---------------------------------------------------------------------* CIB解放の内部サブルーチン          USING DCOM,2                   ADDRESS TO COMM AREA(IEZCOM) FREECIB  DS    0H                       GR2 --> COMMAREA               +                                         GR3 --> CIB          QEDIT ORIGIN=COMCIBPT,         FREE THIS CIB                  +                BLOCK=(3)          B     0(,RA)                   RETURN TO CALLER          DROP  R2                       FORGET COMM-AREA          SPACE , *---------------------------------------------------------------------* 入力されたコマンドをエコーする内部サブルーチン          USING DCIB,3                   ADDRESS TO CIB ECHOCMD  DS    0H                       GR3 --> CIB                    +                                         GR15 -> ENTERED COMMAND LENGTH          MVC   ECHOMSG(LCHOMDL),ECHOMDL INIT ECHO MESSAGE AREA          CVD   RF,DOUBLE                EDIT ENTERED OP-COMMAND MSG          UNPK  ECHOMSG+4+33(2),DOUBLE    I                (MAX 32BYTES)          OI    ECHOMSG+4+34,C'0'         I          CH    RF,=H'32'                 I          BNH   *+4+4                     I          LH    RF,=H'32'                 I          LH    R0,ECHOMSG                I          SH    R0,=H'32'                 I          AR    R0,RF                     I          STH   R0,ECHOMSG                I          LTR   RF,RF                     I          BZ    *+4+4+4+4+2               I          LA    R0,ECHOMSG+4+36           I          LA    R1,32                     I          LA    RE,CIBDATA                I          MVCL  R0,RE                     I          WTO   MF=(E,ECHOMSG)           INFORM IT          B     0(,RA)                   RETURN TO CALLER          DROP  R3                       FORGET CIB          SPACE , *---------------------------------------------------------------------* DOUBLE   DC    D'0'                     DOUBLE WORD WORK AREA ACOMLIST DC    A(0)                     POINTER TO COMLIST LCMDPARM DC    F'0'                     LNG OF START CMD PARM ACMDPARM DC    A(0)                     TXT POINTER OF START CMD PARM ECHOMDL  WTO   'SAMPLE STC PROCESSOR, ENTR CMND=(XX)                   +                             ',MF=L LCHOMDL  EQU   *-ECHOMDL                MESSAGE MODEL AND LENGTH ECHOMSG  DC    (LCHOMDL)X'00'           MESSAGE EDIT AREA *---------------------------------------------------------------------*          LTORG ,                        USER LITERAL PLACE AT HERE *---------------------------------------------------------------------* DCOM     DSECT          IEZCOM ,                       COMMUNICATION AREA DCIB     DSECT          IEZCIB ,                       CIB *---------------------------------------------------------------------*          :          :          END | 
アドレス空間に常駐してオペレーターが指示するまで一定の処理を行い続けるサーバー型のプログラムでは、「次に何を行うか?」といったことをオペレーターからのコマンドによって判定したい場合があります。このような場合、OSのMODIFYコマンドやSTOPコマンドでオペレーターの指示を受け取ることができます。上記のプログラムは、MODIFY及びSTOPコマンドを処理するサンプルです。WTORに比べるとロジックはやや複雑になりますが、STCタスクとして動かす常駐型のサーバー・プログラムでは必須となる機能です。
プログラム起動時の初期設定として、EXTRACTマクロを発行してMVSのコマンド・スケジューラー・リスト(COMMAREA)のアドレスを得ます。STARTコマンドで起動されたSTCタスクの場合は、STARTコマンド用CIBがチェインされているのでそのアドレスを求めます。これは、COMMAREA内のCOMCIBPTフィールドにあります。バッチジョブなど、STARTコマンド以外の方法で起動された場合はチェインされていません。このアドレスを調べれば、STARTコマンドで起動されたSTCタスクかそうでないかを判定できます。STC起動の場合は、BLOCK指定のQEDITマクロを発行してSTARTコマンド用CIBをクリアーしておきます(サンプルでは内部サブルーチンFREECIBで行っています)。STARTコマンドでも起動パラメーター指定を可能にするプログラムであれば、CIB解放前にパラメーター文字列を解析するなりコピーするなりを行います。STC起動されたプログラムの場合、STARTコマンドでパラメーターを指定していなくてもCIBは作成されることを知っておいて下さい。
 S procname,,,parameter 
STARTコマンドでパラメーターを指定する場合は、上記のようにコマンドを入力します。例えば、 S MYSTC1,,,MODE=DEBUG とすれば、MODE=DEBUG の文字列がSTARTコマンド用CIBで渡されます。CIBDATLNはパラメーターの長さ、CIBDATAがパラメーター文字列です。
次に、MODIFYコマンド用のコマンド・キューを作るため、CIBCTR指定のQEDITマクロを発行します。CIBCTRには同時に入力可能なコマンド数(最大255)を指定します。入力されたコマンドは、まとめてプログラムに渡ってくるわけではありません。1つずつ順番に取り出して、1つずつ順番に処理することができます。従って、CIBCTRは1でもかまいませんが、プログラム側のコマンド処理に時間が掛かると、オペレーターは次のコマンドを入力してもMVSにリジェクトされてしまいます。極端に多くする必要なありませんが、10個程度はあってもいいでしょう。CIBCTR=10なら、未処理のコマンドを10個分OS内でキューイングできることになります。ORIGINパラメーターには、COMMAREAのCOMCIBPTフィールドを指定します。これでオペレーターコマンドを受け取る準備ができました。
EXTRACTを出した後で、QEDITマクロも含めてOSのコントロール・ブロックをプログラムで直接参照します。このため、コントロール・ブロックをフィールド名でアクセスするためにコントロール・ブロックのマッピング・マクロを使います。参照するコントロール・ブロックはCOMMAREAとCIBです。それぞれIEZCOMマクロとIEZCIBマクロでマッピングします。DSECT展開マクロでないため、サンプルのように自分でDSECTを定義します。
プログラムは、コマンドを受け取るタイミングになったら、COMMAREA内のCOMECBPTフィールドでポイントされているコマンド入力待ち合わせ用のECBを指定してWAITします。COMECBPTフィールドは、ECBそのものではなくECBアドレスが格納されたポインターフィールドです。既に何らかのコマンドが入力されていたり、新たなコマンドが入力された時点でWAITは解除されます。
COMMAREA内のCOMCIBPTフィールドには、入力されたコマンドのCIBアドレスが入っています。ここが0なら全てのCIBは処理済みなので、次のオペレーター・コマンドの入力を待ち受けるために再びWAITします。CIBアドレスが入っていれば、そのCIBを調べることで入力されたコマンド文字列を求めることができます。CIBのCIBVERBフィールドは、入力されたコマンド種類を示します。x44ならMODIFY、x40ならSTOPコマンドですが、サンプルのように必ずラベル名で参照します。CIBSTOPは、STOPコマンドを示すEQUラベルです。STOPコマンドは、通常プログラムの終了を意味しますから、サンプルのように終了処理へ移ってしまってかまいません。MODIFYコマンドの場合は、入力されたコマンド文字列と長さが必要なのでCIBから求めます。CIBDATLNはコマンド文字列の長さ、CIBDATAがコマンド文字列です。コマンドを入力したコンソールIDもわかります。z/OSではCIBX内のCIBXCNIDまたはCIBXCNNMフィールドを利用します。CIBXはCIBに連続して配置されている拡張CIBで、その先頭アドレスはCIBアドレスにCIBXOFFフィールドの値を加えることで求められます。特定のコンソールからのコマンド入力かどうかをチェックしたり、コマンド発行元コンソールを記録することなどもできます。
コマンド文字列が求められたら、対応するコマンド処理を行い、その後に処理済みコマンドのCIBを解放します(サンプルでは内部サブルーチンFREECIBで行っています)。先にCIBを解放してもかまいませんが、その場合は入力されたコマンド文字列をプログラム側の領域に適宜コピーしておく必要があります。解放したCIB領域を後から参照してはなりません。このサンプルでは、入力されたコマンド文字列と長さを先頭の32バイト分コンソールにエコーしています。
コマンド処理が終わりCIBを解放したら、次のコマンドをチェックします。再びCOMCIBPTフィールドを参照して、次のCIBがセットされているかを調べます。COMCIBPTは、CIBを解放するためのBLOCK指定のQEDITマクロによって内容が更新されます。次のCIBがなければWAITへ回ります。このようなサイクルでオペレーター・コマンドの処理を行っていきます。MODIFYコマンドで独自のコマンド処理をする場合であっても、プログラムはSTCタスクである必要はありません。バッチで起動されても同じロジックで処理できます。異なる点は、初期設定時のSTARTコマンド用CIBの有無だけです。もし、STARTコマンドではパラメーターを受け取らないなら、少し乱暴ですが初期設定時にSTCかどうかを判定せずにSTARTコマンド用CIBをQEDITで無条件にクリアーしてもかまいません。バッチの場合は、そのQEDITがエラーになるだけでABENDするようなことにはなりません。
STOPコマンド入力後もオペレーター・コマンドを受け取るには
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ----+----1----+----2----+----3----+----4----+----5----+----6----+----7-- CMNDSTOP DS    0H          WTO   'SAMPLE STC PROCESSOR, STOP COMMAND ACCEPTED.'          SPACE ,          L     RF,STOPCTR               INCREMENT NUM OF STOP ENTERED          LA    RF,1(,RF)                 I          ST    RF,STOPCTR                V          CH    RF,=H'3'                 3RD TIME ENTER ?          BNL   PROGDONE                 NO, CONTINUE PROCESSING          SPACE ,          L     R2,ACOMLIST              LOAD COMLIST ADDRESS          USING DCOM,2                   ADDRESS TO COMM AREA(IEZCOM)          BAS   RA,FREECIB               FREE STOP COMMAND CIB          QEDIT ORIGIN=COMCIBPT,         SET AVAILABLE COMMAND QUEUES   +                CIBCTR=10          B     CMNDNEXT                 PICKUP NEXT CIB          DROP  R2                       FORGET COMM-AREA          SPACE , PROGDONE DS    0H          SLR   RF,RF                    SET CC=0          L     RD,4(,RD)                LOAD CALLER SAVEAREA          L     RE,12(,RD)               RESTORE CALLER GPR14          LM    R0,RC,20(RD)             RESTORE CALLER GPR0-12          BR    RE                       PROGRAM END | 
STOPコマンドが入ると、QEDITで指定したCIBカウンターは0にされてしまいコマンド・キューは無効になり、以降のMODIFYコマンドは受け付けられなくなります(STOPコマンドだけは入力可能)。STOPコマンドが入った後も、引き続きMODIFYコマンドでコマンドを受け取るためには改めてCIBCTR指定のQEDITマクロを発行する必要があります。