#include "postgres_fe.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <ctype.h>
#include <time.h>
#include <unistd.h>
#include "libpq-fe.h"
#include "libpq-int.h"
#include "fe-auth.h"
#include "pg_config_paths.h"
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "libpq/ip.h"
#include "mb/pg_wchar.h"
Go to the source code of this file.
Data Structures | |
struct | _internalPQconninfoOption |
Defines | |
#define | PGPASSFILE ".pgpass" |
#define | ERRCODE_APPNAME_UNKNOWN "42704" |
#define | ERRCODE_INVALID_PASSWORD "28P01" |
#define | ERRCODE_CANNOT_CONNECT_NOW "57P03" |
#define | DefaultHost "localhost" |
#define | DefaultTty "" |
#define | DefaultOption "" |
#define | DefaultAuthtype "" |
#define | DefaultPassword "" |
#define | DefaultSSLMode "disable" |
#define | MAXBUFSIZE 256 |
#define | LINELEN NAMEDATALEN*5 |
Typedefs | |
typedef struct _internalPQconninfoOption | internalPQconninfoOption |
Functions | |
static bool | connectOptions1 (PGconn *conn, const char *conninfo) |
static bool | connectOptions2 (PGconn *conn) |
static int | connectDBStart (PGconn *conn) |
static int | connectDBComplete (PGconn *conn) |
static PGPing | internal_ping (PGconn *conn) |
static PGconn * | makeEmptyPGconn (void) |
static void | fillPGconn (PGconn *conn, PQconninfoOption *connOptions) |
static void | freePGconn (PGconn *conn) |
static void | closePGconn (PGconn *conn) |
static PQconninfoOption * | conninfo_init (PQExpBuffer errorMessage) |
static PQconninfoOption * | parse_connection_string (const char *conninfo, PQExpBuffer errorMessage, bool use_defaults) |
static int | uri_prefix_length (const char *connstr) |
static bool | recognized_connection_string (const char *connstr) |
static PQconninfoOption * | conninfo_parse (const char *conninfo, PQExpBuffer errorMessage, bool use_defaults) |
static PQconninfoOption * | conninfo_array_parse (const char *const *keywords, const char *const *values, PQExpBuffer errorMessage, bool use_defaults, int expand_dbname) |
static bool | conninfo_add_defaults (PQconninfoOption *options, PQExpBuffer errorMessage) |
static PQconninfoOption * | conninfo_uri_parse (const char *uri, PQExpBuffer errorMessage, bool use_defaults) |
static bool | conninfo_uri_parse_options (PQconninfoOption *options, const char *uri, PQExpBuffer errorMessage) |
static bool | conninfo_uri_parse_params (char *params, PQconninfoOption *connOptions, PQExpBuffer errorMessage) |
static char * | conninfo_uri_decode (const char *str, PQExpBuffer errorMessage) |
static bool | get_hexdigit (char digit, int *value) |
static const char * | conninfo_getval (PQconninfoOption *connOptions, const char *keyword) |
static PQconninfoOption * | conninfo_storeval (PQconninfoOption *connOptions, const char *keyword, const char *value, PQExpBuffer errorMessage, bool ignoreMissing, bool uri_decode) |
static PQconninfoOption * | conninfo_find (PQconninfoOption *connOptions, const char *keyword) |
static void | defaultNoticeReceiver (void *arg, const PGresult *res) |
static void | defaultNoticeProcessor (void *arg, const char *message) |
static int | parseServiceInfo (PQconninfoOption *options, PQExpBuffer errorMessage) |
static int | parseServiceFile (const char *serviceFile, const char *service, PQconninfoOption *options, PQExpBuffer errorMessage, bool *group_found) |
static char * | pwdfMatchesString (char *buf, char *token) |
static char * | PasswordFromFile (char *hostname, char *port, char *dbname, char *username) |
static bool | getPgPassFilename (char *pgpassfile) |
static void | dot_pg_pass_warning (PGconn *conn) |
static void | default_threadlock (int acquire) |
void | pqDropConnection (PGconn *conn) |
PGconn * | PQconnectdbParams (const char *const *keywords, const char *const *values, int expand_dbname) |
PGPing | PQpingParams (const char *const *keywords, const char *const *values, int expand_dbname) |
PGconn * | PQconnectdb (const char *conninfo) |
PGPing | PQping (const char *conninfo) |
PGconn * | PQconnectStartParams (const char *const *keywords, const char *const *values, int expand_dbname) |
PGconn * | PQconnectStart (const char *conninfo) |
PQconninfoOption * | PQconndefaults (void) |
PGconn * | PQsetdbLogin (const char *pghost, const char *pgport, const char *pgoptions, const char *pgtty, const char *dbName, const char *login, const char *pwd) |
static int | connectNoDelay (PGconn *conn) |
static void | connectFailureMessage (PGconn *conn, int errorno) |
static int | useKeepalives (PGconn *conn) |
static int | setKeepalivesIdle (PGconn *conn) |
static int | setKeepalivesInterval (PGconn *conn) |
static int | setKeepalivesCount (PGconn *conn) |
PostgresPollingStatusType | PQconnectPoll (PGconn *conn) |
void | PQfinish (PGconn *conn) |
void | PQreset (PGconn *conn) |
int | PQresetStart (PGconn *conn) |
PostgresPollingStatusType | PQresetPoll (PGconn *conn) |
PGcancel * | PQgetCancel (PGconn *conn) |
void | PQfreeCancel (PGcancel *cancel) |
static int | internal_cancel (SockAddr *raddr, int be_pid, int be_key, char *errbuf, int errbufsize) |
int | PQcancel (PGcancel *cancel, char *errbuf, int errbufsize) |
int | PQrequestCancel (PGconn *conn) |
int | pqPacketSend (PGconn *conn, char pack_type, const void *buf, size_t buf_len) |
PQconninfoOption * | PQconninfoParse (const char *conninfo, char **errmsg) |
PQconninfoOption * | PQconninfo (PGconn *conn) |
void | PQconninfoFree (PQconninfoOption *connOptions) |
char * | PQdb (const PGconn *conn) |
char * | PQuser (const PGconn *conn) |
char * | PQpass (const PGconn *conn) |
char * | PQhost (const PGconn *conn) |
char * | PQport (const PGconn *conn) |
char * | PQtty (const PGconn *conn) |
char * | PQoptions (const PGconn *conn) |
ConnStatusType | PQstatus (const PGconn *conn) |
PGTransactionStatusType | PQtransactionStatus (const PGconn *conn) |
const char * | PQparameterStatus (const PGconn *conn, const char *paramName) |
int | PQprotocolVersion (const PGconn *conn) |
int | PQserverVersion (const PGconn *conn) |
char * | PQerrorMessage (const PGconn *conn) |
int | PQsocket (const PGconn *conn) |
int | PQbackendPID (const PGconn *conn) |
int | PQconnectionNeedsPassword (const PGconn *conn) |
int | PQconnectionUsedPassword (const PGconn *conn) |
int | PQclientEncoding (const PGconn *conn) |
int | PQsetClientEncoding (PGconn *conn, const char *encoding) |
PGVerbosity | PQsetErrorVerbosity (PGconn *conn, PGVerbosity verbosity) |
void | PQtrace (PGconn *conn, FILE *debug_port) |
void | PQuntrace (PGconn *conn) |
PQnoticeReceiver | PQsetNoticeReceiver (PGconn *conn, PQnoticeReceiver proc, void *arg) |
PQnoticeProcessor | PQsetNoticeProcessor (PGconn *conn, PQnoticeProcessor proc, void *arg) |
bool | pqGetHomeDirectory (char *buf, int bufsize) |
pgthreadlock_t | PQregisterThreadLock (pgthreadlock_t newhandler) |
Variables | |
static const internalPQconninfoOption | PQconninfoOptions [] |
static const PQEnvironmentOption | EnvironmentOptions [] |
static const char | uri_designator [] = "postgresql://" |
static const char | short_uri_designator [] = "postgres://" |
pgthreadlock_t | pg_g_threadlock = default_threadlock |
#define DefaultAuthtype "" |
Definition at line 109 of file fe-connect.c.
#define DefaultHost "localhost" |
Definition at line 106 of file fe-connect.c.
#define DefaultOption "" |
Definition at line 108 of file fe-connect.c.
#define DefaultPassword "" |
Definition at line 110 of file fe-connect.c.
Referenced by connectOptions2().
#define DefaultSSLMode "disable" |
Definition at line 114 of file fe-connect.c.
Referenced by connectOptions2().
#define DefaultTty "" |
Definition at line 107 of file fe-connect.c.
#define ERRCODE_APPNAME_UNKNOWN "42704" |
Definition at line 95 of file fe-connect.c.
Referenced by PQconnectPoll().
#define ERRCODE_CANNOT_CONNECT_NOW "57P03" |
Definition at line 100 of file fe-connect.c.
Referenced by internal_ping(), and ProcessStartupPacket().
#define ERRCODE_INVALID_PASSWORD "28P01" |
Definition at line 98 of file fe-connect.c.
Referenced by dot_pg_pass_warning().
#define LINELEN NAMEDATALEN*5 |
#define MAXBUFSIZE 256 |
Definition at line 3756 of file fe-connect.c.
#define PGPASSFILE ".pgpass" |
Definition at line 84 of file fe-connect.c.
Referenced by getPgPassFilename().
typedef struct _internalPQconninfoOption internalPQconninfoOption |
static void closePGconn | ( | PGconn * | conn | ) | [static] |
Definition at line 2860 of file fe-connect.c.
References pg_conn::addr_cur, pg_conn::addrlist, pg_conn::addrlist_family, pg_conn::asyncStatus, CONNECTION_OK, free, pg_conn::lobjfuncs, pgParameterStatus::next, pgNotify::next, pg_conn::nonblocking, pg_conn::notifyHead, pg_conn::notifyTail, NULL, pg_freeaddrinfo_all(), pqClearAsyncResult(), pqDropConnection(), pqFlush(), pqPutMsgEnd(), pqPutMsgStart(), pg_conn::pstatus, pg_conn::sock, and pg_conn::status.
Referenced by PQfinish(), PQreset(), and PQresetStart().
{ PGnotify *notify; pgParameterStatus *pstatus; /* * Note that the protocol doesn't allow us to send Terminate messages * during the startup phase. */ if (conn->sock >= 0 && conn->status == CONNECTION_OK) { /* * Try to send "close connection" message to backend. Ignore any * error. */ pqPutMsgStart('X', false, conn); pqPutMsgEnd(conn); pqFlush(conn); } /* * Must reset the blocking status so a possible reconnect will work. * * Don't call PQsetnonblocking() because it will fail if it's unable to * flush the connection. */ conn->nonblocking = FALSE; /* * Close the connection, reset all transient state, flush I/O buffers. */ pqDropConnection(conn); conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just * absent */ conn->asyncStatus = PGASYNC_IDLE; pqClearAsyncResult(conn); /* deallocate result */ pg_freeaddrinfo_all(conn->addrlist_family, conn->addrlist); conn->addrlist = NULL; conn->addr_cur = NULL; notify = conn->notifyHead; while (notify != NULL) { PGnotify *prev = notify; notify = notify->next; free(prev); } conn->notifyHead = conn->notifyTail = NULL; pstatus = conn->pstatus; while (pstatus != NULL) { pgParameterStatus *prev = pstatus; pstatus = pstatus->next; free(prev); } conn->pstatus = NULL; if (conn->lobjfuncs) free(conn->lobjfuncs); conn->lobjfuncs = NULL; #ifdef ENABLE_GSS { OM_uint32 min_s; if (conn->gctx) gss_delete_sec_context(&min_s, &conn->gctx, GSS_C_NO_BUFFER); if (conn->gtarg_nam) gss_release_name(&min_s, &conn->gtarg_nam); if (conn->ginbuf.length) gss_release_buffer(&min_s, &conn->ginbuf); if (conn->goutbuf.length) gss_release_buffer(&min_s, &conn->goutbuf); } #endif #ifdef ENABLE_SSPI if (conn->ginbuf.length) free(conn->ginbuf.value); conn->ginbuf.length = 0; conn->ginbuf.value = NULL; if (conn->sspitarget) free(conn->sspitarget); conn->sspitarget = NULL; if (conn->sspicred) { FreeCredentialsHandle(conn->sspicred); free(conn->sspicred); conn->sspicred = NULL; } if (conn->sspictx) { DeleteSecurityContext(conn->sspictx); free(conn->sspictx); conn->sspictx = NULL; } #endif }
static int connectDBComplete | ( | PGconn * | conn | ) | [static] |
Definition at line 1452 of file fe-connect.c.
References pg_conn::connect_timeout, CONNECTION_BAD, pg_conn::errorMessage, flag(), NULL, PGRES_POLLING_OK, PGRES_POLLING_READING, PGRES_POLLING_WRITING, PQconnectPoll(), pqWaitTimed(), resetPQExpBuffer(), and pg_conn::status.
Referenced by internal_ping(), PQconnectdb(), PQconnectdbParams(), PQreset(), and PQsetdbLogin().
{ PostgresPollingStatusType flag = PGRES_POLLING_WRITING; time_t finish_time = ((time_t) -1); if (conn == NULL || conn->status == CONNECTION_BAD) return 0; /* * Set up a time limit, if connect_timeout isn't zero. */ if (conn->connect_timeout != NULL) { int timeout = atoi(conn->connect_timeout); if (timeout > 0) { /* * Rounding could cause connection to fail; need at least 2 secs */ if (timeout < 2) timeout = 2; /* calculate the finish time based on start + timeout */ finish_time = time(NULL) + timeout; } } for (;;) { /* * Wait, if necessary. Note that the initial state (just after * PQconnectStart) is to wait for the socket to select for writing. */ switch (flag) { case PGRES_POLLING_OK: /* * Reset stored error messages since we now have a working * connection */ resetPQExpBuffer(&conn->errorMessage); return 1; /* success! */ case PGRES_POLLING_READING: if (pqWaitTimed(1, 0, conn, finish_time)) { conn->status = CONNECTION_BAD; return 0; } break; case PGRES_POLLING_WRITING: if (pqWaitTimed(0, 1, conn, finish_time)) { conn->status = CONNECTION_BAD; return 0; } break; default: /* Just in case we failed to set it in PQconnectPoll */ conn->status = CONNECTION_BAD; return 0; } /* * Now try to advance the state machine. */ flag = PQconnectPoll(conn); } }
static int connectDBStart | ( | PGconn * | conn | ) | [static] |
Definition at line 1310 of file fe-connect.c.
References pg_conn::addr_cur, pg_conn::addrlist, pg_conn::addrlist_family, addrinfo::ai_family, addrinfo::ai_flags, addrinfo::ai_socktype, appendPQExpBuffer(), pg_conn::errorMessage, gai_strerror, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, libpq_gettext, MemSet, NULL, pg_conn::options_valid, pg_conn::outCount, pg_freeaddrinfo_all(), pg_getaddrinfo_all(), PG_PROTOCOL, pg_conn::pghost, pg_conn::pghostaddr, pg_conn::pgport, PGRES_POLLING_WRITING, pg_conn::pgunixsocket, PQconnectPoll(), pqDropConnection(), pg_conn::pversion, pg_conn::send_appname, snprintf(), pg_conn::sslmode, pg_conn::status, UNIXSOCK_PATH, and UNIXSOCK_PATH_BUFLEN.
Referenced by PQconnectStart(), PQconnectStartParams(), PQreset(), PQresetStart(), and PQsetdbLogin().
{ int portnum; char portstr[MAXPGPATH]; struct addrinfo *addrs = NULL; struct addrinfo hint; const char *node; int ret; if (!conn) return 0; if (!conn->options_valid) goto connect_errReturn; /* Ensure our buffers are empty */ conn->inStart = conn->inCursor = conn->inEnd = 0; conn->outCount = 0; /* * Determine the parameters to pass to pg_getaddrinfo_all. */ /* Initialize hint structure */ MemSet(&hint, 0, sizeof(hint)); hint.ai_socktype = SOCK_STREAM; hint.ai_family = AF_UNSPEC; /* Set up port number as a string */ if (conn->pgport != NULL && conn->pgport[0] != '\0') { portnum = atoi(conn->pgport); if (portnum < 1 || portnum > 65535) { appendPQExpBuffer(&conn->errorMessage, libpq_gettext("invalid port number: \"%s\"\n"), conn->pgport); conn->options_valid = false; goto connect_errReturn; } } else portnum = DEF_PGPORT; snprintf(portstr, sizeof(portstr), "%d", portnum); if (conn->pghostaddr != NULL && conn->pghostaddr[0] != '\0') { /* Using pghostaddr avoids a hostname lookup */ node = conn->pghostaddr; hint.ai_family = AF_UNSPEC; hint.ai_flags = AI_NUMERICHOST; } else if (conn->pghost != NULL && conn->pghost[0] != '\0') { /* Using pghost, so we have to look-up the hostname */ node = conn->pghost; hint.ai_family = AF_UNSPEC; } else { #ifdef HAVE_UNIX_SOCKETS /* pghostaddr and pghost are NULL, so use Unix domain socket */ node = NULL; hint.ai_family = AF_UNIX; UNIXSOCK_PATH(portstr, portnum, conn->pgunixsocket); if (strlen(portstr) >= UNIXSOCK_PATH_BUFLEN) { appendPQExpBuffer(&conn->errorMessage, libpq_gettext("Unix-domain socket path \"%s\" is too long (maximum %d bytes)\n"), portstr, (int) (UNIXSOCK_PATH_BUFLEN - 1)); conn->options_valid = false; goto connect_errReturn; } #else /* Without Unix sockets, default to localhost instead */ node = DefaultHost; hint.ai_family = AF_UNSPEC; #endif /* HAVE_UNIX_SOCKETS */ } /* Use pg_getaddrinfo_all() to resolve the address */ ret = pg_getaddrinfo_all(node, portstr, &hint, &addrs); if (ret || !addrs) { if (node) appendPQExpBuffer(&conn->errorMessage, libpq_gettext("could not translate host name \"%s\" to address: %s\n"), node, gai_strerror(ret)); else appendPQExpBuffer(&conn->errorMessage, libpq_gettext("could not translate Unix-domain socket path \"%s\" to address: %s\n"), portstr, gai_strerror(ret)); if (addrs) pg_freeaddrinfo_all(hint.ai_family, addrs); conn->options_valid = false; goto connect_errReturn; } #ifdef USE_SSL /* setup values based on SSL mode */ if (conn->sslmode[0] == 'd') /* "disable" */ conn->allow_ssl_try = false; else if (conn->sslmode[0] == 'a') /* "allow" */ conn->wait_ssl_try = true; #endif /* * Set up to try to connect, with protocol 3.0 as the first attempt. */ conn->addrlist = addrs; conn->addr_cur = addrs; conn->addrlist_family = hint.ai_family; conn->pversion = PG_PROTOCOL(3, 0); conn->send_appname = true; conn->status = CONNECTION_NEEDED; /* * The code for processing CONNECTION_NEEDED state is in PQconnectPoll(), * so that it can easily be re-executed if needed again during the * asynchronous startup process. However, we must run it once here, * because callers expect a success return from this routine to mean that * we are in PGRES_POLLING_WRITING connection state. */ if (PQconnectPoll(conn) == PGRES_POLLING_WRITING) return 1; connect_errReturn: pqDropConnection(conn); conn->status = CONNECTION_BAD; return 0; }
static void connectFailureMessage | ( | PGconn * | conn, | |
int | errorno | |||
) | [static] |
Definition at line 1039 of file fe-connect.c.
References SockAddr::addr, appendPQExpBuffer(), pg_conn::errorMessage, inet_net_ntop(), IS_AF_UNIX, libpq_gettext, NI_MAXHOST, NI_NUMERICSERV, NULL, pg_getnameinfo_all(), pg_conn::pghost, pg_conn::pghostaddr, pg_conn::pgport, pg_conn::raddr, SockAddr::salen, SOCK_STRERROR, and strlcpy().
Referenced by PQconnectPoll().
{ char sebuf[256]; #ifdef HAVE_UNIX_SOCKETS if (IS_AF_UNIX(conn->raddr.addr.ss_family)) { char service[NI_MAXHOST]; pg_getnameinfo_all(&conn->raddr.addr, conn->raddr.salen, NULL, 0, service, sizeof(service), NI_NUMERICSERV); appendPQExpBuffer(&conn->errorMessage, libpq_gettext("could not connect to server: %s\n" "\tIs the server running locally and accepting\n" "\tconnections on Unix domain socket \"%s\"?\n"), SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)), service); } else #endif /* HAVE_UNIX_SOCKETS */ { char host_addr[NI_MAXHOST]; const char *displayed_host; struct sockaddr_storage *addr = &conn->raddr.addr; /* * Optionally display the network address with the hostname. This is * useful to distinguish between IPv4 and IPv6 connections. */ if (conn->pghostaddr != NULL) strlcpy(host_addr, conn->pghostaddr, NI_MAXHOST); else if (addr->ss_family == AF_INET) { if (inet_net_ntop(AF_INET, &((struct sockaddr_in *) addr)->sin_addr.s_addr, 32, host_addr, sizeof(host_addr)) == NULL) strcpy(host_addr, "???"); } #ifdef HAVE_IPV6 else if (addr->ss_family == AF_INET6) { if (inet_net_ntop(AF_INET6, &((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr, 128, host_addr, sizeof(host_addr)) == NULL) strcpy(host_addr, "???"); } #endif else strcpy(host_addr, "???"); if (conn->pghostaddr && conn->pghostaddr[0] != '\0') displayed_host = conn->pghostaddr; else if (conn->pghost && conn->pghost[0] != '\0') displayed_host = conn->pghost; else displayed_host = DefaultHost; /* * If the user did not supply an IP address using 'hostaddr', and * 'host' was missing or does not match our lookup, display the * looked-up IP address. */ if ((conn->pghostaddr == NULL) && (conn->pghost == NULL || strcmp(conn->pghost, host_addr) != 0)) appendPQExpBuffer(&conn->errorMessage, libpq_gettext("could not connect to server: %s\n" "\tIs the server running on host \"%s\" (%s) and accepting\n" "\tTCP/IP connections on port %s?\n"), SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)), displayed_host, host_addr, conn->pgport); else appendPQExpBuffer(&conn->errorMessage, libpq_gettext("could not connect to server: %s\n" "\tIs the server running on host \"%s\" and accepting\n" "\tTCP/IP connections on port %s?\n"), SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)), displayed_host, conn->pgport); } }
static int connectNoDelay | ( | PGconn * | conn | ) | [static] |
Definition at line 1011 of file fe-connect.c.
References appendPQExpBuffer(), pg_conn::errorMessage, libpq_gettext, pg_conn::sock, SOCK_ERRNO, and SOCK_STRERROR.
Referenced by PQconnectPoll().
{ #ifdef TCP_NODELAY int on = 1; if (setsockopt(conn->sock, IPPROTO_TCP, TCP_NODELAY, (char *) &on, sizeof(on)) < 0) { char sebuf[256]; appendPQExpBuffer(&conn->errorMessage, libpq_gettext("could not set socket to TCP no delay mode: %s\n"), SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf))); return 0; } #endif return 1; }
Definition at line 708 of file fe-connect.c.
References pg_conn::errorMessage, fillPGconn(), NULL, parse_connection_string(), PQconninfoFree(), and pg_conn::status.
Referenced by PQconnectStart(), and PQsetdbLogin().
{ PQconninfoOption *connOptions; /* * Parse the conninfo string */ connOptions = parse_connection_string(conninfo, &conn->errorMessage, true); if (connOptions == NULL) { conn->status = CONNECTION_BAD; /* errorMessage is already set */ return false; } /* * Move option values into conn structure */ fillPGconn(conn, connOptions); /* * Free the option info - all is in conn now */ PQconninfoFree(connOptions); return true; }
Definition at line 745 of file fe-connect.c.
References pg_conn::client_encoding_initial, pg_conn::dbName, DefaultPassword, DefaultSSLMode, pg_conn::dot_pgpass_used, pg_conn::errorMessage, free, is_absolute_path, libpq_gettext, NULL, pg_conn::options_valid, PasswordFromFile(), pg_encoding_to_char(), pg_get_encoding_from_locale(), pg_conn::pghost, pg_conn::pgpass, pg_conn::pgport, pg_conn::pgunixsocket, pg_conn::pguser, printfPQExpBuffer(), pg_conn::sslmode, and pg_conn::status.
Referenced by PQconnectStart(), PQconnectStartParams(), and PQsetdbLogin().
{ /* * If database name was not given, default it to equal user name */ if ((conn->dbName == NULL || conn->dbName[0] == '\0') && conn->pguser != NULL) { if (conn->dbName) free(conn->dbName); conn->dbName = strdup(conn->pguser); } /* * Supply default password if none given */ if (conn->pgpass == NULL || conn->pgpass[0] == '\0') { if (conn->pgpass) free(conn->pgpass); conn->pgpass = PasswordFromFile(conn->pghost, conn->pgport, conn->dbName, conn->pguser); if (conn->pgpass == NULL) conn->pgpass = strdup(DefaultPassword); else conn->dot_pgpass_used = true; } /* * Allow unix socket specification in the host name */ if (conn->pghost && is_absolute_path(conn->pghost)) { if (conn->pgunixsocket) free(conn->pgunixsocket); conn->pgunixsocket = conn->pghost; conn->pghost = NULL; } /* * validate sslmode option */ if (conn->sslmode) { if (strcmp(conn->sslmode, "disable") != 0 && strcmp(conn->sslmode, "allow") != 0 && strcmp(conn->sslmode, "prefer") != 0 && strcmp(conn->sslmode, "require") != 0 && strcmp(conn->sslmode, "verify-ca") != 0 && strcmp(conn->sslmode, "verify-full") != 0) { conn->status = CONNECTION_BAD; printfPQExpBuffer(&conn->errorMessage, libpq_gettext("invalid sslmode value: \"%s\"\n"), conn->sslmode); return false; } #ifndef USE_SSL switch (conn->sslmode[0]) { case 'a': /* "allow" */ case 'p': /* "prefer" */ /* * warn user that an SSL connection will never be negotiated * since SSL was not compiled in? */ break; case 'r': /* "require" */ case 'v': /* "verify-ca" or "verify-full" */ conn->status = CONNECTION_BAD; printfPQExpBuffer(&conn->errorMessage, libpq_gettext("sslmode value \"%s\" invalid when SSL support is not compiled in\n"), conn->sslmode); return false; } #endif } else conn->sslmode = strdup(DefaultSSLMode); /* * Resolve special "auto" client_encoding from the locale */ if (conn->client_encoding_initial && strcmp(conn->client_encoding_initial, "auto") == 0) { free(conn->client_encoding_initial); conn->client_encoding_initial = strdup(pg_encoding_to_char(pg_get_encoding_from_locale(NULL, true))); } /* * Only if we get this far is it appropriate to try to connect. (We need a * state flag, rather than just the boolean result of this function, in * case someone tries to PQreset() the PGconn.) */ conn->options_valid = true; return true; }
static bool conninfo_add_defaults | ( | PQconninfoOption * | options, | |
PQExpBuffer | errorMessage | |||
) | [static] |
Definition at line 4419 of file fe-connect.c.
References _PQconninfoOption::compiled, _PQconninfoOption::envvar, _PQconninfoOption::keyword, libpq_gettext, NULL, parseServiceInfo(), pg_fe_getauthname(), printfPQExpBuffer(), and _PQconninfoOption::val.
Referenced by conninfo_array_parse(), conninfo_parse(), conninfo_uri_parse(), and PQconndefaults().
{ PQconninfoOption *option; char *tmp; /* * If there's a service spec, use it to obtain any not-explicitly-given * parameters. */ if (parseServiceInfo(options, errorMessage) != 0) return false; /* * Get the fallback resources for parameters not specified in the conninfo * string nor the service. */ for (option = options; option->keyword != NULL; option++) { if (option->val != NULL) continue; /* Value was in conninfo or service */ /* * Try to get the environment variable fallback */ if (option->envvar != NULL) { if ((tmp = getenv(option->envvar)) != NULL) { option->val = strdup(tmp); if (!option->val) { printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n")); return false; } continue; } } /* * No environment variable specified or the variable isn't set - try * compiled-in default */ if (option->compiled != NULL) { option->val = strdup(option->compiled); if (!option->val) { printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n")); return false; } continue; } /* * Special handling for "user" option */ if (strcmp(option->keyword, "user") == 0) { option->val = pg_fe_getauthname(errorMessage); continue; } } return true; }
static PQconninfoOption * conninfo_array_parse | ( | const char *const * | keywords, | |
const char *const * | values, | |||
PQExpBuffer | errorMessage, | |||
bool | use_defaults, | |||
int | expand_dbname | |||
) | [static] |
Definition at line 4271 of file fe-connect.c.
References conninfo_add_defaults(), conninfo_init(), free, _PQconninfoOption::keyword, libpq_gettext, NULL, parse_connection_string(), PQconninfoFree(), printfPQExpBuffer(), recognized_connection_string(), val, and _PQconninfoOption::val.
Referenced by PQconnectStartParams().
{ PQconninfoOption *options; PQconninfoOption *dbname_options = NULL; PQconninfoOption *option; int i = 0; /* * If expand_dbname is non-zero, check keyword "dbname" to see if val is * actually a recognized connection string. */ while (expand_dbname && keywords[i]) { const char *pname = keywords[i]; const char *pvalue = values[i]; /* first find "dbname" if any */ if (strcmp(pname, "dbname") == 0 && pvalue) { /* * If value is a connection string, parse it, but do not use * defaults here -- those get picked up later. We only want to * override for those parameters actually passed. */ if (recognized_connection_string(pvalue)) { dbname_options = parse_connection_string(pvalue, errorMessage, false); if (dbname_options == NULL) return NULL; } break; } ++i; } /* Make a working copy of PQconninfoOptions */ options = conninfo_init(errorMessage); if (options == NULL) { PQconninfoFree(dbname_options); return NULL; } /* Parse the keywords/values arrays */ i = 0; while (keywords[i]) { const char *pname = keywords[i]; const char *pvalue = values[i]; if (pvalue != NULL) { /* Search for the param record */ for (option = options; option->keyword != NULL; option++) { if (strcmp(option->keyword, pname) == 0) break; } /* Check for invalid connection option */ if (option->keyword == NULL) { printfPQExpBuffer(errorMessage, libpq_gettext("invalid connection option \"%s\"\n"), pname); PQconninfoFree(options); PQconninfoFree(dbname_options); return NULL; } /* * If we are on the dbname parameter, and we have a parsed * connection string, copy those parameters across, overriding any * existing previous settings. */ if (strcmp(pname, "dbname") == 0 && dbname_options) { PQconninfoOption *str_option; for (str_option = dbname_options; str_option->keyword != NULL; str_option++) { if (str_option->val != NULL) { int k; for (k = 0; options[k].keyword; k++) { if (strcmp(options[k].keyword, str_option->keyword) == 0) { if (options[k].val) free(options[k].val); options[k].val = strdup(str_option->val); break; } } } } } else { /* * Store the value, overriding previous settings */ if (option->val) free(option->val); option->val = strdup(pvalue); if (!option->val) { printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n")); PQconninfoFree(options); PQconninfoFree(dbname_options); return NULL; } } } ++i; } PQconninfoFree(dbname_options); /* * Add in defaults if the caller wants that. */ if (use_defaults) { if (!conninfo_add_defaults(options, errorMessage)) { PQconninfoFree(options); return NULL; } } return options; }
static PQconninfoOption * conninfo_find | ( | PQconninfoOption * | connOptions, | |
const char * | keyword | |||
) | [static] |
Definition at line 5080 of file fe-connect.c.
References _PQconninfoOption::keyword.
Referenced by conninfo_getval(), and conninfo_storeval().
{ PQconninfoOption *option; for (option = connOptions; option->keyword != NULL; option++) { if (strcmp(option->keyword, keyword) == 0) return option; } return NULL; }
static const char * conninfo_getval | ( | PQconninfoOption * | connOptions, | |
const char * | keyword | |||
) | [static] |
Definition at line 4988 of file fe-connect.c.
References conninfo_find(), and _PQconninfoOption::val.
Referenced by fillPGconn(), and parseServiceInfo().
{ PQconninfoOption *option; option = conninfo_find(connOptions, keyword); return option ? option->val : NULL; }
static PQconninfoOption * conninfo_init | ( | PQExpBuffer | errorMessage | ) | [static] |
Definition at line 4008 of file fe-connect.c.
References _internalPQconninfoOption::keyword, libpq_gettext, malloc, MemSet, NULL, and printfPQExpBuffer().
Referenced by conninfo_array_parse(), conninfo_parse(), conninfo_uri_parse(), PQconndefaults(), and PQconninfo().
{ PQconninfoOption *options; PQconninfoOption *opt_dest; const internalPQconninfoOption *cur_opt; /* * Get enough memory for all options in PQconninfoOptions, even if some * end up being filtered out. */ options = (PQconninfoOption *) malloc(sizeof(PQconninfoOption) * sizeof(PQconninfoOptions) / sizeof(PQconninfoOptions[0])); if (options == NULL) { printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n")); return NULL; } opt_dest = options; for (cur_opt = PQconninfoOptions; cur_opt->keyword; cur_opt++) { /* Only copy the public part of the struct, not the full internal */ memcpy(opt_dest, cur_opt, sizeof(PQconninfoOption)); opt_dest++; } MemSet(opt_dest, 0, sizeof(PQconninfoOption)); return options; }
static PQconninfoOption * conninfo_parse | ( | const char * | conninfo, | |
PQExpBuffer | errorMessage, | |||
bool | use_defaults | |||
) | [static] |
Definition at line 4098 of file fe-connect.c.
References buf, conninfo_add_defaults(), conninfo_init(), conninfo_storeval(), free, libpq_gettext, NULL, PQconninfoFree(), and printfPQExpBuffer().
Referenced by parse_connection_string().
{ char *pname; char *pval; char *buf; char *cp; char *cp2; PQconninfoOption *options; /* Make a working copy of PQconninfoOptions */ options = conninfo_init(errorMessage); if (options == NULL) return NULL; /* Need a modifiable copy of the input string */ if ((buf = strdup(conninfo)) == NULL) { printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n")); PQconninfoFree(options); return NULL; } cp = buf; while (*cp) { /* Skip blanks before the parameter name */ if (isspace((unsigned char) *cp)) { cp++; continue; } /* Get the parameter name */ pname = cp; while (*cp) { if (*cp == '=') break; if (isspace((unsigned char) *cp)) { *cp++ = '\0'; while (*cp) { if (!isspace((unsigned char) *cp)) break; cp++; } break; } cp++; } /* Check that there is a following '=' */ if (*cp != '=') { printfPQExpBuffer(errorMessage, libpq_gettext("missing \"=\" after \"%s\" in connection info string\n"), pname); PQconninfoFree(options); free(buf); return NULL; } *cp++ = '\0'; /* Skip blanks after the '=' */ while (*cp) { if (!isspace((unsigned char) *cp)) break; cp++; } /* Get the parameter value */ pval = cp; if (*cp != '\'') { cp2 = pval; while (*cp) { if (isspace((unsigned char) *cp)) { *cp++ = '\0'; break; } if (*cp == '\\') { cp++; if (*cp != '\0') *cp2++ = *cp++; } else *cp2++ = *cp++; } *cp2 = '\0'; } else { cp2 = pval; cp++; for (;;) { if (*cp == '\0') { printfPQExpBuffer(errorMessage, libpq_gettext("unterminated quoted string in connection info string\n")); PQconninfoFree(options); free(buf); return NULL; } if (*cp == '\\') { cp++; if (*cp != '\0') *cp2++ = *cp++; continue; } if (*cp == '\'') { *cp2 = '\0'; cp++; break; } *cp2++ = *cp++; } } /* * Now that we have the name and the value, store the record. */ if (!conninfo_storeval(options, pname, pval, errorMessage, false, false)) { PQconninfoFree(options); free(buf); return NULL; } } /* Done with the modifiable input string */ free(buf); /* * Add in defaults if the caller wants that. */ if (use_defaults) { if (!conninfo_add_defaults(options, errorMessage)) { PQconninfoFree(options); return NULL; } } return options; }
static PQconninfoOption * conninfo_storeval | ( | PQconninfoOption * | connOptions, | |
const char * | keyword, | |||
const char * | value, | |||
PQExpBuffer | errorMessage, | |||
bool | ignoreMissing, | |||
bool | uri_decode | |||
) | [static] |
Definition at line 5014 of file fe-connect.c.
References conninfo_find(), conninfo_uri_decode(), free, libpq_gettext, NULL, printfPQExpBuffer(), and _PQconninfoOption::val.
Referenced by conninfo_parse(), conninfo_uri_parse_options(), conninfo_uri_parse_params(), and PQconninfo().
{ PQconninfoOption *option; char *value_copy; /* * For backwards compatibility, requiressl=1 gets translated to * sslmode=require, and requiressl=0 gets translated to sslmode=prefer * (which is the default for sslmode). */ if (strcmp(keyword, "requiressl") == 0) { keyword = "sslmode"; if (value[0] == '1') value = "require"; else value = "prefer"; } option = conninfo_find(connOptions, keyword); if (option == NULL) { if (!ignoreMissing) printfPQExpBuffer(errorMessage, libpq_gettext("invalid connection option \"%s\"\n"), keyword); return NULL; } if (uri_decode) { value_copy = conninfo_uri_decode(value, errorMessage); if (value_copy == NULL) /* conninfo_uri_decode already set an error message */ return NULL; } else { value_copy = strdup(value); if (value_copy == NULL) { printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n")); return NULL; } } if (option->val) free(option->val); option->val = value_copy; return option; }
static char * conninfo_uri_decode | ( | const char * | str, | |
PQExpBuffer | errorMessage | |||
) | [static] |
Definition at line 4901 of file fe-connect.c.
References buf, free, get_hexdigit(), libpq_gettext, malloc, NULL, and printfPQExpBuffer().
Referenced by conninfo_storeval(), and conninfo_uri_parse_params().
{ char *buf = malloc(strlen(str) + 1); char *p = buf; const char *q = str; if (buf == NULL) { printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n")); return NULL; } for (;;) { if (*q != '%') { /* copy and check for NUL terminator */ if (!(*(p++) = *(q++))) break; } else { int hi; int lo; int c; ++q; /* skip the percent sign itself */ /* * Possible EOL will be caught by the first call to * get_hexdigit(), so we never dereference an invalid q pointer. */ if (!(get_hexdigit(*q++, &hi) && get_hexdigit(*q++, &lo))) { printfPQExpBuffer(errorMessage, libpq_gettext("invalid percent-encoded token: \"%s\"\n"), str); free(buf); return NULL; } c = (hi << 4) | lo; if (c == 0) { printfPQExpBuffer(errorMessage, libpq_gettext("forbidden value %%00 in percent-encoded value: \"%s\"\n"), str); free(buf); return NULL; } *(p++) = c; } } return buf; }
static PQconninfoOption * conninfo_uri_parse | ( | const char * | uri, | |
PQExpBuffer | errorMessage, | |||
bool | use_defaults | |||
) | [static] |
Definition at line 4493 of file fe-connect.c.
References conninfo_add_defaults(), conninfo_init(), conninfo_uri_parse_options(), NULL, and PQconninfoFree().
Referenced by parse_connection_string().
{ PQconninfoOption *options; /* Make a working copy of PQconninfoOptions */ options = conninfo_init(errorMessage); if (options == NULL) return NULL; if (!conninfo_uri_parse_options(options, uri, errorMessage)) { PQconninfoFree(options); return NULL; } /* * Add in defaults if the caller wants that. */ if (use_defaults) { if (!conninfo_add_defaults(options, errorMessage)) { PQconninfoFree(options); return NULL; } } return options; }
static bool conninfo_uri_parse_options | ( | PQconninfoOption * | options, | |
const char * | uri, | |||
PQExpBuffer | errorMessage | |||
) | [static] |
Definition at line 4543 of file fe-connect.c.
References buf, cleanup(), conninfo_storeval(), conninfo_uri_parse_params(), free, libpq_gettext, NULL, printfPQExpBuffer(), uri_prefix_length(), and user.
Referenced by conninfo_uri_parse().
{ int prefix_len; char *p; char *buf = strdup(uri); /* need a modifiable copy of the input * URI */ char *start = buf; char prevchar = '\0'; char *user = NULL; char *host = NULL; bool retval = false; if (buf == NULL) { printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n")); return false; } /* Skip the URI prefix */ prefix_len = uri_prefix_length(uri); if (prefix_len == 0) { /* Should never happen */ printfPQExpBuffer(errorMessage, libpq_gettext("invalid URI propagated to internal parser routine: \"%s\"\n"), uri); goto cleanup; } start += prefix_len; p = start; /* Look ahead for possible user credentials designator */ while (*p && *p != '@' && *p != '/') ++p; if (*p == '@') { /* * Found username/password designator, so URI should be of the form * "scheme://user[:password]@[netloc]". */ user = start; p = user; while (*p != ':' && *p != '@') ++p; /* Save last char and cut off at end of user name */ prevchar = *p; *p = '\0'; if (*user && !conninfo_storeval(options, "user", user, errorMessage, false, true)) goto cleanup; if (prevchar == ':') { const char *password = p + 1; while (*p != '@') ++p; *p = '\0'; if (*password && !conninfo_storeval(options, "password", password, errorMessage, false, true)) goto cleanup; } /* Advance past end of parsed user name or password token */ ++p; } else { /* * No username/password designator found. Reset to start of URI. */ p = start; } /* * "p" has been incremented past optional URI credential information at * this point and now points at the "netloc" part of the URI. * * Look for IPv6 address. */ if (*p == '[') { host = ++p; while (*p && *p != ']') ++p; if (!*p) { printfPQExpBuffer(errorMessage, libpq_gettext("end of string reached when looking for matching \"]\" in IPv6 host address in URI: \"%s\"\n"), uri); goto cleanup; } if (p == host) { printfPQExpBuffer(errorMessage, libpq_gettext("IPv6 host address may not be empty in URI: \"%s\"\n"), uri); goto cleanup; } /* Cut off the bracket and advance */ *(p++) = '\0'; /* * The address may be followed by a port specifier or a slash or a * query. */ if (*p && *p != ':' && *p != '/' && *p != '?') { printfPQExpBuffer(errorMessage, libpq_gettext("unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): \"%s\"\n"), *p, (int) (p - buf + 1), uri); goto cleanup; } } else { /* not an IPv6 address: DNS-named or IPv4 netloc */ host = p; /* * Look for port specifier (colon) or end of host specifier (slash), * or query (question mark). */ while (*p && *p != ':' && *p != '/' && *p != '?') ++p; } /* Save the hostname terminator before we null it */ prevchar = *p; *p = '\0'; if (*host && !conninfo_storeval(options, "host", host, errorMessage, false, true)) goto cleanup; if (prevchar == ':') { const char *port = ++p; /* advance past host terminator */ while (*p && *p != '/' && *p != '?') ++p; prevchar = *p; *p = '\0'; if (*port && !conninfo_storeval(options, "port", port, errorMessage, false, true)) goto cleanup; } if (prevchar && prevchar != '?') { const char *dbname = ++p; /* advance past host terminator */ /* Look for query parameters */ while (*p && *p != '?') ++p; prevchar = *p; *p = '\0'; /* * Avoid setting dbname to an empty string, as it forces the default * value (username) and ignores $PGDATABASE, as opposed to not setting * it at all. */ if (*dbname && !conninfo_storeval(options, "dbname", dbname, errorMessage, false, true)) goto cleanup; } if (prevchar) { ++p; /* advance past terminator */ if (!conninfo_uri_parse_params(p, options, errorMessage)) goto cleanup; } /* everything parsed okay */ retval = true; cleanup: free(buf); return retval; }
static bool conninfo_uri_parse_params | ( | char * | params, | |
PQconninfoOption * | connOptions, | |||
PQExpBuffer | errorMessage | |||
) | [static] |
Definition at line 4752 of file fe-connect.c.
References conninfo_storeval(), conninfo_uri_decode(), free, PQExpBufferData::len, libpq_gettext, NULL, printfPQExpBuffer(), and value.
Referenced by conninfo_uri_parse_options().
{ while (*params) { char *keyword = params; char *value = NULL; char *p = params; bool malloced = false; /* * Scan the params string for '=' and '&', marking the end of keyword * and value respectively. */ for (;;) { if (*p == '=') { /* Was there '=' already? */ if (value != NULL) { printfPQExpBuffer(errorMessage, libpq_gettext("extra key/value separator \"=\" in URI query parameter: \"%s\"\n"), params); return false; } /* Cut off keyword, advance to value */ *p = '\0'; value = ++p; } else if (*p == '&' || *p == '\0') { char prevchar; /* Cut off value, remember old value */ prevchar = *p; *p = '\0'; /* Was there '=' at all? */ if (value == NULL) { printfPQExpBuffer(errorMessage, libpq_gettext("missing key/value separator \"=\" in URI query parameter: \"%s\"\n"), params); return false; } /* * If not at the end, advance; now pointing to start of the * next parameter, if any. */ if (prevchar != '\0') ++p; break; } /* Advance, NUL is checked in the 'if' above */ ++p; } keyword = conninfo_uri_decode(keyword, errorMessage); if (keyword == NULL) { /* conninfo_uri_decode already set an error message */ return false; } value = conninfo_uri_decode(value, errorMessage); if (value == NULL) { /* conninfo_uri_decode already set an error message */ free(keyword); return false; } malloced = true; /* * Special keyword handling for improved JDBC compatibility. */ if (strcmp(keyword, "ssl") == 0 && strcmp(value, "true") == 0) { free(keyword); free(value); malloced = false; keyword = "sslmode"; value = "require"; } /* * Store the value if the corresponding option exists; ignore * otherwise. At this point both keyword and value are not * URI-encoded. */ if (!conninfo_storeval(connOptions, keyword, value, errorMessage, true, false)) { /* * Check if there was a hard error when decoding or storing the * option. */ if (errorMessage->len != 0) { if (malloced) { free(keyword); free(value); } return false; } printfPQExpBuffer(errorMessage, libpq_gettext( "invalid URI query parameter: \"%s\"\n"), keyword); if (malloced) { free(keyword); free(value); } return false; } if (malloced) { free(keyword); free(value); } /* Proceed to next key=value pair */ params = p; } return true; }
static void default_threadlock | ( | int | acquire | ) | [static] |
Definition at line 5700 of file fe-connect.c.
References NULL, pthread_mutex_init(), pthread_mutex_lock(), and pthread_mutex_unlock().
{ #ifdef ENABLE_THREAD_SAFETY #ifndef WIN32 static pthread_mutex_t singlethread_lock = PTHREAD_MUTEX_INITIALIZER; #else static pthread_mutex_t singlethread_lock = NULL; static long mutex_initlock = 0; if (singlethread_lock == NULL) { while (InterlockedExchange(&mutex_initlock, 1) == 1) /* loop, another thread own the lock */ ; if (singlethread_lock == NULL) { if (pthread_mutex_init(&singlethread_lock, NULL)) PGTHREAD_ERROR("failed to initialize mutex"); } InterlockedExchange(&mutex_initlock, 0); } #endif if (acquire) { if (pthread_mutex_lock(&singlethread_lock)) PGTHREAD_ERROR("failed to lock mutex"); } else { if (pthread_mutex_unlock(&singlethread_lock)) PGTHREAD_ERROR("failed to unlock mutex"); } #endif }
static void defaultNoticeProcessor | ( | void * | arg, | |
const char * | message | |||
) | [static] |
Definition at line 5456 of file fe-connect.c.
{ (void) arg; /* not used */ /* Note: we expect the supplied string to end with a newline already. */ fprintf(stderr, "%s", message); }
static void defaultNoticeReceiver | ( | void * | arg, | |
const PGresult * | res | |||
) | [static] |
Definition at line 5441 of file fe-connect.c.
References pg_result::noticeHooks, PGNoticeHooks::noticeProc, PGNoticeHooks::noticeProcArg, NULL, and PQresultErrorMessage().
{ (void) arg; /* not used */ if (res->noticeHooks.noticeProc != NULL) (*res->noticeHooks.noticeProc) (res->noticeHooks.noticeProcArg, PQresultErrorMessage(res)); }
static void dot_pg_pass_warning | ( | PGconn * | conn | ) | [static] |
Definition at line 5642 of file fe-connect.c.
References appendPQExpBuffer(), pg_conn::dot_pgpass_used, ERRCODE_INVALID_PASSWORD, pg_conn::errorMessage, getPgPassFilename(), libpq_gettext, pg_conn::password_needed, PG_DIAG_SQLSTATE, PQresultErrorField(), and pg_conn::result.
Referenced by PQconnectPoll().
{ /* If it was 'invalid authorization', add .pgpass mention */ /* only works with >= 9.0 servers */ if (conn->dot_pgpass_used && conn->password_needed && conn->result && strcmp(PQresultErrorField(conn->result, PG_DIAG_SQLSTATE), ERRCODE_INVALID_PASSWORD) == 0) { char pgpassfile[MAXPGPATH]; if (!getPgPassFilename(pgpassfile)) return; appendPQExpBuffer(&conn->errorMessage, libpq_gettext("password retrieved from file \"%s\"\n"), pgpassfile); } }
static void fillPGconn | ( | PGconn * | conn, | |
PQconninfoOption * | connOptions | |||
) | [static] |
Definition at line 669 of file fe-connect.c.
References conninfo_getval(), _internalPQconninfoOption::connofs, free, and _internalPQconninfoOption::keyword.
Referenced by connectOptions1(), and PQconnectStartParams().
{ const internalPQconninfoOption *option; /* * Move option values into conn structure * * Don't put anything cute here --- intelligence should be in * connectOptions2 ... * * XXX: probably worth checking strdup() return value here... */ for (option = PQconninfoOptions; option->keyword; option++) { const char *tmp = conninfo_getval(connOptions, option->keyword); if (tmp && option->connofs >= 0) { char **connmember = (char **) ((char *) conn + option->connofs); if (*connmember) free(*connmember); *connmember = tmp ? strdup(tmp) : NULL; } } }
static void freePGconn | ( | PGconn * | conn | ) | [static] |
Definition at line 2757 of file fe-connect.c.
References pg_conn::appname, pg_conn::client_encoding_initial, PGEventConnDestroy::conn, pg_conn::connect_timeout, pg_conn::dbName, pg_conn::errorMessage, pg_conn::events, pg_conn::fbappname, free, i, pg_conn::inBuffer, pg_conn::keepalives, pg_conn::keepalives_count, pg_conn::keepalives_idle, pg_conn::keepalives_interval, pg_conn::last_query, PGEvent::name, pg_conn::nEvents, pg_conn::outBuffer, PGEvent::passThrough, PGEVT_CONNDESTROY, pg_conn::pghost, pg_conn::pghostaddr, pg_conn::pgoptions, pg_conn::pgpass, pg_conn::pgport, pg_conn::pgtty, pg_conn::pgunixsocket, pg_conn::pguser, PGEvent::proc, pg_conn::replication, pg_conn::requirepeer, pg_conn::rowBuf, pg_conn::sslcert, pg_conn::sslcompression, pg_conn::sslcrl, pg_conn::sslkey, pg_conn::sslmode, pg_conn::sslrootcert, termPQExpBuffer(), and pg_conn::workBuffer.
Referenced by makeEmptyPGconn(), and PQfinish().
{ int i; /* let any event procs clean up their state data */ for (i = 0; i < conn->nEvents; i++) { PGEventConnDestroy evt; evt.conn = conn; (void) conn->events[i].proc(PGEVT_CONNDESTROY, &evt, conn->events[i].passThrough); free(conn->events[i].name); } if (conn->client_encoding_initial) free(conn->client_encoding_initial); if (conn->events) free(conn->events); if (conn->pghost) free(conn->pghost); if (conn->pghostaddr) free(conn->pghostaddr); if (conn->pgport) free(conn->pgport); if (conn->pgunixsocket) free(conn->pgunixsocket); if (conn->pgtty) free(conn->pgtty); if (conn->connect_timeout) free(conn->connect_timeout); if (conn->pgoptions) free(conn->pgoptions); if (conn->appname) free(conn->appname); if (conn->fbappname) free(conn->fbappname); if (conn->dbName) free(conn->dbName); if (conn->replication) free(conn->replication); if (conn->pguser) free(conn->pguser); if (conn->pgpass) free(conn->pgpass); if (conn->keepalives) free(conn->keepalives); if (conn->keepalives_idle) free(conn->keepalives_idle); if (conn->keepalives_interval) free(conn->keepalives_interval); if (conn->keepalives_count) free(conn->keepalives_count); if (conn->sslmode) free(conn->sslmode); if (conn->sslcert) free(conn->sslcert); if (conn->sslkey) free(conn->sslkey); if (conn->sslrootcert) free(conn->sslrootcert); if (conn->sslcrl) free(conn->sslcrl); if (conn->sslcompression) free(conn->sslcompression); if (conn->requirepeer) free(conn->requirepeer); #if defined(KRB5) || defined(ENABLE_GSS) || defined(ENABLE_SSPI) if (conn->krbsrvname) free(conn->krbsrvname); #endif #if defined(ENABLE_GSS) && defined(ENABLE_SSPI) if (conn->gsslib) free(conn->gsslib); #endif /* Note that conn->Pfdebug is not ours to close or free */ if (conn->last_query) free(conn->last_query); if (conn->inBuffer) free(conn->inBuffer); if (conn->outBuffer) free(conn->outBuffer); if (conn->rowBuf) free(conn->rowBuf); termPQExpBuffer(&conn->errorMessage); termPQExpBuffer(&conn->workBuffer); free(conn); #ifdef WIN32 WSACleanup(); #endif }
static bool get_hexdigit | ( | char | digit, | |
int * | value | |||
) | [static] |
Definition at line 4967 of file fe-connect.c.
Referenced by conninfo_uri_decode().
static bool getPgPassFilename | ( | char * | pgpassfile | ) | [static] |
Definition at line 5618 of file fe-connect.c.
References MAXPGPATH, NULL, PGPASSFILE, pqGetHomeDirectory(), snprintf(), and strlcpy().
Referenced by dot_pg_pass_warning(), and PasswordFromFile().
{ char *passfile_env; if ((passfile_env = getenv("PGPASSFILE")) != NULL) /* use the literal path from the environment, if set */ strlcpy(pgpassfile, passfile_env, MAXPGPATH); else { char homedir[MAXPGPATH]; if (!pqGetHomeDirectory(homedir, sizeof(homedir))) return false; snprintf(pgpassfile, MAXPGPATH, "%s/%s", homedir, PGPASSFILE); } return true; }
static int internal_cancel | ( | SockAddr * | raddr, | |
int | be_pid, | |||
int | be_key, | |||
char * | errbuf, | |||
int | errbufsize | |||
) | [static] |
Definition at line 3134 of file fe-connect.c.
References SockAddr::addr, CANCEL_REQUEST_CODE, closesocket, connect, EINTR, recv, SockAddr::salen, send, SOCK_ERRNO, SOCK_ERRNO_SET, SOCK_STRERROR, socket, and strlcpy().
Referenced by PQcancel(), and PQrequestCancel().
{ int save_errno = SOCK_ERRNO; int tmpsock = -1; char sebuf[256]; int maxlen; struct { uint32 packetlen; CancelRequestPacket cp; } crp; /* * We need to open a temporary connection to the postmaster. Do this with * only kernel calls. */ if ((tmpsock = socket(raddr->addr.ss_family, SOCK_STREAM, 0)) < 0) { strlcpy(errbuf, "PQcancel() -- socket() failed: ", errbufsize); goto cancel_errReturn; } retry3: if (connect(tmpsock, (struct sockaddr *) & raddr->addr, raddr->salen) < 0) { if (SOCK_ERRNO == EINTR) /* Interrupted system call - we'll just try again */ goto retry3; strlcpy(errbuf, "PQcancel() -- connect() failed: ", errbufsize); goto cancel_errReturn; } /* * We needn't set nonblocking I/O or NODELAY options here. */ /* Create and send the cancel request packet. */ crp.packetlen = htonl((uint32) sizeof(crp)); crp.cp.cancelRequestCode = (MsgType) htonl(CANCEL_REQUEST_CODE); crp.cp.backendPID = htonl(be_pid); crp.cp.cancelAuthCode = htonl(be_key); retry4: if (send(tmpsock, (char *) &crp, sizeof(crp), 0) != (int) sizeof(crp)) { if (SOCK_ERRNO == EINTR) /* Interrupted system call - we'll just try again */ goto retry4; strlcpy(errbuf, "PQcancel() -- send() failed: ", errbufsize); goto cancel_errReturn; } /* * Wait for the postmaster to close the connection, which indicates that * it's processed the request. Without this delay, we might issue another * command only to find that our cancel zaps that command instead of the * one we thought we were canceling. Note we don't actually expect this * read to obtain any data, we are just waiting for EOF to be signaled. */ retry5: if (recv(tmpsock, (char *) &crp, 1, 0) < 0) { if (SOCK_ERRNO == EINTR) /* Interrupted system call - we'll just try again */ goto retry5; /* we ignore other error conditions */ } /* All done */ closesocket(tmpsock); SOCK_ERRNO_SET(save_errno); return TRUE; cancel_errReturn: /* * Make sure we don't overflow the error buffer. Leave space for the \n at * the end, and for the terminating zero. */ maxlen = errbufsize - strlen(errbuf) - 2; if (maxlen >= 0) { strncat(errbuf, SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)), maxlen); strcat(errbuf, "\n"); } if (tmpsock >= 0) closesocket(tmpsock); SOCK_ERRNO_SET(save_errno); return FALSE; }
Definition at line 2598 of file fe-connect.c.
References pg_conn::auth_req_received, connectDBComplete(), CONNECTION_BAD, ERRCODE_CANNOT_CONNECT_NOW, pg_conn::last_sqlstate, pg_conn::options_valid, PQPING_NO_RESPONSE, PQPING_REJECT, and pg_conn::status.
Referenced by PQping(), and PQpingParams().
{ /* Say "no attempt" if we never got to PQconnectPoll */ if (!conn || !conn->options_valid) return PQPING_NO_ATTEMPT; /* Attempt to complete the connection */ if (conn->status != CONNECTION_BAD) (void) connectDBComplete(conn); /* Definitely OK if we succeeded */ if (conn->status != CONNECTION_BAD) return PQPING_OK; /* * Here begins the interesting part of "ping": determine the cause of the * failure in sufficient detail to decide what to return. We do not want * to report that the server is not up just because we didn't have a valid * password, for example. In fact, any sort of authentication request * implies the server is up. (We need this check since the libpq side of * things might have pulled the plug on the connection before getting an * error as such from the postmaster.) */ if (conn->auth_req_received) return PQPING_OK; /* * If we failed to get any ERROR response from the postmaster, report * PQPING_NO_RESPONSE. This result could be somewhat misleading for a * pre-7.4 server, since it won't send back a SQLSTATE, but those are long * out of support. Another corner case where the server could return a * failure without a SQLSTATE is fork failure, but NO_RESPONSE isn't * totally unreasonable for that anyway. We expect that every other * failure case in a modern server will produce a report with a SQLSTATE. * * NOTE: whenever we get around to making libpq generate SQLSTATEs for * client-side errors, we should either not store those into * last_sqlstate, or add an extra flag so we can tell client-side errors * apart from server-side ones. */ if (strlen(conn->last_sqlstate) != 5) return PQPING_NO_RESPONSE; /* * Report PQPING_REJECT if server says it's not accepting connections. (We * distinguish this case mainly for the convenience of pg_ctl.) */ if (strcmp(conn->last_sqlstate, ERRCODE_CANNOT_CONNECT_NOW) == 0) return PQPING_REJECT; /* * Any other SQLSTATE can be taken to indicate that the server is up. * Presumably it didn't like our username, password, or database name; or * perhaps it had some transient failure, but that should not be taken as * meaning "it's down". */ return PQPING_OK; }
static PGconn * makeEmptyPGconn | ( | void | ) | [static] |
Definition at line 2663 of file fe-connect.c.
References pg_conn::asyncStatus, pg_conn::auth_req_received, pg_conn::client_encoding, pg_conn::dot_pgpass_used, pg_conn::errorMessage, freePGconn(), pg_conn::inBuffer, pg_conn::inBufSize, initPQExpBuffer(), malloc, MemSet, pg_conn::nonblocking, pg_conn::noticeHooks, PGNoticeHooks::noticeProc, PGNoticeHooks::noticeRec, NULL, pg_conn::options_valid, pg_conn::outBuffer, pg_conn::outBufSize, pg_conn::password_needed, PQExpBufferBroken, pg_conn::rowBuf, pg_conn::rowBufLen, pg_conn::setenv_state, pg_conn::sock, pg_conn::status, pg_conn::std_strings, pg_conn::verbosity, pg_conn::workBuffer, and pg_conn::xactStatus.
Referenced by PQconnectStart(), PQconnectStartParams(), and PQsetdbLogin().
{ PGconn *conn; #ifdef WIN32 /* * Make sure socket support is up and running. */ WSADATA wsaData; if (WSAStartup(MAKEWORD(1, 1), &wsaData)) return NULL; WSASetLastError(0); #endif conn = (PGconn *) malloc(sizeof(PGconn)); if (conn == NULL) { #ifdef WIN32 WSACleanup(); #endif return conn; } /* Zero all pointers and booleans */ MemSet(conn, 0, sizeof(PGconn)); /* install default notice hooks */ conn->noticeHooks.noticeRec = defaultNoticeReceiver; conn->noticeHooks.noticeProc = defaultNoticeProcessor; conn->status = CONNECTION_BAD; conn->asyncStatus = PGASYNC_IDLE; conn->xactStatus = PQTRANS_IDLE; conn->options_valid = false; conn->nonblocking = false; conn->setenv_state = SETENV_STATE_IDLE; conn->client_encoding = PG_SQL_ASCII; conn->std_strings = false; /* unless server says differently */ conn->verbosity = PQERRORS_DEFAULT; conn->sock = -1; conn->auth_req_received = false; conn->password_needed = false; conn->dot_pgpass_used = false; #ifdef USE_SSL conn->allow_ssl_try = true; conn->wait_ssl_try = false; #endif /* * We try to send at least 8K at a time, which is the usual size of pipe * buffers on Unix systems. That way, when we are sending a large amount * of data, we avoid incurring extra kernel context swaps for partial * bufferloads. The output buffer is initially made 16K in size, and we * try to dump it after accumulating 8K. * * With the same goal of minimizing context swaps, the input buffer will * be enlarged anytime it has less than 8K free, so we initially allocate * twice that. */ conn->inBufSize = 16 * 1024; conn->inBuffer = (char *) malloc(conn->inBufSize); conn->outBufSize = 16 * 1024; conn->outBuffer = (char *) malloc(conn->outBufSize); conn->rowBufLen = 32; conn->rowBuf = (PGdataValue *) malloc(conn->rowBufLen * sizeof(PGdataValue)); initPQExpBuffer(&conn->errorMessage); initPQExpBuffer(&conn->workBuffer); if (conn->inBuffer == NULL || conn->outBuffer == NULL || conn->rowBuf == NULL || PQExpBufferBroken(&conn->errorMessage) || PQExpBufferBroken(&conn->workBuffer)) { /* out of memory already :-( */ freePGconn(conn); conn = NULL; } return conn; }
static PQconninfoOption * parse_connection_string | ( | const char * | conninfo, | |
PQExpBuffer | errorMessage, | |||
bool | use_defaults | |||
) | [static] |
Definition at line 4048 of file fe-connect.c.
References conninfo_parse(), conninfo_uri_parse(), and uri_prefix_length().
Referenced by connectOptions1(), conninfo_array_parse(), and PQconninfoParse().
{ /* Parse as URI if connection string matches URI prefix */ if (uri_prefix_length(connstr) != 0) return conninfo_uri_parse(connstr, errorMessage, use_defaults); /* Parse as default otherwise */ return conninfo_parse(connstr, errorMessage, use_defaults); }
static int parseServiceFile | ( | const char * | serviceFile, | |
const char * | service, | |||
PQconninfoOption * | options, | |||
PQExpBuffer | errorMessage, | |||
bool * | group_found | |||
) | [static] |
Definition at line 3828 of file fe-connect.c.
References buf, _PQconninfoOption::keyword, libpq_gettext, NULL, printfPQExpBuffer(), _PQconninfoOption::val, and val.
Referenced by parseServiceInfo().
{ int linenr = 0, i; FILE *f; char buf[MAXBUFSIZE], *line; f = fopen(serviceFile, "r"); if (f == NULL) { printfPQExpBuffer(errorMessage, libpq_gettext("service file \"%s\" not found\n"), serviceFile); return 1; } while ((line = fgets(buf, sizeof(buf), f)) != NULL) { linenr++; if (strlen(line) >= sizeof(buf) - 1) { fclose(f); printfPQExpBuffer(errorMessage, libpq_gettext("line %d too long in service file \"%s\"\n"), linenr, serviceFile); return 2; } /* ignore EOL at end of line */ if (strlen(line) && line[strlen(line) - 1] == '\n') line[strlen(line) - 1] = 0; /* ignore leading blanks */ while (*line && isspace((unsigned char) line[0])) line++; /* ignore comments and empty lines */ if (strlen(line) == 0 || line[0] == '#') continue; /* Check for right groupname */ if (line[0] == '[') { if (*group_found) { /* group info already read */ fclose(f); return 0; } if (strncmp(line + 1, service, strlen(service)) == 0 && line[strlen(service) + 1] == ']') *group_found = true; else *group_found = false; } else { if (*group_found) { /* * Finally, we are in the right group and can parse the line */ char *key, *val; bool found_keyword; #ifdef USE_LDAP if (strncmp(line, "ldap", 4) == 0) { int rc = ldapServiceLookup(line, options, errorMessage); /* if rc = 2, go on reading for fallback */ switch (rc) { case 0: fclose(f); return 0; case 1: case 3: fclose(f); return 3; case 2: continue; } } #endif key = line; val = strchr(line, '='); if (val == NULL) { printfPQExpBuffer(errorMessage, libpq_gettext("syntax error in service file \"%s\", line %d\n"), serviceFile, linenr); fclose(f); return 3; } *val++ = '\0'; /* * Set the parameter --- but don't override any previous * explicit setting. */ found_keyword = false; for (i = 0; options[i].keyword; i++) { if (strcmp(options[i].keyword, key) == 0) { if (options[i].val == NULL) options[i].val = strdup(val); found_keyword = true; break; } } if (!found_keyword) { printfPQExpBuffer(errorMessage, libpq_gettext("syntax error in service file \"%s\", line %d\n"), serviceFile, linenr); fclose(f); return 3; } } } } fclose(f); return 0; }
static int parseServiceInfo | ( | PQconninfoOption * | options, | |
PQExpBuffer | errorMessage | |||
) | [static] |
Definition at line 3759 of file fe-connect.c.
References conninfo_getval(), libpq_gettext, MAXPGPATH, NULL, parseServiceFile(), pqGetHomeDirectory(), printfPQExpBuffer(), snprintf(), and strlcpy().
Referenced by conninfo_add_defaults().
{ const char *service = conninfo_getval(options, "service"); char serviceFile[MAXPGPATH]; char *env; bool group_found = false; int status; struct stat stat_buf; /* * We have to special-case the environment variable PGSERVICE here, since * this is and should be called before inserting environment defaults for * other connection options. */ if (service == NULL) service = getenv("PGSERVICE"); if (service == NULL) return 0; if ((env = getenv("PGSERVICEFILE")) != NULL) strlcpy(serviceFile, env, sizeof(serviceFile)); else { char homedir[MAXPGPATH]; if (!pqGetHomeDirectory(homedir, sizeof(homedir))) { printfPQExpBuffer(errorMessage, libpq_gettext("could not get home directory to locate service definition file")); return 1; } snprintf(serviceFile, MAXPGPATH, "%s/%s", homedir, ".pg_service.conf"); errno = 0; if (stat(serviceFile, &stat_buf) != 0 && errno == ENOENT) goto next_file; } status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found); if (group_found || status != 0) return status; next_file: /* * This could be used by any application so we can't use the binary * location to find our config files. */ snprintf(serviceFile, MAXPGPATH, "%s/pg_service.conf", getenv("PGSYSCONFDIR") ? getenv("PGSYSCONFDIR") : SYSCONFDIR); errno = 0; if (stat(serviceFile, &stat_buf) != 0 && errno == ENOENT) goto last_file; status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found); if (status != 0) return status; last_file: if (!group_found) { printfPQExpBuffer(errorMessage, libpq_gettext("definition of service \"%s\" not found\n"), service); return 3; } return 0; }
static char * PasswordFromFile | ( | char * | hostname, | |
char * | port, | |||
char * | dbname, | |||
char * | username | |||
) | [static] |
Definition at line 5505 of file fe-connect.c.
References buf, DEFAULT_PGSOCKET_DIR, getPgPassFilename(), is_absolute_path, libpq_gettext, NULL, pwdfMatchesString(), S_IRWXG, and S_IRWXO.
Referenced by connectOptions2().
{ FILE *fp; char pgpassfile[MAXPGPATH]; struct stat stat_buf; #define LINELEN NAMEDATALEN*5 char buf[LINELEN]; if (dbname == NULL || strlen(dbname) == 0) return NULL; if (username == NULL || strlen(username) == 0) return NULL; /* 'localhost' matches pghost of '' or the default socket directory */ if (hostname == NULL) hostname = DefaultHost; else if (is_absolute_path(hostname)) /* * We should probably use canonicalize_path(), but then we have to * bring path.c into libpq, and it doesn't seem worth it. */ if (strcmp(hostname, DEFAULT_PGSOCKET_DIR) == 0) hostname = DefaultHost; if (port == NULL) port = DEF_PGPORT_STR; if (!getPgPassFilename(pgpassfile)) return NULL; /* If password file cannot be opened, ignore it. */ if (stat(pgpassfile, &stat_buf) != 0) return NULL; #ifndef WIN32 if (!S_ISREG(stat_buf.st_mode)) { fprintf(stderr, libpq_gettext("WARNING: password file \"%s\" is not a plain file\n"), pgpassfile); return NULL; } /* If password file is insecure, alert the user and ignore it. */ if (stat_buf.st_mode & (S_IRWXG | S_IRWXO)) { fprintf(stderr, libpq_gettext("WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n"), pgpassfile); return NULL; } #else /* * On Win32, the directory is protected, so we don't have to check the * file. */ #endif fp = fopen(pgpassfile, "r"); if (fp == NULL) return NULL; while (!feof(fp) && !ferror(fp)) { char *t = buf, *ret, *p1, *p2; int len; if (fgets(buf, sizeof(buf), fp) == NULL) break; len = strlen(buf); if (len == 0) continue; /* Remove trailing newline */ if (buf[len - 1] == '\n') buf[len - 1] = 0; if ((t = pwdfMatchesString(t, hostname)) == NULL || (t = pwdfMatchesString(t, port)) == NULL || (t = pwdfMatchesString(t, dbname)) == NULL || (t = pwdfMatchesString(t, username)) == NULL) continue; ret = strdup(t); fclose(fp); /* De-escape password. */ for (p1 = p2 = ret; *p1 != ':' && *p1 != '\0'; ++p1, ++p2) { if (*p1 == '\\' && p1[1] != '\0') ++p1; *p2 = *p1; } *p2 = '\0'; return ret; } fclose(fp); return NULL; #undef LINELEN }
int PQbackendPID | ( | const PGconn * | conn | ) |
Definition at line 5283 of file fe-connect.c.
References pg_conn::be_pid, CONNECTION_OK, and pg_conn::status.
{ if (!conn || conn->status != CONNECTION_OK) return 0; return conn->be_pid; }
int PQcancel | ( | PGcancel * | cancel, | |
char * | errbuf, | |||
int | errbufsize | |||
) |
Definition at line 3238 of file fe-connect.c.
References pg_cancel::be_key, pg_cancel::be_pid, internal_cancel(), pg_cancel::raddr, and strlcpy().
Referenced by dblink_cancel_query(), DisconnectDatabase(), handle_sigint(), and run_permutation().
{ if (!cancel) { strlcpy(errbuf, "PQcancel() -- no cancel object supplied", errbufsize); return FALSE; } return internal_cancel(&cancel->raddr, cancel->be_pid, cancel->be_key, errbuf, errbufsize); }
int PQclientEncoding | ( | const PGconn * | conn | ) |
Definition at line 5314 of file fe-connect.c.
References pg_conn::client_encoding, CONNECTION_OK, and pg_conn::status.
Referenced by appendStringLiteralConn(), exec_command(), main(), processSQLNamePattern(), SendQuery(), setup_connection(), and SyncVariables().
{ if (!conn || conn->status != CONNECTION_OK) return -1; return conn->client_encoding; }
PQconninfoOption* PQconndefaults | ( | void | ) |
Definition at line 865 of file fe-connect.c.
References conninfo_add_defaults(), conninfo_init(), initPQExpBuffer(), NULL, PQconninfoFree(), PQExpBufferDataBroken, and termPQExpBuffer().
Referenced by check_pghost_envvar(), dblink_fdw_validator(), InitPgFdwOptions(), and main().
{ PQExpBufferData errorBuf; PQconninfoOption *connOptions; /* We don't actually report any errors here, but callees want a buffer */ initPQExpBuffer(&errorBuf); if (PQExpBufferDataBroken(errorBuf)) return NULL; /* out of memory already :-( */ connOptions = conninfo_init(&errorBuf); if (connOptions != NULL) { if (!conninfo_add_defaults(connOptions, &errorBuf)) { PQconninfoFree(connOptions); connOptions = NULL; } } termPQExpBuffer(&errorBuf); return connOptions; }
PGconn* PQconnectdb | ( | const char * | conninfo | ) |
Definition at line 511 of file fe-connect.c.
References conn, connectDBComplete(), CONNECTION_BAD, PQconnectStart(), and pg_conn::status.
Referenced by dblink_connect(), get_db_conn(), libpqrcv_connect(), and main().
{ PGconn *conn = PQconnectStart(conninfo); if (conn && conn->status != CONNECTION_BAD) (void) connectDBComplete(conn); return conn; }
PGconn* PQconnectdbParams | ( | const char *const * | keywords, | |
const char *const * | values, | |||
int | expand_dbname | |||
) |
Definition at line 455 of file fe-connect.c.
References conn, connectDBComplete(), CONNECTION_BAD, PQconnectStartParams(), and pg_conn::status.
Referenced by _connectDB(), connect_pg_server(), ConnectDatabase(), connectDatabase(), do_connect(), doConnect(), ECPGconnect(), GetConnection(), main(), sql_conn(), and vacuumlo().
{ PGconn *conn = PQconnectStartParams(keywords, values, expand_dbname); if (conn && conn->status != CONNECTION_BAD) (void) connectDBComplete(conn); return conn; }
int PQconnectionNeedsPassword | ( | const PGconn * | conn | ) |
Definition at line 5291 of file fe-connect.c.
References NULL, pg_conn::password_needed, and pg_conn::pgpass.
Referenced by _connectDB(), ConnectDatabase(), connectDatabase(), do_connect(), doConnect(), GetConnection(), main(), sql_conn(), and vacuumlo().
{ if (!conn) return false; if (conn->password_needed && (conn->pgpass == NULL || conn->pgpass[0] == '\0')) return true; else return false; }
int PQconnectionUsedPassword | ( | const PGconn * | conn | ) |
Definition at line 5303 of file fe-connect.c.
References pg_conn::password_needed.
Referenced by connect_pg_server(), and dblink_security_check().
{ if (!conn) return false; if (conn->password_needed) return true; else return false; }
PostgresPollingStatusType PQconnectPoll | ( | PGconn * | conn | ) |
Definition at line 1553 of file fe-connect.c.
References SockAddr::addr, pg_conn::addr_cur, pg_conn::addrlist, pg_conn::addrlist_family, addrinfo::ai_addr, addrinfo::ai_addrlen, addrinfo::ai_family, addrinfo::ai_next, appendPQExpBuffer(), appendPQExpBufferChar(), pg_conn::appname, pg_conn::asyncStatus, AUTH_REQ_GSS_CONT, AUTH_REQ_MD5, AUTH_REQ_OK, pg_conn::auth_req_received, connect, connectFailureMessage(), CONNECTION_AUTH_OK, CONNECTION_AWAITING_RESPONSE, CONNECTION_BAD, CONNECTION_MADE, CONNECTION_NEEDED, CONNECTION_OK, CONNECTION_SETENV, CONNECTION_SSL_STARTUP, CONNECTION_STARTED, connectNoDelay(), PQExpBufferData::data, dot_pg_pass_warning(), EINPROGRESS, EINTR, ERRCODE_APPNAME_UNKNOWN, pg_conn::errorMessage, EWOULDBLOCK, pg_conn::fbappname, free, getpeereid(), pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, IS_AF_UNIX, pg_conn::laddr, PQExpBufferData::len, libpq_gettext, malloc, pg_conn::md5Salt, NEGOTIATE_SSL_CODE, pg_conn::next_eo, NULL, PG_DIAG_SQLSTATE, pg_fe_sendauth(), pg_freeaddrinfo_all(), PG_PROTOCOL, PG_PROTOCOL_MAJOR, pg_set_noblock(), PGRES_FATAL_ERROR, PGRES_POLLING_FAILED, PGRES_POLLING_OK, PGRES_POLLING_READING, PGRES_POLLING_WRITING, pqBuildStartupPacket2(), pqBuildStartupPacket3(), pqCheckInBufferSpace(), PQclear(), pqDropConnection(), pqFlush(), pqGetc(), pqGetErrorNotice3(), pqGetInt(), pqGetnchar(), pqGetpwuid(), PQgetResult(), pqGets_append(), PQisBusy(), pqPacketSend(), pqReadData(), PQresultErrorField(), pqsecure_initialize(), pqsecure_open_client(), pqSetenvPoll(), pqStrerror(), printfPQExpBuffer(), pg_conn::pversion, pg_conn::raddr, pg_conn::requirepeer, pg_result::resultStatus, SockAddr::salen, pg_conn::send_appname, pg_conn::setenv_state, setKeepalivesCount(), setKeepalivesIdle(), setKeepalivesInterval(), pg_conn::sigpipe_flag, pg_conn::sigpipe_so, pg_conn::sock, SOCK_ERRNO, SOCK_STRERROR, socket, pg_conn::sslmode, pg_conn::status, STATUS_OK, and useKeepalives().
Referenced by connectDBComplete(), connectDBStart(), and PQresetPoll().
{ PGresult *res; char sebuf[256]; int optval; if (conn == NULL) return PGRES_POLLING_FAILED; /* Get the new data */ switch (conn->status) { /* * We really shouldn't have been polled in these two cases, but we * can handle it. */ case CONNECTION_BAD: return PGRES_POLLING_FAILED; case CONNECTION_OK: return PGRES_POLLING_OK; /* These are reading states */ case CONNECTION_AWAITING_RESPONSE: case CONNECTION_AUTH_OK: { /* Load waiting data */ int n = pqReadData(conn); if (n < 0) goto error_return; if (n == 0) return PGRES_POLLING_READING; break; } /* These are writing states, so we just proceed. */ case CONNECTION_STARTED: case CONNECTION_MADE: break; /* We allow pqSetenvPoll to decide whether to proceed. */ case CONNECTION_SETENV: break; /* Special cases: proceed without waiting. */ case CONNECTION_SSL_STARTUP: case CONNECTION_NEEDED: break; default: appendPQExpBuffer(&conn->errorMessage, libpq_gettext( "invalid connection state, " "probably indicative of memory corruption\n" )); goto error_return; } keep_going: /* We will come back to here until there is * nothing left to do. */ switch (conn->status) { case CONNECTION_NEEDED: { /* * Try to initiate a connection to one of the addresses * returned by pg_getaddrinfo_all(). conn->addr_cur is the * next one to try. We fail when we run out of addresses. */ while (conn->addr_cur != NULL) { struct addrinfo *addr_cur = conn->addr_cur; /* Remember current address for possible error msg */ memcpy(&conn->raddr.addr, addr_cur->ai_addr, addr_cur->ai_addrlen); conn->raddr.salen = addr_cur->ai_addrlen; /* Open a socket */ conn->sock = socket(addr_cur->ai_family, SOCK_STREAM, 0); if (conn->sock < 0) { /* * ignore socket() failure if we have more addresses * to try */ if (addr_cur->ai_next != NULL) { conn->addr_cur = addr_cur->ai_next; continue; } appendPQExpBuffer(&conn->errorMessage, libpq_gettext("could not create socket: %s\n"), SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf))); break; } /* * Select socket options: no delay of outgoing data for * TCP sockets, nonblock mode, close-on-exec. Fail if any * of this fails. */ if (!IS_AF_UNIX(addr_cur->ai_family)) { if (!connectNoDelay(conn)) { pqDropConnection(conn); conn->addr_cur = addr_cur->ai_next; continue; } } if (!pg_set_noblock(conn->sock)) { appendPQExpBuffer(&conn->errorMessage, libpq_gettext("could not set socket to nonblocking mode: %s\n"), SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf))); pqDropConnection(conn); conn->addr_cur = addr_cur->ai_next; continue; } #ifdef F_SETFD if (fcntl(conn->sock, F_SETFD, FD_CLOEXEC) == -1) { appendPQExpBuffer(&conn->errorMessage, libpq_gettext("could not set socket to close-on-exec mode: %s\n"), SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf))); pqDropConnection(conn); conn->addr_cur = addr_cur->ai_next; continue; } #endif /* F_SETFD */ if (!IS_AF_UNIX(addr_cur->ai_family)) { #ifndef WIN32 int on = 1; #endif int usekeepalives = useKeepalives(conn); int err = 0; if (usekeepalives < 0) { appendPQExpBuffer(&conn->errorMessage, libpq_gettext("keepalives parameter must be an integer\n")); err = 1; } else if (usekeepalives == 0) { /* Do nothing */ } #ifndef WIN32 else if (setsockopt(conn->sock, SOL_SOCKET, SO_KEEPALIVE, (char *) &on, sizeof(on)) < 0) { appendPQExpBuffer(&conn->errorMessage, libpq_gettext("setsockopt(SO_KEEPALIVE) failed: %s\n"), SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf))); err = 1; } else if (!setKeepalivesIdle(conn) || !setKeepalivesInterval(conn) || !setKeepalivesCount(conn)) err = 1; #else /* WIN32 */ #ifdef SIO_KEEPALIVE_VALS else if (!setKeepalivesWin32(conn)) err = 1; #endif /* SIO_KEEPALIVE_VALS */ #endif /* WIN32 */ if (err) { pqDropConnection(conn); conn->addr_cur = addr_cur->ai_next; continue; } } /*---------- * We have three methods of blocking SIGPIPE during * send() calls to this socket: * * - setsockopt(sock, SO_NOSIGPIPE) * - send(sock, ..., MSG_NOSIGNAL) * - setting the signal mask to SIG_IGN during send() * * The third method requires three syscalls per send, * so we prefer either of the first two, but they are * less portable. The state is tracked in the following * members of PGconn: * * conn->sigpipe_so - we have set up SO_NOSIGPIPE * conn->sigpipe_flag - we're specifying MSG_NOSIGNAL * * If we can use SO_NOSIGPIPE, then set sigpipe_so here * and we're done. Otherwise, set sigpipe_flag so that * we will try MSG_NOSIGNAL on sends. If we get an error * with MSG_NOSIGNAL, we'll clear that flag and revert to * signal masking. *---------- */ conn->sigpipe_so = false; #ifdef MSG_NOSIGNAL conn->sigpipe_flag = true; #else conn->sigpipe_flag = false; #endif /* MSG_NOSIGNAL */ #ifdef SO_NOSIGPIPE optval = 1; if (setsockopt(conn->sock, SOL_SOCKET, SO_NOSIGPIPE, (char *) &optval, sizeof(optval)) == 0) { conn->sigpipe_so = true; conn->sigpipe_flag = false; } #endif /* SO_NOSIGPIPE */ /* * Start/make connection. This should not block, since we * are in nonblock mode. If it does, well, too bad. */ if (connect(conn->sock, addr_cur->ai_addr, addr_cur->ai_addrlen) < 0) { if (SOCK_ERRNO == EINPROGRESS || SOCK_ERRNO == EWOULDBLOCK || SOCK_ERRNO == EINTR || SOCK_ERRNO == 0) { /* * This is fine - we're in non-blocking mode, and * the connection is in progress. Tell caller to * wait for write-ready on socket. */ conn->status = CONNECTION_STARTED; return PGRES_POLLING_WRITING; } /* otherwise, trouble */ } else { /* * Hm, we're connected already --- seems the "nonblock * connection" wasn't. Advance the state machine and * go do the next stuff. */ conn->status = CONNECTION_STARTED; goto keep_going; } /* * This connection failed --- set up error report, then * close socket (do it this way in case close() affects * the value of errno...). We will ignore the connect() * failure and keep going if there are more addresses. */ connectFailureMessage(conn, SOCK_ERRNO); pqDropConnection(conn); /* * Try the next address, if any. */ conn->addr_cur = addr_cur->ai_next; } /* loop over addresses */ /* * Ooops, no more addresses. An appropriate error message is * already set up, so just set the right status. */ goto error_return; } case CONNECTION_STARTED: { ACCEPT_TYPE_ARG3 optlen = sizeof(optval); /* * Write ready, since we've made it here, so the connection * has been made ... or has failed. */ /* * Now check (using getsockopt) that there is not an error * state waiting for us on the socket. */ if (getsockopt(conn->sock, SOL_SOCKET, SO_ERROR, (char *) &optval, &optlen) == -1) { appendPQExpBuffer(&conn->errorMessage, libpq_gettext("could not get socket error status: %s\n"), SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf))); goto error_return; } else if (optval != 0) { /* * When using a nonblocking connect, we will typically see * connect failures at this point, so provide a friendly * error message. */ connectFailureMessage(conn, optval); pqDropConnection(conn); /* * If more addresses remain, keep trying, just as in the * case where connect() returned failure immediately. */ if (conn->addr_cur->ai_next != NULL) { conn->addr_cur = conn->addr_cur->ai_next; conn->status = CONNECTION_NEEDED; goto keep_going; } goto error_return; } /* Fill in the client address */ conn->laddr.salen = sizeof(conn->laddr.addr); if (getsockname(conn->sock, (struct sockaddr *) & conn->laddr.addr, &conn->laddr.salen) < 0) { appendPQExpBuffer(&conn->errorMessage, libpq_gettext("could not get client address from socket: %s\n"), SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf))); goto error_return; } /* * Make sure we can write before advancing to next step. */ conn->status = CONNECTION_MADE; return PGRES_POLLING_WRITING; } case CONNECTION_MADE: { char *startpacket; int packetlen; #ifdef HAVE_UNIX_SOCKETS /* * Implement requirepeer check, if requested and it's a * Unix-domain socket. */ if (conn->requirepeer && conn->requirepeer[0] && IS_AF_UNIX(conn->raddr.addr.ss_family)) { char pwdbuf[BUFSIZ]; struct passwd pass_buf; struct passwd *pass; uid_t uid; gid_t gid; errno = 0; if (getpeereid(conn->sock, &uid, &gid) != 0) { /* * Provide special error message if getpeereid is a * stub */ if (errno == ENOSYS) appendPQExpBuffer(&conn->errorMessage, libpq_gettext("requirepeer parameter is not supported on this platform\n")); else appendPQExpBuffer(&conn->errorMessage, libpq_gettext("could not get peer credentials: %s\n"), pqStrerror(errno, sebuf, sizeof(sebuf))); goto error_return; } pqGetpwuid(uid, &pass_buf, pwdbuf, sizeof(pwdbuf), &pass); if (pass == NULL) { appendPQExpBuffer(&conn->errorMessage, libpq_gettext("local user with ID %d does not exist\n"), (int) uid); goto error_return; } if (strcmp(pass->pw_name, conn->requirepeer) != 0) { appendPQExpBuffer(&conn->errorMessage, libpq_gettext("requirepeer specifies \"%s\", but actual peer user name is \"%s\"\n"), conn->requirepeer, pass->pw_name); goto error_return; } } #endif /* HAVE_UNIX_SOCKETS */ #ifdef USE_SSL /* * If SSL is enabled and we haven't already got it running, * request it instead of sending the startup message. */ if (IS_AF_UNIX(conn->raddr.addr.ss_family)) { /* Don't bother requesting SSL over a Unix socket */ conn->allow_ssl_try = false; } if (conn->allow_ssl_try && !conn->wait_ssl_try && conn->ssl == NULL) { ProtocolVersion pv; /* * Send the SSL request packet. * * Theoretically, this could block, but it really * shouldn't since we only got here if the socket is * write-ready. */ pv = htonl(NEGOTIATE_SSL_CODE); if (pqPacketSend(conn, 0, &pv, sizeof(pv)) != STATUS_OK) { appendPQExpBuffer(&conn->errorMessage, libpq_gettext("could not send SSL negotiation packet: %s\n"), SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf))); goto error_return; } /* Ok, wait for response */ conn->status = CONNECTION_SSL_STARTUP; return PGRES_POLLING_READING; } #endif /* USE_SSL */ /* * Build the startup packet. */ if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3) startpacket = pqBuildStartupPacket3(conn, &packetlen, EnvironmentOptions); else startpacket = pqBuildStartupPacket2(conn, &packetlen, EnvironmentOptions); if (!startpacket) { /* * will not appendbuffer here, since it's likely to also * run out of memory */ printfPQExpBuffer(&conn->errorMessage, libpq_gettext("out of memory\n")); goto error_return; } /* * Send the startup packet. * * Theoretically, this could block, but it really shouldn't * since we only got here if the socket is write-ready. */ if (pqPacketSend(conn, 0, startpacket, packetlen) != STATUS_OK) { appendPQExpBuffer(&conn->errorMessage, libpq_gettext("could not send startup packet: %s\n"), SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf))); free(startpacket); goto error_return; } free(startpacket); conn->status = CONNECTION_AWAITING_RESPONSE; return PGRES_POLLING_READING; } /* * Handle SSL negotiation: wait for postmaster messages and * respond as necessary. */ case CONNECTION_SSL_STARTUP: { #ifdef USE_SSL PostgresPollingStatusType pollres; /* * On first time through, get the postmaster's response to our * SSL negotiation packet. */ if (conn->ssl == NULL) { /* * We use pqReadData here since it has the logic to * distinguish no-data-yet from connection closure. Since * conn->ssl isn't set, a plain recv() will occur. */ char SSLok; int rdresult; rdresult = pqReadData(conn); if (rdresult < 0) { /* errorMessage is already filled in */ goto error_return; } if (rdresult == 0) { /* caller failed to wait for data */ return PGRES_POLLING_READING; } if (pqGetc(&SSLok, conn) < 0) { /* should not happen really */ return PGRES_POLLING_READING; } if (SSLok == 'S') { /* mark byte consumed */ conn->inStart = conn->inCursor; /* Set up global SSL state if required */ if (pqsecure_initialize(conn) != 0) goto error_return; } else if (SSLok == 'N') { /* mark byte consumed */ conn->inStart = conn->inCursor; /* OK to do without SSL? */ if (conn->sslmode[0] == 'r' || /* "require" */ conn->sslmode[0] == 'v') /* "verify-ca" or * "verify-full" */ { /* Require SSL, but server does not want it */ appendPQExpBuffer(&conn->errorMessage, libpq_gettext("server does not support SSL, but SSL was required\n")); goto error_return; } /* Otherwise, proceed with normal startup */ conn->allow_ssl_try = false; conn->status = CONNECTION_MADE; return PGRES_POLLING_WRITING; } else if (SSLok == 'E') { /* * Server failure of some sort, such as failure to * fork a backend process. We need to process and * report the error message, which might be formatted * according to either protocol 2 or protocol 3. * Rather than duplicate the code for that, we flip * into AWAITING_RESPONSE state and let the code there * deal with it. Note we have *not* consumed the "E" * byte here. */ conn->status = CONNECTION_AWAITING_RESPONSE; goto keep_going; } else { appendPQExpBuffer(&conn->errorMessage, libpq_gettext("received invalid response to SSL negotiation: %c\n"), SSLok); goto error_return; } } /* * Begin or continue the SSL negotiation process. */ pollres = pqsecure_open_client(conn); if (pollres == PGRES_POLLING_OK) { /* SSL handshake done, ready to send startup packet */ conn->status = CONNECTION_MADE; return PGRES_POLLING_WRITING; } if (pollres == PGRES_POLLING_FAILED) { /* * Failed ... if sslmode is "prefer" then do a non-SSL * retry */ if (conn->sslmode[0] == 'p' /* "prefer" */ && conn->allow_ssl_try /* redundant? */ && !conn->wait_ssl_try) /* redundant? */ { /* only retry once */ conn->allow_ssl_try = false; /* Must drop the old connection */ pqDropConnection(conn); conn->status = CONNECTION_NEEDED; goto keep_going; } } return pollres; #else /* !USE_SSL */ /* can't get here */ goto error_return; #endif /* USE_SSL */ } /* * Handle authentication exchange: wait for postmaster messages * and respond as necessary. */ case CONNECTION_AWAITING_RESPONSE: { char beresp; int msgLength; int avail; AuthRequest areq; /* * Scan the message from current point (note that if we find * the message is incomplete, we will return without advancing * inStart, and resume here next time). */ conn->inCursor = conn->inStart; /* Read type byte */ if (pqGetc(&beresp, conn)) { /* We'll come back when there is more data */ return PGRES_POLLING_READING; } /* * Validate message type: we expect only an authentication * request or an error here. Anything else probably means * it's not Postgres on the other end at all. */ if (!(beresp == 'R' || beresp == 'E')) { appendPQExpBuffer(&conn->errorMessage, libpq_gettext( "expected authentication request from " "server, but received %c\n"), beresp); goto error_return; } if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3) { /* Read message length word */ if (pqGetInt(&msgLength, 4, conn)) { /* We'll come back when there is more data */ return PGRES_POLLING_READING; } } else { /* Set phony message length to disable checks below */ msgLength = 8; } /* * Try to validate message length before using it. * Authentication requests can't be very large, although GSS * auth requests may not be that small. Errors can be a * little larger, but not huge. If we see a large apparent * length in an error, it means we're really talking to a * pre-3.0-protocol server; cope. */ if (beresp == 'R' && (msgLength < 8 || msgLength > 2000)) { appendPQExpBuffer(&conn->errorMessage, libpq_gettext( "expected authentication request from " "server, but received %c\n"), beresp); goto error_return; } if (beresp == 'E' && (msgLength < 8 || msgLength > 30000)) { /* Handle error from a pre-3.0 server */ conn->inCursor = conn->inStart + 1; /* reread data */ if (pqGets_append(&conn->errorMessage, conn)) { /* We'll come back when there is more data */ return PGRES_POLLING_READING; } /* OK, we read the message; mark data consumed */ conn->inStart = conn->inCursor; /* * The postmaster typically won't end its message with a * newline, so add one to conform to libpq conventions. */ appendPQExpBufferChar(&conn->errorMessage, '\n'); /* * If we tried to open the connection in 3.0 protocol, * fall back to 2.0 protocol. */ if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3) { conn->pversion = PG_PROTOCOL(2, 0); /* Must drop the old connection */ pqDropConnection(conn); conn->status = CONNECTION_NEEDED; goto keep_going; } goto error_return; } /* * Can't process if message body isn't all here yet. * * (In protocol 2.0 case, we are assuming messages carry at * least 4 bytes of data.) */ msgLength -= 4; avail = conn->inEnd - conn->inCursor; if (avail < msgLength) { /* * Before returning, try to enlarge the input buffer if * needed to hold the whole message; see notes in * pqParseInput3. */ if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength, conn)) goto error_return; /* We'll come back when there is more data */ return PGRES_POLLING_READING; } /* Handle errors. */ if (beresp == 'E') { if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3) { if (pqGetErrorNotice3(conn, true)) { /* We'll come back when there is more data */ return PGRES_POLLING_READING; } } else { if (pqGets_append(&conn->errorMessage, conn)) { /* We'll come back when there is more data */ return PGRES_POLLING_READING; } } /* OK, we read the message; mark data consumed */ conn->inStart = conn->inCursor; #ifdef USE_SSL /* * if sslmode is "allow" and we haven't tried an SSL * connection already, then retry with an SSL connection */ if (conn->sslmode[0] == 'a' /* "allow" */ && conn->ssl == NULL && conn->allow_ssl_try && conn->wait_ssl_try) { /* only retry once */ conn->wait_ssl_try = false; /* Must drop the old connection */ pqDropConnection(conn); conn->status = CONNECTION_NEEDED; goto keep_going; } /* * if sslmode is "prefer" and we're in an SSL connection, * then do a non-SSL retry */ if (conn->sslmode[0] == 'p' /* "prefer" */ && conn->allow_ssl_try && !conn->wait_ssl_try) /* redundant? */ { /* only retry once */ conn->allow_ssl_try = false; /* Must drop the old connection */ pqDropConnection(conn); conn->status = CONNECTION_NEEDED; goto keep_going; } #endif goto error_return; } /* It is an authentication request. */ conn->auth_req_received = true; /* Get the type of request. */ if (pqGetInt((int *) &areq, 4, conn)) { /* We'll come back when there are more data */ return PGRES_POLLING_READING; } /* Get the password salt if there is one. */ if (areq == AUTH_REQ_MD5) { if (pqGetnchar(conn->md5Salt, sizeof(conn->md5Salt), conn)) { /* We'll come back when there are more data */ return PGRES_POLLING_READING; } } #if defined(ENABLE_GSS) || defined(ENABLE_SSPI) /* * Continue GSSAPI/SSPI authentication */ if (areq == AUTH_REQ_GSS_CONT) { int llen = msgLength - 4; /* * We can be called repeatedly for the same buffer. Avoid * re-allocating the buffer in this case - just re-use the * old buffer. */ if (llen != conn->ginbuf.length) { if (conn->ginbuf.value) free(conn->ginbuf.value); conn->ginbuf.length = llen; conn->ginbuf.value = malloc(llen); if (!conn->ginbuf.value) { printfPQExpBuffer(&conn->errorMessage, libpq_gettext("out of memory allocating GSSAPI buffer (%d)"), llen); goto error_return; } } if (pqGetnchar(conn->ginbuf.value, llen, conn)) { /* We'll come back when there is more data. */ return PGRES_POLLING_READING; } } #endif /* * OK, we successfully read the message; mark data consumed */ conn->inStart = conn->inCursor; /* Respond to the request if necessary. */ /* * Note that conn->pghost must be non-NULL if we are going to * avoid the Kerberos code doing a hostname look-up. */ if (pg_fe_sendauth(areq, conn) != STATUS_OK) { conn->errorMessage.len = strlen(conn->errorMessage.data); goto error_return; } conn->errorMessage.len = strlen(conn->errorMessage.data); /* * Just make sure that any data sent by pg_fe_sendauth is * flushed out. Although this theoretically could block, it * really shouldn't since we don't send large auth responses. */ if (pqFlush(conn)) goto error_return; if (areq == AUTH_REQ_OK) { /* We are done with authentication exchange */ conn->status = CONNECTION_AUTH_OK; /* * Set asyncStatus so that PQgetResult will think that * what comes back next is the result of a query. See * below. */ conn->asyncStatus = PGASYNC_BUSY; } /* Look to see if we have more data yet. */ goto keep_going; } case CONNECTION_AUTH_OK: { /* * Now we expect to hear from the backend. A ReadyForQuery * message indicates that startup is successful, but we might * also get an Error message indicating failure. (Notice * messages indicating nonfatal warnings are also allowed by * the protocol, as are ParameterStatus and BackendKeyData * messages.) Easiest way to handle this is to let * PQgetResult() read the messages. We just have to fake it * out about the state of the connection, by setting * asyncStatus = PGASYNC_BUSY (done above). */ if (PQisBusy(conn)) return PGRES_POLLING_READING; res = PQgetResult(conn); /* * NULL return indicating we have gone to IDLE state is * expected */ if (res) { if (res->resultStatus != PGRES_FATAL_ERROR) appendPQExpBuffer(&conn->errorMessage, libpq_gettext("unexpected message from server during startup\n")); else if (conn->send_appname && (conn->appname || conn->fbappname)) { /* * If we tried to send application_name, check to see * if the error is about that --- pre-9.0 servers will * reject it at this stage of the process. If so, * close the connection and retry without sending * application_name. We could possibly get a false * SQLSTATE match here and retry uselessly, but there * seems no great harm in that; we'll just get the * same error again if it's unrelated. */ const char *sqlstate; sqlstate = PQresultErrorField(res, PG_DIAG_SQLSTATE); if (sqlstate && strcmp(sqlstate, ERRCODE_APPNAME_UNKNOWN) == 0) { PQclear(res); conn->send_appname = false; /* Must drop the old connection */ pqDropConnection(conn); conn->status = CONNECTION_NEEDED; goto keep_going; } } /* * if the resultStatus is FATAL, then conn->errorMessage * already has a copy of the error; needn't copy it back. * But add a newline if it's not there already, since * postmaster error messages may not have one. */ if (conn->errorMessage.len <= 0 || conn->errorMessage.data[conn->errorMessage.len - 1] != '\n') appendPQExpBufferChar(&conn->errorMessage, '\n'); PQclear(res); goto error_return; } /* We can release the address list now. */ pg_freeaddrinfo_all(conn->addrlist_family, conn->addrlist); conn->addrlist = NULL; conn->addr_cur = NULL; /* Fire up post-connection housekeeping if needed */ if (PG_PROTOCOL_MAJOR(conn->pversion) < 3) { conn->status = CONNECTION_SETENV; conn->setenv_state = SETENV_STATE_CLIENT_ENCODING_SEND; conn->next_eo = EnvironmentOptions; return PGRES_POLLING_WRITING; } /* Otherwise, we are open for business! */ conn->status = CONNECTION_OK; return PGRES_POLLING_OK; } case CONNECTION_SETENV: /* * Do post-connection housekeeping (only needed in protocol 2.0). * * We pretend that the connection is OK for the duration of these * queries. */ conn->status = CONNECTION_OK; switch (pqSetenvPoll(conn)) { case PGRES_POLLING_OK: /* Success */ break; case PGRES_POLLING_READING: /* Still going */ conn->status = CONNECTION_SETENV; return PGRES_POLLING_READING; case PGRES_POLLING_WRITING: /* Still going */ conn->status = CONNECTION_SETENV; return PGRES_POLLING_WRITING; default: goto error_return; } /* We are open for business! */ conn->status = CONNECTION_OK; return PGRES_POLLING_OK; default: appendPQExpBuffer(&conn->errorMessage, libpq_gettext("invalid connection state %d, " "probably indicative of memory corruption\n"), conn->status); goto error_return; } /* Unreachable */ error_return: dot_pg_pass_warning(conn); /* * We used to close the socket at this point, but that makes it awkward * for those above us if they wish to remove this socket from their own * records (an fd_set for example). We'll just have this socket closed * when PQfinish is called (which is compulsory even after an error, since * the connection structure must be freed). */ conn->status = CONNECTION_BAD; return PGRES_POLLING_FAILED; }
PGconn* PQconnectStart | ( | const char * | conninfo | ) |
Definition at line 633 of file fe-connect.c.
References conn, connectDBStart(), connectOptions1(), connectOptions2(), makeEmptyPGconn(), NULL, and pg_conn::status.
Referenced by PQconnectdb(), and PQping().
{ PGconn *conn; /* * Allocate memory for the conn structure */ conn = makeEmptyPGconn(); if (conn == NULL) return NULL; /* * Parse the conninfo string */ if (!connectOptions1(conn, conninfo)) return conn; /* * Compute derived options */ if (!connectOptions2(conn)) return conn; /* * Connect to the database */ if (!connectDBStart(conn)) { /* Just in case we failed to set it in connectDBStart */ conn->status = CONNECTION_BAD; } return conn; }
PGconn* PQconnectStartParams | ( | const char *const * | keywords, | |
const char *const * | values, | |||
int | expand_dbname | |||
) |
Definition at line 558 of file fe-connect.c.
References conn, connectDBStart(), connectOptions2(), conninfo_array_parse(), pg_conn::errorMessage, fillPGconn(), makeEmptyPGconn(), NULL, PQconninfoFree(), and pg_conn::status.
Referenced by PQconnectdbParams(), and PQpingParams().
{ PGconn *conn; PQconninfoOption *connOptions; /* * Allocate memory for the conn structure */ conn = makeEmptyPGconn(); if (conn == NULL) return NULL; /* * Parse the conninfo arrays */ connOptions = conninfo_array_parse(keywords, values, &conn->errorMessage, true, expand_dbname); if (connOptions == NULL) { conn->status = CONNECTION_BAD; /* errorMessage is already set */ return conn; } /* * Move option values into conn structure */ fillPGconn(conn, connOptions); /* * Free the option info - all is in conn now */ PQconninfoFree(connOptions); /* * Compute derived options */ if (!connectOptions2(conn)) return conn; /* * Connect to the database */ if (!connectDBStart(conn)) { /* Just in case we failed to set it in connectDBStart */ conn->status = CONNECTION_BAD; } return conn; }
PQconninfoOption* PQconninfo | ( | PGconn * | conn | ) |
Definition at line 5098 of file fe-connect.c.
References conninfo_init(), conninfo_storeval(), _internalPQconninfoOption::connofs, initPQExpBuffer(), _internalPQconninfoOption::keyword, NULL, PQExpBufferDataBroken, and termPQExpBuffer().
Referenced by GenerateRecoveryConf().
{ PQExpBufferData errorBuf; PQconninfoOption *connOptions; if (conn == NULL) return NULL; /* We don't actually report any errors here, but callees want a buffer */ initPQExpBuffer(&errorBuf); if (PQExpBufferDataBroken(errorBuf)) return NULL; /* out of memory already :-( */ connOptions = conninfo_init(&errorBuf); if (connOptions != NULL) { const internalPQconninfoOption *option; for (option = PQconninfoOptions; option->keyword; option++) { char **connmember; if (option->connofs < 0) continue; connmember = (char **) ((char *) conn + option->connofs); if (*connmember) conninfo_storeval(connOptions, option->keyword, *connmember, &errorBuf, true, false); } } termPQExpBuffer(&errorBuf); return connOptions; }
void PQconninfoFree | ( | PQconninfoOption * | connOptions | ) |
Definition at line 5139 of file fe-connect.c.
References free, _PQconninfoOption::keyword, NULL, and _PQconninfoOption::val.
Referenced by check_pghost_envvar(), connectDatabase(), connectOptions1(), conninfo_array_parse(), conninfo_parse(), conninfo_uri_parse(), dblink_connstr_check(), GenerateRecoveryConf(), GetConnection(), main(), PQconndefaults(), and PQconnectStartParams().
PQconninfoOption* PQconninfoParse | ( | const char * | conninfo, | |
char ** | errmsg | |||
) |
Definition at line 3986 of file fe-connect.c.
References PQExpBufferData::data, initPQExpBuffer(), NULL, parse_connection_string(), PQExpBufferDataBroken, and termPQExpBuffer().
Referenced by connectDatabase(), dblink_connstr_check(), GetConnection(), and main().
{ PQExpBufferData errorBuf; PQconninfoOption *connOptions; if (errmsg) *errmsg = NULL; /* default */ initPQExpBuffer(&errorBuf); if (PQExpBufferDataBroken(errorBuf)) return NULL; /* out of memory already :-( */ connOptions = parse_connection_string(conninfo, &errorBuf, false); if (connOptions == NULL && errmsg) *errmsg = errorBuf.data; else termPQExpBuffer(&errorBuf); return connOptions; }
char* PQdb | ( | const PGconn * | conn | ) |
Definition at line 5157 of file fe-connect.c.
References pg_conn::dbName.
Referenced by _connectDB(), CloneArchive(), ConnectDatabase(), do_connect(), dumpDatabase(), exec_command(), get_prompt(), main(), ReconnectToServer(), slashUsage(), SyncVariables(), and WriteHead().
{ if (!conn) return NULL; return conn->dbName; }
void pqDropConnection | ( | PGconn * | conn | ) |
Definition at line 396 of file fe-connect.c.
References closesocket, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, pg_conn::outCount, pqsecure_close(), and pg_conn::sock.
Referenced by closePGconn(), connectDBStart(), handleSyncLoss(), PQconnectPoll(), and pqReadData().
{ /* Drop any SSL state */ pqsecure_close(conn); /* Close the socket itself */ if (conn->sock >= 0) closesocket(conn->sock); conn->sock = -1; /* Discard any unread/unsent data */ conn->inStart = conn->inCursor = conn->inEnd = 0; conn->outCount = 0; }
char* PQerrorMessage | ( | const PGconn * | conn | ) |
Definition at line 5266 of file fe-connect.c.
References PQExpBufferData::data, pg_conn::errorMessage, and libpq_gettext.
Referenced by _connectDB(), _doSetSessionAuth(), _doSetWithOids(), _selectOutputSchema(), _selectTablespace(), AcceptResult(), BaseBackup(), check_conn(), check_loadable_libraries(), cluster_one_database(), connect_pg_server(), ConnectDatabase(), connectDatabase(), connectToServer(), dblink_connect(), dblink_error_message(), dblink_send_query(), die_on_query_failure(), do_connect(), do_lo_export(), do_lo_import(), do_lo_unlink(), doConnect(), doCustom(), dumpBlobs(), dumpTableData_copy(), ecpg_check_PQresult(), ecpg_raise_backend(), ECPGconnect(), EndDBCopyMode(), executeCommand(), executeQuery(), executeQueryOrDie(), ExecuteSqlCommand(), ExecuteSqlCommandBuf(), executeStatement(), GetConnection(), handleCopyIn(), handleCopyOut(), HandleCopyStream(), init(), libpqrcv_connect(), libpqrcv_endstreaming(), libpqrcv_identify_system(), libpqrcv_readtimelinehistoryfile(), libpqrcv_receive(), libpqrcv_send(), libpqrcv_startstreaming(), lockTableNoWait(), main(), my_truncate(), overwrite(), pickout(), PSQLexec(), ReceiveAndUnpackTarFile(), ReceiveTarFile(), ReceiveXlogStream(), reindex_one_database(), reindex_system_catalogs(), run_permutation(), sendFeedback(), SendQuery(), sql_conn(), sql_exec(), start_postmaster(), StartRestoreBlob(), storeQueryResult(), StreamLog(), try_complete_step(), vacuum_one_database(), and vacuumlo().
{ if (!conn) return libpq_gettext("connection pointer is NULL\n"); return conn->errorMessage.data; }
void PQfinish | ( | PGconn * | conn | ) |
Definition at line 2962 of file fe-connect.c.
References closePGconn(), and freePGconn().
Referenced by _connectDB(), BaseBackup(), check_for_isn_and_int8_passing_mismatch(), check_for_prepared_transactions(), check_for_reg_data_type_usage(), check_is_super_user(), check_loadable_libraries(), CheckConnection(), clientDone(), cluster_all_databases(), cluster_one_database(), connect_pg_server(), ConnectDatabase(), connectDatabase(), connectToServer(), createNewConnection(), dblink_connect(), dblink_disconnect(), dblink_exec(), dblink_record_internal(), dblink_security_check(), disconnect_all(), DisconnectDatabase(), do_connect(), doConnect(), doCustom(), dumpCreateDB(), dumpTablespaces(), ecpg_finish(), executeCommand(), executeQuery(), executeQueryOrDie(), exit_nicely(), get_db_infos(), get_loadable_libraries(), get_pg_database_relfilenode(), get_rel_infos(), get_tablespace_paths(), GetConnection(), init(), install_support_functions_in_new_db(), libpqrcv_disconnect(), LogStreamerMain(), main(), new_9_0_populate_pg_largeobject_metadata(), old_8_3_check_for_name_data_type_usage(), old_8_3_check_for_tsquery_usage(), old_8_3_check_ltree_usage(), old_8_3_create_sequence_script(), old_8_3_invalidate_bpchar_pattern_ops_indexes(), old_8_3_invalidate_hash_gin_indexes(), old_8_3_rebuild_tsvector_tables(), pgfdw_xact_callback(), PQping(), PQpingParams(), ReconnectToServer(), reindex_all_databases(), reindex_one_database(), reindex_system_catalogs(), set_frozenxids(), set_locale_and_encoding(), sql_conn(), sql_exec(), start_postmaster(), StreamLog(), threadRun(), uninstall_support_functions_from_new_cluster(), vacuum_all_databases(), vacuum_one_database(), vacuumlo(), and WaitForCommands().
{ if (conn) { closePGconn(conn); freePGconn(conn); } }
void PQfreeCancel | ( | PGcancel * | cancel | ) |
Definition at line 3106 of file fe-connect.c.
References free.
Referenced by dblink_cancel_query(), DisconnectDatabase(), ResetCancelConn(), run_permutation(), and SetCancelConn().
{ if (cancel) free(cancel); }
Definition at line 3083 of file fe-connect.c.
References pg_conn::be_key, pg_cancel::be_key, pg_conn::be_pid, pg_cancel::be_pid, malloc, NULL, pg_conn::raddr, pg_cancel::raddr, and pg_conn::sock.
Referenced by dblink_cancel_query(), DisconnectDatabase(), run_permutation(), and SetCancelConn().
bool pqGetHomeDirectory | ( | char * | buf, | |
int | bufsize | |||
) |
Definition at line 5672 of file fe-connect.c.
References NULL, pqGetpwuid(), snprintf(), and strlcpy().
Referenced by getPgPassFilename(), and parseServiceInfo().
{ #ifndef WIN32 char pwdbuf[BUFSIZ]; struct passwd pwdstr; struct passwd *pwd = NULL; if (pqGetpwuid(geteuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd) != 0) return false; strlcpy(buf, pwd->pw_dir, bufsize); return true; #else char tmppath[MAX_PATH]; ZeroMemory(tmppath, sizeof(tmppath)); if (SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, tmppath) != S_OK) return false; snprintf(buf, bufsize, "%s/postgresql", tmppath); return true; #endif }
char* PQhost | ( | const PGconn * | conn | ) |
Definition at line 5181 of file fe-connect.c.
References pg_conn::pghost, and pg_conn::pgunixsocket.
Referenced by _connectDB(), CloneArchive(), do_connect(), exec_command(), get_prompt(), and SyncVariables().
{ if (!conn) return NULL; return conn->pghost ? conn->pghost : conn->pgunixsocket; }
char* PQoptions | ( | const PGconn * | conn | ) |
Definition at line 5205 of file fe-connect.c.
References pg_conn::pgoptions.
{ if (!conn) return NULL; return conn->pgoptions; }
int pqPacketSend | ( | PGconn * | conn, | |
char | pack_type, | |||
const void * | buf, | |||
size_t | buf_len | |||
) |
Definition at line 3307 of file fe-connect.c.
References pqFlush(), pqPutMsgEnd(), pqPutMsgStart(), and pqPutnchar().
Referenced by pg_password_sendauth(), and PQconnectPoll().
{ /* Start the message. */ if (pqPutMsgStart(pack_type, true, conn)) return STATUS_ERROR; /* Send the message body. */ if (pqPutnchar(buf, buf_len, conn)) return STATUS_ERROR; /* Finish the message. */ if (pqPutMsgEnd(conn)) return STATUS_ERROR; /* Flush to ensure backend gets it. */ if (pqFlush(conn)) return STATUS_ERROR; return STATUS_OK; }
const char* PQparameterStatus | ( | const PGconn * | conn, | |
const char * | paramName | |||
) |
Definition at line 5231 of file fe-connect.c.
References pgParameterStatus::name, pgParameterStatus::next, NULL, pg_conn::pstatus, and pgParameterStatus::value.
Referenced by _check_database_version(), applyRemoteGucs(), BaseBackup(), CheckServerVersionForStreaming(), connectDatabase(), connection_warnings(), GetConnection(), is_superuser(), main(), session_username(), setup_connection(), and standard_strings().
char* PQpass | ( | const PGconn * | conn | ) |
Definition at line 5173 of file fe-connect.c.
References pg_conn::pgpass.
Referenced by do_connect().
{ if (!conn) return NULL; return conn->pgpass; }
PGPing PQping | ( | const char * | conninfo | ) |
Definition at line 527 of file fe-connect.c.
References conn, internal_ping(), PQconnectStart(), and PQfinish().
Referenced by test_postmaster_connection().
{ PGconn *conn = PQconnectStart(conninfo); PGPing ret; ret = internal_ping(conn); PQfinish(conn); return ret; }
PGPing PQpingParams | ( | const char *const * | keywords, | |
const char *const * | values, | |||
int | expand_dbname | |||
) |
Definition at line 474 of file fe-connect.c.
References conn, internal_ping(), PQconnectStartParams(), and PQfinish().
Referenced by main().
{ PGconn *conn = PQconnectStartParams(keywords, values, expand_dbname); PGPing ret; ret = internal_ping(conn); PQfinish(conn); return ret; }
char* PQport | ( | const PGconn * | conn | ) |
Definition at line 5189 of file fe-connect.c.
References pg_conn::pgport.
Referenced by _connectDB(), CloneArchive(), do_connect(), exec_command(), get_prompt(), and SyncVariables().
{ if (!conn) return NULL; return conn->pgport; }
int PQprotocolVersion | ( | const PGconn * | conn | ) |
Definition at line 5246 of file fe-connect.c.
References CONNECTION_BAD, PG_PROTOCOL_MAJOR, pg_conn::pversion, and pg_conn::status.
{ if (!conn) return 0; if (conn->status == CONNECTION_BAD) return 0; return PG_PROTOCOL_MAJOR(conn->pversion); }
pgthreadlock_t PQregisterThreadLock | ( | pgthreadlock_t | newhandler | ) |
Definition at line 5735 of file fe-connect.c.
References pg_g_threadlock.
{ pgthreadlock_t prev = pg_g_threadlock; if (newhandler) pg_g_threadlock = newhandler; else pg_g_threadlock = default_threadlock; return prev; }
int PQrequestCancel | ( | PGconn * | conn | ) |
Definition at line 3263 of file fe-connect.c.
References pg_conn::be_key, pg_conn::be_pid, PQExpBufferData::data, pg_conn::errorMessage, internal_cancel(), PQExpBufferData::len, PQExpBufferData::maxlen, pg_conn::raddr, pg_conn::sock, and strlcpy().
{ int r; /* Check we have an open connection */ if (!conn) return FALSE; if (conn->sock < 0) { strlcpy(conn->errorMessage.data, "PQrequestCancel() -- connection is not open\n", conn->errorMessage.maxlen); conn->errorMessage.len = strlen(conn->errorMessage.data); return FALSE; } r = internal_cancel(&conn->raddr, conn->be_pid, conn->be_key, conn->errorMessage.data, conn->errorMessage.maxlen); if (!r) conn->errorMessage.len = strlen(conn->errorMessage.data); return r; }
void PQreset | ( | PGconn * | conn | ) |
Definition at line 2976 of file fe-connect.c.
References closePGconn(), PGEventConnReset::conn, connectDBComplete(), connectDBStart(), pg_conn::errorMessage, pg_conn::events, i, libpq_gettext, PGEvent::name, pg_conn::nEvents, PGEvent::passThrough, PGEVT_CONNRESET, printfPQExpBuffer(), PGEvent::proc, and pg_conn::status.
Referenced by CheckConnection(), and pqEndcopy2().
{ if (conn) { closePGconn(conn); if (connectDBStart(conn) && connectDBComplete(conn)) { /* * Notify event procs of successful reset. We treat an event proc * failure as disabling the connection ... good idea? */ int i; for (i = 0; i < conn->nEvents; i++) { PGEventConnReset evt; evt.conn = conn; if (!conn->events[i].proc(PGEVT_CONNRESET, &evt, conn->events[i].passThrough)) { conn->status = CONNECTION_BAD; printfPQExpBuffer(&conn->errorMessage, libpq_gettext("PGEventProc \"%s\" failed during PGEVT_CONNRESET event\n"), conn->events[i].name); break; } } } } }
PostgresPollingStatusType PQresetPoll | ( | PGconn * | conn | ) |
Definition at line 3036 of file fe-connect.c.
References PGEventConnReset::conn, pg_conn::errorMessage, pg_conn::events, i, libpq_gettext, PGEvent::name, pg_conn::nEvents, PGEvent::passThrough, PGEVT_CONNRESET, PGRES_POLLING_OK, PQconnectPoll(), printfPQExpBuffer(), PGEvent::proc, pg_conn::status, and status().
{ if (conn) { PostgresPollingStatusType status = PQconnectPoll(conn); if (status == PGRES_POLLING_OK) { /* * Notify event procs of successful reset. We treat an event proc * failure as disabling the connection ... good idea? */ int i; for (i = 0; i < conn->nEvents; i++) { PGEventConnReset evt; evt.conn = conn; if (!conn->events[i].proc(PGEVT_CONNRESET, &evt, conn->events[i].passThrough)) { conn->status = CONNECTION_BAD; printfPQExpBuffer(&conn->errorMessage, libpq_gettext("PGEventProc \"%s\" failed during PGEVT_CONNRESET event\n"), conn->events[i].name); return PGRES_POLLING_FAILED; } } } return status; } return PGRES_POLLING_FAILED; }
int PQresetStart | ( | PGconn * | conn | ) |
Definition at line 3017 of file fe-connect.c.
References closePGconn(), and connectDBStart().
Referenced by pqEndcopy2().
{ if (conn) { closePGconn(conn); return connectDBStart(conn); } return 0; }
int PQserverVersion | ( | const PGconn * | conn | ) |
Definition at line 5256 of file fe-connect.c.
References CONNECTION_BAD, pg_conn::status, and pg_conn::sversion.
Referenced by _check_database_version(), appendStringLiteralConn(), BaseBackup(), CheckServerVersionForStreaming(), configure_remote_session(), connectDatabase(), DropBlobIfExists(), main(), restore_toc_entry(), SyncVariables(), vacuum_one_database(), and vacuumlo().
{ if (!conn) return 0; if (conn->status == CONNECTION_BAD) return 0; return conn->sversion; }
int PQsetClientEncoding | ( | PGconn * | conn, | |
const char * | encoding | |||
) |
Definition at line 5322 of file fe-connect.c.
References CONNECTION_OK, NULL, pg_encoding_to_char(), pg_get_encoding_from_locale(), PG_PROTOCOL_MAJOR, PGRES_COMMAND_OK, PQclear(), PQexec(), pqSaveParameterStatus(), pg_conn::pversion, pg_result::resultStatus, and pg_conn::status.
Referenced by CloneArchive(), dblink_connect(), exec_command(), and setup_connection().
{ char qbuf[128]; static const char query[] = "set client_encoding to '%s'"; PGresult *res; int status; if (!conn || conn->status != CONNECTION_OK) return -1; if (!encoding) return -1; /* Resolve special "auto" value from the locale */ if (strcmp(encoding, "auto") == 0) encoding = pg_encoding_to_char(pg_get_encoding_from_locale(NULL, true)); /* check query buffer overflow */ if (sizeof(qbuf) < (sizeof(query) + strlen(encoding))) return -1; /* ok, now send a query */ sprintf(qbuf, query, encoding); res = PQexec(conn, qbuf); if (res == NULL) return -1; if (res->resultStatus != PGRES_COMMAND_OK) status = -1; else { /* * In protocol 2 we have to assume the setting will stick, and adjust * our state immediately. In protocol 3 and up we can rely on the * backend to report the parameter value, and we'll change state at * that time. */ if (PG_PROTOCOL_MAJOR(conn->pversion) < 3) pqSaveParameterStatus(conn, "client_encoding", encoding); status = 0; /* everything is ok */ } PQclear(res); return status; }
PGconn* PQsetdbLogin | ( | const char * | pghost, | |
const char * | pgport, | |||
const char * | pgoptions, | |||
const char * | pgtty, | |||
const char * | dbName, | |||
const char * | login, | |||
const char * | pwd | |||
) |
Definition at line 902 of file fe-connect.c.
References conn, connectDBComplete(), connectDBStart(), connectOptions1(), connectOptions2(), pg_conn::dbName, free, makeEmptyPGconn(), NULL, pg_conn::pghost, pg_conn::pgoptions, pg_conn::pgpass, pg_conn::pgport, pg_conn::pgtty, pg_conn::pguser, and recognized_connection_string().
{ PGconn *conn; /* * Allocate memory for the conn structure */ conn = makeEmptyPGconn(); if (conn == NULL) return NULL; /* * If the dbName parameter contains what looks like a connection string, * parse it into conn struct using connectOptions1. */ if (dbName && recognized_connection_string(dbName)) { if (!connectOptions1(conn, dbName)) return conn; } else { /* * Old-style path: first, parse an empty conninfo string in order to * set up the same defaults that PQconnectdb() would use. */ if (!connectOptions1(conn, "")) return conn; /* Insert dbName parameter value into struct */ if (dbName && dbName[0] != '\0') { if (conn->dbName) free(conn->dbName); conn->dbName = strdup(dbName); } } /* * Insert remaining parameters into struct, overriding defaults (as well * as any conflicting data from dbName taken as a conninfo). */ if (pghost && pghost[0] != '\0') { if (conn->pghost) free(conn->pghost); conn->pghost = strdup(pghost); } if (pgport && pgport[0] != '\0') { if (conn->pgport) free(conn->pgport); conn->pgport = strdup(pgport); } if (pgoptions && pgoptions[0] != '\0') { if (conn->pgoptions) free(conn->pgoptions); conn->pgoptions = strdup(pgoptions); } if (pgtty && pgtty[0] != '\0') { if (conn->pgtty) free(conn->pgtty); conn->pgtty = strdup(pgtty); } if (login && login[0] != '\0') { if (conn->pguser) free(conn->pguser); conn->pguser = strdup(login); } if (pwd && pwd[0] != '\0') { if (conn->pgpass) free(conn->pgpass); conn->pgpass = strdup(pwd); } /* * Compute derived options */ if (!connectOptions2(conn)) return conn; /* * Connect to the database */ if (connectDBStart(conn)) (void) connectDBComplete(conn); return conn; }
PGVerbosity PQsetErrorVerbosity | ( | PGconn * | conn, | |
PGVerbosity | verbosity | |||
) |
Definition at line 5368 of file fe-connect.c.
References pg_conn::verbosity.
Referenced by SyncVariables(), and verbosity_hook().
{ PGVerbosity old; if (!conn) return PQERRORS_DEFAULT; old = conn->verbosity; conn->verbosity = verbosity; return old; }
PQnoticeProcessor PQsetNoticeProcessor | ( | PGconn * | conn, | |
PQnoticeProcessor | proc, | |||
void * | arg | |||
) |
Definition at line 5418 of file fe-connect.c.
References pg_conn::noticeHooks, PGNoticeHooks::noticeProc, PGNoticeHooks::noticeProcArg, and NULL.
Referenced by _connectDB(), ConnectDatabase(), do_connect(), and main().
{ PQnoticeProcessor old; if (conn == NULL) return NULL; old = conn->noticeHooks.noticeProc; if (proc) { conn->noticeHooks.noticeProc = proc; conn->noticeHooks.noticeProcArg = arg; } return old; }
PQnoticeReceiver PQsetNoticeReceiver | ( | PGconn * | conn, | |
PQnoticeReceiver | proc, | |||
void * | arg | |||
) |
Definition at line 5401 of file fe-connect.c.
References pg_conn::noticeHooks, PGNoticeHooks::noticeRec, PGNoticeHooks::noticeRecArg, and NULL.
Referenced by ECPGconnect().
{ PQnoticeReceiver old; if (conn == NULL) return NULL; old = conn->noticeHooks.noticeRec; if (proc) { conn->noticeHooks.noticeRec = proc; conn->noticeHooks.noticeRecArg = arg; } return old; }
int PQsocket | ( | const PGconn * | conn | ) |
Definition at line 5275 of file fe-connect.c.
References pg_conn::sock.
Referenced by HandleCopyStream(), libpq_select(), main(), threadRun(), and try_complete_step().
{ if (!conn) return -1; return conn->sock; }
ConnStatusType PQstatus | ( | const PGconn * | conn | ) |
Definition at line 5213 of file fe-connect.c.
References pg_conn::status.
Referenced by _connectDB(), check_conn(), connect_pg_server(), ConnectDatabase(), connectDatabase(), ConnectionUp(), connectToServer(), dblink_connect(), do_connect(), doConnect(), ecpg_raise_backend(), ECPGconnect(), GetConnection(), libpqrcv_connect(), libpqrcv_PQexec(), main(), pgfdw_xact_callback(), sql_conn(), start_postmaster(), and vacuumlo().
{ if (!conn) return CONNECTION_BAD; return conn->status; }
void PQtrace | ( | PGconn * | conn, | |
FILE * | debug_port | |||
) |
Definition at line 5380 of file fe-connect.c.
References NULL, pg_conn::Pfdebug, and PQuntrace().
PGTransactionStatusType PQtransactionStatus | ( | const PGconn * | conn | ) |
Definition at line 5221 of file fe-connect.c.
References pg_conn::asyncStatus, CONNECTION_OK, PGASYNC_IDLE, pg_conn::status, and pg_conn::xactStatus.
Referenced by dblink_open(), DisconnectDatabase(), ecpg_execute(), ECPGsetcommit(), ECPGtrans(), ECPGtransactionStatus(), ExecQueryUsingCursor(), get_prompt(), pgfdw_xact_callback(), PSQLexec(), SendQuery(), start_lo_xact(), and vacuumlo().
{ if (!conn || conn->status != CONNECTION_OK) return PQTRANS_UNKNOWN; if (conn->asyncStatus != PGASYNC_IDLE) return PQTRANS_ACTIVE; return conn->xactStatus; }
char* PQtty | ( | const PGconn * | conn | ) |
Definition at line 5197 of file fe-connect.c.
References pg_conn::pgtty.
{ if (!conn) return NULL; return conn->pgtty; }
void PQuntrace | ( | PGconn * | conn | ) |
Definition at line 5389 of file fe-connect.c.
References NULL, and pg_conn::Pfdebug.
Referenced by PQtrace().
char* PQuser | ( | const PGconn * | conn | ) |
Definition at line 5165 of file fe-connect.c.
References pg_conn::pguser.
Referenced by _connectDB(), CloneArchive(), do_connect(), exec_command(), get_prompt(), ReconnectToServer(), session_username(), and SyncVariables().
{ if (!conn) return NULL; return conn->pguser; }
static char * pwdfMatchesString | ( | char * | buf, | |
char * | token | |||
) | [static] |
Definition at line 5468 of file fe-connect.c.
References NULL.
Referenced by PasswordFromFile().
{ char *tbuf, *ttok; bool bslash = false; if (buf == NULL || token == NULL) return NULL; tbuf = buf; ttok = token; if (tbuf[0] == '*' && tbuf[1] == ':') return tbuf + 2; while (*tbuf != 0) { if (*tbuf == '\\' && !bslash) { tbuf++; bslash = true; } if (*tbuf == ':' && *ttok == 0 && !bslash) return tbuf + 1; bslash = false; if (*ttok == 0) return NULL; if (*tbuf == *ttok) { tbuf++; ttok++; } else return NULL; } return NULL; }
static bool recognized_connection_string | ( | const char * | connstr | ) | [static] |
Definition at line 4087 of file fe-connect.c.
References uri_prefix_length().
Referenced by conninfo_array_parse(), and PQsetdbLogin().
{ return uri_prefix_length(connstr) != 0 || strchr(connstr, '=') != NULL; }
static int setKeepalivesCount | ( | PGconn * | conn | ) | [static] |
Definition at line 1227 of file fe-connect.c.
References appendPQExpBuffer(), pg_conn::errorMessage, pg_conn::keepalives_count, libpq_gettext, NULL, pg_conn::sock, SOCK_ERRNO, and SOCK_STRERROR.
Referenced by PQconnectPoll().
{ int count; if (conn->keepalives_count == NULL) return 1; count = atoi(conn->keepalives_count); if (count < 0) count = 0; #ifdef TCP_KEEPCNT if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPCNT, (char *) &count, sizeof(count)) < 0) { char sebuf[256]; appendPQExpBuffer(&conn->errorMessage, libpq_gettext("setsockopt(TCP_KEEPCNT) failed: %s\n"), SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf))); return 0; } #endif return 1; }
static int setKeepalivesIdle | ( | PGconn * | conn | ) | [static] |
Definition at line 1150 of file fe-connect.c.
References appendPQExpBuffer(), pg_conn::errorMessage, pg_conn::keepalives_idle, libpq_gettext, NULL, pg_conn::sock, SOCK_ERRNO, and SOCK_STRERROR.
Referenced by PQconnectPoll().
{ int idle; if (conn->keepalives_idle == NULL) return 1; idle = atoi(conn->keepalives_idle); if (idle < 0) idle = 0; #ifdef TCP_KEEPIDLE if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPIDLE, (char *) &idle, sizeof(idle)) < 0) { char sebuf[256]; appendPQExpBuffer(&conn->errorMessage, libpq_gettext("setsockopt(TCP_KEEPIDLE) failed: %s\n"), SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf))); return 0; } #else #ifdef TCP_KEEPALIVE /* Darwin uses TCP_KEEPALIVE rather than TCP_KEEPIDLE */ if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPALIVE, (char *) &idle, sizeof(idle)) < 0) { char sebuf[256]; appendPQExpBuffer(&conn->errorMessage, libpq_gettext("setsockopt(TCP_KEEPALIVE) failed: %s\n"), SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf))); return 0; } #endif #endif return 1; }
static int setKeepalivesInterval | ( | PGconn * | conn | ) | [static] |
Definition at line 1195 of file fe-connect.c.
References appendPQExpBuffer(), pg_conn::errorMessage, pg_conn::keepalives_interval, libpq_gettext, NULL, pg_conn::sock, SOCK_ERRNO, and SOCK_STRERROR.
Referenced by PQconnectPoll().
{ int interval; if (conn->keepalives_interval == NULL) return 1; interval = atoi(conn->keepalives_interval); if (interval < 0) interval = 0; #ifdef TCP_KEEPINTVL if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPINTVL, (char *) &interval, sizeof(interval)) < 0) { char sebuf[256]; appendPQExpBuffer(&conn->errorMessage, libpq_gettext("setsockopt(TCP_KEEPINTVL) failed: %s\n"), SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf))); return 0; } #endif return 1; }
static int uri_prefix_length | ( | const char * | connstr | ) | [static] |
Definition at line 4066 of file fe-connect.c.
References short_uri_designator, and uri_designator.
Referenced by conninfo_uri_parse_options(), parse_connection_string(), and recognized_connection_string().
{ if (strncmp(connstr, uri_designator, sizeof(uri_designator) - 1) == 0) return sizeof(uri_designator) - 1; if (strncmp(connstr, short_uri_designator, sizeof(short_uri_designator) - 1) == 0) return sizeof(short_uri_designator) - 1; return 0; }
static int useKeepalives | ( | PGconn * | conn | ) | [static] |
Definition at line 1132 of file fe-connect.c.
References pg_conn::keepalives, NULL, and val.
Referenced by PQconnectPoll().
{ char *ep; int val; if (conn->keepalives == NULL) return 1; val = strtol(conn->keepalives, &ep, 10); if (*ep) return -1; return val != 0 ? 1 : 0; }
const PQEnvironmentOption EnvironmentOptions[] [static] |
{ { "PGDATESTYLE", "datestyle" }, { "PGTZ", "timezone" }, { "PGGEQO", "geqo" }, { NULL, NULL } }
Definition at line 308 of file fe-connect.c.
pgthreadlock_t pg_g_threadlock = default_threadlock |
Definition at line 385 of file fe-connect.c.
Referenced by PQregisterThreadLock().
const internalPQconninfoOption PQconninfoOptions[] [static] |
Definition at line 167 of file fe-connect.c.
const char short_uri_designator[] = "postgres://" [static] |
Definition at line 328 of file fe-connect.c.
Referenced by uri_prefix_length().
const char uri_designator[] = "postgresql://" [static] |
Definition at line 327 of file fe-connect.c.
Referenced by uri_prefix_length().