1
0
mirror of https://github.com/PDP-10/its.git synced 2026-03-06 11:23:32 +00:00
Files
PDP-10.its/src/sysnet/netwrk.266
2016-11-02 13:20:15 +01:00

2706 lines
76 KiB
Plaintext
Executable File
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
;-*- Mode:MIDAS; -*-
; Netwrk subroutines
; Canonical location is [MIT-AI] SYSNET;NETWRK >
; All changes must be made or copied to this location,
; or they will be lost!
;
; New version partially fixed for HOSTS3, 2/17/83. --KLH
; ITS/20X version, 4/8/83. --Ian
;
; $$ARPA is understood to mean Internet; any address with NE%UNT off
; qualifies as an Internet address.
;
;***************************************************************************
;******* In order to help clean things up and keep stuff working,
;******* please enter here the names of any programs you are aware of
;******* which insert this file! This will assure that future changes
;******* will not break your favorite software.
; AI:SYSENG;CRTSTY
; AI:SYSENG;TELSER
; AI:SYSEN1;HSTLOK
; AI:SYSEN1;PWORD
; AI:SYSEN1;UP
; AI:SYSEN2;PEEK
; AI:SYSEN2;TELNET
; AI:KSC;COMSAT
; AI:SYSNET;FTPS
; AI:SYSNET;FTPU
; AI:KSC;QMAIL
; MX:MT;NTELSUP
; AI:SYSEN1;SENDER
; AI:BAWDEN;PROBE
; AI:SYSENG;DUMP
IFNDEF ITS,[
IFE .OSMID-SIXBIT/ITS/,ITS==1
.ELSE ITS==0
];IFNDEF ITS
IFNDEF 20X,[
IFE .OSMID-SIXBIT/TWENEX/,20X==1
.ELSE 20X==0
];IFNDEF 20X
IFNDEF 10X,[
IFE .OSMID-SIXBIT/TENEX/,10X==1
.ELSE 10X==0
];IFNDEF 10X
TNX==20X\10X ; This is the normally used switch.
.AUXIL ;Don't mention all my symbols in crefs of programs that use me.
.BEGIN NETWRK
;Calling Conventions:
;
;All subroutines herein are called by PUSHJ P,
;and take their skip return if successful, non-skip if error.
;Arguments are passed in ACs A,B,C,D,E. ACs T and TT are freely smashable.
;However, "low level" subroutines generally take arguments and
;return values in T and TT and leave A-E alone.
;Subroutines may alter A-E as documented with each routine.
;The only ACs assumed are A,B,C,D,E,T,TT,P. TT=T+1 is assumed.
;
;The following externally defined symbols are assumed:
;
;GETCHR Routine to read character for HOSTNM/SYMGET routine.
; Returns in T, clobbers TT, skip return unless no chars available.
;
;PUTCHR Routine to write character for HOSTNM/SYMGET and ANALYZE routines.
; Char is passed in T (!!). Mustn't clobber any ACs. Never skips (!!).
;
;SPCHAN Routine to handle special characters for HOSTNM/SYMGET.
; Char is passed in T, number so far read in TT.
; Non-skip return to restart reader, skip to ignore char.
;
;DEBUG Nonzero if debugging. SERVE doesn't time out, and .VALUE'S
; if anything bad happens.
;
;The usual values for ITS predefined symbols are assumed.
;
;The NETWRK subroutines are enclosed in a MIDAS begin block to avoid
;confusion in the local tags. All code produced is pure. Any impure
;locations needed are created as MIDAS variables (eg, .VECTOR).
;Print file version
.TYO6 .IFNM1
.TYO 40
IFN ITS,.TYO6 .IFNM2
IFN TNX,[
DEFINE TYPN ARG
PRINTX "ARG"
TERMIN
RADIX 10.
TYPN \.IFVRS
RADIX 8.
] ;TNX
PRINTX / included in this assembly.
/
qmtch==.qmtch ;In case the .INSRTer didn't have this set, turn it on so that
.qmtch==-1 ;we use "foo" construct, for other-assembler compatability.
;The following symbols are used to select only necessary routines
IFNDEF $$HST3, $$HST3==1 ; 1 = use HOSTS3 format and file.
IFNDEF $$HOSTNM, $$HOSTNM==0 ;Host name file lookup routines.
IFNDEF $$SYMGET, $$SYMGET==0 ;Interactive symbol input routine
IFNDEF $$SYMLOOK,$$SYMLOOK==0 ;table lookup routine.
IFNDEF $$HSTMAP, $$HSTMAP==0 ;HSTMAP, HSTUNMAP, HSTSRC host name table rts
IFNDEF $$HSTSIX, $$HSTSIX==0 ;Sixbit host name abbreviation
IFNDEF $$MIT, $$MIT==1 ;Flush "MIT-" in HSTSIX
IFNDEF $$OWNHST, $$OWNHST==0 ;Routine to get own host address
IFNDEF $$HSTCMP, $$HSTCMP==0 ;Routine to compare two host addresses
IFNDEF $$NETSRC, $$NETSRC==0 ;NETSRC routine to get network names
IFNDEF $$ICP, $$ICP==0 ;Initial Connection Protocol
IFNDEF $$SERVE, $$SERVE==0 ;Respond to an ICP (for a server)
IFNDEF $$SYSDBG, $$SYSDBG==0 ;ARPSRV, CHASRV shouldn't handle SYSDBG itself
IFNDEF $$CONNECT, $$CONNECT==0 ;Network Connection Routine (ARPCON, CHACON)
IFNDEF $$SIMPLE, $$SIMPLE==0 ;Simple-transaction for Chaosnet
IFNDEF $$ANALYZE, $$ANALYZE==0 ;Network Error Analysis Routine
IFNDEF $$ERRHAN, $$ERRHAN==0 ;Automatic ANALYZE in ARPCON, CHACON, etc.
IFNDEF $$LOGGING, $$LOGGING==0 ;Network library usage logging
IFNDEF $$UPTM, $$UPTM==1 ;ANALYZ should give estimated time up again
IFNDEF $$CVH, $$CVH==0 ;1 to include host number conversions
IFNDEF $$LOOK, $$LOOK==0 ;1 to support no network (just lookups)
IFNDEF $$CHAOS, $$CHAOS==0 ;1 to support Chaosnet hosts and rtns
IFNDEF $$ARPA, $$ARPA==0 ;1 to support Arpanet hosts and rtns
IFNDEF $$TCP, $$TCP==0 ;1 to support /TCP switch & routines
IFN $$TCP*$$SYMLOOK,[
$$ARPA==1 ;arpa must be set for TCP to work here
]
IFNDEF $$ALLNET,[ ; 1 for lookup rtns to support all nets
IFE $$HST3,$$ALLNET==0 ; Including ones ITS doesn't handle.
.ELSE $$ALLNET==$$ARPA
]
IFN $$ARPA,[
IFNDEF ARPHST, .SCALAR ARPHST
]
IFN $$TCP,[
IFNDEF USENCP, .SCALAR USENCP
IFNDEF USETCP, .SCALAR USETCP
]
IFNDEF $$PROMPT, $$PROMPT==1 ;1 to use default prompt "Host: "
IFNDEF $$TCPTO, $$TCPTO==15.*30.
IFNDEF $$CHATO, $$CHATO==15.*30.
;;; Summary of entry-points and calling sequences.
;;; Note that all routines listed here skip-return on success, clobber T and TT.
;;;
;;; SYMGET(E:table_p) => A:symbol_value, B,C,D,E:junk
;;; SYMLOOK(A:input, E:table_p) => B:result_descr, T:numeric_value
;;; HSTMAP(A:page#, B:channel#) => RH(A):next_free_page
;;; HSTUNMAP()
;;; HSTSRC(B:host#) => A:TIP_flag,,name_p, D:site_p
;;; HOSTNM() => A:host#, TT:network#, B,C,D,E:junk
;;; HSTLOOK(A:input) => A:host#, TT:network#, B:result_desc, E:junk
;;; HSTSIX(A:host#) => A:sixbit_host_name
;;; OWNHST(A:network#) => A:host# (address of this machine on that network)
;;; HSTCMP(A:host#,B:host#) => skip iff 2 hosts are the same
;;; NETSRC(B:net#) => A:name_p
;;; ARPICP(A:pin#, B:host#, C:socket#, D:imode,,omode) => clobbers all, opens pin+2,pin+3
;;; ICPASN(A:pin#, B:host#, C:socket#, D:imode,,omode, E:phase#)
;;; ARPSRV(A:pin#, B:socket#, C:imode,,omode) => B:host#, C:sysdbg, A,D:junk, opens pin+2,+3
;;; ARPCON(A:pin#, B:host#, C:frn_socket#, D:async,,mode)
;;; CONFIN(A:pin#, , , D:mode)
;;; CHASRV(A:channel#, C:contact_name_p, D:window_size) => B:host#, C:sysdbg, A,D:junk
;;; CHACON(A:channel#, B:host#, C:contact_name_p, D:window_size)
;;; CHASMP(A:channel#, B:host#, C:request, D:answer)
;;; CHALSN(A:channel#, B:zero_or_host#, C:contact_name_p, D:window_size)
;;; TCPCON(A:channel#, B:host#, C:port#)
;;; TCPSRV(A:channel#, B:port#) => B:host#, C:sysdbg, A,D:junk
;;; ANALYZE(A:channel#) => prints error message, with no CRLF
IFE $$LOOK+$$CHAOS+$$ARPA, .FATAL You have to specify at least one network
IFN $$ERRHAN,$$ANALYZE==1
IFN $$SYMGET,$$SYMLOOK==1
IFN $$HOSTNM,$$HSTMAP==1
IFN $$HSTCMP,$$HSTMAP==1
IFN $$SIMPLE,$$CONNECT==1
DEFINE $$LOG
IFN $$LOGGING!TERMIN
$$LOG,[
IFE ITS, .ERR Sorry the LOGging feature is only supported under ITS
;;; For logging connections. Example: LOG OPEN,[B,C]
DEFINE LOG NETOP,CRUFT
%%ZZ==1
PUSHJ P,[ PUSH P,A
PUSH P,[SIXBIT /NETOP/]
IRP CRUFTY,,[CRUFT]
MOVE A,CRUFTY
PUSH P,A
%%ZZ==%%ZZ+1
TERMIN
MOVEI A,%%ZZ
PUSHJ P,NETWRK"LOGACT
REPEAT %%ZZ, POP P,A
POP P,A
POPJ P, ]
TERMIN
];$$LOG
NE%UNT==:<1_32.> ; Escape bit indicating non-Internet address
IFN $$HST3,[
NW$BYT==:301400 ; Byte pointer to network number (approx!)
NE%STR==:<1_33.> ; Escape bit indicating string-type address
; Useful HOSTS3 full word network # values
NW%CHS==:<NE%UNT+<7_24.>> ; CHAOSNET
NW%ARP==:<10._24.> ; ARPANET
NW%MIL==:<26._24.> ; MILNET
NW%LCS==:<18._24.> ; MIT-LCS (18)
NW%AI==:<20015,,> ; MIT-AI-NET (128.52)
; Corresponds to kludge in HOSTS3 that reduces the size of the network table.
DEFINE GETNET AC,(ADDR)
IFNB [ADDR] MOVE AC,ADDR
TDZ AC,[<1_24.>-1]
TERMIN
IFN 0,[
DEFINE GETNET AC,(ADDR)
IFNB [ADDR] MOVE AC,ADDR
TLNN AC,(17_32.) ; Check for non-Internet type addrs
TLNN AC,(1_31.) ; Internet address, see if class A net
TDZA AC,[77,,-1] ; Unternet or class A, zap low 3 octets
TLNN AC,(1_30.) ; Class B or C, see which.
TRZA AC,177777 ; Class B network, zap low 2 octets
TRZ AC,377 ; Class C net, only zap 1 low octet
TERMIN
] ;IFN 0
] ;$$HST3
.ELSE [ ; HOSTS2 format stuff
NW%CHS==:7 ;Chaos net
NW%ARP==:12 ;Arpa net
NW%LCS==:22 ;LCS net
;NW%DLN==:26 ;Dial net (not supported by these routines)
NW$BYT==:331000 ; Byte pointer to network number
DEFINE GETNET AC,(ADDR)
LDB AC,[NW$BYT,,ADDR]
TERMIN
] ;HOSTS2
IFN $$CHAOS,[
IFNDEF $CPKOP,[
IFN ITS, .INSRT SYSTEM; CHSDEF >
.ELSE .INSRT SYSTEM:CHSDEF
]
]
IFN ITS,[
.CALL==43_33 ;IN CASE OUR .INSRT'ER USES CALRET .CALL MACRO.
DEFINE SYSCAL NAME,ARGS
.CALL [SETZ ? SIXBIT /NAME/ ? ARGS ((SETZ))]
TERMIN
];ITS
POP2J: SUB P,[1,,1] ;Exits used in a few places.
POP1J: SUB P,[1,,1]
CPOPJ: POPJ P,
POPJ1: AOS (P)
POPJ P,
IFNDEF NWLOSS,[ ; SO .INSRT'ER CAN SUBSTITUTE SOMETHING FOR LOSSAGE CHKS
IFN ITS,[
DEFINE NWLOSS
.LOSE
TERMIN
];ITS
IFN TNX,[
DEFINE NWLOSS
HALTF
TERMIN
];TNX
];NWLOSS
IFN $$SYMGET+$$SYMLOOK,[
.SCALAR HSTNMF ;Document these!
.SCALAR NOABRV
.SCALAR NTSPCF
]
IFN $$SYMGET,[
;Interactive symbol readin and lookup.
;
; Call: MOVE E,TABLEP
; PUSHJ P,SYMGET
; error
; value of symbol now in A.
;
;Smashes B, C, D, E, T, TT.
;
; TABLEP should be an aobjn ptr to the table
; of symbols from which user input is to select.
; Num is an arbitrary 18-bit field derived from the table.
; The format of the table is:
; [asciz/prompt string/]
; --> value1,,[asciz/upper-case-symbol-1/]
; value2,,[asciz/upper-case-symbol-2/]
; . . .
; Note that this table is an argument to the SYMGET entry. The
; HOSTNM entry uses the table from the HOSTS3 file, not in the same format.
;
;Subroutines used:
; GETCHR, PUTCHR, SPCHAN (see previous page for call sequences)
;
; GETCHR subroutine to get a character (1 arg)
; PUTCHR subroutine to type a character (1 arg).
; input is echoed/completed through PUTCHR
; SPCHAN if a character other than a letter, a number,
; a hyphen, a period, a space, or a CR is seen,
; SPCHAN is called with the char in T. Variable NUMGOT
; will have value of number read thus far (-1 if none).
; Non-skip return restarts reader, skip return ignores char
; and continues.
;
.VECTOR RCPBUF(6) ;input buffer for this routine
.SCALAR CHRCNT,NUMGOT
;Register Usage
;
;A octal host number accum - scratch, if reading name.
;B decimal host number accum - scratch, if reading name.
;C scratch.
;D byte pointer into input buffer
;E (aobjn) pointer to table
;T character or random data
;TT miscellany
IFN $$PROMPT,[
PROMPT: [ASCIZ /Host: /] ; default prompt
]; IFN $$PROMPT
SYMGET: ;interactive symbol input routine, with completion.
SETZM HSTNMF ;Say we are not using the host names table (it has no prompt string).
HSTNM1: REGO:
SKIPN HSTNMF
SKIPA TT,-1(E) ;prompt
MOVE TT,PROMPT
PUSHJ P,ZTYPE
GO3A: MOVEI D,RCPBUF ;PTR TO SPEC STRING
HRLI D,440700 ;PTR INTO COLLECTED STRING
SETZM CHRCNT ;COUNT OF CHARS IN STRING
SETOM NUMGOT ; Value of number read thus far
GO1: PUSHJ P,GETCHR ;GET INPUT CHARACTER
MOVEI T,^M ;NO CHARS AVAIL SAME AS A CR.
JUMPE T,GO1 ;IGNORE NULLS.
CAIL T,"a"
CAILE T,"z"
CAIA ;NOT LOWER CASE
SUBI T,40 ;CONVERT LOWER CASE TO UPPER
CAIE T,12
CAIN T,15
JRST GOTRM ;E-O-L MEANS USER DONE WITH SPEC.
CAIN T,40
JRST GOTRM0 ;SPACE COMPLETE BUT DON'T TERM
CAIN T,177 ;RUBOUT CAUSES COMPLETE RESTART
JRST [ MOVEI TT,[ASCIZ\?
\] ? PUSHJ P, ZTYPE
JRST REGO ]
CAIE T,"?"
CAIN T,33 ;? OR ALT MEANS LIST ALL POSSIBLE HOSTS,
JRST GOTALT ;GIVEN TYPEIN THUS FAR.
JRST GOTC
BAD1: SUB P,[1,,1]
BAD: MOVEI T,7 ;IF BAD CHAR GIVEN, DING BELL.
GOECH: PUSHJ P,PUTCHR
JRST GO1
;GOT A CHARACTER. IS EITHER SPECIAL OR PART OF A NAME
GOTC: CAIN T,"-" ;BY SPECIAL DISPENSATION, HYPHEN
JRST GOTC00
CAIN T,"." ; Also allow period as part of name
JRST GOTC00
CAIN T,"/" ;SLASH AT THIS LEVEL IS JUST A CHARACTER
JRST GOTC00 ;SYML1 WILL HANDLE HOST/IMP AND ADDRESS/NETWORK-NAME CONSTRUCTS
CAIGE T,"0" ;NUMBERS
JRST SPECL
CAIG T,"9"
JRST GOTC00
CAIGE T,"A" ;LETTERS
JRST SPECL
CAIG T,"Z"
JRST GOTC00
;OTHERWISE SPECIAL CHARACTER, HANDLE IT
SPECL: MOVE TT,A
PUSHJ P,SPCHAN
JRST GO3A ;RESTART FROM THE BEGINNING
JRST GO1 ;IGNORE THIS CHAR
;GOT A CHAR. STORE IF IT PLUS STRING THUS FAR MATCHES A NAME, DON'T STORE IF NOT.
;CHAR (NOT ECHOED YET) IS IN T.
GOTC00: PUSH P,D ;PREPARE TO FLUSH THE CHAR IF IT MAKES AN UNDEF SYMBOL.
IDPB T,D ;STORE CHAR IN STRING, FOLLOWED BY A NULL.
PUSH P,D
SETZ TT,
IDPB TT,D
POP P,D
AOS CHRCNT ;INCREMENT COUNT OF CHARS IN STR.
PUSH P,T
MOVEI A,RCPBUF
PUSHJ P,SYML1 ;SEARCH THE TABLE FOR THIS STRING.
JFCL
CAIGE B,
MOVEM T,NUMGOT ; Store number got thus far.
POP P,T
POP P,TT
JUMPN B,GOECH ;NUMBER, OR SYMBOL FOUND OR AMBIGUOUS => THIS CHARACTER IS OK.
SETZ TT, ;SYMBOL UNDEFINED => ZERO OUT THIS CHAR IN THE STRING
DPB TT,D
MOVE D,TT ;BACK UP POINTER TO END OF STRING
SOS CHRCNT
JRST BAD ;AND COMPLAIN.
;GOT A E-O-L, SEE IF HAVE ENOUGH OF NAME TO RENDER IT UNIQUE.
GOTRM: TDZA C,C ;COMPLETE AND TERMINATE
GOTRM0: SETOM C ;JUST COMPLETE
SKIPG CHRCNT ;HMMM, ANYTHING IN STRING STORED?
JRST BAD ;NO, DING...
MOVEI A,RCPBUF ;ELSE LOOK THE STRING UP.
PUSHJ P,SYML1
JRST BAD ;UNDEFINED OR AMBIGUOUS => LOSE.
MOVE A,T
MOVE TT,B ;NUMBER => OK, AND DON'T TYPE ANYTHING. RETURN NUMBER IN A.
AOJE TT,WIN
HRRZ TT,(B) ;FOUND AND UNAMBIGUOUS. COMPLETE THE NAME IF ABBREVIATED.
SKIPE HSTNMF
ADD TT,HSTADR ;GET POINTER TO THE FULL NAME.
HRLI TT,440700
MOVE A,CHRCNT
ILDB T,TT ;IGNORE AS MANY CHARS AS THE USER ACTUALLY GAVE.
JUMPE T,GOTRM2 ;HANDLE USER ABBREVIATION AND /NET FORMS RIGHT
SOJG A,.-2
GOTRM1: ILDB T,TT
JUMPE T,GOTRM2
IDPB T,D ;AS WE COMPLETE THE NAME, STORE THE CHARS INTO THE ARG
AOS CHRCNT ;SO THAT IF THIS IS A SPACE, THE FOLLOWING CR DOESN'T
PUSHJ P,PUTCHR ;TYPE THE SAME STUFF OUT AGAIN.
JRST GOTRM1
GOTRM2: HLRZ A,(B) ;WIN. RETURN LH. OF TABLE WORD.
SKIPE HSTNMF ;NORMALLY IS SYMBOL VALUE, BUT IF READING HOST NAME, IS FILE-
SETO TT, ;RELATIVE ADDRESS OF SITE TABLE ENTRY, TT NON-ZERO MEANS NOT NUMBER
WIN: JUMPN C,GO1 ;SHOULD TERMINATE? NO => GO READ MORE CHARS.
PUSHJ P,CRLF ;YES, GIVE CRLF
JRST POPJ1 ;AND RETURN WINNING NUMBER IN A
;GOT ? OR ALT, LIST ALL NAMES POSSIBLE AT THIS STAGE.
GOTALT: SKIPN CHRCNT
JRST GO1 ;ALTMODE OR ? AFTER A NUMBER IS A NO-OP.
MOVEI A,RCPBUF
SETOM NOABRV
PUSHJ P,SYMLA ;SEARCH FOR ALL POSSIBLE ALTERNATIVES.
JFCL
TLNN B,-1
HRLS B ;IF ONLY ONE, SET IT UP AS RANGE <ONLY ONE>,,<SAME ONE>.
MOVE TT,B
AOJE TT,GO1 ;IF ARG IS A NUMBER, DON'T TYPE ANYTHING.
PUSHJ P,CRLF
HLRZ A,B ;A POINTS TO FIRST, RH(B) POINTS TO LAST.
GOTAL1: HRRZ TT,(A) ;GET THE ADDR OF THE NEXT POSSIBLE MATCH'S NAME STRING
SKIPE HSTNMF
ADD TT,HSTADR
PUSHJ P,ZTYPE ;TYPE IT.
PUSHJ P,CRLF
ADDI A,1
CAIG A,(B)
JRST GOTAL1
SKIPN HSTNMF ;GIVE PROMPT STRING AGAIN
SKIPA TT,-1(E)
MOVE TT,PROMPT
PUSHJ P,ZTYPE
MOVEI TT,RCPBUF ;FOLLOWED BY THE ARG CHARS WE HAVE SO FAR.
PUSHJ P,ZTYPE
JRST GO1
] ;END IFN $$SYMGET
IFN $$SYMLOOK,[
; SYMLOOK - Non-incremental hostname/hostaddr (symbol) lookup routine
; called by the incremental one.
;Numbers are normally octal, but a "." at the end implies decimal.
;Decimal host slash decimal Imp and any address slash network name are allowed.
; The decimal "octet" form is allowed, right justified.
;In the address slash network-name form, the argument is smashed then restored!
;
; A/ <BP to ASCIZ string> ; Can also be 0,,<addr> or -1,,<addr>
; E/ <AOBJN to table> ; e.g. -tablelen,,table
; Returns .+1 if fail:
; B/ 0 for an undefined sym, or <first>,,<last> for an ambiguous one.
; Returns .+2 if won:
; B/ addr of table entry for symbol we found.
; or -1 if argument was a number; value returned in T.
; Clobbers T, TT.
SYMLOOK:
SETZM HSTNMF
SYML1: SETZM NOABRV
SYMLA: PUSH P,C
PUSH P,D
HLRZ TT,A
SKIPE TT ;If A is an address,
CAIN TT,-1 ;or HRROI-style TWENEX string pointer,
HRLI A,440700 ;then turn into canonical PDP-10 BP
MOVE TT,A
MOVE T,A
ILDB T,T ;First character of string
CAIL T,"0" ;Is the argument a number (starts with a digit)?
CAILE T,"9"
JRST SYML6
SETZB C,D ;Yes => accumulate octal number in C, decimal in D.
SYML7: ILDB T,TT
CAIL T,"0"
CAILE T,"9"
JRST SYML8
IMULI C,10
IMULI D,10.
ADDI C,-"0"(T)
ADDI D,-"0"(T)
JRST SYML7
SYML8: CAIN T,"/"
JRST SYMSL1 ;Digits followed by slash
CAIE T,"." ;Out of digits => "." means use the decimal number
JRST SYML9 ;(else use the octal).
MOVE C,D
ILDB T,TT
CAIN T,"/" ;OK to have both a decimal point and a slash
JRST SYMSL1
JUMPE T,SYML9
CAIL T,"0" ; Another number?
CAILE T,"9"
JRST SYML9
; Aha, have num.num so keep going in this vein.
MOVEI D,-"0"(T) ; Initialize D with 1st digit of 2nd number
SYML41: ILDB T,TT
CAIL T,"0"
CAILE T,"9"
JRST [LSH C,8.
ADDI C,(D)
SETZ D,
CAIN T,"."
JRST SYML41
CAIN T,"/"
JRST SYMSL1
JRST SYML9]
IMULI D,10.
ADDI D,-"0"(T)
JRST SYML41
SYML9: JUMPN T,SYMUND ;Any stray chars after the last digit or the "." => error.
MOVE T,C
SETO B, ;Return the number in T and -1 (=> this is a number) in B.
JRST SYMWIN
SYMSL1: SKIPN HSTNMF ;Slash only magic if hacking hosts
JRST SYML9
ILDB T,TT ;Look at character after slash
CAIL T,"0"
CAILE T,"9"
JRST [ADD TT,[070000,,] ; Back up byte-pointer
PUSHJ P,SYMSL4 ; Process slash network-name.
SETZ T,
JRST SYML9 ]
IFE $$ARPA, JRST SYML9
IFN $$ARPA,[
MOVE C,D ;Number slash number, use decimal
MOVEI D,-"0"(T)
SYMSL2: ILDB T,TT
CAIL T,"0"
CAILE T,"9"
JRST [
IFN $$HST3,[ LSH C,16. ? DPB D,[002000,,C] ; Move HOST over and add IMP
ADD D,[NW%ARP]
MOVE TT,[NW%ARP]
MOVEM TT,NTSPCF
];$$HST3
.ELSE [ DPB D,[112000,,C] ;Deposit IMP number into HOST number
MOVEI D,NW%ARP ;And this is obviously Arpa net
DPB D,[NW$BYT,,C]
];HOSTS2
JRST SYML9 ]
IMULI D,10.
ADDI D,-"0"(T)
JRST SYMSL2
];$$ARPA
;;Subroutine to read network name and set NTSPCF to network number
;; Note if HOSTS3 this is a full-word value.
IFE $$ALLNET,[
SYMSL4: MOVEI D,0
SYMSL5: ILDB T,TT
JUMPE T,SYMSL6
LSH D,6
CAIL T,"a"
SUBI T,40
IORI D,-40(T)
JRST SYMSL5
SYMSL6: IRPS FLAG,,[$$CHAOS $$ARPA $$TCP $$TCP
]NAME,,[CHAOS ARPA TCP NCP
]NUM,,[NW%CHS NW%ARP NW%ARP NW%ARP]
IFN FLAG,[ ;Make sure we claim to support this network
MOVE TT,[SIXBIT \NAME\]
PUSHJ P,SYMSXC
MOVE T,[NUM] ;Prefix -- set it
];FLAG
TERMIN
IFN $$TCP,[
MOVE TT,[SIXBIT \TCP\]
PUSHJ P,SYMSXC
JRST [ SETOM USETCP
SETZM USENCP
JRST .+1]
MOVE TT,[SIXBIT \NCP\]
PUSHJ P,SYMSXC
JRST [ SETOM USENCP
SETZM USETCP
JRST .+1]
]
JUMPE T,[POP P,T ? JRST SYMUND] ;Unknown network name, barf
MOVEM T,NTSPCF
POPJ P,
;; Compares sixbit arg in D with sixbit Network name in TT.
;; Returns .+1 if arg is prefix of net name
;; .+2 otherwise
SYMSXC: PUSH P,D
JUMPE D,SYMSX1 ; Don't loop forever if arg is 0
TLNN D,770000 ; Shift until high byte is non-zero
JRST [ LSH D,6 ? JRST .-1 ]
TRNN D,77 ; Shift both until low char non-zero
JRST [ LSH D,-6 ? LSH TT,-6 ? JRST .-1 ]
CAMN D,TT
CAIN D,0
SYMSX1: AOS -1(P)
POP P,D
POPJ P,
];$$ALLNET
IFN $$ALLNET,[
;; Like SYMCMP, but user's string needn't start on word boundary.
;; Compare strings, address of one in T, Byte Pointer to another in C.
;; Smash T, TT, but NOT A, B, C, or D
SYMCMC: PUSH P,C
PUSH P,D
PUSHJ P,SYMCM0 ;Do comparison w/o setting up C
CAIA
AOS -2(P) ; Success, skip return
POP P,D
POP P,C
POPJ P,
SYMSL4: PUSH P,C
MOVE C,TT ;ptr to string
MOVE T,HSTADR
ADD T,NETPTR(T) ;Ptr to network tables
MOVN D,(T) ;Count of networks
HRLZS D ;Prepare AOBJN ptr
HRRI D,2(T) ;Ptr to first network
SYSL4A: HLRZ T,NTLNAM(D) ;Ptr to host string
ADD T,HSTADR
PUSHJ P,SYMCMC ;Is this the network we were given?
JRST SYSL4B ; Nope, try next
MOVE T,NETNUM(D) ;Get the network number
MOVEM T,NTSPCF ;Remember that we specified it
POP P,C
POPJ P,
SYSL4B: MOVE T,HSTADR ;Find start of NETWORK table
ADD T,NETPTR(T)
ADD D,1(T) ;2nd word is size of entries
ADD D,[1,,0] ;Update the counter
JUMPL D,SYSL4A ;Try next match
POP P,C
POP P,(P)
JRST SYMUND ;Else fail.
]; $$ALLNET
;Here to start processing an arg which is not a number.
SYML6: MOVE B,E
ILDB T,TT ;Check for slash and network name
JUMPE T,SYML2 ;None found
CAIE T,"/"
JRST SYML6
MOVEI T,0 ;Ugh, barf, clobber the argument
DPB T,TT
PUSH P,TT
PUSHJ P,SYMLA ;Go do that
JRST [ POP P,TT ? MOVEI T,"/" ? DPB T,TT ? JRST SYMLZ] ;Lost, propagate, fixing arg
POP P,TT ;Note, recursive call didn't return anything in T
MOVEI T,"/" ; since this wasn't a number
DPB T,TT ;Fix argument
PUSH P,TT ;Don't barf at / with nothing after it yet
ILDB T,TT
POP P,TT
CAIE T,0
PUSHJ P,SYMSL4 ;Process network-name argument
JRST SYMWIN ;And take success return
SYML2: HRRZ T,(B) ;Get the next symbol's name from the table.
SKIPE HSTNMF
ADD T,HSTADR
PUSHJ P,SYMCMP ;Does the argument in A abbreviate it?
CAIA
JRST SYML3 ;Yes, we have found the first match.
AOBJN B,SYML2
SYMUND: SETZ B, ;There is no match. Return 0.
JRST SYMLZ
SYML3: PUSH P,B ;Remember where the first match is, and find the last.
SYML4: AOBJP B,SYML5
HRRZ T,(B) ;Get the next symbol's name from the table.
SKIPE HSTNMF
ADD T,HSTADR
PUSHJ P,SYMCMP ;Does the argument in A abbreviate it?
JRST SYML5 ;No => we have gone past the last match.
JRST SYML4
SYML5: SUB B,[1,,1] ;B points at last match.
CAMN B,(P) ;Last and first match are the same table entry?
JRST SYMLW ;Then that one is the value.
MOVE TT,(P)
PUSH P,A
HLLZ A,(B)
SYML5A: HLLZ T,(TT)
CAME T,A
JRST SYML5B
CAME TT,B
AOBJN TT,SYML5A ;If all names have the same value, then just
MOVEM B,-1(P) ;return the last name, e.g. for XEROX.ARPA
JRST SYMLW1 ;and XEROX.COM, return XEROX.COM
SYML5B: MOVE A,-1(P) ;A gets the symbol name of the first match
HRRZ A,(A)
SKIPE HSTNMF
ADD A,HSTADR
HRLI A,440700
HRRZ T,(B)
SKIPE HSTNMF ;and T gets the name of the last match.
ADD T,HSTADR
SKIPN NOABRV ;If processing "BBN?", show all names starting with BBN
;even though "BBN" by itself is a valid name.
PUSHJ P,SYMCMP ;if the first match is an abbreviation of the last,
JRST SYMLL
SYMLW1: POP P,A ;then it's no ambiguity; the first wins.
SYMLW: POP P,B
ANDI B,-1
SYMWIN: POP P,D
POP P,C
JRST POPJ1
SYMLL: POP P,A ;Here if argument is really ambiguous.
HRL B,(P) ;produce 1st match addr,,last match addr.
SUB P,[1,,1]
SYMLZ: POP P,D
POP P,C
POPJ P,
;Compare the ASCIZ string <- A with the one <- T.
;Skip if the one in A is an initial segment of the one in T.
;We clobber C, D, T and TT but NOT A.
SYMCMP: MOVE C,A
; HRLI C,440700 ;Already a BP now.
SYMCM0: HRLI T,440700
SYMCM1: ILDB TT,T
ILDB D,C
JUMPE D,POPJ1 ;1st string ended and no mismatch => win.
CAIL D,140
SUBI D,40 ;Ignore case in the string in A. Assume string in T is all upper.
CAME D,TT
POPJ P, ;mismatch => lose.
JRST SYMCM1
IFE $$HSTMAP,.SCALAR HSTADR
] ;end IFN $$SYMLOOK
IFN $$HSTMAP,[
.SCALAR HSTADR ;Address of HOSTS3 file is stored here.
.SCALAR HSTABN ; AOBJN page pointer to HOSTS3
;The format of the compiled HOSTS3 file is:
; NOTE THIS IS NOT COMPLETELY ACCURATE. See the file
; AI:SYSNET;HOSTS3 > for an uptodate description.
HSTSID==:0 ; wd 0 SIXBIT /HOSTS3/
HSTFN1==:1 ; wd 1 SIXBIT /HOSTS/ usually
HSTVRS==:2 ; wd 2 FN2 of HOSTS file which this was compiled from.
HSTDIR==:3 ; wd 3 SIXBIT /SYSENG/ usually, directory name of source file
HSTMCH==:4 ; wd 4 SIXBIT /AI/ (e.g.), device name of source file
HSTWHO==:5 ; wd 5 UNAME of person who compiled this
HSTDAT==:6 ; wd 6 Date of compilation as sixbit YYMMDD
HSTTIM==:7 ; wd 7 Time of compilation as sixbit HHMMSS
NAMPTR==:10 ; wd 10 Address in file of NAME table.
SITPTR==:11 ; wd 11 Address in file of SITE table.
NETPTR==:12 ; wd 12 Address in file of NETWORK table.
;....expandable....
;NETWORK table
; wd 0 Number of entries in table.
; wd 1 Number of words per entry. (2)
;This table contains one entry for each network known about, sorted
;by network number. A network number is bits 4.8-4.1 of a network
;address; these numbers are assigned by Jon Postel. See symbols below.
;The reason for keeping track of different networks is that the user
;program must make different system calls to use each network.
;Each entry contains:
NETNUM==:0 ; wd 0 network number
NTLNAM==:1 ; wd 1 LH - address in file of name of network
NTRTAB==:1 ; wd 1 RH - address in file of network's address table
;ADDRESS table(s)
; wd 0 Number of entries in table.
; wd 1 Number of words per entry. (2)
;There is one of these tables for each network. It contains entries
;for each site attached to that network, sorted by network address.
;These tables are used to convert a numeric address into a host name.
;Also, the list of network addresses for a site is stored
;within these tables.
;Each entry contains:
ADDADR==:0 ; wd 0 Network address of this entry (including network number).
ADLSIT==:1 ; wd 1 LH - address in file of SITE table entry
ADRCDR==:1 ; wd 1 RH - address in file of next ADDRESS entry for this site
; 0 = end of list
ADRSVC==:2 ; wd 2 RH - fileaddr of services list for this address
; 0 none, else points to SERVICE node of format
SVLCNT==:0 ; <# wds>,,<fileaddr of next, or 0>
SVRCDR==:0
SVLFLG==:1 ; <flags>,,<fileaddr of svc name>
SVRNAM==:1
SVCARG==:2 ; Possible additional parameters
;SITE table
; wd 0 Number of entries in table.
; wd 1 Number of words per entry. (3)
;This table contains entries for each network site,
;not sorted by anything in particular. A site can have more
;than one network address, usually on different networks.
;This is the main, central table.
;Each entry looks like:
STLNAM==:0 ; wd 0 LH - address in file of official host name
STRADR==:0 ; wd 0 RH - address in file of first ADDRESS table entry for this
; site. Successive entries are threaded together
; through ADRCDR.
STLSYS==:1 ; wd 1 LH - address in file of system name (ITS, TIP, TENEX, etc.)
; May be 0 => not known.
STRMCH==:1 ; wd 1 RH - address in file of machine name (PDP10, etc.)
; May be 0 => not known.
STLFLG==:2 ; wd 2 LH - flags:
STFSRV==:400000 ; 4.9 1 => server site (according to NIC)
STFGWY==:200000 ; 4.8 1 => Internet gateway site
; wd 2 RH - not used
;NAMES table:
; wd 0 Number of entries
; wd 1 Number of words per entry. (1)
;This table is used to convert host names into network addresses.
; Followed by entries, sorted by the host name treated as a vector of
; signed integers, looking like:
NMLSIT==:0 ; lh address in file of SITE table entry for this host.
NMRNAM==:0 ; rh address in file of host name
;This name is official if NMRNAM = STLNAM of NMLSIT.
; All names are ASCIZ strings, all letters upper case.
; The strings are stored before, after and between the tables.
; All strings are word-aligned, and fully zero-filled in the last word.
;Network addresses are defined as follows, for purposes of this table:
; 4.9 0
; 4.8-4.1 network number
; Chaos net (number 7):
; 3.9-2.8 0
; 2.7-1.1 address (2.7-1.9 subnet, 1.8-1.1 host)
; Arpa net (number 12): (note, old-format Arpanet addresses
; 3.9-3.8 0 never appear in the host table.)
; 3.7-2.1 Imp
; 1.9 0
; 1.8-1.1 Host
;Map the host table file SYSBIN;HOSTS3 > into core.
;A should contain the page number to start it at.
;B should contain the channel number to use.
;We skip if we succeed, returning in RH(A) the number of the first page not used up.
HSTMAP:
IFN ITS,[
SYSCAL OPEN,[ B ? 5000,,.BII ? ['DSK',,]
IFN $$HST3, ['HOSTS3']
.ELSE ['HOSTS2']
[SIXBIT />/] ? ['SYSBIN']]
POPJ P,
SYSCAL FILLEN,[B ? 2000,,T]
POPJ P,
JUMPLE T,CPOPJ
MOVEI T,1777(T) ;(round up)
LSH T,-10.
PUSH P,A
LSH A,10.
MOVEM A,HSTADR ;Save in HSTADR the address where we are mapping the file.
POP P,A
MOVNS T ;form AOBJN page ptr for CORBLK
HRL A,T
MOVEM A,HSTABN ; save AOBJN for unmapping
SYSCAL CORBLK,[ 1000,,%CBNDR ;Read-Only.
1000,,%JSELF ;into self
A ;as specified
B] ;from file open on channel.
POPJ P,
SYSCAL CLOSE,B
POPJ P,
MOVE T,HSTADR
];ITS
IFN TNX,[
.SCALAR HSTJFN
.SCALAR HSTLEN
PUSH P,1 ? PUSH P,2 ? PUSH P,3
PUSH P,A
MOVSI 1,(GJ%SHT\GJ%OLD)
IFN 20X,[
IFN $$HST3,HRROI 2,[ASCIZ "SYSTEM:HOSTS3.BIN"]
.ELSE HRROI 2,[ASCIZ "SYSTEM:HOSTS2.BIN"]
] ;20X
IFN 10X,[
IFN $$HST3,HRROI 2,[ASCIZ "<SYSTEM>HOSTS3.BIN"]
.ELSE HRROI 2,[ASCIZ "<SYSTEM>HOSTS2.BIN"]
] ;10X
GTJFN
JRST HSTMP7 ; Failed, restore regs.
MOVEM 1,HSTJFN
MOVE 2,[70000,,OF%RD]
OPENF
JRST [MOVE 1,HSTJFN
RLJFN
NOP
JRST HSTMP7]
MOVE 2,[1,,.FBBYV]
MOVEI 3,T
GTFDB ;XXX,,#PAGES
HRRZM T,HSTLEN
HRLZ 1,HSTJFN ;JFN,,FILE PAGE 0
HRRZ 2,(P) ;PAGE NUMBER WITHIN US (saved on stack)
HRLI 2,.FHSLF
HRRZ 3,T
TLO 3,(PM%CNT\PM%RD)
PMAP
IFN 10X,[
TRNE 3,-1 ; Counted out yet?
JRST [ HRRI 3,-1(3) ; Bump count down by 1
TRNE 3,400000 ; and stop if done (count -1)
JRST .+1
ADDI 1,1 ; Increment # of file page
AOJA 2,.-1] ; and # of process page... then repeat PMAP.
] ;10X
POP P,A
POP P,3 ? POP P,2 ? POP P,1
MOVE T,A
IMULI T,1000
MOVEM T,HSTADR
];TNX
MOVE T,HSTSID(T) ;CHECK THAT FIRST WORD OF FILE IS REALLY HOSTS3
IFN $$HST3,CAME T,[SIXBIT /HOSTS3/]
.ELSE CAME T,[SIXBIT/HOSTS2/]
POPJ P,
JRST POPJ1
IFN TNX,[
HSTMP7: POP P,A
POP P,3 ? POP P,2 ? POP P,1
POPJ P,
] ;TNX
; UNMAP HOSTS3.
HSTUNMAP:
SKIPN HSTADR
POPJ P,
IFN ITS,[
MOVE T,HSTABN ; AOBJN PAGE POINTER TO HOSTS3
SYSCAL CORBLK,[ 1000,,0 ; DELETE
1000,,%JSELF ; FROM SELF
T ]
JFCL
];ITS
IFN TNX,[
PUSH P,1 ? PUSH P,2 ? PUSH P,3
SETO 1,
MOVE 2,HSTADR
IDIVI 2,1000 ;PAGE#
HRLI 2,.FHSLF
MOVE 3,HSTLEN
TLO 3,(PM%CNT)
PMAP
IFN 10X,[
TRNE 3,-1 ; Counted out yet?
JRST [ HRRI 3,-1(3) ; Bump count down by 1
TRNE 3,400000 ; and stop if done (count -1)
JRST .+1
AOJA 2,.-1] ; Bump # of process page... then repeat PMAP.
] ;10X
POP P,3 ? POP P,2 ? POP P,1
];TNX
SETZM HSTADR
JRST POPJ1
;Given host number in B, return its host name addr in rh(A) and set sign of A
;if the host is a Tip. Skip if successful. No skip => unknown host.
;We also return in D the address of the SITES table entry for the host.
HSTSRC: MOVE A,B
PUSHJ P,STDHST
MOVE B,A
SKIPN HSTADR ;Fail if the HOSTS3 file isn't loaded.
POPJ P,
PUSH P,C
PUSH P,E
PUSH P,T
GETNET C,B ; Get network number
MOVE D,HSTADR
ADD D,NETPTR(D) ;get address of NETWORKS table.
MOVE TT,0(D) ;get # of entries,
MOVE T,1(D) ;and entry size.
ADDI D,2 ;point at first entry.
HSTSR1: CAMN C,NETNUM(D) ;Find appropriate network
JRST HSTSR2
ADD D,T
SOJG TT,HSTSR1 ;no => look at next entry.
HSTSRX: POP P,T ;unknown network => return non-skipping.
POP P,E
POP P,C
POPJ P,
HSTSR2: HRRZ D,NTRTAB(D) ;Get address of ADDRESS table for that network
ADD D,HSTADR ;Binary-search it
MOVE C,1(D) ;Words per entry
MOVE E,0(D) ;Number of entries in table
MOVEI D,2(D) ;Base address of table
PUSH P,D
HSTSR3: CAIG E,1
JRST HSTSR4 ;Search narrowed down to one location
MOVE T,E
LSH T,-1
MOVE TT,T ;Number of entries in bottom "half" of table
IMUL T,C
ADD T,D ;Probe point
CAMGE B,ADDADR(T)
JRST [ MOVE E,TT ;Move down
JRST HSTSR3 ]
MOVE D,T ;Move up
SUB E,TT
JRST HSTSR3
HSTSR4: POP P,T ; Recover base addr of table
CAME B,ADDADR(D) ; Did we get any match at all?
JRST HSTSRX ; Nope, take non-skip return.
HSTSR5: SUBI D,(C) ; Found one! Back up to find 1st match
CAIGE D,(T) ; Make sure we don't back up past beg
JRST HSTSR6
CAMN B,ADDADR(D) ; As long as we still get a match,
JRST HSTSR5 ; keep backing up.
HSTSR6: ADDI D,(C) ; Recover from backup.
MOVEI E,(D) ; Save ptr to ADDRESS table
HLRZ D,ADLSIT(D) ; Get address of SITES table entry
ADD D,HSTADR
MOVE A,STLFLG ; Check flags
TLNE A,STFGWY ; to see if this one is a gateway.
JRST [ ADDI E,(C) ; Ugh, gateway. Try to skip it.
CAME B,ADDADR(E)
JRST .+1 ; No good, stuck with this one.
JRST HSTSR6] ; Hurray, try next entry!
HLRZ A,STLNAM(D) ;found the host => get the addr of its name
ADD A,HSTADR ;in our address space.
HLRZ C,STLSYS(D)
ADD C,HSTADR ;also get addr of its system type name
MOVE C,(C)
CAME C,[ASCIZ /TAC/] ;If it's a TAC,
CAMN C,[ASCIZ /TIP/] ; Or a TIP,
TLO A,400000 ; set sign bit of A.
AOS -3(P) ;Take skip return
JRST HSTSRX
] ;END $$HSTMAP
IFN $$NETSRC,[
;;; NETSRC(B:net#) => A:name_p
;;; Convert a network number to a network name
NETSRC: SKIPN HSTADR ;Fail if the HOSTS3 file isn't loaded.
POPJ P,
PUSH P,C
PUSH P,D
MOVE D,HSTADR
ADD D,NETPTR(D) ;get address of NETWORKS table.
MOVE TT,0(D) ;get # of entries,
MOVE T,1(D) ;and entry size.
ADDI D,2 ;point at first entry.
NETSR1: CAMN B,NETNUM(D) ;Find appropriate network
JRST NETSR2
ADD D,T
SOJG TT,NETSR1 ;no => look at next entry.
POP P,D ;unknown network => return non-skipping.
POP P,C
POPJ P,
NETSR2: HLRZ A,NTLNAM(D) ;Get address of name of network
ADD A,HSTADR
POP P,D ;unknown network => return non-skipping.
POP P,C
JRST POPJ1
];END $$NETSRC
IFN $$SYMGET*$$HOSTNM,[
;Read in a host name. Works like SYMGET but searches host database.
;We return in A the number of the host, network# in TT.
HOSTNM: ;Host name reader
PUSHJ P,HSTTBP ;E gets aobjn ptr to NAMES table, and set HSTNMF,NTSPCF
PUSHJ P,HSTNM1 ;Do an interactive symbol table lookup.
POPJ P, ;Failed
;TT=0 => A has a number
;else => A has file-relative address of SITE table entry
JUMPE TT,HOSTN1
;JRST HOSTN2
];$$SYMGET*$$HOSTNM
IFN <$$SYMGET*$$HOSTNM>+<$$SYMLOOK*$$HOSTNM>,[
;Code to process result of Host-name lookup, returning full address in A
;with network number extracted into TT.
;Address was supplied, file-relative pointer to SITES table entry in A.
HOSTN2: ADD A,HSTADR
SKIPGE TT,NTSPCF ;Explicitly-specified network?
JRST HOSTN4 ;No, try all nets we know about
HOSTN3: HRRZ E,STRADR(A) ;Find an address for SITE in A on network in TT
HSTN3A: ADD E,HSTADR
GETNET T,ADDADR(E)
CAMN T,TT
JRST [ MOVE A,ADDADR(E) ;This is it
JRST POPJ1 ]
HRRZ E,ADRCDR(E)
JUMPN E,HSTN3A ;Try site's next address
POPJ P, ;Not found
HOSTN4: ;Find a network address for this site
IFN $$CHAOS,[ ;Chaos net is preferred, try it first
MOVE TT,[NW%CHS]
PUSHJ P,HOSTN3
CAIA
JRST POPJ1
HOSTN5:
];$$CHAOS
IFN $$ARPA,[
MOVE TT,[NW%ARP]
PUSHJ P,HOSTN3
CAIA
JRST POPJ1
HOSTN6:
];$$ARPA
IFE $$ALLNET,[
POPJ P, ;Host exists, but not on any network we know about
]; $$ALLNET
IFN $$ALLNET,[
HRRZ E,STRADR(A)
JUMPE E,CPOPJ ;No addresses for this site?
ADD E,HSTADR ;where ADDRESS entry is in core
MOVE A,ADDADR(E) ;A J-random Host Address (some random net)
GETNET TT,A ; Extract the network number
JRST POPJ1 ;Success
]; $$ALLNET
;Number was supplied, it is in A. Determine what network it is on.
HOSTN1:
IFE $$ALLNET,[
GETNET TT,A ;Maybe net was specified explicitly as part of number
JUMPN TT,[ ;Yes, make sure is on a network we know about
IRPS FLAG,,[$$CHAOS $$ARPA]NUM,,[NW%CHS NW%ARP]
IFN FLAG,[ CAMN TT,[NUM]
JRST POPJ1
];FLAG
TERMIN
POPJ P, ] ;Can't find it
]; $$ALLNET
SKIPGE TT,NTSPCF ;Maybe network was specified by name
JRST [ PUSHJ P,STDHST ; Not specified, return standardized number.
JRST POPJ1]
IFN $$HST3, IOR A,TT
.ELSE DPB TT,[NW$BYT,,A]
JRST POPJ1
];<$$SYMGET*$$HOSTNM>+<$$SYMLOOK*$$HOSTNM>
IFN $$SYMLOOK*$$HOSTNM,[
;HSTLOOK takes args like SYMLOOK and looks in the HOSTS3 NAMES table.
;It returns the same things that HOSTNM returns. It clobbers E, T, TT.
;Also returns in B a pointer like SYMLOOK, or zero if no name lookup won.
HSTLOOK:
PUSHJ P,HSTTBP ;E gets aobjn ptr to NAMES table, and set HSTNMF,NTSPCF
PUSHJ P,SYML1 ;Do a non-interactive symbol table search.
POPJ P,
MOVE A,T ;If the input was a number
AOJE B,HOSTN1 ;go canonicalize it
HLRZ A,NMLSIT-1(B) ;Else B points at a NAMES table word, so get
SOJA B,HOSTN2 ;the SITE table entry address, go find appropriate net address
];$$SYMLOOK*$$HOSTNM
IFN <$$SYMGET\$$SYMLOOK>*$$HOSTNM,[
;Put in E an aobjn pointer to the HOSTS3 file's NAMES table. Also set HSTNMF.
HSTTBP: SKIPN E,HSTADR
NWLOSS
ADD E,NAMPTR(E) ;Address of NAMES table
MOVE T,1(E) ;Make sure words per entry is 1
CAIE T,1
NWLOSS
MOVN T,0(E) ;Negative number of entries
HRL E,T
ADDI E,2 ;E now has an aobjn pointer to the NAMES table.
SETOM HSTNMF ;Say that each address needs HSTADR added to it.
SETOM NTSPCF ;Say that no network explicitly specified
POPJ P,
];<$$SYMGET\$$SYMLOOK>*$$HOSTNM
IFN $$SYMGET+$$ANALYZE,[
;TYPE A CRLF. CLOBBER T.
CRLF: MOVEI T,15
PUSHJ P,PUTCHR
MOVEI T,12
PUSHJ P,PUTCHR
POPJ P,
;TYPE ASCIZ STRING POINTED TO BY TT, CLOBBER T.
ZTYPE:
IFN ITS,[
HRLI TT,440700
ZTYPE0: ILDB T,TT
JUMPE T,CPOPJ
PUSHJ P,PUTCHR
JRST ZTYPE0
];ITS
IFN TNX,[
PUSH P,1
HRRO 1,TT
PSOUT
POP P,1
RETURN
];TNX
];$$SYMGET+$$ANALYZE
IFN $$HSTSIX,[
;Given a host number in A, returns a sixbit abbreviation of
;the name of the host, also in A. Clobbers only T and TT.
;You better call HSTMAP before this.
;Always skip returns.
HSTSIX: PUSH P,B
PUSHJ P,STDHST
PUSH P,C
PUSH P,D
PUSH P,E
MOVE B,A
PUSHJ P,HSTSRC ;Find the SITES table entry for this host.
JRST HSTSX9 ;none => unknown host. Use HSTnnn.
SUB D,HSTADR ;D gets addr of SITES table entry relative to file
MOVE B,HSTADR ;(for comparison with LH's of NAMES table words).
ADD B,NAMPTR(B) ;Get address of NAMES table.
MOVE T,1(B) ;Make sure 1 word per entry
CAIE T,1
NWLOSS
MOVE T,0(B) ;T gets number of entries in the table.
SETOB C,E ;E will get the address of the
; longest name shorter than 7 chars, C its length.
HRRZ TT,A ;Check out the official name first
AOJA B,HSTSX0
HSTSX1: ADDI B,1 ;B points at next untried NAMES table entry.
HLRZ TT,NMLSIT(B)
CAME TT,D ;Does this name name the host we are serving?
JRST HSTSX4
HRRZ TT,NMRNAM(B) ;If so, how long is this name?
ADD TT,HSTADR
HSTSX0: HRLI TT,440700
PUSH P,TT
PUSH P,TT
SETZ A,
HSTSX2: ILDB TT,(P)
JUMPE TT,HSTSX3
AOJA A,HSTSX2
HSTSX3: POP P,TT ;Flush garbage
IFN $$MIT,[
MOVE TT,@(P) ;First word of name
TRZ TT,377
CAMN TT,[ASCII/MIT-/]
CAIG A,6 ;Strip off "MIT-" if longer than 6 characters
JRST .+4
SUBI A,4
MOVSI TT,100700
HLLM TT,(P)
];$$MIT
POP P,TT ;Restore pointer to name
CAIG A,6 ;Fit in 6 characters?
CAMG A,C ;and longer than the previous one?
JRST HSTSX4
MOVE E,TT ;Yes, save its name's address.
MOVE C,A ;and the length of that one
HSTSX4: SOJG T,HSTSX1 ;look at all the names in the table.
AOJN E,HSTSX5 ;Jump if found a reasonable name
ADD D,HSTADR ;No short name, truncate official one
MOVEI C,"-" ;Also, will remove hyphens from it
HLRZ E,STLNAM(D)
ADD E,HSTADR ;Pointer to name
IFN $$MIT,[
MOVE A,(E)
TRZ A,377
CAMN A,[ASCII/MIT-/]
JRST [ HRLI E,100700
AOJA E,HSTSX5 ]
];$$MIT
TLOA E,440700
HSTSX5: SUBI E,1
MOVE B,E ;Get BP to name string.
;B has a B.P. to the name string we are going to use.
;C has "- if we should remove all hyphens from it, otherwise C has a number from 1 to 6.
;Convert the name string to SIXBIT in A.
MOVE D,[440600,,A]
SETZ A, ;Convert name to SIXBIT word in A
HSTSX6: ILDB T,B
JUMPE T,HSTSX7 ;Stop if name string runs out (nice, it all fits).
CAMN T,C ;Remove hyphens if requested to
JRST HSTSX6 ;Note C has number from 1 to 6 or "-
SUBI T,40
IDPB T,D
TLNE D,770000 ;Stop after getting one full word.
JRST HSTSX6
HSTSX7: LDB T,D ;If last character is a hyphen, flush it.
CAIN T,'-'
MOVEI T,0
DPB T,D
HSTSX8: POP P,E
POP P,D
POP P,C
POP P,B
JRST POPJ1
;Have to do it numerically. Depends on network.
HSTSX9:
MOVSI A,'NET'
GETNET TT,B
CAMN TT,[NW%CHS]
MOVSI A,'CHS'
CAMN TT,[NW%ARP]
JRST [ MOVSI A,'HST'
IFN $$HST3, LDB T,[002000,,B] ; IMP
.ELSE LDB T,[112000,,B] ;Imp
CAIGE T,100
TRNN B,774
JRST .+1 ;Doesn't fit in old-style
IFN $$HST3, LSH B,-16.
ANDI B,3
LSH B,6 ;Host
DPB T,[000600,,B] ;Convert to old-style
JRST .+1 ]
HRRI A,'000' ;If host number less than 3 digits, pad with zeroes
IFE $$HST3, TLZ B,(.BM (NW$BYT)) ;Host number within network
SETZB T,TT ;T gets sixbit, TT gets char mask
PUSHJ P,HSTS9A
ANDCM A,TT ;Clear characters from A to be clobbered from T
IOR A,T ;Bring in number
JRST HSTSX8
HSTS9A: IDIVI B,8
HRLM C,(P)
SKIPE B
PUSHJ P,HSTS9A
HLRZ C,(P)
LSH T,6
IORI T,'0'(C)
LSH TT,6
IORI TT,77
POPJ P,
];$$HSTSIX
;;; Standardize host number in A. Clobber T.
;;; No skip-return
STDHST:
IFN $$HST3, JRST CVH3NA
.ELSE [
TLNE A,777000 ;Network number specified?
JRST STDHS1 ;Yes, OK
IFN $$ARPA, TLO A,NW%ARP_9 ;No, default to some net we know about
.ELSE IFN $$CHAOS, TLO A,NW%CHS_9
STDHS1:
IFN $$ARPA,[
LDB T,[NW$BYT,,A] ;If Arpanet, standardize to new format
CAIN T,NW%ARP
TDNE A,[177777000]
POPJ P,
LDB T,[000600,,A] ;Imp
LDB A,[060200,,A] ;Host
DPB T,[112000,,A]
TLO A,NW%ARP_9
];$$ARPA
POPJ P,
] ;HOSTS2
IFN $$OWNHST+<$$SYMGET*$$HOSTNM>+<$$SYMLOOK*$$HOSTNM>,[
;;; GIVEN A NETWORK NUMBER IN A (WHICH MUST BE A NETWORK THIS PROGRAM IS
;;; CONDITIONALLY ASSEMBLED TO SUPPORT), RETURN THIS MACHINE'S OWN
;;; ADDRESS ON THAT NETWORK, IN A. CLOBBER T. SKIPS UNLESS HOST NOT ON THAT NET.
OWNHST:
IFN $$ARPA,[
CAME A,[NW%ARP]
JRST OWNHS1
IFN ITS,[
SYSCAL NETHST,[MOVEI -1 ? MOVEM A ? MOVEM A] ;GET OWN ARPANET ADDRESS
POPJ P, ;MUST NOT BE ON ARPANET
PUSHJ P,STDHST ;SYSTEM DOESN'T RETURN NUMBER IN STANDARD FORMAT
JRST POPJ1
];ITS
IFN TNX,[
PUSH P,A
PUSH P,1 ? PUSH P,2 ? PUSH P,3 ? PUSH P,4
MOVEI 1,.GTHSZ
GTHST
CAIA
AOS -5(P) ; Take skip return!
MOVEM 4,-4(P) ; Store result into what will be put in A
POP P,4 ? POP P,3 ? POP P,2 ? POP P,1
POP P,A ;ALREADY IN INTERNET FORMAT
];TNX
OWNHS1:
];$$ARPA
IFN $$CHAOS,[
CAME A,[NW%CHS]
JRST OWNHS2
IFN ITS,[
MOVE A,[SQUOZE 0,MYCHAD]
.EVAL A,
POPJ P, ;MUST NOT BE ON CHAOS NET
];ITS
IFN TNX,[
PUSH P,A
PUSH P,1 ? PUSH P,2
MOVE 1,[SIXBIT "CHSTAT"]
SYSGT
HRR 1,2 ;TABLE#
HRLI 1,2 ;WORD#2,,TABLE#
GETAB
JRST [POP P,2 ? POP P,1
POP P,A ? POPJ P,]
MOVEM 1,-2(P)
POP P,2 ? POP P,1
POP P,A
];TNX
IFN $$HST3, IOR A,[NW%CHS]
.ELSE TLO A,NW%CHS_9
JRST POPJ1
OWNHS2:
];$$CHAOS
POPJ P, ;Some network I don't know about
];$$OWNHST+<$$SYMGET*$$HOSTNM>+<$$SYMLOOK*$$HOSTNM>
;;; Routine to compare two hosts
IFN $$HSTCMP,[
;; Take host #'s in A and B, and skip if they refer to the same host.
;; Clobber no AC'S
;;
;;CALL: MOVE A,[HOST]
;; MOVE B,[HOST]
;; PUSHJ P,HSTCMP
;; different or error (unknown host or unmapped HOSTS3 table)
;; same
HSTCMP: CAMN A,B ;Trivial case
JRST POPJ1
PUSH P,A ;Clobber no AC's
PUSH P,B
PUSH P,T
PUSH P,D
PUSH P,D ;Get's SITE table entry
PUSHJ P,HSTSRC ;Check this one out
JRST HSTCM9 ; Non-existant or not mapped
MOVEM D,(P) ;Remember this site table entry
MOVE B,-4(P) ;Get the other host #
PUSHJ P,HSTSRC ;and look up it's SITE table entry
JRST HSTCM9
MOVE T,(P) ;Recover the first SITE table entry
CAMN T,D ;Compare the two entry pointers
AOS -5(P) ; The same!
HSTCM9: POP P,D
POP P,D
POP P,T
POP P,B
POP P,A
POPJ P,
];$$HSTCMP
;;; Arpanet connection routines
IFN $$ARPA*ITS,[
IFN $$ICP,[
$$CONNECT==1 ;necessary subroutine
; ARPA NETWORK ICP ROUTINE
;
;Call: MOVEI A,pin ;first of group of 3 channels to use (nonconsecutively numbered)
; ;PIN itself is used only for the ICP. PIN+1 is unused.
; ;PIN+2 and PIN+3 are the in and out sides of the TELNET connection.
; MOVEI B,host ;host number to connect to
; MOVEI C,frnsoc ;foreign socket number to icp through
; MOVE D,[imode,,omode] ;input and output modes as in OPEN on NET device.
; PUSHJ P,NETWRK"ARPICP ;do it. Clobbers A,B,C,D,E,T,TT.
; failed ;A holds the channel which lost. If $$ERRHAN, ANALYZ was called.
; succeeded
ARPICP: MOVEI E,0 ;synchronous mode
ICPPHS: PUSHJ P,ICP1 ;This is also the phase table
PUSHJ P,ICP2
PUSHJ P,ICP3
JRST POPJ1
ICPASN: ;asynchronous mode. Same args except E is phase (initially 1).
SKIPL E ;keep calling back with same ACs as returned, until E is zero.
HRREI E,-3 ;asynchronous init
XCT ICPPHS+3(E) ;call appropriate phase
AOJA E,POPJ1 ;and advance to next
;First phase - connect to ICP socket.
ICP1: PUSH P,D ;Assume that all sockets were closed, so ITS has deallocated any
SETZM SKTBAS ;old set of sockets, and we must ask it for a new set.
HRROI D,040044 ;asynchronous, 32-bit read
PUSHJ P,ARPCON ;initiate connection
JRST POP2J ;lose
POP P,D ;win
POPJ P,
;Second phase - get server socket number and connect up.
ICP2: PUSHJ P,CONFIN ;finish ICP connection
JRST POP1J ;lose
SYSCAL IOT,[MOVEI (A) ? MOVEM C] ;get foreign socket number
IFE $$ERRHAN, JRST POP1J ;Connection opened but nothing came through, lose
.ELSE JRST [ POP P,C ? JRST ANALNS ] ;Analyze then take error return
;Due to bug in NCP socket allocation, don't close contact pin yet
ADDI A,2 ;connect our read pin
ADDI C,1 ;to foreign write pin
PUSH P,D
HLROS D ;using input mode, asynchronously
PUSHJ P,ARPCON
JRST POP2J ;lose
ADDI A,1 ;connect our write pin
SUBI C,1 ;to foreign read pin
HRRO D,(P) ;using output mode, asynchronously
PUSHJ P,ARPCON
JRST POP2J ;lose
POP P,D
POPJ P,
;Third phase - finish up connections.
ICP3: PUSHJ P,CONFIN ;finish write connection
JRST POP1J
SUBI A,1
PUSHJ P,CONFIN ;finish read connection
JRST POP1J
SYSCAL CLOSE,[MOVEI -2(A)] ;and now close contact pin
.LOSE %LSSYS
POPJ P,
] ;END IFN $$ICP
IFN $$SERVE,[
;Call: MOVEI A,pin ;first channel number of three consecutive ones.
; ;the first is the ICP listen channel,
; ;the second is the input channel for the TELNET connection,
; ;the third is the output channel for it.
; MOVEI B,icpsoc ;socket to listen for an ICP on.
; MOVE C,[imode,,omode] ;input and output modes as in OPEN on NET device.
; PUSHJ P,NETWRK"ARPSRV ;Listen for and accept an ICP.
; timed out.
; succeeded. B has number of foreign host.
;
;If $$SYSDBG is 0, then connections from hosts locked out by SYSDBG are
;refused, and SERVE fails to skip.
;If $$SYSDBG is 1, then SERVE accepts all connections but returns in C
;a value which is nonzero if the foreign host ought to be locked out by SYSDBG.
;Clobbers A, D, T and TT.
$$CONNECT==1 ;We call ARPCON.
ARPSRV: SYSCAL SSTATU,[MOVEM TT ? MOVEM SYSDBG']
.LOSE %LSSYS
MOVEI TT,377777 ;If debugging, wait forever.
SKIPN DEBUG
MOVEI TT,30.*60. ;Otherwise time out after 60 sec.
ARPSR1: SYSCAL OPEN,[ A ? 5000,,40065 ? [SIXBIT/NET/] ? B]
JRST ARSVLS ;Open a channel to receive the RFC with.
SYSCAL WHYINT,[ A ? 2000,,T ? 2000,,T]
JRST ARSVLS
ARPSR2: CAIN T,%NSRFC ;Have we an RFC to accept?
JRST ARPSR3
SKIPN DEBUG ;No => OK only if debugging
POPJ P, ;(so you can start your server before starting the user).
.CALL CONFIC ;So wait for it to change state and look again.
JRST ARSVLS ;[They also serve who hang and wait]
JRST ARPSR2 ;TRY AGAIN
ARPSR3: HLRZ D,C
TLO D,400000 ;D gets mode for our input socket.
PUSH P,C
SYSCAL RCHST,[ A ? 2000,,C ? 2000,,C ? 2000,,C ? 2000,,B]
.LOSE %LSFIL ;C gets foreign socket ICP'd with.
;B now has host number of host that ICP'd to us.
TLZ B,777000 ;Make sure network number field is 0
IFE $$SYSDBG,[
SKIPL T,SYSDBG ;If system being debugged, may refuse ICP
JRST ARPSR4
ASH T,-9 ;Set to -1000*host# allowed in
ADD T,B ;Zero if this guy allowed in
JUMPN T,ARSVL2
ARPSR4: ];$$SYSDBG
;remember that TT has the "sleep time" arguments for NETBLKs, including CONFI1.
SYSCAL NETAC,A
JRST ARSVL1
ADDI A,1 ;Channel to make input connection on.
ADDI C,3 ;Foreign socket ICP'd with, plus 3, is target for our input.
SETZM SKTBAS'
PUSH P,TT ;See comment 6 lines above!
PUSHJ P,ARPCON
JRST [ POP P,TT ? JRST ARSVL1 ]
MOVE TT,SKTBAS ;Get socket number of our input connection
ADD TT,A
SYSCAL IOT,[1000,,-1(A) ? TT]
.LOSE %LSFIL ;Send our lower socket # to the ICPer.
SYSCAL CLOSE,[1000,,-1(A)] ;Don't need ICP socket any more.
.LOSE %LSFIL
HRRZ D,-1(P) ;Saved C
HRLI D,400000
ADDI A,1 ;Now open our output connection
SUBI C,1 ;to a foreign socket 1 smaller than that used for our input.
PUSHJ P,ARPCON
JRST [ POP P,TT ? JRST ARSVL1 ]
POP P,TT
POP P,C
PUSHJ P,CONFI1 ;Then wait for the two connections to be finished.
JRST ARSVLS ;TT still has the time period (or by now maybe the
SUBI A,1 ;time to wait until).
PUSHJ P,CONFI1
JRST ARSVLS
IFN $$SYSDBG,[
SKIPL C,SYSDBG ;If system being debugged, may disallow
JRST [ SETZ C, ? JRST ARPSR5 ]
ASH C,-9 ;Set to -1000*host# allowed in
TLZ B,777000 ;Clear network number from host number
ADD C,B ;Zero if this guy allowed in
ARPSR5: ];$$SYSDBG
EXCH A,B ;Fix host# returned in B
PUSHJ P,STDHST
EXCH A,B
JRST POPJ1
ARSVL2: SYSCAL CLOSE,A
.LOSE %LSFIL
ARSVL1: POP P,C
ARSVLS: SKIPE DEBUG
NWLOSS
POPJ P,
] ;END IFN $$SERVE
IFN $$CONNECT,[
.SCALAR SKTBAS ; ne 0 => socket number of pin zero
; ARPA NETWORK CONNECT ROUTINE
;
;Call: MOVEI A,pin ;local its chnl and relative socket number to connect
; MOVE B,host ;host number to connect to
; MOVEI C,frnsoc ;foreign socket number to connect to
; MOVEI D,mode ;mode to open in (RH). Bit 4.9=1 => asynchronous
; PUSHJ P,NETWRK"ARPCON
; lossage ;you may call ANALYZE to get an error message.
; ;If $$ERRHAN is nonzero, we call ANALYZE for you.
;
;Clobbers only T and TT. If using asynchronous mode,
;call CONFIN later (with pin number in A) to finish up.
;
; NOTE: AT PRESENT YOU MUST CONNECT THE LOWEST NUMBERED
; PIN FIRST, DUE TO BUGS IN SOCKET-SET ASSIGNMENT IN NCP.
ARPCON: MOVE T,A ;Open operand word
HRL T,D ;is mode,,channel
SKIPN TT,SKTBAS ;get base of local socket group
TLO T,10 ;not yet allocated, use gensoc mode
ADD TT,A ;get local sock number to be opened
; TLZ B,777000 ;*** TEMPORARILY CLEAR NETWORK NUMBER UNTIL ITS IS FIXED ***
MOVEM B,ARPHST ;Save last Arpanet host hacked for ANALYZE
.CALL [ SETZ ;open 'er up
SIXBIT/OPEN/
T ;mode,,channel
['NET',,] ;arpanet device
TT ;local socket
C ;foreign socket
SETZ B ] ;foreign host
IFN $$ERRHAN,JRST ANALNS
.ELSE POPJ P,
SKIPE SKTBAS
JRST CONNE0
SYSCAL RCHST,[A ? MOVEM T ? MOVEM T] ;Get local socket, from first pin
.LOSE %LSSYS
SUB T,A ;get socket base
MOVEM T,SKTBAS
CONNE0: JUMPL D,POPJ1 ;asynchronous, return now
;otherwise, drop into CONFIN
;Call: MOVEI A,pin ;pin number of connection
; MOVEI D,flags ;20 if listening, 0 if not. Left over from call to ARPCON.
; PUSHJ P,CONFIN ;finish connection
; lossage - you may call ANALYZE to get an error message
; win - clobbers only T and TT
CONFIN: MOVEI TT,30.*60. ;wait at most one minute
SKIPE DEBUG ;In debug mode, wait forever
MOVSI TT,177777
CONFI1: MOVEI T,%NSRFS ;Which state we started out in depends
TRNE D,20 ;on whether we were listening or initiating.
MOVEI T,%NSLSN
.CALL CONFIC ;Wait up to time in TT to leave state in T.
.LOSE %LSSYS
CAIE T,%NSOPN ;check good state
CAIN T,%NSINP
JRST POPJ1
CAIE T,%NSRFC
CAIN T,%NSCLI
JRST POPJ1
IFN $$ERRHAN,JRST ANALNS ;losing state
.ELSE POPJ P,
CONFIC: SETZ ;wait for connection to open up
'NETBLK'
A
T ;wait until not in state in T
TT
SETZM T ;return state
];$$CONNECT
];$$ARPA*ITS
IFN $$ERRHAN,[
ANALNS: PUSH P,B ;ANALYZE AND THEN POPJ
PUSH P,C
JRST ANALN1
] ;END IFN $$ERRHAN
;;; Chaos network connection routines
IFN $$CHAOS,[
IFN ITS,[
IFN $$SERVE,[
;Call: MOVEI A,chnl ;Input channel number. That+1 is output channel.
; MOVEI C,contact name ;an ASCIZ string
; MOVEI D,window size
; PUSHJ P,NETWRK"CHASRV
; lossage ;you may call ANALYZE to get an error message.
; ;If $$ERRHAN is nonzero, we call ANALYZE for you.
;
;Returns in B the number of the foreign host.
;
;If $$SYSDBG is 0, then connections from all hosts are
;refused, and SERVE fails to skip.
;If $$SYSDBG is 1, then SERVE accepts all connections but returns in C
;a value which is nonzero if the foreign host ought to be locked out by SYSDBG.
;Clobbers A, D, T and TT.
$$CONNECT==1 ;We call CHALSN.
CHASRV: SYSCAL SSTATU,[MOVEM TT ? MOVEM SYSDBG']
.LOSE %LSSYS
MOVEI TT,%COLSN
PUSHJ P,CHACN0 ;Start things up
POPJ P, ;Lost
;Listen done. Check host number, return OPN or CLS
CAIE TT,%CSRFC ;Have we an RFC to accept?
POPJ P, ;No, something went wrong
SYSCAL PKTIOT,[MOVEI (A) ? MOVEI PKTBUF] ;Get the RFC packet
.LOSE %LSSYS
LDB B,[$CPKSA+PKTBUF] ;Get source host
IFN $$HST3,IOR B,[NW%CHS]
.ELSE TLO B,NW%CHS_9 ;Including network number
IFE $$SYSDBG,[ ;Reject rfc if system down
SKIPL SYSDBG
JRST CHASV1
MOVEI T,%COCLS ;Return CLS
DPB T,[$CPKOP+PKTBUF]
PUSH P,C
MOVEI C,[ASCIZ/System not up/]
PUSHJ P,CHSTNG
POP P,C
SYSCAL PKTIOT,[MOVEI 1(A) ? MOVEI PKTBUF]
.LOSE %LSSYS
JRST CHASRV ;Try again
CHASV1: ];$$SYSDBG
MOVEI T,%COOPN ;Return Open
DPB T,[$CPKOP+PKTBUF]
SYSCAL PKTIOT,[MOVEI 1(A) ? MOVEI PKTBUF]
.LOSE %LSSYS
IFN $$SYSDBG,[
SKIPL C,SYSDBG ;If system being debugged, may disallow
JRST [ SETZ C, ? JRST POPJ1 ]
;Unlike Arpanet, we don't have selective disallow, just disallow everyone
];$$SYSDBG
JRST POPJ1
] ;END IFN $$SERVE
];ITS
IFN TNX,[
];TNX
IFN $$CONNECT,[
IFN ITS,[
;CHAOS NETWORK CONNECT ROUTINE
;
;Call: MOVEI A,chnl ;Input channel number. That+1 is output channel.
; MOVEI B,host ;host number to connect to
; MOVEI C,contact name ;an ASCIZ string
; MOVEI D,window size
; PUSHJ P,NETWRK"CHACON
; lossage ;you may call ANALYZE to get an error message.
; ;If $$ERRHAN is nonzero, we call ANALYZE for you.
;
;Clobbers only T and TT.
;
;CHALSN is the same as CHACON except that it uses LSN instead of RFC.
; B is host number it must be from, or 0 if any host is acceptable.
.VECTOR PKTBUF(%CPMXW) ;Buffer used by Open, Close, and Analyze
CHACON:
$$LOG, LOG CHACON,[B,C]
MOVEI TT,%CORFC
PUSHJ P,CHACN0 ;Start things up
POPJ P, ;Lost
CAIE TT,%CSOPN
JRST CHACNL ;Started but didn't get open
JRST POPJ1 ;CHACON done
CHACN0: SETZM PKTBUF
MOVE T,[PKTBUF,,PKTBUF+1]
BLT T,PKTBUF+%CPMXW-1 ;For extra luck, clear the packet buffer
DPB B,[$CPKDA+PKTBUF] ;Destination host
DPB TT,[$CPKOP+PKTBUF]
PUSHJ P,CHSTNG ;Store string from C
SYSCAL CHAOSO,[MOVEI (A) ? MOVEI 1(A) ? D] ;Assign Chaos index
JRST CHACNL
SYSCAL PKTIOT,[MOVEI 1(A) ? MOVEI PKTBUF] ;Send RFC or LSN
.LOSE %LSFIL
MOVEI TT,$$CHATO ;15-second timeout
SKIPE DEBUG
MOVSI TT,177777 ;Or infinite, in debug mode
LDB T,[$CPKOP+PKTBUF]
CAIE T,%COLSN ;Get the boring state
SKIPA T,[%CSRFS]
MOVEI T,%CSLSN
SYSCAL NETBLK,[MOVEI 1(A) ? T ? TT ? MOVEM TT] ;Await completion of connection
JRST CHACNL
JRST POPJ1 ;Return to second half
CHALSN: MOVEI TT,%COLSN
PUSHJ P,CHACN0 ;Start things up
POPJ P, ;Lost
;Listen done. Check host number, return OPN or CLS
CAIE TT,%CSRFC ;Should be RFC into LSN
JRST CHACNL
SYSCAL PKTIOT,[MOVEI (A) ? MOVEI PKTBUF] ;Get the RFC packet
.LOSE %LSFIL
LDB T,[$CPKSA+PKTBUF] ;Check source host
CAIE T,(B) ;Not looking at network number
JUMPN B,CHALS2 ;Jump if doesn't match
MOVEI T,%COOPN ;Matches or we don't care, return open
DPB T,[$CPKOP+PKTBUF]
SYSCAL PKTIOT,[MOVEI 1(A) ? MOVEI PKTBUF]
.LOSE %LSFIL
JRST POPJ1
CHALS2: MOVEI T,%COCLS ;Return CLS
DPB T,[$CPKOP+PKTBUF]
PUSH P,C
MOVEI C,[ASCIZ/You are the wrong host./]
PUSHJ P,CHSTNG
POP P,C
SYSCAL PKTIOT,[MOVEI 1(A) ? MOVEI PKTBUF]
.LOSE %LSFIL
JRST CHALSN ;Try again
CHACNL: ;CHACON or CHALSN lost
IFN $$ERRHAN, JRST ANALNS
.ELSE POPJ P,
;Store string from C into PKTBUF. Bash T, TT
CHSTNG: PUSH P,B
PUSH P,C
MOVE B,[440800,,PKTBUF+%CPKDT]
MOVEI TT,0
HRLI C,440700
CHSTG1: ILDB T,C
JUMPE T,CHSTG2
IDPB T,B
CAIGE TT,%CPMXC-1
AOJA TT,CHSTG1
CHSTG2: DPB TT,[$CPKNB+PKTBUF]
POP P,C
POP P,B
POPJ P,
] ;END IFN $$CONNECT
];ITS
IFN TNX,[
];TNX
IFN $$SIMPLE,[
IFN ITS,[
; CHASMP
; A - channel pair
; B - foreign host
; C - pointer to asciz string of contact name and arguments (if any)
; D - aobjn pointer to buffer in which answer is returned as asciz string
; Returns:
; non-skip failed to get response, or error response (you can call ANALYZE)
; skip once CLS response, asciz string in D's buffer
; skip twice ANS response, asciz string in D's buffer
CHASMP: PUSH P,D
MOVEI D,5 ;Meaningless window size
MOVEI TT,%CORFC
PUSHJ P,CHACN0 ;Start things up
JRST CHASM9 ;Lose
CAIN TT,%CSCLS
SYSCAL PKTIOT,[MOVEI (A) ? MOVEI PKTBUF] ;Get the ANS/CLS packet
JRST CHASM9 ;Didn't get proper response
LDB TT,[$CPKOP+PKTBUF]
CAIN TT,%COANS
AOSA -1(P) ;Skip twice
CAIN TT,%COCLS
AOSA -1(P) ;Skip once
JRST CHASM9 ;Skip no times (shouldn't get here usually)
PUSH P,C
HLRE C,-1(P) ;Get minus number of words
IMUL C,[-5]
SUBI C,1 ;Number of characters not counting terminator
MOVE D,-1(P)
HRLI D,440700
MOVE TT,[440800,,PKTBUF+%CPKDT]
LDB T,[$CPKNB+PKTBUF]
CAMGE T,C
MOVE C,T
CHASM1: ILDB T,TT
IDPB T,D
SOJG C,CHASM1
IDPB C,D
POP P,C
CHASM9: POP P,D
POPJ P,
] ;END IFN $$SIMPLE
];ITS
IFN TNX,[
];TNX
] ;END IFN $$CHAOS
IFN $$TCP,[
IFN $$SERVE,[
;Call: MOVEI A,chnl ;Input channel number. That+1 is output channel.
; MOVEI B,port#
; PUSHJ P,NETWRK"TCPSRV
; lossage ;you may call ANALYZE to get an error message.
; ;If $$ERRHAN is nonzero, we call ANALYZE for you.
;
;Returns in B the number of the foreign host.
;
;If $$SYSDBG is 0, then connections from all hosts are
;refused, and SERVE fails to skip.
;If $$SYSDBG is 1, then SERVE accepts all connections but returns in C
;a value which is nonzero if the foreign host ought to be locked out by SYSDBG.
;Clobbers A, D, T and TT.
$$CONNECT==1 ;just for TCPCNL
TCPSRV: SYSCAL SSTATU,[MOVEM TT ? MOVEM SYSDBG']
.LOSE %LSSYS
SYSCAL TCPOPN,[MOVEI (A) ? MOVEI 1(A) ? B
[-1] ? [-1]] ; Wild fgn port and host.
JRST TCPCNL ; Bah, failed for some reason.
MOVEI TT,$$TCPTO ;15-second timeout
SKIPE DEBUG
MOVSI TT,177777 ;Or infinite, in debug mode
MOVEI T,%NSLSN ; Initial state to hang on.
TCPSV1: SYSCAL NETBLK,[MOVEI 1(A) ? T ? TT ? MOVEM T ? MOVEM TT]
.LOSE %LSSYS ; Gack?
JUMPLE TT,TCPCNL ; Exit if timed out
CAIN T,%NSRFC ; If in SYN-RECEIVED state
JRST TCPSV1 ; then it's OK to keep waiting.
CAIE T,%NSOPN ; Else should be open now.
CAIN T,%NSRFN
CAIA
JRST TCPCNL ; Aw, phooie.
; TCP connection open now.
SYSCAL RFNAME,[MOVEI 1(A) ? MOVEM T
MOVEM T ; Local port # (should be = ICPSOC)
MOVEM T ; Foreign port #
MOVEM B]; Foreign host #
.LOSE %LSSYS ; Gack?
IFE $$SYSDBG,[ ;Reject rfc if system down
SKIPL SYSDBG
JRST TCPSV2
;I don't know how to do this right. Just send string and close
MOVE T,[440700,,[ASCIZ/System not up/]]
MOVEI TT,13.
SYSCAL SIOT,[MOVEI 1(A) ? T ? TT]
JFCL
SYSCAL CLOSE,[MOVEI (A)]
.LOSE %LSSYS
SYSCAL CLOSE,[MOVEI 1(A)]
.LOSE %LSSYS
JRST TCPSRV ;Try again
TCPSV2: ];$$SYSDBG
IFN $$SYSDBG,[
SKIPL C,SYSDBG ;If system being debugged, may disallow
JRST [ SETZ C, ? JRST POPJ1 ]
;Unlike Arpanet, we don't have selective disallow, just disallow everyone
];$$SYSDBG
JRST POPJ1
] ;END IFN $$SERVE
IFN $$CONNECT,[
;TCP CONNECT ROUTINE
;
;Call: MOVEI A,chnl ;Input channel number. That+1 is output channel.
; MOVEI B,host ;host number to connect to
; MOVEI C,foreign port ;you don't get to pick the local port
; PUSHJ P,NETWRK"TCPCON
; lossage ;you may call ANALYZE to get an error message.
; ;If $$ERRHAN is nonzero, we call ANALYZE for you.
;
;Clobbers only T and TT.
TCPCON:
$$LOG, LOG TCPCON,[B,C]
MOVEI T,1(A) ;Output channel
.CALL [ SETZ ? 'TCPOPN' ? A ? T ? [-1] ? C ? SETZ B ]
JRST TCPCNL ;Didn't even start trying
MOVEI TT,$$TCPTO ;15-second timeout
SKIPE DEBUG
MOVSI TT,177777 ;Or infinite, in debug mode
.CALL [ SETZ ? 'NETBLK' ? MOVEI 1(A) ? MOVEI %NSRFS ? TT
SETZM T ] ;T gets state it went into
.LOSE %LSSYS
CAIE T,%NSOPN ;Good state?
CAIN T,%NSRFN
JRST POPJ1 ;Success
TCPCNL: ;Timed out or failed
IFN $$ERRHAN, JRST ANALNS
.ELSE POPJ P,
];$$CONNECT
];$$TCP
IFN $$ANALYZE*ITS,[
; Network error analysis.
;Call: MOVEI A,pin ;channel number that is losing
; PUSHJ P,ANALYZE
; .VALUE ;always skip-returns
;
;Clobbers only T and TT. Uses the PUTCHR routine to type out its messages.
;Does not type a crlf after the message.
.VECTOR WHYINT(5) ;Cruft returned from WHYINT
ANALYZE:
AOS (P)
PUSH P,B
PUSH P,C
ANALN1: SYSCAL USRVAR,[MOVEI %JSELF ? MOVEI .RIOC(A) ? MOVEM T ] ;Channel open?
.LOSE %LSSYS
JUMPE T,ANALN2 ;No, don't clobber error code with WHYINT
SYSCAL WHYINT,[A ? MOVEM WHYINT ;Get device type
MOVEM WHYINT+1 ? MOVEM WHYINT+2 ? MOVEM WHYINT+3
MOVEM WHYINT+4 ]
.LOSE %LSFIL
MOVE T,WHYINT ; Get device type
IFN $$TCP\$$ARPA,[
CAIE T,%WYNET
CAIN T,%WYTCP
JRST ANAL1 ; Go analyze NCP/TCP channel.
];$$TCP\$$ARPA
IFN $$CHAOS,[
CAIN T,%WYCHA
JRST ANLCHA ;Chaos net channel open, further info available
];$$CHAOS
ANALN2: SYSCAL USRVAR,[MOVEI %JSELF ? MOVEI .RIOS(A) ? MOVEM T] ;Get I/O status wd for channel
.LOSE %LSSYS
LDB TT,[220600,,T] ;only the open-loss code is available
CAIN TT,%EFLDV ;Device full (this one applies to both Arpanet & Chaos net)
JRST [ JSP TT,SPEAK
ASCIZ \All sockets in use.\ ]
CAIN TT,%ENRDV ;Device not ready
JRST [ JSP TT,SPEAK
ASCIZ \Network down.\ ]
IFN $$ARPA,[
CAIE TT,%ENAPP ;Other end of pipeline gone, or
CAIN TT,%ENSDR ;No such directory
JRST [ ;Host is down, say why.
MOVE T,ARPHST ;Go print status for last host hacked, is probably right one
JRST ANALC1 ] ;Unfortunately, channel not open, can't get right host
CAIN TT,%ESCO ;Self-contradictory open
JRST [ JSP TT,SPEAK
ASCIZ \Connection cannot be opened because of inconsistent byte sizes.\ ]
];$$ARPA
SYSCAL IOPUSH,[A] ;Some other error - get ITS error message
.LOSE %LSSYS
.CALL [ SETZ
SIXBIT/OPEN/
MOVEI (A) ;here we rely on .UAI=0
['ERR',,]
MOVEI 3 ;Status from T
SETZ T ]
.LOSE %LSFIL
MOVEI TT,[ASCIZ\? Internal error - \]
PUSHJ P,ZTYPE
ANAL0: SYSCAL IOT,[MOVEI (A) ? MOVEM T] ;copy error message to output device
.LOSE %LSSYS
CAIGE T,40
JRST ANALYX
PUSHJ P,PUTCHR
JRST ANAL0
ANALYX: SYSCAL IOPOP,[A]
.LOSE %LSSYS
ANALX: POP P,C
POP P,B
POPJ P,
IFN $$TCP\$$ARPA,[
; Arpanet channel still open - further information available
ANAL1: HRRZ TT,WHYINT+1 ;get socket state
JUMPE TT,ANALC .SEE %NSCLS ;connection closed
IFN $$TCP,[
CAIN T,%WYTCP
JRST ANAL20 ; Report TCP channel state
] ;$$TCP
CAIN TT,%NSRFS ;state is %NSRFS => we must have timed out at CONFIN.
JRST [ JSP TT,SPEAK
ASCIZ /Timed-out while awaiting response to opening of connection./ ]
CAIN TT,%NSLSN ;same but listening rather than rfc'ing
JRST [ JSP TT,SPEAK
ASCIZ/Timed-out while listening for request to open connection./ ]
JRST ANAL50 ; Give up, complain about illegal state
IFN $$TCP,[
ANAL20: CAILE TT,%NTINP
JRST ANAL50 ; State too big
PUSH P,TCPSTB(TT) ; Get state message
MOVEI TT,[ASCIZ /Connection /]
PUSHJ P,ZTYPE
POP P,TT
JRST SPEAK
TCPSTB: OFFSET -.
%NTCLS:: [ASCIZ /closed./]
%NTLSN:: [ASCIZ /listening./]
%NTSYR:: [ASCIZ /wedged, SYN rcvd but not acked./]
%NTCLU:: [ASCIZ /being closed by foreign host./]
%NTSYN:: [ASCIZ /waiting for response to SYN./]
%NTOPN:: [ASCIZ /open./]
%NTWRT:: [ASCIZ /open, output buffer full./]
%NTCLX:: [ASCIZ /being closed by user./]
%NTCLI:: [ASCIZ /closed, input still available./]
%NTINP:: [ASCIZ /open, input available./]
OFFSET 0
] ;$$TCP
ANAL50: PUSH P,TT
MOVEI TT,[ASCIZ\? Socket entered illegal state #\]
PUSHJ P,ZTYPE
LDB T,[030300,,(P)]
SKIPE T
PUSHJ P,[ ADDI T,"0" ? JRST PUTCHR ]
POP P,T
ANDI T,7
ADDI T,"0"
PUSHJ P,PUTCHR
JRST ANALX
];$$TCP\$$ARPA
SPEAK: PUSHJ P,ZTYPE ;send message from TT
JRST ANALX ; and return
IFN $$TCP\$$ARPA,[
;Say why connection was closed
ANALC: SYSCAL RFNAME,[MOVEI (A) ? MOVEM T
MOVEM T ? MOVEM T ; Local port, fgn port
MOVEM T ] ; Fgn host (NCP: 1.1-1.9)
.LOSE %LSSYS
HRRZ TT,WHYINT+3 ; Get close reason
CAIL TT,LCLSTB
SETO TT,
MOVE TT,CLSTAB(TT) ;get asciz close reason
PUSH P,T ;save host number
PUSH P,TT
PUSHJ P,ZTYPE
POP P,TT
POP P,T
JUMPGE TT,ANALX ;return if host is up
MOVE TT,WHYINT
CAIN TT,%WYTCP ; If TCP, must do further checking
JRST [ GETNET TT,T ; Get network number
CAME TT,[NW%ARP] ; Can only get status for arpanet sites
JRST ANALX ; Sorry, no can do.
JRST .+1] ; Aha, try NETHST call.
PUSHJ P,CRLF ;CRLF between down message and down reason
ANALC1: SYSCAL NETHST,[T ? MOVEM T] ;get information about why host down
.LOSE %LSSYS
MOVE B,T
TRZ T,777760 ;RH gets just reason down
TLNE T,2000 ;skip if down
SETO T,
MOVE TT,DEDTAB(T) ;get asciz string describing situation
PUSHJ P,ZTYPE
IFE $$UPTM,JRST ANALX
IFN $$UPTM,JRST ANALTM
IFN $$UPTM,[
;OPTIONALLY, SAY WHEN THE IMP THINKS THE HOST WILL BE BACK UP.
ANALTM: ANDI B,177760 ; get time back
JUMPE B,ANALX ; flush if nothing
CAIN B,177740 ; -2 means unknown future time
JRST ANALX ; There isn't anything useful to say about this.
MOVEI TT,[ASCIZ / Host is expected back up /]
PUSHJ P,ZTYPE
CAIN B,177760 ; -1 means more than a week
JRST [ JSP TT,SPEAK
ASCIZ /over a week from now./ ]
LDB T,[150300,,B] ; get day of week
LDB TT,[100500,,B] ; get hours time
SUBI TT,5 ; EST/GMT offset
PUSH P,B
.RYEAR B, ; get time info
TLNE B,100000 ; daylight losing time?
AOSL TT ; yes, go ahead an hour
JUMPGE TT,NODAY ; easy way out
ADDI TT,24. ; move up a day
SOSGE T ; and days back
MOVEI T,6 ; back to Sunday
NODAY: MOVE B,TT ; Save real hours
MOVE TT,DOWTAB(T) ; Get string describing day of week.
PUSHJ P,ZTYPE
MOVEI TT,[ASCIZ / at /]
PUSHJ P,ZTYPE
MOVE T,B ; get hours time
PUSHJ P,2DTYPE
MOVEI T,":"
PUSHJ P,PUTCHR
POP P,B ; Restore original time
LDB T,[040400,,B] ; get minutes/5
IMULI T,5. ; make into real minutes
PUSHJ P,2DTYPE
MOVEI TT,[ASCIZ/ EST./]
.RYEAR T,
TLNE T,100000
MOVEI TT,[ASCIZ/ EDT./]
PUSHJ P,ZTYPE
JRST ANALX
;TYPE NUMBER IN T AS TWO DECIMAL DIGITS.
2DTYPE: IDIVI T,10. ; split high and low order
ADDI T,"0" ; ASCIIify
ADDI TT,"0" ; ASCIIify
PUSH P,TT
PUSHJ P,PUTCHR
POP P,T
JRST PUTCHR
DOWTAB: [ASCIZ/on Monday/]
[ASCIZ/on Tuesday/]
[ASCIZ/on Wednesday/]
[ASCIZ/on Thursday/]
[ASCIZ/on Friday/]
[ASCIZ/on Saturday/]
[ASCIZ/on Sunday/]
[ASCIZ/on April Fool's day/]
] ;END IFN $$UPTM
];$$TCP\$$ARPA
IFN $$CHAOS,[
;Analyze on chaos channel, still open
ANLCHA: MOVE TT,WHYINT+1 ;Connection state
CAIE TT,%CSLOS
CAIN TT,%CSCLS
JRST ANLCH1
CAIE TT,%CSINC
JRST ANLCH0 ;Still open
JSP TT,SPEAK
ASCIZ /Connection broken -- foreign host not communicating./
ANLCH0: PUSH P,CHSTTB(TT)
MOVEI TT,[ASCIZ/Timed-out while connection /]
PUSHJ P,ZTYPE
POP P,TT
JRST SPEAK
CHSTTB: [ASCIZ/closed/]
[ASCIZ/listening/]
[ASCIZ/has received RFC/]
[ASCIZ/trying to get connected/] ;has sent RFC
[ASCIZ/open/]
[ASCIZ/lost/]
[ASCIZ/broken/]
ANLCH1: PUSH P,CHSTTB(TT)
MOVEI TT,[ASCIZ/Connection /]
PUSHJ P,ZTYPE
POP P,TT
PUSHJ P,ZTYPE
MOVEI TT,[ASCIZ/ -- /]
PUSHJ P,ZTYPE
HLRZ TT,WHYINT+2 ;get number of input packets
ANLCH2: SOJL TT,ANALX ;scan input looking for CLS, LOS
HLRZ T,WHYINT+4 ;Pick up input channel number
SYSCAL PKTIOT,[T ? MOVEI PKTBUF]
.LOSE %LSFIL
LDB T,[$CPKOP+PKTBUF]
CAIE T,%COCLS
CAIN T,%COLOS
SKIPA B,[440800,,PKTBUF+%CPKDT]
JRST ANLCH2
LDB C,[$CPKNB+PKTBUF]
ANLCH3: SOJL C,ANALX
ILDB T,B
PUSHJ P,PUTCHR
JRST ANLCH3
];$$CHAOS
IFN $$ARPA\$$TCP,[
; Tables
;Close Reasons
[ASCIZ/Illegal close-reason code??/]
CLSTAB: OFFSET -.
%NCNTO::[ASCIZ/Connection never opened??/]
%NCUSR::[ASCIZ/Connection legitimately closed??/]
%NCFRN::[ASCIZ/Connection closed by foreign host./]
%NCRST::[ASCIZ/Connection reset by foreign host./]
%NCDED::400000,,[ASCIZ/Host died./]
%NCINC::400000,,[ASCIZ/Incomplete transmission - foreign host or network died./]
%NCBYT::[ASCIZ/Byte size mismatch??/]
%NCNCP::[ASCIZ/Local Network Control Program reset./]
%NCRFS::[ASCIZ/Request for Connection refused by foreign host./]
LCLSTB::OFFSET 0
;Host Dead Reasons
[ASCIZ/Illegal host-dead code??/]
DEDTAB: [ASCIZ/ Network lossage./] ;0 probably no host-dead-reason returned
[ASCIZ/ Destination Host dead./] ;1 WOULDN'T SAY WHY
[ASCIZ/ Foreign Network Control Program not in operation./]
[ASCIZ/ Destination Host or IMP does not exist./]
[ASCIZ/ Destination Host is initializing its NCP software./]
[ASCIZ/ Destination Host down for scheduled maintenance./]
[ASCIZ/ Destination Host down for scheduled hardware work./]
[ASCIZ/ Destination Host down for scheduled software work./]
[ASCIZ/ Destination Host is in emergency restart./]
[ASCIZ/ Destination Host down due to power failure./]
[ASCIZ/ Destination Host is stopped at a breakpoint./]
[ASCIZ/ Destination Host down due to hardware failure./]
[ASCIZ/ Destination Host is not scheduled to be up./]
[ASCIZ/ (Undefined host-down code 13.)/]
[ASCIZ/ (Undefined host-down code 14.)/]
[ASCIZ/ Destination Host is coming up now./]
];$$ARPA\$$TCP
];END IFN $$ANALYZE*ITS
IFN $$CVH,[
;;;; Utilities - CVH2NA, CVH3NA
; CVH2NA - Convert network host address in A to HOSTS2 format.
; A/ net address (any format)
; Returns A
CVH2NA: PUSH P,B
LDB B,[301400,,A] ; Get high 12 bits of net address
CAIGE B,70 ; If less than lowest HOSTS2-fmt value
JUMPN B,CVH2N3 ; then must be HOSTS3, go convert.
CAIL B,1000 ; If any of high 3 bits set,
JRST CVH2N3 ; then it's a HOSTS3 strange-fmt number.
JUMPN B,CVH2N2
CAILE A,377 ; Zero network, so must be ARPA net
JRST CVH2N1 ; Not just 8 bits, just add net number.
; Old-style 8-bit Arpanet host number
LSHC A,-6.
ROT B,6.
DPB B,[112000,,A]
CVH2N1: TLO A,(12_33)
JRST CVH2N9
; Probably HOSTS2 format number
CVH2N2: JRST CVH2N9 ; For now, that's good enough.
; HOSTS3 format number, convert it.
CVH2N3: CAIN B,12 ; Arpa net?
JRST [ LSHC A,-16.
ANDI A,377
ROT B,16.
DPB B,[112000,,A]
TLO A,(12_33)
JRST CVH2N9]
CAIN B,7+<NE%UNT_-24.> ; Chaos net?
JRST [ ANDI A,177777 ; Yup, fix it up.
TLO A,(7_33)
JRST CVH2N9]
CAIN B,22 ; LCS net?
JRST [ LSHC A,-8.
ANDI A,-1
LSH A,2
LSHC A,8.
TLO A,(22_33)
JRST CVH2N9]
; Not a known net, but try to do something plausible.
ANDCM A,[-1_24.] ; Preserve low 24 bits
DPB B,[331100,,A] ; put net # into HOSTS2 field.
CVH2N9: POP P,B
POPJ P,
] ;$$CVH
; CVH3NA - Convert network host address in A to HOSTS3 (Internet) format.
; A/ net address (any format)
; Returns A
CVH3NA: PUSH P,B
LDB B,[301400,,A] ; Get high 12 bits of net address
CAIGE B,70 ; If less than lowest HOSTS2 value,
JUMPN B,CVH3N3 ; it's already HOSTS3 format! (unless zero)
CAIL B,1000 ; If any of high 3 bits were set,
JRST CVH3N3 ; it must be a HOSTS3 strange-fmt addr.
JUMPN B,CVH3N2 ; If not zero, then must assume HOSTS2 fmt.
; Old-format 8-bit Arpanet host number, or HOSTS2 with zero net.
IFE $$ARPA,IFN $$CHAOS, IOR A,[NW%CHS] ? JRST CVH3N3
CAILE A,377
JRST CVH3N6 ; If greater than 8 bits, assume HOSTS2, zero net.
LSHC A,-6 ; Put 10 bits spacing between host/imp #s.
LSH B,-<2+8.>
LSHC A,<2+8.+6>
TLO A,(12_24.) ; and add ARPA network number.
JRST CVH3N3
; HOSTS2 format number
CVH3N2: TRZE B,7 ; Zap low 3 bits to ensure correct comparison
JRST CVH3N5 ; If any were set, can't be Chaosnet.
CAIN B,7_3 ; Chaos net?
JRST [ ANDI A,177777 ; Yes, kill all but bottom 16 bits
TLO A,(NE%UNT+<7_24.>) ; Add Chaos net #
JRST CVH3N3]
CVH3N5: CAIN B,12_3 ; Arpa net?
CVH3N6: JRST [ LSHC A,-9.
ANDI A,177777
ROT B,9.
DPB B,[201000,,A]
TLO A,(12_24.)
JRST CVH3N3]
CAIN B,22_3 ; LCS net?
JRST [ LSHC A,-8.
LSH A,-2
ANDI A,377
LSHC A,-8.
TLO A,(22_24.)
JRST CVH3N3]
; No match, assume it's HOSTS3.
CVH3N3: POP P,B
POPJ P,
$$LOG,[
;;; Logging - CStacy, 22 October 1984
;;;
;;; This facility is (originally) so that I can see which users are using
;;; the TELNET and FTP facilities on our machine and to help discover who
;;; is using us as a base in attacking other sites. Maybe ITS should do
;;; some sort of network logging like Multics, but I'll just put it in
;;; this library for now since it isn't clear how generally useful it is
;;; or what functionality we want.
LOGO==1 ;Channel for log file.
LOGL==2 ;Channel for log file lock-file.
;;; NOTE: The user could easily become screwed up if we're interrupted.
;;; --We have IOPUSHed channels away from the user without consent.
;;; --We do synchronous file IO behind its back and handle our own errors.
;;; Therefore, LOG processing defers all interrupts.
;;; The LOG stuff is only called before opening and after closing network
;;; channels, and so this should be a first approximation to a safe practice.
;;; Logfile entries are scattered through the file in sequential order.
;;; They are of variable length. They begin with a unique id number;
;;; The log for a particular job can be threaded from the id.
;;;
;;; An transaction entry looks like:
;;; /BEGIN/
;;; BEGIN-CODE (id) The 36 bit unique id code for this job.
;;; TIMESTAMP The time of the entry.
;;; OPCODE Sixbit name of the transaction type.
;;; CRUFT WORDS Transaction dependant data.
;;;
;;;
;;; The NETLOG program (source in AR2:CSTACY;NETLOG) can be used to
;;; expand a logfile into an ASCII representation of some or all of the
;;; transactions.
;;;
;;; It is possible to have incomplete records of network usage
;;; in the logfile, since if many things go wrong we abort the
;;; logging procedure rather than waste time being too robust
;;; when the entire facility is supposed to be invisible.
;;; NETWRK routines may call LOGACT to log some action.
;;; Callers provide any list of cruft they want, the first word
;;; being SIXBIT name of the operation.
;;; Semantics for entries should be documented here for interested
;;; programmers to find out how to decode the log file.
;;;
;;; OPEN: <host-address> <foreign port>
;;; ANALYZ: <host-address> <whyint> ... <whyint+4>
;;;
.SCALAR LOGID ;Our id number in the log file.
;;; LOGACT - Log some action
;;; A/ number of crufty words on the stack (P) before the funcall.
;;; Smashes no ACs and never skips.
;;; Caller must pop his args back off himself.
LOGACT: MOVE T,P ;Save current SP here for a moment.
.SUSET [.RPICLR,,TT] ;Read global interrupt defer word.
PUSH P,TT ;Stack it away for restoration.
.SUSET [.SPICLR,,[0]] ;Defer all interrupts.
.IOPUSH LOGO, ;Push the channels we want,
.IOPUSH LOGL, ;hoping the IOPDL doesn't overflow.
PUSH P,A ;Do not smash ACs.
PUSH P,B
PUSH P,C
PUSH P,D
MOVE B,T ;B gets SP to top of LOGACT frame.
LOGA10: PUSHJ P,LOGOPN ;Open log file if needed.
JRST LOGCLS
SYSCAL ACCESS,[%CLIMM,,LOGO ? C] ;Move to EOF.
JRST LOGCLS
SUB B,A ;Point to first arg.
HRLZ A,A
HRR A,B ;A has length,,adr of crufties.
LOGA20: SYSCAL RQDATE,[%CLOUT,,B]
JRST LOGCLS
SKIPE C,LOGID ;If our id has been initialized,
JRST LOGA30 ; go make an entry.
.SUSET [.RUIND,,C] ;Else find our job number.
HRL C,B ;*** This should be more or less unique? **
MOVEM C,LOGID ;Set our id.
LOGA30: MOVE T,[444400,,[SIXBIT /BEGIN/]]
MOVEI TT,1
SYSCAL SIOT,[%CLIMM,,LOGO ? T ? TT] ;Write entry marker.
JRST LOGCLS
MOVE T,[444400,,B]
MOVEI TT,2
SYSCAL SIOT,[%CLIMM,,LOGO ? T ? TT] ;Write timestamp and id.
JRST LOGCLS
.SUSET [.RUNAME,,B]
.SUSET [.RJNAME,,C]
MOVE T,[444400,,B]
MOVEI TT,2
SYSCAL SIOT,[%CLIMM,,LOGO ? T ? TT] ;UNAME, JNAME.
CAIA
LOGA40: HRRZ T,A ;Get ptr to stacked args.
HRLI T,444400 ;Make BP.
HLRZ TT,A ;Get length.
SYSCAL SIOT,[%CLIMM,,LOGO ? T ? TT] ;Write opcode, crufties.
JRST LOGCLS
LOGCLS: .CLOSE LOGO,
.CLOSE LOGL,
.IOPOP LOGL,
.IOPOP LOGO,
POP P,D
POP P,C
POP P,B
POP P,A
POP P,T ;Probably -1 (no global deferment).
.SUSET [.SPICLR,,T] ;Restore interrupt defer state.
POPJ P, ;All done.
;;; LOGOPN - Seize the logfile lock, and open the logfile for writing.
;;; Uses LOGL and LOGO file channels, and skips on success.
;;; Returns length of the database in C, does not smash other ACs.
;;; Notes:
;;; o If the lock file is missing LOGOPN will re-create it.
;;; o If the logfile itself is missing, we just fail.
LOGMLT==6 ;Maximum # attempts to make trying to seize the lock.
LOGOPN: PUSH P,A
PUSH P,B
SETZ B, ;Count of locking attempts in B.
LOGLOK: SYSCAL OPEN,[%CLBIT,,.BIO\%DOWOV ? %CLIMM,,LOGL
[SIXBIT /DSK/]
[SIXBIT /NETLOG/]
[SIXBIT /LOCK/]
[SIXBIT /SPACY/]]
CAIA
JRST LOGLKD ;Got it!
CAIL B,LOGMLT ;Else if we have exceeded the retry maximum
JRST LOGLKF ; Fail.
.STATUS LOGL,A ;Let's see why the open failed.
LDB A,[220600,,A] ;Get error code.
CAIN A,%ENAFL ;If someone else has the lock
JRST [ MOVEI T,30. ; Sleep for one second.
.SLEEP T, ; (They should give it up soon.)
AOS B ; Keep count of attempts to seize lock.
JRST LOGLOK ] ; Try,try again.
CAIE A,%ENSFL ;Hmmm....Maybe the lock file is missing?
JRST LOGLKF ; Nope - some random lossage.
SYSCAL OPEN,[%CLBIT,,.UAO ? %CLIMM,,LOGL ;Re-create it.
[SIXBIT /DSK/]
[SIXBIT /NETLOG/]
[SIXBIT /LOCK/]
[SIXBIT /SPACY/]]
JRST LOGLKF ; Fail if could not create lock.
.CLOSE LOGL, ;Else close file
JRST LOGLOK ;and try to seize it again.
LOGLKD: SYSCAL OPEN,[%CLBIT,,.BII ? %CLIMM,,LOGO
[SIXBIT /DSK/]
[SIXBIT /NETLOG/]
[SIXBIT / DATA/]
[SIXBIT /SPACY/]]
JRST LOGLKF
SYSCAL FILLEN,[%CLIMM,,LOGO ? %CLOUT,,C]
JRST LOGLKF
.CLOSE LOGO, ;Protocol says no lock competition here.
SYSCAL OPEN,[%CLBIT,,%DOWOV+.UIO ? %CLIMM,,LOGO
[SIXBIT /DSK/]
[SIXBIT /NETLOG/]
[SIXBIT / DATA/]
[SIXBIT /SPACY/]]
CAIA ; Huh? We opened it a moment ago???
AOS -2(P) ;Skip return if won.
LOGLKF: POP P,B
POP P,A
POPJ P,
];$$LOG
.qmtch=qmtch ;set this back to the value the user gave it
.END NETWRK