	! ----- GRANT_IDENTIFIER.FUN -----
	!
	! ----- FUNCTION TO GRANT AN IDENTIFIER -----
	! ----- (No error displayed if already granted) -----
	!
	! ---------- PASSED: ----------
	! -----		ENTERED_USERNAME = Username to grant ident to
	! -----		THE_IDENT = Identifier name to be granted
	! -----		SPECIFIC_NODE = (Optional) Specific node to grant the
	! -----				    identifier on (Default of only the
	! -----				    local node).  If the default local
	! -----				    node or the specified node is in the
	! -----				    DUPLICATE_NODES parameter, then the
	! -----				    identifier will be granted on each
	! -----				    of the duplicate nodes (assuming
	! -----				    that the identifier exists on the
	! -----				    other node(s))
	! -----		ERROR_IF_UNHELD = TRUE to emit an error if the
	! -----				  identifier is not already held on only
	! -----				  the specified (default) node
	! -----		THE_DB = Database to print if error if the identifier is
	! -----			 not held
	!
	! ---------- RETURNED: ----------
	! -----		If ERROR_IF_UNHELD was passed as TRUE, ERROR_IF_UNHELD
	! -----			will be set to FALSE upon return if an un-held
	! -----			identifier was found
	!
	! ----- Last Change 02/16/94 by Brian Lomasky -----
	!
	FUNCTION WORD GRANT_IDENTIFIER(STRING SPECIFIC_NODE,		&
		WORD ERROR_IF_UNHELD, STRING THE_DB)

		%INCLUDE "NUSER.INC"

		DECLARE STRING A_NODE		! NODE TO GRANT IDENTIFIER ON
		DECLARE WORD ERR_FLAG		! TRUE IF DONE READING RIGHTS
		DECLARE WORD FIRST_RECORD_WANTED! TRUE IF FIRST RECORD WANTED
		DECLARE WORD FOUND_IDENTIFIER	! CODE FOR MATCHING RECORD
		DECLARE WORD FOUND_NODE		! TRUE IF MATCHING NODE FOUND
		DECLARE WORD FOUND_USERNAME	! TRUE IF MATCHING USER FOUND
		DECLARE WORD FOUND_VALID_IDENT	! TRUE IF MATCHING IDENT FOUND
		DECLARE WORD FOUND_VALID_NODE	! TRUE IF ALL NODES FOUND
		DECLARE WORD I_O_CHNL		! RIGHTSLIST I/O CHNL TO ACCESS
		DECLARE WORD NODE_INDEX		! LIST OF NODES TO GRANT IDENT
		DECLARE LONG SAVE_ATTRIBUTES	! SAVED IDENTIFIER ATTRIBUTES

		EXTERNAL WORD FUNCTION CALC_DUPL_NODES(			&
			STRING)			! RETURN LIST OF DUPL NODES
		EXTERNAL WORD FUNCTION READ_RIGHTSLIST(WORD,		&
			WORD)			! READ RIGHTSLIST RECORD
		EXTERNAL WORD FUNCTION SEARCH_RIGHTSLIST(WORD, WORD,	&
			WORD)			! READ MATCHING RIGHTSLIST REC
		EXTERNAL WORD FUNCTION VALID_USER(STRING,		&
			WORD, WORD)		! SEE IF VALID USERNAME IDENT

		GRANT_IDENTIFIER = TRUE		! ASSUME ERROR STATUS
		IF DEBUG_MODE THEN
			PRINT "DEBUG>----- Call GRANT_IDENTIFIER"
			PRINT "DEBUG>ENTERED_USERNAME=" +		&
				TRM$(ENTERED_USERNAME) +		&
				", THE_IDENT=" + TRM$(THE_IDENT) +	&
				", SPECIFIC_NODE=" + SPECIFIC_NODE
		END IF

		! ----- CALCULATE LIST OF DUPLICATE NODES TO GRANT THE -----
		! ----- IDENTIFIER ON -----
		EXIT FUNCTION IF CALC_DUPL_NODES(SPECIFIC_NODE)

		! ----- FOR EACH DUPLICATE NODE TO BE ACCESSED: -----
		FOUND_USERNAME = FALSE		! ASSUME NO MATCHING USER FOUND
		FOUND_VALID_IDENT = FALSE	! ASSUME NO MATCHING IDENT FOUND
		FOUND_VALID_NODE = TRUE		! ASSUME ALL NODES WERE FOUND
		NODE_INDEX = 0%
		WHILE NODE_INDEX < NODES_IN_MEMORY
			NODE_INDEX = NODE_INDEX + 1%
			A_NODE = NODE_LISTS(NODE_INDEX)

			! ----- FOR EACH POSSIBLE NODE: -----
			I_O_CHNL = 0%
			FOUND_NODE = FALSE	! ASSUME NO MATCHING NODE FOUND
			! ----- FOR EACH OPEN FILE: -----
			WHILE I_O_CHNL < RIGHTSLIST_COUNTER
				I_O_CHNL = I_O_CHNL + 1%
				! ----- SKIP IF RIGHTSLIST IS UNAVAILABLE -----
				ITERATE IF TRM$(RIGHTSLIST_SPECS(I_O_CHNL)) = ""
				! ----- SKIP IF UNDESIRED NODE -----
				ITERATE IF A_NODE <>			&
					TRM$(RIGHTSLIST_NODES(I_O_CHNL))
				IF DEBUG_MODE THEN
					PRINT "DEBUG>Check node " +	&
						TRM$(RIGHTSLIST_NODES(I_O_CHNL))
				END IF
				! ----- MATCHING NODE WAS FOUND -----
				FOUND_NODE = TRUE
				! ----- VALIDATE USERNAME IDENTIFIER -----
				ITERATE IF VALID_USER(			&
					ENTERED_USERNAME, I_O_CHNL, FALSE)
				! ----- SET FLAG IF MATCHING USER FOUND -----
				! ----- ON JUST THE SPECIFIED NODE -----
				FOUND_USERNAME = TRUE IF SPECIFIC_NODE	&
					= "" OR SPECIFIC_NODE = A_NODE
				! ----- SEE IF IDENTIFIER TO BE GRANTED -----
				! ----- ALREADY EXISTS -----
				KGB_NAME = THE_IDENT
				ITERATE IF NOT SEARCH_RIGHTSLIST(	&
					I_O_CHNL, 2%, FALSE)
				! ----- SET FLAG IF MATCHING IDENT FOUND -----
				! ----- ON JUST THE SPECIFIED NODE -----
				FOUND_VALID_IDENT = TRUE IF		&
					SPECIFIC_NODE = "" OR		&
					SPECIFIC_NODE = A_NODE
				! ----- ERROR IF IN UIC FORMAT -----
				IF KGB_IDENTIFIER > 0% THEN
					! ----- PRINT ERROR IF IDENTIFIER -----
					! ----- IN WRONG FORMAT -----
					PRINT "Error - " +		&
						TRM$(THE_IDENT) +	&
						" on " + TRM$(A_NODE) +	&
						" is a UIC-format" +	&
						" identifier" + BEL
					EXIT FUNCTION
				END IF

				! ----- STORE IDENTIFIER VALUE TO SEARCH -----
				! ----- FOR -----
				SEARCH_IDENTIFIER = KGB_IDENTIFIER

				! ----- STORE IDENTIFIER ATTRIBUTES -----
				SAVE_ATTRIBUTES = KGB_ATTRIBUTES

				! ----- SEE IF THIS IDENTIFIER IS ALREADY -----
				! ----- HELD -----
				ERR_FLAG = FALSE
				FIRST_RECORD_WANTED = TRUE
				! ----- ASSUME NO HOLDER FOUND -----
				FOUND_IDENTIFIER = 0%
				WHILE NOT ERR_FLAG
					IF READ_RIGHTSLIST(		&
						FIRST_RECORD_WANTED, I_O_CHNL)
					THEN
						ERR_FLAG = TRUE
						ITERATE
					END IF
					FIRST_RECORD_WANTED = FALSE

					! ----- SEE IF DONE WITH THIS -----
					! ----- IDENTIFIER -----
					IF SEARCH_IDENTIFIER <> KGB_IDENTIFIER
					THEN
						IF DEBUG_MODE THEN
							PRINT "DEBUG>ID done"
						END IF
						ERR_FLAG = TRUE
						ITERATE
					END IF

					! ----- SKIP IF NON-HOLDER RECORD -----
					ITERATE IF REC_LEN > 16%

					! ----- SKIP IF HOLDER UIC DOES -----
					! ----- NOT MATCH -----
					ITERATE IF SEARCH_HOLDER(0%) <>	&
						KGB_HOLDER(0%)

					IF DEBUG_MODE THEN
						PRINT "DEBUG>Found identifier"
					END IF
					! ----- SET FLAG TO EXIT LOOP -----
					ERR_FLAG = TRUE
					! ----- SET FLAG IF HOLDER WAS -----
					! ----- FOUND -----
					FOUND_IDENTIFIER = 1%
				NEXT
				UNLOCK #I_O_CHNL
				! ----- SEE IF A HOLDER WAS FOUND -----
				IF FOUND_IDENTIFIER = 1% THEN
					! ----- SEE IF WE EXPECT THIS -----
					! ----- WARNING -----
					EXIT FUNCTION IF ERROR_IF_UNHELD&
						AND (SPECIFIC_NODE =	&
						"" OR SPECIFIC_NODE = A_NODE)
					!PRINT "Warning - " +		&
					!	TRM$(ENTERED_USERNAME)	&
					!	+ " on " + TRM$(A_NODE)	&
					!	+ " already holds " +	&
					!	TRM$(THE_IDENT)
					ITERATE
				END IF

				! ----- EXIT IF NON-GRANTED IDENTIFIER -----
				! ----- IS AN ERROR -----
				IF ERROR_IF_UNHELD AND (SPECIFIC_NODE	&
					= "" OR SPECIFIC_NODE = A_NODE)
				THEN
					PRINT "  Error - You can not" +	&
						" change the database"	&
						+ " access for " +	&
						TRM$(ENTERED_USERNAME)	&
						+ " since"
					PRINT "          this user " +	&
						"has no access to the "	&
						+ THE_DB +		&
						" database - Use the" +	&
						" GRANT operation"
					PRINT "          to give" +	&
						" this user access to"	&
						+ " this database"
					! ----- RETURN CODE FOR UN-HELD -----
					! ----- IDENTIFIER -----
					ERROR_IF_UNHELD = FALSE
					EXIT FUNCTION
				END IF

				! ----- STORE GRANTED IDENTIFIER -----
				KGB_IDENTIFIER = SEARCH_IDENTIFIER
				! ----- STORE APPROPRIATE ATTRIBUTES -----
				KGB_ATTRIBUTES = SAVE_ATTRIBUTES
				! ----- STORE UIC OF HOLDER -----
				KGB_HOLDER(0%) = SEARCH_HOLDER(0%)
				KGB_HOLDER(1%) = 0%
				PUT #I_O_CHNL, COUNT 16%
				PRINT "Granted " + TRM$(THE_IDENT) +	&
					" to " + TRM$(ENTERED_USERNAME)	&
					+ " on " + TRM$(A_NODE) + "..."
			NEXT
			IF NOT FOUND_NODE THEN	! IF NO MATCHING NODE WAS FOUND:
				PRINT "Warning - Node " + TRM$(A_NODE)	&
					+ " was not found" + BEL
				FOUND_VALID_NODE = FALSE
			END IF
		NEXT

		IF NOT FOUND_VALID_NODE THEN
			PRINT
			PRINT "        Valid nodes are:"
			I_O_CHNL = 0%
			! ----- FOR EACH OPEN FILE: -----
			WHILE I_O_CHNL < RIGHTSLIST_COUNTER
				I_O_CHNL = I_O_CHNL + 1%
				! ----- SKIP IF RIGHTSLIST IS UNAVAILABLE -----
				ITERATE IF TRM$(RIGHTSLIST_SPECS(I_O_CHNL)) = ""
				PRINT "          " +			&
					TRM$(RIGHTSLIST_NODES(I_O_CHNL))
			NEXT
		END IF
		IF NOT FOUND_VALID_IDENT THEN
			! ----- PRINT ERROR IF IDENTIFIER DOES NOT EXIST -----
			PRINT "Error - " + TRM$(THE_IDENT) +		&
				" is not an existing identifier" + BEL
		END IF

		EXIT FUNCTION IF NOT FOUND_USERNAME OR NOT		&
			FOUND_VALID_IDENT OR NOT FOUND_VALID_NODE

		GRANT_IDENTIFIER = FALSE	! RETURN SUCCESS STATUS
	END FUNCTION
