diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml
index 19d81f960bedeabfc784834d224fa6e7a030e71a..1f1674904afc819c8693e445a74b3c3ccc5ce755 100644
--- a/doc/src/sgml/client-auth.sgml
+++ b/doc/src/sgml/client-auth.sgml
@@ -1,4 +1,4 @@
-<!-- $Header: /cvsroot/pgsql/doc/src/sgml/client-auth.sgml,v 1.22 2001/10/04 22:27:18 petere Exp $ -->
+<!-- $Header: /cvsroot/pgsql/doc/src/sgml/client-auth.sgml,v 1.23 2001/11/02 18:39:57 tgl Exp $ -->
 
 <chapter id="client-authentication">
  <title>Client Authentication</title>
@@ -67,6 +67,19 @@
    tabs.  Records cannot be continued across lines.
   </para>
 
+  <para>
+   Each record specifies a connection type, a client IP address range
+   (if relevant for the connection type), a database name or names,
+   and the authentication method to be used for connections matching
+   these parameters.
+   The first record that matches the type, client address and requested
+   database name of a connection attempt is used to do the
+   authentication step.  There is no <quote>fall-through</> or
+   <quote>backup</>: if one record is chosen and the authentication
+   fails, the following records are not considered. If no record
+   matches, the access will be denied.
+  </para>
+
   <para>
    A record may have one of the three formats
    <synopsis>
@@ -107,7 +120,9 @@ hostssl <replaceable>database</replaceable> <replaceable>IP-address</replaceable
        TCP/IP. To make use of this option the server must be
        built with SSL support enabled. Furthermore, SSL must be
        enabled with the <option>-l</> option or equivalent configuration
-       setting when the server is started.
+       setting when the server is started.  (Note: <literal>host</literal>
+       records will match either SSL or non-SSL connection attempts, but
+       <literal>hostssl</literal> records match only SSL connections.)
       </para>
      </listitem>
     </varlistentry>
@@ -131,8 +146,9 @@ hostssl <replaceable>database</replaceable> <replaceable>IP-address</replaceable
      <term><replaceable>IP mask</replaceable></term>
      <listitem>
       <para>
-       These two fields control to which hosts a
-       <literal>host</literal> record applies, based on their IP
+       These two fields specify to which client machines a
+       <literal>host</literal> or <literal>hostssl</literal>
+       record applies, based on their IP
        address. (Of course IP addresses can be spoofed but this
        consideration is beyond the scope of
        <productname>Postgres</productname>.) The precise logic is that
@@ -151,7 +167,8 @@ hostssl <replaceable>database</replaceable> <replaceable>IP-address</replaceable
      <listitem>
       <para>
        Specifies the method that users must use to authenticate themselves
-       when connecting to that database. The possible choices follow,
+       when connecting under the control of this authentication record.
+       The possible choices are summarized here,
        details are in <xref linkend="auth-methods">.
 
        <variablelist>
@@ -322,17 +339,27 @@ hostssl <replaceable>database</replaceable> <replaceable>IP-address</replaceable
      </listitem>
     </varlistentry>
    </variablelist>
+  </para>
 
-   The first record that matches the client IP address and requested
-   database name of a connection attempt is used to do the
-   authentication step.  There is no <quote>fall-through</> or
-   <quote>backup</>: if one record is chosen and the authentication
-   fails, the following records are not considered. If no record
-   matches, the access will be denied.
+  <para>
+   Since the <filename>pg_hba.conf</filename> records are examined
+   sequentially for each connection attempt, order of the records is
+   very significant.  Typically, earlier records will have tight
+   connection match parameters and weaker authentication methods,
+   while later records will have looser match parameters and stronger
+   authentication methods.  For example, one might wish to use
+   <literal>trust</> authentication for local TCP connections but
+   require a password for remote TCP connections.  In this case a
+   record specifying <literal>trust</> authentication for connections
+   from 127.0.0.1 would appear before a record specifying password
+   authentication for a wider range of allowed client IP addresses.
   </para>
 
   <para>
-   The <filename>pg_hba.conf</filename> file is loaded only on startup
+    <indexterm>
+     <primary>SIGHUP</primary>
+    </indexterm>
+   The <filename>pg_hba.conf</filename> file is read on startup
    and when the <application>postmaster</> receives a
    <systemitem>SIGHUP</systemitem> signal. If you edit the file on an
    active system, you will need to signal the <application>postmaster</>
@@ -632,7 +659,7 @@ host         all        192.168.0.0    255.255.0.0        ident     omicron
     to connect as the database user he is requesting to connect as.
     This is controlled by the ident map
     argument that follows the <literal>ident</> keyword in the
-    <filename>pg_hba.conf</filename> file. The simplest ident map is
+    <filename>pg_hba.conf</filename> file. There is a predefined ident map
     <literal>sameuser</literal>, which allows any operating system
     user to connect as the database user of the same name (if the
     latter exists). Other maps must be created manually.
@@ -640,7 +667,8 @@ host         all        192.168.0.0    255.255.0.0        ident     omicron
 
    <para>
     <indexterm><primary>pg_ident.conf</primary></indexterm>
-    Ident maps are held in the file <filename>pg_ident.conf</filename>
+    Ident maps other than <literal>sameuser</literal> are defined
+    in the file <filename>pg_ident.conf</filename>
     in the data directory, which contains lines of the general form:
 <synopsis>
 <replaceable>map-name</> <replaceable>ident-username</> <replaceable>database-username</>
@@ -657,6 +685,18 @@ host         all        192.168.0.0    255.255.0.0        ident     omicron
     versa.
    </para>
 
+  <para>
+    <indexterm>
+     <primary>SIGHUP</primary>
+    </indexterm>
+   The <filename>pg_ident.conf</filename> file is read on startup
+   and when the <application>postmaster</> receives a
+   <systemitem>SIGHUP</systemitem> signal. If you edit the file on an
+   active system, you will need to signal the <application>postmaster</>
+   (using <application>pg_ctl reload</> or <application>kill -HUP</>)
+   to make it re-read the file.
+  </para>
+
    <para>
     A <filename>pg_ident.conf</filename> file that could be used in
     conjunction with the <filename>pg_hba.conf</> file in <xref
diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml
index fcbb97d00b81c98f9476ba3029b356c2eb945db8..8284d010e646986bf13afb18cf6635431fbd0314 100644
--- a/doc/src/sgml/runtime.sgml
+++ b/doc/src/sgml/runtime.sgml
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.91 2001/10/31 20:35:02 petere Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.92 2001/11/02 18:39:57 tgl Exp $
 -->
 
 <Chapter Id="runtime">
@@ -479,8 +479,10 @@ syslog = 2
      <primary>SIGHUP</primary>
     </indexterm>
     The configuration file is reread whenever the postmaster receives
-    a <systemitem>SIGHUP</> signal. This signal is also propagated to all running
-    backend processes, so that running sessions get the new default.
+    a <systemitem>SIGHUP</> signal (which is most easily sent by means
+    of <application>pg_ctl reload</>).  The postmaster also propagates
+    this signal to all already-running backend processes, so that
+    existing sessions also get the new default.
     Alternatively, you can send the signal to only one backend process
     directly.
    </para>
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 758cf365c80841e6f10a090d8ebb4fda8524fafd..3897a5c75ec7e582a7bda3fdbffe592fd3efef34 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.87 2001/11/01 18:09:58 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.88 2001/11/02 18:39:57 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -15,6 +15,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#include <signal.h>
 #include <unistd.h>
 
 #include "access/heapam.h"
@@ -33,14 +34,15 @@
 #include "utils/syscache.h"
 
 
-static void CheckPgUserAclNotNull(void);
 extern bool Password_encryption;
 
+static void CheckPgUserAclNotNull(void);
+
 /*---------------------------------------------------------------------
  * write_password_file / update_pg_pwd
  *
  * copy the modified contents of pg_shadow to a file used by the postmaster
- * for user authentication.  The file is stored as $PGDATA/pg_pwd.
+ * for user authentication.  The file is stored as $PGDATA/global/pg_pwd.
  *
  * This function set is both a trigger function for direct updates to pg_shadow
  * as well as being called directly from create/alter/drop user.
@@ -57,7 +59,6 @@ write_password_file(Relation rel)
 			   *tempname;
 	int			bufsize;
 	FILE	   *fp;
-	int			flagfd;
 	mode_t		oumask;
 	HeapScanDesc scan;
 	HeapTuple	tuple;
@@ -133,7 +134,7 @@ write_password_file(Relation rel)
 		/*
 		 * The extra columns we emit here are not really necessary. To remove
 		 * them, the parser in backend/libpq/crypt.c would need to be
-		 * adjusted.  Initdb might also need adjustments.
+		 * adjusted.
 		 */
 		fprintf(fp,
 				"%s"
@@ -168,6 +169,7 @@ write_password_file(Relation rel)
 
 	/*
 	 * Rename the temp file to its final name, deleting the old pg_pwd.
+	 * We expect that rename(2) is an atomic action.
 	 */
 	if (rename(tempname, filename))
 		elog(ERROR, "rename %s to %s: %m", tempname, filename);
@@ -176,19 +178,10 @@ write_password_file(Relation rel)
 	pfree((void *) filename);
 
 	/*
-	 * Create a flag file the postmaster will detect the next time it
-	 * tries to authenticate a user.  The postmaster will know to reload
-	 * the pg_pwd file contents.  Note: we used to elog(ERROR) if the file
-	 * creation failed, but it's a little silly to abort the transaction
-	 * at this point, so let's just make it a NOTICE.
+	 * Signal the postmaster to reload its password-file cache.
 	 */
-	filename = crypt_getpwdreloadfilename();
-	flagfd = BasicOpenFile(filename, O_WRONLY | O_CREAT, 0600);
-	if (flagfd < 0)
-		elog(NOTICE, "write_password_file: unable to write %s: %m", filename);
-	else
-		close(flagfd);
-	pfree((void *) filename);
+	if (IsUnderPostmaster)
+		kill(getppid(), SIGHUP);
 }
 
 
diff --git a/src/backend/libpq/crypt.c b/src/backend/libpq/crypt.c
index 8decc40d0ba3f70589d25ec749bf0d609cca7c31..83921ee014f0738f2babce0383134d69f79d736a 100644
--- a/src/backend/libpq/crypt.c
+++ b/src/backend/libpq/crypt.c
@@ -9,7 +9,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Header: /cvsroot/pgsql/src/backend/libpq/crypt.c,v 1.40 2001/11/01 18:10:48 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/libpq/crypt.c,v 1.41 2001/11/02 18:39:57 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -17,6 +17,9 @@
 
 #include <errno.h>
 #include <unistd.h>
+#ifdef HAVE_CRYPT_H
+#include <crypt.h>
+#endif
 
 #include "libpq/crypt.h"
 #include "libpq/libpq.h"
@@ -24,15 +27,15 @@
 #include "storage/fd.h"
 #include "utils/nabstime.h"
 
-#ifdef HAVE_CRYPT_H
-#include <crypt.h>
-#endif
 
-char	  **pwd_cache = NULL;
-int			pwd_cache_count = 0;
+#define CRYPT_PWD_FILE	"pg_pwd"
+
+
+static char	  **pwd_cache = NULL;
+static int		pwd_cache_count = 0;
 
 /*
- * crypt_getpwdfilename --- get name of password file
+ * crypt_getpwdfilename --- get full pathname of password file
  *
  * Note that result string is palloc'd, and should be freed by the caller.
  */
@@ -50,28 +53,8 @@ crypt_getpwdfilename(void)
 }
 
 /*
- * crypt_getpwdreloadfilename --- get name of password-reload-needed flag file
- *
- * Note that result string is palloc'd, and should be freed by the caller.
+ * Open the password file if possible (return NULL if not)
  */
-char *
-crypt_getpwdreloadfilename(void)
-{
-	char	   *pwdfilename;
-	int			bufsize;
-	char	   *rpfnam;
-
-	pwdfilename = crypt_getpwdfilename();
-	bufsize = strlen(pwdfilename) + strlen(CRYPT_PWD_RELOAD_SUFX) + 1;
-	rpfnam = (char *) palloc(bufsize);
-	snprintf(rpfnam, bufsize, "%s%s", pwdfilename, CRYPT_PWD_RELOAD_SUFX);
-	pfree(pwdfilename);
-
-	return rpfnam;
-}
-
-/*-------------------------------------------------------------------------*/
-
 static FILE *
 crypt_openpwdfile(void)
 {
@@ -123,107 +106,128 @@ compar_user(const void *user_a, const void *user_b)
 	return result;
 }
 
-/*-------------------------------------------------------------------------*/
-
-static void
-crypt_loadpwdfile(void)
+/*
+ * Load or reload the password-file cache
+ */
+void
+load_password_cache(void)
 {
-	char	   *filename;
-	int			result;
 	FILE	   *pwd_file;
 	char		buffer[1024];
 
-	filename = crypt_getpwdreloadfilename();
-	result = unlink(filename);
-	pfree(filename);
-
 	/*
-	 * We want to delete the flag file before reading the contents of the
-	 * pg_pwd file.  If result == 0 then the unlink of the reload file was
-	 * successful. This means that a backend performed a COPY of the
-	 * pg_shadow file to pg_pwd.  Therefore we must now do a reload.
+	 * If for some reason we fail to open the password file, preserve the
+	 * old cache contents; this seems better than dropping the cache if,
+	 * say, we are temporarily out of filetable slots.
 	 */
-	if (!pwd_cache || result == 0)
+	if (!(pwd_file = crypt_openpwdfile()))
+		return;
+
+	/* free any old data */
+	if (pwd_cache)
 	{
-		/* free the old data only if this is a reload */
-		if (pwd_cache)
-		{
-			while (pwd_cache_count--)
-				free((void *) pwd_cache[pwd_cache_count]);
-			free((void *) pwd_cache);
-			pwd_cache = NULL;
-			pwd_cache_count = 0;
-		}
+		while (--pwd_cache_count >= 0)
+			pfree(pwd_cache[pwd_cache_count]);
+		pfree(pwd_cache);
+		pwd_cache = NULL;
+		pwd_cache_count = 0;
+	}
 
-		if (!(pwd_file = crypt_openpwdfile()))
-			return;
+	/*
+	 * Read the file and store its lines in current memory context,
+	 * which we expect will be PostmasterContext.  That context will
+	 * live as long as we need the cache to live, ie, until just after
+	 * each postmaster child has completed client authentication.
+	 */
+	while (fgets(buffer, sizeof(buffer), pwd_file) != NULL)
+	{
+		int			blen;
 
 		/*
-		 * Here is where we load the data from pg_pwd.
+		 * We must remove the return char at the end of the string, as
+		 * this will affect the correct parsing of the password entry.
 		 */
-		while (fgets(buffer, sizeof(buffer), pwd_file) != NULL)
-		{
-			/*
-			 * We must remove the return char at the end of the string, as
-			 * this will affect the correct parsing of the password entry.
-			 */
-			if (buffer[(result = strlen(buffer) - 1)] == '\n')
-				buffer[result] = '\0';
+		if (buffer[(blen = strlen(buffer) - 1)] == '\n')
+			buffer[blen] = '\0';
 
+		if (pwd_cache == NULL)
 			pwd_cache = (char **)
-				realloc((void *) pwd_cache,
-						sizeof(char *) * (pwd_cache_count + 1));
-			pwd_cache[pwd_cache_count++] = strdup(buffer);
-		}
-		FreeFile(pwd_file);
-
-		/*
-		 * Now sort the entries in the cache for faster searching later.
-		 */
-		qsort((void *) pwd_cache, pwd_cache_count, sizeof(char *), compar_user);
+				palloc(sizeof(char *) * (pwd_cache_count + 1));
+		else
+			pwd_cache = (char **)
+				repalloc((void *) pwd_cache,
+						 sizeof(char *) * (pwd_cache_count + 1));
+		pwd_cache[pwd_cache_count++] = pstrdup(buffer);
 	}
-}
 
-/*-------------------------------------------------------------------------*/
+	FreeFile(pwd_file);
+
+	/*
+	 * Now sort the entries in the cache for faster searching later.
+	 */
+	qsort((void *) pwd_cache, pwd_cache_count, sizeof(char *), compar_user);
+}
 
-static void
+/*
+ * Parse a line of the password file to extract password and valid-until date.
+ */
+static bool
 crypt_parsepwdentry(char *buffer, char **pwd, char **valdate)
 {
 	char	   *parse = buffer;
 	int			count,
 				i;
 
+	*pwd = NULL;
+	*valdate = NULL;
+
 	/*
 	 * skip to the password field
 	 */
 	for (i = 0; i < 6; i++)
-		parse += (strcspn(parse, CRYPT_PWD_FILE_SEPSTR) + 1);
+	{
+		parse += strcspn(parse, CRYPT_PWD_FILE_SEPSTR);
+		if (*parse == '\0')
+			return false;
+		parse++;
+	}
 
 	/*
 	 * store a copy of user password to return
 	 */
 	count = strcspn(parse, CRYPT_PWD_FILE_SEPSTR);
 	*pwd = (char *) palloc(count + 1);
-	strncpy(*pwd, parse, count);
+	memcpy(*pwd, parse, count);
 	(*pwd)[count] = '\0';
-	parse += (count + 1);
+	parse += count;
+	if (*parse == '\0')
+	{
+		pfree(*pwd);
+		*pwd = NULL;
+		return false;
+	}
+	parse++;
 
 	/*
 	 * store a copy of the date login becomes invalid
 	 */
 	count = strcspn(parse, CRYPT_PWD_FILE_SEPSTR);
 	*valdate = (char *) palloc(count + 1);
-	strncpy(*valdate, parse, count);
+	memcpy(*valdate, parse, count);
 	(*valdate)[count] = '\0';
-	parse += (count + 1);
-}
 
-/*-------------------------------------------------------------------------*/
+	return true;
+}
 
-static int
+/*
+ * Lookup a username in the password-file cache,
+ * return his password and valid-until date.
+ */
+static bool
 crypt_getloginfo(const char *user, char **passwd, char **valuntil)
 {
-	crypt_loadpwdfile();
+	*passwd = NULL;
+	*valuntil = NULL;
 
 	if (pwd_cache)
 	{
@@ -236,14 +240,12 @@ crypt_getloginfo(const char *user, char **passwd, char **valuntil)
 									  compar_user);
 		if (pwd_entry)
 		{
-			crypt_parsepwdentry(*pwd_entry, passwd, valuntil);
-			return STATUS_OK;
+			if (crypt_parsepwdentry(*pwd_entry, passwd, valuntil))
+				return true;
 		}
 	}
 
-	*passwd = NULL;
-	*valuntil = NULL;
-	return STATUS_ERROR;
+	return false;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -256,7 +258,7 @@ md5_crypt_verify(const Port *port, const char *user, const char *pgpass)
 			   *crypt_pwd;
 	int			retval = STATUS_ERROR;
 
-	if (crypt_getloginfo(user, &passwd, &valuntil) == STATUS_ERROR)
+	if (!crypt_getloginfo(user, &passwd, &valuntil))
 		return STATUS_ERROR;
 
 	if (passwd == NULL || *passwd == '\0')
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 1f232bfc3014f3291aca4726cc036a63bfcf0b6b..2c96486cd06e3c032e69a85741b9338c96d12d47 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.253 2001/10/28 06:25:47 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.254 2001/11/02 18:39:57 tgl Exp $
  *
  * NOTES
  *
@@ -746,6 +746,12 @@ PostmasterMain(int argc, char *argv[])
 	if (pgstat_start() < 0)
 		ExitPostmaster(1);
 
+	/*
+	 * Load cached files for client authentication.
+	 */
+	load_hba_and_ident();
+	load_password_cache();
+
 	/*
 	 * We're ready to rock and roll...
 	 */
@@ -852,8 +858,6 @@ ServerLoop(void)
 				later;
 	struct timezone tz;
 
-	load_hba_and_ident();
-
 	gettimeofday(&now, &tz);
 
 	nSockets = initMasks(&readmask, &writemask);
@@ -925,6 +929,7 @@ ServerLoop(void)
 			got_SIGHUP = false;
 			ProcessConfigFile(PGC_SIGHUP);
 			load_hba_and_ident();
+			load_password_cache();
 		}
 
 		/*
diff --git a/src/include/libpq/crypt.h b/src/include/libpq/crypt.h
index 39d677e166b2d385ae6716a2971f8184b9171f98..76dabc89bd45d732de43e654b552a53967c67623 100644
--- a/src/include/libpq/crypt.h
+++ b/src/include/libpq/crypt.h
@@ -1,9 +1,13 @@
 /*-------------------------------------------------------------------------
  *
  * crypt.h
- *	  Interface to hba.c
+ *	  Interface to libpq/crypt.c
  *
+ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
  *
+ * $Id: crypt.h,v 1.17 2001/11/02 18:39:57 tgl Exp $
+ * 
  *-------------------------------------------------------------------------
  */
 #ifndef PG_CRYPT_H
@@ -11,27 +15,22 @@
 
 #include "libpq/libpq-be.h"
 
-#define CRYPT_PWD_FILE	"pg_pwd"
-#define CRYPT_PWD_FILE_SEPCHAR	"'\\t'"
 #define CRYPT_PWD_FILE_SEPSTR	"\t"
-#define CRYPT_PWD_RELOAD_SUFX	".reload"
 
-extern char **pwd_cache;
-extern int	pwd_cache_count;
+#define MD5_PASSWD_LEN	35
+
+#define isMD5(passwd)	(strncmp((passwd),"md5",3) == 0 && \
+						 strlen(passwd) == MD5_PASSWD_LEN)
 
-extern char *crypt_getpwdfilename(void);
-extern char *crypt_getpwdreloadfilename(void);
 
-extern int	md5_crypt_verify(const Port *port, const char *user, const char *pgpass);
+extern char *crypt_getpwdfilename(void);
+extern void load_password_cache(void);
 
+extern int	md5_crypt_verify(const Port *port, const char *user,
+							 const char *pgpass);
 extern bool md5_hash(const void *buff, size_t len, char *hexsum);
 extern bool CheckMD5Pwd(char *passwd, char *storedpwd, char *seed);
 extern bool EncryptMD5(const char *passwd, const char *salt,
 		   size_t salt_len, char *buf);
 
-#define MD5_PASSWD_LEN	35
-
-#define isMD5(passwd)	(strncmp((passwd),"md5",3) == 0 && \
-						 strlen(passwd) == MD5_PASSWD_LEN)
-
 #endif