;<PUP>PUPERS.MAC;11     2-SEP-79 15:59:54    EDIT BY TAFT
;<PUP>PUPERS.MAC;10    18-MAR-77 17:09:08    EDIT BY TAFT
; SEARCH PSVDEF
;<PUP>PUPERS.MAC;9    14-AUG-76 18:31:50    EDIT BY TAFT
; Fix bug in DMPEVB

; Copyright 1979 by Xerox Corporation

	TITLE PUPERS -- EVENT REPORT SERVER FOR PUPSRV
	SUBTTL E. A. Taft / June, 1976

	SEARCH PUPDEF,PSVDEF,STENEX
	USEVAR TOPVAR,TOPPVR	; This is part of the top fork


EVBUFL==1000		; Event buffer length (words)


; Event report service procedure
; Called for any event report socket (see PUPSRV)
;	PB/ Pointer to incoming packet
;	A/ Pup Type of incoming packet
;	SV/ Service table index
; Returns +1
; Clobbers A-D

ERPSRV:	CAIE A,240		; Event report Pup?
	 JRST [	ELOG <Illegal Pup Type %1O from %2P>
		POPJ P,]

; Copy event report from Pup to internal buffer
	PUSH P,EVBUFP-FEVSRV(SV)  ; Save buffer starting point
	LDB D,PUPLEN		; Get length of incoming Pup
	MOVEI B,-MNPLEN+↑D12(D)	; Compute entry length
	ROT B,-8		; Store length as 2 bytes
	IDPB B,EVBUFP-FEVSRV(SV)
	ROT B,8
	IDPB B,EVBUFP-FEVSRV(SV)
	MOVE A,[POINT 8,PBHEAD+3(PB),15]  ; Source port string ptr
	MOVEI C,6		; Number of bytes in port
	ILDB B,A		; Append port to buffer
	IDPB B,EVBUFP-FEVSRV(SV)
	SOJG C,.-2
	MOVE A,[POINT 8,PBHEAD+1(PB)]  ; Pup ID string ptr
	MOVEI C,4		; Number of bytes in ID
	ILDB B,A		; Append Pup ID to buffer
	IDPB B,EVBUFP-FEVSRV(SV)
	SOJG C,.-2
	MOVE A,EVBUFP-FEVSRV(SV)  ; Get buffer pointer
	MOVEI B,PBCONT(PB)	; Make string ptr to Pup contents
	HRLI B,(POINT 8)
	MOVNI C,-MNPLEN(D)	; Number of content bytes
	SKIPE C
	 SOUT			; Copy contents to buffer
	MOVEM A,EVBUFP-FEVSRV(SV)

; Generate event report reply
	PUSHJ P,SWPPRT##	; Swap source and destination ports
	MOVEI A,MNPLEN		; Minimum-length Pup
	DPB A,PUPLEN
	MOVEI A,241		; Event Report Reply type
	PUSHJ P,SNDPUP##	; Send reply
	 JRST [	POP P,EVBUFP-FEVSRV(SV)  ; Failed, don't log report
		POPJ P,]	; Done
	SUB P,[1,,1]		; Succeeded, flush starting point

; Dump event report buffer to log file if necessary
	HRRZ A,EVBUFP-FEVSRV(SV)  ; Get current pointer
	SUB A,EVBUFB-FEVSRV(SV)	; Subtract base of buffer
	CAIL A,EVBUFL-<MXPLEN-MNPLEN+↑D12+3>/4  ; Enough room left?
	 PUSHJ P,DMPEVB		; No, dump event buffer
	POPJ P,

; Dump all event report buffers and reset timer
; Returns +1
; Clobbers A-D, SV

DMPAEB::MOVE SV,[-NEVSRV,,FEVSRV]  ; Setup AOBJN pointer
	PUSHJ P,DMPEVB		; Dump event buffer for each
	AOBJN SV,.-1
	SETO SV,		; No service now in progress
	TIME			; Get now
	ADD A,[LOGLAT*↑D1000]	; Next time to dump buffers
	MOVEM A,ERPTIM		; Save timer
	POPJ P,


; Dump event report buffer to log file
;	SV/ Service table index
; Returns +1
; Clobbers A-D

DMPEVB:	SKIPGE EVBUFP-FEVSRV(SV)  ; Any events buffered?
	 POPJ P,		; No, nothing to do
	MOVSI C,(1B8+1B17)	; Ignore deleted, short form
DMPEV2:	MOVE A,C		; Get bits
	MOVE B,EVFILE-FEVSRV(SV)  ; Get filename string ptr
	GTJFN			; Look for an existing log file
	 JRST [	TLON C,(1B0)	; Failed, maybe make a new version
		 JRST DMPEV2	; Try again
		ELOG <Failed to open %2S%/ - %1J>
		JRST DMPEV3]	; Flush buffer
	MOVE C,A		; Ok, save JFN
	MOVE B,[8B5+1B22]	; Open for append
	OPENF
	 JRST [	ELOG <Failed to open %3F%/ - %1J>
		MOVE A,C	; Failed, recover JFN
		RLJFN		; Release it
		 CAI
		JRST DMPEV3]	; Flush buffer
	MOVE C,EVBUFB-FEVSRV(SV)  ; Ok, get base of buffer
	HRLI C,(POINT 8)	; Make string ptr
	EXCH C,EVBUFP-FEVSRV(SV)  ; Get and reset current pointer
	SUB C,EVBUFB-FEVSRV(SV)	; Compute word offset in rh
	SETZ D,
	LSHC C,-↑D33		; C ← # unused bytes in last word
	LSH D,-1		; D[RH] ← # words *4
	SUBI C,4(D)		; C ← -# of bytes
	MOVE B,EVBUFP-FEVSRV(SV)  ; Start of buffer
	SOUT			; Write buffered bytes to file
	CLOSF			; Close file
	 PUSHJ P,SCREWUP##
	POPJ P,			; Done

; Here if fail to open file
DMPEV3:	MOVE C,EVBUFB-FEVSRV(SV)  ; Get base of buffer
	HRLI C,(POINT 8)	; Make string ptr
	MOVEM C,EVBUFP-FEVSRV(SV)  ; Reset current pointer
	POPJ P,			; Done

; Initialization
; Returns +1
; Clobbers A-D, SV

ERPINI::MOVSI A,-NEVSRV		; Set AOBJN pointer
	MOVE B,[POINT 8,EVBUFF]  ; Start of buffer region
	HRRZM B,EVBUFB(A)	; Assign buffer for server
	MOVEM B,EVBUFP(A)	; Now empty
	ADDI B,EVBUFL		; Advance to next
	AOBJN A,.-3		; Repeat for all servers
	MOVEI A,EVFREB		; Init free storage pointer
	MOVEM A,EVFREE

; Read stuff from command file
	MOVSI A,(1B2+1B17)	; Old file, short form
	HRROI B,[ASCIZ /PUPSRV.RUN/]
	GTJFN			; Lookup command file
	 JRST [	ELOG <Failed to open PUPSRV.RUN%/ - %1J>
		POPJ P,]
	MOVE C,A		; Save JFN
	MOVE B,[7B5+1B19]	; Byte size 7, read
	OPENF
	 JRST [	ELOG <Failed to open PUPSRV.RUN%/ - %1J>
		MOVE A,C	; Release JFN
		RLJFN
		 PUSHJ P,SCREWUP##
		POPJ P,]	; Give up
	HRROI B,EVBUFF		; Read file into buffer region
	MOVNI C,NEVSRV*EVBUFL
	SIN
	SETZ C,			; Append null
	IDPB C,B
	CLOSF			; Close file
	 PUSHJ P,SCREWUP##

; Interpret command file
	MOVE A,[POINT 7,EVBUFF]
	MOVE SV,[-NEVSRV,,FEVSRV]
ERPIN1:	MOVE B,CMDPTR		; Set pointer to command table
	PUSHJ P,FNDKEY##	; Read and lookup keyword
	 JRST [	LDB B,A		; Improper format, get terminator
		JUMPE B,ERPIN3	; Jump if reached end
		JRST ERPIN9]	; Other error
	 JRST ERPIN9		; Name not found
	HRRZ B,0(B)		; Get dispatch
	PUSHJ P,0(B)		; Take it
	 JRST ERPIN9		; Error
	LDB B,A			; Get terminator
	JUMPE B,ERPIN3		; Null means end of command file
	CAIN B,15		; Carriage return?
	 ILDB B,A		; Yes, get next
	CAIE B,12		; Line feed?
	 JRST ERPIN9		; No, malformed
	AOBJN SV,ERPIN1		; Yes, on to next
	SETO SV,
	ELOG <Insufficient table space for all ERP servers>

; Here when done reading command file
ERPIN3:	POPJ P,			; Done

; Here if command file is malformed
ERPIN9:	SETO SV,
	ELOG <Malformed command file PUPSRV.RUN>
	POPJ P,

; Dispatch table for commands
CMDPTR:	-1,,.+1
	[ASCIZ /ERP/],,ERPCMD

; Initialization (cont'd)

; ERP command processing

ERPCMD:	MOVEI C,10		; Octal radix
	NIN			; Input desired local socket #
	 POPJ P,		; Failed
	MOVEM B,SRVSKT##(SV)	; Ok, store it
	PUSH P,A		; Save source string ptr
	HRRO A,EVFREE		; Get free storage pointer
	HRROI B,[ASCIZ /ERP#/]	; Build server name string
	SETZ C,
	SOUT
	MOVE B,SRVSKT##(SV)
	MOVEI C,10
	NOUT
	 PUSHJ P,SCREWUP
	MOVEI A,1(A)		; Update free pointer
	EXCH A,EVFREE		; Recover start
	HRLI A,ERPSRV		; Include dispatch
	MOVSM A,SRVDSP##(SV)	; Store name,,dispatch
	POP P,A			; Recover command string
	MOVE B,EVFREE		; Get free storage pointer
	HRLI B,(POINT 7)
ERPCM1:	ILDB C,A		; Get char of filename
	CAIN C,40		; Ignore leading spaces
	 JUMPL B,ERPCM1
	CAIG C,40		; Legal?
	 JRST ERPCM2		; No, assume end
	IDPB C,B		; Yes, store in buffer
	JRST ERPCM1		; Repeat

ERPCM2:	SETZ C,			; End, append null
	IDPB C,B
	MOVEI B,1(B)		; Update free pointer
	EXCH B,EVFREE		; Recover start
	HRROM B,EVFILE-FEVSRV(SV)  ; Store log filename pointer
	JRST SKPRET##		; Done



; Storage

LS EVBUFB,NEVSRV	; Pointers to beginning of each buffer
LS EVBUFP,NEVSRV	; Current byte pointers
LS EVFILE,NEVSRV	; String pointers to log filenames

LS ERPTIM		; Time at which to force next buffer dump

LS EVFREE		; Free storage pointer

LS EVBUFF,NEVSRV*EVBUFL	; Log buffer region

LS EVFREB,1000		; Free storage region (for initialization)


	END