I include this one not so much because I have found it really useful but becuase I think it has a bit of a cool factor. I first used this back many years ago when I was an operator and would write various utilities for us to use in operations. Since we were in the computer room with the console it was pretty easy just use WTOR to make the program interactive with the console. Back in those days we were batch only and didn’t use TSO. Using WTOR for communication through the operator console is pretty simple but lacks the cool factor associated with using the MODIFY console command. So here is how to use MODIFY and STOP to communicate with a running program.
First we need to get the address of the Communications Parameter List (mapped by the IEZCOM macro). The COM parameter list consists of two words.
COMECBPT DS A Address of ECB for STOP/MODIFY COMCIBPT DS A Address of Command Input Buffer
To get the address of the COM parameter area we can use the EXTRACT macro.
EXTRACT COMPTR,FIELDS=COMM GET POINTER TO COMM FIELDS
COMPTR is a fullword where the address of the COM parameter area will be stored. We request the COM parameter area by specifying FIELDS=COMM.
L R1,COMPTR POINTER TO COMM FIELDS LA R2,4(,R1) CIB ORIGIN L R3,0(,R2) PONTER TO FIRST CIB LTR R3,R3 ANY START CIB PRESENT BZ SETCIB NO - CONTINUE
Next we load the address of the COM parm area into register 1. Now we have to check to see if there is a Command Input Buffer (CIB) related to a START command. If we are running as a Started Task there should be a CIB, otherwise there is no CIB and the pointer is zero.
QEDIT ORIGIN=(R2),BLOCK=(R3) FREE START CIB
If there is a CIB as the result of a START command we need to free the CIB. For this we use the QEDIT macro and pass two parameters. ORIGIN refers the the address of the COMCIBPT field (the second word in the COM parmameter list) and BLOCK points the the CIB we wish to free.
SETCIB DS 0H QEDIT ORIGIN=(R2),CIBCTR=1 SET CIB LIMIT TO ONE AT A TIME
Now we set a limit on how many CIBs may be queued to our job at one time. Initially this value is zero which means that MODIFY commands will not be accepted by our job. We want to allow one CIB to be queued at a time so we set the limit using the QEDIT macro. Here we specify the ORIGIN (again the address of the COMCIBPT field) and specify a limit with the CIBCTR parameter.
LOOP DS 0H L R1,COMPTR COMM FIELDS LA R2,0(,R1) ECB ADDRESS PTR L R3,0(,R2) ECB ADDRESS * WAIT 1,ECB=(R3) WAIT FOR A COMMAND
Now we will wait for a command from the console. We do this by waiting on the ECB pointed to by the COMECBPT field. We could also be doing some work and check to see if the ECB has been posted to interrupt whatever we are currenty doing. Here we just wait for a command.
L R1,COMPTR POINTER TO COMM FIELD LA R2,4(,R1) CIB ORIGIN L R3,0(,R2) PONTER TO FIRST CIB
When the ECB is posted we resume execution and get the address of the CIB. The CIB is mapped by the IEZCIB macro and contains the following fields.
CIBNEXT DS A POINTER TO NEXT CIB ON CHAIN OR ZERO IF LAST CIBVERB DS X VERB INDICATING TYPE OF COMMAND * X'04' - START, X'40' - STOP, X'44' - MODIFY CIBLEN DS X LENGTH IN DOUBLEWORDS OF CIB DS XL4 Reserved CIBASID DS H CIBCONID DS X CONSOLE ID - FROM WHERE COMMAND WAS ISSUED DS X Reserved CIBDATLN DS H LENGTH, IN BYTES, OF CIB DATA CIBDATA DS 0C DATA FROM MODIFY COMMAND
The VERB tells us in the CIB was created as a result of a START, STOP, or MODIFY console command. CIBDATALN is the length of data associated with the command. CIBDATA is a variable length field that contains the data from the START or MODIFY command.
CLI 4(R3),X'44' IS IT A MODIFY COMMAND BE MODIFY * CLI 4(R3),X'40' IS IT A STOP COMMAND BE STOP * WTO '*** UNKNOWN CIB TYPE ***',ROUTCDE=(1,11) B FREECIB
Now we check the VERB to determine what type of command we are dealing with. We only expect to find either a STOP or a MODIFY command.
MODIFY DS 0H WTO '*** MODIFY COMMAND RECEIVED ***',ROUTCDE=(1,11) * LH R5,14(,R3) GET COMMAND LENGTH LA R6,16(,R3) POINT TO COMMAND
Here we process a MODIFY command. We point to the data and get the data length from the CIB.
LR R1,R5 COPY LENGTH BCTR R1,0 SUBTRACT ONE MVC WORK(4),=C'*** ' EX R1,MODMVC MODMVC MVC WORK+4(1),0(R6) LA R1,WORK+4 AR R1,R5 MVC 0(4,R1),=C' ***' LA R1,WORK LA R0,8(,R5) BAL R14,WTO * B FREECIB
Next we copy the data into a message area and BAL to a routine that will WTO the message to the console.
WTO DS 0H STM R14,R12,12(R13) LA R3,SAVEA2 ST R13,4(,R3) ST R3,8(,R13) LR R13,R3 * LR R10,R0 SAVE LENGTH LR R11,R1 SAVE PTR TO TEXT * LA R1,1 CR R10,R1 BL WTO020 * LA R1,80 MAX LEN CR R10,R1 BNH WTO010 * LR R10,R1
Here is the routine to issue the WTO. First we save the caller’s registers, set up a new save area, and then check the length of the message.
WTO010 DS 0H MVC WTOWORK(4),=X'00008000' LA R1,4(,R10) STH R1,WTOWORK BCTR R10,0 EX R10,WTOMVC *WTOMVC MVC WTOWORK+4(1),0(R11) LA R1,WTOWORK LA R1,5(R10,R1) MVC 0(4,R1),=X'00008020'
Now we build the SVC 35 parameter list.
LA R1,WTOWORK SVC 35 * WTO020 DS 0H L R13,4(,R13) LM R14,R12,12(R13) BR R14
Now we point to the parameter list, issue the WTO SVC, and then return to the caller.
STOP DS 0H WTO '*** STOP COMMAND RECEIVED ***',ROUTCDE=(1,11) B EXIT
If the VERB indicates a STOP command we issue a WTO and exit.
FREECIB DS 0H L R1,COMPTR POINTER TO COMM FIELDS LA R2,4(,R1) CIB ORIGIN L R3,0(,R2) PONTER TO FIRST CIB * QEDIT ORIGIN=(R2),BLOCK=(R3) FREE THE CIB * B LOOP
Once we have processed a MODIFY command we need to free the CIB so our program can accept another modify command. We free it using QEDIT the same way we did with the START CIB.
JOB 6920 $HASP373 CIB01 STARTED - INIT 12 - CLASS A - SYS TCS3 f CIB01,HELLO JOB 6920 +*** MODIFY COMMAND RECEIVED *** JOB 6920 +*** HELLO *** f cib01,This is a TEST JOB 6920 +*** MODIFY COMMAND RECEIVED *** JOB 6920 +*** THIS IS A TEST *** f cib01,Parameters to pass to the program JOB 6920 +*** MODIFY COMMAND RECEIVED *** JOB 6920 +*** PARAMETERS TO PASS TO THE PROGRAM *** p cib01 JOB 6920 +*** STOP COMMAND RECEIVED *** JOB 6920 14.09.40 0.00.45 0.00.00 0000 CIB01 MVSSP JOB 6920 14.09.40 0.00.45 0.00.00 0000 CIB01 ######## JOB 6920 $HASP395 CIB01 ENDED
And here is some sample output from running the program and communicating with it using MODIFY and STOP.