	.title	fel
;
;
;	this program is used to kill all subprocesses hanging off of
;	the shell invoked from MCR via the shl [args] command.
;	It may also be used to fel a background process tree when
;	invoked via
;
;	fel taskname
;
;	it is called fell since it fells the process tree.
;
;	it works by sending a message to $Tnn.1, which propagates the
;	message to its child, and so on.  If for some reason $Tnn.1
;	is not installed and running, fell prints an error message
;	with the directive status word value
;
;	this program should be installed as ...fel for efficient
;	use by the user
;
;	This program has been rewritten in assembler due to
;	large memory requirements of its predecessor.
;
;
	.mcall	alun$s,glun$s,sdat$s,exit$s,qiow$s,gmcr$,dir$
;
;	local constants
;
ttylun=1	; lun for terminal io
qioefn=1	; event flag for qios
blank=40	; ASCII code for blank
cr=15		; ASCII code for carriage return
lf=12		; ASCII code for line feed
esc=33		; ASCII code for escape
;
;
;	local impure storage
;
;
gmcrpb:	gmcr$			; get MCR block
lunbuf:	.blkw	6		; buffer for GLUN$
octnum:	.blkb	4		; 6 byte buffer for $cbomg
unit:	.blkb	2		; these 2 bytes will have the unit #
outbuf:	.byte	cr,lf		; formatting buffer for error processor
obuf:	.blkb	132.		; remainder of buffer
buf:	.blkb	132.		; buffer for formatting
number:	.blkb	10.		; buffer for error status
;
;
;	local pure storage
;
;
ermsg1:	.asciz	"Error interrupting "
ermsg2:	.asciz	", status = "
;
;	buffer for child taskname follows
;
tfil:	.ascii	"$"
devc:	.blkb	1		; will have the device character (T)
tnum:	.blkb	2
	.asciz	".1"
	.even
;
;	task name for send data invocation
;
task:	.rad50	"      "
;
;	start of fel code
;
;
;
;	now we must generate the task name for the child - $Tnn.1
;
;
start:
	alun$s	#ttylun,#"TI,#0		; assign lun to terminal
	dir$	#gmcrpb			; get MCR command line
	bcs	nocmd			; none to fetch
	mov	@#$dsw,r0		; length of command line
	mov	#gmcrpb+g.mcrb,r1	; address of command
10$:
	cmpb	(r1)+,#' 		; BLANK?
	beq	20$			; YES
	sob	r0,10$			; try again
	br	nocmd			; just invoked as FEL
20$:
	dec	r0			; account for blank
	beq	nocmd			; trailing blank in command line?
	mov	#6,r2			; need six characters in task name
	mov	#tfil,r3		; output buffer
30$:
	movb	(r1)+,(r3)+		; copy next character
	dec	r2			; decrement counter
	beq	40$			; done
	sob	r0,30$			; do again
35$:
	movb	#' ,(r3)+		; fill with blanks
	sob	r2,35$			; do again
40$:
	clrb	(r2)			; EOS terminate
	br	cvt			; convert to rad50
nocmd:
	glun$s	#ttylun,#lunbuf		; get lun info
	mov	#octnum,r0		; string to format into
	movb	lunbuf+g.lunu,r1	; value to format
	mov	#1,r2			; desire leading zeroes
	call	$cbomg			; convert to octal magnitude
	movb	lunbuf+g.luna,devc	; overwrite devc with ch
	movb	unit,tnum		; copy first number of unit
	movb	unit+1,tnum+1		; copy second number of unit
;
;
;	the next few lines convert the ascii task name to rad50
;
cvt:
	mov	#tfil,r0		; address of ascii string
	mov	#1,r1			; period doesn't terminate
	call	$cat5b			; convert first word
	mov	r1,task			; save first word
	mov	#1,r1			; period doesn't terminate
	call	$cat5b			; convert second word
	mov	r1,task+2		; save second word
	sdat$s	#task,#obuf
	mov	$dsw,r1			; get status
	blt	errsnd			; send error
done:
	exit$s
errsnd:
	mov	#number,r0
	clr	r2
	call	$cbdsg
	clrb	(r0)
	mov	#ermsg1,r1
	mov	#buf,r0
	call	scopy
	mov	#tfil,r1
	call	scopy
	mov	#ermsg2,r1
	call	scopy
	mov	#number,r1
	call	scopy
	mov	#buf,r0
	jmp	errmsg
;
;
;	routine to calculate the length of the zero byte terminated
;	string pointed to by r1. length returned in r0, r1 is left
;	unmodified
;
;
length:
	clr	r0			; initialize count
	mov	r1,-(sp)		; save r1
1$:
	tstb	(r1)+			; see if 0 byte
	beq	2$			; yes, done
	inc	r0
	br	1$
2$:
	mov	(sp)+,r1		; restore r1
	return
;
;
;	routine to copy 0-byte terminated string pointed to by r1
;	to string pointed to by r0.  r1 is left pointing to character
;	after z byte, and r0 points to next available location
;
scopy:
	movb	(r1)+,(r0)+		; copy byte
	bne	scopy			; try again
	tstb	-(r0)			; backup one byte
	return
;
;
;	routine to display error message on terminal.  address of
;	zero byte terminated message is passed in r0
;
;
errmsg:
	mov	r0,r1			; going to scopy into buffer
	mov	#obuf,r0		; destination
	call	scopy			; copy string
	mov	#outbuf,r1		; calculate length
	call	length			; length in r0
	qiow$s	#io.wlb,#ttylun,#qioefn,,,,<r1,r0>
	br	done			; exit
	.end	start
