Trailing-Edge
-
PDP-10 Archives
-
bb-ev83b-bm
-
tcpip-sources/ftp4.mac
There are 2 other files named ftp4.mac in the archive. Click here to see a list.
SUBTTL Subroutine DMPREG
; B/ Address of message
; C/ xx,,PC
; D/ Address of saved ACs
; CALL DMPREG Dump registers on .PRIOU
;Ret+1: Always, Need CRLF to end last line
DMPREG: HRROI A,[ASCIZS (456,421,<->)]
TXNE F,F.STAT
PSOUT ; TELNET prefix if on TELNET connection
ERJMP .+1
HRROI A,(B) ; Make pointer to message
PSOUT ; Specific failure message
ERJMP .+1
HRROI A,[ASCIZ / at /]
PSOUT
ERJMP .+1
MOVX A,<.PRIOU> ; Type the PC
HRRZ B,C ; PC
MOVX C,<OCTRAD>
NOUT
ERJMP .+1
MOVX B,<" ">
BOUT
ERJMP .+1
MOVX B,<.FHSLF,,-1> ; Current error, this fork
SETZ C, ; No limit on message
ERSTR ; Print the error
JFCL
JFCL
HRROI A,[ASCIZ /.
/]
PSOUT
ERJMP .+1
HRROI A,[ASCIZS (456,421,<-AC00: >)]
CALL N4AC
HRROI A,[ASCIZS (456,421,<-AC04: >)]
CALL N4AC
HRROI A,[ASCIZS (456,421,<-AC10: >)]
CALL N4AC
HRROI A,[ASCIZS (456,421,<-AC14: >)]
CALL N4AC
HRROI A,[ASCIZS (456,421,< Please report it. Thank you. >)]
TXNN F,F.STAT ; If User Program
HRLI A,(POINT 7,0,27) ; Omit reply code
PSOUT
RET
SUBTTL Subroutine used by DMPREG
; Routine to print next four registers, A/ title, D/ pointer to values
N4AC: TXNN F,F.STAT ; If User Program
HRLI A,(POINT 7,0,27) ; Omit reply code
PSOUT ; Output TELNET header & title
ERJMP .+1
MOVX A,<.PRIOU>
MOVX C,<NO%MAG+NO%LFL+FLD(^D14,NO%COL)+OCTRAD>
HRLI D,-4 ; Do 4 more registers
N4ACL: MOVE B,(D) ; Get register
NOUT ; Its value
MOVX C,<NO%MAG+NO%LFL+FLD(^D14,NO%COL)+OCTRAD>
AOBJN D,N4ACL ; Back for another
HRROI A,CRLFM
PSOUT
ERJMP .+1
RET
SUBTTL Subroutine HMSMS
; Output title H:M:S.MSC
; A/ Output designator
; B/ Pointer to title
; D/ Time, msec
; CALL HMSMS
HMSMS: SETZ C,
SOUT
MOVE C,D
IDIV C,[^D<60*60*1000>]
MOVE B,C
MOVX C,<DECRAD>
NOUT
JFCL
MOVX B,<":">
BOUT
MOVE C,D
IDIVI C,<^D<60*1000>>
MOVE B,C
MOVX C,<DECRAD>
NOUT
JFCL
MOVX B,<":">
BOUT
MOVE C,D
IDIVI C,<^D<1000>>
MOVE B,C
MOVX C,<DECRAD>
NOUT
JFCL
MOVX B,<".">
BOUT
MOVE B,C
MOVX C,<NO%LFL!NO%ZRO!FLD(3,NO%COL)!DECRAD>
NOUT
JFCL
RET
SUBTTL Subroutine LCLSTS
; F.STAT Set to insert Reply Codes (i.e. is Server Program)
; A/ Destination pointer
; CALL LCLSTS
LCLSTS: SETZ C, ; Build long string at A/
PUSH P,C ; For NOUT of byte size string
HRROI B,VERSTR ; Identify ourselves
CALL BCRLF
HRROI B,[ASCIZ /The current data transfer parameters are:/]
CALL BCRLF
HRROI B,[ASCIZ / MODE /]
SKIPGE C,$MODE
SETZ C,
HLRO D,MODTAB+1(C)
CALL BCCRLF
HRROI B,[ASCIZ / STRU /]
SKIPGE C,$STRU
SETZ C,
HLRO D,STRTAB+1(C)
CALL BCCRLF
HRROI B,[ASCIZ / TYPE /]
SKIPGE C,$TYPE
SETZ C,
HLRO D,TYPTAB+1(C)
IFN TCPP,<
CAIN C,TYPE.A
JRST [SKIPGE B,$FORM
SETZ B,
HLRO D,FRMTAB+1(B)
HRROI B,[ASCIZ / TYPE A /]
JRST .+1]
CAIN C,TYPE.L ; Logical byte?
JRST [PUSH P,A
HRROI A,-1(P) ; Byte size into stack
SETZM (A) ; Clear for digits
SKIPGE B,$BYTE
MOVX B,<^D8>
MOVX C,<DECRAD>
NOUT
CALL BOMB
HRROI D,-1(P) ; Location of digits
HRROI B,[ASCIZ / TYPE L /]
POP P,A
JRST .+1]
> ; End of IFN TCPP
CALL BCCRLF
HRROI B,[ASCIZ /NORETAIN generations /] ;#4
SKIPE RETVER ;#4
HRROI B,[ASCIZ /RETAIN generations /] ;#4
TXNN F,F.STAT ;#4 SERVER?
CALL BCRLF ;#4 NO
TXNN F,F.STAT ; Server?
TXNE F,F.TOPN ; Connection open now?
JRST LCLST6 ; Yes
HRROI B,[ASCIZ / There is no connection currently open./]
CALL BCRLF
JRST LCLSTX ; Done
LCLST6:
PUSH P,A ; Save destination pointer
SETZM STRTMP
MOVX B,<STRTMP,,STRTMP+1>
BLT B,STRTMP+20
MOVX A,<.GTHNS> ; Try for string
HRROI B,STRTMP ; User temp string
MOVE C,FHSTN
MOVX D,<POINT 8,FHSTN,3> ; Point before first byte
GTHST ; Try for name
CALL HST4DB ; If error, print decimal #s
POP P,A
HRROI B,[ASCIZ /A connection is open to host /]
HRROI D,STRTMP
CALL BCCRLF
SETZ B, ; Assume User
HRROI D,[ASCIZ /The data connection is CLOSED./]
SKIPLE DATCON
HRROI D,[ASCIZ /The data connection is OPEN./]
TXNE F,F.STAT ; Server?
HRROI B,[ASCIZS (<100 >,<211 >,<>)] ; Prefix if on TELNET connection
SKIPN B
EXCH B,D
CALL BDCRLF
LCLSTX: POP P,(P) ; Drop temp string
RET
SUBTTL Subroutines HST4DA/B
; Routine to print TELNET header and string pointed to be B and D
BCRLF: SETZ D, ; Just string in B
BCCRLF: PUSH P,B ; String in B & possibly D
HRROI B,[ASCIZS (<100 >,<211->)] ; Prefix if on TELNET connection
SETZ C,
TXNE F,F.STAT ; LIST or STAT?
SOUT ; STAT.
POP P,B
; Routine to print strings pointed to by B and, if non-zero, D
BDCRLF: SETZ C, ; Print string in B
SOUT
HRROI B,(D) ; Possible second string
SKIPE D ; Don't bother if nothing
SOUT
HRROI B,CRLFM ; End the line
SOUT
RET
; MOVX D,<POINT 8,32-bit-address,3> ; Point before first byte
; CALL HST4DA if A/ has destination designator
; or CALL HST4DB if B/ has destination designator
;Ret+1: Always, #.#.#.#
HST4DB: MOVE A,B ; Build address here
HST4DA: MOVX C,<DECRAD> ; Type as four decimal bytes
JRST HST4DM ; Skip over dot
HST4DL: MOVX B,<".">
BOUT
HST4DM: ILDB B,D ; Get next byte
NOUT
JFCL
TLNE D,770000 ; Bit position zero?
JRST HST4DL ; No, have another byte
MOVX B,<C.NUL>
BOUT
RET
SUBTTL Subroutines - CLOSER, CLOSEK, CLOSED
; Note: LH of A may contain flags to be passed to "CLOSF"
; MOVEI A,jfn-variable
; CALL CLOSER Close File & Release JFN
CLOSER: SKIPG 0(A) ; Anything there?
RET ; No such JFN. Return.
PUSH P,A ; Yes. Save a couple AC's
PUSH P,B
HRRZ A,0(A) ; Get JFN itself
GTSTS
JUMPL B,CLOSR1
RLJFN ; Not open. Just release JFN
JFCL
JRST CLOSR2
CLOSR1: CLOSF ; Open, close & release JFN
JFCL
CLOSR2: POP P,B ; Restore AC's
POP P,A
SETOM 0(A) ; And flag JFN gone
RET
; MOVEI A,jfn-variable
; CALL CLOSEK Close File but Keep JFN
CLOSEK: SKIPG (A) ; Close, keeping JFN. File there?
RET ; No.
PUSH P,A ; Yes, save addr where JFN is
HRRZ A,(A) ; Get the JFN
TXO A,CO%NRJ ; Flag to keep the JFN
CLOSF ; Close it
JFCL
POP P,A ; Restore pointer
RET ; Return
; MOVEI A,jfn-variable - DATCON
; CALL CLOSED Close data connection
CLOSED: SKIPG (A) ; Data connection there?
RET ; No.
PUSH P,A ; Yes, save addr (& flags) where JFN is
HRRZ A,(A) ; Get the JFN (& flags)
$CLOSF ; Close it
JFCL
POP P,A ; Restore pointer
SETOM 0(A) ; Data connection gone
RET ; Return
LLITS: XLIST ; Low-seg lits for DMPREG
LIT
LIST
SUBTTL Subroutine UPDFIL
.ORG ;BACK TO HIGH SEGMENT
; Update file's attributes, assumes everything is setup
UPDFIL: SKIPLE LCLJFN ; Have a local file?
SKIPN $FILST ; And information about it?
JRST UPDFI8 ; No, Error??
CLOSK (LCLJFN) ; Make sure closed
REPEAT 0,< ; This is already done in DRCXFD
SKIPE TENEX ; TENEX has no SFUST
JRST UPDFI8 and different dates. Unsupported.
SETO B, ; Whole word for time
HRLI A,<.FBCRV>
SKIPLE C,FILTCR
CHFDB
ERJMP .+1
HRLI A,<.FBWRT>
SKIPLE C,FILTWR
CHFDB
ERJMP .+1
HRLI A,<.FBREF>
SKIPLE C,FILTRD
CHFDB
ERJMP .+1
HRLI A,<.SFAUT>
HRROI B,FILUCR
SKIPE FILUCR ; Make sure have a name
SFUST ; to set
ERJMP .+1
HRLI A,<.SFLWR>
HRROI B,FILUWR
SKIPE FILUWR ; Make sure have a name
SFUST ; to set
ERJMP .+1
> ; End repeat 0
UPDFI8:
RET
SUBTTL Data Transfer Routine, Common to FTP User & Server
; F.SEND, $MODE3, $STRU3, $TYPE3, $BYTE3
; DATCON, LCLJFN open
; CALL XFRDAT
; X/ address of comletion/error message [226,250,451]
XFRDAT: TXZ F,F.ERR!F.FDB!F.TYPX!F.NUL!F.DSK!F.IMG ; Clear flags
MOVE A,$MODE3 ; Get current parameters
MOVE B,$STRU3
MOVE C,$TYPE3
MOVE D,$BYTE3
TXO F,F.CLSD ; Assume close at EOF (NCP always closes)
IFN TCPP,< ; Have to close data connection for EOF?
CAIE A,MODE.C ; Modes Compressed or
CAIN A,MODE.B ; Blocked
TXZ F,F.CLSD ; Don't have to
CAIN A,MODE.S ; Mode S and
CAIE B,STRU.P ; Structure P
SKIPA
TXZ F,F.CLSD ; Doesn't have to
CAIE B,STRU.P
> ; End of IFN TCPP
IFE TCPP,<CAIE C,TYPE.X> ; See if PAGED
TXZA F,F.TYPX ; Not PAGED xfer
TXO F,F.TYPX ; PAGED xfer
IFE TCPF,< ; See if NCP CHANNEL stuff needed
CAIN C,TYPE.I ; IMAGE type?
CAIN D,^D36 ; And not words?
TXZA F,F.IMG ; No. Ok as is
TXO F,F.IMG ; Flag CHANNEL processing
TXNE F,F.TYPX ; But not if paged
TXZ F,F.IMG ; Cannot get here - paged is 36 bits
> ; End of IFE TCPF
SETZM TYXSCT ; Start sequence numbers at 1
SETZM NBYTES ; # bytes processed
HRRZ A,LCLJFN ; See what the local device is
DVCHR
LOAD A,DV$TYP ; Get dev type field
CAIN A,.DVDSK ; Local file DSK:?
TXO F,F.DSK ; Yes
CAIN A,.DVNUL ; NUL: file?
TXO F,F.NUL ; Yes
TXNN F,F.SEND ; Send or receive?
JRST DRECV ; Go to DRECV
; Fall into DSEND
SUBTTL Send Process, decide which case
; Four cases: Paged from Disk, from Disk, from NUL:, Other
DSEND: TXNE F,F.NUL ; NUL: file?
JRST DSENUL ; Yes.
TXNN F,F.DSK ; Local file DSK:?
JRST DSEBY1 ; No, byte by byte
CALL GETFDB ; Set up the FDB copy of local file
JRST DSEEFD ; Illegal instruction interrupt
TXNE F,F.TYPX ; PAGED (DSK:) transfer?
JRST DSEDXT ; Yes.
JRST DSEDSK ; No.
SUBTTL Send Byte by Byte, neither DSK: nor NUL:
DSEBY1: HRRZ A,LCLJFN ; Get some input
BIN
JUMPN B,DSEBY3 ; Got a byte
GTSTS ; Zero byte or EOF/error?
TXC B,GS%OPN+GS%RDF
TXNE B,GS%OPN+GS%RDF+GS%EOF
JRST DSENDX ; EOF/error
MOVX B,<0> ; Zero data byte
DSEBY3:
MOVE A,DATCON ; Write it out
$BOUT
ERJMP DSEEWR
AOS NBYTES ; Count data bytes
CALL TIMEOK ; Wasteful, every byte, but...
JRST DSEBY1
SUBTTL Send from NUL: (a million bits)
DSENUL: SETZM FDBBLK ; Zero FDB block
MOVX A,<FDBBLK,,FDBBLK+1>
BLT A,FDBBKE
MOVX A,<400100,,0> ; Make up a phony FDB for the NUL file
HRR A,LFDB ; System dependent FDB length
MOVEM A,FDBBLK+.FBHDR
MOVX A,<FB%TMP> ; Call it a temp file
MOVEM A,FDBBLK+.FBCTL
MOVX A,<FLD(NUMVAL,NMFLG)+770000> ; Make a protection
MOVEM A,FDBBLK+.FBPRT
MOVE P2,$BYTE3 ; Byte size in B6-B11
STOR P2,FB$BSZ ; Into FDB
MOVX BP,<POINT 0,WINDOW> ; Now build byte pointer
STOR P2,PT$BSZ,+BP
MOVX P1,<^D36> ; Bits per word
IDIVI P1,(P2) ; Bytes per word
MOVE D,P1 ; Save for IDPB count
LSHC P1,<^D<-36+9>> ; Bytes per page in P2
MOVX T1,<^D1000000> ; A million bits
IDIV T1,$BYTE3 ; Is this many bytes
SKIPE T2 ; Partial word?
ADDI T1,1 ; Yes, round up
MOVE P1,T1 ; Number of bytes
MOVEM P1,FDBBLK+.FBSIZ ; Save length for EOF
; D/ # bytes per word
; BP/ Points to data in WINDOW
; P1/ # bytes left to send
; P2/ # bytes per page
SETO A, ; Free up the window page
MOVX B,<.FHSLF,,<WINDOW/1000>>
SETZ C, ; No count
PMAP
MOVE A,BP ; Fill two words
DSENU2: SETZ B, ; with alternating
IDPB B,A ; zero and one
SETO B, ; bytes
IDPB B,A
SOJG D,DSENU2
MOVX A,<WINDOW,,WINDOW+2>
BLT A,WINDOW+777 ; Whole page of them
MOVX A,<PGT$SP> ; Page type
MOVEM A,RECTYP
SETOM PAGNO
SETZM ACCESS
; BP/ POINT $BYTE3,WINDOW, P1 is # bytes left to send, P2 is bytes per page
DSENUP: MOVE T2,P1 ; Number of bytes left in megabit
CAILE P1,(P2) ; This page make a million?
MOVEI T2,(P2) ; No, send a whole page
SUB P1,T2 ; Bytes remaining after this page
MOVEM T2,TYXNPW ; # Bytes in a page to be sent
ADDM T2,NBYTES
AOS A,PAGNO ; Next page
MOVEM A,PAGENO
IFN TCPP,<TXNE F,F.TYPX ; If paged mode,
JRST DSENUX> ; Go send header
MOVN C,T2 ; Negative byte count
MOVE B,BP ; Starting pointer
MOVE A,DATCON ; Send connection
$SOUT ; Send this bunch
ERJMP DSEEWR
JUMPN C,DSEEWR
SKIPA
DSENUX: CALL DSEXHD ; Send PAGED header & data in window
JUMPG P1,DSENUP ; If more to go, send more.
; No more if fall thru. Close file.
TXNE F,F.TYPX ; Paged type?
CALL DSEXFD ; Yes, send FDB & EOF
JRST DSENDX ; End of the NUL: file
SUBTTL Send from disk, not paged
; Bytes of size specified in FDB are packed into $BYTE3 bits for sending
; $BYTE3 $LBYTE3==OPENF File
; ASCII 8 7 7 (7) transform 7 into 8
; IMAGE 36 36 36 x IMAGE 36 overrides x
; LOCAL n n n n x transform x into n
;
; Find # words in file assuming no holes (Hole is a page of zeros)
DSEDSK: LOAD D,FB$BSZ ; File byte size (writer's)
SKIPG D ; In case bad
MOVX D,<^D36> ; Assume words
SKIPG P1,FDBBLK+.FBSIZ ; Bytes in file (in writer's size)
MOVX P1,<1B1> ; If not specified, assume infinite
HRRZ A,LCLJFN ; File
RFBSZ ; Get bytesize in which file is now open
JFCL ; Error return. Should not happen
ANDI B,77 ; In case junk
MOVE C,B ; Copy
;= MOVE C,$LBYT3
MOVX BP,<POINT 0,WINDOW> ; Make pointer to window page
STOR C,PT$BSZ,+BP ; Insert byte size
;#3 convert # of bytes written to # of bytes in mode currently open
PUSH P,C ;#3 SAVE BYTE SIZE
PUSH P,D ;#3 USED ELSEWHERE?
MOVE C,D ;#3
CAMGE B,C ;#3 OPEN LESS THAN WRITE ?
JRST [IDIVI C,(B) ;#3 YES
IMULI P1,(C) ;#3 NUMBER OF BYTES IN CURRENT SIZE
JRST DSEDS1]
DSEDS1: POP P,D ;#3 RESTORE
POP P,C ;#3 RESTORE BYTE SIZE
MOVX A,<^D36> ; Find conversion to local bytes per word
IDIVI A,(C) ; as OPENFed
LSH A,^D9 ; Bytes per page
MOVEM A,P2
; Look for holes in file, if hole, set byte count to + infinity
SETOM PAGNO ; Scan to see if any holes
DSEDSH: AOS A,PAGNO ; A page to check
HRL A,LCLJFN ; In this file
RPACS ; See if its there
TXNE B,PA%PEX ; Exist?
JRST DSEDSH ; Yes. Look onward.
FFUFP ; See if any pages are used beyond here.
SKIPA ; No. Simple sequential file.
MOVX P1,<1B1> ; Yes. Make length be infinite
SUBTTL Send DSK: file, page by page
; BP/ POINT $BYTE3,WINDOW, P1 is # bytes left to send, P2 is bytes per page
SETOM PAGENO ; Starts at page zero-1
DSEDSP: JUMPLE P1,DSENDX ; Leave if all bytes sent
AOS A,PAGENO ; Next page #
HRL A,LCLJFN ; In local file
RPACS ; Page access bits
TXNE B,PA%PEX ; Page exist?
JRST DSEDSQ ; Yes. Send it.
FFUFP ; See if any more pages beyond.
JRST DSENDX ; No. End of file.
SETO A, ; Yes. Pretend this hole was a page of 0.
DSEDSQ:
MOVX B,<.FHSLF,,<WINDOW/1000>>
MOVX C,<PA%RD> ; Map in the page
PMAP
MOVE C,P1 ; Bytes left to send
CAMLE C,P2 ; If more than a page
MOVE C,P2 ; Just a page now
ADDM C,NBYTES ; Count bytes sent
MOVNS C ; - Number of words for SOUT
ADDM C,P1 ; Bytes remaining after this page
MOVE B,BP ; Pointer for SOUT
IFE TCPP,< ; NCP is dependent on channel byte size (8, 32, or 36 only)
TXNE F,F.IMG
CALL UNPK98 ; Have to shuffle bits
> ; End of IFE TCPP ; New B/ POINT $BYTE3,WINDW2, C/ -count
HRRZ A,DATCON ; Send the data
$SOUT
ERJMP DSEEWR
JUMPN C,DSEEWR
CALL TIMEOK ; Update timer
JRST DSEDSP ; Back for next page
SUBTTL Send from DSK:, PAGED type/structure
DSEDXT: SETOM PAGENO ; Set window page number to zero-1
DSEDX1: AOS A,PAGENO ; Next page to consider
DSEDX2: HRRZM A,PAGNO ; Store file page number for net
HRL A,LCLJFN ; Page pointer
RPACS ; Find the access for the page
MOVEM B,ACCESS ; Save bits for net
TXNN B,PA%PEX ; Does page exist?
JRST DSEDX3 ; No. Go see if any more.
MOVX B,<.FHSLF,,<WINDOW/1000>>
MOVX C,<PM%RD> ; Map it in for reading
PMAP
MOVX A,<PGT$SP> ; Simple page (TOPS20)
SKIPE TENEX
MOVX A,<PGT$AP> ; Access controlled page (TENEX)
MOVEM A,RECTYP ; This is a data record
MOVX A,<1000> ; Length is one page of 36-bit bytes
; Kludge compression
SKIPN WINDOW-1(A) ; Or less
SOJG A,.-1 ; Drop trailing zeros
CAIGE A,2 ; Make sure at least some data
MOVX A,<2> ; So loops work
MOVEM A,TYXNDW ; Store in header
ADDM A,NBYTES ; And count in transfer length
CALL DSEXHD ; Send this page
CALL TIMEOK ; Update timeout timer
JRST DSEDX1 ; On to next page
; Missing page
DSEDX3: FFUFP ; Are there any more pages?
JRST DSEDX4 ; No.
HRRZM A,PAGENO ; Yes, save the page number found
JRST DSEDX2 ; Go send it.
DSEDX4: CALL DSEXFD ; Last page handled. Send FDB
; Send reached end of file
DSENDX: MOVX B,<.MOSND> ; Send partial buffer
MOVE A,DATCON ; May omit PUSH if going to close
;#3 always push, the current vax code can't handle data and FIN in same packet
;#3 TXNN F,F.CLSD ; Going to close?
$MTOPR ; No, PUSH data out
ERJMP DSEEMT
JRST XFRDAX ; Done, all ok
SUBTTL Subroutine DSEXFD - Send PAGED descriptor block
DSEXFD: SETZM ACCESS ; Send FDB & EOF for PAGED DSK: file
SETZM PAGNO ; Clear access and page number
MOVX A,<PGT$DP> ; Descriptor page
MOVEM A,RECTYP ; To header
SETO A, ; Release window
MOVX B,<.FHSLF,,<WINDOW/1000>>
SETZ C, ; Just one page
PMAP
MOVX A,<FDBBLK,,WINDOW> ; Put the FDB in it
MOVE C,FDBBLK ; Actual length
ANDI C,77 ; Remove other info
BLT A,WINDOW-1(C)
HRROI A,WINDOW(C) ; Pointer to free word
SETZ C,
MOVX D,<-FDTXSN,,FDTXST> ; Locations of times & user names
DSEXFL: HRRO B,(D) ; String
SOUT ; After FDB
IDPB C,A ; End string with a NUL
HRROI A,1(A) ; Next free word
AOBJN D,DSEXFL ; Back for next
HRRZI C,-WINDOW(A) ; Words used
MOVEM C,TYXNDW ; To header for net
IFN TCPP,< ; TCPP has LAST-PAGE after DESCRIPTOR-PAGE
CALL DSEXHD ; Send descriptor page
TXO F,F.FDB ; FDB sent
MOVX A,<PGT$LP> ; Last page
MOVEM A,RECTYP
SETZM TYXNDW ; No data
> ; End of IFN TCPP ; Fall into DSEXHD to send LAST-PAGE
SUBTTL Subroutine DSEXHD - Send PAGED header & data blocks
; Send PAGED header and data (if any)
; CALL DSEXHD Send header & TYXNDW words from page in window
DSEXHD: AOS A,TYXSCT ; Count the net seq number
IFE TCPP,<
MOVEM A,SEQNO ; Put it in net header area
SETZM CHKSUM ; Initialize checksum
CALL PGCKSM ; Checksum header and page
SETCAM A,CHKSUM ; 1's comp to CHKSUM, will add to 0.
> ; End of IFE TCPP
MOVE C,RECTYP ; Get page type
MOVE B,PGLEN(C) ; Get corresponding header length
IFN TCPP,<MOVEM B,TYXNPW> ; Into header
MOVE A,DATCON
IFE TCPP,<$BOUT ; Now. Send this stuff.
ERJMP DSEEWR>
MOVN C,B ; Now that many words of hdr
MOVX B,<POINT ^D36,TYXHED> ; Point to the data
$SOUT ; Send the header
ERJMP DSEEWR
JUMPN C,DSEEWR
MOVN C,TYXNDW ; And the data area, this long.
MOVX B,<POINT ^D36,WINDOW>
SKIPE C ; Omit if none
$SOUT
ERJMP DSEEWR
JUMPN C,DSEEWR
RET
SUBTTL Receive direction after JFN's are both open. Swallow the data
DRECV: SETO A, ; Get the window page free
MOVX B,<.FHSLF,,<WINDOW/1000>>
SETZ C, ; Just one page
PMAP
DRCVL1: TXNE F,F.TYPX ; Paged transfer?
JRST DRCX ; Yes.
MOVE A,$BYTE3 ; Byte size sent
IFE TCPP,<
MOVNI C,1000 ; Assume 1000 36-bit bytes
TXNE F,F.IMG ; NCP CHANNEL processing?
MOVNI C,1100 ; Yes, if 32 bit bytes 9/8 more
CAIG A,^D8 ; If 8-bit bytes,
IMULI C,4 ; 4 times as many
> ; End of IFE TCPP
IFN TCPP,<
MOVX B,<^D36> ; Bits per word
IDIVI B,(A) ; Bytes per word
IMULI B,1000 ; Page's worth of bytes
MOVNS C,B ; Negative for SIN
> ; End of IFN TCPP
MOVX B,<POINT 0,WINDOW> ; Build byte pointer to WINDOW
STOR A,PT$BSZ,+B
PUSH P,B ; Save starting byte ptr
PUSH P,C ; And count
HRRZ A,DATCON ; Connection from net
$SIN
ERJMP DRCERE
POP P,D ; Starting count
POP P,B ; And pointer
SUB C,D ; Actual count read by SIN
DRCOUT: JUMPE C,DRCEOF ; If no bytes then EOF
ADDM C,NBYTES ; Bytes transferred so far
MOVNS C ; Negative for SOUT
IFE TCPP,<
TXNE F,F.IMG ; NCP CHANNEL processing needed?
CALL PACK89 ; Yes. Call CHANNEL converter
> ; End of IFE TCPP
HRRZ A,LCLJFN ; Where to put the data
TXNN F,F.NUL ; Don't waste time on NUL:
SOUT
ERJMP DRCERE
DRCEFQ: ; PAGED enters here
MOVE A,DATCON ; See if have gotten to EOF yet
$GTSTS
TXNE B,GS%OPN+GS%RDF ; Still happy?
TXNE B,GS%ERR
JRST DRCERD ; No.
TXNE B,GS%EOF ; End of file?
JRST DRCEOF ; Yes
JRST DRCVL1
SUBTTL Receive PAGED transfer.
DRCX: SETO A, ; Throw away any junk in window page
MOVX B,<.FHSLF,,<WINDOW/1000>>
SETZ C, ; Just one page
PMAP
SKIP WINDOW ; Touch it to get a blank page
MOVE A,DATCON ; Now get the header length
$BIN
ERJMP DRCERE
JUMPN B,DRCXB ; Got a non-zero header lmngth
; Following should be NCP only, TCPP should be JRST DRCETD
$GTSTS ; Should be EOF and "last" page
TXNE B,GS%OPN+GS%RDF
TXNE B,GS%ERR
JRST DRCERD ; Error - not open, not read, error
TXNN B,GS%EOF ; EOF?
JRST DRCETD ; No. Should not have a zero byte here.
MOVE C,RECTYP ; EOF. Was last record the "last" page?
CAME C,[PGT$LP]
JRST DRCELP ; No. Error.
TXNN F,F.FDB ; Get FDB?
JRST DRCENF ; No. Error.
JRST XFRDAX ; Good. Finish up.
DRCXB: MOVEM B,TYXHDR ; Store in scratch area
CAIL B,LTYXMN ; Range check it
CAIL B,NTXHDR ; Will it fit in this buffer?
JRST DRCEHL ; No good. Format error
MOVN C,B ; Ok, read the header
IFN TCPP,<ADDI C,1> ; Count included count word
MOVX B,<POINT ^D36,TYXHDR+1>
$SIN
ERJMP DRCERE
JUMPN C,DRCEHR ; If didn't get it all, format error
IFE TCPP,<MOVX C,<TYXHDR+1,,TYXHED>> ; Copy it to real area known length
IFN TCPP,<MOVX C,<TYXHDR,,TYXHED>> ; Copy it to real area known length
BLT C,TYXHED+TYXHDN-1
MOVE C,TYXNDW ; Get the data length out of the header
CAIL C,0 ; Make sure it's reasonable
CAILE C,1000 ; Up to a page
JRST DRCEDL ; Format error
MOVX B,<POINT ^D36,WINDOW> ; Ok, read it into the window
MOVNS C ; This many words, negative.
SKIPE C ; Allow for empty body
$SIN
ERJMP DRCERE
JUMPN C,DRCEDR ; Make sure got it all
AOS C,TYXSCT ; Check the sequence number
IFE TCPP,<
CAME C,SEQNO ; Does it match sender's?
JRST DRCESQ ; No
CALL PGCKSS ; Checksum the net header and data
JUMPN A,DRCECK ; Checksum error!
> ; End of IFE TCPP
MOVE A,RECTYP ; Get data record type
TXNE F,F.DSK ; To disk?
JRST DRCXDS ; Yes.
; PAGED type/structure NOT to DSK:
CAME A,[PGT$SP] ; Simple page or
CAMN A,[PGT$AP] ; Access controlled page?
SKIPA ; Yes
JRST DRCEFQ ; No, ignore non-data info
MOVE C,TYXNDW ; Yes. Output the data to local file.
MOVX B,<POINT ^D36,WINDOW> ; Set AC's like non-paged code.
JRST DRCOUT ; And rejoin that code.
; PAGED type/structure header & data to DSK:
DRCXDS: CAME A,[PGT$SP] ; Simple page or
CAMN A,[PGT$AP] ; Access controlled page?
JRST DRCXDA ; Yes, process data
IFN TCPP,<CAMN A,[PGT$LP] ; Last page?
JRST XFRDAX> ; Yes, done all ok
CAMN A,[PGT$DP] ; Descriptor page?
JRST DRCXFD ; Yes
JRST DRCEFQ ; No, ignore others for growth
SUBTTL PAGED data page to DSK: file
; Put the data in the window into the file
DRCXDA: MOVX A,<.FHSLF,,<WINDOW/1000>>
HRRZ B,PAGNO ; Here in the file
MOVEM B,PAGENO
HRL B,LCLJFN
MOVX C,<PM%WR> ; Write access
PMAP ; In it goes
IFN TCPP,<
MOVE A,RECTYP ; Get page type
CAME A,[PGT$AP] ; Access controlled page
JRST DRCXD2 ; No
MOVE A,TYXNPW ; Header length
CAML A,PGLEN+PGT$AP ; Correct length to contain ACCESS?
> ; End of IFN TCPP
SKIPN TENEX ; Invalid under TOPS-20
JRST DRCXD2 ; Omit ACCESS processing
MOVE A,B ; Now set the file access
MOVE B,ACCESS
SPACS
ERJMP DRCESP
DRCXD2:
SETO A,0 ; And release window (to the file)
MOVX B,<.FHSLF,,<WINDOW/1000>>
SETZ C, ; Just one page
PMAP
MOVE A,TYXNDW ; Count the transferred bytes
ADDM A,NBYTES
JRST DRCEFQ ; See if any more.
SUBTTL Process recieved PAGED descriptor page
; Check for reasonable FDB length
DRCXFD: MOVE A,WINDOW ; Length of FDB
ANDI A,77
CAIL A,MINFDB ; Look like an FDB?
CAILE A,MAXFDB+10
JRST DRCEFL ; No, say format error
; Get extra ASCIZ information after FDB into individual strings
MOVE B,TYXNDW ; Information words there
HRROI B,WINDOW(B) ; Pointer beyond end (negative)
PUSH P,B
HRROI A,WINDOW(A) ; String pointer from window
SETZ C,
MOVX D,<-FDTXSN,,FDTXST>
DRCXFI: HRRO B,(D) ; String
SIN ; Get it
IDPB C,B ; End string with a NUL
HRROI A,1(A) ; Beginning of next string
CAMLE A,(P) ; Anythingthere?
SETZB D,@(D) ; No, stop
AOBJN D,DRCXFI ; Back for next
POP P,(P) ; Discard end address
; Convert date & time strings to internal format (TOPS20 & TENEX differ)
MOVX D,<-FDTXTN,,FDTXT>
DRCXFJ: HRRO A,(D) ; String pointer
SETZ B, ; Any format
IDTIM
TLO B,-1 ; No time on error
HLRZ A,(D) ; FDB offset to corresponding time
MOVE C,B ; Keep FDB value if equivalent to string
SUB C,WINDOW(A) ; See if close to FDB value
MOVMS C ; If magnitude of difference is bigger
CAILE C,4 ; than a few ticks,
MOVEM B,WINDOW(A) ; Use time from string
AOBJN D,DRCXFJ
; Update FDB information
MOVX D,<-FDBTXN,,0> ; Update the FDB
MOVX C,<-FDBTMN,,0> ; Last are times
PUSH P,C
DRCXFN: MOVE A,LCLJFN ; Make pointer to FDB word
HRL A,FDTXT1(D) ; This word of FDB
MOVE B,FDTXT2(D) ; This mask to change
MOVE C,FDTXT1(D) ; From this word of net FDB
MOVE C,WINDOW(C)
CAML D,(P) ; A time?
SKIPL C ; Yes, valid?
CHFDB ; No. Put in the data
CHFDPC: ERJMP .+1 ;DRCECF
AOBJN D,DRCXFN ; Loop for changeable words of FDB
POP P,(P)
REPEAT 0,<
SKIPN F$KPGN ; Able to retain generation number?
JRST DRCXFP ; No
; If original file had a higher generation number, rename it
HRRZ A,LCLJFN ; Get current
MOVX B,<1,,.FBGEN> ; Generation number
MOVEI C,D ; FDB word into D
GTFDB
ERJMP DRCXFP ; Forget it
HLRZS D ; Extract current #
HLRZ C,WINDOW+.FBGEN ; Extract original #
CAMG C,D ; Original greater?
JRST DRCXFP ; No, leave it as is
MOVE D,C ; Save new number
HRROI A,STRTMP ; Get current name
HRRZ B,LCLJFN ; Without extension
MOVX C,<..DEVA!..DIRA!..NAMA!..TYPA!JS%PAF>
JFNS
ERJMP DRCXFP ; Forget it
SETZ C,
IDPB C,A
HRRZ A,D ; New generation #
TXO A,<GJ%NEW!GJ%SHT>
HRROI B,STRTMP ; Get another JFN
GTJFN
ERJMP DRCXFP ; Forget it
HRRZ B,A ; New JFN
HRRZ A,LCLJFN ; First close current file
TXO A,CO%NRJ ; Keeping JFN
CLOSF
ERJMP DRCXFO ; Loose, go cleanup
HRRZS A ; Get rid of flags
RNAMF ; Rename file to higher generation
ERJMP DRCXFO ; Loose, go cleanup
MOVEM B,LCLJFN ; New local JFN, old released
JRST DRCXFP ; All ok
DRCXFO: MOVE A,B ; New JFN
RLJFN ; Forget it
ERJMP .+1
DRCXFP:
> ; End of REPEAT 0
; Set original writer/creator name, if possible
SKIPE TENEX
JRST DRCXFT ; TENEX
; TOPS20
MOVX D,<-FDTXUN,,FDTXUS>
DRCXFR: HRRZ A,LCLJFN ; File
HLL A,(D) ; Function
HRRZ B,(D) ; Build pointer to string
HRLI B,440700 ; ..
ILDB C,B ; See if it's null
JUMPE C,DRCXF1 ; If null, don't set it
HRLI B,440700 ; Rebuild string pointer
SFUST
ERJMP .+1 ; Probably not enabled
DRCXF1: AOBJN D,DRCXFR
JRST DRCXFU
DRCXFT: SETZ A, ; Literal string
HRROI B,FDBUS0 ; String DIRST
SKIPA
STDIR
ERJMP .+2
ERJMP .+1
JFCL
DRCXFU:
JRST DRCEFQ ; Should be EOF now if NCP.
FDTXT1: EXP .FBCTL ; Can change these words
EXP .FBBYV
EXP .FBSIZ
EXP .FBUSW
..Z=.
EXP .FBCRV
EXP .FBWRT
EXP .FBREF
FDBTMN==.-..Z ; Number of times
FDBTXN==.-FDTXT1
FDTXT2: EXP FB%TMP+1000000 ; Temp and (TENEX) ephemeral bits
EXP FB%BSZ ; Byte size
EXP -1 ; EOF
EXP -1 ; User settable word
EXP -1 ; Time this version created
EXP -1 ; Time this version last modified
EXP -1 ; Time last referenced
FDTXST: EXP FDBTM1,FDBTM2,FDBTM3,FDBUS0,FDBUS1
FDTXSN=.-FDTXST
SUBTTL Data transfer Error Messages
DRCECF: JSP X,XFRERR
ASCIZS (452,451,< ? Unable to update local file descriptor.>)
DRCEDL: JSP X,XFRERR
ASCIZS (452,451,< ? Invalid PAGED data block length.>)
DRCEDR: JSP X,XFRERR
ASCIZS (452,451,< ? Premature EOF from network during PAGED data read.>)
DRCEFL: JSP X,XFRERR
ASCIZS (452,451,< ? Invalid PAGED FDB length.>)
DRCEHL: JSP X,XFRERR
ASCIZS (452,451,< ? Invalid PAGED header length.>)
DRCEHR: JSP X,XFRERR
ASCIZS (452,451,< ? Premature EOF from network during PAGED header read.>)
DRCELP: JSP X,XFRERR
ASCIZS (452,451,< ? Last block of PAGED transfer missing.>)
DRCENF: JSP X,XFRERR
ASCIZS (452,451,< ? No descriptor (FDB) information received.>)
DRCERD: JSP X,XFRERR
ASCIZS (452,451,< ? Error on network data connection.>)
DRCERE: JSP X,XFRERR
ASCIZS (452,451,< ? Read error on network data connection.>)
DRCESP: JSP X,XFRERR
ASCIZS (452,451,< ? Error setting local file page access.>)
DRCETD: JSP X,XFRERR
ASCIZS (452,451,< ? PAGED header length was zero.>)
IFE TCPP,<
DRCECK: JSP X,XFRERR
ASCIZS (452,451,< ? Software-detected checksum error from network during paged transfer.>)
DRCESQ: JSP X,XFRERR
ASCIZS (452,451,< ? Sequence error from net during paged transfer.>)
> ; End of IFE TCPP
DSEEFD: JSP X,XFRERR
ASCIZS (452,451,< ? Internal Error - Cannot access local file's FDB.>)
DSEEMT: JSP X,XFRERR
ASCIZS (452,451,< ? Internal Error - MTOPR failed.>)
DSEEWR: JSP X,XFRERR
ASCIZS (452,451,< ? Unexpected close of data connection.>)
MSG226: ASCIZS (252,226,< Transfer completed.>) ; Ok & Connection closed
MSG250: ASCIZS (252,250,< Transfer completed.>) ; Ok & connection open
; X/ Address of reply message
XFRERR: TXO F,F.ERR ; Forces close of connection
SUBTTL Data Transfer Exit
DRCEOF: ; Received end of file
IFE TCPP,<TXNE F,F.DSK ; On disk and
TXNN F,F.IMG ; CHANNEL processing?
JRST DRCEF2 ; No. Skip this.
TXZ F,F.IMG ; Beware loop if CHFDB fails
CLOSK (LCLJFN) ; Yes. Diddle up the EOF pointer
MOVX B,<FB%BSZ> ; Byte size field
MOVX C,<FLD(1,FB%BSZ)> ; One bit bytes
HRRZ A,LCLJFN
HRLI A,.FBBYV ; This word in FDB
CHFDB ; Change it
ERJMP DRCECF
SETO B,
MOVE C,NBYTES ; Number of bytes transferred
IMUL C,$BYTE3 ; Times byte size gives bits
HRLI A,.FBSIZ ; This word
CHFDB ; Store in FDB
ERJMP DRCECF
DRCEF2:
> ; End of IFE TCPP
XFRDAX: SETO A, ; Unmap the window pages
MOVX B,<.FHSLF,,<WINDOW/1000>>
SETZ C, ; No count
PMAP
ADDI B,1
PMAP
HRRI B,<WINDW2/1000>
PMAP
ADDI B,1
PMAP
TXNN F,F.ERR ; Have an error message?
HRROI X,MSG250 ; No, Ok & leaving open
TXNN F,F.CLSD!F.ERR ; Have to close (or error)?
JRST XFRDAZ ; No, all done
CLOSD (DATCON,CO%WCL) ; Wait for other end to see close
TXNN F,F.ERR ; Have an error message?
HRROI X,MSG226 ; No, Ok & closed
XFRDAZ: HRRZM X,$REPLM ; Local reply message address for superior
RET ; Return from XFRDAT
SUBTTL Subroutine GETFDB
; CALL GETFDB Copies Disk FDB into FDBBLK
;Ret+1: Illegal instruction interupt
;Ret+2: Ok
GETFDB: SETZM FDBBLK ; Clear it in case not DSK: or NUL:
MOVX A,<FDBBLK,,FDBBLK+1>
BLT A,FDBBKE
HRRZ A,LCLJFN ; Local file
HRLZ B,LFDB ; System dependent FDB length
MOVEI C,FDBBLK ; Store it here
TXNN F,F.DSK ; If not disk,
JRST GETFDX ; Ok return
GTFDB ; Get the info
ERJMP GETFDY
MOVE A,FDBBLK ; Size of FDB
ANDI A,777
PUSH P,A ; For testing
MOVX D,<-FDTXTN,,FDTXT>
MOVX C,<OT%4YR!OT%TMZ!OT%SCL>
GETFD1: HRRO A,(D) ; String pointer
HLRZ B,(D) ; FDB offset
CAMLE B,(P) ; In FDB?
JRST GETFD2 ; No
MOVE B,FDBBLK(B) ; Get time
ODTIM
ERJMP .+1
AOBJN D,GETFD1
GETFD2:
SKIPE TENEX
JRST GETFD5 ; TENEX
; TOPS20
MOVX D,<-FDTXUN,,FDTXUG>
GETFD3: HRRZ A,LCLJFN ; File
HLL A,(D) ; Function
HRRO B,(D) ; String pointer
GFUST
AOBJN D,GETFD3
JRST GETFD6
GETFD5: HRROI A,FDBUS0 ; String pointer
HLRZ B,FDBBLK(D) ; Directory number
DIRST
ERJMP .+1
GETFD6:
POP P,(P) ; Drop FDB length
GETFDX: AOS (P) ; Skip return
GETFDY: RET
FDTXT: XWD .FBCRV,FDBTM1 ; Times FDB offset,,String variable
XWD .FBWRT,FDBTM2
XWD .FBREF,FDBTM3
FDTXTN==.-FDTXT
FDTXUG: XWD .GFAUT,FDBUS0 ; User name Function code,,String variable
XWD .GFLWR,FDBUS1
FDTXUN==.-FDTXUG
FDTXUS: XWD .SFAUT,FDBUS0 ; User name Function code,,String variable
XWD .SFLWR,FDBUS1
SUBTTL NCP Subroutine PGCKSS
IFE TCPP,<
; Checksum routine for paged transfer type. Two entries, depending
; on whether the header is the preassembled length or
; the length that actually came from net.
; CALL PGCKSS Compute Checksum
; OR
; CALL PGCKSM Compute Checksum
PGCKSS: MOVN B,TYXHDR ; Length from net
HRLZ B,B ; Make AOBJN pointer
HRRI B,TYXHDR+1 ; First word of hdr after its length
JRST PGCKS1 ; Join sender routine
PGCKSM: MOVX B,<-TYXHDN,,0> ; Length of header to be sent
HRRI B,TYXHED ; And where it is.
PGCKS1: SETZ A, ; Start with a sum of 0
JCRY0 .+1 ; Clear carry 0 flag
PGCKL1: ADD A,0(B) ; Sum the data
JCRY0 [AOJA A,.+1] ; End-around carry
AOBJN B,PGCKL1 ; Get the whole header
MOVN B,TYXNDW ; Now the data area, this length
HRLZS B ; Make AOBJN counter
JCRY0 .+1
PGCKL2: ADD A,WINDOW(B) ; Add a data word
JCRY0 [AOJA A,.+1] ; Catch end-around carry
AOBJN B,PGCKL2 ; All the data
AOSE A ; Make -0 into +0
SOS A ; Wasn't -0, correct and return
RET
> ; End of IFE TCPP
SUBTTL NCP routine to shuffle bits to send CHANNEL in non-36 bit bytes
IFE TCPF,<
UNPK98: PUSH P,C ; Negative SOUT byte count
MOVX A,<-1000,,0> ; Process a page of words
MOVX B,<-10,,0> ; State counter
MOVX C,<-2000,,WINDW2-1> ; Pointer for 8/32 bit data
UNPK9L: MOVE T1,WINDOW(A) ; A word of bits
AOBJN C,.+1 ; Count dest ptr
TRNN B,-1 ; Every eight states,
AOBJN C,.+1 ; Have to count another
LSHC T1,@IMISHT(B) ; Break into leftover in T1, new wd in T2
DPB T1,IMIPT1(B) ; Store enough bits in first word
MOVEM T2,0(C) ; And move word into second. Not yet full.
AOBJN B,.+2 ; Step the state counter
MOVX B,<-10,,0> ; Restart it
AOBJN A,UNPK9L ; Loop for whole page
POP P,C ; Negative 36-bit byte count
MOVNS C
IMULI C,^D9 ; Convert to bytes (*9/8)
ASH C,-3 ; This many if 32 bit
MOVE A,$BYTE3 ; Is it eight bit?
CAIG A,^D8 ; (If not, must be 32)
ASH C,2 ; Yes. This many bytes to go out
MOVNS C ; Make it negative again
MOVX B,<POINT 0,WINDW2>
STOR A,PT$BSZ,+B ; Byte size for SOUT pointer
RET ; Back to send it
SUBTTL NCP subroutine to shuffle bits from 8/32 bit wds to 36 bit wds
PACK89: TXNN F,F.DSK ; It is on disk isn't it?
RET ; No. Don't process it.
SETZM WINDW2 ; Yes. Clear the window page
MOVX A,<WINDW2,,WINDW2+1>
BLT A,WINDW2+777
MOVX A,<-1100,,0> ; Number of 32 bit words in window
MOVX B,<-10,,0> ; State counter
MOVX C,<-1000,,WINDW2> ; Where 36 bit words go.
PACK8L: AOBJP A,.+2 ; Count thru input
MOVE T2,WINDOW(A) ; Get two 32 bit words
MOVE T1,WINDOW-1(A)
LSH T1,-4 ; Butt the two 32 bit groups together
LSHC T1,@IMOSHT(B) ; Shift to get the correct 36 bits
MOVEM T1,0(C) ; Store output word
AOBJN C,.+1 ; Count output
AOBJN B,PACK8N ; Need to reset state counter?
MOVX B,<-10,,0> ; Yes.
AOBJN A,.+1 ; And step an extra word.
PACK8N: JUMPL A,PACK8L ; Loop if more to do
MOVX B,<POINT 36,WINDW>]
MOVNI C,1000 ; Packed 36-bit bytes
RET
SUBTTL Tables for in and out CHANNEL processors
IMISHT: REPEAT 10,< XWD 0,-4*<.-IMISHT+1>>
IMIPT1: REPEAT 10,< POINT ^D<32-<4*<.-IMIPT1>>>,-1(C),31>
IMOSHT: REPEAT 10,< EXP <.-IMOSHT+1>*4>
> ; End of IFE TCPF
DLITS:; LIT
XLIST
LIT
LIST
HSTOP==.-1
.ORG ;BACK TO LOW SEGMENT
SUBTTL Interrupt Tables
LEVTAB: EXP RETPC1,RETPC2,RETPC3
IFDEF USER,< ; User Program
CHNTAB: 0 ; 0
0 ; 1
0 ; 2
0 ; 3
0 ; 4
0 ; 5
0 ; 6 Arithmetic Overflowl/nodiv
0 ; 7 Floating Point overflow/FXU
0 ; 8
0 ; 9 PDLOV
0 ; 10 EOF
0 ; 11 IO Data Error
0 ; 12 Quota Exceeded
0 ; 13
0 ; 14 Time of Day
1,,INSINT ; 15 Illeg Instruction Int
0 ; 16 Illeg Memory Read
0 ; 17 Illeg Memory Write
0 ; 18 Illeg Memory Execute
0 ; 19 Fork Term
0 ; 20 Machine size exceeded (Disk/Drum??)
0 ; 21 Trap to User
0 ; 22 New Page
0 ; 23
IFN TCPF,<NTICHN==-1
0>
IFE TCPF,<NTICHN==.-CHNTAB ; 24
3,,NTIINT>
CGICHN==.-CHNTAB ; 25
3,,CGINT ; Bell typed
COICHN==.-CHNTAB ; 26
3,,COINT ; Control-O interrupt
IFE TCPP,<ABBCHN==-1> ; 27
IFN TCPP,<ABBCHN==.-CHNTAB ; IIC from TELNET to top
3,,ABBINT>
ABOCHN==.-CHNTAB ; 28
3,,ABOINT ; IIC from TELNET to top
CTTCHN==.-CHNTAB ; 29
3,,CTTINT
0 ; 30
0 ; 31
0 ; 32
0 ; 33
0 ; 34
0 ; 35
IFN <.-44-CHNTAB>,<PRINTX ; CHNTAB not 36 long>
CHNMSK: <1B<NTICHN>!1B<ABBCHN>!1B<ABOCHN>!1B<CGICHN>!1B<COICHN>!1B<CTTCHN>!1B<.ICILI>>
> ; End of IFDEF USER
SUBTTL Interrupt Tables
IFDEF SERVER,< ; Server program
CHNTAB: 0 ; 0
0 ; 1
0 ; 2
0 ; 3
0 ; 4
0 ; 5
0 ; 6 Arithmetic Overflowl/nodiv
0 ; 7 Floating Point overflow/FXU
0 ; 8
1,,PDLINT ; 9 PDLOV
0 ; 10 EOF
2,,IOXINT ; 11 IO Data Error
2,,QTAINT ; 12 Quota Exceeded
0 ; 13
0 ; 14 Time of Day
1,,INSINT ; 15 Illeg Instruction Int
1,,MEMINT ; 16 Illeg Memory Read
1,,MEMINT ; 17 Illeg Memory Write
1,,MEMINT ; 18 Illeg Memory Execute
0 ; 19 Fork Term
1,,FULINT ; 20 Machine size exceeded (Disk/Drum??)
0 ; 21 Trap to User
0 ; 22 New Page
0 ; 23
TIMCHN==.-CHNTAB ; Channel poked by timing fork every now and then
2,,TIMINT ; 24 Timing Fork Int
CTCCHN==.-CHNTAB ; Channel for Control-C
2,,CTCINT ; 25 Control-C (or E in debug)
DETCHN==.-CHNTAB ; Channel for NVT hangup
2,,DETINT ; 26 Detach Interrupt
CTTCHN==.-CHNTAB ; Channel for Control-T
2,,CTTINT ; 27 Control-T
0 ; 28
0 ; 29
0 ; 30
0 ; 31
0 ; 32
0 ; 33
0 ; 34
0 ; 35
IFN <.-44-CHNTAB>,<PRINTX ; CHNTAB not 36 long>
ONCHNS: 1B<.ICPOV>!1B<.ICDAE>!1B<.ICILI>!1B<.ICIRD>!1B<.ICIWR>!1B18!1B<.ICMSE>!1B<TIMCHN>!1B<CTCCHN>!1B<DETCHN>!1B<CTTCHN>
FAIJFN: BLOCK 1
SUBTTL Constants
DEFINE CC (A,B) <
IFNDEF Z'A, <Z'A==NOTIMP>
>
COMS
PARMAC
IFN IPCLOG,<
INFMSG: 1,,.IPCIW ; .IPCI0 message to info
0 ; .IPCI1 no copy
ASCIZ /[SYSTEM]FTSCTT/ ; .IPCI2 get a PID for this name
ENDMSG==.
>
> ; End of IFDEF SERVER
SUBTTL Constants
GPDP: IOWD PDLL,GPDL ; Global (top-level) stack
PDP: IOWD PDLL,PDL
L1PDP: IOWD PDLL,L1PDL ; Lev 1 PSI stack
L2PDP: IOWD PDLL,L2PDL ; Lev 2 PSI stack
L3PDP: IOWD PDLL,L3PDL ; Lev 3 PSI stack
CMDIP0: POINT 7,CMDIB-1,34 ; Initial pointer to command buffer
WRDBP0:POINT 7,WORDBF-1,34 ;u Initial pointer to word buffer
IFDEF SERVER,<
IFE TCPF,<FTPDAT: 2> ;s Local socket for data connection
IFN TCPF,<FTPDAT: ^D<21-1>> ;s Local port for data connection
> ; End of IFDEF SERVER
IFDEF USER,<
FTPSKT: FTPICS ;u Protocol ICP socket #
IFE TCPF,<
DATSKT: FTPDSK ;u Data socket for FTP version
> ; End of IFE TCPF
USRSKT: USRSKN ;u User socket number U before job #
PMASK: ASCII /
Your Password/
BYTE (7) 15,43,43,43,43 ;u
ASCII /##########/
BYTE (7) 15,115,115,115,115
ASCII /MMMMMMMMMM/
BYTE (7) 15,44,44,44,44
ASCII /$$$$$$$$$$/
BYTE (7) 15,15
PMASK2: BYTE (7) 15,"T","h","a","n"
ASCIZ /k-you.....
/
> ; End of IFDEF USER
T20PAR: EXP 0,T20FDB,T20CDL,T20CD2,T20WDL,T20WD2,T20LDL,T20LD2,T20EOL
TNXPAR: EXP -1,TNXFDB,TNXCDL,TNXCD2,TNXWDL,TNXWD2,TNXLDL,TNXLD2,TNXEOL
PATCHX=VERSIO ; Update version number if patched
PAT:
PATCH: BLOCK 400 ; For patching the binary
DBUGSW: 0 ; Nonzero for debugging
; End of all code. Now the literals.
LITS: XLIST ; LIT Statement
LIT
LIST
LSTOP==.
FREPAG==100 ;u Page of free storage
SUBTTL Global Variables
LOC 200000
GSBAS:
FREE: BLOCK 1 ;u Pointer to (end of) free core
GPDL: BLOCK PDLL ; Stack for top fork
; NB: order must match T20PAR & TNXPAR
TENEX: BLOCK 1 ; Non-zero if running on a TENEX system
LFDB: BLOCK 1 ; Length of disk FDB
EDIT0:
CDELCH: BLOCK 1 ; System-dependent character delete character
CDE2CH: BLOCK 1
CDELWD: BLOCK 1 ; System-dependent word delete character
CDE2WD: BLOCK 1
CDELLN: BLOCK 1 ; System-dependent line delete character
CDE2LN: BLOCK 1
NEDITS==.-EDIT0
EOL: BLOCK 1 ; System-dependent end of input line character
; NB: order must match T20PAR & TNXPAR
VERSTR: BLOCK 20 ; ASCII version number
;s Results of GJINF at start and LOGIN
GJINF1: BLOCK 1 ;s User ID # (TENEX 18-bit Dir # or
; TOPS20 36-bit User #)
GJINF2: BLOCK 1 ;s Connected directory #
GJINF3: BLOCK 1 ;s Job #
GJINF4: BLOCK 1 ;s -1 or attached TTY #
SYSDNM: BLOCK 1 ;s Dir number of SYSTEM
ANOUNO: BLOCK 1 ;s User number of ANONYMOUS or 0
ANNJFN: BLOCK 1 ;s JFN of ANONYMOUS.USERFILE while open
ANOPSW: BLOCK 10 ;s Where to store ANONYMOUS's password
ANOPSE==. ; from system text file
USERNM: BLOCK 1 ;s TENEX: Directory Number (STDIR($USER))
; or ;s TOPS20: User Number (RCUSR($USER))
DIRJFN: ;u Directory JFN in MULTIPLE GET
LSTJFN: BLOCK 1 ;s JFN where LIST or STAT goes.
LCLJFN: BLOCK 1 ; JFN of local mail file, temp files
LCLGEN: BLOCK 1 ;u Local generation #
PRGJFN: BLOCK 1 ;s JFN from RMAP of this program
TJFN: BLOCK 1 ;u JFN of temporary file
$PATH1: BLOCK 1 ;-1 ;s JFN for Rename From
$PATH2: BLOCK 1 ;-1 ;s JFN for Rename To
$PTHS1: BLOCK 40 ;s String space for old name in RNFR
F$SEND: BLOCK 1 ;uCD 0 for rcv data from net, else send.
F$FLST: BLOCK 1 ; CR File status is being requested
F$KPGN: BLOCK 1 ; CD May rename local file to keep gen #
F$DOPN: BLOCK 1 ;uCD Flag to assure data conn opened
F$DTRQ: BLOCK 1 ;uC Data transfer about to be requested
F$DTIP: BLOCK 1 ; C Data transfer in prog (250, no 252)
F$WORK: BLOCK 1 ;uCD TIMEOK increments, CWFORK test/clears
F$DTDR: BLOCK 1 ;uCR Data trans done reply (252-4) came in.
F$STAR: BLOCK 1 ;uC Flag top level is at left margin TYI
F$TCLS: BLOCK 1 ;u Close foreign connection if non-0
F$VBOS: BLOCK 1 ;uCR -1 => VERBOSE typeout; 0 => brief
CGCOUNT:BLOCK 1 ;u -1 if no Control-G, counts upward
$FILST: BLOCK 200 ; CR File status from STAT 213 reply
EFILST==.-1 ; Global for TELNET receiver to top fork
$REPLM: BLOCK 1 ; CD Local data trans reply message address
SUBTTL Network Information
HOSTNN: BLOCK 1 ;u Pointer to host number table
HOSTN: BLOCK 1 ;u Ptr to table of
; <Host #s and bits,,Ptr to ASCIZ>
HSTNAM: BLOCK 1 ;u ASCIZ pointed to from HOSTN table
; Tables above are in the FREE area
HOSTNP: BLOCK 1 ; -# host names,,0 (from GTHST)
LHOSTN: BLOCK 1 ; Local host # (32-bit Internet fmt)
LHSTYP: BLOCK 1 ;u Local host system type (in HS%STY field)
LHSTNM: BLOCK 20 ; Local host name in ASCIZ
;NETLSK:BLOCK 1 ; Local Socket
MYDATS: BLOCK 1 ;s CVSKT of my data connection
FHSTN: BLOCK 1 ; Foreign host # (32-bit Internet fmt)
FHSTYP: BLOCK 1 ;u Foreign host system type (in HS%STY field)
FTNXX: BLOCK 1 ;u Foreign host TENEX/-1, TOPS20/1, other/0
HOSTX: BLOCK 1 ;u Index into HOSTN for that host
FHSTNM: BLOCK 10 ;s Foreign host name in ASCIZ
FORNS: BLOCK 1 ;s Even numbered foreign NVT socket
REPEAT 0,<
NETSKX: BLOCK 1 ;s Index into net tables for the NVT
NBUFN: BLOCK 1 ;s GETAB 'NETBUF' -n,,tab #
NSTSN: BLOCK 1 ;s GETAB 'NETSTS' -n,,tab #
NETAWD: BLOCK 1 ;s NVT GETAB 'NETAWD'
PRIVF: BLOCK 1 ;u Private socket flag
> ; End of REPEAT 0
SUBTTL Data Transfer Parameter Blocks
; Define transfer parameter blocks. The User has three copies: first
; is what has most recently been specified by the user, second is the
; values to be used for the next data transfer (either user values
; or values appropriate for an internal operation (e.g. getting a
; directory listing), third is the values most recently sent to the
; server (eliminates unnecessary commands to the server which
; remembers the parameters which are in effect. The Server has a
; single copy, but defines dummy second and third copies on top of
; the first (allows code to be shared between User & Server programs).
; Note: User requires that $HOST be immediately followed by $SOCK
; (PORT command processing).
DEFINE XFRPAR (L,N<HOST,SOCK,MODE,STRU,TYPE,BYTE,FORM>)<ZZ==.
IRP N,<$'N'L=ZZ
ZZ==ZZ+1> ; End of IRP N
> ; End of DEFINE XFRPAR
PARAMS: XFRPAR ; The data transmission parameters
EPARAMS==ZZ-1 ; End of first copy
NPARS==ZZ-PARAMS ; Number of parameters in block
IFDEF USER,<LOC ZZ> ; Second copy may overlay first
PARAM2: XFRPAR 2 ; Copy during actual transfer
EPAR2==ZZ-1
IFDEF USER,<LOC ZZ> ; Third copy may overlay first
PARAM3: XFRPAR 3 ; Last ones sent out
;EPAR3==ZZ-1
LOC ZZ ; One copy occupies space
$LTYPE: BLOCK 1 ; Local packing
$LBYTE: BLOCK 1 ; Local byte size
$FILLB: BLOCK 1 ; Local filler byte
IBITCT: BLOCK 1 ; Bit count for logging: MAIL/RETR/STOR/APPE
TSBITS: BLOCK 1 ; Bits sent by RETR (cumulative, never used)
NBYTES: BLOCK 1 ; Bytes moved by last file transfer command
PAGENO: BLOCK 1 ; Page # to map in DSK file (global for ^T)
TYXSCT: BLOCK 1 ; Sequence number for paged mode
SUBTTL Paged Mode Header
IFE TCPP,< ; Do NOT separate the next few. They are the "TYPE XTP" header
TYXHED: BLOCK 0 ; Tag the header area
CHKSUM: BLOCK 1 ; Checksum of the data chunk
SEQNO: BLOCK 1 ; Sequence number of the chunk
TYXNDW: BLOCK 1 ; Number of data words goes here
PAGNO: BLOCK 1 ; Page number in disk file
ACCESS: BLOCK 1 ; RPACS arg for disk file
RECTYP: BLOCK 1 ; Type of net chunk
PGT$LP==:-3 ; Last page
PGT$SP==:0 ; Simple data page
PGT$DP==:-3 ; Descriptor page
PGT$AP==:0 ; Access controlled page
TYXHDN==.-TYXHED ; Length of this header
; End of unseparable stuff
PSTOP==. ; Following are constants, not variables
LOC LSTOP ; So back to low segement
EXP TYXHDN,0,0 ; Header length of PGT$LP==PGT$DP, (unused)
PGLEN: EXP TYXHDN ; PGT$SP == PGT$AP
LTYXMN==6 ; Minimum header length
LSTOP==.
LOC PSTOP ; Back to process-private area
> ; End of IFE TCPP
IFN TCPP,< ; Do NOT separate the next few. They are the "STRU P" header
TYXHED: BLOCK 0 ; Tag the header area
TYXNPW: BLOCK 1 ; Header length (4 or 5)
PAGNO: BLOCK 1 ; Page number in disk file
TYXNDW: BLOCK 1 ; Number of data words goes here
RECTYP: BLOCK 1 ; Page type
PGT$LP==:0 ; Last page
PGT$SP==:1 ; Simple data page
PGT$DP==:2 ; Descriptor page
PGT$AP==:3 ; Access controlled page
ACCESS: BLOCK 1 ;(OPTIONAL) ; RPACS arg for disk file
TYXHDN==.-TYXHED ; Length of this header
; End of unseparable stuff
PSTOP==. ; Following are constants, not variables
LOC LSTOP ; So back to low segement
PGLEN: EXP 4,4,4,5 ; Header lengths for PGT$LP, $SP, $DP, $AP
LTYXMN==4 ; Minimum header length
LSTOP==.
LOC PSTOP ; Back to process-private area
> ; End of IFN TCPP
NTXHDR==40 ;u Length to allow on reading net
TYXHDR: BLOCK NTXHDR ;u Make longer in case it grows
SUBTTL TELNET & Data Connection Control & Data Blocks
IFN TCPF,< ; Only one TCP connection to send+receive
PRT227: BLOCK 1 ;u Port # from PORT reply (host in SOC255)
RCON: ; TCP File block including CDB + Buffer headers
SCON: BLOCK <T.SIZE> ; TELNET file block including CDB
BLOCK 2*T.NDBF*.TCPBS ; TELNET buffer headers
TELRBF: BLOCK <T.BFSZ*T.NDBF> ; TELNET receive data buffers
TELSBF: BLOCK <T.BFSZ*T.NDBF> ; TELNET send data buffers
; TCP File block including CDB + Buffer headers
DATCON: BLOCK T.SIZE ; Data connection file block including CDB
BLOCK 2*T.NDBF*.TCPBS ; Data connection buffer headers
DATBUF: BLOCK <2*T.BFSZ*T.NDBF> ; Data connection data buffers
JFNTXS: BLOCK 60 ; Text string from JFNS (used by simulation)
EJFNTX==.-1
> ; End of IFN TCPF
IFE TCPF,<
FORNS: BLOCK 1 ; Foreign socket sent on ICP ("S")
SOCRFC: BLOCK 1 ; Socket requesting data RFC
SOC255: BLOCK 1 ; Socket server claimed he would use
IJFN: BLOCK 1 ; ICP JFN
SCON: BLOCK 1 ; TELNET send con
RCON: BLOCK 1 ; TELNET receive con
DATCON: BLOCK 1 ; Data network socket con
; Data conn JFN if MLFL
NCPBLK: BLOCK 20 ; Connection data block
> ; End of IFE TCPF
GSTOP==.
SUBTTL Process-Private Variable Storage
LOC 300000
PSBAS: BLOCK 1
NTIIA: BLOCK 1 ;u Save AC A here in NTIINT
RETPC1: BLOCK 1 ; Return PC's for PSI system
PI1AC: BLOCK 20 ; Storage for Lev 1 AC's
L1PDL: BLOCK PDLL ; Another on Lev 1 PSI
RETPC2: BLOCK 1
PI2AC: BLOCK 20 ; Storage for Lev 2 AC's
L2PDL: BLOCK PDLL ; And another on Lev 2
RETPC3: BLOCK 1 ; ..
PI3AC: BLOCK 20
PI3PDL:
L3PDL: BLOCK PDLL
PDL: BLOCK PDLL ; Stack for a fork
; Top fork
IRFMOD: BLOCK 1 ;u What RFMOD got after RESET at go
ICOCB: BLOCK 1 ;u Initial FCOC
ICOCC: BLOCK 1
FCOCB: BLOCK 1 ;u Initial FCOC, adjusted
FCOCC: BLOCK 1
RESTRT: BLOCK 1 ;s Flag that we've run before
CPUTIM: BLOCK 1 ;u Timing cells
DAYTIM: BLOCK 1 ;u ..
IFRKTM: BLOCK 1 ;s Time meter for logging
KTIMET: BLOCK 1 ;s Time when job will be killed by
; time of day interrupt
IOXFLG: BLOCK 1 ;s Flag set by IO err PSI
CTCFLG: BLOCK 1 ;s Flag set by ^C PSI
LGOCNT: BLOCK 1 ;s Counter to force logout on time.
DFORKH: BLOCK 1 ;u Fork handle of data copier
RFORKH: BLOCK 1 ;u Fork handle of TELNET receiver
SFORKH: BLOCK 1 ;u Fork handle of TELNET sender
;THISFK:BLOCK 1 ;u This fork's handle
TFORKX: BLOCK 1 ;s Fork handle of timing fork
IFN IPCLOG,<
IPCDAT: BLOCK 100 ;s Data area for msgs to/from IPCF
PIDARG: BLOCK 10 ;s Arg block for IPCF calls
CTLPID: BLOCK 1 ;s PID of FTSCTL
MYPID: BLOCK 1 ;s PID of FTPSRV
>
SUBTTL Command Parsing
PRVKWD: BLOCK 2 ;s Previous keywrd, for sequence-
; dependant commands RNTO, PASS
KEYWRD: BLOCK 2 ;s The command verb
ARGWRD: BLOCK 2 ;s The arg for some commands
CARG1: BLOCK 1 ;s First argument to command
CARG2: BLOCK 1 ;s Second argument to command
$ACCES: BLOCK 3 ;s Argument block for ACCES JSYS
USRFCT: BLOCK 1 ;s Bad user names counter
$USER: BLOCK 11 ;s User name text string
PASFCT: BLOCK 1 ;s Password failure counter
$PASS: BLOCK 11 ;s Password text string
$ACCT: BLOCK 12 ;s Account word or string
$CWD: BLOCK 1 ; 0 ;s Dir Num of CWD command
TEMSTR: BLOCK 50 ;#5 MORE RANDOM STRING SPACE
STRTMP: BLOCK 100 ; A random string space
ESTRTM==.-1
ERRSTR: BLOCK 30 ;s Error string
LPTSTR: BLOCK 30 ;s Arg of XLPTF command
RCDSTR: BLOCK 12 ;s Space to build up a dir name
USERST: BLOCK 20 ;s Name string of directory from CWD
WORDXP: BLOCK 1 ;u Argument to GETWRD. -N,,Table of ASCIZ
RECX: BLOCK 1 ;u Index when found by RECOG, or -1 if none
BREAKC: BLOCK 1 ;u Character after word
LASTCC: BLOCK 1 ;u Last char read by GCH.
WORDBP: BLOCK 1 ;u Pointer into word string storage
WORDBF: BLOCK 40 ;u Word storage
EWORDB==.-1
GCHSAV: BLOCK 1 ;u Saved char (ESC) to read at GCH, or 0
TSINIX: BLOCK 1 ;u Initial count for TSIN routine
WRDBPS: BLOCK 1 ; Beginning of current word/string
CMDIC: BLOCK 1 ;u Input line count, >=0
CMDIP: BLOCK 1 ;u Input line pointer, POINT 7,LINBF
CMDIS: BLOCK 1 ;u Input line space, free <= 5*NLINBF
RDTTYC: BLOCK 1 ;u Control-R text address for RDTTY
SBP: BLOCK 1 ;s Byte pointer as command is scanned
CMDIB: BLOCK LCMDIB ; The TELNET line collected from net
REPLYP: BLOCK 1 ;s Pointer to reply being built
REPLYM: BLOCK LREPLY ;s And answer being built for reply
USERBF: BLOCK 20 ;u User name
EUSRBF==.-1
PASSBF: BLOCK 20 ;u Password
EPASBF==.-1
ACCTBF: BLOCK 20 ;u Account
EACTBF==.-1
PREFIX: BLOCK 1 ;u Flag there is a prefix
SUFFIX: BLOCK 1 ;u Flag there is a suffix
PREFXB: BLOCK 40 ;u String storage for prefix and suffix
SUFFXB: BLOCK 40
FRNPTH: BLOCK 40 ;u Foreign pathname
EFRNPT==.-1
FRNPT2: BLOCK 40 ;u Second foreign path (RENAME)
EFRNP2==.-1
SUBTTL Variables Used by XGTJFN to Parse Filespecs
; PARSE block
JBLOCK: ;s Arg block for long GJTFN
GTJBLK: BLOCK 20;1+.GJJFN+.GJRTY-.GJJFN ; Long GTJFN control block
EJBLOK==.-1
GTJBKE==.-1 ; Last word in block
FJFNS: BLOCK 1 ; Fields specified flag word
LGJDEV==10
GTJDEV: BLOCK LGJDEV ; Device string
LGJDIR==20
GTJDIR: BLOCK LGJDIR ; Directory string
LGJNAM==10
GTJNAM: BLOCK LGJNAM ; Name string
GTJEXT: BLOCK 10 ; Type string
GTJGEN: BLOCK 1 ; Pointer to position of generation #
LGJPRO==10
GTJPRO: BLOCK LGJPRO ; Protection string
LGJACT==10
GTJACT: BLOCK LGJACT ; Account string
FILTMP: BLOCK 1 ; -1 if ;T, 0 otherwise
FILSIZ: BLOCK 1 ; File size
FILTCR: BLOCK 1 ; Time file created
FILTWR: BLOCK 1 ; Time file last written
FILTRD: BLOCK 1 ; Time file last referenced
LFLUCR==10
FILUCR: BLOCK LFLUCR ; User name of creator
LFLUWR==10
FILUWR: BLOCK LFLUWR ; User name of last writer
GTJEND: BLOCK 1 ; (Unused)
; End of PARSE block
GTJLCL: BLOCK GTJEND+1-GTJBLK ; PARSE block for local filespec
GTJSTR: BLOCK 60 ; Space to build a filename string
; .GE. MAX(TENEX=25,101B=30,TOPS-20=.FBLEN)
FDBBLK: BLOCK 50 ; Area to hold an FDB
FDBTM1: BLOCK 10 ; Times
FDBTM2: BLOCK 10
FDBTM3: BLOCK 10
FDBUS0: BLOCK 10 ; User names
FDBUS1: BLOCK 10
FDBBKE==.-1 ; End for BLT to clear
STATMP: BLOCK 2 ;u Values returned by STAT JSYS
RETVER: Z ;#4 FLAG WORD FOR VERSION NUMBER
SUBTTL Mail Information & TELNET Receiver & Pages for PMAPs
MLDIR: BLOCK 1 ;s Directory number of mail recipient
MLUSR: BLOCK 1 ;s User number of mail recipient
MLUNWD=20 ;s Note only first 10 go to forwarder
MLUNST: BLOCK MLUNWD+1 ;s Name of unknown mail addressee
ACTACS: BLOCK 20 ;s AC storage for forwarder fork
MLFWST: BLOCK 30 ;s Name for forwarding
LOGJFN: BLOCK 1 ;s JFN of log file for pmapping mail stat
MALCPU: BLOCK 1 ;s More metering
MLTIMT: BLOCK 1 ;s Temp for GMT time computation
TRBITS: BLOCK 1 ;s Bits recv'd in mail (cumulative, never used)
REPEAT 0,<
ONLNPT: BLOCK 1 ; AOBJN ptr into ONLNTB
$OLNTL==10 ; Max # TTY's can XSEN to
ONLNTB: BLOCK $OLNTL ; Table of TTY's user is logged onto
MSGBPT: BLOCK 1 ; Byte ptr into buffer
MSGLNS: BLOCK 1 ; # lines in XSEN buffer
MLERRC: BLOCK 1 ; Error code returned by WRTSND
MSGCNT: BLOCK 1 ; # chars left in buffer
> ; End of REPEAT 0
; User TELENT receiver fork
RCVLIN: BLOCK 100 ;u Space for the incoming TELNET line
ERCVLN==.-1 ;u End of same
RCVLST: BLOCK 101 ;u Last TELNET line received
TNRSSS: BLOCK 1 ;u TELNET state
REPCOD: BLOCK 1 ;u Reply code as a number
REPIDX: BLOCK 1 ;u And index into reply tables
LOC <<<.+777>/1000>*1000>
TPAG: BLOCK 2000 ; Catches GTJFN echos (-FTP-ECHO.TMP)
WINDOW: BLOCK 2000 ; File window.
WINDW2: BLOCK 2000 ; Pages for expanding 32/36 images
BLTADR: BLOCK 1000 ;s Page for mapping mailbox forwarder
BLTPAG==BLTADR/1000 ;s Becomes page 0 of MAILBOX.EXE/SAV
; 140-147 ASCIZ Name (In/Out), 150-157 ASCIZ Host (Out)
;MSGBUF:BLOCK 2000 ; Room for collecting message txt
;$MBFLN==2000*5 ; # Chars to fit in buffer
IFN .&777,<PRINTX Storage not on page boundaries!!!>
PSTOP==.
'END' ; Convince loader to put symbols above here
LOC LSTOP
LIT ; Shouldn't be any
LSTOP==.
END GO