1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-03 09:13:20 +03:00

Massive commit to run PGINDENT on all *.c and *.h files.

This commit is contained in:
Bruce Momjian
1997-09-07 05:04:48 +00:00
parent 8fecd4febf
commit 1ccd423235
687 changed files with 150775 additions and 136888 deletions

View File

@@ -1,65 +1,65 @@
/*-------------------------------------------------------------------------
*
* auth.c--
* Routines to handle network authentication
* Routines to handle network authentication
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.14 1997/08/19 21:31:23 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.15 1997/09/07 04:42:09 momjian Exp $
*
*-------------------------------------------------------------------------
*/
/*
* INTERFACE ROUTINES
*
* backend (postmaster) routines:
* be_recvauth receive authentication information
* be_setauthsvc do/do not permit an authentication service
* be_getauthsvc is an authentication service permitted?
* backend (postmaster) routines:
* be_recvauth receive authentication information
* be_setauthsvc do/do not permit an authentication service
* be_getauthsvc is an authentication service permitted?
*
* NOTES
* To add a new authentication system:
* 0. If you can't do your authentication over an existing socket,
* you lose -- get ready to hack around this framework instead of
* using it. Otherwise, you can assume you have an initialized
* and empty connection to work with. (Please don't leave leftover
* gunk in the connection after the authentication transactions, or
* the POSTGRES routines that follow will be very unhappy.)
* 1. Write a set of routines that:
* let a client figure out what user/principal name to use
* send authentication information (client side)
* receive authentication information (server side)
* You can include both routines in this file, using #ifdef FRONTEND
* to separate them.
* 2. Edit libpq/pqcomm.h and assign a MsgType for your protocol.
* 3. Edit the static "struct authsvc" array and the generic
* {be,fe}_{get,set}auth{name,svc} routines in this file to reflect
* the new service. You may have to change the arguments of these
* routines; they basically just reflect what Kerberos v4 needs.
* 4. Hack on src/{,bin}/Makefile.global and src/{backend,libpq}/Makefile
* to add library and CFLAGS hooks -- basically, grep the Makefile
* hierarchy for KRBVERS to see where you need to add things.
* NOTES
* To add a new authentication system:
* 0. If you can't do your authentication over an existing socket,
* you lose -- get ready to hack around this framework instead of
* using it. Otherwise, you can assume you have an initialized
* and empty connection to work with. (Please don't leave leftover
* gunk in the connection after the authentication transactions, or
* the POSTGRES routines that follow will be very unhappy.)
* 1. Write a set of routines that:
* let a client figure out what user/principal name to use
* send authentication information (client side)
* receive authentication information (server side)
* You can include both routines in this file, using #ifdef FRONTEND
* to separate them.
* 2. Edit libpq/pqcomm.h and assign a MsgType for your protocol.
* 3. Edit the static "struct authsvc" array and the generic
* {be,fe}_{get,set}auth{name,svc} routines in this file to reflect
* the new service. You may have to change the arguments of these
* routines; they basically just reflect what Kerberos v4 needs.
* 4. Hack on src/{,bin}/Makefile.global and src/{backend,libpq}/Makefile
* to add library and CFLAGS hooks -- basically, grep the Makefile
* hierarchy for KRBVERS to see where you need to add things.
*
* Send mail to post_hackers@postgres.Berkeley.EDU if you have to make
* any changes to arguments, etc. Context diffs would be nice, too.
* Send mail to post_hackers@postgres.Berkeley.EDU if you have to make
* any changes to arguments, etc. Context diffs would be nice, too.
*
* Someday, this cruft will go away and magically be replaced by a
* nice interface based on the GSS API or something. For now, though,
* there's no (stable) UNIX security API to work with...
* Someday, this cruft will go away and magically be replaced by a
* nice interface based on the GSS API or something. For now, though,
* there's no (stable) UNIX security API to work with...
*
*/
#include <stdio.h>
#include <string.h>
#include <sys/param.h> /* for MAXHOSTNAMELEN on most */
#include <sys/param.h> /* for MAXHOSTNAMELEN on most */
#ifndef MAXHOSTNAMELEN
#include <netdb.h> /* for MAXHOSTNAMELEN on some */
#include <netdb.h> /* for MAXHOSTNAMELEN on some */
#endif
#include <pwd.h>
#include <ctype.h> /* isspace() declaration */
#include <ctype.h> /* isspace() declaration */
#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 <arpa/inet.h>
@@ -72,19 +72,19 @@
#include <libpq/hba.h>
#include <libpq/password.h>
static int be_getauthsvc(MsgType msgtype);
static int be_getauthsvc(MsgType msgtype);
/*----------------------------------------------------------------
* common definitions for generic fe/be routines
*----------------------------------------------------------------
*/
struct authsvc {
char name[16]; /* service nickname (for command line) */
MsgType msgtype; /* startup packet header type */
int allowed; /* initially allowed (before command line
* option parsing)?
*/
struct authsvc
{
char name[16]; /* service nickname (for command line) */
MsgType msgtype; /* startup packet header type */
int allowed; /* initially allowed (before command line
* option parsing)? */
};
/*
@@ -99,9 +99,11 @@ struct authsvc {
*/
#if defined(HBA)
static int useHostBasedAuth = 1;
static int useHostBasedAuth = 1;
#else
static int useHostBasedAuth = 0;
static int useHostBasedAuth = 0;
#endif
#if defined(KRB4) || defined(KRB5) || defined(HBA)
@@ -111,19 +113,19 @@ static int useHostBasedAuth = 0;
#endif
static struct authsvc authsvcs[] = {
{ "unauth", STARTUP_UNAUTH_MSG, UNAUTH_ALLOWED },
{ "hba", STARTUP_HBA_MSG, 1 },
{ "krb4", STARTUP_KRB4_MSG, 1 },
{ "krb5", STARTUP_KRB5_MSG, 1 },
#if defined(KRB5)
{ "kerberos", STARTUP_KRB5_MSG, 1 },
{"unauth", STARTUP_UNAUTH_MSG, UNAUTH_ALLOWED},
{"hba", STARTUP_HBA_MSG, 1},
{"krb4", STARTUP_KRB4_MSG, 1},
{"krb5", STARTUP_KRB5_MSG, 1},
#if defined(KRB5)
{"kerberos", STARTUP_KRB5_MSG, 1},
#else
{ "kerberos", STARTUP_KRB4_MSG, 1 },
{"kerberos", STARTUP_KRB4_MSG, 1},
#endif
{ "password", STARTUP_PASSWORD_MSG, 1 }
{"password", STARTUP_PASSWORD_MSG, 1}
};
static n_authsvcs = sizeof(authsvcs) / sizeof(struct authsvc);
static n_authsvcs = sizeof(authsvcs) / sizeof(struct authsvc);
#ifdef KRB4
/* This has to be ifdef'd out because krb.h does exist. This needs
@@ -138,11 +140,11 @@ static n_authsvcs = sizeof(authsvcs) / sizeof(struct authsvc);
#ifdef FRONTEND
/* moves to src/libpq/fe-auth.c */
#else /* !FRONTEND */
#else /* !FRONTEND */
/*
* pg_krb4_recvauth -- server routine to receive authentication information
* from the client
* from the client
*
* Nothing unusual here, except that we compare the username obtained from
* the client's setup packet to the authenticated name. (We have to retain
@@ -151,77 +153,82 @@ static n_authsvcs = sizeof(authsvcs) / sizeof(struct authsvc);
*/
static int
pg_krb4_recvauth(int sock,
struct sockaddr_in *laddr,
struct sockaddr_in *raddr,
char *username)
struct sockaddr_in * laddr,
struct sockaddr_in * raddr,
char *username)
{
long krbopts = 0; /* one-way authentication */
KTEXT_ST clttkt;
char instance[INST_SZ];
AUTH_DAT auth_data;
Key_schedule key_sched;
char version[KRB_SENDAUTH_VLEN];
int status;
strcpy(instance, "*"); /* don't care, but arg gets expanded anyway */
status = krb_recvauth(krbopts,
sock,
&clttkt,
PG_KRB_SRVNAM,
instance,
raddr,
laddr,
&auth_data,
PG_KRB_SRVTAB,
key_sched,
version);
if (status != KSUCCESS) {
sprintf(PQerrormsg,
"pg_krb4_recvauth: kerberos error: %s\n",
krb_err_txt[status]);
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return(STATUS_ERROR);
}
if (strncmp(version, PG_KRB4_VERSION, KRB_SENDAUTH_VLEN)) {
sprintf(PQerrormsg,
"pg_krb4_recvauth: protocol version != \"%s\"\n",
PG_KRB4_VERSION);
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return(STATUS_ERROR);
}
if (username && *username &&
strncmp(username, auth_data.pname, NAMEDATALEN)) {
sprintf(PQerrormsg,
"pg_krb4_recvauth: name \"%s\" != \"%s\"\n",
username,
auth_data.pname);
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return(STATUS_ERROR);
}
return(STATUS_OK);
long krbopts = 0;/* one-way authentication */
KTEXT_ST clttkt;
char instance[INST_SZ];
AUTH_DAT auth_data;
Key_schedule key_sched;
char version[KRB_SENDAUTH_VLEN];
int status;
strcpy(instance, "*"); /* don't care, but arg gets expanded
* anyway */
status = krb_recvauth(krbopts,
sock,
&clttkt,
PG_KRB_SRVNAM,
instance,
raddr,
laddr,
&auth_data,
PG_KRB_SRVTAB,
key_sched,
version);
if (status != KSUCCESS)
{
sprintf(PQerrormsg,
"pg_krb4_recvauth: kerberos error: %s\n",
krb_err_txt[status]);
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return (STATUS_ERROR);
}
if (strncmp(version, PG_KRB4_VERSION, KRB_SENDAUTH_VLEN))
{
sprintf(PQerrormsg,
"pg_krb4_recvauth: protocol version != \"%s\"\n",
PG_KRB4_VERSION);
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return (STATUS_ERROR);
}
if (username && *username &&
strncmp(username, auth_data.pname, NAMEDATALEN))
{
sprintf(PQerrormsg,
"pg_krb4_recvauth: name \"%s\" != \"%s\"\n",
username,
auth_data.pname);
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return (STATUS_ERROR);
}
return (STATUS_OK);
}
#endif /* !FRONTEND */
#endif /* !FRONTEND */
#else
static int
pg_krb4_recvauth(int sock,
struct sockaddr_in *laddr,
struct sockaddr_in *raddr,
char *username)
struct sockaddr_in * laddr,
struct sockaddr_in * raddr,
char *username)
{
sprintf(PQerrormsg,
"pg_krb4_recvauth: Kerberos not implemented on this "
"server.\n");
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
sprintf(PQerrormsg,
"pg_krb4_recvauth: Kerberos not implemented on this "
"server.\n");
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return(STATUS_ERROR);
return (STATUS_ERROR);
}
#endif /* KRB4 */
#endif /* KRB4 */
#ifdef KRB5
@@ -237,37 +244,37 @@ return(STATUS_ERROR);
/*
* pg_an_to_ln -- return the local name corresponding to an authentication
* name
* name
*
* XXX Assumes that the first aname component is the user name. This is NOT
* necessarily so, since an aname can actually be something out of your
* worst X.400 nightmare, like
* ORGANIZATION=U. C. Berkeley/NAME=Paul M. Aoki@CS.BERKELEY.EDU
* Note that the MIT an_to_ln code does the same thing if you don't
* provide an aname mapping database...it may be a better idea to use
* krb5_an_to_ln, except that it punts if multiple components are found,
* and we can't afford to punt.
* necessarily so, since an aname can actually be something out of your
* worst X.400 nightmare, like
* ORGANIZATION=U. C. Berkeley/NAME=Paul M. Aoki@CS.BERKELEY.EDU
* Note that the MIT an_to_ln code does the same thing if you don't
* provide an aname mapping database...it may be a better idea to use
* krb5_an_to_ln, except that it punts if multiple components are found,
* and we can't afford to punt.
*/
static char *
static char *
pg_an_to_ln(char *aname)
{
char *p;
if ((p = strchr(aname, '/')) || (p = strchr(aname, '@')))
*p = '\0';
return(aname);
char *p;
if ((p = strchr(aname, '/')) || (p = strchr(aname, '@')))
*p = '\0';
return (aname);
}
#ifdef FRONTEND
/* moves to src/libpq/fe-auth.c */
#else /* !FRONTEND */
#else /* !FRONTEND */
/*
* pg_krb5_recvauth -- server routine to receive authentication information
* from the client
* from the client
*
* We still need to compare the username obtained from the client's setup
* packet to the authenticated name, as described in pg_krb4_recvauth. This
* packet to the authenticated name, as described in pg_krb4_recvauth. This
* is a bit more problematic in v5, as described above in pg_an_to_ln.
*
* In addition, as described above in pg_krb5_sendauth, we still need to
@@ -286,315 +293,348 @@ pg_an_to_ln(char *aname)
*/
static int
pg_krb5_recvauth(int sock,
struct sockaddr_in *laddr,
struct sockaddr_in *raddr,
char *username)
struct sockaddr_in * laddr,
struct sockaddr_in * raddr,
char *username)
{
char servbuf[MAXHOSTNAMELEN + 1 +
sizeof(PG_KRB_SRVNAM)];
char *hostp, *kusername = (char *) NULL;
krb5_error_code code;
krb5_principal client, server;
krb5_address sender_addr;
krb5_rdreq_key_proc keyproc = (krb5_rdreq_key_proc) NULL;
krb5_pointer keyprocarg = (krb5_pointer) NULL;
/*
* Set up server side -- since we have no ticket file to make this
* easy, we construct our own name and parse it. See note on
* canonicalization above.
*/
strcpy(servbuf, PG_KRB_SRVNAM);
*(hostp = servbuf + (sizeof(PG_KRB_SRVNAM) - 1)) = '/';
if (gethostname(++hostp, MAXHOSTNAMELEN) < 0)
strcpy(hostp, "localhost");
if (hostp = strchr(hostp, '.'))
*hostp = '\0';
if (code = krb5_parse_name(servbuf, &server)) {
sprintf(PQerrormsg,
"pg_krb5_recvauth: Kerberos error %d in krb5_parse_name\n",
code);
com_err("pg_krb5_recvauth", code, "in krb5_parse_name");
return(STATUS_ERROR);
}
/*
* krb5_sendauth needs this to verify the address in the client
* authenticator.
*/
sender_addr.addrtype = raddr->sin_family;
sender_addr.length = sizeof(raddr->sin_addr);
sender_addr.contents = (krb5_octet *) &(raddr->sin_addr);
if (strcmp(PG_KRB_SRVTAB, "")) {
keyproc = krb5_kt_read_service_key;
keyprocarg = PG_KRB_SRVTAB;
}
if (code = krb5_recvauth((krb5_pointer) &sock,
PG_KRB5_VERSION,
server,
&sender_addr,
(krb5_pointer) NULL,
keyproc,
keyprocarg,
(char *) NULL,
(krb5_int32 *) NULL,
&client,
(krb5_ticket **) NULL,
(krb5_authenticator **) NULL)) {
sprintf(PQerrormsg,
"pg_krb5_recvauth: Kerberos error %d in krb5_recvauth\n",
code);
com_err("pg_krb5_recvauth", code, "in krb5_recvauth");
char servbuf[MAXHOSTNAMELEN + 1 +
sizeof(PG_KRB_SRVNAM)];
char *hostp,
*kusername = (char *) NULL;
krb5_error_code code;
krb5_principal client,
server;
krb5_address sender_addr;
krb5_rdreq_key_proc keyproc = (krb5_rdreq_key_proc) NULL;
krb5_pointer keyprocarg = (krb5_pointer) NULL;
/*
* Set up server side -- since we have no ticket file to make this
* easy, we construct our own name and parse it. See note on
* canonicalization above.
*/
strcpy(servbuf, PG_KRB_SRVNAM);
*(hostp = servbuf + (sizeof(PG_KRB_SRVNAM) - 1)) = '/';
if (gethostname(++hostp, MAXHOSTNAMELEN) < 0)
strcpy(hostp, "localhost");
if (hostp = strchr(hostp, '.'))
*hostp = '\0';
if (code = krb5_parse_name(servbuf, &server))
{
sprintf(PQerrormsg,
"pg_krb5_recvauth: Kerberos error %d in krb5_parse_name\n",
code);
com_err("pg_krb5_recvauth", code, "in krb5_parse_name");
return (STATUS_ERROR);
}
/*
* krb5_sendauth needs this to verify the address in the client
* authenticator.
*/
sender_addr.addrtype = raddr->sin_family;
sender_addr.length = sizeof(raddr->sin_addr);
sender_addr.contents = (krb5_octet *) & (raddr->sin_addr);
if (strcmp(PG_KRB_SRVTAB, ""))
{
keyproc = krb5_kt_read_service_key;
keyprocarg = PG_KRB_SRVTAB;
}
if (code = krb5_recvauth((krb5_pointer) & sock,
PG_KRB5_VERSION,
server,
&sender_addr,
(krb5_pointer) NULL,
keyproc,
keyprocarg,
(char *) NULL,
(krb5_int32 *) NULL,
&client,
(krb5_ticket **) NULL,
(krb5_authenticator **) NULL))
{
sprintf(PQerrormsg,
"pg_krb5_recvauth: Kerberos error %d in krb5_recvauth\n",
code);
com_err("pg_krb5_recvauth", code, "in krb5_recvauth");
krb5_free_principal(server);
return (STATUS_ERROR);
}
krb5_free_principal(server);
return(STATUS_ERROR);
}
krb5_free_principal(server);
/*
* The "client" structure comes out of the ticket and is therefore
* authenticated. Use it to check the username obtained from the
* postmaster startup packet.
*/
if ((code = krb5_unparse_name(client, &kusername))) {
sprintf(PQerrormsg,
"pg_krb5_recvauth: Kerberos error %d in krb5_unparse_name\n",
code);
com_err("pg_krb5_recvauth", code, "in krb5_unparse_name");
/*
* The "client" structure comes out of the ticket and is therefore
* authenticated. Use it to check the username obtained from the
* postmaster startup packet.
*/
if ((code = krb5_unparse_name(client, &kusername)))
{
sprintf(PQerrormsg,
"pg_krb5_recvauth: Kerberos error %d in krb5_unparse_name\n",
code);
com_err("pg_krb5_recvauth", code, "in krb5_unparse_name");
krb5_free_principal(client);
return (STATUS_ERROR);
}
krb5_free_principal(client);
return(STATUS_ERROR);
}
krb5_free_principal(client);
if (!kusername) {
sprintf(PQerrormsg,
"pg_krb5_recvauth: could not decode username\n");
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return(STATUS_ERROR);
}
kusername = pg_an_to_ln(kusername);
if (username && strncmp(username, kusername, NAMEDATALEN)) {
sprintf(PQerrormsg,
"pg_krb5_recvauth: name \"%s\" != \"%s\"\n",
username, kusername);
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
if (!kusername)
{
sprintf(PQerrormsg,
"pg_krb5_recvauth: could not decode username\n");
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return (STATUS_ERROR);
}
kusername = pg_an_to_ln(kusername);
if (username && strncmp(username, kusername, NAMEDATALEN))
{
sprintf(PQerrormsg,
"pg_krb5_recvauth: name \"%s\" != \"%s\"\n",
username, kusername);
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
free(kusername);
return (STATUS_ERROR);
}
free(kusername);
return(STATUS_ERROR);
}
free(kusername);
return(STATUS_OK);
return (STATUS_OK);
}
#endif /* !FRONTEND */
#endif /* !FRONTEND */
#else
static int
pg_krb5_recvauth(int sock,
struct sockaddr_in *laddr,
struct sockaddr_in *raddr,
char *username)
struct sockaddr_in * laddr,
struct sockaddr_in * raddr,
char *username)
{
sprintf(PQerrormsg,
"pg_krb5_recvauth: Kerberos not implemented on this "
"server.\n");
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return(STATUS_ERROR);
}
#endif /* KRB5 */
static int
pg_password_recvauth(Port *port, char *database, char *DataDir)
{
PacketBuf buf;
char *user, *password;
if(PacketReceive(port, &buf, BLOCKING) != STATUS_OK) {
sprintf(PQerrormsg,
"pg_password_recvauth: failed to receive authentication packet.\n");
"pg_krb5_recvauth: Kerberos not implemented on this "
"server.\n");
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return STATUS_ERROR;
}
user = buf.data;
password = buf.data + strlen(user) + 1;
return (STATUS_ERROR);
}
return verify_password(user, password, port, database, DataDir);
#endif /* KRB5 */
static int
pg_password_recvauth(Port * port, char *database, char *DataDir)
{
PacketBuf buf;
char *user,
*password;
if (PacketReceive(port, &buf, BLOCKING) != STATUS_OK)
{
sprintf(PQerrormsg,
"pg_password_recvauth: failed to receive authentication packet.\n");
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return STATUS_ERROR;
}
user = buf.data;
password = buf.data + strlen(user) + 1;
return verify_password(user, password, port, database, DataDir);
}
/*
* be_recvauth -- server demux routine for incoming authentication information
*/
int
be_recvauth(MsgType msgtype_arg, Port *port, char *username, StartupInfo* sp)
be_recvauth(MsgType msgtype_arg, Port * port, char *username, StartupInfo * sp)
{
MsgType msgtype;
MsgType msgtype;
/* A message type of STARTUP_MSG (which once upon a time was the only
startup message type) means user wants us to choose. "unauth" is
what used to be the only choice, but installation may choose "hba"
instead.
*/
if (msgtype_arg == STARTUP_MSG) {
if(useHostBasedAuth)
msgtype = STARTUP_HBA_MSG;
else
msgtype = STARTUP_UNAUTH_MSG;
} else
msgtype = msgtype_arg;
if (!username) {
sprintf(PQerrormsg,
"be_recvauth: no user name passed\n");
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return(STATUS_ERROR);
}
if (!port) {
sprintf(PQerrormsg,
"be_recvauth: no port structure passed\n");
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return(STATUS_ERROR);
}
switch (msgtype) {
case STARTUP_KRB4_MSG:
if (!be_getauthsvc(msgtype)) {
sprintf(PQerrormsg,
"be_recvauth: krb4 authentication disallowed\n");
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return(STATUS_ERROR);
}
if (pg_krb4_recvauth(port->sock, &port->laddr, &port->raddr,
username) != STATUS_OK) {
sprintf(PQerrormsg,
"be_recvauth: krb4 authentication failed\n");
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return(STATUS_ERROR);
}
break;
case STARTUP_KRB5_MSG:
if (!be_getauthsvc(msgtype)) {
sprintf(PQerrormsg,
"be_recvauth: krb5 authentication disallowed\n");
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return(STATUS_ERROR);
}
if (pg_krb5_recvauth(port->sock, &port->laddr, &port->raddr,
username) != STATUS_OK) {
sprintf(PQerrormsg,
"be_recvauth: krb5 authentication failed\n");
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return(STATUS_ERROR);
}
break;
case STARTUP_UNAUTH_MSG:
if (!be_getauthsvc(msgtype)) {
sprintf(PQerrormsg,
"be_recvauth: "
"unauthenticated connections disallowed\n");
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return(STATUS_ERROR);
}
break;
case STARTUP_HBA_MSG:
if (hba_recvauth(port, sp->database, sp->user, DataDir) != STATUS_OK) {
sprintf(PQerrormsg,
"be_recvauth: host-based authentication failed\n");
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return(STATUS_ERROR);
}
break;
case STARTUP_PASSWORD_MSG:
if(!be_getauthsvc(msgtype)) {
sprintf(PQerrormsg,
"be_recvauth: "
"plaintext password authentication disallowed\n");
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return(STATUS_ERROR);
/*
* A message type of STARTUP_MSG (which once upon a time was the only
* startup message type) means user wants us to choose. "unauth" is
* what used to be the only choice, but installation may choose "hba"
* instead.
*/
if (msgtype_arg == STARTUP_MSG)
{
if (useHostBasedAuth)
msgtype = STARTUP_HBA_MSG;
else
msgtype = STARTUP_UNAUTH_MSG;
}
if(pg_password_recvauth(port, sp->database, DataDir) != STATUS_OK) {
/* pg_password_recvauth or lower-level routines have already set */
/* the error message */
return(STATUS_ERROR);
else
msgtype = msgtype_arg;
if (!username)
{
sprintf(PQerrormsg,
"be_recvauth: no user name passed\n");
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return (STATUS_ERROR);
}
break;
default:
sprintf(PQerrormsg,
"be_recvauth: unrecognized message type: %d\n",
msgtype);
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return(STATUS_ERROR);
}
return(STATUS_OK);
if (!port)
{
sprintf(PQerrormsg,
"be_recvauth: no port structure passed\n");
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return (STATUS_ERROR);
}
switch (msgtype)
{
case STARTUP_KRB4_MSG:
if (!be_getauthsvc(msgtype))
{
sprintf(PQerrormsg,
"be_recvauth: krb4 authentication disallowed\n");
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return (STATUS_ERROR);
}
if (pg_krb4_recvauth(port->sock, &port->laddr, &port->raddr,
username) != STATUS_OK)
{
sprintf(PQerrormsg,
"be_recvauth: krb4 authentication failed\n");
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return (STATUS_ERROR);
}
break;
case STARTUP_KRB5_MSG:
if (!be_getauthsvc(msgtype))
{
sprintf(PQerrormsg,
"be_recvauth: krb5 authentication disallowed\n");
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return (STATUS_ERROR);
}
if (pg_krb5_recvauth(port->sock, &port->laddr, &port->raddr,
username) != STATUS_OK)
{
sprintf(PQerrormsg,
"be_recvauth: krb5 authentication failed\n");
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return (STATUS_ERROR);
}
break;
case STARTUP_UNAUTH_MSG:
if (!be_getauthsvc(msgtype))
{
sprintf(PQerrormsg,
"be_recvauth: "
"unauthenticated connections disallowed\n");
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return (STATUS_ERROR);
}
break;
case STARTUP_HBA_MSG:
if (hba_recvauth(port, sp->database, sp->user, DataDir) != STATUS_OK)
{
sprintf(PQerrormsg,
"be_recvauth: host-based authentication failed\n");
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return (STATUS_ERROR);
}
break;
case STARTUP_PASSWORD_MSG:
if (!be_getauthsvc(msgtype))
{
sprintf(PQerrormsg,
"be_recvauth: "
"plaintext password authentication disallowed\n");
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return (STATUS_ERROR);
}
if (pg_password_recvauth(port, sp->database, DataDir) != STATUS_OK)
{
/*
* pg_password_recvauth or lower-level routines have already
* set
*/
/* the error message */
return (STATUS_ERROR);
}
break;
default:
sprintf(PQerrormsg,
"be_recvauth: unrecognized message type: %d\n",
msgtype);
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return (STATUS_ERROR);
}
return (STATUS_OK);
}
/*
* be_setauthsvc -- enable/disable the authentication services currently
* selected for use by the backend
* selected for use by the backend
* be_getauthsvc -- returns whether a particular authentication system
* (indicated by its message type) is permitted by the
* current selections
* (indicated by its message type) is permitted by the
* current selections
*
* be_setauthsvc encodes the command-line syntax that
* -a "<service-name>"
* -a "<service-name>"
* enables a service, whereas
* -a "no<service-name>"
* -a "no<service-name>"
* disables it.
*/
void
be_setauthsvc(char *name)
{
int i, j;
int turnon = 1;
if (!name)
return;
if (!strncmp("no", name, 2)) {
turnon = 0;
name += 2;
}
if (name[0] == '\0')
return;
for (i = 0; i < n_authsvcs; ++i)
if (!strcmp(name, authsvcs[i].name)) {
for (j = 0; j < n_authsvcs; ++j)
if (authsvcs[j].msgtype == authsvcs[i].msgtype)
authsvcs[j].allowed = turnon;
break;
int i,
j;
int turnon = 1;
if (!name)
return;
if (!strncmp("no", name, 2))
{
turnon = 0;
name += 2;
}
if (i == n_authsvcs) {
sprintf(PQerrormsg,
"be_setauthsvc: invalid name %s, ignoring...\n",
name);
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
}
return;
if (name[0] == '\0')
return;
for (i = 0; i < n_authsvcs; ++i)
if (!strcmp(name, authsvcs[i].name))
{
for (j = 0; j < n_authsvcs; ++j)
if (authsvcs[j].msgtype == authsvcs[i].msgtype)
authsvcs[j].allowed = turnon;
break;
}
if (i == n_authsvcs)
{
sprintf(PQerrormsg,
"be_setauthsvc: invalid name %s, ignoring...\n",
name);
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
}
return;
}
static int
be_getauthsvc(MsgType msgtype)
{
int i;
for (i = 0; i < n_authsvcs; ++i)
if (msgtype == authsvcs[i].msgtype)
return(authsvcs[i].allowed);
return(0);
int i;
for (i = 0; i < n_authsvcs; ++i)
if (msgtype == authsvcs[i].msgtype)
return (authsvcs[i].allowed);
return (0);
}

View File

@@ -1,32 +1,32 @@
/*-------------------------------------------------------------------------
*
* be-dumpdata.c--
* support for collection of returned tuples from an internal
* PQ call into a backend buffer.
* support for collection of returned tuples from an internal
* PQ call into a backend buffer.
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/libpq/Attic/be-dumpdata.c,v 1.5 1997/08/18 20:52:31 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/libpq/Attic/be-dumpdata.c,v 1.6 1997/09/07 04:42:12 momjian Exp $
*
*-------------------------------------------------------------------------
*/
/*
* INTERFACE ROUTINES
* be_portalinit - initialize backend portal administration
* be_portalpush - add a portal to the top of the portal stack
* be_portalpop - remove portal on the top of the stack & return it
* be_currentportal - return the top portal on the portal stack
* be_newportal - return a new portal.
* be_portalinit - initialize backend portal expected to hold results.
* be_printtup - add a tuple to a backend portal
* be_portalinit - initialize backend portal administration
* be_portalpush - add a portal to the top of the portal stack
* be_portalpop - remove portal on the top of the stack & return it
* be_currentportal - return the top portal on the portal stack
* be_newportal - return a new portal.
* be_portalinit - initialize backend portal expected to hold results.
* be_printtup - add a tuple to a backend portal
*
* NOTES
* Since backend user-defined operators can call queries
* which in turn call user-defined operators can call queries...
* we have to keep track of portals on a stack. BeginCommand()
* puts portals on the stack and the PQ functions remove them.
* Since backend user-defined operators can call queries
* which in turn call user-defined operators can call queries...
* we have to keep track of portals on a stack. BeginCommand()
* puts portals on the stack and the PQ functions remove them.
*
*/
#include <string.h>
@@ -48,274 +48,288 @@
#include <access/printtup.h>
/* ----------------
* backend portal stack for recursive PQexec calls
* backend portal stack for recursive PQexec calls
* ----------------
*/
static Dllist *be_portalstack;
static Dllist *be_portalstack;
/* ----------------
* be_portalinit - initialize backend portal administration
* be_portalinit - initialize backend portal administration
*
* This is called once from InitPostgres() to initialize
* the portal stack.
* This is called once from InitPostgres() to initialize
* the portal stack.
* ----------------
*/
void
be_portalinit(void)
{
be_portalstack = DLNewList();
be_portalstack = DLNewList();
}
/* ----------------
* be_portalpush - add a portal to the top of the portal stack
* be_portalpush - add a portal to the top of the portal stack
*
* used by BeginCommand()
* used by BeginCommand()
* ----------------
*/
void
be_portalpush(PortalEntry *entry)
be_portalpush(PortalEntry * entry)
{
DLAddTail(be_portalstack, DLNewElem(entry));
DLAddTail(be_portalstack, DLNewElem(entry));
}
/* ----------------
* be_portalpop - remove the portal on the top of the stack & return it
* be_portalpop - remove the portal on the top of the stack & return it
*
* used by PQexec()
* used by PQexec()
* ----------------
*/
PortalEntry *
PortalEntry *
be_portalpop(void)
{
PortalEntry *p;
Dlelem* elt;
elt = DLRemTail(be_portalstack);
PortalEntry *p;
Dlelem *elt;
elt = DLRemTail(be_portalstack);
p = (elt ? (PortalEntry *) DLE_VAL(elt) : NULL);
DLFreeElem(elt);
return p;
p = (elt ? (PortalEntry*)DLE_VAL(elt) : NULL);
DLFreeElem(elt);
return p;
}
/* ----------------
* be_currentportal - return the top portal on the portal stack
* be_currentportal - return the top portal on the portal stack
*
* used by be_printtup()
* used by be_printtup()
* ----------------
*/
PortalEntry *
PortalEntry *
be_currentportal(void)
{
Dlelem* elt;
elt = DLGetTail(be_portalstack);
return (elt ? (PortalEntry*)DLE_VAL(elt) : NULL);
Dlelem *elt;
elt = DLGetTail(be_portalstack);
return (elt ? (PortalEntry *) DLE_VAL(elt) : NULL);
}
/* ----------------
* be_newportal - return a new portal.
* be_newportal - return a new portal.
*
* If the user-defined function does not specify a portal name,
* we generate a unique one. Names are generated from a combination
* of a postgres oid and an integer counter which is incremented
* every time we ask for a local portal.
* If the user-defined function does not specify a portal name,
* we generate a unique one. Names are generated from a combination
* of a postgres oid and an integer counter which is incremented
* every time we ask for a local portal.
*
* used by BeginCommand()
* used by BeginCommand()
* ----------------
*/
static Oid be_portaloid;
static Oid be_portaloid;
static u_int be_portalcnt = 0;
PortalEntry *
be_newportal(void)
PortalEntry *
be_newportal(void)
{
PortalEntry *entry;
char buf[PortalNameLength];
/* ----------------
* generate a new name
* ----------------
*/
if (be_portalcnt == 0)
be_portaloid = newoid();
be_portalcnt++;
sprintf(buf, "be_%d_%d", be_portaloid, be_portalcnt);
/* ----------------
* initialize the new portal entry and keep track
* of the current memory context for be_printtup().
* This is important - otherwise whatever we allocate
* will go away and the contents of the portal after
* PQexec() returns will be meaningless.
* ----------------
*/
entry = pbuf_setup(buf);
entry->portalcxt = (Pointer) CurrentMemoryContext;
return entry;
PortalEntry *entry;
char buf[PortalNameLength];
/* ----------------
* generate a new name
* ----------------
*/
if (be_portalcnt == 0)
be_portaloid = newoid();
be_portalcnt++;
sprintf(buf, "be_%d_%d", be_portaloid, be_portalcnt);
/* ----------------
* initialize the new portal entry and keep track
* of the current memory context for be_printtup().
* This is important - otherwise whatever we allocate
* will go away and the contents of the portal after
* PQexec() returns will be meaningless.
* ----------------
*/
entry = pbuf_setup(buf);
entry->portalcxt = (Pointer) CurrentMemoryContext;
return entry;
}
/* ----------------
* be_typeinit - initialize backend portal expected to hold
* query results.
* be_typeinit - initialize backend portal expected to hold
* query results.
*
* used by BeginCommand()
* used by BeginCommand()
* ----------------
*/
void
be_typeinit(PortalEntry *entry,
TupleDesc tupDesc,
int natts)
be_typeinit(PortalEntry * entry,
TupleDesc tupDesc,
int natts)
{
PortalBuffer *portal;
GroupBuffer *group;
int i;
AttributeTupleForm *attrs = tupDesc->attrs;
/* ----------------
* add a new portal group to the portal
* ----------------
*/
portal = entry->portal;
portal->no_groups++;
portal->groups = group = pbuf_addGroup(portal);
group->no_fields = natts;
/* ----------------
* initialize portal group type info
* ----------------
*/
if (natts > 0) {
group->types = pbuf_addTypes(natts);
for (i = 0; i < natts; ++i) {
strncpy(group->types[i].name, attrs[i]->attname.data, NAMEDATALEN);
group->types[i].adtid = attrs[i]->atttypid;
group->types[i].adtsize = attrs[i]->attlen;
PortalBuffer *portal;
GroupBuffer *group;
int i;
AttributeTupleForm *attrs = tupDesc->attrs;
/* ----------------
* add a new portal group to the portal
* ----------------
*/
portal = entry->portal;
portal->no_groups++;
portal->groups = group = pbuf_addGroup(portal);
group->no_fields = natts;
/* ----------------
* initialize portal group type info
* ----------------
*/
if (natts > 0)
{
group->types = pbuf_addTypes(natts);
for (i = 0; i < natts; ++i)
{
strncpy(group->types[i].name, attrs[i]->attname.data, NAMEDATALEN);
group->types[i].adtid = attrs[i]->atttypid;
group->types[i].adtsize = attrs[i]->attlen;
}
}
}
}
/* ----------------
* be_printtup - add a tuple to a backend portal
* be_printtup - add a tuple to a backend portal
*
* used indirectly by ExecRetrieve()
* used indirectly by ExecRetrieve()
*
* This code is pretty much copied from printtup(), dump_type()
* and dump_data(). -cim 2/12/91
* This code is pretty much copied from printtup(), dump_type()
* and dump_data(). -cim 2/12/91
* ----------------
*/
void
be_printtup(HeapTuple tuple, TupleDesc typeinfo)
{
int i;
char *attr;
bool isnull;
Oid typoutput;
PortalEntry *entry = NULL;
PortalBuffer *portal = NULL;
GroupBuffer *group = NULL ;
TupleBlock *tuples = NULL;
char **values;
int *lengths;
MemoryContext savecxt;
/* ----------------
* get the current portal and group
* ----------------
*/
entry = be_currentportal();
portal = entry->portal;
group = portal->groups;
/* ----------------
* switch to the portal's memory context so that
* the tuples we allocate are returned to the user.
* ----------------
*/
savecxt = MemoryContextSwitchTo((MemoryContext)entry->portalcxt);
/* ----------------
* If no tuple block yet, allocate one.
* If the current block is full, allocate another one.
* ----------------
*/
if (group->tuples == NULL) {
tuples = group->tuples = pbuf_addTuples();
tuples->tuple_index = 0;
} else {
tuples = group->tuples;
/* walk to the end of the linked list of TupleBlocks */
while (tuples->next)
tuples = tuples->next;
/* now, tuples is the last TupleBlock, check to see if it is full.
If so, allocate a new TupleBlock and add it to the end of
the chain */
if (tuples->tuple_index == TupleBlockSize) {
tuples->next = pbuf_addTuples();
tuples = tuples->next;
tuples->tuple_index = 0;
int i;
char *attr;
bool isnull;
Oid typoutput;
PortalEntry *entry = NULL;
PortalBuffer *portal = NULL;
GroupBuffer *group = NULL;
TupleBlock *tuples = NULL;
char **values;
int *lengths;
MemoryContext savecxt;
/* ----------------
* get the current portal and group
* ----------------
*/
entry = be_currentportal();
portal = entry->portal;
group = portal->groups;
/* ----------------
* switch to the portal's memory context so that
* the tuples we allocate are returned to the user.
* ----------------
*/
savecxt = MemoryContextSwitchTo((MemoryContext) entry->portalcxt);
/* ----------------
* If no tuple block yet, allocate one.
* If the current block is full, allocate another one.
* ----------------
*/
if (group->tuples == NULL)
{
tuples = group->tuples = pbuf_addTuples();
tuples->tuple_index = 0;
}
}
/* ----------------
* Allocate space for a tuple.
* ----------------
*/
tuples->values[tuples->tuple_index] = pbuf_addTuple(tuple->t_natts);
tuples->lengths[tuples->tuple_index] = pbuf_addTupleValueLengths(tuple->t_natts);
/* ----------------
* copy printable representations of the tuple's attributes
* to the portal.
*
* This seems silly, because the user's function which is calling
* PQexec() or PQfn() will probably just convert this back into the
* internal form anyways, but the point here is to provide a uniform
* libpq interface and this is how the fe libpq interface currently
* works. Pretty soon we'll have to add code to let the fe or be
* select the desired data representation and then deal with that.
* This should not be too hard, as there already exist typrecieve()
* and typsend() procedures for user-defined types (see pg_type.h)
* -cim 2/11/91
* ----------------
*/
values = tuples->values[tuples->tuple_index];
lengths = tuples->lengths[tuples->tuple_index];
for (i = 0; i < tuple->t_natts; i++) {
attr = heap_getattr(tuple, InvalidBuffer, i+1, typeinfo, &isnull);
typoutput = typtoout((Oid) typeinfo->attrs[i]->atttypid);
lengths[i] = typeinfo->attrs[i]->attlen;
if (lengths[i] == -1) /* variable length attribute */
if (!isnull)
lengths[i] = VARSIZE(attr)-VARHDRSZ;
else
lengths[i] = 0;
if (!isnull && OidIsValid(typoutput)) {
values[i] = fmgr(typoutput, attr, gettypelem(typeinfo->attrs[i]->atttypid));
} else
values[i] = NULL;
}
/* ----------------
* increment tuple group counters
* ----------------
*/
portal->no_tuples++;
group->no_tuples++;
tuples->tuple_index++;
/* ----------------
* return to the original memory context
* ----------------
*/
MemoryContextSwitchTo(savecxt);
else
{
tuples = group->tuples;
/* walk to the end of the linked list of TupleBlocks */
while (tuples->next)
tuples = tuples->next;
/*
* now, tuples is the last TupleBlock, check to see if it is full.
* If so, allocate a new TupleBlock and add it to the end of the
* chain
*/
if (tuples->tuple_index == TupleBlockSize)
{
tuples->next = pbuf_addTuples();
tuples = tuples->next;
tuples->tuple_index = 0;
}
}
/* ----------------
* Allocate space for a tuple.
* ----------------
*/
tuples->values[tuples->tuple_index] = pbuf_addTuple(tuple->t_natts);
tuples->lengths[tuples->tuple_index] = pbuf_addTupleValueLengths(tuple->t_natts);
/* ----------------
* copy printable representations of the tuple's attributes
* to the portal.
*
* This seems silly, because the user's function which is calling
* PQexec() or PQfn() will probably just convert this back into the
* internal form anyways, but the point here is to provide a uniform
* libpq interface and this is how the fe libpq interface currently
* works. Pretty soon we'll have to add code to let the fe or be
* select the desired data representation and then deal with that.
* This should not be too hard, as there already exist typrecieve()
* and typsend() procedures for user-defined types (see pg_type.h)
* -cim 2/11/91
* ----------------
*/
values = tuples->values[tuples->tuple_index];
lengths = tuples->lengths[tuples->tuple_index];
for (i = 0; i < tuple->t_natts; i++)
{
attr = heap_getattr(tuple, InvalidBuffer, i + 1, typeinfo, &isnull);
typoutput = typtoout((Oid) typeinfo->attrs[i]->atttypid);
lengths[i] = typeinfo->attrs[i]->attlen;
if (lengths[i] == -1) /* variable length attribute */
if (!isnull)
lengths[i] = VARSIZE(attr) - VARHDRSZ;
else
lengths[i] = 0;
if (!isnull && OidIsValid(typoutput))
{
values[i] = fmgr(typoutput, attr, gettypelem(typeinfo->attrs[i]->atttypid));
}
else
values[i] = NULL;
}
/* ----------------
* increment tuple group counters
* ----------------
*/
portal->no_tuples++;
group->no_tuples++;
tuples->tuple_index++;
/* ----------------
* return to the original memory context
* ----------------
*/
MemoryContextSwitchTo(savecxt);
}

View File

@@ -1,24 +1,24 @@
/*-------------------------------------------------------------------------
*
* be-fsstubs.c--
* support for filesystem operations on large objects
* support for filesystem operations on large objects
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/libpq/be-fsstubs.c,v 1.12 1997/08/12 22:52:48 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/libpq/be-fsstubs.c,v 1.13 1997/09/07 04:42:15 momjian Exp $
*
* NOTES
* This should be moved to a more appropriate place. It is here
* for lack of a better place.
* This should be moved to a more appropriate place. It is here
* for lack of a better place.
*
* Builtin functions for open/close/read/write operations on large objects.
* Builtin functions for open/close/read/write operations on large objects.
*
* These functions operate in the current portal variable context, which
* means the large object descriptors hang around between transactions and
* are not deallocated until explicitly closed, or until the portal is
* closed.
* These functions operate in the current portal variable context, which
* means the large object descriptors hang around between transactions and
* are not deallocated until explicitly closed, or until the portal is
* closed.
*-------------------------------------------------------------------------
*/
@@ -37,340 +37,364 @@
#include <utils/memutils.h>
#include <lib/fstack.h>
#include <utils/mcxt.h>
#include <storage/fd.h> /* for O_ */
#include <storage/fd.h> /* for O_ */
#include <storage/large_object.h>
#include <libpq/be-fsstubs.h>
/*#define FSDB 1*/
#define MAX_LOBJ_FDS 256
static LargeObjectDesc *cookies[MAX_LOBJ_FDS];
static LargeObjectDesc *cookies[MAX_LOBJ_FDS];
static GlobalMemory fscxt = NULL;
static int newLOfd(LargeObjectDesc *lobjCookie);
static void deleteLOfd(int fd);
static int newLOfd(LargeObjectDesc * lobjCookie);
static void deleteLOfd(int fd);
/*****************************************************************************
* File Interfaces for Large Objects
* File Interfaces for Large Objects
*****************************************************************************/
int
lo_open(Oid lobjId, int mode)
{
LargeObjectDesc *lobjDesc;
int fd;
MemoryContext currentContext;
LargeObjectDesc *lobjDesc;
int fd;
MemoryContext currentContext;
#if FSDB
elog(NOTICE,"LOopen(%d,%d)",lobjId,mode);
elog(NOTICE, "LOopen(%d,%d)", lobjId, mode);
#endif
if (fscxt == NULL) {
fscxt = CreateGlobalMemory("Filesystem");
}
currentContext = MemoryContextSwitchTo((MemoryContext)fscxt);
if (fscxt == NULL)
{
fscxt = CreateGlobalMemory("Filesystem");
}
currentContext = MemoryContextSwitchTo((MemoryContext) fscxt);
lobjDesc = inv_open(lobjId, mode);
if (lobjDesc == NULL) { /* lookup failed */
lobjDesc = inv_open(lobjId, mode);
if (lobjDesc == NULL)
{ /* lookup failed */
MemoryContextSwitchTo(currentContext);
#if FSDB
elog(NOTICE, "cannot open large object %d", lobjId);
#endif
return -1;
}
fd = newLOfd(lobjDesc);
/* switch context back to orig. */
MemoryContextSwitchTo(currentContext);
#if FSDB
elog(NOTICE,"cannot open large object %d", lobjId);
#endif
return -1;
}
fd = newLOfd(lobjDesc);
/* switch context back to orig. */
MemoryContextSwitchTo(currentContext);
return fd;
return fd;
}
int
lo_close(int fd)
{
MemoryContext currentContext;
MemoryContext currentContext;
if (fd >= MAX_LOBJ_FDS) {
elog(WARN,"lo_close: large obj descriptor (%d) out of range", fd);
return -2;
}
if (cookies[fd] == NULL) {
elog(WARN,"lo_close: invalid large obj descriptor (%d)", fd);
return -3;
}
if (fd >= MAX_LOBJ_FDS)
{
elog(WARN, "lo_close: large obj descriptor (%d) out of range", fd);
return -2;
}
if (cookies[fd] == NULL)
{
elog(WARN, "lo_close: invalid large obj descriptor (%d)", fd);
return -3;
}
#if FSDB
elog(NOTICE,"LOclose(%d)",fd);
elog(NOTICE, "LOclose(%d)", fd);
#endif
Assert(fscxt != NULL);
currentContext = MemoryContextSwitchTo((MemoryContext)fscxt);
Assert(fscxt != NULL);
currentContext = MemoryContextSwitchTo((MemoryContext) fscxt);
inv_close(cookies[fd]);
inv_close(cookies[fd]);
MemoryContextSwitchTo(currentContext);
MemoryContextSwitchTo(currentContext);
deleteLOfd(fd);
return 0;
deleteLOfd(fd);
return 0;
}
/*
* We assume the large object supports byte oriented reads and seeks so
* that our work is easier.
* We assume the large object supports byte oriented reads and seeks so
* that our work is easier.
*/
int
lo_read(int fd, char *buf, int len)
{
Assert(cookies[fd]!=NULL);
return inv_read(cookies[fd], buf, len);
Assert(cookies[fd] != NULL);
return inv_read(cookies[fd], buf, len);
}
int
lo_write(int fd, char *buf, int len)
{
Assert(cookies[fd]!=NULL);
return inv_write(cookies[fd], buf, len);
Assert(cookies[fd] != NULL);
return inv_write(cookies[fd], buf, len);
}
int
lo_lseek(int fd, int offset, int whence)
{
MemoryContext currentContext;
int ret;
MemoryContext currentContext;
int ret;
if (fd >= MAX_LOBJ_FDS) {
elog(WARN,"lo_seek: large obj descriptor (%d) out of range", fd);
return -2;
}
if (fd >= MAX_LOBJ_FDS)
{
elog(WARN, "lo_seek: large obj descriptor (%d) out of range", fd);
return -2;
}
currentContext = MemoryContextSwitchTo((MemoryContext)fscxt);
currentContext = MemoryContextSwitchTo((MemoryContext) fscxt);
ret = inv_seek(cookies[fd], offset, whence);
ret = inv_seek(cookies[fd], offset, whence);
MemoryContextSwitchTo(currentContext);
MemoryContextSwitchTo(currentContext);
return ret;
return ret;
}
Oid
lo_creat(int mode)
{
LargeObjectDesc *lobjDesc;
MemoryContext currentContext;
Oid lobjId;
if (fscxt == NULL) {
fscxt = CreateGlobalMemory("Filesystem");
}
currentContext = MemoryContextSwitchTo((MemoryContext)fscxt);
lobjDesc = inv_create(mode);
if (lobjDesc == NULL) {
MemoryContextSwitchTo(currentContext);
return InvalidOid;
}
LargeObjectDesc *lobjDesc;
MemoryContext currentContext;
Oid lobjId;
lobjId = lobjDesc->heap_r->rd_id;
inv_close(lobjDesc);
/* switch context back to original memory context */
MemoryContextSwitchTo(currentContext);
return lobjId;
if (fscxt == NULL)
{
fscxt = CreateGlobalMemory("Filesystem");
}
currentContext = MemoryContextSwitchTo((MemoryContext) fscxt);
lobjDesc = inv_create(mode);
if (lobjDesc == NULL)
{
MemoryContextSwitchTo(currentContext);
return InvalidOid;
}
lobjId = lobjDesc->heap_r->rd_id;
inv_close(lobjDesc);
/* switch context back to original memory context */
MemoryContextSwitchTo(currentContext);
return lobjId;
}
int
lo_tell(int fd)
{
if (fd >= MAX_LOBJ_FDS) {
elog(WARN,"lo_tell: large object descriptor (%d) out of range",fd);
return -2;
}
if (cookies[fd] == NULL) {
elog(WARN,"lo_tell: invalid large object descriptor (%d)",fd);
return -3;
}
return inv_tell(cookies[fd]);
if (fd >= MAX_LOBJ_FDS)
{
elog(WARN, "lo_tell: large object descriptor (%d) out of range", fd);
return -2;
}
if (cookies[fd] == NULL)
{
elog(WARN, "lo_tell: invalid large object descriptor (%d)", fd);
return -3;
}
return inv_tell(cookies[fd]);
}
int
lo_unlink(Oid lobjId)
{
return (inv_destroy(lobjId));
return (inv_destroy(lobjId));
}
/*****************************************************************************
* Read/Write using varlena
* Read/Write using varlena
*****************************************************************************/
struct varlena *
loread(int fd, int len)
{
struct varlena *retval;
int totalread = 0;
retval = (struct varlena *)palloc(sizeof(int32) + len);
totalread = lo_read(fd, VARDATA(retval), len);
VARSIZE(retval) = totalread + sizeof(int32);
return retval;
struct varlena *retval;
int totalread = 0;
retval = (struct varlena *) palloc(sizeof(int32) + len);
totalread = lo_read(fd, VARDATA(retval), len);
VARSIZE(retval) = totalread + sizeof(int32);
return retval;
}
int lowrite(int fd, struct varlena *wbuf)
int
lowrite(int fd, struct varlena * wbuf)
{
int totalwritten;
int bytestowrite;
bytestowrite = VARSIZE(wbuf) - sizeof(int32);
totalwritten = lo_write(fd, VARDATA(wbuf), bytestowrite);
return totalwritten;
int totalwritten;
int bytestowrite;
bytestowrite = VARSIZE(wbuf) - sizeof(int32);
totalwritten = lo_write(fd, VARDATA(wbuf), bytestowrite);
return totalwritten;
}
/*****************************************************************************
* Import/Export of Large Object
* Import/Export of Large Object
*****************************************************************************/
/*
* lo_import -
* imports a file as an (inversion) large object.
* imports a file as an (inversion) large object.
*/
Oid
lo_import(text *filename)
lo_import(text * filename)
{
int fd;
int nbytes, tmp;
#define BUFSIZE 1024
char buf[BUFSIZE];
char fnamebuf[8192];
LargeObjectDesc *lobj;
Oid lobjOid;
int fd;
int nbytes,
tmp;
/*
* open the file to be read in
*/
strNcpy(fnamebuf, VARDATA(filename), VARSIZE(filename) - VARHDRSZ);
fd = open(fnamebuf, O_RDONLY, 0666);
if (fd < 0) { /* error */
elog(WARN, "be_lo_import: can't open unix file\"%s\"\n",
fnamebuf);
}
#define BUFSIZE 1024
char buf[BUFSIZE];
char fnamebuf[8192];
LargeObjectDesc *lobj;
Oid lobjOid;
/*
* create an inversion "object"
*/
lobj = inv_create(INV_READ|INV_WRITE);
if (lobj == NULL) {
elog(WARN, "lo_import: can't create inv object for \"%s\"",
fnamebuf);
}
/*
* the oid for the large object is just the oid of the relation
* XInv??? which contains the data.
*/
lobjOid = lobj->heap_r->rd_id;
/*
* read in from the Unix file and write to the inversion file
*/
while ((nbytes = read(fd, buf, BUFSIZE)) > 0) {
tmp = inv_write(lobj, buf, nbytes);
if (tmp < nbytes) {
elog(WARN, "lo_import: error while reading \"%s\"",
fnamebuf);
/*
* open the file to be read in
*/
strNcpy(fnamebuf, VARDATA(filename), VARSIZE(filename) - VARHDRSZ);
fd = open(fnamebuf, O_RDONLY, 0666);
if (fd < 0)
{ /* error */
elog(WARN, "be_lo_import: can't open unix file\"%s\"\n",
fnamebuf);
}
}
close(fd);
inv_close(lobj);
/*
* create an inversion "object"
*/
lobj = inv_create(INV_READ | INV_WRITE);
if (lobj == NULL)
{
elog(WARN, "lo_import: can't create inv object for \"%s\"",
fnamebuf);
}
return lobjOid;
/*
* the oid for the large object is just the oid of the relation
* XInv??? which contains the data.
*/
lobjOid = lobj->heap_r->rd_id;
/*
* read in from the Unix file and write to the inversion file
*/
while ((nbytes = read(fd, buf, BUFSIZE)) > 0)
{
tmp = inv_write(lobj, buf, nbytes);
if (tmp < nbytes)
{
elog(WARN, "lo_import: error while reading \"%s\"",
fnamebuf);
}
}
close(fd);
inv_close(lobj);
return lobjOid;
}
/*
* lo_export -
* exports an (inversion) large object.
* exports an (inversion) large object.
*/
int4
lo_export(Oid lobjId, text *filename)
lo_export(Oid lobjId, text * filename)
{
int fd;
int nbytes, tmp;
#define BUFSIZE 1024
char buf[BUFSIZE];
char fnamebuf[8192];
LargeObjectDesc *lobj;
mode_t oumask;
int fd;
int nbytes,
tmp;
/*
* create an inversion "object"
*/
lobj = inv_open(lobjId, INV_READ);
if (lobj == NULL) {
elog(WARN, "lo_export: can't open inv object %d",
lobjId);
}
#define BUFSIZE 1024
char buf[BUFSIZE];
char fnamebuf[8192];
LargeObjectDesc *lobj;
mode_t oumask;
/*
* open the file to be written to
*/
oumask = umask((mode_t) 0);
strNcpy(fnamebuf, VARDATA(filename), VARSIZE(filename) - VARHDRSZ);
fd = open(fnamebuf, O_CREAT|O_WRONLY, 0666);
umask(oumask);
if (fd < 0) { /* error */
elog(WARN, "lo_export: can't open unix file\"%s\"",
fnamebuf);
}
/*
* read in from the Unix file and write to the inversion file
*/
while ((nbytes = inv_read(lobj, buf, BUFSIZE)) > 0) {
tmp = write(fd, buf, nbytes);
if (tmp < nbytes) {
elog(WARN, "lo_export: error while writing \"%s\"",
fnamebuf);
/*
* create an inversion "object"
*/
lobj = inv_open(lobjId, INV_READ);
if (lobj == NULL)
{
elog(WARN, "lo_export: can't open inv object %d",
lobjId);
}
}
inv_close(lobj);
close(fd);
/*
* open the file to be written to
*/
oumask = umask((mode_t) 0);
strNcpy(fnamebuf, VARDATA(filename), VARSIZE(filename) - VARHDRSZ);
fd = open(fnamebuf, O_CREAT | O_WRONLY, 0666);
umask(oumask);
if (fd < 0)
{ /* error */
elog(WARN, "lo_export: can't open unix file\"%s\"",
fnamebuf);
}
return 1;
/*
* read in from the Unix file and write to the inversion file
*/
while ((nbytes = inv_read(lobj, buf, BUFSIZE)) > 0)
{
tmp = write(fd, buf, nbytes);
if (tmp < nbytes)
{
elog(WARN, "lo_export: error while writing \"%s\"",
fnamebuf);
}
}
inv_close(lobj);
close(fd);
return 1;
}
/*****************************************************************************
* Support routines for this file
* Support routines for this file
*****************************************************************************/
static int
newLOfd(LargeObjectDesc *lobjCookie)
newLOfd(LargeObjectDesc * lobjCookie)
{
int i;
for (i = 0; i < MAX_LOBJ_FDS; i++) {
if (cookies[i] == NULL) {
cookies[i] = lobjCookie;
return i;
int i;
for (i = 0; i < MAX_LOBJ_FDS; i++)
{
if (cookies[i] == NULL)
{
cookies[i] = lobjCookie;
return i;
}
}
}
return -1;
return -1;
}
static void
static void
deleteLOfd(int fd)
{
cookies[fd] = NULL;
cookies[fd] = NULL;
}

View File

@@ -1,24 +1,24 @@
/*-------------------------------------------------------------------------
*
* be-pqexec.c--
* support for executing POSTGRES commands and functions from a
* user-defined function in a backend.
* support for executing POSTGRES commands and functions from a
* user-defined function in a backend.
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/libpq/Attic/be-pqexec.c,v 1.4 1997/08/19 21:31:31 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/libpq/Attic/be-pqexec.c,v 1.5 1997/09/07 04:42:17 momjian Exp $
*
*-------------------------------------------------------------------------
*/
/*
* INTERFACE ROUTINES
* PQfn - call a POSTGRES function
* PQexec - execute a POSTGRES query
*
* PQfn - call a POSTGRES function
* PQexec - execute a POSTGRES query
*
* NOTES
* These routines are compiled into the postgres backend.
* These routines are compiled into the postgres backend.
*/
#include <postgres.h>
@@ -32,356 +32,395 @@
#include <utils/exc.h>
#include <utils/builtins.h>
#ifndef HAVE_MEMMOVE
# include <regex/utils.h>
#include <regex/utils.h>
#else
# include <string.h>
#include <string.h>
#endif
static char *strmake(char *str, int len);
static char *strmake(char *str, int len);
/* ----------------------------------------------------------------
* PQ interface routines
* PQ interface routines
* ----------------------------------------------------------------
*/
/* ----------------
* PQfn - Send a function call to the POSTGRES backend.
* PQfn - Send a function call to the POSTGRES backend.
*
* fnid : function id
* result_buf : pointer to result buffer (&int if integer)
* result_len : length of return value.
* result_is_int : If the result is an integer, this must be non-zero
* args : pointer to a NULL terminated arg array.
* (length, if integer, and result-pointer)
* nargs : # of arguments in args array.
* fnid : function id
* result_buf : pointer to result buffer (&int if integer)
* result_len : length of return value.
* result_is_int : If the result is an integer, this must be non-zero
* args : pointer to a NULL terminated arg array.
* (length, if integer, and result-pointer)
* nargs : # of arguments in args array.
*
* This code scavanged from HandleFunctionRequest() in tcop/fastpath.h
* This code scavanged from HandleFunctionRequest() in tcop/fastpath.h
* ----------------
*/
char *
char *
PQfn(int fnid,
int *result_buf, /* can't use void, dec compiler barfs */
int result_len,
int result_is_int,
PQArgBlock *args,
int nargs)
int *result_buf, /* can't use void, dec compiler barfs */
int result_len,
int result_is_int,
PQArgBlock * args,
int nargs)
{
char *retval; /* XXX - should be datum, maybe ? */
char *arg[8];
int i;
/* ----------------
* fill args[] array
* ----------------
*/
for (i = 0; i < nargs; i++) {
if (args[i].len == VAR_LENGTH_ARG) {
arg[i] = (char*) args[i].u.ptr;
} else if (args[i].len > 4) {
elog(WARN,"arg_length of argument %d too long",i);
} else {
arg[i] = (char*)args[i].u.integer;
char *retval; /* XXX - should be datum, maybe ? */
char *arg[8];
int i;
/* ----------------
* fill args[] array
* ----------------
*/
for (i = 0; i < nargs; i++)
{
if (args[i].len == VAR_LENGTH_ARG)
{
arg[i] = (char *) args[i].u.ptr;
}
else if (args[i].len > 4)
{
elog(WARN, "arg_length of argument %d too long", i);
}
else
{
arg[i] = (char *) args[i].u.integer;
}
}
}
/* ----------------
* call the postgres function manager
* ----------------
*/
retval = (char *)
fmgr(fnid, arg[0], arg[1], arg[2], arg[3],
arg[4], arg[5], arg[6], arg[7]);
/* ----------------
* put the result in the buffer the user specified and
* return the proper code.
* ----------------
*/
if (retval == (char *) NULL) /* void retval */
return "0";
if (result_is_int) {
*result_buf = (int) retval;
} else {
memmove(result_buf, retval, result_len);
}
return "G";
/* ----------------
* call the postgres function manager
* ----------------
*/
retval = (char *)
fmgr(fnid, arg[0], arg[1], arg[2], arg[3],
arg[4], arg[5], arg[6], arg[7]);
/* ----------------
* put the result in the buffer the user specified and
* return the proper code.
* ----------------
*/
if (retval == (char *) NULL)/* void retval */
return "0";
if (result_is_int)
{
*result_buf = (int) retval;
}
else
{
memmove(result_buf, retval, result_len);
}
return "G";
}
/* ----------------
* PQexec - Send a query to the POSTGRES backend
* PQexec - Send a query to the POSTGRES backend
*
* The return value is a string.
* If 0 or more tuples fetched from the backend, return "P portal-name".
* If a query is does not return tuples, return "C query-command".
* If there is an error: return "E error-message".
* The return value is a string.
* If 0 or more tuples fetched from the backend, return "P portal-name".
* If a query is does not return tuples, return "C query-command".
* If there is an error: return "E error-message".
*
* Note: if we get a serious error or an elog(WARN), then PQexec never
* returns because the system longjmp's back to the main loop.
* Note: if we get a serious error or an elog(WARN), then PQexec never
* returns because the system longjmp's back to the main loop.
* ----------------
*/
char *
char *
PQexec(char *query)
{
PortalEntry *entry = NULL;
char *result = NULL;
/* ----------------
* create a new portal and put it on top of the portal stack.
* ----------------
*/
entry = (PortalEntry *) be_newportal();
be_portalpush(entry);
/* ----------------
* pg_eval_dest will put the query results in a portal which will
* end up on the top of the portal stack.
* ----------------
*/
pg_eval_dest(query, (char **) NULL, (Oid *) NULL, 0, Local);
/* ----------------
* pop the portal off the portal stack and return the
* result. Note if result is null, we return C.
* ----------------
*/
entry = (PortalEntry *) be_portalpop();
result = entry->result;
if (result == NULL) {
char *PQE = "Cnull PQexec result";
result = pstrdup(PQE);
}
if (result[0] != 'P')
PortalEntry *entry = NULL;
char *result = NULL;
/* ----------------
* create a new portal and put it on top of the portal stack.
* ----------------
*/
entry = (PortalEntry *) be_newportal();
be_portalpush(entry);
/* ----------------
* pg_eval_dest will put the query results in a portal which will
* end up on the top of the portal stack.
* ----------------
*/
pg_eval_dest(query, (char **) NULL, (Oid *) NULL, 0, Local);
/* ----------------
* pop the portal off the portal stack and return the
* result. Note if result is null, we return C.
* ----------------
*/
entry = (PortalEntry *) be_portalpop();
result = entry->result;
if (result == NULL)
{
/* some successful command was executed,
but it's not one where we return the portal name so
here we should be sure to clear out the portal
(since the caller has no handle on it)
*/
pbuf_close(entry->name);
char *PQE = "Cnull PQexec result";
result = pstrdup(PQE);
}
return result;
if (result[0] != 'P')
{
/*
* some successful command was executed, but it's not one where we
* return the portal name so here we should be sure to clear out
* the portal (since the caller has no handle on it)
*/
pbuf_close(entry->name);
}
return result;
}
/* ----------------------------------------------------------------
* pqtest support
* pqtest support
* ----------------------------------------------------------------
*/
/* ----------------
* pqtest_PQexec takes a text query and returns the number of
* tuples it returns. Note: there is no need to PQclear()
* here - the memory will go away at end transaction.
* pqtest_PQexec takes a text query and returns the number of
* tuples it returns. Note: there is no need to PQclear()
* here - the memory will go away at end transaction.
* ----------------
*/
int
pqtest_PQexec(char *q)
{
PortalBuffer *a;
char *res;
int t;
/* ----------------
* execute the postgres query
* ----------------
*/
res = PQexec(q);
/* ----------------
* return number of tuples in portal or 0 if command returns no tuples.
* ----------------
*/
t = 0;
switch(res[0]) {
case 'P':
a = PQparray(&res[1]);
if (a == NULL)
elog(WARN, "pqtest_PQexec: PQparray could not find portal %s",
res);
t = PQntuples(a);
break;
case 'C':
break;
default:
elog(NOTICE, "pqtest_PQexec: PQexec(%s) returns %s", q, res);
break;
}
return t;
PortalBuffer *a;
char *res;
int t;
/* ----------------
* execute the postgres query
* ----------------
*/
res = PQexec(q);
/* ----------------
* return number of tuples in portal or 0 if command returns no tuples.
* ----------------
*/
t = 0;
switch (res[0])
{
case 'P':
a = PQparray(&res[1]);
if (a == NULL)
elog(WARN, "pqtest_PQexec: PQparray could not find portal %s",
res);
t = PQntuples(a);
break;
case 'C':
break;
default:
elog(NOTICE, "pqtest_PQexec: PQexec(%s) returns %s", q, res);
break;
}
return t;
}
/* ----------------
* utilities for pqtest_PQfn()
* utilities for pqtest_PQfn()
* ----------------
*/
static char *
static char *
strmake(char *str, int len)
{
char *newstr;
if (str == NULL) return NULL;
if (len <= 0) len = strlen(str);
newstr = (char *) palloc((unsigned) len+1);
strNcpy(newstr, str, len);
newstr[len] = (char) 0;
return newstr;
char *newstr;
if (str == NULL)
return NULL;
if (len <= 0)
len = strlen(str);
newstr = (char *) palloc((unsigned) len + 1);
strNcpy(newstr, str, len);
newstr[len] = (char) 0;
return newstr;
}
#define SKIP 0
#define SCAN 1
static char spacestr[] = " ";
static char spacestr[] = " ";
static int
strparse(char *s, char **fields, int *offsets, int maxfields)
{
int len = strlen(s);
char *cp = s, *end = cp + len, *ep;
int parsed = 0;
int mode = SKIP, i = 0;
if (*(end - 1) == '\n') end--;
for (i=0; i<maxfields; i++)
fields[i] = spacestr;
i = 0;
while (!parsed) {
if (mode == SKIP) {
while ((cp < end) &&
(*cp == ' ' || *cp == '\t'))
cp++;
if (cp < end) mode = SCAN;
else parsed = 1;
} else {
ep = cp;
while ((ep < end) && (*ep != ' ' && *ep != '\t'))
ep++;
if (ep < end) mode = SKIP;
else parsed = 1;
fields[i] = strmake(cp, ep - cp);
if (offsets != NULL)
offsets[i] = cp - s;
i++;
cp = ep;
if (i > maxfields)
parsed = 1;
int len = strlen(s);
char *cp = s,
*end = cp + len,
*ep;
int parsed = 0;
int mode = SKIP,
i = 0;
if (*(end - 1) == '\n')
end--;
for (i = 0; i < maxfields; i++)
fields[i] = spacestr;
i = 0;
while (!parsed)
{
if (mode == SKIP)
{
while ((cp < end) &&
(*cp == ' ' || *cp == '\t'))
cp++;
if (cp < end)
mode = SCAN;
else
parsed = 1;
}
else
{
ep = cp;
while ((ep < end) && (*ep != ' ' && *ep != '\t'))
ep++;
if (ep < end)
mode = SKIP;
else
parsed = 1;
fields[i] = strmake(cp, ep - cp);
if (offsets != NULL)
offsets[i] = cp - s;
i++;
cp = ep;
if (i > maxfields)
parsed = 1;
}
}
}
return i;
return i;
}
/* ----------------
* pqtest_PQfn converts it's string into a PQArgBlock and
* calls the specified function, which is assumed to return
* an integer value.
* pqtest_PQfn converts it's string into a PQArgBlock and
* calls the specified function, which is assumed to return
* an integer value.
* ----------------
*/
int
pqtest_PQfn(char *q)
{
int k, j, i, v, f, offsets;
char *fields[8];
PQArgBlock pqargs[7];
int res;
char *pqres;
/* ----------------
* parse q into fields
* ----------------
*/
i = strparse(q, fields, &offsets, 8);
printf("pqtest_PQfn: strparse returns %d fields\n", i); /* debug */
if (i == 0)
return -1;
/* ----------------
* get the function id
* ----------------
*/
f = atoi(fields[0]);
printf("pqtest_PQfn: func is %d\n", f); /* debug */
if (f == 0)
return -1;
/* ----------------
* build a PQArgBlock
* ----------------
*/
for (j=1; j<i && j<8; j++) {
k = j-1;
v = atoi(fields[j]);
if (v != 0 || (v == 0 && fields[j][0] == '0')) {
pqargs[k].len = 4;
pqargs[k].u.integer = v;
printf("pqtest_PQfn: arg %d is int %d\n", k, v); /* debug */
} else {
pqargs[k].len = VAR_LENGTH_ARG;
pqargs[k].u.ptr = (int *) textin(fields[j]);
printf("pqtest_PQfn: arg %d is text %s\n", k, fields[j]); /*debug*/
int k,
j,
i,
v,
f,
offsets;
char *fields[8];
PQArgBlock pqargs[7];
int res;
char *pqres;
/* ----------------
* parse q into fields
* ----------------
*/
i = strparse(q, fields, &offsets, 8);
printf("pqtest_PQfn: strparse returns %d fields\n", i); /* debug */
if (i == 0)
return -1;
/* ----------------
* get the function id
* ----------------
*/
f = atoi(fields[0]);
printf("pqtest_PQfn: func is %d\n", f); /* debug */
if (f == 0)
return -1;
/* ----------------
* build a PQArgBlock
* ----------------
*/
for (j = 1; j < i && j < 8; j++)
{
k = j - 1;
v = atoi(fields[j]);
if (v != 0 || (v == 0 && fields[j][0] == '0'))
{
pqargs[k].len = 4;
pqargs[k].u.integer = v;
printf("pqtest_PQfn: arg %d is int %d\n", k, v); /* debug */
}
else
{
pqargs[k].len = VAR_LENGTH_ARG;
pqargs[k].u.ptr = (int *) textin(fields[j]);
printf("pqtest_PQfn: arg %d is text %s\n", k, fields[j]); /* debug */
}
}
}
/* ----------------
* call PQfn
* ----------------
*/
pqres = PQfn(f, &res, 4, 1, pqargs, i-1);
printf("pqtest_PQfn: pqres is %s\n", pqres); /* debug */
/* ----------------
* free memory used
* ----------------
*/
for (j=0; j<i; j++) {
pfree(fields[j]);
if (pqargs[j].len == VAR_LENGTH_ARG)
pfree(pqargs[j].u.ptr);
}
/* ----------------
* return result
* ----------------
*/
printf("pqtest_PQfn: res is %d\n", res); /* debugg */
return res;
/* ----------------
* call PQfn
* ----------------
*/
pqres = PQfn(f, &res, 4, 1, pqargs, i - 1);
printf("pqtest_PQfn: pqres is %s\n", pqres); /* debug */
/* ----------------
* free memory used
* ----------------
*/
for (j = 0; j < i; j++)
{
pfree(fields[j]);
if (pqargs[j].len == VAR_LENGTH_ARG)
pfree(pqargs[j].u.ptr);
}
/* ----------------
* return result
* ----------------
*/
printf("pqtest_PQfn: res is %d\n", res); /* debugg */
return res;
}
/* ----------------
* pqtest looks at the first character of it's test argument
* and decides which of pqtest_PQexec or pqtest_PQfn to call.
* pqtest looks at the first character of it's test argument
* and decides which of pqtest_PQexec or pqtest_PQfn to call.
* ----------------
*/
int32
pqtest(struct varlena *vlena)
pqtest(struct varlena * vlena)
{
char *q;
/* ----------------
* get the query
* ----------------
*/
q = textout(vlena);
if (q == NULL)
return -1;
switch(q[0]) {
case '%':
return pqtest_PQfn(&q[1]);
break;
default:
return pqtest_PQexec(q);
break;
}
return(0);
char *q;
/* ----------------
* get the query
* ----------------
*/
q = textout(vlena);
if (q == NULL)
return -1;
switch (q[0])
{
case '%':
return pqtest_PQfn(&q[1]);
break;
default:
return pqtest_PQexec(q);
break;
}
return (0);
}

File diff suppressed because it is too large Load Diff

View File

@@ -6,106 +6,116 @@
#include <string.h>
#include <unistd.h>
#ifdef HAVE_CRYPT_H
# include <crypt.h>
#include <crypt.h>
#endif
int
verify_password(char *user, char *password, Port *port,
char *database, char *DataDir)
verify_password(char *user, char *password, Port * port,
char *database, char *DataDir)
{
bool host_ok;
enum Userauth userauth;
char pw_file_name[PWFILE_NAME_SIZE+1];
bool host_ok;
enum Userauth userauth;
char pw_file_name[PWFILE_NAME_SIZE + 1];
char *pw_file_fullname;
FILE *pw_file;
char *pw_file_fullname;
FILE *pw_file;
char pw_file_line[255];
char *p, *test_user, *test_pw;
char salt[3];
char pw_file_line[255];
char *p,
*test_user,
*test_pw;
char salt[3];
find_hba_entry(DataDir, port->raddr.sin_addr, database,
&host_ok, &userauth, pw_file_name, true);
find_hba_entry(DataDir, port->raddr.sin_addr, database,
&host_ok, &userauth, pw_file_name, true);
if(!host_ok) {
sprintf(PQerrormsg,
"verify_password: couldn't find entry for connecting host\n");
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return STATUS_ERROR;
}
if(userauth != Password) {
sprintf(PQerrormsg,
"verify_password: couldn't find entry of type 'password' "
"for this host\n");
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return STATUS_ERROR;
}
if(!pw_file_name || pw_file_name[0] == '\0') {
sprintf(PQerrormsg,
"verify_password: no password file specified\n");
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return STATUS_ERROR;
}
pw_file_fullname = (char *)malloc(strlen(DataDir) + strlen(pw_file_name) + 2);
strcpy(pw_file_fullname, DataDir);
strcat(pw_file_fullname, "/");
strcat(pw_file_fullname, pw_file_name);
pw_file = AllocateFile(pw_file_fullname, "r");
if(!pw_file) {
sprintf(PQerrormsg,
"verify_password: couldn't open password file '%s'\n",
pw_file_fullname);
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return STATUS_ERROR;
}
while(!feof(pw_file)) {
fgets(pw_file_line, 255, pw_file);
p = pw_file_line;
test_user = strtok(p, ":");
test_pw = strtok(NULL, ":");
if(!test_user || !test_pw ||
test_user[0] == '\0' || test_pw[0] == '\0') {
continue;
if (!host_ok)
{
sprintf(PQerrormsg,
"verify_password: couldn't find entry for connecting host\n");
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return STATUS_ERROR;
}
/* kill the newline */
if (test_pw[strlen(test_pw)-1] == '\n')
test_pw[strlen(test_pw)-1] = '\0';
strNcpy(salt, test_pw, 2);
if(strcmp(user, test_user) == 0) {
/* we're outta here one way or the other. */
FreeFile(pw_file);
if(strcmp(crypt(password, salt), test_pw) == 0) {
/* it matched. */
return STATUS_OK;
}
sprintf(PQerrormsg,
"verify_password: password mismatch for '%s'.\n",
user);
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return STATUS_ERROR;
if (userauth != Password)
{
sprintf(PQerrormsg,
"verify_password: couldn't find entry of type 'password' "
"for this host\n");
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return STATUS_ERROR;
}
}
sprintf(PQerrormsg,
"verify_password: user '%s' not found in password file.\n",
user);
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return STATUS_ERROR;
if (!pw_file_name || pw_file_name[0] == '\0')
{
sprintf(PQerrormsg,
"verify_password: no password file specified\n");
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return STATUS_ERROR;
}
pw_file_fullname = (char *) malloc(strlen(DataDir) + strlen(pw_file_name) + 2);
strcpy(pw_file_fullname, DataDir);
strcat(pw_file_fullname, "/");
strcat(pw_file_fullname, pw_file_name);
pw_file = AllocateFile(pw_file_fullname, "r");
if (!pw_file)
{
sprintf(PQerrormsg,
"verify_password: couldn't open password file '%s'\n",
pw_file_fullname);
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return STATUS_ERROR;
}
while (!feof(pw_file))
{
fgets(pw_file_line, 255, pw_file);
p = pw_file_line;
test_user = strtok(p, ":");
test_pw = strtok(NULL, ":");
if (!test_user || !test_pw ||
test_user[0] == '\0' || test_pw[0] == '\0')
{
continue;
}
/* kill the newline */
if (test_pw[strlen(test_pw) - 1] == '\n')
test_pw[strlen(test_pw) - 1] = '\0';
strNcpy(salt, test_pw, 2);
if (strcmp(user, test_user) == 0)
{
/* we're outta here one way or the other. */
FreeFile(pw_file);
if (strcmp(crypt(password, salt), test_pw) == 0)
{
/* it matched. */
return STATUS_OK;
}
sprintf(PQerrormsg,
"verify_password: password mismatch for '%s'.\n",
user);
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return STATUS_ERROR;
}
}
sprintf(PQerrormsg,
"verify_password: user '%s' not found in password file.\n",
user);
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
return STATUS_ERROR;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,50 +1,50 @@
/*-------------------------------------------------------------------------
*
* portalbuf.c--
* portal buffer support routines for src/libpq/portal.c
* portal buffer support routines for src/libpq/portal.c
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/libpq/Attic/portalbuf.c,v 1.4 1997/08/12 20:15:23 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/libpq/Attic/portalbuf.c,v 1.5 1997/09/07 04:42:24 momjian Exp $
*
*-------------------------------------------------------------------------
*/
/*
* INTERFACE ROUTINES
* pbuf_alloc - allocate memory for libpq routines
* pbuf_free - free memory for libpq routines
* pbuf_addPortal - Allocate a new portal buffer
* pbuf_addGroup - Add a new tuple group to the portal
* pbuf_addTypes - Allocate n type blocks
* pbuf_addTuples - Allocate a tuple block
* pbuf_addTuple - Allocate a tuple of n fields (attributes)
* pbuf_addValues - Allocate n bytes for a value
* pbuf_addEntry - Allocate a portal entry
* pbuf_freeEntry - Free a portal entry in the portal table
* pbuf_freeTypes - Free up the space used by a portal
* pbuf_freeTuples - free space used by tuple block
* pbuf_freeGroup - free space used by group, types and tuples
* pbuf_freePortal - free space used by portal and portal's group
* pbuf_getIndex - Return the index of the portal entry
* pbuf_setup - Set up a portal for dumping data
* pbuf_close - Close a portal, remove it from the portal table
* pbuf_findGroup - Return group given the group_index
* pbuf_findFnumber - Return field index of a given field within a group
* pbuf_findFname - Find the field name given the field index
* pbuf_checkFnumber - signal an error if field number is out of bounds
* pbuf_alloc - allocate memory for libpq routines
* pbuf_free - free memory for libpq routines
* pbuf_addPortal - Allocate a new portal buffer
* pbuf_addGroup - Add a new tuple group to the portal
* pbuf_addTypes - Allocate n type blocks
* pbuf_addTuples - Allocate a tuple block
* pbuf_addTuple - Allocate a tuple of n fields (attributes)
* pbuf_addValues - Allocate n bytes for a value
* pbuf_addEntry - Allocate a portal entry
* pbuf_freeEntry - Free a portal entry in the portal table
* pbuf_freeTypes - Free up the space used by a portal
* pbuf_freeTuples - free space used by tuple block
* pbuf_freeGroup - free space used by group, types and tuples
* pbuf_freePortal - free space used by portal and portal's group
* pbuf_getIndex - Return the index of the portal entry
* pbuf_setup - Set up a portal for dumping data
* pbuf_close - Close a portal, remove it from the portal table
* pbuf_findGroup - Return group given the group_index
* pbuf_findFnumber - Return field index of a given field within a group
* pbuf_findFname - Find the field name given the field index
* pbuf_checkFnumber - signal an error if field number is out of bounds
*
* NOTES
* These functions may be used by both frontend routines which
* communicate with a backend or by user-defined functions which
* are compiled or dynamically loaded into a backend.
* These functions may be used by both frontend routines which
* communicate with a backend or by user-defined functions which
* are compiled or dynamically loaded into a backend.
*
* the portals[] array should be organized as a hash table for
* quick portal-by-name lookup.
* the portals[] array should be organized as a hash table for
* quick portal-by-name lookup.
*
* Do not confuse "PortalEntry" (or "PortalBuffer") with "Portal"
* see utils/mmgr/portalmem.c for why. -cim 2/22/91
* Do not confuse "PortalEntry" (or "PortalBuffer") with "Portal"
* see utils/mmgr/portalmem.c for why. -cim 2/22/91
*
*/
#include <string.h>
@@ -55,407 +55,417 @@
#include <libpq/libpq.h> /* where the declarations go */
#include <utils/exc.h>
PortalEntry** portals = (PortalEntry**) NULL;
size_t portals_array_size = 0;
PortalEntry **portals = (PortalEntry **) NULL;
size_t portals_array_size = 0;
/* portals array memory is malloc'd instead of using MemoryContexts */
/* since it will be used by both front and backend programs*/
/* GlobalMemory portals_mmcxt = (GlobalMemory) NULL; */
/* GlobalMemory portals_mmcxt = (GlobalMemory) NULL; */
/* -------------------------------
/* -------------------------------
* portals_realloc --
* grow the size of the portals array by size
* grow the size of the portals array by size
*
* also ensures that elements are initially NULL
* also ensures that elements are initially NULL
*/
static void
portals_realloc(size_t size)
{
size_t oldsize;
int i;
PortalEntry** newp;
oldsize = portals_array_size;
portals_array_size += size;
if (portals)
newp= (PortalEntry**)realloc(portals,
portals_array_size*sizeof(PortalEntry*));
else
newp= (PortalEntry**)malloc(portals_array_size*sizeof(PortalEntry*));
if (newp)
portals = newp;
else
libpq_raise(&PortalError,
form("Cannot alloc more memory in portals_realloc"));
for (i=oldsize;i<portals_array_size;i++)
portals[i]=(PortalEntry*)NULL;
size_t oldsize;
int i;
PortalEntry **newp;
oldsize = portals_array_size;
portals_array_size += size;
if (portals)
newp = (PortalEntry **) realloc(portals,
portals_array_size * sizeof(PortalEntry *));
else
newp = (PortalEntry **) malloc(portals_array_size * sizeof(PortalEntry *));
if (newp)
portals = newp;
else
libpq_raise(&PortalError,
form("Cannot alloc more memory in portals_realloc"));
for (i = oldsize; i < portals_array_size; i++)
portals[i] = (PortalEntry *) NULL;
}
/* --------------------------------
* pbuf_alloc - allocate memory for portal buffers
* pbuf_alloc - allocate memory for portal buffers
*
* remember: palloc() in the backend uses the postgres MemoryContext
* library and palloc() in the frontend (fe-pqstubs.c) calls malloc().
* remember: palloc() in the backend uses the postgres MemoryContext
* library and palloc() in the frontend (fe-pqstubs.c) calls malloc().
* --------------------------------
*/
caddr_t
pbuf_alloc(size_t size)
{
caddr_t addr;
if (size <= 0)
libpq_raise(&MemoryError, form("Invalid argument to pbuf_alloc()."));
addr = (caddr_t) palloc(size);
if (addr == (caddr_t) NULL)
libpq_raise(&MemoryError, form("Cannot Allocate space."));
return (addr);
caddr_t addr;
if (size <= 0)
libpq_raise(&MemoryError, form("Invalid argument to pbuf_alloc()."));
addr = (caddr_t) palloc(size);
if (addr == (caddr_t) NULL)
libpq_raise(&MemoryError, form("Cannot Allocate space."));
return (addr);
}
/* --------------------------------
* pbuf_free - free memory for portal buffers
* pbuf_free - free memory for portal buffers
*
* remember: pfree() in the backend uses the postgres MemoryContext
* library and pfree() in the frontend (fe-pqstubs.c) calls free().
* remember: pfree() in the backend uses the postgres MemoryContext
* library and pfree() in the frontend (fe-pqstubs.c) calls free().
* --------------------------------
*/
void
pbuf_free(caddr_t pointer)
{
if (pointer)
pfree(pointer);
else
libpq_raise(&MemoryError, form("Tried to free NULL memory pointer"));
if (pointer)
pfree(pointer);
else
libpq_raise(&MemoryError, form("Tried to free NULL memory pointer"));
}
/* --------------------------------
* pbuf_addPortal - Allocate a new portal buffer
* pbuf_addPortal - Allocate a new portal buffer
* --------------------------------
*/
PortalBuffer *
PortalBuffer *
pbuf_addPortal()
{
PortalBuffer *portal;
portal = (PortalBuffer *)
pbuf_alloc(sizeof (PortalBuffer));
portal->rule_p = 0;
portal->no_tuples = 0;
portal->no_groups = 0;
portal->groups = NULL;
return (portal);
PortalBuffer *portal;
portal = (PortalBuffer *)
pbuf_alloc(sizeof(PortalBuffer));
portal->rule_p = 0;
portal->no_tuples = 0;
portal->no_groups = 0;
portal->groups = NULL;
return (portal);
}
/* --------------------------------
* pbuf_addGroup - Add a new tuple group to the portal
* pbuf_addGroup - Add a new tuple group to the portal
* --------------------------------
*/
GroupBuffer *
pbuf_addGroup(PortalBuffer *portal)
GroupBuffer *
pbuf_addGroup(PortalBuffer * portal)
{
GroupBuffer *group, *group1;
group = (GroupBuffer *)
pbuf_alloc(sizeof (GroupBuffer));
/* Initialize the new group buffer. */
group->no_tuples = 0;
group->no_fields = 0;
group->types = NULL;
group->tuples = NULL;
group->next = NULL;
if ((group1 = portal->groups) == NULL)
portal->groups = group;
else {
while (group1->next != NULL)
group1 = group1->next;
group1->next = group;
}
return (group);
GroupBuffer *group,
*group1;
group = (GroupBuffer *)
pbuf_alloc(sizeof(GroupBuffer));
/* Initialize the new group buffer. */
group->no_tuples = 0;
group->no_fields = 0;
group->types = NULL;
group->tuples = NULL;
group->next = NULL;
if ((group1 = portal->groups) == NULL)
portal->groups = group;
else
{
while (group1->next != NULL)
group1 = group1->next;
group1->next = group;
}
return (group);
}
/* --------------------------------
* pbuf_addTypes - Allocate n type blocks
* pbuf_addTypes - Allocate n type blocks
* --------------------------------
*/
TypeBlock *
TypeBlock *
pbuf_addTypes(int n)
{
TypeBlock *types;
types = (TypeBlock *)
pbuf_alloc(n * sizeof (TypeBlock));
return (types);
TypeBlock *types;
types = (TypeBlock *)
pbuf_alloc(n * sizeof(TypeBlock));
return (types);
}
/* --------------------------------
* pbuf_addTuples - Allocate a tuple block
* pbuf_addTuples - Allocate a tuple block
* --------------------------------
*/
TupleBlock *
TupleBlock *
pbuf_addTuples()
{
TupleBlock *tuples;
tuples = (TupleBlock *)
pbuf_alloc(sizeof (TupleBlock));
tuples->next = NULL;
tuples->tuple_index = 0;
return (tuples);
TupleBlock *tuples;
tuples = (TupleBlock *)
pbuf_alloc(sizeof(TupleBlock));
tuples->next = NULL;
tuples->tuple_index = 0;
return (tuples);
}
/* --------------------------------
* pbuf_addTuple - Allocate a tuple of n fields (attributes)
* pbuf_addTuple - Allocate a tuple of n fields (attributes)
* --------------------------------
*/
char **
char **
pbuf_addTuple(int n)
{
return (char **)
pbuf_alloc(n * sizeof (char *));
return (char **)
pbuf_alloc(n * sizeof(char *));
}
/* --------------------------------
* pbuf_addTupleValueLengths - Allocate a tuple of n lengths (attributes)
* pbuf_addTupleValueLengths - Allocate a tuple of n lengths (attributes)
* --------------------------------
*/
int *
int *
pbuf_addTupleValueLengths(int n)
{
return (int *)
return (int *)
pbuf_alloc(n * sizeof(int));
}
/* --------------------------------
* pbuf_addValues - Allocate n bytes for a value
* pbuf_addValues - Allocate n bytes for a value
* --------------------------------
*/
char *
char *
pbuf_addValues(int n)
{
return
return
pbuf_alloc(n);
}
/* --------------------------------
* pbuf_addEntry - Allocate a portal entry
* pbuf_addEntry - Allocate a portal entry
* --------------------------------
*/
PortalEntry *pbuf_addEntry()
PortalEntry *
pbuf_addEntry()
{
return (PortalEntry *)
pbuf_alloc (sizeof (PortalEntry));
return (PortalEntry *)
pbuf_alloc(sizeof(PortalEntry));
}
/* --------------------------------
* pbuf_freeEntry - Free a portal entry in the portal table
* the portal is freed separately.
* pbuf_freeEntry - Free a portal entry in the portal table
* the portal is freed separately.
* --------------------------------
*/
void
pbuf_freeEntry(int i)
{
if (portals)
if (portals)
{
pbuf_free ((caddr_t)portals[i]);
portals[i] = NULL;
pbuf_free((caddr_t) portals[i]);
portals[i] = NULL;
}
}
/* --------------------------------
* pbuf_freeTypes - Free up the space used by a portal
* pbuf_freeTypes - Free up the space used by a portal
* --------------------------------
*/
void
pbuf_freeTypes(TypeBlock *types)
pbuf_freeTypes(TypeBlock * types)
{
pbuf_free((caddr_t)types);
pbuf_free((caddr_t) types);
}
/* --------------------------------
* pbuf_freeTuples - free space used by tuple block
* pbuf_freeTuples - free space used by tuple block
* --------------------------------
*/
void
pbuf_freeTuples(TupleBlock *tuples,
int no_tuples,
int no_fields)
pbuf_freeTuples(TupleBlock * tuples,
int no_tuples,
int no_fields)
{
int i, j;
if (no_tuples > TupleBlockSize) {
pbuf_freeTuples (tuples->next, no_tuples - TupleBlockSize, no_fields);
no_tuples = TupleBlockSize;
}
/* For each tuple, free all its attribute values. */
for (i = 0; i < no_tuples; i++) {
for (j = 0; j < no_fields; j++)
if (tuples->values[i][j] != NULL)
pbuf_free((caddr_t)tuples->values[i][j]);
if (tuples->lengths[i])
pbuf_free((caddr_t)tuples->lengths[i]);
if (tuples->values[i])
pbuf_free((caddr_t)tuples->values[i]);
}
pbuf_free((caddr_t)tuples);
int i,
j;
if (no_tuples > TupleBlockSize)
{
pbuf_freeTuples(tuples->next, no_tuples - TupleBlockSize, no_fields);
no_tuples = TupleBlockSize;
}
/* For each tuple, free all its attribute values. */
for (i = 0; i < no_tuples; i++)
{
for (j = 0; j < no_fields; j++)
if (tuples->values[i][j] != NULL)
pbuf_free((caddr_t) tuples->values[i][j]);
if (tuples->lengths[i])
pbuf_free((caddr_t) tuples->lengths[i]);
if (tuples->values[i])
pbuf_free((caddr_t) tuples->values[i]);
}
pbuf_free((caddr_t) tuples);
}
/* --------------------------------
* pbuf_freeGroup - free space used by group, types and tuples
* pbuf_freeGroup - free space used by group, types and tuples
* --------------------------------
*/
void
pbuf_freeGroup(GroupBuffer *group)
pbuf_freeGroup(GroupBuffer * group)
{
if (group->next != NULL)
pbuf_freeGroup(group->next);
if (group->types != NULL)
pbuf_freeTypes(group->types);
if (group->tuples != NULL)
pbuf_freeTuples(group->tuples, group->no_tuples,group->no_fields);
pbuf_free((caddr_t)group);
if (group->next != NULL)
pbuf_freeGroup(group->next);
if (group->types != NULL)
pbuf_freeTypes(group->types);
if (group->tuples != NULL)
pbuf_freeTuples(group->tuples, group->no_tuples, group->no_fields);
pbuf_free((caddr_t) group);
}
/* --------------------------------
* pbuf_freePortal - free space used by portal and portal's group
* pbuf_freePortal - free space used by portal and portal's group
* --------------------------------
*/
void
pbuf_freePortal(PortalBuffer *portal)
pbuf_freePortal(PortalBuffer * portal)
{
if (portal->groups != NULL)
pbuf_freeGroup(portal->groups);
pbuf_free((caddr_t)portal);
if (portal->groups != NULL)
pbuf_freeGroup(portal->groups);
pbuf_free((caddr_t) portal);
}
/* --------------------------------
* pbuf_getIndex - Return the index of the portal entry
* note: portals[] maps portal names to portal buffers.
* pbuf_getIndex - Return the index of the portal entry
* note: portals[] maps portal names to portal buffers.
* --------------------------------
*/
int
pbuf_getIndex(char *pname)
{
int i;
if (portals) {
for (i = 0; i < portals_array_size; i++)
if (portals[i] != NULL &&
strncmp(portals[i]->name, pname, PortalNameLength) == 0)
return i;
}
return (-1);
int i;
if (portals)
{
for (i = 0; i < portals_array_size; i++)
if (portals[i] != NULL &&
strncmp(portals[i]->name, pname, PortalNameLength) == 0)
return i;
}
return (-1);
}
/* --------------------------------
* pbuf_setportalname - assign a user given name to a portal
* pbuf_setportalname - assign a user given name to a portal
* --------------------------------
*/
void
pbuf_setportalinfo(PortalEntry *entry, char *pname)
pbuf_setportalinfo(PortalEntry * entry, char *pname)
{
if (entry)
strNcpy(entry->name, pname, PortalNameLength-1);
if (entry)
strNcpy(entry->name, pname, PortalNameLength - 1);
}
/* --------------------------------
* pbuf_setup - Set up a portal for dumping data
* pbuf_setup - Set up a portal for dumping data
* --------------------------------
*/
PortalEntry *
PortalEntry *
pbuf_setup(char *pname)
{
int i;
if (!portals) /* the portals array has not been allocated yet */
int i;
if (!portals) /* the portals array has not been
* allocated yet */
{
/* allocate portals[] array here */
portals_realloc(PORTALS_INITIAL_SIZE);
/* allocate portals[] array here */
portals_realloc(PORTALS_INITIAL_SIZE);
}
/* If a portal with the same name already exists, close it. */
/* else look for an empty entry in the portal table. */
if ((i = pbuf_getIndex(pname)) != -1)
pbuf_freePortal(portals[i]->portal);
else {
for (i = 0; i < portals_array_size; i++)
if (portals[i] == NULL)
break;
/* If the portal table is full, enlarge it */
if (i >= portals_array_size)
portals_realloc(PORTALS_GROW_BY);
portals[i] = pbuf_addEntry();
strncpy(portals[i]->name, pname, PortalNameLength);
}
portals[i]->portal = pbuf_addPortal();
portals[i]->portalcxt = NULL;
portals[i]->result = NULL;
return portals[i];
/* If a portal with the same name already exists, close it. */
/* else look for an empty entry in the portal table. */
if ((i = pbuf_getIndex(pname)) != -1)
pbuf_freePortal(portals[i]->portal);
else
{
for (i = 0; i < portals_array_size; i++)
if (portals[i] == NULL)
break;
/* If the portal table is full, enlarge it */
if (i >= portals_array_size)
portals_realloc(PORTALS_GROW_BY);
portals[i] = pbuf_addEntry();
strncpy(portals[i]->name, pname, PortalNameLength);
}
portals[i]->portal = pbuf_addPortal();
portals[i]->portalcxt = NULL;
portals[i]->result = NULL;
return portals[i];
}
/* --------------------------------
* pbuf_close - Close a portal, remove it from the portal table
* and free up the space
* pbuf_close - Close a portal, remove it from the portal table
* and free up the space
* --------------------------------
*/
void
pbuf_close(char *pname)
{
int i;
if ((i = pbuf_getIndex(pname)) == -1)
libpq_raise(&PortalError, form("Portal %s does not exist.", pname));
pbuf_freePortal(portals[i]->portal);
pbuf_freeEntry(i);
int i;
if ((i = pbuf_getIndex(pname)) == -1)
libpq_raise(&PortalError, form("Portal %s does not exist.", pname));
pbuf_freePortal(portals[i]->portal);
pbuf_freeEntry(i);
}
/* --------------------------------
* pbuf_findGroup - Return the group given the group_index
* pbuf_findGroup - Return the group given the group_index
* --------------------------------
*/
GroupBuffer *
pbuf_findGroup(PortalBuffer *portal,
int group_index)
GroupBuffer *
pbuf_findGroup(PortalBuffer * portal,
int group_index)
{
GroupBuffer *group;
group = portal->groups;
while (group_index > 0 && group != NULL) {
group = group->next;
group_index--;
}
if (group == NULL)
libpq_raise(&PortalError,
form("Group index %d out of bound.", group_index));
return (group);
GroupBuffer *group;
group = portal->groups;
while (group_index > 0 && group != NULL)
{
group = group->next;
group_index--;
}
if (group == NULL)
libpq_raise(&PortalError,
form("Group index %d out of bound.", group_index));
return (group);
}
/* --------------------------------
@@ -463,49 +473,48 @@ pbuf_findGroup(PortalBuffer *portal,
* --------------------------------
*/
int
pbuf_findFnumber(GroupBuffer *group,
char *field_name)
{
TypeBlock *types;
int i;
types = group->types;
for (i = 0; i < group->no_fields; i++)
if (strncmp(types[i].name, field_name, NAMEDATALEN) == 0)
return (i);
libpq_raise(&PortalError,
form("Field-name %s does not exist.", field_name));
/* not reached, here to make compiler happy */
return 0;
pbuf_findFnumber(GroupBuffer * group,
char *field_name)
{
TypeBlock *types;
int i;
types = group->types;
for (i = 0; i < group->no_fields; i++)
if (strncmp(types[i].name, field_name, NAMEDATALEN) == 0)
return (i);
libpq_raise(&PortalError,
form("Field-name %s does not exist.", field_name));
/* not reached, here to make compiler happy */
return 0;
}
/* --------------------------------
* pbuf_checkFnumber - signal an error if field number is out of bounds
* pbuf_checkFnumber - signal an error if field number is out of bounds
* --------------------------------
*/
void
pbuf_checkFnumber(GroupBuffer *group,
int field_number)
pbuf_checkFnumber(GroupBuffer * group,
int field_number)
{
if (field_number < 0 || field_number >= group->no_fields)
libpq_raise(&PortalError,
form("Field number %d out of bound.", field_number));
if (field_number < 0 || field_number >= group->no_fields)
libpq_raise(&PortalError,
form("Field number %d out of bound.", field_number));
}
/* --------------------------------
* pbuf_findFname - Find the field name given the field index
* pbuf_findFname - Find the field name given the field index
* --------------------------------
*/
char *
pbuf_findFname(GroupBuffer *group,
int field_number)
char *
pbuf_findFname(GroupBuffer * group,
int field_number)
{
pbuf_checkFnumber(group, field_number);
return
(group->types[field_number]).name;
pbuf_checkFnumber(group, field_number);
return
(group->types[field_number]).name;
}

File diff suppressed because it is too large Load Diff

View File

@@ -4,171 +4,185 @@
#include "postgres.h"
#include "libpq/pqcomm.h"
#ifdef HAVE_ENDIAN_H
# include <endian.h>
#ifdef HAVE_ENDIAN_H
#include <endian.h>
#endif
/* --------------------------------------------------------------------- */
/* These definitions for ntoh/hton are the other way around from the
* default system definitions, so we roll our own here.
* default system definitions, so we roll our own here.
*/
#ifndef BYTE_ORDER
#ifndef BYTE_ORDER
#error BYTE_ORDER must be defined as LITTLE_ENDIAN, BIG_ENDIAN or PDP_ENDIAN
#endif
#if BYTE_ORDER == LITTLE_ENDIAN
# define ntoh_s(n) n
# define ntoh_l(n) n
# define hton_s(n) n
# define hton_l(n) n
#else /* BYTE_ORDER != LITTLE_ENDIAN */
# if BYTE_ORDER == BIG_ENDIAN
# define ntoh_s(n) (u_short)(((u_char *)&n)[1] << 8 \
| ((u_char *)&n)[0])
# define ntoh_l(n) (u_long) (((u_char *)&n)[3] << 24 \
| ((u_char *)&n)[2] << 16 \
| ((u_char *)&n)[1] << 8 \
| ((u_char *)&n)[0])
# define hton_s(n) (ntoh_s(n))
# define hton_l(n) (ntoh_l(n))
# else /* BYTE_ORDER != BIG_ENDIAN */
# if BYTE_ORDER == PDP_ENDIAN
# error PDP_ENDIAN macros not written yet
# else /* BYTE_ORDER != anything known */
# error BYTE_ORDER not defined as anything understood
# endif /* BYTE_ORDER == PDP_ENDIAN */
# endif /* BYTE_ORDER == BIG_ENDIAN */
#endif /* BYTE_ORDER == LITTLE_ENDIAN */
#define ntoh_s(n) n
#define ntoh_l(n) n
#define hton_s(n) n
#define hton_l(n) n
#else /* BYTE_ORDER != LITTLE_ENDIAN */
#if BYTE_ORDER == BIG_ENDIAN
#define ntoh_s(n) (u_short)(((u_char *)&n)[1] << 8 \
| ((u_char *)&n)[0])
#define ntoh_l(n) (u_long) (((u_char *)&n)[3] << 24 \
| ((u_char *)&n)[2] << 16 \
| ((u_char *)&n)[1] << 8 \
| ((u_char *)&n)[0])
#define hton_s(n) (ntoh_s(n))
#define hton_l(n) (ntoh_l(n))
#else
/* BYTE_ORDER != BIG_ENDIAN */
#if BYTE_ORDER == PDP_ENDIAN
#error PDP_ENDIAN macros not written yet
#else
/* BYTE_ORDER != anything known */
#error BYTE_ORDER not defined as anything understood
#endif /* BYTE_ORDER == PDP_ENDIAN */
#endif /* BYTE_ORDER == BIG_ENDIAN */
#endif /* BYTE_ORDER == LITTLE_ENDIAN */
/* --------------------------------------------------------------------- */
int pqPutShort(int integer, FILE *f)
{
int retval = 0;
u_short n,s;
s = integer;
n = hton_s(s);
if(fwrite(&n, sizeof(u_short), 1, f) != 1)
retval = EOF;
return retval;
}
int
pqPutShort(int integer, FILE * f)
{
int retval = 0;
u_short n,
s;
s = integer;
n = hton_s(s);
if (fwrite(&n, sizeof(u_short), 1, f) != 1)
retval = EOF;
return retval;
}
/* --------------------------------------------------------------------- */
int pqPutLong(int integer, FILE *f)
{
int retval = 0;
u_long n;
n = hton_l(integer);
if(fwrite(&n, sizeof(u_long), 1, f) != 1)
retval = EOF;
return retval;
}
/* --------------------------------------------------------------------- */
int pqGetShort(int *result, FILE *f)
{
int retval = 0;
u_short n;
int
pqPutLong(int integer, FILE * f)
{
int retval = 0;
u_long n;
if(fread(&n, sizeof(u_short), 1, f) != 1)
retval = EOF;
*result = ntoh_s(n);
return retval;
}
n = hton_l(integer);
if (fwrite(&n, sizeof(u_long), 1, f) != 1)
retval = EOF;
return retval;
}
/* --------------------------------------------------------------------- */
int pqGetLong(int *result, FILE *f)
{
int retval = 0;
u_long n;
if(fread(&n, sizeof(u_long), 1, f) != 1)
retval = EOF;
*result = ntoh_l(n);
return retval;
}
int
pqGetShort(int *result, FILE * f)
{
int retval = 0;
u_short n;
if (fread(&n, sizeof(u_short), 1, f) != 1)
retval = EOF;
*result = ntoh_s(n);
return retval;
}
/* --------------------------------------------------------------------- */
int
pqGetLong(int *result, FILE * f)
{
int retval = 0;
u_long n;
if (fread(&n, sizeof(u_long), 1, f) != 1)
retval = EOF;
*result = ntoh_l(n);
return retval;
}
/* --------------------------------------------------------------------- */
/* pqGetNBytes: Read a chunk of exactly len bytes in buffer s.
Return 0 if ok.
Return 0 if ok.
*/
int pqGetNBytes(char *s, size_t len, FILE *f)
{
int cnt;
int
pqGetNBytes(char *s, size_t len, FILE * f)
{
int cnt;
if (f == NULL)
return EOF;
cnt = fread(s, 1, len, f);
s[cnt] = '\0';
/* mjl: actually needs up to len+1 bytes, is this okay? XXX */
/* mjl: actually needs up to len+1 bytes, is this okay? XXX */
return (cnt == len) ? 0 : EOF;
}
}
/* --------------------------------------------------------------------- */
int pqPutNBytes(const char *s, size_t len, FILE *f)
{
int
pqPutNBytes(const char *s, size_t len, FILE * f)
{
if (f == NULL)
return 0;
if(fwrite(s, 1, len, f) != len)
return EOF;
if (fwrite(s, 1, len, f) != len)
return EOF;
return 0;
}
}
/* --------------------------------------------------------------------- */
int pqGetString(char *s, size_t len, FILE *f)
{
int c;
int
pqGetString(char *s, size_t len, FILE * f)
{
int c;
if (f == NULL)
return EOF;
return EOF;
while (len-- && (c = getc(f)) != EOF && c)
*s++ = c;
*s = '\0';
/* mjl: actually needs up to len+1 bytes, is this okay? XXX */
/* mjl: actually needs up to len+1 bytes, is this okay? XXX */
return 0;
}
}
/* --------------------------------------------------------------------- */
int pqPutString(const char *s, FILE *f)
{
int
pqPutString(const char *s, FILE * f)
{
if (f == NULL)
return 0;
if (fputs(s, f) == EOF)
return EOF;
fputc('\0', f); /* important to send an ending \0 since backend expects it */
fputc('\0', f); /* important to send an ending \0 since
* backend expects it */
fflush(f);
return 0;
}
}
/* --------------------------------------------------------------------- */
int pqGetByte(FILE *f)
{
int
pqGetByte(FILE * f)
{
return getc(f);
}
/* --------------------------------------------------------------------- */
int pqPutByte(int c, FILE *f)
{
if(!f) return 0;
return (putc(c, f) == c) ? 0 : EOF;
}
/* --------------------------------------------------------------------- */
}
/* --------------------------------------------------------------------- */
int
pqPutByte(int c, FILE * f)
{
if (!f)
return 0;
return (putc(c, f) == c) ? 0 : EOF;
}
/* --------------------------------------------------------------------- */

View File

@@ -1,39 +1,39 @@
/*-------------------------------------------------------------------------
*
* pqpacket.c--
* routines for reading and writing data packets sent/received by
* POSTGRES clients and servers
* routines for reading and writing data packets sent/received by
* POSTGRES clients and servers
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/libpq/Attic/pqpacket.c,v 1.5 1997/08/12 22:53:00 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/libpq/Attic/pqpacket.c,v 1.6 1997/09/07 04:42:28 momjian Exp $
*
*-------------------------------------------------------------------------
*/
/* NOTES
* This is the module that understands the lowest-level part
* of the communication protocol. All of the trickiness in
* this module is for making sure that non-blocking I/O in
* the Postmaster works correctly. Check the notes in PacketRecv
* on non-blocking I/O.
* This is the module that understands the lowest-level part
* of the communication protocol. All of the trickiness in
* this module is for making sure that non-blocking I/O in
* the Postmaster works correctly. Check the notes in PacketRecv
* on non-blocking I/O.
*
* Data Structures:
* Port has two important functions. (1) It records the
* sock/addr used in communication. (2) It holds partially
* read in messages. This is especially important when
* we haven't seen enough to construct a complete packet
* header.
* Port has two important functions. (1) It records the
* sock/addr used in communication. (2) It holds partially
* read in messages. This is especially important when
* we haven't seen enough to construct a complete packet
* header.
*
* PacketBuf -- None of the clients of this module should know
* what goes into a packet hdr (although they know how big
* it is). This routine is in charge of host to net order
* conversion for headers. Data conversion is someone elses
* responsibility.
* what goes into a packet hdr (although they know how big
* it is). This routine is in charge of host to net order
* conversion for headers. Data conversion is someone elses
* responsibility.
*
* IMPORTANT: these routines are called by backends, clients, and
* the Postmaster.
* the Postmaster.
*
*/
#include <stdio.h>
@@ -57,134 +57,156 @@
*
*/
int
PacketReceive(Port *port, /* receive port */
PacketBuf *buf, /* MAX_PACKET_SIZE-worth of buffer space */
bool nonBlocking) /* NON_BLOCKING or BLOCKING i/o */
PacketReceive(Port * port, /* receive port */
PacketBuf * buf, /* MAX_PACKET_SIZE-worth of buffer space */
bool nonBlocking) /* NON_BLOCKING or BLOCKING i/o */
{
PacketLen max_size = sizeof(PacketBuf);
PacketLen cc; /* character count -- bytes recvd */
PacketLen packetLen; /* remaining packet chars to read */
Addr tmp; /* curr recv buf pointer */
int addrLen = sizeof(struct sockaddr_in);
int hdrLen;
int flag;
int decr;
hdrLen = sizeof(buf->len);
PacketLen max_size = sizeof(PacketBuf);
PacketLen cc; /* character count -- bytes recvd */
PacketLen packetLen; /* remaining packet chars to read */
Addr tmp; /* curr recv buf pointer */
int addrLen = sizeof(struct sockaddr_in);
int hdrLen;
int flag;
int decr;
if (nonBlocking == NON_BLOCKING) {
flag = MSG_PEEK;
decr = 0;
} else {
flag = 0;
decr = hdrLen;
}
/*
* Assume port->nBytes is zero unless we were interrupted during
* non-blocking I/O. This first recvfrom() is to get the hdr
* information so we know how many bytes to read. Life would
* be very complicated if we read too much data (buffering).
*/
tmp = ((Addr)buf) + port->nBytes;
hdrLen = sizeof(buf->len);
if (port->nBytes >= hdrLen) {
packetLen = ntohl(buf->len) - port->nBytes;
}
else {
/* peeking into the incoming message */
cc = recvfrom(port->sock, (char *)&(buf->len), hdrLen, flag,
(struct sockaddr*) &(port->raddr), &addrLen);
if (cc < hdrLen) {
/* if cc is negative, the system call failed */
if (cc < 0) {
return(STATUS_ERROR);
}
/*
* cc == 0 means the connection was broken at the
* other end.
*/
else if (! cc) {
return(STATUS_INVALID);
} else {
/*
* Worst case. We didn't even read in enough data to
* get the header length.
* since we are using a data stream,
* this happens only if the client is mallicious.
*
* Don't save the number of bytes we've read so far.
* Since we only peeked at the incoming message, the
* kernel is going to keep it for us.
*/
return(STATUS_NOT_DONE);
}
} else {
/*
* This is an attempt to shield the Postmaster
* from mallicious attacks by placing tighter
* restrictions on the reported packet length.
*
* Check for negative packet length
*/
if ((buf->len) <= 0) {
return(STATUS_INVALID);
}
/*
* Check for oversize packet
*/
if ((ntohl(buf->len)) > max_size) {
return(STATUS_INVALID);
}
/*
* great. got the header. now get the true length (including
* header size).
*/
packetLen = ntohl(buf->len);
/*
* if someone is sending us junk, close the connection
*/
if (packetLen > max_size) {
port->nBytes = packetLen;
return(STATUS_BAD_PACKET);
}
packetLen -= decr;
tmp += decr - port->nBytes;
if (nonBlocking == NON_BLOCKING)
{
flag = MSG_PEEK;
decr = 0;
}
}
/*
* Now that we know how big it is, read the packet. We read
* the entire packet, since the last call was just a peek.
*/
while (packetLen) {
cc = recvfrom(port->sock, tmp, packetLen, 0,
(struct sockaddr*) &(port->raddr), &addrLen);
if (cc < 0)
return(STATUS_ERROR);
/*
* cc == 0 means the connection was broken at the
* other end.
else
{
flag = 0;
decr = hdrLen;
}
/*
* Assume port->nBytes is zero unless we were interrupted during
* non-blocking I/O. This first recvfrom() is to get the hdr
* information so we know how many bytes to read. Life would be very
* complicated if we read too much data (buffering).
*/
else if (! cc)
return(STATUS_INVALID);
tmp = ((Addr) buf) + port->nBytes;
if (port->nBytes >= hdrLen)
{
packetLen = ntohl(buf->len) - port->nBytes;
}
else
{
/* peeking into the incoming message */
cc = recvfrom(port->sock, (char *) &(buf->len), hdrLen, flag,
(struct sockaddr *) & (port->raddr), &addrLen);
if (cc < hdrLen)
{
/* if cc is negative, the system call failed */
if (cc < 0)
{
return (STATUS_ERROR);
}
/*
* cc == 0 means the connection was broken at the other end.
*/
else if (!cc)
{
return (STATUS_INVALID);
}
else
{
/*
* Worst case. We didn't even read in enough data to get
* the header length. since we are using a data stream,
* this happens only if the client is mallicious.
*
* Don't save the number of bytes we've read so far. Since we
* only peeked at the incoming message, the kernel is
* going to keep it for us.
*/
return (STATUS_NOT_DONE);
}
}
else
{
/*
* This is an attempt to shield the Postmaster from mallicious
* attacks by placing tighter restrictions on the reported
* packet length.
*
* Check for negative packet length
*/
if ((buf->len) <= 0)
{
return (STATUS_INVALID);
}
/*
* Check for oversize packet
*/
if ((ntohl(buf->len)) > max_size)
{
return (STATUS_INVALID);
}
/*
* great. got the header. now get the true length (including
* header size).
*/
packetLen = ntohl(buf->len);
/*
* if someone is sending us junk, close the connection
*/
if (packetLen > max_size)
{
port->nBytes = packetLen;
return (STATUS_BAD_PACKET);
}
packetLen -= decr;
tmp += decr - port->nBytes;
}
}
/*
* Now that we know how big it is, read the packet. We read the
* entire packet, since the last call was just a peek.
*/
while (packetLen)
{
cc = recvfrom(port->sock, tmp, packetLen, 0,
(struct sockaddr *) & (port->raddr), &addrLen);
if (cc < 0)
return (STATUS_ERROR);
/*
* cc == 0 means the connection was broken at the other end.
*/
else if (!cc)
return (STATUS_INVALID);
/*
fprintf(stderr,"expected packet of %d bytes, got %d bytes\n",
packetLen, cc);
packetLen, cc);
*/
tmp += cc;
packetLen -= cc;
/* if non-blocking, we're done. */
if (nonBlocking && packetLen) {
port->nBytes += cc;
return(STATUS_NOT_DONE);
tmp += cc;
packetLen -= cc;
/* if non-blocking, we're done. */
if (nonBlocking && packetLen)
{
port->nBytes += cc;
return (STATUS_NOT_DONE);
}
}
}
port->nBytes = 0;
return(STATUS_OK);
port->nBytes = 0;
return (STATUS_OK);
}
/*
@@ -192,46 +214,47 @@ PacketReceive(Port *port, /* receive port */
*
* 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.
* 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(Port * port,
PacketBuf * buf,
PacketLen len,
bool nonBlocking)
{
PacketLen totalLen;
int addrLen = sizeof(struct sockaddr_in);
Assert(!nonBlocking);
Assert(buf);
totalLen = len;
len = sendto(port->sock, (Addr) buf, totalLen, /* flags */ 0,
(struct sockaddr *)&(port->raddr), addrLen);
if (len < totalLen) {
sprintf(PQerrormsg,
"FATAL: PacketSend: couldn't send complete packet: errno=%d\n",
errno);
fputs(PQerrormsg, stderr);
return(STATUS_ERROR);
}
return(STATUS_OK);
PacketLen totalLen;
int addrLen = sizeof(struct sockaddr_in);
Assert(!nonBlocking);
Assert(buf);
totalLen = len;
len = sendto(port->sock, (Addr) buf, totalLen, /* flags */ 0,
(struct sockaddr *) & (port->raddr), addrLen);
if (len < totalLen)
{
sprintf(PQerrormsg,
"FATAL: PacketSend: couldn't send complete packet: errno=%d\n",
errno);
fputs(PQerrormsg, stderr);
return (STATUS_ERROR);
}
return (STATUS_OK);
}
/*
* StartupInfo2PacketBuf -
* convert the fields of the StartupInfo to a PacketBuf
* convert the fields of the StartupInfo to a PacketBuf
*
*/
/* moved to src/libpq/fe-connect.c */
/*
PacketBuf*
PacketBuf*
StartupInfo2PacketBuf(StartupInfo* s)
{
PacketBuf* res;
@@ -259,10 +282,10 @@ StartupInfo2PacketBuf(StartupInfo* s)
/*
* PacketBuf2StartupInfo -
* convert the fields of the StartupInfo to a PacketBuf
* convert the fields of the StartupInfo to a PacketBuf
*
*/
/* moved to postmaster.c
/* moved to postmaster.c
StartupInfo*
PacketBuf2StartupInfo(PacketBuf* p)
{

View File

@@ -1,41 +1,41 @@
/*-------------------------------------------------------------------------
*
* pqsignal.c--
* reliable BSD-style signal(2) routine stolen from RWW who stole it
* from Stevens...
* reliable BSD-style signal(2) routine stolen from RWW who stole it
* from Stevens...
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/libpq/pqsignal.c,v 1.5 1996/12/26 22:07:08 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/libpq/pqsignal.c,v 1.6 1997/09/07 04:42:29 momjian Exp $
*
* NOTES
* This shouldn't be in libpq, but the monitor and some other
* things need it...
* This shouldn't be in libpq, but the monitor and some other
* things need it...
*
* A NOTE ABOUT SIGNAL HANDLING ACROSS THE VARIOUS PLATFORMS.
* A NOTE ABOUT SIGNAL HANDLING ACROSS THE VARIOUS PLATFORMS.
*
* config.h defines the macro USE_POSIX_SIGNALS for some platforms and
* not for others. This file and pqsignal.h use that macro to decide
* how to handle signalling.
* config.h defines the macro USE_POSIX_SIGNALS for some platforms and
* not for others. This file and pqsignal.h use that macro to decide
* how to handle signalling.
*
* signal(2) handling - this is here because it affects some of
* the frontend commands as well as the backend server.
*
* Ultrix and SunOS provide BSD signal(2) semantics by default.
*
* SVID2 and POSIX signal(2) semantics differ from BSD signal(2)
* semantics. We can use the POSIX sigaction(2) on systems that
* allow us to request restartable signals (SA_RESTART).
*
* Some systems don't allow restartable signals at all unless we
* link to a special BSD library.
*
* We devoutly hope that there aren't any systems that provide
* neither POSIX signals nor BSD signals. The alternative
* is to do signal-handler reinstallation, which doesn't work well
* at all.
* signal(2) handling - this is here because it affects some of
* the frontend commands as well as the backend server.
*
* Ultrix and SunOS provide BSD signal(2) semantics by default.
*
* SVID2 and POSIX signal(2) semantics differ from BSD signal(2)
* semantics. We can use the POSIX sigaction(2) on systems that
* allow us to request restartable signals (SA_RESTART).
*
* Some systems don't allow restartable signals at all unless we
* link to a special BSD library.
*
* We devoutly hope that there aren't any systems that provide
* neither POSIX signals nor BSD signals. The alternative
* is to do signal-handler reinstallation, which doesn't work well
* at all.
* ------------------------------------------------------------------------*/
#include <postgres.h>
@@ -47,18 +47,20 @@ pqsigfunc
pqsignal(int signo, pqsigfunc func)
{
#if !defined(USE_POSIX_SIGNALS)
return signal(signo, func);
return signal(signo, func);
#else
struct sigaction act, oact;
act.sa_handler = func;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
if (signo != SIGALRM) {
act.sa_flags |= SA_RESTART;
}
if (sigaction(signo, &act, &oact) < 0)
return(SIG_ERR);
return(oact.sa_handler);
#endif /* !USE_POSIX_SIGNALS */
struct sigaction act,
oact;
act.sa_handler = func;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
if (signo != SIGALRM)
{
act.sa_flags |= SA_RESTART;
}
if (sigaction(signo, &act, &oact) < 0)
return (SIG_ERR);
return (oact.sa_handler);
#endif /* !USE_POSIX_SIGNALS */
}

View File

@@ -1,100 +1,100 @@
/*-------------------------------------------------------------------------
*
* util.c--
* general routines for libpq backend
* general routines for libpq backend
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/libpq/Attic/util.c,v 1.3 1996/11/06 08:48:33 scrappy Exp $
* $Header: /cvsroot/pgsql/src/backend/libpq/Attic/util.c,v 1.4 1997/09/07 04:42:31 momjian Exp $
*
*-------------------------------------------------------------------------
*/
/*
* UTILITY ROUTINES
* pqdebug - send a string to the debugging output port
* pqdebug2 - send two strings to stdout
* PQtrace - turn on pqdebug() tracing
* PQuntrace - turn off pqdebug() tracing
* UTILITY ROUTINES
* pqdebug - send a string to the debugging output port
* pqdebug2 - send two strings to stdout
* PQtrace - turn on pqdebug() tracing
* PQuntrace - turn off pqdebug() tracing
*/
#include <stdio.h> /* for sprintf() */
#include <stdio.h> /* for sprintf() */
#include <string.h>
#include <postgres.h>
#include <lib/dllist.h>
#include <libpq/libpq.h> /* where the declarations go */
#include <libpq/libpq.h> /* where the declarations go */
#include <utils/exc.h>
/* ----------------
* exceptions
* exceptions
* ----------------
*/
Exception MemoryError = {"Memory Allocation Error"};
Exception PortalError = {"Invalid arguments to portal functions"};
Exception PostquelError = {"Sql Error"};
Exception ProtocolError = {"Protocol Error"};
char PQerrormsg[ERROR_MSG_LENGTH];
Exception MemoryError = {"Memory Allocation Error"};
Exception PortalError = {"Invalid arguments to portal functions"};
Exception PostquelError = {"Sql Error"};
Exception ProtocolError = {"Protocol Error"};
char PQerrormsg[ERROR_MSG_LENGTH];
int PQtracep = 0; /* 1 to print out debugging messages */
FILE *debug_port = (FILE *) NULL;
int PQtracep = 0; /* 1 to print out debugging messages */
FILE *debug_port = (FILE *) NULL;
/* ----------------------------------------------------------------
* PQ utility routines
* PQ utility routines
* ----------------------------------------------------------------
*/
void
pqdebug(char *target, char *msg)
{
if (!target)
return;
if (PQtracep) {
/*
* if nothing else was suggested default to stdout
*/
if (!debug_port)
debug_port = stdout;
fprintf(debug_port, target, msg);
fprintf(debug_port, "\n");
}
if (!target)
return;
if (PQtracep)
{
/*
* if nothing else was suggested default to stdout
*/
if (!debug_port)
debug_port = stdout;
fprintf(debug_port, target, msg);
fprintf(debug_port, "\n");
}
}
void
pqdebug2(char *target, char *msg1, char *msg2)
{
if (!target)
return;
if (PQtracep) {
/*
* if nothing else was suggested default to stdout
*/
if (!debug_port)
debug_port = stdout;
fprintf(debug_port, target, msg1, msg2);
fprintf(debug_port, "\n");
}
if (!target)
return;
if (PQtracep)
{
/*
* if nothing else was suggested default to stdout
*/
if (!debug_port)
debug_port = stdout;
fprintf(debug_port, target, msg1, msg2);
fprintf(debug_port, "\n");
}
}
/* --------------------------------
* PQtrace() / PQuntrace()
* PQtrace() / PQuntrace()
* --------------------------------
*/
void
PQtrace()
{
PQtracep = 1;
PQtracep = 1;
}
void
PQuntrace()
{
PQtracep = 0;
PQtracep = 0;
}