Path: utzoo!attcan!uunet!lll-winken!lll-tis!helios.ee.lbl.gov!pasteur!ucbvax!CITHEX.CALTECH.EDU!carl
From: carl@CITHEX.CALTECH.EDU (Carl J Lydick)
Newsgroups: comp.os.vms
Subject: Re: SUMMARY - How to find the next available uic
Message-ID: <880704153636.132e@CitHex.Caltech.Edu>
Date: 4 Jul 88 22:49:08 GMT
Sender: daemon@ucbvax.BERKELEY.EDU
Organization: The Internet
Lines: 51

> Whenever we want to add new users to sysuaf.dat, we try to find
> the next uic available for this new user. (For accounting reasons
> we do NOT use any uic that has been used before). The only way I
> could think of was to scan sysuaf.dat completely, using $IDTOASC
> in a wildcard operation, translate the usernames back to individual
> UIC's with $ASCTOID, then examining the group and member value, thus
> finding the highest member value of the specified group.
> But this takes about THIRTY times as much cpu time as does AUTHORIZE
> with a SHOW [XXXX,*]/BRIEF
>
> Does anybody know which calls authorize might be using ?

Since there's been one response to the net describing how to do this in C, and
one  in  MACRO,  I  just thought I'd show how it's done in FORTRAN, viz., much
more easily than in either of the other two languages.  I tried  doing  it  in
DCL,  which  would  have  been as simple as the FORTRAN code, but the DCL read
statement doesn't like the key value to have null bytes in  it  (It  sees  the
null  and  decides  that's  the  end  of the command line!  Is this a bug or a
feature?).  At any rate, here's the FORTRAN program:
********************************************************************************
	PROGRAM NEXT_FREE_UIC
	CHARACTER*6 MEMBER
	INTEGER GROUP, KEYNUM, UIC, NEXT_UIC
	OPEN(UNIT=1,FILE='SYS$SYSTEM:RIGHTSLIST.DAT',SHARED,READONLY,
	1	ACCESS='KEYED',STATUS='OLD',FORM='UNFORMATTED')
	TYPE 10
10	FORMAT(' GROUP: ',$)
	READ 20, GROUP
20	FORMAT(O6)
	KEYNUM = GROUP * '10000'X
	UIC = KEYNUM
	READ(1,KEYGE=KEYNUM,KEYID=0,ERR=900) NEXT_UIC
30	IF ((NEXT_UIC/'10000'X) .NE. GROUP) GOTO 900
	IF (IAND(NEXT_UIC,'FFFF'X) .EQ. 'FFFF'X) GOTO 900
	UIC = NEXT_UIC
	READ(1,ERR=900) NEXT_UIC
	GOTO 30
900	UIC = UIC + 1
	IF (IAND(UIC,'FFFF'X) .EQ. 'FFFF'X) GOTO 950
	TYPE 910, UIC/'10000'X, IAND(UIC,'FFFF'X)
910	FORMAT(1X,'THE NEXT UIC IN THE GROUP IS [',O6.6,',',O6.6,']')
	WRITE(MEMBER,920) IAND(UIC,'FFFF'X)
920	FORMAT(O6.6)
	CALL LIB$SET_SYMBOL('MEMBER', MEMBER)
	GOTO 999
950	TYPE 960, GROUP
960	FORMAT(' GROUP', O6.6, ' IS FULL')
999	END
********************************************************************************
If there were a KEYLT specifier, the loop could be eliminated, and it could
all be done with a single read from the file, by setting KEYNUM equal to
GROUP * '10000'X + 'FFFF'X.