;USR0:<BUDD.HACKS>CTYSPY.MID.437  5-Sep-85 FM+6D.3H.43M.13S., by BUDD
; Enlarge TICBUF, it was stomping on QUIT !!!
;USR0:<BUDD.HACKS>CTYSPY.MID.432  6-Jul-85 FM+4D.6H.3M.54S., by BUDD
; Add TAIL/SHORT command
;MSC:<BUDNE.HACKS>CTYSPY.MID.424  5-Oct-84 FQ+3D.1H.54M.58S., by BUDNE
; MAKE OUTPUT LUUO MACROS USE KEEPSTRUNG ARGS
;MSC:<BUDNE.HACKS>CTYSPY.MID.423  5-Oct-84 FQ+3D.1H.43M.45S., by BUDNE
; ADD REBMAX -- MAXIMUM RELOADS BEFORE QUIT
;MSC:<BUDNE.HACKS>CTYSPY.MID.419 16-Jan-84 FQ+5D.20H.18M.39S., by BUDNE
; ADD SUPPORT FOR 6.0; XPEEK% TTY DATA IN FUNNY SECTIONS
;MSC:<BUDNE.HACKS>CTYSPY.MID.417 16-Jan-84 FQ+5D.20H.8M.6S., by BUDNE
; REMOVE GJ%PHY REPLACE WITH GJ%OLD -- PERHAPS HAVE GOD DO CREATE IF MISSING?
;MSC:<BUDNE.HACKS>CTYSPY.MID.410 19-Dec-83 FM+11M.36S., by BUDNE
; ADDED JCLCHK, STOLEN FROM OZ'S SLEUTH
;MSC:<BUDNE.HACKS>CTYSPY.MID.386 28-Nov-83 LQ+1D.12H.28M.31S., by BUDNE
; MAKE RELOAD CHECK F%MAST
;MSC:<BUDNE.HACKS>CTYSPY.MID.385 28-Nov-83 LQ+1D.12H.25M.10S., by BUDNE
; MAKE DEATH BLT CODE DO UN-PMAP AND RESTART AT +1
;MSC:<BUDNE.HACKS>CTYSPY.MID.380 28-Nov-83 LQ+1D.12H.0M.56S., by BUDNE
; ADD SETBEN SO CHIME'S ARE MORE ACCURATE
;FTN20:<BUDNE>CTYSPY.MID.375 22-Nov-83 FM+2D.12H.20M.25S., by BUDNE
; ADD BIGBEN/CHIME
;FTN20:<BUDNE>CTYSPY.MID.364 17-Nov-83 FQ+4D.21H.20M.46S., by BUDNE
; PUT FINISING TOUCHES ON HEADER STUFF
;FTN20:<BUDNE>CTYSPY.MID.360 17-Nov-83 FQ+4D.21H.12M.12S., by BUDNE
; CREATE STORE ROUTINE SO WE CAN PUT IN STARTUP HEADER!!
;FTN20:<BUDNE>CTYSPY.MID.352 17-Nov-83 FQ+4D.20H.46M.52S., by BUDNE
; CREATE ALL FILE PAGES BEFORE SPYLOP
;FTN20:<BUDNE>CTYSPY.MID.351 17-Nov-83 FQ+4D.20H.41M.55S., by BUDNE
; ADD F%MAST, AND %FATL2 TO AVOID LOOPS IN SLAVE
;MSC:<BUDNE>CTYSPY.MID.350 23-Jun-83 FQ+5D.21H.51M.32S., by BUDNE
; UNMAP & SLEEP AT RELOAD
;MSC:<BUDNE>CTYSPY.MID.342 28-Apr-83 FM+1D.17H.49M.44S., by BUDNE
; IMPROVEMENTS TO DEATH CODE
;MSC:<BUDNE>CTYSPY.MID.339 22-Apr-83 FQ+2D.13H.20M.35S., by BUDNE
; START DOCTOR JUST BEFORE SPY LOOP, NOT IN PSIINI
;MSC:<BUDNE>CTYSPY.MID.319 28-Mar-83 FQ+7D.1H.19M.39S., by BUDNE
; TRY TO RELOAD AT DEATH:
;MSC:<BUDNE>CTYSPY.MID.305 24-Mar-83 FQ+3D.1H.43M.48S., by BUDNE
; ADDED 'LINK DOCTOR' - does checkups every 'FIVE' minutes

TITLE CTYSPY - Program to record last page of CTY output
SUBTTL PHIL BUDNE@DEC, MARCH 15, 1983
.DECSAVE ;Write .CSAVE files

COMMENT `
Date: Wednesday, 16 March 1983  17:39-EST
From: Phil Budne <BUDNE>
To:   SYSTEM, FORUM
Re:   CTYSPYer

Since the CTY for MRFORT is at best hard to get to, I have written
a program ala ITS that saves the last 2 pages (or so) of CTY output
and can type them for any user.  to use just type:

@CTYSPY
****************
*BUGINF: SYSFLM
*FLMSRV - SYSTEM GOING DOWN IN FLAMES
*ADDITIONAL DATA: PI = 3.14
****************
SJ 0: ****** OPR(999) *******
SJ 0:   CRACKLE, CRACKLE, SMOKE SMOKE SMOKE
SJ 0:
.
.
.

-phil
   ========
`
CTYSPY==.FVERS			;SAVE FILE GENERATION

OF%RDU==10000			;NOT IN THIS MIDAS?
.JBUUO==40			;LUUO EVALED INTO HERE
.JB41==41			;LUUO INSTR

F==0
 F%LUNK==400000,,		;PTY LUNKED TO CTY
 F%TRAP==200000,,		;TRAP ^C (AOS QUIT)
 F%MAST==100000,,		;IS MASTER, TRY TO RELOAD
 F%JCLM== 40000,,		;GOT MASTER IN JCL
 F%TAIL== 20000,,		;GOT TAIL COMMAND IN JCL

A==1
B==2
C==3
D==4

E==5
T==6
TT==7

P==17

; MISSING FROM MIDAS:
XPEEK%=:JSYS 626
  .XPPEK==:1			;PEEK FUNCTION

PDLL==40			;NUMBER OF WORDS FOR PUSH DOWN LIST
PURPAG==300			;STARING PAGE FOR PURE CODE & DATA
PURADR=PURPAG_9.
FILPAG==500			;PAGE FOR PMAP FILE (OR SLAVE COPY)
FILADR=FILPAG_9.
SHRPAG==600			;PAGE FOR REAL PMAP FILE IN SLAVE ONLY
SHRADR=SHRPAG_9.

REBMAX==2			;MAXIMUM NUMBER OF RELOADS
1MIN=60.*1000.			;1 MIN IN MS. (FREQ FOR 'TICK')
CHKTIM==5			;TIME BETWEEN LINK CHECKUPS
				;  IN 1MINs
CALL=PUSHJ P,
RET=POPJ P,
PJRST=JUMPA 11,

DEFINE FLD (VAL, MASK)
<.DPB <VAL>,<.BP <MASK>,>,0,>!TERMIN

UUONUM==0

DEFINE NXTUUO UUO
$!UUO=<UUONUM==UUONUM+<1000,,>>	;;ASSIGN SYMBOL
	%!UUO			;;MAKE TABLE ENTRY
TERMIN

DEFINE DEFUUO UUO
    DEFINE UUO &MESS
	IFNB [MESS][ $!UUO [ASCIZ MESS] ]
	.ELSE $!UUO 0
    TERMIN ;;UUO
    NXTUUO UUO
TERMIN ;DEFUUO

DEFINE EJSHLT &MESS
	ERJMP [ JSHLT MESS ]
TERMIN

IMPURE==.
.==<PURE==PURADR>

UUOTAB:
DEFUUO FATAL			;?MSG
DEFUUO TMSG			;NORMAL CHATTER
DEFUUO JSHLT			;?MSG: JSYS ERROR MSG
EXPUNGE  DEFUUO, NXTUUO, UUONUM

	SUBTTL	SHARED DATA DEFINTIONS
.%.==FILADR
DEFINE DATA NAME,LEN=1
NAME=.%.
IFL LEN,.FATAL DATA NAME LENGTH .LT. 0
.%.==.%.+LEN
TERMIN

DVERSION==1
; ** IMPORTANT **
; INCREMENT DVERSION WHENEVER AN INCOMPATIBLE CHANGE IS MADE HERE
; ALLOCATING NEW WORDS BEFORE XXX IS *USUALLY* OK

NUMBUF==120.			;NUMBER OF BUFFERS (LINES) TO KEEP
BUFPWR==4			;BUFSIZ IS ALWAYS A POWER OF 2
BUFSIZ==1_BUFPWR		;BUFFER SIZE IN WORDS

DATA	WVERSION		;DVERSION VALUE OF WRITER
DATA	UDT1			;FIRST TIMESTAMP (2ND AT END)
DATA	FULBUF			;NUMBER OF FULL BUFFERS
DATA	1ST			;OLDEST BUFFER THAT IS FULL
DATA	NEXT			;NEXT BUFFER TO FILL
DATA	NLUNK			;NUMBER OF TIMES MASTER CALLED LUNK
DATA	XXX,50.-<XXX-FILADR>	;FILL UP RESERVED SPACE
DATA	BUFADR,NUMBUF*BUFSIZ	;BUFFER SPACE
DATA	UDT2			;ENDING TIMESTAMP
DATA	ENDFIL,0		;LAST WORD OF PMAP AREA
NWORDS==ENDFIL-FILADR
NPAGES==<NWORDS+777>/1000
	SUBTTL	PURE DATA

FILNAM:	ASCIZ 'SYSTEM:CTYSPY.DATA' ;PMAP FILE NAME
DEBNAM:	ASCIZ 'DSK:CTYSPY.TEST'	;HERE FOR TESTING

	SUBTTL	CTYSPY STARTS HERE

START:	TDZA A, A		;NORMAL ENTRY
	 MOVE A,0		;ENTRY FROM RELOAD
	MOVEM A, REBORN		;REMEMBER RELOAD COUNT
	RESET			;STOP THE WORLD!
	MOVE A, [CALL UUOH]
	MOVEM A, .JB41		;SETUP LUUOS
	MOVE P, [-PDLL,,PDL]	;GET THEE A PIDDLE
	SETZ F,			;CLEAR FLAGS
	SETOM FATALC		;NO FATAL'S YET
	CALL JCLCHK		;WHAT IS MY FATE?
	TLNN F, (F%JCLM)
	 JRST DUMP		;SLAVE....
	JRST GOSPY		;.. OR MASTER!!

KOFFDB:	FLD(.CMFLD,CM%FNC) ? 0 ? 0 ? 0
INIFDB:	FLD(.CMINI,CM%FNC) ? 0 ? 0 ? 0
CONFDB:	FLD(.CMCFM,CM%FNC) ? 0 ? 0 ? 0
JCLFDB:	FLD(.CMKEY,CM%FNC)+CONFDB ? JCLTAB ? 0 ? 0

JCLTAB:	NJCODES,,NJCODES
;;	[ASCIZ "CLEAR"],,-3	;SOMEDAY.. CLEAR/CREATE MASTER FILE
	[ASCIZ "DEBUG"],,-2
	[ASCIZ "GOD"],,-1
;;	[ASCIZ "LOGGER"],,-4	;SOMEDAY.. WRITE CTYLOG.TXT
;;	[ASCIZ "LUMBERJACK"],,-4 ;SOMEDAY.. WRITE CTYLOG.TXT
	[ASCIZ "MASTER"],,-1
	[ASCIZ "PEON"],,0
;;	[ASCIZ "RESET"],,-3	;SOMEDAY.. CLEAR/CREATE MASTER FILE
	[ASCIZ "SHORT"],,1	;SYNONYM FOR TAIL
	[ASCIZ "SLAVE"],,0
	[ASCIZ "START"],,-1
	[ASCIZ "SYSTEM"],,-1
	[ASCIZ "TAIL"],,1
	[ASCIZ "TEST"],,-2
NJCODES==.-JCLTAB-1

JCLCHK:	MOVEI A, .RSINI
	RSCAN
	 TRN
	MOVEI A, CMDBLK
	MOVEI B, KOFFDB		;EAT PROGRAM NAME
	COMND
	MOVEI B, JCLFDB
JCL.1:	COMND
	TLNE A, (CM%NOP)
	 JRST [	JSHLT 'Bad JCL']
	LDB A, [.BP CM%FNC,.CMFNP(C)]
	CAIN A, .CMCFM		;EOL?
	 RET
	HRRZ B, (B)		;GET FLAG
	TRNE B, 777000		;NEGATIVE?
	 TLO F, (F%JCLM)	; YES, FLAG AS MASTER
	CAIN B, -2		;DEBUG?
	 SETOM DBUG		; SET FLAG
	CAIN B, 1		;TAIL?
	 TLO F, (F%TAIL)	; YES, FLAG IT
JCL.2:	MOVEI A, CMDBLK
	MOVEI B, CONFDB
	JRST JCL.1

IFN 0,[
; ANY ENABLED JOB, INDIRECTLY OWNED BY SYSJOB WILL TURN INTO THE
; MASTER. (COULD USE ENQ% BUT ITS UGLEEEE)
JOBCHK:	SKIPE DBUG		;DEBUGGING?
	 JRST RSKP		;THEN ALLWAYS MASTER
	MOVEI A, .FHSLF		;US
	RPCAP			;READ CAPABILITIES
	TRNN C, SC%OPR\SC%WHL	;ANYONE IMPORTANT?
	 RET			; TO THE GALLEYS FOR YOU!!
	SETO A,			;START WITH US
JCK.1:	HRROI B, A		;ONE WORD INTO A
	MOVEI C, .JICPJ		;GET CONTROLING JOB
	GETJI
	 JSHLT 'GETJI failed'
	JUMPL A, R		;NOT CONTROLED
	JUMPE A, RSKP		;SYSJOB!!, A WINNER
	JRST JCK.1		;FIND HIS MASTER..
] ;IFN 0
	SUBTTL	BECOME SYSTEM CTYSPY-ER

GOSPY:	CALL PSIINI		;CRANK UP SOFTWA RE-INTERUPT SYSTEM
	TMSG '[Starting system CTYSPY]'
	SKIPE DBUG		;TESTING?
	 TMSG ' (Test version)'
	TMSG			;CRLF
	CALL SPYINI		;GET PMAP FILE, & LUNK UP
	MOVEI A, DVERSION	;GET OUR DATA VERSION
	MOVEM A, WVERSION	;WE ARE THE MODEL
	GTAD
	MOVEM A, UDT1		;STAMP THE FILE
	MOVEM A, UDT2
...==FILADR+1000
REPEAT NPAGES-1,[
	SKIP ...		;CREATE PAGE
...==...+1000
]
	HRROI A, TMPBUF		;OUTPUT TO TEMP BUF
	HRROI B, [ASCIZ /**** CTYSPY v/]
	SETZ C,			;QUIT ON NULL
	SOUT
	MOVEI B, CTYSPY		;GET VERSION
	MOVEI C, 10.		;GET RADIX
	NOUT			;TYPE
	 JSHLT 'GOSPY NOUT failed'
	HRROI B,[ASCIZ / started on /]
	SETZ C,
	SOUT
	SETOB B,C
	ODTIM
	HRROI B, [ASCIZ \ ****\]
	SETZ C,
	SOUT
	HRROI B, CRLF
	SOUT

	HRROI A, CRLF		;BLANK LINE
	CALL STORE		;STORE IT
	HRROI A, TMPBUF		;GET TEXT
	CALL STORE		;PUT HEADER INTO BUFFER
	HRROI A, CRLF		;TRAILING BLANK LINE
	CALL STORE		;STUFF IT IN TOO

	CALL SETBEN		;SET UP BIG BEN
	MOVEI A, CHKTIM		;WAIT FOR DOCTOR
	MOVEM A, COUNTR
	CALL TIMSET		;START THE DOCTOR

SPYLOP:	CALL CHKLNK		;MAKE SURE LINK IS UP!!
	MOVE A, PTYJFN		;READING FROM "CTY"
	HRROI B,TMPBUF		;STORE INTO TEMP BUFFER
	MOVEI C, BUFSIZ*5	;MAX CHARS
	MOVEI D, ^J		;BUT QUIT ON LF
	SIN			;READ IN A BUF
	 EJSHLT 'PTY SIN failed'
	HRROI A, TMPBUF		;GET NEW LINE
	CALL STORE		;STORE IN PMAP FILE
	JRST SPYLOP

	SUBTTL STORE STRING INTO NEXT AVAILABLE BUFFER
; A/	BP

STORE:	PUSH P, A		;SAVE BP
	CALL PSIOFF		;PROTECT FROM CLOCK******
	MOVE A, FULBUF		;GET BUFFERS IN USE
	CAIGE A, NUMBUF		;ALL FULL?
	 JRST [	MOVE B, NEXT	;NO, FILL NEXT
		AOS NEXT	;KEEP GOING
		JRST STO.1 ]	;GO JOIN THE "HUMAN" RACE
	MOVE A, 1ST		;OLDEST BUF
	MOVE B, A		;SAVE, WE ARE ABOUT TO FILLIT
	ADDI A, 1		;BUMP UP
	CAIL A, NUMBUF		;PAST TOP?
	 SETZ A,		;YES, START AGAIN
	SETOM UDT1		;INDETERMINATE DATA...
	MOVEM A, 1ST		;WORLD SEES ONE LESS RIGHT NOW
	SOS FULBUF		;SOON TO CRUSH A BUF
	GTAD			;GET CURRENT UDT
	MOVEM A, UDT1		;STAMP NEW DATA
	MOVEM A, UDT2		;AT BOTH ENDS
STO.1:	LSH B, BUFPWR		;"MULTIPLY" BUF NUM BY BUFFER SIZE
	MOVE A,(P)		;RESTORE SOURCE
	HRROI B, BUFADR(B)	;GET DEST ADDR
	MOVEI C, BUFSIZ*5	;MAX CHARS
	MOVEI D, ^J		;BUT QUIT ON LF
	SETOM UDT1		;INDETERMINATE...
	SIN			;READ INTO BUF
	 EJSHLT 'COPY SIN failed'
	AOS FULBUF		;MAGIC!! A NEW BUFFER APPEARS
	GTAD			;READY FOR NEW STAMP
	MOVEM A, UDT1		;START STAMP
	MOVEM A, UDT2		;END STAMP
	POP P, B		;RESTORE BP
	PJRST PSION
	SUBTTL	MAIN LOOP FOR SLAVE

DUMP:	CALL DMPINI		;GET FILE READ ONLY
	MOVEI B, 1000.		;NUMBER OF TRIES
TRYBLT:	MOVE A, [SHRADR,,FILADR] ;FROM PMAP TO PRIVATE DATA
	BLT A, ENDFIL
	ERJMP .+2		;PAGES NOT THERE?
	 SKIPN A, UDT2		; END UDT MATCH?
	  FATAL 'No data in PMAP file'
	CAME A, UDT1		;SAME AS WHEN BLT STARTED?
	 SOJG B, TRYBLT		;NO TRY AGAIN
	JUMPLE B, FAILED	;RAN OUT OF TRIES

	MOVE A, WVERSION	;GET WRITERS VERSION
	CAILE A, DVERSION	;GREATER THAN US?
	 FATAL 'Obsolete copy of CTYSPY'
	CAIGE A, DVERSION	;LESS THAN US??
	 FATAL 'This copy of CTYSPY is more recent than the system version!'

	MOVE E, FULBUF		;PRINT ALL FULL BUFFERS
	MOVE T, 1ST		;OLDEST FIRST
	SETZ TT,		;SKIP NOTHING
	TLNN F, (F%TAIL)	;DO JUST TAIL?
	 JRST DMPLOP		; NO, START NOW
	CAIL E, NUMBUF/3	;AT LEAST ONE THIRD OF MAX TO PRINT?
	 MOVEI TT, NUMBUF*2/3	; YES, GET NUMBER TO SKIP

DMPLOP:	SOJG TT,DMPNXT		;MORE TO SKIP?
	MOVE B, T		;COPY BLOCK NUMBER
	LSH B, BUFPWR		;MULTIPLY BY BLOCK SIZE
	HRROI B, BUFADR(B)	;WHERE TO GET IT
	MOVEI A, .PRIOU		;WHERE TO PUT IT
	MOVEI C, BUFSIZ*5	;MAX
	MOVEI D, ^J		;DELIM
	SOUT			;TYPE ON TTY
DMPNXT:	SOJLE E, DMPEND		;ANY MORE?
	ADDI T, 1		;YES, BUMP
	CAIL T, NUMBUF		;TOP?
	 SETZ T,		;YES, START AGAIN
	JRST DMPLOP		;NO, BACK TO WORK

DMPEND:	TMSG			;CRLF
; UNMAP?
	HALTF
	JRST DUMP

FAILED:	FATAL 'Could not read data'
	SUBTTL SPYINI - SET UP FOR MASTER SPY

SPYINI:	MOVEI A, .FHSLF		;US
	SETO C,			;ANYTHING!!
	EPCAP			;PAUSING ONLY TO WHEEL UP...
	TLO F,(F%MAST)		;ITS OK TO RELOAD US

	CALL CHKINI		;INIT DOCTOR DATA
	CALL FILINI		;SET UP PMAP FILE FOR WRITE
	MOVE A, WVERSION	;WHAT IS LAST WRITER VERSION?
	 ERJMP SPYI.0		; HMM BETER ZERO IT
	CAIN A, DVERSION	;SAME VERSION?
	 SKIPE FULBUF		; HAS BEEN USED?
	  JRST SPYI.1		;  YES, DON'T RESET...
SPYI.0:	SETZM FULBUF		;NO FULL BUFFERS
	SETZM 1ST		;FIRST BUFFER TO USE IS 0
	SETZM NEXT		;NEXT BUFFER TO FILL IS 0

SPYI.1:	SETZM NLUNK		;NUMBER OF LUNK ATTEMPS
	CALL CTYGET
	 FATAL 'COULD NOT FIND LOGDES'
	CALL PTYGET
	 FATAL 'COULD NOT GET A PTY'

LUNK:	AOS NLUNK		;NUMBER OF LINK ATTEMPTS
	MOVSI A, (TL%ERO)	;ESTABLISH REMOTE TO LOCAL
	HRR A, PTYDES		;FLAGS,,PTY
	MOVE B, CTYDES		;SPYING ON THE CTY!!
	TLINK			;LUNK UP
	 JSHLT 'TLINK failed'	;DARN IT.
	TLO F, (F%LUNK)		;FLAG LINK SO IT CAN BE RELEASED
	RET

CTYGET:	MOVE A, ['LOGDES]	;LOGGING INFO TABLE
	SYSGT
	MOVE A, B		;GET LENGTH,,TABLE IN 1
	HRLI A, 1		;ENTRY 1,,TABLE
	GETAB			;GET IT
R:	 RET			;MAYBE NOT
	JUMPE A, R		;ALSO PRETTY BAD
	CAIN A, .NULIO		;NUL??
	 RET			;FORGET IT!
	MOVEM A, CTYDES		;SAVE LOGGING DESIGNATOR
RSKP:	AOS (P)
	RET

;; GOD DOES THIS EVER LOSE BIG. - HERE PTY PTY PTY...
;;  COULD TEST FOR AVAIL BY USING DVCHR, BUT THIS AVOIDS THE RACE

PTYGET:	MOVE A, ['PTYPAR]	;PTY STUFF
	SYSGT
	MOVEM A, PTYPAR		;SAVE IT
	HLRZ A, A		;NUMBER OF PTYS
	MOVN A, A		;NEGATIVE
	MOVSI E, (A)		;,,0
PTYLOP:	MOVE A, [170700,,PTYBUF] ;SKIPS FIRST 3 CHARS
	MOVEI B, (E)		;GET PTY NUMBER
	MOVEI C, 10		;BASE 8
	NOUT
	 JSHLT 'NOUT failed'
	MOVEI B, ":		;BE DEVICE LIKE
	IDPB B, A
	SETZ B,			;MAKE ASCIZ
	IDPB B, A
	MOVSI A, (GJ%OLD\GJ%SHT)
	HRROI B, PTYBUF
	GTJFN			;GET A JFN?
	 JRST PTYBOT		;NO LOOP SOME MORE
	MOVEM A, PTYJFN		;SAVE JFN
	MOVE B, [FLD(7,OF%BSZ)\OF%RD]
	OPENF			;OPEN FOR READ
	 JRST [	MOVE A, PTYJFN	;NOPE, SOMEONE ELSES PTY
		RLJFN		;TOSS THE JFN
		 JSHLT 'RLJFN failed' ;???
		JRST PTYBOT]	;LOOK AGAIN

;; HERE WHEN WE HAVE A PTY OF OUR VERY OWN
	MOVEI B, (E)		;PTY NUMBER IN B
	MOVE C, PTYPAR		;PTYS,,TTYNUM
	ADDI B, .TTDES(C)	;TTY DESCRIPTOR
	MOVEM B, PTYDES		;SAVE
	JRST RSKP		;YEAH!!

PTYBOT:	AOBJN E, PTYLOP		;LOOP SOME MORE
	RET			;HERE IF NO PTY EVER FOUND

	SUBTTL	LINK CHECKER LIVES HERE

CHKINI:	MOVEI A, .SNPSY		;SYMBOL LOOKUP
	MOVE B, [.RSQZ 0,TTACTL] ;SYMBOL IN RIGHT SQUOZE FORMAT
	MOVEI C, <.RSQZ 0,STG>	;SYMBOL TABLE FOR SPEED IN LOOKUP
	SNOOP
	 JSHLT 'SNOOP #1 failed'
	HRLI B, 1
	MOVEM B, TTACTL

	MOVEI A, .SNPSY		;SYMBOL LOOKUP
	MOVE B, [.RSQZ 0,TTLINK] ;SYMBOL IN RIGHT SQUOZE FORMAT
	MOVE C, [.RSQZ 0,TTYSRV] ;SYMBOL TABLE FOR SPEED IN LOOKUP
	SNOOP
	 JSHLT 'SNOOP #2 failed'
	MOVEM B, TTLINK
	RET

; CALL WITH TTY IN A, RETURNS LINK WORD IN B
GETLNK:	ADD A, TTACTL		;OFFSET INTO TABLE
	MOVEI B, B		;RETURN IN B
	PEEK
	 JSHLT 'PEEK #1 failed'

	JUMPLE B, RET		;'NOT ACTIVE' (NO DYN DATA)
	TLNE B,-1		;SECTION FOR DYNAMIC DATA?
	 JRST [	ADD B, TTLINK	;  ADD OFFSET FOR LINK WORD
		MOVEM B, PEKMON	;  STORE MONITOR ADDRESS
		MOVEI B, B	;  GET USER ADDRESS
		MOVEM B, PEKADR	;  SAVE
		MOVEI A, PEKBLK	;  GET ARG BLOCK
		XPEEK%		;  GO-FOR-IT!
		 EJSHLT 'XPEEK failed'
		JRST GETL.2]
	MOVE A, TTLINK		;OFFSET INTO DATA
	ADDI A, (B)		;ADD ADDR OF DATA
	HRLI A,1		;PEEK ONE WORD
	MOVEI B, B		;RETURN DATA IN B
	PEEK
	 JSHLT 'PEEK #2 failed'
GETL.2:	CAME B,[-1]		;ANY LINKS?
	 AOS (P)		;MUST BE...
	RET			;NOPE

; MAKE SURE A LINK EXISTS...
CHKLNK:	MOVE A, CTYDES		;GET CTY
	MOVEI A, -.TTDES(A)	;MAKE JUST TTY NUMBER
	CALL GETLNK		;ANY LINKS
	 JRST RELINK		;NO, BETTER TRY AGAIN
	MOVE A, [441100,,B]	;LOAD 9 BIT BYTES
	MOVE C, PTYDES		;GET OUR PTY
	MOVEI C, -.TTDES(C)	;MAKE LOOK LIKE TTY
REPEAT 4,[
	ILDB D, A		;LOAD FIRST BYTE
	CAMN C, D		;US??
	 JRST CHL.0		;YES.. BREATHE EASY
]
; HERE IF NO LINK FOUND
RELINK:	TMSG '[CTYSPY re-linking to CTY]'
	CALL LUNK		;TRY IT..
CHL.0:	MOVEI A, CHKTIM		;TAKE 5...
	MOVEM A, COUNTR		;UNTIL NEXT EXAM
	RET

	SUBTTL	CHIME ON THE HOUR

CHIME:	HRROI A, TICBUF		;OUTPUT TO TEMP BUF
	HRROI B, [ASCIZ /**** CTYSPY v/]
	SETZ C,			;QUIT ON NULL
	SOUT
	MOVEI B, CTYSPY		;GET VERSION
	MOVEI C, 10.		;GET RADIX
	NOUT			;TYPE
	 JSHLT 'CHIME NOUT failed'
	HRROI B,[ASCIZ / hourly checkpoint on /]
	SETZ C,
	SOUT
	SETOB B,C		;NOW, VERBOSE
	ODTIM
	HRROI B, [ASCIZ \ ****\]
	SETZ C,
	SOUT
	HRROI B, CRLF
	SOUT

	HRROI A, TICBUF		;GET TEXT
	CALL STORE		;STORE AND FALL INTO SETBEN

; SET BIGBEN TO CHIME ON NEXT HOUR
SETBEN:	SETO B,			;NOW
	SETZ D,			;NO FLAGS
	ODCNV			;SPLIT UP
	MOVEI D, (D)		;GET SECONDS SINCE MIDNIGHT
	IDIVI D, 1MIN/1000.	;GET MIN
	IDIVI D, 60.		;GET HRS
	MOVN E, E		;GET -MIN TO HOUR
	ADDI E, 60.		;GET MIN TO HOUR
	MOVEM E, BIGBEN		;STORE COUNTDOWN TO HOUR
	RET
	SUBTTL	MAP THE DATA FILE AS SOUL WRITER

FILINI:	MOVSI A, (GJ%OLD\GJ%SHT) ;SHORT FORM, MUST EXIST
	HRROI B, FILNAM		;THE FILE NAME
	SKIPE DBUG
	 HRROI B, DEBNAM	;THIS ONE IF DEBUGGING
	GTJFN
	 JSHLT "Can't get file"
	MOVEI B, OF%RD\OF%WR
	OPENF
	 JSHLT "Can't open data file"
	MOVEM A, FILJFN
	MOVSI A, (A)		;JFN,,PAGE
	MOVE B, [.FHSLF,,FILPAG] ;FORK,,PAGE
	MOVE C, [PM%CNT\PM%RD\PM%WR\NPAGES]
	PMAP			;MAP FOR WRITE
	 EJSHLT 'PMAP failed'
	TMSG 'Mapping '
	MOVEI A, .PRIOU
	MOVE B, FILJFN
	SETZ C,
	JFNS
	TMSG
	RET


	SUBTTL	MAP THE DATA FILE AS READER

DMPINI:	MOVSI A, (GJ%SHT\GJ%OLD) ;SHORT FORM
	HRROI B, FILNAM		;THE FILE NAME
	GTJFN
	 JSHLT "Can't get file"
	MOVEI B, OF%RD\OF%RDU
	OPENF
	 JSHLT "Can't open data file"
	MOVEM A, FILJFN		;SAVE IT FOR LATER..
	HRLZ A, A		;JFN,,0
	MOVE B, [.FHSLF,,SHRPAG] ;*** NOTE *** SHRADR NOT FILADR
	MOVE C, [PM%CNT\PM%RD\NPAGES]
	PMAP			;MAP FOR READ
	 EJSHLT 'PMAP failed'
	RET
	SUBTTL SOFTWARE INTERUPT SYSTEM
	
PSIINI:	MOVEI A, .FHSLF		;THIS PROCESS
	RPCAP			;READ CAPS
	TLO C, (SC%CTC)		;SET ^C CAP
	EPCAP			;ENABLE
	MOVE B, [LEVTAB,,CHNTAB] ;PSI TABLES
	SIR			;SET ADDRS
	MOVE B, [600547,,100000] ;0,1,9,10,11,12,15,16,17,20
	AIC			;ACTIVATCE
	 EJSHLT 'AIC failed'
	MOVSI A, .TICCC		;CTRL/C ON CHAN 0
	ATI			;ADD TTY INTERUPT
 	 EJSHLT 'ATI failed'
PSION:	SETZM QUIT		;NO ^C YET
	MOVEI A, .FHSLF		;US
	EIR			;ENABLE INT SYS
	 ERJMP .+1
	RET

PSIOFF:	MOVEI A, .FHSLF		;US
	DIR			;DIABLE INTERUPT SYSTEM
	 ERJMP .+1
	SKIPE QUIT		;^C RECIEVED IN LOCK?
	 JRST DEATH		;YES EXIT NOW
	SETZM QUIT		;CLEAR FLAG
	RET			;GO HOME

TIMSET:	MOVE  A, [.FHSLF,,.TIMEL] ;THIS PROCESS, ELAPSED TIME
	MOVEI B, 1MIN		;1 MIN IN MS.
	MOVEI C, TIMCHN		;ON THIS CHAN
	TIMER			;SET UP TRAP
	 EJSHLT 'TIMER failed'
	RET

LEVTAB:	PC1 ? PC2 ? PC3		;INTERUPT PC STORAGE
CHNTAB:	OFFSET -.
CTCCHN::1,,CTRLC		;CHAN 0 - ^C
TIMCHN::2,,TICK			;CHAN 1 - TIMER (60 SEC.)

	BLOCK .ICPOV-.
	1,,PANIC		;PDL OV
	1,,PANIC		;EOF
	1,,PANIC		;DATA ERROR
	1,,PANIC		;DISK FULL

	BLOCK .ICILI-.
	1,,PANIC		;ILL INST
	1,,PANIC		;IMR
	1,,PANIC		;IMW

	BLOCK .ICMSE-.
	1,,PANIC		;SYSTEM RESOURCES EXAUSTED

	BLOCK 35.-.
	OFFSET 0
	SUBTTL PSI TRAP ROUTINES

; HERE ON TRAPPED ^C
CTRLC:	TMSG '^C'		;AT LEAST LOOK NORMAL
	AOS QUIT		;SIGNAL ^C, INCASE TRAPPING
	TLNN F, (F%TRAP)	;TRAPPING?
	 JRST DEATH		;NO, KILL ME NOW
DBK:	DEBRK			;RETURN
	 TRN
	 JSHLT 'DEBRK failed'

; HERE ONCE A MINUTE
TICK:	MOVEM T, ACSAVE+T	;STOW BLT AC
	MOVEI T, ACSAVE		;FROM ACS TO SAVE AREA
	BLT T, ACSAVE+T-1	;ALL TEMP ACS
	SOSG BIGBEN		;ON THE HOUR?
	 CALL CHIME		; YES, MAKE NOISE
	SOSG COUNTR		;COUNTER DOWN TO ZERO?
	 CALL CHKLNK		;YES, CHECK ON LINK

	MOVEI A, .DWNTI		;GET TIME OF NEXT SHUTDOWN
	GETAB
	 ERJMP TICK2		;??
	JUMPE A, TICK2		;NONE SCHEDULED
	MOVE B, A		;SAVE IN B
	GTAD			;GET NOW
	SUB B, A		;GET TIME REMAINING 'TILL DOWN
	CAML B, [3*<1MIN/3000>/2] ;SHUTDOWN SOON? (WITHIN 1.5 TICKS?)
	 JRST TICK2		; NO, STAY ALIVE

	HRROI A, [ASCIZ '**** CTYSPY terminating due to pending shutdown ****
']
	CALL STORE		;STORE STRING
	SETOM QUIT		;SAY WE REALLY WANT TO DIE
	TMSG 'CTYSPY: terminating for shutdown'
	TMSG
	JRST DEATH

TICK2:	CALL TIMSET		;RESET TIMER
	MOVSI T, ACSAVE		;FROM SAVE BACK TO ACS
	BLT T, T		;ALL TEMP ACS
	JRST DBK		;NO, KEEP TICKING
	
; HERE ON VARIETY OF TERRIBLE THINGS
PANIC:	JSHLT 'Panic Trap'

;; DEATH -- THE ONLY WAY TO DIE
DEATH:	TLNN F, (F%MAST)	;ARE WE A MASTER?
	 JRST GRAVE		; NO, JUST DIE
	TLNN F, (F%LUNK)	;DO WE HAVE A LINK?
	 JRST DEATH2		;NO, JUST DIE
	MOVSI A, (TL%CRO)	;CLEAR REM TO OBJ
	HRR A, PTYDES		;SLIDE IN OBJ
	SETO B,			;CLEAR FOR ALL REMOTES
	TLINK
	 JSHLT 'Could not unlink'
	TLZ F, (F%LUNK)		;FOR WHAT ITS WORTH
DEATH2:	SKIPN QUIT		;WANT TO DIE
	 JRST RELOAD		;NO, TRY TO RELOAD
GRAVE:	HALTF
	JRST GRAVE

RELOAD:	TLNN F, (F%MAST)	;ARE WE A MASTER?
	 JRST GRAVE		; NO, JUST CROAK
	TMSG '?CTYSPY error... '
	SKIPE DBUG		;TRYING TO DEBUG?
	 JRST GRAVE		;YES, NO SHENANIGANS
	AOS A,REBORN		;GET REBIRTH COUNT
	CAIG A,REBMAX		; EXCEEING REBIRTH LIMIT?
	 JRST RELMSG		;NO GO RELOAD
	TMSG 'Too many errors... Quiting...'
	JRST GRAVE

RELMSG:	TMSG 'Reloading..'	;TELL THEM WHAT WE ARE DOING
	TMSG
	AOS QUIT		;EXIT ON ERROR
	SETO A,			;UNMAP
	MOVE B, [.FHSLF,,FILPAG] ;FROM US
	MOVE C, [PM%CNT\<1000-FILPAG>] ;THIS MANY
	PMAP			;UNMAP FILE PAGES
	 ERJMP .+1		;HUSH IT UP
	SETO A,			;CLOSE
	CLOSF			;ALL FILES
	 TRN			;NO MATTER
	MOVEI A, 1MIN		;WAIT
	DISMS			;ONE MINUTE
	MOVSI A, (GJ%OLD)	;OLD FILE
	HRROI B, [ASCIZ /SYS:CTYSPY.EXE/] ;FROM SYS
	GTJFN			;GET IT
	 JSHLT 'Could not find CTYSPY.EXE' ;SORRY
	MOVEM A, 17		;STORE IN ACS

	MOVE B, [DIEBLT,,C]	;MOVE CODE..
	BLT B, EBLT		;..INTO ACS
	SETO A,			;UNMAP
	MOVSI B, .FHSLF		;FROM 0
	MOVE 0,REBORN		;SAVE RELOAD COUNT
	JRST D

DIEBLT:	OFFSET C-.
	PM%CNT\1000		; C
	PMAP			; D
	MOVSI A, .FHSLF		; 5
	HRRI A, (17)		; 6
	GET			; 7
	RESET			; 10
	MOVEI A, .FHSLF		; 11
	GEVEC			; 12
EBLT::	JRST 1(B)		; 13
	OFFSET 0

	SUBTTL	LUUO HANDLR

UUOH:	PUSH P, A
	LDB A, [.BP <777000,,>,.JBUUO] ;GET OPCODE
	CALL @UUOTAB-1(A)
	POP P, A
	RET

%FATAL:	HRRO A, .JBUUO		;GET STRING ADDR
	TRNE A, -1		;ANYTHING?
	 ESOUT			;YEP
%FATL2:	AOSN FATALC		;SECOND FATAL?
	 JRST DEATH		;NO
	RET			;YES, JUST RETURN

%TMSG:	HRRO A, .JBUUO		;GET STRING ADDR
	TRNN A, -1		;ANYTHING?
	 HRROI A, CRLF		;DEFAULT OF CRLF
	PSOUT
	RET

CRLF:	ASCIZ "
"

%JSHLT:	HRRO A, .JBUUO		;GET TEXT
	TRNN A, -1		;WAS THERE ANY?
	 HRROI A, [ASCIZ 'JSYS error'] ;DEFAULT MESS
	ESOUT			;TYPE IT
	HRROI A, [ASCIZ ': ']	;PUNCTUATE!!
	PSOUT
	MOVEI A, .PRIOU		;TO TTY
	HRLOI B, .FHSLF		;THIS PROCESS, LAST ERROR
	SETZ C,
	ERSTR
	 TRNA
	  TRN
	TMSG
	JRST %FATL2

	SUBTTL	IMPURE DATA

PURE==.
.==IMPURE

PDL:	BLOCK PDLL		;PDL SWEET PDL
TMPBUF:	BLOCK BUFSIZ		;TEMP BUF FOR TEXT
TICBUF:	BLOCK <200.+4>/5	;TEMP BUF USED AT CLOCK LEVEL
QUIT:	BLOCK 1			;NUMBER OF ^C'S WHILE TRAPPING
CTYDES:	BLOCK 1			;SYSJOB OUTPUT GOES HERE
PTYPAR:	BLOCK 1			;PTY INFO
PTYJFN:	BLOCK 1			;PTY JFN
PTYDES:	BLOCK 1			;DEVICE DESCRIPTOR FOR PTY
PTYBUF:	ASCIZ 'PTY' ? BLOCK 1	;PROTOTYPE PTY DEVICE NAME
FILJFN:	BLOCK 1			;PMAP FILE JFN
PC1:	BLOCK 1			;PSI LEVEL 1 PC
PC2:	BLOCK 1			;PSI LEVEL 2 PC
PC3:	BLOCK 1			;PSI LEVEL 3 PC
TTACTL:	BLOCK 1			;MONITOR TABLE FOR ACTIVE LINES
TTLINK:	BLOCK 1			;OFFSET INTO TTY DYNAMIC DATA FOR LINKS
COUNTR:	BLOCK 1			;5 MIN COUNTDOWN FOR LINK DOCTOR
BIGBEN:	BLOCK 1			;MINUTES 'TILL THE HOUR
ACSAVE:	BLOCK 20		;HOME AWAY FROM HOME
DBUG:	BLOCK 1			;-1 IFF DEBUGING
FATALC:	BLOCK 1			;-1 NORMALLY, 0 AFTER FIRST FATAL
REBORN:	BLOCK 1			;-1 IFF RELOADED
CMDBLK:	0			;FLAGS + REPARSE
	.PRIIN,,.PRIOU		;JFNS
	-1,,[0]			;PROMPT
	-1,,STRBUF
	-1,,STRBUF
	5*LSTRBF
	0
	-1,,ATMBUF
	5*LATMBF
	CMDGTJ
STRBUF:	BLOCK	<LSTRBF==20>
ATMBUF:	BLOCK	<LATMBF==10>
CMDGTJ:	BLOCK	20		;COMND GTJFN BLOCK
PEKBLK:	PEKLEN			;*** XPEEK% BLOCK ****
	.XPPEK			;FUNCTION
PEKCNT:	1			;COUNT
	0			;WORDS XFERED
PEKMON:	0			;MONITOR ADDR
PEKADR:	0			;USER ADDR
PEKLEN==.-PEKBLK		;*** END OF XPEEK BLOCK ***


IMPURE==.
.==PURE
JUNK:	CONSTANTS

	END START
