diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c
index 7c847ae354c01d828155d9c31e7e90d5252d0a6d..91241376184e6f5e8f6b06bd06ac7f94c98c943c 100644
--- a/src/backend/libpq/hba.c
+++ b/src/backend/libpq/hba.c
@@ -5,7 +5,7 @@
  *	  wherein you authenticate a user by seeing what IP address the system
  *	  says he comes from and possibly using ident).
  *
- *	$Id: hba.c,v 1.55 2001/02/10 02:31:26 tgl Exp $
+ *	$Id: hba.c,v 1.56 2001/07/30 14:50:21 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -22,6 +22,7 @@
 
 #include "libpq/libpq.h"
 #include "miscadmin.h"
+#include "nodes/pg_list.h"
 #include "storage/fd.h"
 
 
@@ -31,6 +32,13 @@
 #define IDENT_USERNAME_MAX 512
  /* Max size of username ident server can return */
 
+static List *hba_lines = NULL;	/* A list of lists: entry for every line,
+								 * list of tokens on each line.
+								 */
+
+static List *ident_lines = NULL;/* A list of lists: entry for every line,
+								 * list of tokens on each line.
+								 */
 
 /* Some standard C libraries, including GNU, have an isblank() function.
    Others, including Solaris, do not.  So we have our own.
@@ -38,31 +46,31 @@
 static bool
 isblank(const char c)
 {
-	return c == ' ' || c == 9 /* tab */ ;
+	return c == ' ' || c == 0x09;/* tab */
 }
 
 
+/*
+ *  Grab one token out of fp.  Tokens are strings of non-blank
+ *  characters bounded by blank characters, beginning of line, and end
+ *  of line.	Blank means space or tab.  Return the token as *buf.
+ *  Leave file positioned to character immediately after the token or
+ *  EOF, whichever comes first.  If no more tokens on line, return null
+ *  string as *buf and position file to beginning of next line or EOF,
+ *  whichever comes first.
+ */
 static void
 next_token(FILE *fp, char *buf, const int bufsz)
 {
-/*--------------------------------------------------------------------------
-  Grab one token out of fp.  Tokens are strings of non-blank
-  characters bounded by blank characters, beginning of line, and end
-  of line.	Blank means space or tab.  Return the token as *buf.
-  Leave file positioned to character immediately after the token or
-  EOF, whichever comes first.  If no more tokens on line, return null
-  string as *buf and position file to beginning of next line or EOF,
-  whichever comes first.
---------------------------------------------------------------------------*/
 	int			c;
 	char	   *eb = buf + (bufsz - 1);
 
 	/* Move over inital token-delimiting blanks */
-	while (isblank(c = getc(fp)));
+	while (isblank(c = getc(fp)))
+		;
 
 	if (c != '\n')
 	{
-
 		/*
 		 * build a token in buf of next characters up to EOF, eol, or
 		 * blank.
@@ -72,160 +80,214 @@ next_token(FILE *fp, char *buf, const int bufsz)
 			if (buf < eb)
 				*buf++ = c;
 			c = getc(fp);
-
-			/*
-			 * Put back the char right after the token (putting back EOF
-			 * is ok)
-			 */
 		}
+		/*
+		 * Put back the char right after the token (putting back EOF
+		 * is ok)
+		 */
 		ungetc(c, fp);
 	}
 	*buf = '\0';
 }
 
 
-
 static void
-read_through_eol(FILE *file)
+read_to_eol(FILE *file)
 {
 	int			c;
 
-	do
-		c = getc(file);
-	while (c != '\n' && c != EOF);
+	while ((c = getc(file)) != '\n' && c != EOF)
+		;
 }
 
 
-
+/*
+ *  Process the file line by line and create a list of list of tokens.
+ */
 static void
-read_hba_entry2(FILE *file, UserAuth *userauth_p, char *auth_arg,
-				bool *error_p)
+tokenize_file(FILE *file, List **lines)
 {
-/*--------------------------------------------------------------------------
-  Read from file FILE the rest of a host record, after the mask field,
-  and return the interpretation of it as *userauth_p, auth_arg, and
-  *error_p.
----------------------------------------------------------------------------*/
 	char		buf[MAX_TOKEN];
+	List		*next_line = NIL;
+	bool		comment_found = false;
 
-	/* Get authentication type token. */
-	next_token(file, buf, sizeof(buf));
-
-	if (strcmp(buf, "trust") == 0)
-		*userauth_p = uaTrust;
-	else if (strcmp(buf, "ident") == 0)
-		*userauth_p = uaIdent;
-	else if (strcmp(buf, "password") == 0)
-		*userauth_p = uaPassword;
-	else if (strcmp(buf, "krb4") == 0)
-		*userauth_p = uaKrb4;
-	else if (strcmp(buf, "krb5") == 0)
-		*userauth_p = uaKrb5;
-	else if (strcmp(buf, "reject") == 0)
-		*userauth_p = uaReject;
-	else if (strcmp(buf, "crypt") == 0)
-		*userauth_p = uaCrypt;
-	else
+	while (1)
 	{
-		*error_p = true;
+		next_token(file, buf, sizeof(buf));
+		if (feof(file))
+			break;
 
+		/* trim off comment, even if inside a token */
+		if (strstr(buf,"#") != NULL)
+		{
+			*strstr(buf,"#") = '\0';
+			comment_found = true;
+		}
+
+		/* add token to list */
 		if (buf[0] != '\0')
-			read_through_eol(file);
+		{
+			if (next_line == NIL)
+			{
+				/* make a new line List */
+				next_line = lcons(pstrdup(buf), NIL);
+				*lines = lappend(*lines, next_line);
+			}
+			else
+				/* append token to line */
+				next_line = lappend(next_line, pstrdup(buf));
+		}
+		else
+			/* force a new List line */
+			next_line = NIL;
+
+		if (comment_found)
+		{
+			/* Skip the rest of the line */
+			read_to_eol(file);
+			next_line = NIL;
+			comment_found = false;
+		}
+	}
+}
+
+
+/*
+ * Free memory used by lines/tokens
+ */
+static void free_lines(List **lines)
+{
+	if (*lines)
+	{
+		List *line, *token;
+
+		foreach(line, *lines)
+		{
+			foreach(token,lfirst(line))
+				pfree(lfirst(token));
+			freeList(lfirst(line));
+		}
+		freeList(*lines);
+		*lines = NULL;
+	}
+}
+
+
+/*
+ *  Read from file FILE the rest of a host record, after the mask field,
+ *  and return the interpretation of it as *userauth_p, auth_arg, and
+ *  *error_p.
+ */
+static void
+parse_hba_auth(List *line, UserAuth *userauth_p, char *auth_arg,
+				bool *error_p)
+{
+	char		*token = NULL;
+
+	if (!line)
+		*error_p = true;
+	else
+	{
+		/* Get authentication type token. */
+		token = lfirst(line);
+		if (strcmp(token, "trust") == 0)
+			*userauth_p = uaTrust;
+		else if (strcmp(token, "ident") == 0)
+			*userauth_p = uaIdent;
+		else if (strcmp(token, "password") == 0)
+			*userauth_p = uaPassword;
+		else if (strcmp(token, "krb4") == 0)
+			*userauth_p = uaKrb4;
+		else if (strcmp(token, "krb5") == 0)
+			*userauth_p = uaKrb5;
+		else if (strcmp(token, "reject") == 0)
+			*userauth_p = uaReject;
+		else if (strcmp(token, "crypt") == 0)
+			*userauth_p = uaCrypt;
+		else
+			*error_p = true;
 	}
 
 	if (!*error_p)
 	{
 		/* Get the authentication argument token, if any */
-		next_token(file, buf, sizeof(buf));
-		if (buf[0] == '\0')
+		line = lnext(line);
+		if (!line)
 			auth_arg[0] = '\0';
 		else
 		{
-			StrNCpy(auth_arg, buf, MAX_AUTH_ARG - 1);
-			next_token(file, buf, sizeof(buf));
-			if (buf[0] != '\0')
-			{
+			StrNCpy(auth_arg, token, MAX_AUTH_ARG - 1);
+			/* If there is more on the line, it is an error */
+			if (lnext(line))
 				*error_p = true;
-				read_through_eol(file);
-			}
 		}
 	}
 }
 
 
-
+/*
+ *  Process the non-comment lines in the config file.
+ *
+ *  See if it applies to a connection to a host with IP address "*raddr"
+ *  to a database named "*database".	If so, return *found_p true
+ *  and *userauth_p and *auth_arg as the values from the entry.
+ *  If not, leave *found_p as it was.  If the record has a syntax error,
+ *  return *error_p true, after issuing a message to stderr.	If no error,
+ *  leave *error_p as it was.
+ */
 static void
-process_hba_record(FILE *file, hbaPort *port, bool *matches_p, bool *error_p)
+parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p)
 {
-/*---------------------------------------------------------------------------
-  Process the non-comment record in the config file that is next on the file.
-  See if it applies to a connection to a host with IP address "*raddr"
-  to a database named "*database".	If so, return *matches_p true
-  and *userauth_p and *auth_arg as the values from the entry.
-  If not, leave *matches_p as it was.  If the record has a syntax error,
-  return *error_p true, after issuing a message to stderr.	If no error,
-  leave *error_p as it was.
----------------------------------------------------------------------------*/
-	char		db[MAX_TOKEN],
-				buf[MAX_TOKEN];
-
-	/* Read the record type field. */
-
-	next_token(file, buf, sizeof(buf));
-
-	if (buf[0] == '\0')
-		return;
+	char		*db;
+	char		*token;
 
+	Assert(line != NIL);
+	token = lfirst(line);
 	/* Check the record type. */
-
-	if (strcmp(buf, "local") == 0)
+	if (strcmp(token, "local") == 0)
 	{
 		/* Get the database. */
-
-		next_token(file, db, sizeof(db));
-
-		if (db[0] == '\0')
-			goto syntax;
-
+		line = lnext(line);
+		if (!line)
+			goto hba_syntax;
+		db = lfirst(line);
+
+		line = lnext(line);
+		if (!line)
+			goto hba_syntax;
 		/* Read the rest of the line. */
-
-		read_hba_entry2(file, &port->auth_method, port->auth_arg, error_p);
+		parse_hba_auth(line, &port->auth_method, port->auth_arg, error_p);
+		if (*error_p)
+			goto hba_syntax;
 
 		/*
 		 * For now, disallow methods that need AF_INET sockets to work.
 		 */
-
 		if (!*error_p &&
 			(port->auth_method == uaIdent ||
 			 port->auth_method == uaKrb4 ||
 			 port->auth_method == uaKrb5))
-			*error_p = true;
-
-		if (*error_p)
-			goto syntax;
+			goto hba_syntax;
 
 		/*
 		 * If this record isn't for our database, or this is the wrong
 		 * sort of connection, ignore it.
 		 */
-
 		if ((strcmp(db, port->database) != 0 && strcmp(db, "all") != 0 &&
 			 (strcmp(db, "sameuser") != 0 || strcmp(port->database, port->user) != 0)) ||
 			port->raddr.sa.sa_family != AF_UNIX)
 			return;
 	}
-	else if (strcmp(buf, "host") == 0 || strcmp(buf, "hostssl") == 0)
+	else if (strcmp(token, "host") == 0 || strcmp(token, "hostssl") == 0)
 	{
-		struct in_addr file_ip_addr,
-					mask;
-		bool		discard = 0;/* Discard this entry */
+		struct in_addr file_ip_addr, mask;
 
 #ifdef USE_SSL
 		/* If SSL, then check that we are on SSL */
-		if (strcmp(buf, "hostssl") == 0)
+		if (strcmp(token, "hostssl") == 0)
 		{
 			if (!port->ssl)
-				discard = 1;
+				return;
 
 			/* Placeholder to require specific SSL level, perhaps? */
 			/* Or a client certificate */
@@ -234,67 +296,50 @@ process_hba_record(FILE *file, hbaPort *port, bool *matches_p, bool *error_p)
 		}
 #else
 		/* If not SSL, we don't support this */
-		if (strcmp(buf, "hostssl") == 0)
-			goto syntax;
+		if (strcmp(token, "hostssl") == 0)
+			goto hba_syntax;
 #endif
 
 		/* Get the database. */
-
-		next_token(file, db, sizeof(db));
-
-		if (db[0] == '\0')
-			goto syntax;
+		line = lnext(line);
+		if (!line)
+			goto hba_syntax;
+		db = lfirst(line);
 
 		/* Read the IP address field. */
-
-		next_token(file, buf, sizeof(buf));
-
-		if (buf[0] == '\0')
-			goto syntax;
+		line = lnext(line);
+		if (!line)
+			goto hba_syntax;
+		token = lfirst(line);
 
 		/* Remember the IP address field and go get mask field. */
-
-		if (!inet_aton(buf, &file_ip_addr))
-		{
-			read_through_eol(file);
-			goto syntax;
-		}
+		if (!inet_aton(token, &file_ip_addr))
+			goto hba_syntax;
 
 		/* Read the mask field. */
+		line = lnext(line);
+		if (!line)
+			goto hba_syntax;
+		token = lfirst(line);
 
-		next_token(file, buf, sizeof(buf));
-
-		if (buf[0] == '\0')
-			goto syntax;
-
-		if (!inet_aton(buf, &mask))
-		{
-			read_through_eol(file);
-			goto syntax;
-		}
+		if (!inet_aton(token, &mask))
+			goto hba_syntax;
 
 		/*
 		 * This is the record we're looking for.  Read the rest of the
 		 * info from it.
 		 */
-
-		read_hba_entry2(file, &port->auth_method, port->auth_arg, error_p);
-
+		line = lnext(line);
+		if (!line)
+			goto hba_syntax;
+		parse_hba_auth(line, &port->auth_method, port->auth_arg, error_p);
 		if (*error_p)
-			goto syntax;
-
-		/*
-		 * If told to discard earlier. Moved down here so we don't get
-		 * "out of sync" with the file.
-		 */
-		if (discard)
-			return;
+			goto hba_syntax;
 
 		/*
 		 * If this record isn't for our database, or this is the wrong
 		 * sort of connection, ignore it.
 		 */
-
 		if ((strcmp(db, port->database) != 0 && strcmp(db, "all") != 0 &&
 			 (strcmp(db, "sameuser") != 0 || strcmp(port->database, port->user) != 0)) ||
 			port->raddr.sa.sa_family != AF_INET ||
@@ -302,98 +347,75 @@ process_hba_record(FILE *file, hbaPort *port, bool *matches_p, bool *error_p)
 			return;
 	}
 	else
-	{
-		read_through_eol(file);
-		goto syntax;
-	}
-
-	*matches_p = true;
+		goto hba_syntax;
 
+	/* Success */
+	*found_p = true;
 	return;
 
-syntax:
+hba_syntax:
 	snprintf(PQerrormsg, PQERRORMSG_LENGTH,
-			 "process_hba_record: invalid syntax in pg_hba.conf file\n");
+			 "parse_hba: invalid syntax in pg_hba.conf file\n");
 	fputs(PQerrormsg, stderr);
 	pqdebug("%s", PQerrormsg);
 
 	*error_p = true;
+	return;
 }
 
 
-
-static void
-process_open_config_file(FILE *file, hbaPort *port, bool *hba_ok_p)
+/*
+ *  Process the hba file line by line.
+ */
+static bool
+check_hba(hbaPort *port)
 {
-/*---------------------------------------------------------------------------
-  This function does the same thing as find_hba_entry, only with
-  the config file already open on stream descriptor "file".
-----------------------------------------------------------------------------*/
-	bool		found_entry = false;	/* found an applicable entry? */
-	bool		error = false;	/* found an erroneous entry? */
-	bool		eof = false;	/* end of hba file */
-
-	while (!eof && !found_entry && !error)
-	{
-		/* Process a line from the config file */
-		int			c = getc(file);
+	List 	*line;
+	bool	found_entry = false;
+	bool	error = false;
 
-		if (c == EOF)
-			eof = true;
-		else
-		{
-			ungetc(c, file);
-			if (c == '#')
-				read_through_eol(file);
-			else
-				process_hba_record(file, port, &found_entry, &error);
-		}
+	foreach (line, hba_lines)
+	{
+		parse_hba(lfirst(line), port, &found_entry, &error);
+		if (found_entry || error)
+			break;
 	}
 
 	if (!error)
 	{
 		/* If no matching entry was found, synthesize 'reject' entry. */
-
 		if (!found_entry)
 			port->auth_method = uaReject;
-
-		*hba_ok_p = true;
+		return true;
 	}
+	else
+		return false;
 }
 
 
-
-static void
-find_hba_entry(hbaPort *port, bool *hba_ok_p)
-{
 /*
- * Read the config file and find an entry that allows connection from
- * host "raddr", user "user", to database "database".  If found,
- * return *hba_ok_p = true and *userauth_p and *auth_arg representing
- * the contents of that entry.	If there is no matching entry, we
- * set *hba_ok_p = true, *userauth_p = uaReject.
- *
- * If the config file is unreadable or contains invalid syntax, we
- * issue a diagnostic message to stderr (ie, the postmaster log file)
- * and return without changing *hba_ok_p.
- *
+ * Read the config file and create a List of Lists of tokens in the file.
  * If we find a file by the old name of the config file (pg_hba), we issue
  * an error message because it probably needs to be converted.	He didn't
  * follow directions and just installed his old hba file in the new database
  * system.
  */
+static void
+load_hba()
+{
 
 	int			fd,
 				bufsize;
 	FILE	   *file;			/* The config file we have to read */
 	char	   *old_conf_file;
 
-	/* The name of old config file that better not exist. */
-
-	/* Fail if config file by old name exists. */
-
-
-	/* put together the full pathname to the old config file */
+	if (hba_lines)
+		free_lines(&hba_lines);
+	/*
+	 *	The name of old config file that better not exist.
+	 *	Fail if config file by old name exists.
+	 *	Put together the full pathname to the old config file.
+	 */
 	bufsize = (strlen(DataDir) + strlen(OLD_CONF_FILE) + 2) * sizeof(char);
 	old_conf_file = (char *) palloc(bufsize);
 	snprintf(old_conf_file, bufsize, "%s/%s", DataDir, OLD_CONF_FILE);
@@ -403,11 +425,10 @@ find_hba_entry(hbaPort *port, bool *hba_ok_p)
 		/* Old config file exists.	Tell this guy he needs to upgrade. */
 		close(fd);
 		snprintf(PQerrormsg, PQERRORMSG_LENGTH,
-		  "A file exists by the name used for host-based authentication "
-		   "in prior releases of Postgres (%s).  The name and format of "
-		   "the configuration file have changed, so this file should be "
-				 "converted.\n",
-				 old_conf_file);
+			"A file exists by the name used for host-based authentication "
+			"in prior releases of Postgres (%s).  The name and format of "
+			"the configuration file have changed, so this file should be "
+			"converted.\n", old_conf_file);
 		fputs(PQerrormsg, stderr);
 		pqdebug("%s", PQerrormsg);
 	}
@@ -425,16 +446,15 @@ find_hba_entry(hbaPort *port, bool *hba_ok_p)
 		if (file == NULL)
 		{
 			/* The open of the config file failed.	*/
-
 			snprintf(PQerrormsg, PQERRORMSG_LENGTH,
-					 "find_hba_entry: Unable to open authentication config file \"%s\": %s\n",
+					 "load_hba: Unable to open authentication config file \"%s\": %s\n",
 					 conf_file, strerror(errno));
 			fputs(PQerrormsg, stderr);
 			pqdebug("%s", PQerrormsg);
 		}
 		else
 		{
-			process_open_config_file(file, port, hba_ok_p);
+			tokenize_file(file, &hba_lines);
 			FreeFile(file);
 		}
 		pfree(conf_file);
@@ -443,35 +463,175 @@ find_hba_entry(hbaPort *port, bool *hba_ok_p)
 }
 
 
+/*
+ *  Take the line and compare it to the needed map, pg_user and ident_user.
+ */
 static void
-interpret_ident_response(char *ident_response,
-						 bool *error_p, char *ident_username)
+parse_ident_usermap(List *line, const char *usermap_name, const char *pg_user,
+				 const char *ident_user, bool *found_p, bool *error_p)
+{
+	char		*token;
+	char		*file_map;
+	char		*file_pguser;
+	char		*file_ident_user;
+
+	*error_p = false;
+	*found_p = false;
+
+	/* A token read from the file */
+	Assert(line != NIL);
+	token = lfirst(line);
+	file_map = token;
+
+	line = lnext(line);
+	if (!line)
+		goto ident_syntax;
+	token = lfirst(line);
+	if (token[0] != '\0')
+	{
+		file_ident_user = token;
+		line = lnext(line);
+		if (!line)
+			goto ident_syntax;
+		token = lfirst(line);
+		if (token[0] != '\0')
+		{
+			file_pguser = token;
+			if (strcmp(file_map, usermap_name) == 0 &&
+				strcmp(file_pguser, pg_user) == 0 &&
+				strcmp(file_ident_user, ident_user) == 0)
+				*found_p = true;
+		}
+	}
+
+	return;
+
+ident_syntax:
+	snprintf(PQerrormsg, PQERRORMSG_LENGTH,
+			 "parse_ident_usermap: invalid syntax in pg_ident.conf file\n");
+	fputs(PQerrormsg, stderr);
+	pqdebug("%s", PQerrormsg);
+	*error_p = true;
+	return;
+}
+
+
+/*
+ *  Process the ident usermap file line by line.
+ */
+static bool
+check_ident_usermap(const char *usermap_name,
+					const char *pg_user,
+					const char *ident_user)
+{
+	List 	*line;
+	bool	found_entry = false, error = false;
+
+	if (usermap_name[0] == '\0')
+	{
+		snprintf(PQerrormsg, PQERRORMSG_LENGTH,
+			"load_ident_usermap: hba configuration file does not "
+			"have the usermap field filled in in the entry that pertains "
+			"to this connection.  That field is essential for Ident-based "
+			"authentication.\n");
+		fputs(PQerrormsg, stderr);
+		pqdebug("%s", PQerrormsg);
+		found_entry = false;
+	}
+	else if (strcmp(usermap_name, "sameuser") == 0)
+	{
+		if (strcmp(pg_user, ident_user) == 0)
+			found_entry = true;
+		else
+			found_entry = false;
+	}
+	else
+	{
+		foreach(line, ident_lines)
+		{
+			parse_ident_usermap(lfirst(line), usermap_name, pg_user,
+								ident_user, &found_entry, &error);
+			if (found_entry || error)
+				break;
+		}
+	}
+	return found_entry;
+}
+
+
+/*
+ *  See if the user with ident username "ident_user" is allowed to act
+ *  as Postgres user "pguser" according to usermap "usermap_name".   Look
+ *  it up in the usermap file.
+ *
+ *  Special case: For usermap "sameuser", don't look in the usermap
+ *  file.  That's an implied map where "pguser" must be identical to
+ *  "ident_user" in order to be authorized.
+ *
+ *  Iff authorized, return *checks_out_p == true.
+ */
+static void
+load_ident()
 {
-/*----------------------------------------------------------------------------
-  Parse the string "*ident_response" as a response from a query to an Ident
-  server.  If it's a normal response indicating a username, return
-  *error_p == false and the username as *ident_username.  If it's anything
-  else, return *error_p == true and *ident_username undefined.
-----------------------------------------------------------------------------*/
-	char	   *cursor;			/* Cursor into *ident_response */
+	FILE	   *file;		/* The map file we have to read */
+	char	   *map_file;	/* The name of the map file we have to
+							 * read */
+	int			bufsize;
 
-	cursor = &ident_response[0];
+	if (ident_lines)
+		free_lines(&ident_lines);
+
+	/* put together the full pathname to the map file */
+	bufsize = (strlen(DataDir) + strlen(USERMAP_FILE) + 2) * sizeof(char);
+	map_file = (char *) palloc(bufsize);
+	snprintf(map_file, bufsize, "%s/%s", DataDir, USERMAP_FILE);
+
+	file = AllocateFile(map_file, PG_BINARY_R);
+	if (file == NULL)
+	{
+		/* The open of the map file failed.  */
+		snprintf(PQerrormsg, PQERRORMSG_LENGTH,
+			"load_ident_usermap: Unable to open usermap file \"%s\": %s\n",
+			map_file, strerror(errno));
+		fputs(PQerrormsg, stderr);
+		pqdebug("%s", PQerrormsg);
+	}
+	else
+	{
+		tokenize_file(file, &ident_lines);
+		FreeFile(file);
+	}
+	pfree(map_file);
+}
+
+
+/*
+ *  Parse the string "*ident_response" as a response from a query to an Ident
+ *  server.  If it's a normal response indicating a username, return
+ *  *error_p == false and the username as *ident_user.  If it's anything
+ *  else, return *error_p == true and *ident_user undefined.
+ */
+static bool
+interpret_ident_response(char *ident_response,
+						 char *ident_user)
+{
+	char	   *cursor = ident_response;/* Cursor into *ident_response */
 
 	/*
 	 * Ident's response, in the telnet tradition, should end in crlf
 	 * (\r\n).
 	 */
 	if (strlen(ident_response) < 2)
-		*error_p = true;
+		return false;
 	else if (ident_response[strlen(ident_response) - 2] != '\r')
-		*error_p = true;
+		return false;
 	else
 	{
 		while (*cursor != ':' && *cursor != '\r')
 			cursor++;			/* skip port field */
 
 		if (*cursor != ':')
-			*error_p = true;
+			return false;
 		else
 		{
 			/* We're positioned to colon before response type field */
@@ -482,24 +642,23 @@ interpret_ident_response(char *ident_response,
 			while (isblank(*cursor))
 				cursor++;		/* skip blanks */
 			i = 0;
-			while (*cursor != ':' && *cursor != '\r' && !isblank(*cursor)
-				   && i < (int) (sizeof(response_type) - 1))
+			while (*cursor != ':' && *cursor != '\r' && !isblank(*cursor) &&
+				   i < (int) (sizeof(response_type) - 1))
 				response_type[i++] = *cursor++;
 			response_type[i] = '\0';
 			while (isblank(*cursor))
 				cursor++;		/* skip blanks */
 			if (strcmp(response_type, "USERID") != 0)
-				*error_p = true;
+				return false;
 			else
 			{
-
 				/*
 				 * It's a USERID response.  Good.  "cursor" should be
 				 * pointing to the colon that precedes the operating
 				 * system type.
 				 */
 				if (*cursor != ':')
-					*error_p = true;
+					return false;
 				else
 				{
 					cursor++;	/* Go over colon */
@@ -507,10 +666,10 @@ interpret_ident_response(char *ident_response,
 					while (*cursor != ':' && *cursor != '\r')
 						cursor++;
 					if (*cursor != ':')
-						*error_p = true;
+						return false;
 					else
 					{
-						int			i;	/* Index into *ident_username */
+						int			i;	/* Index into *ident_user */
 
 						cursor++;		/* Go over colon */
 						while (isblank(*cursor))
@@ -518,9 +677,9 @@ interpret_ident_response(char *ident_response,
 						/* Rest of line is username.  Copy it over. */
 						i = 0;
 						while (*cursor != '\r' && i < IDENT_USERNAME_MAX)
-							ident_username[i++] = *cursor++;
-						ident_username[i] = '\0';
-						*error_p = false;
+							ident_user[i++] = *cursor++;
+						ident_user[i] = '\0';
+						return true;
 					}
 				}
 			}
@@ -529,39 +688,39 @@ interpret_ident_response(char *ident_response,
 }
 
 
+/*
+ *  Talk to the ident server on host "remote_ip_addr" and find out who
+ *  owns the tcp connection from his port "remote_port" to port
+ *  "local_port_addr" on host "local_ip_addr".  Return the username the
+ *  ident server gives as "*ident_user".
 
-static void
-ident(const struct in_addr remote_ip_addr, const struct in_addr local_ip_addr,
-	  const ushort remote_port, const ushort local_port,
-	  bool *ident_failed, char *ident_username)
-{
-/*--------------------------------------------------------------------------
-  Talk to the ident server on host "remote_ip_addr" and find out who
-  owns the tcp connection from his port "remote_port" to port
-  "local_port_addr" on host "local_ip_addr".  Return the username the
-  ident server gives as "*ident_username".
-
-  IP addresses and port numbers are in network byte order.
-
-  But iff we're unable to get the information from ident, return
-  *ident_failed == true (and *ident_username undefined).
-----------------------------------------------------------------------------*/
-
+ *  IP addresses and port numbers are in network byte order.
 
+ *  But iff we're unable to get the information from ident, return
+ *  false.
+ */
+static int
+ident(const struct in_addr remote_ip_addr,
+	  const struct in_addr local_ip_addr,
+	  const ushort remote_port,
+	  const ushort local_port,
+	  char *ident_user)
+{
 	int			sock_fd,		/* File descriptor for socket on which we
 								 * talk to Ident */
 				rc;				/* Return code from a locally called
 								 * function */
+	bool ident_return;
 
 	sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
 	if (sock_fd == -1)
 	{
 		snprintf(PQerrormsg, PQERRORMSG_LENGTH,
-			 "Failed to create socket on which to talk to Ident server. "
-				 "socket() returned errno = %s (%d)\n",
-				 strerror(errno), errno);
+			"Failed to create socket on which to talk to Ident server. "
+			"socket() returned errno = %s (%d)\n", strerror(errno), errno);
 		fputs(PQerrormsg, stderr);
 		pqdebug("%s", PQerrormsg);
+		ident_return = false;
 	}
 	else
 	{
@@ -595,13 +754,13 @@ ident(const struct in_addr remote_ip_addr, const struct in_addr local_ip_addr,
 		{
 			snprintf(PQerrormsg, PQERRORMSG_LENGTH,
 				"Unable to connect to Ident server on the host which is "
-					 "trying to connect to Postgres "
-					 "(IP address %s, Port %d). "
-					 "errno = %s (%d)\n",
-					 inet_ntoa(remote_ip_addr), IDENT_PORT, strerror(errno), errno);
+				"trying to connect to Postgres "
+				"(IP address %s, Port %d). "
+				"errno = %s (%d)\n",
+				inet_ntoa(remote_ip_addr), IDENT_PORT, strerror(errno), errno);
 			fputs(PQerrormsg, stderr);
 			pqdebug("%s", PQerrormsg);
-			*ident_failed = true;
+			ident_return = false;
 		}
 		else
 		{
@@ -614,260 +773,106 @@ ident(const struct in_addr remote_ip_addr, const struct in_addr local_ip_addr,
 			if (rc < 0)
 			{
 				snprintf(PQerrormsg, PQERRORMSG_LENGTH,
-						 "Unable to send query to Ident server on the host which is "
-					  "trying to connect to Postgres (Host %s, Port %d),"
-						 "even though we successfully connected to it.  "
-						 "errno = %s (%d)\n",
-						 inet_ntoa(remote_ip_addr), IDENT_PORT, strerror(errno), errno);
+					"Unable to send query to Ident server on the host which is "
+					"trying to connect to Postgres (Host %s, Port %d),"
+					"even though we successfully connected to it.  "
+					"errno = %s (%d)\n",
+					inet_ntoa(remote_ip_addr), IDENT_PORT, strerror(errno), errno);
 				fputs(PQerrormsg, stderr);
 				pqdebug("%s", PQerrormsg);
-				*ident_failed = true;
+				ident_return = false;
 			}
 			else
 			{
 				char		ident_response[80 + IDENT_USERNAME_MAX];
 
-				rc = recv(sock_fd, ident_response, sizeof(ident_response) - 1, 0);
+				rc = recv(sock_fd, ident_response,
+						  sizeof(ident_response) - 1, 0);
 				if (rc < 0)
 				{
 					snprintf(PQerrormsg, PQERRORMSG_LENGTH,
-						  "Unable to receive response from Ident server "
-							 "on the host which is "
-					  "trying to connect to Postgres (Host %s, Port %d),"
-					"even though we successfully sent our query to it.  "
-							 "errno = %s (%d)\n",
-							 inet_ntoa(remote_ip_addr), IDENT_PORT,
-							 strerror(errno), errno);
+						"Unable to receive response from Ident server "
+						"on the host which is "
+						"trying to connect to Postgres (Host %s, Port %d),"
+						"even though we successfully sent our query to it.  "
+						"errno = %s (%d)\n",
+						inet_ntoa(remote_ip_addr), IDENT_PORT,
+						strerror(errno), errno);
 					fputs(PQerrormsg, stderr);
 					pqdebug("%s", PQerrormsg);
-					*ident_failed = true;
+					ident_return = false;
 				}
 				else
 				{
-					bool		error;	/* response from Ident is garbage. */
-
 					ident_response[rc] = '\0';
-					interpret_ident_response(ident_response, &error, ident_username);
-					*ident_failed = error;
+					ident_return = interpret_ident_response(ident_response,
+															ident_user);
 				}
 			}
 			close(sock_fd);
 		}
 	}
+	return ident_return;
 }
 
 
-
-static void
-parse_map_record(FILE *file,
-				 char *file_map, char *file_pguser, char *file_iuser)
-{
-/*---------------------------------------------------------------------------
-  Take the noncomment line which is next on file "file" and interpret
-  it as a line in a usermap file.  Specifically, return the first
-  3 tokens as file_map, file_iuser, and file_pguser, respectively.	If
-  there are fewer than 3 tokens, return null strings for the missing
-  ones.
-
----------------------------------------------------------------------------*/
-	char		buf[MAX_TOKEN];
-
-	/* A token read from the file */
-
-	/* Set defaults in case fields not in file */
-	file_map[0] = '\0';
-	file_pguser[0] = '\0';
-	file_iuser[0] = '\0';
-
-	next_token(file, buf, sizeof(buf));
-	if (buf[0] != '\0')
-	{
-		strcpy(file_map, buf);
-		next_token(file, buf, sizeof(buf));
-		if (buf[0] != '\0')
-		{
-			strcpy(file_iuser, buf);
-			next_token(file, buf, sizeof(buf));
-			if (buf[0] != '\0')
-			{
-				strcpy(file_pguser, buf);
-				read_through_eol(file);
-				return;
-			}
-		}
-		snprintf(PQerrormsg, PQERRORMSG_LENGTH,
-				 "Incomplete line in pg_ident: %s", file_map);
-		fputs(PQerrormsg, stderr);
-		pqdebug("%s", PQerrormsg);
-	}
-}
-
-
-
-static void
-verify_against_open_usermap(FILE *file,
-							const char *pguser,
-							const char *ident_username,
-							const char *usermap_name,
-							bool *checks_out_p)
-{
-/*--------------------------------------------------------------------------
-  This function does the same thing as verify_against_usermap,
-  only with the config file already open on stream descriptor "file".
----------------------------------------------------------------------------*/
-	bool		match;			/* We found a matching entry in the map
-								 * file */
-	bool		eof;			/* We've reached the end of the file we're
-								 * reading */
-
-	match = false;				/* initial value */
-	eof = false;				/* initial value */
-	while (!eof && !match)
-	{
-		/* Process a line from the map file */
-
-		int			c;			/* a character read from the file */
-
-		c = getc(file);
-		ungetc(c, file);
-		if (c == EOF)
-			eof = true;
-		else
-		{
-			if (c == '#')
-				read_through_eol(file);
-			else
-			{
-				/* The following are fields read from a record of the file */
-				char		file_map[MAX_TOKEN + 1];
-				char		file_pguser[MAX_TOKEN + 1];
-				char		file_iuser[MAX_TOKEN + 1];
-
-				parse_map_record(file, file_map, file_pguser, file_iuser);
-				if (strcmp(file_map, usermap_name) == 0 &&
-					strcmp(file_pguser, pguser) == 0 &&
-					strcmp(file_iuser, ident_username) == 0)
-					match = true;
-			}
-		}
-	}
-	*checks_out_p = match;
-}
-
-
-
-static void
-verify_against_usermap(const char *pguser,
-					   const char *ident_username,
-					   const char *usermap_name,
-					   bool *checks_out_p)
+/*
+ *  Talk to the ident server on the remote host and find out who owns the
+ *  connection described by "port".  Then look in the usermap file under
+ *  the usermap *auth_arg and see if that user is equivalent to
+ *  Postgres user *user.
+ *
+ *  Return STATUS_OK if yes.
+ */
+int
+authident(struct sockaddr_in *raddr, struct sockaddr_in *laddr,
+		  const char *pg_user, const char *auth_arg)
 {
-/*--------------------------------------------------------------------------
-  See if the user with ident username "ident_username" is allowed to act
-  as Postgres user "pguser" according to usermap "usermap_name".   Look
-  it up in the usermap file.
-
-  Special case: For usermap "sameuser", don't look in the usermap
-  file.  That's an implied map where "pguser" must be identical to
-  "ident_username" in order to be authorized.
-
-  Iff authorized, return *checks_out_p == true.
+	/* We were unable to get ident to give us a username */
+	char		ident_user[IDENT_USERNAME_MAX + 1];
 
---------------------------------------------------------------------------*/
+	/* The username returned by ident */
+	if (!ident(raddr->sin_addr, laddr->sin_addr,
+		  raddr->sin_port, laddr->sin_port, ident_user))
+		return STATUS_ERROR;
 
-	if (usermap_name[0] == '\0')
-	{
-		*checks_out_p = false;
-		snprintf(PQerrormsg, PQERRORMSG_LENGTH,
-			   "verify_against_usermap: hba configuration file does not "
-		   "have the usermap field filled in in the entry that pertains "
-		  "to this connection.  That field is essential for Ident-based "
-				 "authentication.\n");
-		fputs(PQerrormsg, stderr);
-		pqdebug("%s", PQerrormsg);
-	}
-	else if (strcmp(usermap_name, "sameuser") == 0)
-	{
-		if (strcmp(ident_username, pguser) == 0)
-			*checks_out_p = true;
-		else
-			*checks_out_p = false;
-	}
+	if (check_ident_usermap(auth_arg, pg_user, ident_user))
+		return STATUS_OK;
 	else
-	{
-		FILE	   *file;		/* The map file we have to read */
-		char	   *map_file;	/* The name of the map file we have to
-								 * read */
-		int			bufsize;
-
-		/* put together the full pathname to the map file */
-		bufsize = (strlen(DataDir) + strlen(USERMAP_FILE) + 2) * sizeof(char);
-		map_file = (char *) palloc(bufsize);
-		snprintf(map_file, bufsize, "%s/%s", DataDir, USERMAP_FILE);
-
-		file = AllocateFile(map_file, PG_BINARY_R);
-		if (file == NULL)
-		{
-			/* The open of the map file failed.  */
-
-			snprintf(PQerrormsg, PQERRORMSG_LENGTH,
-					 "verify_against_usermap: Unable to open usermap file \"%s\": %s\n",
-					 map_file, strerror(errno));
-			fputs(PQerrormsg, stderr);
-			pqdebug("%s", PQerrormsg);
-
-			*checks_out_p = false;
-		}
-		else
-		{
-			verify_against_open_usermap(file,
-									pguser, ident_username, usermap_name,
-										checks_out_p);
-			FreeFile(file);
-		}
-		pfree(map_file);
-
-
-	}
+		return STATUS_ERROR;
 }
 
 
-
+/*
+ *  Determine what authentication method should be used when accessing database
+ *  "database" from frontend "raddr", user "user".  Return the method,
+ *  an optional argument, and STATUS_OK.
+ *  Note that STATUS_ERROR indicates a problem with the hba config file.
+ *  If the file is OK but does not contain any entry matching the request,
+ *  we return STATUS_OK and method = uaReject.
+ */
 int
-authident(struct sockaddr_in * raddr, struct sockaddr_in * laddr,
-		  const char *postgres_username,
-		  const char *auth_arg)
+hba_getauthmethod(hbaPort *port)
 {
-/*---------------------------------------------------------------------------
-  Talk to the ident server on the remote host and find out who owns the
-  connection described by "port".  Then look in the usermap file under
-  the usermap *auth_arg and see if that user is equivalent to
-  Postgres user *user.
-
-  Return STATUS_OK if yes.
----------------------------------------------------------------------------*/
-	bool		checks_out;
-	bool		ident_failed;
 
-	/* We were unable to get ident to give us a username */
-	char		ident_username[IDENT_USERNAME_MAX + 1];
-
-	/* The username returned by ident */
-
-	ident(raddr->sin_addr, laddr->sin_addr,
-		  raddr->sin_port, laddr->sin_port,
-		  &ident_failed, ident_username);
-
-	if (ident_failed)
+	if (check_hba(port))
+		return STATUS_OK;
+	else
 		return STATUS_ERROR;
+}
 
-	verify_against_usermap(postgres_username, ident_username, auth_arg,
-						   &checks_out);
-
-	return checks_out ? STATUS_OK : STATUS_ERROR;
+/*
+ * Clear tokenized file contents and force reload on next use.
+ */
+void load_hba_and_ident(void)
+{
+	load_hba();
+	load_ident();
 }
 
 
+/* Character set stuff.  Not sure it really belongs in this file. */
+
 #ifdef CYR_RECODE
 #define CHARSET_FILE "charset.conf"
 #define MAX_CHARSETS   10
@@ -882,8 +887,9 @@ struct CharsetItem
 	char		Table[MAX_TOKEN];
 };
 
+
 static bool
-InRange(char *buf, int host)
+CharSetInRange(char *buf, int host)
 {
 	int			valid,
 				i,
@@ -989,7 +995,7 @@ GetCharSetByHost(char *TableName, int host, const char *DataDir)
 		else
 		{
 			if (c == '#')
-				read_through_eol(file);
+				read_to_eol(file);
 			else
 			{
 				/* Read the key */
@@ -1009,7 +1015,7 @@ GetCharSetByHost(char *TableName, int host, const char *DataDir)
 							next_token(file, buf, sizeof(buf));
 							if (buf[0] != '\0')
 							{
-								if (InRange(buf, host))
+								if (CharSetInRange(buf, host))
 								{
 									/* Read the charset */
 									next_token(file, buf, sizeof(buf));
@@ -1050,7 +1056,7 @@ GetCharSetByHost(char *TableName, int host, const char *DataDir)
 							}
 							break;
 					}
-					read_through_eol(file);
+					read_to_eol(file);
 				}
 			}
 		}
@@ -1066,23 +1072,7 @@ GetCharSetByHost(char *TableName, int host, const char *DataDir)
 		pfree((struct CharsetItem *) ChArray[i]);
 	}
 }
-
 #endif
 
-int
-hba_getauthmethod(hbaPort *port)
-{
-/*---------------------------------------------------------------------------
-  Determine what authentication method should be used when accessing database
-  "database" from frontend "raddr", user "user".  Return the method,
-  an optional argument, and STATUS_OK.
-  Note that STATUS_ERROR indicates a problem with the hba config file.
-  If the file is OK but does not contain any entry matching the request,
-  we return STATUS_OK and method = uaReject.
-----------------------------------------------------------------------------*/
-	bool		hba_ok = false;
-
-	find_hba_entry(port, &hba_ok);
-
-	return hba_ok ? STATUS_OK : STATUS_ERROR;
-}
+
+
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 3e92f16720e76c8077b1863d130350a1711fa678..c1cd24c7d60919bc73c51a8d052ac3ab9fe1105d 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -37,7 +37,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.231 2001/07/03 16:52:12 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.232 2001/07/30 14:50:22 momjian Exp $
  *
  * NOTES
  *
@@ -809,6 +809,8 @@ ServerLoop(void)
 
 	nSockets = initMasks(&readmask, &writemask);
 
+	load_hba_and_ident();
+
 	for (;;)
 	{
 		Port	   *port;
@@ -874,6 +876,7 @@ ServerLoop(void)
 		if (got_SIGHUP)
 		{
 			got_SIGHUP = false;
+			load_hba_and_ident();
 			ProcessConfigFile(PGC_SIGHUP);
 		}
 
@@ -993,7 +996,7 @@ ProcessStartupPacket(Port *port, bool SSLdone)
 
 	buf = palloc(len);
 	pq_getbytes(buf, len);
-	
+
 	packet = buf;
 
 	/*
@@ -1479,7 +1482,7 @@ reaper(SIGNAL_ARGS)
 #endif
 		/*
 		 * Check if this child was the statistics collector. If
-		 * so, start a new one. 
+		 * so, start a new one.
 		 */
 		if (pgstat_ispgstat(pid))
 		{
@@ -1987,19 +1990,8 @@ DoBackend(Port *port)
 		av[ac++] = "-o";
 		av[ac++] = ttybuf;
 	}
-
 	av[ac] = (char *) NULL;
 
-	/*
-	 * Release postmaster's working memory context so that backend can
-	 * recycle the space.  Note this does not trash *MyProcPort, because
-	 * ConnCreate() allocated that space with malloc() ... else we'd need
-	 * to copy the Port data here.
-	 */
-	MemoryContextSwitchTo(TopMemoryContext);
-	MemoryContextDelete(PostmasterContext);
-	PostmasterContext = NULL;
-
 	/*
 	 * Debug: print arguments being passed to backend
 	 */
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index acf89356e80781874e3eaf85d829440d3687a8ef..0de677a94421cde2de44e7616ef5a753891dbeea 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.227 2001/06/29 16:05:56 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.228 2001/07/30 14:50:24 momjian Exp $
  *
  * NOTES
  *	  this is the "main" module of the postgres backend and
@@ -1120,7 +1120,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
 	unsigned short remote_port;
 
 	char	   *potential_DataDir = NULL;
-	
+
 	/*
 	 * Catch standard options before doing much else.  This even works on
 	 * systems without getopt_long.
@@ -1144,16 +1144,27 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
 	 *
 	 * If we are running under the postmaster, this is done already.
 	 */
-	if (!IsUnderPostmaster)
+	if (IsUnderPostmaster)
+	{
+		MemoryContextSwitchTo(TopMemoryContext);
+		ClientAuthentication(MyProcPort); /* might not return */
+		/*
+		 * Release postmaster's working memory context so that backend can
+		 * recycle the space.  Note this does not trash *MyProcPort, because
+		 * ConnCreate() allocated that space with malloc() ... else we'd need
+		 * to copy the Port data here.  We delete it here because the
+		 * authorization file tokens are stored in this context.
+		 */
+		MemoryContextDelete(PostmasterContext);
+		PostmasterContext = NULL;
+	}
+	else
 	{
 		SetProcessingMode(InitProcessing);
 		EnableExceptionHandling(true);
 		MemoryContextInit();
 	}
 
-	if (IsUnderPostmaster)
-		ClientAuthentication(MyProcPort); /* might not return */
-
 	/*
 	 * Set default values for command-line options.
 	 */
@@ -1714,7 +1725,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
 	if (!IsUnderPostmaster)
 	{
 		puts("\nPOSTGRES backend interactive interface ");
-		puts("$Revision: 1.227 $ $Date: 2001/06/29 16:05:56 $\n");
+		puts("$Revision: 1.228 $ $Date: 2001/07/30 14:50:24 $\n");
 	}
 
 	/*
diff --git a/src/include/libpq/hba.h b/src/include/libpq/hba.h
index 9afd9f841732c2a0cc001033b05eea55e53593bd..f6493373e23536079f57ce312bf0a7b6c4e23612 100644
--- a/src/include/libpq/hba.h
+++ b/src/include/libpq/hba.h
@@ -4,7 +4,7 @@
  *	  Interface to hba.c
  *
  *
- * $Id: hba.h,v 1.19 2001/03/22 04:00:47 momjian Exp $
+ * $Id: hba.h,v 1.20 2001/07/30 14:50:24 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -40,8 +40,9 @@ typedef enum UserAuth
 
 typedef struct Port hbaPort;
 
-int			hba_getauthmethod(hbaPort *port);
+int	hba_getauthmethod(hbaPort *port);
 int authident(struct sockaddr_in * raddr, struct sockaddr_in * laddr,
 		  const char *postgres_username, const char *auth_arg);
+void load_hba_and_ident(void);
 
 #endif