1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-19 13:42:17 +03:00
I've completed the patch to fix the protocol and authentication issues I
was discussing a couple of weeks ago.  The particular changes are:

- the protocol has a version number
- network byte order is used throughout
- the pg_hba.conf file is used to specify what method is used to
  authenticate a frontend (either password, ident, trust, reject, krb4
  or krb5)
- support for multiplexed backends is removed
- appropriate changes to man pages
- the -a switch to many programs to specify an authentication service
  no longer has any effect
- the libpq.so version number has changed to 1.1

The new backend still supports the old protocol so old interfaces won't
break.
This commit is contained in:
Marc G. Fournier
1998-01-26 01:42:53 +00:00
parent 91d983aa11
commit d5bbe2aca5
41 changed files with 1611 additions and 2288 deletions

View File

@@ -7,10 +7,13 @@
#
#
# IDENTIFICATION
# $Header: /cvsroot/pgsql/src/interfaces/libpq/Attic/Makefile.in,v 1.4 1998/01/17 23:39:11 scrappy Exp $
# $Header: /cvsroot/pgsql/src/interfaces/libpq/Attic/Makefile.in,v 1.5 1998/01/26 01:42:24 scrappy Exp $
#
#-------------------------------------------------------------------------
SO_MAJOR_VERSION=1
SO_MINOR_VERSION=1
SRCDIR= ../..
include $(SRCDIR)/Makefile.global
@@ -19,7 +22,7 @@ INCLUDE_OPT= -I$(SRCDIR)/include -I$(SRCDIR)/backend
PORTNAME=@PORTNAME@
CFLAGS+= $(INCLUDE_OPT)
CFLAGS+= $(INCLUDE_OPT) -DFRONTEND
ifdef KRBVERS
CFLAGS+= $(KRBFLAGS)
@@ -34,20 +37,20 @@ install-shlib-dep :=
ifeq ($(PORTNAME), linux)
ifdef LINUX_ELF
install-shlib-dep := install-shlib
shlib := libpq.so.1
shlib := libpq.so.$(SO_MAJOR_VERSION).$(SO_MINOR_VERSION)
LDFLAGS_SL = -shared
CFLAGS += $(CFLAGS_SL)
endif
endif
ifeq ($(PORTNAME), bsd)
install-shlib-dep := install-shlib
shlib := libpq.so.1.0
shlib := libpq.so.$(SO_MAJOR_VERSION).$(SO_MINOR_VERSION)
LDFLAGS_SL = -x -Bshareable -Bforcearchive
CFLAGS += $(CFLAGS_SL)
endif
ifeq ($(PORTNAME), i386_solaris)
install-shlib-dep := install-shlib
shlib := libpq.so.1
shlib := libpq.so.$(SO_MAJOR_VERSION).$(SO_MINOR_VERSION)
LDFLAGS_SL = -G -z text
CFLAGS += $(CFLAGS_SL)
endif

View File

@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-auth.c,v 1.12 1997/12/04 00:28:08 scrappy Exp $
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-auth.c,v 1.13 1998/01/26 01:42:25 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
@@ -42,6 +42,11 @@
#include "fe-auth.h"
#include "fe-connect.h"
#ifdef HAVE_CRYPT_H
#include <crypt.h>
#endif
/*----------------------------------------------------------------
* common definitions for generic fe/be routines
*----------------------------------------------------------------
@@ -457,49 +462,49 @@ pg_krb5_sendauth(const char *PQerrormsg, int sock,
#endif /* KRB5 */
static int
pg_password_sendauth(Port *port, const char *user, const char *password)
pg_password_sendauth(PGconn *conn, const char *password, AuthRequest areq)
{
PacketBuf buf;
char *tmp;
/* Encrypt the password if needed. */
buf.len = htonl(sizeof(PacketBuf));
buf.msgtype = STARTUP_PASSWORD_MSG;
buf.data[0] = '\0';
if (areq == AUTH_REQ_CRYPT)
password = crypt(password, conn->salt);
tmp = buf.data;
strncpy(tmp, user, strlen(user) + 1);
tmp += strlen(user) + 1;
strncpy(tmp, password, strlen(password) + 1);
return packetSend(port, &buf, sizeof(PacketBuf), BLOCKING);
return packetSend(conn, password, strlen(password) + 1);
}
/*
* fe_sendauth -- client demux routine for outgoing authentication information
*/
int
fe_sendauth(MsgType msgtype, Port *port, const char *hostname,
const char *user, const char *password, const char *PQerrormsg)
fe_sendauth(AuthRequest areq, PGconn *conn, const char *hostname,
const char *password, const char *PQerrormsg)
{
switch (msgtype)
switch (areq)
{
case AUTH_REQ_OK:
break;
case AUTH_REQ_KRB4:
#ifdef KRB4
case STARTUP_KRB4_MSG:
if (pg_krb4_sendauth(PQerrormsg, port->sock, &port->laddr,
&port->raddr,
if (pg_krb4_sendauth(PQerrormsg, conn->sock, &conn->laddr.in,
&conn->raddr.in,
hostname) != STATUS_OK)
{
(void) sprintf(PQerrormsg,
"fe_sendauth: krb4 authentication failed\n");
/* fputs(PQerrormsg, stderr); */
return (STATUS_ERROR);
}
break;
#else
(void)sprintf(PQerrormsg,
"fe_sendauth: krb4 authentication not supported\n");
return (STATUS_ERROR);
#endif
case AUTH_REQ_KRB5:
#ifdef KRB5
case STARTUP_KRB5_MSG:
if (pg_krb5_sendauth(PQerrormsg, port->sock, &port->laddr,
&port->raddr,
if (pg_krb5_sendauth(PQerrormsg, conn->sock, &conn->laddr.in,
&conn->raddr.in,
hostname) != STATUS_OK)
{
(void) sprintf(PQerrormsg,
@@ -507,15 +512,29 @@ fe_sendauth(MsgType msgtype, Port *port, const char *hostname,
return (STATUS_ERROR);
}
break;
#else
(void)sprintf(PQerrormsg,
"fe_sendauth: krb5 authentication not supported\n");
return (STATUS_ERROR);
#endif
case STARTUP_MSG:
break;
case STARTUP_PASSWORD_MSG:
case STARTUP_CRYPT_MSG:
pg_password_sendauth(port, user, password);
default:
break;
}
case AUTH_REQ_PASSWORD:
case AUTH_REQ_CRYPT:
if (pg_password_sendauth(conn, password, areq) != STATUS_OK)
{
(void)sprintf(PQerrormsg,
"fe_sendauth: error sending password authentication\n");
return (STATUS_ERROR);
}
break;
default:
(void)sprintf(PQerrormsg,
"fe_sendauth: authentication type %u not supported\n",areq);
return (STATUS_ERROR);
}
return (STATUS_OK);
}

View File

@@ -6,13 +6,16 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: fe-auth.h,v 1.6 1997/09/08 21:55:35 momjian Exp $
* $Id: fe-auth.h,v 1.7 1998/01/26 01:42:26 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef FE_AUTH_H
#define FE_AUTH_H
#include "libpq-fe.h"
/*----------------------------------------------------------------
* Common routines and definitions
*----------------------------------------------------------------
@@ -29,9 +32,8 @@
#endif /* KRB4 || KRB5 */
extern int
fe_sendauth(MsgType msgtype, Port *port, const char *hostname,
const char *user, const char *password,
const char *PQerromsg);
fe_sendauth(AuthRequest areq, PGconn *conn, const char *hostname,
const char *password, const char *PQerromsg);
extern void fe_setauthsvc(const char *name, char *PQerrormsg);
#define PG_KRB4_VERSION "PGVER4.1" /* at most KRB_SENDAUTH_VLEN chars */

View File

@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.58 1998/01/23 02:31:18 scrappy Exp $
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.59 1998/01/26 01:42:28 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
@@ -21,14 +21,14 @@
#include <ctype.h>
#include <string.h>
#include <netdb.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <errno.h>
#include <signal.h>
#include <ctype.h> /* for isspace() */
#include "postgres.h"
#include "libpq/pqcomm.h" /* for decls of MsgType, PacketBuf,
* StartupInfo */
#include "fe-auth.h"
#include "fe-connect.h"
#include "libpq-fe.h"
@@ -44,7 +44,6 @@
/* use a local version instead of the one found in pqpacket.c */
static ConnStatusType connectDB(PGconn *conn);
static void startup2PacketBuf(StartupInfo *s, PacketBuf *res);
static void freePGconn(PGconn *conn);
static void closePGconn(PGconn *conn);
static int conninfo_parse(const char *conninfo, char *errorMessage);
@@ -78,6 +77,7 @@ static PQconninfoOption PQconninfoOptions[] = {
/* Option-name Environment-Var Compiled-in Current value */
/* Label Disp-Char */
/* ----------------- --------------- --------------- --------------- */
/* "authtype" is ignored as it is no longer used. */
{"authtype", "PGAUTHTYPE", DefaultAuthtype, NULL,
"Database-Authtype", "", 20},
@@ -183,7 +183,6 @@ PQconnectdb(const char *conninfo)
conn->Pfout = NULL;
conn->Pfin = NULL;
conn->Pfdebug = NULL;
conn->port = NULL;
conn->notifyList = DLNewList();
tmp = conninfo_getval("host");
@@ -198,8 +197,6 @@ PQconnectdb(const char *conninfo)
conn->pguser = tmp ? strdup(tmp) : NULL;
tmp = conninfo_getval("password");
conn->pgpass = tmp ? strdup(tmp) : NULL;
tmp = conninfo_getval("authtype");
conn->pgauth = tmp ? strdup(tmp) : NULL;
tmp = conninfo_getval("dbname");
conn->dbName = tmp ? strdup(tmp) : NULL;
@@ -209,14 +206,6 @@ PQconnectdb(const char *conninfo)
*/
conninfo_free();
/*
* try to set the auth service if one was specified
*/
if (conn->pgauth)
{
fe_setauthsvc(conn->pgauth, conn->errorMessage);
}
/* ----------
* Connect to the database
* ----------
@@ -326,7 +315,6 @@ PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions, cons
conn->Pfout = NULL;
conn->Pfin = NULL;
conn->Pfdebug = NULL;
conn->port = NULL;
conn->notifyList = DLNewList();
if ((pghost == NULL) || pghost[0] == '\0')
@@ -467,44 +455,31 @@ connectDB(PGconn *conn)
{
struct hostent *hp;
StartupInfo startup;
PacketBuf pacBuf;
PacketLen pacLen;
int status;
MsgType msgtype;
int laddrlen = sizeof(struct sockaddr);
Port *port = conn->port;
StartupPacket sp;
AuthRequest areq;
int laddrlen = sizeof(SockAddr);
int portno,
family,
len;
bool salted = false;
char* tmp;
/*
* Initialize the startup packet.
*
* This data structure is used for the seq-packet protocol. It describes
* the frontend-backend connection.
*
*
*/
strncpy(startup.user, conn->pguser, sizeof(startup.user));
strncpy(startup.database, conn->dbName, sizeof(startup.database));
strncpy(startup.tty, conn->pgtty, sizeof(startup.tty));
MemSet((char *)&sp, 0, sizeof (StartupPacket));
sp.protoVersion = (ProtocolVersion)htonl(PG_PROTOCOL_LATEST);
strncpy(sp.user, conn->pguser, SM_USER);
strncpy(sp.database, conn->dbName, SM_DATABASE);
strncpy(sp.tty, conn->pgtty, SM_TTY);
if (conn->pgoptions)
{
strncpy(startup.options, conn->pgoptions, sizeof(startup.options));
}
else
startup.options[0] = '\0';
startup.execFile[0] = '\0'; /* not used */
strncpy(sp.options, conn->pgoptions, SM_OPTIONS);
/*
* Open a connection to postmaster/backend.
*
*/
port = (Port *) malloc(sizeof(Port));
MemSet((char *) port, 0, sizeof(Port));
if (conn->pghost != NULL)
{
@@ -524,28 +499,28 @@ connectDB(PGconn *conn)
#endif
portno = atoi(conn->pgport);
family = (conn->pghost != NULL) ? AF_INET : AF_UNIX;
port->raddr.in.sin_family = family;
conn->raddr.sa.sa_family = family;
if (family == AF_INET)
{
memmove((char *) &(port->raddr.in.sin_addr),
memmove((char *) &(conn->raddr.in.sin_addr),
(char *) hp->h_addr,
hp->h_length);
port->raddr.in.sin_port = htons((unsigned short) (portno));
conn->raddr.in.sin_port = htons((unsigned short) (portno));
len = sizeof(struct sockaddr_in);
}
else
{
len = UNIXSOCK_PATH(port->raddr.un, portno);
len = UNIXSOCK_PATH(conn->raddr.un, portno);
}
/* connect to the server */
if ((port->sock = socket(family, SOCK_STREAM, 0)) < 0)
if ((conn->sock = socket(family, SOCK_STREAM, 0)) < 0)
{
(void) sprintf(conn->errorMessage,
"connectDB() -- socket() failed: errno=%d\n%s\n",
errno, strerror(errno));
goto connect_errReturn;
}
if (connect(port->sock, (struct sockaddr *) & port->raddr, len) < 0)
if (connect(conn->sock, &conn->raddr.sa, len) < 0)
{
(void) sprintf(conn->errorMessage,
"connectDB() failed: Is the postmaster running and accepting%s connections at '%s' on port '%s'?\n",
@@ -566,7 +541,7 @@ connectDB(PGconn *conn)
"connectDB(): getprotobyname failed\n");
goto connect_errReturn;
}
if (setsockopt(port->sock, pe->p_proto, TCP_NODELAY,
if (setsockopt(conn->sock, pe->p_proto, TCP_NODELAY,
&on, sizeof(on)) < 0)
{
(void) sprintf(conn->errorMessage,
@@ -576,8 +551,7 @@ connectDB(PGconn *conn)
}
/* fill in the client address */
if (getsockname(port->sock, (struct sockaddr *) & port->laddr,
&laddrlen) < 0)
if (getsockname(conn->sock, &conn->laddr.sa, &laddrlen) < 0)
{
(void) sprintf(conn->errorMessage,
"connectDB() -- getsockname() failed: errno=%d\n%s\n",
@@ -585,91 +559,9 @@ connectDB(PGconn *conn)
goto connect_errReturn;
}
/* by this point, connection has been opened */
/* This section of code is new as of Nov 19, 1997. It sends just the
* user's login to the backend. This allows the backend to search
* pg_user to see if the user has a password defined. If the user
* does have a password in pg_user, then the backend will send a
* packet back with a randomly generated salt, so the user's password
* can be encrypted.
*/
pacLen = sizeof(pacBuf.len) + sizeof(pacBuf.msgtype) + strlen(startup.user) + 1;
pacBuf.len = htonl(pacLen);
pacBuf.msgtype = htonl(STARTUP_USER_MSG);
strcpy(pacBuf.data, startup.user);
status = packetSend(port, &pacBuf, pacLen, BLOCKING);
if (status == STATUS_ERROR) {
sprintf(conn->errorMessage, "connectDB() -- couldn't send complete packet: errno=%d\n%s\n", errno, strerror(errno));
goto connect_errReturn;
}
/* Check to see if the server sent us a salt back to encrypt the
* password to send for authentication. --TAB
*/
status = packetReceive(port, &pacBuf, BLOCKING);
if (status != STATUS_OK) {
sprintf(conn->errorMessage, "connectDB() -- couldn't receive un/salt packet: errno=%d\n%s\n", errno, strerror(errno));
goto connect_errReturn;
}
pacBuf.msgtype = ntohl(pacBuf.msgtype);
switch (pacBuf.msgtype) {
case STARTUP_SALT_MSG:
salted = true;
if (!conn->pgpass) {
sprintf(conn->errorMessage, "connectDB() -- backend requested a password, but none was given\n");
goto connect_errReturn;
}
tmp = crypt(conn->pgpass, pacBuf.data);
free((void*)conn->pgpass);
conn->pgpass = strdup(tmp);
break;
case STARTUP_UNSALT_MSG:
salted = false;
break;
default:
sprintf(conn->errorMessage, "connectDB() -- backend did not supply a salt packet\n");
goto connect_errReturn;
}
if (salted)
msgtype = STARTUP_CRYPT_MSG;
else
msgtype = fe_getauthsvc(conn->errorMessage);
/* pacBuf = startup2PacketBuf(&startup);*/
startup2PacketBuf(&startup, &pacBuf);
pacBuf.msgtype = (MsgType) htonl(msgtype);
status = packetSend(port, &pacBuf, sizeof(PacketBuf), BLOCKING);
if (status == STATUS_ERROR)
{
sprintf(conn->errorMessage,
"connectDB() -- couldn't send complete packet: errno=%d\n%s\n", errno, strerror(errno));
goto connect_errReturn;
}
/* authenticate as required */
if (fe_sendauth(msgtype, port, conn->pghost,
conn->pguser, conn->pgpass,
conn->errorMessage) != STATUS_OK)
{
(void) sprintf(conn->errorMessage,
"connectDB() -- authentication failed with %s\n",
conn->pghost);
goto connect_errReturn;
}
/* free the password so it's not hanging out in memory forever */
if (conn->pgpass != NULL)
{
free(conn->pgpass);
}
/* set up the socket file descriptors */
conn->Pfout = fdopen(port->sock, "w");
conn->Pfin = fdopen(dup(port->sock), "r");
conn->Pfout = fdopen(conn->sock, "w");
conn->Pfin = fdopen(dup(conn->sock), "r");
if ((conn->Pfout == NULL) || (conn->Pfin == NULL))
{
(void) sprintf(conn->errorMessage,
@@ -678,19 +570,92 @@ connectDB(PGconn *conn)
goto connect_errReturn;
}
conn->port = port;
/* Send the startup packet. */
if (packetSend(conn, (char *)&sp, sizeof(StartupPacket)) != STATUS_OK)
{
sprintf(conn->errorMessage,
"connectDB() -- couldn't send complete packet: errno=%d\n%s\n", errno, strerror(errno));
goto connect_errReturn;
}
/*
* Get the response from the backend, either an error message or an
* authentication request.
*/
do
{
int beresp;
if ((beresp = pqGetc(conn->Pfin, conn->Pfdebug)) == EOF)
{
(void)sprintf(conn->errorMessage,
"connectDB() -- error getting authentication request\n");
goto connect_errReturn;
}
/* Handle errors. */
if (beresp == 'E')
{
pqGets(conn->errorMessage, sizeof (conn->errorMessage),
conn->Pfin, conn->Pfdebug);
goto connect_errReturn;
}
/* Check it was an authentication request. */
if (beresp != 'R')
{
(void)sprintf(conn->errorMessage,
"connectDB() -- expected authentication request\n");
goto connect_errReturn;
}
/* Get the type of request. */
if (pqGetInt((int *)&areq, 4, conn->Pfin, conn->Pfdebug))
{
(void)sprintf(conn->errorMessage,
"connectDB() -- error getting authentication request type\n");
goto connect_errReturn;
}
/* Get the password salt if there is one. */
if (areq == AUTH_REQ_CRYPT &&
pqGetnchar(conn->salt, sizeof (conn->salt),
conn->Pfin, conn->Pfdebug))
{
(void)sprintf(conn->errorMessage,
"connectDB() -- error getting password salt\n");
goto connect_errReturn;
}
/* Respond to the request. */
if (fe_sendauth(areq, conn, conn->pghost, conn->pgpass,
conn->errorMessage) != STATUS_OK)
goto connect_errReturn;
}
while (areq != AUTH_REQ_OK);
/* free the password so it's not hanging out in memory forever */
if (conn->pgpass != NULL)
{
free(conn->pgpass);
}
return CONNECTION_OK;
connect_errReturn:
/*
* Igor/6/3/97 - We need to free it here...otherwise the function
* returns without setting conn->port to port. Because of that any way
* of referencing this variable will be lost and it's allocated memory
* will not be freed.
*/
free(port); /* PURIFY */
return CONNECTION_BAD;
}
@@ -746,8 +711,6 @@ freePGconn(PGconn *conn)
free(conn->pguser);
if (conn->notifyList)
DLFreeList(conn->notifyList);
if (conn->port)
free(conn->port);
free(conn);
}
@@ -845,112 +808,27 @@ PQreset(PGconn *conn)
*
* RETURNS: STATUS_ERROR if the write fails, STATUS_OK otherwise.
* SIDE_EFFECTS: may block.
* NOTES: Non-blocking writes would significantly complicate
* buffer management. For now, we're not going to do it.
*
*/
int
packetSend(Port *port,
PacketBuf *buf,
PacketLen len,
bool nonBlocking)
packetSend(PGconn *conn,
char *buf,
size_t len)
{
PacketLen doneLen = write(port->sock, buf, len);
/* Send the total packet size. */
if (doneLen < len)
{
return (STATUS_ERROR);
}
return (STATUS_OK);
if (pqPutInt(4 + len, 4, conn->Pfout, conn->Pfdebug))
return STATUS_ERROR;
/* Send the packet itself. */
if (pqPutnchar(buf, len, conn->Pfout, conn->Pfdebug))
return STATUS_ERROR;
pqFlush(conn->Pfout, conn->Pfdebug);
return STATUS_OK;
}
/*
* packetReceive()
*
This is a less stringent PacketReceive(), defined in backend/libpq/pqpacket.c
We define it here to avoid linking in all of libpq.a
* packetReceive -- receive a packet on a port
*
* RETURNS: STATUS_ERROR if the read fails, STATUS_OK otherwise.
* SIDE_EFFECTS: may block.
* NOTES: Non-blocking reads would significantly complicate
* buffer management. For now, we're not going to do it.
*
*/
int
packetReceive(Port *port, PacketBuf *buf, bool nonBlocking) {
PacketLen max_size = sizeof(PacketBuf);
PacketLen cc; /* character count -- recvd */
PacketLen packetLen;
int addrLen = sizeof(struct sockaddr_in);
int hdrLen;
int msgLen;
/* Read the packet length into the PacketBuf
*/
hdrLen = sizeof(PacketLen);
cc = recvfrom(port->sock, (char*)&packetLen, hdrLen, 0, (struct sockaddr*)&port->raddr, &addrLen);
if (cc < 0)
return STATUS_ERROR;
else if (!cc)
return STATUS_INVALID;
else if (cc < hdrLen)
return STATUS_NOT_DONE;
/* convert to local form of integer and check for oversized packet
*/
buf->len = packetLen;
if ((packetLen = ntohl(packetLen)) > max_size) {
port->nBytes = packetLen;
return STATUS_INVALID;
}
/* fetch the rest of the message
*/
msgLen = packetLen - cc;
cc = recvfrom(port->sock, (char*)&buf->msgtype, msgLen, 0, (struct sockaddr*)&port->raddr, &addrLen);
if (cc < 0)
return STATUS_ERROR;
else if (!cc)
return STATUS_INVALID;
else if (cc < msgLen)
return STATUS_NOT_DONE;
return STATUS_OK;
}
/*
* startup2PacketBuf()
*
* this is just like StartupInfo2Packet(), defined in backend/libpq/pqpacket.c
* but we repeat it here so we don't have to link in libpq.a
*
* converts a StartupInfo structure to a PacketBuf
*/
static void
startup2PacketBuf(StartupInfo *s, PacketBuf *res)
{
char *tmp;
/* res = (PacketBuf*)malloc(sizeof(PacketBuf)); */
res->len = htonl(sizeof(PacketBuf));
/* use \n to delimit the strings */
res->data[0] = '\0';
tmp = res->data;
strncpy(tmp, s->database, sizeof(s->database));
tmp += sizeof(s->database);
strncpy(tmp, s->user, sizeof(s->user));
tmp += sizeof(s->user);
strncpy(tmp, s->options, sizeof(s->options));
tmp += sizeof(s->options);
strncpy(tmp, s->execFile, sizeof(s->execFile));
tmp += sizeof(s->execFile);
strncpy(tmp, s->tty, sizeof(s->tty));
}
/* ----------------
* Conninfo parser routine

View File

@@ -6,26 +6,23 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: fe-connect.h,v 1.5 1997/12/04 00:28:13 scrappy Exp $
* $Id: fe-connect.h,v 1.6 1998/01/26 01:42:30 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef FE_CONNECT_H
#define FE_CONNECT_H
#include <sys/types.h>
#include "libpq-fe.h"
/*----------------------------------------------------------------
* Common routines and definitions
*----------------------------------------------------------------
*/
extern int packetSend(Port *port, PacketBuf *buf, PacketLen len, bool nonBlocking);
extern int packetReceive(Port *port, PacketBuf *buf, bool nonBlocking);
int packetSend(PGconn *conn, char *buf, size_t len);
#endif /* FE_CONNECT_H */
#ifndef FE_CONNECT_H
#define FE_CONNECT_H
int packetSend(Port *port, PacketBuf *buf, PacketLen len, bool nonBlocking);
int packetReceive(Port *port, PacketBuf *buf, bool nonBlocking);
#endif

View File

@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.45 1997/12/23 20:00:06 thomas Exp $
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.46 1998/01/26 01:42:35 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
@@ -168,7 +168,7 @@ getTuple(PGconn *conn, PGresult *result, int binary)
if ((nfields % BYTELEN) > 0)
nbytes++;
if (pqGetnchar(bitmap, nbytes, pfin, pfdebug) == 1)
if (nbytes >= MAX_FIELDS || pqGetnchar(bitmap, nbytes, pfin, pfdebug) == 1)
{
sprintf(conn->errorMessage,
"Error reading null-values bitmap from row data stream\n");
@@ -189,10 +189,10 @@ getTuple(PGconn *conn, PGresult *result, int binary)
else
{
/* get the value length (the first four bytes are for length) */
pqGetInt(&vlen, VARHDRSZ, pfin, pfdebug);
pqGetInt(&vlen, 4, pfin, pfdebug);
if (binary == 0)
{
vlen = vlen - VARHDRSZ;
vlen = vlen - 4;
}
if (vlen < 0)
vlen = 0;

View File

@@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.8 1997/09/08 21:55:44 momjian Exp $
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.9 1998/01/26 01:42:36 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
@@ -51,38 +51,28 @@ pqGetc(FILE *fin, FILE *debug)
int
pqPutnchar(const char *s, int len, FILE *f, FILE *debug)
{
if (f == NULL)
return 1;
if (debug)
fprintf(debug, "To backend> %s\n", s);
if (fwrite(s, 1, len, f) != len)
return 1;
return 0;
return (pqPutNBytes(s, len, f) == EOF ? 1 : 0);
}
/* --------------------------------------------------------------------- */
/* pqGetnchar:
get a string of exactly len length from stream f
get a string of exactly len bytes in buffer s (which must be 1 byte
longer) from stream f and terminate it with a '\0'.
*/
int
pqGetnchar(char *s, int len, FILE *f, FILE *debug)
{
int cnt;
int status;
if (f == NULL)
return 1;
cnt = fread(s, 1, len, f);
s[cnt] = '\0';
/* mjl: actually needs up to len+1 bytes, is this okay? XXX */
status = pqGetNBytes(s, len, f);
if (debug)
fprintf(debug, "From backend (%d)> %s\n", len, s);
return 0;
return (status == EOF ? 1 : 0);
}
/* --------------------------------------------------------------------- */
@@ -92,21 +82,14 @@ pqGetnchar(char *s, int len, FILE *f, FILE *debug)
int
pqGets(char *s, int len, FILE *f, FILE *debug)
{
int c;
const char *str = s;
int status;
if (f == NULL)
return 1;
while (len-- && (c = getc(f)) != EOF && c)
*s++ = c;
*s = '\0';
/* mjl: actually needs up to len+1 bytes, is this okay? XXX */
status = pqGetString(s, len, f);
if (debug)
fprintf(debug, "From backend> \"%s\"\n", str);
fprintf(debug, "From backend> \"%s\"\n", s);
return 0;
return (status == EOF ? 1 : 0);
}
/* --------------------------------------------------------------------- */
@@ -173,20 +156,13 @@ pqGetInt(int *result, int bytes, FILE *f, FILE *debug)
int
pqPuts(const char *s, FILE *f, FILE *debug)
{
if (f == NULL)
if (pqPutString(s, f) == EOF)
return 1;
if (fputs(s, f) == EOF)
return 1;
fputc('\0', f); /* important to send an ending \0 since
* backend expects it */
fflush(f);
if (debug)
{
fprintf(debug, "To backend> %s\n", s);
}
return 0;
}

View File

@@ -6,7 +6,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: libpq-fe.h,v 1.24 1997/12/04 00:28:15 scrappy Exp $
* $Id: libpq-fe.h,v 1.25 1998/01/26 01:42:37 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
@@ -138,13 +138,15 @@ extern "C"
FILE *Pfin;
FILE *Pfout;
FILE *Pfdebug;
void *port; /* really a Port* */
int sock; /* The socket */
SockAddr laddr; /* Local address */
SockAddr raddr; /* Remote address */
char salt[2];
int asyncNotifyWaiting;
Dllist *notifyList;
char *pguser; /* Postgres username of user who is
* connected */
char *pgpass;
char *pgauth;
PGlobjfuncs *lobjfuncs; /* Backend function OID's for large object
* access */
} PGconn;