; UPD ID= 2200, SNARK:<6.1.MONITOR>TVTSRV.MAC.8, 5-Jun-85 11:23:05 by MCCOLLUM ;TCO 6.1.1406 - Update copyright notice. ; UPD ID= 2000, SNARK:<6.1.MONITOR>TVTSRV.MAC.7, 23-May-85 14:53:47 by MCCOLLUM ;Fix typo in previous edit ; UPD ID= 1990, SNARK:<6.1.MONITOR>TVTSRV.MAC.6, 17-May-85 16:05:18 by MCCOLLUM ;TCO 6.1.1238 - Document the TVTNTV BUGHLT. ; UPD ID= 1422, SNARK:<6.1.MONITOR>TVTSRV.MAC.5, 29-Jan-85 11:38:44 by PAETZOLD ;TCO 6.1.1159 - Make monitor believe that TVTs are high speed. ;TCO 6.1.1158 - Decrease possible scheduler latency by incrementing PSKD1. ; UPD ID= 1044, SNARK:<6.1.MONITOR>TVTSRV.MAC.4, 12-Nov-84 15:27:52 by PAETZOLD ;TCO 6.1041 - Move ARPANET to XCDSEC ; UPD ID= 966, SNARK:<6.1.MONITOR>TVTSRV.MAC.3, 6-Nov-84 10:40:26 by PAETZOLD ;TCO 6.2268 - Make arg check in CHKTVT. ; UPD ID= 958, SNARK:<6.1.MONITOR>TVTSRV.MAC.2, 5-Nov-84 19:17:23 by PRATT ;TCO 6.1.1032 - Make TTYSRV compile independently: Rename TTANDV to TVTSRV ; UPD ID= 932, SNARK:<6.1.MONITOR>TTANDV.MAC.5, 28-Oct-84 11:31:10 by PRATT ;TCO 6.1.1022 - Add code for NTINF% "return remote hostname" ; UPD ID= 905, SNARK:<6.1.MONITOR>TTANDV.MAC.4, 20-Oct-84 12:16:29 by PRATT ;More TCO 6.1.1010 - Move TVTLEN to TTYDEF ; UPD ID= 765, SNARK:<6.1.MONITOR>TTANDV.MAC.2, 27-Aug-84 15:56:46 by PRATT ;TCO 6.1.1010 - Make TTANDV assemble independently of TTYSRV ; UPD ID= 3890, SNARK:<6.MONITOR>TTANDV.MAC.4, 11-Mar-84 10:35:20 by PAETZOLD ;More TCO 6.1733 - sendall fixes. Accept "DO BINARY". Fix up message TTC7SN ; UPD ID= 3519, SNARK:<6.MONITOR>TTANDV.MAC.3, 24-Jan-84 07:23:05 by HAUDEL ;TCO 6.1931 - Delete instuction that builds only 18 bit address. ; UPD ID= 2726, SNARK:<6.MONITOR>TTANDV.MAC.2, 22-Jul-83 14:58:06 by PAETZOLD ;TCO 6.1733 - Merge TCP/IP changes in release 6 again ;TTANDV.MAC.15, 5-Jul-83 08:29:57, Edit by PAETZOLD ;TCP changes for 5.1. Combine TTNTDV and TTTVDV. Remove NCP code. ;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED ;OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE. ; ;COPYRIGHT (C) DIGITAL EQUIPMENT CORPORATION 1976, 1985. ;ALL RIGHTS RESERVED. SEARCH ANAUNV,TTYDEF,PROLOG TTITLE (TVTSRV,TVTSRV,< - ARPANET TVT Dependent routine>) SUBTTL TVT Dependent Code COMMENT ! These routines support TCP Virtual Terminals, which are very similar to ARPANET NVTs. They speak "new" TELNET protcol. TVTs are operated by the TCP portion of the Internet fork. This fork does the listen, etc. and there is no usermode equivalent of NETSRV. The listen is special in that it is marked as a TVT, which means that the buffers involved are TTYSRV buffers in monitor space and not user-supplied buffers in some user's space. Further, no PSI are generated for buffer completions. Allocation (window) is set by the number of bytes available in the TTY buffers. TVTs use the TELNET protocol through TCP connections. Most of the TELNET code is in TTNTDV and this module uses that code. ! RESCD ;PARAMETERS NEGTM0==^D30000 ;NEGOTIATION TIME-OUT (BETWEEN 1 & 2 OF THESE) TMSNTT==^D500 ;TIME PER CHARACTER OF TTMSG BEFORE FLUSHING ;NVT SPECIAL CHARACTERS IACCH==377 ;INITIATE COMMAND DNTCH==376 ;DON'T DOCH==375 ;DO WNTCH==374 ;WON'T WILCH==373 ;WILL SBCH==372 ;SB BEGINNING OF SUB NEGOTIATION GACH==371 ;GA GO AHEAD ELCH==370 ;EL ERASE LINE ECCH==367 ;EC ERASE CHARACTER AYTCH==366 ;AYT ARE YOU THERE? AOCH==365 ;AO ABORT OUTPUT IPCH==364 ;IP INTERRUPT PROCESS BRKCH==363 ;BREAK DMCH==362 ;DM DATA MARK NOPCH==361 ;NOP SECH==360 ;SE END OF SUBNEGOTIATION ;NVT OPTION DEFINITIONS BINOPT==0 ;BINARY ECHOPT==1 ;ECHO RCNOPT==2 ;RECONNECTION SGAOPT==3 ;SUPPRESS GA NAMOPT==4 ;NEGOTIATE MESSAGE SIZE STSOPT==5 ;STATUS TMKOPT==6 ;TIMING MARK OPTION RCTOPT==7 ;RCTE OPTION WILOPT==10 ;OFFSET FOR REQUESTS MAXOPT==^D18 ;ONLY 1 HALF WORD OF OPTION BITS TTNETW=TTDEV ;BITS IN TTNETW DEFSTR PTITC,TTNETW,5,3 ;COUNT, SYNC-INS NV%WKS==1B8 ;RCTE WAKEUP SEEN MSKSTR NVWKS,TTNETW,NV%WKS NV%RCS==1B9 ;RCTE CHAAGE IN STATE MSKSTR NVRCS,TTNETW,NV%RCS NV%NNV==1B10 ;NEW STYLE NVT MSKSTR NVNNV,TTNETW,NV%NNV NV%TMO==1B11 ;NEGOTIATION TIME-OUT STARTED MSKSTR NVTMO,TTNETW,NV%TMO DEFSTR NVSTP,TTNETW,14,3 ;CURRENT NVT STATE ;THE FOLLOWING NVT STATES ARE STORED IN TTNETW BITS 12-14 (NVSTP) .DFWIL==1 ;DEFERRED WILL .DFWNT==2 ;DEFERRED WONT .DFDO==3 ;DEFERRED DO .DFDNT==4 ;DEFERRED DONT .DFIAC==5 ;DEFERRED IAC NV%GAB==1B15 ;BIT IN TTNETW -- SUPPRESS GO-AHEAD MSKSTR NVGAB,TTNETW,NV%GAB NV%CRI==1B16 ;BIT IN TTNETW, LAST CHAR IN WAS CR MSKSTR NVCRI,TTNETW,NV%CRI NV%CRP==1B17 ;BIT IN TTNETW -- LAST CHAR OUT WAS CR MSKSTR NVCRP,TTNETW,NV%CRP TTBRKC=TTDDLN ;BREAK CLASSES FOR NVT'S DEFSTR PBRCT,TTBRKC,8,9 ;BITS 0-8: OUTSTANDING BREAK COUNT ;BITS 9-17: LAST RCTE COMMAND SENT ;BITS 18-35: LAST BREAK CLASSES SENT MAXBRC==777 NVTOPF=TTDDLN+1 ;LH -- BIT FOR EACH OPTION IN PROGRESS ;RH -- BIT FOR RESULT OF EACH OPTION ;TVTLEN IS DEFINED IN TTYDEF ;TEMP CODE TO DO TTYDIS AND TTYAWK CODE. REMOVED FROM TTYSRV ;ROUTINES TO ADJUST LOCK STATUS BEFORE AND AFTER DISMISSING. ;THIS CODE PUTS AN ENTRY ON THE JSB STACK IN THE EVENT THE PROCESS ;IS INTERRUPTED WHILE DISMISSED. ;PUT ENTRY ON JSB STACK, AND GO OKINT ;ACCEPTS: T2/ ADDRESS OF DYNAMIC DATA TTYDIS: JE TTLCK,(T2),R ;THIS IS A HACK TO KEEP FSIINI HAPPY. ;SINCE THE SWAPPABLE MONITOR IS NOT ;LOADED YET, WE CAN'T USE THE NORMAL ;LOCKING STATEGY. THIS IS ACCEPTABLE ;HERE SINCE NO CONFUISION CAN RESULT. SKIPE INSKED ;IN THE SCHEDULER? RET ;YES. DON'T MANIPULATE THE JSB STACK SAVET ;SAVE ALL REGISTERS LOAD T1,TINTL,(T2) ;GET INTERNAL LINE NUMBER MOVEI T2,STKCD3 ;GET PROPER CODE CALL JSBSTK ;QUEUE UP THE ENTRY OKINT ;ALLOW INTS NOW RET ;AND DONE ;DISMISS WAS SATISFIED. DEQUEUE THE ENTRY AND GO NOINT TTYAWK: JE TTLCK,(T2),R ;THIS IS A HACK TO KEEP FSIINI HAPPY. ;SINCE THE SWAPPABLE MONITOR IS NOT ;LOADED YET, WE CAN'T USE THE NORMAL ;LOCKING STATEGY. THIS IS ACCEPTABLE ;HERE SINCE NO CONFUISION CAN RESULT. SKIPE INSKED ;IN THE SCHEDULER? RET ;YES. DON'T MANIPULATE THE JSB STACK SAVET ;SAVE ALL REGISTERS NOINT ;PREVENT INTS LOAD T1,TINTL,(T2) ;GET INTERNAL LINE NUMBER MOVEI T2,STKCD3 ;GET TYPE CALLRET JSFRMV ;REMOVE ENTRY AND DONE ;TCOBN - ENTRY FOR BINARY OUTPUT. NO TRANSLATION NO LINKS. ;TCOBQ - ENTRY FOR BINARY OUTPUT. NO TRANSLATION NO LINKS. ; NO SPECIAL HANDELING RESCD ;ACCEPTS: ; T1/ CHARACTER (UP TO 9 BITS) ; T2/ ADDRESS OF DYNAMIC DATA ; CALL TCOBN ;RETURNS +1: ALWAYS TCOBQ: ;HERE FOR NOW EVENTUAL WILL GO PAST ; SPECIAL CHARATER VECTOR CALL TCOBN: SAVELN ;SAVE LINE NUMBER ANDI T1,377 ;8 BITS OF CHARACTER CALL TCOU6 ;GO OUTPUT THE CHARACTER WITHOUT ADDING ; PARITY OR DOING LINKS RET ;RETURN ;TTC7SN - LINE IS A NVT. SEE IF NVT LOGINS ARE ALLOWED TTC7SN::TXNE T1,SF%NVT ;SEE IF NVT LOGINS ALLOWED JRST RTRUE ;YES, GO LOGIN IN HRROI T1,[ASCIZ/ ?Internet logins are currently disallowed /] CALL TTEMES JRST RFALSE ;FAIL ;CKNNVT - CHECK IF THIS NVT IS USING NEW PROTOCOL ;ACCEPTS: ; T2/ ADDRESS OF DYNAMIC DATA ; CALL CKNNVT ;RETURNS +1: OLD NVT PROTOCOL ; +2: NEW NVT PROTOCOL CKNNVT: JE NVNNV,TTNETW(T2),R ;OLD NVT PROTOCOL? RETURN RETSKP ;NEW PROTOCOL. SKIP RETURN TVTSOF:: ;SET BUFFER COUNT FOR TVTS MOVE T4,IBFRC1 ;TVTs NEED MULTIPLE BUFFERS MOVEM T4,TTBFRC(T1) ;SET COUNT FIELDS RET ;AND RETURN ;NVTXGA - SEND GA ;ACCEPTS: ; T2/ ADDRESS OF DYNAMIC DATA ;RETURNS +1: ALWAYS NVTRRR: STKVAR NVTRR0: SETZM NVTCH ;ASSUME ZERO COMMAND JE NVRCS,TTNETW(T2),NVTRR1 ;ANY CHANGE IN STATE? ; NO, BYPASS THIS NONSENSE. CALL GTBRKC ;GET BREAK CLASSES MOVEM T1,NVTCH ;SAVE THAT CALL GTSPCC ;GET BREAK CLASS FOR SPECIAL ECHO CHAR. IORM T1,NVTCH ;MUST BREAK ON ALL OF THEM SKIPE T1 ;ANY SPECIAL BREAKS? MOVEI T1,2 ;YES, SUPPRESS ECHO OF BREAKS MOVE T3,TTFLGS(T2) ;GET FLAGS TXNN T3, ;NO ECHO WANTED? IORI T1,6 ;SUPPRESS ALL ECHOES TXC T3, TXCN T3, ;SUPPRESS ECHOES OF BREAKS? IORI T1,2 ;YES, ... IORI T1,11 ;CAUSE BREAK CLASS TO CHANGE HRLM T1,NVTCH ;SAVE THE COMMAND SKIPA T1,[^D10] ;NEED 4 CHARS FOR BREAK CLASSES NVTRR1: MOVEI T1,6 ;NEED 6 FOR SB ETC CALL NVTRSV ;RESERVE SPACE RET ;RETURN MOVEI T1,SBCH ;BEGINNING OF SUBNEGOTIATIONS CALL NVTSSP ;SEND IAC-SB MOVEI T1,RCTOPT CALL TCOBQ ;SAY WHICH OPTION WE ARE CHANGING HLRZ T1,NVTCH ;GET COMMAND CALL TCOBN ;SEND THE COMMAND JUMPE T1,NVTRR3 ;NO CHANGE, SKIP THE FOLLOWING HRRZ T1,NVTCH ;GET NEW BREAK CLASSES LSH T1,-8 ;GET HIGH ORDER BYTE CALL TCOBN ;SEND IT HRRZ T1,NVTCH ;AND LOW ORDER TOO. CALL TCOBN ;SEND LOW ORDER BYTE NVTRR3: MOVEI T1,SECH ;END OF SUBNEGOTIATIONS CALL NVTSSP ;SEND SE LOAD T1,PBRCT,(T2) ;GET OUTSTANDING BREAKS MOVE T3,NVTCH ;GET BREAK INFO BACK SKIPE T3 ;SKIP IF NONE MOVEM T3,TTBRKC(T2) ;SET NEW CURRENT BREAK CLASSES SOS T1 ;DECREMENT OUTSTANDING BRKS STOR T1,PBRCT,(T2) ;STORE BACK SETZRO NVRCS,TTNETW(T2) ;CANCEL STATE CHANGE OKSKD1 JUMPN T1,NVTRR0 ;REPEAT IF BREAKS STILL OUTSTANDING RET ENDSV. ; TABLE OF BREAK CLASS FOR EACH CHARACTER U==1 L==2 N==4 FC==10 CC==20 K6==40 K7==100 K8==200 K9==400 CHWTB: BYTE(9)CC,CC,CC,CC,CC,CC,CC,CC ; ^@ - ^G BYTE(9)FC,FC,FC,FC,FC,FC,CC,CC ; ^H - ^O BYTE(9)CC,CC,CC,CC,CC,CC,CC,CC ; ^P - ^W BYTE(9)CC,CC,CC,CC,CC,CC,CC,FC ; ^X - EOL BYTE(9)K9,K6,K8,K8,K8,K8,K8,K8 ; SPACE - ' BYTE(9)K7,K7,K8,K8,K6,K8,K6,K8 ; ( - / BYTE(9)N,N,N,N,N,N,N,N ; DIGITS BYTE(9)N,N,K6,K6,K7,K8,K7,K6 ; 8, 9 - ? BYTE(9)K8,U,U,U,U,U,U,U ; @ - G BYTE(9)U,U,U,U,U,U,U,U ; H - O BYTE(9)U,U,U,U,U,U,U,U ; P - W BYTE(9)U,U,U,K7,K8,K7,K8,K8 ; X - _ BYTE(9)K8,L,L,L,L,L,L,L ; ' - g BYTE(9)L,L,L,L,L,L,L,L ; h - o BYTE(9)L,L,L,L,L,L,L,L ; p - w BYTE(9)L,L,L,K7,K7,K7,K8,CC ; x - RUBOUT ;GTBRKC - GET TERMINAL BREAK CLASSES ;ACCEPTS: ; T2/ DYNAMIC DATA ADDRESS ;RETURNS +1: ALWAYS ; T1/ BREAK CLASSES GTBRKC: SETZ T1, MOVE T3,TTFLGS(T2) TXNE T3,TT%WKA ;BREAK ON ALPHANUMERICS TRO T1,7 ;UPPER AND LOWER CASE AND NUMBERS TXNE T3,TT%WKP ;PUNCTUATION TRO T1,740 TXNE T3,TT%WKN ;NON-FORMATTING CONTROLS TRO T1,20 TXNE T3,TT%WKF ;FORMATTERS TRO T1,10 RET ;GTSPCC - GET BREAK CLASS FOR CHARACTERS NEEDING SPECIAL ECHOES ;ACCEPTS: ; T2/ ADDRESS OF DYNAMIC DATA ;RETURNS +1: ALWAYS ; T1/ BREAK CLASS FOR CHARACTERS NEEDING SPECIAL OUTPUT GTSPCC: STKVAR CALL TTYGPI ;GET PI CHARACTERS AS COCFORMAT MOVE T1,NVCOC1 ;SAVE COC WORDS FROM TTYGPI MOVE T3,NVCOC2 CALL TTRCOC ;GET CONTROL CHAR OUTPUT MODES ANDCMI T3,377 ;ONLY CONTROL CHARACTERS IORI T3,2B<40*2-^D36+1> ;FAKE A NORMAL ECHO FOR SPACE ANDCM T3,NVCOC2 ;FORCE ZEROES FOR INT CHARS ANDCM T1,NVCOC1 XOR T1,NVTNMD ;COMPARE TO ASSUMED ECHO MODE XOR T3,NVTNMD+1 MOVE T1,NVFMCC ;SAVE T1 MOVEI T1,FC ;ASSUME NEEDS FORMATTERS EXCH T1,NVFMCC ;SAY SO AND GET T1 BACK TDZN T1,[BYTE (2)0,0,0,0,0,0,0,0,3,3,3,3,3,3] TDNE T3,[BYTE (2)0,0,0,0,0,0,0,0,0,0,0,0,0,3] SKIPA SETZM NVFMCC ;NOT NEEDED AFTER ALL TDZN T1,[BYTE (2)3,3,3,3,3,3,3,3,0,0,0,0,0,0,3,3,3,3] TDNE T3,[BYTE (2)3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,3] MOVEI T1,CC ;NEED SPECIAL ECHO FOR NON-FORMATTERS IOR T1,NVFMCC TRNE T3, ; SPACE? IORI T1,K9 ;NEED SPECIAL ECHO FOR SPACE RET ENDSV. ;TTYGPI - GET NORMAL MODES FOR ECHO (MUST AGREE WITH THAT IN USER TELNET) ;ACCEPTS: ; T2/ ADDRESS OF DYNAMIC DATA ;RETURNS +1: ALWAYS ; T1/ COC1 WORD BASED ON INTERRUPT CHARACTERS ; T3/ COC2 WORD BASED ON INTERRUPT CHARACTERS TTYGPI: STKVAR SETZM NVTCC1 ;ZERO COC TYPE WORDS HERE SETZM NVTCC2 MOVEM T2,NVDYND ;NEED THIS ACCUMULATOR MOVE T1,TTPSI(T2) ;GET PSI BITS ANDCMI T1,77 ;MASK OUT EXTRANEOUS BITS TRZE T1,100 ;IS SPACE AN INTERRUPT? TRO T1,10 ;YES, SET BIT 40(8) TRZE T1,20 ;RUBOUT? TRO T1,4 ;SET BIT 41(8) LSH T1,-1 ;AVOID SIGN BIT TTGPI1: MOVN T2,T1 ;COMPLEMENT ALL BUT RIGHTMOST 1 AND T2,T1 ;GET JUST THAT BIT ANDCAM T2,T1 ;CLEAR IT MUL T2,T2 ;SQUARE IT LSH T3,1 ;FILL THE GAP IORB T3,NVTCC2 ;OR IN BITS IORB T2,NVTCC1 JUMPN T1,TTGPI1 ;LOOP TILL ALL ARE DONE LSHC T2,1 IOR T2,NVTCC1 ;OR IN BITS IOR T3,NVTCC2 LSHC T2,1 MOVE T1,T2 ;MOVE FIRST WORD TO T1 MOVE T2,NVDYND ;RESTORE ADDRESS OF DYNAMIC DATA RET ENDSV. NVTNMD: BYTE (2)0,0,0,0,0,0,0,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2 ;TTCOBN - NVT CLEAR OUTPUT BUFFERS ;ENTERS CLEAR BUFFER ROUTINE AFTER DEVICE DEPENDENT CODE TO PREVENT ; LOOPING ;ACCEPTS: ; T2/ ADDRESS OF DYNAMIC DATA ;RETURNS +1: ALWAYS TTCOBN: NOSKD1 CHNOFF DLSCHN CALLRET TTCOB5 ;NVTDOB - PERFORM DOBE SEQUENCE CALLED FROM TTDOBE ;ACCEPTS: ; T2/ ADDRESS OF DYNAMIC DATA ; TDJRST OFF VDOBE ;DOBE ;RETURNS +1: ALWAYS NVTDOB: CALL CKNNVT ;NEW NVT? RET ;NO. JUST RETURN MOVEI T1,TMKOPT ;TIMING MARK OPTION CALL NVTNGT ;GO NEGOTIATE OPTION JFCL ;IGNORE FAILURE RET ;NVTPAR - CHECK STPAR ARGUMENT AND NEGOTIATE ANY NEEDED OPTIONS ;ACCEPTS: ; T1/ NEW JFN MODE WORD ; T2/ ADDRESS OF DYNAMIC DATA ; TDCALL OFF VSTPAR ;STPAR JSYS ;RETURNS +1: ALWAYS TVTPAR::STKVAR MOVEM T1,NVJFMW ;SAVE NEW JFN MODE WORD CALL CKNNVT ;NEW NVT? JRST NVTPA1 ;NO OLD STYLE MOVE T3,T1 ;COPY NEW STATE XOR T1,TTFLGS(T2) ;GET DIFFERENCE TXNN T1,TT%DUM ;CHANGE IN ECHO? JRST NVTPA2 ;NO, TRY NEXT MOVX T1,ECHOPT+WILOPT ;ECHO OPTION REQUEST TXNN T3,TT%DUM ;NEGOTIATE ON? SKIPA T3,[IFIW!NVTNGT] ;YES NEGOTIATE ECHO MOVE T3,[IFIW!NVTNGF] ;NO CALL @T3 ;CALL THE ROUTINE SKIPA ;SET TO LINE HALF DUPLEX JRST NVTPA2 ;CHECK FOR OTHER NEGOTIATIONS SETONE TT%DUM,NVJFMW ;SET IT TO LINE HALF DUPLEX NVTPA2: ;OTHER CHECKS GO HERE IF ANY NVTPAX: MOVE T1,NVJFMW ;RESTORE NEW JFN MODE WORD RET NVTPA1: XOR T1,TTFLGS(T2) ;GET ANY CHANGES TXNN T1,TT%DUM ;DUPLEX MODE JRST NVTPAX ;NONE EXIT MOVE T1,NVJFMW TXNE T1,TT%DUM ;IS NEW FULL? SKIPA T1,[204] ;NO. SEND "YOU ECHO" MOVEI T1,203 ;YES. SEND "I ECHO" CALL TCOBN JRST NVTPAX ;RETURN ENDSV. ;NVTNGT - NEGOTIATE AN OPTION ;ACCEPTS: ; T1/ OPTION REQUEST ; T2/ ADDRESS OF DYNAMIC DATA ;RETURN +1: FAILURE COULD NOT GET OPTION ; +2: SUCCESS GOT OPTION NVTNGT: MOVEI T3,[IFIW!NVTXWL ;GET ADDRESS OF WILL IFIW!NVTXDO] ; AND DO ROUTINES CALL NVTNGC ;GO NEGOTIATE THEM AOS 0(P) ;SUCCESS RET ;FAILURE ;NVTNGF - REFUSE OPTION ;ACCEPTS: ; T1/ OPTION REQUEST ; T2/ ADDRESS OF DYNAMIC DATA ;RETURN +1: SUCCESS REFUSED OPTION ; +2: FAILURE COULD NOT REFUSE OPTION NVTNGF: MOVEI T3,[IFIW!NVTXWN ;GET ADDRESS OF WON'T IFIW!NVTXDN] ; AND DON'T ROUTINES NVTNGC: CAIL T1,MAXOPT ;LEGAL OPTION RET ;NO STKVAR NOINT ;MAKE SURE WE ARE NOT INTERRUPTABLE MOVEM T1,NNGOPT ;SAVE OPTION MOVEM T2,NNGDAD ;AND ADDRESS OF DYNAMIC DATA MOVEM T3,NNGADD ;AND ADDRESS OF ROUTINES MOVE T3,BITS(T1) ;CONVERT OPTION TO FLAG BITS IORM T3,NVTOPF(T2) ;SET OPTION NEGOTIATION IN PROGRESS BIT TRZN T1,WILOPT ;ARE WE ASKING FOR THIS OPTION AOS NNGADD ;NO. BUMP TO DO OR DON'T MOVE T3,NNGADD ;GET ADDRESS OF ROUTINE CALL @0(T3) ;SAY "DO, WIL, DONT, WONT" MOVE T1,NNGOPT ;GET OPTION BACK ROT T1,-9 ;INTO TOP 9 BITS MOVE T2,NNGDAD ;GET DYNAMIC DATA ADDRESS CALL TTYDIS ;SET UP FOR DISMISS MOVE T2,NNGDAD ;GET DYNAMIC DATA ADDRESS DYNST ;GET STATIC LINE NUMBER MOVSS T2 ;MOVE IT TO THE LEFT HALF IOR T1,T2 ;LINE NUMBER IN 9-17 HRRI T1,NVTNTT ;ACTIVATION TEST MDISMS MOVE T2,NNGDAD ;GET ADDRESS OF DYNAMIC DATA CALL TTYAWK ;GO NOINT AGAIN SETZRO NVTMO,TTNETW(T2) ;CANCEL ANY TIME-OUT IN PROGRESS MOVE T1,NNGOPT ;GET OPTION AGAIN MOVS T3,BITS(T1) ;CONVERT TO FLAG TDNN T3,NVTOPF(T2) ;IS IT OFF AOS 0(P) ;SKIP IF SUCCESSFUL OKINT ;INTERRUPTS ARE NOW OK RET ENDSV. ;NVTNTT - WAIT ROUTINE FOR NVT NEGOTIATIONS ;ACCEPTS T1/ BITS 18-26 OPTION NUMBER ; BITS 27-35 TTY NUMBER NVTNTT: LDB T3,[POINT 9,1,26] ;GET OPTION NUMBER MOVE T3,BITS(T3) ANDI T1,777 ;LINE NUMBER MOVE T2,T1 ;GET LINE NUMBER IN T2 CALL STADYN ;GET ADDRESS OF DYNAMIC DATA JRST T1(T4) ;NOT ACTIVE. THIS SHOULD NOT HAPPEN SKIPE TTNETW(T2) ;SATISFIED IF DISCONNECTED TDNN T3,NVTOPF(T2) JRST 1(T4) ;NEGOTIATION COMPLETE JRST 0(T4) NVTSTD: IFIW!NVTNRM ;NOTHING DEFERRED IFIW!NVTWIL ;DEFERRED WILL IFIW!NVTWNT ;DEFERRED WONT IFIW!NVTDO ;DEFERRED DO IFIW!NVTDNT ;DEFERRED DONT IFIW!NVTIAC ;DEFERRED IAC IFIW!NVTNRM ;NOT USED IFIW!NVTNRM ;NOT USED ;NVTNRM - NORMAL NVT CHARACTER PROCESSING ;ACCEPTS: ; T1/ CHARACTER ; T2/ ADDRESS OF DYNAMIC DATA ;RETURN +1: ALWAYS NVTNRM: CAIL T1,200 ;POSSIBLE NVT CONTROL CHARACTER? JRST NVTCTL ;PROCESS POSSIBLE NVT CONTROL CHARACTER NVTDCH: MOVE T3,NVTOPF(T2) TXNE T3,<1B> JRST NVTUPB ; Binary, skip special checks JE NVCRI,TTNETW(T2),[ ;WAS LAST CH CR? CAIE T1,.CHCRT ;NO. IS THIS ONE? JRST NVTUPB ;NO, PROCEED NORMALLY SETONE NVCRI,(T2) ;YES, REMEMBER IT JRST NVTUPB] ;AND SEND IT ON SETZRO NVCRI,(T2) ;YES, FORGET THAT JUMPE T1,R ;NULL? CAIN T1,.CHLFD ;WAS THIS ONE A LINE FEED RET ;YES, FORGET IT NVTUPB: SETZ Q2, ;NO SPECIAL FLAGS PUSH P,Q1 ;SAVE Q1 DYNST ;GET LINE NUMBER FOR TTCHI NOSKD1 ;TTCHI EXPECTS TO BE CALLED NOSKED CALL TTCHI ;STUFF IT IN TTY BUFFER NOP ;IGNORE ERROR RETURN OKSKD1 POP P,Q1 RET ;NVTCTL - TELNET CONTROL CODES RECEIVED ;ACCEPTS: ; T1/ CHARACTER ; T2/ ADDRESS OF DYNAMIC DATA ;RETURN +1: ALWAYS NVTCTL: SKIPGE TTNETW(T2) ;IF NO SOCKETS ATTACHED, JRST NVTDCH ;IGNORE CHAR CALL CKNNVT ;NEW STYLE NVT? JRST NVTCT0 ;NO, LOOK FOR OLD STYLE COMMANDS CAIE T1,IACCH ;YES, IS IAC JRST NVTDCH ;NO, CONTINUE PROCESSING JRST NVTCL4 ;YES. TAKE CARE OF IT NVTCT0: CAIN T1,202 ;NOP RET CAIN T1,200 ;SYNC CHAR? JRST NVTCL1 CAIN T1,203 ;ECHO OFF? JRST NVTCL2 CAIN T1,204 ;ECHO ON? JRST NVTCL3 JRST NVTDCH NVTCL1: PUSH P,T1 ;SAVE A TEMP AC LOAD T1,PTITC,(T2) ;SYNC COUNTS 1, INS COUNTS -1 AOJ T1, STOR T1,PTITC,(T2) POP P,T1 ;RESTORE THE AC RET NVTCL3: TDZA T1,T1 ;FULLDUPLEX ZERO AC AND SKIP NVTCL2: MOVEI T1,.TTLDX ;LINE HALF DUPLEX STOR T1,TT%DUM,TTFLGS(T2) ;SET DUPLEX MODE FULL/HALF RET ;PROCESS IAC NVTCL4: MOVEI T3,.DFIAC ;SET TO DEFFERED IAC STOR T3,NVSTP,(T2) RET ;NVTIAC - PROCESS BYTE AFTER IAC ;ACCEPTS: ; T1/ CHARACTER ; T2/ ADDRESS OF DYNAMIC DATA ;RETURN +1: ALWAYS NVTIAC: CAIGE T1,SECH ;END OF SUBNEGOTIATIONS RET ;NOT A VALID COMMAND SETONE NVNNV,TTNETW(T2) ;MARK THIS NEW PROTOCOL SETZ T3, ;NEXT STATE IF ANY XCT NVTDTB-SECH(T1) ;DISPATCH ON THE CHARACTER JRST NVTDCH ;SPECIAL FUNCTION CHARACTER STOR T3,NVSTP,(T2) ;NEXT STATE RET NVTDTB: RET ;(360) END OF SUBNEGOTIATION RET ;(361) NOP -- IGNORE JRST NVTCL1 ;(362) NEW DATA MARK RET ;(363) BREAK -- IGNORE MOVEI T1,3 ;(364) IP -- CONVERT TO ^C MOVEI T1,"O"-100 ;(365) AO -- CONVERT TO ^O MOVEI T1,"T"-100 ;(366) AYT -- CONVERT TO ^T MOVEI T1,177 ;(367) EC -- CONVERT TO DEL MOVEI T1,"U"-100 ;(370) EL -- CONVERT TO ^U RET ;(371) GA -- IGNORE RET ;(372) SB -- SHOULDN'T GET THIS TROA T3,.DFWIL ;(373) DEFER WILL TROA T3,.DFWNT ;(374) DEFER WONT TROA T3,.DFDO ;(375) DEFER DO TROA T3,.DFDNT ;(376) DEFER DONT JFCL ;(377) IAC IAC -- IAC ;NVTSSP - SEND SPECIAL CHARACTER ;ACCEPTS: ; T1/ CHARACTER ; T2/ ADDRESS OF DYNAMIC DATA ;RETURN +1: ALWAYS NVTSSP: PUSH P,T1 ;SAVE CHARACTER MOVEI T1,2 ;NEED 2 CHARACTERS CALL NVTRSV ;RESERVE SPACE IN BUFFER (NOSKED) JRST [ POP P,T1 ;COULDN'T GET DON'T WAIT RET] ;RETURN HRROI T1,IACCH ;SAME AS 377, BUT PREVENT ITS DOUBLING CALL TCOBN ;CALL TCOBN TO GET CR-NULL IF NEEDED POP P,T1 ;GET BACK SPECIAL CHARACTER CALL TCOBQ ;SEND IT OKSKD1 RET ;NVTRSV - RESERVE SPACE IN BUFFER FOR CHARACTERS SPECIFIED IN 1 ;ACCEPTS: ; T1/ NUMBER OF CHARACTERS ; T2/ ADDRESS OF DYNAMIC DATA ;RETURN +1: FAILURE NO ROOM ; +2 SUCCESS NVTRSV: NOSKD1 ;MAKE SURE SPACE DOESN'T DISAPPEAR LOAD T3,TOMAX,(T2) ;MAXIMUM BYTES IN OUTPUT BUFFER SUB T3,TTOCT(T2) ;SPACE IN OUTPUT BUFFERS CAML T3,T1 ;WILL THEY FIT RETSKP ;YES. ENOUGH ROOM, RETURN SKIP OKSKD1 MOVE T3,FORKX ;GET FORK NUMBER CAMN T3,INTFRK ;IS THIS THE INTERNET FORK? RETBAD ;YES SO JUST RETURN SKIPN INSKED ;IN THE SCHEDULER SKIPE NSKED ;OR NO SKED RETBAD ;YES TELL HIM THERE WAS NO ROOM PUSH P,T1 ;NO. WAIT FOR SPACE PUSH P,T2 ;SAVE ARGUMENTS MOVEI T1,TCOTST ;GET ADDRESS OF WAIT ROUTINE CALL TTYDIS ;SET UP FOR DISMISS DYNST ;GET LINE NUMBER HRL T1,T2 ;MOVE IT TO THE LEFT HALF MDISMS ;WAIT FOR SPACE POP P,T2 ;RESTORE ARGUMENTS CALL TTYAWK ;GO NOINT AGAIN POP P,T1 JRST NVTRSV ;TRY AGAIN ;NVTRFU - SEND WONT (REFUSE) ;ACCEPTS: ; T2/ ADDRESS OF DYNAMIC DATA ; OPTION ON TOP OF STACK ;RETURN +1: ALWAYS NVTRFU: MOVEI T1,WNTCH ;NVTSRP - SEND REPLY IN 1 FOR OPTION ON STACK ;ACCEPTS: ; T1/ REPLY ; T2/ ADDRESS OF DYNAMIC DATA ; OPTION ON TOP OF STACK ;RETURN +1: ALWAYS NVTSRP: PUSH P,T1 ;SAVE REPLY MOVEI T1,3 CALL NVTRSV ;RESERVE SPACE FOR THREE CHARACTERS JRST [ ADJSP P,-2 ;NO ROOM CLEAN UP STACK RET] HRROI T1,IACCH ;SAME AS 377 BUT PREVENT DOUBLING CALL TCOBN ;USE TCOBN TO GET CR-NULL IF NEEDED POP P,T1 ;GET REPLY CALL TCOBQ ;SEND IT POP P,T1 ;GET OPTION CALL TCOBQ ;SEND IT OKSKD1 RET ;NVTSWL - SEND WILL ;ACCEPTS: ; T2/ ADDRESS OF DYNAMIC DATA ; OPTION ON TOP OF STACK ;RETURN +1: ALWAYS ;NVTXWL - ENTRY FOR OPTION IN T1 NVTXWL: PUSH P,T1 ;SAVE OPTION NVTSWL: MOVEI T1,WILCH ;ENTER HERE WHEN OPTION IS ON STACK JRST NVTSRP ;SEND REPLY ;NVTSNR - SEND NO REPLY ;ACCEPTS: ; T2/ ADDRESS OF DYNAMIC DATA ; OPTION ON TOP OF STACK ;RETURN +1: ALWAYS NVTSNR: ADJSP P,-1 ;NO REPLY NECESSARY OR POSSIBLE RET ;NVTSWN - SEND WONT ;ACCEPTS: ; T2/ ADDRESS OF DYNAMIC DATA ; OPTION ON TOP OF STACK ;RETURN +1: ALWAYS ;NVTXWN - ENTRY FOR OPTION IN T1 NVTXWN: PUSH P,T1 ;SAVE OPTION NVTSWN: MOVEI T1,WNTCH ;ENTER HERE WHEN OPTION ALREADY PUSHED JRST NVTSRP ;NVTSDO - SEND "DO" ;ACCEPTS: ; T2/ ADDRESS OF DYNAMIC DATA ; OPTION ON TOP OF STACK ;RETURN +1: ALWAYS ;NVTXDO - ENTRY FOR OPTION IN T1 NVTXDO: PUSH P,T1 ;SAVE OPTION NVTSDO: MOVEI T1,DOCH ;ENTER HERE WHEN OPTION ALREADY PUSHED JRST NVTSRP ;NVTSDN - SEND "DONT" ;ACCEPTS: ; T2/ ADDRESS OF DYNAMIC DATA ; OPTION ON TOP OF STACK ;RETURN +1: ALWAYS ;NVTXDN - ENTRY FOR OPTION IN T1 NVTXDN: PUSH P,T1 ;SAVE OPTION NVTSDN: MOVEI T1,DNTCH ;ENTER HERE WHEN OPTION ALREADY PUSHED JRST NVTSRP ;NVTDO - PROCESS "DO" ;ACCEPTS: ; T1/ OPTION ; T2/ ADDRESS OF DYNAMIC DATA ;RETURN +1: ALWAYS NVTDO: CAIL T1,WILOPT ;ARE WE WILLING? JRST NVTDO1 ;NO MOVE T3,BITS+WILOPT(T1) ;YES GET FLAG BITS TDNE T3,NVTOPF(T2) ;OUTSTANDING REQUEST JRST NVTWI2 ;YES GO PROCESS IT NVTDO1: PUSH P,T1 ;REMEMBER THE OPTION MOVSS T3 ;PUT BIT IN "OPTIONS ON" HALF TDNE T3,NVTOPF(T2) ;IS THE OPTION ON? JRST NVTSNR ;YES, SEND NO REPLY CAIGE T1,NVTLOP ;DO WE KNOW ABOUT THIS OPTION CALL @NVTDOD(T1) ;YES. ATTEMPT EXECUTION JRST NVTRFU ;CAN'T DO IT -- REFUSE IORM T3,NVTOPF(T2) ;SET OPTION ON JRST NVTSWL ;AND SEND "WILL" NVTDOD: IFIW!RSKP ;BINARY XMIT -- OK WITH US IFIW!NVTECN ;TURN ECHOS ON IFIW!R ;RECONNECT -- REFUSE FOR NOW IFIW!NVTSGA ;SUPPRESS GA -- WONDERFUL NEWS IFIW!R ;MESSAGE SIZE -- REFUSE IFIW!R ;STATUS -- REFUSE IFIW!NVTDTM ;TIMING MARK -- TRY TO DO IT ; IFIW!NVTDRC ;REMOTE CONTROLLED TRANS & ECHO IFIW!R ;DO NOT DO IT FOR NOW NVTLOP=.-NVTDOD ;ACTION ROUTINES FOR "DO" ;TURN ECHOES ON NVTECN: MOVX T1,TT%DUM ANDCAM T1,TTFLGS(T2) ;SET TO FULL DUPLEX RETSKP ;SET SUPPRESS GA BIT NVTSGA: SETONE NVGAB,TTNETW(T2) RETSKP ;DO TIMING MARK PROTOCOL NVTDTM: RETSKP ;NVTDNT - PROCESS "DONT" ;ACCEPTS: ; T1/ OPTION ; T2/ ADDRESS OF DYNAMIC DATA ;RETURN +1: ALWAYS NVTDNT: CAIL T1,WILOPT ;ARE WE WILLING FOR THIS OPTION JRST NVTDN1 ;NO MOVE T3,BITS+WILOPT(T1) ;GET FLAG BITS TDNE T3,NVTOPF(T2) ;OUTSTANDING REQUEST JRST NVTWN2 ;YES NVTDN1: PUSH P,T1 ;SAVE OPTION MOVSS T3 ;PUT BIT IN "OPTION ON" HALF TDNN T3,NVTOPF(T2) ;OPTION ALREADY OFF? JRST NVTSNR ;YES. SEND NO REPLY CAIGE T1,NVTLOP ;DO WE KNOW ABOUT THIS OPTION? CALL @NVTDND(T1) ;YES. PERFORM ACTION ANDCAM T3,NVTOPF(T2) ;CLEAR THE OPTION JRST NVTSWN ;AND SEND "WON'T" NVTDND: IFIW!R ;DILEMMA -- HE WANTS OFF, BUT WE CAN'T IFIW!NVTECF ;ECHO OFF IFIW!R ;OPTION NOT ON, NO REPLY IFIW!NVTAGA ;HE WONT SUPPRESS GA -- NUTS IFIW!R ;MESSAGE SIZE OPTION IFIW!R ;STATUS OPTION IFIW!R ;TIMING MARK -- HUH? IFIW!R ;TURN OFF RCTE ;"DONT" ACTION ROUTINES ;TURN ECHOS OFF NVTECF: MOVX T1,TT%DUM ;DUPLEX MODE IORM T1,TTFLGS(T2) ;SET TO LINE HALF DUPLEX RET ;TURN OFF SUPPRESS GA BIT NVTAGA: SETZRO NVGAB,TTNETW(T2) RET NVTWIL - ;PROCESS "WILL" ;ACCEPTS: ; T1/ OPTION ; T2/ ADDRESS OF DYNAMIC DATA ;RETURN +1: ALWAYS NVTWIL: CAIL T1,WILOPT ;ONLY WILOPT OPTIONS JRST NVTWI1 ;OTHERS CANNOT BE OUTSTANDING MOVE T3,BITS(T1) ;GET THE BIT FOR THE OPTION TDNN T3,NVTOPF(T2) ;IS THIS OPTION OUTSTANDING? JRST NVTWI1 ;NO. NVTWI2: MOVS T1,T3 ;PUT BITS IN OPTION ON HALF IORM T1,NVTOPF(T2) ;SET WILL BIT ANDCAM T3,NVTOPF(T2) ;AND CLEAR OUTSTANDING BIT RET NVTWI1: PUSH P,T1 ;SAVE THE OPTION MOVSS T3 ;PUT BIT IN "OPTONS ON" HALF TDNE T3,NVTOPF(T2) ;IS OPTION ALREADY ON? JRST NVTSNR ;YES. SEND NO REPLY CAIGE T1,NVTLOP ;LEGAL OPTION? CALL @NVTWID(T1) ;YES. CALL ACTION ROUTINE JRST NVTSDN ;UNIMPLEMENTED OPTION OR CAN'T COMPLY IORM T3,NVTOPF(T2) ;DONE. SET OPTION "ON" JRST NVTSDO ;AND SEND "DO" NVTWID: IFIW!RSKP ;WILL BINARY -- DO IFIW!R ;WILL ECHO -- DONT IFIW!R ;RECONNECT -- DONT IFIW!RSKP ;SUPPRESS GA -- DO, DO, DO , DO! IFIW!R ;MESSAGE SIZE -- DONT IFIW!R ;STATUS -- DONT IFIW!R ;TIMING MARK -- HUH? IFIW!R ;WHAT'S HE TRYING TO DO? ;NVTWNT - PROCESS "WONT" ;ACCEPTS: ; T1/ OPTION ; T2/ ADDRESS OF DYNAMIC DATA ;RETURN +1: ALWAYS NVTWNT: CAIL T1,MAXOPT ;LEGAL OPTION JRST NVTWN1 ;NO. OPTION NOT HANDLED MOVE T3,BITS(T1) ;GET BIT FOR OPTION TDNN T3,NVTOPF(T2) ;IS THIS OPTION OUTSTANDING JRST NVTWN1 ;NO. REQUEST NVTWN2: HLR T3,T3 ;YES. NEG ACKNOWLEDGE ANDCAM T3,NVTOPF(T2) ;CLEAR BOTH OUTSTAND AND WILL FLAGS RET NVTWN1: PUSH P,T1 ;SAVE OPTION MOVSS T3 ;PUT BIT IN "OPTIONS ON" HALF TDNN T3,NVTOPF(T2) ;OPTION ALREADY OFF? JRST NVTSNR ;YES. SEND NO RPLY ANDCAM T3,NVTOPF(T2) ;STRANGELY ENOUGH, THE USER END JRST NVTSDN ;NEVER HAS ANY OPTIONS TO TURN OFF ; TCP PARAMETERS: LSNPRT==27 ; PORT TELNET LISTENS ON LSNTMO==^D<5*60> ; TIMEOUT TVTRXP==1001,,1 ; TVT RETRANSMISSION PARAMETERS ; (NO BACKOFF, CONSTANT 1 SECOND) RS LSNTIM ; TEMP HOLDER FOR TIME TO TRY ANOTHER LISTEN ;DOES SKIPE TTOCT(B) AND SKIPE TSALC(B) FOR TVTS ;SKIPS ONLY IF ABSOLUTELY NO CHARS TO BE HANDLED FOR LINE ;ACCEPTS DYN LINE # IN B ;RETURNS TTOCT+TSALC IN T1 TVSBE1::CALL TTSOBE JRST TVSBE2 ;NO SKIP IF NORMAL OUTPUT TO BE DONE OPSTR ,TSALC,(B) ;NO SKIP IF SENDALL TO BE DONE RETSKP ;SKIP ONLY IF ABSOLUTELY NO CHARS TVSBE2: OPSTR ,TSALC,(B) RET ;NO-SKIP, COUNT IN A ;TVMSNT - TEST TO SEE IF SEND ALL SHOULD BE DONE ;FNCALL OFF TTVT36 One Line ;FNCALL OFF TTVT37 All Lines ;ACCEPTS: ; T2/ LINE NUMBER ;RETURNS: +1 DO NOT SEND MESSAGE ; +2 SEND MESSAGE SWAPCD TVMSNT::SASUBR JUMPL T2,R ; return now if no such lines CALL LCKTTY ;GET DYNAMIC DATA ADDRESS IF IT EXIST JRST TVMSN1 ;NO DYNAMIC DATA DO NOT SEND SKIPG TTNETW(T2) ;ANY CONNECTIONS? JRST TVMSN1 ;NO DO NOT SEND MESSAGE CALL ULKTTY ;YES UNLOCK TTY DATABASE AOS TVTNOF ;INDICATE OUTPUT FOR TVTS MOVE T2,MSCT ;GET COUNT OF CHARACTERS IN MESSAGE IMULI T2,TMSNTT ;MULTIPLY BY ALLOWABLE TIME PER CHAR. ADD T2,TODCLK ;GET TIME MESSAGE TO BE DISCARDED MOVEM T2,TVMSTM ;SAVE TIME FOR TCP FORK RETSKP ;SEND MESSAGE TVMSN1: CALL ULKTTY ;UNLOCK TTY RETBAD ;NO DO NOT SEND MESSAGE ;TVMNTR ;ROUTINE TO CLEAR ALL TVT SNDALL REQUEST ;Called NOSKED from OPSCAN on TVMSTM timeout set by TVMSNT RESCD TVMNTR::MOVE T3,TVTPTR ;GET AOBJN COUNTER FOR TVT'S TMSNR1: SKIPN T2,TTACTL(T3) ;GET ADDRESS OF DYNAMIC DATA JRST TMSNR2 ;IF NON-STANDARD BLOCK CHECK JE TTSAL,(T2),TMSNR2 ;IF DOING SENDALL CLEAR IT CALL CLRSAL ;CLEAR SENDALL FROM LINE TMSNR2: AOBJN T3,TMSNR1 ;HAVE WE DONE ALL OF THE LINES RET ;YES RETURN ;TVRFIL ;Routine to signal TVT buffer refill when empty. Called from GTTCI. TVRFIL: SKIPG TTNETW(T2) ;STILL CONNECTED TO NETWORK? RET ;NO, NOTHING TO DO SAVEAC ;SAVE ACS NOSKED ;OWN THE SYSTEM SKIPL RA+PRCLCK ;IS REASSEMBLER RUNNING ALREADY? JRST TVRFI3 ;YES SO AVOID LOCK CONTENTION LOAD TCB,PTVT,(T2) ;NO, GET TCB IF EXISTS JUMPE TCB,TVRFI3 ;IF NO TCB THEN GET OUT OF HERE SETSEC TCB,INTSEC ;TCB'S ARE IN INTSEC JN TRCB,(TCB),TVRFI2 ;IF RECV BUFFER EXISTS RUN THE RA LOAD T1,QNEXT,<+TCBRPQ(TCB)> ;NO, GET NEXT ITEM ON RA QUEUE CAIN T1,TCBRPQ(TCB) ;IS RA QUEUE EMPTY? JRST TVRFI3 ;YES NO NEED TO RUN THE RA TVRFI2: ;HERE TO RUN RA $SIGNL(RA,20) ;RUN REASSEMBLER AFTER SHORT DELAY TVRFI3: ;HERE WHEN ALL DONE OKSKED ;RETURN THE SYSTEM RET ;ASNTVT ;ASSIGN A TCP VIRTUAL TERMINAL ;T1/ TCB (WITH AN%NTP flag for new protocol) ;CALL ASNNVT ;RETURNS +1: FAILURE ; +2: SUCESS ;T1/ LINE NUMBER ;T2/ ADDRESS OF DYNAMIC DATA AND DATA BASE LOCKED SWAPCD ASNTVT::STKVAR MOVEM T1,FLGTCB HRRZ T1,TVTPTR ;GET FIRST TVT LINE NUMBER SETZ T3, ;START WITH FIRST TVT NOSKED ASNTV1: MOVE T2,T1 ;GET FIRST TVT OFFSET ADD T2,T3 ;ADD CURRENT TVT MOVEM T2,TVLIN ;SAVE LINE NUMBER CALL STADYN ;IS IT INITIALIZED JUMPE T2,ASNTV4 ;NO. NO DYNAMIC DATA SKIPG TTNETW(T2) ;FREE? JRST ASNTV3 ;YES. ASNTV2: CAIGE T3,NTTTVT-1 ;LOOKED AT ALL TVT'S? AOJA T3,ASNTV1 ;NO OKSKED ;YES, RETBAD ;RETURN BAD ASNTV3: LOAD T2,TCJOB,(T2) ;GET JOB FOR WHICH THIS IS A CNTRL TTY. CAIN T2,-1 ;IS THERE ONE JRST ASNTV4 ; No, use this one HLRZ T2,JOBPT(T2) ; Yes, is it really there? CAMN T2,TVLIN ; Skip if TCJOB has obsolete data JRST ASNTV2 ;YES. TTY ALREADY ATTACHED? ; if job-0 ought to use TTYASC ; if other job, ought to use TTYASO ; For now, they are essentially the same ASNTV4: MOVE T2,TVLIN ;GET LINE NUMBER BACK CALL TTYASC ;ASSIGN TVT JRST ASNTV6 ;COULD NOT ASSIGN IT MOVE T2,TVLIN ;GET LINE NUMBER CALL LCKTTY ;AND LOCK DATA BASE JRST ASNTV5 ;CANNOT LOCK DATA BASE. SHOULD'NT HAPPEN SETONE TCJOB,(T2) ;INDICATE NO CONTROLLING JOB FOR TERM. SETONE TTPRM,(T2) ;MAKE DATA PERMANENT UNTIL NVT CLOSED MOVE T1,FLGTCB ; Get arg back TXNN T1,AN%NTP ;NEW TELNET PROTOCOL REQUEST? TLZA T3,-1 ;NO, MAKE ZEROES MOVX T3,NVNNV ;YES, MAKE NEW NVB BIT HLLZM T3,TTNETW(T2) ;CLEAR TTNETW EXCEPT FOR NVNNV SETZM NVTOPF(T2) ;CLEAR OPTION STATUS HRRZ T1,FLGTCB ; Get the TCB STOR T1,PTVT,(T2) ;REMEMBER UNIT SETONE TT%DUM,TTFLGS(T2) ;SET DUPLEX MODE MOVEI T1,.TTIDL ;SET TO BE AN "IDEAL" TERMINAL STOR T1,TTTYP,(T2) MOVE T1,TVLIN ;RETURN LINE NUMBER OKSKED RETSKP ASNTV5: CALL ULKTTY ;UNLOCK DATA BASE ASNTV6: HRRZ T1,TVTPTR ;GET FIRST TVT MOVE T3,TVLIN ;SET UP TO TRY NEXT LINE SUB T3,T1 ;GET TVT NUMBER IN 3 JRST ASNTV2 ;AND TRY NEXT TVT ENDSV. ;TVTCSO ;START OUTPUT TO A LINE CALLED FROM STRTOU ;RETURNS +2: ALWAYS RESCD TVTCSO:: AOS TVTNOF ; request tty scan AOS TCPFLG ; Say it is TCP that needs to run AOS INTFLG ; Get the Internet fork to run it AOS PSKD1 ; Get the scheduler out of the null job RETSKP ;TVTDOB ;TVT dismiss until output buffer empty ;Avoid doing a TELNET timing mark option negotiation if the ;connection is closing since the other end will not respond. SWAPCD TVTDOB: LOAD TCB,PTVT,(T2) ; Get TCB if exists JUMPE TCB,R ; Return if none SETSEC TCB,INTSEC ; TCBs are in INTSEC LOAD T1,TSSYN,(TCB) ; Get send state CAIE T1,SYNCED ; Can we send? RET ; No LOAD T1,TRSYN,(TCB) ; Get receive side state CAIE T1,SYNCED ; Can other end reply? RET ; No JRST NVTDOB ; Yes and yes. Do normal TELNET stuff ;TVTCOB ;TVT CLEAR OUTPUT BUFFER CALLED FROM TTCBF2 ;ACCEPTS: ;T2/ ADDRESS OF DYNAMIC DATA ;RETURNS +1: ALWAYS RESCD TVTCOB:: SKIPE INSKED ;IN SCHEDULER RET ;YES RETURN IMMEDIATELY PUSH P,TCB SKIPG TCB,TTNETW(T2) ;STILL CONNECTED TO NETWORK? JRST TVTCO3 ;NO. RETURN SETSEC TCB,INTSEC ; TCBs in Internet section JN TERR,(TCB),TVTCO3 ; Don't DM if connection error NOINT ;PROTECT POSSIBLE ILOCKS CALL CKNNVT ;NEW STYLE NVT? JRST TVTCO1 ;OLD STYLE MOVEI T1,DMCH ;DATA MARK CHARACTER CALL NVTSSP ;SEND NEW DM JRST TVTCO2 TVTCO1: MOVX T1,1 ;RESERVE ONE CHARACTER CALL NVTRSV ;GO REESERVE IT JRST TVTCO2 ;NONE AVAILABLE CANNOT WAIT MOVX T1,200 CALL TCOBN ;SEND CHARACTER OKSKD1 TVTCO2: OKINT TVTCO3: POP P,TCB RET ;CHECK OVERDUE NEGOTIATIONS RESCD TVTNCK::STKVAR MOVE T2,TVTPTR ;POINTER TO TVTS TVTNCL: MOVEM T2,TVTCTR ;SAVE TVT COUNTER HRRZ T2,T2 ;GET JUST RIGHT HALF CALL LCKTTY ;GET ADDRESS OF DYAMIC DATA AND LOCK JRST TVTNCE ;NOT ACTIVE SKIPGE TTNETW(T2) ;ATTACHED? JRST TVTNCE ;NO, SKIP IT MOVX T3,NVTMO ;TIME OUT HLLZ T1,NVTOPF(T2) ;GET OUTSTANDING OPTIONS JUMPE T1,[ANDCAM T3,TTNETW(T2) ;NONE, CANCEL TIME-OUT IF ANY JRST TVTNCE] XORB T3,TTNETW(T2) ;YES, COUNT COUNTER TXNN T3,NVTMO ;COUNT FROM 1 TO 0? HRRZS NVTOPF(T2) ;YES, CANCEL OUTSTANDING OPTION TVTNCE: CALL ULKTTY ;UNLOCK DATA BASE MOVE T2,TVTCTR ;GET AOBJ COUNTER AOBJN T2,TVTNCL ;ANY MORE TVT'S MOVE T1,TODCLK ;NO. GET TIME OF DAY ADDI T1,NEGTM0 ;ADD TIME OUT QUANITY MOVEM T1,TVTNTM ;SAVE TIME FOR NEXT CHECK RET ENDSV. ;SNDTVT ;Send virtual terminal data ;TCB/ Locked connection block ;PKT/ Pointer to Internet portion of packet being filled ;TPKT/ Pointer to TCP portion of packet ;T1/ Max number of characters to send ;T2/ Line block address ;CALL SNDTVT ;Ret+1: Always. Terminal data moved into packet. T1 has number of chrs. SNDTVT::LOCAL DMOVEM T1,XFRCNT ; T1,2 to XFRCNT and LINBLK LOAD PKTPTR,PTDO,(TPKT) ; Get TCP data offset HRLI PKTPTR,() ; Pointer to data area MOVEI CNT,0 ; Init number moved to packet MOVEI T3,(1B) ; RCTE-on bit TDNE T3,NVTOPF(T2) ; Have we said we will do RCTE? CALL CKNNVT ; And is this a "new" TELNET terminal? JRST SNDTV1 ; No. JE PBRCT,(T2),SNDTV1 ; Check the break count CALL NVTRRR ; Try to send SNDTV1: SKIPG TTNETW(T2) ; Still connected? JRST SNDTV2 ; No JE TERR,(TCB),SNDTV3 ; Error on connection (retrans timeout)? SNDTV2: IFQN. TTSAL,(T2) ; Check for sendall in progress CALL CLRSAL ; Clear it ENDIF. CALL TTCOBN ; Flush output buffer JRST SNDTV9 ; And return SNDTV3: SETONE TTOTP,(T2) ; Indicate output active ; Move characters from the terminal output buffer(s) into the packet. ; XFRCNT has space left in packet and CNT will be left with number ; moved. SNDTV4: SOJL XFRCNT,SNDTV5 ; Jump if packet filled MOVE T2,LINBLK ; Restore address of data area NOSKD1 CALL TTSND ; Get a chr from output buf to T3 JRST SNDTV6 ; Failed to get any OKSKD1 IDPB T1,PKTPTR ; Add to packet AOJA CNT,SNDTV4 ; Count it up and try for another SNDTV6: OKSKD1 ; Go OKSKED again JRST SNDTV9 ; And join below SNDTV5: SETZRO TTOTP,(LINBLK) ; Clear output active bit SNDTV9: MOVE T1,CNT ; Return number in packet RESTORE RET ;PRCTVT ;Process TCP Virtual Terminal data ;T1/ Byte pointer into packet where to begin (index by TPKT) ;T2/ Pointer to dynamic line data block ;T3/ Maximum number of characters to do ;PKT/ Pointer to Internet portion of packet ;TPKT/ Pointer to TCP portion of packet ;TCB/ Locked connection block ;CALL PRCTVT ;Ret+1: Always. Given number of characters have been moved. PRCTVT::LOCAL MOVEM T1,PKTPTR DMOVEM T2,LINBLK PRCTV1: SOJL XFRCNT,PRCTVX ; Jump if all done ILDB T1,PKTPTR ; Get a character MOVE T2,LINBLK ; Line block address LOAD T3,NVSTP,(T2) ; Current Telnet command state SETZRO NVSTP,(T2) ; Reset for normal dispatch next time PUSH P,LINBLK ; Some of these are crashed by TTYSRV PUSH P,XFRCNT ; or TELNET PUSH P,PKTPTR CALL @NVTSTD(T3) ; Dispatch to Telnet routine POP P,PKTPTR POP P,XFRCNT POP P,LINBLK JRST PRCTV1 ; Do another PRCTVX: RESTORE RET ;CHKTVT ;SEE IF THIS LINE NUMBER IS A TVT ;ACCEPTS: ;T2/ INTERNAL LINE NUMBER ;CALL CHKTVT ;RETURNS +1: IF NOT TVT ; +2: IF TVT RESCD CHKTVT:: ACVAR ;GET AN AC TO WORK WITH SKIPL T2 ;LEGIT LINE NUMBER? CAIL T2,NLINES ;LEGIT LINE NUMBER? RETBAD ;NO LOAD W1,TTSTY,(T2) ;GET LINE TYPE FOR THIS LINE CAIE W1,TT.TVT ;IS IT A TVT? RETBAD ;NO. FAILURE RETSKP ;RETURN SUCCESS ENDAV. ;END ACVAR SWAPCD ;TVTCHK ;See if this line is a TCP Virtual terminal ;T2/ Internal line number ; CALL TVTCHK ;Ret+1: Line not initialized. T2 0 Inactive Not locked, okint ; T2 -1 Becoming active Not locked, okint ; T2 adr Non-standard blk Locked, noint ; +2: Line initialized. T2 adr Std dynamic data Locked, noint TVTCHK:: CAIL T2,NLINES ; Legal terminal line number? JRST TVTCH8 ; TCP Never calls with non-TVT LOAD T1,TTSTY,(T2) ; Line type for this line CAIE T1,TT.TVT ; Is it a TVT? JRST TVTCH8 ; No. CALL LCKTTY ; Get addr of dynamic data and lock RET ; Line not initialized JRST TVTCHX ; Return with line blk addr in T2 TVTCH8: BUG.(HLT,TVTNTV,TTYSRV,SOFT,,,< Cause: TVTCHK was called to determine the status of a TVT line, but the line number provided by TCP is not a TVT line. TCP should never call TVTCHK with a non-TVT line. >) TVTCHX: RETSKP ;TVTISP ;Get number of holes in input buffer ;T2/ Pointer to line block ; CALL TVTISP ;Ret+1: Always. Space available in T1 TVTISP::LOAD T1,TIMAX,(T2) ; Max capacity of line SUB T1,TTICT(T2) ; Less what is already there RET ; Gives amount left ;TVTOSP Get number of bytes in output buffer ;T2/ Line block pointer ; CALL TVTOSP ;Ret+1: Always. Number in T1. TVTOSP::LOAD T1,TSALC,(T2) ; Sendall count plus SKIPE T1 ; If sendall, bump count so ADDI T1,1 ; extra TTSND clears sndall info ADD T1,TTOCT(T2) ; regular count JE ,(T2),TVTOSX MOVEI T1,0 ; Hung on ^S, say no avail for output TVTOSX: RET ;TVTDTS ;Close a full duplex TCP virtual terminal connection upon carrier-off ;T2/ Line number ; CALL TVTDTS ;Ret+1: Always RESCD TVTDTS::CALL TVTDTT ; Detach the TVT RET RET ; Success ;TVTDET ;Detach a job from a TCP virtual terminal connection returns to ;caller's caller, TVTDTT returns to caller. Called from HLTJB ;when a job logs off ;T2/ Line number ;CALL TVTDET (FNCALL off of TTVT11, TTVT19) ;Ret+1: Failure. T1/ 1B0 + Addr of routine if dismiss needed ; or, Error code if failed ;Ret+2: Success TVTDET::POP P,0(P) ; Flush return address TVTDTT: SE1CAL ; Enter section 1 SAVEPQ ; Save local ACs STKVAR ; Space for line number and block addr MOVEM T2,TVTDLN ; Save the line number CALL TVTCHK ; See if this is a TVT RETSKP ; Not assigned. Return. MOVEM T2,TVTDAD ; Save addr of dynamic data area CALL CLRPRM ; Clear permanent bit, allowing deassign SKIPG TTNETW(T2) ; Is there a connection? JRST TVTDE1 ; No PUSH P,TCB LOAD TCB,PTVT,(T2) ; Get the TCB SETSEC TCB,INTSEC ; Make extended address JE TSUOP,(TCB),TVTDE0 ; Already closed? XMOVEI T1,TCBLCK(TCB) ; Lock to lock MOVX T2, ; Function to call IFE REL6, ; Do a cross-job close IFN REL6, ; Do a cross-job close TVTDE0: SETZRO TVTL,(TCB) ; Prevent OPSCAN from finding this TCB POP P,TCB MOVE T2,TVTDAD ; Restore pointer to data block TVTDE1: SETZM TTNETW(T2) ; Flush the connection LOAD T3,TCJOB,(T2) ; Get owning job CAIN T3,-1 ; Is there one? JRST TVTDT2 ; No. Just go deallocate data block. MOVE T2,TVTDLN ; Get TTY line number MOVEI T1,.TTDES(T2) ; Make into device designator CALL CHKDES ; Get index to device tables JRST [ MOVE T2,TVTDAD ; Get dynamic data address back CALL ULKTTY RETBAD] ; Invalid device designator????? SETZRO DV%OPN,DEVCHR(T2) ; Permit RELD at LGOUT to win MOVE T2,TVTDAD ; Dynamic data block address MOVE T1,TVTDLN ; Terminal line number CAMN T1,CTRLTT ; Controlling terminal for this job? JRST TVTDT2 ; Yes. Go deassign database LOAD T3,TCJOB,(T2) ; Get owning job HLRZ T3,JOBPT(T3) ; Get controlling terminal of job CAME T1,T3 ; Is this a controlling terminaL JRST TVTDT2 ; No. Go detach it ; A job exists on this line and the net connection has been broken. ; Generate a carrier off PSI for the top fork. This will cause the ; terminal data block to be deassigned. MOVE T2,TVTDLN ; Get line number NOSKD1 CALL NTYCOF ; Start the carrier off action OKSKD1 MOVE T2,TVTDAD ; Get address CALL ULKTTY ; Unlock the data block RETSKP ; And give a good return ; Deassign the terminal's data block TVTDT2: JE TTSAL,(T2),TVTDT3 ; Doing a Send-All? CALL CLRSAL ; No longer doing a sendall TVTDT3: CALL ULKTTY ; Unshare the data block MOVE T2,TVTDLN ; TVT Line number MOVEI T1,.TTDES(T2) ; Form device designator CALL CHKDES ; Get index to device tables RETBAD ; Invalid device designator???? MOVEM T2,TVTDAD ; Save index to device tables MOVE T2,TVTDLN ; Get terminal line number CALL TTYDE0 ; Deallocate the line RETBAD ; Return error or test routine MOVE T2,TVTDAD ; Device table index HRROS DEVUNT(T2) ; Set owning job to -1 SETZRO DV%ASN!DV%OPN,DEVCHR(T2) ; Not assigned or openned MOVE T2,TVTDLN ; Get line number CAME T2,CTRLTT ; Controlling terminal RETSKP ; No. SETOM CTRLTT ; Yes. Indicate no terminal MOVE T2,JOBNO ; Get job number HRROS JOBPT(T2) ; This nob no longer has a terminal RETSKP ENDSV. TVTIGA::RET ;TVTOPR ;Main routine to operate TVTs ;CALL TVTOPR ;Ret+1: Always. TVTOPR::SKIPLE TVTNOF ; Output scan needed? CALL OPSCAN ; Yes. Signal PZ where possible MOVE T1,TODCLK ; Now CAML T1,TVTNTM ; Time for check on overdue CALL TVTNCK ; Telnet negotiations MOVE T1,LSNTIM ; Get time for listening SKIPE TVTLSN ; if no socket CAMG T1,TODCLK ; time for another stab? CALL LISTEN ; Try a listen RET ;LISTEN ;Set up a TCB listening on the TELNET port ;CALL LISTEN ;Ret+1: Always. TVTLSN set ge 0 if error, le 0 if OK. LISTEN: MOVE T1,FACTSW ; broadcast req TXNN T1,SF%NVT ; NVT logins allowed? JRST LSN1 ; No, Don't open MOVE T1,[TCP%PS+TCP%VT+TVTCDB] MOVEI T2,LSNTMO ; Timeout SETZ T3, ; Default re-transmission algorithm OPEN% ; Do the listen CAIA ; Don't save if failed MOVEM T1,TVTLSN ; Save LSN1: MOVE T1,TODCLK ; Get clock ADDI T1,^D60000 ; in one minute MOVEM T1,LSNTIM ; try again regardless RET ; Return TVTCDB: BLOCK .TCPCS ; Connection block .X==. RELOC TVTCDB+.TCPLP LSNPRT RELOC .X PURGE .X ;TVTOPN ;Open a TCP Virtual Terminal; Called in Job-0 context ;TCB/ Pointer to TCB ;CALL TVTOPN ;Ret+1: Always, T1 zero if OK or error code (ELT+^D4) otherwise TVTOPN::HRRZ T1,TCB ; Needs TCB TXO T1,AN%NTP ; Say it will speak new Telnet CALL ASNTVT ; Assign a virtual terminal JRST TVTOP7 ; Failed (not available, etc) STOR T1,TVTL,(TCB) ; Save in connection block PUSH P,T2 ; Save line block address MOVE T2,T1 ; Put line number in right place MOVEI T1,"C"-100 ; Get a control-C to awaken the job NOSKD1 CALL TTCHI ; Type it for the guy JFCL ; Ignore error return OKSKD1 SETZM TVTLSN ; Get another listen done SETZM TVTNTM ; Get done quickly POP P,T2 ; Restore line block address CALL ULKTTY ; Block now stable SETZ T1, ; No error JRST TVTOPX TVTOP7: MOVX T1,ELT+^D4 ; Out of resources error TVTOPX: RET ;TVTCLS ;Close a TCP Virtual Terminal ;T1/ Code for reason ;TCB/ Pointer to connection block ;CALL TVTCLS ;Ret+1: Always. RESCD TVTCLS::LOCAL MOVEM T1,CCODE CAIE CCODE,XFP+^D12 ; "Closing" or CAIN CCODE,EFP+^D7 ; "Connection error or rejected" CAIA ; (other end restarted) JRST TVTCL1 ; No. Something else ;Here when other end restarted and we received a RESET. PRCRST ;called [USRERR with EFP+^D7] ABTCON with EFP+^D7. Beware: it ;may be THE listening connection. ;Here when remote end is closing. We are in the process of ;sending and ACK for his FIN, but may not be done sending ;everything from this end yet -- for instance, "Detached job N ;..." msg. So, get the job to clean itself up and call TVTDTS ;via TTHNGU (from FLOGO1 as called from JOBCOF by top fork of ;the job), or via TTYDEA as called from TTYDAS from LDTACH or ;HLTJB. LOAD T2,TVTL,(TCB) ; Get the line number JUMPE T2,TVTCL2 ; TVT may not be assigned if during NOSKD1 ; OPEN (if so, need another listen) CALL NTYCOF ; Start the carrier off sequence OKSKD1 JRST TVTCLX ; and leave TVTCL1: CAIN CCODE,XLP+^D3 ; "Closed" JRST TVTCL4 ; Yes, just go detach it CAIN CCODE,ELT+^D4 ; "No free terminals" JRST TVTCL2 ; Go fake CLOSE & release JCN CAIE CCODE,ELP+^D14 ; "Connection reset" due to ; Retransmission timeout? JRST TVTCLX ; No, Something else. Ignore it. ;Here when a connection OPENed correctly but there were no free ;TVTs. PRCACK (or PRCSYN) called USREVT(OK) which called TVTOPN ;which called ASNTVT which failed. TVTOPN tried to send a ;message and then a RST to the other end before calling ;ABTCON(ELT+^D4) which called USREVT(ELT+^D4) which called ;TVTCLS(ELT+^D4). The state is NOT.NOT but we have to fake a ;CLOSE and release the JCN. ;Here when we have suffered a retransmission timeout on an open ;connection. REXMIT called [USRERR with ELP+^D9, "RX timeout", ;and] ABTCON with ELP+^D14, "Connection reset", which made the ;connection dead (state is NOTSYN in both directions) and called ;USREVT with ELP+^D14 who called us. All that remains is to get ;the job detached. Note that the job may or may not be logged ;in. TVTCL2: SETZRO TSUOP,(TCB) ; Don't send a FIN ;If this is a valid Job0 JCN we are dealing with the LISTENing ;port. The "said open" bit tells whether the timeout happened ;while the connection was opening (must do another listen) or ;after it had opened (next listen is already in progress). JN TSOPN,(TCB),TVTCL4 ; Jump if next listen already done LOAD T1,TJCN,(TCB) ; or if not a valid Job0 CAIN T1,-1 ; JCN JRST TVTCL4 SETZM TVTLSN ; Get another listen done SETZM TVTNTM ; Now. TVTCL4: LOAD T2,TVTL,(TCB) ; Get line number SKIPE T2 ; TVT not assigned if during open CALL TVTDTS ; Detach owning job JN TOWNR,(TCB),TVTCL5 ; Jump if TVT not owned by Job-0 (never) LOAD T1,TJCN,(TCB) ; Get our (Job-0) handle on the TCB CALLX (XCDSEC,RETJCN) ; Release it SETZRO TJCN,(TCB) ; (RETJCN can't do this if TJCN was -1) TVTCL5: TVTCLX: RESTORE RET SWAPCD ;OPSCAN Get packets sent on each connection with output waiting ;CALL OPSCAN ;Ret+1: Always. OPSCAN: LOCAL PUSH P,TCB SETZM TVTNOF ; Clear the run request flag MOVE TVTP,TVTPTR ; AOBJN for all TVTs OPSCA1: HRRZ T2,TVTP ; Next line number CALL LCKTTY ; Lock and get dynamic area to T2, NOINT JUMPLE T2,OPSCA8 ; Non standard block MOVE LINADR,T2 ; Save the terminal block ptr LOAD TCB,PTVT,(T2) ; Have a TCB? JUMPE TCB,OPSCA7 ; Jump if not there (??) SETSEC TCB,INTSEC ; Make extended address JE TTVT,(TCB),OPSCA7 ; Jump if not a TVT (??) LOAD T3,TVTL,(TCB) ; Get the line number JUMPE T3,OPSCA7 ; USREVT released the TVT line (??) CALL TVSBE1 ; Any output waiting? SKIPA T4,T1 ; Yes. Get PZ to call SNDTVT JRST OPSCA7 ; No. MOVX T1,^D200 ; The function to queue for PZ if a lot MOVX T2, ; to send - wait a bit, maybe more CAIGE T4,^D8 ; Less that 8 is echoing so MOVX T2, ; Force it now CALL (T2) ; See Note above OPSCA7: MOVE T2,LINADR ; Restore address of terminal block OPSCA8: CALL ULKTTY ; Decrease reference count, OKINT AOBJN TVTP,OPSCA1 ; Loop over all TVTs SKIPE T2,TVMSTM ; Any TTMSG's out? CAMLE T2,TODCLK ; Yes, time to flush yet? JRST OPSCAX ; No, return. NOSKED ; Prevent anyone from changing data CALL TVMNTR ; Flush all TTMSG's to TVTs OKSKED SETZM TVMSTM ; Clear timer OPSCAX: POP P,TCB RESTORE RET ;TVTMSG ;Routine to output a greeting message to a TVT TVMSGZ==^D60 ; size of buffer for TVTMSG in words TVTMSG:: ; Routine to type out a greeting message STKVAR > MOVX T1, ; The file must allready exist HRROI T2,[ASCIZ/SYSTEM:INTERNET-LOGIN-MESSAGE.TXT/] GTJFN% ; Get the JFN ERJMP R ; assume file does not exist MOVEM T1,TVMSGJ ; Save the JFN MOVX T2,<7B5!OF%RD> ; we want read access OPENF% ; open up the file ERJMP TVMSG2 ; handle errors SETZM TVMSGB ; zero the first word of the buffer MOVEI T2,1+TVMSGB ; get the address of the block HRLI T2,-1(T2) ; build complete BLT ac BLT T2,TVMSGZ-1+TVMSGB ; zero the whole buffer HRROI T2,TVMSGB ; destination pointer MOVNI T3,<-1> ; read as much as we can SIN% ; read in the string from the file ERJMP .+1 ; handle errors ADDI T3,-1 ; get the number of characters read JUMPE T3,TVMSG1 ; skip this stuff if none read MOVEI T1,.PRIOU ; output to primary designator MOVEI T2,TVMSGB ; get the address of the buffer HRLI T2,440700 ; build a byte pointer MOVNS T3 ; exact number of characters to output SOUT% ; output the string ERJMP .+1 ; handle errors TVMSG1: ; here also when buffer was empty MOVE T1,TVMSGJ ; get the JFN CLOSF% ; close it ERJMP .+1 RET ; return to caller TVMSG2: ; here when the OPENF% failed MOVE T1,TVMSGJ ; get the JFN RLJFN ; release it ERJMP .+1 RET ; return to caller ;TVRRH - TVT device dependent "return remote host" code ; ; Given the line #, returns the originating hostname, line and ; network type. Places this info in the users NTINF% .NWRRH ; argument block. NTINF has already checked the user arguments ; for validity. ; ; Call with T1/ address of internal arg block ; ; ARG+.NWABC/ # of bytes available for host name ; ARG+.NWFNC/ not used ; ARG+.NWNNP/ byte pointer to store hostname string ; ARG+.NWLIN/ address of dynamic data for line ; ARG+.NWTTF/ flags, and network and terminal types ; ARG+.NWNNU/ node # word 1 ; ARG+.NWNU1/ node # word 2 ; ; Returns + 1 on error with T1/ error code ; + 2 on success SWAPCD TVRRH:: STKVAR MOVEM T1,UAB ;SAVE POINTER TO ARG BLOCK MOVX T4,NW%TCP ;SET NETWORK TYPE DPB T4,[POINT 9,.NWTTF(T1),17] ;STORE NETWORK TYPE NOSKED ;DON'T LET TCB GO AWAY MOVE T2,.NWLIN(T1) ;GET TDB ADDRESS LOAD T3,PTVT,(T2) ;GET TCB IF IT EXISTS JUMPE T3,[OKSKED ;GO SET "NO NODE NAME KNOWN" AND RETURN CALLRET TVRRH1] SETSEC T3,INTSEC ;TCB'S ARE IN INTSEC LOAD T3,TFH,(T3) ;GET FOREIGN HOST OKSKED ;ALL OKAY AGAIN MOVEM T3,.NWNNU(T1) ;SAVE IT MOVE T2,.NWNNP(T1) ;GET POINTER FOR DEPOSITING HOSTNAME MOVX T1,.GTHNS ;RETURN PRIMARY NAME GTHST% ERJMP .+1 ;GOT AN ERROR TDZA T1,T1 ;HAVE A NODE NAME TVRRH1: MOVX T1,NW%NNN ;GET "NO NODE NAME KNOWN" FLAG MOVE T3,UAB SKIPE T1 ;GOT A NODE NAME ? IORM T1,.NWTTF(T3) ;NO - SET THE "NO NODE NAME KNOWN" FLAG RETSKP TNXEND END