;-*-MIDAS-*-

TITLE	BOJ SLAVE -- MLSLV, Works with MLDEV

.XCREF A,B,C,D,E,TT,I,Q,J,R,W,H,P,T,U

ICPSOC==123			;This is the Postel-approved number

A=1
B=2
C=3
D=4
E=5
T=6
TT=7
I=10
H=11
J=12
Q=13
W=14
P=15
IOP=16
U=17

CH==,,-1	;BIT TYPEOUT MASK FOR CHANNEL NAMES

CHNETI==1
CHNETO==2
CHDEV==4

DEFINE SYSCAL NAME,ARGS
	.CALL [ SETZ ? SIXBIT /NAME/ ? ARGS ((SETZ))]
TERMIN

MAXLOG==20		;MAXIMUM # OF LOGIN TRIES
BUFL==400		;SIZE OF BUFFER.  SENDING TO MLDEV CAN USE FULL SIZE.

DEFINE CHECK TAG,LEN
IFN .-TAG-<LEN>,.ERR WRONG TABLE LENGTH
TERMIN

LOC	42
	JSR TSINT
LOC	100

GO:	.CLOSE 1,			;CLOSE DISK CHANNEL USED FOR LOADING
	.SUSET [.RUNAM,,DEBUG]
	HLLOS DEBUG				;IF WE ARE IN A LOGGED-IN TREE
	AOSN DEBUG				;SOMEONE MUST BE DEBUGGING MLSLV.
	 .SUSET [.SJNAME,,[SIXBIT/MLSLV/]]	;IF NOT DEBUGGING, RECTIFY JNAME
	.CALL [	SETZ
		SIXBIT /SSTATU/
		2000,,A				;IGNORE THE DIE TIME
		SETZM SYSDBG]
	JFCL
	MOVE P,[-LPDL-1,,PDL-1]
	SETZM ALLOC
	SETZM NBFOXF
	SETZM NBFIXF
	MOVE A,[440800,,NBUFO]
	MOVEM A,NBUFOP
	MOVEI A,NBUFL
	MOVEM A,NBUFOC
	.SUSET [.SMASK,,[%PIIOC+%PIRLT+%PIILO+%PIMPV+%PIPDL]]
	MOVE A,[600000,,[60.*60.]]
	SKIPN DEBUG				;IF DEBUGGING, DON'T LIGHT FUSE
	 .REALT A,
	  JFCL
	;Find out what kind of server we're supposed to be
	.SUSET [.RXJNAME,,A]
	CAME A,[SIXBIT/TCP/]
	 JRST CHAICP
TCPICP:	MOVEI A,CHNETI
	MOVEI B,ICPSOC
	PUSHJ P,NETWRK"TCPSRV
	 JSR LOGOUT
	TLZ B,777000		;Clear network number
	TDNN B,[177700000]	;Try to reduce to old-style number
	 TRNE B,374
	  JRST GO1		;Can't
	LDB A,[000200,,B]
	LSH A,6
	LSH B,-9
	IOR B,A
	JRST GO1

CHAICP:	MOVEI A,CHNETI
	MOVEI C,[ASCIZ/MLDEV/]
	MOVEI D,8
	PUSHJ P,NETWRK"CHASRV
	 JSR LOGOUT
GO1:	ANDI B,777		;Kludgey unique number (low 9 bits of host)
	MOVEM B,JOBUSR
	MOVSI D,(SETZ)
	.REALT D,
	JFCL
	JRST GO4		;Start up

;ANY CHANGES IN THIS SHOULD BE REPORTED TO INFO-MLDEV@AI AND 
;UPDATED IN MLSLV ALSO.  NEW VERSION MUST THEN BE UPDATED
;SIMULTANEOUSLY ON ALL ITS'S AND ON MULTICS.

;[Next line is inoperative]
;ICP IS TO SOCKET 197. IF DOING MOSTLY INPUT, 199. IF MOSTLY OUTPUT

;COMMAND FORMAT:	TO SLAVE
;AOBJN POINTER (RH = COMMAND CODE)
;BLOCK OF ARGUMENTS

;COMMAND CODES:
COPENI==1	;OPEN FOR INPUT
		;ARG1:	DEVICE
		;ARG2:	FN1
		;ARG3:	FN2
		;ARG4:	SNAME
		;ARG5:	OPEN MODE

COPENO==2	;OPEN FOR OUTPUT
		;ARG1:	DEVICE
		;ARG2:	FN1
		;ARG3:	FN2
		;ARG4:	SNAME
		;ARG5:	OPEN MODE

CDATA==3	;WRITE DATA (WD COUNT INCLUDES DATA WDS AND BYTE COUNT WD).
		;# OF BYTES OF DATA
		;DATA, PACKED ILDB-STYLE INTO AT MOST 200 WORDS.

CALLOC==4	;READ ALLOCATE
		;ARG:	ALLOCATION IN BYTES

CICLOS==5	;INPUT CLOSE
		;ARG:	IGNORED

COCLOS==6	;OUTPUT CLOSE
		;ARG:	IGNORED

CFDELE==7	;.FDELE (DELETE OR RENAME)
		;ARG1:  DEV
		;ARG2:	FN1
		;ARG3:	FN2
		;ARG4:	0 OR NEW FN1
		;ARG5:	0 OR NEW FN2
		;ARG6:	SNAME

CRNMWO==10	;.FDELE (RENAME WHILE OPEN)
		;ARG1:	NEW FN1
		;ARG2:	NEW FN2

CNOOP=11	;NOOP
		;ARG:	ECHOED BY THE NOOP REPLY

CACCES==12	;ACCESS
		;ARG1: TRANSACTION NUMBER.
		;ARG2: ACCESS POINTER
		;ARG3: NEW ALLOCATION

CSYSCL==13	;RANDOM SYSTEM CALL. 11 (DECIMAL) ARGUMENTS.
		;ARG1: SYSTEM CALL NAME IN SIXBIT
		;ARG2: FLAGS (CONTROL-BIT ARGUMENT)
		;ARG3: NUMBER OF FOLLOWING ARGS THAT HAVE SIGNIFICANCE
		;ARG4: 1ST ARG TO SYSTEM CALL
		;...
		;ARG11: 8TH ARG TO SYSTEM CALL

CREUSE==14	;REINITIALIZE YOURSELF, BECAUSE WE ARE ABOUT TO BE REUSED
		;BY A NEW CREATOR FOR A NEW FILE.

CLOGIN==15	;LOGIN USER (RECORD XUNAME FOR SYS: DELETION PURPOSES, ETC.)
		;ARG1: XUNAME (USED AS "TERMINAL NAME" IN LOGIN CALL)

CMAX==16	;LARGEST COMMAND NUMBER, PLUS ONE.

;REPLIES FROM SLAVE START WITH AN AOBJN POINTER (RH = REPLY CODE)
;FOLLOWED BY A BLOCK OF ARGUMENTS

R==,,-1		;REPLY CODES:

RDATA==1	;INPUT DATA (WD COUNT INCLUDES DATA WDS AND BYTE COUNT WD).
		;# OF BYTES OF DATA
		;DATA, PACKED ILDB-STYLE INTO WORDS.
		;NOTE:  SLAVE MUST ALWAYS SEND FULLY POPULATED WORDS
		;EXCEPT WHEN EOF IS REACHED.

ROPENI==2	;INPUT OPEN STATUS. 1 OR 11 ARGUMENTS.
		;ARG1: -1 => SUCCEEDED; >0 => OPEN LOSS NUMBER
		;ARG2-ARG11 PRESENT ONLY IF ARG1 IS -1.
		 ;ARG2: REAL DEVICE NAME (USUALLY SIXBIT/DSK/)
		 ;ARG3: REAL FN1
		 ;ARG4: REAL FN2
		 ;ARG5: REAL SNAME
		 ;ARG6: FILE LENGTH
		 ;ARG7: BYTE SIZE OPEN IN
		 ;ARG8: FILE LENGTH IN BYTE SIZE WRITTEN IN
		 ;ARG9: BYTE SIZE WRITTEN IN
		 ;ARG10: FILDTP - -1 IF "RFDATE" WINS ON THIS FILE
		 ;ARG11: CREATION DATE (IF "RFDATE" WINS).

ROPENO==3	;OUTPUT OPEN STATUS. 1 OR 11 ARGUMENTS.
		;ARG1: -1 => SUCCEEDED; >0 => OPEN LOSS NUMBER
		;ARG2-ARG11 PRESENT ONLY IF ARG1 IS -1.
		 ;ARG2: REAL DEVICE NAME
		 ;ARG3: REAL FN1
		 ;ARG4: REAL FN2
		 ;ARG5: REAL SNAME
		 ;ARG6: FILE LENGTH (-1 => FILLEN FAILS ON THIS DEVICE)
		 ;ARG7: BYTE SIZE OPEN IN
		 ;ARG8: FILE LENGTH IN BYTE SIZE WRITTEN IN
		 ;ARG9: BYTE SIZE WRITTEN IN
		 ;ARG10: FILDTP - -1 IF "RFDATE" WINS ON THIS FILE
		 ;ARG11: CREATION DATE (IF "RFDATE" WINS).

REOF==4		;EOF ON INPUT
		;ARG:	IGNORED

RFDELE==5	;.FDELE STATUS. 1ST ARGUMENT:
		;RH:	-1 => SUCCEEDED
		;	 >=0 => FAILURE CODE
		;LH:	-1 => DELETE OR RENAME
		;	 0 => RENAME WHILE OPEN
		;IF RENAME WHILE OPEN CALL SUCCEEDED, THERE ARE 4 MORE ARGS:
		 ;ARG2: REAL DEVICE NAME
		 ;ARG3: REAL FN1 (AS RENAMED)
		 ;ARG4: REAL FN2
		 ;ARG5: REAL SNAME

RNOOP==6	;NOOP REPLY
		;ARG:	ECHO ARG SENT BY NOOP COMMAND

RACCES==7	;ACKNOWLEDGE ACCESS
		;ARG: TRANSACTION NUMBER FROM CACCES.

RSYSCL==10	;RESPOND TO SYSTEM CALL. 9 ARGUMENTS.
		;ARG1: <ERROR CODE OR 0>,,<# OF TIMES CALL SKIPPED>
		;ARG2: 1ST VALUE FROM SYSTEM CALL.
		;...
		;ARG9: 8TH VALUE FROM SYSTEM CALL.

RICLOS==11	;RESPOND TO INPUT-CLOSE.

ROCLOS==12	;RESPOND TO OUTPUT CLOSE.

RIOC==13	;REFLECT AN IOC ERROR
		;ARG:	IOC ERROR CODE, RIGHT-JUSTIFIED IN WORD.

RREUSE==14	;ACKNOWLEDGE A CREUSE.  ARG IS MEANINGLESS (NONE RETURNED).

RLOGIN==15	;ACKNOWLEDGE A LOGIN.  ARG IS MEANINGLESS (NONE RETURNED).

RMAX==16	;LAST REPLY CODE + 1.

GO4:	SYSCAL WHYINT,[1000,,CHNETI ? 2000,,A ? 2000,,B ? 2000,,C]
	 JSR LOGOUT
	CAIN A,%WYCHA
	 HLRZS C		;Non-zero if input available
	JUMPN C,GO5	;IF THERE ARE COMMANDS FOR US, HACK THEM.
	SKIPGE EOFI
	 JRST GO5
	SKIPE C,ALLOC	;ELSE, IF WE HAVE MORE ALLOCATION, SEND MORE DATA.
	 JRST ALLI1	;NO COMMANDS AND NO ALLOC => WAIT FOR COMMAND.
GO5:	PUSHJ P,SYSFRC		;Force system output buffer before waiting
	HRROI IOP,B		;Read command
	PUSHJ P,NTIIOT
	JUMPGE B,BYE2
	HRRZ A,B
	CAIL A,CMAX
	 JSR LOGOUT
	MOVEM B,LCMND'
	JRST @CMDTB(A)

;JUMP TO COMMAND HANDLER ROUTINE, LH(B) HAS - # ARGS TO READ OUT OF NET
CMDTB:	OFFSET -.
		BYE3
COPENI::	OPNI
COPENO::	OPNO
CDATA::		IOTO
CALLOC::	ALLI
CICLOS::	CLSI
COCLOS::	CLSO
CFDELE::	FDEL1
CRNMWO::	FDEL2
CNOOP::		YNOOP
CACCES::	YACCES
CSYSCL::	YSYSCL
CREUSE::	YREUSE
CLOGIN::	LOGIN
CMAX::	OFFSET 0

OPNI:	SKIPA A,[ROPENI]
OPNO:	 MOVEI A,ROPENO		;OPENI AND OPENO SAME EXCEPT FOR REPLY CODE.
	PUSH P,A
	HRRI B,DEV
	PUSHJ P,NTIIOB		;READ THE FILENAMES AND MODE.
	.SUSET [.SSNAME,,SNAME]
	POP P,B
	MOVE A,OPNM
	ANDI A,2
	MOVEM A,BLOKMD		;WE MUST BE AWARE WHETHER USING BLOCK MODE.
	SYSCAL OPEN,[4000,,OPNM ? 1000,,CHDEV
		DEV ? FN1 ? FN2 ? SNAME
		3000,,C]
	 JRST OPNIL		;IF OPEN LOSES, REPORT THAT.
	SETZM EOFI		;IT WON, REPORT THAT.
	HRLI B,-11.

;REPLY TO A SUCCESSFUL OPEN. B SHOULD HAVE REPLY HEADER, -11.,,<CODE>
OPNRCH:	SETO C,
	PUSHJ P,OPNRC1		;SEND FILE NAMES
	SYSCAL FILLEN,[ 1000,,CHDEV
		REPEAT 4,[ ? 2000,,DEVRCH+.RPCNT ]]
	 SETOM DEVRCH
	MOVEI A,36.		;IF FILLEN FAILED, WE MUST ESTIMATE
	MOVE B,OPNM		;THE BYTE SIZE:  7 IN UNIT ASCII MODE,
	TRNN B,6		;ELSE 36.
	 MOVEI A,7
	SKIPGE DEVRCH
	 MOVEM A,DEVRCH+1
	.RSYSI D,		;TEMPORARY CODE TO COMPENSATE FOR OLD SYSTEM
	CAMG D,[SIXBIT/1040/]
	 JRST [	MOVEM A,DEVRCH+1
		MOVEM A,DEVRCH+3
		MOVE A,DEVRCH
		MOVEM A,DEVRCH+2
		JRST .+1 ]
	SKIPLE A,DEVRCH+1
	 CAIL A,37.
	  .VALUE
	SETOM DEVRCH+4		;NOW READ THE FILE'S DATE
	SYSCAL RFDATE,[ 1000,,CHDEV ? 2000,,DEVRCH+5]
	 SETZM DEVRCH+4		;OR SAY IT HAS NONE.
	MOVE IOP,[-6,,DEVRCH]
	PUSHJ P,NETOFR
	MOVE A,DEVRCH+1
	MOVEM A,BYTSIZ		;NOW FIGURE OUT HOW TO HACK THIS BYTE SIZE.
	MOVEI A,36.
	IDIV A,BYTSIZ
	MOVEM A,BYTSWD
	IMULI A,BUFL
	MOVEM A,BUFSIZ
	HRLZ A,BYTSIZ
	LSH A,6
	IOR A,[440000,,BUF]
	MOVEM A,BUFBP		;SET UP BP. TO BUFFER'S BEGINNING.
	SETZM ALLOC
	JRST GO4

OPNRC1:	MOVE IOP,[-2,,B]
	PUSHJ P,NETOUT
	.CALL  [SETZ
		SIXBIT /RCHST/
		1000,,CHDEV
		2000,,DEVRCH
		2000,,DEVRCH+1
		2000,,DEVRCH+2
		2000,,DEVRCH+3
		2000,,DEVRCH+4
		2000,,DEVRCH+5
		2000,,DEVRCH+6
		SETZM DEVRCH+7]
	JSR LOGOUT
	MOVE IOP,[-4,,DEVRCH]
	PUSHJ P,NETOUT
	POPJ P,

OPNIL:	HRLI B,-1		;REPLY TO FAILING OPEN.
	MOVE IOP,[-2,,B]
	PUSHJ P,NETOFR
	JRST GO4

ALLI:	HRRI B,C
	PUSHJ P,NTIIOB	;READ ALLOC AMOUNT INTO C
	MOVEM C,LALLOC'
	ADDB C,ALLOC	;INCREASE ALLOC
	SKIPGE EOFI	;CAN'T ACTUALLY TRANSFER ANYTHING IF AT EOF.
	 JRST GO4
ALLI1:	MOVE B,BUFSIZ
	CAML C,B
	 MOVE C,B	;WE CAN'T IOT MORE THAN A BUFFERFULL AT ONCE.
	SKIPN BLOKMD
	 JRST ALLI2	;NOW GO DO THE XFRS IN UNIT MODE WITH SIOT,
	MOVN B,C	;OR IN BLOCK MODE WITH IOT.
	HRLZS B
	HRRI B,BUF
	.IOT CHDEV,B
	MOVEI C,-BUF(B)	;HOW MANY BYTES DID WE GET?
	SKIPGE B
	 SETOM EOFI	;NOT ALL WE ASKED FOR => AT EOF NOW.
	JRST ALLI3	;GO SEND OUR DATA (AND MAYBE EOF) TO MLDEV.

ALLI2:	IDIV C,BYTSWD	;ROUND DOWN BYTE COUNT TO MULTIPLE OF A WORD
	IMUL C,BYTSWD	;SINCE SUPPOSED TO SEND FULLY POPULATED WORDS
	JUMPE C,GO5	;JUMP IF NOT ENOUGH ALLOC TO READ ANYTHING
	MOVE B,BUFBP
	MOVE A,C
	SYSCAL SIOT,[1000,,CHDEV ? B ? A]
	 JSR LOGOUT
	LDB D,[360600,,B]
	CAIE D,44	;MAKE B POINT AT THE FIRST WORD NOT READ INTO AT ALL.
	 AOS B
	SKIPE A
	 SETOM EOFI
	SUB C,A

;NOW WE HAVE READ DATA FROM DEVICE INTO BUFFER.
;C HAS # BYTES READ.
;B POINTS AT 1ST UNUSED WORD OF BUF.
ALLI3:	JUMPE C,ALLI4
	HRLZI IOP,-BUF(B)
	MOVNS IOP	;- # WORDS CONTAINING DATA.
	ADD IOP,[-1,,RDATA]
	MOVEM IOP,HDR0	;SET UP RDATA CMD CONTAINING THEM AND BYTE COUNT.
	MOVEM C,HDR1
	ADD IOP,[-1,,HDR0-RDATA]
	PUSHJ P,NETOUT	;Translate to bytes and send.  But let the system
	PUSHJ P,BUFFRC	;decide where to put in the packet boundaries.
	MOVNS C
	ADDM C,ALLOC	;DEDUCT BYTES SENT FROM ALLOCATION.
ALLI4:	SKIPL EOFI	;NOW, IF WE REACHED EOF, TELL MLDEV THAT.
	 JRST GO4	;ELSE HANDLE ANOTHER COMMAND.
		;NOTE WE MIGHT STILL HAVE SOME ALLOCATION LEFT.
		;IF SO, THEN WE WILL HANDLE IT AS SOON AS THERE
		;ARE NO COMMANDS PENDING.

ALLEOF:	HRROI B,REOF	;HERE WHEN WE REACH EOF:  SEND REOF REPLY.
	JRST REPLY1

IOTO:	HRROI IOP,C		;HANDLE CDATA (DATE TO WRITE TO DEVICE)
	PUSHJ P,NTIIOT		;READ BYTE COUNT.
	ADD B,[1,,]
	HRRI B,BUF		;READ THE DATA.
	PUSHJ P,NTIIOB
	SKIPE BLOKMD
	 JRST [	.IOT CHDEV,B
		JRST GO4]	;IN BLOCK MODE, SEND OUT AS WORDS.
	MOVE B,BUFBP
	SYSCAL SIOT,[1000,,CHDEV ? B ? C]
	 JSR LOGOUT
	JRST GO4		;IN UNIT MODE, SEND OUT AS BYTES.

CLSI:	HRRI B,C
	PUSHJ P,NTIIOB
	.CLOSE CHDEV,
	HRROI IOP,[RICLOS]
	PUSHJ P,NETOFR
	JRST GO4

CLSO:	HRRI B,C
	PUSHJ P,NTIIOB
	.CLOSE CHDEV,
	HRROI IOP,[ROCLOS]
	PUSHJ P,NETOFR
	JRST GO4

;HERE FOR CREUSE COMMAND, WHICH MEANS MLDEV IS ABOUT TO USE US FOR A DIFFERENT FILE
;AND WASNTS US TO REINITIALIZE EVERYTHING APPROPRIATE.
YREUSE:	HRRI B,C	;IGNORE THE ARGUMENT.
	PUSHJ P,NTIIOB
	SETZM ALLOC	;DON'T EVEN TRY SENDING OUT MORE DATA.
	HRROI IOP,[RREUSE]
	PUSHJ P,NETOFR	;SO JUST ACKNOWLEDGE.
	JRST GO4

LOGIN:	HRRI B,UNAME		; READ LOGIN ID
	PUSHJ P,NTIIOB
	SETZM TRMNAM
	MOVE A,[440600,,TRMNAM]
	MOVEM A,TNAMBP
	MOVEI A,6
	MOVEM A,TNAMCC		;6 SIXBIT CHARACTERS IN WORD
	MOVE A,JOBUSR		;THE HOST AT THE OTHER END OF LINE
	PUSHJ P,OCTPNT
	MOVEI A,'J
	PUSHJ P,SIXTYP
	.SUSET [.RUIND,,A]	;THE USER INDEX IS MORE USEFUL
	PUSHJ P,OCTPNT
	MOVEI C,MAXLOG		;MAXIMUM LOGIN TRIES
	SKIPA B,UNAME
LOGIN1:	 AOS UNAME
	.CALL [	SETZ
		SIXBIT /LOGIN/
		UNAME		;UNAME
		TRMNAM		; "CONSOLE" (HOST AND USER INDEX)
		SETZ B ]	; XUNAME
	SOJG C,LOGIN1		;KEEP TRYING UNTIL WE MAKE IT		
	HRROI IOP,[RLOGIN]	; AND ACKNOWLEDGE
	PUSHJ P,NETOFR
	JRST GO4

;LOGIN UTILITY ROUTINES

OCTPNT:	IDIVI A,10		;THE NELSON RECURSIVE NUMBER PRINTER
	HRLM B,(P)
	SKIPE A
	 PUSHJ P,OCTPNT
	HLRZ A,(P)
	ADDI A,'0
SIXTYP:	SOSL TNAMCC		;MAXIMUM OF 6 CHARACTERS
	 IDPB A,TNAMBP
CPOPJ:	POPJ P,

FDEL1:	HRRI B,DEV
	PUSHJ P,NTIIOB
	MOVEI A,[SETZ ? SIXBIT /RENAME/
			DEV ? FN1 ? FN2 ? FSNAM
			FN2+1 ? FN2+2
			SETZB C]
	SKIPE SNAME			; 0=>deleting
	 JRST FDEL5
	HRROI C,%ENSMD	; RETURN "MODE NOT AVAILABLE" ERROR IF NOT LOGGED IN
	SKIPN UNAME
	 JRST FDEL4
	MOVEI A,[SETZ ? SIXBIT /DELETE/
			DEV ? FN1 ? FN2 ? FSNAM
			SETZB C]
FDEL5:	.CALL (A)
	 SKIPA		; Leave failure code in C if no skip
	  MOVEI C,-1	; Set code of -1 to mean succeeded
	HRROS C		; Set left half to -1 for RENAME/DELETE
			; Can't return the real name so just return code
			; Drop through to FDEL4
FDEL4:	MOVE B,[-1,,RFDELE] ; only sending status word
	MOVE IOP,[-2,,B]	; Code is in "C". 
	PUSHJ P,NETOFR
	JRST GO4

FDEL2:	HRRI B,FN1
	PUSHJ P,NTIIOB
	.CALL [	SETZ ? 'RENMWO ? 1000,,CHDEV ? FN1 ? FN2
			SETZB C]
	 SKIPA		; If failure leave code in C
	  MOVEI C,-1	; Otherwise set -1 to mean success
			; Left half is zero here to mean reply to Rename while open
	TRNN C,400000	; RH sign will be on if we succeeded
	 JRST FDEL4	; jump if call failed.
	MOVE B,[-5,,RFDELE]
	PUSHJ P,OPNRC1	; Get the real file name and send it.
	PUSHJ P,NETFRC
	JRST GO4

YNOOP:	HRRI B,C	;GET NOOP ARG
	PUSHJ P,NTIIOB
	HRROI B,RNOOP	;NOOP REPLY
REPLY1:	MOVE IOP,[-2,,B]	;BLKO POINTER FOR NOOP REPLY
	PUSHJ P,NETOFR
	JRST GO4	;BACK FOR NEXT COMMAND

;HANDLE CACCES COMMAND
YACCES:	HRRI B,B
	PUSHJ P,NTIIOB	;GET TRANSACTION NUMBER FOR REPLY IN C
	EXCH B,C	;AND ACCESS POINTER INTO B.  NEW ALLOCATION IN D, USED ONLY IF INPUT.
	.CALL [	SETZ
		'ACCESS
		1000,,CHDEV
		SETZ B]	;PUT IT INTO DEV CHANNEL
	 JSR LOGOUT
	SETZM EOFI
	HRROI B,RACCES
	MOVE IOP,[-2,,B]
	PUSHJ P,NETOFR	;SEND REPLY
	MOVE A,OPNM
	TRNE A,1	;IF OTHER END IS READING FILE, SEND WHAT WE'VE BEEN ALLOCATED.
	 JRST GO4	;IF OTHER SIDE IS WRITING, WAIT FOR IT TO SEND MORE DATA.
	MOVE C,D	;PROCESS NEW ALLOCATION SUPPLIED AS PART OF CACCES COMMAND,
	MOVEM D,ALLOC
	JRST ALLI1	;THEN SEND NEW STUFF.

;HANDLE REQUEST TO EXECUTE SYSTEM CALL.
YSYSCL:	HRRI B,YSYSB
	PUSHJ P,NTIIOB	;READ SYS CALL NAME AND ARGS.
	MOVEI A,CHDEV	;1ST ARG IS NORMALLY DEV CHANNEL NUMBER,
	MOVE B,YSYSB
	CAME B,[SIXBIT/MLINK/]
	 MOVEM A,YSYSB+3 ;BUT FOR "MLINK" CALL, IT IS SENT BY MASTER.
	MOVEM B,YSYSC+1
	MOVSI C,-NYSYSI
	MOVSI D,(SETZ)
	ANDCAM D,YSYSI(C)
	AOBJN C,.-1
	SOS C,YSYSB+2	;# OF INPUT ARGUMENTS-1
	IORM D,YSYSI(C)	;SET END OF ARG LIST AT APPROPRIATE PLACE
	.CALL YSYSC
	 JRST [MOVSS A ? JRST YSYS1]
	MOVEI A,1		;SUCCESSFUL CALL RETURNS HERE - SAY WAS 1 SKIP.
YSYS1:	MOVEM A,YSYSS
	MOVE IOP,[-YSYSRL,,YSYSR]
	PUSHJ P,NETOFR		;REPLY, GIVING MASTER VALUES RETURNED.
	JRST GO4

TSINT:	0
INTPC:	0
	MOVEM A,TSINTA		;IO INTR, CHECK SOCKET STATES
	SKIPL A,TSINT
	 JRST TSFW
TSINTX:	MOVE A,TSINTA
	.DISMISS INTPC

TSINTA:	0

TSFW:	TRNN A,%PIIOC		;HERE FOR 1ST WORD INTERRUPT.
	 JSR LOGOUT
	.SUSET [.RBCHN,,A]	;ONLY ONE WE CAN HANDLE IS AN IOC ERROR
	CAIE A,CHDEV		;ON THE DEVICE BEING USED.
	 JSR LOGOUT		;IOC ERROR ON NET SOCKET MEANS MLDEV WANTS US TO DIE.
	MOVSS A
	ADD A,[.RIOS,,A]	;WHEN THAT HAPPENS, SEND OUT A RIOC COMMAND
	.SUSET A		;CONTAINING THE IOC ERROR NUMBER.
	LDB C,[330400,,A]
	.DISMI [.+1]
	HRROI B,RIOC
	MOVE IOP,[-2,,B]
	PUSHJ P,NETOFR
	JRST GO4		;ALSO ABORT WHATEVER WE WERE DOING.

BYE1:	JSR LOGOUT
BYE2:	JSR LOGOUT
BYE3:	JSR LOGOUT

LOGOUT:	0
	SKIPE DEBUG
	.VALUE
	.LOGOUT
	JRST .-2

;NETWORK 36-BIT OUTPUT ROUTINES

NETOFR:	PUSHJ P,NETOUT		;Output then force
NETFRC:	PUSHJ P,BUFFRC		;Force our buffer and system's too
SYSFRC:	.CALL [ SETZ ? SIXBIT/FORCE/ ? SETZI CHNETO ]	;Send it
	 JSR LOGOUT		;Probably connection closed
	POPJ P,

BUFFRC:	PUSH P,H		;Force our buffer into system
	PUSH P,J
	PUSH P,Q
	AOSE NBFOXF
	 JRST NETFR1
	MOVE H,NBFOXW		;Send extra word
	MOVEI J,0		;Padded with zeros
	PUSHJ P,NETOU2
NETFR1:	PUSHJ P,NETBFO		;Code-convert buffer
POPQJH:	POP P,Q
	POP P,J
	POP P,H
	POPJ P,

;Send words, IOP is aobjn pointer
NETOUT:	PUSH P,H
	PUSH P,J
	PUSH P,Q
	AOSE NBFOXF
	 JRST NETOU1
	MOVE H,NBFOXW		;Send saved word from last time
	MOVE J,(IOP)		;Followed by first new word
	PUSHJ P,NETOU2
	AOBJP IOP,POPQJH
NETOU1:	MOVE H,(IOP)		;Send two words
	AOBJP IOP,NETOU3	;No more
	MOVE J,(IOP)
	PUSHJ P,NETOU2
	AOBJN IOP,NETOU1
	JRST POPQJH

NETOU3:	MOVEM H,NBFOXW		;Send this word next time
	SETOM NBFOXF
	JRST POPQJH

;Send pair of 36-bit words in H,J
NETOU2:	MOVE Q,NBUFOC		;Space in buffer?
	CAIGE Q,9
	 PUSHJ P,NETBFO		;Make some
	MOVNI Q,9
	ADDM Q,NBUFOC
REPEAT 9,[
	ROTC H,8
	IDPB J,NBUFOP
]
	POPJ P,

;Send and refresh the buffer -- clobbers Q only
NETBFO:	MOVEI Q,NBUFL
	SUB Q,NBUFOC		;Number of 8-bit bytes in buffer
	JUMPE Q,CPOPJ		;Empty
	PUSH P,J
	MOVE J,[440800,,NBUFO]
	MOVEM J,NBUFOP
	ADDM Q,NBUFOC
	.CALL [ SETZ ? SIXBIT/SIOT/ ? MOVEI CHNETO ? J ? SETZ Q ]
	 JSR LOGOUT		;Probably connection closed
	POP P,J
	POPJ P,

;Read 36-bit words from network into aobjn pointer in IOP
;If an odd number of words, NTIFRC will clean up the extra word
;(Calls to NTIFRC must match calls to NETFRC at other end).
NTIIOB:	MOVE IOP,B
	PUSHJ P,NTIIOT
NTIFRC:	SETZM NBFIXF		;Swallow extra word, if any
	POPJ P,

NTIIOT:	PUSH P,H
	PUSH P,J
	PUSH P,Q
	AOSE NBFIXF		;If have extra word, recieve it first
	 JRST NTIIO1
	MOVE H,NBFIXW
	MOVEM H,(IOP)
	AOBJP IOP,POPQJH
NTIIO1:	HLRO H,IOP		;Compute how much input we need
	ASH H,-1		;Rounded-up negative number of word pairs
	IMUL H,[-9]		;Number of bytes
	CAILE H,NBUFL		;Take at most one buffer full
	 MOVEI H,NBUFL
	PUSH P,H
	IDIVI H,9		;Store number of word pairs
	MOVEM H,NBUFIC
	POP P,H
	MOVE J,[440800,,NBUFI]
	MOVEM J,NBUFIP
	.CALL [ SETZ ? SIXBIT/SIOT/ ? MOVEI CHNETI ? J ? SETZ H ]
	 JSR LOGOUT		;Probably connection closed
	SKIPE H
	 JSR LOGOUT		;Failed to transfer, could be TCP conn closed
NTIIO2:	MOVEI J,0		;Receive two words into H,J
REPEAT 9,[
IFN .RPCNT, LSHC H,8
	ILDB Q,NBUFIP
	IOR J,Q
]
	MOVEM H,(IOP)
	AOBJP IOP,NTIIO3
	MOVEM J,(IOP)
	AOBJP IOP,POPQJH
	SOSLE NBUFIC
	 JRST NTIIO2
	JRST NTIIO1		;Need another buffer full

NTIIO3:	MOVEM J,NBFIXW		;Save this word for next time
	SETOM NBFIXF
	JRST POPQJH

NBUFL==360.			;Number of 8-bit bytes of network buffer
NBUFO:	BLOCK NBUFL/4		;NBUFL must be multiple of 4 and 9
NBUFOP:	440800,,NBUFO		;Fill pointer for network buffer
NBUFOC:	NBUFL			;Bytes remaining
NBFOXF:	0			;-1 => extra word in NBFOXW
NBFOXW:	0			;extra word not sent yet

NBUFI:	BLOCK NBUFL/4
NBUFIP:	440800,,NBUFI		;Take pointer for network buffer
NBUFIC:	0
NBFIXF:	0			;-1 => extra word in EXTRAW
NBFIXW:	0			;extra word not sent yet

LPDL==20
PDL:	BLOCK LPDL+4

PATCH:
PAT:	BLOCK 40

RCH:	BLOCK 10	?	STATE=RCH+4	;THIS IS THE SOCKET STATE

OPN:
DEV:	0
FN1:	0
FN2:	0
SNAME:	0
OPNM:	0
FSNAM:	0
	BLOCK 10		;SLOP FOR NET IOTS INTO HERE

;LOGIN STUFF

UNAME:	0
TRMNAM:	0
TNAMBP:	0	;BYTE POINTER INTO UNAME
TNAMCC:	0	;SIXBIT CHARACTER COUNT
JOBUSR:	0	;THE FOREIGN USER
DEBUG:	-1	;DEBUG FLAG
SYSDBG:	0	;SYSTEM BEING DEBUGGED FLAG
VERSIO:	.FNAM1
	.FNAM2

BLOKMD:	0	;-1 => DEVICE OPEN IN BLOCK MODE.
EOFI:	0	;-1 => HAVE REACHED EOF ON INPUT
ALLOC:	0	;-1 => ALLOCATION FOR DATA TO MLDEV, IN BYTES.

HDR0:	0	;HOLDS -N,,RDATA
HDR1:	0	;HOLDS BYTE COUNT OF RDATA COMMAND.
BUF:	BLOCK BUFL
BUFBP:	0	;B.P. TO ILDB 1ST BYTE OF BUFFER.
BYTSIZ:	0	;BYTE SIZE WE ARE XFERRING TO DEVICE.
BYTSWD:	0	;# BYTES PER WORD.
BUFSIZ:	0	;BUFFER SIZE IN BYTES.

YSYSBL==11.
YSYSB:	BLOCK YSYSBL
	BLOCK 10		;SLOP FOR NET IOTS INTO HERE

YSYSR:	1-YSYSRL,,RSYSCL ;CODE FOR "REPLY TO SYSTEM CALL"
YSYSS:	0		;ERROR CODE,,# SKIPS
YSYSV:	BLOCK 10	;VALUES RETURNED BY SYSTEM CALL GO HERE.
YSYSRL==.-YSYSR

YSYSC:	SETZ		;BLOCK FILLED IN FOR DOING SYSTEM CALL
	SIXBIT/GAZONK/	;NAME OF CALL STORED HERE
	4000,,YSYSB+1	;CONTROL BITS
	3000,,A		;ERROR RETURN ARGUMENT
REPEAT 8,2000,,YSYSV+.RPCNT	;COLLECT OUTPUT ARGS
YSYSI:	NYSYSI==8
REPEAT NYSYSI, YSYSB+3+.RPCNT	;INPUT ARGS, SIGN BIT WILL GET TURNED ON IN LAST ONE

DEVRCH:	BLOCK 8	;SPACE FOR .RCHST ON DSK

$$HST3==1
$$CHAOS==1
$$TCP==1
$$SERVE==1

.INSRT SYSENG;NETWRK

LITTER:	CONSTANTS
VARS::	VARIABLES

END	GO
