.TITLE SEND MSG TO ANOTHER TERMINAL(S) .IDENT *17NO76* ; ; ; AUTHOR: PHILIP D. BROOKE ; DIGITAL EQUIPMENT CORPORATION ; ; ; '...SEN' IS AN MCR COMMAND THAT WILL TRANSMIT A MESSAGE TO ANOTHER TERMINAL ; OR TERMINALS THAT EXIST IN THE SYSTEM. THE DESTINATION TERMINAL ALARM ; IS SOUNDED ONCE AND THE MESSAGE IS PRINTED IN THE FORMAT: ; **TTMM "MESSAGE" ; WHERE TTMM IS THE PHYSICAL DEVICE AND UNIT NUMBER OF THE SENDING ; TERMINAL. ; ; FOUR TRANSMISSION MODES ARE AVAILABLE: ; 1) SEN TTNN[:] "MESSAGE" ; WILL PRINT "MESSAGE" ON TTNN. ; 2) SEN OPR[:] "MESSAGE" ; WILL PRINT "MESSAGE" ON THE CONSOLE OUTPUT (CO:) DEVICE. ; 3) SEN LOG[:] "MESSAGE" ; WILL PRINT "MESSAGE" ON ALL LOGGED-IN TERMINALS EXCEPT ; THE SENDER'S. THE USER MUST BE PRIVILEGED IN ORDER TO USE ; THIS FORM OF THE COMMAND. ; 4) SEN ALL[:] "MESSAGE" ; WILL PRINT "MESSAGE" ON EVERY TERMINAL IN THE SYSTEM ; (INCLUDING SLAVED ONES) EXCEPT FOR THE SENDER'S TERMINAL. ; ; ; TASK BUILD INSTRUCTIONS: ; SEND/PR/AB/-CP/DS/MU/-FX/-FP,SEND/-SP=SEND,[1,1]EXEC.STB ; / ; PAR=GEN ; PRI=225 ; STACK=20 ; TASK=...SEN ; UNITS=1 ; ASG=TI:1 ; UIC=[1,1] ; / ; ; ; ; ; .MCALL GMCR$, ALUN$S, QIOW$, QIOW$S, EXIT$S, DIR$, GLUN$ .MCALL ISTAT$, STATE$, TRAN$, CALL, RETURN, QIO$S, WTSE$S .MCALL SETF$S, ASTX$S, IHAR$S, ENAR$S ; ; $RONLY = 1 ; GENERATE TPARS STUFF READ-ONLY ; ; .PSECT IMPURE,RW,D,LCL,REL,CON ; DEVICE: .WORD 0 ; THE UNIT WORD M U S T IMMEDIATELY FOLLOW THE DEVICE WORD UNIT: .WORD 0 LUNINF: .BLKW 6 ; GMCR: GMCR$ ERRQIO: QIOW$ IO.WVB,1,1,,,,<,,60> ; ; ; .PSECT PURE,RO,I,LCL,REL,CON ; ; ENTRY: DIR$ #GMCR BCC 5$ ; BR IF WE ARE MCR ROUTINE JMP EXIT ; ELSE, DO NOT ALLOW USER TO RUN 5$: MOV 0,R3 ; SAVE CHARACTER COUNT MOV R3,R0 ; SAVE IT AGAIN MOV #GMCR+G.MCRB,R4 ; GET MCR BUFER ADDRESS MOV #SNDSTB,R5 ; ADX OF STARTING STATE IN STATE TABLE MOV #SNDKTB,R2 ; ADX OF KEYWORD TABLE MOV #1,R1 ; PROCESS BLANKS NORMALLY CALL @#.TPARS ; PARSE INPUT STRING BCC UNEXIT ; BR IF INPUT CORRECT ; SYNERR: MOV #SYNMSG,ERRQIO+Q.IOPL ; GET ERROR MSG ADX MOV #SYNSIZ,ERRQIO+Q.IOPL+2 ; GET ERROR MSG LENGTH DIR$ #ERRQIO ; PRINT SYNTAX ERROR MESSAGE ; MOV #GMCR+G.MCRB,R1 ; GET MCR BUFFER ADX MOV R1,ERRQIO+Q.IOPL ; SET IT IN THE QIO DPB MOV R0,ERRQIO+Q.IOPL+2 ; SET THE BUFFER LENGTH IN THE QIO DPB MOV #40,ERRQIO+Q.IOPL+4 ; SINGLE SPACE NOW DIR$ #ERRQIO ; OUTPUT ENTIRE TYPED-IN LINE ; SUB R3,R0 ; DETERMINE LENGTH OF SCANNED STRING 1$: MOVB #40,(R1)+ ; BLANK OUT COMMAND LINE CMP R1,R4 ; IS THIS ADDRESS OF ERROR? BNE 1$ ; BR IF NO, CONTINUE MOVB #'^,@R1 ; SET ASCII POINTER TO ERROR INC R0 ; INCLUDE THE CAROT IN TYPEOUT MOV #GMCR+G.MCRB,ERRQIO+Q.IOPL ; SET THE MCR BFR ADX IN THE QIO DPB... MOV R0,ERRQIO+Q.IOPL+2 ; ...AND THE BUFFER LENGTH DIR$ #ERRQIO ; OUTPUT ASCII POINTER TO PART OF C.S. IN ERROR BR EXIT ; UNEXIT: MOVB #7,-(R4) ; DEPOSIT A BEL CHARACTER MOVB #11,-(R4) ; A HORIZONTAL TAB ALUN$S #1,#"TI ; ASSIGN A LUN TO THE REQUESTING TERMINAL BCS EXIT ; BR ON ANY ERROR DIR$ #GLUN ; NOW FIND OUT WHAT PHYSICAL DEVICE TI REALLY IS MOV R4,R2 ; SAVE CURRENT LINE ADDRESS MOVB LUNINF+2,R4 ; PICK UP TERMINAL'S UNIT # BIC #177700,R4 ASHC #-3,R4 ASH #-13.,R5 BIC #177770,R5 BIS #60,R5 MOVB R5,-(R2) ; STORE LOW-ORDER UNIT# IN THE BFR BIS #60,R4 MOVB R4,-(R2) ; STORE HIGH-ORDER UNIT# IN THE BFR MOVB LUNINF+1,-(R2) ; STORE 2ND CHAR OF DEVICE NAME MOVB LUNINF,-(R2) ; STORE 1ST CHAR MOVB #'*,-(R2) ; DEPOSIT A FLAG IN THE MSG BFR MOVB #'*,-(R2) MOV R2,R1 ; SAVE THE (POSSIBLY NEW) BEGINNING ADX OF BFR SUB #GMCR+G.MCRB,R1 ; OBTAIN THE DIFFERENCE IN LENGTH... ; ...BETWEEN THE NEW ADX AND THE OLD SUB R1,R0 ; FORM THE LENGTH OF THE NEW LINE TST UNIT ; SENDING TO A SUBSET OF ALL TERMINALS? BMI SNDALL ; YES. HUGGY BEAR ALUN$S #1,DEVICE,UNIT BCS EXIT DIR$ #GLUN ; GET INSIDE DOPE ON DESTINATION DEVICE BIT #UC.TTY,LUNINF+U.C1 ; IS IT A TTY-LIKE DEVICE? BEQ EXIT ; BR IF NO. DON'T DO SEND QIOW$S #IO.WBT,#1,#1,,,, ; EXIT: EXIT$S ; SNDALL: MOV @#.PUDBA,R3 ; GET ADX OF 1ST PUD ENTRY MOV @#.PUDEA,-(SP) ; GET ADX OF LAST PUD ENTRY CLR R1 ; KEEP COUNT OF #QIO REQUESTS IHAR$S ; PREVENT ANY DECR TO R1 JUST YET 1$: BIT #UC.TTY,U.C1(R3) ; THIS A TTY DEVICE? BEQ 2$ ; BR IF NO, DON'T ATTEMPT A SEND CMP UNIT,#-2 ; SENDING ONLY TO LOGGED-IN TERMINALS? BNE 3$ ; BR IF NO. SENDING TO EVERY TERMINAL BITB #UT.LG,U.PR(R3) ; IS TERMINAL LOGGED ON? BNE 3$ ; YES, PROCEED WITH SEND. ELSE NO NEED. 2$: ADD #U.SZ,R3 ; GET NEXT PUD ENTRY ADX CMP @SP,R3 ; LAST ENTRY PROCESSED? BHI 1$ ; BR IF NO, GO BACK & LOOK AT IT BR 4$ ; ELSE, GO WAIT ON ALL QIOS TO BE FINISHED 3$: MOVB U.UN(R3),R4 ; PICK UP RECEIVER TTY'S UNIT # CMP LUNINF,@R3 ; SAME DEVICE AS ISSUING TERMINAL? BNE 5$ ; BR IF NO, ISSUE QIO CMPB LUNINF+2,R4 ; SAME UNIT#? BEQ 2$ ; BR IF YES, DON'T ISSUE QIO 5$: ALUN$S #1,@R3,R4 ; ASSIGN TO CURRENT DEVICE & UNIT INC R1 ; SHOW ANOTHER TERMINAL TO GET OUTPUT QIO$S #IO.WVB,#1,,,,#IODONE, BR 2$ ; GO LOOK FOR MORE TERMINALS ; 4$: TST R1 ; WERE ANY TERMINALS ACTUALLY SENT THE MESSAGE? BEQ EXIT ; BR IF NO ENAR$S ; IT'S SAFE NOW: ALL QIOS ISSUED WTSE$S #2 ; WAIT FOR AST TO SIGNAL THAT ALL I/O DONE BR EXIT ; ; ; I/O DONE AST SERVICE FOR 'SEN ALL' CLASS OF QIOS ; IODONE: DEC R1 ; HAS ALL OUTPUT COMPLETED? BGT 1$ ; BR IF NO SETF$S #2 ; YES. SIGNAL MAINLINE TO CONTINUE 1$: TST (SP)+ ; POP THE I/O STATUS WORD ADDRESS ASTX$S ; EXIT THE AST ; ; ; ACTION ROUTINES FOR THE PARSER ; SETDV1: MOVB .PCHAR,DEVICE ; STORE 1ST CHARACTER OF DEVICE NAME RETURN ; SETDV2: MOVB .PCHAR,DEVICE+1 ; STORE 2ND CHARACTER OF DEVICE NAME RETURN ; SETUNT: MOV .PNUMB,UNIT ; STORE THE DEVICE UNIT NUMBER BMI ABSCAN ; GO AND ABORT SCAN RETURN ; CKPRIV: MOV @#.CRTSK,R1 ; GET TASK'S ATL ADDRESS MOV A.TI(R1),R1 ; GET PUD ADDRESS OF THE TI: BITB #UT.PR,U.PR(R1) ; IS USER PRIVILEGED? BNE PRIVOK ; BR IF YES. OK TO DO SEND ALL: ABSCAN: DEC R4 ; POINT TO ILLEGAL DEVICE NAME INC R3 ; ...AND THAT MAKES LENGTH A LITTLE MORE PRIVOK: RETURN ; ADJUSTED REGS SHOULD BOMB SCAN ; SETALL: JSR PC,CKPRIV ; ENSURE USER IS PRIV FOR THIS COMMAND DEC UNIT ; REMEMBER THAT THIS WAS SEN ALL RETURN ; SETLOG: JSR PC,CKPRIV ; MUST BE PRIVILEGED FOR THIS COMMAND SUB #2,UNIT ; REMEMBER THAT THIS WAS SEN LOG RETURN ; SETOPR: MOV #DEVICE,R1 ; ADDRESS OF WORD THAT HOLDS DEVICE NAME MOV #"CO,(R1)+ ; SET TTN AS OPERATOR'S CONSOLE, WHERE THE MOV #0,(R1)+ ; DEFAULT IS CO: OPRUNT == .-2 ; GLOBAL FOR CHANGING DEFAULT UNIT FOR OPERATOR'S CONSOLE RETURN .PSECT PURDAT,RO,D,LCL,REL,CON .NLIST BEX ; ; ; EXECUTIVE DIRECTIVES GLUN: GLUN$ 1,LUNINF ; DPB FOR OBTAINING PUD INFORMATION ; ; ; SYNTAX ERROR MESSAGE SYNMSG: .ASCII '[SEN -- INDICATED ITEM IS IN ERROR]' SYNSIZ = .-SYNMSG .EVEN ; ; ; PARSING TABLES ; ISTAT$ SNDSTB,SNDKTB ; ; SKIP COMMAND NAME AND FOLLOWING SEPARATORS STATE$ START TRAN$ $STRNG ; STATE$ TRAN$ $BLANK ; ; ; READ DEVICE AND UNIT NUMBER. A UNIT NUMBER IS REQUIRED. STATE$ TRAN$ "ALL",COLON,SETALL TRAN$ "LOG",COLON,SETLOG TRAN$ "OPR",COLON,SETOPR TRAN$ $ANY,,SETDV1 ; STATE$ TRAN$ $ANY,,SETDV2 ; STATE$ TRAN$ $NUMBR,,SETUNT ; STATE$ COLON TRAN$ ':,COLBLK TRAN$ 040,$EXIT TRAN$ 011,$EXIT ; STATE$ COLBLK TRAN$ 040,$EXIT TRAN$ 011,$EXIT TRAN$ $LAMDA,$EXIT ; ; STATE$ ; ; ; ; ; .END ENTRY