OBJNAM XFORCE.LIT ; extended replacement for FORCE.LIT command VMAJOR=2 ; Created 12-Dec-84, last modified 19-Feb-86 VMINOR=2 ; By Irv Bromberg, Medic/OS Consultants VEDIT=13. ; 78 Wildginger Way, Toronto, CANADA M3H 5X1 ; Phone (416) 586-4499 IF EQ,1 Extensions implemented -- (1) -- delete vestigial error: AND @TCB,D3 prior to TRMICP (2) -- allow control codes to be forced using ^ as leadin (3) -- reduce waiting time if job locked in J.TOW state (4) -- if job locked in J.TOW state then flush output for duration of force (5) -- if flushing output queue wait for job to reach sleep or external wait or terminal input wait state before restoring original terminal driver. (6) -- don't force trailing spaces/tabs (even if followed by comment symbol) (7) -- pause after each control code so TDV will not think multi-char sequence WARNING -- If output could be immediately inhibited do not use KILL command prior to FORCE as it will not finish -- use FLUSH command instead. Application note: When forcing control codes consider what T.STS mode the target job's terminal is in, else the forced control codes may be ignored or may not have their desired effect. Often it is necessary to put forced control codes on the next line after a monitor-level command, for example: XFORCE JOB2 VUE FILNAM ; no control codes on this line -- T.STS is NIL, would be lost ^[^J^J^Z^[F^M ; this line is not forced until JOB2 reaches J.TIW state and ; by that time T.STS is DAT!ECS!XLT so control codes work. ENDC SEARCH SYS SEARCH SYSSYM SEARCH TRM JCB=A0 User=A1 Buffer=A2 SavPos=A3 TCB=A5 Atemp=A6 Char=D1 JName=D3 Count=D3 Flags=D5 ; 0 set for single-line force ; 1 set on error - job guarded or not attached and user is running CMD file ; 2 set if force is to self ; 3 set if output queue flushed through FLUSH.TDV HT=9. CR=13. SPACE=32. PHDR -1,0,PH$REE!PH$REU SUBW #6,SP ; get some workspace FILNAM @SP,XXX ; get job name MOV @SP,JName ADDW #6,SP MOV JOBTBL,A3 CLR Flags JOBIDX CMP JName,JOBNAM(A6) BNE NxtJob BSET #2,Flags ; set = forcing to self NxtJob: MOV (A3)+,D7 BEQ NxtJob ; skip unallocated jobs CMP D7,#-1 ; end of job table? BNE Srch TYPECR CALL ChkCMZ BR Process Srch: MOV D7,JCB CMP JName,JOBNAM(JCB) BNE NxtJob MOV JOBTRM(JCB),TCB ; get TCB MOV TCB,D7 ; test if attached BNE Process TYPECR CALL ChkCMZ Process:BTST #2,Flags BNE ModeChk MOVW JOBTYP(JCB),D7 ANDW #J.GRD,D7 BEQ ModeChk JOBIDX CMPW JOBUSR(A6),#^H0102 ; OPR: can force to guarded job BEQ ModeChk TYPECR CALL ChkCMZ ModeChk:BYP ; check if single or multi-line LIN BEQ NxtCmd BSET #0,Flags ; set = single-line command BTST #1,Flags JNE Done BR Force NxtCmd: KBD Done ; get next command to force BYP CMPB @Buffer,#'; ; skip if comment BEQ NxtCmd LIN ; empty line? BNE Force ; no, force it Done: MOVB #CR,Char TTY BTST #3,Flags ; was output flushed through FLUSH.TDV? BEQ Quit ; no, exit ; wait for job to reach SLP or EXW or TIW state before restoring TDV ; maximum wait = 10 seconds (50 x 200 ms) MOVW #50-1,Count ; -1 for DBF loop Loop: SLEEP #2000. CTRLC More ; not done but do it anyway if ^C hit MOVW JOBSTS(JCB),D7 ; test for SLP or EXW or TIW state ANDW #,D7 DBNE Count,Loop BNE DoIt More: TYPECR DoIt: POP T.TDV(TCB) ; then restore original terminal driver Quit: EXIT Force: BTST #1,Flags ; error from command file? BNE NxtCmd ; yes, discard until empty line BTST #2,Flags ; forcing to self? JNE Move ; yes, know it's OK to do it MOV #10.,Count ; try 0.5 x 10 = 5 seconds ChkECC: TST T.ECC(TCB) ; don't force more until echo done BNE Wait ; wait for echo to finish MOVW #J.TIW,D7 ; wait until job is waiting for ANDW JOBSTS(JCB),D7 ; terminal input JNE Move ; yes, TIW state, go do TRMICP Wait: CTRLC Done SLEEP #5000. ; wait 1/2 sec and try again SUB #1,Count BNE ChkECC MOVW #J.TOW,D7 ; check for TOW state lockup ANDW JOBSTS(JCB),D7 BNE DoFlush ; yes, output locked, flush it TST T.ECC(TCB) ; check for echo lockup BNE DoFlush ; yes, echo locked, flush output Busy: TYPECR CALL ChkCMZ JMP Force DoFlush:TYPECR <%Output inhibited -- flushing output queue> BSET #3,Flags ; remember we did it PUSH T.TDV(TCB) ; save terminal driver LEA Atemp,FLUSH ; index FLUSH.TDV MOV Atemp,T.TDV(TCB) ; switch to FLUSH.TDV CLR T.ECC(TCB) ; discard echo count JRUN J.TOW ; make locked job run & flush output JMP Force ; go back to do output flush NxtChr: ADD #1,Buffer Move: MOVB @Buffer,Char CMPB Char,#HT ; don't force trailing spaces/tabs BEQ ChkTrl CMPB Char,#SPACE BEQ ChkTrl CMPB Char,#'^ ; check for CTRL-code leadin BNE ChkCmt INC Buffer ; skip to next character MOVB @Buffer,Char ; get char to be CTRL'ed UCS ; normalize CMPB Char,#'@ ; must be within range @ to _ BLO ChkCmt ; else pass through unchanged CMPB Char,#'_ BHI ChkCmt SUBB #'@,Char ; convert to control-code BR Inp ChkTrl: ; space/tab found, check if it is a trailing character, discard if so MOV Buffer,SavPos ; save position in buffer BYP ; bypass blanks/tabs LIN ; end of line? BEQ EndCmd ; yes, leave buffer pointing to end MOV SavPos,Buffer ; restore position in buffer BR Inp ; and force the legitimate space/tab ChkCmt: CMPB Char,#'; ; don't force comments BNE Inp EndCmd: MOVB #CR,Char ; terminate command with CR Inp: CMPB Char,#SPACE ; If char is a control-code then BHIS Normal ; pause long enough so that TDV will TRMICP ; not think it is a lead-in to a multi- SLEEP #600. ; character sequence. BR ChkLIN Normal: TRMICP ; force input character ChkLIN: LIN ; command line finished? BNE NxtChr ; no, go back to move more BTST #0,Flags ; was it a single-line command? JEQ NxtCmd ; no, go back for more JMP Done ChkCMZ: JOBIDX User ; if command file in progress must TSTW JOBCMZ(User) ; discard lines until empty line BNE 10$ POP ; discard RTN address JMP Done 10$: BSET #1,Flags ; signal error in command file RTN ; FLUSH.TDV is like PSEUDO.TDV but has NULL output bit set in terminal ; attributes word: WORD [FLU],[SH ] ; FLUSH driver name FLUSH: WORD ^O300 ; null output, local echo RTN ; No Input routine. RTN ; No OUTPUT routine. BR Echo ; ECHO routine. RTN ; No CRT routine. Echo: CLR T.ECC(TCB) ; cancel any echo characters RTN END .