Commit 9b4bfbdc authored by Peter Eisentraut's avatar Peter Eisentraut

Handle reading of startup packet and authentication exchange after forking

a new postmaster child process.  This should eliminate problems with
authentication blocking (e.g., ident, SSL init) and also reduce problems
with the accept queue filling up under heavy load.

The option to send elog output to a different file per backend (postgres -o)
has been disabled for now because the initialization would have to happen
in a different order and it's not clear we want to keep this anyway.
parent 588463a4
...@@ -8,48 +8,34 @@ ...@@ -8,48 +8,34 @@
* *
* *
* IDENTIFICATION * 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 #include "postgres.h"
*
* 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 <sys/types.h> /* needed by in.h on Ultrix */ #include <sys/types.h> /* needed by in.h on Ultrix */
#include <netinet/in.h> #include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include "postgres.h"
#include "libpq/auth.h" #include "libpq/auth.h"
#include "libpq/crypt.h" #include "libpq/crypt.h"
#include "libpq/hba.h" #include "libpq/hba.h"
#include "libpq/libpq.h" #include "libpq/libpq.h"
#include "libpq/password.h" #include "libpq/password.h"
#include "libpq/pqformat.h"
#include "miscadmin.h" #include "miscadmin.h"
static void sendAuthRequest(Port *port, AuthRequest areq, PacketDoneProc handler); static void sendAuthRequest(Port *port, AuthRequest areq);
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 int checkPassword(Port *port, char *user, char *password); static int checkPassword(Port *port, char *user, char *password);
static int old_be_recvauth(Port *port); static int old_be_recvauth(Port *port);
static int map_old_to_new(Port *port, UserAuth old, int status); static int map_old_to_new(Port *port, UserAuth old, int status);
static void auth_failed(Port *port); 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; char *pg_krb_server_keyfile;
...@@ -325,25 +311,28 @@ pg_krb5_recvauth(Port *port) ...@@ -325,25 +311,28 @@ pg_krb5_recvauth(Port *port)
/* /*
* Handle a v0 password packet. * Handle a v0 password packet.
*/ */
static int 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; PasswordPacketV0 *pp;
char *user, char *user,
*password, *password,
*cp, *cp,
*start; *start;
port = (Port *) arg; pq_getint(&len, 4);
pp = (PasswordPacketV0 *) pkt; len -= 4;
buf = palloc(len);
pq_getbytes(buf, len);
pp = (PasswordPacketV0 *) buf;
/* /*
* The packet is supposed to comprise the user name and the password * The packet is supposed to comprise the user name and the password
* as C strings. Be careful the check that this is the case. * as C strings. Be careful the check that this is the case.
*/ */
user = password = NULL; user = password = NULL;
len -= sizeof(pp->unused); len -= sizeof(pp->unused);
...@@ -371,6 +360,7 @@ pg_passwordv0_recvauth(void *arg, PacketLen len, void *pkt) ...@@ -371,6 +360,7 @@ pg_passwordv0_recvauth(void *arg, PacketLen len, void *pkt)
fputs(PQerrormsg, stderr); fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg); pqdebug("%s", PQerrormsg);
pfree(buf);
auth_failed(port); auth_failed(port);
} }
else else
...@@ -385,15 +375,15 @@ pg_passwordv0_recvauth(void *arg, PacketLen len, void *pkt) ...@@ -385,15 +375,15 @@ pg_passwordv0_recvauth(void *arg, PacketLen len, void *pkt)
status = checkPassword(port, user, password); status = checkPassword(port, user, password);
pfree(buf);
port->auth_method = saved; port->auth_method = saved;
/* Adjust the result if necessary. */ /* Adjust the result if necessary. */
if (map_old_to_new(port, uaPassword, status) != STATUS_OK) if (map_old_to_new(port, uaPassword, status) != STATUS_OK)
auth_failed(port); 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) ...@@ -413,7 +403,6 @@ pg_passwordv0_recvauth(void *arg, PacketLen len, void *pkt)
static void static void
auth_failed(Port *port) auth_failed(Port *port)
{ {
char buffer[512];
const char *authmethod = "Unknown auth method:"; const char *authmethod = "Unknown auth method:";
switch (port->auth_method) switch (port->auth_method)
...@@ -441,19 +430,20 @@ auth_failed(Port *port) ...@@ -441,19 +430,20 @@ auth_failed(Port *port)
break; break;
} }
sprintf(buffer, "%s authentication failed for user '%s'", elog(FATAL, "%s authentication failed for user \"%s\"",
authmethod, port->user); authmethod, port->user);
PacketSendError(&port->pktInfo, buffer);
} }
/* /*
* 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 void
be_recvauth(Port *port) ClientAuthentication(Port *port)
{ {
int status = STATUS_ERROR;
/* /*
* Get the authentication method to use for this frontend/database * Get the authentication method to use for this frontend/database
...@@ -463,97 +453,77 @@ be_recvauth(Port *port) ...@@ -463,97 +453,77 @@ be_recvauth(Port *port)
*/ */
if (hba_getauthmethod(port) != STATUS_OK) if (hba_getauthmethod(port) != STATUS_OK)
PacketSendError(&port->pktInfo, elog(FATAL, "Missing or erroneous pg_hba.conf file, see postmaster log for details");
"Missing or erroneous pg_hba.conf file, see postmaster log for details");
/* Handle old style authentication. */
else if (PG_PROTOCOL_MAJOR(port->proto) == 0) else if (PG_PROTOCOL_MAJOR(port->proto) == 0)
{ {
/* Handle old style authentication. */
if (old_be_recvauth(port) != STATUS_OK) if (old_be_recvauth(port) != STATUS_OK)
auth_failed(port); auth_failed(port);
return;
} }
else
{
/* Handle new style authentication. */
AuthRequest areq = AUTH_REQ_OK;
PacketDoneProc auth_handler = NULL;
switch (port->auth_method) /* Handle new style authentication. */
{
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;
case uaKrb5: switch (port->auth_method)
areq = AUTH_REQ_KRB5; {
auth_handler = handle_krb5_auth; case uaReject:
break;
case uaTrust: /*
areq = AUTH_REQ_OK; * This could have come from an explicit "reject" entry in
auth_handler = handle_done_auth; * pg_hba.conf, but more likely it means there was no
break; * 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: case uaKrb4:
if (authident(&port->raddr.in, &port->laddr.in, sendAuthRequest(port, AUTH_REQ_KRB4);
port->user, port->auth_arg) == STATUS_OK) status = pg_krb4_recvauth(port);
{ break;
areq = AUTH_REQ_OK;
auth_handler = handle_done_auth;
}
break; case uaKrb5:
sendAuthRequest(port, AUTH_REQ_KRB5);
status = pg_krb5_recvauth(port);
break;
case uaPassword: case uaIdent:
areq = AUTH_REQ_PASSWORD; status = authident(&port->raddr.in, &port->laddr.in,
auth_handler = handle_password_auth; port->user, port->auth_arg);
break; break;
case uaCrypt: case uaPassword:
areq = AUTH_REQ_CRYPT; sendAuthRequest(port, AUTH_REQ_PASSWORD);
auth_handler = handle_password_auth; status = recv_and_check_password_packet(port);
break; 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) case uaTrust:
sendAuthRequest(port, areq, auth_handler); status = STATUS_OK;
else break;
auth_failed(port);
} }
if (status == STATUS_OK)
sendAuthRequest(port, AUTH_REQ_OK);
else
auth_failed(port);
} }
...@@ -562,134 +532,50 @@ be_recvauth(Port *port) ...@@ -562,134 +532,50 @@ be_recvauth(Port *port)
*/ */
static void static void
sendAuthRequest(Port *port, AuthRequest areq, PacketDoneProc handler) sendAuthRequest(Port *port, AuthRequest areq)
{ {
char *dp, StringInfoData buf;
*sp;
int i;
uint32 net_areq;
/* Convert to a byte stream. */ pq_beginmessage(&buf);
pq_sendbyte(&buf, 'R');
net_areq = htonl(areq); pq_sendint(&buf, (int32) areq, sizeof(int32));
dp = port->pktInfo.pkt.ar.data;
sp = (char *) &net_areq;
*dp++ = 'R';
for (i = 1; i <= 4; ++i)
*dp++ = *sp++;
/* Add the salt for encrypted passwords. */ /* Add the salt for encrypted passwords. */
if (areq == AUTH_REQ_CRYPT) if (areq == AUTH_REQ_CRYPT)
{ {
*dp++ = port->salt[0]; pq_sendint(&buf, port->salt[0], 1);
*dp++ = port->salt[1]; pq_sendint(&buf, port->salt[1], 1);
i += 2;
} }
PacketSendSetup(&port->pktInfo, i, handler, (void *) port); pq_endmessage(&buf);
} pq_flush();
/*
* 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;
} }
/*
* 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. * Called when we have received the password packet.
*/ */
static int static int
readPasswordPacket(void *arg, PacketLen len, void *pkt) recv_and_check_password_packet(Port *port)
{ {
char password[sizeof(PasswordPacket) + 1]; StringInfoData buf;
Port *port = (Port *) arg; int32 len;
int result;
/* Silently truncate a password that is too big. */
if (pq_getint(&len, 4) == EOF)
if (len > sizeof(PasswordPacket)) return STATUS_ERROR; /* client didn't want to send password */
len = sizeof(PasswordPacket); initStringInfo(&buf);
pq_getstr(&buf);
StrNCpy(password, ((PasswordPacket *) pkt)->passwd, len);
if (DebugLvl)
if (checkPassword(port, port->user, password) != STATUS_OK) fprintf(stderr, "received password packet with len=%d, pw=%s\n",
auth_failed(port); len, buf.data);
else
sendAuthRequest(port, AUTH_REQ_OK, handle_done_auth); result = checkPassword(port, port->user, buf.data);
pfree(buf.data);
return STATUS_OK; /* don't close the connection yet */ return result;
} }
...@@ -734,10 +620,8 @@ old_be_recvauth(Port *port) ...@@ -734,10 +620,8 @@ old_be_recvauth(Port *port)
break; break;
case STARTUP_PASSWORD_MSG: case STARTUP_PASSWORD_MSG:
PacketReceiveSetup(&port->pktInfo, pg_passwordv0_recvauth, status = recv_and_check_passwordv0(port);
(void *) port); break;
return STATUS_OK;
default: default:
fprintf(stderr, "Invalid startup message type: %u\n", msgtype); fprintf(stderr, "Invalid startup message type: %u\n", msgtype);
...@@ -760,8 +644,8 @@ map_old_to_new(Port *port, UserAuth old, int status) ...@@ -760,8 +644,8 @@ map_old_to_new(Port *port, UserAuth old, int status)
{ {
switch (port->auth_method) switch (port->auth_method)
{ {
case uaCrypt: case uaCrypt:
case uaReject: case uaReject:
status = STATUS_ERROR; status = STATUS_ERROR;
break; break;
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* *
...@@ -116,16 +116,13 @@ int UnBlockSig, ...@@ -116,16 +116,13 @@ int UnBlockSig,
*/ */
typedef struct bkend 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 */ long cancel_key; /* cancel key for cancels for this backend */
} Backend; } Backend;
/* list of active backends. For garbage collection only now. */ /* list of active backends. For garbage collection only now. */
static Dllist *BackendList; 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 */ /* The socket number we are listening for connections on */
int PostPortNumber; int PostPortNumber;
char *UnixSocketDir; char *UnixSocketDir;
...@@ -221,21 +218,20 @@ extern int optreset; ...@@ -221,21 +218,20 @@ extern int optreset;
static void pmdaemonize(int argc, char *argv[]); static void pmdaemonize(int argc, char *argv[]);
static Port *ConnCreate(int serverFd); static Port *ConnCreate(int serverFd);
static void ConnFree(Port *port); static void ConnFree(Port *port);
static void ClosePostmasterPorts(Port *myConn); static void ClosePostmasterPorts(void);
static void reset_shared(unsigned short port); static void reset_shared(unsigned short port);
static void SIGHUP_handler(SIGNAL_ARGS); static void SIGHUP_handler(SIGNAL_ARGS);
static void pmdie(SIGNAL_ARGS); static void pmdie(SIGNAL_ARGS);
static void reaper(SIGNAL_ARGS); static void reaper(SIGNAL_ARGS);
static void schedule_checkpoint(SIGNAL_ARGS); static void schedule_checkpoint(SIGNAL_ARGS);
static void dumpstatus(SIGNAL_ARGS);
static void CleanupProc(int pid, int exitstatus); static void CleanupProc(int pid, int exitstatus);
static int DoBackend(Port *port); static int DoBackend(Port *port);
static void ExitPostmaster(int status); static void ExitPostmaster(int status);
static void usage(const char *); static void usage(const char *);
static int ServerLoop(void); static int ServerLoop(void);
static int BackendStartup(Port *port); static int BackendStartup(Port *port);
static int readStartupPacket(void *arg, PacketLen len, void *pkt); static int ProcessStartupPacket(Port *port);
static int processCancelRequest(Port *port, PacketLen len, void *pkt); static void processCancelRequest(Port *port, void *pkt);
static int initMasks(fd_set *rmask, fd_set *wmask); static int initMasks(fd_set *rmask, fd_set *wmask);
static char *canAcceptConnections(void); static char *canAcceptConnections(void);
static long PostmasterRandom(void); static long PostmasterRandom(void);
...@@ -661,7 +657,6 @@ PostmasterMain(int argc, char *argv[]) ...@@ -661,7 +657,6 @@ PostmasterMain(int argc, char *argv[])
* garbage collecting the backend processes. * garbage collecting the backend processes.
*/ */
BackendList = DLNewList(); BackendList = DLNewList();
PortList = DLNewList();
/* /*
* Record postmaster options. We delay this till now to avoid * Record postmaster options. We delay this till now to avoid
...@@ -690,7 +685,6 @@ PostmasterMain(int argc, char *argv[]) ...@@ -690,7 +685,6 @@ PostmasterMain(int argc, char *argv[])
pqsignal(SIGCHLD, reaper); /* handle child termination */ pqsignal(SIGCHLD, reaper); /* handle child termination */
pqsignal(SIGTTIN, SIG_IGN); /* ignored */ pqsignal(SIGTTIN, SIG_IGN); /* ignored */
pqsignal(SIGTTOU, SIG_IGN); /* ignored */ pqsignal(SIGTTOU, SIG_IGN); /* ignored */
pqsignal(SIGWINCH, dumpstatus); /* dump port status */
/* /*
* We're ready to rock and roll... * We're ready to rock and roll...
...@@ -794,7 +788,6 @@ ServerLoop(void) ...@@ -794,7 +788,6 @@ ServerLoop(void)
fd_set readmask, fd_set readmask,
writemask; writemask;
int nSockets; int nSockets;
Dlelem *curr;
struct timeval now, struct timeval now,
later; later;
struct timezone tz; struct timezone tz;
...@@ -841,27 +834,6 @@ ServerLoop(void) ...@@ -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. * Wait for something to happen.
*/ */
...@@ -915,126 +887,26 @@ ServerLoop(void) ...@@ -915,126 +887,26 @@ ServerLoop(void)
*/ */
#ifdef HAVE_UNIX_SOCKETS #ifdef HAVE_UNIX_SOCKETS
if (ServerSock_UNIX != INVALID_SOCK && if (ServerSock_UNIX != INVALID_SOCK
FD_ISSET(ServerSock_UNIX, &rmask) && && FD_ISSET(ServerSock_UNIX, &rmask))
(port = ConnCreate(ServerSock_UNIX)) != NULL)
{ {
PacketReceiveSetup(&port->pktInfo, port = ConnCreate(ServerSock_UNIX);
readStartupPacket, if (port)
(void *) port); BackendStartup(port);
StreamClose(port->sock);
ConnFree(port);
} }
#endif #endif
if (ServerSock_INET != INVALID_SOCK && if (ServerSock_INET != INVALID_SOCK
FD_ISSET(ServerSock_INET, &rmask) && && FD_ISSET(ServerSock_INET, &rmask))
(port = ConnCreate(ServerSock_INET)) != NULL)
{ {
PacketReceiveSetup(&port->pktInfo, port = ConnCreate(ServerSock_INET);
readStartupPacket, if (port)
(void *) 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) ...@@ -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 static int
readStartupPacket(void *arg, PacketLen len, void *pkt) ProcessStartupPacket(Port *port)
{ {
Port *port; StartupPacket *packet;
StartupPacket *si;
char *rejectMsg; char *rejectMsg;
int32 len;
void *buf;
port = (Port *) arg; pq_getbytes((char *)&len, 4);
si = (StartupPacket *) pkt; 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 * The first field is either a protocol version number or a special
* request code. * request code.
*/ */
port->proto = ntohl(packet->protoVersion);
port->proto = ntohl(si->protoVersion);
if (port->proto == CANCEL_REQUEST_CODE) if (port->proto == CANCEL_REQUEST_CODE)
return processCancelRequest(port, len, pkt); {
processCancelRequest(port, packet);
return 127; /* XXX */
}
if (port->proto == NEGOTIATE_SSL_CODE) if (port->proto == NEGOTIATE_SSL_CODE)
{ {
...@@ -1114,7 +1000,7 @@ readStartupPacket(void *arg, PacketLen len, void *pkt) ...@@ -1114,7 +1000,7 @@ readStartupPacket(void *arg, PacketLen len, void *pkt)
{ {
postmaster_error("failed to send SSL negotiation response: %s", postmaster_error("failed to send SSL negotiation response: %s",
strerror(errno)); strerror(errno));
return STATUS_ERROR;/* Close connection */ return STATUS_ERROR; /* close the connection */
} }
#ifdef USE_SSL #ifdef USE_SSL
...@@ -1130,11 +1016,10 @@ readStartupPacket(void *arg, PacketLen len, void *pkt) ...@@ -1130,11 +1016,10 @@ readStartupPacket(void *arg, PacketLen len, void *pkt)
} }
} }
#endif #endif
/* ready for the normal startup packet */ /* regular startup packet should follow... */
PacketReceiveSetup(&port->pktInfo, /* FIXME: by continuing to send SSL negotiation packets, a
readStartupPacket, client could run us out of stack space */
(void *) port); return ProcessStartupPacket(port);
return STATUS_OK; /* Do not close connection */
} }
/* Could add additional special packet types here */ /* Could add additional special packet types here */
...@@ -1146,46 +1031,35 @@ readStartupPacket(void *arg, PacketLen len, void *pkt) ...@@ -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_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))) PG_PROTOCOL_MINOR(port->proto) > PG_PROTOCOL_MINOR(PG_PROTOCOL_LATEST)))
{ elog(FATAL, "unsupported frontend protocol");
PacketSendError(&port->pktInfo, "Unsupported frontend protocol.");
return STATUS_OK; /* don't close the connection yet */
}
/* /*
* Get the parameters from the startup packet as C strings. The * Get the parameters from the startup packet as C strings. The
* packet destination was cleared first so a short packet has zeros * packet destination was cleared first so a short packet has zeros
* silently added and a long packet is silently truncated. * silently added and a long packet is silently truncated.
*/ */
StrNCpy(port->database, packet->database, sizeof(port->database));
StrNCpy(port->database, si->database, sizeof(port->database)); StrNCpy(port->user, packet->user, sizeof(port->user));
StrNCpy(port->user, si->user, sizeof(port->user)); StrNCpy(port->options, packet->options, sizeof(port->options));
StrNCpy(port->options, si->options, sizeof(port->options)); StrNCpy(port->tty, packet->tty, sizeof(port->tty));
StrNCpy(port->tty, si->tty, sizeof(port->tty));
/* The database defaults to the user name. */ /* The database defaults to the user name. */
if (port->database[0] == '\0') 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 * 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) if ((int) sizeof(port->database) >= NAMEDATALEN)
port->database[NAMEDATALEN - 1] = '\0'; port->database[NAMEDATALEN - 1] = '\0';
if ((int) sizeof(port->user) >= NAMEDATALEN) if ((int) sizeof(port->user) >= NAMEDATALEN)
port->user[NAMEDATALEN - 1] = '\0'; port->user[NAMEDATALEN - 1] = '\0';
/* Check a user name was given. */ /* Check a user name was given. */
if (port->user[0] == '\0') if (port->user[0] == '\0')
{ elog(FATAL, "no PostgreSQL user name specified in startup packet");
PacketSendError(&port->pktInfo,
"No Postgres username specified in startup packet.");
return STATUS_OK; /* don't close the connection yet */
}
/* /*
* If we're going to reject the connection due to database state, say * If we're going to reject the connection due to database state, say
...@@ -1195,27 +1069,19 @@ readStartupPacket(void *arg, PacketLen len, void *pkt) ...@@ -1195,27 +1069,19 @@ readStartupPacket(void *arg, PacketLen len, void *pkt)
rejectMsg = canAcceptConnections(); rejectMsg = canAcceptConnections();
if (rejectMsg != NULL) if (rejectMsg != NULL)
{ elog(FATAL, "%s", rejectMsg);
PacketSendError(&port->pktInfo, rejectMsg);
return STATUS_OK; /* don't close the connection yet */
}
/* Start the authentication itself. */ return STATUS_OK;
be_recvauth(port);
return STATUS_OK; /* don't close the connection yet */
} }
/* /*
* The client has sent a cancel request packet, not a normal * The client has sent a cancel request packet, not a normal
* start-a-new-backend packet. Perform the necessary processing. * start-a-new-connection packet. Perform the necessary processing.
* Note that in any case, we return STATUS_ERROR to close the * Nothing is sent back to the client.
* connection immediately. Nothing is sent back to the client.
*/ */
static void
static int processCancelRequest(Port *port, void *pkt)
processCancelRequest(Port *port, PacketLen len, void *pkt)
{ {
CancelRequestPacket *canc = (CancelRequestPacket *) pkt; CancelRequestPacket *canc = (CancelRequestPacket *) pkt;
int backendPID; int backendPID;
...@@ -1230,7 +1096,7 @@ processCancelRequest(Port *port, PacketLen len, void *pkt) ...@@ -1230,7 +1096,7 @@ processCancelRequest(Port *port, PacketLen len, void *pkt)
{ {
if (DebugLvl) if (DebugLvl)
postmaster_error("processCancelRequest: CheckPointPID in cancel request for process %d", backendPID); postmaster_error("processCancelRequest: CheckPointPID in cancel request for process %d", backendPID);
return STATUS_ERROR; return;
} }
/* See if we have a matching backend */ /* See if we have a matching backend */
...@@ -1244,24 +1110,24 @@ processCancelRequest(Port *port, PacketLen len, void *pkt) ...@@ -1244,24 +1110,24 @@ processCancelRequest(Port *port, PacketLen len, void *pkt)
{ {
/* Found a match; signal that backend to cancel current op */ /* Found a match; signal that backend to cancel current op */
if (DebugLvl) 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); kill(bp->pid, SIGINT);
} }
else else
{ {
/* Right PID, wrong key: no way, Jose */ /* Right PID, wrong key: no way, Jose */
if (DebugLvl) 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 */ /* No matching backend */
if (DebugLvl) if (DebugLvl)
postmaster_error("processCancelRequest: bad PID in cancel request for process %d", backendPID); elog(DEBUG, "bad pid in cancel request for process %d", backendPID);
return STATUS_ERROR;
} }
/* /*
...@@ -1295,6 +1161,7 @@ canAcceptConnections(void) ...@@ -1295,6 +1161,7 @@ canAcceptConnections(void)
return NULL; return NULL;
} }
/* /*
* ConnCreate -- create a local connection data structure * ConnCreate -- create a local connection data structure
*/ */
...@@ -1318,7 +1185,6 @@ ConnCreate(int serverFd) ...@@ -1318,7 +1185,6 @@ ConnCreate(int serverFd)
} }
else else
{ {
DLAddHead(PortList, DLNewElem(port));
RandomSalt(port->salt); RandomSalt(port->salt);
port->pktInfo.state = Idle; port->pktInfo.state = Idle;
} }
...@@ -1326,6 +1192,7 @@ ConnCreate(int serverFd) ...@@ -1326,6 +1192,7 @@ ConnCreate(int serverFd)
return port; return port;
} }
/* /*
* ConnFree -- free a local connection data structure * ConnFree -- free a local connection data structure
*/ */
...@@ -1339,22 +1206,20 @@ ConnFree(Port *conn) ...@@ -1339,22 +1206,20 @@ ConnFree(Port *conn)
free(conn); free(conn);
} }
/* /*
* ClosePostmasterPorts -- close all the postmaster's open sockets * ClosePostmasterPorts -- close all the postmaster's open sockets
* *
* This is called during child process startup to release file descriptors * This is called during child process startup to release file descriptors
* that are not needed by that child process. All descriptors other than * that are not needed by that child process.
* the one for myConn (if it's not null) are closed.
* *
* Note that closing the child's descriptor does not destroy the client * Note that closing the child's descriptor does not destroy the client
* connection prematurely, since the parent (postmaster) process still * connection prematurely, since the parent (postmaster) process still
* has the socket open. * has the socket open.
*/ */
static void static void
ClosePostmasterPorts(Port *myConn) ClosePostmasterPorts(void)
{ {
Dlelem *curr;
/* Close the listen sockets */ /* Close the listen sockets */
if (NetServer) if (NetServer)
StreamClose(ServerSock_INET); StreamClose(ServerSock_INET);
...@@ -1363,25 +1228,6 @@ ClosePostmasterPorts(Port *myConn) ...@@ -1363,25 +1228,6 @@ ClosePostmasterPorts(Port *myConn)
StreamClose(ServerSock_UNIX); StreamClose(ServerSock_UNIX);
ServerSock_UNIX = INVALID_SOCK; ServerSock_UNIX = INVALID_SOCK;
#endif #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 ...@@ -1847,7 +1693,7 @@ static int
BackendStartup(Port *port) BackendStartup(Port *port)
{ {
Backend *bn; /* for backend cleanup */ Backend *bn; /* for backend cleanup */
int pid; pid_t pid;
/* /*
* Compute the cancel key that will be assigned to this backend. The * Compute the cancel key that will be assigned to this backend. The
...@@ -1872,42 +1718,45 @@ BackendStartup(Port *port) ...@@ -1872,42 +1718,45 @@ BackendStartup(Port *port)
beos_before_backend_startup(); beos_before_backend_startup();
#endif #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__ #ifdef __BEOS__
/* Specific beos backend startup actions */ /* Specific beos backend startup actions */
beos_backend_startup(); beos_backend_startup();
#endif #endif
#ifdef CYR_RECODE status = DoBackend(port);
{ if (status != 0)
/* 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))
{ {
fprintf(stderr, gettext("%s child[%d]: BackendStartup: backend startup failed\n"), fprintf(stderr, gettext("%s child[%d]: BackendStartup: backend startup failed\n"),
progname, (int) getpid()); progname, (int) getpid());
ExitPostmaster(1); proc_exit(status);
} }
else else
ExitPostmaster(0); proc_exit(0);
} }
/* in parent */ /* in parent, error */
if (pid < 0) if (pid < 0)
{ {
free(bn);
#ifdef __BEOS__ #ifdef __BEOS__
/* Specific beos backend startup actions */ /* Specific beos backend startup actions */
beos_backend_startup_failed(); beos_backend_startup_failed();
...@@ -1917,8 +1766,9 @@ BackendStartup(Port *port) ...@@ -1917,8 +1766,9 @@ BackendStartup(Port *port)
return STATUS_ERROR; return STATUS_ERROR;
} }
if (DebugLvl) /* in parent, normal */
fprintf(stderr, gettext("%s: BackendStartup: pid %d user %s db %s socket %d\n"), if (DebugLvl >= 1)
fprintf(stderr, gettext("%s: BackendStartup: pid=%d user=%s db=%s socket=%d\n"),
progname, pid, port->user, port->database, progname, pid, port->user, port->database,
port->sock); port->sock);
...@@ -1926,13 +1776,6 @@ BackendStartup(Port *port) ...@@ -1926,13 +1776,6 @@ BackendStartup(Port *port)
* Everything's been successful, it's safe to add this backend to our * Everything's been successful, it's safe to add this backend to our
* list of backends. * 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->pid = pid;
bn->cancel_key = MyCancelKey; bn->cancel_key = MyCancelKey;
DLAddHead(BackendList, DLNewElem(bn)); DLAddHead(BackendList, DLNewElem(bn));
...@@ -1940,6 +1783,7 @@ BackendStartup(Port *port) ...@@ -1940,6 +1783,7 @@ BackendStartup(Port *port)
return STATUS_OK; return STATUS_OK;
} }
/* /*
* split_opts -- split a string of options and append it to an argv array * split_opts -- split a string of options and append it to an argv array
* *
...@@ -1990,6 +1834,7 @@ DoBackend(Port *port) ...@@ -1990,6 +1834,7 @@ DoBackend(Port *port)
char optbuf[ARGV_SIZE]; char optbuf[ARGV_SIZE];
char ttybuf[ARGV_SIZE]; char ttybuf[ARGV_SIZE];
int i; int i;
int status;
struct timeval now; struct timeval now;
struct timezone tz; struct timezone tz;
...@@ -2004,14 +1849,22 @@ DoBackend(Port *port) ...@@ -2004,14 +1849,22 @@ DoBackend(Port *port)
* Signal handlers setting is moved to tcop/postgres... * Signal handlers setting is moved to tcop/postgres...
*/ */
SetProcessingMode(InitProcessing);
/* Save port etc. for ps status */ /* Save port etc. for ps status */
MyProcPort = port; MyProcPort = port;
/* Reset MyProcPid to new backend's pid */ /* Reset MyProcPid to new backend's pid */
MyProcPid = getpid(); MyProcPid = getpid();
whereToSendOutput = Remote;
status = ProcessStartupPacket(port);
if (status == 127)
return 0; /* cancel request processed */
/* Close the postmaster's other sockets */ /* Close the postmaster's other sockets */
ClosePostmasterPorts(port); ClosePostmasterPorts();
/* /*
* Don't want backend to be able to see the postmaster random number * Don't want backend to be able to see the postmaster random number
...@@ -2162,26 +2015,6 @@ schedule_checkpoint(SIGNAL_ARGS) ...@@ -2162,26 +2015,6 @@ schedule_checkpoint(SIGNAL_ARGS)
errno = save_errno; 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 * CharRemap
...@@ -2336,7 +2169,7 @@ SSDataBase(int xlop) ...@@ -2336,7 +2169,7 @@ SSDataBase(int xlop)
on_exit_reset(); on_exit_reset();
/* Close the postmaster's sockets */ /* Close the postmaster's sockets */
ClosePostmasterPorts(NULL); ClosePostmasterPorts();
/* Set up command-line arguments for subprocess */ /* Set up command-line arguments for subprocess */
av[ac++] = "postgres"; av[ac++] = "postgres";
...@@ -2463,7 +2296,7 @@ postmaster_error(const char *fmt, ...) ...@@ -2463,7 +2296,7 @@ postmaster_error(const char *fmt, ...)
fprintf(stderr, "%s: ", progname); fprintf(stderr, "%s: ", progname);
va_start(ap, fmt); va_start(ap, fmt);
fprintf(stderr, gettext(fmt), ap); vfprintf(stderr, gettext(fmt), ap);
va_end(ap); va_end(ap);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
} }
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* this is the "main" module of the postgres backend and * this is the "main" module of the postgres backend and
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
#include "libpq/pqformat.h" #include "libpq/pqformat.h"
#include "libpq/pqsignal.h" #include "libpq/pqsignal.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "libpq/auth.h"
#include "nodes/print.h" #include "nodes/print.h"
#include "optimizer/cost.h" #include "optimizer/cost.h"
#include "optimizer/planner.h" #include "optimizer/planner.h"
...@@ -1142,11 +1143,13 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha ...@@ -1142,11 +1143,13 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
*/ */
if (!IsUnderPostmaster) if (!IsUnderPostmaster)
{ {
SetProcessingMode(InitProcessing);
EnableExceptionHandling(true); EnableExceptionHandling(true);
MemoryContextInit(); MemoryContextInit();
} }
SetProcessingMode(InitProcessing); if (IsUnderPostmaster)
ClientAuthentication(MyProcPort); /* might not return */
/* /*
* Set default values for command-line options. * Set default values for command-line options.
...@@ -1567,13 +1570,11 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha ...@@ -1567,13 +1570,11 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
* restart... */ * restart... */
} }
pq_init(); /* initialize libpq at backend startup */ pq_init(); /* initialize libpq at backend startup */
whereToSendOutput = Remote;
BaseInit(); BaseInit();
} }
else else
{ {
/* interactive case: database name can be last arg on command line */ /* interactive case: database name can be last arg on command line */
whereToSendOutput = Debug;
if (errs || argc - optind > 1) if (errs || argc - optind > 1)
{ {
fprintf(stderr, "%s: invalid command line arguments\nTry -? for help.\n", argv[0]); 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 ...@@ -1709,7 +1710,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
if (!IsUnderPostmaster) if (!IsUnderPostmaster)
{ {
puts("\nPOSTGRES backend interactive interface "); 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");
} }
/* /*
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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,...) ...@@ -129,10 +129,6 @@ elog(int lev, const char *fmt,...)
/* size of the prefix needed for timestamp and pid, if enabled */ /* size of the prefix needed for timestamp and pid, if enabled */
size_t timestamp_size; 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 */ /* Save error str before calling any function that might change errno */
errorstr = useful_strerror(errno); errorstr = useful_strerror(errno);
...@@ -336,10 +332,9 @@ elog(int lev, const char *fmt,...) ...@@ -336,10 +332,9 @@ elog(int lev, const char *fmt,...)
/* syslog doesn't want a trailing newline, but other destinations do */ /* syslog doesn't want a trailing newline, but other destinations do */
strcat(msg_buf, "\n"); strcat(msg_buf, "\n");
/* Write to debug file, if open and enabled */ /* write to terminal */
/* NOTE: debug file is typically pointed at stderr */ if (Use_syslog <= 1 || whereToSendOutput == Debug)
if (Debugfile >= 0 && Use_syslog <= 1) write(2, msg_buf, strlen(msg_buf));
write(Debugfile, msg_buf, strlen(msg_buf));
if (lev > DEBUG && whereToSendOutput == Remote) if (lev > DEBUG && whereToSendOutput == Remote)
{ {
...@@ -371,17 +366,6 @@ elog(int lev, const char *fmt,...) ...@@ -371,17 +366,6 @@ elog(int lev, const char *fmt,...)
MemoryContextSwitchTo(oldcxt); 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 */ /* done with the message, release space */
if (fmt_buf != fmt_fixedbuf) if (fmt_buf != fmt_fixedbuf)
free(fmt_buf); free(fmt_buf);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 @@ ...@@ -28,6 +28,7 @@
#include "catalog/catname.h" #include "catalog/catname.h"
#include "catalog/pg_shadow.h" #include "catalog/pg_shadow.h"
#include "libpq/libpq-be.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/lsyscache.h" #include "utils/lsyscache.h"
...@@ -279,6 +280,7 @@ SetCharSet() ...@@ -279,6 +280,7 @@ SetCharSet()
int i; int i;
unsigned char FromChar, unsigned char FromChar,
ToChar; ToChar;
char ChTable[80];
for (i = 0; i < 128; i++) for (i = 0; i < 128; i++)
{ {
...@@ -286,11 +288,17 @@ SetCharSet() ...@@ -286,11 +288,17 @@ SetCharSet()
RecodeBackTable[i] = i + 128; 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') if (p && *p != '\0')
{ {
map_file = (char *) malloc((strlen(DataDir) + map_file = malloc(strlen(DataDir) + strlen(p) + 2);
strlen(p) + 2) * sizeof(char));
if (! map_file) if (! map_file)
elog(FATAL, "out of memory"); elog(FATAL, "out of memory");
sprintf(map_file, "%s/%s", DataDir, p); sprintf(map_file, "%s/%s", DataDir, p);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 @@ ...@@ -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_KRB4_VERSION "PGVER4.1" /* at most KRB_SENDAUTH_VLEN chars */
#define PG_KRB5_VERSION "PGVER5.1" #define PG_KRB5_VERSION "PGVER5.1"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment