From: murphy@npri6.npri.com (David P. Murphy)
Newsgroups: vmsnet.internals
Subject: Re: DETACHED process -> INTERACTIVE
Date: 17 Aug 92 14:32:47 GMT
Organization: NPRI, Alexandria VA


>How can I change the mode of a process from DETACHED
>to INTERACTIVE, that would be nice for some DECwindows
>related process startups (run/detached) which will run
>SYLOGIN and LOGIN (now we have to check for f$mode()
>= interactive or other) ? E.g. we run/detached DECW$SESSIONCOM
>to startup Session manager on terminals which are also
>used to connect to other (U*X) hosts and therefore should
>not be hardwired to a system via DECW$START_LOGIN.
>
>moravec@Ph1.Uni-Koeln.De (Andreas Moravec)

here follows the .MAR file i wrote to accomplish the same thing
for a VT100 interactive process.  there was a hack of a lot
of bookkeeping involved (process-permanent files, various fields
in the PRC and JIB structures, etc.) and i'm not promising this
will work first time through for you, but it might get you started.
ignore the parts you don't want, such as resetting the username.
good luck.

ok
dpm

	.title HackAutoLogin
	.ident /V01-000/

	.library	"sys$library:starlet.mlb"

	$ssdef
	$fabdef
	$namdef
	$rabdef
	$devdef
	$prvdef
	$climsgdef

	.library	"sys$library:lib.mlb"

	$prcdef
	$pcbdef
	$jibdef
	$ucbdef
	$ttyucbdef

; all of the PPD and IDF symbols, and the PRC symbols that lack a dollar sign,
; must be linked in from SYS$SYSTEM:DCLDEF.STB, since we do not have access
; to the special macro libraries that are proprietary to Digital.

$EQU	USE_MSG_FILE	1

.if defined USE_MSG_FILE
	.psect	$data pic, usr, con, rel, lcl, noshr, noexe, rd, wrt, novec

msg00:	.ascii	/made it this far . . ./
msg00a:	.ascii	/got to HERE . . ./
msg01:	.ascii	/successfully closed sys$input/
msg02:	.ascii	/successfully flushed sys$output/
msg03:	.ascii	/successfully closed sys$output/
msg04:	.ascii	/successfully opened new sys$input/
msg05:	.ascii	/successfully connected new sys$input/
msg06:	.ascii	/successfully back from HackSysIn()/
msg07:	.ascii	/successfully opened new sys$output/
msg08:	.ascii	/successfully connected new sys$output/
msg09:	.ascii	/successfully back from HackSysOut()/
msg10:	.ascii	/should return EXIT_SUCCESS from HackSysInSysOut()/

ptrfao:
	.ascid	/the PPD is !XL, the PRC is !XL, and the IDF is !XL./
ptrstr:
	.ascid	/                                                                  /
.endc

	.psect	$code pic, con, rel, lcl, shr, exe, rd, nowrt, long

	.entry	HackSysInSysOut, ^m<>

; this is just a shell routine so that i can shift into executive mode.
; everything is done in the "real" routine, and its return value is echoed.

	$cmexec_s	routin=RealHackSysInSysOut, arglst=(ap)
	ret


	.entry	RealHackSysInSysOut, ^m<r2,r3,r4,r5,r6,r7,r8,r9,r10,r11>

; the following steps need to be executed:
;
;    1.  close sys$input
;    2.  close sys$output
;    3.  open the terminal as sys$input
;    4.  move new values for sys$input into the PPD, the PRC, and the IDF
;    5.  open the terminal as sys$output
;    6.  move new values for sys$output into the PPD, the PRC, and the IDF
;    7.  set the "silent logout" flag in the PRC
;    8.  pass the new IFIs back to the caller

	devname     =  4
	devnamelen  =  8
	filename    = 12
	filenamelen = 16
	inpIFIptr   = 20
	outIFIptr   = 24
.if defined USE_MSG_FILE
	msgrab      = 28
.endc

	moval	krnerrhnd, (fp)			; kernel-mode error handler

; we need references to privileged structures in P1 space

.if defined USE_MSG_FILE
	movl	msgrab(ap), r0			; begin debug printf()
	moval	msg00, rab$l_rbf(r0)
	movw	#22, rab$w_rsz(r0)
	pushl	msgrab(ap)
	calls	#1, g^sys$put
	pushl	msgrab(ap)
	calls	#1, g^sys$flush			; end debug printf()
.endc

	movab	g^ctl$ag_clidata, r9		; pointer to the PPD
	movl	ppd$l_prc(r9), r10		; pointer to the PRC
	movl	prc_l_idflnk(r10), r11		; pointer to the IDF

.if defined USE_MSG_FILE
	$fao_s	ctrstr = ptrfao, outbuf = ptrstr, outlen = ptrstr, -
		p1 = r9, p2 = r10, p3 = r11
	movl	msgrab(ap), r0			; begin debug printf()
	movl	ptrstr+4, rab$l_rbf(r0)
	movw	#66, rab$w_rsz(r0)
	pushl	msgrab(ap)
	calls	#1, g^sys$put
	pushl	msgrab(ap)
	calls	#1, g^sys$flush			; end debug printf()
.endc

; now we need some local storage to play with

	movl	prc_l_inprab(r10), r7		; pointer to a RAB
	movl	rab$l_fab(r7), r6		; pointer to a FAB
	movl	fab$l_nam(r6), r8		; pointer to a NAM

; close the current sys$input file, which should be a mailbox.

	movw	ppd$w_inpifi(r9), fab$w_ifi(r6)		; use the IFI

.if defined USE_MSG_FILE
	movl	msgrab(ap), r0			; begin debug printf()
	moval	msg00a, rab$l_rbf(r0)
	movw	#17, rab$w_rsz(r0)
	pushl	msgrab(ap)
	calls	#1, g^sys$put
	pushl	msgrab(ap)
	calls	#1, g^sys$flush			; end debug printf()
.endc

	pushl	r6
	calls	#1, g^sys$close
	blbs	r0, CLOSE_OUT
	brw	OUCH

; close the current sys$output file, which should be the null device.

CLOSE_OUT:

.if defined USE_MSG_FILE
	movl	msgrab(ap), r0			; begin debug printf()
	moval	msg01, rab$l_rbf(r0)
	movw	#29, rab$w_rsz(r0)
	pushl	msgrab(ap)
	calls	#1, g^sys$put
	pushl	msgrab(ap)
	calls	#1, g^sys$flush			; end debug printf()
.endc

	movw	ppd$w_outifi(r9), fab$w_ifi(r6)		; use the IFI
	movw	ppd$w_outisi(r9), rab$w_isi(r7)		; use the ISI

	pushl	r7
	calls	#1, g^sys$flush
	blbs	r0, CLOSE
	brw	OUCH

CLOSE:

.if defined USE_MSG_FILE
	movl	msgrab(ap), r0			; begin debug printf()
	moval	msg02, rab$l_rbf(r0)
	movw	#31, rab$w_rsz(r0)
	pushl	msgrab(ap)
	calls	#1, g^sys$put
	pushl	msgrab(ap)
	calls	#1, g^sys$flush			; end debug printf()
.endc

	pushl	r6
	calls	#1, g^sys$close
	blbs	r0, OPEN_IN
	brw	OUCH


; open the terminal as the new sys$input file.

OPEN_IN:

.if defined USE_MSG_FILE
	movl	msgrab(ap), r0			; begin debug printf()
	moval	msg03, rab$l_rbf(r0)
	movw	#30, rab$w_rsz(r0)
	pushl	msgrab(ap)
	calls	#1, g^sys$put
	pushl	msgrab(ap)
	calls	#1, g^sys$flush			; end debug printf()
.endc

	movb	#fab$m_prn, fab$b_rat(r6)		; set characteristics
	movb	#fab$c_vfc, fab$b_rfm(r6)		; for SYS$INPUT in
	movb	#<fab$m_get ! fab$m_put>, fab$b_fac(r6)	; the FAB
	movl	#<fab$m_ppf ! fab$m_sqo ! fab$m_inp>, fab$l_fop(r6)

	movl	devname(ap), fab$l_fna(r6)	; point to the terminal name,
	movb	devnamelen(ap), fab$b_fns(r6)	; including the length

	pushl	r6
	calls	#1, g^sys$open
	blbs	r0, IN_CONNECT
	brw	OUCH

IN_CONNECT:

.if defined USE_MSG_FILE
	movl	msgrab(ap), r0			; begin debug printf()
	moval	msg04, rab$l_rbf(r0)
	movw	#33, rab$w_rsz(r0)
	pushl	msgrab(ap)
	calls	#1, g^sys$put
	pushl	msgrab(ap)
	calls	#1, g^sys$flush			; end debug printf()
.endc

	pushl	r7
	calls	#1, g^sys$connect
	blbs	r0, IN_OPEN_OK
	brw	OUCH

IN_OPEN_OK:

.if defined USE_MSG_FILE
	movl	msgrab(ap), r0			; begin debug printf()
	moval	msg05, rab$l_rbf(r0)
	movw	#36, rab$w_rsz(r0)
	pushl	msgrab(ap)
	calls	#1, g^sys$put
	pushl	msgrab(ap)
	calls	#1, g^sys$flush			; end debug printf()
.endc

; have to kick into kernel gear to move the SYS$INPUT values into the PPD.

	$cmkrnl_s	routin=HackSysIn, arglst=(ap)

.if defined USE_MSG_FILE
	movl	msgrab(ap), r0			; begin debug printf()
	moval	msg06, rab$l_rbf(r0)
	movw	#34, rab$w_rsz(r0)
	pushl	msgrab(ap)
	calls	#1, g^sys$put
	pushl	msgrab(ap)
	calls	#1, g^sys$flush			; end debug printf()
.endc

; open the terminal as the new sys$output file.

	clrw	fab$w_ifi(r6)				; clear the IFI
	clrw	rab$w_isi(r7)				; clear the ISI

	movb	#fab$m_prn, fab$b_rat(r6)		; set characteristics
	movb	#fab$c_vfc, fab$b_rfm(r6)		; for SYS$OUTPUT in
	movb	#<fab$m_get ! fab$m_put>, fab$b_fac(r6)	; the FAB
	movl	#<fab$m_ppf ! fab$m_sqo>, fab$l_fop(r6)

	movl	devname(ap), fab$l_fna(r6)	; point to the terminal name,
	movb	devnamelen(ap), fab$b_fns(r6)	; including the length

	pushl	r6
	calls	#1, g^sys$open
	blbs	r0, OUT_CONNECT
	brw	OUCH

OUT_CONNECT:

.if defined USE_MSG_FILE
	movl	msgrab(ap), r0			; begin debug printf()
	moval	msg07, rab$l_rbf(r0)
	movw	#34, rab$w_rsz(r0)
	pushl	msgrab(ap)
	calls	#1, g^sys$put
	pushl	msgrab(ap)
	calls	#1, g^sys$flush			; end debug printf()
.endc

	pushl	r7
	calls	#1, g^sys$connect
	blbs	r0, OUT_OPEN_OK
	brw	OUCH

OUT_OPEN_OK:

.if defined USE_MSG_FILE
	movl	msgrab(ap), r0			; begin debug printf()
	moval	msg08, rab$l_rbf(r0)
	movw	#37, rab$w_rsz(r0)
	pushl	msgrab(ap)
	calls	#1, g^sys$put
	pushl	msgrab(ap)
	calls	#1, g^sys$flush			; end debug printf()
.endc

; have to kick into kernel gear to move the SYS$OUTPUT values into the PPD.

	$cmkrnl_s	routin=HackSysOut

.if defined USE_MSG_FILE
	movl	msgrab(ap), r0			; begin debug printf()
	moval	msg09, rab$l_rbf(r0)
	movw	#35, rab$w_rsz(r0)
	pushl	msgrab(ap)
	calls	#1, g^sys$put
	pushl	msgrab(ap)
	calls	#1, g^sys$flush			; end debug printf()
.endc

; the caller needs the two IFIs returned to him so that he can correctly
; redefine the five concealed process logicals created by VMS (sys$input,
; sys$output, sys$command, sys$error, and tt).

	movw	ppd$w_inpifi(r9), @inpIFIptr(ap)
	movw	ppd$w_outifi(r9), @outIFIptr(ap)

; finished.  get the hell out of here.

.if defined USE_MSG_FILE
	movl	msgrab(ap), r0			; begin debug printf()
	moval	msg10, rab$l_rbf(r0)
	movw	#49, rab$w_rsz(r0)
	pushl	msgrab(ap)
	calls	#1, g^sys$put
	pushl	msgrab(ap)
	calls	#1, g^sys$flush			; end debug printf()
.endc

	movzbl	#SS$_NORMAL, r0

OUCH:
	ret


; move the new values for SYS$INPUT into the PPD.

	.entry	HackSysIn, ^m<r2,r3,r4,r5,r6,r7,r8,r9,r10,r11>

	movw	rab$w_isi(r7), ppd$w_inpisi(r9)
	movw	fab$w_ifi(r6), ppd$w_inpifi(r9)
	movw	fab$l_stv(r6), ppd$w_inpchan(r9)
	movl	fab$l_dev(r6), ppd$l_inpdev(r9)

	movc3	#ppd$s_inpfid, nam$w_fid(r8), ppd$w_inpfid(r9)
	movc3	#ppd$s_inpdid, nam$w_did(r8), ppd$w_inpdid(r9)
	movc5	#nam$c_dvi, nam$t_dvi(r8), #0, #ppd$s_inpdvi, ppd$t_inpdvi(r9)

		; need to construct an ASCIC string in the ppd's "filename"

	movb	filenamelen(ap), ppd$t_filename(r9)
	movc5	filenamelen(ap), @filename(ap), #0, #<ppd$s_filename-1>, -
			ppd$t_filename+1(r9)

	ret


; move the new values for SYS$OUTPUT into the PPD, the PRC, and the IDF.
; also move some values for SYS$INPUT that were not moved before,
; but those are moved from the PPD into something else.

	.entry	HackSysOut, ^m<r2,r3,r4,r5,r6,r7,r8,r9,r10,r11>

; move the new values for SYS$OUTPUT into the PPD.

	movw	rab$w_isi(r7), ppd$w_outisi(r9)
	movw	fab$w_ifi(r6), ppd$w_outifi(r9)
	movl	fab$l_dev(r6), ppd$l_outdev(r9)

		; set the "concealed i/o" bits in the "flags" word

	bisb	#<ppd$m_inpccl ! ppd$m_outccl>, ppd$w_flags(r9)

		; copy the "file id" and the "directory id"

	movc3	#ppd$s_outfid, nam$w_fid(r8), ppd$w_outfid(r9)
	movc3	#ppd$s_outdid, nam$w_did(r8), ppd$w_outdid(r9)

		; copy the "device id" which is an ascic string

	movc5	#nam$c_dvi, nam$t_dvi(r8), #0, #ppd$s_outdvi, ppd$t_outdvi(r9)

; also move some new values into the PRC

	movl	prc_l_inprab(r10), r4
	movw	ppd$w_inpchan(r9), prc_w_inpchan(r10)
	movw	ppd$w_outifi(r9), prc_w_outifi(r10)
	movw	ppd$w_outisi(r9), prc_w_outisi(r10)
	movl	ppd$l_outdev(r9), prc_l_outrabctx(r10)
	movl	ppd$l_outdev(r9), rab$l_ctx(r4)

	movb	#<prc_m_inpccl ! prc_m_outccl>, prc_b_outflags(r10)
	movl	#<prc_m_ctrlt  ! prc_m_ctrly>,  prc_l_outofband(r10)

	movc3	#ppd$s_outdvi, ppd$t_outdvi(r9), prc_t_outdvi(r10)

; keep moving values . . . this time into the IDF

		; change SYS$OUTPUT values in the IDF

	movw	ppd$w_outifi(r9), idf_w_outifi(r11)
	movw	ppd$w_outisi(r9), idf_w_outisi(r11)
	movl	ppd$l_outdev(r9), idf_l_outrabctx(r11)
	movb	#<idf_m_outccl ! idf_m_inpccl>, idf_b_outflags(r11)
	movc5	#ppd$s_outdvi, ppd$t_outdvi(r9), #0, #idf_s_outdvi, -
			idf_t_outdvi(r11)

	tstl	idf_l_lnk(r11)
	beql	CHANGE_TOP_IDF

	movl	r11, r4
	movl	idf_l_lnk(r11), r11
	tstl	idf_l_lnk(r11)
	bneq	TOO_DEEP

	movw	idf_w_outifi(r4),    idf_w_outifi(r11)
	movw	idf_w_outisi(r4),    idf_w_outisi(r11)
	movb	idf_b_outflags(r4),  idf_b_outflags(r11)
	movl	idf_l_outrabctx(r4), idf_l_outrabctx(r11)
	movc3	#idf_s_outdvi, idf_t_outdvi(r4), idf_t_outdvi(r11)

CHANGE_TOP_IDF:

		; change SYS$INPUT values in the IDF

	movw	ppd$w_inpifi(r9), idf_w_inpifi(r11)
	movl	ppd$l_outdev(r9), idf_l_inprabctx(r11)
	movc3	#ppd$s_inpfid, ppd$w_inpfid(r9), idf_w_inpfid(r11)
	movc3	#ppd$s_inpdid, ppd$w_inpdid(r9), idf_w_inpdid(r11)

	movc5	#ppd$s_inpdvi, ppd$t_inpdvi(r9), #0, #idf_s_inpdvi, -
			idf_t_inpdvi(r11)

; there is a bit in the "flags" word of the PRC that is called
; the "silent logout" flag.  this bit must be clear for loginout.exe to
; issue the message "  SMITH_J     logged out at 7-MAR-1988 17:53:42.39"
; which is the desired action.  don't bother testing, just clear it.
;
; note: this does not work.

	bicw2	#prc_m_autologo, prc_w_flags(r10)

	ret

TOO_DEEP:
	pushl	#0
	pushl	#CLI$_STKOVF
	calls	#2, g^lib$signal

	ret


; change values in the PCB and the JIB to resemble another process.  the only
; argument is the extended pid of the process that we want to look like, and
; it is passed by value.  we are going to change the username, the account,
; the terminal name, and the job type (from detached to local).  do *NOT* change
; the process name!  the others are pretty insignificant, at least compared to
; the process name, so hack hack hack.  but we will leave the latter to a call
; to sys$setprn() from a higher level routine.
;
; this would be a good point to also change values in the PHD,
; but there is nothing in there worth hacking at.

	.entry	HackPCBandJIB, ^m<>

	$cmkrnl_s	routin=RealHackPCBandJIB, arglst=(ap)
	ret

	.entry	RealHackPCBandJIB, ^m<r2,r3,r4,r5,r6,r7,r8,r9,r10,r11>

	hispid = 4

	moval	krnerrhnd, (fp)			; kernel-mode error handler

	movl	@#ctl$gl_pcb, r6		; get a pointer to our PCB

	movl	hispid(ap), r0			; using the pid passed to us,
	jsb	g^exe$epid_to_pcb		; get the other guy's PCB
	beql	BADPID				; if he really exists
	movl	r0, r7				; and save it

	movl	pcb$l_jib(r6), r8		; obtain the JobInfoBlock
	movl	pcb$l_jib(r7), r9		; pointers for both processes

		; copy the accountName, the userName and the terminal.

	movc3	#jib$s_account, jib$t_account(r9), jib$t_account(r8)
	movc3	#jib$s_account, jib$t_account(r8), g^ctl$t_account

	movc3	#jib$s_username, jib$t_username(r9), jib$t_username(r8)
	movc3	#jib$s_username, jib$t_username(r8), g^ctl$t_username

	movc3	#pcb$s_terminal, pcb$t_terminal(r7), pcb$t_terminal(r6)

		; the jobType should always be "LOCAL" for our purposes.
		; likewise, make sure that the "DETACHED" flag is clear.

	movb	#jib$c_local, jib$b_jobtype(r8)
	bicw2	#prc$m_detach, g^ctl$gl_creprc_flags

	movzbl	#SS$_NORMAL, r0
	ret

BADPID:
	movzwl	#SS$_NONEXPR, r0
	ret


; change values in the UCB for the specified terminal.

	.entry	HackUCB, ^m<>

	$cmkrnl_s	routin=RealHackUCB, arglst=(ap)
	ret

	.entry	RealHackUCB, ^m<r2,r3,r4,r5,r6,r7,r8,r9,r10,r11>

	devnam = 4

	moval	krnerrhnd, (fp)		; kernel-mode error handler

	movl	@#ctl$gl_pcb, r6	; get a pointer to our PCB
	movl	r6, r4			; the lock routine needs our PCB
	jsb	g^sch$iolockw		; lock I/O database for write access
	movl	devnam(ap), r1		; r1 = (struct STRDESC *) devnam
	jsb	g^ioc$searchdev		; search for the device name -
					; status returned in r0, pointer to
					; the proper UCB returned in r1
	blbs	r0, OKUCB		; whoops, couldn't find the device
	cmpl	r0, #SS$_DEVALLOC	; or maybe it's just already allocated
	beql	OKUCB			; if so, too bad for that guy
	movl	r0, r9			; a real error --- save the status
	jsb	g^sch$iounlock		; unlock the I/O database
	movl	r9, r0			; restore the error status
	ret

OKUCB:
	bbc	#dev$v_red, ucb$l_devchar2(r1), GOTUCB	; skip if not redirected
	movl	ucb$l_tt_logucb(r1), r1			; ready

GOTUCB:
	movl	pcb$l_pid(r6), ucb$l_pid(r1)	; set the owner of the device
	jsb	g^sch$iounlock			; unlock I/O database
	movzbl	#SS$_NORMAL, r0			; success
	ret


	.entry	HackPrivileges, ^m<>

	$cmkrnl_s	routin=RealHackPrivileges, arglst=(ap)
	ret

	.entry	RealHackPrivileges, ^m<r2,r3,r4,r5,r6,r7,r8,r9,r10,r11>

	privflag = 4
	privbuf  = 8

	cmpb	privflag(ap), #1
	bneq	SET_NEW_PRIVS
	movq	pcb$q_priv(r4), @privbuf(ap)
	ret

SET_NEW_PRIVS:
	cmpb	privflag(ap), #2
	bneq	RESTORE_PRIVS
	bisl2	#<prv$m_sysnam ! prv$m_group ! prv$m_share>, pcb$q_priv(r4)
	ret

RESTORE_PRIVS:
	movq	@privbuf(ap), pcb$q_priv(r4)
	bicl2	#prv$m_cmkrnl, pcb$q_priv(r4)
	ret

	.end
-- 
murphy@npri6.npri.com 602 Cameron St. Alexandria, VA 22314 (703) 683-9090

              When every one is dead the Great Game is finished.  Not before.
                              --- Hurree Babu, "Kim"