.TITLE HOST - CONNECT TI: TO OTHER HOST .IDENT /003012/ .Enable LC ; ; V3011 18-SEP-80 J. A. SCHRIESHEIM ; ADDED PASSTHROUGH CONNECT LOGIC ; ; ; v3012 25-Sep-80 C. Strutt ; Added ^N to pass ^O to remote host and suppress output til ^O... received ; But make the ^N subject to change with /SUPRES: switch. ; Collect high water mark data on incoming receives if D$$BUG defined ; ;D$$BUG=0 ;define for debugging .MCALL CRBDF$,CNBDF$,NSSYM$,ISTAT$,STATE$,TRAN$ .MCALL OPNW$S,REC$S,SND$S,CLSW$S .MCALL DIR$,GMCR$,ASTX$S,DSAR$S,ENAR$S,GPRT$S,SPND$S,EXIT$S .MCALL ALUN$S,CLEF$S,SETF$S,WTSE$S,QIOW$S,QIO$S CRBDF$ CNBDF$ NSSYM$ .MACRO ERROR MSG MOV #'MSG,R0 JMP ERROR .ENDM ERROR .MACRO MESSAGE LINE .NCHR $$$LNG, .ASCII <$$$LNG+1><15>\'LINE'\ .ENDM MESSAGE .MACRO PUSH LIST .IRP .L, MOV .L,-(SP) .ENDR .ENDM PUSH .MACRO POP LIST .IRP .L, MOV (SP)+,.L .ENDR .ENDM POP .PSECT POOL,D AVAIL: .WORD POOL,0 POOL: .WORD 0,POOLNG .PSECT ;+ ; COMMAND LINE PARSER STATE TABLES ;- ISTAT$ .MCRST,.MCRKW STATE$ TRAN$ $STRNG ; THE MCR COMMAND. STATE$ TRAN$ $EOS,$EXIT ; END OF COMMAND TRAN$ $BLANK ; OR SEPERATOR. STATE$ TRAN$ !NODS,,SETNOD ; THE NODE NAME STATE$ SWTS ; SCAN FOR SWITCHES TRAN$ $EOS,$EXIT TRAN$ <'/> STATE$ SWTS2 TRAN$ !SWTESC,SWTS TRAN$ !SWTPAU,SWTS TRAN$ !SWTSPS,SWTS STATE$ NODS ; PROCESS NODE NAME (LISTS) TRAN$ $EOS,$EXIT TRAN$ $STRNG,NODS TRAN$ <':>,NODS TRAN$ $LAMDA,$EXIT STATE$ SWTESC ; PROCESS /ESCAPE: SWITCH TRAN$ "ESCAPE" STATE$ TRAN$ <':> STATE$ TRAN$ $NUMBR,$EXIT,SETESN TRAN$ $ANY,$EXIT,SETESC STATE$ SWTPAU ; PROCESS /PAUSE: SWITCH TRAN$ "PAUSE" STATE$ TRAN$ <':> STATE$ TRAN$ $NUMBR,$EXIT,SETPAN TRAN$ $ANY,$EXIT,SETPAU STATE$ SWTSPS ; process /SUPRES: switch TRAN$ "SUPRES" STATE$ TRAN$ <':> STATE$ TRAN$ $NUMBR,$EXIT,SETSPN TRAN$ $ANY,$EXIT,SETSPS STATE$ .PAGE ;+ ; COMMAND PARSER ACTION ROUTINES ;- .PSECT POOL,D SETNOD: MOV #NODE,R1 ; POINT TO NODE NAME BUFFER MOV .PSTPT,R2 ; POINT TO USER SUPPLIED NAME(S) MOV .PSTCN,R0 ; GET LENGTH BEQ 30$ ; IF EQ, NULL TRANSITION CMP R0,#NODEL-1 ; IS THE NODE LIST TOO LONG FOR BUFFER ? BHI 90$ ; IF HI, YES - REJECT 20$: MOVB (R2)+,(R1)+ ; OTHERWISE INSERT USER'S NAME(S) SOB R0,20$ CLRB (R1) ; MAKE LIST ASCIZ 30$: RETURN 90$: ADD #2,(SP) RETURN SETESN: MOVB .PNUMB,ESCAPE RETURN SETESC: MOVB .PCHAR,ESCAPE RETURN SETPAN: MOVB .PNUMB,PAUSE RETURN SETPAU: MOVB .PCHAR,PAUSE RETURN SETSPN: MOVB .PNUMB,SUPRES RETURN SETSPS: MOVB .PCHAR,SUPRES RETURN .PSECT DATA,D STATUS: .BYTE 0 ; STATUS SWITCHES: DET = 001 ; DETACH TERMINAL CLS = 002 ; CLOSE THE LINK ABT = 004 ; NOTIFY OF LINK ABORT PAU = 010 ; PAUSE THE PROGRAM EXT = 020 ; EXIT THE PROGRAM PAUSE: .BYTE 'P-100 ESCAPE: .BYTE 'Y-100 SUPRES: .Byte 'N-100 CTRLO: .Byte 0 ; set non-zero when ^O typed (cleared on second ; ^O or receipt of data after ^O echo CTRLOS: .Byte 0 ; set non-zero whilst we are gobbling characters ; CTRLO CTRLOS ; 0 0 normal - pass all chars ; -1 -1 ^O typed - supress all chars ; until ^O... echo received ; -1 0 ^O typed - wait for another ; ^O to be typed or data from 20 BELL: .BYTE 7 .Even TTYBF: .WORD 0,TTYBF RECLN:: .WORD 200. .if df D$$BUG HWM: .Word 0 ; holds high water mark for incoming message size IMSGCT: .Blkw 200. ; holds nr of incoming messages of each length .endc .PSECT POOL,D CONBLK: .BYTE 2 ; LUN FOR LINK .BYTE 1 ; EVENT FLAG FOR LINK I/O .BYTE 0 ; CURRENT HOP COUNT .BYTE 23. ; TARGET OBJECT TYPE .WORD NODE ; POINTER TO ASCIZ NODE LIST .WORD 0 ; POINTER TO ASCIZ TARGET TASK NAME .WORD 0 ; POINTER TO 3 ASCIZ ACCESS CONTROL STRINGS NODEL=80. ; MAX LENGTH OF NODE NAME LIST NODE: .ASCIZ /MILL20/ ; DEFAULT NODE NAME .BLKB > IOSTA: .BLKW 2 MCR: GMCR$ .PSECT POOL,D NONET: MESSAGE SYNTAX: MESSAGE INIT: MESSAGE CONERR: MESSAGE ERRBUF: .BLKB 132. .EVEN .PSECT TEXT,D BYE: MESSAGE .PSECT POOL,D START: ALUN$S #1,#"NS,#0 ALUN$S #2,#"NS,#0 OPNW$S #1,#1,#IOSTA BCS 101$ TSTB IOSTA BMI 101$ DIR$ #MCR ; GET MCR COMMAND LINE. BCS 10$ ; IF ONE IS AVAILABLE MOV #.MCRST,R5 ; THEN MOV #G.MCRB+MCR,R4 ; PARSE THE COMMAND LINE MOVB $DSW,R3 MOV #.MCRKW,R2 MOV #3*400+1,R1 CALL .TPARS ; IF SYNTAX ERROR BCS 102$ ; THEN NOTIFY USER. 10$: MOV #CONBLK,R5 ; POINT TO CONNECT PARAMETERS CALL $CONN ; ATTEMPT TO CONNECT TO SERVER BCS 20$ ; IF CS, ERROR DSAR$S ; DISABLE AST'S CALL RECINI ; HANG INITIAL RECEIVES BCS 103$ ; IF CS, EXIT JMP ATTCH ; ELSE, CONTINUE 20$: MOV #ERRBUF,R0 ; ELSE, POINT TO ERROR MESSAGE BUFFER MOV #$ERROR,R1 ; POINT TO ERROR MESSAGE RETURNED 30$: MOVB (R1)+,(R0)+ ; COPY ERROR MESSAGE INTO BUFFER BNE 30$ ; ... SUB #CONERR+2,R0 ; CALC MESSAGE LENGTH MOVB R0,CONERR ; SET LENGTH ERROR CONERR ; CONNECT ERROR 101$: ERROR NONET ; NO NETWORK 102$: ERROR SYNTAX ; COMMAND SYNTAX ERROR 103$: ERROR INIT ; INITIALING ERROR .PSECT CODE,I GONE: MOV #BYE,R0 ERROR: MOVB (R0)+,R1 QIOW$S #IO.WLB,#3,#3,,,, EXIT: CLSW$S #1,#1 .if df D$$BUG MOV HWM,R0 ; copy high water mark IOT ; so we can see it in a register dump .endc EXIT$S SPND: BICB #PAU,STATUS SPND$S ATTCH: QIOW$S #IO.ATA,#3,#3,,,,<#SND> 10$: TSTB STATUS BEQ 30$ BITB #EXT,STATUS BNE EXIT BITB #ABT,STATUS BNE GONE BITB #PAU,STATUS BNE SPND 30$: CLEF$S #1 ENAR$S WTSE$S #1 40$: DSAR$S MOV TTYBF,R5 BEQ 10$ MOV R5,R4 MOV (R4)+,TTYBF BNE 50$ MOV #TTYBF,TTYBF+2 50$: ENAR$S MOV (R4)+,R3 .if df D$$BUG ; debug only code CMP R3,HWM ; check for exceeding high water mark BLE 55$ ; we are not MOV R3,HWM ; yes we are - store new high 55$: PUSH R2 ; save a register MOV R3,R2 ; copy the length ASL R2 ; form a word offset INC IMSGCT(R2) ; bump a count for this length POP R2 ; restore register .endc ;df D$$BUG TSTB CTRLO ; are we suppressing characters (gobbling?) BEQ 59$ ; no TSTB CTRLOS ; are we really suppressing characters? BEQ 58$ ; no so finish with ^O processing for now 56$: ; here to look for the sequence ^O... suppressing any ; characters that come before it CMPB (R4)+,#'^+200 ; start of the sequence? BNE 57$ ; nope DEC R3 ; adjust character count BEQ 100$ ; if we end the buffer we're through CMPB (R4)+,#'O+200 ; next character BNE 57$ ; no match, so start over from the next character DEC R3 ; keep the character count right BEQ 100$ ; if we've no more chars we've finished .rept 3 CMPB (R4)+,#'. ; match the next char? BNE 57$ ; no so restart the sequence DEC R3 ; adjust the character count BEQ 100$ ; if we end the buffer that's it .endr ; if we get here, we have successfully recognised the ; ^O... sequence, so reset the flag and output the buffer ; from the start of the sequence CLRB CTRLOS ; reset the flag to stop more suppressing SUB #5,R4 ; restore the pointer and counts to the ADD #5,R3 ; start of the sequence BR 59$ ; and type out from there 57$: ; here when we fail to match, but we must still suppress ; so keep looking while there's characters to check DEC R3 ; decrement the character count BNE 56$ ; loop while there's more in the buffer BR 100$ ; there is no more in the buffer; we haven't ; recognised the sequence so the whole ; buffer is thrown away and a receive posted immediately 58$: CLRB CTRLO ; we've got data so cancel the ^O 59$: QIO$S #IO.WAL,#3,,,R5,#60$, ; put the (remainder of the) buffer BR 40$ ; out to the terminal 60$: MOV (SP)+,R0 MOV R0,R1 CMP (R0)+,(R0)+ REC$S #2,,R1,#REC, BCS 99$ ASTX$S 99$: BPT 100$: MOV R5,R4 ; copy buffer address CMP (R4)+,(R4)+ ; point to the data area REC$S #2,,R5,#REC, ; post a receive for more data BCS 99$ ; if an error occurs go elsewhere JMP 40$ ; back to look for more data SND: CMPB ESCAPE,(SP) BEQ 70$ CMPB PAUSE,(SP) BEQ 80$ CMPB SUPRES,(SP) ; if user typed the 'suppress output' char BNE 10$ ; no MOVB #'O-100,(SP) ; convert it to a ^O for the other host TSTB CTRLO ; are we already in a ^O state? BNE 5$ ; yup COMB CTRLO ; no, well we are now, so mark it MOVB CTRLO,CTRLOS ; and set to suppress characters for a while BR 10$ ; now ship the ^O to him 5$: CLRB CTRLO ; set the state back to no ^O processing CLRB CTRLOS ; and no character gobbling 10$: MOV #5,R1 MOV #AVAIL,R0 CALL $RQCB BCS 40$ MOV R0,R1 CMP (R0)+,(R0)+ MOVB (SP),(R0) ; INSERT THE CHARACTER. SND$S #2,,R1,#60$, BCS BREAK 20$: TST (SP)+ ASTX$S 40$: QIO$S #IO.WAL,#3,,,,,<#BELL,#1,#0> BR 20$ 60$: MOV (SP)+,R2 MOV #5,R1 MOV #AVAIL,R0 CALL $RLCB ASTX$S 70$: BISB #DET!CLS!EXT,STATUS ; CLOSE THE LINK BR 90$ 80$: BISB #DET!PAU,STATUS ; DETACH THE TERMINAL 90$: TST (SP)+ ABORT: BITB #DET,STATUS BEQ 10$ BICB #DET,STATUS QIOW$S #IO.DET,#3,#1 10$: BITB #CLS,STATUS BEQ 70$ BICB #CLS,STATUS CLSW$S #1,#1 70$: ASTX$S BREAK: BPT RECINI: MOV #3.,R2 ; INITIATE 3 READS 60$: MOV #4,R1 ADD RECLN,R1 MOV #AVAIL,R0 PUSH R2 CALL $RQCB POP R2 BCS 90$ MOV R0,R1 CMP (R0)+,(R0)+ REC$S #2,,R1,#REC, BCS 90$ SOB R2,60$ 90$: RETURN REC: MOV (SP)+,R0 TSTB (R0) BMI 40$ BITB #PAU,STATUS BNE 70$ CLR (R0) MOV #TTYBF,R1 TST (R1)+ BNE 10$ SETF$S #1 10$: MOV R0,@(R1)+ MOV R0,-(R1) BR 90$ 40$: BISB #DET!CLS!ABT,STATUS BR ABORT 70$: MOV R0,R1 TST (R0)+ MOV (R0)+,R2 .if df D$$BUG ; debug only code CMP R2,HWM ; compare count against high water mark BLE 80$ ; if hwm not exceeded skip this MOV R2,HWM ; new high water mark 80$: PUSH R3 ; save a register MOV R2,R3 ; copy the length ASL R3 ; form a word address INC IMSGCT(R3) ; bump a count for this length POP R3 ; restore register .endc ;df D$$BUG QIOW$S #IO.WAL,#3,#1,,R1,, REC$S #2,,R1,#REC, 90$: ASTX$S .PSECT POOL,D .BLKB 200. POOLNG =.-POOL .END START