diff options
| author | Marc G. Fournier | 1998-01-26 01:42:53 +0000 |
|---|---|---|
| committer | Marc G. Fournier | 1998-01-26 01:42:53 +0000 |
| commit | d5bbe2aca55bc833e38c768d7f82c129b8b70c83 (patch) | |
| tree | 47f4e1ecb3277869bb276e5433df335d920d1baf /src/interfaces/libpq | |
| parent | 91d983aa1140e3ae109684ff7c916583ed059e0e (diff) | |
From: Phil Thompson <phil@river-bank.demon.co.uk>
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.
Diffstat (limited to 'src/interfaces/libpq')
| -rw-r--r-- | src/interfaces/libpq/Makefile.in | 13 | ||||
| -rw-r--r-- | src/interfaces/libpq/fe-auth.c | 81 | ||||
| -rw-r--r-- | src/interfaces/libpq/fe-auth.h | 10 | ||||
| -rw-r--r-- | src/interfaces/libpq/fe-connect.c | 354 | ||||
| -rw-r--r-- | src/interfaces/libpq/fe-connect.h | 17 | ||||
| -rw-r--r-- | src/interfaces/libpq/fe-exec.c | 8 | ||||
| -rw-r--r-- | src/interfaces/libpq/fe-misc.c | 48 | ||||
| -rw-r--r-- | src/interfaces/libpq/libpq-fe.h | 8 |
8 files changed, 208 insertions, 331 deletions
diff --git a/src/interfaces/libpq/Makefile.in b/src/interfaces/libpq/Makefile.in index dd9c774a118..5f9c26d2db6 100644 --- a/src/interfaces/libpq/Makefile.in +++ b/src/interfaces/libpq/Makefile.in @@ -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 diff --git a/src/interfaces/libpq/fe-auth.c b/src/interfaces/libpq/fe-auth.c index 8f96230f02d..7f25afcb38e 100644 --- a/src/interfaces/libpq/fe-auth.c +++ b/src/interfaces/libpq/fe-auth.c @@ -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); } diff --git a/src/interfaces/libpq/fe-auth.h b/src/interfaces/libpq/fe-auth.h index 6f188a541ec..e4676fcd97b 100644 --- a/src/interfaces/libpq/fe-auth.h +++ b/src/interfaces/libpq/fe-auth.h @@ -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 */ diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index 37dd88d425d..ee95ac59de5 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -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,81 +559,93 @@ 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) + /* set up the socket file descriptors */ + conn->Pfout = fdopen(conn->sock, "w"); + conn->Pfin = fdopen(dup(conn->sock), "r"); + if ((conn->Pfout == NULL) || (conn->Pfin == NULL)) + { + (void) sprintf(conn->errorMessage, + "connectDB() -- fdopen() failed: errno=%d\n%s\n", + errno, strerror(errno)); + goto connect_errReturn; + } + + /* 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; } - /* authenticate as required */ - if (fe_sendauth(msgtype, port, conn->pghost, - conn->pguser, conn->pgpass, - conn->errorMessage) != STATUS_OK) + /* + * Get the response from the backend, either an error message or an + * authentication request. + */ + + do { - (void) sprintf(conn->errorMessage, - "connectDB() -- authentication failed with %s\n", - conn->pghost); - goto connect_errReturn; + 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) @@ -667,30 +653,9 @@ connectDB(PGconn *conn) free(conn->pgpass); } - /* set up the socket file descriptors */ - conn->Pfout = fdopen(port->sock, "w"); - conn->Pfin = fdopen(dup(port->sock), "r"); - if ((conn->Pfout == NULL) || (conn->Pfin == NULL)) - { - (void) sprintf(conn->errorMessage, - "connectDB() -- fdopen() failed: errno=%d\n%s\n", - errno, strerror(errno)); - goto connect_errReturn; - } - - conn->port = port; - 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,113 +808,28 @@ 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; -/* - * 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 + /* Send the packet itself. */ - * 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; -} + if (pqPutnchar(buf, len, conn->Pfout, conn->Pfdebug)) + return STATUS_ERROR; -/* - * 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; + pqFlush(conn->Pfout, conn->Pfdebug); -/* 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)); + return STATUS_OK; } + /* ---------------- * Conninfo parser routine * ---------------- diff --git a/src/interfaces/libpq/fe-connect.h b/src/interfaces/libpq/fe-connect.h index 7a68e3dedcd..999ae05dac4 100644 --- a/src/interfaces/libpq/fe-connect.h +++ b/src/interfaces/libpq/fe-connect.h @@ -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 diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c index 1f452ffe2d1..b9517cebbf2 100644 --- a/src/interfaces/libpq/fe-exec.c +++ b/src/interfaces/libpq/fe-exec.c @@ -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; diff --git a/src/interfaces/libpq/fe-misc.c b/src/interfaces/libpq/fe-misc.c index 9f5fd907b54..d1c18ee05ae 100644 --- a/src/interfaces/libpq/fe-misc.c +++ b/src/interfaces/libpq/fe-misc.c @@ -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; - - if (f == NULL) - return 1; + int status; - 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; - - if (f == NULL) - return 1; + int status; - 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; } diff --git a/src/interfaces/libpq/libpq-fe.h b/src/interfaces/libpq/libpq-fe.h index ce54af85b04..933c3034051 100644 --- a/src/interfaces/libpq/libpq-fe.h +++ b/src/interfaces/libpq/libpq-fe.h @@ -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; |
