diff options
author | Bruce Momjian <bruce@momjian.us> | 1997-09-07 05:04:48 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 1997-09-07 05:04:48 +0000 |
commit | 1ccd423235a48739d6f7a4d7889705b5f9ecc69b (patch) | |
tree | 8001c4e839dfad8f29ceda7f8c5f5dbb8759b564 /src/backend/libpq | |
parent | 8fecd4febf8357f3cc20383ed29ced484877d5ac (diff) | |
download | postgresql-1ccd423235a48739d6f7a4d7889705b5f9ecc69b.tar.gz postgresql-1ccd423235a48739d6f7a4d7889705b5f9ecc69b.zip |
Massive commit to run PGINDENT on all *.c and *.h files.
Diffstat (limited to 'src/backend/libpq')
-rw-r--r-- | src/backend/libpq/auth.c | 838 | ||||
-rw-r--r-- | src/backend/libpq/be-dumpdata.c | 448 | ||||
-rw-r--r-- | src/backend/libpq/be-fsstubs.c | 470 | ||||
-rw-r--r-- | src/backend/libpq/be-pqexec.c | 613 | ||||
-rw-r--r-- | src/backend/libpq/hba.c | 1336 | ||||
-rw-r--r-- | src/backend/libpq/password.c | 190 | ||||
-rw-r--r-- | src/backend/libpq/portal.c | 946 | ||||
-rw-r--r-- | src/backend/libpq/portalbuf.c | 609 | ||||
-rw-r--r-- | src/backend/libpq/pqcomm.c | 1016 | ||||
-rw-r--r-- | src/backend/libpq/pqcomprim.c | 230 | ||||
-rw-r--r-- | src/backend/libpq/pqpacket.c | 361 | ||||
-rw-r--r-- | src/backend/libpq/pqsignal.c | 78 | ||||
-rw-r--r-- | src/backend/libpq/util.c | 98 |
13 files changed, 3835 insertions, 3398 deletions
diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c index abf59e25b17..ff6711d3b5c 100644 --- a/src/backend/libpq/auth.c +++ b/src/backend/libpq/auth.c @@ -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); + sprintf(PQerrormsg, + "pg_krb5_recvauth: Kerberos not implemented on this " + "server.\n"); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); -return(STATUS_ERROR); + return (STATUS_ERROR); } -#endif /* KRB5 */ + +#endif /* KRB5 */ static int -pg_password_recvauth(Port *port, char *database, char *DataDir) +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; - } + 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; + user = buf.data; + password = buf.data + strlen(user) + 1; - return verify_password(user, password, port, database, DataDir); + 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; - - /* 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); + 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); } - 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); + + 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); } - break; - default: - sprintf(PQerrormsg, - "be_recvauth: unrecognized message type: %d\n", - msgtype); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); - return(STATUS_ERROR); - } - return(STATUS_OK); + 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); } diff --git a/src/backend/libpq/be-dumpdata.c b/src/backend/libpq/be-dumpdata.c index b47e79fa65c..db0a99141d6 100644 --- a/src/backend/libpq/be-dumpdata.c +++ b/src/backend/libpq/be-dumpdata.c @@ -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); } diff --git a/src/backend/libpq/be-fsstubs.c b/src/backend/libpq/be-fsstubs.c index 58a827838db..e3a464b087f 100644 --- a/src/backend/libpq/be-fsstubs.c +++ b/src/backend/libpq/be-fsstubs.c @@ -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 */ - MemoryContextSwitchTo(currentContext); -#if FSDB - elog(NOTICE,"cannot open large object %d", lobjId); + 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); + return -1; + } + + fd = newLOfd(lobjDesc); - /* switch context back to orig. */ - MemoryContextSwitchTo(currentContext); + /* switch context back to orig. */ + MemoryContextSwitchTo(currentContext); - return fd; + return fd; } int lo_close(int fd) { - 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; - } + 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 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) { + 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; + } + + lobjId = lobjDesc->heap_r->rd_id; + + inv_close(lobjDesc); + + /* switch context back to original memory context */ MemoryContextSwitchTo(currentContext); - return InvalidOid; - } - - lobjId = lobjDesc->heap_r->rd_id; - - inv_close(lobjDesc); - - /* switch context back to original memory context */ - MemoryContextSwitchTo(currentContext); - - return lobjId; + + 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; - - /* - * 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); - } - - /* - * 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); + int fd; + int nbytes, + tmp; + +#define BUFSIZE 1024 + char buf[BUFSIZE]; + char fnamebuf[8192]; + LargeObjectDesc *lobj; + Oid lobjOid; + + /* + * 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; - - /* - * create an inversion "object" - */ - lobj = inv_open(lobjId, INV_READ); - if (lobj == NULL) { - elog(WARN, "lo_export: can't open inv object %d", - lobjId); - } - - /* - * 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); + int fd; + int nbytes, + tmp; + +#define BUFSIZE 1024 + char buf[BUFSIZE]; + char fnamebuf[8192]; + LargeObjectDesc *lobj; + mode_t oumask; + + /* + * create an inversion "object" + */ + lobj = inv_open(lobjId, INV_READ); + if (lobj == NULL) + { + elog(WARN, "lo_export: can't open inv object %d", + lobjId); + } + + /* + * 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); } - } - inv_close(lobj); - close(fd); + /* + * 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; + 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; } diff --git a/src/backend/libpq/be-pqexec.c b/src/backend/libpq/be-pqexec.c index caa710129a9..06185e4534f 100644 --- a/src/backend/libpq/be-pqexec.c +++ b/src/backend/libpq/be-pqexec.c @@ -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); } - } - - /* ---------------- - * 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; + + /* ---------------- + * 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); } diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c index 0cc2bbf6ac9..014eca14fa3 100644 --- a/src/backend/libpq/hba.c +++ b/src/backend/libpq/hba.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * hba.c-- - * Routines to handle host based authentication (that's the scheme - * wherein you authenticate a user by seeing what IP address the system - * says he comes from and possibly using ident). + * Routines to handle host based authentication (that's the scheme + * wherein you authenticate a user by seeing what IP address the system + * says he comes from and possibly using ident). * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.19 1997/08/27 03:48:31 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.20 1997/09/07 04:42:21 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -27,263 +27,356 @@ #include <libpq/libpq.h> #include <libpq/pqcomm.h> #include <libpq/hba.h> -#include <port/inet_aton.h> /* For inet_aton() */ +#include <port/inet_aton.h> /* For inet_aton() */ #include <storage/fd.h> /* Some standard C libraries, including GNU, have an isblank() function. Others, including Solaris, do not. So we have our own. */ -static bool -isblank(const char c) { - return(c == ' ' || c == 9 /* tab */); +static bool +isblank(const char c) +{ + return (c == ' ' || c == 9 /* tab */ ); } -static void -next_token(FILE *fp, char *buf, const int bufsz) { +static void +next_token(FILE * fp, char *buf, const int bufsz) +{ /*-------------------------------------------------------------------------- Grab one token out of fp. Tokens are strings of non-blank characters bounded by blank characters, beginning of line, and end - of line. Blank means space or tab. Return the token as *buf. + of line. Blank means space or tab. Return the token as *buf. Leave file positioned to character immediately after the token or EOF, whichever comes first. If no more tokens on line, return null string as *buf and position file to beginning of next line or EOF, - whichever comes first. + whichever comes first. --------------------------------------------------------------------------*/ - int c; - char *eb = buf+(bufsz-1); - - /* Move over inital token-delimiting blanks */ - while (isblank(c = getc(fp))) ; - - if (c != '\n') { - /* build a token in buf of next characters up to EOF, eol, or blank. */ - while (c != EOF && c != '\n' && !isblank(c)) { - if (buf < eb) *buf++ = c; - c = getc(fp); - /* Put back the char right after the token (putting back EOF is ok) */ - } - ungetc(c, fp); - } - *buf = '\0'; + int c; + char *eb = buf + (bufsz - 1); + + /* Move over inital token-delimiting blanks */ + while (isblank(c = getc(fp))); + + if (c != '\n') + { + + /* + * build a token in buf of next characters up to EOF, eol, or + * blank. + */ + while (c != EOF && c != '\n' && !isblank(c)) + { + if (buf < eb) + *buf++ = c; + c = getc(fp); + + /* + * Put back the char right after the token (putting back EOF + * is ok) + */ + } + ungetc(c, fp); + } + *buf = '\0'; } static void -read_through_eol(FILE *file) { - int c; - do - c = getc(file); - while (c != '\n' && c != EOF); +read_through_eol(FILE * file) +{ + int c; + + do + c = getc(file); + while (c != '\n' && c != EOF); } static void -read_hba_entry2(FILE *file, enum Userauth *userauth_p, char usermap_name[], - bool *error_p, bool *matches_p, bool find_password_entries) { +read_hba_entry2(FILE * file, enum Userauth * userauth_p, char usermap_name[], + bool * error_p, bool * matches_p, bool find_password_entries) +{ /*-------------------------------------------------------------------------- Read from file FILE the rest of a host record, after the mask field, and return the interpretation of it as *userauth_p, usermap_name, and *error_p. ---------------------------------------------------------------------------*/ - char buf[MAX_TOKEN]; - - bool userauth_valid; - - /* Get authentication type token. */ - next_token(file, buf, sizeof(buf)); - userauth_valid = false; - if (buf[0] == '\0') { - *error_p = true; - } else { - userauth_valid = true; - if(strcmp(buf, "trust") == 0) { - *userauth_p = Trust; - } else if(strcmp(buf, "ident") == 0) { - *userauth_p = Ident; - } else if(strcmp(buf, "password") == 0) { - *userauth_p = Password; - } else { - userauth_valid = false; - } - - if((find_password_entries && strcmp(buf, "password") == 0) || - (!find_password_entries && strcmp(buf, "password") != 0)) { - *matches_p = true; - } else { - *matches_p = false; - } - } - - if(!userauth_valid || !*matches_p || *error_p) { - if (!userauth_valid) { - *error_p = true; - } - read_through_eol(file); - } else { - /* Get the map name token, if any */ - next_token(file, buf, sizeof(buf)); - if (buf[0] == '\0') { - *error_p = false; - usermap_name[0] = '\0'; - } else { - strncpy(usermap_name, buf, USERMAP_NAME_SIZE); - next_token(file, buf, sizeof(buf)); - if (buf[0] != '\0') { - *error_p = true; - read_through_eol(file); - } else *error_p = false; - } - } + char buf[MAX_TOKEN]; + + bool userauth_valid; + + /* Get authentication type token. */ + next_token(file, buf, sizeof(buf)); + userauth_valid = false; + if (buf[0] == '\0') + { + *error_p = true; + } + else + { + userauth_valid = true; + if (strcmp(buf, "trust") == 0) + { + *userauth_p = Trust; + } + else if (strcmp(buf, "ident") == 0) + { + *userauth_p = Ident; + } + else if (strcmp(buf, "password") == 0) + { + *userauth_p = Password; + } + else + { + userauth_valid = false; + } + + if ((find_password_entries && strcmp(buf, "password") == 0) || + (!find_password_entries && strcmp(buf, "password") != 0)) + { + *matches_p = true; + } + else + { + *matches_p = false; + } + } + + if (!userauth_valid || !*matches_p || *error_p) + { + if (!userauth_valid) + { + *error_p = true; + } + read_through_eol(file); + } + else + { + /* Get the map name token, if any */ + next_token(file, buf, sizeof(buf)); + if (buf[0] == '\0') + { + *error_p = false; + usermap_name[0] = '\0'; + } + else + { + strncpy(usermap_name, buf, USERMAP_NAME_SIZE); + next_token(file, buf, sizeof(buf)); + if (buf[0] != '\0') + { + *error_p = true; + read_through_eol(file); + } + else + *error_p = false; + } + } } static void -process_hba_record(FILE *file, - const struct in_addr ip_addr, const char database[], - bool *matches_p, bool *error_p, - enum Userauth *userauth_p, char usermap_name[], - bool find_password_entries) { +process_hba_record(FILE * file, + const struct in_addr ip_addr, const char database[], + bool * matches_p, bool * error_p, + enum Userauth * userauth_p, char usermap_name[], + bool find_password_entries) +{ /*--------------------------------------------------------------------------- Process the non-comment record in the config file that is next on the file. See if it applies to a connection to a host with IP address "ip_addr" to a database named "database[]". If so, return *matches_p true and *userauth_p and usermap_name[] as the values from the entry. If not, return matches_p false. If the record has a syntax error, - return *error_p true, after issuing a message to stderr. If no error, + return *error_p true, after issuing a message to stderr. If no error, leave *error_p as it was. ---------------------------------------------------------------------------*/ - char buf[MAX_TOKEN]; /* A token from the record */ - - /* Read the record type field */ - next_token(file, buf, sizeof(buf)); - if (buf[0] == '\0') *matches_p = false; - else { - /* if this isn't a "host" record, it can't match. */ - if (strcmp(buf, "host") != 0) { - *matches_p = false; - read_through_eol(file); - } else { - /* It's a "host" record. Read the database name field. */ - next_token(file, buf, sizeof(buf)); - if (buf[0] == '\0') *matches_p = false; - else { - /* If this record isn't for our database, ignore it. */ - if (strcmp(buf, database) != 0 && strcmp(buf, "all") != 0) { - *matches_p = false; - read_through_eol(file); - } else { - /* Read the IP address field */ - next_token(file, buf, sizeof(buf)); - if (buf[0] == '\0') *matches_p = false; - else { - int valid; /* Field is valid dotted decimal */ - /* Remember the IP address field and go get mask field */ - struct in_addr file_ip_addr; /* IP address field value */ - - valid = inet_aton(buf, &file_ip_addr); - if (!valid) { - *matches_p = false; - read_through_eol(file); - } else { - /* Read the mask field */ - next_token(file, buf, sizeof(buf)); - if (buf[0] == '\0') *matches_p = false; - else { - struct in_addr mask; - /* Got mask. Now see if this record is for our host. */ - valid = inet_aton(buf, &mask); - if (!valid) { - *matches_p = false; - read_through_eol(file); - } else { - if (((file_ip_addr.s_addr ^ ip_addr.s_addr) & mask.s_addr) - != 0x0000) { - *matches_p = false; - read_through_eol(file); - } else { - /* This is the record we're looking for. Read - the rest of the info from it. - */ - read_hba_entry2(file, userauth_p, usermap_name, - error_p, matches_p, find_password_entries); - if (*error_p) { - sprintf(PQerrormsg, - "process_hba_record: invalid syntax in " - "hba config file " - "for host record for IP address %s\n", - inet_ntoa(file_ip_addr)); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); - } - } - } - } - } - } - } - } - } - } + char buf[MAX_TOKEN]; /* A token from the record */ + + /* Read the record type field */ + next_token(file, buf, sizeof(buf)); + if (buf[0] == '\0') + *matches_p = false; + else + { + /* if this isn't a "host" record, it can't match. */ + if (strcmp(buf, "host") != 0) + { + *matches_p = false; + read_through_eol(file); + } + else + { + /* It's a "host" record. Read the database name field. */ + next_token(file, buf, sizeof(buf)); + if (buf[0] == '\0') + *matches_p = false; + else + { + /* If this record isn't for our database, ignore it. */ + if (strcmp(buf, database) != 0 && strcmp(buf, "all") != 0) + { + *matches_p = false; + read_through_eol(file); + } + else + { + /* Read the IP address field */ + next_token(file, buf, sizeof(buf)); + if (buf[0] == '\0') + *matches_p = false; + else + { + int valid; /* Field is valid dotted + * decimal */ + + /* + * Remember the IP address field and go get mask + * field + */ + struct in_addr file_ip_addr; /* IP address field + * value */ + + valid = inet_aton(buf, &file_ip_addr); + if (!valid) + { + *matches_p = false; + read_through_eol(file); + } + else + { + /* Read the mask field */ + next_token(file, buf, sizeof(buf)); + if (buf[0] == '\0') + *matches_p = false; + else + { + struct in_addr mask; + + /* + * Got mask. Now see if this record is + * for our host. + */ + valid = inet_aton(buf, &mask); + if (!valid) + { + *matches_p = false; + read_through_eol(file); + } + else + { + if (((file_ip_addr.s_addr ^ ip_addr.s_addr) & mask.s_addr) + != 0x0000) + { + *matches_p = false; + read_through_eol(file); + } + else + { + + /* + * This is the record we're + * looking for. Read the rest of + * the info from it. + */ + read_hba_entry2(file, userauth_p, usermap_name, + error_p, matches_p, find_password_entries); + if (*error_p) + { + sprintf(PQerrormsg, + "process_hba_record: invalid syntax in " + "hba config file " + "for host record for IP address %s\n", + inet_ntoa(file_ip_addr)); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + } + } + } + } + } + } + } + } + } + } } static void -process_open_config_file(FILE *file, - const struct in_addr ip_addr, const char database[], - bool *host_ok_p, enum Userauth *userauth_p, - char usermap_name[], bool find_password_entries) { +process_open_config_file(FILE * file, + const struct in_addr ip_addr, const char database[], + bool * host_ok_p, enum Userauth * userauth_p, + char usermap_name[], bool find_password_entries) +{ /*--------------------------------------------------------------------------- This function does the same thing as find_hba_entry, only with the config file already open on stream descriptor "file". ----------------------------------------------------------------------------*/ - bool found_entry; - /* We've processed a record that applies to our connection */ - bool error; - /* Said record has invalid syntax. */ - bool eof; /* We've reached the end of the file we're reading */ - - found_entry = false; /* initial value */ - error = false; /* initial value */ - eof = false; /* initial value */ - while (!eof && !found_entry && !error) { - /* Process a line from the config file */ - - int c; /* a character read from the file */ - - c = getc(file); ungetc(c, file); - if (c == EOF) eof = true; - else { - if (c == '#') read_through_eol(file); - else { - process_hba_record(file, ip_addr, database, - &found_entry, &error, userauth_p, usermap_name, - find_password_entries); - } - } - } - if (found_entry) { - if (error) *host_ok_p = false; - else *host_ok_p = true; - } else *host_ok_p = false; -} + bool found_entry; + + /* We've processed a record that applies to our connection */ + bool error; + + /* Said record has invalid syntax. */ + bool eof; /* We've reached the end of the file we're + * reading */ + + found_entry = false; /* initial value */ + error = false; /* initial value */ + eof = false; /* initial value */ + while (!eof && !found_entry && !error) + { + /* Process a line from the config file */ + + int c; /* a character read from the file */ + + c = getc(file); + ungetc(c, file); + if (c == EOF) + eof = true; + else + { + if (c == '#') + read_through_eol(file); + else + { + process_hba_record(file, ip_addr, database, + &found_entry, &error, userauth_p, usermap_name, + find_password_entries); + } + } + } + if (found_entry) + { + if (error) + *host_ok_p = false; + else + *host_ok_p = true; + } + else + *host_ok_p = false; +} void -find_hba_entry(const char DataDir[], const struct in_addr ip_addr, - const char database[], - bool *host_ok_p, enum Userauth *userauth_p, - char usermap_name[], bool find_password_entries) { +find_hba_entry(const char DataDir[], const struct in_addr ip_addr, + const char database[], + bool * host_ok_p, enum Userauth * userauth_p, + char usermap_name[], bool find_password_entries) +{ /*-------------------------------------------------------------------------- Read the config file and find an entry that allows connection from - host "ip_addr" to database "database". If not found, return - *host_ok_p == false. If found, return *userauth_p and *usermap_name + host "ip_addr" to database "database". If not found, return + *host_ok_p == false. If found, return *userauth_p and *usermap_name representing the contents of that entry. When a record has invalid syntax, we either ignore it or reject the @@ -298,133 +391,167 @@ find_hba_entry(const char DataDir[], const struct in_addr ip_addr, follow directions and just installed his old hba file in the new database system. ----------------------------------------------------------------------------*/ - int fd; - - FILE *file; /* The config file we have to read */ - - char *old_conf_file; - /* The name of old config file that better not exist. */ - - /* Fail if config file by old name exists. */ - - - /* put together the full pathname to the old config file */ - old_conf_file = (char *) malloc((strlen(DataDir) + - strlen(OLD_CONF_FILE)+2)*sizeof(char)); - sprintf(old_conf_file, "%s/%s", DataDir, OLD_CONF_FILE); - - if ((fd = open(old_conf_file,O_RDONLY,0)) != -1) { - /* Old config file exists. Tell this guy he needs to upgrade. */ - close(fd); - sprintf(PQerrormsg, - "A file exists by the name used for host-based authentication " - "in prior releases of Postgres (%s). The name and format of " - "the configuration file have changed, so this file should be " - "converted.\n", - old_conf_file); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); - } else { - char *conf_file; /* The name of the config file we have to read */ - - /* put together the full pathname to the config file */ - conf_file = (char *) malloc((strlen(DataDir) + - strlen(CONF_FILE)+2)*sizeof(char)); - sprintf(conf_file, "%s/%s", DataDir, CONF_FILE); - - file = AllocateFile(conf_file, "r"); - if (file == NULL) { - /* The open of the config file failed. */ - - *host_ok_p = false; - - sprintf(PQerrormsg, - "find_hba_entry: Host-based authentication config file " - "does not exist or permissions are not setup correctly! " - "Unable to open file \"%s\".\n", - conf_file); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); - } else { - process_open_config_file(file, ip_addr, database, host_ok_p, userauth_p, - usermap_name, find_password_entries); - FreeFile(file); - } - free(conf_file); - } - free(old_conf_file); - return; +---------------------------------------------------------------------------*/ + int fd; + + FILE *file; /* The config file we have to read */ + + char *old_conf_file; + + /* The name of old config file that better not exist. */ + + /* Fail if config file by old name exists. */ + + + /* put together the full pathname to the old config file */ + old_conf_file = (char *) malloc((strlen(DataDir) + + strlen(OLD_CONF_FILE) + 2) * sizeof(char)); + sprintf(old_conf_file, "%s/%s", DataDir, OLD_CONF_FILE); + + if ((fd = open(old_conf_file, O_RDONLY, 0)) != -1) + { + /* Old config file exists. Tell this guy he needs to upgrade. */ + close(fd); + sprintf(PQerrormsg, + "A file exists by the name used for host-based authentication " + "in prior releases of Postgres (%s). The name and format of " + "the configuration file have changed, so this file should be " + "converted.\n", + old_conf_file); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + } + else + { + char *conf_file; /* The name of the config file we + * have to read */ + + /* put together the full pathname to the config file */ + conf_file = (char *) malloc((strlen(DataDir) + + strlen(CONF_FILE) + 2) * sizeof(char)); + sprintf(conf_file, "%s/%s", DataDir, CONF_FILE); + + file = AllocateFile(conf_file, "r"); + if (file == NULL) + { + /* The open of the config file failed. */ + + *host_ok_p = false; + + sprintf(PQerrormsg, + "find_hba_entry: Host-based authentication config file " + "does not exist or permissions are not setup correctly! " + "Unable to open file \"%s\".\n", + conf_file); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + } + else + { + process_open_config_file(file, ip_addr, database, host_ok_p, userauth_p, + usermap_name, find_password_entries); + FreeFile(file); + } + free(conf_file); + } + free(old_conf_file); + return; } static void -interpret_ident_response(char ident_response[], - bool *error_p, char ident_username[]) { +interpret_ident_response(char ident_response[], + bool * error_p, char ident_username[]) +{ /*---------------------------------------------------------------------------- Parse the string "ident_response[]" as a response from a query to an Ident - server. If it's a normal response indicating a username, return + server. If it's a normal response indicating a username, return *error_p == false and the username as ident_username[]. If it's anything else, return *error_p == true and ident_username[] undefined. ----------------------------------------------------------------------------*/ - char *cursor; /* Cursor into ident_response[] */ - - cursor = &ident_response[0]; - - /* Ident's response, in the telnet tradition, should end in crlf (\r\n). */ - if (strlen(ident_response) < 2) *error_p = true; - else if (ident_response[strlen(ident_response)-2] != '\r') *error_p = true; - else { - while (*cursor != ':' && *cursor != '\r') cursor++; /* skip port field */ - - if (*cursor != ':') *error_p = true; - else { - /* We're positioned to colon before response type field */ - char response_type[80]; - int i; /* Index into response_type[] */ - cursor++; /* Go over colon */ - while (isblank(*cursor)) cursor++; /* skip blanks */ - i = 0; - while (*cursor != ':' && *cursor != '\r' && !isblank(*cursor) - && i < sizeof(response_type)-1) - response_type[i++] = *cursor++; - response_type[i] = '\0'; - while (isblank(*cursor)) cursor++; /* skip blanks */ - if (strcmp(response_type, "USERID") != 0) - *error_p = true; - else { - /* It's a USERID response. Good. "cursor" should be pointing to - the colon that precedes the operating system type. - */ - if (*cursor != ':') *error_p = true; - else { - cursor++; /* Go over colon */ - /* Skip over operating system field. */ - while (*cursor != ':' && *cursor != '\r') cursor++; - if (*cursor != ':') *error_p = true; - else { - int i; /* Index into ident_username[] */ - cursor ++; /* Go over colon */ - while (isblank(*cursor)) cursor++; /* skip blanks */ - /* Rest of line is username. Copy it over. */ - i = 0; - while (*cursor != '\r' && i < IDENT_USERNAME_MAX) - ident_username[i++] = *cursor++; - ident_username[i] = '\0'; - *error_p = false; - } - } - } - } - } + char *cursor; /* Cursor into ident_response[] */ + + cursor = &ident_response[0]; + + /* + * Ident's response, in the telnet tradition, should end in crlf + * (\r\n). + */ + if (strlen(ident_response) < 2) + *error_p = true; + else if (ident_response[strlen(ident_response) - 2] != '\r') + *error_p = true; + else + { + while (*cursor != ':' && *cursor != '\r') + cursor++; /* skip port field */ + + if (*cursor != ':') + *error_p = true; + else + { + /* We're positioned to colon before response type field */ + char response_type[80]; + int i; /* Index into response_type[] */ + + cursor++; /* Go over colon */ + while (isblank(*cursor)) + cursor++; /* skip blanks */ + i = 0; + while (*cursor != ':' && *cursor != '\r' && !isblank(*cursor) + && i < sizeof(response_type) - 1) + response_type[i++] = *cursor++; + response_type[i] = '\0'; + while (isblank(*cursor)) + cursor++; /* skip blanks */ + if (strcmp(response_type, "USERID") != 0) + *error_p = true; + else + { + + /* + * It's a USERID response. Good. "cursor" should be + * pointing to the colon that precedes the operating + * system type. + */ + if (*cursor != ':') + *error_p = true; + else + { + cursor++; /* Go over colon */ + /* Skip over operating system field. */ + while (*cursor != ':' && *cursor != '\r') + cursor++; + if (*cursor != ':') + *error_p = true; + else + { + int i; /* Index into + * ident_username[] */ + + cursor++; /* Go over colon */ + while (isblank(*cursor)) + cursor++; /* skip blanks */ + /* Rest of line is username. Copy it over. */ + i = 0; + while (*cursor != '\r' && i < IDENT_USERNAME_MAX) + ident_username[i++] = *cursor++; + ident_username[i] = '\0'; + *error_p = false; + } + } + } + } + } } static void ident(const struct in_addr remote_ip_addr, const struct in_addr local_ip_addr, - const ushort remote_port, const ushort local_port, - bool *ident_failed, char ident_username[]) { + const ushort remote_port, const ushort local_port, + bool * ident_failed, char ident_username[]) +{ /*-------------------------------------------------------------------------- Talk to the ident server on host "remote_ip_addr" and find out who owns the tcp connection from his port "remote_port" to port @@ -437,169 +564,204 @@ ident(const struct in_addr remote_ip_addr, const struct in_addr local_ip_addr, *ident_failed == true (and ident_username[] undefined). ----------------------------------------------------------------------------*/ - int sock_fd; - /* File descriptor for socket on which we talk to Ident */ - - int rc; /* Return code from a locally called function */ - - sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); - if (sock_fd == -1) { - sprintf(PQerrormsg, - "Failed to create socket on which to talk to Ident server. " - "socket() returned errno = %s (%d)\n", - strerror(errno), errno); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); - } else { - struct sockaddr_in ident_server; - /* Socket address of Ident server on the system from which client - is attempting to connect to us. - */ - ident_server.sin_family = AF_INET; - ident_server.sin_port = htons(IDENT_PORT); - ident_server.sin_addr = remote_ip_addr; - rc = connect(sock_fd, - (struct sockaddr *) &ident_server, sizeof(ident_server)); - if (rc != 0) { - sprintf(PQerrormsg, - "Unable to connect to Ident server on the host which is " - "trying to connect to Postgres " - "(IP address %s, Port %d). " - "errno = %s (%d)\n", - inet_ntoa(remote_ip_addr), IDENT_PORT, strerror(errno), errno); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); - *ident_failed = true; - } else { - char ident_query[80]; - /* The query we send to the Ident server */ - sprintf(ident_query, "%d,%d\n", - ntohs(remote_port), ntohs(local_port)); - rc = send(sock_fd, ident_query, strlen(ident_query), 0); - if (rc < 0) { - sprintf(PQerrormsg, - "Unable to send query to Ident server on the host which is " - "trying to connect to Postgres (Host %s, Port %d)," - "even though we successfully connected to it. " - "errno = %s (%d)\n", - inet_ntoa(remote_ip_addr), IDENT_PORT, strerror(errno), errno); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); - *ident_failed = true; - } else { - char ident_response[80+IDENT_USERNAME_MAX]; - rc = recv(sock_fd, ident_response, sizeof(ident_response)-1, 0); - if (rc < 0) { - sprintf(PQerrormsg, - "Unable to receive response from Ident server " - "on the host which is " - "trying to connect to Postgres (Host %s, Port %d)," - "even though we successfully sent our query to it. " - "errno = %s (%d)\n", - inet_ntoa(remote_ip_addr), IDENT_PORT, - strerror(errno), errno); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); - *ident_failed = true; - } else { - bool error; /* response from Ident is garbage. */ - ident_response[rc] = '\0'; - interpret_ident_response(ident_response, &error, ident_username); - *ident_failed = error; - } - } - close(sock_fd); - } - } + int sock_fd; + + /* File descriptor for socket on which we talk to Ident */ + + int rc; /* Return code from a locally called + * function */ + + sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); + if (sock_fd == -1) + { + sprintf(PQerrormsg, + "Failed to create socket on which to talk to Ident server. " + "socket() returned errno = %s (%d)\n", + strerror(errno), errno); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + } + else + { + struct sockaddr_in ident_server; + + /* + * Socket address of Ident server on the system from which client + * is attempting to connect to us. + */ + ident_server.sin_family = AF_INET; + ident_server.sin_port = htons(IDENT_PORT); + ident_server.sin_addr = remote_ip_addr; + rc = connect(sock_fd, + (struct sockaddr *) & ident_server, sizeof(ident_server)); + if (rc != 0) + { + sprintf(PQerrormsg, + "Unable to connect to Ident server on the host which is " + "trying to connect to Postgres " + "(IP address %s, Port %d). " + "errno = %s (%d)\n", + inet_ntoa(remote_ip_addr), IDENT_PORT, strerror(errno), errno); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + *ident_failed = true; + } + else + { + char ident_query[80]; + + /* The query we send to the Ident server */ + sprintf(ident_query, "%d,%d\n", + ntohs(remote_port), ntohs(local_port)); + rc = send(sock_fd, ident_query, strlen(ident_query), 0); + if (rc < 0) + { + sprintf(PQerrormsg, + "Unable to send query to Ident server on the host which is " + "trying to connect to Postgres (Host %s, Port %d)," + "even though we successfully connected to it. " + "errno = %s (%d)\n", + inet_ntoa(remote_ip_addr), IDENT_PORT, strerror(errno), errno); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + *ident_failed = true; + } + else + { + char ident_response[80 + IDENT_USERNAME_MAX]; + + rc = recv(sock_fd, ident_response, sizeof(ident_response) - 1, 0); + if (rc < 0) + { + sprintf(PQerrormsg, + "Unable to receive response from Ident server " + "on the host which is " + "trying to connect to Postgres (Host %s, Port %d)," + "even though we successfully sent our query to it. " + "errno = %s (%d)\n", + inet_ntoa(remote_ip_addr), IDENT_PORT, + strerror(errno), errno); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + *ident_failed = true; + } + else + { + bool error; /* response from Ident is + * garbage. */ + + ident_response[rc] = '\0'; + interpret_ident_response(ident_response, &error, ident_username); + *ident_failed = error; + } + } + close(sock_fd); + } + } } static void -parse_map_record(FILE *file, - char file_map[], char file_pguser[], char file_iuser[]) { +parse_map_record(FILE * file, + char file_map[], char file_pguser[], char file_iuser[]) +{ /*--------------------------------------------------------------------------- Take the noncomment line which is next on file "file" and interpret it as a line in a usermap file. Specifically, return the first - 3 tokens as file_map, file_iuser, and file_pguser, respectively. If + 3 tokens as file_map, file_iuser, and file_pguser, respectively. If there are fewer than 3 tokens, return null strings for the missing ones. ---------------------------------------------------------------------------*/ - char buf[MAX_TOKEN]; - /* A token read from the file */ - - /* Set defaults in case fields not in file */ - file_map[0] = '\0'; - file_pguser[0] = '\0'; - file_iuser[0] = '\0'; - - next_token(file, buf, sizeof(buf)); - if (buf != '\0') { - strcpy(file_map, buf); - next_token(file, buf, sizeof(buf)); - if (buf != '\0') { - strcpy(file_iuser, buf); - next_token(file, buf, sizeof(buf)); - if (buf != '\0') { - strcpy(file_pguser, buf); - read_through_eol(file); - } - } - } + char buf[MAX_TOKEN]; + + /* A token read from the file */ + + /* Set defaults in case fields not in file */ + file_map[0] = '\0'; + file_pguser[0] = '\0'; + file_iuser[0] = '\0'; + + next_token(file, buf, sizeof(buf)); + if (buf != '\0') + { + strcpy(file_map, buf); + next_token(file, buf, sizeof(buf)); + if (buf != '\0') + { + strcpy(file_iuser, buf); + next_token(file, buf, sizeof(buf)); + if (buf != '\0') + { + strcpy(file_pguser, buf); + read_through_eol(file); + } + } + } } static void -verify_against_open_usermap(FILE *file, - const char pguser[], - const char ident_username[], - const char usermap_name[], - bool *checks_out_p) { +verify_against_open_usermap(FILE * file, + const char pguser[], + const char ident_username[], + const char usermap_name[], + bool * checks_out_p) +{ /*-------------------------------------------------------------------------- This function does the same thing as verify_against_usermap, only with the config file already open on stream descriptor "file". ---------------------------------------------------------------------------*/ - bool match; /* We found a matching entry in the map file */ - bool eof; /* We've reached the end of the file we're reading */ - - match = false; /* initial value */ - eof = false; /* initial value */ - while (!eof && !match) { - /* Process a line from the map file */ - - int c; /* a character read from the file */ - - c = getc(file); ungetc(c, file); - if (c == EOF) eof = true; - else { - if (c == '#') read_through_eol(file); - else { - /* The following are fields read from a record of the file */ - char file_map[MAX_TOKEN+1]; - char file_pguser[MAX_TOKEN+1]; - char file_iuser[MAX_TOKEN+1]; - - parse_map_record(file, file_map, file_pguser, file_iuser); - if (strcmp(file_map, usermap_name) == 0 && - strcmp(file_pguser, pguser) == 0 && - strcmp(file_iuser, ident_username) == 0) - match = true; - } - } - } - *checks_out_p = match; + bool match; /* We found a matching entry in the map + * file */ + bool eof; /* We've reached the end of the file we're + * reading */ + + match = false; /* initial value */ + eof = false; /* initial value */ + while (!eof && !match) + { + /* Process a line from the map file */ + + int c; /* a character read from the file */ + + c = getc(file); + ungetc(c, file); + if (c == EOF) + eof = true; + else + { + if (c == '#') + read_through_eol(file); + else + { + /* The following are fields read from a record of the file */ + char file_map[MAX_TOKEN + 1]; + char file_pguser[MAX_TOKEN + 1]; + char file_iuser[MAX_TOKEN + 1]; + + parse_map_record(file, file_map, file_pguser, file_iuser); + if (strcmp(file_map, usermap_name) == 0 && + strcmp(file_pguser, pguser) == 0 && + strcmp(file_iuser, ident_username) == 0) + match = true; + } + } + } + *checks_out_p = match; } static void verify_against_usermap(const char DataDir[], - const char pguser[], - const char ident_username[], - const char usermap_name[], - bool *checks_out_p) { + const char pguser[], + const char ident_username[], + const char usermap_name[], + bool * checks_out_p) +{ /*-------------------------------------------------------------------------- See if the user with ident username "ident_username" is allowed to act as Postgres user "pguser" according to usermap "usermap_name". Look @@ -610,151 +772,194 @@ verify_against_usermap(const char DataDir[], "ident_username" in order to be authorized. Iff authorized, return *checks_out_p == true. - + --------------------------------------------------------------------------*/ - if (usermap_name[0] == '\0') { - *checks_out_p = false; - sprintf(PQerrormsg, - "verify_against_usermap: hba configuration file does not " - "have the usermap field filled in in the entry that pertains " - "to this connection. That field is essential for Ident-based " - "authentication.\n"); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); - } else if (strcmp(usermap_name, "sameuser") == 0) { - if (strcmp(ident_username, pguser) == 0) *checks_out_p = true; - else *checks_out_p = false; - } else { - FILE *file; /* The map file we have to read */ - - char *map_file; /* The name of the map file we have to read */ - - /* put together the full pathname to the map file */ - map_file = (char *) malloc((strlen(DataDir) + - strlen(MAP_FILE)+2)*sizeof(char)); - sprintf(map_file, "%s/%s", DataDir, MAP_FILE); - - file = AllocateFile(map_file, "r"); - if (file == NULL) { - /* The open of the map file failed. */ - - *checks_out_p = false; - - sprintf(PQerrormsg, - "verify_against_usermap: usermap file for Ident-based " - "authentication " - "does not exist or permissions are not setup correctly! " - "Unable to open file \"%s\".\n", - map_file); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); - } else { - verify_against_open_usermap(file, - pguser, ident_username, usermap_name, - checks_out_p); - FreeFile(file); - } - free(map_file); - - - } + if (usermap_name[0] == '\0') + { + *checks_out_p = false; + sprintf(PQerrormsg, + "verify_against_usermap: hba configuration file does not " + "have the usermap field filled in in the entry that pertains " + "to this connection. That field is essential for Ident-based " + "authentication.\n"); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + } + else if (strcmp(usermap_name, "sameuser") == 0) + { + if (strcmp(ident_username, pguser) == 0) + *checks_out_p = true; + else + *checks_out_p = false; + } + else + { + FILE *file; /* The map file we have to read */ + + char *map_file; /* The name of the map file we + * have to read */ + + /* put together the full pathname to the map file */ + map_file = (char *) malloc((strlen(DataDir) + + strlen(MAP_FILE) + 2) * sizeof(char)); + sprintf(map_file, "%s/%s", DataDir, MAP_FILE); + + file = AllocateFile(map_file, "r"); + if (file == NULL) + { + /* The open of the map file failed. */ + + *checks_out_p = false; + + sprintf(PQerrormsg, + "verify_against_usermap: usermap file for Ident-based " + "authentication " + "does not exist or permissions are not setup correctly! " + "Unable to open file \"%s\".\n", + map_file); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + } + else + { + verify_against_open_usermap(file, + pguser, ident_username, usermap_name, + checks_out_p); + FreeFile(file); + } + free(map_file); + + + } } static void -authident(const char DataDir[], - const Port port, const char postgres_username[], - const char usermap_name[], - bool *authentic_p) { +authident(const char DataDir[], + const Port port, const char postgres_username[], + const char usermap_name[], + bool * authentic_p) +{ /*--------------------------------------------------------------------------- - Talk to the ident server on the remote host and find out who owns the + Talk to the ident server on the remote host and find out who owns the connection described by "port". Then look in the usermap file under - the usermap usermap_name[] and see if that user is equivalent to + the usermap usermap_name[] and see if that user is equivalent to Postgres user user[]. Return *authentic_p true iff yes. ---------------------------------------------------------------------------*/ - bool ident_failed; - /* We were unable to get ident to give us a username */ - char ident_username[IDENT_USERNAME_MAX+1]; - /* The username returned by ident */ - - ident(port.raddr.sin_addr, port.laddr.sin_addr, - port.raddr.sin_port, port.laddr.sin_port, - &ident_failed, ident_username); - - if (ident_failed) *authentic_p = false; - else { - bool checks_out; - verify_against_usermap(DataDir, - postgres_username, ident_username, usermap_name, - &checks_out); - if (checks_out) *authentic_p = true; - else *authentic_p = false; - } + bool ident_failed; + + /* We were unable to get ident to give us a username */ + char ident_username[IDENT_USERNAME_MAX + 1]; + + /* The username returned by ident */ + + ident(port.raddr.sin_addr, port.laddr.sin_addr, + port.raddr.sin_port, port.laddr.sin_port, + &ident_failed, ident_username); + + if (ident_failed) + *authentic_p = false; + else + { + bool checks_out; + + verify_against_usermap(DataDir, + postgres_username, ident_username, usermap_name, + &checks_out); + if (checks_out) + *authentic_p = true; + else + *authentic_p = false; + } } extern int -hba_recvauth(const Port *port, const char database[], const char user[], - const char DataDir[]) { +hba_recvauth(const Port * port, const char database[], const char user[], + const char DataDir[]) +{ /*--------------------------------------------------------------------------- Determine if the TCP connection described by "port" is with someone allowed to act as user "user" and access database "database". Return STATUS_OK if yes; STATUS_ERROR if not. -----------------------------------------------------------------------------*/ - bool host_ok; - /* There's an entry for this database and remote host in the pg_hba file */ - char usermap_name[USERMAP_NAME_SIZE+1]; - /* The name of the map pg_hba specifies for this connection (or special - value "SAMEUSER") - */ - enum Userauth userauth; - /* The type of user authentication pg_hba specifies for this connection */ - int retvalue; - /* Our eventual return value */ - - - find_hba_entry(DataDir, port->raddr.sin_addr, database, - &host_ok, &userauth, usermap_name, - false /* don't find password entries of type 'password' */); - - if (!host_ok) retvalue = STATUS_ERROR; - else { - switch (userauth) { - case Trust: - retvalue = STATUS_OK; - break; - case Ident: { - /* Here's where we need to call up ident and authenticate the user */ - - bool authentic; /* He is who he says he is. */ - - authident(DataDir, *port, user, usermap_name, &authentic); - - if (authentic) retvalue = STATUS_OK; - else retvalue = STATUS_ERROR; - } - break; - default: - retvalue = STATUS_ERROR; - Assert(false); - } - } - return(retvalue); +----------------------------------------------------------------------------*/ + bool host_ok; + + /* + * There's an entry for this database and remote host in the pg_hba + * file + */ + char usermap_name[USERMAP_NAME_SIZE + 1]; + + /* + * The name of the map pg_hba specifies for this connection (or + * special value "SAMEUSER") + */ + enum Userauth userauth; + + /* + * The type of user authentication pg_hba specifies for this + * connection + */ + int retvalue; + + /* Our eventual return value */ + + + find_hba_entry(DataDir, port->raddr.sin_addr, database, + &host_ok, &userauth, usermap_name, + false /* don't find password entries of type + 'password' */ ); + + if (!host_ok) + retvalue = STATUS_ERROR; + else + { + switch (userauth) + { + case Trust: + retvalue = STATUS_OK; + break; + case Ident: + { + + /* + * Here's where we need to call up ident and authenticate + * the user + */ + + bool authentic; /* He is who he says he + * is. */ + + authident(DataDir, *port, user, usermap_name, &authentic); + + if (authentic) + retvalue = STATUS_OK; + else + retvalue = STATUS_ERROR; + } + break; + default: + retvalue = STATUS_ERROR; + Assert(false); + } + } + return (retvalue); } /*---------------------------------------------------------------- * This version of hba was written by Bryan Henderson - * in September 1996 for Release 6.0. It changed the format of the + * in September 1996 for Release 6.0. It changed the format of the * hba file and added ident function. * * Here are some notes about the original host based authentication - * the preceded this one. + * the preceded this one. * * based on the securelib package originally written by William * LeFebvre, EECS Department, Northwestern University @@ -765,4 +970,3 @@ hba_recvauth(const Port *port, const char database[], const char user[], * (pnfisher@unity.ncsu.edu) * -----------------------------------------------------------------*/ - diff --git a/src/backend/libpq/password.c b/src/backend/libpq/password.c index 346d59e8bf6..1efc2e668a3 100644 --- a/src/backend/libpq/password.c +++ b/src/backend/libpq/password.c @@ -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]; - - char *pw_file_fullname; - FILE *pw_file; - - 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); + bool host_ok; + enum Userauth userauth; + char pw_file_name[PWFILE_NAME_SIZE + 1]; + + char *pw_file_fullname; + FILE *pw_file; + + 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); + + 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(!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(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; + } - 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; + } - 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); + 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; + } + } - pw_file = AllocateFile(pw_file_fullname, "r"); - if(!pw_file) { sprintf(PQerrormsg, - "verify_password: couldn't open password file '%s'\n", - pw_file_fullname); + "verify_password: user '%s' not found in password file.\n", + user); fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + 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; } diff --git a/src/backend/libpq/portal.c b/src/backend/libpq/portal.c index 301773be9f5..c3c8fe55e38 100644 --- a/src/backend/libpq/portal.c +++ b/src/backend/libpq/portal.c @@ -1,642 +1,655 @@ /*------------------------------------------------------------------------- * * portal.c-- - * generalized portal support routines + * generalized portal support routines * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/libpq/Attic/portal.c,v 1.6 1997/08/12 22:52:55 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/libpq/Attic/portal.c,v 1.7 1997/09/07 04:42:23 momjian Exp $ * *------------------------------------------------------------------------- */ /* - * INTERFACE ROUTINES - * PQnportals - Return the number of open portals. - * PQpnames - Return all the portal names - * PQparray - Return the portal buffer given a portal name - * PQrulep - Return 1 if an asynchronous portal - * PQntuples - Return the number of tuples in a portal buffer - * PQninstances - same as PQntuples using object terminology - * PQngroups - Return the number of tuple groups in a portal buffer - * PQntuplesGroup - Return the number of tuples in a tuple group - * PQninstancesGroup - same as PQntuplesGroup using object terminology - * PQnfieldsGroup - Return the number of fields in a tuple group - * PQfnumberGroup - Return field number given (group index, field name) - * PQftypeGroup - Return field type given (group index, field index) - * PQfsizeGroup - Return field size given (group index, field index) - * PQfnameGroup - Return field name given (group index, field index) - * PQgroup - Return the tuple group that a particular tuple is in - * PQgetgroup - Return the index of the group that a tuple is in - * PQnfields - Return the number of fields in a tuple - * PQfnumber - Return the field index of a field name in a tuple - * PQfname - Return the name of a field - * PQftype - Return the type of a field - * PQfsize - Return the size of a field - * PQftype - Return the type of a field - * PQsametype - Return 1 if the two tuples have the same type - * PQgetvalue - Return an attribute (field) value - * PQgetlength - Return an attribute (field) length - * PQclear - free storage claimed by named portal - * PQnotifies - Return a list of relations on which notification - * has occurred. - * PQremoveNotify - Remove this notification from the list. + * INTERFACE ROUTINES + * PQnportals - Return the number of open portals. + * PQpnames - Return all the portal names + * PQparray - Return the portal buffer given a portal name + * PQrulep - Return 1 if an asynchronous portal + * PQntuples - Return the number of tuples in a portal buffer + * PQninstances - same as PQntuples using object terminology + * PQngroups - Return the number of tuple groups in a portal buffer + * PQntuplesGroup - Return the number of tuples in a tuple group + * PQninstancesGroup - same as PQntuplesGroup using object terminology + * PQnfieldsGroup - Return the number of fields in a tuple group + * PQfnumberGroup - Return field number given (group index, field name) + * PQftypeGroup - Return field type given (group index, field index) + * PQfsizeGroup - Return field size given (group index, field index) + * PQfnameGroup - Return field name given (group index, field index) + * PQgroup - Return the tuple group that a particular tuple is in + * PQgetgroup - Return the index of the group that a tuple is in + * PQnfields - Return the number of fields in a tuple + * PQfnumber - Return the field index of a field name in a tuple + * PQfname - Return the name of a field + * PQftype - Return the type of a field + * PQfsize - Return the size of a field + * PQftype - Return the type of a field + * PQsametype - Return 1 if the two tuples have the same type + * PQgetvalue - Return an attribute (field) value + * PQgetlength - Return an attribute (field) length + * PQclear - free storage claimed by named portal + * PQnotifies - Return a list of relations on which notification + * has occurred. + * PQremoveNotify - Remove this notification from the list. * - * 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. + * 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. * - * 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 <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> /* ---------------------------------------------------------------- - * Helper routines for PQ portal interface routines below + * Helper routines for PQ portal interface routines below * ---------------------------------------------------------------- */ static int in_range(char *msg, int value, int min, int max) { - if (value < min || value >= max) { - sprintf(PQerrormsg, "FATAL: %s, %d is not in range [%d,%d)\n", - msg, value, min, max); - pqdebug("%s", PQerrormsg); - fputs(PQerrormsg, stderr); - return(0); - } - return(1); + if (value < min || value >= max) + { + sprintf(PQerrormsg, "FATAL: %s, %d is not in range [%d,%d)\n", + msg, value, min, max); + pqdebug("%s", PQerrormsg); + fputs(PQerrormsg, stderr); + return (0); + } + return (1); } static int valid_pointer(char *msg, void *ptr) { - if (!ptr) { - sprintf(PQerrormsg, "FATAL: %s\n", msg); - pqdebug("%s", PQerrormsg); - fputs(PQerrormsg, stderr); - return(0); - } - return(1); + if (!ptr) + { + sprintf(PQerrormsg, "FATAL: %s\n", msg); + pqdebug("%s", PQerrormsg); + fputs(PQerrormsg, stderr); + return (0); + } + return (1); } /* ---------------------------------------------------------------- - * PQ portal interface routines + * PQ portal interface routines * ---------------------------------------------------------------- */ /* -------------------------------- - * PQnportals - Return the number of open portals. - * If rule_p, only return asynchronous portals. + * PQnportals - Return the number of open portals. + * If rule_p, only return asynchronous portals. * -------------------------------- */ int PQnportals(int rule_p) { - int i, n = 0; - - for (i = 0; i < portals_array_size; ++i) { - if (portals[i] && portals[i]->portal) { - if (!rule_p || portals[i]->portal->rule_p) { - ++n; - } + int i, + n = 0; + + for (i = 0; i < portals_array_size; ++i) + { + if (portals[i] && portals[i]->portal) + { + if (!rule_p || portals[i]->portal->rule_p) + { + ++n; + } + } } - } - return(n); + return (n); } /* -------------------------------- - * PQpnames - Return all the portal names - * If rule_p, only return asynchronous portals. + * PQpnames - Return all the portal names + * If rule_p, only return asynchronous portals. * - * the caller must have allocated sufficient memory for char** pnames - * (an array of PQnportals strings of length PortalNameLength). + * the caller must have allocated sufficient memory for char** pnames + * (an array of PQnportals strings of length PortalNameLength). * - * notice that this assumes that the user is calling PQnportals and - * PQpnames with the same rule_p argument, and with no intervening - * portal closures. if not, you can get in heap big trouble.. + * notice that this assumes that the user is calling PQnportals and + * PQpnames with the same rule_p argument, and with no intervening + * portal closures. if not, you can get in heap big trouble.. * -------------------------------- */ void PQpnames(char **pnames, int rule_p) { - int i, cur_pname = 0; - - if (!valid_pointer("PQpnames: invalid name buffer", pnames)) - return; - - for (i = 0; i < portals_array_size; ++i) { - if (portals[i] && portals[i]->portal) { - if (!rule_p || portals[i]->portal->rule_p) { - strncpy(pnames[cur_pname], portals[i]->name, PortalNameLength); - ++cur_pname; - } + int i, + cur_pname = 0; + + if (!valid_pointer("PQpnames: invalid name buffer", pnames)) + return; + + for (i = 0; i < portals_array_size; ++i) + { + if (portals[i] && portals[i]->portal) + { + if (!rule_p || portals[i]->portal->rule_p) + { + strncpy(pnames[cur_pname], portals[i]->name, PortalNameLength); + ++cur_pname; + } + } } - } } /* -------------------------------- - * PQparray - Return the portal buffer given a portal name + * PQparray - Return the portal buffer given a portal name * -------------------------------- */ -PortalBuffer * +PortalBuffer * PQparray(char *pname) { - int i; - - if (!valid_pointer("PQparray: invalid name buffer", pname)) - return NULL; - - if ((i = pbuf_getIndex(pname)) < 0) - return((PortalBuffer *) NULL); - return(portals[i]->portal); + int i; + + if (!valid_pointer("PQparray: invalid name buffer", pname)) + return NULL; + + if ((i = pbuf_getIndex(pname)) < 0) + return ((PortalBuffer *) NULL); + return (portals[i]->portal); } /* -------------------------------- - * PQrulep - Return 1 if an asynchronous portal + * PQrulep - Return 1 if an asynchronous portal * -------------------------------- */ int -PQrulep(PortalBuffer *portal) +PQrulep(PortalBuffer * portal) { - if (!valid_pointer("PQrulep: invalid portal pointer", portal)) - return(-1); - - return(portal->rule_p); + if (!valid_pointer("PQrulep: invalid portal pointer", portal)) + return (-1); + + return (portal->rule_p); } /* -------------------------------- - * PQntuples - Return the number of tuples in a portal buffer + * PQntuples - Return the number of tuples in a portal buffer * -------------------------------- */ int -PQntuples(PortalBuffer *portal) +PQntuples(PortalBuffer * portal) { - if (!valid_pointer("PQntuples: invalid portal pointer", portal)) - return(-1); - - return(portal->no_tuples); + if (!valid_pointer("PQntuples: invalid portal pointer", portal)) + return (-1); + + return (portal->no_tuples); } int -PQninstances(PortalBuffer *portal) +PQninstances(PortalBuffer * portal) { - return(PQntuples(portal)); + return (PQntuples(portal)); } /* -------------------------------- - * PQngroups - Return the number of tuple groups in a portal buffer + * PQngroups - Return the number of tuple groups in a portal buffer * -------------------------------- */ int -PQngroups(PortalBuffer *portal) +PQngroups(PortalBuffer * portal) { - if (!valid_pointer("PQngroups: invalid portal pointer", portal)) - return(-1); - - return(portal->no_groups); + if (!valid_pointer("PQngroups: invalid portal pointer", portal)) + return (-1); + + return (portal->no_groups); } /* -------------------------------- - * PQntuplesGroup - Return the number of tuples in a tuple group + * PQntuplesGroup - Return the number of tuples in a tuple group * -------------------------------- */ int -PQntuplesGroup(PortalBuffer *portal, int group_index) +PQntuplesGroup(PortalBuffer * portal, int group_index) { - GroupBuffer *gbp; - - if (!valid_pointer("PQntuplesGroup: invalid portal pointer", portal) || - !in_range("PQntuplesGroup: group index", - group_index, 0, portal->no_groups)) - return(-1); + GroupBuffer *gbp; - gbp = pbuf_findGroup(portal, group_index); - if (gbp) - return(gbp->no_tuples); - return(-1); + if (!valid_pointer("PQntuplesGroup: invalid portal pointer", portal) || + !in_range("PQntuplesGroup: group index", + group_index, 0, portal->no_groups)) + return (-1); + + gbp = pbuf_findGroup(portal, group_index); + if (gbp) + return (gbp->no_tuples); + return (-1); } int -PQninstancesGroup(PortalBuffer *portal, int group_index) +PQninstancesGroup(PortalBuffer * portal, int group_index) { - return(PQntuplesGroup(portal, group_index)); + return (PQntuplesGroup(portal, group_index)); } /* -------------------------------- - * PQnfieldsGroup - Return the number of fields in a tuple group + * PQnfieldsGroup - Return the number of fields in a tuple group * -------------------------------- */ int -PQnfieldsGroup(PortalBuffer *portal, int group_index) +PQnfieldsGroup(PortalBuffer * portal, int group_index) { - GroupBuffer *gbp; - - if (!valid_pointer("PQnfieldsGroup: invalid portal pointer", portal) || - !in_range("PQnfieldsGroup: group index", - group_index, 0, portal->no_groups)) - return(-1); - gbp = pbuf_findGroup(portal, group_index); - if (gbp) - return(gbp->no_fields); - return(-1); + GroupBuffer *gbp; + + if (!valid_pointer("PQnfieldsGroup: invalid portal pointer", portal) || + !in_range("PQnfieldsGroup: group index", + group_index, 0, portal->no_groups)) + return (-1); + gbp = pbuf_findGroup(portal, group_index); + if (gbp) + return (gbp->no_fields); + return (-1); } /* -------------------------------- - * PQfnumberGroup - Return the field number (index) given - * the group index and the field name + * PQfnumberGroup - Return the field number (index) given + * the group index and the field name * -------------------------------- */ int -PQfnumberGroup(PortalBuffer *portal, int group_index, char *field_name) -{ - GroupBuffer *gbp; - - if (!valid_pointer("PQfnumberGroup: invalid portal pointer", portal) || - !valid_pointer("PQfnumberGroup: invalid field name pointer", - field_name) || - !in_range("PQfnumberGroup: group index", - group_index, 0, portal->no_groups)) - return(-1); - gbp = pbuf_findGroup(portal, group_index); - if (gbp) - return(pbuf_findFnumber(gbp, field_name)); - return(-1); +PQfnumberGroup(PortalBuffer * portal, int group_index, char *field_name) +{ + GroupBuffer *gbp; + + if (!valid_pointer("PQfnumberGroup: invalid portal pointer", portal) || + !valid_pointer("PQfnumberGroup: invalid field name pointer", + field_name) || + !in_range("PQfnumberGroup: group index", + group_index, 0, portal->no_groups)) + return (-1); + gbp = pbuf_findGroup(portal, group_index); + if (gbp) + return (pbuf_findFnumber(gbp, field_name)); + return (-1); } /* -------------------------------- - * PQfnameGroup - Return the field (attribute) name given - * the group index and field index. + * PQfnameGroup - Return the field (attribute) name given + * the group index and field index. * -------------------------------- */ -char * -PQfnameGroup(PortalBuffer *portal, int group_index, int field_number) -{ - GroupBuffer *gbp; - - if (!valid_pointer("PQfnameGroup: invalid portal pointer", portal) || - !in_range("PQfnameGroup: group index", - group_index, 0, portal->no_groups)) - return((char *) NULL); - - if ((gbp = pbuf_findGroup(portal, group_index)) && - in_range("PQfnameGroup: field number", - field_number, 0, gbp->no_fields)) - return(pbuf_findFname(gbp, field_number)); - return((char *) NULL); +char * +PQfnameGroup(PortalBuffer * portal, int group_index, int field_number) +{ + GroupBuffer *gbp; + + if (!valid_pointer("PQfnameGroup: invalid portal pointer", portal) || + !in_range("PQfnameGroup: group index", + group_index, 0, portal->no_groups)) + return ((char *) NULL); + + if ((gbp = pbuf_findGroup(portal, group_index)) && + in_range("PQfnameGroup: field number", + field_number, 0, gbp->no_fields)) + return (pbuf_findFname(gbp, field_number)); + return ((char *) NULL); } /* -------------------------------- - * PQftypeGroup - Return the type of a field given - * the group index and field index + * PQftypeGroup - Return the type of a field given + * the group index and field index * -------------------------------- */ int -PQftypeGroup(PortalBuffer *portal, int group_index, int field_number) +PQftypeGroup(PortalBuffer * portal, int group_index, int field_number) { - GroupBuffer *gbp; - - if (!valid_pointer("PQftypeGroup: invalid portal pointer", portal) || - !in_range("PQftypeGroup: group index", - group_index, 0, portal->no_groups)) - return(-1); - - if ((gbp = pbuf_findGroup(portal, group_index)) && - in_range("PQftypeGroup: field number", field_number, 0, gbp->no_fields)) - return(gbp->types[field_number].adtid); - return(-1); + GroupBuffer *gbp; + + if (!valid_pointer("PQftypeGroup: invalid portal pointer", portal) || + !in_range("PQftypeGroup: group index", + group_index, 0, portal->no_groups)) + return (-1); + + if ((gbp = pbuf_findGroup(portal, group_index)) && + in_range("PQftypeGroup: field number", field_number, 0, gbp->no_fields)) + return (gbp->types[field_number].adtid); + return (-1); } /* -------------------------------- - * PQfsizeGroup - Return the size of a field given - * the group index and field index + * PQfsizeGroup - Return the size of a field given + * the group index and field index * -------------------------------- */ int -PQfsizeGroup(PortalBuffer *portal, int group_index, int field_number) +PQfsizeGroup(PortalBuffer * portal, int group_index, int field_number) { - GroupBuffer *gbp; - - if (!valid_pointer("PQfsizeGroup: invalid portal pointer", portal) || - !in_range("PQfsizeGroup: tuple index", - group_index, 0, portal->no_groups)) - return(-1); - - if ((gbp = pbuf_findGroup(portal, group_index)) && - in_range("PQfsizeGroup: field number", field_number, 0, gbp->no_fields)) - return(gbp->types[field_number].adtsize); - return(-1); + GroupBuffer *gbp; + + if (!valid_pointer("PQfsizeGroup: invalid portal pointer", portal) || + !in_range("PQfsizeGroup: tuple index", + group_index, 0, portal->no_groups)) + return (-1); + + if ((gbp = pbuf_findGroup(portal, group_index)) && + in_range("PQfsizeGroup: field number", field_number, 0, gbp->no_fields)) + return (gbp->types[field_number].adtsize); + return (-1); } /* -------------------------------- - * PQgroup - Return the tuple group that a particular tuple is in + * PQgroup - Return the tuple group that a particular tuple is in * -------------------------------- */ -GroupBuffer * -PQgroup(PortalBuffer *portal, int tuple_index) -{ - GroupBuffer *gbp; - int tuple_count = 0; - - if (!valid_pointer("PQgroup: invalid portal pointer", portal) || - !in_range("PQgroup: tuple index", - tuple_index, 0, portal->no_tuples)) - return((GroupBuffer *) NULL); - - for (gbp = portal->groups; - gbp && tuple_index >= (tuple_count += gbp->no_tuples); - gbp = gbp->next) - ; - if (!in_range("PQgroup: tuple not found: tuple index", - tuple_index, 0, tuple_count)) - return((GroupBuffer *) NULL); - return(gbp); +GroupBuffer * +PQgroup(PortalBuffer * portal, int tuple_index) +{ + GroupBuffer *gbp; + int tuple_count = 0; + + if (!valid_pointer("PQgroup: invalid portal pointer", portal) || + !in_range("PQgroup: tuple index", + tuple_index, 0, portal->no_tuples)) + return ((GroupBuffer *) NULL); + + for (gbp = portal->groups; + gbp && tuple_index >= (tuple_count += gbp->no_tuples); + gbp = gbp->next) + ; + if (!in_range("PQgroup: tuple not found: tuple index", + tuple_index, 0, tuple_count)) + return ((GroupBuffer *) NULL); + return (gbp); } /* -------------------------------- - * PQgetgroup - Return the index of the group that a - * particular tuple is in + * PQgetgroup - Return the index of the group that a + * particular tuple is in * -------------------------------- */ int -PQgetgroup(PortalBuffer *portal, int tuple_index) -{ - GroupBuffer *gbp; - int tuple_count = 0, group_count = 0; - - if (!valid_pointer("PQgetgroup: invalid portal pointer", portal) || - !in_range("PQgetgroup: tuple index", - tuple_index, 0, portal->no_tuples)) - return(-1); - - for (gbp = portal->groups; - gbp && tuple_index >= (tuple_count += gbp->no_tuples); - gbp = gbp->next) - ++group_count; - if (!gbp || !in_range("PQgetgroup: tuple not found: tuple index", - tuple_index, 0, tuple_count)) - return(-1); - return(group_count); +PQgetgroup(PortalBuffer * portal, int tuple_index) +{ + GroupBuffer *gbp; + int tuple_count = 0, + group_count = 0; + + if (!valid_pointer("PQgetgroup: invalid portal pointer", portal) || + !in_range("PQgetgroup: tuple index", + tuple_index, 0, portal->no_tuples)) + return (-1); + + for (gbp = portal->groups; + gbp && tuple_index >= (tuple_count += gbp->no_tuples); + gbp = gbp->next) + ++group_count; + if (!gbp || !in_range("PQgetgroup: tuple not found: tuple index", + tuple_index, 0, tuple_count)) + return (-1); + return (group_count); } /* -------------------------------- - * PQnfields - Return the number of fields in a tuple + * PQnfields - Return the number of fields in a tuple * -------------------------------- */ int -PQnfields(PortalBuffer *portal, int tuple_index) +PQnfields(PortalBuffer * portal, int tuple_index) { - GroupBuffer *gbp; - - if (!valid_pointer("PQnfields: invalid portal pointer", portal) || - !in_range("PQnfields: tuple index", - tuple_index, 0, portal->no_tuples)) - return(-1); - gbp = PQgroup(portal, tuple_index); - if (gbp) - return(gbp->no_fields); - return(-1); + GroupBuffer *gbp; + + if (!valid_pointer("PQnfields: invalid portal pointer", portal) || + !in_range("PQnfields: tuple index", + tuple_index, 0, portal->no_tuples)) + return (-1); + gbp = PQgroup(portal, tuple_index); + if (gbp) + return (gbp->no_fields); + return (-1); } /* -------------------------------- - * PQfnumber - Return the field index of a given - * field name within a tuple. + * PQfnumber - Return the field index of a given + * field name within a tuple. * -------------------------------- */ int -PQfnumber(PortalBuffer *portal, int tuple_index, char *field_name) +PQfnumber(PortalBuffer * portal, int tuple_index, char *field_name) { - GroupBuffer *gbp; - - if (!valid_pointer("PQfnumber: invalid portal pointer", portal) || + GroupBuffer *gbp; + + if (!valid_pointer("PQfnumber: invalid portal pointer", portal) || !valid_pointer("PQfnumber: invalid field name pointer", field_name) || - !in_range("PQfnumber: tuple index", - tuple_index, 0, portal->no_tuples)) - return(-1); - gbp = PQgroup(portal, tuple_index); - if (gbp) - return(pbuf_findFnumber(gbp, field_name)); - return(-1); + !in_range("PQfnumber: tuple index", + tuple_index, 0, portal->no_tuples)) + return (-1); + gbp = PQgroup(portal, tuple_index); + if (gbp) + return (pbuf_findFnumber(gbp, field_name)); + return (-1); } /* -------------------------------- - * PQfname - Return the name of a field + * PQfname - Return the name of a field * -------------------------------- */ -char * -PQfname(PortalBuffer *portal, int tuple_index, int field_number) -{ - GroupBuffer *gbp; - - if (!valid_pointer("PQfname: invalid portal pointer", portal) || - !in_range("PQfname: tuple index", - tuple_index, 0, portal->no_tuples)) - return((char *) NULL); - - if ((gbp = PQgroup(portal, tuple_index)) && - in_range("PQfname: field number", - field_number, 0, gbp->no_fields)) - return(pbuf_findFname(gbp, field_number)); - return((char *) NULL); +char * +PQfname(PortalBuffer * portal, int tuple_index, int field_number) +{ + GroupBuffer *gbp; + + if (!valid_pointer("PQfname: invalid portal pointer", portal) || + !in_range("PQfname: tuple index", + tuple_index, 0, portal->no_tuples)) + return ((char *) NULL); + + if ((gbp = PQgroup(portal, tuple_index)) && + in_range("PQfname: field number", + field_number, 0, gbp->no_fields)) + return (pbuf_findFname(gbp, field_number)); + return ((char *) NULL); } /* -------------------------------- - * PQftype - Return the type of a field + * PQftype - Return the type of a field * -------------------------------- */ int -PQftype(PortalBuffer *portal, int tuple_index, int field_number) +PQftype(PortalBuffer * portal, int tuple_index, int field_number) { - GroupBuffer *gbp; - - if (!valid_pointer("PQftype: invalid portal pointer", portal) || - !in_range("PQfname: tuple index", - tuple_index, 0, portal->no_tuples)) - return(-1); - - if ((gbp = PQgroup(portal, tuple_index)) && - in_range("PQftype: field number", field_number, 0, gbp->no_fields)) - return(gbp->types[field_number].adtid); - return(-1); + GroupBuffer *gbp; + + if (!valid_pointer("PQftype: invalid portal pointer", portal) || + !in_range("PQfname: tuple index", + tuple_index, 0, portal->no_tuples)) + return (-1); + + if ((gbp = PQgroup(portal, tuple_index)) && + in_range("PQftype: field number", field_number, 0, gbp->no_fields)) + return (gbp->types[field_number].adtid); + return (-1); } /* -------------------------------- - * PQfsize - Return the size of a field + * PQfsize - Return the size of a field * -------------------------------- */ int -PQfsize(PortalBuffer *portal, int tuple_index, int field_number) +PQfsize(PortalBuffer * portal, int tuple_index, int field_number) { - GroupBuffer *gbp; - - if (!valid_pointer("PQfsize: invalid portal pointer", portal) || - !in_range("PQfsize: tuple index", - tuple_index, 0, portal->no_tuples)) - return(-1); - - if ((gbp = PQgroup(portal, tuple_index)) && - in_range("PQfsize: field number", field_number, 0, gbp->no_fields)) - return(gbp->types[field_number].adtsize); - return(-1); + GroupBuffer *gbp; + + if (!valid_pointer("PQfsize: invalid portal pointer", portal) || + !in_range("PQfsize: tuple index", + tuple_index, 0, portal->no_tuples)) + return (-1); + + if ((gbp = PQgroup(portal, tuple_index)) && + in_range("PQfsize: field number", field_number, 0, gbp->no_fields)) + return (gbp->types[field_number].adtsize); + return (-1); } - + /* -------------------------------- - * PQsametype - Return 1 if the two tuples have the same type - * (in the same group) + * PQsametype - Return 1 if the two tuples have the same type + * (in the same group) * -------------------------------- */ int -PQsametype(PortalBuffer *portal, int tuple_index1, int tuple_index2) -{ - GroupBuffer *gbp1, *gbp2; - - if (!valid_pointer("PQsametype: invalid portal pointer", portal) || - !in_range("PQsametype: tuple index 1", - tuple_index1, 0, portal->no_tuples) || - !in_range("PQsametype: tuple index 2", - tuple_index2, 0, portal->no_tuples)) - return(-1); - - gbp1 = PQgroup(portal, tuple_index1); - gbp2 = PQgroup(portal, tuple_index2); - if (gbp1 && gbp2) - return(gbp1 == gbp2); - return(-1); +PQsametype(PortalBuffer * portal, int tuple_index1, int tuple_index2) +{ + GroupBuffer *gbp1, + *gbp2; + + if (!valid_pointer("PQsametype: invalid portal pointer", portal) || + !in_range("PQsametype: tuple index 1", + tuple_index1, 0, portal->no_tuples) || + !in_range("PQsametype: tuple index 2", + tuple_index2, 0, portal->no_tuples)) + return (-1); + + gbp1 = PQgroup(portal, tuple_index1); + gbp2 = PQgroup(portal, tuple_index2); + if (gbp1 && gbp2) + return (gbp1 == gbp2); + return (-1); } static TupleBlock * -PQGetTupleBlock(PortalBuffer *portal, - int tuple_index, - int *tuple_offset) -{ - GroupBuffer *gbp; - TupleBlock *tbp; - int tuple_count = 0; - - if (!valid_pointer("PQGetTupleBlock: invalid portal pointer", portal) || - !valid_pointer("PQGetTupleBlock: invalid offset pointer", - tuple_offset) || - !in_range("PQGetTupleBlock: tuple index", - tuple_index, 0, portal->no_tuples)) - return((TupleBlock *) NULL); - - for (gbp = portal->groups; - gbp && tuple_index >= (tuple_count += gbp->no_tuples); - gbp = gbp->next) - ; - if (!gbp || - !in_range("PQGetTupleBlock: tuple not found: tuple index", - tuple_index, 0, tuple_count)) - return((TupleBlock *) NULL); - tuple_count -= gbp->no_tuples; - for (tbp = gbp->tuples; - tbp && tuple_index >= (tuple_count += TupleBlockSize); - tbp = tbp->next) - ; - if (!tbp || - !in_range("PQGetTupleBlock: tuple not found: tuple index", - tuple_index, 0, tuple_count)) - return((TupleBlock *) NULL); - tuple_count -= TupleBlockSize; - - *tuple_offset = tuple_index - tuple_count; - return(tbp); +PQGetTupleBlock(PortalBuffer * portal, + int tuple_index, + int *tuple_offset) +{ + GroupBuffer *gbp; + TupleBlock *tbp; + int tuple_count = 0; + + if (!valid_pointer("PQGetTupleBlock: invalid portal pointer", portal) || + !valid_pointer("PQGetTupleBlock: invalid offset pointer", + tuple_offset) || + !in_range("PQGetTupleBlock: tuple index", + tuple_index, 0, portal->no_tuples)) + return ((TupleBlock *) NULL); + + for (gbp = portal->groups; + gbp && tuple_index >= (tuple_count += gbp->no_tuples); + gbp = gbp->next) + ; + if (!gbp || + !in_range("PQGetTupleBlock: tuple not found: tuple index", + tuple_index, 0, tuple_count)) + return ((TupleBlock *) NULL); + tuple_count -= gbp->no_tuples; + for (tbp = gbp->tuples; + tbp && tuple_index >= (tuple_count += TupleBlockSize); + tbp = tbp->next) + ; + if (!tbp || + !in_range("PQGetTupleBlock: tuple not found: tuple index", + tuple_index, 0, tuple_count)) + return ((TupleBlock *) NULL); + tuple_count -= TupleBlockSize; + + *tuple_offset = tuple_index - tuple_count; + return (tbp); } /* -------------------------------- - * PQgetvalue - Return an attribute (field) value + * PQgetvalue - Return an attribute (field) value * -------------------------------- */ -char * -PQgetvalue(PortalBuffer *portal, - int tuple_index, - int field_number) +char * +PQgetvalue(PortalBuffer * portal, + int tuple_index, + int field_number) { - TupleBlock *tbp; - int tuple_offset; + TupleBlock *tbp; + int tuple_offset; - tbp = PQGetTupleBlock(portal, tuple_index, &tuple_offset); - if (tbp) - return(tbp->values[tuple_offset][field_number]); - return((char *) NULL); + tbp = PQGetTupleBlock(portal, tuple_index, &tuple_offset); + if (tbp) + return (tbp->values[tuple_offset][field_number]); + return ((char *) NULL); } /* -------------------------------- - * PQgetAttr - Return an attribute (field) value - * this differs from PQgetvalue in that the value returned is - * a copy. The CALLER is responsible for free'ing the data returned. + * PQgetAttr - Return an attribute (field) value + * this differs from PQgetvalue in that the value returned is + * a copy. The CALLER is responsible for free'ing the data returned. * -------------------------------- */ -char * -PQgetAttr(PortalBuffer *portal, - int tuple_index, - int field_number) -{ - TupleBlock *tbp; - int tuple_offset; - int len; - char* result = NULL; - - tbp = PQGetTupleBlock(portal, tuple_index, &tuple_offset); - if (tbp) { - len = tbp->lengths[tuple_offset][field_number]; - result = malloc(len + 1); - memcpy(result, - tbp->values[tuple_offset][field_number], - len); - result[len] = '\0'; - } - return result; +char * +PQgetAttr(PortalBuffer * portal, + int tuple_index, + int field_number) +{ + TupleBlock *tbp; + int tuple_offset; + int len; + char *result = NULL; + + tbp = PQGetTupleBlock(portal, tuple_index, &tuple_offset); + if (tbp) + { + len = tbp->lengths[tuple_offset][field_number]; + result = malloc(len + 1); + memcpy(result, + tbp->values[tuple_offset][field_number], + len); + result[len] = '\0'; + } + return result; } /* -------------------------------- - * PQgetlength - Return an attribute (field) length + * PQgetlength - Return an attribute (field) length * -------------------------------- */ int -PQgetlength(PortalBuffer *portal, - int tuple_index, - int field_number) +PQgetlength(PortalBuffer * portal, + int tuple_index, + int field_number) { - TupleBlock *tbp; - int tuple_offset; + TupleBlock *tbp; + int tuple_offset; - tbp = PQGetTupleBlock(portal, tuple_index, &tuple_offset); - if (tbp) - return(tbp->lengths[tuple_offset][field_number]); - return(-1); + tbp = PQGetTupleBlock(portal, tuple_index, &tuple_offset); + if (tbp) + return (tbp->lengths[tuple_offset][field_number]); + return (-1); } /* ---------------- - * PQclear - free storage claimed by named portal + * PQclear - free storage claimed by named portal * ---------------- */ void PQclear(char *pname) -{ - if (!valid_pointer("PQclear: invalid portal name pointer", pname)) - return; - pbuf_close(pname); +{ + if (!valid_pointer("PQclear: invalid portal name pointer", pname)) + return; + pbuf_close(pname); } /* @@ -644,74 +657,81 @@ PQclear(char *pname) * This is going away with pending rewrite of comm. code... */ /* static SLList pqNotifyList;*/ -static Dllist *pqNotifyList = NULL; +static Dllist *pqNotifyList = NULL; /* remove invalid notifies before returning */ void PQcleanNotify() { - Dlelem *e, *next; - PQNotifyList *p; - - e = DLGetHead(pqNotifyList); - - while (e) { - next = DLGetSucc(e); - p = (PQNotifyList*)DLE_VAL(e); - if (p->valid == 0) { - DLRemove(e); - DLFreeElem(e); - pfree(p); - } - e = next; - } + Dlelem *e, + *next; + PQNotifyList *p; + + e = DLGetHead(pqNotifyList); + + while (e) + { + next = DLGetSucc(e); + p = (PQNotifyList *) DLE_VAL(e); + if (p->valid == 0) + { + DLRemove(e); + DLFreeElem(e); + pfree(p); + } + e = next; + } } void PQnotifies_init() { - Dlelem *e; - PQNotifyList *p; - - if (pqNotifyList == NULL) { - pqNotifyList = DLNewList(); - } - else { - /* clean all notifies */ - for (e = DLGetHead(pqNotifyList); e != NULL; e = DLGetSucc(e)) { - p = (PQNotifyList*)DLE_VAL(e); - p->valid = 0; + Dlelem *e; + PQNotifyList *p; + + if (pqNotifyList == NULL) + { + pqNotifyList = DLNewList(); + } + else + { + /* clean all notifies */ + for (e = DLGetHead(pqNotifyList); e != NULL; e = DLGetSucc(e)) + { + p = (PQNotifyList *) DLE_VAL(e); + p->valid = 0; + } + PQcleanNotify(); } - PQcleanNotify(); - } } -PQNotifyList * +PQNotifyList * PQnotifies() { - Dlelem *e; - PQcleanNotify(); - e = DLGetHead(pqNotifyList); - return (e ? (PQNotifyList*)DLE_VAL(e) : NULL); + Dlelem *e; + + PQcleanNotify(); + e = DLGetHead(pqNotifyList); + return (e ? (PQNotifyList *) DLE_VAL(e) : NULL); } void -PQremoveNotify(PQNotifyList *nPtr) +PQremoveNotify(PQNotifyList * nPtr) { - nPtr->valid = 0; /* remove later */ + nPtr->valid = 0; /* remove later */ } void PQappendNotify(char *relname, int pid) { - PQNotifyList *p; - - if (pqNotifyList == NULL) - pqNotifyList = DLNewList(); - - p = (PQNotifyList*)pbuf_alloc(sizeof(PQNotifyList)); - strNcpy(p->relname, relname, NAMEDATALEN-1); - p->be_pid = pid; - p->valid = 1; - DLAddTail(pqNotifyList, DLNewElem(p)); + PQNotifyList *p; + + if (pqNotifyList == NULL) + pqNotifyList = DLNewList(); + + p = (PQNotifyList *) pbuf_alloc(sizeof(PQNotifyList)); + strNcpy(p->relname, relname, NAMEDATALEN - 1); + p->be_pid = pid; + p->valid = 1; + DLAddTail(pqNotifyList, DLNewElem(p)); } diff --git a/src/backend/libpq/portalbuf.c b/src/backend/libpq/portalbuf.c index b7a527dcfaf..ed2d5bbe615 100644 --- a/src/backend/libpq/portalbuf.c +++ b/src/backend/libpq/portalbuf.c @@ -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; } - diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c index cfa0aebc521..6a7df5771ac 100644 --- a/src/backend/libpq/pqcomm.c +++ b/src/backend/libpq/pqcomm.c @@ -1,37 +1,37 @@ /*------------------------------------------------------------------------- * * pqcomm.c-- - * Communication functions between the Frontend and the Backend + * Communication functions between the Frontend and the Backend * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/libpq/pqcomm.c,v 1.19 1997/08/12 22:52:58 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/libpq/pqcomm.c,v 1.20 1997/09/07 04:42:25 momjian Exp $ * *------------------------------------------------------------------------- */ /* * INTERFACE ROUTINES - * pq_gettty - return the name of the tty in the given buffer - * pq_getport - return the PGPORT setting - * pq_close - close input / output connections - * pq_flush - flush pending output - * pq_getstr - get a null terminated string from connection - * pq_getnchar - get n characters from connection - * pq_getint - get an integer from connection - * pq_putstr - send a null terminated string to connection - * pq_putnchar - send n characters to connection - * pq_putint - send an integer to connection - * pq_getinaddr - initialize address from host and port number - * pq_getinserv - initialize address from host and service name - * pq_connect - create remote input / output connection - * pq_accept - accept remote input / output connection - * pq_async_notify - receive notification from backend. + * pq_gettty - return the name of the tty in the given buffer + * pq_getport - return the PGPORT setting + * pq_close - close input / output connections + * pq_flush - flush pending output + * pq_getstr - get a null terminated string from connection + * pq_getnchar - get n characters from connection + * pq_getint - get an integer from connection + * pq_putstr - send a null terminated string to connection + * pq_putnchar - send n characters to connection + * pq_putint - send an integer to connection + * pq_getinaddr - initialize address from host and port number + * pq_getinserv - initialize address from host and service name + * pq_connect - create remote input / output connection + * pq_accept - accept remote input / output connection + * pq_async_notify - receive notification from backend. * * NOTES - * These functions are used by both frontend applications and - * the postgres backend. + * These functions are used by both frontend applications and + * the postgres backend. * */ #include <stdio.h> @@ -39,7 +39,7 @@ #include <signal.h> #include <errno.h> #include <fcntl.h> -#include <unistd.h> /* for ttyname() */ +#include <unistd.h> /* for ttyname() */ #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> @@ -49,208 +49,217 @@ #if defined(linux) #ifndef SOMAXCONN -#define SOMAXCONN 5 /* from Linux listen(2) man page */ -#endif /* SOMAXCONN */ -#endif /* linux */ +#define SOMAXCONN 5 /* from Linux listen(2) man page */ +#endif /* SOMAXCONN */ +#endif /* linux */ #include <postgres.h> #include <libpq/pqsignal.h> #include <libpq/auth.h> -#include <libpq/libpq.h> /* where the declarations go */ +#include <libpq/libpq.h> /* where the declarations go */ /* ---------------- - * declarations + * declarations * ---------------- */ -FILE *Pfout, *Pfin; -FILE *Pfdebug; /* debugging libpq */ -int PQAsyncNotifyWaiting; /* for async. notification */ +FILE *Pfout, + *Pfin; +FILE *Pfdebug; /* debugging libpq */ +int PQAsyncNotifyWaiting; /* for async. notification */ /* -------------------------------- - * pq_init - open portal file descriptors + * pq_init - open portal file descriptors * -------------------------------- */ void pq_init(int fd) { - Pfin = fdopen(fd, "r"); - Pfout = fdopen(dup(fd), "w"); - if (!Pfin || !Pfout) - elog(FATAL, "pq_init: Couldn't initialize socket connection"); - PQnotifies_init(); - if (getenv("LIBPQ_DEBUG")) { - Pfdebug = stderr; - }else { - Pfdebug = NULL; - } + Pfin = fdopen(fd, "r"); + Pfout = fdopen(dup(fd), "w"); + if (!Pfin || !Pfout) + elog(FATAL, "pq_init: Couldn't initialize socket connection"); + PQnotifies_init(); + if (getenv("LIBPQ_DEBUG")) + { + Pfdebug = stderr; + } + else + { + Pfdebug = NULL; + } } /* ------------------------- - * pq_getc(File* fin) - * - * get a character from the input file, + * pq_getc(File* fin) + * + * get a character from the input file, * - * if Pfdebug is set, also echo the character fetched into Pfdebug + * if Pfdebug is set, also echo the character fetched into Pfdebug * - * used for debugging libpq + * used for debugging libpq */ static int -pq_getc(FILE* fin) +pq_getc(FILE * fin) { - int c; + int c; - c = getc(fin); - if (Pfdebug && c != EOF) - putc(c,Pfdebug); - return c; + c = getc(fin); + if (Pfdebug && c != EOF) + putc(c, Pfdebug); + return c; } /* -------------------------------- - * pq_gettty - return the name of the tty in the given buffer + * pq_gettty - return the name of the tty in the given buffer * -------------------------------- */ void pq_gettty(char *tp) -{ - strncpy(tp, ttyname(0), 19); +{ + strncpy(tp, ttyname(0), 19); } /* -------------------------------- - * pq_getport - return the PGPORT setting + * pq_getport - return the PGPORT setting * -------------------------------- */ int pq_getport() { - char *envport = getenv("PGPORT"); - - if (envport) - return(atoi(envport)); - return(atoi(DEF_PGPORT)); + char *envport = getenv("PGPORT"); + + if (envport) + return (atoi(envport)); + return (atoi(DEF_PGPORT)); } /* -------------------------------- - * pq_close - close input / output connections + * pq_close - close input / output connections * -------------------------------- */ void pq_close() { - if (Pfin) { - fclose(Pfin); - Pfin = NULL; - } - if (Pfout) { - fclose(Pfout); - Pfout = NULL; - } - PQAsyncNotifyWaiting = 0; - PQnotifies_init(); - pq_unregoob(); + if (Pfin) + { + fclose(Pfin); + Pfin = NULL; + } + if (Pfout) + { + fclose(Pfout); + Pfout = NULL; + } + PQAsyncNotifyWaiting = 0; + PQnotifies_init(); + pq_unregoob(); } /* -------------------------------- - * pq_flush - flush pending output + * pq_flush - flush pending output * -------------------------------- */ void pq_flush() { - if (Pfout) - fflush(Pfout); + if (Pfout) + fflush(Pfout); } /* -------------------------------- - * pq_getstr - get a null terminated string from connection + * pq_getstr - get a null terminated string from connection * -------------------------------- */ int pq_getstr(char *s, int maxlen) { - int c = '\0'; - - if (Pfin == (FILE *) NULL) { -/* elog(DEBUG, "Input descriptor is null"); */ - return(EOF); - } - - while (maxlen-- && (c = pq_getc(Pfin)) != EOF && c) - *s++ = c; - *s = '\0'; - - /* ----------------- - * If EOF reached let caller know. - * (This will only happen if we hit EOF before the string - * delimiter is reached.) - * ----------------- - */ - if (c == EOF) - return(EOF); - return(!EOF); + int c = '\0'; + + if (Pfin == (FILE *) NULL) + { +/* elog(DEBUG, "Input descriptor is null"); */ + return (EOF); + } + + while (maxlen-- && (c = pq_getc(Pfin)) != EOF && c) + *s++ = c; + *s = '\0'; + + /* ----------------- + * If EOF reached let caller know. + * (This will only happen if we hit EOF before the string + * delimiter is reached.) + * ----------------- + */ + if (c == EOF) + return (EOF); + return (!EOF); } /* * USER FUNCTION - gets a newline-terminated string from the backend. - * + * * Chiefly here so that applications can use "COPY <rel> to stdout" - * and read the output string. Returns a null-terminated string in s. + * and read the output string. Returns a null-terminated string in s. * * PQgetline reads up to maxlen-1 characters (like fgets(3)) but strips * the terminating \n (like gets(3)). * * RETURNS: - * EOF if it is detected or invalid arguments are given - * 0 if EOL is reached (i.e., \n has been read) - * (this is required for backward-compatibility -- this - * routine used to always return EOF or 0, assuming that - * the line ended within maxlen bytes.) - * 1 in other cases + * EOF if it is detected or invalid arguments are given + * 0 if EOL is reached (i.e., \n has been read) + * (this is required for backward-compatibility -- this + * routine used to always return EOF or 0, assuming that + * the line ended within maxlen bytes.) + * 1 in other cases */ -int PQgetline(char *s, int maxlen) +int +PQgetline(char *s, int maxlen) +{ + if (!Pfin || !s || maxlen <= 1) + return (EOF); + + if (fgets(s, maxlen - 1, Pfin) == NULL) { - if (!Pfin || !s || maxlen <= 1) - return(EOF); - - if(fgets(s, maxlen - 1, Pfin) == NULL) - { - return feof(Pfin) ? EOF : 1; - } - else - { - for( ; *s; s++) - { - if(*s == '\n') - { - *s = '\0'; - break; - } - } - } - - return 0; - } + return feof(Pfin) ? EOF : 1; + } + else + { + for (; *s; s++) + { + if (*s == '\n') + { + *s = '\0'; + break; + } + } + } + + return 0; +} /* * USER FUNCTION - sends a string to the backend. - * + * * Chiefly here so that applications can use "COPY <rel> from stdin". * * RETURNS: - * 0 in all cases. + * 0 in all cases. */ int PQputline(char *s) { - if (Pfout) { - fputs(s, Pfout); - fflush(Pfout); - } - return(0); + if (Pfout) + { + fputs(s, Pfout); + fflush(Pfout); + } + return (0); } /* -------------------------------- - * pq_getnchar - get n characters from connection + * pq_getnchar - get n characters from connection * -------------------------------- */ int @@ -259,228 +268,239 @@ pq_getnchar(char *s, int off, int maxlen) return pqGetNBytes(s + off, maxlen, Pfin); #if 0 - int c = '\0'; - - if (Pfin == (FILE *) NULL) { -/* elog(DEBUG, "Input descriptor is null"); */ - return(EOF); - } - - s += off; - while (maxlen-- && (c = pq_getc(Pfin)) != EOF) - *s++ = c; - - /* ----------------- - * If EOF reached let caller know - * ----------------- - */ - if (c == EOF) - return(EOF); - return(!EOF); + int c = '\0'; + + if (Pfin == (FILE *) NULL) + { +/* elog(DEBUG, "Input descriptor is null"); */ + return (EOF); + } + + s += off; + while (maxlen-- && (c = pq_getc(Pfin)) != EOF) + *s++ = c; + + /* ----------------- + * If EOF reached let caller know + * ----------------- + */ + if (c == EOF) + return (EOF); + return (!EOF); #endif } /* -------------------------------- - * pq_getint - get an integer from connection - * we receive an integer a byte at a type and reconstruct it so that - * machines with different ENDIAN representations can talk to each - * other + * pq_getint - get an integer from connection + * we receive an integer a byte at a type and reconstruct it so that + * machines with different ENDIAN representations can talk to each + * other * -------------------------------- */ int pq_getint(int b) { - int n, status = 1; - - if(!Pfin) - return EOF; - /* mjl: Seems inconsisten w/ return value of pq_putint (void). Also, - EOF is a valid return value for an int! XXX */ - - switch(b) - { - case 1: - status = ((n = fgetc(Pfin)) == EOF); - break; - case 2: - status = pqGetShort(&n, Pfin); - break; - case 4: - status = pqGetLong(&n, Pfin); - break; - default: - fprintf(stderr, "** Unsupported size %d\n", b); - } - - if(status) - { - sprintf(PQerrormsg, - "FATAL: pq_getint failed: errno=%d\n", errno); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); - n = 0; - } - - return n; + int n, + status = 1; + + if (!Pfin) + return EOF; + + /* + * mjl: Seems inconsisten w/ return value of pq_putint (void). Also, + * EOF is a valid return value for an int! XXX + */ + + switch (b) + { + case 1: + status = ((n = fgetc(Pfin)) == EOF); + break; + case 2: + status = pqGetShort(&n, Pfin); + break; + case 4: + status = pqGetLong(&n, Pfin); + break; + default: + fprintf(stderr, "** Unsupported size %d\n", b); + } + + if (status) + { + sprintf(PQerrormsg, + "FATAL: pq_getint failed: errno=%d\n", errno); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + n = 0; + } + + return n; } /* -------------------------------- - * pq_putstr - send a null terminated string to connection + * pq_putstr - send a null terminated string to connection * -------------------------------- */ void pq_putstr(char *s) { - if(pqPutString(s, Pfout)) - { - sprintf(PQerrormsg, - "FATAL: pq_putstr: fputs() failed: errno=%d\n", errno); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + if (pqPutString(s, Pfout)) + { + sprintf(PQerrormsg, + "FATAL: pq_putstr: fputs() failed: errno=%d\n", errno); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); } } /* -------------------------------- - * pq_putnchar - send n characters to connection + * pq_putnchar - send n characters to connection * -------------------------------- */ void pq_putnchar(char *s, int n) +{ + if (pqPutNBytes(s, n, Pfout)) { - if(pqPutNBytes(s, n, Pfout)) - { sprintf(PQerrormsg, - "FATAL: pq_putnchar: fputc() failed: errno=%d\n", - errno); + "FATAL: pq_putnchar: fputc() failed: errno=%d\n", + errno); fputs(PQerrormsg, stderr); pqdebug("%s", PQerrormsg); - } } +} /* -------------------------------- - * pq_putint - send an integer to connection - * we chop an integer into bytes and send individual bytes - * machines with different ENDIAN representations can still talk to each - * other + * pq_putint - send an integer to connection + * we chop an integer into bytes and send individual bytes + * machines with different ENDIAN representations can still talk to each + * other * -------------------------------- */ void pq_putint(int i, int b) { - int status; - - if(!Pfout) return; - - status = 1; - switch(b) - { - case 1: - status = (fputc(i, Pfout) == EOF); - break; - case 2: - status = pqPutShort(i, Pfout); - break; - case 4: - status = pqPutLong(i, Pfout); - break; - default: - fprintf(stderr, "** Unsupported size %d\n", b); - } - - if(status) - { + int status; + + if (!Pfout) + return; + + status = 1; + switch (b) + { + case 1: + status = (fputc(i, Pfout) == EOF); + break; + case 2: + status = pqPutShort(i, Pfout); + break; + case 4: + status = pqPutLong(i, Pfout); + break; + default: + fprintf(stderr, "** Unsupported size %d\n", b); + } + + if (status) + { sprintf(PQerrormsg, - "FATAL: pq_putint failed: errno=%d\n", errno); + "FATAL: pq_putint failed: errno=%d\n", errno); fputs(PQerrormsg, stderr); pqdebug("%s", PQerrormsg); - } + } } /* --- - * pq_sendoob - send a string over the out-of-band channel - * pq_recvoob - receive a string over the oob channel - * NB: Fortunately, the out-of-band channel doesn't conflict with - * buffered I/O because it is separate from regular com. channel. + * pq_sendoob - send a string over the out-of-band channel + * pq_recvoob - receive a string over the oob channel + * NB: Fortunately, the out-of-band channel doesn't conflict with + * buffered I/O because it is separate from regular com. channel. * --- */ int pq_sendoob(char *msg, int len) { - int fd = fileno(Pfout); - - return(send(fd,msg,len,MSG_OOB)); + int fd = fileno(Pfout); + + return (send(fd, msg, len, MSG_OOB)); } int pq_recvoob(char *msgPtr, int *lenPtr) { - int fd = fileno(Pfout); - int len = 0; - - len = recv(fd,msgPtr+len,*lenPtr,MSG_OOB); - *lenPtr = len; - return(len); + int fd = fileno(Pfout); + int len = 0; + + len = recv(fd, msgPtr + len, *lenPtr, MSG_OOB); + *lenPtr = len; + return (len); } /* -------------------------------- - * pq_getinaddr - initialize address from host and port number + * pq_getinaddr - initialize address from host and port number * -------------------------------- */ int -pq_getinaddr(struct sockaddr_in *sin, - char *host, - int port) +pq_getinaddr(struct sockaddr_in * sin, + char *host, + int port) { - struct hostent *hs; - - memset((char *) sin, 0, sizeof(*sin)); - - if (host) { - if (*host >= '0' && *host <= '9') - sin->sin_addr.s_addr = inet_addr(host); - else { - if (!(hs = gethostbyname(host))) { - perror(host); - return(1); - } - if (hs->h_addrtype != AF_INET) { - sprintf(PQerrormsg, - "FATAL: pq_getinaddr: %s not on Internet\n", - host); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); - return(1); - } - memmove((char *) &sin->sin_addr, - hs->h_addr, - hs->h_length); + struct hostent *hs; + + memset((char *) sin, 0, sizeof(*sin)); + + if (host) + { + if (*host >= '0' && *host <= '9') + sin->sin_addr.s_addr = inet_addr(host); + else + { + if (!(hs = gethostbyname(host))) + { + perror(host); + return (1); + } + if (hs->h_addrtype != AF_INET) + { + sprintf(PQerrormsg, + "FATAL: pq_getinaddr: %s not on Internet\n", + host); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + return (1); + } + memmove((char *) &sin->sin_addr, + hs->h_addr, + hs->h_length); + } } - } - sin->sin_family = AF_INET; - sin->sin_port = htons(port); - return(0); + sin->sin_family = AF_INET; + sin->sin_port = htons(port); + return (0); } /* -------------------------------- - * pq_getinserv - initialize address from host and servive name + * pq_getinserv - initialize address from host and servive name * -------------------------------- */ int -pq_getinserv(struct sockaddr_in *sin, char *host, char *serv) +pq_getinserv(struct sockaddr_in * sin, char *host, char *serv) { - struct servent *ss; - - if (*serv >= '0' && *serv <= '9') - return(pq_getinaddr(sin, host, atoi(serv))); - if (!(ss = getservbyname(serv, NULL))) { - sprintf(PQerrormsg, - "FATAL: pq_getinserv: unknown service: %s\n", - serv); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); - return(1); - } - return(pq_getinaddr(sin, host, ntohs(ss->s_port))); + struct servent *ss; + + if (*serv >= '0' && *serv <= '9') + return (pq_getinaddr(sin, host, atoi(serv))); + if (!(ss = getservbyname(serv, NULL))) + { + sprintf(PQerrormsg, + "FATAL: pq_getinserv: unknown service: %s\n", + serv); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + return (1); + } + return (pq_getinaddr(sin, host, ntohs(ss->s_port))); } /* @@ -488,279 +508,297 @@ pq_getinserv(struct sockaddr_in *sin, char *host, char *serv) * This is used for receiving async. notification from the backend. */ void -pq_regoob(void (*fptr)()) +pq_regoob(void (*fptr) ()) { - int fd = fileno(Pfout); + int fd = fileno(Pfout); + #if defined(hpux) - ioctl(fd, FIOSSAIOOWN, getpid()); + ioctl(fd, FIOSSAIOOWN, getpid()); #elif defined(sco) - ioctl(fd, SIOCSPGRP, getpid()); + ioctl(fd, SIOCSPGRP, getpid()); #else - fcntl(fd, F_SETOWN, getpid()); -#endif /* hpux */ - pqsignal(SIGURG,fptr); + fcntl(fd, F_SETOWN, getpid()); +#endif /* hpux */ + pqsignal(SIGURG, fptr); } void pq_unregoob() { - pqsignal(SIGURG,SIG_DFL); + pqsignal(SIGURG, SIG_DFL); } void pq_async_notify() { - char msg[20]; - /* int len = sizeof(msg);*/ - int len = 20; - - if (pq_recvoob(msg,&len) >= 0) { - /* debugging */ - printf("received notification: %s\n",msg); - PQAsyncNotifyWaiting = 1; - /* PQappendNotify(msg+1);*/ - } else { - extern int errno; - printf("SIGURG but no data: len = %d, err=%d\n",len,errno); - } + char msg[20]; + + /* int len = sizeof(msg); */ + int len = 20; + + if (pq_recvoob(msg, &len) >= 0) + { + /* debugging */ + printf("received notification: %s\n", msg); + PQAsyncNotifyWaiting = 1; + /* PQappendNotify(msg+1); */ + } + else + { + extern int errno; + + printf("SIGURG but no data: len = %d, err=%d\n", len, errno); + } } /* * Streams -- wrapper around Unix socket system calls * * - * Stream functions are used for vanilla TCP connection protocol. + * Stream functions are used for vanilla TCP connection protocol. */ /* * StreamServerPort -- open a sock stream "listening" port. * * This initializes the Postmaster's connection - * accepting port. + * accepting port. * * ASSUME: that this doesn't need to be non-blocking because - * the Postmaster uses select() to tell when the socket - * is ready. + * the Postmaster uses select() to tell when the socket + * is ready. * * RETURNS: STATUS_OK or STATUS_ERROR */ int StreamServerPort(char *hostName, short portName, int *fdP) { - struct sockaddr_in sin; - int fd; - int one = 1; - - - if (! hostName) - hostName = "localhost"; - - memset((char *)&sin, 0, sizeof sin); - - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - sprintf(PQerrormsg, - "FATAL: StreamServerPort: socket() failed: errno=%d\n", - errno); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); - return(STATUS_ERROR); - } - - if((setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, - sizeof(one))) == -1) { - sprintf(PQerrormsg, - "FATAL: StreamServerPort: setsockopt (SO_REUSEADDR) failed: errno=%d\n", - errno); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); - return(STATUS_ERROR); - } - - sin.sin_family = AF_INET; - sin.sin_port = htons(portName); - - if (bind(fd, (struct sockaddr *)&sin, sizeof sin) < 0) { - sprintf(PQerrormsg, - "FATAL: StreamServerPort: bind() failed: errno=%d\n", - errno); - pqdebug("%s", PQerrormsg); - strcat(PQerrormsg, "\tIs another postmaster already running on that port?\n"); - strcat(PQerrormsg, "\tIf not, wait a few seconds and retry.\n"); - fputs(PQerrormsg, stderr); - return(STATUS_ERROR); - } - - listen(fd, SOMAXCONN); - - /* MS: I took this code from Dillon's version. It makes the - * listening port non-blocking. That is not necessary (and - * may tickle kernel bugs). - - fcntl(fd, F_SETFD, 1); - fcntl(fd, F_SETFL, FNDELAY); - */ - - *fdP = fd; - return(STATUS_OK); + struct sockaddr_in sin; + int fd; + int one = 1; + + + if (!hostName) + hostName = "localhost"; + + memset((char *) &sin, 0, sizeof sin); + + if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + { + sprintf(PQerrormsg, + "FATAL: StreamServerPort: socket() failed: errno=%d\n", + errno); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + return (STATUS_ERROR); + } + + if ((setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &one, + sizeof(one))) == -1) + { + sprintf(PQerrormsg, + "FATAL: StreamServerPort: setsockopt (SO_REUSEADDR) failed: errno=%d\n", + errno); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + return (STATUS_ERROR); + } + + sin.sin_family = AF_INET; + sin.sin_port = htons(portName); + + if (bind(fd, (struct sockaddr *) & sin, sizeof sin) < 0) + { + sprintf(PQerrormsg, + "FATAL: StreamServerPort: bind() failed: errno=%d\n", + errno); + pqdebug("%s", PQerrormsg); + strcat(PQerrormsg, "\tIs another postmaster already running on that port?\n"); + strcat(PQerrormsg, "\tIf not, wait a few seconds and retry.\n"); + fputs(PQerrormsg, stderr); + return (STATUS_ERROR); + } + + listen(fd, SOMAXCONN); + + /* + * MS: I took this code from Dillon's version. It makes the listening + * port non-blocking. That is not necessary (and may tickle kernel + * bugs). + * + * fcntl(fd, F_SETFD, 1); fcntl(fd, F_SETFL, FNDELAY); + */ + + *fdP = fd; + return (STATUS_OK); } /* * StreamConnection -- create a new connection with client using - * server port. + * server port. * * This one should be non-blocking. - * + * * RETURNS: STATUS_OK or STATUS_ERROR */ int -StreamConnection(int server_fd, Port *port) +StreamConnection(int server_fd, Port * port) { - int addrlen; - - /* accept connection (and fill in the client (remote) address) */ - addrlen = sizeof(struct sockaddr_in); - if ((port->sock = accept(server_fd, - (struct sockaddr *) &port->raddr, - &addrlen)) < 0) { - elog(WARN, "postmaster: StreamConnection: accept: %m"); - return(STATUS_ERROR); - } - - /* fill in the server (local) address */ - addrlen = sizeof(struct sockaddr_in); - if (getsockname(port->sock, (struct sockaddr *) &port->laddr, - &addrlen) < 0) { - elog(WARN, "postmaster: StreamConnection: getsockname: %m"); - return(STATUS_ERROR); - } - { - struct protoent *pe; - int on=1; - - pe = getprotobyname ("TCP"); - if ( pe == NULL ) - { - elog(WARN, "postmaster: getprotobyname failed"); - return(STATUS_ERROR); + int addrlen; + + /* accept connection (and fill in the client (remote) address) */ + addrlen = sizeof(struct sockaddr_in); + if ((port->sock = accept(server_fd, + (struct sockaddr *) & port->raddr, + &addrlen)) < 0) + { + elog(WARN, "postmaster: StreamConnection: accept: %m"); + return (STATUS_ERROR); + } + + /* fill in the server (local) address */ + addrlen = sizeof(struct sockaddr_in); + if (getsockname(port->sock, (struct sockaddr *) & port->laddr, + &addrlen) < 0) + { + elog(WARN, "postmaster: StreamConnection: getsockname: %m"); + return (STATUS_ERROR); } - if ( setsockopt (port->sock, pe->p_proto, TCP_NODELAY, - &on, sizeof (on)) < 0 ) - { - elog(WARN, "postmaster: setsockopt failed"); - return(STATUS_ERROR); + { + struct protoent *pe; + int on = 1; + + pe = getprotobyname("TCP"); + if (pe == NULL) + { + elog(WARN, "postmaster: getprotobyname failed"); + return (STATUS_ERROR); + } + if (setsockopt(port->sock, pe->p_proto, TCP_NODELAY, + &on, sizeof(on)) < 0) + { + elog(WARN, "postmaster: setsockopt failed"); + return (STATUS_ERROR); + } } - } - - port->mask = 1 << port->sock; - - /* reset to non-blocking */ - fcntl(port->sock, F_SETFL, 1); - - return(STATUS_OK); + + port->mask = 1 << port->sock; + + /* reset to non-blocking */ + fcntl(port->sock, F_SETFL, 1); + + return (STATUS_OK); } -/* +/* * StreamClose -- close a client/backend connection */ void StreamClose(int sock) { - close(sock); + close(sock); } /* --------------------------- - * StreamOpen -- From client, initiate a connection with the - * server (Postmaster). + * StreamOpen -- From client, initiate a connection with the + * server (Postmaster). * * RETURNS: STATUS_OK or STATUS_ERROR * * NOTE: connection is NOT established just because this - * routine exits. Local state is ok, but we haven't - * spoken to the postmaster yet. + * routine exits. Local state is ok, but we haven't + * spoken to the postmaster yet. * --------------------------- */ int -StreamOpen(char *hostName, short portName, Port *port) +StreamOpen(char *hostName, short portName, Port * port) { - struct hostent *hp; - int laddrlen = sizeof(struct sockaddr_in); - extern int errno; - - if (!hostName) - hostName = "localhost"; - - /* set up the server (remote) address */ - if (!(hp = gethostbyname(hostName)) || hp->h_addrtype != AF_INET) { - sprintf(PQerrormsg, - "FATAL: StreamOpen: unknown hostname: %s\n", - hostName); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); - return(STATUS_ERROR); - } - memset((char *) &port->raddr, 0, sizeof(port->raddr)); - memmove((char *) &(port->raddr.sin_addr), - (char *) hp->h_addr, - hp->h_length); - port->raddr.sin_family = AF_INET; - port->raddr.sin_port = htons(portName); - - /* connect to the server */ - if ((port->sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - sprintf(PQerrormsg, - "FATAL: StreamOpen: socket() failed: errno=%d\n", - errno); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); - return(STATUS_ERROR); - } - if (connect(port->sock, (struct sockaddr *)&port->raddr, - sizeof(port->raddr)) < 0) { - sprintf(PQerrormsg, - "FATAL: StreamOpen: connect() failed: errno=%d\n", - errno); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); - return(STATUS_ERROR); - } - - /* fill in the client address */ - if (getsockname(port->sock, (struct sockaddr *) &port->laddr, - &laddrlen) < 0) { - sprintf(PQerrormsg, - "FATAL: StreamOpen: getsockname() failed: errno=%d\n", - errno); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); - return(STATUS_ERROR); - } - - return(STATUS_OK); + struct hostent *hp; + int laddrlen = sizeof(struct sockaddr_in); + extern int errno; + + if (!hostName) + hostName = "localhost"; + + /* set up the server (remote) address */ + if (!(hp = gethostbyname(hostName)) || hp->h_addrtype != AF_INET) + { + sprintf(PQerrormsg, + "FATAL: StreamOpen: unknown hostname: %s\n", + hostName); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + return (STATUS_ERROR); + } + memset((char *) &port->raddr, 0, sizeof(port->raddr)); + memmove((char *) &(port->raddr.sin_addr), + (char *) hp->h_addr, + hp->h_length); + port->raddr.sin_family = AF_INET; + port->raddr.sin_port = htons(portName); + + /* connect to the server */ + if ((port->sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) + { + sprintf(PQerrormsg, + "FATAL: StreamOpen: socket() failed: errno=%d\n", + errno); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + return (STATUS_ERROR); + } + if (connect(port->sock, (struct sockaddr *) & port->raddr, + sizeof(port->raddr)) < 0) + { + sprintf(PQerrormsg, + "FATAL: StreamOpen: connect() failed: errno=%d\n", + errno); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + return (STATUS_ERROR); + } + + /* fill in the client address */ + if (getsockname(port->sock, (struct sockaddr *) & port->laddr, + &laddrlen) < 0) + { + sprintf(PQerrormsg, + "FATAL: StreamOpen: getsockname() failed: errno=%d\n", + errno); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + return (STATUS_ERROR); + } + + return (STATUS_OK); } -static char *authentication_type_name[] = { - 0, 0, 0, 0, 0, 0, 0, - "the default authentication type", - 0, 0, - "Kerberos v4", - "Kerberos v5", - "host-based authentication", - "unauthenication", - "plaintext password authentication" +static char *authentication_type_name[] = { + 0, 0, 0, 0, 0, 0, 0, + "the default authentication type", + 0, 0, + "Kerberos v4", + "Kerberos v5", + "host-based authentication", + "unauthenication", + "plaintext password authentication" }; -char *name_of_authentication_type(int type) +char * +name_of_authentication_type(int type) { - char *result = 0; + char *result = 0; - if(type >= 1 && type <= LAST_AUTHENTICATION_TYPE) { - result = authentication_type_name[type]; - } + if (type >= 1 && type <= LAST_AUTHENTICATION_TYPE) + { + result = authentication_type_name[type]; + } - if(result == 0) { - result = "<unknown authentication type>"; - } + if (result == 0) + { + result = "<unknown authentication type>"; + } - return result; + return result; } diff --git a/src/backend/libpq/pqcomprim.c b/src/backend/libpq/pqcomprim.c index 3501b63c7b6..8675205d784 100644 --- a/src/backend/libpq/pqcomprim.c +++ b/src/backend/libpq/pqcomprim.c @@ -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 +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; - - if(fread(&n, sizeof(u_short), 1, f) != 1) - retval = EOF; - - *result = ntoh_s(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; - } +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; - +int +pqPutByte(int c, FILE * f) +{ + if (!f) + return 0; + return (putc(c, f) == c) ? 0 : EOF; - } - -/* --------------------------------------------------------------------- */ +} +/* --------------------------------------------------------------------- */ diff --git a/src/backend/libpq/pqpacket.c b/src/backend/libpq/pqpacket.c index 6f67ddc5f5b..9f56556537f 100644 --- a/src/backend/libpq/pqpacket.c +++ b/src/backend/libpq/pqpacket.c @@ -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); - - 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; - - 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; + 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); + + 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; + + 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. + + /* + * Now that we know how big it is, read the packet. We read the + * entire packet, since the last call was just a peek. */ - else if (! cc) - return(STATUS_INVALID); - + 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) { diff --git a/src/backend/libpq/pqsignal.c b/src/backend/libpq/pqsignal.c index 0c91f50df03..727a2a7207d 100644 --- a/src/backend/libpq/pqsignal.c +++ b/src/backend/libpq/pqsignal.c @@ -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 */ } diff --git a/src/backend/libpq/util.c b/src/backend/libpq/util.c index e8ca2e4ccc5..f4efec13f3a 100644 --- a/src/backend/libpq/util.c +++ b/src/backend/libpq/util.c @@ -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; } - - - - |