Google
 

Trailing-Edge - PDP-10 Archives - SRI_NIC_PERM_SRC_1_19910112 - 7/ap23-tcpip/mnetdv.mac
There are 10 other files named mnetdv.mac in the archive. Click here to see a list.
; Edit= 9111 to MNETDV.MAC on 22-Jun-89 by WONG (TCO none)
;Change RETERR to RETBAD in routines GTHHNN and GTHNUM so that we can return
;back to the .GTHST% to unlock GTHLCK and not back to the user without
;unlocking GTHLCK.
; Edit= 9108 to MNETDV.MAC on 14-Jun-89 by GSCOTT
;MNTSET should do work directly rather than depending on the internet fork and
;add code to have a reasonable interlock on the host tables. 
; Edit= 9037 to MNETDV.MAC on 29-Nov-88 by LOMARTIRE
;Fix bug in .GTHHN function of GTHST% and use a better error code
; Edit= 9006 to MNETDV.MAC on 8-Nov-88 by LOMARTIRE
;Merge Production changes to BUG text
; Edit= 8982 to MNETDV.MAC on 13-Oct-88 by GSCOTT
;Prevent "[Internet Network ...]" messages from being split up on the CTY. 
; Edit= 8975 to MNETDV.MAC on 30-Sep-88 by GSCOTT
;Speed up reading HOSTS.TXT file by a factor of 10, include rewrite of ADRINI
;as well as HSTINI and better error recovery for both routines.
; Edit= 8969 to MNETDV.MAC on 13-Sep-88 by GSCOTT
;Prevent ILLUUO and ILMNRF BUGHLTs when there is a bad format to HOSTS.TXT or
;INTERNET.ADDRESS files. Fix up some error messages that report format errors
;in these files.
; Edit= 8926 to MNETDV.MAC on 22-Aug-88 by LOMARTIRE
;Improve BUG. documentation
; Edit= 8828 to MNETDV.MAC on 13-Apr-88 by RASPUZZI
;Prevent SKDPF1s and PITRAPs the right way now. HSTSTS is now greater than
;400000 and HOSTNN will be soon. Add them directly to the hash block address
;instead of using them in effective address calculation. Gross but it will
;hopefully work.
; Edit= 8806 to MNETDV.MAC on 18-Mar-88 by GSCOTT (TCO 7.1261)
;Install TCO 7.1261 in autopatch sources. 
; UPD ID= 8689, RIP:<7.MONITOR>MNETDV.MAC.6,  18-Mar-88 10:52:50 by GSCOTT
;TCO 7.1261 - Set NOADDR to be not normally dumpable.
; UPD ID= 8670, RIP:<7.MONITOR>MNETDV.MAC.5,  26-Feb-88 10:36:52 by GSCOTT
;TCO 7.1243 - Use SYSTEM:HOSTS.DEBUG if DBUGSW is greater than one.
; UPD ID= 8554, RIP:<7.MONITOR>MNETDV.MAC.4,  11-Feb-88 11:03:14 by GSCOTT
;TCO 7.1218 - Update copyright date.
; UPD ID= 8425, RIP:<7.MONITOR>MNETDV.MAC.3,   4-Feb-88 13:29:58 by GSCOTT
;TCO 7.1210 - Set NOHSTN normally not dumpable.
; UPD ID= 2123, SNARK:<6.1.MONITOR>MNETDV.MAC.11,   5-Jun-85 09:58:02 by MCCOLLUM
;TCO 6.1.1406  - Update copyright notice.
; UPD ID= 1957, SNARK:<6.1.MONITOR>MNETDV.MAC.10,  12-May-85 14:54:53 by PAETZOLD
;TCO 6.1.1380 - Make HOSTN larger.
; UPD ID= 1608, SNARK:<6.1.MONITOR>MNETDV.MAC.9,   8-Mar-85 11:53:53 by PAETZOLD
;Document BUGxxx's
; UPD ID= 1570, SNARK:<6.1.MONITOR>MNETDV.MAC.8,  26-Feb-85 17:17:32 by PAETZOLD
;document BUGxxx's
; UPD ID= 1235, SNARK:<6.1.MONITOR>MNETDV.MAC.7,  22-Dec-84 11:43:29 by PAETZOLD
;More TCO 6.1.1079 - Make the XJRST conditional based on REL6 switch for 5.4.
; UPD ID= 1178, SNARK:<6.1.MONITOR>MNETDV.MAC.6,  11-Dec-84 13:15:23 by PAETZOLD
;TCO 6.1.1079 - Use an XJRST referecing TVTJFN in ATNVT.
; UPD ID= 1038, SNARK:<6.1.MONITOR>MNETDV.MAC.5,  12-Nov-84 15:25:34 by PAETZOLD
;TCO 6.1041 - Move ARPANET to XCDSEC
; UPD ID= 999, SNARK:<6.1.MONITOR>MNETDV.MAC.4,   7-Nov-84 14:46:40 by PRATT
;TCO 6.1.1030 - Add IPCI to INTNAM for communicating over the CI
; UPD ID= 917, SNARK:<6.1.MONITOR>MNETDV.MAC.3,  23-Oct-84 19:49:20 by PAETZOLD
; UPD ID= 312, SNARK:<TCPIP.5.4.MONITOR>MNETDV.MAC.11,  18-Oct-84 15:41:24 by PAETZOLD
;TCO 6.1.1024 - Add .GTHLA function to GTHST%.
; UPD ID= 304, SNARK:<TCPIP.5.4.MONITOR>MNETDV.MAC.10,  15-Oct-84 14:46:20 by PAETZOLD
;Fix alphabetical order problem in OPSTAB.
; UPD ID= 287, SNARK:<TCPIP.5.4.MONITOR>MNETDV.MAC.9,  24-Sep-84 13:55:04 by PURRETTA
;Update copyright notice.
; UPD ID= 163, SNARK:<TCPIP.5.4.MONITOR>MNETDV.MAC.8,   3-Jun-84 17:26:35 by PAETZOLD
;Make  MNTHLT  reset  NETON  for  each interface so that it stays down. 
;Clean up MNTHLT in general.  Remove MNTKIL since no one uses it.
;Add VMS, TACs, and MSDOS to OPSTAB.
; UPD ID= 159, SNARK:<TCPIP.5.4.MONITOR>MNETDV.MAC.7,   1-Jun-84 11:35:17 by PAETZOLD
;AOS INTFLG in MNTSET.
; UPD ID= 156, SNARK:<TCPIP.5.4.MONITOR>MNETDV.MAC.6,  31-May-84 11:25:18 by PAETZOLD
;Use indirects in MNTRSV
; UPD ID= 155, SNARK:<TCPIP.5.4.MONITOR>MNETDV.MAC.5,  31-May-84 10:58:54 by PAETZOLD
;Add MNTRSV.  Add some ENDSV.'s.
; UPD ID= 129, SNARK:<TCPIP.5.4.MONITOR>MNETDV.MAC.4,  14-May-84 16:13:25 by PAETZOLD
;MNTHLT needs an EA.ENT.
; UPD ID= 33, SNARK:<TCPIP.5.4.MONITOR>MNETDV.MAC.3,   7-Apr-84 13:15:19 by PAETZOLD
;Remove some spaces in initial HSTINI message.
; UPD ID= 31, SNARK:<TCPIP.5.4.MONITOR>MNETDV.MAC.2,   5-Apr-84 22:46:02 by PAETZOLD
;Add IPNI to INTNAM. Change SITE-ADDRESS.TXT to INTERNET.ADDRESS. Clean
;up  MNTSTS  output.  Use  NETPRT  to  print  out  network numbers. Add
;informational message during startup when calling HSTINI.
; UPD ID= 4022, SNARK:<6.MONITOR>MNETDV.MAC.13,  31-Mar-84 16:20:59 by PAETZOLD
;TCO 6.2019 - Use ADJSPs
; UPD ID= 3941, SNARK:<6.MONITOR>MNETDV.MAC.12,  18-Mar-84 13:15:57 by PAETZOLD
;More TCO 6.1733 - Do not check for dots in GTHSIL.
; UPD ID= 3935, SNARK:<6.MONITOR>MNETDV.MAC.11,  17-Mar-84 13:01:33 by PAETZOLD
;More TCO 6.1733 - Add Fuzzballs to OPSTAB
; UPD ID= 3921, SNARK:<6.MONITOR>MNETDV.MAC.10,  14-Mar-84 10:17:06 by PAETZOLD
;More TCO 6.1733 - Add Foonex to OPSTAB as Tenex
; UPD ID= 3901, SNARK:<6.MONITOR>MNETDV.MAC.9,  11-Mar-84 14:28:21 by PAETZOLD
;More TCO 6.1733 - 5.3 needs a EA.ENT in MNTINI
; UPD ID= 3894, SNARK:<6.MONITOR>MNETDV.MAC.8,  11-Mar-84 10:36:16 by PAETZOLD
;More TCO 6.1733 - Allow  JFNs in ATNVT%. New HSTINI preference scheme.
;Make HSTINI set  up gateway (HS%GAT)  and  network  (HS%NET)  entries.
;Make  RDFLD fold case to upper. Add TAC and WAITS to OPSTAB. Check and
;dispatch for Pup JFN in .ATNVT.
; UPD ID= 3826, SNARK:<6.MONITOR>MNETDV.MAC.7,  29-Feb-84 18:15:40 by PAETZOLD
;More TCO 6.1733 - ANBSEC and MNTSEC removal.  Bug fixes.  Cleanup.
;<TCPIP.5.3.MONITOR>MNETDV.MAC.4,  6-Dec-83 23:53:55, Edit by PAETZOLD
;Call CHKI7 from MNTCHK
;TCO 6.1867 - Use SAVEAC and not SAVP1
;Add subtitles.  Make code that was RSCOD SWAPCD.
;More TCO 6.1733 - Fix day one off by one bug with NUMOPS
;More TCO 6.1733 - NCPFRK has gone away.  HSTLUK Changes.  HSTINI changes.
;<TCPIP.5.1.MONITOR>MNETDV.MAC.42,  5-Jul-83 08:28:09, Edit by PAETZOLD
;New host table support
;IP debuging switch support
;Use ANAUNV as the universal

;	COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1976, 1988.
;	ALL RIGHTS RESERVED.
;
;	THIS SOFTWARE IS FURNISHED UNDER A  LICENSE AND MAY BE USED AND  COPIED
;	ONLY IN  ACCORDANCE  WITH  THE  TERMS OF  SUCH  LICENSE  AND  WITH  THE
;	INCLUSION OF THE ABOVE  COPYRIGHT NOTICE.  THIS  SOFTWARE OR ANY  OTHER
;	COPIES THEREOF MAY NOT BE PROVIDED  OR OTHERWISE MADE AVAILABLE TO  ANY
;	OTHER PERSON.  NO  TITLE TO  AND OWNERSHIP  OF THE  SOFTWARE IS  HEREBY
;	TRANSFERRED.
;
;	THE INFORMATION IN THIS  SOFTWARE IS SUBJECT  TO CHANGE WITHOUT  NOTICE
;	AND SHOULD  NOT  BE CONSTRUED  AS  A COMMITMENT  BY  DIGITAL  EQUIPMENT
;	CORPORATION.
;
;	DIGITAL ASSUMES NO  RESPONSIBILITY FOR  THE USE OR  RELIABILITY OF  ITS
;	SOFTWARE ON EQUIPMENT THAT IS NOT SUPPLIED BY DIGITAL.


	SEARCH ANAUNV,PROLOG
	TTITLE (MNETDV,MNETDV,< - Internet Multinet Interface>)
	.DIREC FLBLST		;[8975] First line binary listing only please
	Subttl	Table of Contents

;		     Table of Contents for MNETDV
;
;				  Section		      Page
;
;
;    1. MNTINI - Initialization  . . . . . . . . . . . . . . .   4
;    2. MNETON - Turn Networks On if They Have Never Been On .   7
;    3. CHKR Fork Routines
;        3.1    MNTCHK - Periodic Check  . . . . . . . . . . .   8
;        3.2    MNTSTS - Report Network State Changes  . . . .   9
;    4. Low and High Priority Packet Output Queueing . . . . .  11
;    5. NTWPKT - Packet Queueing Routine . . . . . . . . . . .  12
;    6. NTSNDI - Queue an Internet Packet  . . . . . . . . . .  13
;    7. FNDNCT and NETACT - Routines to Find NCTs  . . . . . .  14
;    8. HSTHSH - Find Host Table Entries . . . . . . . . . . .  15
;    9. Host, Network Status and Configuration Routines  . . .  16
;   10. Routines Dealing With Network Shutdown . . . . . . . .  18
;   11. Routines Dealing With Network States . . . . . . . . .  19
;   12. Routine to Resolve Interface State . . . . . . . . . .  20
;   13. Host File Routines
;       13.1    Read SYSTEM:HOSTS.TXT
;           13.1.1    Initialization . . . . . . . . . . . . .  21
;           13.1.2    Read Entry . . . . . . . . . . . . . . .  25
;           13.1.3    Add Host . . . . . . . . . . . . . . . .  27
;       13.2    Table of Operating System Types  . . . . . . .  29
;       13.3    Read Line from File  . . . . . . . . . . . . .  30
;       13.4    Read Character from File . . . . . . . . . . .  31
;       13.5    Read Field from File . . . . . . . . . . . . .  32
;       13.6    Read Host Number . . . . . . . . . . . . . . .  34
;       13.7    Error Handlers . . . . . . . . . . . . . . . .  35
;   14. Address File Routines
;       14.1    Read SYSTEM:INTERNET.ADDRESS . . . . . . . . .  37
;       14.2    Get To Beginning Of Line . . . . . . . . . . .  44
;       14.3    Read Character from File . . . . . . . . . . .  45
;       14.4    Read Field from File . . . . . . . . . . . . .  46
;       14.5    Read Four Decimal Bytes  . . . . . . . . . . .  47
;       14.6    Error Handlers . . . . . . . . . . . . . . . .  48
;       14.7    Print bad line on CTY  . . . . . . . . . . . .  50
;       14.8    Tables . . . . . . . . . . . . . . . . . . . .  51
;   15. CVHST% JSYS - Convert Host Number to String  . . . . .  52
;   16. GTHST% JSYS  . . . . . . . . . . . . . . . . . . . . .  53
;       16.1    Name Table Size, Index Into Name Space . . . .  55
;       16.2    Convert Number to String and String to Number   56
;       16.3    Status by Index and Status by Number . . . . .  57
;       16.4    Move String From/To User Space . . . . . . . .  58
;       16.5    Get Hostnumber on a Network  . . . . . . . . .  59
;       16.6    Get Status of a Network  . . . . . . . . . . .  60
;       16.7    Get Local Network Addresses  . . . . . . . . .  61
;       16.8    Host Table Lock Routines . . . . . . . . . . .  62
;   17. ATNVT% JSYS - Attach connection to NVT . . . . . . . .  63
;   18. NETRDY GETAB Table . . . . . . . . . . . . . . . . . .  64
	Subttl	Table of Contents (page 2)

;		     Table of Contents for MNETDV
;
;				  Section		      Page
;
;
;   19. Utility Routines
;       19.1    HSTLUK - Lookup Host Names . . . . . . . . . .  65
;       19.2    CVNHST - Convert host number to new format . .  67
;   20. End of MNETDV  . . . . . . . . . . . . . . . . . . . .  68
	SUBTTL MNTINI - Initialization

	XSWAPCD

;Called at system startup, initializes tables and storage needed by Multinet.

XNENT (MNTINI,G)		;MNTINI::
	CALL NETINI		; initialize the 1822 buffers
	MOVEI T1,BMNTLK		; Beginning of pages needed to lock down
	SETSEC T1,INTSEC	; In proper section
	MOVEI T2,EMNTLK		; End of area to lock
	SETSEC T2,INTSEC	; Same section
	CALL LKSTOR		; Lock storage
	SETZM DEFADR		; Clear default address field
	SETZM PRFADR		; Clear preferred address field
	SETZM PRFNFD		; Also clear preferred shifted network
	SETZM PRFNET		; And preferred network
	SETZM NETSUP		; Networks not yet up

	MOVSI T1,-%NETS		; Get number of networks we handle
	SKIPA P1,NCTVT		; get link to the first NCT
MNTIN0:	LOAD P1,NTLNK,(P1)	; get next on list
	MOVE T2,NCTVT+1(T1)	; Get next pointer
	STOR T2,NTLNK,(P1)	; Link it to this one
	AOBJN T1,MNTIN0		; Loop through all
	SETZRO NTLNK,(P1)	; Clear last pointer (End of list)

;[8975] Read SYSTEM:INTERNET.ADDRESS file and then return

	CALL ADRINI		;(/) Get our address read
	 BUG.(INF,NOADDR,MNETDV,SOFT,<Failed to find SYSTEM:INTERNET.ADDRESS file>,,<

Cause:	The SYSTEM:INTERNET.ADDRESS file was either not found or is corrupted.

Action:	Insure that the file is in SYSTEM: and is valid.
>,,<DB%NND>)			;[8969][7.1261] 
;Load the internet host names file

	TMSG <
[Loading Internet host names]>	;[8975] Tell CTY what is happening
	CALL HSTINI		;[8975] (/) Get the system to know site names
	IFSKP.			;[8975] If it worked
	  TMSG < [OK]
>				;[8975] Tell me it worked
	ELSE.			;[8975] So, HSTINI didn't skip return
	  BUG.(INF,NOHSTN,MNETDV,SOFT,<Failed to find host name file SYSTEM:HOSTS.TXT>,,<

Cause:	The SYSTEM:HOSTS.TXT file was not found.  The file SYSTEM:HOSTS.DEBUG
	is used if DBUGSW is 2 or greater.

Action:	Insure that the appropriate file is in SYSTEM: and is valid.
>,,<DB%NND>)			;[7.1261] 
	ENDIF.			;[8969]
	CALL NETHSI		;(/) Initialize the network hash table

;Enable networks if needed.

	MOVE T1,DBUGSW		; Get system switch
	CAIG T1,1		; are we stand alone?
	 TDZA T1,T1		; we are not stand alone
	  MOVEI T1,1		; we are stand alone
	SKIPE DBUGIP		; IP Debuging?
	 XORI T1,1		; yes so reverse flag
	SKIPN T1		; System normal?
	 SKIPN DEFADR		; Did addresses initialize properly?
	  JRST MNTINX		; No, return now
	JRST MNTON1		; Go turn on networks
;LKSTOR - Lock down a region of core
;Call with 1/ Xtended address of start
;	   2/ Xtened address of end
;Returns +1 always

LKSTOR:	TRZ T1,777		; Round down to nearest page

LKST1:	PUSH P,T1		; Save start
	PUSH P,T2		; and end
	CALLX (MSEC1,MLKMA)	; Lock down the page
	POP P,T2		; Restore ACs
	POP P,T1		; ...
	ADDI T1,PGSIZ		; Increment to next page
	CAMG T1,T2		; Past last address?
	JRST LKST1		; Loop
	RET
	SUBTTL MNETON - Turn Networks On if They Have Never Been On

;Turn networks on if NETSUP has been off.  Called by CALL MNETON$X or by MNTINI

XNENT (MNETON,G)		;MNETON::

MNTON1:	SKIPA P1,NCTVT		; Point to vector table
MNTON2:  LOAD P1,NTLNK,(P1)	; get next in list
	JUMPE P1,MNTINY		; Return when done
	MNTCALL NTINI		; Initialize network device
	SETOM NETON(P1)		; Turn it on
	SETZM NTPRIO(P1)	; Clear priority cell
	MNTCALL NTRSRT		; get it going
	JRST MNTON2		; and loop
MNTINY:	SETOM NETSUP		; Networks are now initialized
MNTINX:	RET			; And return
	SUBTTL CHKR Fork Routines -- MNTCHK - Periodic Check

;CHKR Fork routine for keeping things going on all nets. Called every
;four minutes or whenever JB0FLG is non-zero.

XNENT (MNTCHK,G)		;MNTCHK::, XMNTCH::
	SKIPA P1,NCTVT		; Point to the vector table
MNTCH0:	 LOAD P1,NTLNK,(P1)	; Get next in list
	JUMPE P1,MNTCH2		; Go check the rest 
	SKIPE NTSTCH(P1)	; Change of state?
	 CALL MNTSTS		; Yes
	SKIPN NETON(P1)		; If network off
	 JRST MNTCH0		; Loop
				; Want net on
	MNTCALL NTSCHK		; Check status, keep stuff consistent
	 JFCL			; Ignore error return
	SKIPG NETON(P1)		; If needs restarting
	 SKIPL NTRDY(P1)	; Or isn't ready
	  MNTCALL NTRSRT	; Restart it
	MOVE T1,TODCLK		; Get time now
	CAML T1,NTTOUT(P1)	; Output timed out?
	 SKIPN NTTOUT(P1)	; Output actually going?
	  JRST MNTCH1		; No timeout
	BUG.(INF,NTOHNG,MNETDV,SOFT,<Network output hung>,<<P1,ENTRY>>,<

Cause:	Multinet has declared the output interface for a network hung.
	The network interface is reset.

Data:	ENTRY - Entry into NCT Vector table of hung interface
>)
	MNTCALL NTRSRT		; If timeout, reset net
MNTCH1:	MNTCALL NTISRT		; Make sure input is happening
	MOVE T1,SCTLW		; System shutdown?
	TXNN T1,<1B3>
	 JRST MNTCH0		; No, loop through all
				; System shutdown
	SETZM NTRDY(P1)		; Imp off
	SETZM NETON(P1)		; Net off
	SETZM NTORDY(P1)	; output off
	SETO T1,		; Abort entry
	MNTCALL NTKILL		; Drop ready line
	JRST MNTCH0		; and loop through the rest

MNTCH2:
	SKIPE IMPGDM		; Any "imp going down" messages?
	 CALL CHKI7		; Yes, go print it
	RET			; And return
	SUBTTL CHKR Fork Routines -- MNTSTS - Report Network State Changes
       
;[8982] Here to log network change of state, returns +1 always
;Call with P1/ NCT index
;Returns +1 always

MNTSTS:	SKIPGE NTLADR(P1)	;Is there an address set?
	RET			;Don't report if no address set
	STKVAR <<MNTMSG,40>>	;Place to build message
	SETZM NTSTCH(P1)	;Reset the state change time
	MOVEI T1,MNTMSG		;Point to the message area
	HRLI T1,(Point 7)	;Make a byte pointer into it
	HRROI T2,[ASCIZ/
[Internet Network /]		;Load initial part of message
	CALL MNTSTO		;(T1,T2/T1) Copy a part of the string
	CALL NETPRT		;(T1,P1/T1) Print out the network number
	HRROI T2,[ASCIZ / on/]	;Assume it is on
	SKIPN NETON(P1)		;Is it on?
 	HRROI T2,[ASCIZ / off/] ;No
	CALL MNTSTO		;(T1,T2/T1) Copy a part of the string
	HRROI T2,[ASCIZ /, Output on /] ;Assume on
	SKIPN NTORDY(P1)	;Is output on?
        HRROI T2,[ASCIZ /, Output off /] ;Nope, its off today
	CALL MNTSTO		;(T1,T2/T1) Copy a part of the string
	SETO T2,		;Use current time
	MOVX T3,OT%SCL		;Suppress columnation on the time
	ODTIM%			;Output the time that this is occuring
	 ERJMP .+1		;Avoid MONNEJ if no date and time set
	HRROI T2,[ASCIZ/]
/]				;Point to cleanup hitter
	CALL MNTSTO		;(T1,T2/T1) Store final string 
	IDPB T3,T1		;Insure null at end of string
	MOVE T1,JB0TT		;Load CTY terminal number
	HRROI T2,MNTMSG		;Point to message
	TTMSG%			;Send that to the CTY
	 ERJMP .+1		;No MONNEJs please

	SKIPN NTORDY(P1)	;Did the hardware come up?
	CALLRET INTDWN		;No, signal it's down
	CALLRET	INTUP		;Signal that it's available for use

	ENDSV.			;End of STKVAR for MNTSTS
;Local routine to print the network number for current NCT
;Call with P1/ NCT index and T1/ output pointer
;Returns +1 always, T1 updated

NETPRT:	STKVAR <NPRTX,NPRBP,NPRPTR> ;[8982] Local storage
	MOVEM T1,NPRPTR		;[8982] Save output pointer
	MOVE T1,NTNET(P1)	; Get the network number
	LSH T1,10		; Move it over one byte
	CAMG T1,[BYTE (4)0(8)0,377,377,377] ; Class A or B?
	LSH T1,10		; yes move it over one more byte
	CAMG T1,[BYTE (4)0(8)0,377,377,377] ; Class A?
	LSH T1,10		; yes move it over one more byte
	MOVEM T1,NPRTX		; save it
	MOVEI T1,.GTHNS		; Get host name function
	MOVE T2,NPRPTR		;[8982] Restore output pointer
	MOVE T3,NPRTX		; Get the network number
	GTHST%			; Output the network number
	 ERJMP NETPR1		; on error assume no name
	MOVE T1,T2		;[8982] Return pointer in T1
	RET 			; and return

NETPR1:	MOVX T1,<POINT 8,NPRTX,3> ;No net name, get the octet pointer
	MOVEM T1,NPRBP		; and save it
	MOVEI T4,4		; four octets
	MOVE T1,NPRPTR		;[8982] Reload output pointer
	MOVEI T3,12		;[8982] Output in decimal

NETPR2:	ILDB T2,NPRBP		; get a byte
	NOUT%			; output the octet
	 ERJMP .+1		; handle errors
	SOJE T4,R		; on the last one return
	MOVEI T2,"."		;[8982] Otherwise get a dot
	IDPB T2,T1		;[8982] Store that please
	JRST NETPR2		; and do the rest
	ENDSV.

;[8982] Local routine to append to a string 
;Call T1/ destination pointer, T2/ source pointer (-1,,addr)
;Returns +1 always, T1 and T2 updated, T3/ 0

MNTSTO:	TLC T2,-1		;Is the source
	TLCN T2,-1		; minus one?
	HRLI T2,(POINT 7)	;Yes, make a byte pointer
MNTST1:	ILDB T3,T2		;Get a source byte
	JUMPE T3,R		;Return if null
	IDPB T3,T1		;Store it
	JRST MNTST1		;Get another character
	SUBTTL Low and High Priority Packet Output Queueing

;NTHSND - Put packet on High priority Q.
;T2/ packet pointer
;P1/ NCT address
;Returns+1	Refused
;Returns+2	Packet succesfully queued

	XRESCD

NTSNDX:	BUG.(CHK,BADADR,MNETDV,SOFT,<No NCT for address>,<<T1,ADR>>,<

Cause:	The multinet output queuing mechanism was called for a local
	address that has not been defined.

Data:	ADR - Host address
>)
	RET			; return

NTHSND::SAVEAC <P1>
	CALL FNDNCT
         JSP CX,NTSNDX		; Nope
	XMOVEI T1,NTHOBO(P1)	; Point to Q
	JRST NTQPKT		; And queue it

;NTLSND - Put packet on low priority Q
;T2/ packet pointer
;P1/ NCT address
;Returns+1	Refused
;Returns+2	Packet succesfully queued

NTLSND::SAVEAC <P1>
	CALL FNDNCT
         JSP CX,NTSNDX		; Not found
	XMOVEI T1,NTLOBO(P1)
	JRST NTQPKT
	SUBTTL NTWPKT - Packet Queueing Routine

;NTWPKT - Put packet on FIFO Q
;T1/	pointer to Q head
;T2/	packet pointer
;P1/	NCT address
;Returns+1	Refused
;Returns+2	Packet succesfully queued

NTQPKT:	SKIPN NTORDY(P1)	; Output allowed?
         RET			; No, fail
	TRNN T2,-1		; Is the address good?
	BUG.(HLT,BADBUF,MNETDV,SOFT,<Null buffer address>,,<

Cause:	Multinet has been called to queue an output buffer with a null
	address.
>)
	HRRZS 0(T2)		; Make sure succesor chain is NIL
	PIOFF			; Insure intergrety of queues
	SKIPE T3,1(T1)		; Q empty?
         JRST NTQPK2		; No, put on tail
	MOVEM T2,0(T1)		; Yes, set head pointer
	SKIPA			; Don't chain, no predecessor
NTQPK2:	 STOR T2,NBQUE,(T3)	; Chain from predecessor to new guy
	MOVEM T2,1(T1)		; This is new tail of Q
	PION			; Allow interrupts again
	MNTCALL NTOSRT		; Start output if needed
	RETSKP			; And return succesfully
	SUBTTL NTSNDI - Queue an Internet Packet

;NTSNDI - Default routine for enquing an internet packet
;      T1/	Local host
;      T2/	packet pointer
;      P1/	NCT address
;Returns+1	Refused,  T1 has an ICMP error code
;Returns+2	Packet succesfully queued

NTSNDI::MNTCALL NTOTOK		; Can this packet be sent?
         RET			; No, T1 has reason
	MNTCALL NTLLDR		; Make a local header
	XMOVEI T1,NTIOBO(P1)	; Point to right Q
	CALL NTQPKT		; And Q the packet
	 CAIA			; Failed
	  RETSKP		; Success
	MOVX T1,<ICM%SQ>	; Back off a minute, interface unusable
	RET			; return
	SUBTTL FNDNCT and NETACT - Routines to Find NCTs

;FNDNCT - Host number to NCT
;T1/	Host address
;Returns+1	No NCT for that net
;Returns+2	P1/ pointer to the NCT for a (usable) interface on that net

FNDNCT::SAVET			; Save temps
	NETNUM T2,T1		; Get the network number
	CALL NETHSH		; Look it up in the tables
	 RET			; No, knowledge of that net
	SKIPL P1,NETGWY(T2)	; Get the interface
	 RET			; Not directly connected
	RETSKP			; And skip return

;NETNCT - Host or Net to NCT of a (possibly down) interface on that net.

;T1/	Host address or Net number
;Returns+1	No NCT for that net
;Returns+2	P1/ pointer to the NCT for a (usable) interface on that net

NETNCT::SAVET			; Save temps
	TXNN T1,-1B11		; Host address?
	  JRST NETNC0		; No
	NETNUM T1,T1		; Get the network number
NETNC0:	XMOVEI P1,NCTVT		; Point to the table
NETNCL:	LOAD P1,NTLNK,(P1)	; Get net in the chain
	JUMPE P1,R		; No more
	CAMN T1,NTNET(P1)	; Same network?
	  RETSKP		; yes, success
	JRST NETNCL		; else loop
	SUBTTL HSTHSH - Find Host Table Entries

;Given a host number in T1 finds entry for that number in host tables.
;Call: T1/ host number
;Returns+1 if not found
;Returns+2 found, T2/ is table index, or -1 if no more room in tables.

HSTHSH::
	MOVE T2,T1		;DO A HASH
	IDIVI T2,NHOSTS		;GET INITIAL GUESS, DIV BY PRIME
	EXCH T2,T3		;2/ FIRST GUESS
	IDIVI T3,NHOSTS		;DIV BY PRIME AGAIN
	CAIN T4,0		;GET INCREMENT
         MOVEI T4,1
	MOVEI T3,NHOSTS		;COUNTER FOR GUESSES
	SETSEC T2,INTSEC	;LOOK IN THE RIGHT SECTION
HSTHLP:	ADDI T2,HOSTNN		;[8828] Point to host name
	SKIPLE (T2)		;[8969][8828] No host there?
	IFSKP.			;[8969][8828] If not,
	  SUBI T2,HOSTNN	;[8828] Point to hash block again
          RET			;NO, 2/ WHERE TO PUT IT
	ENDIF.			;[8828]
	CAME T1,(T2)		;[8828] Match?
	IFSKP.			;[8828] If so,
	  SUBI T2,HOSTNN	;[8828] Point back to hash block
          RETSKP
	ENDIF.			;[8828]
	SUBI T2,HOSTNN		;[8828] Point back to hash block
	ADDI T2,(T4)		;STEP BY INCREMENT
	CAML T2,[XWD INTSEC,NHOSTS] ;CHECK FOR OVERFLOW
	SUBI T2,NHOSTS		;WRAP AROUND IF NEEDED
	SOJG T3,HSTHLP		;COUNT DOWN GUESSES
	SETO T2,		;-1 TABLE FULL
	RET			;RETURN ERROR
	SUBTTL Host, Network Status and Configuration Routines

	XSWAPCD

;NETCHK - Check if our interface on a given net is up
;T1/	Host number
;Returns+1	if interface is down
;Returns+2	if it is up

NETCHK::SAVEAC <P1>
	CALL NETNCT		; Find the NCT
	 TRNA			; No such Net
	SKIPL NTRDY(P1)      	; Network up?
	RET			; No
	RETSKP			; Yes, return good

;NETCMP - Check if a host is on a given interface.

;T1/	Host number
;P1/	Pointer to NCT
;Returns+1	if host is not on that interface
;Returns+2	if it is

NETCMP::SAVET			; Save temps
	NETNUM T1,T1		; Get the net number
	MOVE T2,NTNET(P1)	; And that of this NCT
	CAME T2,T1		; Same?
	 RET			; No
	RETSKP			; Yes

;LCLNET - Check if a host address is on a net we're connected to.
;T1/	Host address
;Returns+1	If no intersecting network
;Returns+2	If we have an intersecting network
;(Note that this doesn't mean that the interface is currently usable)

LCLNET::SAVET			; Save temps
	NETNUM T1,T1		; Get the net number
	XMOVEI T3,NCTVT		; Point to the interface table
LCLNT0:	LOAD T3,NTLNK,(T3)	; get the next in the list
	JUMPE T3,R		; end of the list
	CAMN T1,NTNET(T3)	; On this network?
	 RETSKP			; yes, return success
	JRST LCLNT0		; loop through all

;LCLHST 
;Check  if  a  given  address (possibly with non-zero logical host
;field) is one of ours
;T1/	32 bit address
;Returns+1	if it is not one of ours
;Returns+2	if it is

LCLHST::SAVEAC <P1>
	PUSH P,T1		; Save address
	SKIPA P1,NCTVT		; First interface
LCLHS0:  LOAD P1,NTLNK,(P1)	; Next interface
	JUMPE P1,LCLHS9		; No more
	MOVE T1,(P)		; Address again
	ANDCM T1,NTNLHM(P1)	; without logical host field
	CAME T1,NTLADR(P1)	; Is this one of ours?
         JRST LCLHS0		; No, loop through all

	AOS -1(P)		; Success! it's me, skip return
LCLHS9:	POP P,T1		; Restore address
	RET
	SUBTTL Routines Dealing With Network Shutdown

;T1/ Reason, a la 1822
;T2/ GTAD when back up

XNENT (MNTHLT,G)		;MNTHLT::
				; Tell all interfaces we are going away.
	SAVEAC <P1>
	STKVAR <<MHLTRS,2>>
	DMOVEM T1,MHLTRS	; save the time and reason
	MOVX T1,<377777777777>	; Stop pings
	MOVEM T1,PINGTM		; Save new ping time
				; shutdown each interface
	SKIPA P1,NCTVT		; Get pointer to tables
MNTHL2:	 LOAD P1,NTLNK,(P1)	; Get next NCT
	JUMPE P1,R		; done?
	SETZM NETON(P1)		; No, say that we want this interface off.
	DMOVE T1,MHLTRS		; Get why/when.
	MNTCALL NTKILL		; Do halt instruction
	JRST MNTHL2		; Loop through all
	SUBTTL Routines Dealing With Network States

;MNTSET - Set a network status.
;	T1/	Network number, or host address
;	T2/	value
; Possible values are:  -ive = on
;			zero = off
;			+ive = request cycle

MNTSET::SAVEAC <P1>
	CALL NETNCT		;(T1/P1) Find the NCT
         RET			;Return now if none
	SKIPGE T2		;Skip if -ive argument
	SETO T2,		;Normalize it to -1
	SKIPLE T2		;[9108] Skip if not +ive
	HRRZI T2,-1		;[9108] Insure 0,,-1 for +ive quantity
	MOVEM T2,NETON(P1)	; Set function

	IFE. T2			;[9108] Turn interface off?
	  SETOB T1,T2		;[9108] Load -1 arguments
	  MNTCALL NTKILL	;[9108] (T1,T2,P1/) Kill interface
	ELSE.			;[9108] Not turning off
	  IFG. T2		;[9108] Is a cycle requested?
	    SETOB T1,T2		;[9108] Load arguments
	    MNTCALL NTKILL	;[9108] (T1,T2,P1/) Kill interface
	  ENDIF.		;[9108] End of cycle requested code
	  MNTCALL NTRSRT	;[9108] (P1/) Restart the hardware
	  MNTCALL NTISRT	;[9108] (P1/)  and start input
	ENDIF.			;[9108] End of action code

	AOS INTFLG		; Ask for the internet fork
	RETSKP			; Success return

MNTRED::			; ROUTINE TO RETURN NETWORK STATE
	SAVEAC <P1>
	SETZ T2,		; ASSUME NET IS DOWN
	CALL NETNCT		; GET THE NCT
         RET			; NO NCT
	MOVE T2,NETON(P1)	; GET THE STATE
	RETSKP			; SUCCESS RETURN
	SUBTTL Routine to Resolve Interface State

MNTRSV::			; Resolve interface state (P1/ NCT)
	SKIPL NETON(P1)		; do we want it up?
	 JRST MNTRS2		; no
	SKIPE NTRDY(P1)		; yes. is it up?
	 RET			; want up and is up so return.
	CALL @NTRSRT(P1)	; want up and is down so make it up.
	RET			; and return

MNTRS2:				; Here when not wanted up.
	SKIPE NETON(P1)		; want it down?
	 JRST MNTRS3		; no must want it cycled.
	SKIPN NTRDY(P1)		; is it down?
	 RET			; want down and is down so return.
	CALL @NTKILL(P1)	; want down and is up so take it down.
	RET			; and return to caller

MNTRS3:				; here when we want to cycle
	SKIPE NTRDY(P1)		; is it up now?
	 CALL @NTKILL(P1)	; yes so make it down
	SETOM NETON(P1)		; and say that we want it up
	RET			; and return to caller
	SUBTTL Host File Routines -- Read SYSTEM:HOSTS.TXT -- Initialization

COMMENT \

Initialize the host tables.  Called at system startup (and possibly other
times).  Reads in SYSTEM:HOSTS.TXT or SYSTEM:HOSTS.DEBUG and sets up the host
tables from it.  The format of the file is documented in RFC 952, "DoD Internet
Host Table Specification", which is available online at the NIC.  [9108] The
host table lock is now acquired during the time we are playing with the tables.

The host tables are put in INTSEC and have the following format:

Tables indexed by a hash of the host number:

	HOSTNN - The 32 bit host number
	HSTSTS - Status bits
	HOSTPN - index in HOSTN of primary name for this number

Tables indexed by order in the host name file:

	HOSTN - LH 18 bit address in HSTNAM
	        RH Index into hashed tables

HSTNAM - a block NHSTN long which holds the null terminated name strings
\
	TMPBSZ==10		;[8969] Size of TRVAR for temp buffer in words
	LINBSZ==^D80		;[8975] Size of TRVAR of line buffer in words

HSTINI::SAVEP			;[8975] Save P1-P4
	TRVAR <<TMPBUF,TMPBSZ>,<LINBUF,LINBSZ>,NAMPTR,NAMIDX,NAMSPC,NAMCNT,SAVPDL,BOL,TERM,HSTS,HBEST,HGOOD,NAMLST,NUMLST,NETMSK,ENTTYP,HSTFIL,HSTPGC,HSTPAG,HSTPTR,HSTCNT> ;[8969][8975]
	SETOM HSTPAG		;[8975] Start with page 0 of file
	SETZM HSTCNT		;[8975] No characters available to read
	MOVEM P,SAVPDL		;[8975] Save a stack fence in case of errors

	CALL LCKGTH		;[9108] (/) Lock the host table for us

;Open up the proper HOSTS.TXT or HOSTS.DEBUG file based on DBUGSW.

	MOVX T1,GJ%SHT!GJ%OLD	;GTJFN FLAGS.  FILE MUST EXIST.
	MOVE T2,DBUGSW		;[7.1243] Load debug switch
	CAILE T2,1		;[7.1243] Is it 2 or above?
	SKIPA T2,[-1,,[ASCIZ/SYSTEM:HOSTS.DEBUG/]] ;[7.1243] Yes, use debug ver
	HRROI T2,[ASCIZ/SYSTEM:HOSTS.TXT/] ;[7.1243] No, usual filename
	MOVEM T2,HSTFIL		;[8975] Remember the filename we used today
	GTJFN%			;Look for the file
	 ERJMP ULKGTH		;[9108] (/) Not found (probably), unlock, ret
	MOVEM T1,P3		;[8975] Save the JFN
	MOVX T2,7B5!OF%RD	;We need read access and 7 bit bytes
	OPENF%			;Open up the JFN
	 ERJMP HSTIE1		;Handle errors
	SIZEF%			;Get size of file
	 ERJMP HSTIE1		;Punt file
	MOVEM T3,HSTPGC		;Save page count	
;Initialize table pointers and clear all memory associated with these tables.

	PUTSEC T1,INTSEC	;INITIAL HOSTN INDEX
	MOVEM T1,NAMIDX
	MOVEI T1,NHOSTN		;SIZE OF HOSTN
	MOVEM T1,NAMCNT		;SAVE
	MOVNI T1,NHSTN		;SIZE OF NAME SPACE
	MOVEM T1,NAMSPC		;SAVE
	PUTSEC T1,INTSEC	;INITIAL INDEX INTO NAME SPACE
	MOVEM T1,NAMPTR		;SAVE

	MOVE T1,[XWD INTSEC,HSTNAM] ;CLEAR THE CURRENT TABLES
	SETZM 0(T1)		;CLEAR FIRST WORD OF NAME SPACE
	MOVE T2,[XWD HSTNAM,HSTNAM+1] ;GET THE BLT AC
	BLT T2,NHSTN-1(T1)	;ZAP
	MOVE T1,[XWD INTSEC,HOSTN] ;GET THE ADDRESS OF HOSTN
	SETZM 0(T1)		;ZERO THE FIRST WORD
	MOVE T2,[XWD HOSTN,HOSTN+1] ;GET THE BLT AC
	BLT T2,NHOSTN-1(T1)	;ZERO THE REST OF THE TABLE
	PUTSEC T1,INTSEC	;GET AN INDEX INTO THE CORRECT SECTION
	ADDI T1,HOSTNN		;[8828] Point to host number
	SETZM (T1)		;[8828] Zero the first word of HOSTNN
	MOVE T2,[HOSTNN,,HOSTNN+1] ;GET THE BLT AC
	BLT T2,NHOSTS-1(T1)	;[8828] Zero the rest of HOSTNN
	ADDI T1,<HSTSTS-HOSTNN>	;[8828] Start at first word of status
	SETZM (T1)		;[8828] Zero the first word of HSTSTS
	MOVE T2,[HSTSTS,,HSTSTS+1] ;GET THE BLT AC
	BLT T2,NHOSTS-1(T1)	;[8828] Zero the rest of HSTSTS
	SUBI T1,HSTSTS		;[8828] Set back to hash address
	SETZM HOSTPN(T1)	;ZERO THE FIRST WORD OF HOSTPN
	MOVE T2,[HOSTPN,,HOSTPN+1] ;GET THE BLT AC
	BLT T2,HOSTPN+NHOSTS-1(T1) ;ZERO THE REST OF HOSTPN
;Set up mask of preferred network for later use.

	MOVE T1,PRFNET		;GET PREFERRED NETWORK NUMBER
	MOVX T2,<MASKB 4,27>	;NETWORK MASK FOR CLASS C NETWORK
	LSH T1,^D8		;SHIFT INTO POSITION FOR CLASS C NETWORK
	CAMN T1,PRFNFD		;CLASS C?
	IFSKP.
	  MOVX T2,<MASKB 4,19>	;NETWORK MASK FOR CLASS B NETWORK
	  LSH T1,^D8		;SHIFT INTO POSITION
	  CAMN T1,PRFNFD	;CLASS B?
	  ANSKP.
	    MOVX T2,<MASKB 4,11> ;NETWORK MASK FOR CLASS A NETWORK
	    LSH T1,^D8
	    CAME T1,PRFNFD	;CLASS A?
	    BUG.(HLT,HSTNET,MNETDV,SOFT,<PRFNFD or PRFNET incorrect>,,<

Cause:	The preferred network number is messed up.  This probably indicates
	that the SYSTEM:INTERNET.ADDRESS file is messed up.
>)
	ENDIF.
	MOVEM T2,NETMSK		;SAVE HOST MASK FOR LATER
	SUBTTL Host File Routines -- Read SYSTEM:HOSTS.TXT -- Read Entry

;Start of loop to read a line from the host file and add it to the host table.

HSTIN6:				;LOOP FOR PROCESSING ENTRIES
	MOVE P,SAVPDL		;[8975] Reset stack fence
	CALL GLINE		;[8975](P3/P4) Read a (non comment) line in
	 JRST HFILDN		;[8975] Done with file
	CALL RDFLD		;(P4/P4,T1) Read a field from the file
	MOVE T1,TMPBUF		;GET FIRST WORD
	SETZ T2,		;ZERO MEANS UNKNOWN TYPE OF ENTRY
	CAMN T1,[ASCIZ/HOST/]	;HOST?
	MOVX T2,HS%SRV		;YES
	CAMN T1,[ASCIZ/NET/]	;NETWORK?
	MOVX T2,HS%NET		;YES
	CAMN T1,[ASCIZ/GATEW/]	;GATEWAY?
	MOVX T2,HS%GAT		;YES
	JUMPE T2,HSTIE6		;[8975] Owie if not one of the above three
	MOVEM T2,ENTTYP		;SAVE ENTRY TYPE

;Read in all host numbers, pushing them onto the stack after each one is read.
;A -1 is pushed onto the stack at the end of the host numbers.

	MOVEM P,NUMLST		;SAVE POINTER TO NUMBERS
HSTIN7:				;LOOP FOR READING IN ALL THE NUMBERS
	CALL RDHNUM		;(P4/P4,T1) Read a host number
	CALL HSTHSH		;(T1/T1,T2) Hash it into the tables
	 NOP			;Ignore skip return
	JUMPL T2,HSTIE2		;[8975] No room in tables for this host
	PUSH P,T2		;[8975] Save the index on the stack
	ADDI T2,HOSTNN		;[8828] Point to host number
	MOVEM T1,(T2)		;[8828] Save the host number in HOSTNN
	MOVE T1,TERM		;Get field terminator
	CAIN T1,","		;[8975] Comma terminated this hostnumber?
	JRST HSTIN7		;[8975] Yes, get more host numbers 
	CAIE T1,":"		;End of list?
	JRST HSTIE7		;[8975] Nope
	PUSH P,[-1]		;Flag end of list of host numbers
;All addresses are on the stack.  Read in all names, BLTing them to the HSTNAM
;area and saving their addresses on the stack.

	MOVEM P,NAMLST		;START OF NAME LIST 
HSTIN9:
	CALL RDFLD		;(P4/P4,T1) Read the next field
	JUMPE T1,HSTIE3		;If no host name read, a format error
	ADDI T1,1		;COUNT THE NULL TERMINATOR
	IDIVI T1,5		;CONVERT CHAR COUNT TO WORD COUNT
	SKIPE T2		;Round up if needed
	ADDI T1,1		;Yes, round up
	PUSH P,T1		;Save number of words needed
	ADDM T1,NAMSPC		;DECREMENT NAME SPACE LEFT
	SKIPLE NAMSPC		;TABLE FULL?
	JRST HSTIE4		;Yes, error
	MOVE T1,0(P)		;Get count of words in name back
	XMOVEI T2,TMPBUF	;Point to name read
	MOVE T3,NAMPTR		;Get offset of start of space in that table
	ADDI T3,HSTNAM		;Add in address of beginning of table
	CALL XBLTA		;(T1,T2,T3/) Move the name
	POP P,T1		;Restore count of words in name
	PUSH P,NAMPTR		;Save this index
	ADDM T1,NAMPTR		;Update table
	MOVE T1,TERM		;Get terminator
	CAIN T1,","		;[8975] Comma terminated this hostnumber?
	JRST HSTIN9		;[8975] Yes, get more host numbers 
	CAIE T1,":"		;End of list?
	JRST HSTIE9		;[8975] Nope, error here
	PUSH P,[-1]		;FLAG END OF LIST

;All names have been read.  If this entry is for a HOST, skip over the machine
;type and get the operating system type.

	MOVE T2,ENTTYP		;GET ENTRY TYPE
	CAME T2,[HS%SRV]	;SKIP IF A HOST ENTRY
	JRST HST12A		;NETS AND GW'S SKIP MACHINE TYPE/OS/PROTOCOLS
	CALL SKPFLD		;(P4/P4) Skip machine type
	CALL RDFLD		;(P4/P4,T1) Read operating system
	SETZ T2,		;Clear T2 incase a blank operating system type
	JUMPE T1,HSTI12		;Jump if no operating system type present
	MOVEI T1,OPSTAB		;Operating system type table
	MOVE T2,[POINT 7,TMPBUF] ;Point to name
	TBLUK%			;Lookup operating system type in table
	 ERJMP .+1		;Avoid MONNEJ
	TXNE T2,TL%NOM!TL%AMB	;No match?
	TDZA T2,T2		;Then no opsys
	HRRZ T2,(T1)		;else get table value of operating system type 
HSTI12:	TXO T2,HS%SRV		;Fold in OS type with server bit
HST12A:	MOVEM T2,HSTS		;Save entry type and operating system type
	SUBTTL Host File Routines -- Read SYSTEM:HOSTS.TXT -- Add Host

;Now things are set up as follows: NUMLST points to a list of HOSTNN indices
;for this host.  NAMLST points to a list of HSTNAM indices for its names.  HSTS
;holds the operating system type.

	HRRZ T3,NUMLST		;POINT TO LIST OF NUMBERS
	MOVE T2,NAMIDX		;INDEX OF PRIMARY NAME IN HOSTN

;This loop will select the primary address to reach this host as well as
;filling in HOSTPN and HSTSTS.  We will always prefer the PRFADR address in the
;event this is our local host.  Failing that, we prefer an address that is on
;PRFADR's network, which is presumably the best network to reach that host.
;Failing that, we prefer any network we are directly connected to, so we can
;avoid gateways.  If all else fails, we'll take the first listed address.

	SETZM HBEST		;INITIALLY NO BEST INDEX
	SETZM HGOOD		;NOR A GOOD INDEX

HSTI13:	SKIPG T4,1(T3)		;Get the next address to check
	JRST HSTI14		;DONE WITH THE LIST
	MOVEM T2,HOSTPN(T4)	;Save pointer to name in HOSTPN table
	MOVE T1,HSTS		;Load the operating system type and flags
	ADDI T4,HSTSTS		;[8828] Find status block
	MOVEM T1,(T4)		;[8828] Store operating system type
	SUBI T4,HSTSTS		;[8828] Restore to hash block address
	ADDI T4,HOSTNN		;[8828] Now point to host number
	MOVE T1,(T4)		;[8828] Get the number
	SUBI T4,HOSTNN		;[8828] Point back to hash block
	CAMN T1,DEFADR		;OUR DEFAULT ADDRESS IS ALWAYS BEST
	JRST HSTI15		;SO SET IT AS BEST UNCONDITIONALLY
	CAMN T1,PRFADR		;(PROBABLY UNNECESSARY) PREFERRED ADDRESS IS
	JRST HSTI15		; ALMOST AS GOOD
	SKIPE HBEST		;HAVE A BEST ADDRESS YET?
	JRST HSTI16		;YES, NO NEED TO CONSIDER ANY OTHERS
	AND T1,NETMSK		;NO, GET NETWORK BYTES ONLY
	CAME T1,PRFNFD		;IS THIS ADDRESS ON PREFERRED NETWORK?
	JRST HSTI17		;Nope, have to look a little bit
HSTI15:	MOVEM T4,HBEST		;YES, CONSIDER IT BEST
	JRST HSTI16		;And keep looking through addresses read in

HSTI17:	SKIPE HGOOD		;NOT ON DEFAULT NET, HAVE A GOOD ADDRESS YET?
	JRST HSTI16		;Yes, no need to look at this address
	ADDI T4,HOSTNN		;[8828] Point to host number
	MOVE T1,(T4)		;[8828] No, get address again
	SUBI T4,HOSTNN		;[8828] And now back to hash block
	CALL NETNCT		;(T1/P1,T1) Do we have an interface on that net
	JRST HSTI16		;Nope keep looking
	MOVEM T4,HGOOD		;YES, CONSIDER IT A GOOD ADDRESS

HSTI16:	AOJA T3,HSTI13		;LOOP THROUGH NUMBER LIST
;Here when the entire table of addresses we read in have been looked at.  If we
;got a best address (on preferred net with us) use that, otherwise use a good
;address if we are on that net, otherwise use the first address specified.

HSTI14:	HRRZ T2,NAMLST		;GET NAME LIST
	MOVE T3,NAMIDX		;GET INDEX INTO NAME TABLE
	SKIPE T1,HBEST		;GET BEST NUMBER INDEX
	JRST HSTI18		;Got one, use it
	SKIPE T1,HGOOD		;NO BEST INDEX, GET A GOOD INDEX
	JRST HSTI18		;Got one good address, use it
	HRRZ T1,NUMLST		;NO GOOD INDEX, POINT TO LIST OF NUMBERS
	MOVE T1,1(T1)		;USE FIRST AS DEFAULT

;Store the address we want to use for each name specified.

HSTI18:	SKIPG T4,1(T2)		;GET NEXT NAME ON THE LIST
	JRST HSTI19		;DONE
	STOR T4,HSTNMP,(T3)	;SET NAME POINTER
	STOR T1,HSTIDX,(T3)	;SAVE NUMBER INDEX
	MOVX T4,1B0		;NICKNAME FLAG
	HRRZ CX,NAMLST		;START OF LIST
	CAME T2,CX		;THIS THE FIRST NAME?
	IORM T4,HOSTN(T3)	;NO, FLAG AS A NICKNAME
	ADDI T3,1		;INCREMENT NAME TABLE INDEX
	SOSG NAMCNT		;COUNT DOWN TOTAL NUMBER OF NAMES
	JRST HSTIE5		;Oops the name tabe is full!
	AOJA T2,HSTI18		;Loop for all name names read

;All addresses stored, we are ready to get the next entry in the file

HSTI19:	MOVEM T3,NAMIDX		;SAVE NEW INDEX INTO NAME TABLE
	JRST HSTIN6		;ONWARD

;[8975] Here when read of hosts file has been completed, save number of hosts, 
;dump JFN, reset stack pointer, and skip return.

HFILDN:	HRRZ T1,NAMIDX		;Get count of host names
	MOVNM T1,MHOSTS		;Save
	SETZ T1,		;Indicate no mapping desired
	MOVEI T2,FPG0A		;Load address (not page number)
	CALL SETMPG		;(T1,T2/) Unmap old page
	MOVE T1,P3		;Get back JFN
	CLOSF%			;Close it
	 ERJMP .+1		;Avoid MONNEJ
	MOVE P,SAVPDL		;Get back stack fence
	CALL ULKGTH		;[9108] (/) Allow access to host table again
	RETSKP			;And skip return
	SUBTTL Host File Routines -- Table of Operating System Types

;
;TBLUK% table for operating system names

OPSTAB:	XWD NUMOPS,NUMOPS
	XWD [ASCIZ/ANTS/],.HSANT
	XWD [ASCIZ/ELF/],.HSELF
	XWD [ASCIZ/FOONEX/],.HS10X
	XWD [ASCIZ/FUZZ/],.HSFUZ
	XWD [ASCIZ/ITS/],.HSITS
	XWD [ASCIZ/MSDOS/],.HSDOS
	XWD [ASCIZ/MTIP/],.HSMTP
	XWD [ASCIZ/MULTICS/],.HSMLT
	XWD [ASCIZ/TAC/],.HSTAC
	XWD [ASCIZ/TENEX/],.HS10X
	XWD [ASCIZ/TIP/],.HSTIP
	XWD [ASCIZ/TOPS10/],.HSDEC
	XWD [ASCIZ/TOPS20/],.HST20
	XWD [ASCIZ/TOPS20AN/],.HST20
	XWD [ASCIZ/ULTRIX/],.HSUNX ;[8975]
	XWD [ASCIZ/UNIX/],.HSUNX
	XWD [ASCIZ/VMS/],.HSVMS
	XWD [ASCIZ/WAITS/],.HSDEC
NUMOPS=.-OPSTAB-1
	SUBTTL Host File Routines -- Read Line from File

;[8975] GLINE - Read a line in that isn't a comment line eating nulls
;Call with P3/ JFN of file
;Returns+1 if EOF
;Returns+2 with line read into LINBUF, P4/ pointing into LINBUF

GLINE:	SAVEAC <P1>		;Save the P
	MOVEI P1,<LINBSZ*5>-1	;Load space available in line buffer
	MOVEI P4,LINBUF		;Point to line buffer
	HRLI P4,(POINT 7)	;Make it a byte pointer

GLINE1:	CALL GCHAR		;(P3/T1) Get a character from the file
	 JRST HFILDN		;EOF
	CAIE T1,"!"		;Is it any flavor
	CAIN T1,";"		; of comment line?
	JRST GLINE7		;Yes, eat rest of line
	CAIN T1,.CHLFD		;Is it a line feed?
	JRST GLINE1		;Yes, a blank line was seen here
	CAIE T1,.CHCRT		;Is it a return or 
	CAIN T1,.CHFFD		; is it a form feed?
	JRST GLINE1		;Yes, check next character
	CAIE T1," "		;Space
	CAIN T1,.CHTAB		; or tab?
	JRST GLINE1		;Yep
	JRST GLINE2		;Nope, its a real line!

GLINE7:	CALL GCHAR		;(P3/T1) Get next character to eat
	 RET			;EOF in comment 
	CAIN T1,.CHLFD		;Is it EOL?
	JRST GLINE1		;Yes
	JRST GLINE7		;Nope, eat some more

GLINE3:	CALL GCHAR		;(P3/T1) Get the next character
	 MOVEI T1,.CHLFD	;EOF, load a line feed to tie off buffer

GLINE2:	IDPB T1,P4		;Store character in output buffer
	CAIE T1,.CHLFD		;End of loop?
	SOJG P1,GLINE3		;Nope, get more characters if room

	JUMPE P1,HFILTL		;Error if line too long
	MOVEI P4,LINBUF		;Point to line buffer
	HRLI P4,(POINT 7)	;Make byte pointer to that fine buffer
	RETSKP			;Skip return ourselves
	SUBTTL Host File Routines -- Read Character from File

;Routine to read one non null character from file.
;Returns +1 if EOF or error
;Returns +2 with T1/ character

GCHAR:	SOSGE HSTCNT		;Is there a character available?
	IFSKP.			;If so
	  ILDB T1,HSTPTR	;Get a character
	  JUMPN T1,RSKP		;Skip return for non null
	  JRST GCHAR		;Get next character
	ENDIF.			;End of characters available code

;No characters left, we have to play like we are a PMAP JSYS and get more data.

	SOSGE HSTPGC		;Count down one page
	RET			;End of file
	SETZ T1,		;Indicate no mapping desired
	MOVEI T2,FPG0A		;Load address (not page number)
	CALL SETMPG		;(T1,T2/) Unmap old page
	AOS T1,HSTPAG		;Get page number to map
	MOVE T2,P3		;Get JFN of the file
	IMULI T2,MLJFN		;Compute internal address of it
	HLL T1,FILOFN(T2)	;Get OFN,,pn
	MOVX T2,<PTRW!FPG0A>	;Get access and address of page to map
	CALL SETMPG		;(T1,T2/) Map that page in for us
	SKIP FPG0A		;Page fault it in
	 ERJMP R		;Return now if file damage
	MOVE T1,[POINT 7,FPG0A]	;Point to address we mapped file into
	MOVEM T1,HSTPTR		;Store the pointer to the data
	MOVEI T2,PGSIZ*5	;Load number of 7 bit bytes there
	MOVEM T2,HSTCNT		;Store as bytes available
	JRST GCHAR		;OK, now get a byte
	SUBTTL Host File Routines -- Read Field from File

;[8975] RDFLD - Read next field.  Field is terminated by a comma or colon.
;Leading spaces and tabs are eaten.
;
;Returns+1 always with
;	T1/ number of characters read
;	T2 and TERM/ terminating character
;	T3/ end of string pointer into TMPBUF
;	P4/ updated
;	TMPBUF/ string (Null terminated)
;ACs:
;	T1/ characters read
;	T2/ current character
;	T3/ pointer to TMPBUF (returned)
;	P4/ pointer to LINBUF (given)

RDFLD:	SETZ T1,		;Clear returned field length
	MOVEI T3,TMPBUF		;Point to temp buffer
	HRLI T3,(POINT 7)	;Make that a byte pointer
	SETZM TMPBUF		;First word of buffer must be zero

;Eat any leading spaces or tabs.

RDFLD1:	ILDB T2,P4		;Load byte from line pointer
	CAIE T2,.CHTAB		;Tab
	CAIN T2," "		; or space?
	JRST RDFLD1		;Yes, ignore it

;Read through and store the field until a comma or colon or space or tab or
;return or line feed is seen.

RDFLD2:	CAIE T2,":"		;Was it a colon
	CAIN T2,","		; or a comma?
	JRST RDFLDX		;Yes, this is the end of the field
	CAIE T2," "		;Was it a space
	CAIN T2,.CHTAB		; or tab?
	JRST RDFLDD		;Yes, eat until terminator seen
	CAIN T2,.CHLFD		;Line feed seen?
	JRST PEOLX		;Yes, error
	CAIL T2,"A"+40		;LOWER CASE?
	SUBI T2,40		;YES, RAISE
	IDPB T2,T3		;Save that character in the temp buffer
	AOS T1			;Count character we just stored
	CAIL T1,<TMPBSZ*5>-1	;Was that the last character?
	JRST PEFLDX		;Yep, this line is in error
	ILDB T2,P4		;Load next character from line
	JRST RDFLD2		;Continue 
;Here if space or tab seen after the field has been read, eat until terminator.

RDFLDD:	ILDB T2,P4		;Load a character from the line
	CAIE T2,","		;Was it a comma?
	CAIN T2,":"		; or a colon?
	JRST RDFLDX		;Yes, field terminator seen
	CAIN T2,.CHLFD		;Is it a line feed?
	JRST PEOLX		;Yes, error
	JRST RDFLDD		;Yes, loop until terminator seen

;Here when terminator seen, store it and the count and return.

RDFLDX:	MOVEM T2,TERM		;Save terminator
	SETZ T2,		;Load a null
	IDPB T2,T3		;Null terminates the string
	RET			; and return

;[8975] SKPFLD - Skip to next field (next ":").
;Returns +1 always.

SKPFLD:	ILDB T2,P4		;Load a byte from the pointer
	CAIN T2,":"		;Start of new field?
	RET			;Yes, done
	CAIN T2,.CHLFD		;Is it the end of line character?
	JRST PEOLX		;Yes so error
        JRST SKPFLD		;No, continue munching along
	SUBTTL Host File Routines -- Read Host Number

;[8975] RDHNUM - Read a host number.  Attempts to do it quickly since it will
;do it often.  Returns+1 always, T1/ number

;ACs:
;	T1/ host number returned 
;	T2/ character
;	T3/ current number accumulator
;	T4/ count of octets to read-1 (0 is last one)
;	P4/ pointer to line buffer

RDHNUM:	SETZ T1,		;Clear returned host number
	MOVEI T4,3		;Load the number of numbers to read -1

RDHNU1:	SETZ T3,		;Clear this digit's counter

RDNHU2:	ILDB T2,P4		;Load a character

	CAIE T2,.CHTAB		;I guess we could check for TABs too
	CAIN T2," "		;Is it a message from space?
	JRST RDNHU2		;Yes, eat it
	CAIN T2,.CHLFD		;Is it a linefeed?
	JRST RDHNE1		;Uh oh
	CAIE T2,","		;Is it a comma
	CAIN T2,":"		; or is it a colon?
	JUMPE T4,RDNHU3		;Yes, fine if last octet
	CAIN T2,"."		;Is it a dot?
	JUMPN T4,RDNHU3		;Yes, fine if not last octet
	CAIL T2,"0"		;Is it a
	CAILE T2,"9"		; digit?
	JRST RDHNE2		;Nope, error

;Appears to be a digit, count it in and continue reading

	IMULI T3,^D10		;Shift over previously accumulated digits
	ADDI T3,-"0"(T2)	;Convert character to binary and add it in
	JRST RDNHU2		; and get another character

;Here when comma or Dot seen, accumulate host number and loop for more or ret.

RDNHU3:	EXCH T3,T1		;Get octets read so far
	LSH T3,^D8		;Shift over by one octet
	ADDM T3,T1		;Add in new part of octet
	SOJGE T4,RDHNU1		;Count down and jump if more to read
	MOVEM T2,TERM		;Save terminator for later check
	RET			;And return
	SUBTTL Host File Routines -- Error Handlers

;Error handlers for HSTINI 

HSTIE1:	MOVE T1,P3		;[8975] Error on OPENF, recover the JFN
	RLJFN%			;Release the JFN
	 ERJMP .+1		;Ignore errors
	CALLRET ULKGTH		;[9108] (/) Unlock and return+1 to the caller

HSTIE2:	JSP T1,HFILER		;[8975] Can't hash it into tables
	ASCIZ/%Number tables full before end of / ;[8975]

HSTIE3:	JSP T1,HFILER		;[8975] No host name read
	ASCIZ/%Null name not allowed in / ;[8975]

HSTIE4:	JSP T1,HFILER		;[8975] Table out of space
	ASCIZ/%Name table out of space before end of / ;[8975]

HSTIE5:	JSP T1,HFILER		;[8975] We think that name table is full
	ASCIZ/%More than NHOSTN hosts in / ;[8975]

HSTIE6:	JSP T1,HFILER		;[8975] Not HOST, NET, or GATEW
	ASCIZ/%Unknown entry type in / ;[8975]

HSTIE7:	JSP T1,HFILER		;[8975] Not colon or comma after addresses
	ASCIZ/%Illegal character in address field in / ;[8975]

HSTIE9:	JSP T1,HFILER		;[8975] Not colon or comma after addresses
	ASCIZ/%Illegal character in name field in / ;[8975]

RDHNE1:	JSP T1,HFILER		;[8975] Linefeed in host number
	ASCIZ/%Missing host number in /	;[8975]

RDHNE2:	JSP T1,HFILER		;[8975] Illegal character in host number
	ASCIZ/%Bad host number format in / ;[8975]

PEOLX:	JSP T1,HFILER		;[8975] End of line when reading field
	ASCIZ/%Premature end of line in / ;[8975]

PEFLDX:	JSP T1,HFILER		;[8975] Oops, field too big
	ASCIZ/%Field too long in / ;[8975]

HFILTL:	JSP T1,HFILER		;[8975] Line too long by GLINE's account
	ASCIZ/%Line too long in / ;[8975]

;[8975] HFILER - Error printout routine.  Outputs line from HOSTS.TXT with
;an uparrow at the spot we stopped parsing.  HSTFIL points to hosts filename 
;we are reading.
;Call:	JSP T1,HFILER
;	ASCIZ/%error/
;Returns always to HFILDN

HFILER:	CALL TCRLF		;(/) Output a crlf first
	HRLI T1,(POINT 7)	;Make a byte pointer from the address
	PSOUT%			;Send that to the CTY please
	MOVE T1,HSTFIL		;Point to host filename again
	PSOUT%			;Send that to the CTY
	CALL TCRLF		;(/) Output yet another crlf
	MOVEI T2,LINBUF		;Point to line buffer
	HRLI T2,(POINT 7)	;Make it a byte pointer

HFILE3:	ILDB T1,T2		;Load a character from line buffer
	PBOUT%			;Print on the CTY
	CAIN T1,.CHLFD		;Terminator to this line?
	JRST HFILDN		;Done if end of this line
	CAME T2,P4		;Is it time for the signal character?
	JRST HFILE3		;Nope
	MOVEI T1,"^"		;Load uparrow
	PBOUT%			;Send to the CTY
	JRST HFILE3		;Loop for entire line

;Small routine to print a CRLF on the console terminal preserving T1
;Returns +1 always

TCRLF:	PUSH P,T1		;Save T1
	HRROI T1,CRLF		;Point to CRLF
	PSOUT%			;Send that to the CTY
	POP P,T1		;Restore T1
	RET			;Return to caller

	ENDTV.			;End of HSTINI TRVAR
	SUBTTL Address File Routines -- Read SYSTEM:INTERNET.ADDRESS

;ADRINI
;Reads in the file SYSTEM:INTERNET.ADDRESS and initializes the interface tables
;from it.  Called from MNTINI at system startup, does skip return if
;successful.

;Entries are of the form:
;	AN20#0, 10 0 0 79,NCP,PACKET-SIZE:1004,DEFAULT
;	IPNI#0, 192 5 6 1,PACKET-SIZE:1500,PREFERRED
;	IPCI#0, 192 5 5 4,PACKET-SIZE:632

; AC usage
;	P1/ NCT associated with local address in P2
;	P2/ Local address once read
;	P3/ JFN of input file
;	P4/ Pointer into line buffer

	BUFSIZ==10		;[8969] Size of temp string buffer
	LINSIZ==<^D135/5>	;[8975] Size of line buffer

ADRINI::SAVEPQ			;Watch your ps and qs
	TRVAR <<LINBUF,LINSIZ>,<TMPBUF,BUFSIZ>> ;[8975]
	MOVX T1,GJ%OLD!GJ%SHT	;[8975] Old file, short form
	HRROI T2,[ASCIZ /SYSTEM:INTERNET.ADDRESS/] ;The filename desired
	GTJFN			;[8975] Get a JFN on that file please
	 RET			;[8975] Can't, probably file not found
	MOVEM T1,P3		;[8975] Save JFN in P3
	MOVX T2,FLD(7,OF%BSZ)!OF%RD ;[8975] Open for reading
	OPENF			;[8975] Pry it open
	 ERJMP ADRINO		;[8975] Can't open it!

	SETZ T1,		; clear an index
ADRIN1:	SKIPN NLHOST(T1)	; slot used?
	JRST ADRLP0		; no, done with table, enter main loop
	SETOM NLHOST(T1)	; empty that slot
	AOJA T1,ADRIN1		; and loop
;Here to examine next line in file

ADRLP0:	CALL GBOL		;[8975](P3/P4) Read in a non-comment line
	 JRST ADRDUN		; Done with file

;Read in the interface type for keyword match

	CALL GFIELD		;[8975](P4/P4,T2) Read in a field today
	CALL REEAT		;[8975](P4/P4) Back up over the terminator

;The interface type has been read, see if it is in the table.

	MOVEI T1,INTNAM		; point to type table
	HRROI T2,TMPBUF		;[8975] Point to the buffer we use
	TBLUK			; and look it up
	 ERJMP .+1		;[8969] Avoid MONNEJ
	TXNE T2,TL%NOM!TL%AMB	; match?
	JRST ADRUIT		;[8975] Nope, unknown interface type
	HRRZ T4,(T1)		; get entry

;Read in interface number if needed

	CALL GCH		;[8975](P4/P4,T2) Get terminator
	 JRST ADIERR		;[8975] Not EOL here!
	CAIE T2,","		;[8975] Comma?
	IFSKP.			;[8975] If not
	  SETZ T2,		;[8975] Yes, use interface 0 
	ELSE.			;[8975] Not comma, should be number sign
	  CAIE T2,"#"		;[8975] Interface number?
	  JRST ADIERR		;[8975] Nope, error
	  MOVE T1,P4		;[8975] Point to line buffer
	  MOVEI T3,^D10		; read in decimal
	  NIN			;Read number into T2
	   ERJMP ADIERR		;[8969] Error, maybe EOF
	  MOVEM T1,P4		;[8975] Store pointer back
	ENDIF.			;[8975] And continue

	CALL REEAT		;[8975](P4/P4) Backup over terminator
	SETZ P1,		;[8975] In case no particular interface
	CAIN T4,NT.NIN		; No particular interface?
	JRST ADGNUM		; right, No NCT associated with it
; Now find the NCT for the interface
;	T2/ interface number
;	T4/ interface type

	XMOVEI P1,NCTVT		;[8975] Point to vector table
ADFINT:	MOVE P1,(P1)		;[8975] Get next in list
	JUMPE P1,ADIGON		;[8975] Specified interface is not found
	LOAD T1,NTDEV,(P1)	;[8975] Get interface type
	CAIE T1,(T4)		; Same as we're looking for?
	JRST ADFINT		; No, try next
	SOJGE T2,ADFINT		; Try another if not right number

;Read in the address on that interface, hash it into the table

ADGNUM:	CALL GCH		;[8975](P4/T4,T2) Get character
	 JRST ADRNER		;[8975] EOL
	CAIE T2,","		;[8975] Must be comma
	JRST ADRNER		;[8975] It wasn't
	CALL ADG4DB		;(T4,P4/T1) Get 4 decimal bytes into T1
	 JRST ADINER		;[8975] Error!
	MOVEM T1,P2		; Get into right register
	CALL HSTHSH		;(T1/T2) Hash it into table
	 JUMPL T2,NETFUL	; No room for number
	ADDI T2,HOSTNN		;[8828] Point to host number
	MOVEM P2,(T2)		;[8828] Put number in table
	MOVX CX,HS%UP!HS%SLF!HS%VAL ;It is me, I'm up, valid status
	ADDI T2,<HSTSTS-HOSTNN>	;[8828] Find status word
	IORM CX,(T2)		;[8828] Mark it so in status
	SUBI T2,HSTSTS		;[8828] Now restore hash block address

	SETZ T2,		; clear an index
ADGNM1:	SKIPLE NLHOST(T2)	; anything in this slot?
	AOJA T2,ADGNM1		; No, try next
	SKIPL NLHOST(T2)	; empty?
	JRST NETFUL		; No, table overflow.
	MOVEM P2,NLHOST(T2)	; save number
	JUMPE P1,ADGNM2		;[8975] Skip next if no NCT assoc with number
	MOVEM P2,NTLADR(P1)	;[8975] Set local address
	NETNUM T1,P2		; Get the network number
	MOVEM T1,NTNET(P1)	;[8975] Set it in NCT
ADGNM2:	CALL REEAT		;[8975](P4/P4) Reeat last character
;Now
;	P1/ NCT associated with local address in P2
;	P2/ Local address once read
;	P3/ JFN of input file
;	P4/ Pointer into line buffer

;Time to read in the keywords following the "interface[#n],address".
;Come to the top of this loop with the comma (or eol) next to be read.

ADRLP3:	CALL GCH		;[8975](P4/P4,T1) Check character after address
	 JRST ADRLP0		;[8975] EOF or EOL is OK
	CAIE T2,","		;[8969] Comma?
	JRST ADRKER		;[8969] Nope, format error

	CALL GFIELD		;[8975](P4/P4,T2) Get the next field
	CALL REEAT		;[8975](P4/P4) Backup over the terminator

	MOVEI T1,TYPNAM		; point to type table
	HRROI T2,TMPBUF		;[8975] Point to the buffer in question
	TBLUK			; and look it up in table
	 ERJMP .+1		;[8975] Avoid MONNEJ
	TXNE T2,TL%NOM!TL%AMB	; good name?
	JRST ADRUND		;[8969] No
	MOVE T1,(T1)		; get routine address
	CALL (T1)		; go to it
	JRST ADRLP3		; and loop
;DEFAULT keyword, used to set this address as the primary host name.

ADDFLT:	NETNUM T1,P2		; Get the network number
	MOVEM T1,DEFNET		; Save as default network number
	SKIPN PRFNET		; Preferred network set up?
	MOVEM T1,PRFNET		; Save as preferred network number
	MOVE T2,P2		; Get number
	ANDX T2,-1B27		; mask off network number (Class C)
	CAIG T1,177777		; Class B or A?
	ANDX T2,-1B19		; Mask for class B
	CAIG T1,377		; Class A?
	ANDX T2,-1B11		; yes, mask appropriately
	MOVEM T2,NETFLD		; Set as default network field
	MOVEM P2,DEFADR		; Save as default address
	SKIPN PRFNFD		; Preferred network field set up?
	MOVEM T2,PRFNFD		; Set as preferred network field
	SKIPN PRFADR		; Preferred address set up?
	MOVEM P2,PRFADR		; Save as preferred address
				; Kludge up the 8 bit host address
	MOVE T2,P2		; get number again
	ROTC T2,-6		; Save IMP number
	LSH T2,-^D10		; Flush middle bits
	ROTC T2,6		; Combine Host and IMP
	ANDI T2,377		; Round to 8 bits
	MOVEM T2,NOHOST		; Save in proper cell
	RET			; and return

;PREFERRED keyword to set this address as the preferred one for this host.

ADDPRF:	NETNUM T1,P2		; Get the network number
	MOVEM T1,PRFNET		; Save as preferred network number
	MOVE T2,P2		; Get number
	ANDX T2,-1B27		; mask off network number (Class C)
	CAIG T1,177777		; Class B or A?
	ANDX T2,-1B19		; Mask for class B
	CAIG T1,377		; Class A?
	ANDX T2,-1B11		; yes, mask appropriately
	MOVEM T2,PRFNFD		; Set as preferred network field
	MOVEM P2,PRFADR		; Save as preferred address
	RET
;NCP keyword, indicates that this network uses Arpanet NCP protocol

ADNCP:	MOVEI T1,NT.NCP		; get NCP network type
	STOR T1,NTTYP,(P1)	;[8975] Save in NCT
REPEAT 0,<			;[8969] This code is a slow no-op
	MOVE T1,NTNET(P1)	;[8975] Get the network number
	CAILE T1,^D255		; Valid type A address?
	 JFCL			; Error
; once host tables are right, find hosts for this net and set in NCP tables
>				;[8969] end of repeat 0
	RET			; and done

;PACKET-SIZE:n keyword, next parameter is the maximum packet size for this
;interface in decimal bytes.

ADPSIZ:	CALL GCH		;[8975] Read terminator of keyword
	 JRST ADRPER		;[8975] Uh oh
	CAIE T2,":"		;[8975] Must be colon
	JRST ADRPER		;[8975] Nope you lose today
	MOVE T1,P4		;[8975] Get pointer to data
	MOVEI T3,^D10		; decimal
	NIN
	 ERJMP ADRERP		;[8969] Error, invalid packet size
	MOVEM T1,P4		;[8975] Restore the pointer
	JUMPLE T2,ADRERP	;[8969] Jump if zero or -ive size
	MOVEM T2,NTPSIZ(P1)	;[8975] Save the size
	CALLRET REEAT		;[8975] (P4/P4) Reeat terminator and return

;LOGICAL-HOST-MASK keyword, next parameter is the 32-bit mask for this
;interface in decimal bytes.

ADLHM:	CALL GCH		;[8975] Read terminator of keyword
	 JRST ADRLER		;[8975] Uh oh
	CAIE T2,":"		;[8975] Must be colon
	JRST ADRLER		;[8975] Nope you lose today
	CALL ADG4DB		;(P4,T4/P4,T1) Read 4 decimal bytes
	 JRST ADRILH		;[8975] Can't read that logical host mask
	MOVEM T1,NTNLHM(P1)	;[8975] Save the mask
	CALLRET REEAT		;[8975](P4/P4) Reeat terminator and return
;Here when it is time to close the file and return +2 to our caller.

ADRDUN:	CLOSF			; Close the JFN
	 ERJMP .+1		;[8969] Avoid MONNEJ, don't worry if fails
	MOVE P2,NLHOST+0	; Get default default network
	SKIPN DEFADR		; was default address set?
	CALL ADDFLT		;(P2/) No, use this one as default
	RETSKP			; And return succesfully
	SUBTTL Address File Routines -- Get To Beginning Of Line

;[8975] GBOL - Read in a non-comment line for GCH.
;Call with P3/ JFN
;Returns +1 if EOF hit
;Returns +2 with LINBUF/ line read in, P4/ pointer into LINBUF

GBOL:	MOVE T1,P3		;Get JFN
	HRROI T2,LINBUF		;Point to line buffer
	MOVEI T3,<LINSIZ*5>-1	;Load maximum characters to read
	MOVEI T4,.CHLFD		;End of a line feed
	SIN%			;Read in a line of the file
	 ERJMPR GBOL7		;Error, could be EOF, check it out
	JUMPE T3,GBOL6		;Line too long?  This should not happen
	IDPB T4,T2		;Insure a line feed is at end of buffer
	MOVEI P4,LINBUF		;Point to line buffer
	HRLI P4,(POINT 7)	;Make it a byte pointer

;A line as been read into the line buffer.  See if it is a comment line or a
;blank line and if so, read another line.  

GBOL1:	CALL GCH		;(P4/T1) Get non-blank non-comment character
	 JRST GBOL		;Linefeed, nothing on this line
	CALL REEAT		;(P4/P4) Backup the pointer one character
	RETSKP			;Return +2 

;Here if line too long!

GBOL6:	TMSG <%Line too long in SYSTEM:INTERNET.ADDRESS
>
	SETZ P4,		;No pointer to this error
	CALL PERROR		;(P4/) Print this bad line please
	JRST GBOL		;Get another line

;Here when SIN returned an error, it should have been the usual IOX4 error.

GBOL7:	CAIN T1,IOX4		;Should be end of file
	RET			;EOF!
	TMSG <%Error while reading SYSTEM:INTERNET.ADDRESS
>
	RET			;Assume we are at EOF now

;[8975] Small routine to backup the byte pointer in P4
;Call with P4/ byte pointer
;Returns +1 always, P4/ backed up one character

REEAT:	SETO CX,		;Load a -1
	ADJBP CX,P4		;Get the byte pointer backed up one character
	MOVEM CX,P4		;Reload new byte pointer
	RET			;Return +1
	SUBTTL Address File Routines -- Read Character from File

;[8975] GCH - read the next non-comment, non-blank, non-null character
;Call with P4/ line buffer pointer
;Returns +1 if EOF or EOL
;Returns +2 if character T2/ character

GCH:	CALL GCH1		;(P4/T1) Get a byte
	 RET			;Gosh, EOF or EOL
	CAIE T2,"!"		;[8969] Is it a bang?
	CAIN T2,";"		; or a semi?
	JRST GCHSMC		;Yes, ignore it
	CAIE T2,.CHTAB		;Tab?
	CAIN T2," "		; or SPACE?
	JRST GCH		;Yes, skip it
	RETSKP			;Else return+2 with T2/character

GCHSMC:	CALL GBIN		;(P4/T1) Comment seen, get a byte
	 RET			;EOF or EOL
	JRST GCHSMC		;Loop for all characters until EOF or EOL

;Small routine to read characters, eats returns, nulls, and form feeds
;Call with P4/ line buffer pointer
;Returns +1 if EOF
;Returns +2 T1/ JFN, T2/ character

GCH1:	CALL GBIN		;(P4/T1) BIN a byte
	 RET			;Oops, EOF or EOL
	CAIE T2,.CHCRT		;Ignore return
	CAIN T2,.CHFFD		; and form-feed
	JRST GCH1		;It was one, eat it
	RETSKP			; return with T2/ character

;Small routine to do a BIN, eats nulls
;Call with P4/ line buffer pointer
;Returns +1 if EOF or EOL
;Returns +2 T2/ character

GBIN:	ILDB T2,P4		;[8975] Get a character from the line buffer
	CAIN T2,.CHLFD		;[8975] End of line?
	CALLRET REEAT		;[8975] Yep, reeat it and return
	JUMPN T2,RSKP		;Return good if character there
	JRST GBIN		;Flush nulls
	SUBTTL Address File Routines -- Read Field from File

;[8975] Routine to read a string into TMPBUF from the file.
;Call with P4/ pointer to line buffer
;Returns +1 always T2/ terminator which is not reeaten

GFIELD:	SETZM TMPBUF		;First word should be zero
	MOVEI T4,<BUFSIZ*5>-1	;Load total size of buffer
	MOVEI T3,TMPBUF		;Point to temp buffer
	HRLI T3,(POINT 7)	;Make a byte pointer

GFIEL1:	CALL GCH		;(P4/T2) Get character from file
	 JRST GFIEL2		;End of that field
	CAIE T2,"#"		;Is it a legal
	CAIN T2,","		; terminator?
	JRST GFIEL2		;Yep, end of that field
	CAIN T2,":"		;Is it a colon?
	JRST GFIEL2		;Yep, that's a terminator
	IDPB T2,T3		;Store that character in string
	SOJGE T4,GFIEL1		;Loop for all of them
		
GFIEL2:	SETZ T4,		;Load a zero
	IDPB T4,T3		;Store it at end of string
	RET			;Return to caller
	SUBTTL Address File Routines -- Read Four Decimal Bytes

;ADG4DB - Read in 4 decimal bytes from INTERNET.ADDRESS file
;Call:	T4/ String pointer to error message
;	P4/ Pointer to line buffer
;Returns+1 if failure
;Returns+2 Success, T1/ address

ADG4DB:	SETZ T4,		;[8975] Clear the returned mask word
	MOVEI Q1,4		;There are 4 fields to an address
ADG4D2:	MOVE T1,P4		;[8975] Get pointer to data
	MOVX T3,^D10		;Again decimal
	NIN			;Input number from terminal
	 ERJMP R		;[8975] Return +1 if error
	MOVEM T1,P4		;[8975] Restore pointer to data
	IORM T2,T4		;[8975] Merge in latest part
	SOJLE Q1,ADG4D8		;Count this digit and jump if 4 octets read
	LSH T4,^D8		;[8975] No shift over part read so far
	JRST ADG4D2		;Loop through all 4 fields

ADG4D8:	MOVEM T4,T1		;[8975] Return full address
	RETSKP			;[8975] Skip return
	SUBTTL Address File Routines -- Error Handlers

;[8975] Here on various format errors in INTERNET.ADDRESS

ADRUIT:	JSP T1,ADRERR		;[8975] TBLUK failed
	ASCIZ /%Unknown interface type/	;[8975]

ADIERR:	JSP T1,ADRERR		;[8975] Error on the NIN
	ASCIZ /%Error in interface number/ ;[8975]

ADIGON:	JSP T1,ADRERR		;[8975] Couldn't find the NCT for interface
	ASCIZ /%Specifed interface was not found/ ;[8975]

ADRNER:	JSP T1,ADRERR		;[8975] 
	ASCIZ /%Comma not after interface type/ ;[8975]

ADINER:	JSP T1,ADRERR		;[8975] Can't read address for this interface
	ASCIZ /%Invalid address/ ;[8975]

ADRUND:	JSP T1,ADRERR		;[8975] TBLUK failed
	ASCIZ /%Unknown network descriptor/ ;[8975]

ADRPER:	JSP T1,ADRERR		;[8975] Colon not after "PACKET-SIZE"
	ASCIZ /%Colon not after PACKET-SIZE/ ;[8975]

ADRERP:	JSP T1,ADRERR		;[8975]
	ASCIZ /%Invalid PACKET-SIZE/ ;[8975]

ADRLER:	JSP T1,ADRERR		;[8975] Colon not after "PACKET-SIZE"
	ASCIZ /%Colon not after LOGICAL-HOST-MASK/ ;[8975]

ADRILH:	JSP T1,ADRERR		;[8975] ADG4DB failed to read LHM
	ASCIZ /%Invalid LOGICAL-HOST-MASK value field/ ;[8975]

ADRKER:	JSP T1,ADRERR		;[8975]
	ASCIZ /%Format error in network interface descriptor list/ ;[8975]

;Here to write error string pointed to by T1, print line in error, and loop.

ADRERR:	HRLI T1,(POINT 7)	;[8975] Insure byte pointer in T1
	PSOUT			;Write error string to the CTY
	HRROI T1,[ASCIZ / in SYSTEM:INTERNET.ADDRESS file
/]				;[8969] Finish the error string
	PSOUT			;[8975] on the CTY
	CALL PERROR		;(P4/) Print offending line
	JRST ADRLP0		; And loop
;Here if EOF in a bad place in INTERNET.ADDRESS file.

ADREOF: HRROI T1,[ASCIZ /%Premature EOF in SYSTEM:INTERNET.ADDRESS

/]				;[8969]
	PSOUT			;Send that to the CTY
	CALL PERROR		;(P4/) Print bad line
	JRST ADRDUN		;Finish up here

;[8975] Here when OPENF fails for SYSTEM:INTERNET.ADDRESS

ADRINO:	MOVE T1,P3		;[8975] Load the JFN
	RLJFN			;[8975] Release it
	 ERJMP .+1		;[8975] Avoid the usual MONNEJ
	TMSG <%Can't open SYSTEM:INTERNET.ADDRESS 
>				;[8975] Useful error message
	RET			;[8975] Return +1 (error)

;Here if no room in host table for our host name.

NETFUL:	BUG.(HLT,NORMIA,MNETDV,SOFT,<No room in host tables for local address>,,<

Cause:	The Internet Multinet code is unable to allocate space in the network 
	hash table for a local address from the SYSTEM:INTERNET.ADDRESS file.
>)
	SUBTTL Address File Routines -- Print bad line on CTY

;[8975] PERROR - Print out the erring line in the file.
;Call with LINBUF/ current line, P4/ current pointer

PERROR:	CALL REEAT		;(P4/P4) Back up one character please
	MOVEI T2,LINBUF		;Point to line buffer
	HRLI T2,(Point 7)	;Make a byte pointer out of it

PERLP:	ILDB T1,T2		;Get a character from the line
	PBOUT%			;Print it
	CAIN T1,.CHLFD		;End of string?
	RET			;Yes, return now
	CAME T2,P4		;Point of error?
	JRST PERLP		;Nope
	MOVEI T1,"^"		;Load signal character
	PBOUT%			;Print it
	JRST PERLP		;And loop


	ENDTV.			;End of TRVAR for ADRINI
	SUBTTL Address File Routines -- Tables 

; Tables for address file keywords

; Start a table definition

DEFINE TABLE(NAME)<
NAME:  XWD ..'NAME,..'NAME
..TABLE==0		; Init count
>
DEFINE TABEND(NAME)
< ..'NAME==..TABLE>

DEFINE KEY(NAME,DATA)
< XWD [ASCIZ /NAME/],DATA
  ..TABLE==..TABLE+1		; Increment the count of entries
>

; Table of interface type names

TABLE(INTNAM)
KEY AN20,NT.ANX			; AN20 Interface
KEY IPCI,NT.CIP		  	; KLIPA Interface
KEY IPNI,NT.NIP			; KLNI Interface
TABEND(INTNAM)

; Take of modifiers

TABLE(TYPNAM)
KEY DEFAULT,ADDFLT		; This is the 'primary' address for host
KEY LOGICAL-HOST-MASK,ADLHM	; Logical host mask for this network
KEY NCP,ADNCP			; network uses Arpanet NCP protocal
KEY PACKET-SIZE,ADPSIZ		; Maximum packet size allowed
KEY PREFERRED,ADDPRF		; This is the 'preferred' address for host
TABEND(TYPNAM)
	SUBTTL CVHST% JSYS - Convert Host Number to String

REPEAT 1,<			;THIS JSYS IS VERY TEMPORARY
XNENT (.CVHST,G)		;.CVHST::
	MCENT
	SETOB P1,P2		;NO NAME YET
	MOVE T1,T2		;GET HOST NUMBER IN RIGHT PLACE
	CALL GTHNTS		;CONVERT NUMBER TO STRING
	JUMPL P1,[EMRETN(CVHST1)] ;STRING NOT FOUND
	LOAD P4,HSTNMP,(P1)	;GET THE NAME POINTER
	SETSEC P4,INTSEC	;INTO PROPER SECTION
	ADDI P4,HSTNAM		;POINT TO NAME
	MOVE P3,[<POINT 7,0>!1B12] ;EXTENDED POINTER WORD
	UMOVE T1,1		;GET DESINATION
	CALL GTHSOU		;WRITE STRING TO USER SPACE
	UMOVEM T1,1		;WRITE UPDATED POINTER TO USER SPACE
	JRST SKMRTN
>
	SUBTTL GTHST% JSYS

;The  GTHST%  JSYS, Get information on a Host or Network, Moved here
;from NETWRK because expansion allows it  to  be  general  over  all
;Interfaces rather than just NCP. Called as in JSYS documentation

;The following register conventions are used in it
;
;P1 - Index into Name tables
;P2 - Index into Hash tables
;P3,P4 - Byte pointers (extended or otherwise)
;P5,P6 - Scratch

XNENT (.GTHST,G)		;.GTHST::
	MCENT

	SKIPL T1		;Check range of
	CAIL T1,GTHMAX		; function code
	RETERR (ARGX02)		;Bad function code
	SETOB P1,P2		;No number nor name
	CALL LCKGTH		;[9108] (/) Lock the name table
	CALL @GTHDSP(T1)	;[9108] (P1,P2/T1) Do the function
	 RETERR (,<CALL ULKGTH>) ;[9108] (/) Unlock and return error in T1 
	CALL ULKGTH		;[9108] (/) Unlock
	SMRETN			;[9108] and give skip return

GTHDSP:	NCTDSP GTHSIZ		;[9108](00) Get name table size
	NCTDSP GTHIDX		;[9108](01) Index into name space
	NCTDSP GTHNUM		;[9108](02) Convert number to string
	NCTDSP GTHSTR		;[9108](03) Convert string to number
	NCTDSP GTHHNN		;[9108](04) Status by number
	NCTDSP GTHHNI		;[9108](05) Status by index
	NCTDSP GTHNHN		;[9108](06) Get local number on a network
	NCTDSP GTHNST		;[9108](07) Get status table of a network
	NCTDSP GTHNLA		;[9108](10) Get local addresses on networks
GTHMAX==.-GTHDSP		;NUMBER OF FUNCTIONS

;[8975] Utility routine to write host string to user space

GTHTUS:	LOAD P4,HSTNMP,(P1)	;Get the name pointer
	SETSEC P4,INTSEC	;Into proper section
	ADDI P4,HSTNAM		;Point to name
	MOVE P3,[<POINT 7,0>!1B12] ;Extended pointer word
	UMOVE T1,2		;Get dest
	CALL GTHSOU		;Write string
	UMOVEM T1,2		;Update user's pointer
;	CALLRET GTHSXX		;Common exit routine

;Common exit routine for functions 2, 3, 4.

GTHSXX:	MOVX T4,HS%NCK		;SET THE NICKNAME FLAG
	ADDI P2,HSTSTS		;[8828] Point to status block
	SKIPL P1		;NO NAME
	SKIPL HOSTN(P1)		;DID WE HAVE ONE?
	SKIPA T4,(P2)		;[8828] No
	IOR T4,(P2)		;[8828] Return status
	SUBI P2,HSTSTS		;[8828] Reset to hash block address
	UMOVEM T4,4
	ADDI P2,HOSTNN		;[8828] Point to host number
	MOVE T3,(P2)		;[8828] Return host number
	UMOVEM T3,3
	RETSKP			;[9108] Skip return 

;[8975] Utility routine to convert number to string
;Call with T1/ number
;Returns +1 always, P1/ -1 if not found, P1/ name index if found

GTHNTS:	CALL CVNHST		;MAKE IT NEW FORMAT
	CALL HSTHSH		;GET ITS INDEX
	 JRST GTHNT1		;Not found, return -1 in P1
	MOVE P2,T2		;SAVE INDEX
	SKIPG P1,HOSTPN(T2)	;HAS IT A NAME?
GTHNT1:	SETO P1,		;NO
	RET
	SUBTTL GTHST% JSYS -- Name Table Size, Index Into Name Space

;Function 0 - Get name table size

GTHSIZ:	HRLZ T2,MHOSTS		;-LENGTH,,1ST INDEX
	UMOVEM T2,2		;RETURN TO USER
	MOVSI T3,-NHOSTS	;NUMBER OF HOST SLOTS
	UMOVEM T3,3		;RETURN TO USER
	MOVE T4,PRFADR		;GET PREFERRED ADDRESS
	UMOVEM T4,4		;RETURN TO USER
	RETSKP			;[9108] Skip return

;Function 1 - Index into name space

GTHIDX:	MOVN T1,MHOSTS		;GET NUMBER OF HOST NAMES IN USE
	HRRZ P1,T3		;CHECK RANGE OF HOST NAME INDEX
	CAML P1,T1
	RETBAD (GTJIX1)		;[9108] Bad index to HOSTN
	SETSEC P1,INTSEC	;IN THE RIGHT SECTION
	LOAD P2,HSTIDX,(P1)	;GET INDEX INTO HOSTNN
	SETSEC P2,INTSEC	;AND IN THE PROPER SECTION
	JRST GTHTUS		;WRITE THE STRING
	SUBTTL GTHST% JSYS -- Convert Number to String and String to Number

;Function 2 - Convert number to string

GTHNUM:	MOVE T1,T3		;GET HOST NUMBER
	CALL GTHNTS		;CONVERT NUMBER TO STRING
	JUMPGE P1,GTHTUS	;[8975] If legal, write to user space and ret
	RETBAD (GTHSX3)		;[8975][9111] Error, return no string for that
				; number

;Function 3 - Convert string to number.

GTHSTR:	CALL GTHSTN		;CONVERT STRING TO NUMBER
	SKIPL T2		;VAILD STRING FOUND?
	RETBAD (GTHSX5)		;[9108] No, return invalid string error
	MOVE P1,T2		; Save
	SETSEC P1,INTSEC	; in the right section
	SKIPN T1,T4		;Copy host number
	RETBAD (GTHSX2)		;[9108] No host found error
	CALL CVNHST		; Convert number to 32 bits if necessary
	CALL HSTHSH		; Look it up in tables
	RETBAD (GTHSX2)		;[9108] Not there
	MOVE P2,T2		; Save that index
	JRST GTHSXX		;EXIT

;Utility routine to convert host string to a number

GTHSTN:	STKVAR <<GTHSBF,10>>
	MOVEI P3,GTHSBF		; Point to buffer
	HRLI P3,(<POINT 7,0>)	; ....
	CALL GTHSIN		;GET STRING FROM USER
	MOVEI T1,GTHSBF		;MAKE BYTE POINTER
	HRLI T1,(<POINT 7,0>)
	CALLRET HSTLUK		;LOOKUP NAME
	SUBTTL GTHST% JSYS -- Status by Index and Status by Number

;Function 5 - Status by index

GTHHNI:	HRRZ T1,T3		;GET INDEX
	CAIL T1,NHOSTS		; Compare to table size
	RETBAD (GTJIX1)		;[9108] Bad index
	SETSEC T1,INTSEC	; Put in proper section
	LOAD T1,HSTIDX,(T1)	; get index to tables
	SETSEC T1,INTSEC	; Again in right section
	ADDI T1,HOSTNN		;[8828] Point to host number
	SKIPA T1,(T1)		;[8828] Get number

;Fucntion 4 - Status by number

GTHHNN:	MOVE T1,T3		;GET HOST NUMBER
	CALL GTHNTS		;CONVERT NUMBER TO INDEX
	JUMPL P1,[RETBAD (GTHSX2)] ;[9037][9111] Unknown host
	JRST GTHSXX		;EXIT
	SUBTTL GTHST% JSYS -- Move String From/To User Space

; Move string from user space

GTHSIN:	UMOVE T1,2		; GET POINTER
	MOVE T4,[XCTBU [ILDB T2,T1]]
	TLNN T1,777777		; IF JFN DO THE JSYS
	MOVE T4,[BIN]
	TLC T1,777777		; CHECK FOR LH -1
	TLCN T1,777777
	HRLI T1,(<POINT 7,0>)	; USE STANDARD POINTER
	MOVEI P5,MAXLC		; UP TO 39 CHARS
GTHSIL:	XCT T4			; DO RIGHT OPERATION
	SOSG P5			; Decrement counter
	MOVEI T2,0		; AFTER MAXLC CHARS FORCE NULL
	CAIL T2,140		; LOWER CASE?
	TRZ T2,40		; YES, RAISE
        CAIG T2,40		; END ON SPACE OR LESS
        MOVEI T2,0		; terminating with null
	IDPB T2,P3		; Stick it in destination string
	JUMPG T2,GTHSIL		; loop if more to it
	CAME T4,[BIN]		; DON'T BACKUP A TTY
	BKJFN			; backup to before termination
	 NOP			; (shouldn't fail)
	UMOVEM T1,2		; restore updated pointer
	RET			; and return

; Write string to user space
; Called with T1 - Dest in user space
; Returns +1 T1 updated pointer

GTHSOU:	MOVE T4,[XCTBU [IDPB T2,T1]]
	TLNN T1,777777		; IF JFN DO THE JSYS
	MOVE T4,[BOUT]
	TLC T1,777777		; CHECK FOR LH -1
	TLCN T1,777777
	HRLI T1,(<POINT 7,0>)	; USE STANDARD POINTER
GTHSOL:	ILDB T2,P3		; Get next byte
	JUMPE T2,GTHSOX		; If a null
	XCT T4			; DO RIGHT OPERATION
	JRST GTHSOL		; Loop
GTHSOX:	CAMN T4,[BOUT]		; Don't backup a JFN
	RET			; Return now if a JFN
	XCT T4			; Stick on NULL
	BKJFN			; Backup destination
	 NOP			; ...
	RET			; and return
	SUBTTL GTHST% JSYS -- Get Hostnumber on a Network

;Function 6 -  Get hostnumber on a network
; Accepts T2 - Network number, or host number on the net
; Returns +1 if no interface on that network
; +2 if we have one, T2 - Hostnumber

GTHNHN:	MOVE T1,T2		; Get number
	CALL NETNCT		; Look for an NCT for that net
	RETBAD (GTHSX5)		;[9108] Return error if none
	MOVE T1,NTLADR(P1)	; Get our number there
	UMOVEM T1,T2		; Restore it to user
	RETSKP			;[9108] and do a skip return
	SUBTTL GTHST% JSYS -- Get Status of a Network

;Function 7 - Get status of a network
; Accepts T2 - Network number or host number on the net
;	    T3 - Pointer to where to store data
;	    T4 - -Number of words,,offset of first
; Returns +1 if no such network or invalid offset
;	    +2 if good arguments with data in table

GTHNST:	MOVE T1,T2		; Get number
	CALL NETNCT		; Look it up
	 RETBAD (GTHSX5)	;[9108] Bad number
	HLRE T1,T4		; Get number wanted
	MOVMS T1		; Magnitude
	ADDI T1,(T4)		; Add in first
	CAILE T1,NTXUPP-NTRDY+1	; Size of area
	RETBAD (GTJIX1)		;[9108] Bad size
	XMOVEI P1,NTRDY(P1)	; Point to start of area
	ADDI P1,(T4)		; Add in offset of fist word
	XCTU [HRR T4,T3]	; Setup an AOBJN destination pointer
GTHNS0:	MOVE T1,0(P1)		; get a word
	UMOVEM T1,0(T4)		; Store it
	AOS P1			; Increment source pointer
	AOBJN T4,GTHNS0		; And loop through all desired
	RETSKP			;[9108] Do a skip return at the end
	SUBTTL GTHST% JSYS -- Get Local Network Addresses

;Function 10 - Get Local Network Addresses
; Accepts   T3/ Address of where to store data
;	    T4/ Number of words
; Returns +1 if invalid offset
;	    +2 if good arguments with data in table
; Updates callers T4 count of items returned.

GTHNLA:	SKIPG T4		;[9108] Count is positive?
	RETBAD (ARGX24)		;[9108] No, return error
	MOVE P1,NCTVT		; Get address of the first NCT
	JRST GTHLA3		; Report on this NCT
GTHLA1:				; Get the next NCT
	LOAD P1,NTLNK,(P1)	; Get address of the next NCT
	JUMPN P1,GTHLA3		; Go report on this NCT
GTHLA2:				; Here when all NCTs examined
	XCTU [SUB T4,4]		; Fix up the count
	XCTU [MOVNM T4,4]	; Save the count for the caller
	RETSKP			;[9108] Success return
GTHLA3:		  		; NCT Chasing loop
	SKIPG T1,NTLADR(P1)	; Get address on this NCT
	JRST GTHLA1		; No address defined.  get next NCT.
	UMOVEM T1,(T3)		; Save interface address for user
	SOJLE T4,GTHLA2		; Count exhausted?
	AOJA T3,GTHLA1 		; No so do the next NCT
	SUBTTL GTHST% JSYS -- Host Table Lock Routines

;[9108] Define the lock word, done here because only used here.

RSI GTHLCK,<-1>			;[9108] Host table lock word

;[9108] LCKGTH, routine to lock host table.
;Returns +1 always, table locked, NOINT

LCKGTH:	NOINT			;[9108] Don't allow ^C out
	LOCK GTHLCK		;[9108] Lock it, blocking if not locked 
	RET			;[9108] Return +1 always

;[9108] ULKGTH, routine to unlock host table.
;Returns +1 always, table unlocked and OKINT

ULKGTH:	UNLOCK GTHLCK		;[9108] Unlock the host table
	OKINT			;[9108] Reallow interrupts
	RET			;[9108] Return +1 always
	SUBTTL ATNVT% JSYS - Attach connection to NVT

; ATtach connection to NVT
; Call:	1	; [Receive] jfn of opened network connection (JCN for TCP)
;	2	; Send jfn of open network connection (NCP only)
;	ATNVT
; Returns
;	+1	; Cannot attach
;	+2	; Ok.  the jfn is released, ac 1 has line number of
;		; Attached pty.

XNENT (.ATNVT,G)		;.ATNVT::
	MCENT
	TXNE T1,AN%TCP		; Attach TCP Virtual Terminal?
         JRST TATNVT		; Yes, go to TCP code
	XJRST [MSEC1,,TVTJFN]	; we were given a JFN
	SUBTTL NETRDY GETAB Table

; GNTRDY
; Get  the  NETRDY  table. Attempts to find the data from the NCT for
; the primary network

XNENT (GNTRDY,G)		;GNTRDY::
	MOVE T1,DEFADR		; get primary address
	CALL NETNCT		; Find an NCT for it
	 RETERR()		; Error
	MOVE T1,@GNTAB(T2)	; get an entry
	RET			; And return

; Indirect table for deriving the data

GNTAB:	IFIW!<P1>B17+NTRDY	; NETRDY From the NCT
	IFIW!<P1>B17+NETON	; As NETON
	IFIW+NETENT		; NETENT has its own cell
	IFIW!<P1>B17+NTIUPT	; NCPUPT
	IFIW+IGDMSG		; Last Imp going down message
	IFIW!<P1>B17+NTXDNT	; Last ready line drop
	IFIW!<P1>B17+NTXUPP	; last ready line up time
	IFIW+IGDTIM		; Last Imp going down message time
	SUBTTL Utility Routines -- HSTLUK - Lookup Host Names

;HSTLUK - Lookup host names
;Call with T1/ pointer to string of name or number
;Returns+1 always, T1/ updated pointer
;	If number given, T4/ number, T2/ 0
;	If name given, T4/ number, T2/ address of found name string

HSTLUK:	SAVEPQ			;Get some room
	MOVE Q1,T1		;Save pointer to host name
	MOVEI T3,10		;Load radix for NIN
	NIN			;Try to get a number
	 JRST HSTLKI		;Not there try a name
	MOVE Q1,T1		;Save updated pointer to string
	MOVE T1,T2		;Load host number
	CALL CVNHST		;(T1/T1) Convert host number to new format
	MOVE T4,T1		;Return host number in T4
	MOVE T1,Q1		;And updated pointer in T1
	SETZ T2,		;Indicate that the host number was found
	RET			;Return to caller
HSTLKI:	HRLZ T2,MHOSTS		;Scan the table
	PUTSEC P1,INTSEC	;In this section

HSTLK0:	MOVE T1,Q1		;Point to source string again
	LOAD T4,HSTNMP,(P1)	;Load a name pointer
	ADD T4,[XWD INTSEC,HSTNAM] ;Point to the table
	MOVE T3,[<POINT 7,0>!1B12] ;Make extended pointer

HSTCMP:	ILDB Q2,T1		;Get character from supplied string
	ILDB Q3,T3		;Get character from this host name
	SKIPN Q2		;Null byte?
	JUMPE Q3,HSTCM2		;If the the other byte null then we have match
	CAIN Q2,(Q3)		;Not null, are they the same?
	JRST HSTCMP		;Yes, so keep comparing

HSTLK2:	AOS P1			;No match, point to next slot in table
	AOBJN T2,HSTLK0		;Step to next host
	SETZ T4,		;No host found
	RET			;Return

HSTCM2:	LOAD T4,HSTIDX,(P1)	;We have a match, get the index
	SETSEC T4,INTSEC	;In the correct section
	ADDI T4,HSTSTS		;[8828] And set to status block
	MOVE Q3,(T4)		;[8828] Get entry status bits
	SUBI T4,HSTSTS		;[8828] Now set back to hash block
	TXNN Q3,HS%SRV		;Host name?
	JRST HSTLK2		;No, a gateway or net, skip over it
	ADDI T4,HOSTNN		;[8828] Point to host number
	MOVE T4,(T4)		;[8828] Get the host number
	HRR T2,P1		;Get the name string address
	RET			; and return to caller
	SUBTTL Utility Routines -- CVNHST - Convert host number to new format

;CVNHST - Routine to convert host number in T1 to host and network number in T1
;Call with T1/ host number
;Returns +1 always T1/ new format host number with network number applied

CVNHST::CAMN T1,[-1]		;If -1 use local host number
	MOVE T1,PRFADR		;Default local host
	AND T1,[HSTMSK]		;Cut down to size
	TLNE T1,37700		;Any network number stuff?
	RET			;Yes, so return
	ANDI T1,377		;Turn off all other bits
	TRZE T1,100		;Set the host bits
	TRO T1,200000		;Units host bit
	TRZE T1,200		;Twos host bit?
	TRO T1,400000		;Set twos host bit
	JUMPE T1,R		;If zero leave it zero
	IOR T1,NETFLD		;Add default network number
	RET			;Return T1/ address
	SUBTTL End of MNETDV

	TNXEND
	END