perm filename UPDATE.OLD[HST,NET] blob sn#745656 filedate 1984-03-13 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00015 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00004 00002	TITLE UPDATE  History FTPUP A B C D E H X P DIN DOUT DVER ERR PUPVER PUPEFT SRINIC SRINIC HNSPRT PDLEN BUFLEN NICVER DSKVER ENDMK ENDEND FTPCOM PTYJOB DIRHLN DIRHDR VERPTR VERLSN VERSTS VERTRM VERCON VCNSTS VERHST EFTGEN EFTGSK EFTLSN EFTSTS EFTLSK EFTHST PUPMAX PKTBUF PKTLEN PKTTYP PKTDST PKTSRC PKTBFD PUPOVH OURHST PUPDSV PUPMSV PUPMHS PDL DIBUF DOBUF DVIBUF DVOBUF PUPIBF ERBUF ERRORS CHANGE CRLF MAIHD1 MAIHD2 MAIHD3 MAIBLK NIORTS ERRTNS PUPDIR PUPHSP NUMNAM NAMLKP NUMADR ADRLKP NUMENT FSTENT PUPVRS HDRSIZ ENTPTR CPUPTR OPSPTR PRTPTR DOMSTR DOMHST DOMNAM DOMNUM
C00018 00003	LOOKUP/ENTER blocks for files  VERFIL HSTFIL ERRFIL DIRFIL PHSFIL
C00019 00004	Output subroutines  NETSTR NETST1 DECOUT OCTOUT OCTOU1 CPOPJ1 CPOPJ
C00021 00005	Error handling  MESTYP MESTY1 MAILMS ERRERR
C00024 00006	Get and compare NIC version strings  VERNIC VERNI1 VERNI2 VERIN VERIN1 VERIN2 VEROUT VEROU1 VEROU2 VERCOM VERCO1
C00030 00007	Get new NIC table from Host Name Server  NEWNIC NEWNI1 NEWNI2 NEWNI3
C00034 00008	FTP new HOSTS3.BIN from NIC  NEWNIC NEWNI1 NEWNI2 NEWNI3
C00038 00009	Read PUP directory version number  RDPVER RDPDIR
C00041 00010	Get PUP version from Ethernet  GETVER GETVE1
C00045 00011	Get new PUP directory  GNPDIR GNPDI1 GNPDI2 GNPDI3 GNPDI4 GETCOR GETCO1
C00051 00012	File output routines  PUTCH PUTCH1 PUTSTR PUTST1 PUTDEC PUTOCT PUTOC1 PUTSIX PUTDAT MONTH
C00054 00013	More subroutines  OUTADR OUTNAM OUTNLP COMPAR COMPLP COMPL1 COMPL2 CMPLUZ PUTATR PUTALP PUTAT1
C00060 00014	Create PUPHST.TXT file  PUPHST HDRLP MAINLP ATTLP ATTLP1 ALLDUN SHORT
C00066 00015	Top level  NICUPD NICERR PUPUPD PUPERR PUPHAK UPDATE PPNOK NOERRS
C00072 ENDMK
C⊗;
TITLE UPDATE ;⊗ History FTPUP A B C D E H X P DIN DOUT DVER ERR PUPVER PUPEFT SRINIC SRINIC HNSPRT PDLEN BUFLEN NICVER DSKVER ENDMK ENDEND FTPCOM PTYJOB DIRHLN DIRHDR VERPTR VERLSN VERSTS VERTRM VERCON VCNSTS VERHST EFTGEN EFTGSK EFTLSN EFTSTS EFTLSK EFTHST PUPMAX PKTBUF PKTLEN PKTTYP PKTDST PKTSRC PKTBFD PUPOVH OURHST PUPDSV PUPMSV PUPMHS PDL DIBUF DOBUF DVIBUF DVOBUF PUPIBF ERBUF ERRORS CHANGE CRLF MAIHD1 MAIHD2 MAIHD3 MAIBLK NIORTS ERRTNS PUPDIR PUPHSP NUMNAM NAMLKP NUMADR ADRLKP NUMENT FSTENT PUPVRS HDRSIZ ENTPTR CPUPTR OPSPTR PRTPTR DOMSTR DOMHST DOMNAM DOMNUM

COMMENT ⊗

This is a WAITS program to automatically update NIC and PUP host tables.
It runs at SAIL and S1-A (LLL), with different code chosen by assembly switches.

Written by Joe Weening, SU-AI, July 1983.

Currently, this program does the following:
1. Gets the version number of the current host table from the host name server
   at SRI-NIC, and compares it with the version number of our file.  The version
   number is stored as a character string in the file HOSTS.VER[HST,NET].  If
   needed, a new host table is retrieved.  For S1-A, the binary HOSTS3 table is
   retrieved using FTP on a PTY subjob into HOSTS3.BIN[HST,NET].  For SAIL, the
   text table is retrieved from the host name server into HOSTS.TXT[HST,NET].
2. For SAIL, sends out the version number of our PUP network directory, and
   collects replies indicating higher version numbers at other Ethernet sites.
   Updates the directory, kept as the binary file PUPNET.DIR[HST,NET], if a
   newer version is present, and converts this to a text version in RFC810
   format, stored as PUPHST.TXT[HST,NET].

Future plans include the following:
3. Merge the text form of the NIC and PUP tables into a binary HOSTS3-format
   table, and store it as HOSTS3.BIN[HST,NET].  This can now be done with the
   HOSTS3 program.  (Perhaps should load "do merge" into TTY input buffer.)


   Jul 83 JJW	Initial implementation (get HOSTS.TXT from NIC Hostname server).
   Sep 83 JJW	Get binary PUP network directory using PUP network directory
		update protocol.  Conversion to text form done by separate program.
18-Dec-83 JJW	Merged in PUPHST code from separate program.
27-Jan-84 JJW	FTLLL etc. defined from WATSIT[S,SYS].  FTPUP switch introduced.
11-Feb-84 JJW	FTLLL code to get HOSTS3.BIN from NIC, running FTP on a PTY.
02-Mar-84 JJW	PUPHST includes domain-style names for known hosts in NIC table.

History: end of comment ⊗
PRINTS /Have you listed your changes at History: on page 2?
/

;Switch definitions
.INSERT WATSIT[S,SYS]		;Define FTSUAI, FTLLL, etc.
FTPUP←←IFN FTLLL,<0;>-1		;Everyone except LLL is a Stanford PUP site

A←1				;AC definitions
B←2
C←3
D←4
E←5
H←10
X←11
P←17

;I/O channels.  0, 1, and 2 are reserved for NETWRK, used for IMP I/O.
;NETWRK is not used for PUP I/O, since it doesn't handle packet and EFTP modes.

DIN←←3				;Disk input channel
DOUT←←4				;Disk output channel
DVER←←5				;Disk channel for HOSTS.VER file
ERR←←6				;Disk channel for error message file
IFN FTPUP,<
PUPVER←←7			;PUP channel for version request
PUPEFT←←10			;PUP channel for EFTP directory update
>;IFN FTPUP

;Host number for SRI-NIC.  We could use HSTNAM in NETWRK, but then we'd lose if
;there was something wrong with the host table.
IFE FTLLL,<
SRINIC←←<BYTE (4)0(8)=10,0,0,=51> ;ARPAnet address
>;IFE FTLLL
IFN FTLLL,<
SRINIC←←<BYTE (4)0(8)=26,0,0,=73> ;MILnet address
>;IFN FTLLL
HNSPRT←←=101			;Host Name Server port number

IFN FTPUP,<MSCSKT←←4>		;Misc. server socket number

;Other definitions
PDLEN←←20			;Stack
BUFLEN←←40			;Length of various blocks

;Data for NIC table update

NICVER:	BLOCK BUFLEN		;Version string from NIC
DSKVER:	BLOCK BUFLEN		;Version string on disk

IFE FTLLL,<
ENDMK:	12			;Chars that mark end of NIC host table
	"E"
	"N"
	"D"
ENDEND←←.
>;IFE FTLLL

IFN FTLLL,<
				;Command line typed on PTY to run FTP.
FTPCOM:	ASCIZ*FTP/Q HOSTS3.BIN←{26.0.0.73}<NETINFO>HOSTS3.BIN
*
PTYJOB:	BLOCK 1			;Job number of job created on PTY for FTP
>;IFN FTLLL

IFN FTPUP,<
;Definitions for reading header of PUP network directory from file

DIRHLN←←4			;Number of header words to read
DIRHDR:	BLOCK DIRHLN
VERPTR:	POINT 16,DIRHDR+3,15	;Byte ptr for version number

;MTAPE blocks for PUP operations

VERLSN:	1			;Listen block for PUP version request
VERSTS:	0			;Status bits returned
	-1			;Local socket
	0			;Don't wait
	=8			;Byte size
	MSCSKT			;Foreign socket
	-1			;Foreign host (broadcast)

VERTRM:	3			;Terminate block for PUPVER
	0			;Status
	0			;Local socket
	0			;Don't wait

VERCON:	0			;Connect block for PUPVER
VCNSTS:	0			;Status
	-1			;Local socket
	-1			;Do wait (though in packet mode we won't)
	=8			;Byte size
	MSCSKT			;Foreign socket
VERHST:	0			;Foreign host

EFTGEN:	21			;Gensym block for EFTP socket
EFTGSK:	0

EFTLSN:	1			;Listen block for EFTP
EFTSTS:	0			;Status bits returned
EFTLSK:	0			;Local socket
	0			;Don't wait
	=8			;Byte size
	-1			;Foreign socket (whatever they choose)
EFTHST:	0			;Foreign host

;Definitions for sending packet-mode PUPs

PUPMAX←←=140			;Maximum PUP packet length
PKTBUF:	BLOCK PUPMAX		;PUP packet buffer

;Pointers into PKTBUF

PKTLEN:	POINT 16,PKTBUF,15	;PUP length (in bytes)
PKTTYP:	POINT 16,PKTBUF,31	;PUP Type
PKTDST:	POINT 16,PKTBUF+2,15	;PUP Destination host
PKTSRC:	POINT 16,PKTBUF+3,31	;PUP Source host
PKTBFD←←PKTBUF+5		;Location of data within PUP
PUPOVH←←=22			;Number of overhead bytes in a PUP

;Data for PUP network directory update

OURHST:	BLOCK 1			;Our PUP address (from an incoming packet)
PUPDSV:	BLOCK 1			;PUP directory on disk's version number
PUPMSV:	BLOCK 1			;Highest version number from misc. servers
PUPMHS:	BLOCK 1			;Host number that has highest version

>;IFN FTPUP

;Other things

PDL:	BLOCK PDLEN
DIBUF:	BLOCK 3			;Buffer headers
DOBUF:	BLOCK 3
DVIBUF:	BLOCK 3
DVOBUF:	BLOCK 3
IFN FTPUP,<
PUPIBF:	BLOCK 3
>;IFN FTPUP
ERBUF:	BLOCK 3
ERRORS:	0			;-1 if we have errors
CHANGE:	0			;-1 if anything changed
CRLF:	BYTE (7)15,12

;Definitions for error messages

DEFINE MESSAG(MESS) <
	JRST [  MOVEI A,[ASCIZ\MESS
\]
		JRST MESTYP]
>

;Header lines for error message file
MAIHD1:	ASCIZ\MAIL/SUBJECT BUG-HOST\
MAIHD2:	BYTE (7)15,12,14	;CRLF,FF
MAIHD3:	ASCIZ/Report from UPDATE of host tables

/

;Data block for SWAP UUO
MAIBLK:	SIXBIT/SYS/
	SIXBIT/MAIL/
	SIXBIT/DMP/
	0,,1			;RPG startup
	0
	0

NIORTS←←-1			;Use network I/O routines for IMP
ERRTNS←←-1			;Error routines
.INSERT NETWRK.FAI[S,NET]	;Wonderful network I/O package

IFN FTPUP,<
PUPDIR:	BLOCK 1			;Address of PUP directory read in
PUPHSP:	BLOCK 1			;Saved PDL ptr

;Data from header block in PUP directory.  All blocks and tables are guaranteed
;to be on an even 16-bit byte boundary, i.e., at the start of a PDP-10 word.
NUMNAM:	BLOCK 1			;Number of name blocks
NAMLKP:	BLOCK 1			;Pointer to name lookup table
NUMADR:	BLOCK 1			;Number of address blocks
ADRLKP:	BLOCK 1			;Pointer to address lookup table
NUMENT:	BLOCK 1			;Number of 16-bit words occupied by entry blocks
FSTENT:	BLOCK 1			;Pointer to first entry block
PUPVRS:	BLOCK 1			;Version of PUP directory
HDRSIZ←←.-NUMNAM		;Size of header block

ENTPTR:	BLOCK 1			;Byte pointer to step through entry blocks
CPUPTR:	BLOCK 1			;Directory address of CPU attribute string
OPSPTR:	BLOCK 1			;Op-System
PRTPTR:	BLOCK 1			;Protocols

;For the HOSTS3 program to match entries of Stanford hosts, we make PUPHST.TXT
;contain domain-style names in addition to the names in the PUP network
;directory.  This is done in a rather ad-hoc fashion.

DEFINE SHOSTS<
SHOST(50,300,SU-SHASTA.ARPA)
SHOST(50,301,SU-HNV.ARPA)
SHOST(50,302,SU-AI.ARPA)
SHOST(50,303,SU-SCORE.ARPA)
SHOST(50,310,SU-DSN.ARPA)
SHOST(50,313,SU-NAVAJO.ARPA)
SHOST(50,314,SU-WHITNEY.ARPA)
SHOST(50,315,SU-GLACIER.ARPA)
SHOST(50,324,SU-CARMEL.ARPA)
SHOST(50,325,SU-SIERRA.ARPA)
SHOST(50,327,SU-COYOTE.ARPA)
SHOST(55,125,SU-ARDVAX.ARPA)
SHOST(55,126,SU-SAFE.ARPA)
SHOST(55,127,SUMEX-AIM.ARPA)
>;DEFINE SHOSTS

DOMSTR:	BLOCK 1			;Addr of domain name to use, if non-zero
DEFINE SHOST(A,B,NAME)<
	A⊗10+B
>
DOMHST:	SHOSTS
DEFINE SHOST(A,B,NAME)<
	[ASCIZ/NAME, /]
>
DOMNAM:	SHOSTS
DOMNUM←←.-DOMNAM

>;IFN FTPUP
;LOOKUP/ENTER blocks for files ;⊗ VERFIL HSTFIL ERRFIL DIRFIL PHSFIL

VERFIL:	SIXBIT/HOSTS/		;File with NIC version string
	SIXBIT/VER/
	0
	0

IFE FTLLL,<
HSTFIL:	SIXBIT/HOSTS/		;NIC host table
	SIXBIT/TXT/
	0
	0
>;IFE FTLLL

ERRFIL:	SIXBIT/$MAIL/		;Error message mail file
	SIXBIT/TMP/
	0
	0

IFN FTPUP,<
DIRFIL:	SIXBIT/PUPNET/		;PUP network directory
	SIXBIT/DIR/
	0
	0

PHSFIL:	SIXBIT/PUPHST/		;PUP text file
	SIXBIT/TXT/
	0
	0
>;IFN FTPUP
;Output subroutines ;⊗ NETSTR NETST1 DECOUT OCTOUT OCTOU1 CPOPJ1 CPOPJ

;Output a string to current network connection.  Call:
;	MOVEI A,[ASCIZ/string/]
;	PUSHJ P,NETSTR
;	<error return>
;	<normal return>
;Clobbers 0 and A.
NETSTR:	HRLI A,440700		;Make byte ptr
NETST1:	ILDB 0,A		;Get char
	JUMPE 0,CPOPJ1		;All done
	PUSHJ P,NETOCH		;Send char
	 POPJ P,		;Error return
	JRST NETST1

;Numeric output routines.  Call with number in A, clobbers B and C.

DECOUT:	SKIPA C,[=10]		;Decimal
OCTOUT:	MOVEI C,=8		;Octal
OCTOU1:	IDIVI A,(C)
	HRLM B,(P)
	JUMPE A,.+2
	PUSHJ P,OCTOU1
	HLRZ B,(P)
	ADDI B,"0"
	OUTCHR B
	POPJ P,

CPOPJ1:	AOS (P)
CPOPJ:	POPJ P,
;Error handling ;⊗ MESTYP MESTY1 MAILMS ERRERR

;Error message handler.  Generally the MESSAG macro is used on errors, which
;causes a jump to here.  This then does a POPJ P, which indicates to the next
;level up that there was an error.

MESTYP:	OUTSTR (A)		;Type error message on terminal
	HRLI A,440700		;Make byte ptr
	SKIPGE ERRORS		;Have there been previous errors?
	JRST MESTY1		;Yes, add current text to output
	SETOM ERRORS		;No, this is the first time we're here
	PUSH P,A		;Save ptr while we output header
	INIT ERR,0		;Open error file
	 SIXBIT/DSK/
	 ERBUF,,0
	 JRST ERRERR
	SETZM ERRFIL+3		;Create error file on our area
	ENTER ERR,ERRFIL
	 JRST ERRERR
	MOVE A,[POINT 7,MAIHD1]
	PUSHJ P,MESTY1		;Output first part of header
	MOVE A,[POINT 7,MAIHD2]
	PUSHJ P,MESTY1		;Second part
	MOVE A,[POINT 7,MAIHD3]
	PUSHJ P,MESTY1		;Third part
	POP P,A			;Now output message
MESTY1:	ILDB 0,A
	JUMPE 0,CPOPJ
	SOSG ERBUF+2
	OUT ERR,
	CAIA
	JRST ERRERR
	IDPB 0,ERBUF+1
	JRST MESTY1

;Here to mail accumulated error text.
MAILMS:	RELEAS ERR,		;Write out error file
	MOVE 14,ERRFIL		;Set input filename for MAIL
	MOVE 13,ERRFIL+1
	MOVEI 11,0		;File is on alias area
	MOVEI 12,0		;No returned message
	MOVEI 0,MAIBLK
	SWAP 0,			;Swap to mail
	POPJ P,			;Return if we get back somehow

;Here for error within an error
ERRERR:	OUTSTR [ASCIZ/Error in writing error file!
/]
	HALT .
;Get and compare NIC version strings ;⊗ VERNIC VERNI1 VERNI2 VERIN VERIN1 VERIN2 VEROUT VEROU1 VEROU2 VERCOM VERCO1

;Get version string from the NIC Host Name Server.  Call:
;	PUSHJ P,VERNIC
;	<error return>
;	<success, version string in NICVER>
VERNIC:	MOVE A,[SRINIC]		;Set host number for NETWRK
	MOVEM A,HOST
	MOVEI A,HNSPRT		;And port number
	MOVEM A,ICPSKT
	PUSHJ P,CONECT		;Call NETWRK subroutine
	 JRST [	PUSHJ P,MTPERR
		MESSAG Can't connect to NIC for version request.]
	 JRST [	PUSHJ P,NIOERR
		MESSAG Can't connect to NIC for version request.]
	MOVEI A,[ASCIZ/VERSION
/]
	PUSHJ P,NETSTR		;Send a version request
	 MESSAG Error in sending version request.
	PUSHJ P,NETSND		;Force output out
	 MESSAG Error in sending version request.
	;Now read in characters until connection closes.
	MOVE C,[POINT 7,NICVER]	;Ptr to start depositing chars
VERNI1:	PUSHJ P,NETICW		;Get a char
	 JRST [	TRNN 0,IODEND	;Connection closed?
		MESSAG I/O error in version request reply.
		JRST VERNI2]
	IDPB 0,C		;Store char
	CAMN C,[POINT 7,NICVER+BUFLEN-1,34] ;Check for overflow
	MESSAG Buffer overflow in version request reply.
	JRST VERNI1		;Back for more

VERNI2:	MOVEI 0,0		;End with a null
	IDPB 0,C
	PUSHJ P,CLOSER		;Call NETWRK to close connection
	JRST CPOPJ1		;And take success return


;Get version string of current NIC host table on disk.  Call:
;	PUSHJ P,VERIN
;	<error return>
;	<success, version string in DSKVER>
VERIN:	SETZM DSKVER		;In case LOOKUP fails
	INIT DVER,0
	 SIXBIT/DSK/
	 DVOBUF,,DVIBUF
	 MESSAG INIT error for version file input.
	SETZM VERFIL+3		;Look on alias area
	LOOKUP DVER,VERFIL
	 JRST CPOPJ1		;If no version file, just return
	MOVE C,[POINT 7,DSKVER]	;Ptr to start depositing chars
VERIN1:	SOSG DVIBUF+2
	IN DVER,
	 JRST VERIN2
	GETSTS DVER,A
	TRNN A,IODEND		;End of file?
	MESSAG Input error on version file.
	TDZA 0,0		;End with a null
VERIN2:	ILDB 0,DVIBUF+1
	IDPB 0,C
	JUMPE 0,CPOPJ1		;Null or EOF marks end
	CAMN C,[POINT 7,DSKVER+BUFLEN-1,34] ;Check for overflow
	MESSAG Buffer overflow in version file input.
	JRST VERIN1		;Back for more


;Output NIC version string to the file.  Call:
;	<call VERIN; leave DVER channel open>
;	 ...
;	PUSHJ P,VEROUT
;	<error return>
;	<success return>
VEROUT:	SETZM VERFIL+3		;Clear PPN clobbered by LOOKUP
	ENTER DVER,VERFIL	;Open in Read-Alter mode
	 MESSAG ENTER error for version file output.
	USETO DVER,0		;Position at beginning
	MOVE C,[POINT 7,NICVER]
VEROU1:	ILDB 0,C
	JUMPE 0,VEROU2		;Check for end
	SOSG DVOBUF+2
	OUT DVER,
	CAIA
	MESSAG Output error on version file.
	IDPB 0,DVOBUF+1
	JRST VEROU1

VEROU2:	RELEAS DVER,		;Put file in place
	JRST CPOPJ1


;Compare version strings stored in NICVER and DSKVER.  Call:
;	PUSHJ P,VERCOM
;	<return if the same>
;	<return if different>
VERCOM:	MOVE C,[POINT 7,NICVER]	;Set byte pointers
	MOVE D,[POINT 7,DSKVER]
VERCO1:	ILDB A,C		;Get a byte from each string
	ILDB B,D
	JUMPE A,[JUMPN B,CPOPJ1	;Exit if at end of first string
		 POPJ P,]
	JUMPE B,CPOPJ1		;Or second
	CAIN A,(B)		;Compare
	JRST VERCO1		;Keep checking
	JRST CPOPJ1		;Different
;Get new NIC table from Host Name Server ;⊗ NEWNIC NEWNI1 NEWNI2 NEWNI3

IFE FTLLL,<

;Read in a new table from NIC Host Name Server.  Call:
;	PUSHJ P,NEWNIC
;	<error return>
;	<success>
NEWNIC:	MOVEI A,1		;This helps prevent second CONECT losing
	SLEEP A,
	MOVE A,[SRINIC]		;Set host number
	MOVEM A,HOST
	MOVEI A,HNSPRT		;And port number
	MOVEM A,ICPSKT
	PUSHJ P,CONECT
	 JRST [	PUSHJ P,MTPERR
		MESSAG Can't connect to NIC for host table request.]
	 JRST [	PUSHJ P,NIOERR
		MESSAG Can't connect to NIC for host table request.]
	MOVEI A,[ASCIZ/ALL
/]
	PUSHJ P,NETSTR		;Ask for the whole table
	 MESSAG Error in sending host table request.
	PUSHJ P,NETSND		;Force output out
	 MESSAG Error in sending host table request.

	INIT DOUT,0		;Get ready to write new file
	 SIXBIT/DSK/
	 DOBUF,,0
	 MESSAG INIT error for host table output.
	MOVEI A,DOUT
	SHOWIT A,
	SETZM HSTFIL+3		;Write file on our area
	ENTER DOUT,HSTFIL
	 MESSAG ENTER error for host table output.
	MOVEI A,346		;Lowcore pointer for optimal number of buffers
	PEEK A,
	HLRZ A,A
	OUTBUF DOUT,(A)
	MOVEI C,0		;Initialize byte count
	MOVEI E,ENDMK		;Initialize endmark tester

NEWNI1:	PUSHJ P,NETICW		;Get a character from the network
	 JRST [ TRNN 0,IODEND	;Test for connection close
		MESSAG I/O error in host table request reply.
		JRST NEWNI3]
	SOSG DOBUF+2		;Output the character
	OUT DOUT,
	 CAIA
	MESSAG Output error in writing host table file.
	IDPB 0,DOBUF+1
	SKIPGE E		;Skip unless already seen endmark
	AOJA C,NEWNI1		;Go back for more
	CAMN 0,(E)		;Compare current char to next in endmark
	AOJA E,NEWNI2		;If same, set up for next char
	MOVEI E,ENDMK		;If different, start test at beginning
	AOJA C,NEWNI1		;Go back for more

NEWNI2:	CAIN E,ENDEND		;Matched entire endmark?
	SETOM E			;Yes, note this
	AOJA C,NEWNI1		;And go finish input

NEWNI3:	OUT DOUT,		;Do last output
	 CAIA
	MESSAG Output error in writing host table file.
	SKIPL E			;Was endmark seen?
	MESSAG Endmark of NIC host table not received.
	RELEAS DOUT,		;Yes, put new file in place
	PUSHJ P,CLOSER		;Close net connection
	JRST CPOPJ1		;And take success return

>;IFE FTLLL
;FTP new HOSTS3.BIN from NIC ;⊗ NEWNIC NEWNI1 NEWNI2 NEWNI3

IFN FTLLL,<

;Call:
;	PUSHJ P,NEWNIC
;	<error return>
;	<success>
NEWNIC:	PTYGET A		;Get a PTY, returns line number in A
	 MESSAG PTYGET for FTP failed.
	MOVEI B,5		;PTJOBX LOGIN code
	PTJOBX A		;Login a job
	 MESSAG Couldn't login job on PTY for FTP.
	MOVEM B,PTYJOB		;Save job number
	MOVEI B,FTPCOM		;Get FTP command line
	PTWRS7 A		;Type it on the PTY
	;Now loop, waiting for FTP to finish, or some error.
	MOVEI D,=300		;Time out after 300 tries (10 mins)
	MOVEI C,2		;Number of seconds per try
NEWNI1:	SLEEP C,		;Sleep 2 seconds
NEWNI2:	PTRD1S A		;Empty PTY's output buffer
	 JRST NEWNI3		;Nothing more to read
	OUTCHR B		;Show what it said
	JRST NEWNI2		;Go back for more

NEWNI3:	MOVE B,PTYJOB		;Check FTP job's runtime
	RUNTIM B,
	CAIL B,=30000		;Don't let it use more than 30 cpu secs
	JRST [	PTYREL A	;It's probably looping; kill it
		MESSAG FTP aborted after 30 cpu seconds.]
	MOVEI B,6		;PTJOBX IWAITS code
	PTJOBX A		;Is it waiting for input?
	 JRST [ SOJG D,NEWNI1	;No, keep waiting (unless timeout)
		PTYREL A	;Looks like it's hung
		MESSAG FTP aborted after 10 elapsed minutes.]
	PTYREL A		;I think we succeeded!
	;At this point, we should probably do some consistency checks on the
	;binary file, having FTPed it to a different name temporarily, and
	;then rename it to HOSTS3.BIN if all OK.
	JRST CPOPJ1		;Success return

>;IFN FTLLL
;Read PUP directory version number ;⊗ RDPVER RDPDIR

IFN FTPUP,<			;Several pages

;Here to read saved version number from PUP network directory on disk.  Call:
;	PUSHJ P,RDPVER
;	<error return>
;	<success, version number in PUPDSV>
RDPVER:	INIT DIN,17		;Open disk input in dump mode
	 SIXBIT/DSK/
	 0
	 MESSAG INIT error for PUP network directory input.
	SETZM DIRFIL+3		;Read file on our area
	LOOKUP DIN,DIRFIL
	 JRST CPOPJ1		;Just return if no file
	IN DIN,[IOWD DIRHLN,DIRHDR ↔ 0]	;Read the header
	 CAIA
	MESSAG Input error for PUP network directory.
	LDB A,VERPTR		;Get version number
	MOVEM A,PUPDSV		;Store as disk version number
	JRST CPOPJ1

;Here to read the entire PUP network directory into core (only used when
;hacking PUPHST on the directory we already have).
;	PUSHJ P,RDPDIR
;	<error return>
;	<success, location of directory in PUPDIR>
RDPDIR:	INIT DIN,17		;Open disk input in dump mode
	 SIXBIT/DSK/
	 0
	 MESSAG INIT error for PUP network directory input.
	SETZM DIRFIL+3		;Read file on our area
	LOOKUP DIN,DIRFIL
	 JRST CPOPJ1		;Just return if no file
	HRRZ A,JOBFF↑		;Place to read in the data
	MOVEM A,PUPDIR
	MOVEI B,-1(A)		;Make IOWD in B
	HLL B,DIRFIL+3
	MOVS C,DIRFIL		;Negative of file size
	SUBI A,1(C)		;Highest location we need
	CORE A,			;Get core for input file
	 MESSAG CORE UUO failed.
	SETZ C,			;End dump mode command list
	IN DIN,B		;Input the PUP directory
	 CAIA
	MESSAG Input of PUP directory failed.
	MOVE A,VERPTR		;Get ptr to version number
	SUBI A,DIRHDR		;Relocate to our location
	ADD A,PUPDIR
	LDB A,A			;Get version number
	MOVEM A,PUPDSV		;Store as disk version number
	JRST CPOPJ1
;Get PUP version from Ethernet ;⊗ GETVER GETVE1

;This page IFN FTPUP

;Here to get version number from misc servers on the Ethernet.  Assumes
;our version number is already in PUPDSV.  Call:
;	PUSHJ P,GETVER
;	<error return>
;	<success, highest version number in PUPMSV, host in PUPMHS>
GETVER:	MOVE A,PUPDSV		;Our version
	MOVEM A,PUPMSV		;Is best so far
	INIT PUPVER,15		;Packet mode
	 SIXBIT/PUP/
	 0			;No buffers
	 MESSAG INIT error for PUP version request.
	MTAPE PUPVER,VERLSN	;Listen
	SKIPE VERSTS
	 MESSAG Error in LISTEN MTAPE for PUP version request.
	SETZM PKTBUF		;Clear out old header, so WAITS fills this
	MOVE A,[PKTBUF,,PKTBUF+1] ;stuff in.
	BLT A,PKTBFD
	MOVEI A,240		;Set packet type to NetDirVersion
	DPB A,PKTTYP
	MOVE A,PUPDSV		;Get our version number
	DPB A,[POINT 16,PKTBFD,15] ;Store in packet
	MOVEI A,PUPOVH+2	;Length = overhead + 2 data bytes
	DPB A,PKTLEN
	ADDI A,2+2+3		;Plus Ethernet header plus rounding
	LSH A,-2		;Convert to words
	HRLOI A,-1(A)		;<len-1>,,-1
	EQVI A,PKTBUF-1		;<-len>,,PKTBUF-1
	SETZ B,			;End IOWD list
	OUT PUPVER,A		;Send the packet
	 CAIA
	MESSAG Error in PUP version request output.
	MOVEI C,5		;Number of seconds to wait for replies
	MOVEI D,1
GETVE1:	MTAPE PUPVER,[10]	;Skip if input available
	 JRST [	SOJL C,CPOPJ1	;We can't wait forever
		SLEEP D,	;Wait one second
		JRST GETVE1]	;Try again
	IN PUPVER,[IOWD PUPMAX,PKTBUF ↔ 0] ;Read packet
	 CAIA
	MESSAG Input error in PUP version reply.
	LDB A,PKTTYP		;Check reply type
	LDB B,[POINT 16,PKTBFD,15] ;And version number
	CAIN A,240		;NetDirVersion?
	CAMGE B,PUPMSV		;At least as good as best so far?
	JRST GETVE1		;No, ignore it
	LDB A,PKTSRC		;Get source of this reply
	MOVEM A,PUPMHS		;Save host number
	MOVEM B,PUPMSV		;This is the best version now
	LDB A,PKTDST		;Get our own address while we're at it
	MOVEM A,OURHST		;We'll need it later
	JRST GETVE1		;Keep trying until tired
;Get new PUP directory ;⊗ GNPDIR GNPDI1 GNPDI2 GNPDI3 GNPDI4 GETCOR GETCO1

;This page IFN FTPUP

;Here to get new PUP network directory from host in PUPMHS.  Call:
;	PUSHJ P,GNPDIR
;	<error return>
;	<success return>
GNPDIR:	INIT PUPEFT,13		;EFTP mode
	 SIXBIT/PUP/
	 0,,PUPIBF
	 MESSAG INIT failure for EFTP channel.
	MOVEI A,=8		;Change byte size
	DPB A,[POINT 6,PUPIBF+1,11] ;in buffer header
	INBUF PUPEFT,2		;Set up buffer ring
	MOVE A,PUPMHS		;Set host number in MTAPE blocks
	MOVEM A,VERHST
	MOVEM A,EFTHST
	MTAPE PUPEFT,EFTGEN	;Gensym a socket for EFTP
	MOVE A,EFTGSK		;Copy into listen block
	MOVEM A,EFTLSK
	MTAPE PUPEFT,EFTLSN	;Listen on EFTP channel
	SKIPE EFTSTS		;Check status bits
	MESSAG Error in LISTEN MTAPE for PUP directory update.
	MTAPE PUPVER,VERTRM	;Close previous connection on PUPVER
	MTAPE PUPVER,VERCON	;Get new connection to this host
	SKIPE VCNSTS
	MESSAG Error in CONNECT MTAPE for PUP directory update.
	SETZM PKTBUF		;Clear out old header, so WAITS fills this
	MOVE A,[PKTBUF,,PKTBUF+1] ;stuff in.
	BLT A,PKTBFD
	MOVEI A,241		;Packet type SendNetDir
	DPB A,PKTTYP
	MOVE A,OURHST			;Our host number
	DPB A,[POINT 16,PKTBFD,15]	;is first part of port number
	MOVE A,EFTGSK			;EFTP socket
	DPB A,[POINT 16,PKTBFD+1,15]	;is the rest
	LSH A,-=16
	DPB A,[POINT 16,PKTBFD,31]
	MOVEI A,PUPOVH+6	;Length = overhead + 6 data bytes
	DPB A,PKTLEN
	ADDI A,2+2+3		;Plus Ethernet header plus rounding
	LSH A,-2		;Convert to words
	HRLOI A,-1(A)		;<len-1>,,-1
	EQVI A,PKTBUF-1		;<-len>,,PKTBUF-1
	SETZ B,			;End IOWD list
	OUT PUPVER,A		;Send the packet
	 CAIA
	MESSAG Error in PUP directory request output.
	RELEAS PUPVER,		;Done with version request channel
	;Now EFTP the directory into core.
	MOVE A,JOBFF↑
	PUSHJ P,GETCOR		;Clear core, set C to bytes cleared
	HRRZ B,JOBFF↑		;Start storing here
	HRLI B,(<POINT 8,0>)	;Make byte ptr to IDPB
GNPDI1:	SOSG PUPIBF+2		;See if there's more EFTP input
	IN PUPEFT,
	 CAIA			;Yes, there is
	JRST GNPDI4		;No, check for end
GNPDI2:	SOJGE C,GNPDI3		;Jump if there's room for this byte
	MOVEI A,1(B)		;No room.  Get address of next word to store
	PUSHJ P,GETCOR		;Get and clear some core
	SOS C			;Fix byte count
GNPDI3:	ILDB A,PUPIBF+1		;Load byte
	IDPB A,B		;Store byte
	JRST GNPDI1		;Continue copying

GNPDI4:	STATO PUPEFT,IODEND	;End of input?
	 MESSAG Error in PUP directory input.
	RELEAS PUPEFT,		;Yes, all done with EFTP channel
	INIT DOUT,17		;Open disk output channel in dump mode
	 SIXBIT/DSK/
	 0
	 MESSAG Disk INIT failure in writing PUP directory.
	SETZM DIRFIL+3		;Write file on our area
	ENTER DOUT,DIRFIL	;Enter directory file
	 MESSAG ENTER error in writing PUP directory.
	HRRZ A,JOBFF↑		;Addr of start of data
	MOVEM A,PUPDIR		;Store for PUPHST
	SUBI A,1		;-1 for IOWD
	SUBM A,B		;-<word count> in RH(B)
	HRL A,B			;Make IOWD
	SETZ B,			;End IOWD list
	OUT DOUT,A		;Do dump mode output
	 CAIA
	MESSAG Output error in writing PUP directory file.
	RELEAS DOUT,
	JRST CPOPJ1		;All done, hooray!

;Here to clear core and expand if necessary.
;Call:	MOVE A,<starting address of core to clear>
;	PUSHJ P,GETCOR
;	<return with core cleared from (A) to JOBREL, byte count in C>
GETCOR:	CAMGE A,JOBREL↑		;Need more core?
	JRST GETCO1		;No.  (Must be first call to GETCOR)
	MOVEI C,1777(A)		;Yes, get 2 pages
	CORE C,
	 MESSAG CORE UUO failed in PUP directory input.
GETCO1:	SETZM (A)		;Zero first word
	MOVEI C,1(A)		;Make BLT word
	HRLI C,(A)
	BLT C,@JOBREL↑		;Clear core
	MOVE C,JOBREL↑
	SUBI C,-1(A)		;Count of words gotten
	LSH C,2			;Times 4 for 8-bit bytes
	POPJ P,
;File output routines ;⊗ PUTCH PUTCH1 PUTSTR PUTST1 PUTDEC PUTOCT PUTOC1 PUTSIX PUTDAT MONTH

;Output a character in A, unless H is 0.
PUTCH:	JUMPE H,CPOPJ
	SOSG DOBUF+2
	OUT DOUT,
	JRST PUTCH1
;Here we have an output error.  Unwind stack to level of call to PUPHST and
;return error message.
	MOVE P,PUPHSP
	MESSAG Output error in writing PUPHST file.

PUTCH1:	IDPB A,DOBUF+1
	POPJ P,

;Output an ASCIZ string with address or byte ptr in B.  Clobbers A and B.
PUTSTR:	TLNN B,-1		;Byte ptr?
	HRLI B,440700		;No, make one
PUTST1:	ILDB A,B		;Get a char
	JUMPE A,CPOPJ		;Return if done
	PUSHJ P,PUTCH		;Output it
	JRST PUTST1

;Output an octal or decimal number in A.  Clobbers A, B, and C.
PUTDEC:	SKIPA C,[=10]
PUTOCT:	MOVEI C,10
PUTOC1:	IDIV A,C
	HRLM B,(P)
	JUMPE A,.+2
	PUSHJ P,PUTOC1
	HLRZ A,(P)
	ADDI A,"0"
	JRST PUTCH

;Output a left-adjusted sixbit word in B.  Clobbers A and B.
PUTSIX:	JUMPE B,CPOPJ
	SETZ A,
	LSHC A,6
	ADDI A,40
	PUSHJ P,PUTCH
	JRST PUTSIX

;Output the date in system date format in A.  Clobbers A and B.
PUTDAT:	IDIVI A,=31		;Get day of month - 1 in B
	PUSH P,A		;Save the rest
	MOVEI A,1(B)
	PUSHJ P,PUTDEC
	POP P,A
	IDIVI A,=12		;Get month - 1 in B
	PUSH P,A		;Save the rest
	MOVE B,MONTH(B)		;Get ASCII month
	PUSHJ P,PUTSTR
	POP P,A			;Get year - 1964
	ADDI A,=64
	JRST PUTDEC

MONTH:	[ASCIZ/-Jan-/]
	[ASCIZ/-Feb-/]
	[ASCIZ/-Mar-/]
	[ASCIZ/-Apr-/]
	[ASCIZ/-May-/]
	[ASCIZ/-Jun-/]
	[ASCIZ/-Jul-/]
	[ASCIZ/-Aug-/]
	[ASCIZ/-Sep-/]
	[ASCIZ/-Oct-/]
	[ASCIZ/-Nov-/]
	[ASCIZ/-Dec-/]
;More subroutines ;⊗ OUTADR OUTNAM OUTNLP COMPAR COMPLP COMPL1 COMPL2 CMPLUZ PUTATR PUTALP PUTAT1

;Here to output all addresses for address pointer in A.
OUTADR:	LSH A,-1		;Get PDP-10 address of address block
	ADD A,PUPDIR
	MOVEI X,(A)
	HRLI X,442000		;Byte ptr to beginning of address block
	ILDB A,X		;Get pointer to next address
	PUSH P,A		;Save it
	IBP X			;Skip pointer to owning entry block
	MOVEI B,[ASCIZ/SU /]
	PUSHJ P,PUTSTR
	ILDB A,X		;Get address
	PUSH P,A		;Save it
	MOVSI B,-DOMNUM		;Set up to check for domain names
	CAME A,DOMHST(B)
	AOBJN B,.-1
	JUMPGE B,.+3		;Jump if AOBJN exhausted
	MOVE B,DOMNAM(B)
	MOVEM B,DOMSTR
	LSH A,-10		;Get subnet number
	PUSHJ P,PUTOCT
	MOVEI A,"#"
	PUSHJ P,PUTCH
	POP P,A			;Get back address
	ANDI A,377		;Get host number
	PUSHJ P,PUTOCT
	POP P,C			;Get back next address block pointer
	JUMPE C,CPOPJ		;Zero marks end
	MOVEI B,[ASCIZ/, /]
	PUSHJ P,PUTSTR
	MOVE A,C
	JRST OUTADR		;Print next address

;Here to output all names for name pointer in A.
OUTNAM:	LSH A,-1		;Get PDP-10 address of name block
	ADD A,PUPDIR
	MOVEI X,(A)
	HRLI X,442000		;Byte ptr to beginning of name block
	ILDB A,X		;Get pointer to next name
	PUSH P,A		;Save it
	IBP X			;Skip pointer to owning entry block
	TLC X,3000		;Convert to 8-bit byte ptr
	ILDB B,X		;Get number of bytes in string
OUTNLP:	ILDB A,X		;Get a character
	CAIL A,"a"
	CAILE A,"z"
	CAIA
	SUBI A,"a"-"A"		;Force uppercase
	PUSHJ P,PUTCH		;Output the character
	SOJG B,OUTNLP		;Repeat till done
	POP P,C			;Get back next name block pointer
	JUMPE C,CPOPJ		;Zero marks end
	MOVEI B,[ASCIZ/, /]
	PUSHJ P,PUTSTR
	MOVE A,C
	JRST OUTNAM		;Print next name

;Here to compare an attribute name with a fixed string.
;Call:	MOVE A,<directory address of name>
;	PUSHJ P,COMPAR
;	 ASCIZ/string/
;	 <return here if equal>
;	<return here if not equal>
;Preserves A, B, and C.
COMPAR:	PUSH P,A		;Preserve ACs
	PUSH P,B
	PUSH P,C
	MOVSI C,(<POINT 7,0>)	;Make byte pointer
	HLLM C,-3(P)
	LSH A,-1		;Get PDP-10 address of name string
	ADD A,PUPDIR
	HRLI A,(<POINT 8,0>)	;Make byte pointer
	ILDB B,A		;Get character count
COMPLP:	ILDB C,-3(P)		;Get byte from fixed string
	JUMPE C,COMPL2		;Jump if end of fixed string
	SOJL B,COMPL1		;Jump if end of name string
	ILDB D,A		;Get byte from name string
	CAIN C,(D)		;See if the same
	 JRST COMPLP		;Yes, go back for more if any
	;Here when match fails or name string runs out before fixed string
COMPL1:	ILDB C,-3(P)		;Zap to end of fixed string
	JUMPN C,COMPL1
	JRST CMPLUZ		;Failed
	;Here when at end of fixed string
COMPL2:	SKIPE B			;Both strings ended
CMPLUZ:	AOS -3(P)
	POP P,C			;Restore ACs
	POP P,B
	POP P,A
	JRST CPOPJ1		;Jump over string

;Here to output a string, all uppercased, followed by a colon.
;Call:	MOVE C,<address in directory>
;	PUSHJ P,PUTATR
PUTATR:	MOVEI A,":"		;Print this
	JUMPE C,PUTCH		;If no entry
	MOVEI A," "		;Else start with a space
	PUSHJ P,PUTCH
	LSH C,-1
	ADD C,PUPDIR
	HRLI C,(<POINT 8,0>)	;Make byte ptr
	ILDB B,C		;Get byte count
PUTALP:	SOJL B,PUTAT1		;Return when all done
	ILDB A,C		;Get a byte
	CAIL A,"a"		;Force uppercase
	CAILE A,"z"
	CAIA
	SUBI A,"a"-"A"
	PUSHJ P,PUTCH		;Output the character
	JRST PUTALP		;Back for more
PUTAT1:	MOVEI B,[ASCIZ/ :/]	;End text
	JRST PUTSTR
;Create PUPHST.TXT file ;⊗ PUPHST HDRLP MAINLP ATTLP ATTLP1 ALLDUN SHORT

PUPHST:	INIT DOUT,0		;Open output file in buffer mode
	 SIXBIT/DSK/
	 DOBUF,,0
	 MESSAG INIT failure for PUPHST output channel
	ENTER DOUT,PHSFIL
	 MESSAG ENTER failure for PUPHST output file
	MOVEM P,PUPHSP		;Save PDL ptr in case of output error
	SETO H,			;Enable output
	MOVSI A,-HDRSIZ		;Set up to copy header block
	MOVE B,PUPDIR
	HRLI B,442000		;Byte ptr to beginning of directory
HDRLP:	ILDB C,B		;Get a 16-bit word
	MOVEM C,NUMNAM(A)	;Store it
	AOBJN A,HDRLP
	MOVE A,FSTENT		;First entry block
	LSH A,-1		;Make PDP-10 address
	ADD A,PUPDIR
	HRLI A,442000		;Make byte ptr
	MOVEM A,ENTPTR		;And save it
	;Print date and time and PPN here.
	MOVEI B,[ASCIZ/;Stanford PUP network directory.  Created by [/]
	PUSHJ P,PUTSTR
	GETPPN C,
	HLLZ B,C
	PUSHJ P,PUTSIX
	MOVEI A,","
	PUSHJ P,PUTCH
	HRLZ B,C
	PUSHJ P,PUTSIX
	MOVEI B,[ASCIZ/] using UPDATE on /]
	PUSHJ P,PUTSTR
	DATE A,
	PUSHJ P,PUTDAT
	MOVEI B,[ASCIZ/.

NET : SU 0#0 : SU-ETHERNET :

/]
	PUSHJ P,PUTSTR
;Now go through all of the entries
MAINLP:	SOSGE NUMENT		;Count down entry words
	 JRST ALLDUN		;Got 'em all
	ILDB A,ENTPTR		;Pointer to 1st name block
	JUMPE A,ALLDUN		;It might end this way
	PUSH P,A		;Save it
	SOSGE NUMENT		;Count down entry words
	 JRST SHORT
	ILDB A,ENTPTR		;Pointer to 1st address block
	PUSH P,A		;Save it
	;Peek ahead at first address block.  If subnet number or host number is
	;zero, then this isn't a host entry and we don't want to output any-
	;thing.  Also, if the socket number is non-zero, we want to ignore it.
	LSH A,-1		;Get PDP-10 word address
	ADD A,PUPDIR
	LDB H,[POINT 16,1(A),15];Subnet and host number
	LDB B,[POINT 16,1(A),31];First 16 bits of socket
	LDB C,[POINT 16,2(A),15];Last 16 bits of socket
	TRNE H,177400		;If subnet is zero
	TRNN H,377		;Or host is zero
	SETZ H,			;Then disable output
	SKIPN B			;If either part of socket number is non-zero
	SKIPE C
	SETZ H,			;Then disable output
	;If H is zero, PUTCH (and PUTSTR) will return without outputting anything.
	MOVEI B,[ASCIZ/HOST : /]
	PUSHJ P,PUTSTR
	POP P,A			;Get back address pointer
	SETZM DOMSTR		;Clear ptr to domain-style name
	PUSHJ P,OUTADR		;Output all addresses, set DOMNAM if needed
	MOVEI B,[ASCIZ/ : /]
	PUSHJ P,PUTSTR
	SKIPE B,DOMSTR		;Skip unless there's a domain-style name
	PUSHJ P,PUTSTR		;Output domain name
	POP P,A			;Get back name pointer
	PUSHJ P,OUTNAM		;Output all names
	MOVEI B,[ASCIZ/ :/]
	PUSHJ P,PUTSTR
	SOSGE NUMENT		;Count down entry words
	 JRST SHORT
	ILDB C,ENTPTR		;Get number of attributes
	SETZM CPUPTR		;Zero attribute pointers
	SETZM OPSPTR
	SETZM PRTPTR
ATTLP:	SOJL C,ATTLP1		;Count down attributes
	SOSGE NUMENT		;Count down entry words
	 JRST SHORT
	ILDB A,ENTPTR		;Get attribute name
	SOSGE NUMENT		;Count down entry words
	 JRST SHORT
	ILDB B,ENTPTR		;Get attribute value
	PUSHJ P,COMPAR		;See if it's one of the attributes we want
	 ASCIZ/CPU/
	 MOVEM B,CPUPTR
	PUSHJ P,COMPAR
	 ASCIZ/Op-Sys/
	 MOVEM B,OPSPTR
	PUSHJ P,COMPAR
	 ASCIZ/IP-Protocols/
	 MOVEM B,PRTPTR
	JRST ATTLP		;Back for more
ATTLP1:	IBP ENTPTR		;Bump the pointer, since an entry block is always
				;of odd size, but next block starts on a word
	MOVE C,CPUPTR		;Now put out the attributes in the right order
	PUSHJ P,PUTATR
	MOVE C,OPSPTR
	PUSHJ P,PUTATR
	MOVE C,PRTPTR
	PUSHJ P,PUTATR
	MOVEI B,[ASCIZ/
/]
	PUSHJ P,PUTSTR
	JRST MAINLP		;Continue

ALLDUN:	RELEAS DOUT,
	JRST CPOPJ1		;Success return

SHORT:	MESSAG Inconsistency in input file - ended in middle of entry block

>;IFN FTPUP
;Top level ;⊗ NICUPD NICERR PUPUPD PUPERR PUPHAK UPDATE PPNOK NOERRS

NICUPD:	OUTSTR [ASCIZ/Getting latest version number from NIC name server.
/]
	PUSHJ P,VERNIC		;Get NIC directory version string
	 JRST NICERR		;Error of some kind
	OUTSTR [ASCIZ/NIC's version string is /]
	OUTSTR NICVER
	OUTSTR CRLF
	PUSHJ P,VERIN		;Get version from disk file
	 JRST NICERR		;Error
	OUTSTR [ASCIZ/Saved version string is /]
	OUTSTR DSKVER
	OUTSTR CRLF
	PUSHJ P,VERCOM		;Compare version strings
	 JRST [	OUTSTR [ASCIZ/No update of NIC host table needed.
/]
		POPJ P,]
	OUTSTR [ASCIZ/Getting new host table from NIC name server.
/]
	PUSHJ P,NEWNIC		;Read in the new host table
	 JRST NICERR		;Some error
	PUSHJ P,VEROUT		;Output version string to file
	 JRST NICERR		;Some error
	OUTSTR [ASCIZ/New host table successfully installed.
/]
	SETOM CHANGE		;Indicate change
	POPJ P,

NICERR:	RELEAS DVER,3		;Don't write any files!
	RELEAS DOUT,3
	POPJ P,

IFN FTPUP,<
PUPUPD:	PUSHJ P,RDPVER		;Read version from PUP directory on disk
	 JRST PUPERR		;Error
	OUTSTR [ASCIZ/Our PUP network directory is version /]
	MOVE A,PUPDSV
	PUSHJ P,OCTOUT
	OUTSTR CRLF
	PUSHJ P,GETVER		;Get version from misc servers
	 JRST PUPERR		;Error of some kind
	MOVE A,PUPMSV		;Highest version reported
	CAMG A,PUPDSV		;Compare with our version
	 JRST [	OUTSTR [ASCIZ/No update of PUP network directory needed.
/]
		POPJ P,]
	OUTSTR [ASCIZ/Getting new PUP directory version /]
	PUSHJ P,OCTOUT		;Output version in A
	OUTSTR [ASCIZ/ from host /]
	LDB A,[POINT 8,PUPMHS,27]
	PUSHJ P,OCTOUT		;Subnet
	OUTCHR ["#"]
	LDB A,[POINT 8,PUPMHS,35]
	PUSHJ P,OCTOUT		;Host
	OUTSTR CRLF
	PUSHJ P,GNPDIR		;Get new PUP directory
	 JRST PUPERR		;Some error
	OUTSTR [ASCIZ/New PUP directory successfully installed.
/]
	PUSHJ P,PUPHST		;Write new PUPHST.TXT file
	 JRST PUPERR
	OUTSTR [ASCIZ/PUPHST output file compiled successfully.
/]
	SETOM CHANGE		;Indicate change
	POPJ P,

PUPERR:	RELEAS DOUT,3		;Don't write file
	POPJ P,
>;IFN FTPUP

PUPHAK:
IFN FTPUP,<
	PUSHJ P,RDPDIR		;Get the current PUP network directory
	 EXIT			;Some error
	OUTSTR [ASCIZ/PUP directory version /]
	MOVE A,PUPDSV
	PUSHJ P,OCTOUT
	OUTSTR CRLF
	PUSHJ P,PUPHST		;Make a new PUPHST.TXT
	 PUSHJ P,PUPERR		;Unless there's an error
	OUTSTR [ASCIZ/PUPHST output file compiled successfully.
/]
>;IFN FTPUP
	EXIT

	TDZA D,D		;Start -1 to run PUPHST on existing directory
UPDATE:	MOVEI D,1		;Normal start
	RESET
	MOVE P,[IOWD PDLEN,PDL]
	MOVEI A,0		;Code to lookup disk PPN
	DSKPPN A,		;What's our alias?
	CAMN A,['HSTNET']	;Is it the expected?
	JRST PPNOK		;Yes
	OUTSTR [ASCIZ/You are not aliased to [HST,NET].  Do you want to proceed,
with files read and written from your alias area (Y or N)? /]
	INCHRW A		;Get a char
	CAIE A,15
	OUTSTR CRLF
	CAIN A,15		;Ho hum
	INCHRW A
	CAIE A,"Y"
	CAIN A,"y"
	JRST PPNOK
	EXIT

PPNOK:	JUMPE D,PUPHAK		;Jump if special start
	PUSHJ P,NICUPD		;Update NIC table
IFN FTPUP,<
	OUTSTR [ASCIZ/--------------------------------------------------
/]
	PUSHJ P,PUPUPD		;Update PUP table
>;IFN FTPUP
	SKIPN ERRORS		;Were there errors?
	JRST NOERRS
	MOVEI A,[ASCIZ/UPDATE aborted due to errors.
/]
	PUSHJ P,MESTYP
	PUSHJ P,MAILMS		;Mail errors to interested people
	EXIT

NOERRS:	SKIPN CHANGE		;Did anything change?
	EXIT			;No, all done
	OUTSTR CRLF
IFE FTLLL,<
	MOVEI A,[ASCIZ/New NIC or PUP table installed.  Please check the log and run HOSTS3.
/]
>;IFE FTLLL
IFN FTLLL,<
	MOVEI A,[ASCIZ/New HOSTS3.BIN from NIC installed on [HST,NET] at S1-A.
/]
>;IFN FTLLL
	PUSHJ P,MESTYP
	PUSHJ P,MAILMS
	EXIT

	END UPDATE