;********************************************************************
;*                                                                  *
;*  Program:  SETUSER                                               *
;*                                                                  *
;*  Purpose:                                                        *
;*                                                                  *
;*	program to change the USERNAME, UIC, PRIVILEGES & DEFAULT   *
;*	DIRECTORY of a process                                      *
;*                                                                  *
;*	note:	must be linked with system symbol table             *
;*                                                                  *
;*	i.e., LINK SETUSER,SYS$SYSTEM:SYS.STB/SELECTIVE             *
;*                                                                  *
;*  Programmer:  Richard Snyder                                     *
;*               The KeTech Corporation                             *
;*                                                                  *
;********************************************************************
	.title	setuser
	.library	/sys$library:lib.mlb/

	$prvdef
	$jibdef
	$jpidef
	$pcbdef
	$phddef
	$ssdef
	$opcdef
	$uaidef

	.psect	$data,noexe

get_start_list:	.word	8		;	item list to obtain information
		.word	jpi$_authpriv	;	about the user that is running
		.long	authpriv	;	the program
		.long	0
		.word	12
		.word	jpi$_username
		.long	start_name
		.long	0
		.long	0

authpriv:	.blkq			;	storage for initial user
start_name:	.blkb	12		;	characteristics

get_uaf_list:	.word	4		;	item list to obtain information
		.word	uai$_uic	;	about the target user
		.long	uic
		.long	0
		.word	8
		.word	uai$_priv
		.long	prv
		.long	0
		.word	16
		.word	uai$_defdev
		.long	ddev
		.long	0
		.word	64
		.word	uai$_defdir
		.long	ddir
		.long	0
		.long	0

ddir:		.blkb	64 		;	storage for information
ddev:		.blkb	16		;	about the target user
prv:		.blkb	8
uic:		.blkb	4

log:		.ascid		/SYS$DISK/
name:		.ascid		/            /
prmt:		.ascid		/Username: /
                                                          
;
;	security operator message logging program usage
;
opmsg:		.long	msg_length
		.long	opcom_msg

opcom_msg:	.long	opc$m_nm_security@8 + opc$_rq_rqst
		.long	0
		.ascii	/Setuser from **/
opc1:		.blkb	12
		.ascii	/** to **/
opc2:		.blkb	12
		.ascii	/**     Status:  /
opc3:		.blkb	7
msg_length	=	.-opcom_msg 

success:	.ascii	/Success/
failure:	.ascii	/Failure/

istatus:	.blkl	1
;
	.psect	$code,nowrt
	.entry	setuser,^m<>
;
; 	Read in the new username
;
	pushal	prmt
	pushal	name
	calls	#2,g^lib$get_foreign
	blbs	r0,99998$
	jmp	99999$
;
;	get information about user running program
;
99998$:
	$getjpi_s	itmlst=get_start_list
;
;	check if user has necessary privileges
;
	extzv		#prv$v_setprv,#1,authpriv,r0
	tstl		r0
	beql		10$
	insv		#1,#prv$v_sysprv,#1,authpriv
	insv		#1,#prv$v_cmkrnl,#1,authpriv
	brw		11$
;
;	user does not have setprv, check if he has cmkrnl & sysprv
;
10$:	extzv		#prv$v_sysprv,#1,authpriv,r0
	extzv		#prv$v_cmkrnl,#1,authpriv,r1
	addb2		r1,r0
	cmpb		r0,#2
	beql		11$
	movl		#ss$_nopriv,r0	
	jmp		99997$
;
;                 
;
11$:
	$setprv_s	enbflg=#1,-
			prvadr=authpriv
;
; 	Get information from sysuaf.dat
;
	$getuai_s	usrnam=name,-
			itmlst=get_uaf_list
	blbc	r0,99997$
;
; Change mode to KERNEL to gain access to the "no-touchies"
;
;                        
	$cmkrnl_s	kernel
;
;	set default directory
;       
	pushal	ddir+1				; construct descriptor
	movzbl	ddir,-(sp)
	movl	sp,r0
	pushl	#0
	pushl	#0   
	pushl	r0              
	calls	#3,sys$setddir                                        
	addl2	#8,sp				; delete descriptor
;
;	set default device
;                                                          
	pushal	ddev+1				; construct descriptor
	movzbl	ddev,-(sp)
	pushl	sp
	pushal	log
	calls	#2,g^lib$set_logical                                  
	addl2	#8,sp				; delete descriptor
	jmp	99999$
;
;	error trap
;
99997$:	pushl	r0
	movc3	#12,start_name,opc1
	movc3	#12,name+8,opc2
	movc3	#7,failure,opc3
	$sndopr_s	msgbuf=opmsg
	popl	r0
	ret
;
;	normal exit
;
99999$:	movc3	#12,start_name,opc1
	movc3	#12,name+8,opc2
	movc3	#7,success,opc3
	$sndopr_s	msgbuf=opmsg
	movl	#1,r0
	ret

;
; Modify the "no-touchies"
;
	.entry	kernel,^m<r2,r3,r4,r5,r6>

	moval	exc,(fp)			; set handler
;
	movl	g^sch$gl_curpcb,r6		; Get the current PCB
	movl	uic,pcb$l_uic(r6)		; set uic
;
	movq	prv,g^ctl$gq_procpriv		; set priv
	movq	prv,pcb$q_priv(r6)
	movl	pcb$l_phd(r6),r4
	movq	prv,phd$q_privmsk(r4)
;
	movl	pcb$l_jib(r6),r6		; Get the current JIB
	movc5	#12,@name+4,#32,#12,jib$t_username(r6)	; set usernames
	movc5	#12,@name+4,#32,#12,g^ctl$t_username
;
	movzwl	#ss$_normal,r0			; Successful
	ret					;   return
;
	.entry	exc,^m<>			; kernel mode excp handler
	$exit_s
	.end	setuser
