Google
 

Trailing-Edge - PDP-10 Archives - BB-H138D-BM - 5-1-sources/ftp.mac
There are 5 other files named ftp.mac in the archive. Click here to see a list.
; UPD ID= 2, SNARK:<5.ARPA-UTILITIES>FTP.MAC.5,  28-Oct-81 13:47:47 by PAETZOLD
; UPD ID= 2115, SNARK:<5.ARPA-UTILITIES>FTP.MAC.4,   2-Jun-81 12:42:07 by PAETZOLD
; TCO 5.1358 Convert to extended leaders (finally)
; Change CVHST calls to GTHST calls
; Use GTHST for host number not hostn
; Build routine to simulate GDSTS jsys for extended hosts
; Change ICP timeout from 100 to 30 seconds
; Update version and copyright information
; UPD ID= 1141, SNARK:<5.ARPA-UTILITIES>FTP.MAC.3,   8-Oct-80 14:25:57 by LYONS
; Add code to turn on our privs.
; UPD ID= 668, SNARK:<5.ARPA-UTILITIES>FTP.MAC.2,  16-Jun-80 19:12:03 by LYONS
; FIX AC PROBLEM BETWEEN FTP AND MACSYM SAVEAC CODE
;<4.ARPA-UTILITIES>FTP.MAC.8, 11-Oct-79 11:32:02, Edit by LCAMPBELL
; Update version and edit numbers for release 4
;<4.ARPA-UTILITIES>FTP.MAC.7, 10-Oct-79 11:40:15, Edit by LCAMPBELL
; Recognize TOPS20 sites as PDP10s (assume 36-bit paged xfers)
;<4.ARPA-UTILITIES>FTP.MAC.6, 19-Jul-79 00:34:59, Edit by LCAMPBELL
;<4.ARPA-UTILITIES>FTP.MAC.5, 18-Jul-79 22:07:33, Edit by LCAMPBELL
; In BYE cmd, wait for reply before closing connections
; DISCONNECT will now force the close without waiting
;<4.ARPA-UTILITIES>FTP.MAC.4, 10-Jul-79 18:34:08, Edit by LCAMPBELL
; Also leave B19 zero, it now has meaning
;<4.ARPA-UTILITIES>FTP.MAC.3, 23-Apr-79 18:44:08, Edit by LCAMPBELL
; Leave DEC-reserved bit (B18) zero on SFMODs
;<4.ARPA-UTILITIES>FTP.MAC.2,  9-Jan-79 13:58:46, Edit by LCAMPBELL
; Update copyright notice
;<3.ARPA-UTILITIES>FTP.MAC.4, 14-Nov-77 10:17:37, EDIT BY CROSSLAND
;CORRECT COPYRIGHT NOTICE
;<3.ARPA-UTILITIES>FTP.MAC.3, 26-Oct-77 02:36:05, EDIT BY CROSSLAND
;UPDATE COPYRIGHT FOR RELEASE 3
;<3.ARPA-UTILITIES>FTP.MAC.2,  5-Oct-77 00:00:07, EDIT BY CROSSLAND
;ALLOW FOR ERROR RETURN AFTER RFBSZ JSYS
;<A-UTILITIES>FTP.MAC.2, 23-Nov-76 14:38:45, EDIT BY CLEMENTS
; FIX TO RDTTY LOGIC
;<2MURPHY>FTP.MAC.11, 22-Sep-76 14:41:53, EDIT BY CLEMENTS
;fix to allow psi to superior
;<2MURPHY>FTP.MAC.10, 15-Sep-76 17:54:17, EDIT BY MURPHY
; FIX FOR LACK OF A PMF IN RMAP IN MAKFRK
;<2MURPHY>FTP.MAC.5,  9-Sep-76 13:47:00, EDIT BY MURPHY
;FIX PMAPS WITH AC3 NOT SET, FOR TOPS20, AND A COUPLE EOL'S
;<2MURPHY>FTP.MAC.2, 16-Jul-76 17:17:22, EDIT BY MURPHY
;CHANGE STENEX TO MONSYM,MACSYM
;<SOURCES>FTP.MAC;8    21-JUL-75 12:56:22    EDIT BY CLEMENTS
; CHANGE TO DEFAULT NO STATISTICS
; CLEAR DEFAULT TYPE BEFORE OPENING CONNECTION TO A NEW HOST.
;  THIS SO TENEX THEN IBM SITE DOESN'T SAY 8-BIT PAGED XFERS.
;<SOURCES>FTP.MAC;7    24-JUN-75 17:19:50    EDIT BY CLEMENTS
; PUT IN CHECK FOR OPEN CONNECTION ON ACCT, QUOTE, CWD CMDS
;<SOURCES>FTP.MAC;6     2-JUN-75 14:11:38    EDIT BY CLEMENTS
;<SOURCES>FTP.MAC;5    12-MAR-75 00:03:55    EDIT BY CLEMENTS


;This software is furnished under a license and may only be used
;  or copied in accordance with the terms of such license.
;
;Copyright (C) 1976,1977,1978,1979,1980,1981 by
;Digital Equipment Corporation, Maynard, Mass.


	TITLE FTP - User half of the File Transfer Protocol

	SALL
	.DIRECT FLBLST
	.REQUIRE SYS:MACREL

VWHO==0			;LAST EDITED BY DEC
VMAJOR==5		;MAJOR VERSION #
VMINOR==0		;REVISION #
VEDIT==^D31		;EDIT NUMBER

	LOC	<.JBVER==137>
VERSIO:	<VWHO>B2+<VMAJOR>B11+<VMINOR>B17+VEDIT ;VERSIONS FOR TYPEOUT
	RELOC

SEARCH MONSYM,MACSYM

;AC DEFINITIONS

F=0	;FLAGS
A=1	;A-D ARE TEMPS FOR JSYSES
B=2
C=3
D=4
T1=10		;VERY TEMP
T2=11		; ..
X=12	;MESSAGE POINTER
BP=15
P=17	;STANDARD STACK

;FLAGS IN AC F

R.NTIC==1		;COUNTER FOR NETWORK INTERRUPTS VS TIMEOUT.
R.MATC==2		;MATCH IN COMMAND SCANNER
R.AMB==4		;AMBIGUOUS COMMAND
R.LCUC==10		;LOWER CASE TO UPPER IN WORD COLLECTOR
R.HDX==20		;HALF DUPLEX CONSOLE FOR PRIMARY I/O
R.IMG==40		;IMAGE MODE BIT SHUFFLING REQUIRED
R.HCOM==100		;COMMAND SCANNER WILL ACCEPT HOST NAME AS WORD
R.HCM1==200		;WORD SCANNER TRIED HOST NAMES
R.CHOK==400		;A GOOD CHARACTER SEEN IN NUMERIC INPUT ROUTINE
R.SPTC==1000		;SPACE IS A TERM, NOT DATA, IN TSIN ROUTINE
R.APPE==2000		;APPEND VERSUS SEND COMMAND
R.ABOR==4000		;DATA XFR ABORTED
R.NOEC==10000		;MASKING PASSWORD
R.QUOC==20000		;CONTROL V LAST CHAR IN
R.RNIL==40000		;RECEIVE SIDE GOING TO NIL:
R.KJFN==100000		;KEEP LOCAL JFN AFTER CWFORK
R.MAIL==200000		;mail file flag in send routine
R.DSK==400000		;LOCAL FILE IS ON DSK
L.TYPX==1		;TRANSFER IS PAGED MODE
L.TMP1==2		;TEMP FLAG. USED IN NAME PARSING IN MGET

DEFINE CLOSE (JFN)<
	MOVEI A,JFN
	PUSHJ P,CLOSER
>
DEFINE CLOSK (JFN)<
	MOVEI A,JFN
	PUSHJ P,CLOSEK
>
;FINITE STATE MACHINE PARAMETERS
;STATE CODES

FSDEAD==0
FSCLZD==1
FSPNDG==2
FSLSNG==3
FSRFCR==4
FSCLW2==5
FSRFCS==6
FSOPND==7
FSCLSW==10
FSDATW==11
FSRFN1==12
FSCLZW==13
FSRFN2==14
FSKILD==15
FSFREE==16

;OPERATING SYSTEM PARAMS IN HOST TABLE (1.30 OR LATER)

SERVER==1B0		;SITE IS A SERVER
USER==1B1		;SITE IS A USER
NICKNM==1B2		;NAME IS A NICKNAME
OPS10X==1B8		;SYSTEM RUNS TENEX
OPSITS==2B8		;SYSTEM RUNS I.T.S
OPST10==3B8		;SYSTEM RUNS SOME KIND OF DEC TOPS10 MONITOR
OPSTIP==4B8		;SITE IS A TIP
OPSMTT==5B8		;SITE IS A MAG-TAPE TIP
OPSELF==6B8		;ELF
OPSANT==7B8		;ANTS
OPSMLT==10B8		;Multics
OPST20==11B8		;TOPS-20
OPSUNX==12B8		;Unix

EOL==37		;TENEX END OF LINE ON INPUT
C.ESC==33
C.LF==12
C.CR==15
C.HRLD=="*"		;THE HERALD FOR TYPEIN
C.SRVH==74		;"LESS-THAN" PREFIXES SERVER OUTPUT
CDELLN=="U"-100			;INTERNAL CODE MEANING COMMAND DELETED

FREPAG==100		;PAGE OF FREE STORAGE
			;GETS HOST GETAB DATA
DEFINE PS(A,B)<A=PSPC
PSPC==PSPC+B>
DEFINE GS(A,B)<A=GSPC
GSPC==GSPC+B>

;BASE OF PROCESS AND GLOBAL TEMPS. GLOBAL FIRST.

GSBAS==200000
GSPC==GSBAS
PSBAS==300000
PSPC==PSBAS

GS WINDOW,2000		;FIRST, TO GET ON A PAGE BOUNDARY. FILE WINDOW.
GS WINDW2,2000		;AND A COUPLE PAGES FOR EXPANDING 32/36 IMG

;MACROS AND PARAMETERS

DEFINE MSG (XMSG)<
	HRROI A,[ASCIZ \XMSG\]
	PSOUT
>
DEFINE VMSG (XMSG)<
	PUSH P,A
	HRROI A,[ASCIZ \XMSG\]
	SKIPE F.VBOS		;VERBOSE TYPEOUT?
	PSOUT
	POP P,A
>
DEFINE NOISE (XMSG)<
	HRROI A,[ASCIZ \XMSG\]
	MOVE C,BREAKC
	CAIN C,C.ESC
	PSOUT
>

DEFINE ND (X,Y)<
IFNDEF X,<X==Y>>

ND PDLL,100		;STACK LENGTH
ND FTPICS,3		;PROTOCOL ICP SOCKET FOR FTP
ND USRSKN,100		;USER SOCKET NUMBER U BEFORE JOB-XLATION
ND DWTIME,^D120		;SECONDS TO WAIT FOR DATA CONNECTION
ND LFDB,25		;LENGTH OF FDB OF DSK FILE

ND DEBUG,1		;DEBUGGING CODE ASSEMBLY SWITCH
;START OF PROGRAM. INITIALIZE STUFF.

GO:	RESET			;CLEAR STUFF IN SYSTEM
	MOVEI A,.FHSLF		;OUR PROCESS
	RPCAP			;GET OUR POSSIBLE PRIVS
	MOVE C,B		;MAKE THE OUR ACTUAL PRIVS
	EPCAP			;ASK FOR THEM
	MOVEI F,0		;ALL FLAGS OFF
	MOVE P,GPDP		;INITIAL STACK POINTER
	MOVEI A,100		;SET UP PARAMS ABOUT USER CONSOLE
	RFMOD			;SEE WHAT IT IS
	MOVEM B,IRFMOD		;STORE IT
	TRNE B,3B33		;FULL OR HALF DUPLEX?
	TRO F,R.HDX		;HALF.
	RFCOC			;SEE WHAT THE ECHOING IS
	TLZ B,(3B3)		;TURN OFF ^A
	TDZ C,[3B13!3B19]	;AND ^X AND ESC
	MOVEM B,FCOCB		;SAVE THEM
	MOVEM C,FCOCC		; ..
	SFCOC			;AND SET THEM IN SYSTEM
	SETOM DFORKH		;NO INFERIORS YET.
	SETOM RFORKH		; ..
	SETOM SFORKH		; ..
	SETZM PREFIX		;NO PARTIAL FILE NAMES YET
	SETZM SUFFIX		; ..
	MOVEI A,FREPAG*1000	;FREE STORAGE
	MOVEM A,FREE		;BASE TO POINTER
	MOVE A,['HOSTN ']
	MOVEI B,HOSTN		;TABLE POINTER
	PUSHJ P,SYSGET		;GET TABLE FROM SYSTEM
	MOVE A,['HSTNAM']
	MOVEI B,HSTNAM		;ANOTHER ONE
	PUSHJ P,SYSGET
	MOVE X,HOSTN		;MAKE POINTERS TO THE ASCIZ
	HRRZ A,HSTNAM		;BY ADDING ON TABLE BASE
	ADDM A,(X)		;TO EACH WORD IN HOSTN TABLE
	AOBJN X,.-1		; ..
	SETOM F.HELP		;HAVENT TYPED DUMMY MSG YET
	SETZM F.TOPN		;NO CONNECTION NOW OPEN
	SETZM F.TCLS		;AND NO REQUEST TO CLOSE IT
	SETOM F.NST1		;NO STATISTICS COMMAND YET
	SETZM F.VBOS		;NO VERBOSE COMMAND YET EITHER
	SETOM PARAMS		;CLEAR ALL TRANSMISSION PARAMETERS
	MOVE A,[PARAMS,,PARAMS+1]
	BLT A,EPARAM		;TO "DEFAULT - UNSPECIFIED".
	MOVE A,[PARAMS,,PARAM2]	;AND COPY THEM TO OTHER TWO GROUPS
	BLT A,PARAM2+NPARS-1
	MOVE A,[PARAMS,,PARAM3]
	BLT A,PARAM3+NPARS-1
;FALL THRU
GO01:
	MOVEI A,.GTHSZ		;LOCAL HOST INFO FUNCTION
	GTHST%			;GET INFO ON US
	 ERJMP HALTGO		;CANT FAIL
	MOVEM D,LHOSTN		;SAVE OUR HOST NUMBER
	MOVEI A,.GTHNS		;HOST NAME FUNCTION
	HRROI B,LHSTNM		;DESTINATION POINTER
	MOVE C,LHOSTN		;GET THE HOST NUMBER
	GTHST%			;GET PRIMARY HOST NAME STRING
	 ERJMP [MOVE A,[ASCII/Site /] ;THIS JUST HAPPENS TO FIT
		MOVEM A,LHSTNM	;SAVE THE FIRST WORD OF STRING
		HRROI A,LHSTNM+1 ; GET BYTE POINTER
		MOVE B,LHOSTN	;HOST NUMBER
		MOVEI C,10	;IN BASE 8
		NOUT		;OUTPUT THE HOST NUMBER
		 ERCAL BOMB	;DEATH ON ERRORS
		JRST .+1]	;CONTINUE WITH FLOW
	HRROI A,LHSTNM		;SIGN ON MESSAGE
	PSOUT
	HRROI A,[ASCIZ / FTP User process /]
	PSOUT
	LDB B,[POINT 9,VERSIO,11] ;GET MAJOR VERSION
	MOVEI A,101		;TYPE VERSION
	MOVEI C,10		;OCTAL NUMBERS
	SKIPE B			;PRINT IF NON-ZERO
	NOUT
	  JFCL
	LDB B,[POINT 6,VERSIO,17] ;GET MINOR VERSION
	JUMPE B,VERSI1		;SKIP IF 0
	SUBI B,1
	IDIVI B,^D26		;MAKE 2 LETTERS
	JUMPE B,VERSI0		;ANY FIRST LETTER?
	HRRZI B,"A"-1(B)	;YES, PRINT
	BOUT
VERSI0:	HRRZI B,"A"(C)		;PRINT SECOND LETTER
	BOUT
VERSI1:	HRRZ B,VERSIO		;GET EDIT NUMBER
	MOVEI C,10		;OCTAL NUMBERS
	JUMPE B,VERSI2		;SKIP IF EDIT IS 0
	MOVEI B,"("		;PRINT OPEN PAREN
	BOUT
	HRRZ B,VERSIO		;GET EDIT NUMBER AGAIN
	NOUT			;PRINT IT
	  JFCL
	MOVEI B,")"		;PRINT CLOSE PAREN
	BOUT
VERSI2:	LDB B,[POINT 3,VERSIO,2] ;GET GROUP CODE
	JUMPE B,VERSI3		;SKIP IF ZERO
	MOVEI B,"-"		;PRINT -
	BOUT
	LDB B,[POINT 3,VERSIO,2] ;GET GROUP CODE
	NOUT
	  JFCL
VERSI3:	MOVE A,[7,,CGICHN]	;CHANNEL FOR BELL INTERRUPT
	ATI
	MOVE A,[17,,COICHN]	;AND CONTROL O
	ATI
	MOVEI A,400000		;SET UP PSI FOR THIS FORK
	MOVE B,[LEVTAB,,CHNTAB]		;INT VECTORS
	SIR
	EIR
	MOVE B,CHNMSK
	AIC
;FALL INTO COMMAND READER
CRCOM:	MOVEI A,101		;TRY TO PREVENT MIXING TTY LINES
	DOBE			; ..
	RFPOS
	HRRZ B,B		;GET LINE POSITION
	JUMPE B,COMMAN		;JUMP IF AT LEFT MARGIN
	HRROI A,CRLFM
	PSOUT			;CARRIAGE RETURN AND COMMAND INPUT
COMMAN:	MOVEI A,101		;TRY TO PREVENT MIXING TTY LINES
	DOBE			; ..
	MOVEI A,100		;SET WAKE SET FOR NON-ALPHAS
	RFMOD
	TRZ B,1B23
	TRO B,16B23		;WAKE ON CONTROLS AND PUNCT
	SFMOD			; ..
	MOVEI A,"*"		;PROMPT CHARACTER
	PBOUT
	SETOM F.STAR		;NOTE AM AT COMMAND INPUT
	MOVE P,GPDP		;JUST IN CASE
	TRZ F,R.KJFN		;CLEAR FOR ALL CASES EXCEPT .MGET
;;;THIS SHOULD BE PROVOKED BY INT.
	SKIPE F.TCLS		;REQUEST TO CLOSE CONNECTION?
	PUSHJ P,TCLOS1		;YES. DO SO.
	PUSHJ P,GCHINI		;START OF LINE
	MOVE X,COMTBX		;INDEX TO COMMAND KEYWORDS
	MOVEM X,WORDXP		;TO ARG CELL OF GETWRD
	SKIPN F.TOPN		;UNLESS A CONNECTION IS OPEN,
	TRO F,R.HCOM		;A HOST NAME IS OK AS COMMAND
	PUSHJ P,GETWRD		;GET A WORD (LC = UC)
	  JRST BLANKQ		;MAY BE BLANK LINE
	JRST COMOK		;ALL RIGHT. DISMISS TO IT.

BLANKQ:	MOVE A,BREAKC	;WHAT WAS THE BREAK?
	CAIN A,"?"		;HELP REQUEST?
	JRST [	PUSHJ P,HLPCOM	;YES, DO IT
		 JFCL
		JRST CRCOM]	;DONE
	CAIN A,CDELLN	;LINE DELETED?
	JRST XXXCOM	;YES
	CAIE A,C.LF	;LF OR ESC ARE BLANKS
	CAIN A,C.ESC
	JRST CRCOM	;TREAT AS BLANKS
	CAIN A,";"	;COMMENT?
	JRST COMMNT	;YES
	JRST DUMMY	;NO. ERROR

XXXCOM:	MOVE P,GPDP		;RESET STACK
	JRST CRCOM

COMMNT:	MOVEI BP,0		;CHARS TO BIT BUCKET
	MOVEI X,777777		;AND ITS A BIG BUCKET
	PUSHJ P,TSIN1		;READ REST OF COMMNT LINE
	  JRST XXXCOM		;RUBOUT?
	JRST COMMAN		;TYPE STAR.
NOTIMP:	MSG <
UNIMPLEMENTED COMMAND >
	HRROI A,WORDBF
	PSOUT
DUMMY:	MOVE P,GPDP		;JUST IN CASE
	MOVEI A,100		;BACK TO STANDARD ECHOING
	MOVE B,FCOCB		;..
	MOVE C,FCOCC
	SFCOC
	HRROI A,[ASCIZ /
? Type "HELP<RETURN>" for help./]
	AOSE F.HELP
	HRROI A,[ASCIZ /
?ERROR IN COMMAND./]
ERRCOM:	PUSH P,A
	MOVEI A,100
	DOBE			;CLEAR TYPEAHEAD
	CFIBF
	POP P,A
	PSOUT
	JRST CRCOM		;AND TRY AGAIN

COMOK:	SETZM F.NOST		;ASSUME WILL WANT TIMING STATISTICS
	SKIPE F.TCLS		;REQUEST TO CLOSE CONNECTION?
	PUSHJ P,TCLOS1		;YES. DO SO.
	MOVEI A,100		;OK, TURN CONTROL ECHOING BACK ON
	MOVE B,FCOCB
	MOVE C,FCOCC
	SFCOC
	SKIPGE C,RECX		;GET THE COMMAND INDEX
	JRST DUMMY		;NONE
	TRZE F,R.HCM1		;WAS COMMAND A HOST NAME?
	JRST .HOST1		;YES. BACK DOOR INTO HOST ROUTINE
	HLRZ C,COMTB2(C)	;GET ROUTINE TO HANDLE IT
	PUSHJ P,0(C)		;GO TO IT
	  JRST DUMMY		;FAILURE.
	JRST COMMAN		;GET NEXT COMMAND
;GET WORD ROUTINE. LOOKS UP COMMANDS AND ARGS, COLLECTS TEXT.
;CALL: WORDXP/ -N,,TABLE OF ASCIZ ADDRESSES, OR 0 IF NONE
;FAIL RETURN IF NOT A UNIQUE WORD AND WORDXP WAS NON-0, OR IF
;RUBOUT TYPED.
;GOOD RETURN WITH RH X/ OFFSET INTO WORD POINTERS

GETWLC:	TRZA F,R.LCUC		;ENTRY FOR LC LEFT ALONE
GETWRD:	TRO F,R.LCUC		;ENTRY FOR UC = LC
GETW01:	SETZM WORDBF		;CLEAR WHERE WORD READ INTO
	MOVE A,[WORDBF,,WORDBF+1]
	BLT A,EWORDB		;CLEAR IT
	MOVE A,WRDBP0		;INITIAL BYTE PTR TO IT
	MOVEM A,WORDBP		; ..
	TRZ F,R.HCM1		;THIS WORD IS NOT A HOST NAME (YET)

GETWL1:	PUSHJ P,GCH		;GET A CHARACTER
	  JRST GETWBK		;BREAK CHAR
	SETZM F.STAR		;NOT AT LEFT MARGIN ANY MORE
	TRNN F,R.LCUC		;CONVERT LC TO UC?
	JRST GETW02		;NO
	CAIL C,141		;YES. LC?
	CAILE C,172
	SKIPA			;NO
	TRZ C,40		;YES. MAKE UC
GETW02:	IDPB C,WORDBP		;ADD TO STRING STORAGE
	JRST GETWL1		;AND READ SOME MORE

GETWBK:	SETZM F.STAR		;NOT AT LEFT MARGIN NOW
	MOVEM C,BREAKC		;SAVE THE BREAK
	CAIN C,CDELLN		;RUBOUT?
	JRST XXXCOM		;YES, FLUSH COMMAND
GETWEW:	PUSHJ P,RECOG		;ASSUME TERM OK. RECOGNIZE THE WORD.
	  POPJ P,0		;BLANK INPUT
	  JRST GTWEWD		;NOT A UNIQUE WORD. DING.
	SETZM WORDXP		;FORCE NEXT CALLER TO DECLARE HIS TABLE
	JRST CPOPJ1		;GOOD. RETURN IT. X/ GOOD POINTER OR 0,
				;  AND BREAK CHAR IN BREAKC
   REPEAT 0,<
GTWDCH:	MOVE BP,WORDBP		;AT START OF WORD?
	CAMN BP,WRDBP0		; ..
	JRST GTWDNG		;YES. NO MORE TO DELETE
	MOVEI A,"\"		;NO. DO SOME RUBBING OUT
	PBOUT			;FLAG DELETED CHAR
	LDB A,WORDBP		;TYPE IT OUT
	PBOUT
	MOVEI A,0		;REMOVE IT FROM BUFFER
	DPB A,WORDBP		; ..
	MOVSI A,070000		;BACK UP POINTER
	ADD A,WORDBP		; ..
	SKIPGE A
	SUB A,[430000,,1]	; ..
	MOVEM A,WORDBP		;NEW POINTER
	JRST GETWL1		;GET ANOTHER CHARACTER
   >				;REPEAT 0

GTWDNG:	MOVEI A,7		;BELL
	PBOUT
	JRST GETWL1		;READ MORE

   REPEAT 0,<
GTWDW:	HRROI A,[ASCIZ /_
/]
	PSOUT
	JRST GETW01		;RIGHT BACK TO TOP.
   >				;REPEAT 0

GTWEWD:	MOVE A,BREAKC		;WAS RECOGNITION REQUESTED?
	CAIE A,C.ESC		; ..
	JRST GTWEW1		;NO.
	TRNE F,R.AMB		;AMBIGUOUS OR UNKNOWN?
	JRST GTWDNG		;AMBIG. DING AND READ ON.
GTWEW1:	HRROI A,[ASCIZ / ? /]	;UNKNOWN. COMPLAIN.
	PSOUT
	POPJ P,0		;FAIL RETURN
;COULD BE JRST GETW01 BUT FOR .HOST SECOND ENTRY... FIX?
RECOG:	SKIPN X,WORDXP		;IS THERE A TABLE TO TRY?
	  JRST CPOPJ2		;NO. GOOD RETURN THEN.
	SETOM RECX		;YES. CLEAR INDEX TO NONE
	MOVE A,WRDBP0		;WAS THERE ANY INPUT?
	CAMN A,WORDBP		; ..
	POPJ P,0		;NO. NON-SKIP RETURN
	TRZ X,-1		;CLEAR TO A COUNTER IN RH
	TRZ F,R.AMB!R.MATC	;CLEAR MATCH COUNTERS
RECGL1:	MOVE A,WRDBP0		;START OF WORD BUFFER
	MOVE B,X		;MAKE A POINTER TO A TEST WORD
	ADD B,WORDXP		;WORD ADDRESS OF CURRENT TEST WORD
	MOVE B,(B)		; ..
	HRLI B,440700		;AND POINTER LH
RECGL2:	ILDB C,A		;CHAR FROM INPUT
	ILDB D,B		;CHAR FROM LITERAL
	CAME C,D		;MATCH?
	JRST RECOG1		;NO.
	JUMPN C,RECGL2		;YES. LOOP IF NOT END OF WORD
	HRRZM X,RECX		;MATCHED TO END. SAVE INDEX.
	TRO F,R.MATC		;A MATCH,
	TRZ F,R.AMB		;AND EXACT ISN'T AMBIGUOUS
	JRST CPOPJ2		;GOOD RETURN.

RECOG1:	JUMPN C,RECOG2		;NOT A MATCH. TYPEIN DONE?
	HRRZM X,RECX		;YES. MATCHED TO END OF TYPEIN.
	TROE F,R.MATC		;AT LEAST ONE MATCH
	TRO F,R.AMB		;MORE THAN ONE. AMBIGUOUS.
RECOG2:	AOBJN X,RECGL1		;TRY ALL TEST WORDS.
	TRNE F,R.MATC		;A MATCH AT ALL?
	JRST RECOG3		;YES. DON'T TRY HOST NAMES
	MOVE A,HOSTN		;POINTER TO HOST NAMES
	CAME A,WORDXP		;IS THAT WHAT WE SEARCHED?
	TRNN F,R.HCOM		;NO. SHOULD WE?
	JRST RECOG3		;DON'T DO HOST SEARCH
	MOVEM A,WORDXP		;YES. SET TO SEARCH IT.
	HLLZ X,A		;SET UP COUNTER
	TRO F,R.HCM1		;FLAG HAVE NOW TRIED HOST TABLE.
	JRST RECGL1		; DO SO.

RECOG3:	TRNE F,R.MATC		;GOOD RETURN IF NON-AMBIG MATCH
	TRNE F,R.AMB
	JRST CPOPJ1		;NOT A GOOD ANSWER. ONE SKIP.
	MOVE X,RECX		;GET THE ANSWER
CPOPJ2:	AOS 0(P)		;OK. DOUBLE SKIP RETURN
	JRST CPOPJ1		; ..
GCHINI:	SETZM GCHSAV		;NO SAVED CHARACTER
	PUSHJ P,LINCLR		;CLEAR LINE BUFFER
	POPJ P,0		;RETURN

GCH:
GCHSVQ:	SKIPE C,GCHSAV		;ANY SAVED CHARACTER?
	JRST GCH01		;YES. RETURN IT.
GCHTYI:	PUSHJ P,TYI		;GET A TYPED IN CHARACTER
	CAIN C,C.ESC		;ESCAPE?
	JRST GCHESC		;YES.
	CAIE C,0		;FLUSH OUT NULLS AND CR'S
	CAIN C,15
	JRST GCH
	CAIN C,14		;FOR NOW, ^L IS LF.
	MOVEI C,C.LF
	JRST GCHRET		;RETURN THE CHARACTER

GCH01:	SETZM GCHSAV		;NO LONGER A SAVED CHAR
GCHRET:	MOVEM C,LASTCC		;SAVE CHARACTER
BREAKQ:	CAIL C,141		;RETURN CHAR, SKIP UNLESS BRK.
	CAILE C,172
	SKIPA
	JRST CPOPJ1		;LOWER CASE LETTER
	CAIL C,101
	CAILE C,132
	SKIPA
	JRST CPOPJ1		;UPPER CASE LETTER
	CAIL C,60
	CAILE C,71
	SKIPA
	JRST CPOPJ1		;DIGIT
	CAIE C,"."
	CAIN C,"-"
	JRST CPOPJ1		;LEGAL PUNCTUATION
	POPJ P,0
GCHESC:	MOVEM C,GCHSAV		;RETURN THE ESC LATER
	PUSHJ P,RECOG		;SEE IF A WORD MATCHES
	  JRST GCH		;NO NON-BREAKS AT ALL. RETURN BREAK
	  JRST GCH02		;NO.
	SKIPN WORDXP		;IF NO TABLE,
	JRST GCH		;RETURN THE ESC AS A TERM.
	JUMPE D,GCH		;AND IF MATCHED TO END, ALSO RETURN ESC
	MOVE C,WRDBP0		;START OF WORD TYPED IN
	MOVEI B,"?"		;MAKE SURE B NON-ZERO
	MOVE D,RECX		;THE MATCHING INDEX
	ADD D,WORDXP		;POINTER TO WORDS
	MOVE D,(D)		;THE TEXT ADDRESS
	HRLI D,440700		;START OF GOOD WORD
GCHESL:	ILDB A,D		;LITERAL CHAR
	JUMPE A,GCHES2		;QUIT AT END OF ASCIZ
	SKIPE B			;RUN OUT OF INPUT?
	ILDB B,C		;NO. GET ANOTHER INPUT CHAR
	JUMPN B,GCHES1		;IF NOT TO END, DON'T FAKE TYPEIN
	PBOUT			;OUTPUT THE LITERAL CHAR
	IDPB A,WORDBP		;AND PUT IT IN TYPEIN BUFFER
;;;	AOS CCHCNT		;COUNT OF SUCH CHARACTERS
GCHES1:	JRST GCHESL		;LOOP TILL END OF LITERAL

GCHES2:	IDPB A,WORDBP		;PUT NULL IN INPUT WORD
	MSG < >
	JRST GCH		;AND RETURN THE ESC

GCH02:	MOVEI A,7		;DOESN'T MATCH. DING.
	PBOUT
	SETZM GCHSAV		;DON'T SEE THE ESC AGAIN
	JRST GCH		;AND READ AGAIN
;COMMAND DEFINITIONS

DEFINE COMS <
CC (<CONNECT>,.HOST,< to host-name or octal-number>)
CC (<LOGIN>,.LOGIN,< username password optional-account>)
CC (<ACCOUNT>,.ACCT,< number or string>)
CC (<GET>,.GET,< REMOTE-FILE to LOCAL-FILE>)
CC (<SEND>,.SEND,< LOCAL-FILE to REMOTE-FILE>)
CC (<MULTIPLE>,.MULT,< GET/SEND. Allows "*", TENEX sites only.>)
CC (<APPEND>,.APPE,< LOCAL-FILE to REMOTE-FILE>)
CC (<RENAME>,.RENAM,< REMOTE-FILE to be NEW-REMOTE-FILE>)
CC (<DELETE>,.DELET,< REMOTE-FILE>)
CC (<DIRECTORY>,.DIREC,< of REMOTE-USER>)
CC (<CWD>,.CWD,< change working directory to NAME>)
CC (<STATUS>,.STATU,< of remote system>)
CC (<MAIL>,.MAIL,< <FILE> to REMOTE-USER>)
CC (<BYTE>,.BYTE,< size of data connection>)
CC (<DISCONNECT>,.DISC,< from remote host forcibly>)
CC (<QUIT>,.QUIT,< returns to EXEC, without closing connection>)
REPEAT 0,<
CC (<PREFIX>,.PREFI,< STRING TO PUT IN FRONT OF FOREIGN FILENAMES>)
CC (<SUFFIX>,.SUFFI,< STRING TO PUT AT END OF FOREIGN FILE NAMES>)
>
CC (<IMAGE>,.IMAGE,< declares image file type>)
CC (<TENEX>,.TENEX,< a shorthand for IMAGE, BYTE 36>)
CC (<PAGED>,.PAGED,< a shorthand for TYPE X, BYTE 36 (TENEX sites only)>)
CC (<ASCII>,.ASC,< a shorthand for TYPE A, BYTE 8>)
CC (<TYPE>,.TYPE,< sets data type>)
CC (<MODE>,.MODE,< sets transmission mode>)
CC (<STRUCTURE>,.STRU,< sets structure of data>)
CC (<VERBOSE>,.VERBOS,< typeout mode>)
CC (<BRIEF>,.BRIEF,< typeout mode>)
CC (<QUOTE>,.QUOTE,< arbitrary-FTP-line>)
CC (<BYE>,.BYE,< closes connection cleanly>)
CC(<STATISTICS>,.STATS,< turns on typeout of timing statistics>)
CC(<NOSTATISTICS>,.NOSTA,< turns off typeout of timing statistics>)
CC (<HELP>,.HELP,< types this information>)
>
COMTB1:	DEFINE CC (WORD,TAG,HELP)<
	EXP [ASCIZ \WORD\]>
	COMS
NCOMS==.-COMTB1
COMTBX:	-NCOMS,,COMTB1		;POINTER TO COMMAND WORDS

IF2,<
DEFINE CC (WORD,TAG,HELP)<
ND TAG,NOTIMP
>
	COMS
>
COMTB2:	DEFINE CC (WORD,TAG,HELP)<
	XWD TAG,[ASCIZ \HELP\]>
	COMS

.BYE:	SKIPE F.TOPN		; if connection exists
	PUSHJ P,SNDBYE		; request the close
	JRST CPOPJ1		; return OK

.DISC:	SKIPE F.TOPN		;IF THERE IS A CONNECTION,
	PUSHJ P,SNDBYE		;SEND A BYE COMMAND ON NET
	PUSHJ P,TCLOS1		; force close of connection
	JRST CPOPJ1		;GOOD RETURN FROM COMMAND.

SNDBYE:	MOVEI A,[0]		;NO BODY OF BYE MESSAGE
	MOVEI B,[ASCIZ /BYE  /]
	PUSHJ P,TELSND		;OUTPUT THE "BYE" COMMAND
	POPJ P,0

.QUIT:	HALTF			;PAUSE
	JRST CPOPJ1		;CONTINUE
.HELP:	MSG <C, E, S or ? >
	MOVEI A,100
	RFMOD
	TRO B,17B23
	SFMOD
	PUSHJ P,LINCLR		;CLEAR LINE BUFFER
	PUSHJ P,TYI		;GET ANSWER
	MOVE A,C		;IT CAME BACK IN C
	CAIN A,CDELLN		;LINE DELETED?
	JRST XXXCOM		;YES
	CAIE A,"C"
	CAIN A,"C"+40
	JRST HLPCOM
	CAIE A,"E"
	CAIN A,"E"+40
	JRST HLPEXM
	CAIE A,"S"
	CAIN A,"S"+40
	JRST HLPSTS
	CAIN A,"?"
	JRST HLPQM
	JRST DUMMY

HLPQM:	MSG <
Type "C" for a list of commands, "E" for a example of FTP use,
or "S" for current status.
>
	JRST .HELP
HLPCOM:	MSG <
 Commands are:
>
	MOVSI X,-NCOMS
HELP01:	HRRO A,COMTB1(X)	;COMMAND KEYWORD
	PSOUT
	HRRO A,COMTB2(X)	;AND HELP TEXT
	PSOUT
	HRROI A,CRLFM		;EOL
	PSOUT
	AOBJN X,HELP01
	MSG <
Type BELL (^G) to abort a file transfer and return to command level.
Type ^O to clear typeout buffer.
Use ^V to quote characters in LOGIN.
>
	JRST CPOPJ1

HLPSTS:	SKIPE F.TOPN		;CONNECTION OPEN NOW?
	JRST HELP02		;YES
	MSG <
There is no connection currently open.>
	JRST HELP03
HELP02:	MSG <
A connection is open to host >
	MOVEI A,.GTHNS		;HOST NAME FUNCTION
	MOVEI B,.PRIOU		;OUTPUT TO TTY
	MOVE C,FHSTN		;GET THE 4N HOST NUMBER
	GTHST%			;OUTPUT THE HOST NAME
	 ERJMP [MOVEI A,.PRIOU	;ON ERROR 
		MOVE B,FHSTN	;GET THE 4N HOST NUMBER
		MOVEI C,10	;IN OCTAL
		NOUT		;OUTPUT THE 4N HOST NUMBER
		 ERCAL BOMB	;ON ERROR DIE
		JRST .+1]	;REJOIN CODE
HELP03:	HRROI A,CRLFM
	PSOUT
	JRST CPOPJ1		;GOOD RETURN FROM HELP COMMAND.

HLPEXM:	HRROI A,HLPEX1		;LONG MESSAGE
	PSOUT
	JRST CPOPJ1

HLPEX1:	ASCIZ /
@FTP		;call in the subsystem
*BBN		;connect to host BBN
*LOG SMITH SECRET 12345		;declare name, password, account
				; the password will not be echoed.
*DIR *.MAC
(to local file) TTY: [confirm]	;get a partial directory listing
*GET PROGRAM.MAC		;must end with carriage return
(to local file) <esc>PROGRAM.MAC  ;escape causes same name to be used
*DISCON			;break the network connections
*QUIT
@
/
;COMMANDS START HERE.
;CONNECT TO HOST COMMAND

.HOST:	SKIPE F.TOPN		;IS TELNET CONNECTION OPEN?
	PUSHJ P,TCLOSE		;YES. CLOSE IT AND ANY DATA.
	NOISE < (to) HOST-NAME or OCTAL NUMBER >
	PUSHJ P,SST1		;SKIP SPACES AND TABS
	CAIL C,"0"		;FIRST CHAR AN OCTAL DIGIT?
	CAILE C,"7"
	SKIPA			;NO
	JRST HOST03		;YES. READ THE HOST NUMBER
	MOVE X,HOSTN		;POINTER TO NAMES OF HOSTS
	MOVEM X,WORDXP		;ARG TO GET WORD
	PUSHJ P,GETWRD		;READ A HOST NAME
	  JRST DUMMY		;BAD NAME
.HOST2:
	MOVE A,HOSTN		;BASE OF TABLE
	ADDI A,0(X)		;ADD IN OFFSET FROM GETWRD
	MOVEM A,HOSTX		;SAVE THIS HANDY INDEX
	MOVEI A,.GTHSN		;HOST STRING TO NUMBER FUNCTION
	HRRZ B,HOSTX		;GET THE HOST NAME INDEX
	HRRO B,(B)		;GET POINTER TO HOST NAME STRING
	GTHST%			;GET HOST NUMBER
	 ERCAL BOMB		;DIE ON ERROR
	 ERCAL BOMB		;ON ERROR DIE
	MOVEM C,FHSTN		;SAVE THE 4N HOST NUMBER
HOST04:				;NOW OPEN THE CONNECTION
	SETOM $TYPE		;ASSUME DEFAULT TYPE
	PUSHJ P,DOICP		;OPEN THE TELNET CONNECTIONS
	  JRST HOST01		;NO GOOD
	MSG < Connection opened.
 Assuming >
	MOVE A,HOSTX		;SEE WHAT TO ASSUME FOR BYTE SIZE
	HLRZ A,0(A)		;GET HOST DESCRIPTOR
	ANDI A,(77B8)		;OP SYS FIELD
	MOVEI B,^D8		;START AT EIGHT
	CAIE A,(OPS10X)		;A TENEX?
	CAIN A,(OPSITS)		;OR A MAC ITS SYSTEM?
	MOVEI B,^D36		;YES. ASSUME 36 BIT
	CAIE A,(OPST20)		; Also for TOPS20
	CAIN A,(OPST10)		;SAME FOR TOPS10 SYSTEMS
	MOVEI B,^D36
	MOVEM B,$BYTE		;STASH THE ANSWER
	MOVEI C,TYPE.I		;AND IMAGE MODE IF 36-BIT.
	CAIE A,(OPST20)		; also TOPS20
	CAIN A,(OPS10X)		;IMAGE IF 36 UNLESS 10X, THEN PAGED.
	MOVEI C,TYPE.X		;PAGED.
	CAIN B,^D36
	MOVEM C,$TYPE
;FALL THRU
;FALLS THRU
	MOVEI A,101		;DECLARE DECISION TO USER TO CHANGE
	MOVEI C,12		; IF HE DOESN'T LIKE IT.
	NOUT
	  JFCL
	MSG <-bit connections>
	MOVE B,$TYPE		;DECLARE PAGED IF SO
	HRROI A,[ASCIZ /, Paged transfers/]
	CAIN B,TYPE.X		; ..
	PSOUT
	HRROI A,[ASCIZ /.
/]
	PSOUT
	PUSHJ P,MAKFRK		;CREATE NEEDED INFERIORS
	  JRST MKFERR		;CAN'T
	MOVEM X,RFORKH		;ONE FOR TELNET RECEIVE
	PUSHJ P,MAKFRK
	  JRST MKFERR
	MOVEM X,DFORKH		;ONE FOR DATA FLOW.
	MOVE A,RFORKH		;RECEIVER HANDLE
	MOVEI B,RFRKSA		;AND STARTING ADDRESS
	SFORK			;START IT.
	JRST CRCOM		;GOOD RETURN

HOST01:	SETOM FHSTN		;NO CURRENT FOREIGN HOST
	JRST CRCOM		;SEE WHAT TO DO NOW.

.HOST1:	SKIPE F.TOPN		;TELNET CONN OPEN?
	PUSHJ P,TCLOSE		;YES. CLOSE IT.
	MOVE X,RECX		;GET THE HOST TABLE INDEX
	JRST .HOST2		;AND GO OPEN CONN.

HOST03:	PUSHJ P,OCTIN		;READ OCTAL NUMBER
	  JRST DUMMY		;(CAN'T HAPPEN)
	MOVEM A,FHSTN		;SAVE THE HOST NUMBER
	JRST HOST04		;GO OPEN CONNECTION

MKFERR:	MSG <
? Can't create forks to handle TELNET connections.
>
	PUSHJ P,BOMB
;LOGIN COMMAND. TAKES NAME, OPTIONAL PASSWORD, OPTIONAL ACCT.

.LOGIN:	SETZM PUSER		;SO CAN TELL WHAT WAS TYPED IN
	SETZM PPASS
	SETZM PACCT
	SKIPE F.TOPN		;TELNET OPEN?
	JRST LOGI01		;YES. GOOD.
NOCONN:	PUSHJ P,TCLOS1		;MAKE SURE IT REALLY IS CLOSED
	HRROI A,[ASCIZ /
? Type a "CONNECT" command first./]
	JRST ERRCOM		;NO GOOD.

LOGI01:	NOISE <(user-ident) >
	PUSHJ P,SST1		;SKIP BREAK CHARS
	MOVEI X,5*<EUSRBF-USERBF> ;COUNT
	MOVE BP,[440700,,USERBF];POINTER
	PUSHJ P,TSIN		;GET THE STRING, ALLOW SPACES
	  JRST XXXCOM		;NO GOOD - RUBOUT TYPED.
	HRROI A,USERBF		;POINTER TO IT
	MOVEM A,PUSER		; ..
	MOVE C,BREAKC		;RETRIEVE BREAK CHARACTER
	CAIN C,C.LF		;END OF LINE?
	JRST LOGINX		;YES.
	NOISE <(password) >
	MOVEI A,100
	RFMOD			;KILL ECHOING FOR PASSWORD
	TRZ B,3B25		; ..
	SFMOD
	TRO F,R.NOEC		;FLAG ECHOING IS OFF
	HRROI A,PMASK		;PASSWORD MASK
	TRNE B,14		;IF NOT FULL DUPLEX,
	PSOUT			;TYPE MASK
	PUSHJ P,SST1
	MOVEI X,5*<EPASBF-PASSBF>
	MOVE BP,[440700,,PASSBF]
	PUSHJ P,TSIN
	  TROA F,R.AMB		;BORROW FLAG OVER ECHO SET
	TRZ F,R.AMB!R.NOEC	; ..
LOGI1A:	MOVEI A,100
	RFMOD
	TRO B,2B25		;ECHOING BACK ON
	SFMOD
	HRROI A,PMASK2		;AND FINAL ONE
	TRNE B,14		;IF NOT FULL DUPLEX
	PSOUT
	MOVE A,BREAKC		;ECHO THE BREAK
	CAIN A,C.LF		;LINEFEED?
	JRST [	CALL PCRLF	;YES, TYPE A CR AND LF
		JRST LOGI1Q]
	PBOUT
LOGI1Q:	TRNE F,R.AMB		;NOW WAS A RUBOUT TYPED?
	JRST XXXCOM		;YES.
	HRROI A,PASSBF
	MOVEM A,PPASS		;SAY THERE'S A PASSWORD TO SEND

LOGI02:	PUSHJ P,SST1
	CAIN C,C.LF
	JRST LOGINX
	NOISE < (account) >
	MOVEI X,5*<EACTBF-ACCTBF>
	MOVE BP,[440700,,ACCTBF]
	PUSHJ P,TSIN
	  JRST XXXCOM
	HRROI A,ACCTBF
	MOVEM A,PACCT
	PUSHJ P,SST
	CAIE C,C.LF		;SHOULD BE END OF LINE
	JRST DUMMY
LOGINX:	SKIPN A,PUSER
	JRST LOGINZ
	HRROI B,[ASCIZ /USER /]
	PUSHJ P,TELSND
	SKIPN A,PPASS
	JRST LOGINZ
	HRROI B,[ASCIZ /PASS /]
	PUSHJ P,TELSND
	SKIPN A,PACCT
	JRST LOGINZ
	HRROI B,[ASCIZ /ACCT /]
	PUSHJ P,TELSND
LOGINZ:	JRST CPOPJ1

;HERE ON PSI CAUSE BY TELNET RCV FORK REQUESTING ABORT

ABOINT:	SETOM F.ABOR		;FLAG WHICH KIND OF INT.
	JRST CGINT1

;HERE ON BELL TYPED

CGINT:	SETOM CGFLAG
CGINT1:	MOVEM A,NTIIA		;PRESERVE AC
	MOVEI A,7		;TYPE A BELL
	PBOUT
	HRRZ A,RETPC3		;GET THE INT PC
	CAIE A,FWPC		;FORK WAIT?
	CAIN A,FWPC+1		; ..
	SKIPA A,[10000,,FWPC+1]	;YES. BREAK IT OUT.
	SKIPA A,NTIIA		;NO. RESTORE AC A.
	MOVEM A,RETPC3		;NOTE AC A CLOBBERED
	TRO F,R.ABOR		;FLAG IN TOP LEVEL AC
	DEBRK

COINT:	MOVEM A,NTIIA		;CLEAR OUTPUT BUFFER INT
	MOVEI A,101		;OUTPUT PRIMARY JFN
	CFOBF
	MOVE A,NTIIA
	DEBRK
;GET FILE FROM HOST COMMAND.

.GET:	SKIPN F.TOPN		;IS THERE A FOREIGN HOST?
	JRST NOCONN		;NO. MUST BE.
	NOISE < (foreign-filename<RETURN>) >
	MOVEI X,5*<EFRNPT-FRNPTH>
	MOVE BP,[440700,,FRNPTH]
	PUSHJ P,TSIN1		;READ THE STRING
	  JRST XXXCOM		;RUBOUT
GET01:	MSG < to local-file >
	PBIN
	CAIE A,C.ESC		;DEFAULT?
	JRST GET02		;NO
	HRROI A,FRNPTH		;YES, TYPE IT.
	PSOUT
	HRROI A,CRLFM		;AND END OF LINE
	PSOUT
	MOVSI A,400001		;FEED IN SAME STRING AS REMOTE.
	HRROI B,FRNPTH		; ..
	GTJFN
	  JRST GETXX1		;NO GOOD
	JRST GET03		;OK.

GET02:	CAIN A,CDELLN		;RUBOUT?
	JRST XXXCOM		;YES.
	MOVEI A,100		;NO. BACK UP AND GET JFN
	BKJFN
	  JRST GETXX1		;CAN'T FAIL?
	MOVSI A,460003
	MOVE B,[100,,101]
	GTJFN
	  JRST GETXX1
GET03:	MOVEM A,LCLJFN
	PUSHJ P,GETS1		;DO THE WORK OF THE GET
	  JFCL
	JRST CPOPJ1
GETS1:	HRRZ A,LCLJFN
	SKIPG B,$BYTE		;IS THERE A DECLARED BYTE SIZE?
	MOVEI B,10		;NO. DEFAULT IS 10
	SKIPG C,$TYPE		;EXCEPT IF IT'S ASCII,
	MOVEI B,7		;DISC FILE SHOULD BE ASCII
	CAIN C,TYPE.I		;IMAGE TYPE?
	MOVEI B,44		;YES. MAKE WORDS, WILL FIX BELOW
	ROT B,-6		;PUT IT IN RIGHT PLACE FOR OPENF
	HRRI B,100000		;AND OPEN FOR WRITING.
	OPENF
	  JRST GETXX1

	SETZM SNDRCV		;DIRECTION FLAG
	PUSHJ P,PREDAT		;SEND ANY MODE, TYPE PARAMS.
	HRROI B,[ASCIZ /RETR /]	;PROTOCOL RETRIEVAL CUE
DIREC9:	HRROI A,FRNPTH		;NAME FOR IT
	PUSHJ P,TELSND		;SEND THE COMMAND
	PUSHJ P,CWFORK		;COMMON FORK WAIT AND WRAPUP
	JRST CPOPJ1		;RETURN FROM GET SUBR

GETXX1:	CLOSK LCLJFN		;CLOSE BUT KEEP JFN
GETXX2:	MSG <
? Can't open local file.>
	POPJ P,0		;NON-SKIP RETURN FROM GETS1
CWFORK:				;COMMON WAIT FOR DATA FORK.
	SETZM CGFLAG		;NOT ABORTED YET
	SETZM F.ABOR		; ..
	SETZM F.DTIP		;NO DATA TRANSFER IN PROGRESS
	SETZM F.DTDR		;NOR DONE REPLY
	SETZM F.DOPN		;COUNT WHEN DATA CONN IS OPENED
	TRZ F,R.ABOR
	MOVE A,DFORKH		;GET RUN AND CONSOLE TIMES
	RUNTM			;BEFORE ANYTHING STARTS
	MOVEM A,CPUTIM
	MOVEM C,DAYTIM
	SETZM NBYTES		;NUMBER OF BYTES TRANSFERRED
	MOVE A,DFORKH		;START THE DATA TRANSFER FORK
	MOVEI B,DFRKSA		;WHERE IT STARTS
	SFORK			;MAKE THE DATA GO.
FWPC==.	;FOR THE INT ROUTINE TO LOOK FOR WFORK JSYS
	WFORK
	MOVE A,DFORKH		;MAKE SURE GOOD TERMINATION
	RFSTS			; ..
	HLRZ A,A		;SHOULD BE A 2 FOR HALTF
	MOVE C,CGFLAG		;DONT GRIPE IF FORCED BY USER OR SERVER
	IOR C,F.ABOR		; ..
	SKIPN C			; ..
	CAIN A,2		; ..
	JRST CWFK7		;OK
	PUSH P,B		;STASH THE PC
	MSG <
? DATA FORK TERMINATED, PC = >
	MOVEI A,101
	POP P,B
	HRRZS B
	MOVEI C,10
	NOUT
	  JFCL
	PUSHJ P,PCRLF
CWFK7:	MOVE A,DFORKH		;FORK HANDLE
	HFORK			;STOP IT IN CASE WASN'T VOLUNTARY
	RUNTM			;GET CONSOLE AND RUN TIMES
	SUB A,CPUTIM		;DIFFERENCE IN TIMES
	IMULI A,^D1000		;MAKE MILLISECONDS
	PUSH P,B
	IDIVI A,(B)
	POP P,B
	MOVEM A,CPUTIM
	SUB C,DAYTIM
	IMULI C,^D1000
	IDIVI C,(B)
	MOVEM C,DAYTIM
	MOVEI A,101		;DON'T FOUL TIMING WITH TTY WAIT
	DOBE			; SO WAIT FIRST FOR TTY.
	SKIPE F.DTIP		;TRANSFER IN PROGRESS?
	TRNE F,R.ABOR		;AND NOT ABORTED?
	JRST CWFK2		;DONT WAIT
	MOVNI X,^D30		;YES, WAIT A LITTLE BIT
CWFKL1:	SKIPE F.DTDR		;DONE REPLY IN YET?
	JRST CWFK2		;YES.
	MOVEI A,^D2000		;NO. WAIT FOR IT.
	DISMS
	AOJL X,CWFKL1		;CHECK NOW
CWFK2:	HRROI A,[ASCIZ /
 No completion reply received.
/]
	SKIPN F.DTDR		;252-4 RECEIVED?
	PSOUT			;NO. SAY SO.
	HRROI A,[ASCIZ /
 Aborted.
/]
	SKIPE CGFLAG
	PSOUT
	HRROI A,[ASCIZ /Data connection was never established.
/]
	SKIPN F.DOPN		;DATA EVER OPENED?
	PSOUT			;NO. SAY SO.
CWFK1:	TRNE F,R.KJFN		;WANT TO HANG ON TO JFN?
	 JRST [	CLOSK LCLJFN
		JRST CWFK6]	;YES. CLOSE AND KEEP.
	CLOSE LCLJFN		;NO. CLOSE AND RELEASE.
CWFK6:	CLOSE DATJFN		;CLOSE AND RELEASE NET DATA CONN
	MOVE A,CGFLAG		;SEE IF SHOULD GIVE STATISTICS
	IOR A,F.ABOR
	IOR A,F.NOST		;REQUESTED NO STATS?
	IOR A,F.NST1		;OR USER SAID NOSTAT?
	JUMPN A,CWNOST		;NO STATS
	MOVEI A,101		;TTY INTERFERENCE NOT DESIRED
	DOBE
	CALL PCRLF		;PRINT SUMMARY
	MOVEI A,101		;FIRST, AMOUNT OF DATA
	MOVE B,NBYTES		; ..
	MOVEI C,12
	NOUT
	  JFCL
	MSG <. bytes transferred, run time = >
	MOVEI A,101
	MOVE B,CPUTIM
	MOVEI C,12
	NOUT
	  JFCL
	MSG <. MS,
 Elapsed time = >
	MOVEI A,101
	MOVE B,DAYTIM
	MOVEI C,12
	NOUT
	  JFCL
	MSG <. MS, Rate = >
	SKIPG B,$BYTE
	MOVEI B,10
	IMUL B,NBYTES		;BITS
	IMULI B,^D1000
	IDIV B,DAYTIM		;BAUD
	MOVEI A,101
	MOVEI C,12
	NOUT
	  JFCL
	MSG <. Baud.
>
CWNOST:	POPJ P,0
;SEND LOCAL FILE TO FOREIGN HOST
;ALSO MAIL FILE WHICH USES MOSTLY SAME CODE

.MAIL:	TRZ F,R.APPE		;NOT APPEND
	TRO F,R.MAIL		;MAIL FILE
	JRST MAIL01		;USE COMMON CODE
.SEND:	TRZA F,R.APPE		;NOT APPEND COMMAND
.APPE:	TRO F,R.APPE		;APPEND, NOT SEND COMMAND.
	TRZ F,R.MAIL		;APPEND OR SEND, NOT MAIL
MAIL01:	SKIPN F.TOPN		;HAVE TO BE CONNECTED FIRST.
	JRST NOCONN		; ..
	NOISE < (local-file) >
	MOVSI A,120003		;GET THE LOCAL FILE NAME
	MOVE B,[100,,101]	;FROM TTY
	GTJFN
	  JRST XXXCOM		;BAD CONFIRM, PROBABLY.
	MOVEM A,LCLJFN		;STORE JFN FOR THAT FILE
	MOVEI A,100		;HAVE TO GET THE TERMINATOR BACK
	BKJFN			; ..
	  PUSHJ P,BOMB		;CAN'T
	PBIN			;READ IT.
	MOVEM A,BREAKC		;SAVE IT
	TRNE F,R.MAIL		;MAIL FILE?
	JRST [	MSG < to remote-user >
		JRST MAIL02]
	MSG <
 to remote-file >
MAIL02:	MOVEI X,5*<EFRNPT-FRNPTH>
	MOVE BP,[440700,,FRNPTH]	;WHERE TO SAVE FOREIGN PATHNAME
	SETZM FRNPTH		;CLEAR WHOLE WORD SO SKIPE WORKS BELOW
	PUSHJ P,TSIN1		;FOREIGN FILE NAME
	  JRST XXXCOM
SND01:	CAIN C,C.ESC	;ESCAPE TERM?
	SKIPE FRNPTH	;AND NO OTHER CHARACTERS?
	JRST SND02		;NO
	MOVE C,[001100,,000001]	;TYPE FILE NAME LOCALLY
	TRNE F,R.MAIL		;BUT FO MAIL FILE,
	MOVSI C,1000		;JUST FILE NAME FOR USER NAME
	HRROI A,FRNPTH
	HRRZ B,LCLJFN
	JFNS
	PUSHJ P,SNDS1		;CALL FILE SENDER
	  JFCL
	JRST SND03		;WRAP UP

SND02:	PUSHJ P,SNDS2
	  JFCL
SND03:	CLOSE LCLJFN
	JRST CRCOM
SNDS1:	HRROI A,FRNPTH
	PSOUT
	HRROI A,CRLFM
	PSOUT
SNDS2:	SETO B,		;TRY TO FIGURE OUT THE RIGHT SIZE FOR LOCAL JFN
	MOVE A,$BYTE
	SKIPG $TYPE		;ASCII?
	MOVEI B,7		;YES. LOCAL IS ASCII TOO
	SKIPGE B		;ANY DECISION FOR ASCII?
	MOVE B,A		;NO. USE DECLARED BYTE SIZE
	SKIPG B			;IF ANY
	MOVEI B,10		;NO. USE DEFAULT EIGHT-BIT FOR IMAGE
	LSH B,^D30		;PUT IN PLACE FOR OPENF
	HRRI B,200000		;READ FILE
	TRNE F,R.MAIL		;IF MAIL FILE, FORCE ASCII READ
	MOVE B,[070000,,200000]
	HRRZ A,LCLJFN
	OPENF
	  JRST SNDX1
	SETOM SNDRCV		;DIRECTION FLAG FOR DATA FORK
	TRNE F,R.MAIL		;IF MAIL, SET ASCII PARAMS
	 JRST [	PUSHJ P,PREASC
		JRST MAIL03]
	PUSHJ P,PREDAT		;SET UP SOCKET 255 MECHANISM
	HRROI B,[ASCIZ /STOR /]	;TELL FOREIGN GUY TO STORE FILE
	TRNE F,R.APPE		;OR MAYBE APPEND IT,
	HRROI B,[ASCIZ /APPE /]	; ..
MAIL03:	TRNE F,R.MAIL		;MAIL?
	HRROI B,[ASCIZ /MLFL /]	;YES. DIFFERENT FTP COMMAND
	HRROI A,FRNPTH		;UNDER THIS NAME
	PUSHJ P,TELSND
	PUSHJ P,CWFORK		;FORK WAIT ROUTINE
	JRST CPOPJ1		;SUCCESSFUL COMPLETION

SNDX1:	CLOSK LCLJFN
	CLOSE DATJFN
	MSG <
? Can't open local file.>
	POPJ P,0
.MULT:	SKIPN F.TOPN		;TELNET OPEN?
	JRST NOCONN		;NO. BITCH.
	TRZ F,R.APPE!R.HCOM	;WRITE, DON'T SEARCH HOST NAMES
	PUSHJ P,GCHINI
	MOVE X,MLTTBX		;SET UP TO SEARCH TABLE
	MOVEM X,WORDXP		; ..
	PUSHJ P,GETWRD		;GET OR SEND WORD
	  JRST DUMMY		;NEITHER
	SKIPGE C,RECX		;GOOD ANSWER?
	JRST DUMMY
	HLRZ C,MLTTB2(C)	;GET ROUTINE ADDRESS
	PUSHJ P,0(C)		;DISPATCH
	  JRST DUMMY
	JRST COMMAN

DEFINE MULTM <
CC (<GET>,.MGET)
CC (<SEND>,.MSEND)
>

DEFINE CC (WORD,TAG)<
	EXP [ASCIZ \WORD\]
>
MLTTB1:	MULTM
NMCOMS==.-MLTTB1
MLTTBX:	XWD -NMCOMS,MLTTB1

DEFINE CC (WORD,TAG)<
	XWD TAG,0>

MLTTB2:	MULTM
.MSEND:	TRZ F,R.MAIL!R.APPE
	NOISE < (LOCAL FILE GROUP) >
	MOVSI A,100103
	MOVE B,[100,,101]	;GET THE FILE NAMES FROM TTY
	GTJFN
	  JRST XXXCOM
	MOVEM A,LCLJFN
	PUSHJ P,PCRLF
MSL1:	HRROI A,FRNPTH		;PLACE TO BUILD FOREIGN FILE NAME
	SKIPN PREFIX		;IS THERE A PREFIX FIRST?
	JRST MS02		;NO
	HRROI B,PREFXB		;YES. POINT TO IT
	MOVEI C,0
	SOUT
MS02:	HRRZ B,LCLJFN		;NOW PUT ON THE NAME AND EXTENSIOL
	MOVE C,[001100,,1]	;LET SYSTEM PARSE FILE NAME
	JFNS
	SKIPN SUFFIX		;TRAILER? (ACCT, PPN,...)
	JRST MS03		;NO
	HRROI B,SUFFXB		;YES. POINTER TO IT
	MOVEI C,0
	SOUT
MS03:	TRO F,R.KJFN		;KEEP JFN FOR STARS
	SETOM F.NOST		;PREVENT VERBOSITY
	PUSHJ P,SNDS1		;AND DO THE SEND
	  JFCL
	MOVE A,LCLJFN		;NOW STEP TO NEXT FILE
	GNJFN
	  JRST MS90		;NO MORE.
	JRST MSL1		;GO SEND THIS ONE

MS90:	PUSHJ P,PCRLF
	SKIPLE A,LCLJFN		;CLOSE OUT THESE JFNS AND RELEASE THEM
	CLOSF
	  JFCL
	SETOM LCLJFN
	SKIPLE A,DATJFN		; ..
	CLOSF
	  JFCL
	SETOM DATJFN
	JRST CPOPJ1		;RETURN TO .MULT
.MGET:	NOISE < (REMOTE FILE GROUP) >
	SETZM FRNPTH
	MOVE BP,[440700,,FRNPTH]
	MOVEI X,5*<EFRNPT-FRNPTH>
	PUSHJ P,TSIN		;GET A TENEX FILE-GROUP
	  JRST XXXCOM
	MOVSI A,411001		;A TEMP FILE TO HOLD LIST.
	HRROI B,[ASCIZ /-FTP-TEMP-.TMP;P770000;T/]
	GTJFN
	  JRST MGX1		;CAN'T
	MOVEM A,LCLJFN
	MOVE B,[070000,,100000]	;WRITE ON IT
	OPENF
	  JRST MGX2		;CAN'T
	SETZM SNDRCV		;DECLARE RECEIVE DIRECTION
	TRO F,R.KJFN		;KEEP THE DIRECTORY FILE JFN
	PUSHJ P,PREASC		;SEND PARAMS FOR NLST
	SETOM F.NOST		;DON'T TYPE OUT ABOUT THE NLST
	HRROI B,[ASCIZ /NLST /]
	HRROI A,FRNPTH		;SEND NLST OF THE PATH NAME
	PUSHJ P,TELSND
	PUSHJ P,CWFORK		;WAIT FOR THE FILE TO COME IN.
	HRRZ A,LCLJFN		;NOW RE-OPEN THE TEMP FOR READING
	MOVE B,[070000,,200000]	; ..
	OPENF
	  JRST MGX3		;CAN'T
	MOVEM A,DIRJFN		;HOLD IT
	SETOM LCLJFN
	PUSHJ P,PREDAT		;NOW SET UP PARAMS FOR DATA XFER
MGL1:	HRRZ A,DIRJFN		;MAIN LOOP. GET A FILE NAME
	HRROI B,FRNPTH		;WHERE IT GOES
	MOVEI C,5*<EFRNPT-FRNPTH>
	MOVEI D,12		;QUIT ON LINEFEED
	SIN
	GTSTS
	TLNE B,1000		;HIT EOF YET?
	JRST MG90		;YES. QUIT
;NO, FALL THRU
MG00:	MOVE A,[440700,,FRNPTH]	;FORCE A NULL AT END OF NAME
MG00L:	ILDB B,A		;SCAN NAME
	CAIE B,15
	CAIN B,12
	SKIPA
	JUMPN B,MG00L
	MOVEI B,0		;END OF NAME. MAKE A NULL
	DPB B,A			;SMASH OVER THE CR, LF, OR NULL
	MOVE A,[440700,,FRNPTH]	;HAVE TO PEEL OUT NAME AND EXT.
	ILDB B,A		; SEE IF DIRECTORY ON FRONT
	CAIE B,"<"
	JRST MG01		;NO
	MOVEI X,5*<EFRNPT-FRNPTH>
MGL2:	ILDB B,A		;YES. LOOK FOR CLOSING BRKT
	CAIN B,">"
	JRST MG02
	SOJG X,MGL2
	JRST MGX4		;OOPS. LOSING BIG.

MG01:	MOVE A,[440700,,FRNPTH]
MG02:	MOVE B,[440700,,FRNPT2]	;PLACE TO BUILD UP LOCAL FILE
	TLZ F,L.TMP1		;NO DOTS SEEN IN NAME
	SETZM FRNPT2
MGL3:	ILDB C,A
	CAIN C,";"		;QUIT AT THE VERSION, IF TENEX.
	JRST MG03
	CAIN C,"."		;IF TOPS20, QUIT ON 2ND DOT
	TLON F,L.TMP1		;DOT. SECOND ONE?
	SKIPA			;NO.
	JRST MG03		;YES, SECOND DOT.
	CAIE C,15
	CAIN C,0
	JRST MG03		;OR AT END OF PATHNAME
	IDPB C,B
	JRST MGL3		;BUILD UP NAME.EXT

MG03:	MOVEI C,0		;TERMINATOR
	IDPB C,B
	MOVSI A,400001
	HRROI B,FRNPT2
	GTJFN			;TRY TO GET THIS NAME AS JFN
	  JRST MGX5		;CAN'T
	MOVEM A,LCLJFN		;OK
	HRROI A,FRNPT2		;ANNOUNCE IT
	PSOUT
	PUSHJ P,PCRLF
	HRRZ A,LCLJFN
	PUSHJ P,GETS1		;DO THE FILE GET
	  JFCL
	CLOSE LCLJFN
	SKIPE CGFLAG		;USER TYPE BELL?
	JRST MG90		;YES. QUIT.
	JRST MGL1		;LOOP THRU ALL FILES IN LIST

MG90:	SKIPG A,DIRJFN		;DIRECTORY FILE? (BETTER BE)
	JRST MG91		;NO.
	CLOSK DIRJFN		;CLOSF THE FILE SO IN CAN BE DELETED
	HRRZ A,DIRJFN		;NOW DELETE AND RELEASE THE JFN
	DELF			;DELETE AND RELEASE JFN
	  JFCL
MG91:	SETOM DIRJFN
	CLOSE LCLJFN
	CLOSE DATJFN
	JRST CPOPJ1		;RETURN FROM .MGET
;ERRORS IN GET MULTIPLE...

MGX2:	CLOSE LCLJFN
MGX1:	MSG <
? CAN'T OPEN SCRATCH FILE
>
	JRST MG90		;GO WRAP UP
MGX3==MGX2
MGX4:	MSG <
? CAN'T PARSE >
	HRROI A,FRNPTH
	PSOUT
	PUSHJ P,PCRLF
	JRST MGL1

MGX5:	PUSH P,A		;SAVE ERROR
	MSG <
? CAN'T OPEN LOCAL FILE - GTJFN:
>
	HRROI B,FRNPT2
	PSOUT
	PUSHJ P,PCRLF
	POP P,B
	MOVEI A,101
	HRLI B,400000
	MOVEI C,0
	ERSTR
	  JFCL
	  JFCL
	JRST MGL1		;TRY THE NEXT ONE.
.BYTE:	NOISE < (decimal number) >
	PUSHJ P,DECIN		;READ THE DESIRED BYTE SIZE
	  JRST XXXCOM		;FAILED
	CAIE A,44		;SCAN FOR LEGAL VALUES
	CAIN A,40		; ..
	JRST BYTE01
	CAIN A,10		; ..
	JRST BYTE01
	MSG <
? Must be 36, 32 or 8 bit bytes.>
	JRST CPOPJ1

BYTE01:	MOVEM A,$BYTE		;STORE THE BYTE SIZE
	NOISE <
>
	JRST CPOPJ1		; ..

.ASC:	MOVEI A,10		;EIGHT BIT BYTES
	MOVEM A,$BYTE
	MOVEI A,TYPE.A		;ASCII TYPE
	MOVEM A,$TYPE
	NOISE <
>
	JRST CPOPJ1
.TENEX:	MOVEI A,44		;36-BIT CONNECTION
	MOVEM A,$BYTE
.IMAGE:	MOVEI A,TYPE.I		;CODE FOR IMAGE TRANSMISSION
	MOVEM A,$TYPE
	JRST CMDNRT

.BRIEF:	TDZA A,A		;CLEAR VERBOSE FLAG
.VERBO:	SETO A,			;SET VERBOSE FLAG
	MOVEM A,F.VBOS		; ..
	JRST CMDNRT

.STATS:	TDZA A,A
.NOSTA:	SETO A,
	MOVEM A,F.NST1		;STATISTICS TYPEOUT ALLOW/SUPPRESS
CMDNRT:	NOISE <
>
	JRST CPOPJ1

.PAGED:	MOVEI A,44		;SET BYTE SIZE TO A WORD
	MOVEM A,$BYTE		; ..
	MOVEI A,TYPE.X		;AND TO PAGED TYPE
	MOVEM A,$TYPE
	JRST CMDNRT
.STATU:	SKIPN F.TOPN
	JRST NOCONN
	NOISE < of host:
>
	HRROI B,[ASCIZ /STAT /]
	HRROI A,[0]
	PUSHJ P,TELSND		;"STAT " WITH NO ARG.
	JRST CPOPJ1

.RENAM:	SKIPN F.TOPN
	JRST NOCONN
	NOISE < existing-file<RETURN>: >
	MOVEI X,5*<EFRNPT-FRNPTH>
	MOVE BP,[440700,,FRNPTH]
	PUSHJ P,TSIN1
	  JRST XXXCOM
	MSG <
 to be: >
	MOVEI X,5*<EFRNP2-FRNPT2>
	MOVE BP,[440700,,FRNPT2]
	PUSHJ P,TSIN1
	  JRST XXXCOM
	HRROI B,[ASCIZ /RNFR /]	;FIRST COMMAND
	HRROI A,FRNPTH		;OLD NAME
	PUSHJ P,TELSND
	HRROI B,[ASCIZ /RNTO /]
	HRROI A,FRNPT2
	PUSHJ P,TELSND
	JRST CRCOM
.DELET:	SKIPN F.TOPN
	JRST NOCONN
	NOISE < FOREIGN FILE: >
	MOVEI X,5*<EFRNPT-FRNPTH>
	MOVE BP,[440700,,FRNPTH]
	PUSHJ P,TSIN1
	  JRST XXXCOM
	MSG <
Do you really want to delete >
	HRROI A,FRNPTH
	PSOUT
	MSG <? (Y or N) >
	MOVEI A,100		;BREAK ON ALL CHARS
	RFMOD
	TRO B,3B23
	SFMOD
	PUSHJ P,TYI
	TRZ C,40
	CAIE C,"Y"
	JRST XXXCOM
	HRROI B,[ASCIZ /DELE /]
	HRROI A,FRNPTH
	PUSHJ P,TELSND
	JRST CRCOM
.ACCT:	SKIPN F.TOPN		;CONNECTION OPEN SOMEWHERE?
	JRST NOCONN		;NO.
	MOVEI X,5*<EACTBF-ACCTBF>
	MOVE BP,[440700,,ACCTBF]
	PUSHJ P,TSIN
	  JRST XXXCOM
	CAIE C,C.LF
	JRST DUMMY
	HRROI A,ACCTBF		;UPDATE ACCOUNT POINTER
	MOVEM A,PACCT		;IN CASE NEEDED LATER
	HRROI B,[ASCIZ /ACCT /]	;SEND THE FTP COMMAND
	MOVE A,PACCT		; ..
	PUSHJ P,TELSND
	JRST CPOPJ1		;END OF ACCOUNT COMMAND

.QUOTE:	SKIPN F.TOPN		;CONNECTION OPEN?
	JRST NOCONN		;NO, DON'T SEND QUOTE
	MOVEI X,5*<ESTRTM-STRTMP>
	MOVE BP,[440700,,STRTMP]
	PUSHJ P,TSIN1		;READ A STRING INCLUDING SPACES
	  JRST XXXCOM		;QUIT ON RUBOUT
	HRROI B,[0]		;NO KEYWORD.
	HRROI A,STRTMP		;DATA IS WHAT WAS IN USER TYPEIN
	PUSHJ P,TELSND		;SEND IT
	JRST CPOPJ1

.CWD:	SKIPN F.TOPN		;CONNECTION OPEN?
	JRST NOCONN		;NO, DON'T SEND THE CWD YET
	MOVEI X,5*<ESTRTM-STRTMP>
	MOVE BP,[440700,,STRTMP]
	PUSHJ P,TSIN1		;READ THE FOREIGN DIRECTORY
	  JRST XXXCOM		;RUBOUT?
	CAIE C,C.LF		;EOL?
	JRST DUMMY
	HRROI A,STRTMP		;THE ARGUMENT
	HRROI B,[ASCIZ /CWD /]	;THE TELNET COMMAND
	PUSHJ P,TELSND		;SEND IT
	JRST CPOPJ1		;END OF CWD COMMAND
.DIREC:	SKIPN F.TOPN
	JRST NOCONN
	NOISE < OF >
	PUSHJ P,SST1
	CAIN C,C.LF		;NULL ARG?
	JRST DIREC1		;YES. PLUG IN *.*
	MOVEI X,5*<EFRNPT-FRNPTH>
	MOVE BP,[440700,,FRNPTH]
	PUSHJ P,TSIN1
	  JRST XXXCOM
	JRST DIREC2

DIREC1:	MOVE A,[ASCII /*.*/]
	MOVEM A,FRNPTH
DIREC2:	MSG <
to local-file: >
	MOVSI A,420003
	MOVE B,[100,,101]
	GTJFN
	  JRST XXXCOM
	MOVEM A,LCLJFN
	MOVE B,[070000,,100000]
	OPENF
	  JRST GETXX1
	SETZM SNDRCV
	PUSHJ P,PREASC
	SETOM F.NOST		;NO STATISTICS
	HRROI B,[ASCIZ /LIST /]
	JRST DIREC9		;REJOIN GET COMMAND FOR DATA XFER
;INITIAL CONNECTION PROTOCOL
;CALLED ONLY FROM HOST CONNECT COMMAND

DOICP:	SETOM IJFN		;THESE JFNS NOT YET ASSIGNED
	SETOM RJFN
	SETOM SJFN
	HRROI A,GTJSTR		;PUT STRING FOR SOCKET IN BUFFER
	HRROI B,[ASCIZ /NET:/]	;DEVICE FIELD IS FIRST
	SETZ C,			;QUIT ON NULL
	SOUT
	PUSH P,A		;SAVE LOCATION OF THIS NUMBER FOR LATER
	MOVE B,USRSKT		;DEFAULT USER SOCKET NUMBER
	MOVE C,[140003,,10]	;FLAGS FOR NOUT AS 3-DIGIT OCTAL
	NOUT
	  PUSHJ P,BOMB
	MOVEI B,"."		;END OF LOCAL HALF
	IDPB B,A		;SEPARATOR
	MOVE B,FHSTN		;FOREIGN HOST NUMBER
	MOVEI C,10		;OCTAL
	NOUT			;TO STRING
	  PUSHJ P,BOMB
	MOVEI B,"-"		;SEPARATOR BEFORE SOCKET NUMBER
	IDPB B,A		; TO STRING
	PUSH P,A		;SAVE STRING ADDRESS FOR FINAL SOCKET
	MOVE B,FTPSKT		;STANDARD FTP ICP SOCKET
	MOVEI C,10		;OUTPUT IN OCTAL
	NOUT			;TO STRING
	  PUSHJ P,BOMB
	HRROI B,[ASCIZ /;T/]	;MAKE LOCAL SOCKET BE RELATIVE TO JOB.
	MOVEI C,0		; ..
	SOUT			;BY ADDING ;T TO OUTPUT NAME
	MOVSI A,1		;GTJFN SHORT FORM, STRING.
	HRROI B,GTJSTR		;POINTER TO STRING
	GTJFN			;GET A JFN
	  JRST ICPFL2		;IMP NOT CONNECTED FAILURE.
	MOVEM A,IJFN		;SAVE JFN OF THIS CONNECTION
	MOVE B,[400000,,200000]	;OPEN THE CONNECTION TO READ 32BIT NUM
	PUSHJ P,.OPENF		;OPEN USING PI AND DISMIS FOR SPEED
	  JRST ICPFL3		;CAN'T OPEN CONNECTION.
	BIN			;GET THE REMOTE HOST'S SOCKET "S"
	MOVEM B,FORNS		;SAVE FOREIGN S
	SKIPN F.VBOS		;VERBOSE?
	JRST DOICP2		;NO
	PUSH P,A		;YES.
	HRROI A,[ASCIZ /(RCVD FOR'N SOCKET # /]
	PSOUT
	PUSH P,B
	PUSH P,C
	MOVEI A,101
	MOVEI C,10
	NOUT
	  JFCL
	POP P,C
	POP P,B
	HRROI A,[ASCIZ /)
/]
	PSOUT
	POP P,A
DOICP2:	CLOSF			;FREE THE ICP SOCKET.
	  JFCL
	POP P,A			;BACK UP TO START OF 4N SOCKET IN STRING
ICPA:	MOVEI C,10		;OCTAL NUMBER FOR SOCKET
	NOUT			;PUT IT IN THE STRING
	  PUSHJ P,BOMB
	HRROI B,[ASCIZ /;T/]	;AND ;T AFTER NEW NUMBER
	SETZ C,
	SOUT			;ADD TO STRING
	POP P,A			;RETRV POS OF LCL SOCKET IN JFN STR
	MOVE B,USRSKT		;PROTOCOL SAYS PREVIOUS +2
	ADDI B,2		;IS THE PLACE HE WILL CONNECT TO
	MOVE C,[140003,,10]	;AGAIN A 3-DIGIT OCTAL NUMBER
	NOUT
	  PUSHJ P,BOMB
	MOVEI B,"."		;RESTORE TERMINATOR CLOBBERED BY NOUT
	IDPB B,A		;NOW HAVE NEW NAME FOR SOCKET PAIR.
ICPB:	HRROI B,GTJSTR		;POINTER TO NAME STRING
	MOVSI A,1		;SET UP FOR GTJFN OF THIS PAIR
	GTJFN			;GET THE SEND JFN
	  JRST ICPFL4		;CAN'T
	MOVEM A,SJFN		;SAVE TELNET SEND JFN
	HRROI B,GTJSTR		;AND ANOTHER PAIR FOR RECEIVE
	MOVSI A,1		; ..
	GTJFN			; ..
	  JRST ICPFL5
	MOVEM A,RJFN		;TELNET RECEIVE JFN
	MOVE A,SJFN		;NOW OPEN THEM
	MOVE B,[103400,,100000]	;OPEN FOR SEND, NO WAIT, BUFFERED.
	OPENF			; ..
	  JRST ICPFL6
	MOVE A,RJFN		;OPEN RECEIVE SIDE
	MOVE B,[100000,,200000]	;EIGHT BIT BYTES, WAIT.
	OPENF
	  JRST ICPFL7		;CAN'T OPEN.
	VMSG <(OPENED RCV SOCKET)
>
	MOVE A,SJFN		;SEE IF SEND SIDE MADE IT YET.
	PUSHJ P,OPNWAT
	  JRST ICPFL8		;NO GOOD ON SEND SIDE.
	VMSG <(OPENED SEND SOCKET)
>
	SETOM F.TOPN		;TELNET CONNECTION IS NOW OPEN.
CPOPJ1:	AOS 0(P)		;SUCCEEDED IN ICP'ING
CPOPJ:	POPJ P,0		;RETURN
ICPFL4:	JSP X,ICPFX
	ASCIZ /No JFN for TELNET send side/
ICPFL5:	JSP X,ICPFX
	ASCIZ /No JFN for TELNET receive side/
ICPFL6:	JSP X,ICPFX
	ASCIZ /Can't open TELNET send connection/
ICPFL7:	JSP X,ICPFX
	ASCIZ /Can't open TELNET receive connetion/
ICPFL8==ICPFL6
ICPFL2:	JSP X,ICPFX2		;TWO DEEP ON STACK. SET X TO MSG
	ASCIZ /IMP is disconnected/
ICPFL3:	MOVEI X,[ASCIZ /host is rejecting/]
	PUSHJ P,HSTCHK		;IS HOST UP?
	  MOVEI X,[ASCIZ /host is disconnected/]	;NO
ICPFX2:	POP P,(P)		;REMOVE 4N SOCK BYTE POINTER
ICPFX1:	POP P,(P)		;REMOVE LOCAL SOCK BYTE PTR
ICPFX:	HRROI A,[ASCIZ /
Can't connect to server because  /]
	PSOUT
	HRROI A,(X)		;TYPE ERROR MESSAGE
	PSOUT
	CLOSE IJFN
	CLOSE RJFN
	CLOSE SJFN
	POPJ P,0		;FAIL RETURN FROM ICP ATTEMPT
;SUBROUTINES

HSTCHK:	PUSH P,A		;SKIP IF HOST IS UP
	PUSH P,B
	MOVE A,['IMPHRT']	;TABLE OF HOST BITS
	SYSGT
	PUSH P,B		;SAVE TABLE NUMBER
	MOVE A,FHSTN		;HOST TO CHECK ON
	IDIVI A,44		;CONVERT TO WORD AND BIT NUMBER
	HRLM A,0(P)		;STASH WORD NUMBER
	POP P,A			;XWD WORD,TABLE
	GETAB			;GET THE WORD WITH HOST BIT IN IT
	  SETZ A,		;NOT THERE. ASSUME DOWN (IMPOSS)
	ROT A,(B)		;SELECT THE BIT
	SKIPGE A		;TEST BIT IN SIGN OF A FOR UPNESS
	AOS -2(P)		;ON = UP = SKIP RETURN
BAPOPJ:	POP P,B			;RESTORE AC'S
APOPJ:	POP P,A
	POPJ P,0

SYSGET:	PUSH P,A		;SAVE ARGS
	PUSH P,B
	SETZM 0(B)		;IN CASE LOSES
	SYSGT
	JUMPE B,BAPOPJ		;IF NONE.
	MOVE A,FREE		;OK. MAKE POINTER
	HLL A,B			;- COUNT
	MOVEM A,@0(P)		;STORE ANSWER
	PUSH P,B		;NOW GET THE DATA
	HLLZ X,B		;MAKE AOBJN COUNTER
SYSGTL:	MOVSI A,(X)		;ITEM NUMBER
	HRR A,(P)		;TABLE NUMBER
	GETAB			;GET THE DATA
	  JRST SYSGTX		;CAN'T FAIL!!
	AOS C,FREE		;PUT IN FREE SPACE
	MOVEM A,-1(C)
	AOBJN X,SYSGTL
SYSGTX:	POP P,(P)
	JRST BAPOPJ		;RESTORE B AND A, RETURN
;CALLED FROM DOICP ROUTINE ONLY
.OPENF:	PUSH P,A		;JFN TO STACK
	TLO B,3000		;CHANGE NET OPEN MODE TO NO WAIT
	OPENF			;TRY OPENING
	  JRST APOPJ		;IMMEDIATE FAILURE. REPORT IT
	JRST OPNWT0		;GO WAIT FOR SOME ACTION

OPNWAT:	PUSH P,A		;SAVE THE JFN TO WAIT FOR
OPNWT0:	TRZ F,R.NTIC		;CLEAR WAIT COUNTER
	MOVEI B,24		;INTERRUPT MTOPR FOR NET
	MOVSI C,777700+NTICHN	;NO PI FOR INS, INR, NTICHN FOR FSM
	MTOPR			;ASSIGN THE NTICHN INT
OPNWTL:	TRZ F,R.NTIC		;CLEAR COUNTER AGAIN
	MOVE A,0(P)		;GET THE JFN TO WAIT FOR
	GDSTS			;LOOK AT FSM
	ROT B,4			;STATE CODE
	ANDI B,17
	CAIN B,FSOPND		;CONNECTION OPENED?
	JRST OPNWIN		;YES. GOOD.
	CAIE B,FSRFCS		;RFC STILL OUTSTANDING?
	JRST OPNFL		;NO. MUST HAVE FAILED.
	MOVEI A,^D30000		;WAIT THIRTY SECONDS
	TRON F,R.NTIC		;SET COUNTER UP SINCE WAITING
OPNWTK:	DISMS			;WAIT A WHILE. TAG FOR INT CHECK.
	JRST OPNWTL		;WAIT SOME MORE, NEW STATE.

OPNWIN:	POP P,A			;GET BACK JFN
	MOVEI B,24		;TURN INTERRUPT OFF FOR FSM
	SETO C,
	MTOPR
	JRST CPOPJ1		;AND SKIP RETURN FROM OPNWAT

OPNFL:	POP P,A			;GET JFN BACK
	CLOSF			;CLOSE THE CONNECTION
	  JFCL
	POPJ P,0		;RETURN FAILURE FROM OPNWAT

NTIINT:	MOVEM A,NTIIA		;SAVE AN AC
	TRON F,R.NTIC		;FIRST CHANGE OF STATE?
	DEBRK			;YES. WAIT SOME MORE.
	HRRZ A,RETPC3		;NO. SEE IF STILL IN THE DISMS
	CAIE A,OPNWTK
	CAIN A,OPNWTK+1
	SKIPA A,[10000,,OPNWTL]	;YES. BREAK OUT OF IT.
	SKIPA A,NTIIA		;NO. GET BACK USER AC
	MOVEM A,RETPC3		;YES. CHANGE RETURN. BAD AC OK.
	DEBRK
;INFERIOR FORK ROUTINES.

RFRKSA:	MOVE P,PDP		;PROCESS STACK

TNRSOL:	SETZM RCVLIN		;START OF LINE. CLEAR BUFFER.
	MOVE A,[RCVLIN,,RCVLIN+1]
	BLT A,ERCVLN		; ..
	MOVEI X,5*<ERCVLN-RCVLIN>	;COUNT LINE LENGTH
	MOVE BP,[440700,,RCVLIN]	;POINT TO START OF BUFFER

TNRL01:	MOVE A,RJFN
	BIN
	JUMPN B,TNR001
	GTSTS
	TLC B,600000
	TLNE B,601000
	JRST TNR002
	MOVEI B,0
TNR001:	CAIL B,200		;TELNET CONTROL CHARACTER?
	JRST TELCON		;YES.
	CAIE B,0		;SKIP NULLS AND CAR RETS
	CAIN B,C.CR
	JRST TNRL01		; ..
	CAIN B,C.LF		;END OF LINE?
	JRST TNREOL		; YES.
	IDPB B,BP		;NO. STORE CHARACTER IN INPUT BUFFER.
	SOJG X,TNRL01		;COUNT IN CASE OF HUGE LINE
TNREOL:	MOVEI B,0		;MAKE SURE A NULL AT END
	IDPB B,BP
	TLNE BP,760000		;FILL WORD OUT TO END
	JRST .-2
	SETZB A,X		;CLEAR NUMBER AND DIGIT COUNTER
	MOVE BP,[440700,,RCVLIN]
TNRNL1:	ILDB B,BP		;GET A REPLY CODE DIGIT
	CAIL B,"0"		;DECIMAL DIGIT?
	CAILE B,"9"		; ..
	JRST TNREON		;NO.
	IMULI A,12		;YES. ACCUMULATE DECIMAL NUMBER
	ADDI A,-"0"(B)		; ..
	AOJA X,TNRNL1		;COUNT DIGITS. LOOP.
TNREON:	SKIPN X			;WERE THERE ANY DIGITS IN NUMBER?
	MOVEI A,-1		;NO. MAKE A PHONY REPLY VALUE.
	MOVEM A,REPCOD		;STORE REPLY CODE
	MOVSI X,-NREPS		;COUNTER FOR NUMBER OF KNOWN REPLIES
TNRL02:	HRRZ B,REPTB1(X)	;GET A KNOWN REPLY
	CAMN B,REPCOD		;IS THAT WHAT WE GOT?
	JRST TNRRF		;REPLY FOUND.
	AOBJN X,TNRL02		;NO. LOOP
TNRFNY:	MOVEI A,C.SRVH		;PREFIX CHARACTER
	PBOUT			;TYPE IT
	HRROI A,RCVLIN		;FUNNY REPLY. NOT FOUND. TYPE IT.
	PSOUT
	HRROI A,CRLFM		;AND EOL
	PSOUT
	JRST TNRRF2		;TO REST OF REPLY HANDLER

TNRRF:	MOVEM X,REPIDX		;SAVE INDEX INTO TABLES
	MOVE B,REPTB1(X)	;GET BITS FOR WHAT TO DO.
REPEAT 0,< ;THIS SLOWS DOWN OUTPUT A LOT. WHAT TO DO?
	MOVEI A,101		;TRY NOT TO MIX TTY OUTPUT LINES
	DOBE
>
	SKIPN F.VBOS		;ALL TYPEOUT WANTED?
	JRST TNRRF1		;NO
	TLZ B,(RC.TTX)		;YES. DIDDLE UP FLAGS
	TLO B,(RC.TWL)		; ..
TNRRF1:	MOVEI A,C.SRVH		;HERALD PREFIXING SERVER TYPEOUT
	TLNE B,(RC.TWL!RC.TTX)	;TYPEING?
	PBOUT			;YES. PREFIX CHARACTER FIRST
	MOVSI A,070000		;BACK UP POINTER
	ADD A,BP		;TO JUST AFTER DIGITS
	TLNE B,(RC.TTX)		;TYPE TEXT?
	PSOUT			;YES.
	HRROI A,RCVLIN		;TYPE WHOLE THING?
	TLNE B,(RC.TWL)		; ..
	PSOUT			;YES.
	HRROI A,CRLFM		;EOL
	TLNE B,(RC.TWL!RC.TTX)	;ANY TYPING?
	JRST [	PSOUT			;YES. END THE LINE.
		MOVEI A,"*"
		SKIPE F.STAR		;IN COMMAND INPUT?
		PBOUT			;YES. RE-CUE
		JRST .+1]
	HRRZ C,REPTB2(X)	;DISPATCH ADDRESS, IF ANY.
	TLNE B,(RC.DSP)		;DISPATCH?
	PUSHJ P,0(C)		;YES.
TNRRF2:	MOVE A,REPCOD		;GET THE REPLY NUMBER
	CAIL A,^D401		;IN THE RANGE TO ABORT DATA?
	CAILE A,^D599		; ..
	JRST TNRRF3		;NO
	MOVEI A,-1		;INTERRUPT SUPERIOR
	MOVSI B,(1B<ABOCHN>)	;ON ABORT CHANNEL
	IIC
TNRRF3:	JRST TNRSOL		;GO GET ANOTHER LINE.
;BITS WHICH DRIVE RESPONSE RECEIVER.

RC.TTX==1B0	;TYPE THE TEXT BUT NOT THE NUMBER
RC.TWL==1B1	;TYPE THE WHOLE LINE
RC.DSP==1B2	;DISPATCH TO A HANDLER

RADIX 10
REPTB1:	EXP 000+RC.TTX		;GENERAL INFO.
	EXP 030+RC.TTX		;SERVER AVAILABILITY
	EXP 050+RC.TTX		;FTP COMMENT, USER INFO
	EXP 100+RC.TTX		;SYSTEM STATUS REPLY
	EXP 150+RC.TTX		;FILE STATUS REPLY
	EXP 151+RC.TTX		;DIRECTORY LISTING REPLY
	EXP 200			;JUST AN OK TO LAST COMMAND
	EXP 201+RC.TTX		;ABORT HAS TERMINATED ACTIVITY
	EXP 202+RC.TWL		;BAD ABORT ( NO ACTIVITY)
	EXP 230+RC.TTX		;LOGIN RECEIVED
	EXP 231+RC.TTX+RC.DSP	;LOGGED OUT.
	EXP 232			;LOGOUT RECEIVED BUT HOLDING
	EXP 250+RC.TTX+RC.DSP	;TRANSFER STARTED
	EXP 251+RC.DSP		;RESTART MARKER
	EXP 252+RC.TTX+RC.DSP	;TRANSFER COMPLETED
	EXP 253+RC.TTX+RC.DSP	;RENAME COMPLETED
	EXP 254+RC.TTX+RC.DSP	;DELETE COMPLETED
	EXP 255+RC.DSP		;SOCKET REPLY
	EXP 256+RC.TTX		;MAIL DONE.
	EXP 300+RC.TTX		;GREETING.
	EXP 301+RC.TWL		;INCOMPLETE COMMAND
	EXP 330			;ENTER PASSWORD
	EXP 331			;PASS OK, SEND ACCT
	EXP 350+RC.TTX		;SEND MAIL.
	EXP 400+RC.TTX		;NOT IMPL
	EXP 401+RC.TWL		;NO MORE USERS NOW
	EXP 430+RC.TWL		;LOGIN FAILURE
	EXP 431+RC.TTX		;LOGIN FAILURE
	EXP 432+RC.TWL		;USER CANT USE THIS SERVICE
	EXP 434+RC.TWL		;LOGOUT FORCED
	EXP 435+RC.TWL		;LOGOUT FORCED
	EXP 436+RC.TWL		;LOGOUT FORCED
	EXP 450+RC.TTX		;FILE NOT FOUND
	EXP 451+RC.TTX		;ACCESS DENIED
	EXP 452+RC.TWL		;TRANSFER FAILED
	EXP 453+RC.TWL		; ..
	EXP 454+RC.TWL		;CAN'T HOOK TO YOUR SOCKET
	EXP 500+RC.TTX		;GIBBERISH RCVD
	EXP 501+RC.TTX		; ..
	EXP 502+RC.TTX		; ..
	EXP 503+RC.TTX		; ..
	EXP 504+RC.TTX		; ..
	EXP 505+RC.TTX		; ..
	EXP 506+RC.TTX		; ..
NREPS==.-REPTB1			;LENGTH OF TABLE
RADIX 8
REPTB2:	REPEAT ^D10,<EXP BOMB>
	EXP REP231,BOMB,REP250,REP251,REP252,REP253,REP254,REP255
REPEAT NREPS-<.-REPTB2>,<EXP BOMB>

TELCON:	JRST TNRL01		;PROCESS TELNET CONTROLS HERE

TNR002:	SKIPE F.TCLS		; close request already in?
	HALTF			; yes, just quit
	MSG <
-- Connection has terminated --
>
	SETOM F.TCLS		;REQUEST CLOSE OF FOREIGN CONNS AND FRKS
	MOVEI A,-1		;INTERRUPT SUPERIOR
	MOVSI B,(1B<ABOCHN>)
	IIC
	HALTF

;Acknowledgement of BYE command

REP231:	SETOM F.TCLS		; request close of connection
	POPJ P,

;SPECIAL HANDLING OF SOME REPLIES

REP251:	POPJ P,0		;RESTART REPLY

REP255:	ADDI BP,1		;MOVE OVER FIVE CHARACTERS, "SOCK "
	MOVEI A,0		;SEE IF WE CAN READ A NUMBER
RP255L:	ILDB B,BP		;CHARACTER
	CAIL B,"0"		;DIGIT?
	CAILE B,"9"		; ..
	JRST RP255A		;NO.
	IMULI A,12
	ADDI A,-"0"(B)		;ADD IN THE DIGIT
	JRST RP255L		;BUILD THE NUMBER
RP255A:	MOVEM A,SOC255		;STORE FOR RECEIVE FORK TO SEE.
	POPJ P,0		;RETURN TO TELNET DISPATCHER.

REP250:	SETZM F.DTDR		;NO DATA TRANS DONE REPLY
	SETOM F.DTIP		;DATA TRANS IN PROG, ALLEGEDLY
	POPJ P,0		;RETURN
REP252:	SETOM F.DTDR		;DONE REPLY CAME IN
	SETZM F.DTIP		;NOT IN PROGRESS
	POPJ P,0

REP253==REP252
REP254==REP252		;THESE SAME AS ABOVE, FUNCTIONALLY.
;THE DATA TRANSFER FORK. FIRST GET THE NETWORK DATA CONNECTION,
;THEN DO THE FILE TRANSFER ITSELF.

DFRKSA:	SETOM DATJFN		;NO DATA CONN YET
	SETOM SOC255		;NO 255 REPLY IN YET.
	MOVE P,PDP		;FRESH FORK, GET A STACK
	SETZM TYXSCT		;START SEQUENCE NUMBERS AT 1
	TLZ F,L.TYPX		;ASSUME NOT PAGED XFER
	MOVE A,$TYPE2		;SEE IF THAT'S TRUE
	CAIE A,TYPE.X		; ..
	JRST DFRKI1		;NOT PAGED TYPE
	TLO F,L.TYPX		;SET FLAG
	MOVE A,$BYTE2		;OK, BUT LEGAL ONLY FOR 36 BITS
	CAIE A,44		; ..
	JRST DFRK1X		;NO GOOD.
	SKIPN SNDRCV		;AND ON SENDING, ONLY FROM DSK
	JRST DFRKI1		;RCVNG, OK.
	HRRZ A,LCLJFN		;SEND. SEE IF A DISK
	DVCHR
	TLNE B,777		;DISK?
	JRST DFRK2X		;NO, COMPLAIN
DFRKI1:	HRROI A,GTJSTR		;FIRST BUILD STRING FOR LISTENING SKT
	HRROI B,[ASCIZ /NET:/]	;DEVICE FIELD
	MOVEI C,0
	SOUT
	MOVE B,USRSKT		;CONSTRUCT SOCKET NUMBER TO LISTEN ON
	ADDI B,4		;FTP SAYS THE DEFAULT IS TELNET+2
	SKIPE SNDRCV		;DIRECTION OF TRANSFER?
	ADDI B,1		;MAKE RIGHT SEX. NOT NEEDED BY GTJFN..
	MOVEI C,10		;OCTAL NUMBER
	NOUT
	  PUSHJ P,BOMB
	HRROI B,[ASCIZ /.;T/]	;NO EXTENSION, MAKES A LISTENER.
	MOVEI C,0
	SOUT
	MOVSI A,1		;SHORT FORM JFN
	HRROI B,GTJSTR		; ..
	GTJFN
	  JRST NODJFN		;CAN'T GET IT?
	MOVEM A,DATJFN		;STORE JFN
DFRK00:	SKIPG B,$BYTE2		;WAS A BYTE SIZE STATED?
	MOVEI B,10		;NO. DEFAULT IS EIGHT-BIT BYTES
	MOVEM B,$BYTE2		;STORE BACK IN CASE DEFAULT
	LSH B,36		;PUT IT IN LEFT 6 BITS
	TLO B,(5B9)		;BUFFERED SEND
	TRO B,200000		;ASSUME LISTENING.
	SKIPE SNDRCV		;WHICH DIRECTION?
	TRC B,300000		;SENDING. CHANGE TO WRITE.
	OPENF			;MAKE IT LISTEN
	  JRST NODJF2		;DIED ALREADY.
	MOVEI X,DWTIME		;SECONDS TO WAIT FOR ACTION HERE.
DATW1:	MOVEI A,^D1000		;WAIT A SECOND
	DISMS
	MOVE A,DATJFN		;SEE WHAT CONNECTION STATE IS
	CALL SGDSTS		;CALL THE SIMULATED GDSTS ROUTINE
	HLRZ A,B		;GET STATE, LEFT 4 BITS.
	ANDI A,740000		; ..
	CAIN A,(<FSRFCR>B3)	;WHEN CONNECTION REQUEST COMES IN,
	JRST DFRK01		;THIS IS THE STATE IT GOES TO.
	SOJG X,DATW1		;NOT YET. COUNT DOWN TIMER.
NODJF2:	CLOSE DATJFN		;COMMON ERROR RETURN HERE
NODJFN:	SETOM SOC255		;NO SOCKET NUMBER
	MSG <
? Can't open the data connection.
>
	SETOM F.TCLS		;REQUEST TELNET CLOSEDOWN
	HALTF
	JRST .-1		;END OF DATA FORK ON DISASTER.
DFRK1X:	MSG <
? Paged mode transfer must be 36-bit bytesize.
>
	HALTF
	JRST .-1
DFRK2X:	MSG <
? Paged mode SENDs must be from DSK files.
>
	HALTF
	JRST .-1

SGDSTS:				;ROUTINE TO SIMULATE GDSTS
	STKVAR <SKTSTS,<SGDSTD,<.NCSIZ-.NCFHS+1>>> ;STORAGE
	MOVE B,A		;PUT JFN INTO CORRECT AC
	MOVEI A,.GTNJF		;NETWORK JFN FUNCTION
	MOVEI C,SGDSTD		;GET ADDRESS OF DATA AREA
	MOVX D,<-<.NCSIZ-.NCFHS+1>,,.NCFHS> ;WORDS THAT WE WANT
	GTNCP%			;GET INFORMATION ABOUT THE JFN
	 ERCAL BOMB		;ON ERROR DIE
	MOVE A,B		;GET JFN IN RIGHT PLACE
	SETZM SKTSTS		;ZERO SOCKET STATUS WORD
	MOVE B,<.NCFSM-.NCFHS>+SGDSTD ;GET CONNECTION STATE
	DPB B,[POINT 4,SKTSTS,3] ;PUT FSM STATE IN BITS 0-3
	MOVE B,<.NCSIZ-.NCFHS>+SGDSTD ;GET THE BYTE SIZE
	DPB B,[POINT 6,SKTSTS,17] ;PUT BYTE SIZE IN CORRECT PLACE
	MOVE B,SKTSTS		;GET THE STATUS WORD FOR THE CALLER

	MOVE C,<.NCFHS-.NCFHS>+SGDSTD ;GET 4N HOST NUMBER
	MOVE D,<.NCFSK-.NCFHS>+SGDSTD ;GET 4N SOCKET NUMBER
	RET			; RETURN TO CALLER
;MORE OF DATA FORK. HERE WHEN RFC RECEIVED ON LISTENING DATA SKT.

DFRK01:	HLRZ A,B		;SEE IF THE BYTE SIZE MATCHES
	ANDI A,77		; ..
	CAME A,$BYTE2		; ..
	JRST NODJF4		;NOT RIGHT BYTE SIZE
	CAME C,FHSTN		;AND THE FOREIGN HOST TOO.
	JRST NODJF3		;DOESN'T MATCH. FLUSH IT.
	MOVEM D,SOCRFC		;RFC SOCKET NUMBER.
	SUBI D,2		;SEE IF SOCKET IS THE DEFAULT
	TRZ D,1			;IGNORE SEX OF SOCKET
	CAMN D,FORNS		;MATCH?
	JRST DFRK03		;YES. DON'T WAIT FOR 255 REPLY
DATW2:	SKIPLE SOC255		;HAS A 255 SOCKET REPLY COME IN?
	JRST DFRK02		;YES. CHECK IT OUT
	MOVEI A,^D1000		;NO. WAIT ANOTHER SECOND FOR IT.
	DISMS
	SOJG X,DATW2		;SEE IF IT'S HERE NOW
	MSG <
(No socket verification received. Proceeding anyway.)
>
	JRST DFRK03		;GO DO THE TRANSFER

DFRK02:	MOVE D,SOC255		;GET THE 255 REPLY NUMBER
	XOR D,SOCRFC		;COMPARE WITH RFC SOCKET
	TRZ D,1			;IGNORING SEX BIT
	JUMPE D,DFRK03		;GO TRANSFER IF THEY MATCH
	MSG <
Socket verification does not match.
>
	JRST NODJF2		;QUIT ON THIS ERROR.

DFRK03:	SKIPN F.VBOS		;WANT COMMENTS?
	JRST DFRK3A		;NO
	MSG <(Accepting data connection, socket >
	MOVEI A,101
	MOVEI C,10
	MOVE B,SOCRFC
	NOUT
	  JFCL
	HRROI B,[ASCIZ /, host /]
	MOVEI C,0
	SOUT
	MOVE B,A		;PUT POINTER IN CORRECT PLACE
	MOVEI A,.GTHNS		;HOST NAME FUNCTION
	MOVE C,FHSTN		;GET THE 4N HOST NUMBER
	GTHST%			;OUTPUT THE HOST NAME
	 ERJMP [MOVE A,B	;PUT BYTE POINTER IN CORRECT PLACE
		MOVE B,FHSTN	;GET THEE 4N HOST NUMBER
		MOVEI C,10	;USE OCTAL
		NOUT		;OUTPUT HOST NUMBER IN OCTAL
		 ERCAL BOMB	;ON ERROR DIE
		MOVE B,A	;PUT POINTER WHERE CODE EXPECTS IT
		JRST .+1]	;REJOIN CODE
	MOVE A,B		;PUT POINTER BACK IN CORRECT PLACE
	MSG <.)
>
DFRK3A:	AOS F.DOPN		;FLAG OPENING CONNECTION
	MOVE A,DATJFN		;NOW WILLING TO OPEN THE CONNECTION.
	MOVEI B,20		;ACCEPT THE RFC
	MTOPR			; ..
	SKIPN SNDRCV		;WHICH WAY?
	JRST RECEIV		;RECEIVE FROM SERVER
	JRST DSEND		;SEND TO SERVER

NODJF3:	MSG <Data connection from wrong host.
>
	JRST NODJF2
NODJF4:	MSG <Data connection not right byte size.
>
	JRST NODJF2
;SEND PROCESS

DSEND:	HRRZ A,LCLJFN		;SEE IF ITS A DISK
	DVCHR
	TLNN B,777		; ..
	JRST SNDDSK		;YES.
DSNDL1:	HRRZ A,LCLJFN
	BIN
	JUMPN B,DSND1
	GTSTS
	TLC B,600000
	TLNE B,601000
	JRST SNDEOF
	MOVEI B,0
DSND1:	MOVE A,DATJFN
	BOUT
	AOS NBYTES
	JRST DSNDL1

SNDEOF:	SETO A,			;UNMAP FILE PAGES, IF ANY
	MOVE B,[400000,,<WINDOW/1000>]
	MOVEI C,0		;JUST ONE PAGE
	PMAP
	ADDI B,1
	PMAP
	HRRI B,<WINDW2/1000>
	PMAP
	ADDI B,1
	PMAP
	MOVE A,DATJFN
	HRLI A,(1B1)		;WAIT FOR OTHER END TO SEE CLOSE
	CLOSF
	  JFCL
	SETOM DATJFN
	HALTF
	JRST .-1
SNDDSK:	HRRZ A,LCLJFN
	MOVSI B,LFDB
	MOVEI C,FDB
	GTFDB
	TLNE F,L.TYPX		;PAGED TRANSFER WANTED?
	JRST SNDTYX		;YES.
	LDB D,[POINT 6,FDB+11,11]	;BYTE SIZE
	SKIPN D			;IN CASE BAD
	MOVEI D,44
	MOVEI B,44
	IDIVI B,(D)		;B GETS BYTES PER WORD
	MOVE C,FDB+12		;AND C GETS BYTES, IN WRITER'S SIZE
	IDIVI C,(B)		;GET WRITER'S WORDS
	SKIPE D
	ADDI C,A		;AND PARTIAL WORD, IF ANY
	MOVEM C,NWORDS		;REAL NUMBER OF WORDS
	SETZM PAGENO		;STARTS AT PAGE 0
	RFBSZ			;SEE WHAT SIZE FILE IS NOW OPEN IN
	JFCL			;ERROR RETURN.  SHOULD NOT HAPPEN
	ANDI B,77		;IN CASE JUNK
	MOVE C,B		;COPY
	ROT B,-14		;TO BYTE SIZE PLACE IN BYTE PTR
	IOR B,[440000,,WINDOW]	;MAKE POINTER TO WINDOW PAGE
	MOVEM B,IBPTR		;SAVE IT
	MOVEI B,44		;FIND CONVERSION TO LOCAL BYTES PER WD
	IDIVI B,(C)		; ..
	MOVEM B,LCLBPW		;SAVE THAT.
SNDDL1:	MOVS A,LCLJFN		;MAP IN A PAGE OF FILE
	HRR A,PAGENO
	MOVE B,[400000,,<WINDOW/1000>]
	MOVSI C,(1B2)		;READABLE
	PMAP
	MOVE A,$TYPE3		;SEE IF IMAGE
	MOVE B,$BYTE3		;AND NOT 36 BIT
	CAIE B,44
	CAIE A,TYPE.I
	SKIPA			;SIMPLE CASE
	JRST SNDIMG		;HAVE TO SHUFFLE BITS
	MOVE A,DATJFN		;SEND THE DATA
	MOVE B,IBPTR
	MOVE C,NWORDS
	CAIL C,1000
	MOVEI C,1000		;UP TO A PAGE
	MOVNS C
	ADDM C,NWORDS		;UPDATE COUNT, MAKE - FOR SOUT
	IMUL C,LCLBPW		;SCALE FOR WORDS TO BYTES
	MOVN D,C		;+ BYTES
	ADDM D,NBYTES		;COUNT THEM
	SOUT
SNDDNP:	AOS PAGENO		;SEND DISK NEXT PAGE
	SKIPLE NWORDS		;MORE TO GO?
	JRST SNDDL1		;YES
	JRST SNDEOF		;NO.
;ROUTINE TO SHUFFLE BITS TO SEND IMAGE IN NON-36 BIT BYTES

SNDIMG:	MOVSI A,-1000		;PROCESS A PAGE
	MOVSI B,-10		;STATE COUNTER
	MOVE C,[-2000,,WINDW2-1]	;POINTER TO OUTPUT OF THIS RTN
SNDIM1:	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
	  MOVSI B,-10		;RESTART IT
	AOBJN A,SNDIM1		;LOOP FOR WHOLE PAGE
	MOVE C,NWORDS		;NUMBER OF WORDS TO TRANSFER
	CAIL C,1000		;WITH A MAX OF 1000
	MOVEI C,1000		; ..
	MOVNS C			;NEGATIVE FOR SOUT
	ADDM C,NWORDS		;AND COUNT DOWN TOTAL LEFT
	IMULI C,11		;CONVERT TO BYTES
	ASH C,-3		;THIS MANY IF 32 BIT
	MOVE B,$BYTE3		;IS IT EIGHT BIT?
	CAIG B,10		; ..
	ASH C,2			;YES. THIS MANY BYTES TO GO OUT
	MOVN D,C		;MAKE IT PLUS AGAIN
	ADDM D,NBYTES		;FOR THE COUNT SUMMARY
	LSH B,30		;BYTE SIZE FOR SOUT POINTER
	IOR B,[440000,,WINDW2]	; ..
	HRRZ A,DATJFN		;CONNECTION JFN
	SOUT			;SEND IT
	JRST SNDDNP		;SEND DISK, NEXT PAGE.

;TABLES FOR IN AND OUT IMAGE 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>
;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.

PGCKSS:	MOVN B,TYXHDR		;LENGTH FROM NET
	HRLZ B,B		;MOKE AOBJN POINTER
	HRRI B,TYXHDR+1		;FIRST WORD OF HDR AFTER ITS LENGTH
	JRST PGCKS1		;JOIN SENDER ROUTINE

PGCKSM:	MOVSI B,-TYXHDN		;LENGTH OF HEADER I AM GOING TO SEND
	HRRI B,TYXHED		;AND WHERE IT IS.
PGCKS1:	MOVEI A,0		;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
	AOJE A,CPOPJ		;MAKE -0 INTO +0
	SOJA A,CPOPJ		;WASN'T -0, CORRECT AND RETURN
;SEND DIRECTION, FROM DISK FILE, PAGED MODE.

SNDTYX:	SETOM PAGENO		;SET WINDOW PAGE NUMBER TO ZERO-1
STX001:	AOS A,PAGENO		;NEXT PAGE TO CONSIDER
STX003:	HRRZM A,PAGNO		;STORE IN HEADER
	HRL A,LCLJFN		;PAGE POINTER
	RPACS			;FIND THE ACCESS FOR THE PAGE
	MOVEM B,ACCESS		;STORE IN CASE IT EXISTS, IN HDR.
	TLNN B,(1B5)		;DOES PAGE EXIST?
	JRST STX002		;NO. GO SEE IF ANY MORE.
	MOVE B,[400000,,<WINDOW/1000>]
	MOVSI C,(1B2)		;MAP IT IN FOR READING
	PMAP
	SETZM RECTYP		;THIS IS A DATA RECORD
	MOVEI A,1000		;IT IS A PAGE LONG
	MOVEM A,TYXNDW		;STORE IN HEADER
	ADDM A,NBYTES		;AND COUNT IN TRANSFER LENGTH
	PUSHJ P,STXPP1		;SEND THIS PAGE
	JRST STX001		;LOOK AT NEXT PAGE

STX002:	FFUFP			;ARE THERE ANY MORE PAGES?
	  JRST STX004		;NO.
	HRRZM A,PAGENO		;YES, SAVE THE PAGE NUMBER FOUND
	JRST STX003		;AND GO GET IT.
STX004:	PUSHJ P,STXEOF		;LAST PAGE HANDLED. SEND FDB
	JRST SNDEOF		;AND CLOSE OUT.

STXEOF:	SETZM ACCESS		;CLEAR ACCESS AND PAGE NUMBER
	SETZM PAGNO		; ..
	MOVNI A,3		;CODE FOR EOF IS -3
	MOVEM A,RECTYP		;TO HEADER
	SETO A,			;CLEAR WINDOW PAGE
	MOVE B,[400000,,<WINDOW/1000>]
	MOVEI C,0		;JUST ONE PAGE
	PMAP
	MOVSI A,FDB		;COPY THE FDB TO THE WINDOW
	HRRI A,WINDOW		; ..
	BLT A,WINDOW+LFDB-1
	MOVEI A,LFDB		;SET THAT AS LENGTH OF DATA
	MOVEM A,TYXNDW		; ..
STXPP1:	AOS A,TYXSCT		;COUNT BUFFERLOADS
	MOVEM A,SEQNO
	SETZM CHKSUM		;COUNT UP THE CHECKSUN
	PUSHJ P,PGCKSM		; ..
	SETCAM A,CHKSUM		;1'S COMP TO CKSUM, WILL ADD TO 0.
	MOVE A,DATJFN		;NOW. SEND THIS STUFF.
	MOVEI B,TYXHDN		;FIRST THE LENGTH
	BOUT
	MOVNI C,TYXHDN		;NOW THAT MANY WORDS OF HDR
	MOVE B,[444400,,TYXHED]	;POINT TO THE DATA
	SOUT
	MOVN C,TYXNDW		;THEN THE DATA
	MOVE B,[444400,,WINDOW]
	SOUT
	POPJ P,0
;RECEIVE DIRECTION AFTER JFN'S ARE BOTH OPEN. SWALLOW THE DATA

RECEIV:	TRZ F,R.RNIL!R.DSK	;ASSUME NOT READING TO NIL
	SETO A,			;GET THE WINDOW PAGE FREE
	MOVE B,[400000,,<WINDOW/1000>]
	MOVEI C,0		;JUST ONE PAGE
	PMAP
	HRRZ A,LCLJFN		;SEE WHAT THE LOCAL DEVICE IS
	DVCHR			; ..
	HLRZ A,B		;GET DEV TYPE FIELD
	ANDI A,777		; ..
	CAIN A,0		;IS IT THE DSK?
	TRO F,R.DSK		;YES.
	CAIN A,15		;NIL DEVICE?
	TRO F,R.RNIL		;YES. FLAG TO SKIP SOUT TO IT.
RCVL1:	TLNE F,L.TYPX		;PAGED TRANSFER?
	JRST RCVTYX		;YES.
	MOVE A,DATJFN		;CONNECTION FROM NET
	MOVE B,$BYTE2		;BYTE SIZE SENT
	MOVE C,$TYPE3		;SEE IF IMAGE STUFF NEEDED
	CAIN C,TYPE.I		;IMAGE TYPE?
	CAIN B,44		;AND NOT WORDS?
	TRZA F,R.IMG		;NO. OK AS IS
	JRST [	TRO F,R.IMG	;FLAG IMAGE PROCESSING
		MOVNI C,1100	;IF 32 BIT BYTES
		CAIG B,10	; OR IS IT EIGHT?
		MOVNI C,4400	;YES. THIS MANY PER PAGE AFTER PACKING
		JRST RCVIM1]	;ONWARD
	MOVNI C,1000
	CAIG B,10
	MOVNI C,4000
RCVIM1:	LSH B,30
	HRRI B,WINDOW-1
	PUSH P,B		;SAVE STARTING BYTE PTR
	PUSH P,C		;AND COUNT
	SIN
	POP P,D			;STARTING COUNT
	POP P,B			;AND POINTER
RCV1:	HRRZ A,LCLJFN		;WHERE TO PUT THE DATA
	SUB C,D
RCV2:	ADDM C,NBYTES		;BYTES TRANSFERRED SO FAR
	MOVNS C			;NEGATIVE FOR SOUT
	TRNE F,R.IMG		;IMAGE PROCESSING NEEDED?
	PUSHJ P,RCVIMC		;YES. CALL IMAGE CONVERTER
	TRNN F,R.RNIL		;DONT WASTE TIME ON NIL
	SOUT
RCVEFQ:	MOVE A,DATJFN		;SEE IF HAVE GOTTEN TO EOF YET
	GTSTS
	TLNE B,600000		;STILL HAPPY?
	TLNE B,400		; ..
	JRST RCVERR		;NO.
	TLNE B,1000		;END OF FILE?
	JRST RCVEOF		;YES
	JRST RCVL1
RCVERR:	MSG <
? Error on network data connection.
>
RCVEOF:	TRNE F,R.DSK		;ON DISK?
	TRNN F,R.IMG		;AND IMAGE PROCESSED?
	JRST RCVEF1		;NO. SKIP THIS.
	CLOSK LCLJFN		;YES. DIDDLE UP THE EOF POINTER
	MOVSI B,7700		;BYTE SIZE FIELD
	MOVSI C,100		;ONE BIT BYTES
	HRRZ A,LCLJFN		; ..
	HRLI A,11		;THIS WORD IN FDB
	CHFDB			;CHANGE IT
	SETO B,
	MOVE C,NBYTES		;NUMBER OF BYTES TRANSFERRED
	IMUL C,$BYTE3		;TIMES BYTE SIZE GIVES BITS
	HRLI A,12		;THIS WORD
	CHFDB			;STORE IN FDB
RCVEF1:	MOVE A,DATJFN		;CLOSE THE DATA CONNECTION
	HRLI A,(1B1)		;WAIT FOR OTHER END TO AGREE
	CLOSF
	  JFCL
	SETOM DATJFN
	SETO A,			;UNMAP FILE PAGES, IF ANY
	MOVE B,[400000,,<WINDOW/1000>]
	MOVEI C,0		;JUST ONE PAGE
	PMAP
	ADDI B,1
	PMAP
	HRRI B,<WINDW2/1000>
	PMAP
	ADDI B,1
	PMAP
	HALTF
	JRST .-1

RTXFER:	MSG <
? Format error from network during paged transfer.
>
	JRST RCVEF1
RTXSQE:	MSG <
? Sequence error from net during paged transfer.
>
	JRST RCVEF1
RTXCKE:	MSG <
? Software-detected checksum error from network during paged transfer.
>
	JRST RCVEF1
;ROUTINE TO SHUFFLE BITS FROM 32 BIT WDS TO 36 BIT WDS

RCVIMC:	TRNN F,R.DSK		;IT IS ON DISK ISNT IT?
	POPJ P,0		;NO. DONT PROCESS IT.
	SETZM WINDW2		;YES. CLEAR THE WINDOW PAGE
	MOVE A,[WINDW2,,WINDW2+1]
	BLT A,WINDW2+777	; ..
	MOVSI A,-1100		;NUMBER OF 32 BIT WORDS IN WINDOW
	MOVSI B,-10		;STATE COUNTER
	MOVE C,[-1000,,WINDW2]	;WHERE 36 BIT WORDS GO.
RCVIC1:	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,RCVIC2		;NEED TO RESET STATE COUNTER?
	MOVSI B,-10		;YES.
	AOBJN A,.+1		;AND STEP AN EXTRA WORD.
RCVIC2:	JUMPL A,RCVIC1		;LOOP IF MORE TO DO
	HRRZ A,LCLJFN		;DONE. SET FOR SOUT.
	MOVE B,[444400,,WINDW2]
	MOVNI C,1000
	POPJ P,0
;RECEIVE IN TYPE X (PAGED) TRANSFER.

RCVTYX:	SETO A,0		;THROW AWAY ANY JUNK IN WINDOW PAGE
	MOVE B,[400000,,<WINDOW/1000>]
	MOVEI C,0		;JUST ONE PAGE
	PMAP
	SKIP WINDOW		;TOUCH IT TO GET A BLANK PAGE
	MOVE A,DATJFN		;NOW GET THE COUNT HEADER OF THE PAGE
	BIN
	JUMPE B,RTXEFQ		;PREMATURE END OF FILE?
	MOVEM B,TYXHDR		;STORE IN SCRATCH AREA
	CAIL B,6		;RANGE CHECK IT
	CAIL B,NTXHDR		;WILL IT FIT IN THIS BUFFER?
	JRST RTXFER		;NO GOOD. FORMAT ERROR
	MOVNI C,(B)		;OK, READ THE HEADER
	MOVE B,[444400,,TYXHDR+1]
	SIN
	JUMPN C,RTXFER		;IF DIDN'T GET IT ALL, FORMAT ERROR
	MOVE C,[TYXHDR+1,,TYXHED] ;COPY IT TO REAL AREA KNOWN LENGTH
	BLT C,TYXHED+TYXHDN-1
	MOVE C,TYXNDW		;GET THE LENGTH OUT OF THE HEADER
	CAIL C,0		;MAKE SURE IT'S REASONABLE
	CAILE C,1000		;UP TO A PAGE
	JRST RTXFER		;FORMAT ERROR
	MOVE B,[444400,,WINDOW]	;OK, READ IT INTO THE WINDOW
	MOVNI C,(C)		;THIS MANY WORDS, NEGATIVE.
	SKIPE C			;ALLOW FOR EMPTY BODY
	SIN
	JUMPN C,RTXFER		;MAKE SURE GOT IT ALL
	AOS C,TYXSCT		;CHECK THE SEQUENCE NUMBER
	CAME C,SEQNO		;DOES IT MATCH SENDER'S?
	JRST RTXSQE		;NO
	PUSHJ P,PGCKSS		;CHECKSUM THE NET HEADER AND DATA
	JUMPN A,RTXCKE		;CHECKSUM ERROR!
	TRNE F,R.DSK		;OK, IT'S GOOD. TO DISK?
	JRST RTXDSK		;YES.
	SKIPE RECTYP		;NO. IS IT A DATA BLK?
	JRST RCVEFQ		;NO, IGNORE IT.
	MOVE C,TYXNDW		;YES. OUTPUT THE DATA TO LOCAL FILE.
	MOVE B,[444400,,WINDOW]	;SET AC'S LIKE NON-PAGED CODE.
	JRST RCV2		;AND REJOIN THAT CODE.
RTXDSK:	MOVN A,RECTYP		;IS THIS DATA OR EOF?
	JUMPE A,RTXDDT		;DISK DATA
	CAIE A,3		;NOT DATA. EOF?
	JRST RCVEFQ		;NO, IGNORE OTHERS FOR GROWTH
RTXEOF:	MOVE A,TYXNDW		;GET LENGTH OF FDB
	CAIL A,25		;LOOK LIKE AN FDB?
	CAILE A,30		; ..
	JRST RTXFER		;NO, SAY FORMAT ERROR
	MOVSI D,-NFDBTX		;YES. SET UP THE FDB
RTXEFL:	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)	; ..
	CHFDB			;PUT IN THE DATA
	AOBJN D,RTXEFL		;LOOP FOR CHANGEABLE WORDS OF FDB
	JRST RCVEFQ		;SHOULD BE EOF NOW.

RTXDDT:	MOVE A,[400000,,<WINDOW/1000>]
				;PUT THE DATA IN THE FILE FROM THE FORK
	MOVE B,PAGNO		;HERE IN THE FILE
	HRL B,LCLJFN		; ..
	MOVSI C,040000		;WRITE ACCESS
	PMAP			;IN IT GOES
   REPEAT 0,<			;INVALID UNDER TOPS20
	MOVE A,B		;NOW SET THE FILE ACCESS
	MOVE B,ACCESS		; ..
	SPACS
	SETO A,0		;AND RELEASE WINDOW IN THE FORK
	MOVE B,[400000,,<WINDOW/1000>]
	MOVEI C,0		;JUST ONE PAGE
	PMAP
   >				;REPEAT 0
	MOVE A,TYXNDW		;COUNT THE TRANSFERRED BYTED
	ADDM A,NBYTES		; ..
	JRST RCVEFQ		;SEE IF ANY MORE.

RTXEFQ:	MOVE A,DATJFN		;GOT A ZERO AS FIRST BIN.
	GTSTS			;SHOULD BE EOF AND LAST THING A DDB
	TLNE B,600000
	TLNE B,400
	JRST RCVERR
	TLNN B,1000		;EOF?
	JRST RTXFER		;NO. SHOULD NOT HAVE A ZERO BYTE HERE.
	MOVN C,RECTYP		;EOF. WAS LAST RECORD THE FDB?
	CAIE C,3		; ..
	JRST RTXFER		;NO. ERROR.
	JRST RCVEF1		;GOOD. FINISH UP.

FDTXT1:	EXP 1,11,12,24		;CAN CHANGE THESE WORDS
NFDBTX==.-FDTXT1
FDTXT2:	400001,,0		;TEMP AND EPHEMERAL BITS
	77B11			;BYTE SIZE
	-1			;EOF
	-1			;AND USER SETTABLE WORD
PREASC:	SETOM $TYPE2		;ENTRY FOR ASCII XFER, LIKE LIST
	SETOM $MODE2		; ..
	SETOM $STRU2
	SETOM $BYTE2
	JRST PREDT1

PREDAT:	MOVE A,[PARAMS,,PARAM2]	;COPY PERMANENT PARAMS
	BLT A,EPAR2		; ..
PREDT1:	SETOM SOC255		;NO SOCKET RESPONSE YET
	SETZM F.ABOR		;CLEAR FORCED ABORT FLAG
	SKIPG B,$TYPE2		;ANY TYPE STATED?
	MOVEI B,0		;NO. DEFAULT
	CAMN B,$TYPE3
	JRST PREDT2
	MOVEM B,$TYPE3		;NEED TO SEND IT
	HLRZ A,TYPTAB(B)	;GET THE CUE CHARACTER
	HRROI B,[ASCIZ /TYPE /]
	CAIN A,"X"		;TYPE X?
	JRST [HRROI A,[ASCIZ /XTP/]
		PUSHJ P,TELSND	;YES, EXPAND X TO XTP
		JRST PREDT2]	;AND ON TO NEXT PARAM.
	PUSHJ P,TELSP		;SEND PARAMETER CHARACTER
PREDT2:	SKIPG B,$STRU2		;STRUCTURE STATED?
	MOVEI B,0		;NO
	CAMN B,$STRU3		;NEW STRUCTURE?
	JRST PREDT3		;NO
	MOVEM B,$STRU3		;YES. UPDATE AND SEND
	HLRZ A,STRTAB(B)	;CUE CHARACTER
	HRROI B,[ASCIZ /STRU /]
	PUSHJ P,TELSP		;SEND PARAMETER
PREDT3:	SKIPG B,$MODE2		;AND SAME FOR MODE ...
	MOVEI B,0
	CAMN B,$MODE3		;NEW MODE?
	JRST PREDT4		;NO
	MOVEM B,$MODE3
	HLRZ A,MODTAB(B)
	HRROI B,[ASCIZ /MODE /]
	PUSHJ P,TELSP
PREDT4:	SKIPG B,$BYTE2		;BYTE SIZE SPECIFIED?
	MOVEI B,10		;SEND THE DEFAULT, SOME DON'T ASSUME 8.
	CAMN B,$BYTE3		;NEW BYTE SIZE?
	JRST PREDT5		;NO
	MOVEM B,$BYTE3		;YES. UPDATE AND SEND
	HRROI A,STRTMP		;YES.
	MOVEI C,12		;MUST CONVERT IT TO A STRING FOR SENDER
	NOUT
	  PUSHJ P,BOMB
	HRROI B,[ASCIZ /BYTE /]	;THE FTP DIRECTIVE
	HRROI A,STRTMP		;AND THE VALUE
	PUSHJ P,TELSND		;SEND IT OUT
PREDT5:	POPJ P,0
;ODDS AND ENDS

BOMB:	HRROI A,[ASCIZ /
? "IMPOSSIBLE ERROR" IN FTP USER PROCESS AT LOCATION /]
	PSOUT
	HRRZ B,0(P)
	SUBI B,1
	MOVEI A,101
	MOVEI C,10
	NOUT			;TYPE ERROR LOC IN OCTAL
	  PUSHJ P,BOMB
HALTGO:	HALTF			;HALT AND RESTART
	JRST GO

CRLFM:	ASCIZ /
/

TYIAZ:	PUSHJ P,TYI		;TYI, GETTING LEGAL COMMAND CHARACTER
	CAIG A,"Z"
	CAIGE A,"A"
	SKIPA
	JRST CPOPJ1		;LETTER
	CAIE A,"."
	CAIN A,"-"
	JRST CPOPJ1		;ALLOWED PUNCTUATION
	CAIG A,"9"
	CAIGE A,"0"
	POPJ P,0		;NOT LEGAL
	JRST CPOPJ1		;OK.

   REPEAT 0,<		;USE RDTTY UNDER TOPS20
TYI:	PUSH P,A		;WRONG AC
	PBIN
	MOVE C,A
	POP P,A
	CAIE C,0
	CAIN C,15
	JRST TYI
	CAIN C,EOL
	MOVEI C,C.LF
	POPJ P,0
   >				;REPEAT 0

;BUFFERED TTY INPUT

;CLEAR LINE BUFFER

LINCLR:	MOVEI A,NLINBF*5	;INIT COUNT
	MOVEM A,INLINS
	SETZM INLINC
	MOVE A,[POINT 7,LINBUF]	;INIT PTR
	MOVEM A,INLINP
	POPJ P,

;GET A CHAR

TYI:	SOSGE INLINC		;GOT ANY?
	JRST [	PUSHJ P,TYI1	;NO, GET MORE
		 POPJ P,	;LOSE
		JRST TYI]	;TRY AGAIN
	ILDB C,INLINP		;GET CHAR, RETURN IN C
	RET

;REFILL BUFFER

TYI1:	SAVEAC <A,B>		;PRESERVE ALL
	MOVE A,INLINP		;CURRENT POINTER
	MOVE B,INLINS		;CURRENT REMAINING SPACE
	TXO B,RD%BRK+RD%TOP+RD%PUN+RD%CRF+RD%RND
	SETZ C,
	RDTTY
	 JSHLT
	TXNE B,RD%BFE		;DELETED ALL?
	JRST [	MOVEI C,CDELLN	;YES, RETURN CODE
		POPJ P,]
	HRRZ B,B		;GET UPDATED SPACE COUNT
	EXCH B,INLINS		;SAVE IT, GET OLD
	SUB B,INLINS		;COMPUTE NUMBER CHARS JUST READ
	MOVEM B,INLINC		;SAVE IT
	RETSKP			;ALL SET

PCRLF:	HRROI A,CRLFM
	PSOUT
	POPJ P,0
SST1:	MOVE C,LASTCC		;CHECK LAST COMMAND CHAR
	CAIE C,C.ESC		;ESCAPE?
	JRST SST		;NO. USE IT.
				;YES. FALL INTO SSST, SKIPPING ESC.
SSST:	PUSHJ P,GCH
	 JFCL
SST:	MOVE C,LASTCC		;GET THE CHAR LAST TYPED IN
	CAIE C,40		;SPACE?
	CAIN C,11		;TAB?
	JRST SSST		;YES. DISCARD
	JUMPE C,SSST		;ALSO NULLS IN INITIALIZATION.
	MOVEM C,GCHSAV		;NO. SAVE SO GCH SEES IT NEXT.
	POPJ P,0		;RETURN

OCTIN:	TRZ F,R.CHOK		;NO OK CHARS SEEN
	SETZM WORDXP		;IN CASE OF ESC.
	PUSHJ P,SST		;SKIP TO NON-BLANK.
	MOVEI A,0		;CLEAR ANSWER
OCTINL:	PUSHJ P,GCH		;GET A CHARACTER
	CAIL C,"0"		;OCTAL DIGIT?
	CAILE C,"7"		; ..
	JRST OCTINX		;NO
	TRO F,R.CHOK		;YES. SEEN AT LEAST ONE.
	LSH A,3			;ACCUMULATE OCTAL NUMBER
	ADDI A,-"0"(C)		; ..
	JRST OCTINL
OCTINX:	CAIN C,CDELLN		;RUBOUT?
	POPJ P,0		;YES. FAIL RETURN
	TRZE F,R.CHOK		;OK CHAR SEEN?
	AOS 0(P)		;YES.
	POPJ P,0		;RETURN

DECIN:	PUSHJ P,SST
DECIN1:	SETZM WORDXP		;IN CASE OF ESC
	TRZ F,R.CHOK		;NO CHARS SEEN YET THAT ARE DIGITS
	MOVEI A,0		;START NUMBER AT 0
DECINL:	PUSHJ P,GCH		;READ A CHAR
	CAIL C,"0"		;DIGIT?
	CAILE C,"9"		; ..
	JRST OCTINX		;NO. SAME EXIT AS OCTAL.
	TRO F,R.CHOK		;OK, SEEN A DIGIT
	IMULI A,12		;ACCUMULATE DECIMAL NUMBER
	ADDI A,-"0"(C)		; ..
	JRST DECINL		;GET NEXT DIGIT OR BREAK
;SUBROUTINE TO SEND STUFF ON THE TELNET CONNECTION

TELSND:	HRLI A,440700
	HRLI B,440700		;MAKE ILDB POINTERS
	PUSH P,A
	PUSH P,B		;STACK THEM
	MOVE A,SJFN
TELSL1:	ILDB B,0(P)		;GET A CHARACTER
	JUMPE B,TELSN1
	BOUT
	JRST TELSL1
TELSN1:	ILDB B,-1(P)
	JUMPE B,TELSN2
	BOUT
	JRST TELSN1
TELSN2:	MOVEI B,C.CR
	BOUT
	MOVEI B,C.LF
	BOUT
	MOVEI B,21		;SEND ACCUMULATED BUFFER
	MTOPR			; ..
	JRST BAPOPJ		;RESTORE ACS B AND A, RETURN

;SUBROUTINE TO CLOSE OPEN CONNECTIONS

TCLOSE:	HRROI A,[ASCIZ / (Closing previous connection.) /]
	SKIPE F.TOPN		;IS TELNET CONNECTION OPEN?
	PSOUT
TCLOS1:	SKIPLE A,RFORKH
	KFORK
	SKIPLE A,DFORKH
	KFORK
	SKIPL A,RJFN
	CLOSF
	  JFCL
	SKIPL A,SJFN
	CLOSF
	  JFCL
	SETOM RJFN
	SETOM SJFN
	SETOM RFORKH
	SETOM DFORKH
	SETZM F.TOPN		;TELNET CONNECTION NOT OPEN.
	SETZM F.TCLS		;REQUEST FOR CLOSE HAS BEEN SATISFIED
	SETOM PARAM3		;SAY HAVE SENT NO PARAMS
	MOVE A,[PARAM3,,PARAM3+1]
	BLT A,PARAM3+NPARS-1
	POPJ P,0
;SUBROUTINE TO SEND A LETTER-PARAM TO TELNET CONN
;CALL:	A/ THE CHARACTER
;      B/THE KEYWORD ADDRESS

TELSP:	SETZM STRTMP
	DPB A,[POINT 7,STRTMP,6]
	HRROI A,STRTMP
	JRST TELSND		;MOSTLY JUST USE TELSND ROUTINE

TSIN:	TROA F,R.SPTC		;SPACE IS A TERM CHAR
TSIN1:	TRZ F,R.SPTC		;THIS ENTRY, ITS A DATA CHARACTER
	MOVEM X,TSINIX		;SAVE INITIAL COUNT
	SETZM WORDXP		;MAKE SURE ESC DOES NOTHING WIERD
	TRZ F,R.QUOC		;NOT QUOTING
TSINL:	PUSHJ P,GCH		;GET A CHARACTER
	  JFCL
	TRZE F,R.QUOC		;QUOTE CHAR LAST?
	JRST TSIN3		;YES. NO CHECKS.
	CAIE C,"V"&77		;QUOTE CHAR?
	JRST TSIN2		;NO
	TRO F,R.QUOC		;YES. NOTE,
	JRST TSINL		;AND GET ANOTHER CHAR.
TSIN2:	TRNE F,R.SPTC		;WHAT IS A SPACE?
	CAIE C,40		;TERM. AND IS THIS A SPACE?
	SKIPA			;NOT A BREAK
	JRST TSINX		;BREAK. DO SO.
	CAIE C,C.ESC		;ESCAPE?
	CAIN C,C.LF		;ONE OF THE END-OF-LINES?
	JRST TSINX		;CONTROL. BREAK.
	CAIN C,CDELLN		;RUBOUT?
	POPJ P,0		;YES. QUIT NON-SKIP
   REPEAT 0,<
	CAIN C,"A"&77		;CONTROL A
	JRST TSINA		;YES. DELETE A CHAR.
	CAIN C,"X"&77		;CONTROL X?
	JRST TSINDW		;YES. DELETE WORD.
   >				;REPEAT 0
TSIN3:	IDPB C,BP		;PUT AWAY THE CHAR
	SOJG X,TSINL		;END TEST
	POPJ P,0		;FAILED END TEST LENGTH

TSINX:	MOVEM C,LASTCC		;STASH THE CHARACTER
	MOVEM C,BREAKC		; ..
	MOVEI A,0		;AND TERMINATE STRING WITH A NULL
	IDPB A,BP		; ..
	JRST CPOPJ1		;GOOD RETURN
   REPEAT 0,<
TSINA:	CAML X,TSINIX		;X ALREADY AT MAX?
	JRST DING		;YES
	MOVEI A,"\"		;PREFIX DELETED CHAR
	PBOUT			; ..
	LDB A,BP		;GET THE DISCARD CHARACTER
	TRNN F,R.NOEC		;UNLESS PASSWORD,
	PBOUT			;TYPE IT
	PUSHJ P,TSINBK		;BACK A CHAR
	JRST TSINL		;GET ANOTHER CHAR
TSINDW:	CAML X,TSINIX		;AT BEGINNING?
	JRST DING		;YES
	HRROI A,[ASCIZ /_
/]
	PSOUT
   >			;REPEAT 0
TSINDL:	CAML X,TSINIX
	JRST TSINL
	PUSHJ P,TSINBK
	JRST TSINDL
DING:	MOVEI A,7
	PBOUT
	JRST TSINL
TSINBK:	MOVEI C,0
	DPB C,BP
	ADD BP,[7B5]
	SKIPGE BP
	SUB BP,[430000,,1]
	AOJA X,CPOPJ

KEYLTR:	PUSHJ P,SST
	PUSHJ P,GCH		;NOW READ THE CHARACTER
	  JFCL			;SYMBOL CONST OR NOT, WHO CARES.
	CAIN C,CDELLN
	POPJ P,0		;RUBOUT RETURN
	CAIL C,140		;LOWER CASE?
	TRZ C,40		;MAKE UPPER
	MOVEI D,0		;INDEX ANSWER TO 0
KEYLTL:	HLRZ B,0(X)		;GET GOOD ANSWER
	CAMN B,C		;MATCH?
	JRST KEYLT1		;YES.
	ADDI D,1		;NO. TRY NEXT ONE
	AOBJN X,KEYLTL		; ..
	POPJ P,0		;NOT THERE.
KEYLT1:	HRRZ B,0(X)		;DISPATCH ADDRESS IS AN ANSWER TOO
	PUSHJ P,GCH		;AND AN EOL, HOPEFULLY.
	  JFCL			;SYM OR TERM
	CAIE C,C.LF		;LEGAL TERM?
	CAIN C,C.ESC		; ..
	JRST CPOPJ1		;YES
	POPJ P,0		;NO. ERROR RETURN
;PARAMETER SETTING COMMANDS

.TYPE:	NOISE < (key letter) >
	MOVE X,[-NTYPES,,TYPTAB]
	PUSHJ P,KEYLTR
	  JRST XXXCOM
	JRST 0(B)
TYPE$A:
TYPE$X:
TYPE$L:
TYPE$I:	HRRZM D,$TYPE
	JRST CPOPJ1
TYPE$E:
TYPE$P:	MSG <
? type not implemented>
	JRST CRCOM

.MODE:	NOISE < (key letter) >
	MOVE X,[-NMODES,,MODTAB]
	PUSHJ P,KEYLTR
	  JRST XXXCOM
	JRST 0(B)
MODE$S:
	HRRZM D,$MODE
	JRST CPOPJ1
MODE$B:
MODE$T:
MODE$H:	MSG <
? mode not implemented>
	JRST CRCOM
.STRU:	NOISE < (key letter) >
	MOVE X,[-NSTRUS,,STRTAB]
	PUSHJ P,KEYLTR
	  JRST XXXCOM
	JRST 0(B)
STRU$F:	HRRZM D,$STRU
	JRST CPOPJ1
STRU$R:	MSG <
? RECORD structure not implemented>
	JRST CRCOM

.FORM:	NOISE < (key letter) >
	MOVE X,[-NFORMS,,FRMTAB]
	PUSHJ P,KEYLTR
	  JRST XXXCOM
	JRST 0(B)

FORM$U:	HRRZM D,$FORM
	JRST CPOPJ1
FORM$P:	MSG <
? Print Format not implemented.>
	JRST CRCOM

CLOSER:	SKIPGE 0(A)
	POPJ P,0		;NO JFN THERE
	PUSH P,A
	PUSH P,B
	HRRZ A,0(A)
	GTSTS
	JUMPGE B,[	RLJFN
			  JFCL
			JRST CLOSR1]
	CLOSF
	  JFCL
CLOSR1:	POP P,B
	POP P,A
	SETOM 0(A)
	POPJ P,0

CLOSEK:	SKIPGE 0(A)
	POPJ P,0
	PUSH P,A
	HRRZ A,0(A)
	HRLI A,400000
	CLOSF
	  JFCL
	POP P,A
	POPJ P,0
;SUBROUTINE TO MAKE AN INFERIOR. RETURNS HANDLE IN X.

MAKFRK:	MOVSI A,(1B1)		;PASS ON CAPABILITIES
	CFORK			;MAKE THE FORK
	  POPJ P,0		;CAN'T
	MOVEM A,THISFK		;SAVE THE FORK HANDLE AS SEEN FROM TOP
	rpcap			;make it legal to psi the superior
	tlo b,(1b9)		; ..
	tlo c,(1b9)		; ..
	epcap
	MOVE X,A		;COPY FOR RETURN FROM THIS ROUTINE
IFN DEBUG,<
	MOVE A,[400000,,770]	;IS DDT PRESENT?
	RPACS			; ..
	TLNE B,(1B5)
	SKIPA D,[-777770]	;YES. PRETEND STORAGE RUNS TO TOP
>
	MOVNI D,GSTOP		;TOP OF GLOBAL STORAGE. ABOVE CODE.
	LSH D,11		;IN PAGES
	HRRI D,0		;- # PAGES,,0
MKFKL1:	MOVEI A,0(D)		;POINTER TO PAGE IN TOP FORK
	HRLI A,400000		; ..
	HRLZ B,X		;INFERIOR HANDLE
	HRR B,A			;SAME PAGE
	MOVSI C,160000		;ALL ACCESS
	PMAP			;CREATE THE PAGE IN INFERIOR
MKFKN1:	AOBJN D,MKFKL1		;LOOP FOR WHOLE COMMON CODE
	MOVNI D,PSTOP-PSBAS	;LENGTH OF PROCESS PRIVATE STUFF
	LSH D,11		;IN PAGES
	HRRI D,<PSBAS_<-11>>	;WHERE IT STARTS
MKFKL2:	SETO A,0		;MAKE PAGE GO AWAY IN INFERIOR
	SETZ C,0		; ..
	MOVSI B,(X)		;FORK HANDLE
	HRRI B,(D)		;PAGE NUMBER
	PMAP			;ALL GONE
	MOVSI B,400000		;NOW LET GO OF IT IN TOP FORK
	HRRI B,(D)		; ..
	SETO A,
	MOVEI C,0		;JUST ONE PAGE
	PMAP
	AOBJN D,MKFKL2		;FOR ALL PRIVATE PAGES
	JRST CPOPJ1
;CONSTANTS

PDP:	IOWD PDLL,PDL
GPDP:	IOWD PDLL,GPDL		;GLOBAL (TOP-LEVEL) STACK
WRDBP0:	010700,,WORDBF-1	;INITIAL POINTER TO WORD BUFFER
LEVTAB:	RETPC1
	RETPC2
	RETPC3
CHNTAB:	3,,NTIINT
NTICHN==.-1-CHNTAB
	3,,CGINT		;BELL TYPED
CGICHN==.-1-CHNTAB
	3,,COINT		;CONTROL O INTERRUPT
COICHN==.-1-CHNTAB
	3,,ABOINT		;IIC FROM TELNET TO TOP
ABOCHN==.-1-CHNTAB
	REPEAT 44+CHNTAB-.,<0>
CHNMSK:	EXP <1B<NTICHN>!1B<ABOCHN>!1B<CGICHN>!1B<COICHN>>

FTPSKT:	FTPICS			;PROTOCOL ICP SOCKET #
USRSKT:	USRSKN			;USER SOCKET NUMBER U BEFORE JOB #

PATCHX=VERSIO			;KEEP TRACK OF PATCHES IN THE VERSION NUMBER

PATCH:
PAT:	BLOCK 400

PMASK:	ASCII /
Your Password/
	BYTE (7) 15,43,43,43,43
	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.....
/
;MACROS FOR THE PARAMETER VALUES AND TABLES
;THESE MATCH THOSE IN FTPSRV. THE DEFAULT IS BY DEFINITION THE FIRST
;ENTRY IN EACH TABLE

DEFINE KM (A,B)<
ZZ==0
IRP B,<
	XWD "B",A'$'B
A'.'B==ZZ
ZZ==ZZ+1
>
N'A'S==ZZ
>

TYPTAB:	KM (TYPE,<A,E,I,L,P,X>)
STRTAB: KM (STRU,<F,R>)
MODTAB: KM (MODE,<S,B,T,H>)
FRMTAB:	KM (FORM,<U,P>)
;STORAGE AREAS

PS WORDXP,1			;ARGUMENT TO GETWRD. -N,,TABLE OF ASCIZ
PS RECX,1			;INDEX WHEN WORD FOUND BY RECOG
PS BREAKC,1			;CHARACTER AFTER WORD
PS LASTCC,1			;LAST CHAR READ BY GCH.
PS WORDBP,1			;POINTER INTO WORD STRING STORAGE
PS WORDBF,40			;WORD STORAGE
EWORDB=PSPC-1
PS CCHCNT,1			;COUNT OF CHARS FAKED BY ESCAPE
PS GCHSAV,1			;SAVED CHAR (ESC) TO READ AT GCH
PS INLINC,1			;INPUT LINE COUNT
PS INLINP,1			;INPUT LINE POINTER
PS INLINS,1			;INPUT LINE SPACE
NLINBF==^D30			;SIZE OF LINE BUFFER
PS LINBUF,NLINBF		;LINE BUFFER

GS IRFMOD,1			;WHAT RFMOD GOT AFTER RESET AT GO
GS FCOCB,1			;INITIAL FCOC, ADJUSTED
GS FCOCC,1			; ..
GS LHSTNM,10			;STRING STORAGE OF LOCAL NAME
GS LHOSTN,1			;LOCAL NUMBER
GS FHSTN,1			;FOREIGN HOST NUMBER
GS HOSTX,1			;INDEX INTO HOSTN FOR THAT HOST
GS FORNS,1			;FOREIGN SOCKET SENT ON ICP ("S")
GS SOCRFC,1			;SOCKET REQUESTING DATA RFC
GS SOC255,1			;SOCKET SERVER CLAIMED HE WOULD USE
GS IJFN,1			;ICP JFN
GS SJFN,1			;TELNET SEND JFN
GS RJFN,1			;TELNET RECEIVE JFN
GS DATJFN,1			;DATA NETWORK SOCKET JFN
GS LCLJFN,1			;LOCAL DATA JFN
GS DIRJFN,1			;DIRECTORY JFN IN MULTIPLE GET
GS SNDRCV,1			;0 FOR RCV DATA FROM NET, ELSE SEND.
GS F.TOPN,1			;TELNET CONNECTION OPEN IF THIS NONZERO
GS F.TCLS,1			;REQUEST TO CLOSE FOREIGN CONNECTION
GS F.DTIP,1			;DATA TRANSFER IN PROG (250, NO 252)
GS F.DTDR,1			;DATA TRANS DONE REPLY (252-4) CAME IN.
GS F.DOPN,1			;FLAG TO ASSURE DATA CONN OPENED
GS F.ABOR,1			;TELNET RCVR THINKS DATA SHOULD ABORT
GS F.VBOS,1			;VERBOSE TYPEOUT REQUESTED
GS CGFLAG,1			;BELL TYPED.
GS RFORKH,1			;FORK HANDLE OF TELNET RECEIVER
GS SFORKH,1			;FORK HANDLE OF TELNET SENDER
GS DFORKH,1			;FORK HANDLE OF DATA COPIER
PS THISFK,1			;THIS FORK'S HANDLE

GS FRNPTH,40			;FOREIGN PATHNAME
EFRNPT=GSPC-1
GS FRNPT2,40			;SECOND FOREIGN PATH (RENAME)
EFRNP2=GSPC-1
GS RCVLIN,100			;SPACE FOR THE INCOMING TELNET LINE
ERCVLN=GSPC-1			;END OF SAME
GS REPCOD,1			;REPLY CODE AS A NUMBER
GS REPIDX,1			;AND INDEX INTO REPLY TABLES
PS NTIIA,1			;SAVE AC A HERE IN NTIINT
PS RETPC1,1
PS RETPC2,1
PS RETPC3,1

GS PREFIX,1			;FLAG THERE IS A PREFIX
GS SUFFIX,1			;FLAG THERE IS A SUFFIX
GS PREFXB,40			;STRING STORAGE FOR PREFIX AND SUFFIX
GS SUFFXB,40
GS F.STAR,1			;FLAG TOP LEVEL IS AT LEFT MARGIN TYI
GS FREE,1			;POINTER TO FREE CORE
GS HOSTN,1			;POINTERS TO HOST NUMBERS AND BITS
GS HSTNAM,1			;AND ASCII
;HEADER FOR PAGED TRANSFERS. DO NOT SEPARATE.
GS TYXHED,0			;NAME OF HEADER
GS CHKSUM,1			;CHECKSUM OF HEADER AND DATA
GS SEQNO,1			;SEQUENCE OF DATA AND EOF BLOCKS
GS TYXNDW,1			;NUMBER OF DATA WORDS AFTER THIS HEADER
GS PAGNO,1			;PAGE NUMBER IF THIS IS DATA
GS ACCESS,1			;SPACS ARG IF THIS IS DATA
GS RECTYP,1			;0 FOR DATA, -3 FOR EOF
TYXHDN==6			;LENGTH OF THIS BLOCK
;END OF DO NOT SEPARATE GROUP
GS TYXSCT,1			;SEQUENCE NUMBER FOR PAGED MODE
NTXHDR==40			;LENGTH TO ALLOW ON READING NET
GS TYXHDR,NTXHDR		;MAKE LONGER IN CASE IT GROWS
GS PARAMS,0			;THE DATA TRANSMISSION PARAMETERS
GS $BYTE,1			;TRANSMISSION BYTE SIZE
GS $SOCK,1			;SOCKET NUMBER SERVER WILL CONN TO
GS $HOST,1			;HOST ABOVE SOCKET IS IN
GS $TYPE,1			;TYPE, STRUCTURE AND MODE
GS $STRU,1
GS $MODE,1
GS $FORM,1
EPARAMS==GSPC-1
NPARS==GSPC-PARAMS
;DO NOT SEPARATE ABOVE. CLEARED TOGETHER.
GS PARAM2,0			;COPY DURING ACTUAL TRANSFER
GS $BYTE2,1			;MUST BE SAME ORDER AS ABOVE
GS $SOCK2,1
GS $HOST2,1
GS $TYPE2,1
GS $STRU2,1
GS $MODE2,1
GS $FORM2,1
EPAR2==GSPC-1
;DO NOT SEPARATE ABOVE EITHER
GS PARAM3,0			;LAST ONES SENT OUT
GS $BYTE3,1			;MUST BE SAME ORDER AS ABOVE
GS $SOCK3,1
GS $HOST3,1
GS $TYPE3,1
GS $STRU3,1
GS $MODE3,1
GS $FORM3,1
EPAR3==GSPC-1
;DO NOT SEPARATE ABOVE EITHER

PS STRTMP,100			;A RANDOM STRING SPACE
ESTRTM==PSPC-1
PS TSINIX,1			;INITIAL COUNT FOR TSIN ROUTINE
GS F.HELP,1			;FLAG -1 WHEN DUMMY MSG NOT YET TYPED
GS F.NOST,1			;FLAG NO STATISTICS TO BE TYPED
GS F.NST1,1			;FLAG USER TYPED NOSTAT COMMAND

GS NBYTES,1			;NUMBER OF BYTES IN A TRANSFER
GS NWORDS,1			;NUMBER OF WORDS IN DSK FILE
GS FDB,LFDB			;SPACE FOR DSK FILE FDB
GS PAGENO,1			;PAGE NUMBER TO MAP IN DSK FILE
GS IBPTR,1			;POINTER TO WINDOW PAGE
GS LCLBPW,1			;BYTES PER WORD IN LOCAL FILE AS OPEN
GS CPUTIM,1			;TIMING CELLS
GS DAYTIM,1			; ..
GS PUSER,1			;POINTER TO USER STRING
GS USERBF,20			;USER NAME
EUSRBF=GSPC-1
GS PPASS,1			;SAME FOR PASSWORD
GS PASSBF,20
EPASBF=GSPC-1
GS PACCT,1			;AND ACCOUNT
GS ACCTBF,20
EACTBF=GSPC-1

PS PDL,PDLL
GS GPDL,PDLL
PS GTJSTR,40		;STRING STORAGE FOR GTJFN ARG

PS PSTOP,0
GS GSTOP,0

	END GO