Trailing-Edge
-
PDP-10 Archives
-
bb-kl11i-bm_tops20_v7_0_atpch_1-22
-
autopatch/mshost.x19
There is 1 other file named mshost.x19 in the archive. Click here to see a list.
;This software is furnished under a license and may only be used
; or copied in accordance with the terms of such license.
;
;Copyright (C) 1979,1980,1981,1982 by Digital Equipment Corporation
; 1983,1984,1985,1986 Maynard, Massachusetts, USA
TITLE MSHOST - Host table module for MS and friends
SEARCH GLXMAC,MSUNV,MACSYM
PROLOG (MSHOST)
CPYRYT
MSINIT
GLOBS
GLOBRS
;Routines defined herein
INTERNAL HSTINI, NAMINI, VALID8
;Routines defined elsewhere
;MSUTL.MAC
EXTERNAL ALCSB, COMPAC, COUNTS, MOVST0, MOVST2, RELSB, TBADDS
EXTERNAL ALCFOB
;Global data items defined herein
INTERNAL HOSTAB
;Global data items defined elsewhere
;MS.MAC
EXTERNAL MYHSPT, MYHDPT
;Local storage
IMPUR0
TOPS10<
MYHOST: BLOCK 1 ; Sixbit name of our host
NODNAM: BLOCK 2 ; ASCIZ name of node fetched from HOSTS.TXT
>;end TOPS10
LHOSTN: BLOCK 1 ; Local host number
CFSINI: BLOCK 1 ; CFS table initialization flag
PMRINI: BLOCK 1 ; PMR table initialization flag
HOSTAB: BLOCK 1 ; Address of the host table
SMLBUF==40 ; 199. characters ought to do it.
ATMBF2: BLOCK SMLBUF ; For parsing DNHOST.TXT
PURE
;Switches for UPS:DNHOST.TXT
SWTTAB: SWTTB0,,SWTTB0
CMD (NOMAIL20,NT%KWL)
SWTTB0==.-SWTTAB-1
SUBTTL Routines to parse host tables, determine what nets are present, etc.
;Figure out if we're on a network, and what our local host name is
; If we're both a DECNET and an ARPANET host, the ARPANET host name is used
; Also, note whether XMAILR exists
NAMINI: $SAVE <E> ; [3105]Save an AC
STKVAR <NODARG,<CFIGBL,10>> ; [3105]Add arg block for CNFIG%
TXZ F,F%ARPA!F%DECN!F%ANFX ; Assume no XMAILR or nets
TOPS20< MOVEI A,10 ; [3105]Length is 10
MOVEM A,CFIGBL ; [3105]Initialize the argument block
MOVX A,.CFINF ; [3105]Get Info
MOVEI B,CFIGBL ; [3105] from the CNFIG% jsys
CNFIG% ; [3105] into CFIGBL
ERJMP [JRETER <Can't find network info with CNFIG>
RET] ; [3105]Assume no network
MOVE A,.CFISO(B) ; [3105]Get the network bits
MOVE E,A ; [3105]Store them here
TXNN E,CF%ARP ; [3105]Do we have arpanet?
JRST NAMIN2 ; [3105]No...
MOVX A,.GTHSZ ; Try new style JSYS
GTHST ; for local host number
ERJMP NAMIN2 ; No ARPANET, try DECNET
MOVEM D,LHOSTN ; OK, save local host number
MOVE C,D ; Find our name
MOVE B,MYHSPT
MOVX A,.GTHNS
GTHST
ERJMP [JRETER <Can't find local host name with GTHST>
JRST NAMIN2] ; Eh? maybe try old stuff
TXO F,F%ARPA ; Remember net exists
NAMIN2: TXNN E,CF%DCN ; [3105]Do we have DECnet?
RET ; [3105]No, so we're done
MOVEI A,.NDGLN ; Get DECnet host name
MOVE B,MYHDPT
MOVEM B,NODARG ; Setup arg block for NODE jsys
MOVEI B,NODARG ; Point to it
NODE ; Get our name
ERJMP R ; Return - no network
TXO F,F%DECN!F%DNNM ; Set flag - we have DECnet, Default node names
; Edit 2370...
; Earlier code stuffed DECnet host name in ARPAnet node name string
; if there's no ARPAnet. This tends to break things, such as the
; default host name used for local user addresses, so MYHDEC is now
; the default host name always, and ARPAnet mail is the exception.
; This means there's no need to stuff the DECnet host name in MYHNAM
; so...
RET ; and return
>;End TOPS20
TOPS10<
MOVEI A,.GTLOC ; Get location of job 0 (crock)
GETTAB A, ; ..
JRST NOANF ; Failure, assume no net
SKIPN A ; ..
JRST NOANF ; ..
MOVEM A,LHOSTN ; Save local host number
MOVE C,A ; Copy to good place
MOVE A,[.NDRNN,,B] ; Function to return node name
MOVEI B,2 ; Length of arg block
NODE. A, ; Get our node name
JRST NOANF ; Ratz... assume no net
MOVEM A,MYHOST ; Save sixbit name for later checking
MOVE B,A ; Get SIXBIT into better AC
MOVE C,MYHSPT ; Where to put ASCII name
NAMIN2: SETZ A,
LSHC A,6 ; Get SIXBIT character in A
ADDI A,40 ; Make ASCII
IDPB A,C ; Stuff into name
JUMPN B,NAMIN2 ; Do all chars
IDPB B,C ; Insure ASCIZ
TXO F,F%ANFX ; Remember presence of ANF10 net
; Now see if there is a DECNET network
MOVEI A,B ; point to the DNET. table
MOVE B,[DN.FLE+<.DNLNN,,3>]
DNET. A,
RET ; there must be non DECNET network
MOVE B,D ; Get SIXBIT into better AC
MOVE C,MYHDPT ; Where to put ASCII name
NAMIN3: SETZ A,
LSHC A,6 ; Get SIXBIT character in C
ADDI A,40 ; Make ASCII
IDPB A,C ; Stuff into name
JUMPN B,NAMIN3 ; Do all chars
IDPB B,C ; Insure ASCIZ
TXOA F,F%DECN ; Remember presence of DECNET net
NOANF: SETZM MYHNAM ; No networks what-so-ever
RET ; Home, James
>;End TOPS10
SUBTTL HSTINI - init hostname tables
; HSTINI - Initialize host table control variables
;
HSTINI::SETZM HOSTAB ; no host table yet
SETZM PMRINI ; PMR hasn't been read
SETZM CFSINI ; We don't know about CFS either
RET ; All done
;
; VALID8 - Validate the existance of a host name
;
; - This routine uses HOSTAB as a cache of validated host names
; rather than the definitive source of legal hosts. It first
; checks this table to see if the requested host has already been
; validated.
; - Failing this, we ask the O/S for validation, first via DECnet, then
; ARPAnet (if TOPS20), then via ANF10 (if TOPS10)
; - If the host is still unknown, and the PMR table has not been parsed
; yet, then it is parsed, and the new hosts added to HOSTAB. HOSTAB
; is checked once more for the requested host name, and if not found
; VALID8 returns a failure (+1).
;
; A/ Pointer to ASCIZ host name string
;
; Returns:
; +1 - No such host
; +2 - Valid host
;
; This table contains the host name validation routines, in the order they
; are tried. If we haven't already validated this host, VALID8 uses these
; routines to figure out who this host is...
;
V8TABL:
TOPS20< CALL VALCFS> ; CFS, for TOPS-20 systems only
CALL VALDNA ; DECnet
TOPS20< CALL VALARP> ; ARPAnet
TOPS10<;CALL VALANF> ; ANF-10
V8NUM==.-V8TABL ; This is the table size
;
;
VALID8: STKVAR <SVPTR> ;Place to save the host name pointer
TLC A,-1 ; Did we get a -1,,addr?
TLCN A,-1 ; If so, it was a 0, so don't skip
HRLI A,(POINT 7,) ; Otherwise make it a pointer
MOVEM A,SVPTR ; Save pointer to host name
SKIPE B,HOSTAB ; Any host table?
IFNSK. ; No skip => table exists
EXCH A,B ; Put arguments where they're expected
$CALL S%TBLK ; Look up the host
EXCH A,B ; Put things back where they're expected
TXNE A,TL%EXM ; Has this host already been checked?
RETSKP ; Yes, this is a valid host
MOVE A,SVPTR ; Put the pointer back in A
ENDIF. ; Here when we have to take the longer route
MOVSI C,-V8NUM ; Make an AOBJN pointer
VALID9: XCT V8TABL(C) ; Check out the host
IFSKP. ; Skip return means this is a valid host
CALL NEWHST ; Add this host to HOSTAB
RET ; No room for host entry
RETSKP ; And return good
ENDIF. ; Otherwise...
AOBJN C,VALID9 ; Loop through the validation table
CALL VALPMR ; Check to see if we already loaded PMR table
RET ; Yes we did, so the host isn't valid
RETSKP ; It was a PMR host
SUBTTL Network Host name validation routines
;
; VALANF - TOPS-10 only routine to ask the system if the host name supplied
; is a valid ANF-10 host
;
; Called with A/ Pointer to ASCIZ host name
;
; Returns
; +1 - Not an ANF-10 host
; +2 - Valid host, B/ HOSTAB-style node block
;
TOPS10<
;VALANF:RET> ; For now
;
; VALARP - TOPS-20 only routine to ask the system if the host name supplied
; is valid
;
; Called with A/ Pointer to ASCIZ host name
;
; Returns
; +1 - Not an ARPAnet host
; +2 - Valid host, B/ HOSTAB-style node block
;
TOPS20<
VALARP: $SAVE <A,C,D> ; Save caller's ac's
STKVAR <HOSTN,HSTR,HBLK> ; Node number, host string block address
MOVEM A,HSTR ; save the pointer to the host name here
MOVE B,A ; Put the pointer in B
MOVX A,.GTHSN ; Convert name to host number function
GTHST% ; Ask the ARPAnet
ERJMP R ; Not a valid name
TXNN D,HS%SRV ; Is this a server host?
RET ; No, so it's not a legitimate host
MOVEM C,HOSTN ; Save host number for a bit
CALL ALCNB ; get a node block
IFNSK. ; No skip means memory exhausted,
MOVE A,HSTR ; So release the string block,
$TEXT(KBFTOR,<%Memory space exhausted.>)
$TEXT(KBFTOR,<%Cannot add ARPAnet host ^T/A/.>)
CALL RELSB ; because we can't build a HOSTAB entry
RET ; Bad return.
ENDIF.
MOVEM A,HBLK ; save the address of the block
MOVE A,HSTR ; get the string pointer back
CALL COUNTS ; find out how long it is
CALL ALCSB ; and get a string block that long
IFNSK. ; No skip means no memory left
$TEXT(KBFTOR,<%Memory space exhausted.>)
$TEXT(KBFTOR,<%Cannot add ARPAnet host ^T/A/.>)
RET ; No memory, no deal
ENDIF. ;
MOVE A,HBLK ; get the node block address
MOVEM B,N.NAME(A) ; save the address of the string block in it
MOVE A,B ; put the string block in A
HRLI A,(POINT 7,) ; make the string block address a pointer
MOVE B,HSTR ; get the pointer to the actual node name
CALL MOVST2 ; and move the host name into the string block
MOVX B,NT%ARP ; ARPANET host flag to RH
CAMN C,LHOSTN ; Is this us?
TXO B,NT%LCL ; Yes, light local host flag
MOVE A,HBLK ; get the node block address back
MOVEM B,N.FLGS(A) ; Set flags in node block
HRLZ B,N.NAME(A) ; get the address of the name string
HRR B,A ; Node block address to RH
RETSKP ; Here means it's a valid name
> ; End TOPS20 conditional
; VALCFS - TOPS-20 only routine to validate the host name supplied with the
; list of known CFS hosts that are sharing POBOX:. This routine
; is called AFTER VALID8 has looked in HOSTAB, so the only thing
; to do is to check if HOSTAB includes the CFS hosts. If it does,
; then obviously the host name isn't a CFS host. If it doesn't,
; then we load the CFS host names from SYSTEM:CFS-HOSTS.TXT and
; look again.
;
TOPS20<
VALCFS: $SAVE <A,C> ; Save the caller's ac's
STKVAR CFSSAV ; place to keep the pointer
SKIPN CFSINI ; Is CFS table initialized?
RET ; Yes, so we already checked it
MOVEM A,CFSSAV ; Save the host name pointer
CALL CFSOPN ; No, so open the file
RET ; No file, no CFS hosts
CALL CFSPRS ; Parse the CFS hosts into HOSTAB
CALL CFSCLS ; Close the CFS file
MOVE B,CFSSAV ; Put the string pointer in B
MOVEI A,HOSTAB ; Get the host table address
CALL S%TBLK ; Look it up
TXNN B,TL%EXM ; Did we find a match?
RET ; nope, not a CFS host
RETSKP ; yes, it's good
; CFSOPN - Open the CFS host name file (SYSTEM:CFS-HOSTS.TXT)
;
; Returns:
;
; +1 - file not found or open error
; +2 - succeeded, JFN in A
;
CFSOPN:
RET ; Do this later
; CFSPRS - Parse the CFS host name file
;
; Returns +1 always
;
CFSPRS:
RET
; CFSCLS - Close the CFS host name file
;
; Returns +1 always
;
CFSCLS:
RET
> ; End of TOPS20 conditional
;
; VALDNA - DECnet routine to validate the supplied host name
;
; Called with A/ Pointer to ASCIZ host name
;
; Returns
; +1 - Not a DECnet host name
; +2 - Valid DECnet host name
; with B/ TBLUK-style node block
;
VALDNA: $SAVE <A,C> ; Save the caller's ac's
STKVAR <VNBLK,VHPTR> ; local storage
MOVEM A,VHPTR ; Save the pointer to the node name
CALL NODVFY ; Call O/S-specific DECnet routine
RET ; Not a valid node
CALL ALCNB ; Allocate a node block
IFNSK. ; If there's no more memory,
$TEXT(KBFTOR,<%Memory space exhausted.>)
$TEXT(KBFTOR,<%Cannot add DECnet host ^T/A/.>)
RET ; And return bad
ENDIF. ;
MOVEM A,VNBLK ; Save N-block address
MOVE A,VHPTR ; Get the pointer to the node name
CALL COUNTS ; Count the bytes in it
CALL ALCSB ; Get a string block for it
IFNSK. ; If we're out of memory now...
MOVE A,VNBLK ; Get the N-block address
CALL RELNB ; And release it
$TEXT(KBFTOR,<%Memory space exhausted.>)
$TEXT(KBFTOR,<%Cannot add DECnet host ^T/A/.>)
RET ; and return bad
ENDIF. ;
MOVE A,VNBLK ; Get the node block address
MOVEM B,N.NAME(A) ; Stuff string address into N-block
MOVE A,B ; Set up for MOVST0
HRLI A,(POINT 7,) ; Byte pointer
MOVE B,VHPTR ; Get the pointer to the node name
CALL MOVST2 ; Copy to new block
MOVE B,VNBLK ; Point to N-block
MOVE A,N.NAME(B) ; Point to name string
HRLI A,(POINT 7,) ; ..
MOVE B,MYHDPT
TOPS20< STCMP > ; See if this name matches local node name
TOPS10< $CALL S%SCMP> ; Ditto
MOVX B,NT%DCN!NT%NM0 ; DECNET node, name in heap space
SKIPN A ; A = 0 if name matched
TXO B,NT%LCL ; Match, this is the local node
MOVE A,VNBLK ; Point to node block again
MOVEM B,N.FLGS(A) ; Stuff flags into N-block
HRR B,A ; Set up for TBADDS
HRL B,N.NAME(B) ; Ptr to name string in LH
RETSKP ; Return the HOSTAB-style node block address
; NODVFY - Operating System-specific DECnet Node name verification routine
;
; Called with A/ Pointer to ASCIZ node name string
;
; Returns:
; +1 - Not a valid name
; +2 - Valid
;
NODVFY: STKVAR <<NODBLK,2>> ; Temporary storage
TOPS20< MOVEI B,NODBLK ; Point to argument block
MOVEM A,.NDNOD(B) ; Save the pointer to the host name
MOVX A,.NDVFY ; NODE% JSYS Verify function
NODE% ; Call TOPS-20
ERJMP R ; Shouldn't happen, but just in case
MOVE B,.NDFLG(B) ; Get the flags returned by NODE%
TXNN B,ND%EXM ; Was it an exact match?
RET ; Nope, no good.
RETSKP ; Node name is ok.
>; End of TOPS20 conditional
TOPS10< CALL ASCSIX ; Turn the node name into SIXBIT
MOVEM B,.DNNAM+NODBLK ; And save it for DNET.
MOVE A,[DN.FLK+<.DNNDI,,2>] ; Args to ask DNET if this node valid
MOVEM A,NODBLK ; Save it away
MOVEI A,NODBLK ; Point to block
DNET. A, ; Is this a valid DECNET node name?
CAIE A,DNNSN% ; No such node.
RETSKP ; Node name is ok.
RET ; Node name is not legit.
;Convert ASCIZ string pointed to by A into SIXBIT in B
ASCSIX: SETZ B,
MOVE D,[POINT 6,B]
ASCSX1: ILDB C,A ; Next byte
JUMPE C,R ; Stop on null
CAIGE C,40 ; Insure no random ctrl chars
JRST ASCSX1 ; just ignore 'em if present
CAIL C,140 ; Uppercasify
TRZ C,40 ; ..
SUBI C,40 ; SIXBIT-ify
IDPB C,D ; Stuff
TRNN B,77 ; Stop at six chars
JRST ASCSX1 ; ..
R: RET
>; End of TOPS10 conditional
;
; NEWHST - Add the specified host name to HOSTAB
;
; Called with B/ TBLUK-style entry (string-addr,,block-addr)
;
; Returns +1 always
; with B/ Address of new HOSTAB slot
;
; Note: if HOSTAB is full, then the host just doesn't get into the table.
;
NEWHST: MOVEI A,HOSTAB ; Get the TBLUK header
CALL TBADDS ; Add it to the table.
RET ; No more room
MOVE B,A ; Put the entry where callers expect it.
RETSKP ; All set
; VALPMR - Check to see if the PMR tables have been loaded, if not
; do so and look for the specified host name again. Otherwise
; just return +1
;
; Called with A/ pointer to ASCIZ host name
;
; Returns:
; +1 - invalid host name
; +2 - Valid host, B/ Pointer into HOSTAB entry
;
VALPMR: SKIPE PMRINI ; Have we been here already?
RET ; Yes, so the host name is invalid
SETOM PMRINI ; Set the PMR flag
CALL HSTIND ; Initialize the table
MOVE B,A ; Put the host name here
MOVE A,HOSTAB ; and the address of the table
$CALL S%TBLK ; Look it up
EXCH A,B ; Put argument where it's expected
TXNN A,TL%EXM ; Match?
RET ; Nope
RETSKP ; Yes, return good.
;See if DECNET host name table exists, and add hosts to table if so.
TOPS20<
HSTIND: $SAVE <A,B,C> ; Just in case, save work registers
TRVAR <FBITS,HSTJFN,HFPGS,HFPGN,HFPTR,HFCNT,HSTR,HDST,SSTR,PATH,PTHFLG>
MOVX A,GJ%OLD!GJ%SHT ; Look for existing file
HRROI B,[ASCIZ /UPS:DNHOST.TXT/]
GTJFN
ERJMP R ; No table, just quit
MOVX B,OF%RD
OPENF ; open for read
JFATAL <Cannot open DECnet host name table>
MOVEM A,HSTJFN ; Save JFN
SIZEF ; Get file size
JFCL ; Unlikely
MOVEM C,HFPGS ; Save page count
MOVE A,C ; Acquire space to map file
$CALL M%AQNP ; ..
MOVEM A,HFPGN ; Save page no. of 1st page
LSH A,^D9 ; Form word address
HRLI A,(POINT 7,) ; Form byte pointer
MOVEM A,HFPTR ; save
HRLZ A,HSTJFN ; Map from file page zero
HRLI B,.FHSLF ; to fork page
HRR B,HFPGN ; here
MOVE C,HFPGS ; Page count
TXO C,PM%RD!PM%PLD!PM%CNT
PMAP
MOVE A,HSTJFN ; Get JFN back
MOVE B,[1,,.FBSIZ] ; Get byte count for file
MOVEI C,C ; Into C
GTFDB
MOVEM C,HFCNT ; Save
SETZM PATH ; No path block yet
; JRST HSTID1 ; Enter host parse loop
HSTID1: MOVE A,[POINT 7,ATMBF2] ; Where to build host name string
MOVEM A,HDST ; Init destination pointer
SETZM FBITS ; No flag bits known yet
SETZM SSTR ; No synonyms yet
SETZM PTHFLG ; Clear the path flag (set when parsing a path)
SETZM PATH ; Init path-seen flag
HSTID2: CALL BYTIN ; Get a byte
JRST HSTIDE ; Error or EOF - quit
CAIN B,"/" ; Check for switches
CALL HSTIDK ; Go handle
CAIN B,"," ; Comma? (routing info follows)
JRST [ SETZ B, ; Insure ASCIZ for name string
IDPB B,HDST ; ..
CALL CPYAT2 ; Allocate a string block
JRST HSTIDM ; Insufficient memory
MOVEM A,PATH ; Save addr of temp block
MOVE A,[POINT 7,ATMBF2] ; Reinit atom buffer pointer
MOVEM A,HDST ; for collection of path string
SETOM PTHFLG ; We are now parsing a path
JRST HSTID2] ; Go eat path string
CAIE B,";" ; Start of comment?
CAIN B,"!" ; ..
JRST HSTID3 ; Yes, go gobble it up
;Here with a valid character which is an element of a hostname
CAIN B,.CHLFD ; EOL? (Line Feed)
JRST HSTID5 ; Yes, quit this line
CAIN B,"=" ; Start of synonym?
JRST HSTIDS ; Yes, go handle synonym
IDPB B,HDST ; Save character
JRST HSTID2 ; Get next
;Here for comment, gobble it up to EOL
HSTID3: CALL BYTIN ; Eat chars until EOL
JRST HSTIDE
CAIN B,.CHLFD ; EOL?
JRST HSTID5 ; Yes, start interpreting chars again
JRST HSTID3 ; No, eat more comment
;Here on EOL to process this line
HSTID5: MOVE A,[POINT 7,ATMBF2] ; Get a virgin pointer
CAME A,HDST ; Was the pointer touched?
SKIPN PTHFLG ; Were we parsing a path?
IFNSK. ; No?
SKIPE A,PATH ; No, release path block if need be
CALL RELSB ; ..
JRST HSTID1 ; Don't put null name in table
ENDIF.
MOVEI B,0 ; Yes, add terminating null
IDPB B,HDST ; ..
SKIPE PATH ; Was a path string seen?
IFNSK. ; No?
CALL CPYAT2 ; Yes, copy to a string block
JRST HSTIDM ; Memory allocation error
MOVE D,PATH ; Get addr of hostname string
MOVEM A,PATH ; Save addr of path string
MOVE A,[POINT 7,ATMBF2] ; Copy host name string to atom buffer
MOVE B,D ; Set up for MOVST0
CALL MOVST0 ; Do the copy
MOVEM A,HDST ; Set up HDST so ASCIZing doesn't lose
MOVE A,D ; Get string block address back
CALL RELSB ; Release it
ENDIF. ; Rejoin mail line.
MOVE A,MYHDPT ; Local host name
HRROI B,ATMBF2 ; This host name
STCMP ; See if the same
SKIPN A ; A=0 if name matched
SKIPA B,[NT%LCL!NT%DCN] ; Local, set flag
MOVX B,NT%DCN ; Set DECnet flag
IORB B,FBITS ; Add in any switch-induced bits
TXNE B,NT%KWL ; Can this host receive 20-style mail?
JRST HSTID1 ; No, just reuse string block
HSTID7: MOVE A,[POINT 7,ATMBF2] ; Point to this name
CALL COUNTS ; Count the characters
ADDI A,5 ; Allow space for flag bits
CALL ALCSB ; Allocate a string block
JRST HSTIDM ; Insufficient memory
MOVEM B,HSTR ; Save address of string block
MOVX A,CM%FW ; Light bit that says "dere's flags here!"
IORM A,(B) ; ..
MOVEI A,1(B) ; Skip flags word, set up for MOVST0
HRLI A,(POINT 7,) ; ..
MOVEI B,ATMBF2 ; Address of name string
CALL MOVST0 ; Copy name string to string block
CALL ALCNB ; Allocate node block
JRST HSTIDM ; Insufficient memory
MOVE B,FBITS ; Flag bits
MOVEM B,N.FLGS(A) ; to node block
MOVE B,PATH ; Path string
MOVEM B,N.PATH(A) ; to node block
MOVE B,SSTR ; Addr of node block for real name
MOVEM B,N.REAL(A) ; to node block
MOVE B,HSTR ; String address
MOVEM B,N.NAME(A) ; to node block
HRLZS B,B ; and to LH for TBADD
HRR B,A ; Node block address to RH
MOVE D,B ; Preserve over this stuff
HLR B,B ; Get string address to RH
MOVE A,(B) ; Get possible flags word
TLNN A,(177B6) ; Is this a flags word?
TXNN A,CM%FW ; ..
SKIPA
ADDI B,1 ; Yes, skip the flags and point to string
HRLI B,(POINT 7,) ; Form kosher byte pointer
SKIPN A,HOSTAB ; See if already have an entry
JRST HSTID4 ; No table, so add the entry
$CALL S%TBLK ; ..
TXNE B,TL%EXM ; Do we have an entry?
JRST HSTID6 ; Yes, go link this to it
HSTID4: MOVE B,D ; No, restore HOSTAB entry
MOVEI A,HOSTAB ; Host name table
CALL TBADDS ; Add to table, maybe expanding table
JRST [ $TEXT(KBFTOR,<%Can't add DECnet node ^T/ATMBF2/ to host table>)
$TEXT(KBFTOR,<%Because: ^E/A/>)
CAIN A,ERTBF$ ; Is host table full?
JRST [WARN<Insufficient Memory>
RET]
JRST HSTID1] ; Get next node
JRST HSTID1 ; Get next
;Here if we've found an entry for a host already in the table. Link
; the node block for this entry to the end of the chain of node blocks
; for this name.
HSTID6: HRRZ C,(A) ; Get pointer to 1st node block
HSTD6A: SKIPE A,N.NEXT(C) ; Is this the last block in the chain?
JRST [ MOVE C,A ; No, keep looking
JRST HSTD6A] ; ..
HRRZM D,N.NEXT(C) ; Yes, append this block to the chain
JRST HSTID1 ; Keep parsing
;Parse switch
;Call: A/ JFN of input file
;Return +1: always, B/ terminating character, A preserved, C trashed
HSTIDK: STKVAR <TERM,IJFN,<TSTR,10>> ; Terminating character, JFN, string
MOVEM A,IJFN ; Save JFN
MOVEI C,TSTR ; Point to place to stuff switch
HRLI C,(POINT 7,)
HSTDK0: CALL BYTIN ; Get a byte
JRST HSTDK1 ; Let someone else bite it on this one
CAIG B,172
CAIGE B,101 ; If not alphabetic,
JRST [ CAIG B,71 ; And also not numeric
CAIGE B,60 ; ..
JRST HSTDK1 ; It terminates this field
JRST .+2] ; Don't TRZ numbers
TRZ B,40 ; Uppercase
IDPB B,C ; Stuff into switch
JRST HSTDK0 ; Loop thru all chars
HSTDK1: MOVEM B,TERM ; Save terminator
SETZ B, ; Insure ASCIZ
IDPB B,C
MOVEI B,TSTR ; Point to switch name
MOVEI A,SWTTAB ; Switch table
$CALL S%TBLK ; Get the sucker
JUMPF [ WARN <Internal error at HSTDK1>
RET]
TXNN B,TL%EXM!TL%ABR ; Found this switch?
RET ; Just ignore unknown switches
HRRZ A,(A) ; Get bits associated with switch
IORM A,FBITS ; Save for posterity
MOVE A,IJFN ; Restore A
MOVE B,TERM ; Return terminator
RET ; Return
;Still in TOPS20
;Still in TOPS20
;Here to handle synonym -- insure that what it is a synonym for is in the
; table, add it to table, and point its entry to real thing
HSTIDS: MOVEI B,0 ; Tie off this string
IDPB B,HDST ; ..
CALL CPYAT2 ; Copy synonym name to string block
JRST HSTIDM ; Insufficient memory
MOVEM A,SSTR ; Address of synonym string
MOVE C,[POINT 7,ATMBF2] ; Where to accumulate "real" name
HSTIS0: CALL BYTIN ; Next byte of real name
JRST HSTIDE
CAIN B,12 ; EOL?
JRST HSTIS1 ; Yes...
IDPB B,C ; No, stuff this char
JRST HSTIS0 ; Keep going
HSTIS1: MOVEI B,0 ; Terminate string
IDPB B,C ; ..
MOVE A,[POINT 7,ATMBF2] ; Point to the real name again
CALL VALID8 ; Call the host validation routine
IFNSK. ; No such host
HRROI A,ATMBF2 ; for error message
HRRO B,SSTR
WARN (UPS:DNHOST.TXT has bad format)
WARN < %2S=%1S, but %1S is not defined>
MOVE A,SSTR ; Release synonym string block
CALL RELSB
CALLRET HSTIDE ; Just quit now
ENDIF. ;
HRRZ A,(B) ; Get real N-block address
EXCH A,SSTR ; Get addr of synonym name, save real N-blk adr
MOVE D,A ; Safer AC
MOVE A,[POINT 7,ATMBF2] ; Copy synonym name to string space
MOVE B,D ; Set up for MOVST0
CALL MOVST0 ; Do the copy
MOVE A,D ; Release SSTR block
CALL RELSB ; ..
MOVE A,SSTR ; Get addr of real N-block
MOVE B,N.FLGS(A) ; Get flag bits for real name
TXZ B,NT%NXL ; Don't propagate no-translate bit
TXO B,NT%SYN ; Light synonym bit
IORM B,FBITS
HRROI A,[ASCIZ /Interoffice-mail/]
HRROI B,ATMBF2 ; Point to current synonym
STCMP ; Does synonym CONTAIN "Interoffice-mail"?
TXNE A,SC%SUB ; If so, it should never be translated
JRST [ MOVX A,NT%NXL ; Yes, light no-translate bit
IORM A,FBITS ; ..
MOVX A,NT%LCL ; Don't propagate "local" bit
ANDCAM A,FBITS ; ..
JRST .+1]
JRST HSTID7 ; Add to host table
;Memory allocation errors all come here
HSTIDM: WARN <Can't build host table because: insufficient memory>
; JRST HSTIDE
;Here on OK finish
HSTIDE: SETO A, ; Unmap file pages
HRLI B,.FHSLF ; from fork
HRR B,HFPGN ; Starting page
MOVE C,HFPGS ; page count
TXO C,PM%CNT
PMAP
MOVE A,HFPGS ; Release storage too
MOVE B,HFPGN
$CALL M%RLNP
MOVE A,HSTJFN
CLOSF ; EOF - close file
JFCL
RET ; Return
;Utility routine to read bytes, ignoring null, LWSP, and CR
;Return +1: EOF or error, msg already typed if error
; +2: OK, byte in B, A preserved
BYTIN: SOSGE HFCNT ; Any bytes left?
RET ; No, nonskip return
ILDB B,HFPTR ; Yes, fetch next
JUMPE B,BYTIN ; Ignore nulls
CAIE B," " ; spaces
CAIN B,.CHCRT ; and CR
JRST BYTIN
CAIE B,.CHFFD ; and Form feeds
CAIN B,.CHTAB ; and tabs
JRST BYTIN
RETSKP
> ; End TOPS20 conditional
;CPYAT2 - Count the bytes in the string in the atom buffer, allocate
; a chunk for it, and copy the string into the chunk.
;Call: no arguments
;Return +1: failure, no room
; +2: OK, A has address of first word of string in chunk
CPYAT2: STKVAR <STRAD>
MOVE A,[POINT 7,ATMBF2] ; Count the bytes
CALL COUNTS ; ..
CALL ALCSB ; Get a chunk
RET ; Propagate failure
MOVEM B,STRAD ; Save string address
MOVE A,B ; Copy address of string space
HRLI A,(POINT 7,) ; Form byte pointer
MOVEI B,ATMBF2 ; Copy from atom buffer to chunk
CALL MOVST0 ; With the null
MOVE A,STRAD ; Return string address to caller
RETSKP ; Success!
;HSTIND - Here from HSTINI for TOPS10
; to get list of all possible hosts
TOPS10<
HSTIND:
;See if host name table exists, and add hosts to table if so.
TRVAR <FBITS,HSTJFN,HFPTR,HFCNT,HSTR,HDST,SSTR,PATH,REDIFN>
MOVEI A,FDXSIZ ; Size of file descriptor
$CALL M%GMEM ; Try to allocate space
JUMPF HSTERR ; No space??
HRLZM A,.FDLEN(B) ;
MOVSI A,(SIXBIT /INI/) ; Structure name
MOVEM A,.FDSTR(B)
MOVE A,[SIXBIT /DNHOST/]
MOVEM A,.FDNAM(B)
MOVSI A,(SIXBIT /TXT/) ; Extension
MOVEM A,.FDEXT(B)
MOVE A,[XWD 5,34]
MOVEM A,.FDPPN(B)
MOVE A,B
CALL ALCFOB
JRST HSTERR
MOVX A,FB.LSN ; Don't try to remove sequence numbers
ANDCAM A,FOB.CW(B) ; ALCFOB set this
SETZM REDIFN ; No read IFN
MOVX A,FOB.MZ ; Fake smaller FOB to bypass protection checks
$CALL F%IOPN ; Open
JUMPF HSTERR
MOVEM A,REDIFN ; Remember IFN for reading and releasing
SETZM HFCNT ; Byte count in file buffer
SETZM HFPTR ; Byte pointer
SETZM PATH ; No path block yet
; JRST HSTID1 ; Enter host parse loop
HSTID1: MOVE A,[POINT 7,ATMBF2] ; Where to build host name string
MOVEM A,HDST ; Init destination pointer
SETZM FBITS ; No flag bits known yet
SETZM SSTR ; No synonyms yet
SETZM PATH ; Init path-seen flag
HSTID2: CALL BYTIN ; Get a byte
JRST HSTIDE ; Error or EOF - quit
CAIN B,"/" ; Check for switches
CALL HSTIDK ; Go handle
CAIN B,"," ; Comma? (routing info follows)
JRST [ SETZ B, ; Insure ASCIZ for name string
IDPB B,HDST ; ..
CALL CPYAT2 ; Allocate a string block
JRST HSTIDM ; Insufficient memory
MOVEM A,PATH ; Save addr of temp block
MOVE A,[POINT 7,ATMBF2] ; Reinit atom buffer pointer
MOVEM A,HDST ; for collection of path string
JRST HSTID2] ; Go eat path string
CAIE B,";" ; Start of comment?
CAIN B,"!" ; ..
JRST HSTID3 ; Yes, go gobble it up
;Here with a valid character which is an element of a hostname
CAIN B,12 ; EOL?
JRST HSTID5 ; Yes, quit this line
CAIN B,"=" ; Start of synonym?
JRST HSTIDS ; Yes, go handle synonym
IDPB B,HDST ; Save character
JRST HSTID2 ; Get next
;Here for comment, gobble it up to EOL
HSTID3: CALL BYTIN ; Eat chars until EOL
JRST HSTIDE
CAIN B,12 ; EOL?
JRST HSTID5 ; Yes, start interpreting chars again
JRST HSTID3 ; No, eat more comment
;Here on EOL to process this line
HSTID5: MOVE A,[POINT 7,ATMBF2] ; Get a virgin pointer
CAMN A,HDST ; Has this pointer been touched?
JRST [ SKIPE A,PATH ; No, release path block if need be
CALL RELSB ; ..
JRST HSTID2] ; Don't put null name in table
MOVEI B,0 ; Yes, add terminating null
IDPB B,HDST ; ..
SKIPE PATH ; Was a path string seen?
JRST [ CALL CPYAT2 ; Yes, copy to a string block
JRST HSTIDM ; Memory allocation error
MOVE D,PATH ; Get addr of hostname string
MOVEM A,PATH ; Save addr of path string
MOVE A,[POINT 7,ATMBF2] ; Copy host name string to atom buffer
MOVE B,D ; Set up for MOVST0
CALL MOVST0 ; Do the copy
MOVEM A,HDST ; Set up HDST so ASCIZing doesn't lose
MOVE A,D ; Get string block address back
CALL RELSB ; Release it
JRST .+1] ; Rejoin main flow
MOVE A,MYHDPT ; Local host name
HRROI B,ATMBF2 ; This host name
$CALL S%SCMP ; See if the same
SKIPN A ; A=0 if name matched
SKIPA B,[NT%LCL!NT%DCN] ; Local, set flag
MOVX B,NT%DCN ; Set DECnet flag
IORB B,FBITS ; Add in any switch-induced bits
TXNE B,NT%KWL ; Can this host receive 20-style mail?
JRST HSTID1 ; No, just reuse string block
HSTID7: MOVE A,[POINT 7,ATMBF2] ; Point to this name
CALL COUNTS ; Count the characters
ADDI A,5 ; Allow space for flag bits
CALL ALCSB ; Allocate a string block
JRST HSTIDM ; Insufficient memory
MOVEM B,HSTR ; Save address of string block
MOVX A,CM%FW ; Light bit that says "dere's flags here!"
IORM A,(B) ; ..
MOVEI A,1(B) ; Skip flags word, set up for MOVST0
HRLI A,(POINT 7,) ; ..
MOVEI B,ATMBF2 ; Address of name string
CALL MOVST0 ; Copy name string to string block
CALL ALCNB ; Allocate node block
JRST HSTIDM ; Insufficient memory
MOVE B,FBITS ; Flag bits
MOVEM B,N.FLGS(A) ; to node block
MOVE B,PATH ; Path string
MOVEM B,N.PATH(A) ; to node block
MOVE B,SSTR ; Addr of node block for real name
MOVEM B,N.REAL(A) ; to node block
MOVE B,HSTR ; String address
MOVEM B,N.NAME(A) ; to node block
HRLZS B,B ; and to LH for TBADD
HRR B,A ; Node block address to RH
MOVE D,B ; Preserve over this stuff
HLR B,B ; Get string address to RH
MOVE A,(B) ; Get possible flags word
TLNN A,(177B6) ; Is this a flags word?
TXNN A,CM%FW ; ..
SKIPA
ADDI B,1 ; Yes, skip the flags and point to string
HRLI B,(POINT 7,) ; Form kosher byte pointer
SKIPN A,HOSTAB ; See if already have an entry
JRST HSTID4 ; No table, so add the entry
$CALL S%TBLK ; ..
TXNE B,TL%EXM ; Do we have an entry?
JRST HSTID6 ; Yes, go link this to it
HSTID4: MOVE B,D ; No, restore HOSTAB entry
MOVEI A,HOSTAB ; Host name table
CALL TBADDS ; Add to table, maybe expanding table
JRST [ $TEXT(KBFTOR,<%Can't add DECnet node ^T/ATMBF2/ to host table>)
CAIN A,ERTBF$ ; Is host table full?
JRST [WARN<Insufficient Memory>
RET]
JRST HSTID1] ; Get next node
JRST HSTID1 ; Get next
;Here if we've found an entry for a host already in the table. Link
; the node block for this entry to the end of the chain of node blocks
; for this name.
HSTID6: HRRZ C,(A) ; Get pointer to 1st node block
HSTD6A: SKIPE A,N.NEXT(C) ; Is this the last block in the chain?
JRST [ MOVE C,A ; No, keep looking
JRST HSTD6A] ; ..
HRRZM D,N.NEXT(C) ; Yes, append this block to the chain
JRST HSTID1 ; Keep parsing
;Parse switch
;Call: A/ JFN of input file
;Return +1: always, B/ terminating character, A preserved, C trashed
HSTIDK: STKVAR <TERM,IJFN,<TSTR,10>> ; Terminating character, JFN, string
MOVEM A,IJFN ; Save JFN
MOVEI C,TSTR ; Point to place to stuff switch
HRLI C,(POINT 7,)
HSTDK0: CALL BYTIN ; Get a byte
JRST HSTDK1 ; Let someone else bite it on this one
CAIG B,172
CAIGE B,101 ; If not alphabetic,
JRST [ CAIG B,71 ; And also not numeric
CAIGE B,60 ; ..
JRST HSTDK1 ; It terminates this field
JRST .+2] ; Don't TRZ numbers
TRZ B,40 ; Uppercase
IDPB B,C ; Stuff into switch
JRST HSTDK0 ; Loop thru all chars
HSTDK1: MOVEM B,TERM ; Save terminator
SETZ B, ; Insure ASCIZ
IDPB B,C
MOVEI B,TSTR ; Point to switch name
MOVEI A,SWTTAB ; Switch table
$CALL S%TBLK ; Get the sucker
JUMPF [ WARN <Internal error at HSTDK1>
RET]
TXNN B,TL%EXM!TL%ABR ; Found this switch?
RET ; Just ignore unknown switches
HRRZ A,(A) ; Get bits associated with switch
IORM A,FBITS ; Save for posterity
MOVE A,IJFN ; Restore A
MOVE B,TERM ; Return terminator
RET ; Return
;Still in TOPS10
;Still in TOPS10
;Here to handle synonym -- insure that what it is a synonym for is in the
; table, add it to table, and point its entry to real thing
HSTIDS: MOVEI B,0 ; Tie off this string
IDPB B,HDST ; ..
CALL CPYAT2 ; Copy synonym name to string block
JRST HSTIDM ; Insufficient memory
MOVEM A,SSTR ; Address of synonym string
MOVE C,[POINT 7,ATMBF2] ; Where to accumulate "real" name
HSTIS0: CALL BYTIN ; Next byte of real name
JRST HSTIDE
CAIN B,12 ; EOL?
JRST HSTIS1 ; Yes...
IDPB B,C ; No, stuff this char
JRST HSTIS0 ; Keep going
HSTIS1: MOVEI B,0 ; Terminate string
IDPB B,C ; ..
MOVE A,HOSTAB ; Point to host name table
MOVE B,[POINT 7,ATMBF2] ; Look up this entry
$CALL S%TBLK ; Better exist
TXNN B,TL%EXM ; Does it?
JRST [ HRROI A,ATMBF2 ; for error message
HRRO B,SSTR
WARN (SYS:HOSTS.TXT has bad format)
WARN < %2S=%1S, but %1S is not defined>
MOVE A,SSTR ; Release synonym string block
CALL RELSB
CALLRET HSTIDE] ; Just quit now
HRRZ A,(A) ; Get real N-block address
EXCH A,SSTR ; Get addr of synonym name, save real N-blk adr
MOVE D,A ; Safer AC
MOVE A,[POINT 7,ATMBF2] ; Copy synonym name to string space
MOVE B,D ; Set up for MOVST0
CALL MOVST0 ; Do the copy
MOVE A,D ; Release SSTR block
CALL RELSB ; ..
MOVE A,SSTR ; Get addr of real N-block
MOVE B,N.FLGS(A) ; Get flag bits for real name
TXZ B,NT%NXL ; Don't propagate no-translate bit
TXO B,NT%SYN ; Light synonym bit
IORM B,FBITS
; HRROI A,[ASCIZ /Interoffice-mail/]
; HRROI B,ATMBF2 ; Point to current synonym
; STCMP ; Does synonym CONTAIN "Interoffice-mail"?
; TXNE A,SC%SUB ; If so, it should never be translated
; JRST [ MOVX A,NT%NXL ; Yes, light no-translate bit
; IORM A,FBITS ; ..
; MOVX A,NT%LCL ; Don't propagate "local" bit
; ANDCAM A,FBITS ; ..
; JRST .+1]
JRST HSTID7 ; Add to host table
;Memory allocation errors all come here
HSTIDM: WARN <Can't build host table because: insufficient memory>
; JRST HSTIDE
;Here on OK finish
HSTIDE: MOVE A,REDIFN ; Get file IFN
$CALL F%REL ; Done, close file
JFCL
SETZM REDIFN
HSTERR: RET ; Return
;Utility routine to read bytes, ignoring null, LWSP, and CR
;Return +1: EOF or error, msg already typed if error
; +2: OK, byte in B, A preserved
BYTIN: SOSGE HFCNT ; Any bytes left?
JRST RDBUF ; Try for more
ILDB B,HFPTR ; Yes, fetch next
JUMPE B,BYTIN ; Ignore nulls
CAIE B," " ; spaces
CAIN B,15 ; and CR
JRST BYTIN
CAIN B,11 ; Ignore tabs
JRST BYTIN
RETSKP
RDBUF: MOVE A,REDIFN ; Get the IFN for this file
$CALL F%IBUF ; Try to get a buffer
JUMPF RDONE
MOVEM A,HFCNT ; Save byte count
MOVEM B,HFPTR ; and pointer
JRST BYTIN
RDONE: RET
repeat 0,<
NODUUO: STKVAR <NBLK,SBLK,NPAG> ; Node block addr, Node name string block
; And NODE. UUO block address
$CALL M%GPAG ; Get a free page
MOVEM A,NPAG ; Save address for later
MOVE E,A ; Copy block address
HRLI E,.NDLND ; Insert NODE. function to list nodes
MOVEI B,1000 ; Length of block
MOVEM B,(A) ; Set for UUO
NODE. E, ; Return list of reachable nodes
JRST NODUUX ; There are no ANF-10 nodes
MOVNS E ; Get negative node count
MOVSS E ; Form into left half for AOBJN
HRRI E,1(A) ; Point to first node in list
NODUU0: MOVE C,(E) ; Get next node number to convert
MOVEI B,2 ; Number of words in block
MOVE A,[.NDRNN,,B] ; Set up for node uuo
NODE. A, ; Convert node number to name
JRST NODUU3 ; Node went off-line
MOVE B,A ; Get SIXBIT into better AC
MOVE C,[POINT 7,NODNAM]; Where to put ASCII name
NODUU1: SETZ A,
LSHC A,6 ; Get SIXBIT character in A
ADDI A,40 ; Make ASCII
IDPB A,C ; Stuff into name
JUMPN B,NODUU1 ; Do all chars
IDPB B,C ; Insure ASCIZ
MOVE A,[POINT 7,NODNAM]
CALL COUNTS ; Count the bytes in it
ADDI A,5 ; Account for flag word
CALL ALCSB ; Get a string block for it
JRST [ WARN <Can't get string block for local node names>
JRST NODUUM]
MOVEM B,SBLK ; Save address of string block
MOVX A,CM%FW ; There are flags in first word of block
IORM A,(B) ;
MOVEI A,1(B) ; Set up for MOVST2
HRLI A,(POINT 7,) ; Byte pointer
MOVE B,[POINT 7,NODNAM] ; Pointer to name
CALL MOVST2 ; Copy to new block
CALL ALCNB
JRST [ WARN <Can't get node block for local nodes>
JRST NODUUM]
MOVEM A,NBLK ; Save address of node block
MOVE A,[POINT 7,NODNAM] ; Name of node we are processing
MOVE B,MYHSPT ; Name of our host
$CALL S%SCMP ; See if this name matches local node name
MOVX B,NT%DCN!NT%NM0 ; DECNET node, name in heap space
SKIPN A ; A = 0 if name matched
TXO B,NT%LCL ; Match, this is the local node
MOVE A,NBLK ; Point to node block
MOVEM B,N.FLGS(A) ; Stuff flags into N-block
MOVE B,SBLK ; Get string block address
MOVEM B,N.NAME(A) ; and save pointer in node block
HRLZS B,B ; Set up for TBADDS with LH=string pointer
HRR B,A ; and right half in node block pointer
MOVEI A,HOSTAB ; Addr of ptr to host table
CALL TBADDS ; Load 'em on up!
JRST [$TEXT(KBFTOR,<%Can't add ANF node ^T/NODNAM/ to host table.>)
CAIN A,EREIT$ ; Is node already in table?
JRST NODUU3 ; Try the next node
JRST NODUUM] ; No more room
NODUU3: AOBJN E,NODUU0 ; Loop through all blocks we got
JRST NODUUX ; Finish up
NODUUM: WARN <Insufficient memory>
NODUUX: MOVE A,NPAG ; Get node block address back again
$CALL M%RPAG ; Return the page to the free pool
RET
>;End TOPS10
>; end repeat 0
;ALCNB - Allocate a node block
;Call: no arguments
;Return +1: failure, no memory
; +2: success, A/ address of Node Block (N.SIZE inited)
ALCNB: MOVEI A,N.LEN ; Length of a node block
$CALL M%GMEM ; Get a chunk
JUMPF R ; Error, nonskip return
MOVEM A,N.SIZE(B) ;
MOVE A,B ; Return addr of block in A for caller
RETSKP ; Good return
;RELNB - Release a node block
;Call: A/ address of node block
;Return +1: always
RELNB: MOVE B,A ; Set up for M%RMEM
MOVEI A,N.LEN ; Length of a node block
$CALL M%RMEM
RET
END
; Edit 2462 to MSHOST.MAC by PRATT on 1-Nov-85
; Merge many changes in -10, -20, and common code.
; *** Edit 2479 to MSHOST.MAC by PRATT on 20-Nov-85
; Fix off by one bug in VALID8 that kept Arpa mail from working
; *** Edit 2484 to MSHOST.MAC by SANTEE on 21-Nov-85
; Clean up the various edit histories.
; *** Edit 2485 to MSHOST.MAC by MAYO on 21-Nov-85
;
; *** Edit 2486 to MSHOST.MAC by PRATT on 22-Nov-85
; Copyright statements
; *** Edit 2651 to MSHOST.MAC by SANTEE on 2-Feb-86
; Eliminate the need for MSUTAB at all. Move the few useful lines elsewhere.
; *** Edit 2700 to MSHOST.MAC by RASPUZZI on 20-May-86
; Change MS to look for UPS:DNHOST.TXT instead of SYSTEM:DECNET-HOSTS.TXT
; Edit= 3105 to MSHOST.MAC on 17-May-88 by WADDINGTON, for SPR #21402
;Use the CNFIG% JSYS instead of relying on the NODE% jsys failure to determine
;if DECnet exists.