diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c
index dcb702e95967604d0b78062c0b9fb04c385e644c..9d8ffa7db1c05f40828423e6a01b5cfe0e7ff90c 100644
--- a/src/backend/libpq/auth.c
+++ b/src/backend/libpq/auth.c
@@ -8,48 +8,34 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.52 2001/03/22 03:59:30 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.53 2001/06/20 18:07:55 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
-/*
- * INTERFACE ROUTINES
- *
- *	   backend (postmaster) routines:
- *		be_recvauth				receive authentication information
- */
-#include <sys/param.h>			/* for MAXHOSTNAMELEN on most */
-#ifndef  MAXHOSTNAMELEN
-#include <netdb.h>				/* for MAXHOSTNAMELEN on some */
-#endif
-#include <pwd.h>
-#include <ctype.h>
+
+#include "postgres.h"
 
 #include <sys/types.h>			/* needed by in.h on Ultrix */
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
-#include "postgres.h"
-
 #include "libpq/auth.h"
 #include "libpq/crypt.h"
 #include "libpq/hba.h"
 #include "libpq/libpq.h"
 #include "libpq/password.h"
+#include "libpq/pqformat.h"
 #include "miscadmin.h"
 
-static void sendAuthRequest(Port *port, AuthRequest areq, PacketDoneProc handler);
-static int	handle_done_auth(void *arg, PacketLen len, void *pkt);
-static int	handle_krb4_auth(void *arg, PacketLen len, void *pkt);
-static int	handle_krb5_auth(void *arg, PacketLen len, void *pkt);
-static int	handle_password_auth(void *arg, PacketLen len, void *pkt);
-static int	readPasswordPacket(void *arg, PacketLen len, void *pkt);
-static int	pg_passwordv0_recvauth(void *arg, PacketLen len, void *pkt);
+static void sendAuthRequest(Port *port, AuthRequest areq);
+
 static int	checkPassword(Port *port, char *user, char *password);
 static int	old_be_recvauth(Port *port);
 static int	map_old_to_new(Port *port, UserAuth old, int status);
 static void auth_failed(Port *port);
 
+static int	recv_and_check_password_packet(Port *port);
+static int	recv_and_check_passwordv0(Port *port);
 
 char	   *pg_krb_server_keyfile;
 
@@ -325,25 +311,28 @@ pg_krb5_recvauth(Port *port)
 /*
  * Handle a v0 password packet.
  */
-
 static int
-pg_passwordv0_recvauth(void *arg, PacketLen len, void *pkt)
+recv_and_check_passwordv0(Port *port)
 {
-	Port	   *port;
+	int32		len;
+	char	   *buf;
 	PasswordPacketV0 *pp;
 	char	   *user,
 			   *password,
 			   *cp,
 			   *start;
 
-	port = (Port *) arg;
-	pp = (PasswordPacketV0 *) pkt;
+	pq_getint(&len, 4);
+	len -= 4;
+	buf = palloc(len);
+	pq_getbytes(buf, len);
+
+	pp = (PasswordPacketV0 *) buf;
 
 	/*
 	 * The packet is supposed to comprise the user name and the password
 	 * as C strings.  Be careful the check that this is the case.
 	 */
-
 	user = password = NULL;
 
 	len -= sizeof(pp->unused);
@@ -371,6 +360,7 @@ pg_passwordv0_recvauth(void *arg, PacketLen len, void *pkt)
 		fputs(PQerrormsg, stderr);
 		pqdebug("%s", PQerrormsg);
 
+		pfree(buf);
 		auth_failed(port);
 	}
 	else
@@ -385,15 +375,15 @@ pg_passwordv0_recvauth(void *arg, PacketLen len, void *pkt)
 
 		status = checkPassword(port, user, password);
 
+		pfree(buf);
 		port->auth_method = saved;
 
 		/* Adjust the result if necessary. */
-
 		if (map_old_to_new(port, uaPassword, status) != STATUS_OK)
 			auth_failed(port);
 	}
 
-	return STATUS_OK;			/* don't close the connection yet */
+	return STATUS_OK;
 }
 
 
@@ -413,7 +403,6 @@ pg_passwordv0_recvauth(void *arg, PacketLen len, void *pkt)
 static void
 auth_failed(Port *port)
 {
-	char		buffer[512];
 	const char *authmethod = "Unknown auth method:";
 
 	switch (port->auth_method)
@@ -441,19 +430,20 @@ auth_failed(Port *port)
 			break;
 	}
 
-	sprintf(buffer, "%s authentication failed for user '%s'",
-			authmethod, port->user);
-
-	PacketSendError(&port->pktInfo, buffer);
+	elog(FATAL, "%s authentication failed for user \"%s\"",
+		 authmethod, port->user);
 }
 
 
+
 /*
- * be_recvauth -- server demux routine for incoming authentication information
+ * Client authentication starts here.  If there is an error, this
+ * function does not return and the backend process is terminated.
  */
 void
-be_recvauth(Port *port)
+ClientAuthentication(Port *port)
 {
+	int status = STATUS_ERROR;
 
 	/*
 	 * Get the authentication method to use for this frontend/database
@@ -463,97 +453,77 @@ be_recvauth(Port *port)
 	 */
 
 	if (hba_getauthmethod(port) != STATUS_OK)
-		PacketSendError(&port->pktInfo,
-						"Missing or erroneous pg_hba.conf file, see postmaster log for details");
+		elog(FATAL, "Missing or erroneous pg_hba.conf file, see postmaster log for details");
 
+	/* Handle old style authentication. */
 	else if (PG_PROTOCOL_MAJOR(port->proto) == 0)
 	{
-		/* Handle old style authentication. */
-
 		if (old_be_recvauth(port) != STATUS_OK)
 			auth_failed(port);
+		return;
 	}
-	else
-	{
-		/* Handle new style authentication. */
-
-		AuthRequest areq = AUTH_REQ_OK;
-		PacketDoneProc auth_handler = NULL;
 
-		switch (port->auth_method)
-		{
-			case uaReject:
-
-				/*
-				 * This could have come from an explicit "reject" entry in
-				 * pg_hba.conf, but more likely it means there was no
-				 * matching entry.	Take pity on the poor user and issue a
-				 * helpful error message.  NOTE: this is not a security
-				 * breach, because all the info reported here is known at
-				 * the frontend and must be assumed known to bad guys.
-				 * We're merely helping out the less clueful good guys.
-				 * NOTE 2: libpq-be.h defines the maximum error message
-				 * length as 99 characters.  It probably wouldn't hurt
-				 * anything to increase it, but there might be some client
-				 * out there that will fail.  So, be terse.
-				 */
-				{
-					char		buffer[512];
-					const char *hostinfo = "localhost";
-
-					if (port->raddr.sa.sa_family == AF_INET)
-						hostinfo = inet_ntoa(port->raddr.in.sin_addr);
-					sprintf(buffer,
-							"No pg_hba.conf entry for host %s, user %s, database %s",
-							hostinfo, port->user, port->database);
-					PacketSendError(&port->pktInfo, buffer);
-					return;
-				}
-				break;
-
-			case uaKrb4:
-				areq = AUTH_REQ_KRB4;
-				auth_handler = handle_krb4_auth;
-				break;
+	/* Handle new style authentication. */
 
-			case uaKrb5:
-				areq = AUTH_REQ_KRB5;
-				auth_handler = handle_krb5_auth;
-				break;
+	switch (port->auth_method)
+	{
+		case uaReject:
 
-			case uaTrust:
-				areq = AUTH_REQ_OK;
-				auth_handler = handle_done_auth;
-				break;
+			/*
+			 * This could have come from an explicit "reject" entry in
+			 * pg_hba.conf, but more likely it means there was no
+			 * matching entry.	Take pity on the poor user and issue a
+			 * helpful error message.  NOTE: this is not a security
+			 * breach, because all the info reported here is known at
+			 * the frontend and must be assumed known to bad guys.
+			 * We're merely helping out the less clueful good guys.
+			 */
+		{
+			const char *hostinfo = "localhost";
+
+			if (port->raddr.sa.sa_family == AF_INET)
+				hostinfo = inet_ntoa(port->raddr.in.sin_addr);
+			elog(FATAL, 
+				 "No pg_hba.conf entry for host %s, user %s, database %s",
+				 hostinfo, port->user, port->database);
+			return;
+		}
+		break;
 
-			case uaIdent:
-				if (authident(&port->raddr.in, &port->laddr.in,
-							  port->user, port->auth_arg) == STATUS_OK)
-				{
-					areq = AUTH_REQ_OK;
-					auth_handler = handle_done_auth;
-				}
+		case uaKrb4:
+			sendAuthRequest(port, AUTH_REQ_KRB4);
+			status = pg_krb4_recvauth(port);
+			break;
 
-				break;
+		case uaKrb5:
+			sendAuthRequest(port, AUTH_REQ_KRB5);
+			status = pg_krb5_recvauth(port);
+			break;
 
-			case uaPassword:
-				areq = AUTH_REQ_PASSWORD;
-				auth_handler = handle_password_auth;
-				break;
+		case uaIdent:
+			status = authident(&port->raddr.in, &port->laddr.in,
+							   port->user, port->auth_arg);
+			break;
 
-			case uaCrypt:
-				areq = AUTH_REQ_CRYPT;
-				auth_handler = handle_password_auth;
-				break;
-		}
+		case uaPassword:
+			sendAuthRequest(port, AUTH_REQ_PASSWORD);
+			status = recv_and_check_password_packet(port);
+			break;
 
-		/* Tell the frontend what we want next. */
+		case uaCrypt:
+			sendAuthRequest(port, AUTH_REQ_CRYPT);
+			status = recv_and_check_password_packet(port);
+			break;
 
-		if (auth_handler != NULL)
-			sendAuthRequest(port, areq, auth_handler);
-		else
-			auth_failed(port);
+		case uaTrust:
+			status = STATUS_OK;
+			break;
 	}
+
+	if (status == STATUS_OK)
+		sendAuthRequest(port, AUTH_REQ_OK);
+	else
+		auth_failed(port);
 }
 
 
@@ -562,134 +532,50 @@ be_recvauth(Port *port)
  */
 
 static void
-sendAuthRequest(Port *port, AuthRequest areq, PacketDoneProc handler)
+sendAuthRequest(Port *port, AuthRequest areq)
 {
-	char	   *dp,
-			   *sp;
-	int			i;
-	uint32		net_areq;
+	StringInfoData buf;
 
-	/* Convert to a byte stream. */
-
-	net_areq = htonl(areq);
-
-	dp = port->pktInfo.pkt.ar.data;
-	sp = (char *) &net_areq;
-
-	*dp++ = 'R';
-
-	for (i = 1; i <= 4; ++i)
-		*dp++ = *sp++;
+	pq_beginmessage(&buf);
+	pq_sendbyte(&buf, 'R');
+	pq_sendint(&buf, (int32) areq, sizeof(int32));
 
 	/* Add the salt for encrypted passwords. */
-
 	if (areq == AUTH_REQ_CRYPT)
 	{
-		*dp++ = port->salt[0];
-		*dp++ = port->salt[1];
-		i += 2;
+		pq_sendint(&buf, port->salt[0], 1);
+		pq_sendint(&buf, port->salt[1], 1);
 	}
 
-	PacketSendSetup(&port->pktInfo, i, handler, (void *) port);
-}
-
-
-/*
- * Called when we have told the front end that it is authorised.
- */
-
-static int
-handle_done_auth(void *arg, PacketLen len, void *pkt)
-{
-
-	/*
-	 * Don't generate any more traffic.  This will cause the backend to
-	 * start.
-	 */
-
-	return STATUS_OK;
-}
-
-
-/*
- * Called when we have told the front end that it should use Kerberos V4
- * authentication.
- */
-
-static int
-handle_krb4_auth(void *arg, PacketLen len, void *pkt)
-{
-	Port	   *port = (Port *) arg;
-
-	if (pg_krb4_recvauth(port) != STATUS_OK)
-		auth_failed(port);
-	else
-		sendAuthRequest(port, AUTH_REQ_OK, handle_done_auth);
-
-	return STATUS_OK;
-}
-
-
-/*
- * Called when we have told the front end that it should use Kerberos V5
- * authentication.
- */
-
-static int
-handle_krb5_auth(void *arg, PacketLen len, void *pkt)
-{
-	Port	   *port = (Port *) arg;
-
-	if (pg_krb5_recvauth(port) != STATUS_OK)
-		auth_failed(port);
-	else
-		sendAuthRequest(port, AUTH_REQ_OK, handle_done_auth);
-
-	return STATUS_OK;
+	pq_endmessage(&buf);
+	pq_flush();
 }
 
 
-/*
- * Called when we have told the front end that it should use password
- * authentication.
- */
-
-static int
-handle_password_auth(void *arg, PacketLen len, void *pkt)
-{
-	Port	   *port = (Port *) arg;
-
-	/* Set up the read of the password packet. */
-
-	PacketReceiveSetup(&port->pktInfo, readPasswordPacket, (void *) port);
-
-	return STATUS_OK;
-}
-
 
 /*
  * Called when we have received the password packet.
  */
 
 static int
-readPasswordPacket(void *arg, PacketLen len, void *pkt)
+recv_and_check_password_packet(Port *port)
 {
-	char		password[sizeof(PasswordPacket) + 1];
-	Port	   *port = (Port *) arg;
-
-	/* Silently truncate a password that is too big. */
-
-	if (len > sizeof(PasswordPacket))
-		len = sizeof(PasswordPacket);
-
-	StrNCpy(password, ((PasswordPacket *) pkt)->passwd, len);
-
-	if (checkPassword(port, port->user, password) != STATUS_OK)
-		auth_failed(port);
-	else
-		sendAuthRequest(port, AUTH_REQ_OK, handle_done_auth);
-
-	return STATUS_OK;			/* don't close the connection yet */
+	StringInfoData buf;
+	int32		len;
+	int			result;
+
+	if (pq_getint(&len, 4) == EOF)
+		return STATUS_ERROR;	/* client didn't want to send password */
+	initStringInfo(&buf);
+	pq_getstr(&buf);
+
+	if (DebugLvl)
+		fprintf(stderr, "received password packet with len=%d, pw=%s\n",
+				len, buf.data);
+
+	result = checkPassword(port, port->user, buf.data);
+	pfree(buf.data);
+	return result;
 }
 
 
@@ -734,10 +620,8 @@ old_be_recvauth(Port *port)
 			break;
 
 		case STARTUP_PASSWORD_MSG:
-			PacketReceiveSetup(&port->pktInfo, pg_passwordv0_recvauth,
-							   (void *) port);
-
-			return STATUS_OK;
+			status = recv_and_check_passwordv0(port);
+			break;
 
 		default:
 			fprintf(stderr, "Invalid startup message type: %u\n", msgtype);
@@ -760,8 +644,8 @@ map_old_to_new(Port *port, UserAuth old, int status)
 {
 	switch (port->auth_method)
 	{
-			case uaCrypt:
-			case uaReject:
+		case uaCrypt:
+		case uaReject:
 			status = STATUS_ERROR;
 			break;
 
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index f1a0bd074479d7a7387419dea67799c5b6bb8fe0..d6cbaf34b59fc2c91972e2f76db82ec7a9d8f0dd 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -28,7 +28,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.223 2001/06/19 23:40:10 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.224 2001/06/20 18:07:55 petere Exp $
  *
  * NOTES
  *
@@ -116,16 +116,13 @@ int			UnBlockSig,
  */
 typedef struct bkend
 {
-	int			pid;			/* process id of backend */
+	pid_t		pid;			/* process id of backend */
 	long		cancel_key;		/* cancel key for cancels for this backend */
 } Backend;
 
 /* list of active backends.  For garbage collection only now. */
 static Dllist *BackendList;
 
-/* list of ports associated with still open, but incomplete connections */
-static Dllist *PortList;
-
 /* The socket number we are listening for connections on */
 int			PostPortNumber;
 char	   *UnixSocketDir;
@@ -221,21 +218,20 @@ extern int	optreset;
 static void pmdaemonize(int argc, char *argv[]);
 static Port *ConnCreate(int serverFd);
 static void ConnFree(Port *port);
-static void ClosePostmasterPorts(Port *myConn);
+static void ClosePostmasterPorts(void);
 static void reset_shared(unsigned short port);
 static void SIGHUP_handler(SIGNAL_ARGS);
 static void pmdie(SIGNAL_ARGS);
 static void reaper(SIGNAL_ARGS);
 static void schedule_checkpoint(SIGNAL_ARGS);
-static void dumpstatus(SIGNAL_ARGS);
 static void CleanupProc(int pid, int exitstatus);
 static int	DoBackend(Port *port);
 static void ExitPostmaster(int status);
 static void usage(const char *);
 static int	ServerLoop(void);
 static int	BackendStartup(Port *port);
-static int	readStartupPacket(void *arg, PacketLen len, void *pkt);
-static int	processCancelRequest(Port *port, PacketLen len, void *pkt);
+static int	ProcessStartupPacket(Port *port);
+static void	processCancelRequest(Port *port, void *pkt);
 static int	initMasks(fd_set *rmask, fd_set *wmask);
 static char *canAcceptConnections(void);
 static long PostmasterRandom(void);
@@ -661,7 +657,6 @@ PostmasterMain(int argc, char *argv[])
 	 * garbage collecting the backend processes.
 	 */
 	BackendList = DLNewList();
-	PortList = DLNewList();
 
 	/*
 	 * Record postmaster options.  We delay this till now to avoid
@@ -690,7 +685,6 @@ PostmasterMain(int argc, char *argv[])
 	pqsignal(SIGCHLD, reaper);	/* handle child termination */
 	pqsignal(SIGTTIN, SIG_IGN); /* ignored */
 	pqsignal(SIGTTOU, SIG_IGN); /* ignored */
-	pqsignal(SIGWINCH, dumpstatus);		/* dump port status */
 
 	/*
 	 * We're ready to rock and roll...
@@ -794,7 +788,6 @@ ServerLoop(void)
 	fd_set		readmask,
 				writemask;
 	int			nSockets;
-	Dlelem	   *curr;
 	struct timeval now,
 				later;
 	struct timezone tz;
@@ -841,27 +834,6 @@ ServerLoop(void)
 			}
 		}
 
-#ifdef USE_SSL
-
-		/*
-		 * If we are using SSL, there may be input data already read and
-		 * pending in SSL's input buffers.  If so, check for additional
-		 * input from other clients, but don't delay before processing.
-		 */
-		for (curr = DLGetHead(PortList); curr; curr = DLGetSucc(curr))
-		{
-			Port	   *port = (Port *) DLE_VAL(curr);
-
-			if (port->ssl && SSL_pending(port->ssl))
-			{
-				timeout_tv.tv_sec = 0;
-				timeout_tv.tv_usec = 0;
-				timeout = &timeout_tv;
-				break;
-			}
-		}
-#endif
-
 		/*
 		 * Wait for something to happen.
 		 */
@@ -915,126 +887,26 @@ ServerLoop(void)
 		 */
 
 #ifdef HAVE_UNIX_SOCKETS
-		if (ServerSock_UNIX != INVALID_SOCK &&
-			FD_ISSET(ServerSock_UNIX, &rmask) &&
-			(port = ConnCreate(ServerSock_UNIX)) != NULL)
+		if (ServerSock_UNIX != INVALID_SOCK
+			&& FD_ISSET(ServerSock_UNIX, &rmask))
 		{
-			PacketReceiveSetup(&port->pktInfo,
-							   readStartupPacket,
-							   (void *) port);
+			port = ConnCreate(ServerSock_UNIX);
+			if (port)
+				BackendStartup(port);
+			StreamClose(port->sock);
+			ConnFree(port);
 		}
 #endif
 
-		if (ServerSock_INET != INVALID_SOCK &&
-			FD_ISSET(ServerSock_INET, &rmask) &&
-			(port = ConnCreate(ServerSock_INET)) != NULL)
+		if (ServerSock_INET != INVALID_SOCK
+			&& FD_ISSET(ServerSock_INET, &rmask))
 		{
-			PacketReceiveSetup(&port->pktInfo,
-							   readStartupPacket,
-							   (void *) port);
+			port = ConnCreate(ServerSock_INET);
+			if (port)
+				BackendStartup(port);
+			StreamClose(port->sock);
+			ConnFree(port);
 		}
-
-		/*
-		 * Scan active ports, processing any available input.  While we
-		 * are at it, build up new masks for next select().
-		 */
-		nSockets = initMasks(&readmask, &writemask);
-
-		curr = DLGetHead(PortList);
-
-		while (curr)
-		{
-			Port	   *port = (Port *) DLE_VAL(curr);
-			int			status = STATUS_OK;
-			Dlelem	   *next;
-
-			if (FD_ISSET(port->sock, &rmask)
-#ifdef USE_SSL
-				|| (port->ssl && SSL_pending(port->ssl))
-#endif
-				)
-			{
-				if (DebugLvl > 1)
-					postmaster_error("ServerLoop: handling reading %d", port->sock);
-
-				if (PacketReceiveFragment(port) != STATUS_OK)
-					status = STATUS_ERROR;
-			}
-
-			if (FD_ISSET(port->sock, &wmask))
-			{
-				if (DebugLvl > 1)
-					postmaster_error("ServerLoop: handling writing %d", port->sock);
-
-				if (PacketSendFragment(port) != STATUS_OK)
-					status = STATUS_ERROR;
-			}
-
-			/* Get this before the connection might be closed. */
-
-			next = DLGetSucc(curr);
-
-			/*
-			 * If there is no error and no outstanding data transfer going
-			 * on, then the authentication handshake must be complete to
-			 * the postmaster's satisfaction.  So, start the backend.
-			 */
-
-			if (status == STATUS_OK && port->pktInfo.state == Idle)
-			{
-
-				/*
-				 * Can we accept a connection now?
-				 *
-				 * Even though readStartupPacket() already checked, we have
-				 * to check again in case conditions changed while
-				 * negotiating authentication.
-				 */
-				char	   *rejectMsg = canAcceptConnections();
-
-				if (rejectMsg != NULL)
-					PacketSendError(&port->pktInfo, rejectMsg);
-				else
-				{
-
-					/*
-					 * If the backend start fails then keep the connection
-					 * open to report it.  Otherwise, pretend there is an
-					 * error to close our descriptor for the connection,
-					 * which will now be managed by the backend.
-					 */
-					if (BackendStartup(port) != STATUS_OK)
-						PacketSendError(&port->pktInfo,
-										"Backend startup failed");
-					else
-						status = STATUS_ERROR;
-				}
-			}
-
-			/* Close the connection if required. */
-
-			if (status != STATUS_OK)
-			{
-				StreamClose(port->sock);
-				DLRemove(curr);
-				ConnFree(port);
-				DLFreeElem(curr);
-			}
-			else
-			{
-				/* Set the masks for this connection. */
-
-				if (nSockets <= port->sock)
-					nSockets = port->sock + 1;
-
-				if (port->pktInfo.state == WritingPacket)
-					FD_SET(port->sock, &writemask);
-				else
-					FD_SET(port->sock, &readmask);
-			}
-
-			curr = next;
-		}						/* loop over active ports */
 	}
 }
 
@@ -1074,28 +946,42 @@ initMasks(fd_set *rmask, fd_set *wmask)
 
 
 /*
- * Called when the startup packet has been read.
+ * Read the startup packet and do something according to it.
+ *
+ * Returns STATUS_OK or STATUS_ERROR, or might call elog(FATAL) and
+ * not return at all.
  */
-
 static int
-readStartupPacket(void *arg, PacketLen len, void *pkt)
+ProcessStartupPacket(Port *port)
 {
-	Port	   *port;
-	StartupPacket *si;
+	StartupPacket *packet;
 	char	   *rejectMsg;
+	int32		len;
+	void	   *buf;
 
-	port = (Port *) arg;
-	si = (StartupPacket *) pkt;
+	pq_getbytes((char *)&len, 4);
+	len = ntohl(len);
+	len -= 4;
+
+	if (len < sizeof(len) || len > sizeof(len) + sizeof(StartupPacket))
+		elog(FATAL, "invalid length of startup packet");
+
+	buf = palloc(len);
+	pq_getbytes(buf, len);
+	
+	packet = buf;
 
 	/*
 	 * The first field is either a protocol version number or a special
 	 * request code.
 	 */
-
-	port->proto = ntohl(si->protoVersion);
+	port->proto = ntohl(packet->protoVersion);
 
 	if (port->proto == CANCEL_REQUEST_CODE)
-		return processCancelRequest(port, len, pkt);
+	{
+		processCancelRequest(port, packet);
+		return 127;				/* XXX */
+	}
 
 	if (port->proto == NEGOTIATE_SSL_CODE)
 	{
@@ -1114,7 +1000,7 @@ readStartupPacket(void *arg, PacketLen len, void *pkt)
 		{
 			postmaster_error("failed to send SSL negotiation response: %s",
 							 strerror(errno));
-			return STATUS_ERROR;/* Close connection */
+			return STATUS_ERROR; /* close the connection */
 		}
 
 #ifdef USE_SSL
@@ -1130,11 +1016,10 @@ readStartupPacket(void *arg, PacketLen len, void *pkt)
 			}
 		}
 #endif
-		/* ready for the normal startup packet */
-		PacketReceiveSetup(&port->pktInfo,
-						   readStartupPacket,
-						   (void *) port);
-		return STATUS_OK;		/* Do not close connection */
+		/* regular startup packet should follow... */
+		/* FIXME: by continuing to send SSL negotiation packets, a
+           client could run us out of stack space */
+		return ProcessStartupPacket(port);
 	}
 
 	/* Could add additional special packet types here */
@@ -1146,46 +1031,35 @@ readStartupPacket(void *arg, PacketLen len, void *pkt)
 		PG_PROTOCOL_MAJOR(port->proto) > PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST) ||
 		(PG_PROTOCOL_MAJOR(port->proto) == PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST) &&
 		 PG_PROTOCOL_MINOR(port->proto) > PG_PROTOCOL_MINOR(PG_PROTOCOL_LATEST)))
-	{
-		PacketSendError(&port->pktInfo, "Unsupported frontend protocol.");
-		return STATUS_OK;		/* don't close the connection yet */
-	}
+		elog(FATAL, "unsupported frontend protocol");
 
 	/*
 	 * Get the parameters from the startup packet as C strings.  The
 	 * packet destination was cleared first so a short packet has zeros
 	 * silently added and a long packet is silently truncated.
 	 */
-
-	StrNCpy(port->database, si->database, sizeof(port->database));
-	StrNCpy(port->user, si->user, sizeof(port->user));
-	StrNCpy(port->options, si->options, sizeof(port->options));
-	StrNCpy(port->tty, si->tty, sizeof(port->tty));
+	StrNCpy(port->database, packet->database, sizeof(port->database));
+	StrNCpy(port->user, packet->user, sizeof(port->user));
+	StrNCpy(port->options, packet->options, sizeof(port->options));
+	StrNCpy(port->tty, packet->tty, sizeof(port->tty));
 
 	/* The database defaults to the user name. */
-
 	if (port->database[0] == '\0')
-		StrNCpy(port->database, si->user, sizeof(port->database));
+		StrNCpy(port->database, packet->user, sizeof(port->database));
 
 	/*
 	 * Truncate given database and user names to length of a Postgres
-	 * name.
+	 * name.  This avoids lookup failures when overlength names are
+	 * given.
 	 */
-	/* This avoids lookup failures when overlength names are given. */
-
 	if ((int) sizeof(port->database) >= NAMEDATALEN)
 		port->database[NAMEDATALEN - 1] = '\0';
 	if ((int) sizeof(port->user) >= NAMEDATALEN)
 		port->user[NAMEDATALEN - 1] = '\0';
 
 	/* Check a user name was given. */
-
 	if (port->user[0] == '\0')
-	{
-		PacketSendError(&port->pktInfo,
-					"No Postgres username specified in startup packet.");
-		return STATUS_OK;		/* don't close the connection yet */
-	}
+		elog(FATAL, "no PostgreSQL user name specified in startup packet");
 
 	/*
 	 * If we're going to reject the connection due to database state, say
@@ -1195,27 +1069,19 @@ readStartupPacket(void *arg, PacketLen len, void *pkt)
 	rejectMsg = canAcceptConnections();
 
 	if (rejectMsg != NULL)
-	{
-		PacketSendError(&port->pktInfo, rejectMsg);
-		return STATUS_OK;		/* don't close the connection yet */
-	}
+		elog(FATAL, "%s", rejectMsg);
 
-	/* Start the authentication itself. */
-
-	be_recvauth(port);
-
-	return STATUS_OK;			/* don't close the connection yet */
+	return STATUS_OK;
 }
 
+
 /*
  * The client has sent a cancel request packet, not a normal
- * start-a-new-backend packet.	Perform the necessary processing.
- * Note that in any case, we return STATUS_ERROR to close the
- * connection immediately.	Nothing is sent back to the client.
+ * start-a-new-connection packet.  Perform the necessary processing.
+ * Nothing is sent back to the client.
  */
-
-static int
-processCancelRequest(Port *port, PacketLen len, void *pkt)
+static void
+processCancelRequest(Port *port, void *pkt)
 {
 	CancelRequestPacket *canc = (CancelRequestPacket *) pkt;
 	int			backendPID;
@@ -1230,7 +1096,7 @@ processCancelRequest(Port *port, PacketLen len, void *pkt)
 	{
 		if (DebugLvl)
 			postmaster_error("processCancelRequest: CheckPointPID in cancel request for process %d", backendPID);
-		return STATUS_ERROR;
+		return;
 	}
 
 	/* See if we have a matching backend */
@@ -1244,24 +1110,24 @@ processCancelRequest(Port *port, PacketLen len, void *pkt)
 			{
 				/* Found a match; signal that backend to cancel current op */
 				if (DebugLvl)
-					postmaster_error("processCancelRequest: sending SIGINT to process %d", bp->pid);
+					elog(DEBUG, "processing cancel request: sending SIGINT to process %d",
+						 backendPID);
 				kill(bp->pid, SIGINT);
 			}
 			else
 			{
 				/* Right PID, wrong key: no way, Jose */
 				if (DebugLvl)
-					postmaster_error("processCancelRequest: bad key in cancel request for process %d", bp->pid);
+					elog(DEBUG, "bad key in cancel request for process %d",
+						 backendPID);
 			}
-			return STATUS_ERROR;
+			return;
 		}
 	}
 
 	/* No matching backend */
 	if (DebugLvl)
-		postmaster_error("processCancelRequest: bad PID in cancel request for process %d", backendPID);
-
-	return STATUS_ERROR;
+		elog(DEBUG, "bad pid in cancel request for process %d", backendPID);
 }
 
 /*
@@ -1295,6 +1161,7 @@ canAcceptConnections(void)
 	return NULL;
 }
 
+
 /*
  * ConnCreate -- create a local connection data structure
  */
@@ -1318,7 +1185,6 @@ ConnCreate(int serverFd)
 	}
 	else
 	{
-		DLAddHead(PortList, DLNewElem(port));
 		RandomSalt(port->salt);
 		port->pktInfo.state = Idle;
 	}
@@ -1326,6 +1192,7 @@ ConnCreate(int serverFd)
 	return port;
 }
 
+
 /*
  * ConnFree -- free a local connection data structure
  */
@@ -1339,22 +1206,20 @@ ConnFree(Port *conn)
 	free(conn);
 }
 
+
 /*
  * ClosePostmasterPorts -- close all the postmaster's open sockets
  *
  * This is called during child process startup to release file descriptors
- * that are not needed by that child process.  All descriptors other than
- * the one for myConn (if it's not null) are closed.
+ * that are not needed by that child process.
  *
  * Note that closing the child's descriptor does not destroy the client
  * connection prematurely, since the parent (postmaster) process still
  * has the socket open.
  */
 static void
-ClosePostmasterPorts(Port *myConn)
+ClosePostmasterPorts(void)
 {
-	Dlelem	   *curr;
-
 	/* Close the listen sockets */
 	if (NetServer)
 		StreamClose(ServerSock_INET);
@@ -1363,25 +1228,6 @@ ClosePostmasterPorts(Port *myConn)
 	StreamClose(ServerSock_UNIX);
 	ServerSock_UNIX = INVALID_SOCK;
 #endif
-
-	/* Close any sockets for other clients, and release memory too */
-	curr = DLGetHead(PortList);
-
-	while (curr)
-	{
-		Port	   *port = (Port *) DLE_VAL(curr);
-		Dlelem	   *next = DLGetSucc(curr);
-
-		if (port != myConn)
-		{
-			StreamClose(port->sock);
-			DLRemove(curr);
-			ConnFree(port);
-			DLFreeElem(curr);
-		}
-
-		curr = next;
-	}
 }
 
 
@@ -1847,7 +1693,7 @@ static int
 BackendStartup(Port *port)
 {
 	Backend    *bn;				/* for backend cleanup */
-	int			pid;
+	pid_t		pid;
 
 	/*
 	 * Compute the cancel key that will be assigned to this backend. The
@@ -1872,42 +1718,45 @@ BackendStartup(Port *port)
 	beos_before_backend_startup();
 #endif
 
-	if ((pid = fork()) == 0)
-	{							/* child */
+	/*
+	 * Make room for backend data structure.  Better before the fork()
+	 * so we can handle failure cleanly.
+	 */
+	bn = (Backend *) malloc(sizeof(Backend));
+	if (!bn)
+	{
+		fprintf(stderr, gettext("%s: BackendStartup: malloc failed\n"),
+				progname);
+		return STATUS_ERROR;
+	}
+
+	pid = fork();
+
+	if (pid == 0)				/* child */
+	{
+		int		status;
+
+		free(bn);
 #ifdef __BEOS__
 		/* Specific beos backend startup actions */
 		beos_backend_startup();
 #endif
 
-#ifdef CYR_RECODE
-		{
-			/* Save charset for this host while we still have client addr */
-			char		ChTable[80];
-			static char cyrEnvironment[100];
-
-			GetCharSetByHost(ChTable, port->raddr.in.sin_addr.s_addr, DataDir);
-			if (*ChTable != '\0')
-			{
-				snprintf(cyrEnvironment, sizeof(cyrEnvironment),
-						 "PG_RECODETABLE=%s", ChTable);
-				putenv(cyrEnvironment);
-			}
-		}
-#endif
-
-		if (DoBackend(port))
+		status = DoBackend(port);
+		if (status != 0)
 		{
 			fprintf(stderr, gettext("%s child[%d]: BackendStartup: backend startup failed\n"),
 					progname, (int) getpid());
-			ExitPostmaster(1);
+			proc_exit(status);
 		}
 		else
-			ExitPostmaster(0);
+			proc_exit(0);
 	}
 
-	/* in parent */
+	/* in parent, error */
 	if (pid < 0)
 	{
+		free(bn);
 #ifdef __BEOS__
 		/* Specific beos backend startup actions */
 		beos_backend_startup_failed();
@@ -1917,8 +1766,9 @@ BackendStartup(Port *port)
 		return STATUS_ERROR;
 	}
 
-	if (DebugLvl)
-		fprintf(stderr, gettext("%s: BackendStartup: pid %d user %s db %s socket %d\n"),
+	/* in parent, normal */
+	if (DebugLvl >= 1)
+		fprintf(stderr, gettext("%s: BackendStartup: pid=%d user=%s db=%s socket=%d\n"),
 				progname, pid, port->user, port->database,
 				port->sock);
 
@@ -1926,13 +1776,6 @@ BackendStartup(Port *port)
 	 * Everything's been successful, it's safe to add this backend to our
 	 * list of backends.
 	 */
-	if (!(bn = (Backend *) calloc(1, sizeof(Backend))))
-	{
-		fprintf(stderr, gettext("%s: BackendStartup: malloc failed\n"),
-				progname);
-		ExitPostmaster(1);
-	}
-
 	bn->pid = pid;
 	bn->cancel_key = MyCancelKey;
 	DLAddHead(BackendList, DLNewElem(bn));
@@ -1940,6 +1783,7 @@ BackendStartup(Port *port)
 	return STATUS_OK;
 }
 
+
 /*
  * split_opts -- split a string of options and append it to an argv array
  *
@@ -1990,6 +1834,7 @@ DoBackend(Port *port)
 	char		optbuf[ARGV_SIZE];
 	char		ttybuf[ARGV_SIZE];
 	int			i;
+	int			status;
 	struct timeval now;
 	struct timezone tz;
 
@@ -2004,14 +1849,22 @@ DoBackend(Port *port)
 	 * Signal handlers setting is moved to tcop/postgres...
 	 */
 
+	SetProcessingMode(InitProcessing);
+
 	/* Save port etc. for ps status */
 	MyProcPort = port;
 
 	/* Reset MyProcPid to new backend's pid */
 	MyProcPid = getpid();
 
+	whereToSendOutput = Remote;
+
+	status = ProcessStartupPacket(port);
+	if (status == 127)
+		return 0;				/* cancel request processed */
+
 	/* Close the postmaster's other sockets */
-	ClosePostmasterPorts(port);
+	ClosePostmasterPorts();
 
 	/*
 	 * Don't want backend to be able to see the postmaster random number
@@ -2162,26 +2015,6 @@ schedule_checkpoint(SIGNAL_ARGS)
 	errno = save_errno;
 }
 
-static void
-dumpstatus(SIGNAL_ARGS)
-{
-	int			save_errno = errno;
-	Dlelem	   *curr;
-
-	PG_SETMASK(&BlockSig);
-
-	fprintf(stderr, "%s: dumpstatus:\n", progname);
-
-	curr = DLGetHead(PortList);
-	while (curr)
-	{
-		Port	   *port = DLE_VAL(curr);
-
-		fprintf(stderr, "\tsock %d\n", port->sock);
-		curr = DLGetSucc(curr);
-	}
-	errno = save_errno;
-}
 
 /*
  * CharRemap
@@ -2336,7 +2169,7 @@ SSDataBase(int xlop)
 		on_exit_reset();
 
 		/* Close the postmaster's sockets */
-		ClosePostmasterPorts(NULL);
+		ClosePostmasterPorts();
 
 		/* Set up command-line arguments for subprocess */
 		av[ac++] = "postgres";
@@ -2463,7 +2296,7 @@ postmaster_error(const char *fmt, ...)
 
 	fprintf(stderr, "%s: ", progname);
 	va_start(ap, fmt);
-	fprintf(stderr, gettext(fmt), ap);
+	vfprintf(stderr, gettext(fmt), ap);
 	va_end(ap);
 	fprintf(stderr, "\n");
 }
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2692053a39df9118fa03451fff937a726cf27399..476c2f72c3ae5df777a7440f7d8f56527878e052 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.222 2001/06/19 23:40:10 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.223 2001/06/20 18:07:55 petere Exp $
  *
  * NOTES
  *	  this is the "main" module of the postgres backend and
@@ -45,6 +45,7 @@
 #include "libpq/pqformat.h"
 #include "libpq/pqsignal.h"
 #include "miscadmin.h"
+#include "libpq/auth.h"
 #include "nodes/print.h"
 #include "optimizer/cost.h"
 #include "optimizer/planner.h"
@@ -1142,11 +1143,13 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
 	 */
 	if (!IsUnderPostmaster)
 	{
+		SetProcessingMode(InitProcessing);
 		EnableExceptionHandling(true);
 		MemoryContextInit();
 	}
 
-	SetProcessingMode(InitProcessing);
+	if (IsUnderPostmaster)
+		ClientAuthentication(MyProcPort); /* might not return */
 
 	/*
 	 * Set default values for command-line options.
@@ -1567,13 +1570,11 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
 								 * restart... */
 		}
 		pq_init();				/* initialize libpq at backend startup */
-		whereToSendOutput = Remote;
 		BaseInit();
 	}
 	else
 	{
 		/* interactive case: database name can be last arg on command line */
-		whereToSendOutput = Debug;
 		if (errs || argc - optind > 1)
 		{
 			fprintf(stderr, "%s: invalid command line arguments\nTry -? for help.\n", argv[0]);
@@ -1709,7 +1710,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
 	if (!IsUnderPostmaster)
 	{
 		puts("\nPOSTGRES backend interactive interface ");
-		puts("$Revision: 1.222 $ $Date: 2001/06/19 23:40:10 $\n");
+		puts("$Revision: 1.223 $ $Date: 2001/06/20 18:07:55 $\n");
 	}
 
 	/*
diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
index e2ffb7bc825abbce04b96993559755541fd6a6ea..2a41d3b57fdfb96bb537158836d0ad1d63caf88d 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/error/elog.c,v 1.86 2001/06/08 21:16:48 petere Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/error/elog.c,v 1.87 2001/06/20 18:07:56 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -129,10 +129,6 @@ elog(int lev, const char *fmt,...)
 	/* size of the prefix needed for timestamp and pid, if enabled */
 	size_t		timestamp_size;
 
-	/* ignore debug msgs if noplace to send */
-	if (lev == DEBUG && Debugfile < 0)
-		return;
-
 	/* Save error str before calling any function that might change errno */
 	errorstr = useful_strerror(errno);
 
@@ -336,10 +332,9 @@ elog(int lev, const char *fmt,...)
 	/* syslog doesn't want a trailing newline, but other destinations do */
 	strcat(msg_buf, "\n");
 
-	/* Write to debug file, if open and enabled */
-	/* NOTE: debug file is typically pointed at stderr */
-	if (Debugfile >= 0 && Use_syslog <= 1)
-		write(Debugfile, msg_buf, strlen(msg_buf));
+	/* write to terminal */
+	if (Use_syslog <= 1 || whereToSendOutput == Debug)
+		write(2, msg_buf, strlen(msg_buf));
 
 	if (lev > DEBUG && whereToSendOutput == Remote)
 	{
@@ -371,17 +366,6 @@ elog(int lev, const char *fmt,...)
 		MemoryContextSwitchTo(oldcxt);
 	}
 
-	if (lev > DEBUG && whereToSendOutput != Remote)
-	{
-		/*
-		 * We are running as an interactive backend, so just send the
-		 * message to stderr.  But don't send a duplicate if Debugfile
-		 * write, above, already sent to stderr.
-		 */
-		if (Debugfile != fileno(stderr))
-			fputs(msg_buf, stderr);
-	}
-
 	/* done with the message, release space */
 	if (fmt_buf != fmt_fixedbuf)
 		free(fmt_buf);
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index df46469f0007eefed292958ba8ef8e8d6d66b86e..4f2b940b7eaa4f84626c3175371d5ecd2e25d11a 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.71 2001/06/14 01:09:22 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.72 2001/06/20 18:07:56 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -28,6 +28,7 @@
 
 #include "catalog/catname.h"
 #include "catalog/pg_shadow.h"
+#include "libpq/libpq-be.h"
 #include "miscadmin.h"
 #include "utils/builtins.h"
 #include "utils/lsyscache.h"
@@ -279,6 +280,7 @@ SetCharSet()
 	int			i;
 	unsigned char FromChar,
 				ToChar;
+	char		ChTable[80];
 
 	for (i = 0; i < 128; i++)
 	{
@@ -286,11 +288,17 @@ SetCharSet()
 		RecodeBackTable[i] = i + 128;
 	}
 
-	p = getenv("PG_RECODETABLE");
+	if (IsUnderPostmaster)
+	{
+		GetCharSetByHost(ChTable, MyProcPort->raddr.in.sin_addr.s_addr, DataDir);
+		p = ChTable;
+	}
+	else
+		p = getenv("PG_RECODETABLE");
+
 	if (p && *p != '\0')
 	{
-		map_file = (char *) malloc((strlen(DataDir) +
-									strlen(p) + 2) * sizeof(char));
+		map_file = malloc(strlen(DataDir) +	strlen(p) + 2);
 		if (! map_file)
 			elog(FATAL, "out of memory");
 		sprintf(map_file, "%s/%s", DataDir, p);
diff --git a/src/include/libpq/auth.h b/src/include/libpq/auth.h
index 649823f0e76804bd371af87859641628c92c663c..df973df555efc8fd21e069829294776debcf4e14 100644
--- a/src/include/libpq/auth.h
+++ b/src/include/libpq/auth.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: auth.h,v 1.16 2001/03/22 04:00:47 momjian Exp $
+ * $Id: auth.h,v 1.17 2001/06/20 18:07:56 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -21,7 +21,7 @@
  *----------------------------------------------------------------
  */
 
-void		be_recvauth(Port *port);
+void		ClientAuthentication(Port *port);
 
 #define PG_KRB4_VERSION "PGVER4.1"		/* at most KRB_SENDAUTH_VLEN chars */
 #define PG_KRB5_VERSION "PGVER5.1"