;USR0:UDPJFN.MAC.2 2-Aug-85 FM+2D.1H.58M.22S., by BUDD ; Fix name check in HSTNLK, make = a port delim [11] SEARCH UDPUNV,ANAUNV,PROLOG TTITLE (UDPJFN,UDPJFN,< - JSYS Interface for UDP>) SUBTTL June 1985 Phil Budne@BU/DSG ; Copyright (C) 1985 Philip L. Budne ; Much code ripped off from TCPJFN ; This module implements the JFN interface to TOPS-20AN UDP ; ; N.B. ; ; The AC Defs in this module are different than the rest of the TCP/IP ; modules so watch out. IFNDEF REL6, ;Run under Rel 6 IFNDEF RFSP, ;Use resident free space STS=P1 JFN=P2 PTR=P3 DEV=P4 F1=P5 UCB=Q1 FX=Q3 DEFINE SAVEAT, EXTERN UOPEN,RELUCB,UGET,UPUT,UBPUT ;from UDPUDP EXTERN UDPON,UDPIFG,UDPBSZ ;from STG IFN REL6,UDP2RT==RSKP ;Skip return IFE REL6,UDP2RT==SK2RET ;Double skip return PRVPRT==1777 ;Highest secure UDP port SUBTTL UDP Device DTB SWAPCD UDPDTB:: ; DTB for UDP: device IFN REL6, ; length of DTB DTBDSP UDPSET ;*Directory setup routine DTBDSP UDPNAM ;*Name lookup DTBDSP UDPEXT ;*Extension lookup DTBDSP UDPVER ;*Version lookup DTBBAD (DESX9) ; Protection insertion DTBBAD (DESX9) ; Account insertion DTBBAD (DESX9) ; Status insertion (temporary permanent etc) DTBDSP UDPOPN ;*Open file DTBDSP UDPSQI ;*Byte input DTBDSP UDPSQO ;*Byte output DTBDSP UDPCLZ ;*Close file DTBBAD (DESX9) ; Rename DTBBAD (DESX9) ; Delete file DTBBAD (DESX9) ; Dump mode input DTBBAD (DESX9) ; Dump mode output DTBBAD (DESX9) ; Mount device DTBBAD (DESX9) ; Dismount device DTBBAD (DESX9) ; Initialize directory of device DTBDSP UDPMTP ;*Do mtape operation DTBDSP UDPGTD ;*Get device status DTBBAD (DESX9) ; Set device status DTBDSP UDPSQF ;*Force record out, (soutr jsys) DTBDSP RFTADN ; Read file time and date DTBDSP SFTADN ; Set file time and date DTBDSP UDPSFI ;*Set jfn for input DTBDSP UDPSFO ;*Set jfn for output DTBDSP UDPATR ;*Check attribute DTBDSP UDPRJF ;*Release jfn UDPDND==. SUBTTL GTJFN Setup Handling ;Format of a UDP: GTJFN string is as follows: ;UDP:[lcl-host-][lcl-port].[f4n-host-][f4n-port][;A1...][;A2...][;A3...] ;Square brackets denote fields which may or may not be present. Not ;all fields may be omitted for any given GTJFN string. UDPSET: ;directory setup CALL SKUDPU ;UDP up? RETBAD (TCPX16) ;no TQNE ;any wildcards? RETBAD(GJFX17) ;yes...error NOINT ;stop psi's SKIPE FILTCB(JFN) ;do we have a prototype UCB yet? JRST UDP2RT ;yes so success return MOVX T1,UCBSIZ ;get the size of the UCB CALL GETBLK ;get storage for the prototype UCB SKIPN T1 ;did we get the storage? RETBAD (TCPXX1,) ;no so return with an error MOVEM T1,FILTCB(JFN) ;save the DCB address MOVE UCB,FILTCB(JFN) ;get the UCB AC set up for later use MOVX T2,UCBSIZ ;get the size again CALL CLRBLK ;clear out the UCB STOR JFN,UCBJFN,(UCB) ;tell the UCB which JFN it belongs too JRST UDP2RT ;tell upper level stuff we suceeded SUBTTL GTJFN File Name, and File Generation Handling UDPNAM: ;decode gtjfn name string SKIPN UCB,FILTCB(JFN) ;get the UCB address JRST UDPNM3 ;error if does not exist TMNE UCBNAM,(UCB) ;have we allready done this? JRST UDP2RT ;yes so do not do it again SETZ T2, ;local host rules CALL HSTPRT ;decode host name and port number from string JRST UDPNM3 ;if error then badness STOR T2,UCBLH,(UCB) ;save the local host number ;; STOR T2,UCBOLH,(UCB) STOR T3,UCBLP,(UCB) ;save the local port number JUMPE T2,OKRET ;default local host? MOVE T1,T2 ;get the local host CALL NTNCTS ;get out address on that net RETBAD (TCPXX2) LOAD T2,UCBLH,(UCB) ;get the local host address CAME T2,T1 ;legit address? JRST UDPNM3 ;no OKRET: ;here on success return SETONE UCBNAM,(UCB) ;flag that we do not have to do this again TQNE ;do we need to unlock? JRST UDP2RT ;no OKINT ;yes so allow interrupts JRST UDP2RT ;skip 2 return UDPNM3: ;here on error from HSTPRT MOVEI T1,TCPXX2 ;get error code NOKRET: ;here on error return OKINT ;allow interrupts RET ;and return UDPVER: ;decode GTJFN version spec JUMPE T1,OKRET ;return if no version stuff MOVEI T1,TCPXX4 ;get error code JRST NOKRET ;return with error SUBTTL GTJFN File Name Extension Handling UDPEXT: ;decode GTJFN extension string SKIPN UCB,FILTCB(JFN) ;get the UCB address JRST UDPEX2 ;error if does not exists TMNE UCBEXT,(UCB) ;have we allready done this once? JRST OKRET ;yes so do not do it again SETO T2, ;4n host rules CALL HSTPRT ;decode host name and port number from string JRST UDPEX2 ;handle error return STOR T2,UCBFH,(UCB) ;save the foreign host number ;;; STOR T2,UCBOFH,(UCB) STOR T3,UCBFP,(UCB) ;save the foreign port number ;;; STOR T3,UCBOFP,(UCB) JN UCBLH,(UCB),OKRET ;non default local host? MOVE T1,T2 ;get the foreign host address CALL NTNCTS ;get our address on the net JRST UDPEX1 ;we do not have one STOR T1,UCBLH,(UCB) ;save the new local host number ;;; STOR T1,UCBOLH,(UCB) SETONE UCBEXT,(UCB) ;flag so we do not do this again JRST OKRET ;everything is fine UDPEX1: ;here when we have no adr on that net MOVE T1,DEFADR ;get out default address STOR T1,UCBLH,(UCB) ;this is now our local address ;;; STOR T1,UCBLH,(UCB) SETONE UCBEXT,(UCB) ;flag so we do not do this again JRST OKRET ;and return to caller UDPEX2: ;here on error from hstprt MOVEI T1,TCPXX3 ;get the error code JRST NOKRET ;error return SUBTTL GTJFN File Name Attribute Handling UDPATR: ;here to check attributes from gtjfn TRVAR ;temporary storage SKIPE T1 ;pointer exist? HRLI T1,010700 ;yes...make it a seven bit pointer MOVEM T1,UDPATP ;save the data pointer SKIPN UCB,FILTCB(JFN) ;get the UCB address RETERR(TCPXX5) ;error if no UCB MOVSI T1,-UATLEN ;build aobjn pointer UDPALP: ;attribute checking loop HLRZ T3,UATTBL(T1) ;get a code from the table CAME T3,T2 ;is this our attribute? JRST UDPAL2 ;no HRRZ T3,UATTBL(T1) ;get the dispatch address JRST (T3) ;dispatch to the handling routine UDPAL2: ;here when entry was a match AOBJN T1,UDPALP ;check others if there are more RETBAD (TCPXX5) ;no such attribute UATTBL: ;table of attribute codes .PFTLH,,UTTRLH ;local-host .PFTFH,,UTTRFH ;foreign host UATLEN==.-UATTBL ;number of attributes SUBTTL Foreign-Host and Local-Host Attributes UTTRFH: ;foreign-host attribute MOVE T1,UDPATP ;get the pointer CALL HSTHST ;decode the host number RETBAD (TCPXX7) ;failure so get error code STOR T2,UCBFH,(UCB) ;save the foreign host number ;;; STOR T2,UCBOFH,(UCB) RETSKP ;return success UTTRLH: ;local-host attribute MOVE T1,UDPATP ;get the pointer CALL HSTHST ;decode the host number RETBAD (TCPXX8) ;failure so get error code STOR T2,UCBLH,(UCB) ;save the local host number ;;; STOR T2,UCBOLH,(UCB) MOVE T1,T2 ;get host number into correct place CALL NTNCTS ;get our NCT on that net RETBAD (TCPXX8) ;no address LOAD T2,UCBLH,(UCB) ;get the address user wants CAME T1,T2 ;same? RETBAD (TCPXX8) ;no RETSKP ;return success SUBTTL CLOSF and RELJFN Handling UDPRJF: ;here on rljfn UDPCLZ: ;here on a closf SAVEAT SKIPN T1,FILTCB(JFN) ;UCB Exist? RETSKP ;no SETZM FILTCB(JFN) ;no more UCB TMNE UCBOPN,(T1) ;Real (open) UCB? IFSKP. CALL RETBLK ;no so just release the space RETSKP ;and success return ENDIF. CALL RELUCB ;Close it down RETSKP SUBTTL OPENF Handling UDPOPN: ;perform openf SAVEAT SKIPN UCB,FILTCB(JFN) ;get the UCB address RETBAD(TCPX35) ; can not reopen a UDP JFN (JFN w/o UCB?) CALL SKUDPU ;UDP up and running? RETBAD (TCPX16) ;no so return with an error ;here to check user arguments TMNE UCBOPN,(UCB) ;Now open? RETBAD (TCPX35) ; may not reopen TQNE ;check illegal access modes RETBAD (TCPX17) ;if any of these on then badness TQNN ;must be readable RETBAD (TCPX17) ;if not readable then error TQNN ;must be writable RETBAD (TCPX17) ;if not writeable then error LDB T1,PBYTSZ ;get byte size user wants CAIE T1,^D32 ;is it 32 bit bytes? CAIN T1,^D8 ;or 8 bit bytes? SKIPA ;one or the other so ok RETBAD (TCPX18) ;bad byte size error LOAD T1,IOMODE ;get the mode user asked for CAIE T1,0 ;Normal mode? RETBAD (TCPX30) ;no so error ;Ask the ACJ if this is OK [perhaps should use new .GOxxx code?] LOAD T1,UCBFH,(UCB) ;Get the foreign host number LOAD T2,UCBFP,(UCB) ;Get the foreign port number GTOKM (.GOANA,,[RETBAD()]) ; ask acj for its blessing ;Everything is OK. Fall through. SUBTTL OPENF% Continued.... ;Falls through from above LOAD T1,UCBLP,(UCB) ;Get the local port CAILE T1,PRVPRT ;Not active - special low port? IFSKP. MOVX T1, TDNN T1,CAPENB ;Required privs? RETBAD(NTWZX1) ;Indicate must be network wizard ENDIF. MOVE T1,UCB CALL UOPEN ;Get real UCB JUMPL T1,UDPOP5 ;BBN errors are negative MOVEM T1,FILTCB(JFN) ;save in JFN block MOVE UCB,T1 ;set pointer LDB T1,PBYTSZ ;get byte size user wants CAIE T1,^D8 ;8 bit bytes? IFSKP. SETONE UCB8B,(UCB) ;yes so set the flag ENDIF. SETONE UCBHT,(UCB) ;Set high thruput SETZM UCBOBF(UCB) ;output buffer SETZM UCBIBF(UCB) ;input buffer SETZM FILLEN(JFN) ;initially zero length SETZM FILBNI(JFN) ;zero input byte number SETZM FILBNO(JFN) ;zero output byte number SETZM FILBCI(JFN) ;zero input bytes remaining count SETZM FILBCO(JFN) ;zero output bytes remaining count RETSKP UDPOP5: ;here on error return from UOPEN SETZRO ;not blocking now SETZM FILTCB(JFN) ;no UCB anymore CALL ERTRAN ;get the real error code SETONE ;Flag an error RETBAD ;and return with error SUBTTL Support Routines for Sequential IO UDPSFI: ;Switch to INPUT TMNE FILINP ;allready doing input? RET ;yes so just return SETONE FILINP ;no so doing input now SETZRO FILOUP ;and not doing output now SETZRO FILNO,(JFN) ;not doing new OUTPUT now RET ;return to caller UDPSFO: ;Switch to OUTPUT TMNE FILOUP ;allready doing output? RET ;yes so just return SETONE FILOUP ;now doing output SETONE FILNO,(JFN) ;doing new OUTPUT now SETZRO FILINP ;not doing input now RET ;return to caller UDPSIO: ;Set up for I/O SETZRO ;no longer blocking SKIPN UCB,FILTCB(JFN) ;get the TCB address if it exists RETERR(TCPX35) ;in case no TCB (which should not happen) RETSKP ;Alls well SUBTTL Support Routines for Buffers UDPGTB: ;routine to get a buffer ;address of buffer returned in T1 NOINT ;go noint MOVE T1,UDPBSZ ;get buffer size IFE RFSP,< CALL ASGSWP ;get some swappable free space > ;IFE RFSP IFN RFSP,< HRLI T1,.RESP3 ;get priority IFE REL6,< MOVX T2,B35> ;from the general pool > ;IFE REL6 IFN REL6,< MOVX T2,B35> ;from the decnet pool > ;IFN REL6 CALL ASGRES ;get some resident free space > ;IFN RFSP JRST UDPGT2 ;error OKINT ;allow interrupts RETSKP ;success return UDPGT2: ;here when we could not get the space OKINT ;allow interrupts SETONE ;set the block flag MOVEI T1,^D1000 ;wait 1 seconf CALL SETBKT ;compute wait HRRI T1,BLOCKT ;the scheduler test RET ;lower level will block UDPRLB: ;routine to release a buffer ;Address of buffer in T1 JUMPE T1,R ;helper for UDPBFD - lets EXCH work NOINT ;stop interrupts IFE RFSP,< MOVE T2,UDPBSZ ;length of the block CALL RELSWP ;release swappable free space > ;IFE RFSP IFN RFSP,< CALL RELRES ;release resident free space > ;IFN RFSP OKINT ;allow interrupts SETZ T1, ;help UDPBFD - lets EXCH work RET ;and return to caller UDPBFD:: ;routine to discard all buffers from ;UCB addressed by T1 SAVEAC ;do not destroy this AC MOVE UCB,T1 ;put the UCB address in the correct place SETZ T1, ;UDPRLB will help us after this SETZ EXCH T1,UCBIBF(UCB) ;delete input buffer CALL UDPRLB EXCH T1,UCBOBF(UCB) ;delete output buffer CALLRET UDPRLB SUBTTL Sequential Input (BIN/SIN) UDPSQI: ;Byte Input SAVEAT ;save most acs UDSQI0: ;here to see if input is possible CALL UDPSIO ;set things up (like UCB) RET ;pass down any problems or errors SKIPN UCBIBF(UCB) ;have an input buffer? JRST UDSQI1 ; no, go get it SKIPG FILBCI(JFN) ;any bytes left in this buffer? JRST UDSQI5 ; no bytes left so go finish off this buffer ILDB T1,FILBFI(JFN) ;bytes left so get one AOS FILBNI(JFN) ;we read one byte SOSG FILBCI(JFN) ;and there is one less byte in the buffer JRST UDSQI6 ;get another buffer if we finished this one RET ;we did not finish the buffer so return UDSQI1: CALL UDPGTB ;get a buffer RET ;pass down blocks and errors MOVEM T1,UCBIBF(UCB) ;store buffer UDSQI5: ;here when the input buffer is done CALL UDPGIB ;get another input buffer RET ;pass down errors and blocks JRST UDSQI0 ;go try to input this character again ;here when last i/o finished the buffer UDSQI6: SAVEAC CALL UDPGIB ;try to refill buffer NOP ; nevermind (we already got one!) RET ;and return to caller SUBTTL Get Input Buffer Routine UDPGIB: ;Here to get an input buffer setup MOVE T1,UCB ;get UCB in T1 UDPGI1: CALL UGET ;Fill buffer from an internet packet JUMPE T1,UDGIBR ;nothing there TMNE UCB8B,(UCB) ;32 bit mode? IFSKP. ADDI T1,3 ;Add bytes/word - 1 LSH T1,-2 ;Div by bytes/word ENDIF. MOVEM T1,FILBCI(JFN) ;save the number of bytes available ADDM T1,FILLEN(JFN) ;update file length MOVE T1,UCBIBF(UCB) ;get the buffer address HRLI T1,(POINT 8,) ;assume 8 bit TMNN UCB8B,(UCB) ;32 bit mode? HRLI T1,(POINT 32,) ; yes so get a 32 bit byte pointer MOVEM T1,FILBFI(JFN) ;save the new pointer RETSKP ;and return UDGIBR: ;here when nothing in input queue LOAD T1,UCBWAI,(UCB) ;get wait bit MOVSI T1,(T1) ;in LH HRRI T1,UDPBOT ;get test (wait for bit set) SETONE ;say we are blocking RET ;return to lower levels SUBTTL Sequential Output (BOUT/SOUT) UDPSQO: ;byte Output SAVEAT ;save most acs TRVAR MOVEM T1,UDPSOB ;save the byte to output CALL UDPSIO ;set up UCB etc RET ;pass down any problems or errors ;here to try to output the byte UDSQO1: SKIPN UCBOBF(UCB) ;have a buffer? JRST UDSQO3 ; no get one TMNN UCBOB,(UCB) ;buffer ready? CALL UDPOST ; no set it up now TMNE UCBPU,(UCB) ;are we here for a push? JRST UDSQO2 ; yes so send a buffer now JE UCBHT,(UCB),UDSQO4 ;handle interactive different ;here when we are high throughput mode SOSGE FILBCO(JFN) ;is the buffer full allready? JRST UDSQO2 ; yes send now MOVE T1,UDPSOB ;get the byte IDPB T1,FILBFO(JFN) ;deposit the byte AOS FILBNO(JFN) ;account for each byte SKIPG FILBCO(JFN) ;buffer now full? CALL UDPOUT ;yes so output it NOP ;allow blocks and errors RET ;and return ;here when buffer full coming in (or push) UDSQO2: CALL UDPOUT ;try to output the buffer RET ;allow blocks and errors JE UCBPU,(UCB),UDSQO1 ;go try to output the character again SETZRO UCBPU,(UCB) ;turn off the push flag SETZM FILBNO(JFN) ;make sure next output to this jfn SETZM FILBCO(JFN) ;goes to a new buffer RET ;successfull return ;here when no current buffer UDSQO3: CALL UDPGTB ;get an output buffer RET ;pass down blocks and errors MOVEM T1,UCBOBF(UCB) ;save address of buffer CALL UDPOST ;set up output buffer pointers/counters JRST UDSQO1 ;go try to output the character again ;here when we are interactive UDSQO4: SETZM FILBCO(JFN) ;make sure we get called every time SOSGE UDPBCO(UCB) ;buffer allready full? JRST UDSQO2 ;yes so try to output it AOS FILBNO(JFN) ;account for each byte MOVE T1,UDPSOB ;get the byte IDPB T1,FILBFO(JFN) ;output the byte SKIPGE UDPBCO(UCB) ;buffer full now? CALL UDPOUT ; yes so start outputing it NOP ; allow errors and blocks RET ;and return SUBTTL UDP Output Buffer Setup UDPOST: ;Setup Output Buffer MOVE T1,UDPBSZ ;get number of words in buffer TMNE UCB8B,(UCB) ;8 bit mode? LSH T1,2 ;yes so 8 bit bytes SETZM FILBCO(JFN) ;in case interactive TMNE UCBHT,(UCB) ;high throughput? MOVEM T1,FILBCO(JFN) ;yes save the number of bytes available TMNN UCBHT,(UCB) ;interactive MOVEM T1,UDPBCO(UCB) ;yes save number of bytes available MOVE T1,UCBOBF(UCB) ;get the address of the buffer HRLI T1,(POINT 8,) ;get an 8 bit pointer TMNN UCB8B,(UCB) ;32 bit bytes? HRLI T1,(POINT 32,) ;yes so get a 32 bit byte pointer MOVEM T1,FILBFO(JFN) ;save the new pointer SETZM FILBNO(JFN) ;save new byte count SETONE UCBOB,(UCB) ;say buffer is setup RET ;return to caller SUBTTL UDP Output Buffer Queueing UDPOUT: ;here to output the current buffeer SETZRO UCBOB,(UCB) ;must reset buffer MOVE T1,UCB ;get UCB MOVE T2,FILBNO(JFN) ;get the byte count ; JUMPE T2,RSKP ;Don't send nothing TMNN UCB8B,(UCB) ;32 bit mode? LSH T2,2 ; yes so 4 octets per byte CALL UPUT ;Send packet JUMPE T1,RSKP ;Alls Well! ;; here if UPUT failed to get a buffer SETONE ;set the block flag MOVEI T1,^D1000 ;wait 1 second CALL SETBKT ;compute wait HRRI T1,BLOCKT ;the scheduler test RET ;lower level will block SUBTTL MTOPR Handling UDPMTP: TQNN ;CHECK TO SEE IF OPENED RETBAD (CLSX1) ;NO ERROR XCTU [HRRZ 3,2] ;GET MTOPR OP CODE MOVSI T1,-UDPMTL ;FORM AOBJN POINTER UDPMT0: HLRZ T4,UDPMTF(T1) ;GET CODE CAIN T4,0(T3) ;IS THIS THE ONE? JRST [ HRRZ T3,UDPMTF(T1) ;GET DISPATCH ADDRESS JRST 0(T3)] ;GO DO IT AOBJN T1,UDPMT0 ;DO ALL OF THEM RETBAD (MTOX1) ;ERROR ;MTOPR DISPATCH TABLE DEFINE DEF(FNC,ADDR) < <&<-1,,0>>+> > ;DEF UDPMTF: DEF UOU,UDMUOU ;BLOCK OUTPUT DEF UPS,UDMUPS ;SET PSI ; DEF UIN,UDMUIN ;BLOCK INPUT UDPMTL==.-UDPMTF ;LENGTH OF TABLE ; BLOCK OUTPUT FUNCTION UDMUOU: SAVEAT ;Save temp acs CALL UDPSIO ;Set up for I/O RET ; pass failure SKIPE FILBFO(JFN) ;Done buffered output already?? RETERR(MTOX9) ; Output still pending??!!! MOVE T1,UCB ;Get UCB CALL UBPUT ;Do buffered send. UMOVEM T1,4 ;return buyes sent (or 0 or -1) RETSKP ;; SET DATA AVAIL PSI CHAN. UDMUPS: CALL UDPSIO ;GET UCB RET ; PASS FAILURE NOINT LOCK JFNLCK ;LOCK THE JFN CALL REAJFN ;CHECK AND REASSIGN THE JFN IF NECESSARY JFCL UNLOCK JFNLCK ;RELEASE THE LOCK OKINT SKIPG 3 ;IS THE CHANNEL NON-NEGATIVE? RETBAD (MTOX18) ; BAD VALUE CAIE 3,77 ;IS IT 77 ? CAIG 3,^D35 ; NO, IS IT .LE. 35? TRNA ; YES, OK RETBAD (MTOX18) ; NO, LOSER STOR 3,UCBICD,(UCB) ;SAVE CHAN MOVE T1,FORKX ;GET CURRENT FORK STOR T1,UCBIFD,(UCB) ;SAVE PSI FORK STOR T1,UCBFRK,(UCB) ;SAVE OWNER FORK RETSKP SUBTTL SOUTR and GDSTS Handling UDPSQF: ;Force record out SAVEAT ;save most acs SETZRO ;we are no longer blocking CALL UDPSIO ;can we still do constructive work? RET ;no so return with error or block SETONE UCBPU,(UCB) ;set the push flag CALL UDSQO1 ;join the normal byte output code TMNE ;want to block? RET ;yes so return TMNE ;have an error RET ;yes so return RETSKP ;otherwise skip return UDPGTD: ;GDSTS Handling SAVEAT ;save most acs SETO T1, ;Perpare for nasty return SKIPN UCB,FILTCB(JFN) ;get the UCB address RET ; What a ripoff! MOVE T1,UCBCTR(UCB) ;Get number of waiting packets LOAD T2,UCLFH,(UCB) ;get the last 4n host number UMOVEM T2,3 ;save in users AC3 LOAD T2,UCLFP,(UCB) ;get the last 4n port number UMOVEM T2,4 ;save in users AC4 RET ;and return to caller ;; the following code is duplicated from TCPJFN, but is not global. ;;; HSTNLK IS BUGGY!! (FIXED [11]) IFN 1,< SUBTTL Decode Host-Port Specification ; Call: ; T1/ pointer to string ; T2/ NON-ZERO INDICATES RULES FOR FOREIGN HOSTS ; NON-SKIP RETURN INDICATES FAILURE ; Skip return indicates success ; T1/ updated string pointer ; T2/ host number ; T3/ port number HSTF%A==1B0 ;pound sign found flag HSTF%F==1B1 ;foreign host flag HSTPRT: ;routine to decode host-port spec STKVAR ;LOCAL STORAGE SETZM HSTPHN ;zero the host number SETZM HSTPDP ;zero the dash pointer flag SETZM HSTPOT ;zero the port number JUMPE T1,R ;if null user is trying wildcard - disallow HRLI T1,010700 ;make the pointer a byte pointer MOVEM T1,HSTPT1 ;save the initial byte pointer SETZ T4, ;zero the flag word SKIPE T2 ;4n host rules? TXO T4,HSTF%F ;yes so set the flag HSTLP1: ;loop looking for terminator for field MOVE T3,T1 ;save the old byte pointer ILDB T2,T1 ;get a character CAIE T2,"#" ;is it the special port delimitor? JRST HSTLP2 ;no so keep checking TXNE T4,HSTF%A ;have we allready had one? RET ;yes so this is an error TXO T4,HSTF%A ;flag that we have seen one JRST HSTLP1 ;and look for more characters HSTLP2: ;here on characters not quoted by ^v CAIL T2,"A" ;is it an alpha character? CAILE T2,"Z" SKIPA ;not a-z JRST HSTLP1 ;a-z so keep looking CAIL T2,"A"+40 ;is it little a through z CAILE T2,"Z"+40 SKIPA ;not little a-z JRST HSTLP1 ;little a-z so keep looking CAIL T2,"0" ;is it numeric? CAILE T2,"9" SKIPA JRST HSTLP1 ;numeric so keep looking CAIE T2,"-" ;is it our favorite delimitor? CAIN T2,"=" ;[11] or alternate? TRNA ;[11] yes! JRST HSTPR2 ;no MOVEM T3,HSTPDP ;save the latest dash pointer JRST HSTLP1 ;keep looking SUBTTL Decode Host-Port Specification...Continued HSTPR2: ;here when we have determined end of string MOVEM T3,HSTPT2 ;save the final pointer CAMN T1,HSTPT1 ;same as initial pointer? RET ;yes error SKIPN HSTPDP ;do we have a host name or number? JRST HSTPR4 ;no MOVE T1,HSTPT1 ;get the initial pointer MOVEI T3,10 ;octal number NIN ;attempt to read host number ERJMP HSTPR3 ;hmmm. not number. must be a string JUMPLE T2,R ;host number must be positive MOVEM T2,HSTPHN ;save the host number JRST HSTPR4 ;go check for the port number HSTPR3: ;here when the host name is alphanumeric MOVE T1,HSTPT1 ;get the byte pointer CALL HSTNLK ;go look up the name RET ;not found MOVEM T1,HSTPHN ;save the host number HSTPR4: ;here to check for port number MOVE T1,HSTPDP ;get the dash pointer IBP T1 ;increment the pointer SKIPN HSTPDP ;was there a dash? MOVE T1,HSTPT1 ;no so get the initial pointer MOVEM T1,HSTPPP ;save the port number pointer MOVE T2,HSTPT2 ;get the final pointer CALL STRLEN ;get the length of the string? JUMPLE T3,HSTPR5 ;handle case of no port number MOVE T1,HSTPPP ;get the port number pointer MOVEI T3,12 ;we use decimal for ports NIN ;read in the port number ERJMP HSTPR5 ;on error there is no port number MOVEM T2,HSTPOT ;save the port number CAILE T2,177777 ;legit port number? RET ;no error TXNE T4,HSTF%F ;foreign host spec? JRST HSTPR5 ;yes so no checks CAILE T2,PRVPRT ;special low port number? CAIL T2,100000 ;special high port number? IFNSK. LDB T3,T1 ;yes to either, get the next character CAIE T3,"#" ;is it the special port delimiter? RET ;no so error CAIG T2,PRVPRT ;if low port number, OPENF% will validate ANSKP. ;else must validate privileges JE ,CAPENB,R ENDIF. ;fall through SUBTTL Decode Host-Port Specification...Continued HSTPR5: ;here after we have port number AOS T2,JOBUNI ;get next unique number for this job ANDI T2,77 ;only last 6 bits please MOVE T3,JOBNO ;get my job number LSH T3,6 ;shift over IOR T2,T3 ;get the default port number ADDI T2,100000 ;add in the offset TXNN T4,HSTF%F ;4N host? SKIPE HSTPOT ;no so is it zero port number? SKIPA ;not 4N or not zero MOVEM T2,HSTPOT ;local and zero so use default port MOVE T1,HSTPT2 ;get the final pointer IBP T1 ;increment the pointer MOVE T2,HSTPHN ;set the host number MOVE T3,HSTPOT ;get the port number RETSKP ;return success SUBTTL Host Number Decode Routine ;Call: ;T1/ Pointer to string ;Non-skip return for error ;Skip return for success ;T1/ 32 bit host number right justified HSTHST: ;Host number decode routine STKVAR SKIPN T1 ;string exist? RET ;no so error return SETZM HSTHSN ;zero the host number word MOVX T2, ;get pointer for the host number word MOVEM T2,HSTHSP ;save the pointer MOVEI T4,4 ;four numeric fields HSTHSL: ;loop for reading fields MOVEI T3,12 ;fields are decimal NIN ;read in a field ERJMP R ;trap errors IDPB T2,HSTHSP ;deposit the field CAIN T4,1 ;is this the last field? JRST HSTHSX ;yes LDB T2,T1 ;no so get the next character CAIE T2,"." ;better be a dot RET ;it is not...error return SOJA T4,HSTHSL ;get the next field HSTHSX: ;here when we have the whole host number MOVE T1,HSTHSN ;get the host number RETSKP ;and return success SUBTTL Host Name Decode Routine ;Call: ;T1/ Pointer to string ;Non-skip return for error ;Skip return for success ;T1/ 32 bit host number right justified HSTNLK: ;Host name lookup routine SAVEAC ;do not trash this AC STKVAR MOVEM T1,HNLKPT ;save the pointer HRLZ T1,MHOSTS ;get the AOBJN ac HSTNL1: ;name chasing loop MOVE T2,HNLKPT ;get the string pointer MOVEM T2,HNLKP1 ;save it where we can use it HRRZ T2,T1 ;get the index out of the AOBJN AC SETSEC T2,INTSEC ;make sure we touch the proper section LOAD T2,HSTNMP,(T2) ;get the address of a name string ADD T2,[INTSEC,,HSTNAM] ;get the entire address MOVX T3, ;make a byte pointer MOVEM T3,HNLKP2 ;save the second pointer HSTNL2: ;loop for checking out a host name ;;;; ILDB T4,HNLKP2 ;get a byte of the second string ;;;; JUMPE T4,HSTNL3 ;if this is a null byte we have success ;;;; ILDB T3,HNLKP1 ;get a byte of the first string ;;;; JUMPE T3,HSTNL3 ;if this is a null byte we have success ;;;; CAIN T3,(T4) ;bytes match? ;;;; JRST HSTNL2 ;yes so keep checking DO. ;[11] loop for checking out a host name ILDB T3,HNLKP1 ;[11] get a byte of the first string ILDB T4,HNLKP2 ;[11] get a byte of the second string IFE. T4 ;[11] table string terminates? JUMPE T3,HSTNL3 ;[11] and user string ends too?? a win! MOVE T3,HNLKP1 ;[11] get user bp CAMN T3,HSTPDP ;[11] now resting on final dash? JRST HSTNL3 ;[11] yes! found host! EXIT. ;[11] else was a prefix, get next host (save?) ENDIF. ;[11] end of user string null. JUMPE T4,ENDLP. ;[11] HSTNAM string run out? CAIN T3,(T4) ;[11] bytes match? LOOP. ;[11] yes so keep checking OD. ;[11] bottom of host checking loop ;[11] here when current host name did not match ;here when current host name did not match AOBJN T1,HSTNL1 ;go check out the next host RET ;we did not find a host name HSTNL3: ;here when we found the host name SETSEC T1,INTSEC ;reference proper section LOAD T1,HSTIDX,(T1) ;get the HOSTNN index SETSEC T1,INTSEC ;reference proper section MOVE T1,HOSTNN(T1) ;get the host number RETSKP ;and success return SUBTTL String Length Subroutine STRLEN: ;Calculate length of string given two SAVEAC ;7-bit byte pointers, T1-T4 destroyed ;t1/ pointer one ;t2/ pointer two ;length returned in T3 IBP T1 ;advance both pointers IBP T2 ;to put them in a known state SETO T3, ADJBP T3,T2 ;backspace the second pointer SETO T2, ADJBP T2,T1 ;backspace the first pointer MOVE T1,T2 ;put first pointer into correct ac MOVEI T4,(T1) ;get the address SUBI T1,(T4) ;fix pointer for zero base address SUBI T3,(T4) ;and second pointer also MULI T1,5 ;five byte per word MULI T3,5 ;in this pointer also SUBI T4,-4(T3) ;get offset for second pointer SUBI T2,-4(T1) ;get offset for first pointer HRRZS T2 ;zero the left half HRRZ T3,T4 ;for this pointer also SUBI T3,(T2) ;get the length in bytes RET ;return to caller SKUDPU: ;Skip if UDP is up and initialized SKIPE UDPON ;UDP on? SKIPN UDPIFG ;and UDP initialized? RET ;no so no skip return RETSKP ;yes and yes so skip return SUBTTL Random Routines SAVAT: ;support routine for saveat macro ADJSP P,10 ;make room on the stack DMOVEM Q1,-7(P) ;save Q1 and Q2 MOVEM Q3,-5(P) ;save Q3 DMOVEM P2,-4(P) ;save P2 and P3 DMOVEM P4,-2(P) ;save P4 and P5 MOVEM P6,-0(P) ;save P5 PUSHJ P,0(CX) ;return to caller RSTAT: ;restoration routine SKIPA ;handle non skip return AOS -10(P) ;bump return address DMOVE P5,-1(P) ;restore P5 and P6 DMOVE P3,-3(P) ;restore P3 and P4 MOVE P2,-4(P) ;restore P2 DMOVE Q2,-6(P) ;restore Q2 and Q3 MOVE Q1,-7(P) ;restore Q1 ADJSP P,-10 ;fix up stack RET ;and return ERTRAN: ;here to translate BBN errors to error codes ANDI T1,37 ;get just low order bits CAILE T1,ERTMAX ;error code we know about? SETZ T1, ;no so fix it up MOVE T1,ERTABL(T1) ;get the new error code RET ;and return to caller ERTABL: EXP TCPX25,TCPX25,TCPX25,TCPX30,TCPX20,TCPXX3,TCPX19,TCPX31 EXP TCPX25,TCPX32,TCPX25,TCPX25,TCPX33,TCPXX8,TCPX25,TCPX25 EXP TCPXX1,TCPX34,TCPX25,TCPX25,TCPX34,TCPX34,TCPX34,TCPX25 EXP TCPX25,TCPX25,TCPX25,TCPX25,TCPX25,TCPX34,TCPX25,TCPX16 ERTMAX=.-ERTABL-1 NTNCTS: ;get out host number on a net SAVEAC ;save this ac CALL NETNCT ;lookup the host number RET ;error return MOVE T1,NTLADR(P1) ;put adr into a safe AC RETSKP ;skip return > ;IFN 1 (DUPLICATED CODE) SUBTTL UDP INPUT WAIT TEST RESCD ;(Identical to INTBOT from IPIPIP) ;UDPBOT Scheduler test for a wait bit being on. ;T1/ Index to INTWTB ;T4/ Return address ; JSP T4,UDPBOT ;Ret+1: Wait flag still off ;Ret+2: Wait flag now on UDPBOT: JUMPE T1,UDPBOX ; Beware bit 0 IDIVI T1,^D36 MOVE T2,BITS(T2) TDNN T2,INTWTB(T1) JRST 0(T4) UDPBOX: JRST 1(T4) SWAPCD TNXEND END