	.TITLE	INACTV - CHECK TERMINAL INACTIVITY
	.IDENT	/V01/
	.SBTTL	NIFTY NOTICE & ASSORTED LIBRARY CALLS

;
;	COPYRIGHT (C) 1979
;		MANAGEMENT SCIENCE ASSOCIATES, INC.
;		5100 CENTRE AVENUE
;		PITTSBURGH, PENNSYLVANIA  15232
;
;	THIS SOFTWARE IS DISTRIBUTED WITHOUT COST, AND MAY BE
;	REPRODUCED ONLY WITH THE INCLUSION OF THIS COPYRIGHT
;	STATEMENT.  MANAGEMENT SCIENCE ASSOCIATES ASSUMES NO
;	RESPONSIBILITY FOR THE PERFORMANCE OF THIS SOFTWARE.
;
;	AUTHOR:	MARK PILANT
;		JULY 1979
;

; THIS PROGRAM IS TO BE RUN AS A DETACHED PROCESS TO CHECK TERMINAL
; INACTIVITY. IF IT FINDS A TERMINAL THAT HAS BEEN INACTIVE FOR 15 MINUTES,
; IT SENDS A MESSAGE TO THE TERMINAL TO THE EFFECT THAT IF NOTHING IS
; TYPES FOR ANOTHER 15 MINUTES THE JOB WILL BE KILLED.

	.ENABL	DBG

	.LIBRARY	"SYS$LIBRARY:LIB.MLB"

	$DDBDEF
	$IPLDEF
	$PHDDEF
	$UCBDEF

; USEFUL MACROS

	.MACRO	DCDTRM	SYMBOL,TRMINL
	...T1=	0
	.IRPC	CHAR,TRMINL
	...T1=	...T1+1
.IF	EQ,	...T1-3
	SYMBOL=	<^A\CHAR\-^A\A\>*^D8
.ENDC;	EQ,	...T1-3
.IF	EQ,	...T1-4
	SYMBOL=	SYMBOL+1+CHAR
.ENDC;	EQ,	...T1-4
	.ENDR;	CHAR,TRMINL
	.ENDM	DCDTRM

	.MACRO	IGNTRM	BASE,TRMINL
	DCDTRM	...T2,TRMINL
	...T3=	.
	.=	BASE+...T2-1
	.BYTE	FL.NCH			;DON'T CHECK THIS TERMINAL
	.=	...T3
	.ENDM	IGNTRM

	.MACRO	GENTRM	TRMCOD,?LAB..1,?LAB..2
	...T5=	TRMCOD/^D8		;CALC CONTROLLER CODE
	...T6=	...T5*^D8		;CALC CODE OF FIRST UNIT ON CONTROLLER
	...T6=	TRMCOD-...T6		;CALC UNIT NUMBER
	...T5=	...T5+^A/A/		;CONVERT TO ASCII
	...T6=	...T6+^A/0/		;SAME HERE
	.LONG	LAB..2-LAB..1
	.LONG	LAB..1
	.SAVE_PSECT
	.PSECT	$MSG$,LCL,NOEXE,NOPIC,NOSHR,RD,REL,USR,NOWRT,LONG
LAB..1:	.ASCII	/TT/<...T5><...T6>
LAB..2:
	.RESTORE_PSECT
	.ENDM	GENTRM

	.MACRO	TIMSTR	MINUTE,STRADR
STRADR:	.ASCID	\0 00:'MINUTE':00.00\
	.ENDM	TIMSTR
	.PAGE
	.SBTTL	ASSEMBLY PARAMATERS AND OTHER MISC. THINGS

; NAME OF LAST TERMINAL TO CHECK FOR

	DCDTRM	LASTRM,TTF7

; GENERATE STRING FOR HIBERNATE TIME

	TIMSTR	15,SLPSTR

; NEEDED FLAGS

	FL.NCH=	^O1			;DON'T CHECK ANY TERMINAL WITH THIS SET
	FL.WRN=	^O2			;TERMINAL HAS BEEN SENT WARNING MESSAGE
	FL.PRT=	^O4			;USER LOGGED IN BETWEEN 15 MINUTE CHECKS
	FL.KIL=	^O10			;SET IF PROCESS SHOULD BE DELETED

; NOTE:
;	THE STORAGE FROM OPRCNT THROUGH FLAGS MUST BE IN CONSECUTIVE MEMORY

; STORAGE FOR OPERATION COUNTS

OPRCNT:	.BLKL	LASTRM

; STORAGE FOR ACCUMULATED CPU TIME (IN CASE PROCESS IS VERY CPU BASED)

CPUTIM:	.BLKL	LASTRM

; STORAGE FOR LOGIN TIME

LOGTIM:	.BLKL	LASTRM

; STORAGE FOR OWNER PID

OWNPID:	.BLKL	LASTRM

; STORAGE FOR USEFUL FLAGS

FLAGS:	.REPT	LASTRM
	.BYTE	0
	.ENDR;	LASTRM

; TERMINALS TO NOT CHECK

	IGNTRM	FLAGS,TTB0		;PDP-11 TERMINAL
	IGNTRM	FLAGS,TTB1		;MARK PILANT'S OFFICE
	IGNTRM	FLAGS,TTB2		;GENE BUTTYAN'S OFFICE
	IGNTRM	FLAGS,TTB3		;RICH MICKELSEN'S OFFICE
	IGNTRM	FLAGS,TTB4		;TOM LAWRENCE'S OFFICE
	IGNTRM	FLAGS,TTB5		;OPERATOR TERMINAL
	IGNTRM	FLAGS,TTB7		;SOMETIMES OPERATOR TERMINAL & QUEUE
	IGNTRM	FLAGS,TTF7		;NEW YORK VARIAN LINE

; VALID TERMINAL NAME DESCRIPTORS

	.ENABL	LSB
TRMNAM:
	...T4=0
	.REPT	LASTRM
	GENTRM	...T4
	...T4=	...T4+1
	.ENDR;	LSTERM
	.DSABL	LSB

; MISC. STORAGE

SLPTIM:	.BLKQ	1			;DELTA TIME FOR SLEEPING
KILTIM:	.BLKQ	1			;TIME JOB WAS KILLED
WRNMSG:	.ASCID	/***WARNING*** If nothing is done for 15 minutes, your job will be killed./
KILMSG:	.ASCID	/HH:MM:SS.CC -- Job being killed./

; HERE I GO....

	.ENTRY	INACTV,^M<R2,R3,R4,R5,R6,R7,R8,R9,R10>

	MOVC5	#0,OPRCNT,#0,#FLAGS-OPRCNT,OPRCNT	;CLEAR NEEDED STUFF
	$BINTIM_S	SLPSTR,SLPTIM	;CONVERT TIME STRING TO 64 BIT FORMAT
NEXT:	$CMKRNL_S	CHKTRM		;I NEED TO BE IN KERNAL MODE TO DO ANYTHING
	MOVL	#LASTRM,R8		;INDEX OF LAST TERMINAL TO CHECK
10$:	BITB	#FL.NCH,FLAGS[R8]	;CHECKING THIS TERMINAL?
	BNEQ	20$			;XFER IF NOT
	BITB	#FL.WRN,FLAGS[R8]	;GET WARNING?
	BEQL	15$			;XFER IF NO WARNING TO SEND
	$BRDCST_S	MSGBUF=WRNMSG,DEVNAM=TRMNAM[R8]	;ELSE SEND MESSAGE
	BRW	20$			;GO CHECK NEXT
15$:	BITB	#FL.KIL,FLAGS[R8]	;KILL PROCESS?
	BEQL	20$			;XFER IF NOT
	$GETTIM_S	TIMADR=KILTIM	;GET TIME JOB IS TO BE KILLED
	$ASCTIM_S	TIMBUF=KILMSG,TIMADR=KILTIM,CVTFLG=#1
	$BRDCST_S	MSGBUF=KILMSG,DEVNAM=TRMNAM[R8]
	MULL3	#4,R8,R9		;CALC OFFSET FOR DEFERRED MODE
	$DELPRC_S	OWNPID(R9)	;DELETE PROCESS
	CLRL	OPRCNT[R8]		;RESET ALL COUNTS
	CLRL	OWNPID[R8]
	CLRL	CPUTIM[R8]
	BICB2	#FL.KIL,FLAGS[R8]	;RESET NEEDED FLAGS
20$:	SOBGEQ	R8,23$			;CONTINUE TILL DONE
	BRB	26$			;XFER WHEN DONE
23$:	BRW	10$			;ELSE DO NEXT
26$:	$SCHDWK_S	DAYTIM=SLPTIM
	BLBS	R0,30$			;XFER IF NO ERRORS
	RET				;ELSE KILL IMAGE
30$:	$HIBER_S			;WAIT
	BLBS	R0,40$			;XFER IF NO ERRORS
	RET				;ELSE KILL IMAGE
40$:	BRW	NEXT			;NEXT...
CHKTRM:	.WORD	^M<R2,R3,R4,R5,R6,R7,R8,R9,R10>
RSTART:	MOVL	@#SCH$GL_CURPCB,R4	;GET ADDR OF CURRENT PCB
	JSB	SCH$IOLOCKR		;LOCK I/O DATA BASE FOR READING
	MOVL	@#SCH$GL_PCBVEC,R10	;GET ADDR OF PCB VECTOR
	MOVAL	@#IOC$GL_DEVLIST-DDB$L_LINK,R6	;GET BASE OFFSET
NXTDDB:	MOVL	DDB$L_LINK(R6),R6	;GET ADDR OF VALID DDB
	BNEQU	10$			;XFER IF ANOTHER TO DO
	MOVL	@#SCH$GL_CURPCB,R4	;GET ADDRESS OF CURRENT PCB
	JSB	SCH$IOUNLOCK		;UNLOCK I/O DATA BASE
	RET				;RETURN TO FINISH UP
10$:	CMPW	DDB$T_NAME+1(R6),#^A/TT/	;IS DEVICE A TERMINAL?
	BNEQ	NXTDDB			;XFER IF NOT
	MOVAL	DDB$L_UCB-UCB$L_LINK(R6),R7	;GET ADDR OF UCB
NXTUCB:	MOVL	UCB$L_LINK(R7),R7	;GET ADDR OF VALID UCB
	BEQLU	NXTDDB			;GET NEXT DDB WHEN DONE
	CLRL	R8			;RESET TERMINAL INDEX
	SUBB3	#^A/A/,DDB$T_NAME+3(R6),R8	;CONVERT CONTROLLER NUMBER
	MULL2	#8,R8			;TIMES NUMBER OF UNITS IN CONTROLLER
	ADDW2	UCB$W_UNIT(R7),R8	;ADD IN UNIT (ON CONTROLLER)
	BITB	#FL.NCH,FLAGS[R8]	;SHOULD I CHECK THIS ONE?
	BNEQ	NXTUCB			;XFER IF NOT
	TSTL	UCB$L_PID(R7)		;ANY OWNER?
	BNEQ	10$			;XFER IF NONE
	BICB2	#FL.WRN,FLAGS[R8]	;ELSE RESET WARNING FLAG
	CLRL	OPRCNT[R8]		;AND OPERATION COUNT
	CLRL	OWNPID[R8]		;AND ANY PREVIOYS OWNER
	CLRL	CPUTIM[R8]		;RESET CPU TIME USED
	BRW	NXTUCB			;GET NEXT UNIT
10$:	TSTL	OWNPID[R8]		;IS THIS NEW OWNER
	BEQL	20$			;XFER IF POSSIBLE
	CMPL	UCB$L_PID(R7),OWNPID[R8]	;SAME AS BEFORE?
	BEQL	30$			;XFER IF SO...SEE IF USER WAS WARNED
	BISB2	#FL.PRT,FLAGS[R8]	;NEW USER
20$:	MOVL	UCB$L_PID(R7),OWNPID[R8]	;SAVE NEW OWNER
	MOVL	UCB$L_OPCNT(R7),OPRCNT[R8]	; AND OPERATION COUNT
	MOVZWL	UCB$L_PID(R7),R1	;GET PCB INDEX
	MOVL	(R10)[R1],R1		;GET ADDR OF PCB
	CMPW	PCB$L_UIC+2(R1),#1	;GROUP 1 (JOBCTL MAYBE?)
	BEQL	NXTUCB			;XFER IF SO...DON'T CHECK
	DSBINT	#IPL$_SYNCH		;DISABLE SWAPPING
	BBS	#PCB$V_PHDRES,PCB$L_STS(R1),25$	;XFER IF THERE IS A PHD
	ENBINT				;ENABLE SWAPPING
	CLRL	CPUTIM[R8]		;NO CPU TIME
	BICB2	#FL.WRN,FLAGS[R8]	;NO WARNING GIVEN
	BRW	NXTUCB			;GET NEXT DEVICE
25$:	MOVL	PCB$L_PHD(R1),R1	;GET ADDR OF PHD
	MOVL	PHD$L_CPUTIM(R1),CPUTIM[R8]	;SAVE CURRENT CPU TIME
	ENBINT				;ENABLE SWAPPING
	BICB2	#FL.WRN,FLAGS[R8]	;NO WARNING GIVEN
	BRW	NXTUCB			;GET NEXT UNIT
30$:	CMPL	UCB$L_OPCNT(R7),OPRCNT[R8]	;DID USER TYPE ANYTHING?
	BEQL	40$			;XFER IF NOT..CHECK CPU TIME
	MOVL	UCB$L_OPCNT(R7),OPRCNT[R8]	;ELSE SAVE NEW COUNT
	BICB2	#FL.WRN!FL.PRT,FLAGS[R8]	;NO WARNING
	BRW	NXTUCB			;GET NEXT UCB
40$:	DSBINT	#IPL$_SYNCH		;DISABLE SWAPPING
	MOVZWL	UCB$L_PID(R7),R1	;GET PCB INDEX
	MOVL	(R10)[R1],R1		;GET PCB ADDRESS
	BBS	#PCB$V_PHDRES,PCB$L_STS(R1),45$	;XFER IF THERE IZ A PHD
	ENBINT				;ENABLE SWAPPING
	BRW	NXTUCB			;ELSE GET NEXT DEVICE
45$:	MOVL	PCB$L_PHD(R1),R1	;GET PHD ADDRESS
	CMPL	PHD$L_CPUTIM(R1),CPUTIM[R8]	;KEPT THE MACHINE BUSY ANY?
	BEQL	50$			;XFER IF NOT..POSSIBLE CANDIDATE FOR AXE
	ENBINT				;ENABLE SWAPPING
	MOVL	PHD$L_CPUTIM(R1),CPUTIM[R8]	;ELSE SAVE NEW CPU TIME
	BICB2	#FL.WRN!FL.PRT,FLAGS[R8]	;NO WARNING
	BRW	NXTUCB			;GET NEXT DEVICE
50$:	ENBINT				;ENABLE SWAPPING
	BITB	#FL.PRT,FLAGS[R8]	;LOGIN IN BETWEEN CHECKS?
	BEQL	60$			;NO...I MUST GET NASTY
	BICB2	#FL.PRT,FLAGS[R8]	;YES, GIVE USER BENEFIT OF DOUBT..NOT YET
	BRW	NXTUCB			;GO GET NEXT DEVICE
60$:	BITB	#FL.WRN,FLAGS[R8]	;DID USER GET ONE WARNING?
	BEQL	70$			;NO, SEND ONE
	BISB2	#FL.KIL,FLAGS[R8]	;YES, SET TO DELETE PROCESS
	BICB2	#FL.WRN,FLAGS[R8]	;NO WARNING...KILL!!!
	BRW	NXTUCB			;THEN GET NEXT DEVICE
70$:	BISB2	#FL.WRN,FLAGS[R8]	;SET TO SEND WARNING
	BRW	NXTUCB			;GET NEXT UNIT

; THAT'S ALL FOLKS

	.END	INACTV
