Google
 

Trailing-Edge - PDP-10 Archives - SRI_NIC_PERM_SRC_3_19910112 - utilities/idlkil.mac
There are no other files named idlkil.mac in the archive.
title	IDLKIL - kill idle jobs
subttl	NH Samuelson, 2644, 8/10/81

	search	slaunv
	slaplg	idl

idledt==^d6
;edit date		description
;6  10/28/81	Add countdown for errors
;5  10/16/81	Include program name in log entry
;4  10/15/81	Double time limits if NOT in EXEC
;3  8/20/81	remove minimum threshold for idle time
;2  8/20/81	use TTMSG%, not SOUT% to avoid hanging on output

	.reques	sys:macrel
subttl	Definitions

nd maxjob,200			;128 jobs should be plenty
nd maxerr,^d10			;10 errors before death.
nd maxwin,10			;8 "winners" who will not be logged off.
nd jilen,.jimax+1		;number of entries to return from GETJI
nd txtlen,^d132			;max length of command in .ini file
subttl	Storage

zerbeg:				;start of area to clear on startup
txtbuf:	block	<txtlen/5+1>
atmbuf:	block	<txtlen/5+1>
inijfn:	block	1		;jfn for ini file
logjfn:	block	1		;jfn for log file
numwin:	block	1		;initial aobjn counter for winners
wintbl:	block	maxwin		;user numbers for exempt users
curdtm:	block	1		;current date/time
lasact:	block	maxjob		;when we last saw action on this job
lasrtm:	block	maxjob		;run time when last active
lgitim:	block	maxjob		;when this job logged in
flags:	block	maxjob		;random flags
jiblk:	block	jilen		;storage for GETJI info
zerend==.-1			;end of area to clear on startup

lim01:	^d30*nbsmin		;30 minutes till first warning
lim02:	^d40*nbsmin		;40 minutes till logout
limdet:	^d10*nbsmin		;10 minutes, no warning, for detached jobs
trshld:	^d2*^d1000		;runtime threshold, two seconds
errcnt:	maxerr			;countdown for errors

dispat:	block	maxjob		;where to go to look at this job
stak:	block	stksiz		;pdl

;command state block for COMND%
csb:	z			;flags,,no reparse
	z	.nulio		;input jfn will be filled in
	-1,,[asciz/IDLKIL> /]	;no control-r stuff
	-1,,txtbuf		;start of input buffer
	-1,,txtbuf		;next thing to parse
	z	txtlen		;space left in buffer
	z			;characters left in buffer
	-1,,atmbuf		;start of atom buffer
	z	txtlen		;size of atom buffer
	z	jfnblk		;pointer to gtjfn block

jfnblk:	block	20		;for COMND to do GTJFN
subttl	initialization

entvec:	jrst	go
	jrst	go
	vernum

go:	makstk
	reset
	movei	t1,.fhslf	;check our capabilities
	rpcap%
	txnn	t3,sc%whl!sc%opr ;am I god?
	 jrst	no.god		;no, loose
	clearm	zerbeg		;clear everything
	move	t1,[zerbeg,,zerbeg+1]
	blt	t1,zerend
	movei	t1,er.job	;assume no jobs anywere
	movem	t1,dispat
	move	t1,[dispat,,dispat+1] ;prepare for blt
	blt	t1,dispat+maxjob-1
	call	inifil		;read the initialization file
	call	st.log		;start the log file
	jrst	main		;go to the main loop
subttl	main loop

main:	gtad%			;get current date/time
	movem	t1,curdtm
	move	p1,[-maxjob,,1]	;setup for aobjn
main.1:	movei	t1,(p1)		;job number to check
	move	t2,[-jilen,,jiblk] ;where to put the data
	clear	t3,		;get all job info
	getji%
	 erjmp	no.ji		;check for errors
;we have a job here, see if it is the same as the last time
	skipn	t1,jiblk+.jilln	;get login time
	 jrst	no.job		;not logged in
	camn	t1,lgitim(p1)	;compare with old data
	jrst	@dispat(p1)	;he is idle, go see what to do.

is.new:	movem	t1,lgitim(p1)
	skipge	jiblk+.jibat	;is this a batch job?
	 jrst	is.bat		;yes!
	move	p2,numwin	;see if he is a winner
	move	t1,jiblk+.jiuno	;get his user number
	camn	t1,wintbl(p2)	;is he a winner
	 jrst	is.win		;yes
	aobjn	p2,.-2

is.act:	move	t1,curdtm	;the job is active
	movem	t1,lasact(p1)	;save his run time and the current time
	move	t1,jiblk+.jirt
	movem	t1,lasrtm(p1)
	movei	t1,chkidl	;where to go next time
	movem	t1,dispat(p1)
	jrst	nxtjob
ck.bat:	jrst	nxtjob
ck.win:	jrst	nxtjob
nxtjob:	aobjn	p1,main.1	;look at the next job
main.9:	movei	t1,^d30*^d1000	;wait 30 seconds and do it again
	disms%
	jrst	main
subttl	subroutines

is.bat:	skipa	t1,[ck.bat]	;ignore all batch jobs for now
is.win:	movei	t1,ck.win	;dont do any checking on exempt jobs
	movem	t1,dispat(p1)
	jrst	nxtjob

chkidl:	move	t1,jiblk+.jirt	;latest run time
	sub	t1,lasrtm(p1)	;get the change
	camle	t1,trshld	;changed more than minimum
	 jrst	is.act		;yes, he is active
	move	t2,curdtm	;get current date/time
	sub	t2,lasact(p1)	;how long idle?
	skipge	t1,jiblk+.jitno	;get terminal number
	 jrst	is.det		;he is detached...
	skipn	jiblk+.jit20	;[4]skip if in exec
	 ash	t2,-1		;[4]not exec, double the time limit
	camg	t2,lim01	;short time?
	 jrst	nxtjob		;yes, dont do anything yet
	txo	t1,.ttdes	;make terminal designator for SOUT%
	hrroi	t2,[asciz/


Your job has been idle for a LONG time.  It will be logged out
in a few minutes if still inactive.

/]
;;;	clearb	t3,t4
;;;	sout%
	ttmsg%			;force it out

	hrroi	t2,[asciz/ Warn idle job /]
	call	displa
	movei	t1,chkkil	;change dispatch address
	movem	t1,dispat(p1)
	jrst	nxtjob

chkkil:	move	t1,jiblk+.jirt	;latest run time
	sub	t1,lasrtm(p1)	;get the change
	camle	t1,trshld	;changed more than minimum
	 jrst	is.act		;yes, he is active
	move	t2,curdtm	;get current date/time
	sub	t2,lasact(p1)	;how long idle?
	skipge	t1,jiblk+.jitno	;get terminal number
	 jrst	is.det		;he is detached...
	skipn	jiblk+.jit20	;[4]skip if in exec
	 ash	t2,-1		;[4]not exec, double the time limit
	camg	t2,lim02	;too long?
	 jrst	nxtjob		;not yet
	txo	t1,.ttdes	;make terminal designator for SOUT%
	hrroi	t2,[asciz/


Your job has been idle for TOO LONG.  Goodbye.

/]
;;;	clearb	t3,t4
;;;	sout%
	ttmsg%

	hrroi	t2,[asciz/ Kill idle job /]
	call	displa
kilhim:	movei	t1,(p1)		;log him off...
	lgout%
	 erjmp	.+1		;must ignore errors here, in case he
				;just logged out himself...
	movei	t1,er.job	;in case he is still there next time...
	movem	t1,dispat(p1)
	jrst	nxtjob

is.det:	camg	t2,limdet	;too long?
	 jrst	nxtjob		;not yet
	hrroi	t2,[asciz/ Kill detached job /]
	call	displa
	jrst	kilhim		;yes...no warning, just kill him

no.job:	skipn	lgitim(p1)	;do we know he is gone?
	 jrst	nxtjob		;yes, forget it
	clearm	lgitim(p1)
	movei	t1,er.job
	movem	t1,dispat(p1)
	jrst	nxtjob

displa:	hrroi	t1,txtbuf	;build string here first
	push	p,t2		;save starting string
	seto	t2,
	clear	t3,
	odtim%
	pop	p,t2
	sout%
	movei	t2,(p1)		;get job #
	movei	t3,^d10		;decimal
	nout%
	 jfcl
	hrroi	t2,[asciz/ user /]
	clear	t3,
	sout%
	move	t2,jiblk+.jiuno	;get user number
	dirst%			;convert to user name
	 erjmp	[hrroi	t2,[asciz/Unknown/]
		sout%
		jrst	.+1]

;[5] add program name to log entry
	hrroi	t2,[asciz/ in /]
	sout%
	skipn	t2,jiblk+.jipnm	;[5] use program name if any
	 move	t2,jiblk+.jisnm	;[5] else use subsystem name
	skipn	t2		;[5] if still none,
	 move	t2,[sixbit/*NONE*/]
pgm.lp:	clear	t3,
	rotc	t2,6		;[5] bring next char into t3
	addi	t3," "		;[5] convert sixbit to ascii
	idpb	t3,t1
	jumpn	t2,pgm.lp	;[5] loop over whole name

do.tty:	skipge	jiblk+.jitno	;detached?
	 jrst	no.tty
	hrroi	t2,[asciz/ on TTY/]
	clear	t3,
	sout%
	movei	t3,^d8		;octal
	move	t2,jiblk+.jitno
	nout%
	 jfcl
no.tty:	hrroi	t2,[asciz/
/]
	sout%
	call	wrtlog
	ret

wrtlog:	skipn	t1,logjfn	;log file?
	 ret			;no
	movx	t2,<<7b5>!of%app>
	openf%
	 erjmp	jserr0##
	hrroi	t2,txtbuf
	clear	t3,
	sout%
	 ercal	jserr0##
	txo	t1,co%nrj	;dont release the jfn
	closf%
	 erjmp	jserr0##
	ret

er.job:	tmsg	<
%Error in IDLKIL while processing job >
	movei	t1,.priou
	movei	t2,(p1)
	movei	t3,^d10
	nout%
	 jfcl
	tmsg	<.   Please notify Sam
>
	sosl	errcnt		;count down error counter
	 jrst	nxtjob		;still ok...
	tmsg	<?Max error count exceeded>
	haltf%
	 jrst	main		;in case of continue


die:	tmsg	<
?Fatal error in IDLKIL initialization>
	haltf
	 jrst	main

no.god:	tmsg	<?Wheel or Operator capability required>
	haltf%
	 jrst	no.god

no.ji:	cain	t1,gtjix4	;no such job?
	 jrst	no.job		;yes, clear our data
	cain	t1,gtjix3	;invalid job number?
	 jrst	main.9		;yes, must be thru, go sleep
	call	jshlt0##	;tell about the error and quit
subttl	log initialization

st.log:	hrroi	t1,txtbuf
	seto	t2,
	clear	t3,
	odtim%			;start with time and date
	hrroi	t2,[asciz/ Idle Job Killer started
  The following users are exempt: /]
	sout%
	move	p2,numwin
	jrst	lg.exm
lg.ex0:	hrroi	t2,[asciz/, /]
	sout%
lg.exm:	move	t2,wintbl(p2)
	dirst%
	 erjmp	.+1
	aobjn	p2,lg.ex0
	hrroi	t2,[asciz/
/]
	sout%
	call	wrtlog		;write the first part to the log file
	hrroi	t1,txtbuf
	hrroi	t2,[asciz/  Jobs not using more than /]
	sout%
	move	t2,trshld	;threshold for idle time
	idivi	t2,^d100	;convert to tenths of seconds
	idivi	t2,^d10		;convert to seconds
	movem	t3,p1		;save remainder
	movei	t3,^d10
	nout%
	 jfcl
	skipe	p1		;remainder non-zero?
	 jrst	[movei	t2,"."
		bout%
		move	t2,p1
		nout%
		 jfcl
		jrst	.+1]
	hrroi	t2,[asciz/ seconds in /]
	clear	t3,
	sout%
	move	t2,lim02	;get limit
	idivi	t2,nbsmin	;convert back to minutes
	movei	t3,^d10
	nout%
	 jfcl
	hrroi	t2,[asciz/ minutes will be killed,
  with detached jobs killed after /]
	clear	t3,
	sout%
	move	t2,limdet
	idivi	t2,nbsmin
	movei	t3,^d10
	nout%
	 jfcl
	hrroi	t2,[asciz/ minutes.
Time limits are doubled if the job is in a user program, rather than the EXEC.

/]
	clear	t3,
	sout%
	call	wrtlog		;finish the log entry
	ret			;all done
subttl	file initialization

keytbl:	n$key,,n$key
KEY	DETACHED
KEY	EXEMPT
KEY	IDLE
KEY	LOG
KEY	THRESHOLD
n$key==.-keytbl-1

inifil:	movx	t1,<gj%sht!gj%old>
	hrroi	t2,[asciz/system:idle-job-killer.init/]
	gtjfn%
	 erjmp	[tmsg	<?Cant get SYSTEM:IDLE-JOB-KILLER.INIT>
		jrst	jshlt0##]
	movem	t1,inijfn	;store the jfn
	hrlm	t1,csb+.cmioj	;in the CSB also
	movx	t2,<<7b5>!of%her!of%rd>
	openf%			;open for read
	 erjmp	[tmsg	<?Cant open init file>
		jrst	jshlt0##]
	jrst	ini.1
ini.0:	movei	t2,[flddb. .cmcfm]
	call	docomd
ini.1:	movei	t2,[flddb. .cmini]
	call	docomd
	movei	t2,[flddb. .cmkey,,keytbl]
	call	docomd
	hrrz	t2,(t2)		;get dispatch address
	jrst	(t2)		;go


inieof:	skipg	t1,numwin	;how many winners do we have
	 jrst	[tmsg	<?No EXEMPT users> ;must have some...
		jrst	die]
	movni	t1,(t1)		;make it negative for aobjn
	hrlzm	t1,numwin
	move	t1,inijfn
	closf%
	 erjmp	.+1		;ignore error on close
	ret

.IDLE:	movei	t2,[flddb.	.cmnum,,^d10]
	call	docomd
	caig	t2,^d15		;must be at least 15 minutes
	 jrst	[tmsg	<IDLE time limit must be at least 15 minutes>
		jrst	die]
	imuli	t2,nbsmin	;convert minutes to correct form
	movem	t2,lim02	;save as final limit
	subi	t2,^d10*nbsmin	;warn 10 minutes earlier
	movem	t2,lim01
	jrst	ini.0

.DETAC:	movei	t2,[flddb.	.cmnum,,^d10]
	call	docomd
	caig	t2,^d5		;must be at least 15 minutes
	 jrst	[tmsg	<DETACH time limit must be at least 5 minutes>
		jrst	die]
	imuli	t2,nbsmin	;convert minutes to correct form
	movem	t2,limdet	;save as new limit
	jrst	ini.0

.THRES:	movei	t2,[flddb.	.cmnum,,^d10]
	call	docomd
;;;	caig	t2,^d1000	;must be at least 1 second
;;;	 jrst	[tmsg	<THRESHOLD must be at least 1000 ms>
;;;		jrst	die]
	caile	t2,^d60*^d1000	;not over 60 seconds
	 jrst	[tmsg	<THRESHOLD too big>
		jrst	die]
	movem	t2,trshld	;store new threshold
	jrst	ini.0

.EXEMP:	movei	t2,[flddb. .cmusr]
	call	docomd
	aos	t1,numwin	;another winner
	cail	t1,maxwin	;too many?
	 jrst	[tmsg	<?Too many EXEMPT entries>
		jrst	die]
	movem	t2,wintbl-1(t1)	;store this user number
	jrst	ini.0

.LOG:	movei	t2,[flddb. .cmofi,,,,<system:idle-job-killer.log>]
	call	docomd
	movem	t2,logjfn	;save the jfn
	jrst	ini.0

docomd:	movei	t1,csb
	comnd%
	 erjmp	[movei	t1,.fhslf
		geter%
		tlz	t2,-1
		jrst	chkerr]
	txnn	t1,cm%nop	;parse ok?
	 ret			;yes
chkerr:	cain	t2,iox4		;eof?
	 jrst	[movei	t2,[inieof]
		ret]
	tmsg	<?Error reading init file>
	jrst	jshlt0##

	end	<3,,entvec>