;	Change UIC, username and account to that of the input username.
;	If username not specified then SYSTEM is used.  Also, set default
;	to new username default directory and run login file.
;	Written for VMS 4.x

;	Oct, 1985	modified to get setprv	PRB
;	Aug, 1985	D.Jacobs


	.title	set_user

	.library	/sys$library:lib/
	$phddef					;process header definitions
	$prvdef					;privileges
	$uafdef					;uaf record offsets
	$jibdef					;job info offsets
	$pcbdef					;process control block offsets

	.psect	data,noexe,rd,wrt

uaf_fab:
	$fab	fac=get,-			;file access is 'get'
		fnm=<sys$system:sysuaf.dat>,-	;uaf file name
		org=idx,-			;file is indexed
		shr=<del,get,put,upd>		;file is shared

uaf_rab:
	$rab	fab=uaf_fab,-
		kbf=user_name,-			;key is user name
		krf=0,-				;primary key
		ksz=12,-			;user name size is 12
		rac=key,-			;access is by key
		rop=nlk,-			;don't lock record
		ubf=uaf_record,-		;put record here
		usz=uaf$s_uafdef		;size of record

uaf_record:
	.blkb	uaf$s_uafdef			;start of uaf record

privilege:
	.quad	0				;mask for privileges
nopriv:	.quad	^xffffffffffffffff		;mask for noall

noprv:	.ascid	/Insufficient privilege to run SETPRV/

finish:	.long	user_name_desc-finish_str
	.address	finish_str
finish_str:	.ascii	/You are now /
user_name:	.ascii	/            /		;user you want to be
user_name_size=.-user_name
user_name_desc:
	.long		user_name_size
	.address	user_name

invoke:	.ascid	/Invoking login file.../
at_login:
	.ascid	/@login/			;to run the login file
sys_login:
	.ascid	/SYS$LOGIN/			;pointer to login directory
job_table:
	.ascid	/LNM$JOB/			;job logical name table

length: .blkw	1				;length of user name

default_desc:
	.long		default_size
	.address	default
default:.ascii  /SYSTEM/			;default user name
default_size=.-default

defdev_desc:
	.long		defdev_size
	.address	def_dev
def_dev:.ascii  /SYS$SYSDISK:/			;default disk
defdev_size=.-def_dev

sys_disk_desc:
	.long		sys_disk_size
	.address	sys_disk
sys_disk:
	.ascii /SYS$DISK/			;system logical name
sys_disk_size=.-sys_disk

disk_desc:					;disk logical name and directory
	.long		disk_size
	.address	disk
disk:	.ascii /                              /
disk_size=.-disk

	.psect	code,exe,pic,rd,nowrt

;**************************************************************************
	.entry	main,^m<>

	pushaw	length
	pushl	#0
	pushab	user_name_desc
	calls	#3,g^lib$get_foreign		;get user name
	blbs	r0,test_input			;did it work? If not then exit.
	brw	end

test_input:
	tstw	length				;was anything entered?
	bneq	set_priv
	movc3	#default_size,-			;if not then use SYSTEM
		default,user_name

set_priv:
	insv	#1,#prv$v_sysprv,#1,privilege	;set the right bit for sysprv
	insv	#1,#prv$v_cmkrnl,#1,privilege	;set the right bit for cmkrnl
	$setprv_s-				;try to set the priv
		enbflg=#1,prvadr=privilege
	blbs	r0,check_priv			;did it work? If not then exit.
	brw	end

check_priv:
	cmpl	r0,#ss$_notallpriv		;see if priv was set
	bneq	open_uaf			;if ok then continue
	pushab	noprv				;otherwise
	calls	#1,g^lib$put_output		;error message

open_uaf:
	$open	fab=uaf_fab			;open uaf file, exit if fail
	blbs	r0,connect
	brw	end

connect:
	$connect-				;establish a record stream
		rab=uaf_rab
	blbs	r0,get_rec			;did it work? If not then exit.
	brw	end

get_rec:
	$get	rab=uaf_rab			;get record, exit if not found
	blbs	r0,close_file
	brw	end

close_file:
	$close	fab=uaf_fab			;close file
	blbs	r0,set_directory		;did it work? If not then exit.
	brw	end

set_directory:
	moval	uaf_record,r6		
	addl3	r6,#1,r7			;r6 is length, r7 is string
	tstb	uaf$t_defdev(r6)		;see if there is a disk device
	bneq	set_logical			;if not then use default device
	movb	#defdev_size,-			;set the length for default
		uaf$t_defdev(r6)
	movc3	#defdev_size,-			;put default name in uaf
		def_dev, uaf$t_defdev(r7)

set_logical:
	cvtbw	uaf$t_defdev(r6), r0		;temp spot for that length thing
	movw	r0,disk_desc			;set length in descriptor
	movc3	r0,-				;put device name in descriptor
		uaf$t_defdev(r7), disk
	movw	r3,r5				;address of spot after disk string

	pushab	disk_desc
	pushab	sys_disk_desc			;set the logical "sys$disk"
	calls	#2,g^lib$set_logical		;this is like "set def sys$disk"
	blbs	r0,set_default			;did it work? If not then exit.
	brw	end

set_default:
	cvtbw	uaf$t_defdir(r6), r0		;temp spot for that length thing
	addw2	r0,disk_desc			;length(dir) + length(disk)
	movc3	r0,-				;put directory name in descriptor
		uaf$t_defdir(r7), (r5)

	pushl	#0
	pushl	#0
	pushal	disk_desc
	calls	#3,g^sys$setddir		;set default to directory
	blbs	r0,set_login
	brw	end

set_login:
	pushab	job_table
	pushab	disk_desc
	pushab	sys_login
	calls	#3,g^lib$set_logical		;set logical "sys$login"
	blbs	r0,tweak_jib			;exit if fail
	brw	end

tweak_jib:
	$cmkrnl_s -
		routin=tweak,-
		arglst=#0			;set up JIB
	blbs	r0,clear_priv			;did it work? If not then exit.
	brw	end

clear_priv:
	$setprv_s-				;set proc/priv=noall
		enbflg=#0,prvadr=nopriv,-
		prmflg=#1
	blbs	r0,set_normal_priv		;did it work? If not then exit.
	brw	end

set_normal_priv:
	$setprv_s-				;now set priv to new users
		enbflg=#1,-			;privileges.
		prvadr=uaf$q_priv(r6),-
		prmflg=#1
	blbs	r0,set_name			;did it work? If not then exit.
	brw	end

set_name:
	$setprn_s-
		prcnam=user_name_desc		;set process name = user name
	cmpl	r0,#ss$_duplnam			;check for user logged in.
	beql	print_message
	blbs	r0,print_message		;did it work? If not then exit.
	brw	end

print_message:
	pushab	finish
	calls	#1,g^lib$put_output		;msg-"you are now:"
	blbc	r0,end
	pushab	invoke
	calls	#1,g^lib$put_output		;msg-"invoking login file"
	blbc	r0,end

run_login:
	pushab	at_login
	calls	#1,g^lib$do_command		;run login file

end:	$exit_s r0				;end set_user main

	.entry	tweak,^m<>			;set up job info block with new
						;UIC, username and account.
					;r6 = address of UAF
					;r10= address of JIB
					;r11= address of PCB

	movl	@#ctl$gl_phd,r5			;get address of PHD
	movl	@#sch$gl_curpcb,r11		;get current PCB address
	movl	uaf$l_uic(r6),pcb$l_uic(r11)	;change uic in PCB
	movl	pcb$l_jib(r11),r10		;get JIB address
	movq	nopriv,phd$q_authpriv(r5)	;get all privs

	movc3	#jib$s_username,-
		uaf$t_username(r6),-	 	;change username in JIB
		jib$t_username(r10)
	movc3	#jib$s_username,-
		uaf$t_username(r6),-		;change username in p1
		ctl$t_username

	movc3	#jib$s_account,-
		uaf$t_account(r6),-		;change account in JIB
		jib$t_account(r10)
	movc3	#jib$s_account,-
		uaf$t_account(r6),-		;change account in p1
		ctl$t_account

	movl	#ss$_normal,r0			;successfull completion

	ret

	.end	main
