; ACE manipulations
;
; Copyright (c) 1995 Glenn C. Everhart
; All Rights Reserved
;
; Contains valuable trade secret information, not to be revealed
; by any means whatsoever without written permission by Glenn C.
; Everhart.
;
; One entry reads the ACE if it exists (or returns an empty ACE of
; the right prefix). Another will read the ACE and replace it with
; a new one (or just fill the new one in if there was no old one)
; so these can be used to fill in the ACE for the file...
;
; Note we set up our channel and FID 5,5 by hand here, in somewhat
; obscure fashion, so it is harder for outsiders to tell which file
; is being tagged or queried. The channel is left assigned as short
; a time as possible.
	.title	JTLicAce
; modify ACE by deleting old one and adding new one
; Copyright (c) 1995 Glenn C. Everhart
; All Rights Reserved
	$atrdef
	$acldef
	$acedef
	$fibdef
	$dscdef
	$iodef
	.psect	pdata,rd,wrt,quad
; FIB for filacc to use
fafib:	.long	0
fafid:	.long	0,0,0,0,0,0,0,0,0,0,0,0,0
fafds:	.long	0	;fib$l_status
fafd:	.long	.-fafib
	.address	fafib
faios:	.long	0,0
; set up data areas we need here
myfib:	.long	<fib$m_nolock+fib$m_norecord>	;don't alter dates
fibfid:	.blkw	3	;file id
fibdid:	.blkw	3	; dir id
fibctx:	.long	0
	.blkl	7	;other junk
fibacx:	.long	0	; acl context
fibast:	.long	0
fibsts:	.long	0,0
myfibl=.-myfib
mytgt:	.ascii	/LCGE/	;my flag indicator in ACE
; set up a fib
inbuf:	.long	0	;header
	.long	0	;flags go here
mynam:	.long	0	; should equal mytgt for my ACE
myprod:	.long	0	; product name to check
	.blkl	125	; rest of ACE
bufsiz=255
myfid:	.long	0,0	; file id
iosb:	.long	0,0	; iosb for synchronization
prdnam:	.ascii	/FCAE/	; "eacf" backwards product name literal
; myprod should equal it.
; generate a descriptor for my fib
mfdsc:	.long	myfibl
	.address myfib;
;
lpct:	.long	0
vchn:	.long	0
; itemlist to get file chars (so existence test has something to do)
chril3:	.word	4
	.word	atr$c_uchar
	.address	ufchr
	.long	0,0
ufchr:	.long	0		;file characs
; Itemlist to read our ACL
myitl3:	.word	255	;buff size
	.word	atr$c_readace	;read an ACE
	.address	inbuf	;to here
	.long	0,0	; terminate list
;
dskchn:	.long	0	;channel to disk
; delete acl entry item list
mydla:	.word	255	;size
	.word atr$c_delaclent	;delete entry
	.address	inbuf	; delete the one we find
	.long	0,0		; terminate the list
myadd:	.word	255
	.word	atr$c_addaclent	; add an entry
	.address	myace
	.long	0,0
myace:
	.word	0
myacf:	.word	0	;flags
	.blkl	128		; our ACL entry scratch storage
	.long	0	;safety
;;;;
;;;; stuff out of jtdmn
syslit:	.ascii	/SYS /
gcelit:	.ascii	/LCGE/	;special literal
rtnst:	.long	0	;return status
ainbf:	.blkb	4	;hdr here
	.blkl	1	;my "call dmn" flg or 0
gcetgt:	.long	0	;will be "LCGE" for my ACEs
	.blkl	224	;data
	.blkl	8	;safety
fid:	.long	0,0	;file id scratch storage
; descriptors for io$_access
mf3tp1:	.word	255
	.word	atr$c_addaclent
lmyfdsc:
; Itemlist to get old ace, delete it, add replacement one.
myil3:	.word	255	;length of itemlist item
	.word	atr$c_fndacetyp	;find ace
	.address	ainbf		;of our type
	.long	0,0,0,0	;terminate the list after finding
myin2:	.word	255
	.word	atr$c_delaclent	;delete an acl entry...
	.address	ainbf	;namely the old one
; locs to zero if the ace is empty now (0 in byte 16)
mf3b1:	.word	255
	.word	atr$c_addaclent	;add new ace
mf3b2:	.address	mdace	;modified ace
	.long	0,0	;null terminate the list
	.long	0
mdace:	.blkb	256
devlit: .ascii	/DEVI  /
makstr:	.ascii	/             /
	.blkb	12
	.align	long
dnhdr:	.word	13	;length of "sys$sysdevice"
	.byte	dsc$k_dtype_t	;fixed text
	.byte	1
	.address	makstr	;address of string data
	.align long
;;;;
p1=4
p2=8
p3=12
p4=16
; alpha wants code and data .psects separate
; call replent(ifid,ichan,newace,scssystemid)
; where ifid is FID we start with, chan is channel to disk we want,
; and newace is ACE to put in. If newace 1st byte = 0 just delete old
; ace.
	.psect pcode,rd,exe,quad
	.entry	replent,^m<r2,r3,r4,r5,r6,r7,r8,r9,r10,r11>
	movq	@p1(ap),myfid		; get file id
	movzwl	@p2(ap),dskchn		; get disk channel
; form sys$sysdevice & get a channel to it.
	movl	syslit,makstr
	movb	#^A/$/,makstr+3		;sys$
	movl	syslit,makstr+4		;sys$sys 
	movl	devlit,makstr+7		;sys$sysdevi
; (yes, I KNOW the above isn't aligned!)
	movl	#^a/CE  /,makstr+11	;sys$sysdevice
; form sys$sysdevice name in pieces to make it harder to follow
	movab	dnhdr,r11
	movab	dskchn,r10	;return channel here
	$assign_s	devnam=(r11),chan=(r10)
; hard wire to FID 5,5
	movw	#5,myfid
	movw	#5,myfid+2	;5,5,0
	movw	#0,myfid+4
	pushr	#^m<r0,r1,r2,r3,r4,r5>
	clrl	myace		; if p3 not there read ace as empty
	movab	myace,r2
	movl	p3(ap),r1	;get new ace
	beql	1$
	movc3	#256,(r1),(r2)		; get a copy of our ACE arg
1$:	movc5   #0,myfib,#0,#myfibl,myfib	;clear our FIB out
	popr	#^m<r0,r1,r2,r3,r4,r5>
	movl	myfid,fibfid
	movw	myfid+4,fibfid+4	; copy the FID into our FIB
3$:	movab	myitl3,r8		; get find-ace itemlist
	$qiow_s efn=#1,chan=dskchn,iosb=iosb,func=#io$_access,p1=mfdsc,p5=r8
; check status
	blbc	r0,900$
	blbc	iosb,953$
	blbc	fibast,953$
	brb	901$
900$:	brw	930$
901$:
	cmpl	mynam,mytgt		; got a target ACE entry?
	bneq	3$			; if not keep looking
	cmpl	myprod,prdnam		; right product flag?
	bneq	3$			; if not keep looking
	cmpl	myace+32,@16(ap)	; got right node?
	bneq	3$
;
; LOOKS like we got our ACE so delete it and add the other if that
; is appropriate.
	movab	mydla,r8		; get my delete access
	$qiow_s efn=#1,chan=dskchn,iosb=iosb,func=#io$_modify,p1=mfdsc,p5=r8
953$:	movl	mytgt,myace+8	;ensure we insert our marking
	movab	myadd,r8		; add the new item
	movl	prdnam,myprod		; insert product code too
	movl	#1,iosb
	tstb	myace		; is the new ACE empty?
	beql	4$		; if so scram
	$qiow_s efn=#1,chan=dskchn,iosb=iosb,func=#io$_modify,p1=mfdsc,p5=r8
4$:	movzwl	iosb,r0
	pushl	r0
	$dassgn_s	chan=dskchn
	popl	r0
	ret
930$:	movl	#2,r0
	pushl	r0
	$dassgn_s	chan=dskchn
	popl	r0
	ret
; getace - Entry to read an ACL for our ACE (if any) (used where
; the ACL is too long so we can't tell if our ACE is there or not.)
; Reads using channel in arg
; call findace(chan,ace,scssystemid)
; returns r0=1 if all ok, else r0 even.
; call to read a license ACE ands return it if found.
	.entry findace,^m<r2,r3,r4,r5,r6,r7,r8,r9,r10,r11>
	movl	#8,r0
	movl	@4(ap),vchn	;get the channel
;	beql	999$
	pushl	4(ap)	;copy args
	pushl	8(ap)
	pushl	12(ap)
	calls	#3,getace
;	jsb	getace		; find ace if any
;ainbf gets the ACE. Pass it back.
;	blbc	r0,999$
	pushr	#^m<r0,r1,r2,r3,r4,r5>
	movab	ainbf,r1	; ACE we found
	movl	8(ap),r2	; user's ace dest
	beql	99$
	movc3	#256,(r1),(r2)	; copy the data to user's site
99$:
	popr	#^m<r0,r1,r2,r3,r4,r5>
999$:
	ret
	.entry getace,^m<r2,r3,r4,r5,r6,r7,r8,r9,r10,r11>
	clrl	lpct
	clrl	fibacx		;init acl context
	clrl	fibast
        clrl    fibctx		;init fib context
        clrl    fibdid        ;clear the DID...
        clrw    fibdid+4       ;...fid all out
	movw	#5,fibfid
	clrw	fibfid+4
	movw	#5,fibfid+2	; set fid 5,5,0
	movl	syslit,makstr
	movb	#^A/$/,makstr+3		;sys$
	movl	syslit,makstr+4		;sys$sys 
	movl	devlit,makstr+7		;sys$sysdevi
; (yes, I KNOW the above isn't aligned!)
	movl	#^a/CE  /,makstr+11	;sys$sysdevice
; form sys$sysdevice name in pieces to make it harder to follow
	movab	dnhdr,r11
	movab	vchn,r10	;return channel here
	$assign_s	devnam=(r11),chan=(r10)
; hard wire to FID 5,5
	movw	#5,myfid
	movw	#5,myfid+2	;5,5,0
	movw	#0,myfid+4
	movl	mytgt,ainbf+8
	movl	prdnam,ainbf+12	;set our flags in there
	movl	prdnam,myprod		; insert product code too
; ace format
;ace:   .byte	40	;size
;	.byte ace$c_info
;	.byte	1
;	.byte	14
;	.long	1
;	.ascii	/LCGE/
;	.ascii	/FCAE/	;"EACF" backwards
;	.long	ff	;facility mask
;	.long	0,0	;exp date
;	.long	0	;cpu type
;	.long	0	;scsnode (scssystemid)
;	.long	0	;hw model
;
; Set up the "sought" ACE looking like one of ours EXCEPT no xor masks of
; junk. We'll add some numbers to things so time, systemid, scsnode
; and so on will be hidden from view, being transformed to something
; whose meaning is not so obvious.
	movb	#40,ainbf	;length
	movb	#ace$c_info,ainbf+1
	movb	#1,ainbf+2
	movb	#14,ainbf+3
	movl	#1,ainbf+4
	movl	mytgt,ainbf+8
	movl	prdnam,ainbf+12
	movl	#^x3ff,ainbf+16	;facility code. Default to all at first.
	clrl	ainbf+20	;time 
	clrl	ainbf+24	;time
	clrl	ainbf+28	;system cpu model
	clrl	ainbf+32	;scssystemid
	movl	@12(ap),ainbf+32	;use transformed scssystemid
	clrl	ainbf+36	;hw model
        pushr   #^m<r0,r1,r2,r3,r4,r5,r6,r7>
	movc5	#0,fibctx,#0,#48,fibctx	;clr fib generally past fid
100$:
        movab   myil3,r7        ;address of itemlist
	incl	lpct
	cmpl	lpct,#250	;max tries (got to terminate somewhere)
	bgeq	200$		;if over this then exit
        $qiow_s efn=#0,chan=vchn,iosb=iosb,func=#io$_access,p1=mfdsc,p5=r7
        movl    iosb,r6         ;get result for debug
	blbc	r6,200$		;exit on error/end
	blbc	fibast,200$	;exit on ast status err
	blbc	r0,200$		;on qio call or i/o status
	cmpl	gcelit,gcetgt	;our entry?
	bneq	100$		; if no, go look some more
	brw	300$		; if eql yes, though so use if ok
200$:
        popr    #^m<r0,r1,r2,r3,r4,r5,r6,r7>
; nothing valid, so set up a fake but empty ACE buffer for our caller
; in the right format.
	movb	#40,ainbf	;length
	movb	#ace$c_info,ainbf+1
	movb	#1,ainbf+2
	movb	#14,ainbf+3
	movl	#1,ainbf+4
	movl	mytgt,ainbf+8
	movl	prdnam,ainbf+12
	movl	#^x3ff,ainbf+16	;facility code. Default to all at first.
	clrl	ainbf+20	;time 
	clrl	ainbf+24	;time
	clrl	ainbf+28	;system cpu type
	clrl	ainbf+32	;scssystemid
	movl	@12(ap),ainbf+32	;use transformed scssystemid
	clrl	ainbf+36	;hw model
	$dassgn_s	chan=vchn
	movl	#2,r0		;flag error to caller
	ret
300$:
	brb	301$
302$:	brw	100$
301$:
	cmpl	prdnam,ainbf+12	; got the right product code?
	bneq	302$		; if not, keep looking.
	cmpl	ainbf+32,@12(ap)	;right node?
	bneq	302$
        popr    #^m<r0,r1,r2,r3,r4,r5,r6,r7>
	movl	#1,r0		;flag NO error to caller
	pushl	r0
	$dassgn_s	chan=vchn
	popl	r0
	ret
; call replent(ifid,ichan,newace)
; where ifid is FID we start with, chan is channel to disk we want,
; and newace is ACE to put in. If newace 1st byte = 0 just delete old
; ace.
; call findace(chan,ace)
; returns r0=1 if all ok, else r0 even.
; call to read a license ACE ands return it if found.
; add & subtract 8byte int entries
	.entry	qsub,^m<r2,r3,r4,r5,r6,r7,r8,r9,r10,r11>
	movl	4(ap),r2	;1st arg
	movl	(r2)+,r3
	movl	(r2)+,r4	;hi half
	movl	8(ap),r2
	movl	(r2)+,r5
	movl	(r2),r6		;hi half
	subl2	r3,r5	;subt lo half
	sbwc	r4,r6	;subt hi half
	movl	12(ap),r2
	movl	r5,(r2)+
	movl	r6,(r2)	;store result
	ret
	.entry	qadd,^m<r2,r3,r4,r5,r6,r7,r8,r9,r10,r11>
	movl	4(ap),r2	;1st arg
	movl	(r2)+,r3
	movl	(r2)+,r4	;hi half
	movl	8(ap),r2
	movl	(r2)+,r5
	movl	(r2),r6		;hi half
	addl2	r3,r5	;add lo half
	adwc	r4,r6	;add hi half
	movl	12(ap),r2
	movl	r5,(r2)+
	movl	r6,(r2)	;store result
	ret
	.end
