From: don@zl2tnm.gen.nz
Newsgroups: vmsnet.internals
Subject: RE: re: idle terminal...
Date: 10 Nov 92 23:49:46 +1300
Organization: The Wolery

Ehud Gavron 602-570-2546 <GAVRON@IT.SUNQUEST.COM> writes:
>       HOWEVER, all those require explicit code be run by the user
>       before termination can occur.  In the event that the user was
>       disconnected (terminal, non vtas) or killed (batch job termination)
>       then that process is STUCK until $cmkrnl intervention.

Not a problem.  Usually, your own process is deleted by a call to $EXIT
from supervisor mode (eg when your batch run ends or terminal line hangs
up) or exec mode (LOGINOUT.EXE), which in turn $DELPRCs us if it can't
find any reason not to.  Thus, it's a simple matter to drop an exec mode
exit handler to unset the bits.  Code is attached. 

Of course you still can't STOP/ID=0, but hey, them's the breaks.  8-)


Don Stokes, ZL2TNM (DS555)                       don@zl2tnm.gen.nz (home)
Network Manager, Computing Services Centre           don@vuw.ac.nz (work)
Victoria University of Wellington, New Zealand             +64-4-495-5052

	.title NODIE	Save us from $DELPRC/$FORCEX/$SUSPND attempts
;++
;
; This ghastly hack protects us from attack by people without $CMKRNL and
; a fair bit of internals knowlege.  Without reaching into the PCB and
; tweaking bits, we cannot be $DELPRCed (aka STOP/ID), $SUSPNDed (aka 
; SET PROCESS/SUSPEND) or $FORCEXed (various utilities).
;
; When we log out, or the terminal line goes away, we have an exit handler
; that turns off our countermeasures so that the ensuing $DELPRC will 
; succeed.
;
;	Don Stokes <don@zl2tnm.gen.nz>			10-Nov-1992
;		Guarantee this?  You _gotta_ be kidding!
;
;--

		.link "SYS$SYSTEM:SYS.STB"/selective_search
		.library "SYS$LIBRARY:LIB.MLB"
		$PCBDEF

trickybits	= PCB$M_SUSPEN!PCB$M_DELPEN!PCB$M_FORCPEN ; Body-armour bits
;
; Mainline code: call exit handler stuff in exec mode
;		 tweak STS field from kernel mode
;
	.entry nodie, ^M<>
		$CMEXEC_S routin=install_code	; Install code to let us die
		blbc R0, 99$			; cleanly
		$CMKRNL_S routin=stayalive	; Set survivalist flags
99$:		ret                             ; Done, exit.


;
; Code to install an exit handler in P1 space to undo our dirty work before
; $DELPRC is called.
; Exec mode, image context.
;
	.entry install_code, ^M<>
		movl #undo_code_len, R1		; R1=length of allocated block
		jsb EXE$ALOP1PROC		; Get P1 pool, pool addr in R2
		movl R2, R6			; R2 clobbered by MOVC3
		moval status_o(R2), statusaddr	; Fix up exit handler block
		moval (R2), exitaddr		; Fix up handler address
		movc3 #undo_code_len, undo_code, (R2) ; Copy code to P1
		$DCLEXH_S exitblock_o(R6)	; Declare exec mode handler
		blbc R0, 99$			; ok?
		movl #1, R0			; Success.
99$:		ret


;
; Set the bits to protect us from suspnd, forcex or delprc attempts.
; Kernel mode, image context.
;
	.entry stayalive, ^M<>
		bisl #trickybits, PCB$L_STS(R4)
		movl #1, R0
		ret


;
; Code to load into P1 starts here
; Entered in exec mode, exit handler context.
;
undo_code:	.word ^M<>		; Start P1 code
		$CMKRNL_S routin=1$		; Run dirty work in kernel mode
		ret				; Done

  1$:		.word ^m<>			; We're in kernel mode now
		bicl2 #trickybits, PCB$L_STS(R4); Clear some bits
		ret				; All done, return to exec mode

  exitblock:	.long 0				; Exit block:	Pointer
  exitaddr:	.blkl				;		Handler addr
		.long 1				;		Arg count
  statusaddr:	.blkl				; 		Addr of status
  status:	.blkl				; 		Status code

undo_code_len = .-undo_code		; End of P1 code


status_o 	= status-undo_code		; Offset into status address
						; for fixup
exitblock_o	= exitblock-undo_code		; Offset of handler block


		.end nodie