From:	CRDGW2::CRDGW2::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX"  2-OCT-1989 19:55
To:	MRGATE::"ARISIA::EVERHART"
Subj:	Next UIC in a Group and DCL binary keys

Message-Id:  <8910022343.AA20326@crdgw1.ge.com>
Received: From NSFNET-RELAY.AC.UK by CRVAX.SRI.COM with TCP; Mon,  2 OCT 89 13:20:42 PDT
Received: from ncdlab.ulcc.ac.uk by NSFnet-Relay.AC.UK   via Janet with NIFTP
           id aa04264; 2 Oct 89 17:47 BST
Date:           Mon, 2 Oct 89  17:02 BST
From: Nick de Smith <"PSI%JANET.000000000040::NICK%ncdlab.ulcc.ac.uk"@NSFnet-Relay.AC.UK>
To: INFO-VAX <@NSFnet-Relay.AC.UK:INFO-VAX@crvax.sri.com>
Subject:        Next UIC in a Group and DCL binary keys

Hi,

Recently there have been some misleading messages on INFO-VAX regarding
what can and cannot be done with indexed keys in DCL. The final message that I
saw said that you "can't do a read on a binary key" (DOMILLER@UALR.BITNET).

The FACT is that you can use indexed keys without any trouble, by using
the syntactic translation qualifier, "&". RTFM.

In order to demonstrate this, I am including a DCL program to find the
next free UIC in a group. Actually, I'm including 2. There is a real problem in
determining the "next free member in a group" - Where do you look? Not all UICs
are associated with VMS users; some are only in the RIGHTSLIST. NEXT_UIC.COM
looks in SYSUAF for the next free member in a group; NEXT_UIC_RIGHTS.COM looks
in the RIGHTSLIST. Since the RIGHTSLIST file can be read-only (why, oh why?)
this latter file can be used by users without SYSPRV etc. Chose the file that
you want.

regards
nick	(long live DCL! long running in EXEC mode!)
	(my mail drop is in the signature below, NOT in the message header. This
	is a fact, not a mere hypothosis on my part)

Ps. Files follow at end of this message...

=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
| Nick de Smith                  |  Voice:   +44 892 511000         |
| Applied Telematics Group Ltd   |  PSImail: +234213300154::NICK    |
| Telematics House               |  Fax:     +44 892 38556 (G3)     |
| Tunbridge Wells, Kent          |  Telex:   95398 TELEMA G (UK)    |
| TN1 1DJ, England               | Internet: NICK@NCDLAB.ULCC.AC.UK |
! Janet:  NICK@UK.AC.ULCC.NCDLAB | (NICK%NCDLAB.ULCC.AC.UK@UKACRL)  |
|   "Though the wise man may make his home in a glass house, its    |
|    the happy man that drops his anchor in the bay of discontent"  |
=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=

/\/\/\/\/\/\/\/\/\/\/\ NEXT_UIC.COM /\/\/\/\/\/\/\/\/\

$	Setv = 'F$Verify("No")
$!
$! File:	NEXT_UIC.COM
$! Author:	Nick de Smith
$! Date:	27-Apr-89
$!
$! Description:
$! Command file to determine the next free member number in a UIC group.
$! Pass:
$!	P1	Name of the group to search. Either an identifier that is in the correct group, or
$!		a group number (eg. 100). Note that if you specify a number, you must specify it in
$!		the form that it is displayed by VMS (which is actually in octal), not as a binary integer.
$! Returns:
$!	NEXT_MEMBER	DCL global symbol that contains the number of the next free member in the searched
$!			group, or "-1" if the group did not exist.
$!	NEXT_UIC	DCL global symbol that contains the text of the next UIC to use, if NEXT_MEMBER was not -1.
$!
$! Example:
$!		$ @NEXT_UIC	100
$!		$ If NEXT_MEMBER .ne. -1
$!		$ Then	UAF = "$AUTHORIZE"
$!		$	UAF ADD /IDENTIFIER /VALUE=UIC:'NEXT_UIC' JIM_LAD
$!		$ EndIf
$!
$!		This example checks group 100 (octal) for the next free member number, and if one could be determined,
$!		adds it as the identifier "JIM_LAD".
$!
$	Set Symbol /Scope=(NoLocal)						! Insulate ourselves
$!
$	Name	= F$Parse( F$Environment( "PROCEDURE" ),,, "NAME" )		! Correct name for procedure
$	Info	= "%" + Name + "-I, "						! Information message
$	Warn	= "%" + Name + "-W, "						! Warning message
$	Fatal	= "%" + Name + "-F, "						! Fatal error message
$	TRUE	= (1.eq.1)
$	FALSE	= (1.eq.0)
$	Say	= "Write SYS$OUTPUT"						! Write on the log file (if any)
$!
$	UAF$W_MEM	= %x24
$	UAF$W_GRP	= %x26
$!
$	SYSUAF = F$Parse( "SYSUAF", "SYS$SYSTEM:.DAT;" )			! Construct UAF name
$	Set NoOn								! Make sure we close down
$	On CONTROL_Y Then Goto END
$!
$	P1 := 'P1								! Pick up name of GROUP to search
$	If P1 .eqs. "" Then P1 = "USER"						! Default to "USER"
$	Grp = F$Identifier( P1, "NAME_TO_NUMBER" ) / %x10000			! Try to treat it as a name...
$	If Grp .eq. 0 Then Grp = F$Integer( "%o''P1'" )				! ...if name not found, treat as an integer
$!
$	Group = "****"								! Pre-extend the group keyword
$	Group[  0, 16 ] = 0							! Start at member 0
$	Group[ 16, 16 ] = Grp							! ...in the selected group
$!
$	NEXT_MEMBER	== -1							! Assume no next member
$	NEXT_UIC	== ""							!   ''   ''  ''    ''
$	Expected_Member = 1							! Expect to start with member 1
$	Open /Read /Error=OPEN_ERROR SYSUAF_FILE &SYSUAF			! Open the UAF file
$	Read /Error=READ_ERROR /Index=1 /Match=GE /Key=&Group SYSUAF_FILE Record
$	If F$CvUI( UAF$W_GRP*8, 16, Record ) .ne. Grp Then Goto END		! If the group doesn't match, then exit
$ 10$:
$	Member = F$CvUI( UAF$W_MEM*8, 16, Record )				! Get current member number
$	If Expected_Member .lt. Member Then Goto 15$				! If we found a gap, use it
$	If Expected_Member .eq. Member Then Expected_Member = Member + 1	! ...else expected is next entry
$	Read /Error=15$ /Index=1 SYSUAF_FILE Record				! Read next record
$	If F$CvUI( UAF$W_GRP*8, 16, Record ) .ne. Grp Then Goto 15$		! If the group doesn't match, then exit
$	Goto 10$
$ 15$:
$	NEXT_MEMBER	== Expected_Member					! Return next member number...
$	NEXT_UIC	== F$Fao( "[!OL,!OL]", Grp, NEXT_MEMBER )		! ...and next UIC string
$	Goto END								! ...and exit
$!
$ READ_ERROR:
$	Say Fatal, F$Fao( "Error reading from ""!AS""!/!AS", SYSUAF, F$Message( $STATUS ) )
$	Goto END
$!
$ OPEN_ERROR:
$	Say Fatal, F$Fao( "Failed to open ""!AS""!/!AS", SYSUAF, F$Message( $STATUS ) )
$	Goto END
$!
$ END:	Close /Error=20$ SYSUAF_FILE
$ 20$:	Setv = F$Verify( Setv )



\/\/\/\/\/\ NEXT_UIC_RIGHTS.COM /\/\/\/\/\

$	Setv = 'F$Verify("No")
$!
$! File:	NEXT_UIC_RIGHTS.COM
$! Author:	Nick de Smith
$! Date:	27-Apr-89
$!
$! Description:
$! Command file to determine the next free member number in a UIC group.
$! Note that we search the system RIGHTSLIST file, not the UAF. This is because not all UICs in the rightslist
$! need be allocated to users.
$!
$! Pass:
$!	P1	Name of the group to search. Either an identifier that is in the correct group, or
$!		a group number (eg. 100). Note that if you specify a number, you must specify it in
$!		the form that it is displayed by VMS (which is actually in octal), not as a binary integer.
$! Returns:
$!	NEXT_MEMBER	DCL global symbol that contains the number of the next free member in the searched
$!			group, or "-1" if the group did not exist.
$!	NEXT_UIC	DCL global symbol that contains the text of the next UIC to use, if NEXT_MEMBER was not -1.
$!
$! Example:
$!		$ @NEXT_UIC_RIGHTS	100
$!		$ If NEXT_MEMBER .ne. -1
$!		$ Then	UAF = "$AUTHORIZE"
$!		$	UAF ADD /IDENTIFIER /VALUE=UIC:'NEXT_UIC' JIM_LAD
$!		$ EndIf
$!
$!		This example checks group 100 (octal) for the next free member number, and if one could be determined,
$!		adds it as the identifier "JIM_LAD".
$!
$	Set Symbol /Scope=(NoLocal)						! Insulate ourselves
$!
$	Name	= F$Parse( F$Environment( "PROCEDURE" ),,, "NAME" )		! Correct name for procedure
$	Info	= "%" + Name + "-I, "						! Information message
$	Warn	= "%" + Name + "-W, "						! Warning message
$	Fatal	= "%" + Name + "-F, "						! Fatal error message
$	TRUE	= (1.eq.1)
$	FALSE	= (1.eq.0)
$	Say	= "Write SYS$OUTPUT"						! Write on the log file (if any)
$!
$	KGB$L_IDENTIFIER	= %x0
$	KGB$T_NAME		= %x10
$	KGB$S_NAME		= %x20
$!
$	RIGHTS = F$Parse( "RIGHTSLIST", "SYS$SYSTEM:.DAT;" )			! Construct rightslist name
$	Set NoOn								! Make sure we close down
$	On CONTROL_Y Then Goto END
$!
$	P1 := 'P1								! Pick up name of GROUP to search
$	If P1 .eqs. "" Then P1 = "USER"						! Default to "USER"
$	Grp = F$Identifier( P1, "NAME_TO_NUMBER" ) / %x10000			! Try to treat it as a name...
$	If Grp .eq. 0 Then Grp = F$Integer( "%o''P1'" )				! ...if name not found, treat as an integer
$!
$	Group = "****"								! Pre-extend the group keyword
$	Group[  0, 16 ] = 0							! Start at member 0
$	Group[ 16, 16 ] = Grp							! ...in the selected group
$!
$	NEXT_MEMBER	== -1							! Assume no next member
$	NEXT_UIC	== ""							!   ''   ''  ''    ''
$	Expected_Member = 0							! Expect to start with member 0
$	Open /Read /Error=OPEN_ERROR RIGHTS_FILE &RIGHTS			! Open the rightslist file
$	Read /Error=READ_ERROR /Index=0 /Match=GE /Key=&Group RIGHTS_FILE Record ! read the first record
$	If F$CvUI( (KGB$L_IDENTIFIER+2)*8, 16, Record ) .ne. Grp Then Goto END	! If the group doesn't match, then exit
$ 10$:
$	Member = F$CvUI( KGB$L_IDENTIFIER*8, 16, Record )			! Get current member number
$	If Expected_Member .lt. Member Then Goto 15$				! If we found a gap, use it
$	If Expected_Member .eq. Member Then Expected_Member = Member + 1	! ...else expected is next entry
$	Read /Error=15$ /Index=1 RIGHTS_FILE Record				! Read next record
$	If F$CvUI( (KGB$L_IDENTIFIER+2)*8, 16, Record ) .ne. Grp Then Goto 15$	! If the group doesn't match, then exit
$	Goto 10$
$ 15$:
$	NEXT_MEMBER	== Expected_Member					! Return next member number...
$	NEXT_UIC	== F$Fao( "[!OL,!OL]", Grp, NEXT_MEMBER )		! ...and next UIC string
$	Goto END								! ...and exit
$!
$ READ_ERROR:
$	Say Fatal, F$Fao( "Error reading from ""!AS""!/!AS", RIGHTS, F$Message( $STATUS ) )
$	Goto END
$!
$ OPEN_ERROR:
$	Say Fatal, F$Fao( "Failed to open ""!AS""!/!AS", RIGHTS, F$Message( $STATUS ) )
$	Goto END
$!
$ END:	Close /Error=20$ RIGHTS_FILE
$ 20$:	Setv = F$Verify( Setv )


\/\/\/\/\/\/ end (so there!) /\/\/\/\/\/

