04.2 オペレーター応答とコマンドを受け取る(WTORとQEDIT)

プログラムがコンソール・オペレーターと通信(対話)を行うには2つの方法があります。1つは、メッセージを出力してそのメッセージに対する応答を受け取る方法です。もう1つは、メッセージとは無関係にオペレーターがMODIFYコマンドやSTOPコマンドによってプログラムに指示を与える方法です。

前者は、プログラムでオペレーターの判断を必要とする何らかの事態が起きたときに利用されます。例えば、DASDボリュームを初期化することがパラメーターで指定された時に、本当にクリアーしてもいいのかを再確認するような機能を持たせる場合や、誤った入力データを見つけたような時に処理不能で異常終了するのか、誤ったデータを無視して処理を続けるのかなどを選択させるような場合に、その旨のメッセージをコンソールに出してこの後どう動くかをオペレーターに判断してもらうようなプログラムを作ることができます。
後者は、システム運用などの都合によって、プログラムに特定の動作を行わせたり動きを変える場合などに利用されます。バッチ処理のように入力データが終わったらプログラムの処理も終わるのではなく、一定時間あるいはオペレーターが指示するまで動き続ける常駐型のプログラムを作る際に必要となる機能です。MODIFYコマンドでプログラムの動作や機能を変更し、STOPコマンドでプログラムを終了させるのが一般的です。

メッセージに対するオペレーター応答を受け取る

WTORマクロは、コンソールにメッセージを表示してオペレーターからの応答を受け取ります。出力するメッセージの指定方法はWTOマクロと同じですが、オペレーターからの応答を受け取る領域とその長さ及び待ち受けのためのECBアドレスを追加で指定します。
WTORマクロの完了は、オペレーターが応答を入力したときではありません。コンソールへのメッセージ出力がスケジュールされたら完了してプログラムに戻ってきます。この時、返答領域にオペレーターからの応答が入力されているかはわかりません(殆どの場合未だ入力されてません)。オペレーターからの応答を待ち受けるには、WTORマクロで指定したECBでWAITマクロを発行しなければなりません。オペレーターが応答すればWAITマクロが完了します。
バッチ処理のプログラムではあまり必要ありませんが、WTORマクロの後ですぐにWAITを出さず、オペレーターが入力するまでの間も止まることなく別の処理を行うこともできます。なお、WTORでもマクロ完了時にGR1にメッセージ識別番号が返ります。必要なら応答を待たずにメッセージを取り消すことも可能です。

最初の例は、古典的なWTORマクロのコーディングです。2番目は、後から追加されたTEXTパラメーターによって利用可能なメッセージ・テキストをマクロの外に記述する方法です。

オペレーター・コマンドを受け取る

アドレス空間に常駐してオペレーターが指示するまで一定の処理を行い続けるサーバー型のプログラムでは、「次に何を行うか?」といったことをオペレーターからのコマンドによって判定したい場合があります。このような場合、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コマンド入力後もオペレーター・コマンドを受け取るには

STOPコマンドが入ると、QEDITで指定したCIBカウンターは0にされてしまいコマンド・キューは無効になり、以降のMODIFYコマンドは受け付けられなくなります(STOPコマンドだけは入力可能)。STOPコマンドが入った後も、引き続きMODIFYコマンドでコマンドを受け取るためには改めてCIBCTR指定のQEDITマクロを発行する必要があります。