.TITLE RRU - RUN TASKS AT ALL TERMINALS .MCALL QIO$C,QIOW$C,EXIT$S,SPWN$,WTSE$C,DIR$,ASTX$S,GCMLB$,GCML$ .MCALL FSRSZ$ .NLIST BEX .NLIST ME ; ; MACRO DEFINITIONS ; .MACRO DSWERR BCC .+10 MOV $DSW,R0 HALT .ENDM .MACRO IOERR TSTB IOST BPL .+10 MOV IOST,R0 EMT 50 .ENDM .MACRO SKIP A,?B,?C B: CMPB #A,(R0) BEQ .+4 BR C TSTB (R0)+ SOB R5,B JMP DONE C: .ENDM .PAGE ; ; MESSAGE DEFINTIONS ; CMP: .ASCII /RRU COMPLETED./ CMPL = .-CMP .EVEN WARN: .ASCII /**** WARNING - YOU ARE ISSUING A COMMAND TO A TERMINAL/ .ASCII / WHICH IS NOT YOUR OWN./<15><12> .ASCII / YOU WILL BECOME THE OWNER, BUT YOU WILL BE LOCKED OUT/ .ASCII / UNTIL COMPLETED. ****/<15><12> .ASCII /CONTINUE [Y OR N]:/ WARNL = .-WARN .EVEN WARNP: .ASCII /**** WARNING - YOU ARE EXECUTING COMMANDS AT A TERMINAL NOT/ .ASCII / UNDER YOUR UIC! ****/ WARNPL = .-WARNP .EVEN USED: .ASCII /**** ERROR - TERMINAL ALREADY OWNED, PRIVILEDGED, OR NON-EXISTENT. ****/ USEDL = .-USED .EVEN CMDE: .ASCII /**** ILLEGAL COMMAND FORMAT ****/ CMDEL = .-CMDE .EVEN .PAGE ; ; STORAGE DEFINITIONS ; FSRSZ$ 1 IOST: .BLKW 2 ;I/O STATUS BLOCK MCRB: GCMLB$ 2,RRU,,1 ;COMMAND LINE BUFFER MCR: .ASCII /MCR.../ ;TASK NAME TTBF: .BLKW 6 ;TTY INFO BUFFER INP: .BLKW 6 ;INPUT BUFFER SRCE: .WORD 0 ;SOURCE TTY UCB ADDRESS PRVS: .WORD 0 ;FLAG WORD FOR PRIVILEDGED TERMINAL DEST: .WORD 0 ;DESTINATION TTY UCB ADDRESS PRVD: .WORD 0 ;FLAG WORD FOR PRIVILEDGED TERMINAL LOGUIC: .WORD 0 ;STORAGE FOR LOGIN UIC SPAWN: SPWN$ MCR...,,,,,7,,,MCRB,80.,0,TT ;SPAWN MCR .PAGE ; ; START OF MAIN CODE ; START: GCML$ #MCRB ;GET THE COMMAND LINE BCC .+6 ;OKAY? JMP CHKCMD ;OTHERWISE CHECK ERROR MOV MCRB+G.CMLD+2,R0 ;GET POINTER TO COMMAND MOV MCRB+G.CMLD,R5 ;SAVE LENGTH SKIP 40 ;SKIP SPACES MOV R0,R3 ;SAVE WHERE WE ARE CLR R1 ;INIT CALL $COTB ;CONVERT TTY NUMBER TSTB -(R0) ;BACK UP OVER TERMINATOR MOV R0,R2 ;GET WHERE WE ARE NOW SUB R3,R2 ;FIND HOW MANY WE SKIPPED SUB R2,R5 ;KEEP TRACK OF HOURS SKIP 40 ;SKIP SPACES CMPB #':,(R0)+ ;DO WE HAVE THE ":"? BEQ .+6 ;YES JMP CMDERR ;NO DEC R5 ;COUNT THE ":" MOV R0,-(SP) ;SAVE FOR LATER MOV R5,-(SP) ; TST R1 ;IF NO NUMBER SPECIFIED, DON'T CHANGE BEQ 2$ ;NONE SPECIFIED OR ZERO BPL .+6 ;OKAY, SO FAR JMP CMDERR ;ERROR IF NEGATIVE MOV R1,SPAWN+S.PWVT ;SAVE IT 2$: CLR PRVS ;ASSUME UNPRIVILEDGED TERMINALS CLR PRVD ; ; GET THE UCB ADDRESSES FOR SOURCE AND DESTINATION MOV $TKTCB,R0 ;POINT TO OUR TCB MOV T.UCB(R0),R1 ;GET TO OUR UCB BIT #U2.PRV,U.CW2(R1) ;CHECK FOR PRIVILEDGED TERMINAL BEQ 1$ ;NOT PRIV. COM PRVS ;FLAG PRIVILEDGED SOURCE 1$: MOV R1,SRCE ;SAVE OUR UCB MOV $DEVHD,R0 ;POINT TO THE DEVICES FUCB: CMP #"TT,D.NAM(R0) ;GOT THE RIGHT DCB BEQ GUCB ;CHECK OUT THE POSSIBILITY FUCB2: MOV D.LNK(R0),R0 ;GET NEXT DCB BNE FUCB ;LOOP UNTIL RUN OUT JMP ERROR ;GET OUT GUCB: TST D.UNIT(R0) ;ANY UNITS FOR THIS DCB BNE 1$ ;SURE ARE TST SPAWN+S.PWVT ;ARE WE LOOKING FOR TT0:? BNE FUCB2 ;SKIP CHECK IF UNIT WON'T MATCH MOV D.UCB(R0),R1 ;THERE IS ONLY ONE UNIT FOR TT0: BR GDEST ;CONTINUE 1$: MOV D.UCBL(R0),R4 ;SAVE UCB LENGTH MOVB D.UNIT+1(R0),R5 ;SAVE HIGHEST UNIT NUMBER MOV D.UCB(R0),R1 ;GET THE UCB MOVB D.UNIT(R0),R2 ;GET FIRST UNIT NUMBER GUCB1: CMPB SPAWN+S.PWVT,R2 ;IS THIS THE DEST. UCB? BEQ GDEST ;GO PROCESS IT ADD R4,R1 ;IF NOT, CHECK NEXT UNIT UCB INC R2 ;NEXT UCB AND UNIT CMP R2,R5 ;HAVE WE COVERED THEM ALL? BLE GUCB1 ;NO JMP FUCB2 ;OTHERWISE, LOOK FOR NEW DCB GDEST: MOV R1,DEST ;SAVE THE UCB ADDRESS BIT #U2.PRV,U.CW2(R1) ;IS DESTINATION TERMINAL PRIVILEDGED? BEQ GALL ;BR IF NO COM PRVD ;FLAG IF YES GALL: MOV DEST,R0 ;GET DEST. UCB MOV SRCE,R1 ;GET SOURCE UCB BIT #U2.LOG,U.CW2(R0) ;NO ONE LOGGED ON? BNE CONT ;OKAY TST U.OWN(R0) ;SOMEONE ELSE GOT IT? BEQ 1$ ;NO JMP ERROR ; 1$: CMP U.LUIC(R0),U.LUIC(R1) ;SAME USER? BEQ CONT ;GO DO TASK WITHOUT QUESTION TST PRVS ;PRIVILEDGED SOURCE TERMINAL? BEQ SNP ;BR IF NO QIOW$C IO.WVB,5,1,,IOST,, ;WARN HIM WHAT HE'S DOING DSWERR ; IOERR ; BR CONT ;CONTINUE AS USUAL SNP: TST PRVD ;SOURCE NOT PRIV.; IS DEST. PRIV? BEQ 3$ ;BR IF NO JMP ERROR ;IF YES, DON'T LET UNPRIV. TOUCH PRIV. 3$: JMP LOCK ;NEED TO LOCK AND CHANGE ; ; CONT: MOV (SP)+,SPAWN+S.PWCL ;AND LENGTH MOV (SP)+,SPAWN+S.PWCA ;SAVE OUR COMMAND ADDRESS DIR$ #SPAWN ;SPAWN THE TASK DSWERR ; WTSE$C 7 ;WAIT FOR IT DSWERR ; JMP START ;KEEP SENDING DONE: QIOW$C IO.WVB,5,1,,IOST,, ;PRINT THE COMPLETION 1$: EXIT$S ;GET OUT ERROR: QIOW$C IO.WVB,5,1,,IOST,, ;PRINT ERROR MESSAGE DSWERR ; IOERR ; EXIT$S ;GET OUT .PAGE LOCK: QIOW$C IO.RPR,5,1,,IOST,, ;GIVE WARNING DSWERR ; IOERR ; CMPB #'Y,INP ;IS IT "Y" FOR YES BEQ LOCK2 ;YES, SO CONTINUE JMP DONE ;OTHERWISE, END LOCK2: MOV (SP)+,SPAWN+S.PWCL ;AND LENGTH MOV (SP)+,SPAWN+S.PWCA ;SAVE OUR COMMAND ADDRESS QIO$C IO.ATA,5,1,,IOST,, ;DON'T ALLOW ANY THING THRU DSWERR ; MOV DEST,R0 ;GET DEST. UCB MOV SRCE,R1 ;AND SOURCE UCB MOV U.LUIC(R0),LOGUIC ;SAVE LOGIN UIC MOV U.LUIC(R1),U.LUIC(R0) ;SET SOURCE UIC AS THIS UIC DIR$ #SPAWN ;ISSUE THE MCR COMMAND DSWERR ; WTSE$C 7 ;WAIT FOR THE COMPLETION DSWERR ; MOV DEST,R0 ;GET THE DEST. UCB AGAIN MOV LOGUIC,U.LUIC(R0) ;RESTORE UICSHIP QIOW$C IO.DET,5,1 ;DETACH FROM THE TERMINAL NOW DSWERR ; JMP START ;KEEP PROCESSING ; CHKCMD: CMPB MCRB+G.ERR,#GE.EOF ;GOT A CONTRL Z? BNE CMDERR ;NO JMP DONE ;EXIT CMDERR: QIOW$C IO.WVB,5,1,,IOST,, ;PRINT ERROR DSWERR ; IOERR ; EXIT$S .PAGE NORAST: MOV (SP)+,R0 ;CLEAN STACK ASTX$S ;RETURN XCAST: MOV (SP)+,R0 ;CLEAN STACK ASTX$S ;RETURN .END START