PostgreSQL Source Code  git master
fe-connect.c File Reference
#include "postgres_fe.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 "common/ip.h"
#include "common/scram-common.h"
#include "mb/pg_wchar.h"
#include "port/pg_bswap.h"
Include dependency graph for fe-connect.c:

Go to the source code of this file.

Data Structures

struct  _internalPQconninfoOption
 

Macros

#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 DefaultTargetSessionAttrs   "any"
 
#define DefaultSCRAMChannelBinding   SCRAM_CHANNEL_BINDING_TLS_UNIQUE
 
#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 PGconnmakeEmptyPGconn (void)
 
static bool fillPGconn (PGconn *conn, PQconninfoOption *connOptions)
 
static void freePGconn (PGconn *conn)
 
static void closePGconn (PGconn *conn)
 
static void release_all_addrinfo (PGconn *conn)
 
static void sendTerminateConn (PGconn *conn)
 
static PQconninfoOptionconninfo_init (PQExpBuffer errorMessage)
 
static PQconninfoOptionparse_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 PQconninfoOptionconninfo_parse (const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
 
static PQconninfoOptionconninfo_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 PQconninfoOptionconninfo_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 PQconninfoOptionconninfo_storeval (PQconninfoOption *connOptions, const char *keyword, const char *value, PQExpBuffer errorMessage, bool ignoreMissing, bool uri_decode)
 
static PQconninfoOptionconninfo_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, const char *token)
 
static char * passwordFromFile (const char *hostname, const char *port, const char *dbname, const char *username, const char *pgpassfile)
 
static void pgpassfileWarning (PGconn *conn)
 
static void default_threadlock (int acquire)
 
void pqDropConnection (PGconn *conn, bool flushInput)
 
PGconnPQconnectdbParams (const char *const *keywords, const char *const *values, int expand_dbname)
 
PGPing PQpingParams (const char *const *keywords, const char *const *values, int expand_dbname)
 
PGconnPQconnectdb (const char *conninfo)
 
PGPing PQping (const char *conninfo)
 
PGconnPQconnectStartParams (const char *const *keywords, const char *const *values, int expand_dbname)
 
PGconnPQconnectStart (const char *conninfo)
 
static int count_comma_separated_elems (const char *input)
 
static char * parse_comma_separated_list (char **startptr, bool *more)
 
PQconninfoOptionPQconndefaults (void)
 
PGconnPQsetdbLogin (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)
 
static bool saveErrorMessage (PGconn *conn, PQExpBuffer savedMessage)
 
static void restoreErrorMessage (PGconn *conn, PQExpBuffer savedMessage)
 
PostgresPollingStatusType PQconnectPoll (PGconn *conn)
 
void PQfinish (PGconn *conn)
 
void PQreset (PGconn *conn)
 
int PQresetStart (PGconn *conn)
 
PostgresPollingStatusType PQresetPoll (PGconn *conn)
 
PGcancelPQgetCancel (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)
 
PQconninfoOptionPQconninfoParse (const char *conninfo, char **errmsg)
 
PQconninfoOptionPQconninfo (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)
 
PGContextVisibility PQsetErrorContextVisibility (PGconn *conn, PGContextVisibility show_context)
 
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
 

Macro Definition Documentation

◆ DefaultAuthtype

#define DefaultAuthtype   ""

Definition at line 124 of file fe-connect.c.

◆ DefaultHost

#define DefaultHost   "localhost"

Definition at line 121 of file fe-connect.c.

Referenced by connectOptions2(), passwordFromFile(), and pqPacketSend().

◆ DefaultOption

#define DefaultOption   ""

Definition at line 123 of file fe-connect.c.

◆ DefaultSCRAMChannelBinding

#define DefaultSCRAMChannelBinding   SCRAM_CHANNEL_BINDING_TLS_UNIQUE

Definition at line 126 of file fe-connect.c.

◆ DefaultSSLMode

#define DefaultSSLMode   "disable"

Definition at line 130 of file fe-connect.c.

Referenced by connectOptions2().

◆ DefaultTargetSessionAttrs

#define DefaultTargetSessionAttrs   "any"

Definition at line 125 of file fe-connect.c.

◆ DefaultTty

#define DefaultTty   ""

Definition at line 122 of file fe-connect.c.

◆ ERRCODE_APPNAME_UNKNOWN

#define ERRCODE_APPNAME_UNKNOWN   "42704"

Definition at line 91 of file fe-connect.c.

Referenced by PQconnectPoll().

◆ ERRCODE_CANNOT_CONNECT_NOW

#define ERRCODE_CANNOT_CONNECT_NOW   "57P03"

Definition at line 96 of file fe-connect.c.

Referenced by internal_ping(), and ProcessStartupPacket().

◆ ERRCODE_INVALID_PASSWORD

#define ERRCODE_INVALID_PASSWORD   "28P01"

Definition at line 94 of file fe-connect.c.

Referenced by auth_failed(), pgpassfileWarning(), and recv_password_packet().

◆ LINELEN

#define LINELEN   NAMEDATALEN*5

Referenced by passwordFromFile().

◆ MAXBUFSIZE

#define MAXBUFSIZE   256

Definition at line 4478 of file fe-connect.c.

Referenced by parseServiceFile().

◆ PGPASSFILE

#define PGPASSFILE   ".pgpass"

Definition at line 80 of file fe-connect.c.

Referenced by connectOptions2().

Typedef Documentation

◆ internalPQconninfoOption

Function Documentation

◆ closePGconn()

static void closePGconn ( PGconn conn)
static

Definition at line 3585 of file fe-connect.c.

References pg_conn::asyncStatus, CONNECTION_BAD, pg_conn::errorMessage, free, pg_conn::lobjfuncs, pgNotify::next, pgParameterStatus::next, pg_conn::nonblocking, pg_conn::notifyHead, pg_conn::notifyTail, PGASYNC_IDLE, pqClearAsyncResult(), pqDropConnection(), pg_conn::pstatus, release_all_addrinfo(), resetPQExpBuffer(), sendTerminateConn(), and pg_conn::status.

Referenced by PQfinish(), PQreset(), and PQresetStart().

3586 {
3587  PGnotify *notify;
3588  pgParameterStatus *pstatus;
3589 
3590  sendTerminateConn(conn);
3591 
3592  /*
3593  * Must reset the blocking status so a possible reconnect will work.
3594  *
3595  * Don't call PQsetnonblocking() because it will fail if it's unable to
3596  * flush the connection.
3597  */
3598  conn->nonblocking = false;
3599 
3600  /*
3601  * Close the connection, reset all transient state, flush I/O buffers.
3602  */
3603  pqDropConnection(conn, true);
3604  conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just absent */
3605  conn->asyncStatus = PGASYNC_IDLE;
3606  pqClearAsyncResult(conn); /* deallocate result */
3608  release_all_addrinfo(conn);
3609 
3610  notify = conn->notifyHead;
3611  while (notify != NULL)
3612  {
3613  PGnotify *prev = notify;
3614 
3615  notify = notify->next;
3616  free(prev);
3617  }
3618  conn->notifyHead = conn->notifyTail = NULL;
3619  pstatus = conn->pstatus;
3620  while (pstatus != NULL)
3621  {
3622  pgParameterStatus *prev = pstatus;
3623 
3624  pstatus = pstatus->next;
3625  free(prev);
3626  }
3627  conn->pstatus = NULL;
3628  if (conn->lobjfuncs)
3629  free(conn->lobjfuncs);
3630  conn->lobjfuncs = NULL;
3631 }
static void release_all_addrinfo(PGconn *conn)
Definition: fe-connect.c:3530
PGnotify * notifyHead
Definition: libpq-int.h:392
void pqDropConnection(PGconn *conn, bool flushInput)
Definition: fe-connect.c:431
static void sendTerminateConn(PGconn *conn)
Definition: fe-connect.c:3558
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:381
pgParameterStatus * pstatus
Definition: libpq-int.h:422
struct pgNotify * next
Definition: libpq-fe.h:167
PQExpBufferData errorMessage
Definition: libpq-int.h:494
#define free(a)
Definition: header.h:65
struct pgParameterStatus * next
Definition: libpq-int.h:258
ConnStatusType status
Definition: libpq-int.h:380
PGnotify * notifyTail
Definition: libpq-int.h:393
bool nonblocking
Definition: libpq-int.h:387
void pqClearAsyncResult(PGconn *conn)
Definition: fe-exec.c:726
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:145
PGlobjfuncs * lobjfuncs
Definition: libpq-int.h:427

◆ connectDBComplete()

static int connectDBComplete ( PGconn conn)
static

Definition at line 1841 of file fe-connect.c.

References pg_conn::addr_cur, pg_conn_host::addrlist, pg_conn::connect_timeout, CONNECTION_BAD, CONNECTION_NEEDED, pg_conn::connhost, pg_conn::errorMessage, flag(), pg_conn::nconnhost, PGRES_POLLING_OK, PGRES_POLLING_READING, PGRES_POLLING_WRITING, PQconnectPoll(), pqDropConnection(), pqWaitTimed(), resetPQExpBuffer(), pg_conn::status, and pg_conn::whichhost.

Referenced by internal_ping(), PQconnectdb(), PQconnectdbParams(), PQreset(), and PQsetdbLogin().

1842 {
1844  time_t finish_time = ((time_t) -1);
1845  int timeout = 0;
1846 
1847  if (conn == NULL || conn->status == CONNECTION_BAD)
1848  return 0;
1849 
1850  /*
1851  * Set up a time limit, if connect_timeout isn't zero.
1852  */
1853  if (conn->connect_timeout != NULL)
1854  {
1855  timeout = atoi(conn->connect_timeout);
1856  if (timeout > 0)
1857  {
1858  /*
1859  * Rounding could cause connection to fail; need at least 2 secs
1860  */
1861  if (timeout < 2)
1862  timeout = 2;
1863  /* calculate the finish time based on start + timeout */
1864  finish_time = time(NULL) + timeout;
1865  }
1866  }
1867 
1868  for (;;)
1869  {
1870  int ret = 0;
1871 
1872  /*
1873  * Wait, if necessary. Note that the initial state (just after
1874  * PQconnectStart) is to wait for the socket to select for writing.
1875  */
1876  switch (flag)
1877  {
1878  case PGRES_POLLING_OK:
1879 
1880  /*
1881  * Reset stored error messages since we now have a working
1882  * connection
1883  */
1885  return 1; /* success! */
1886 
1887  case PGRES_POLLING_READING:
1888  ret = pqWaitTimed(1, 0, conn, finish_time);
1889  if (ret == -1)
1890  {
1891  conn->status = CONNECTION_BAD;
1892  return 0;
1893  }
1894  break;
1895 
1896  case PGRES_POLLING_WRITING:
1897  ret = pqWaitTimed(0, 1, conn, finish_time);
1898  if (ret == -1)
1899  {
1900  conn->status = CONNECTION_BAD;
1901  return 0;
1902  }
1903  break;
1904 
1905  default:
1906  /* Just in case we failed to set it in PQconnectPoll */
1907  conn->status = CONNECTION_BAD;
1908  return 0;
1909  }
1910 
1911  if (ret == 1) /* connect_timeout elapsed */
1912  {
1913  /*
1914  * If there are no more hosts, return (the error message is
1915  * already set)
1916  */
1917  if (++conn->whichhost >= conn->nconnhost)
1918  {
1919  conn->whichhost = 0;
1920  conn->status = CONNECTION_BAD;
1921  return 0;
1922  }
1923 
1924  /*
1925  * Attempt connection to the next host, starting the
1926  * connect_timeout timer
1927  */
1928  pqDropConnection(conn, true);
1929  conn->addr_cur = conn->connhost[conn->whichhost].addrlist;
1930  conn->status = CONNECTION_NEEDED;
1931  if (conn->connect_timeout != NULL)
1932  finish_time = time(NULL) + timeout;
1933  }
1934 
1935  /*
1936  * Now try to advance the state machine.
1937  */
1938  flag = PQconnectPoll(conn);
1939  }
1940 }
struct addrinfo * addr_cur
Definition: libpq-int.h:414
void pqDropConnection(PGconn *conn, bool flushInput)
Definition: fe-connect.c:431
int pqWaitTimed(int forRead, int forWrite, PGconn *conn, time_t finish_time)
Definition: fe-misc.c:997
char * connect_timeout
Definition: libpq-int.h:336
pg_conn_host * connhost
Definition: libpq-int.h:398
char * flag(int b)
Definition: test-ctype.c:33
PostgresPollingStatusType PQconnectPoll(PGconn *conn)
Definition: fe-connect.c:2003
PQExpBufferData errorMessage
Definition: libpq-int.h:494
struct addrinfo * addrlist
Definition: libpq-int.h:315
ConnStatusType status
Definition: libpq-int.h:380
PostgresPollingStatusType
Definition: libpq-fe.h:72
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:145
int nconnhost
Definition: libpq-int.h:396
int whichhost
Definition: libpq-int.h:397

◆ connectDBStart()

static int connectDBStart ( PGconn conn)
static

Definition at line 1688 of file fe-connect.c.

References pg_conn::addr_cur, pg_conn_host::addrlist, addrinfo::ai_family, addrinfo::ai_flags, AI_NUMERICHOST, addrinfo::ai_socktype, appendPQExpBuffer(), Assert, CHT_HOST_ADDRESS, CHT_HOST_NAME, CHT_UNIX_SOCKET, CONNECTION_BAD, CONNECTION_NEEDED, pg_conn::connhost, pg_conn::errorMessage, gai_strerror, pg_conn_host::host, pg_conn_host::hostaddr, i, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, libpq_gettext, MAXPGPATH, MemSet, pg_conn::nconnhost, pg_conn::options_valid, pg_conn::outCount, pg_freeaddrinfo_all(), pg_getaddrinfo_all(), PG_PROTOCOL, PGRES_POLLING_WRITING, pg_conn_host::port, PQconnectPoll(), pqDropConnection(), pg_conn::pversion, pg_conn::send_appname, snprintf(), pg_conn::sslmode, pg_conn::status, pg_conn_host::type, UNIXSOCK_PATH, UNIXSOCK_PATH_BUFLEN, and pg_conn::whichhost.

Referenced by PQconnectStart(), PQconnectStartParams(), PQreset(), PQresetStart(), and PQsetdbLogin().

1689 {
1690  char portstr[MAXPGPATH];
1691  int ret;
1692  int i;
1693 
1694  if (!conn)
1695  return 0;
1696 
1697  if (!conn->options_valid)
1698  goto connect_errReturn;
1699 
1700  /* Ensure our buffers are empty */
1701  conn->inStart = conn->inCursor = conn->inEnd = 0;
1702  conn->outCount = 0;
1703 
1704  /*
1705  * Look up socket addresses for each possible host using
1706  * pg_getaddrinfo_all.
1707  */
1708  for (i = 0; i < conn->nconnhost; ++i)
1709  {
1710  pg_conn_host *ch = &conn->connhost[i];
1711  struct addrinfo hint;
1712  int thisport;
1713 
1714  /* Initialize hint structure */
1715  MemSet(&hint, 0, sizeof(hint));
1716  hint.ai_socktype = SOCK_STREAM;
1717  hint.ai_family = AF_UNSPEC;
1718 
1719  /* Figure out the port number we're going to use. */
1720  if (ch->port == NULL || ch->port[0] == '\0')
1721  thisport = DEF_PGPORT;
1722  else
1723  {
1724  thisport = atoi(ch->port);
1725  if (thisport < 1 || thisport > 65535)
1726  {
1728  libpq_gettext("invalid port number: \"%s\"\n"),
1729  ch->port);
1730  conn->options_valid = false;
1731  goto connect_errReturn;
1732  }
1733  }
1734  snprintf(portstr, sizeof(portstr), "%d", thisport);
1735 
1736  /* Use pg_getaddrinfo_all() to resolve the address */
1737  ret = 1;
1738  switch (ch->type)
1739  {
1740  case CHT_HOST_NAME:
1741  ret = pg_getaddrinfo_all(ch->host, portstr, &hint, &ch->addrlist);
1742  if (ret || !ch->addrlist)
1744  libpq_gettext("could not translate host name \"%s\" to address: %s\n"),
1745  ch->host, gai_strerror(ret));
1746  break;
1747 
1748  case CHT_HOST_ADDRESS:
1749  hint.ai_flags = AI_NUMERICHOST;
1750  ret = pg_getaddrinfo_all(ch->hostaddr, portstr, &hint, &ch->addrlist);
1751  if (ret || !ch->addrlist)
1753  libpq_gettext("could not parse network address \"%s\": %s\n"),
1754  ch->host, gai_strerror(ret));
1755  break;
1756 
1757  case CHT_UNIX_SOCKET:
1758 #ifdef HAVE_UNIX_SOCKETS
1759  hint.ai_family = AF_UNIX;
1760  UNIXSOCK_PATH(portstr, thisport, ch->host);
1761  if (strlen(portstr) >= UNIXSOCK_PATH_BUFLEN)
1762  {
1764  libpq_gettext("Unix-domain socket path \"%s\" is too long (maximum %d bytes)\n"),
1765  portstr,
1766  (int) (UNIXSOCK_PATH_BUFLEN - 1));
1767  conn->options_valid = false;
1768  goto connect_errReturn;
1769  }
1770 
1771  /*
1772  * NULL hostname tells pg_getaddrinfo_all to parse the service
1773  * name as a Unix-domain socket path.
1774  */
1775  ret = pg_getaddrinfo_all(NULL, portstr, &hint, &ch->addrlist);
1776  if (ret || !ch->addrlist)
1778  libpq_gettext("could not translate Unix-domain socket path \"%s\" to address: %s\n"),
1779  portstr, gai_strerror(ret));
1780  break;
1781 #else
1782  Assert(false);
1783  conn->options_valid = false;
1784  goto connect_errReturn;
1785 #endif
1786  }
1787  if (ret || !ch->addrlist)
1788  {
1789  if (ch->addrlist)
1790  {
1791  pg_freeaddrinfo_all(hint.ai_family, ch->addrlist);
1792  ch->addrlist = NULL;
1793  }
1794  conn->options_valid = false;
1795  goto connect_errReturn;
1796  }
1797  }
1798 
1799 #ifdef USE_SSL
1800  /* setup values based on SSL mode */
1801  if (conn->sslmode[0] == 'd') /* "disable" */
1802  conn->allow_ssl_try = false;
1803  else if (conn->sslmode[0] == 'a') /* "allow" */
1804  conn->wait_ssl_try = true;
1805 #endif
1806 
1807  /*
1808  * Set up to try to connect, with protocol 3.0 as the first attempt.
1809  */
1810  conn->whichhost = 0;
1811  conn->addr_cur = conn->connhost[0].addrlist;
1812  conn->pversion = PG_PROTOCOL(3, 0);
1813  conn->send_appname = true;
1814  conn->status = CONNECTION_NEEDED;
1815 
1816  /*
1817  * The code for processing CONNECTION_NEEDED state is in PQconnectPoll(),
1818  * so that it can easily be re-executed if needed again during the
1819  * asynchronous startup process. However, we must run it once here,
1820  * because callers expect a success return from this routine to mean that
1821  * we are in PGRES_POLLING_WRITING connection state.
1822  */
1823  if (PQconnectPoll(conn) == PGRES_POLLING_WRITING)
1824  return 1;
1825 
1826 connect_errReturn:
1827  pqDropConnection(conn, true);
1828  conn->status = CONNECTION_BAD;
1829  return 0;
1830 }
int inEnd
Definition: libpq-int.h:434
void pg_freeaddrinfo_all(int hint_ai_family, struct addrinfo *ai)
Definition: ip.c:88
#define UNIXSOCK_PATH(path, port, sockdir)
Definition: pqcomm.h:70
int inStart
Definition: libpq-int.h:432
struct addrinfo * addr_cur
Definition: libpq-int.h:414
#define UNIXSOCK_PATH_BUFLEN
Definition: pqcomm.h:86
int outCount
Definition: libpq-int.h:439
char * host
Definition: libpq-int.h:308
#define MemSet(start, val, len)
Definition: c.h:908
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
void pqDropConnection(PGconn *conn, bool flushInput)
Definition: fe-connect.c:431
#define AI_NUMERICHOST
Definition: getaddrinfo.h:73
pg_conn_host_type type
Definition: libpq-int.h:307
#define gai_strerror
Definition: getaddrinfo.h:146
int pg_getaddrinfo_all(const char *hostname, const char *servname, const struct addrinfo *hintp, struct addrinfo **result)
Definition: ip.c:57
#define MAXPGPATH
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
char * hostaddr
Definition: libpq-int.h:309
pg_conn_host * connhost
Definition: libpq-int.h:398
char * sslmode
Definition: libpq-int.h:353
PostgresPollingStatusType PQconnectPoll(PGconn *conn)
Definition: fe-connect.c:2003
PQExpBufferData errorMessage
Definition: libpq-int.h:494
bool options_valid
Definition: libpq-int.h:386
#define Assert(condition)
Definition: c.h:699
struct addrinfo * addrlist
Definition: libpq-int.h:315
ProtocolVersion pversion
Definition: libpq-int.h:405
ConnStatusType status
Definition: libpq-int.h:380
int i
int inCursor
Definition: libpq-int.h:433
char * port
Definition: libpq-int.h:310
int nconnhost
Definition: libpq-int.h:396
#define PG_PROTOCOL(m, n)
Definition: pqcomm.h:106
int whichhost
Definition: libpq-int.h:397
#define libpq_gettext(x)
Definition: libpq-int.h:760
bool send_appname
Definition: libpq-int.h:417

◆ connectFailureMessage()

static void connectFailureMessage ( PGconn conn,
int  errorno 
)
static

Definition at line 1425 of file fe-connect.c.

References SockAddr::addr, appendPQExpBuffer(), CHT_HOST_ADDRESS, pg_conn::connhost, pg_conn::errorMessage, pg_conn_host::host, pg_conn_host::hostaddr, inet_net_ntop(), IS_AF_UNIX, libpq_gettext, NI_MAXHOST, NI_NUMERICSERV, pg_getnameinfo_all(), pg_conn_host::port, pg_conn::raddr, SockAddr::salen, SOCK_STRERROR, strlcpy(), pg_conn_host::type, and pg_conn::whichhost.

Referenced by PQconnectPoll().

1426 {
1427  char sebuf[256];
1428 
1429 #ifdef HAVE_UNIX_SOCKETS
1430  if (IS_AF_UNIX(conn->raddr.addr.ss_family))
1431  {
1432  char service[NI_MAXHOST];
1433 
1434  pg_getnameinfo_all(&conn->raddr.addr, conn->raddr.salen,
1435  NULL, 0,
1436  service, sizeof(service),
1437  NI_NUMERICSERV);
1439  libpq_gettext("could not connect to server: %s\n"
1440  "\tIs the server running locally and accepting\n"
1441  "\tconnections on Unix domain socket \"%s\"?\n"),
1442  SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),
1443  service);
1444  }
1445  else
1446 #endif /* HAVE_UNIX_SOCKETS */
1447  {
1448  char host_addr[NI_MAXHOST];
1449  const char *displayed_host;
1450  const char *displayed_port;
1451  struct sockaddr_storage *addr = &conn->raddr.addr;
1452 
1453  /*
1454  * Optionally display the network address with the hostname. This is
1455  * useful to distinguish between IPv4 and IPv6 connections.
1456  */
1457  if (conn->connhost[conn->whichhost].type == CHT_HOST_ADDRESS)
1458  strlcpy(host_addr, conn->connhost[conn->whichhost].hostaddr, NI_MAXHOST);
1459  else if (addr->ss_family == AF_INET)
1460  {
1461  if (inet_net_ntop(AF_INET,
1462  &((struct sockaddr_in *) addr)->sin_addr.s_addr,
1463  32,
1464  host_addr, sizeof(host_addr)) == NULL)
1465  strcpy(host_addr, "???");
1466  }
1467 #ifdef HAVE_IPV6
1468  else if (addr->ss_family == AF_INET6)
1469  {
1470  if (inet_net_ntop(AF_INET6,
1471  &((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr,
1472  128,
1473  host_addr, sizeof(host_addr)) == NULL)
1474  strcpy(host_addr, "???");
1475  }
1476 #endif
1477  else
1478  strcpy(host_addr, "???");
1479 
1480  /* To which host and port were we actually connecting? */
1481  if (conn->connhost[conn->whichhost].type == CHT_HOST_ADDRESS)
1482  displayed_host = conn->connhost[conn->whichhost].hostaddr;
1483  else
1484  displayed_host = conn->connhost[conn->whichhost].host;
1485  displayed_port = conn->connhost[conn->whichhost].port;
1486  if (displayed_port == NULL || displayed_port[0] == '\0')
1487  displayed_port = DEF_PGPORT_STR;
1488 
1489  /*
1490  * If the user did not supply an IP address using 'hostaddr', and
1491  * 'host' was missing or does not match our lookup, display the
1492  * looked-up IP address.
1493  */
1494  if (conn->connhost[conn->whichhost].type != CHT_HOST_ADDRESS &&
1495  strcmp(displayed_host, host_addr) != 0)
1497  libpq_gettext("could not connect to server: %s\n"
1498  "\tIs the server running on host \"%s\" (%s) and accepting\n"
1499  "\tTCP/IP connections on port %s?\n"),
1500  SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),
1501  displayed_host,
1502  host_addr,
1503  displayed_port);
1504  else
1506  libpq_gettext("could not connect to server: %s\n"
1507  "\tIs the server running on host \"%s\" and accepting\n"
1508  "\tTCP/IP connections on port %s?\n"),
1509  SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),
1510  displayed_host,
1511  displayed_port);
1512  }
1513 }
char * host
Definition: libpq-int.h:308
struct sockaddr_storage addr
Definition: pqcomm.h:64
pg_conn_host_type type
Definition: libpq-int.h:307
#define SOCK_STRERROR
Definition: libpq-int.h:774
#define NI_MAXHOST
Definition: getaddrinfo.h:88
#define IS_AF_UNIX(fam)
Definition: ip.h:24
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
char * hostaddr
Definition: libpq-int.h:309
pg_conn_host * connhost
Definition: libpq-int.h:398
ACCEPT_TYPE_ARG3 salen
Definition: pqcomm.h:65
char * inet_net_ntop(int af, const void *src, int bits, char *dst, size_t size)
Definition: inet_net_ntop.c:77
SockAddr raddr
Definition: libpq-int.h:404
PQExpBufferData errorMessage
Definition: libpq-int.h:494
#define NI_NUMERICSERV
Definition: getaddrinfo.h:81
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
int pg_getnameinfo_all(const struct sockaddr_storage *addr, int salen, char *node, int nodelen, char *service, int servicelen, int flags)
Definition: ip.c:122
char * port
Definition: libpq-int.h:310
int whichhost
Definition: libpq-int.h:397
#define libpq_gettext(x)
Definition: libpq-int.h:760

◆ connectNoDelay()

static int connectNoDelay ( PGconn conn)
static

Definition at line 1397 of file fe-connect.c.

References appendPQExpBuffer(), pg_conn::errorMessage, libpq_gettext, pg_conn::sock, SOCK_ERRNO, and SOCK_STRERROR.

Referenced by PQconnectPoll().

1398 {
1399 #ifdef TCP_NODELAY
1400  int on = 1;
1401 
1402  if (setsockopt(conn->sock, IPPROTO_TCP, TCP_NODELAY,
1403  (char *) &on,
1404  sizeof(on)) < 0)
1405  {
1406  char sebuf[256];
1407 
1409  libpq_gettext("could not set socket to TCP no delay mode: %s\n"),
1410  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
1411  return 0;
1412  }
1413 #endif
1414 
1415  return 1;
1416 }
#define SOCK_STRERROR
Definition: libpq-int.h:774
#define SOCK_ERRNO
Definition: libpq-int.h:773
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
pgsocket sock
Definition: libpq-int.h:401
PQExpBufferData errorMessage
Definition: libpq-int.h:494
#define libpq_gettext(x)
Definition: libpq-int.h:760

◆ connectOptions1()

static bool connectOptions1 ( PGconn conn,
const char *  conninfo 
)
static

Definition at line 804 of file fe-connect.c.

References CONNECTION_BAD, pg_conn::errorMessage, fillPGconn(), parse_connection_string(), PQconninfoFree(), and pg_conn::status.

Referenced by PQconnectStart(), and PQsetdbLogin().

805 {
806  PQconninfoOption *connOptions;
807 
808  /*
809  * Parse the conninfo string
810  */
811  connOptions = parse_connection_string(conninfo, &conn->errorMessage, true);
812  if (connOptions == NULL)
813  {
814  conn->status = CONNECTION_BAD;
815  /* errorMessage is already set */
816  return false;
817  }
818 
819  /*
820  * Move option values into conn structure
821  */
822  if (!fillPGconn(conn, connOptions))
823  {
824  conn->status = CONNECTION_BAD;
825  PQconninfoFree(connOptions);
826  return false;
827  }
828 
829  /*
830  * Free the option info - all is in conn now
831  */
832  PQconninfoFree(connOptions);
833 
834  return true;
835 }
static PQconninfoOption * parse_connection_string(const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:4797
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:5965
PQExpBufferData errorMessage
Definition: libpq-int.h:494
static bool fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
Definition: fe-connect.c:762
ConnStatusType status
Definition: libpq-int.h:380

◆ connectOptions2()

static bool connectOptions2 ( PGconn conn)
static

Definition at line 902 of file fe-connect.c.

References Assert, calloc, CHT_HOST_ADDRESS, CHT_HOST_NAME, CHT_UNIX_SOCKET, pg_conn::client_encoding_initial, CONNECTION_BAD, pg_conn::connhost, count_comma_separated_elems(), pg_conn::dbName, DEFAULT_PGSOCKET_DIR, DefaultHost, DefaultSSLMode, pg_conn::errorMessage, free, pg_conn_host::host, pg_conn_host::hostaddr, i, is_absolute_path, libpq_gettext, malloc, MAXPGPATH, pg_conn::nconnhost, pg_conn::options_valid, parse_comma_separated_list(), pg_conn_host::password, passwordFromFile(), pg_encoding_to_char(), pg_fe_getauthname(), pg_get_encoding_from_locale(), pg_conn::pghost, pg_conn::pghostaddr, pg_conn::pgpass, PGPASSFILE, pg_conn::pgpassfile, pg_conn::pgpassfile_used, pg_conn::pgport, pg_conn::pguser, pg_conn_host::port, pqGetHomeDirectory(), printfPQExpBuffer(), snprintf(), pg_conn::sslmode, pg_conn::status, pg_conn::target_session_attrs, pg_conn_host::type, and pg_conn::whichhost.

Referenced by PQconnectStart(), PQconnectStartParams(), and PQsetdbLogin().

903 {
904  /*
905  * Allocate memory for details about each host to which we might possibly
906  * try to connect. For that, count the number of elements in the hostaddr
907  * or host options. If neither is given, assume one host.
908  */
909  conn->whichhost = 0;
910  if (conn->pghostaddr && conn->pghostaddr[0] != '\0')
912  else if (conn->pghost && conn->pghost[0] != '\0')
914  else
915  conn->nconnhost = 1;
916  conn->connhost = (pg_conn_host *)
917  calloc(conn->nconnhost, sizeof(pg_conn_host));
918  if (conn->connhost == NULL)
919  goto oom_error;
920 
921  /*
922  * We now have one pg_conn_host structure per possible host. Fill in the
923  * host details for each one.
924  */
925  if (conn->pghostaddr != NULL && conn->pghostaddr[0] != '\0')
926  {
927  int i;
928  char *s = conn->pghostaddr;
929  bool more = true;
930 
931  for (i = 0; i < conn->nconnhost && more; i++)
932  {
933  conn->connhost[i].hostaddr = parse_comma_separated_list(&s, &more);
934  if (conn->connhost[i].hostaddr == NULL)
935  goto oom_error;
936 
937  conn->connhost[i].type = CHT_HOST_ADDRESS;
938  }
939 
940  /*
941  * If hostaddr was given, the array was allocated according to the
942  * number of elements in the hostaddr list, so it really should be the
943  * right size.
944  */
945  Assert(!more);
946  Assert(i == conn->nconnhost);
947  }
948 
949  if (conn->pghost != NULL && conn->pghost[0] != '\0')
950  {
951  int i;
952  char *s = conn->pghost;
953  bool more = true;
954 
955  for (i = 0; i < conn->nconnhost && more; i++)
956  {
957  conn->connhost[i].host = parse_comma_separated_list(&s, &more);
958  if (conn->connhost[i].host == NULL)
959  goto oom_error;
960 
961  /* Identify the type of host. */
962  if (conn->pghostaddr == NULL || conn->pghostaddr[0] == '\0')
963  {
964  conn->connhost[i].type = CHT_HOST_NAME;
965 #ifdef HAVE_UNIX_SOCKETS
966  if (is_absolute_path(conn->connhost[i].host))
967  conn->connhost[i].type = CHT_UNIX_SOCKET;
968 #endif
969  }
970  }
971  if (more || i != conn->nconnhost)
972  {
973  conn->status = CONNECTION_BAD;
975  libpq_gettext("could not match %d host names to %d hostaddr values\n"),
977  return false;
978  }
979  }
980 
981  /*
982  * If neither host or hostaddr options was given, connect to default host.
983  */
984  if ((conn->pghostaddr == NULL || conn->pghostaddr[0] == '\0') &&
985  (conn->pghost == NULL || conn->pghost[0] == '\0'))
986  {
987  Assert(conn->nconnhost == 1);
988 #ifdef HAVE_UNIX_SOCKETS
989  conn->connhost[0].host = strdup(DEFAULT_PGSOCKET_DIR);
990  conn->connhost[0].type = CHT_UNIX_SOCKET;
991 #else
992  conn->connhost[0].host = strdup(DefaultHost);
993  conn->connhost[0].type = CHT_HOST_NAME;
994 #endif
995  if (conn->connhost[0].host == NULL)
996  goto oom_error;
997  }
998 
999  /*
1000  * Next, work out the port number corresponding to each host name.
1001  */
1002  if (conn->pgport != NULL && conn->pgport[0] != '\0')
1003  {
1004  int i;
1005  char *s = conn->pgport;
1006  bool more = true;
1007 
1008  for (i = 0; i < conn->nconnhost && more; i++)
1009  {
1010  conn->connhost[i].port = parse_comma_separated_list(&s, &more);
1011  if (conn->connhost[i].port == NULL)
1012  goto oom_error;
1013  }
1014 
1015  /*
1016  * If exactly one port was given, use it for every host. Otherwise,
1017  * there must be exactly as many ports as there were hosts.
1018  */
1019  if (i == 1 && !more)
1020  {
1021  for (i = 1; i < conn->nconnhost; i++)
1022  {
1023  conn->connhost[i].port = strdup(conn->connhost[0].port);
1024  if (conn->connhost[i].port == NULL)
1025  goto oom_error;
1026  }
1027  }
1028  else if (more || i != conn->nconnhost)
1029  {
1030  conn->status = CONNECTION_BAD;
1032  libpq_gettext("could not match %d port numbers to %d hosts\n"),
1034  return false;
1035  }
1036  }
1037 
1038  /*
1039  * If user name was not given, fetch it. (Most likely, the fetch will
1040  * fail, since the only way we get here is if pg_fe_getauthname() failed
1041  * during conninfo_add_defaults(). But now we want an error message.)
1042  */
1043  if (conn->pguser == NULL || conn->pguser[0] == '\0')
1044  {
1045  if (conn->pguser)
1046  free(conn->pguser);
1047  conn->pguser = pg_fe_getauthname(&conn->errorMessage);
1048  if (!conn->pguser)
1049  {
1050  conn->status = CONNECTION_BAD;
1051  return false;
1052  }
1053  }
1054 
1055  /*
1056  * If database name was not given, default it to equal user name
1057  */
1058  if (conn->dbName == NULL || conn->dbName[0] == '\0')
1059  {
1060  if (conn->dbName)
1061  free(conn->dbName);
1062  conn->dbName = strdup(conn->pguser);
1063  if (!conn->dbName)
1064  goto oom_error;
1065  }
1066 
1067  /*
1068  * Supply default password if none given. Note that the password might be
1069  * different for each host/port pair.
1070  */
1071  if (conn->pgpass == NULL || conn->pgpass[0] == '\0')
1072  {
1073  /* If password file wasn't specified, use ~/PGPASSFILE */
1074  if (conn->pgpassfile == NULL || conn->pgpassfile[0] == '\0')
1075  {
1076  char homedir[MAXPGPATH];
1077 
1078  if (pqGetHomeDirectory(homedir, sizeof(homedir)))
1079  {
1080  if (conn->pgpassfile)
1081  free(conn->pgpassfile);
1082  conn->pgpassfile = malloc(MAXPGPATH);
1083  if (!conn->pgpassfile)
1084  goto oom_error;
1085  snprintf(conn->pgpassfile, MAXPGPATH, "%s/%s",
1086  homedir, PGPASSFILE);
1087  }
1088  }
1089 
1090  if (conn->pgpassfile != NULL && conn->pgpassfile[0] != '\0')
1091  {
1092  int i;
1093 
1094  for (i = 0; i < conn->nconnhost; i++)
1095  {
1096  /*
1097  * Try to get a password for this host from pgpassfile. We use
1098  * host name rather than host address in the same manner as
1099  * PQhost().
1100  */
1101  char *pwhost = conn->connhost[i].host;
1102 
1103  if (conn->connhost[i].type == CHT_HOST_ADDRESS &&
1104  conn->connhost[i].host != NULL &&
1105  conn->connhost[i].host[0] != '\0')
1106  pwhost = conn->connhost[i].hostaddr;
1107 
1108  conn->connhost[i].password =
1109  passwordFromFile(pwhost,
1110  conn->connhost[i].port,
1111  conn->dbName,
1112  conn->pguser,
1113  conn->pgpassfile);
1114  /* If we got one, set pgpassfile_used */
1115  if (conn->connhost[i].password != NULL)
1116  conn->pgpassfile_used = true;
1117  }
1118  }
1119  }
1120 
1121  /*
1122  * validate sslmode option
1123  */
1124  if (conn->sslmode)
1125  {
1126  if (strcmp(conn->sslmode, "disable") != 0
1127  && strcmp(conn->sslmode, "allow") != 0
1128  && strcmp(conn->sslmode, "prefer") != 0
1129  && strcmp(conn->sslmode, "require") != 0
1130  && strcmp(conn->sslmode, "verify-ca") != 0
1131  && strcmp(conn->sslmode, "verify-full") != 0)
1132  {
1133  conn->status = CONNECTION_BAD;
1135  libpq_gettext("invalid sslmode value: \"%s\"\n"),
1136  conn->sslmode);
1137  return false;
1138  }
1139 
1140 #ifndef USE_SSL
1141  switch (conn->sslmode[0])
1142  {
1143  case 'a': /* "allow" */
1144  case 'p': /* "prefer" */
1145 
1146  /*
1147  * warn user that an SSL connection will never be negotiated
1148  * since SSL was not compiled in?
1149  */
1150  break;
1151 
1152  case 'r': /* "require" */
1153  case 'v': /* "verify-ca" or "verify-full" */
1154  conn->status = CONNECTION_BAD;
1156  libpq_gettext("sslmode value \"%s\" invalid when SSL support is not compiled in\n"),
1157  conn->sslmode);
1158  return false;
1159  }
1160 #endif
1161  }
1162  else
1163  {
1164  conn->sslmode = strdup(DefaultSSLMode);
1165  if (!conn->sslmode)
1166  goto oom_error;
1167  }
1168 
1169  /*
1170  * Resolve special "auto" client_encoding from the locale
1171  */
1172  if (conn->client_encoding_initial &&
1173  strcmp(conn->client_encoding_initial, "auto") == 0)
1174  {
1177  if (!conn->client_encoding_initial)
1178  goto oom_error;
1179  }
1180 
1181  /*
1182  * Validate target_session_attrs option.
1183  */
1184  if (conn->target_session_attrs)
1185  {
1186  if (strcmp(conn->target_session_attrs, "any") != 0
1187  && strcmp(conn->target_session_attrs, "read-write") != 0)
1188  {
1189  conn->status = CONNECTION_BAD;
1191  libpq_gettext("invalid target_session_attrs value: \"%s\"\n"),
1192  conn->target_session_attrs);
1193  return false;
1194  }
1195  }
1196 
1197  /*
1198  * Only if we get this far is it appropriate to try to connect. (We need a
1199  * state flag, rather than just the boolean result of this function, in
1200  * case someone tries to PQreset() the PGconn.)
1201  */
1202  conn->options_valid = true;
1203 
1204  return true;
1205 
1206 oom_error:
1207  conn->status = CONNECTION_BAD;
1209  libpq_gettext("out of memory\n"));
1210  return false;
1211 }
#define calloc(a, b)
Definition: header.h:55
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
char * pgpassfile
Definition: libpq-int.h:345
char * host
Definition: libpq-int.h:308
char * dbName
Definition: libpq-int.h:341
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
bool pgpassfile_used
Definition: libpq-int.h:409
#define DefaultSSLMode
Definition: fe-connect.c:130
pg_conn_host_type type
Definition: libpq-int.h:307
char * client_encoding_initial
Definition: libpq-int.h:337
#define malloc(a)
Definition: header.h:50
#define PGPASSFILE
Definition: fe-connect.c:80
#define MAXPGPATH
char * hostaddr
Definition: libpq-int.h:309
pg_conn_host * connhost
Definition: libpq-int.h:398
#define is_absolute_path(filename)
Definition: port.h:86
static int count_comma_separated_elems(const char *input)
Definition: fe-connect.c:841
char * target_session_attrs
Definition: libpq-int.h:366
char * pguser
Definition: libpq-int.h:343
char * sslmode
Definition: libpq-int.h:353
char * pg_fe_getauthname(PQExpBuffer errorMessage)
Definition: fe-auth.c:1043
PQExpBufferData errorMessage
Definition: libpq-int.h:494
static char * passwordFromFile(const char *hostname, const char *port, const char *dbname, const char *username, const char *pgpassfile)
Definition: fe-connect.c:6379
int pg_get_encoding_from_locale(const char *ctype, bool write_message)
Definition: chklocale.c:433
#define free(a)
Definition: header.h:65
const char * pg_encoding_to_char(int encoding)
Definition: encnames.c:607
bool options_valid
Definition: libpq-int.h:386
#define Assert(condition)
Definition: c.h:699
char * pgpass
Definition: libpq-int.h:344
ConnStatusType status
Definition: libpq-int.h:380
static char * parse_comma_separated_list(char **startptr, bool *more)
Definition: fe-connect.c:865
#define DefaultHost
Definition: fe-connect.c:121
char * pghostaddr
Definition: libpq-int.h:330
bool pqGetHomeDirectory(char *buf, int bufsize)
Definition: fe-connect.c:6543
int i
char * port
Definition: libpq-int.h:310
char * pgport
Definition: libpq-int.h:333
int nconnhost
Definition: libpq-int.h:396
int whichhost
Definition: libpq-int.h:397
#define libpq_gettext(x)
Definition: libpq-int.h:760
char * pghost
Definition: libpq-int.h:325
#define DEFAULT_PGSOCKET_DIR
char * password
Definition: libpq-int.h:312

◆ conninfo_add_defaults()

static bool conninfo_add_defaults ( PQconninfoOption options,
PQExpBuffer  errorMessage 
)
static

Definition at line 5193 of file fe-connect.c.

References _PQconninfoOption::compiled, _PQconninfoOption::envvar, _PQconninfoOption::keyword, libpq_gettext, parseServiceInfo(), pg_fe_getauthname(), printfPQExpBuffer(), and _PQconninfoOption::val.

Referenced by conninfo_array_parse(), conninfo_parse(), conninfo_uri_parse(), and PQconndefaults().

5194 {
5196  char *tmp;
5197 
5198  /*
5199  * If there's a service spec, use it to obtain any not-explicitly-given
5200  * parameters. Ignore error if no error message buffer is passed because
5201  * there is no way to pass back the failure message.
5202  */
5203  if (parseServiceInfo(options, errorMessage) != 0 && errorMessage)
5204  return false;
5205 
5206  /*
5207  * Get the fallback resources for parameters not specified in the conninfo
5208  * string nor the service.
5209  */
5210  for (option = options; option->keyword != NULL; option++)
5211  {
5212  if (option->val != NULL)
5213  continue; /* Value was in conninfo or service */
5214 
5215  /*
5216  * Try to get the environment variable fallback
5217  */
5218  if (option->envvar != NULL)
5219  {
5220  if ((tmp = getenv(option->envvar)) != NULL)
5221  {
5222  option->val = strdup(tmp);
5223  if (!option->val)
5224  {
5225  if (errorMessage)
5226  printfPQExpBuffer(errorMessage,
5227  libpq_gettext("out of memory\n"));
5228  return false;
5229  }
5230  continue;
5231  }
5232  }
5233 
5234  /*
5235  * Interpret the deprecated PGREQUIRESSL environment variable. Per
5236  * tradition, translate values starting with "1" to sslmode=require,
5237  * and ignore other values. Given both PGREQUIRESSL=1 and PGSSLMODE,
5238  * PGSSLMODE takes precedence; the opposite was true before v9.3.
5239  */
5240  if (strcmp(option->keyword, "sslmode") == 0)
5241  {
5242  const char *requiresslenv = getenv("PGREQUIRESSL");
5243 
5244  if (requiresslenv != NULL && requiresslenv[0] == '1')
5245  {
5246  option->val = strdup("require");
5247  if (!option->val)
5248  {
5249  if (errorMessage)
5250  printfPQExpBuffer(errorMessage,
5251  libpq_gettext("out of memory\n"));
5252  return false;
5253  }
5254  continue;
5255  }
5256  }
5257 
5258  /*
5259  * No environment variable specified or the variable isn't set - try
5260  * compiled-in default
5261  */
5262  if (option->compiled != NULL)
5263  {
5264  option->val = strdup(option->compiled);
5265  if (!option->val)
5266  {
5267  if (errorMessage)
5268  printfPQExpBuffer(errorMessage,
5269  libpq_gettext("out of memory\n"));
5270  return false;
5271  }
5272  continue;
5273  }
5274 
5275  /*
5276  * Special handling for "user" option. Note that if pg_fe_getauthname
5277  * fails, we just leave the value as NULL; there's no need for this to
5278  * be an error condition if the caller provides a user name. The only
5279  * reason we do this now at all is so that callers of PQconndefaults
5280  * will see a correct default (barring error, of course).
5281  */
5282  if (strcmp(option->keyword, "user") == 0)
5283  {
5284  option->val = pg_fe_getauthname(NULL);
5285  continue;
5286  }
5287  }
5288 
5289  return true;
5290 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
char * pg_fe_getauthname(PQExpBuffer errorMessage)
Definition: fe-auth.c:1043
static int parseServiceInfo(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:4491
#define libpq_gettext(x)
Definition: libpq-int.h:760

◆ conninfo_array_parse()

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 5029 of file fe-connect.c.

References conninfo_add_defaults(), conninfo_init(), free, i, _internalPQconninfoOption::keyword, _PQconninfoOption::keyword, libpq_gettext, options, parse_connection_string(), PQconninfoFree(), printfPQExpBuffer(), recognized_connection_string(), _internalPQconninfoOption::val, and _PQconninfoOption::val.

Referenced by PQconnectStartParams().

5032 {
5034  PQconninfoOption *dbname_options = NULL;
5036  int i = 0;
5037 
5038  /*
5039  * If expand_dbname is non-zero, check keyword "dbname" to see if val is
5040  * actually a recognized connection string.
5041  */
5042  while (expand_dbname && keywords[i])
5043  {
5044  const char *pname = keywords[i];
5045  const char *pvalue = values[i];
5046 
5047  /* first find "dbname" if any */
5048  if (strcmp(pname, "dbname") == 0 && pvalue)
5049  {
5050  /*
5051  * If value is a connection string, parse it, but do not use
5052  * defaults here -- those get picked up later. We only want to
5053  * override for those parameters actually passed.
5054  */
5055  if (recognized_connection_string(pvalue))
5056  {
5057  dbname_options = parse_connection_string(pvalue, errorMessage, false);
5058  if (dbname_options == NULL)
5059  return NULL;
5060  }
5061  break;
5062  }
5063  ++i;
5064  }
5065 
5066  /* Make a working copy of PQconninfoOptions */
5067  options = conninfo_init(errorMessage);
5068  if (options == NULL)
5069  {
5070  PQconninfoFree(dbname_options);
5071  return NULL;
5072  }
5073 
5074  /* Parse the keywords/values arrays */
5075  i = 0;
5076  while (keywords[i])
5077  {
5078  const char *pname = keywords[i];
5079  const char *pvalue = values[i];
5080 
5081  if (pvalue != NULL && pvalue[0] != '\0')
5082  {
5083  /* Search for the param record */
5084  for (option = options; option->keyword != NULL; option++)
5085  {
5086  if (strcmp(option->keyword, pname) == 0)
5087  break;
5088  }
5089 
5090  /* Check for invalid connection option */
5091  if (option->keyword == NULL)
5092  {
5093  printfPQExpBuffer(errorMessage,
5094  libpq_gettext("invalid connection option \"%s\"\n"),
5095  pname);
5096  PQconninfoFree(options);
5097  PQconninfoFree(dbname_options);
5098  return NULL;
5099  }
5100 
5101  /*
5102  * If we are on the first dbname parameter, and we have a parsed
5103  * connection string, copy those parameters across, overriding any
5104  * existing previous settings.
5105  */
5106  if (strcmp(pname, "dbname") == 0 && dbname_options)
5107  {
5108  PQconninfoOption *str_option;
5109 
5110  for (str_option = dbname_options; str_option->keyword != NULL; str_option++)
5111  {
5112  if (str_option->val != NULL)
5113  {
5114  int k;
5115 
5116  for (k = 0; options[k].keyword; k++)
5117  {
5118  if (strcmp(options[k].keyword, str_option->keyword) == 0)
5119  {
5120  if (options[k].val)
5121  free(options[k].val);
5122  options[k].val = strdup(str_option->val);
5123  if (!options[k].val)
5124  {
5125  printfPQExpBuffer(errorMessage,
5126  libpq_gettext("out of memory\n"));
5127  PQconninfoFree(options);
5128  PQconninfoFree(dbname_options);
5129  return NULL;
5130  }
5131  break;
5132  }
5133  }
5134  }
5135  }
5136 
5137  /*
5138  * Forget the parsed connection string, so that any subsequent
5139  * dbname parameters will not be expanded.
5140  */
5141  PQconninfoFree(dbname_options);
5142  dbname_options = NULL;
5143  }
5144  else
5145  {
5146  /*
5147  * Store the value, overriding previous settings
5148  */
5149  if (option->val)
5150  free(option->val);
5151  option->val = strdup(pvalue);
5152  if (!option->val)
5153  {
5154  printfPQExpBuffer(errorMessage,
5155  libpq_gettext("out of memory\n"));
5156  PQconninfoFree(options);
5157  PQconninfoFree(dbname_options);
5158  return NULL;
5159  }
5160  }
5161  }
5162  ++i;
5163  }
5164  PQconninfoFree(dbname_options);
5165 
5166  /*
5167  * Add in defaults if the caller wants that.
5168  */
5169  if (use_defaults)
5170  {
5171  if (!conninfo_add_defaults(options, errorMessage))
5172  {
5173  PQconninfoFree(options);
5174  return NULL;
5175  }
5176  }
5177 
5178  return options;
5179 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
static PQconninfoOption * conninfo_init(PQExpBuffer errorMessage)
Definition: fe-connect.c:4757
static PQconninfoOption * parse_connection_string(const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:4797
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:5965
static char ** options
static bool recognized_connection_string(const char *connstr)
Definition: fe-connect.c:4840
#define free(a)
Definition: header.h:65
static bool conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5193
static Datum values[MAXATTR]
Definition: bootstrap.c:164
int i
long val
Definition: informix.c:689
#define libpq_gettext(x)
Definition: libpq-int.h:760

◆ conninfo_find()

static PQconninfoOption * conninfo_find ( PQconninfoOption connOptions,
const char *  keyword 
)
static

Definition at line 5906 of file fe-connect.c.

References _PQconninfoOption::keyword.

Referenced by conninfo_getval(), and conninfo_storeval().

5907 {
5909 
5910  for (option = connOptions; option->keyword != NULL; option++)
5911  {
5912  if (strcmp(option->keyword, keyword) == 0)
5913  return option;
5914  }
5915 
5916  return NULL;
5917 }

◆ conninfo_getval()

static const char * conninfo_getval ( PQconninfoOption connOptions,
const char *  keyword 
)
static

Definition at line 5815 of file fe-connect.c.

References conninfo_find(), and _PQconninfoOption::val.

Referenced by fillPGconn(), and parseServiceInfo().

5817 {
5819 
5820  option = conninfo_find(connOptions, keyword);
5821 
5822  return option ? option->val : NULL;
5823 }
static PQconninfoOption * conninfo_find(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:5906

◆ conninfo_init()

static PQconninfoOption * conninfo_init ( PQExpBuffer  errorMessage)
static

Definition at line 4757 of file fe-connect.c.

References _internalPQconninfoOption::keyword, libpq_gettext, malloc, MemSet, options, PQconninfoOptions, and printfPQExpBuffer().

Referenced by conninfo_array_parse(), conninfo_parse(), conninfo_uri_parse(), PQconndefaults(), and PQconninfo().

4758 {
4760  PQconninfoOption *opt_dest;
4761  const internalPQconninfoOption *cur_opt;
4762 
4763  /*
4764  * Get enough memory for all options in PQconninfoOptions, even if some
4765  * end up being filtered out.
4766  */
4767  options = (PQconninfoOption *) malloc(sizeof(PQconninfoOption) * sizeof(PQconninfoOptions) / sizeof(PQconninfoOptions[0]));
4768  if (options == NULL)
4769  {
4770  printfPQExpBuffer(errorMessage,
4771  libpq_gettext("out of memory\n"));
4772  return NULL;
4773  }
4774  opt_dest = options;
4775 
4776  for (cur_opt = PQconninfoOptions; cur_opt->keyword; cur_opt++)
4777  {
4778  /* Only copy the public part of the struct, not the full internal */
4779  memcpy(opt_dest, cur_opt, sizeof(PQconninfoOption));
4780  opt_dest++;
4781  }
4782  MemSet(opt_dest, 0, sizeof(PQconninfoOption));
4783 
4784  return options;
4785 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
#define MemSet(start, val, len)
Definition: c.h:908
#define malloc(a)
Definition: header.h:50
static const internalPQconninfoOption PQconninfoOptions[]
Definition: fe-connect.c:183
static char ** options
#define libpq_gettext(x)
Definition: libpq-int.h:760

◆ conninfo_parse()

static PQconninfoOption * conninfo_parse ( const char *  conninfo,
PQExpBuffer  errorMessage,
bool  use_defaults 
)
static

Definition at line 4851 of file fe-connect.c.

References buf, conninfo_add_defaults(), conninfo_init(), conninfo_storeval(), free, libpq_gettext, options, PQconninfoFree(), and printfPQExpBuffer().

Referenced by parse_connection_string().

4853 {
4854  char *pname;
4855  char *pval;
4856  char *buf;
4857  char *cp;
4858  char *cp2;
4860 
4861  /* Make a working copy of PQconninfoOptions */
4862  options = conninfo_init(errorMessage);
4863  if (options == NULL)
4864  return NULL;
4865 
4866  /* Need a modifiable copy of the input string */
4867  if ((buf = strdup(conninfo)) == NULL)
4868  {
4869  printfPQExpBuffer(errorMessage,
4870  libpq_gettext("out of memory\n"));
4871  PQconninfoFree(options);
4872  return NULL;
4873  }
4874  cp = buf;
4875 
4876  while (*cp)
4877  {
4878  /* Skip blanks before the parameter name */
4879  if (isspace((unsigned char) *cp))
4880  {
4881  cp++;
4882  continue;
4883  }
4884 
4885  /* Get the parameter name */
4886  pname = cp;
4887  while (*cp)
4888  {
4889  if (*cp == '=')
4890  break;
4891  if (isspace((unsigned char) *cp))
4892  {
4893  *cp++ = '\0';
4894  while (*cp)
4895  {
4896  if (!isspace((unsigned char) *cp))
4897  break;
4898  cp++;
4899  }
4900  break;
4901  }
4902  cp++;
4903  }
4904 
4905  /* Check that there is a following '=' */
4906  if (*cp != '=')
4907  {
4908  printfPQExpBuffer(errorMessage,
4909  libpq_gettext("missing \"=\" after \"%s\" in connection info string\n"),
4910  pname);
4911  PQconninfoFree(options);
4912  free(buf);
4913  return NULL;
4914  }
4915  *cp++ = '\0';
4916 
4917  /* Skip blanks after the '=' */
4918  while (*cp)
4919  {
4920  if (!isspace((unsigned char) *cp))
4921  break;
4922  cp++;
4923  }
4924 
4925  /* Get the parameter value */
4926  pval = cp;
4927 
4928  if (*cp != '\'')
4929  {
4930  cp2 = pval;
4931  while (*cp)
4932  {
4933  if (isspace((unsigned char) *cp))
4934  {
4935  *cp++ = '\0';
4936  break;
4937  }
4938  if (*cp == '\\')
4939  {
4940  cp++;
4941  if (*cp != '\0')
4942  *cp2++ = *cp++;
4943  }
4944  else
4945  *cp2++ = *cp++;
4946  }
4947  *cp2 = '\0';
4948  }
4949  else
4950  {
4951  cp2 = pval;
4952  cp++;
4953  for (;;)
4954  {
4955  if (*cp == '\0')
4956  {
4957  printfPQExpBuffer(errorMessage,
4958  libpq_gettext("unterminated quoted string in connection info string\n"));
4959  PQconninfoFree(options);
4960  free(buf);
4961  return NULL;
4962  }
4963  if (*cp == '\\')
4964  {
4965  cp++;
4966  if (*cp != '\0')
4967  *cp2++ = *cp++;
4968  continue;
4969  }
4970  if (*cp == '\'')
4971  {
4972  *cp2 = '\0';
4973  cp++;
4974  break;
4975  }
4976  *cp2++ = *cp++;
4977  }
4978  }
4979 
4980  /*
4981  * Now that we have the name and the value, store the record.
4982  */
4983  if (!conninfo_storeval(options, pname, pval, errorMessage, false, false))
4984  {
4985  PQconninfoFree(options);
4986  free(buf);
4987  return NULL;
4988  }
4989  }
4990 
4991  /* Done with the modifiable input string */
4992  free(buf);
4993 
4994  /*
4995  * Add in defaults if the caller wants that.
4996  */
4997  if (use_defaults)
4998  {
4999  if (!conninfo_add_defaults(options, errorMessage))
5000  {
5001  PQconninfoFree(options);
5002  return NULL;
5003  }
5004  }
5005 
5006  return options;
5007 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
static PQconninfoOption * conninfo_storeval(PQconninfoOption *connOptions, const char *keyword, const char *value, PQExpBuffer errorMessage, bool ignoreMissing, bool uri_decode)
Definition: fe-connect.c:5841
static PQconninfoOption * conninfo_init(PQExpBuffer errorMessage)
Definition: fe-connect.c:4757
static char * buf
Definition: pg_test_fsync.c:67
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:5965
static char ** options
#define free(a)
Definition: header.h:65
static bool conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5193
#define libpq_gettext(x)
Definition: libpq-int.h:760

◆ conninfo_storeval()

static PQconninfoOption * conninfo_storeval ( PQconninfoOption connOptions,
const char *  keyword,
const char *  value,
PQExpBuffer  errorMessage,
bool  ignoreMissing,
bool  uri_decode 
)
static

Definition at line 5841 of file fe-connect.c.

References conninfo_find(), conninfo_uri_decode(), free, libpq_gettext, printfPQExpBuffer(), and _PQconninfoOption::val.

Referenced by conninfo_parse(), conninfo_uri_parse_options(), conninfo_uri_parse_params(), and PQconninfo().

5845 {
5847  char *value_copy;
5848 
5849  /*
5850  * For backwards compatibility, requiressl=1 gets translated to
5851  * sslmode=require, and requiressl=0 gets translated to sslmode=prefer
5852  * (which is the default for sslmode).
5853  */
5854  if (strcmp(keyword, "requiressl") == 0)
5855  {
5856  keyword = "sslmode";
5857  if (value[0] == '1')
5858  value = "require";
5859  else
5860  value = "prefer";
5861  }
5862 
5863  option = conninfo_find(connOptions, keyword);
5864  if (option == NULL)
5865  {
5866  if (!ignoreMissing)
5867  printfPQExpBuffer(errorMessage,
5868  libpq_gettext("invalid connection option \"%s\"\n"),
5869  keyword);
5870  return NULL;
5871  }
5872 
5873  if (uri_decode)
5874  {
5875  value_copy = conninfo_uri_decode(value, errorMessage);
5876  if (value_copy == NULL)
5877  /* conninfo_uri_decode already set an error message */
5878  return NULL;
5879  }
5880  else
5881  {
5882  value_copy = strdup(value);
5883  if (value_copy == NULL)
5884  {
5885  printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n"));
5886  return NULL;
5887  }
5888  }
5889 
5890  if (option->val)
5891  free(option->val);
5892  option->val = value_copy;
5893 
5894  return option;
5895 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
static PQconninfoOption * conninfo_find(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:5906
static char * conninfo_uri_decode(const char *str, PQExpBuffer errorMessage)
Definition: fe-connect.c:5726
static struct @131 value
#define free(a)
Definition: header.h:65
#define libpq_gettext(x)
Definition: libpq-int.h:760

◆ conninfo_uri_decode()

static char * conninfo_uri_decode ( const char *  str,
PQExpBuffer  errorMessage 
)
static

Definition at line 5726 of file fe-connect.c.

References buf, free, get_hexdigit(), libpq_gettext, malloc, printfPQExpBuffer(), and generate_unaccent_rules::str.

Referenced by conninfo_storeval(), and conninfo_uri_parse_params().

5727 {
5728  char *buf;
5729  char *p;
5730  const char *q = str;
5731 
5732  buf = malloc(strlen(str) + 1);
5733  if (buf == NULL)
5734  {
5735  printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n"));
5736  return NULL;
5737  }
5738  p = buf;
5739 
5740  for (;;)
5741  {
5742  if (*q != '%')
5743  {
5744  /* copy and check for NUL terminator */
5745  if (!(*(p++) = *(q++)))
5746  break;
5747  }
5748  else
5749  {
5750  int hi;
5751  int lo;
5752  int c;
5753 
5754  ++q; /* skip the percent sign itself */
5755 
5756  /*
5757  * Possible EOL will be caught by the first call to
5758  * get_hexdigit(), so we never dereference an invalid q pointer.
5759  */
5760  if (!(get_hexdigit(*q++, &hi) && get_hexdigit(*q++, &lo)))
5761  {
5762  printfPQExpBuffer(errorMessage,
5763  libpq_gettext("invalid percent-encoded token: \"%s\"\n"),
5764  str);
5765  free(buf);
5766  return NULL;
5767  }
5768 
5769  c = (hi << 4) | lo;
5770  if (c == 0)
5771  {
5772  printfPQExpBuffer(errorMessage,
5773  libpq_gettext("forbidden value %%00 in percent-encoded value: \"%s\"\n"),
5774  str);
5775  free(buf);
5776  return NULL;
5777  }
5778  *(p++) = c;
5779  }
5780  }
5781 
5782  return buf;
5783 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
#define malloc(a)
Definition: header.h:50
char * c
static char * buf
Definition: pg_test_fsync.c:67
#define free(a)
Definition: header.h:65
static bool get_hexdigit(char digit, int *value)
Definition: fe-connect.c:5794
#define libpq_gettext(x)
Definition: libpq-int.h:760

◆ conninfo_uri_parse()

static PQconninfoOption * conninfo_uri_parse ( const char *  uri,
PQExpBuffer  errorMessage,
bool  use_defaults 
)
static

Definition at line 5298 of file fe-connect.c.

References conninfo_add_defaults(), conninfo_init(), conninfo_uri_parse_options(), options, and PQconninfoFree().

Referenced by parse_connection_string().

5300 {
5302 
5303  /* Make a working copy of PQconninfoOptions */
5304  options = conninfo_init(errorMessage);
5305  if (options == NULL)
5306  return NULL;
5307 
5308  if (!conninfo_uri_parse_options(options, uri, errorMessage))
5309  {
5310  PQconninfoFree(options);
5311  return NULL;
5312  }
5313 
5314  /*
5315  * Add in defaults if the caller wants that.
5316  */
5317  if (use_defaults)
5318  {
5319  if (!conninfo_add_defaults(options, errorMessage))
5320  {
5321  PQconninfoFree(options);
5322  return NULL;
5323  }
5324  }
5325 
5326  return options;
5327 }
static PQconninfoOption * conninfo_init(PQExpBuffer errorMessage)
Definition: fe-connect.c:4757
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:5965
static bool conninfo_uri_parse_options(PQconninfoOption *options, const char *uri, PQExpBuffer errorMessage)
Definition: fe-connect.c:5351
static char ** options
static bool conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5193

◆ conninfo_uri_parse_options()

static bool conninfo_uri_parse_options ( PQconninfoOption options,
const char *  uri,
PQExpBuffer  errorMessage 
)
static

Definition at line 5351 of file fe-connect.c.

References appendPQExpBufferChar(), appendPQExpBufferStr(), buf, cleanup(), conninfo_storeval(), conninfo_uri_parse_params(), PQExpBufferData::data, dbname, free, initPQExpBuffer(), libpq_gettext, password, port, PQExpBufferDataBroken, printfPQExpBuffer(), termPQExpBuffer(), uri_prefix_length(), and user.

Referenced by conninfo_uri_parse().

5353 {
5354  int prefix_len;
5355  char *p;
5356  char *buf = NULL;
5357  char *start;
5358  char prevchar = '\0';
5359  char *user = NULL;
5360  char *host = NULL;
5361  bool retval = false;
5362  PQExpBufferData hostbuf;
5363  PQExpBufferData portbuf;
5364 
5365  initPQExpBuffer(&hostbuf);
5366  initPQExpBuffer(&portbuf);
5367  if (PQExpBufferDataBroken(hostbuf) || PQExpBufferDataBroken(portbuf))
5368  {
5369  printfPQExpBuffer(errorMessage,
5370  libpq_gettext("out of memory\n"));
5371  goto cleanup;
5372  }
5373 
5374  /* need a modifiable copy of the input URI */
5375  buf = strdup(uri);
5376  if (buf == NULL)
5377  {
5378  printfPQExpBuffer(errorMessage,
5379  libpq_gettext("out of memory\n"));
5380  goto cleanup;
5381  }
5382  start = buf;
5383 
5384  /* Skip the URI prefix */
5385  prefix_len = uri_prefix_length(uri);
5386  if (prefix_len == 0)
5387  {
5388  /* Should never happen */
5389  printfPQExpBuffer(errorMessage,
5390  libpq_gettext("invalid URI propagated to internal parser routine: \"%s\"\n"),
5391  uri);
5392  goto cleanup;
5393  }
5394  start += prefix_len;
5395  p = start;
5396 
5397  /* Look ahead for possible user credentials designator */
5398  while (*p && *p != '@' && *p != '/')
5399  ++p;
5400  if (*p == '@')
5401  {
5402  /*
5403  * Found username/password designator, so URI should be of the form
5404  * "scheme://user[:password]@[netloc]".
5405  */
5406  user = start;
5407 
5408  p = user;
5409  while (*p != ':' && *p != '@')
5410  ++p;
5411 
5412  /* Save last char and cut off at end of user name */
5413  prevchar = *p;
5414  *p = '\0';
5415 
5416  if (*user &&
5417  !conninfo_storeval(options, "user", user,
5418  errorMessage, false, true))
5419  goto cleanup;
5420 
5421  if (prevchar == ':')
5422  {
5423  const char *password = p + 1;
5424 
5425  while (*p != '@')
5426  ++p;
5427  *p = '\0';
5428 
5429  if (*password &&
5430  !conninfo_storeval(options, "password", password,
5431  errorMessage, false, true))
5432  goto cleanup;
5433  }
5434 
5435  /* Advance past end of parsed user name or password token */
5436  ++p;
5437  }
5438  else
5439  {
5440  /*
5441  * No username/password designator found. Reset to start of URI.
5442  */
5443  p = start;
5444  }
5445 
5446  /*
5447  * There may be multiple netloc[:port] pairs, each separated from the next
5448  * by a comma. When we initially enter this loop, "p" has been
5449  * incremented past optional URI credential information at this point and
5450  * now points at the "netloc" part of the URI. On subsequent loop
5451  * iterations, "p" has been incremented past the comma separator and now
5452  * points at the start of the next "netloc".
5453  */
5454  for (;;)
5455  {
5456  /*
5457  * Look for IPv6 address.
5458  */
5459  if (*p == '[')
5460  {
5461  host = ++p;
5462  while (*p && *p != ']')
5463  ++p;
5464  if (!*p)
5465  {
5466  printfPQExpBuffer(errorMessage,
5467  libpq_gettext("end of string reached when looking for matching \"]\" in IPv6 host address in URI: \"%s\"\n"),
5468  uri);
5469  goto cleanup;
5470  }
5471  if (p == host)
5472  {
5473  printfPQExpBuffer(errorMessage,
5474  libpq_gettext("IPv6 host address may not be empty in URI: \"%s\"\n"),
5475  uri);
5476  goto cleanup;
5477  }
5478 
5479  /* Cut off the bracket and advance */
5480  *(p++) = '\0';
5481 
5482  /*
5483  * The address may be followed by a port specifier or a slash or a
5484  * query or a separator comma.
5485  */
5486  if (*p && *p != ':' && *p != '/' && *p != '?' && *p != ',')
5487  {
5488  printfPQExpBuffer(errorMessage,
5489  libpq_gettext("unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): \"%s\"\n"),
5490  *p, (int) (p - buf + 1), uri);
5491  goto cleanup;
5492  }
5493  }
5494  else
5495  {
5496  /* not an IPv6 address: DNS-named or IPv4 netloc */
5497  host = p;
5498 
5499  /*
5500  * Look for port specifier (colon) or end of host specifier
5501  * (slash) or query (question mark) or host separator (comma).
5502  */
5503  while (*p && *p != ':' && *p != '/' && *p != '?' && *p != ',')
5504  ++p;
5505  }
5506 
5507  /* Save the hostname terminator before we null it */
5508  prevchar = *p;
5509  *p = '\0';
5510 
5511  appendPQExpBufferStr(&hostbuf, host);
5512 
5513  if (prevchar == ':')
5514  {
5515  const char *port = ++p; /* advance past host terminator */
5516 
5517  while (*p && *p != '/' && *p != '?' && *p != ',')
5518  ++p;
5519 
5520  prevchar = *p;
5521  *p = '\0';
5522 
5523  appendPQExpBufferStr(&portbuf, port);
5524  }
5525 
5526  if (prevchar != ',')
5527  break;
5528  ++p; /* advance past comma separator */
5529  appendPQExpBufferChar(&hostbuf, ',');
5530  appendPQExpBufferChar(&portbuf, ',');
5531  }
5532 
5533  /* Save final values for host and port. */
5534  if (PQExpBufferDataBroken(hostbuf) || PQExpBufferDataBroken(portbuf))
5535  goto cleanup;
5536  if (hostbuf.data[0] &&
5537  !conninfo_storeval(options, "host", hostbuf.data,
5538  errorMessage, false, true))
5539  goto cleanup;
5540  if (portbuf.data[0] &&
5541  !conninfo_storeval(options, "port", portbuf.data,
5542  errorMessage, false, true))
5543  goto cleanup;
5544 
5545  if (prevchar && prevchar != '?')
5546  {
5547  const char *dbname = ++p; /* advance past host terminator */
5548 
5549  /* Look for query parameters */
5550  while (*p && *p != '?')
5551  ++p;
5552 
5553  prevchar = *p;
5554  *p = '\0';
5555 
5556  /*
5557  * Avoid setting dbname to an empty string, as it forces the default
5558  * value (username) and ignores $PGDATABASE, as opposed to not setting
5559  * it at all.
5560  */
5561  if (*dbname &&
5562  !conninfo_storeval(options, "dbname", dbname,
5563  errorMessage, false, true))
5564  goto cleanup;
5565  }
5566 
5567  if (prevchar)
5568  {
5569  ++p; /* advance past terminator */
5570 
5571  if (!conninfo_uri_parse_params(p, options, errorMessage))
5572  goto cleanup;
5573  }
5574 
5575  /* everything parsed okay */
5576  retval = true;
5577 
5578 cleanup:
5579  termPQExpBuffer(&hostbuf);
5580  termPQExpBuffer(&portbuf);
5581  if (buf)
5582  free(buf);
5583  return retval;
5584 }
static char password[100]
Definition: streamutil.c:54
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
static PQconninfoOption * conninfo_storeval(PQconninfoOption *connOptions, const char *keyword, const char *value, PQExpBuffer errorMessage, bool ignoreMissing, bool uri_decode)
Definition: fe-connect.c:5841
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:128
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
static char * buf
Definition: pg_test_fsync.c:67
static int port
Definition: pg_regress.c:90
static void cleanup(void)
Definition: bootstrap.c:875
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:396
static bool conninfo_uri_parse_params(char *params, PQconninfoOption *connOptions, PQExpBuffer errorMessage)
Definition: fe-connect.c:5595
#define free(a)
Definition: header.h:65
#define PQExpBufferDataBroken(buf)
Definition: pqexpbuffer.h:67
char * dbname
Definition: streamutil.c:51
static char * user
Definition: pg_regress.c:93
static int uri_prefix_length(const char *connstr)
Definition: fe-connect.c:4817
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:89
#define libpq_gettext(x)
Definition: libpq-int.h:760

◆ conninfo_uri_parse_params()

static bool conninfo_uri_parse_params ( char *  params,
PQconninfoOption connOptions,
PQExpBuffer  errorMessage 
)
static

Definition at line 5595 of file fe-connect.c.

References conninfo_storeval(), conninfo_uri_decode(), free, _internalPQconninfoOption::keyword, PQExpBufferData::len, libpq_gettext, printfPQExpBuffer(), and value.

Referenced by conninfo_uri_parse_options().

5598 {
5599  while (*params)
5600  {
5601  char *keyword = params;
5602  char *value = NULL;
5603  char *p = params;
5604  bool malloced = false;
5605 
5606  /*
5607  * Scan the params string for '=' and '&', marking the end of keyword
5608  * and value respectively.
5609  */
5610  for (;;)
5611  {
5612  if (*p == '=')
5613  {
5614  /* Was there '=' already? */
5615  if (value != NULL)
5616  {
5617  printfPQExpBuffer(errorMessage,
5618  libpq_gettext("extra key/value separator \"=\" in URI query parameter: \"%s\"\n"),
5619  keyword);
5620  return false;
5621  }
5622  /* Cut off keyword, advance to value */
5623  *p++ = '\0';
5624  value = p;
5625  }
5626  else if (*p == '&' || *p == '\0')
5627  {
5628  /*
5629  * If not at the end, cut off value and advance; leave p
5630  * pointing to start of the next parameter, if any.
5631  */
5632  if (*p != '\0')
5633  *p++ = '\0';
5634  /* Was there '=' at all? */
5635  if (value == NULL)
5636  {
5637  printfPQExpBuffer(errorMessage,
5638  libpq_gettext("missing key/value separator \"=\" in URI query parameter: \"%s\"\n"),
5639  keyword);
5640  return false;
5641  }
5642  /* Got keyword and value, go process them. */
5643  break;
5644  }
5645  else
5646  ++p; /* Advance over all other bytes. */
5647  }
5648 
5649  keyword = conninfo_uri_decode(keyword, errorMessage);
5650  if (keyword == NULL)
5651  {
5652  /* conninfo_uri_decode already set an error message */
5653  return false;
5654  }
5655  value = conninfo_uri_decode(value, errorMessage);
5656  if (value == NULL)
5657  {
5658  /* conninfo_uri_decode already set an error message */
5659  free(keyword);
5660  return false;
5661  }
5662  malloced = true;
5663 
5664  /*
5665  * Special keyword handling for improved JDBC compatibility.
5666  */
5667  if (strcmp(keyword, "ssl") == 0 &&
5668  strcmp(value, "true") == 0)
5669  {
5670  free(keyword);
5671  free(value);
5672  malloced = false;
5673 
5674  keyword = "sslmode";
5675  value = "require";
5676  }
5677 
5678  /*
5679  * Store the value if the corresponding option exists; ignore
5680  * otherwise. At this point both keyword and value are not
5681  * URI-encoded.
5682  */
5683  if (!conninfo_storeval(connOptions, keyword, value,
5684  errorMessage, true, false))
5685  {
5686  /* Insert generic message if conninfo_storeval didn't give one. */
5687  if (errorMessage->len == 0)
5688  printfPQExpBuffer(errorMessage,
5689  libpq_gettext("invalid URI query parameter: \"%s\"\n"),
5690  keyword);
5691  /* And fail. */
5692  if (malloced)
5693  {
5694  free(keyword);
5695  free(value);
5696  }
5697  return false;
5698  }
5699 
5700  if (malloced)
5701  {
5702  free(keyword);
5703  free(value);
5704  }
5705 
5706  /* Proceed to next key=value pair, if any */
5707  params = p;
5708  }
5709 
5710  return true;
5711 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
static PQconninfoOption * conninfo_storeval(PQconninfoOption *connOptions, const char *keyword, const char *value, PQExpBuffer errorMessage, bool ignoreMissing, bool uri_decode)
Definition: fe-connect.c:5841
static char * conninfo_uri_decode(const char *str, PQExpBuffer errorMessage)
Definition: fe-connect.c:5726
static struct @131 value
#define free(a)
Definition: header.h:65
#define libpq_gettext(x)
Definition: libpq-int.h:760

◆ count_comma_separated_elems()

static int count_comma_separated_elems ( const char *  input)
static

Definition at line 841 of file fe-connect.c.

Referenced by connectOptions2().

842 {
843  int n;
844 
845  n = 1;
846  for (; *input != '\0'; input++)
847  {
848  if (*input == ',')
849  n++;
850  }
851 
852  return n;
853 }

◆ default_threadlock()

static void default_threadlock ( int  acquire)
static

Definition at line 6572 of file fe-connect.c.

References pthread_mutex_init(), pthread_mutex_lock(), and pthread_mutex_unlock().

Referenced by PQregisterThreadLock().

6573 {
6574 #ifdef ENABLE_THREAD_SAFETY
6575 #ifndef WIN32
6576  static pthread_mutex_t singlethread_lock = PTHREAD_MUTEX_INITIALIZER;
6577 #else
6578  static pthread_mutex_t singlethread_lock = NULL;
6579  static long mutex_initlock = 0;
6580 
6581  if (singlethread_lock == NULL)
6582  {
6583  while (InterlockedExchange(&mutex_initlock, 1) == 1)
6584  /* loop, another thread own the lock */ ;
6585  if (singlethread_lock == NULL)
6586  {
6587  if (pthread_mutex_init(&singlethread_lock, NULL))
6588  PGTHREAD_ERROR("failed to initialize mutex");
6589  }
6590  InterlockedExchange(&mutex_initlock, 0);
6591  }
6592 #endif
6593  if (acquire)
6594  {
6595  if (pthread_mutex_lock(&singlethread_lock))
6596  PGTHREAD_ERROR("failed to lock mutex");
6597  }
6598  else
6599  {
6600  if (pthread_mutex_unlock(&singlethread_lock))
6601  PGTHREAD_ERROR("failed to unlock mutex");
6602  }
6603 #endif
6604 }
CRITICAL_SECTION * pthread_mutex_t
Definition: pthread-win32.h:8
int pthread_mutex_init(pthread_mutex_t *mp, void *attr)
Definition: pthread-win32.c:35
int pthread_mutex_lock(pthread_mutex_t *mp)
Definition: pthread-win32.c:45
int pthread_mutex_unlock(pthread_mutex_t *mp)
Definition: pthread-win32.c:54

◆ defaultNoticeProcessor()

static void defaultNoticeProcessor ( void *  arg,
const char *  message 
)
static

Definition at line 6330 of file fe-connect.c.

Referenced by makeEmptyPGconn().

6331 {
6332  (void) arg; /* not used */
6333  /* Note: we expect the supplied string to end with a newline already. */
6334  fprintf(stderr, "%s", message);
6335 }
void * arg

◆ defaultNoticeReceiver()

static void defaultNoticeReceiver ( void *  arg,
const PGresult res 
)
static

Definition at line 6315 of file fe-connect.c.

References pg_result::noticeHooks, PGNoticeHooks::noticeProc, PGNoticeHooks::noticeProcArg, and PQresultErrorMessage().

Referenced by makeEmptyPGconn().

6316 {
6317  (void) arg; /* not used */
6318  if (res->noticeHooks.noticeProc != NULL)
6320  PQresultErrorMessage(res));
6321 }
PGNoticeHooks noticeHooks
Definition: libpq-int.h:186
void * noticeProcArg
Definition: libpq-int.h:155
PQnoticeProcessor noticeProc
Definition: libpq-int.h:154
char * PQresultErrorMessage(const PGresult *res)
Definition: fe-exec.c:2663
void * arg

◆ fillPGconn()

static bool fillPGconn ( PGconn conn,
PQconninfoOption connOptions 
)
static

Definition at line 762 of file fe-connect.c.

References conninfo_getval(), _internalPQconninfoOption::connofs, pg_conn::errorMessage, free, _internalPQconninfoOption::keyword, libpq_gettext, and printfPQExpBuffer().

Referenced by connectOptions1(), and PQconnectStartParams().

763 {
765 
766  for (option = PQconninfoOptions; option->keyword; option++)
767  {
768  if (option->connofs >= 0)
769  {
770  const char *tmp = conninfo_getval(connOptions, option->keyword);
771 
772  if (tmp)
773  {
774  char **connmember = (char **) ((char *) conn + option->connofs);
775 
776  if (*connmember)
777  free(*connmember);
778  *connmember = strdup(tmp);
779  if (*connmember == NULL)
780  {
782  libpq_gettext("out of memory\n"));
783  return false;
784  }
785  }
786  }
787  }
788 
789  return true;
790 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
static const internalPQconninfoOption PQconninfoOptions[]
Definition: fe-connect.c:183
PQExpBufferData errorMessage
Definition: libpq-int.h:494
#define free(a)
Definition: header.h:65
static const char * conninfo_getval(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:5815
#define libpq_gettext(x)
Definition: libpq-int.h:760

◆ freePGconn()

static void freePGconn ( PGconn conn)
static

Definition at line 3409 of file fe-connect.c.

References pg_conn::appname, pg_conn::client_encoding_initial, PGEventConnDestroy::conn, conn, pg_conn::connect_timeout, pg_conn::connhost, pg_conn::dbName, pg_conn::errorMessage, pg_conn::events, pg_conn::fbappname, free, pg_conn_host::host, pg_conn_host::hostaddr, 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::nconnhost, pg_conn::nEvents, pg_conn::outBuffer, PGEvent::passThrough, pg_conn_host::password, PGEVT_CONNDESTROY, pg_conn::pghost, pg_conn::pghostaddr, pg_conn::pgoptions, pg_conn::pgpass, pg_conn::pgpassfile, pg_conn::pgport, pg_conn::pgtty, pg_conn::pguser, pg_conn_host::port, PGEvent::proc, pg_conn::replication, pg_conn::requirepeer, pg_conn::rowBuf, pg_conn::scram_channel_binding, pg_conn::sslcert, pg_conn::sslcompression, pg_conn::sslcrl, pg_conn::sslkey, pg_conn::sslmode, pg_conn::sslrootcert, pg_conn::target_session_attrs, termPQExpBuffer(), and pg_conn::workBuffer.

Referenced by makeEmptyPGconn(), and PQfinish().

3410 {
3411  int i;
3412 
3413  /* let any event procs clean up their state data */
3414  for (i = 0; i < conn->nEvents; i++)
3415  {
3416  PGEventConnDestroy evt;
3417 
3418  evt.conn = conn;
3419  (void) conn->events[i].proc(PGEVT_CONNDESTROY, &evt,
3420  conn->events[i].passThrough);
3421  free(conn->events[i].name);
3422  }
3423 
3424  /* clean up pg_conn_host structures */
3425  if (conn->connhost != NULL)
3426  {
3427  for (i = 0; i < conn->nconnhost; ++i)
3428  {
3429  if (conn->connhost[i].host != NULL)
3430  free(conn->connhost[i].host);
3431  if (conn->connhost[i].hostaddr != NULL)
3432  free(conn->connhost[i].hostaddr);
3433  if (conn->connhost[i].port != NULL)
3434  free(conn->connhost[i].port);
3435  if (conn->connhost[i].password != NULL)
3436  free(conn->connhost[i].password);
3437  }
3438  free(conn->connhost);
3439  }
3440 
3441  if (conn->client_encoding_initial)
3443  if (conn->events)
3444  free(conn->events);
3445  if (conn->pghost)
3446  free(conn->pghost);
3447  if (conn->pghostaddr)
3448  free(conn->pghostaddr);
3449  if (conn->pgport)
3450  free(conn->pgport);
3451  if (conn->pgtty)
3452  free(conn->pgtty);
3453  if (conn->connect_timeout)
3454  free(conn->connect_timeout);
3455  if (conn->pgoptions)
3456  free(conn->pgoptions);
3457  if (conn->appname)
3458  free(conn->appname);
3459  if (conn->fbappname)
3460  free(conn->fbappname);
3461  if (conn->dbName)
3462  free(conn->dbName);
3463  if (conn->replication)
3464  free(conn->replication);
3465  if (conn->pguser)
3466  free(conn->pguser);
3467  if (conn->pgpass)
3468  free(conn->pgpass);
3469  if (conn->pgpassfile)
3470  free(conn->pgpassfile);
3471  if (conn->keepalives)
3472  free(conn->keepalives);
3473  if (conn->keepalives_idle)
3474  free(conn->keepalives_idle);
3475  if (conn->keepalives_interval)
3476  free(conn->keepalives_interval);
3477  if (conn->keepalives_count)
3478  free(conn->keepalives_count);
3479  if (conn->scram_channel_binding)
3480  free(conn->scram_channel_binding);
3481  if (conn->sslmode)
3482  free(conn->sslmode);
3483  if (conn->sslcert)
3484  free(conn->sslcert);
3485  if (conn->sslkey)
3486  free(conn->sslkey);
3487  if (conn->sslrootcert)
3488  free(conn->sslrootcert);
3489  if (conn->sslcrl)
3490  free(conn->sslcrl);
3491  if (conn->sslcompression)
3492  free(conn->sslcompression);
3493  if (conn->requirepeer)
3494  free(conn->requirepeer);
3495 #if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
3496  if (conn->krbsrvname)
3497  free(conn->krbsrvname);
3498 #endif
3499 #if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
3500  if (conn->gsslib)
3501  free(conn->gsslib);
3502 #endif
3503  /* Note that conn->Pfdebug is not ours to close or free */
3504  if (conn->last_query)
3505  free(conn->last_query);
3506  if (conn->inBuffer)
3507  free(conn->inBuffer);
3508  if (conn->outBuffer)
3509  free(conn->outBuffer);
3510  if (conn->rowBuf)
3511  free(conn->rowBuf);
3512  if (conn->target_session_attrs)
3513  free(conn->target_session_attrs);
3514  termPQExpBuffer(&conn->errorMessage);
3515  termPQExpBuffer(&conn->workBuffer);
3516 
3517  free(conn);
3518 
3519 #ifdef WIN32
3520  WSACleanup();
3521 #endif
3522 }
PGEvent * events
Definition: libpq-int.h:375
char * replication
Definition: libpq-int.h:342
char * pgpassfile
Definition: libpq-int.h:345
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:128
PQExpBufferData workBuffer
Definition: libpq-int.h:497
char * requirepeer
Definition: libpq-int.h:359
char * host
Definition: libpq-int.h:308
char * dbName
Definition: libpq-int.h:341
char * keepalives
Definition: libpq-int.h:346
char * keepalives_idle
Definition: libpq-int.h:347
char * client_encoding_initial
Definition: libpq-int.h:337
char * sslkey
Definition: libpq-int.h:355
char * sslcompression
Definition: libpq-int.h:354
PGconn * conn
Definition: streamutil.c:55
char * hostaddr
Definition: libpq-int.h:309
char * connect_timeout
Definition: libpq-int.h:336
pg_conn_host * connhost
Definition: libpq-int.h:398
char * keepalives_interval
Definition: libpq-int.h:348
char * appname
Definition: libpq-int.h:339
char * target_session_attrs
Definition: libpq-int.h:366
char * last_query
Definition: libpq-int.h:384
PGdataValue * rowBuf
Definition: libpq-int.h:447
char * pguser
Definition: libpq-int.h:343
char * scram_channel_binding
Definition: libpq-int.h:352
char * inBuffer
Definition: libpq-int.h:430
char * sslmode
Definition: libpq-int.h:353
PQExpBufferData errorMessage
Definition: libpq-int.h:494
char * sslcert
Definition: libpq-int.h:356
#define free(a)
Definition: header.h:65
char * pgoptions
Definition: libpq-int.h:338
char * pgpass
Definition: libpq-int.h:344
char * sslrootcert
Definition: libpq-int.h:357
PGEventProc proc
Definition: libpq-int.h:160
char * outBuffer
Definition: libpq-int.h:437
char * pghostaddr
Definition: libpq-int.h:330
int nEvents
Definition: libpq-int.h:376
int i
void * passThrough
Definition: libpq-int.h:162
char * fbappname
Definition: libpq-int.h:340
char * port
Definition: libpq-int.h:310
char * pgport
Definition: libpq-int.h:333
int nconnhost
Definition: libpq-int.h:396
char * name
Definition: libpq-int.h:161
char * sslcrl
Definition: libpq-int.h:358
char * keepalives_count
Definition: libpq-int.h:350
char * pghost
Definition: libpq-int.h:325
char * pgtty
Definition: libpq-int.h:334
char * password
Definition: libpq-int.h:312

◆ get_hexdigit()

static bool get_hexdigit ( char  digit,
int *  value 
)
static

Definition at line 5794 of file fe-connect.c.

Referenced by conninfo_uri_decode().

5795 {
5796  if ('0' <= digit && digit <= '9')
5797  *value = digit - '0';
5798  else if ('A' <= digit && digit <= 'F')
5799  *value = digit - 'A' + 10;
5800  else if ('a' <= digit && digit <= 'f')
5801  *value = digit - 'a' + 10;
5802  else
5803  return false;
5804 
5805  return true;
5806 }
static struct @131 value

◆ internal_cancel()

static int internal_cancel ( SockAddr raddr,
int  be_pid,
int  be_key,
char *  errbuf,
int  errbufsize 
)
static

Definition at line 3810 of file fe-connect.c.

References SockAddr::addr, CANCEL_REQUEST_CODE, closesocket, connect, EINTR, pg_hton32, PGINVALID_SOCKET, recv, SockAddr::salen, send, SOCK_ERRNO, SOCK_ERRNO_SET, SOCK_STRERROR, socket, and strlcpy().

Referenced by PQcancel(), and PQrequestCancel().

3812 {
3813  int save_errno = SOCK_ERRNO;
3814  pgsocket tmpsock = PGINVALID_SOCKET;
3815  char sebuf[256];
3816  int maxlen;
3817  struct
3818  {
3819  uint32 packetlen;
3821  } crp;
3822 
3823  /*
3824  * We need to open a temporary connection to the postmaster. Do this with
3825  * only kernel calls.
3826  */
3827  if ((tmpsock = socket(raddr->addr.ss_family, SOCK_STREAM, 0)) == PGINVALID_SOCKET)
3828  {
3829  strlcpy(errbuf, "PQcancel() -- socket() failed: ", errbufsize);
3830  goto cancel_errReturn;
3831  }
3832 retry3:
3833  if (connect(tmpsock, (struct sockaddr *) &raddr->addr,
3834  raddr->salen) < 0)
3835  {
3836  if (SOCK_ERRNO == EINTR)
3837  /* Interrupted system call - we'll just try again */
3838  goto retry3;
3839  strlcpy(errbuf, "PQcancel() -- connect() failed: ", errbufsize);
3840  goto cancel_errReturn;
3841  }
3842 
3843  /*
3844  * We needn't set nonblocking I/O or NODELAY options here.
3845  */
3846 
3847  /* Create and send the cancel request packet. */
3848 
3849  crp.packetlen = pg_hton32((uint32) sizeof(crp));
3850  crp.cp.cancelRequestCode = (MsgType) pg_hton32(CANCEL_REQUEST_CODE);
3851  crp.cp.backendPID = pg_hton32(be_pid);
3852  crp.cp.cancelAuthCode = pg_hton32(be_key);
3853 
3854 retry4:
3855  if (send(tmpsock, (char *) &crp, sizeof(crp), 0) != (int) sizeof(crp))
3856  {
3857  if (SOCK_ERRNO == EINTR)
3858  /* Interrupted system call - we'll just try again */
3859  goto retry4;
3860  strlcpy(errbuf, "PQcancel() -- send() failed: ", errbufsize);
3861  goto cancel_errReturn;
3862  }
3863 
3864  /*
3865  * Wait for the postmaster to close the connection, which indicates that
3866  * it's processed the request. Without this delay, we might issue another
3867  * command only to find that our cancel zaps that command instead of the
3868  * one we thought we were canceling. Note we don't actually expect this
3869  * read to obtain any data, we are just waiting for EOF to be signaled.
3870  */
3871 retry5:
3872  if (recv(tmpsock, (char *) &crp, 1, 0) < 0)
3873  {
3874  if (SOCK_ERRNO == EINTR)
3875  /* Interrupted system call - we'll just try again */
3876  goto retry5;
3877  /* we ignore other error conditions */
3878  }
3879 
3880  /* All done */
3881  closesocket(tmpsock);
3882  SOCK_ERRNO_SET(save_errno);
3883  return true;
3884 
3885 cancel_errReturn:
3886 
3887  /*
3888  * Make sure we don't overflow the error buffer. Leave space for the \n at
3889  * the end, and for the terminating zero.
3890  */
3891  maxlen = errbufsize - strlen(errbuf) - 2;
3892  if (maxlen >= 0)
3893  {
3894  strncat(errbuf, SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)),
3895  maxlen);
3896  strcat(errbuf, "\n");
3897  }
3898  if (tmpsock != PGINVALID_SOCKET)
3899  closesocket(tmpsock);
3900  SOCK_ERRNO_SET(save_errno);
3901  return false;
3902 }
#define closesocket
Definition: port.h:292
struct sockaddr_storage addr
Definition: pqcomm.h:64
#define connect(s, name, namelen)
Definition: win32_port.h:446
#define recv(s, buf, len, flags)
Definition: win32_port.h:448
#define SOCK_STRERROR
Definition: libpq-int.h:774
#define pg_hton32(x)
Definition: pg_bswap.h:121
#define SOCK_ERRNO
Definition: libpq-int.h:773
unsigned int uint32
Definition: c.h:325
int pgsocket
Definition: port.h:31
ACCEPT_TYPE_ARG3 salen
Definition: pqcomm.h:65
#define SOCK_ERRNO_SET(e)
Definition: libpq-int.h:775
#define socket(af, type, protocol)
Definition: win32_port.h:442
#define PGINVALID_SOCKET
Definition: port.h:33
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define CANCEL_REQUEST_CODE
Definition: pqcomm.h:190
ProtocolVersion MsgType
Definition: pqcomm.h:115
#define EINTR
Definition: win32_port.h:334
#define send(s, buf, len, flags)
Definition: win32_port.h:449

◆ internal_ping()

static PGPing internal_ping ( PGconn conn)
static

Definition at line 3248 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_ATTEMPT, PQPING_NO_RESPONSE, PQPING_OK, PQPING_REJECT, and pg_conn::status.

Referenced by PQping(), and PQpingParams().

3249 {
3250  /* Say "no attempt" if we never got to PQconnectPoll */
3251  if (!conn || !conn->options_valid)
3252  return PQPING_NO_ATTEMPT;
3253 
3254  /* Attempt to complete the connection */
3255  if (conn->status != CONNECTION_BAD)
3256  (void) connectDBComplete(conn);
3257 
3258  /* Definitely OK if we succeeded */
3259  if (conn->status != CONNECTION_BAD)
3260  return PQPING_OK;
3261 
3262  /*
3263  * Here begins the interesting part of "ping": determine the cause of the
3264  * failure in sufficient detail to decide what to return. We do not want
3265  * to report that the server is not up just because we didn't have a valid
3266  * password, for example. In fact, any sort of authentication request
3267  * implies the server is up. (We need this check since the libpq side of
3268  * things might have pulled the plug on the connection before getting an
3269  * error as such from the postmaster.)
3270  */
3271  if (conn->auth_req_received)
3272  return PQPING_OK;
3273 
3274  /*
3275  * If we failed to get any ERROR response from the postmaster, report
3276  * PQPING_NO_RESPONSE. This result could be somewhat misleading for a
3277  * pre-7.4 server, since it won't send back a SQLSTATE, but those are long
3278  * out of support. Another corner case where the server could return a
3279  * failure without a SQLSTATE is fork failure, but NO_RESPONSE isn't
3280  * totally unreasonable for that anyway. We expect that every other
3281  * failure case in a modern server will produce a report with a SQLSTATE.
3282  *
3283  * NOTE: whenever we get around to making libpq generate SQLSTATEs for
3284  * client-side errors, we should either not store those into
3285  * last_sqlstate, or add an extra flag so we can tell client-side errors
3286  * apart from server-side ones.
3287  */
3288  if (strlen(conn->last_sqlstate) != 5)
3289  return PQPING_NO_RESPONSE;
3290 
3291  /*
3292  * Report PQPING_REJECT if server says it's not accepting connections. (We
3293  * distinguish this case mainly for the convenience of pg_ctl.)
3294  */
3295  if (strcmp(conn->last_sqlstate, ERRCODE_CANNOT_CONNECT_NOW) == 0)
3296  return PQPING_REJECT;
3297 
3298  /*
3299  * Any other SQLSTATE can be taken to indicate that the server is up.
3300  * Presumably it didn't like our username, password, or database name; or
3301  * perhaps it had some transient failure, but that should not be taken as
3302  * meaning "it's down".
3303  */
3304  return PQPING_OK;
3305 }
static int connectDBComplete(PGconn *conn)
Definition: fe-connect.c:1841
bool options_valid
Definition: libpq-int.h:386
#define ERRCODE_CANNOT_CONNECT_NOW
Definition: fe-connect.c:96
ConnStatusType status
Definition: libpq-int.h:380
bool auth_req_received
Definition: libpq-int.h:407
char last_sqlstate[6]
Definition: libpq-int.h:385

◆ makeEmptyPGconn()

static PGconn * makeEmptyPGconn ( void  )
static

Definition at line 3313 of file fe-connect.c.

References pg_conn::asyncStatus, pg_conn::auth_req_received, pg_conn::client_encoding, conn, CONNECTION_BAD, defaultNoticeProcessor(), defaultNoticeReceiver(), pg_conn::errorMessage, freePGconn(), pg_conn::inBuffer, pg_conn::inBufSize, initPQExpBuffer(), malloc, MemSet, pg_conn::nonblocking, pg_conn::noticeHooks, PGNoticeHooks::noticeProc, PGNoticeHooks::noticeRec, pg_conn::options_valid, pg_conn::outBuffer, pg_conn::outBufSize, pg_conn::password_needed, PG_SQL_ASCII, PGASYNC_IDLE, PGINVALID_SOCKET, pg_conn::pgpassfile_used, PQERRORS_DEFAULT, PQExpBufferBroken, PQSHOW_CONTEXT_ERRORS, PQTRANS_IDLE, pg_conn::rowBuf, pg_conn::rowBufLen, pg_conn::setenv_state, SETENV_STATE_IDLE, pg_conn::show_context, pg_conn::sock, pg_conn::ssl_in_use, pg_conn::status, pg_conn::std_strings, pg_conn::verbosity, pg_conn::workBuffer, and pg_conn::xactStatus.

Referenced by PQconnectStart(), PQconnectStartParams(), and PQsetdbLogin().

3314 {
3315  PGconn *conn;
3316 
3317 #ifdef WIN32
3318 
3319  /*
3320  * Make sure socket support is up and running.
3321  */
3322  WSADATA wsaData;
3323 
3324  if (WSAStartup(MAKEWORD(1, 1), &wsaData))
3325  return NULL;
3326  WSASetLastError(0);
3327 #endif
3328 
3329  conn = (PGconn *) malloc(sizeof(PGconn));
3330  if (conn == NULL)
3331  {
3332 #ifdef WIN32
3333  WSACleanup();
3334 #endif
3335  return conn;
3336  }
3337 
3338  /* Zero all pointers and booleans */
3339  MemSet(conn, 0, sizeof(PGconn));
3340 
3341  /* install default notice hooks */
3344 
3345  conn->status = CONNECTION_BAD;
3346  conn->asyncStatus = PGASYNC_IDLE;
3347  conn->xactStatus = PQTRANS_IDLE;
3348  conn->options_valid = false;
3349  conn->nonblocking = false;
3351  conn->client_encoding = PG_SQL_ASCII;
3352  conn->std_strings = false; /* unless server says differently */
3353  conn->verbosity = PQERRORS_DEFAULT;
3355  conn->sock = PGINVALID_SOCKET;
3356  conn->auth_req_received = false;
3357  conn->password_needed = false;
3358  conn->pgpassfile_used = false;
3359 #ifdef USE_SSL
3360  conn->allow_ssl_try = true;
3361  conn->wait_ssl_try = false;
3362  conn->ssl_in_use = false;
3363 #endif
3364 
3365  /*
3366  * We try to send at least 8K at a time, which is the usual size of pipe
3367  * buffers on Unix systems. That way, when we are sending a large amount
3368  * of data, we avoid incurring extra kernel context swaps for partial
3369  * bufferloads. The output buffer is initially made 16K in size, and we
3370  * try to dump it after accumulating 8K.
3371  *
3372  * With the same goal of minimizing context swaps, the input buffer will
3373  * be enlarged anytime it has less than 8K free, so we initially allocate
3374  * twice that.
3375  */
3376  conn->inBufSize = 16 * 1024;
3377  conn->inBuffer = (char *) malloc(conn->inBufSize);
3378  conn->outBufSize = 16 * 1024;
3379  conn->outBuffer = (char *) malloc(conn->outBufSize);
3380  conn->rowBufLen = 32;
3381  conn->rowBuf = (PGdataValue *) malloc(conn->rowBufLen * sizeof(PGdataValue));
3382  initPQExpBuffer(&conn->errorMessage);
3383  initPQExpBuffer(&conn->workBuffer);
3384 
3385  if (conn->inBuffer == NULL ||
3386  conn->outBuffer == NULL ||
3387  conn->rowBuf == NULL ||
3388  PQExpBufferBroken(&conn->errorMessage) ||
3389  PQExpBufferBroken(&conn->workBuffer))
3390  {
3391  /* out of memory already :-( */
3392  freePGconn(conn);
3393  conn = NULL;
3394  }
3395 
3396  return conn;
3397 }
PGContextVisibility show_context
Definition: libpq-int.h:426
int rowBufLen
Definition: libpq-int.h:448
bool password_needed
Definition: libpq-int.h:408
PQExpBufferData workBuffer
Definition: libpq-int.h:497
#define MemSet(start, val, len)
Definition: c.h:908
bool pgpassfile_used
Definition: libpq-int.h:409
#define malloc(a)
Definition: header.h:50
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:381
PGSetenvStatusType setenv_state
Definition: libpq-int.h:415
PGconn * conn
Definition: streamutil.c:55
int inBufSize
Definition: libpq-int.h:431
PGNoticeHooks noticeHooks
Definition: libpq-int.h:372
bool ssl_in_use
Definition: libpq-int.h:458
PGVerbosity verbosity
Definition: libpq-int.h:425
PQnoticeReceiver noticeRec
Definition: libpq-int.h:152
PGdataValue * rowBuf
Definition: libpq-int.h:447
pgsocket sock
Definition: libpq-int.h:401
#define PGINVALID_SOCKET
Definition: port.h:33
char * inBuffer
Definition: libpq-int.h:430
PQnoticeProcessor noticeProc
Definition: libpq-int.h:154
static void freePGconn(PGconn *conn)
Definition: fe-connect.c:3409
PQExpBufferData errorMessage
Definition: libpq-int.h:494
bool std_strings
Definition: libpq-int.h:424
bool options_valid
Definition: libpq-int.h:386
int outBufSize
Definition: libpq-int.h:438
#define PQExpBufferBroken(str)
Definition: pqexpbuffer.h:59
ConnStatusType status
Definition: libpq-int.h:380
bool auth_req_received
Definition: libpq-int.h:407
char * outBuffer
Definition: libpq-int.h:437
bool nonblocking
Definition: libpq-int.h:387
static void defaultNoticeProcessor(void *arg, const char *message)
Definition: fe-connect.c:6330
int client_encoding
Definition: libpq-int.h:423
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:89
static void defaultNoticeReceiver(void *arg, const PGresult *res)
Definition: fe-connect.c:6315
PGTransactionStatusType xactStatus
Definition: libpq-int.h:382

◆ parse_comma_separated_list()

static char* parse_comma_separated_list ( char **  startptr,
bool more 
)
static

Definition at line 865 of file fe-connect.c.

References malloc, and startptr.

Referenced by connectOptions2().

866 {
867  char *p;
868  char *s = *startptr;
869  char *e;
870  int len;
871 
872  /*
873  * Search for the end of the current element; a comma or end-of-string
874  * acts as a terminator.
875  */
876  e = s;
877  while (*e != '\0' && *e != ',')
878  ++e;
879  *more = (*e == ',');
880 
881  len = e - s;
882  p = (char *) malloc(sizeof(char) * (len + 1));
883  if (p)
884  {
885  memcpy(p, s, len);
886  p[len] = '\0';
887  }
888  *startptr = e + 1;
889 
890  return p;
891 }
#define malloc(a)
Definition: header.h:50
e
Definition: preproc-init.c:82
static XLogRecPtr startptr
Definition: basebackup.c:106

◆ parse_connection_string()

static PQconninfoOption * parse_connection_string ( const char *  conninfo,
PQExpBuffer  errorMessage,
bool  use_defaults 
)
static

Definition at line 4797 of file fe-connect.c.

References conninfo_parse(), conninfo_uri_parse(), and uri_prefix_length().

Referenced by connectOptions1(), conninfo_array_parse(), and PQconninfoParse().

4799 {
4800  /* Parse as URI if connection string matches URI prefix */
4801  if (uri_prefix_length(connstr) != 0)
4802  return conninfo_uri_parse(connstr, errorMessage, use_defaults);
4803 
4804  /* Parse as default otherwise */
4805  return conninfo_parse(connstr, errorMessage, use_defaults);
4806 }
static PQconninfoOption * conninfo_parse(const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:4851
static int uri_prefix_length(const char *connstr)
Definition: fe-connect.c:4817
static PQconninfoOption * conninfo_uri_parse(const char *uri, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5298
static char * connstr
Definition: pg_dumpall.c:59

◆ parseServiceFile()

static int parseServiceFile ( const char *  serviceFile,
const char *  service,
PQconninfoOption options,
PQExpBuffer  errorMessage,
bool group_found 
)
static

Definition at line 4560 of file fe-connect.c.

References buf, i, _internalPQconninfoOption::keyword, _PQconninfoOption::keyword, libpq_gettext, MAXBUFSIZE, printfPQExpBuffer(), _internalPQconninfoOption::val, and _PQconninfoOption::val.

Referenced by parseServiceInfo().

4565 {
4566  int linenr = 0,
4567  i;
4568  FILE *f;
4569  char buf[MAXBUFSIZE],
4570  *line;
4571 
4572  f = fopen(serviceFile, "r");
4573  if (f == NULL)
4574  {
4575  printfPQExpBuffer(errorMessage, libpq_gettext("service file \"%s\" not found\n"),
4576  serviceFile);
4577  return 1;
4578  }
4579 
4580  while ((line = fgets(buf, sizeof(buf), f)) != NULL)
4581  {
4582  linenr++;
4583 
4584  if (strlen(line) >= sizeof(buf) - 1)
4585  {
4586  fclose(f);
4587  printfPQExpBuffer(errorMessage,
4588  libpq_gettext("line %d too long in service file \"%s\"\n"),
4589  linenr,
4590  serviceFile);
4591  return 2;
4592  }
4593 
4594  /* ignore EOL at end of line */
4595  if (strlen(line) && line[strlen(line) - 1] == '\n')
4596  line[strlen(line) - 1] = 0;
4597 
4598  /* ignore leading blanks */
4599  while (*line && isspace((unsigned char) line[0]))
4600  line++;
4601 
4602  /* ignore comments and empty lines */
4603  if (strlen(line) == 0 || line[0] == '#')
4604  continue;
4605 
4606  /* Check for right groupname */
4607  if (line[0] == '[')
4608  {
4609  if (*group_found)
4610  {
4611  /* group info already read */
4612  fclose(f);
4613  return 0;
4614  }
4615 
4616  if (strncmp(line + 1, service, strlen(service)) == 0 &&
4617  line[strlen(service) + 1] == ']')
4618  *group_found = true;
4619  else
4620  *group_found = false;
4621  }
4622  else
4623  {
4624  if (*group_found)
4625  {
4626  /*
4627  * Finally, we are in the right group and can parse the line
4628  */
4629  char *key,
4630  *val;
4631  bool found_keyword;
4632 
4633 #ifdef USE_LDAP
4634  if (strncmp(line, "ldap", 4) == 0)
4635  {
4636  int rc = ldapServiceLookup(line, options, errorMessage);
4637 
4638  /* if rc = 2, go on reading for fallback */
4639  switch (rc)
4640  {
4641  case 0:
4642  fclose(f);
4643  return 0;
4644  case 1:
4645  case 3:
4646  fclose(f);
4647  return 3;
4648  case 2:
4649  continue;
4650  }
4651  }
4652 #endif
4653 
4654  key = line;
4655  val = strchr(line, '=');
4656  if (val == NULL)
4657  {
4658  printfPQExpBuffer(errorMessage,
4659  libpq_gettext("syntax error in service file \"%s\", line %d\n"),
4660  serviceFile,
4661  linenr);
4662  fclose(f);
4663  return 3;
4664  }
4665  *val++ = '\0';
4666 
4667  if (strcmp(key, "service") == 0)
4668  {
4669  printfPQExpBuffer(errorMessage,
4670  libpq_gettext("nested service specifications not supported in service file \"%s\", line %d\n"),
4671  serviceFile,
4672  linenr);
4673  fclose(f);
4674  return 3;
4675  }
4676 
4677  /*
4678  * Set the parameter --- but don't override any previous
4679  * explicit setting.
4680  */
4681  found_keyword = false;
4682  for (i = 0; options[i].keyword; i++)
4683  {
4684  if (strcmp(options[i].keyword, key) == 0)
4685  {
4686  if (options[i].val == NULL)
4687  options[i].val = strdup(val);
4688  if (!options[i].val)
4689  {
4690  printfPQExpBuffer(errorMessage,
4691  libpq_gettext("out of memory\n"));
4692  fclose(f);
4693  return 3;
4694  }
4695  found_keyword = true;
4696  break;
4697  }
4698  }
4699 
4700  if (!found_keyword)
4701  {
4702  printfPQExpBuffer(errorMessage,
4703  libpq_gettext("syntax error in service file \"%s\", line %d\n"),
4704  serviceFile,
4705  linenr);
4706  fclose(f);
4707  return 3;
4708  }
4709  }
4710  }
4711  }
4712 
4713  fclose(f);
4714 
4715  return 0;
4716 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
#define MAXBUFSIZE
Definition: fe-connect.c:4478
static char * buf
Definition: pg_test_fsync.c:67
int i
long val
Definition: informix.c:689
#define libpq_gettext(x)
Definition: libpq-int.h:760

◆ parseServiceInfo()

static int parseServiceInfo ( PQconninfoOption options,
PQExpBuffer  errorMessage 
)
static

Definition at line 4491 of file fe-connect.c.

References conninfo_getval(), libpq_gettext, MAXPGPATH, parseServiceFile(), pqGetHomeDirectory(), printfPQExpBuffer(), snprintf(), stat, status(), and strlcpy().

Referenced by conninfo_add_defaults().

4492 {
4493  const char *service = conninfo_getval(options, "service");
4494  char serviceFile[MAXPGPATH];
4495  char *env;
4496  bool group_found = false;
4497  int status;
4498  struct stat stat_buf;
4499 
4500  /*
4501  * We have to special-case the environment variable PGSERVICE here, since
4502  * this is and should be called before inserting environment defaults for
4503  * other connection options.
4504  */
4505  if (service == NULL)
4506  service = getenv("PGSERVICE");
4507 
4508  /* If no service name given, nothing to do */
4509  if (service == NULL)
4510  return 0;
4511 
4512  /*
4513  * Try PGSERVICEFILE if specified, else try ~/.pg_service.conf (if that
4514  * exists).
4515  */
4516  if ((env = getenv("PGSERVICEFILE")) != NULL)
4517  strlcpy(serviceFile, env, sizeof(serviceFile));
4518  else
4519  {
4520  char homedir[MAXPGPATH];
4521 
4522  if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
4523  goto next_file;
4524  snprintf(serviceFile, MAXPGPATH, "%s/%s", homedir, ".pg_service.conf");
4525  if (stat(serviceFile, &stat_buf) != 0)
4526  goto next_file;
4527  }
4528 
4529  status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
4530  if (group_found || status != 0)
4531  return status;
4532 
4533 next_file:
4534 
4535  /*
4536  * This could be used by any application so we can't use the binary
4537  * location to find our config files.
4538  */
4539  snprintf(serviceFile, MAXPGPATH, "%s/pg_service.conf",
4540  getenv("PGSYSCONFDIR") ? getenv("PGSYSCONFDIR") : SYSCONFDIR);
4541  if (stat(serviceFile, &stat_buf) != 0)
4542  goto last_file;
4543 
4544  status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
4545  if (status != 0)
4546  return status;
4547 
4548 last_file:
4549  if (!group_found)
4550  {
4551  printfPQExpBuffer(errorMessage,
4552  libpq_gettext("definition of service \"%s\" not found\n"), service);
4553  return 3;
4554  }
4555 
4556  return 0;
4557 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
struct stat stat_buf
Definition: pg_standby.c:103
#define MAXPGPATH
#define stat(a, b)
Definition: win32_port.h:266
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
static int parseServiceFile(const char *serviceFile, const char *service, PQconninfoOption *options, PQExpBuffer errorMessage, bool *group_found)
Definition: fe-connect.c:4560
static const char * conninfo_getval(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:5815
bool pqGetHomeDirectory(char *buf, int bufsize)
Definition: fe-connect.c:6543
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
#define libpq_gettext(x)
Definition: libpq-int.h:760

◆ passwordFromFile()

static char * passwordFromFile ( const char *  hostname,
const char *  port,
const char *  dbname,
const char *  username,
const char *  pgpassfile 
)
static

Definition at line 6379 of file fe-connect.c.

References buf, DEFAULT_PGSOCKET_DIR, DefaultHost, is_absolute_path, libpq_gettext, LINELEN, pwdfMatchesString(), S_IRWXG, S_IRWXO, S_ISREG, and stat.

Referenced by connectOptions2().

6381 {
6382  FILE *fp;
6383  struct stat stat_buf;
6384 
6385 #define LINELEN NAMEDATALEN*5
6386  char buf[LINELEN];
6387 
6388  if (dbname == NULL || strlen(dbname) == 0)
6389  return NULL;
6390 
6391  if (username == NULL || strlen(username) == 0)
6392  return NULL;
6393 
6394  /* 'localhost' matches pghost of '' or the default socket directory */
6395  if (hostname == NULL)
6397  else if (is_absolute_path(hostname))
6398 
6399  /*
6400  * We should probably use canonicalize_path(), but then we have to
6401  * bring path.c into libpq, and it doesn't seem worth it.
6402  */
6403  if (strcmp(hostname, DEFAULT_PGSOCKET_DIR) == 0)
6405 
6406  if (port == NULL)
6407  port = DEF_PGPORT_STR;
6408 
6409  /* If password file cannot be opened, ignore it. */
6410  if (stat(pgpassfile, &stat_buf) != 0)
6411  return NULL;
6412 
6413 #ifndef WIN32
6414  if (!S_ISREG(stat_buf.st_mode))
6415  {
6416  fprintf(stderr,
6417  libpq_gettext("WARNING: password file \"%s\" is not a plain file\n"),
6418  pgpassfile);
6419  return NULL;
6420  }
6421 
6422  /* If password file is insecure, alert the user and ignore it. */
6423  if (stat_buf.st_mode & (S_IRWXG | S_IRWXO))
6424  {
6425  fprintf(stderr,
6426  libpq_gettext("WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n"),
6427  pgpassfile);
6428  return NULL;
6429  }
6430 #else
6431 
6432  /*
6433  * On Win32, the directory is protected, so we don't have to check the
6434  * file.
6435  */
6436 #endif
6437 
6438  fp = fopen(pgpassfile, "r");
6439  if (fp == NULL)
6440  return NULL;
6441 
6442  while (!feof(fp) && !ferror(fp))
6443  {
6444  char *t = buf,
6445  *ret,
6446  *p1,
6447  *p2;
6448  int len;
6449 
6450  if (fgets(buf, sizeof(buf), fp) == NULL)
6451  break;
6452 
6453  len = strlen(buf);
6454 
6455  /* Remove trailing newline */
6456  if (len > 0 && buf[len - 1] == '\n')
6457  {
6458  buf[--len] = '\0';
6459  /* Handle DOS-style line endings, too, even when not on Windows */
6460  if (len > 0 && buf[len - 1] == '\r')
6461  buf[--len] = '\0';
6462  }
6463 
6464  if (len == 0)
6465  continue;
6466 
6467  if ((t = pwdfMatchesString(t, hostname)) == NULL ||
6468  (t = pwdfMatchesString(t, port)) == NULL ||
6469  (t = pwdfMatchesString(t, dbname)) == NULL ||
6470  (t = pwdfMatchesString(t, username)) == NULL)
6471  continue;
6472 
6473  /* Found a match. */
6474  ret = strdup(t);
6475  fclose(fp);
6476 
6477  if (!ret)
6478  {
6479  /* Out of memory. XXX: an error message would be nice. */
6480  return NULL;
6481  }
6482 
6483  /* De-escape password. */
6484  for (p1 = p2 = ret; *p1 != ':' && *p1 != '\0'; ++p1, ++p2)
6485  {
6486  if (*p1 == '\\' && p1[1] != '\0')
6487  ++p1;
6488  *p2 = *p1;
6489  }
6490  *p2 = '\0';
6491 
6492  return ret;
6493  }
6494 
6495  fclose(fp);
6496  return NULL;
6497 
6498 #undef LINELEN
6499 }
#define LINELEN
struct stat stat_buf
Definition: pg_standby.c:103
static char * buf
Definition: pg_test_fsync.c:67
#define S_IRWXG
Definition: win32_port.h:292
#define is_absolute_path(filename)
Definition: port.h:86
static int port
Definition: pg_regress.c:90
#define S_ISREG(m)
Definition: win32_port.h:310
#define stat(a, b)
Definition: win32_port.h:266
static char * username
Definition: initdb.c:132
char * dbname
Definition: streamutil.c:51
#define DefaultHost
Definition: fe-connect.c:121
static char * pwdfMatchesString(char *buf, const char *token)
Definition: fe-connect.c:6342
static char * hostname
Definition: pg_regress.c:89
#define S_IRWXO
Definition: win32_port.h:304
#define libpq_gettext(x)
Definition: libpq-int.h:760
#define DEFAULT_PGSOCKET_DIR

◆ pgpassfileWarning()

static void pgpassfileWarning ( PGconn conn)
static

Definition at line 6507 of file fe-connect.c.

References appendPQExpBuffer(), ERRCODE_INVALID_PASSWORD, pg_conn::errorMessage, libpq_gettext, pg_conn::password_needed, PG_DIAG_SQLSTATE, pg_conn::pgpassfile, pg_conn::pgpassfile_used, PQresultErrorField(), and pg_conn::result.

Referenced by PQconnectPoll().

6508 {
6509  /* If it was 'invalid authorization', add pgpassfile mention */
6510  /* only works with >= 9.0 servers */
6511  if (conn->pgpassfile_used && conn->password_needed && conn->result)
6512  {
6513  const char *sqlstate = PQresultErrorField(conn->result,
6515 
6516  if (sqlstate && strcmp(sqlstate, ERRCODE_INVALID_PASSWORD) == 0)
6518  libpq_gettext("password retrieved from file \"%s\"\n"),
6519  conn->pgpassfile);
6520  }
6521 }
char * pgpassfile
Definition: libpq-int.h:345
bool password_needed
Definition: libpq-int.h:408
bool pgpassfile_used
Definition: libpq-int.h:409
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:57
PGresult * result
Definition: libpq-int.h:451
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
PQExpBufferData errorMessage
Definition: libpq-int.h:494
char * PQresultErrorField(const PGresult *res, int fieldcode)
Definition: fe-exec.c:2709
#define ERRCODE_INVALID_PASSWORD
Definition: fe-connect.c:94
#define libpq_gettext(x)
Definition: libpq-int.h:760

◆ PQbackendPID()

int PQbackendPID ( const PGconn conn)

Definition at line 6142 of file fe-connect.c.

References pg_conn::be_pid, CONNECTION_OK, and pg_conn::status.

Referenced by get_prompt(), and StartLogStreamer().

6143 {
6144  if (!conn || conn->status != CONNECTION_OK)
6145  return 0;
6146  return conn->be_pid;
6147 }
ConnStatusType status
Definition: libpq-int.h:380
int be_pid
Definition: libpq-int.h:420

◆ PQcancel()

int PQcancel ( PGcancel cancel,
char *  errbuf,
int  errbufsize 
)

Definition at line 3914 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(), pgfdw_cancel_query(), setup_cancel_handler(), ShutdownWorkersHard(), sigTermHandler(), and try_complete_step().

3915 {
3916  if (!cancel)
3917  {
3918  strlcpy(errbuf, "PQcancel() -- no cancel object supplied", errbufsize);
3919  return false;
3920  }
3921 
3922  return internal_cancel(&cancel->raddr, cancel->be_pid, cancel->be_key,
3923  errbuf, errbufsize);
3924 }
static int internal_cancel(SockAddr *raddr, int be_pid, int be_key, char *errbuf, int errbufsize)
Definition: fe-connect.c:3810
int be_pid
Definition: libpq-int.h:507
int be_key
Definition: libpq-int.h:508
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
SockAddr raddr
Definition: libpq-int.h:506

◆ PQclientEncoding()

int PQclientEncoding ( const PGconn conn)

Definition at line 6176 of file fe-connect.c.

References pg_conn::client_encoding, CONNECTION_OK, and pg_conn::status.

Referenced by appendQualifiedRelation(), appendStringLiteralConn(), dblink_connect(), dblink_get_conn(), exec_command_encoding(), main(), processSQLNamePattern(), SendQuery(), setup_connection(), and SyncVariables().

6177 {
6178  if (!conn || conn->status != CONNECTION_OK)
6179  return -1;
6180  return conn->client_encoding;
6181 }
ConnStatusType status
Definition: libpq-int.h:380
int client_encoding
Definition: libpq-int.h:423

◆ PQconndefaults()

PQconninfoOption* PQconndefaults ( void  )

Definition at line 1230 of file fe-connect.c.

References conninfo_add_defaults(), conninfo_init(), initPQExpBuffer(), PQconninfoFree(), PQExpBufferDataBroken, and termPQExpBuffer().

Referenced by check_pghost_envvar(), dblink_fdw_validator(), get_connect_string(), InitPgFdwOptions(), and main().

1231 {
1232  PQExpBufferData errorBuf;
1233  PQconninfoOption *connOptions;
1234 
1235  /* We don't actually report any errors here, but callees want a buffer */
1236  initPQExpBuffer(&errorBuf);
1237  if (PQExpBufferDataBroken(errorBuf))
1238  return NULL; /* out of memory already :-( */
1239 
1240  connOptions = conninfo_init(&errorBuf);
1241  if (connOptions != NULL)
1242  {
1243  /* pass NULL errorBuf to ignore errors */
1244  if (!conninfo_add_defaults(connOptions, NULL))
1245  {
1246  PQconninfoFree(connOptions);
1247  connOptions = NULL;
1248  }
1249  }
1250 
1251  termPQExpBuffer(&errorBuf);
1252  return connOptions;
1253 }
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:128
static PQconninfoOption * conninfo_init(PQExpBuffer errorMessage)
Definition: fe-connect.c:4757
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:5965
#define PQExpBufferDataBroken(buf)
Definition: pqexpbuffer.h:67
static bool conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5193
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:89

◆ PQconnectdb()

PGconn* PQconnectdb ( const char *  conninfo)

Definition at line 592 of file fe-connect.c.

References conn, connectDBComplete(), CONNECTION_BAD, PQconnectStart(), and pg_conn::status.

Referenced by dblink_connect(), dblink_get_conn(), get_db_conn(), libpqConnect(), and main().

593 {
594  PGconn *conn = PQconnectStart(conninfo);
595 
596  if (conn && conn->status != CONNECTION_BAD)
597  (void) connectDBComplete(conn);
598 
599  return conn;
600 }
PGconn * conn
Definition: streamutil.c:55
static int connectDBComplete(PGconn *conn)
Definition: fe-connect.c:1841
PGconn * PQconnectStart(const char *conninfo)
Definition: fe-connect.c:718
ConnStatusType status
Definition: libpq-int.h:380

◆ PQconnectdbParams()

PGconn* PQconnectdbParams ( const char *const *  keywords,
const char *const *  values,
int  expand_dbname 
)

Definition at line 536 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().

539 {
540  PGconn *conn = PQconnectStartParams(keywords, values, expand_dbname);
541 
542  if (conn && conn->status != CONNECTION_BAD)
543  (void) connectDBComplete(conn);
544 
545  return conn;
546 
547 }
PGconn * conn
Definition: streamutil.c:55
static int connectDBComplete(PGconn *conn)
Definition: fe-connect.c:1841
ConnStatusType status
Definition: libpq-int.h:380
static Datum values[MAXATTR]
Definition: bootstrap.c:164
PGconn * PQconnectStartParams(const char *const *keywords, const char *const *values, int expand_dbname)
Definition: fe-connect.c:639

◆ PQconnectionNeedsPassword()

int PQconnectionNeedsPassword ( const PGconn conn)

Definition at line 6150 of file fe-connect.c.

References password, pg_conn::password_needed, and PQpass().

Referenced by _connectDB(), connectDatabase(), ConnectDatabase(), do_connect(), doConnect(), GetConnection(), main(), sql_conn(), and vacuumlo().

6151 {
6152  char *password;
6153 
6154  if (!conn)
6155  return false;
6156  password = PQpass(conn);
6157  if (conn->password_needed &&
6158  (password == NULL || password[0] == '\0'))
6159  return true;
6160  else
6161  return false;
6162 }
static char password[100]
Definition: streamutil.c:54
bool password_needed
Definition: libpq-int.h:408
char * PQpass(const PGconn *conn)
Definition: fe-connect.c:5999

◆ PQconnectionUsedPassword()

int PQconnectionUsedPassword ( const PGconn conn)

Definition at line 6165 of file fe-connect.c.

References pg_conn::password_needed.

Referenced by _connectDB(), connect_pg_server(), ConnectDatabase(), and dblink_security_check().

6166 {
6167  if (!conn)
6168  return false;
6169  if (conn->password_needed)
6170  return true;
6171  else
6172  return false;
6173 }
bool password_needed
Definition: libpq-int.h:408

◆ PQconnectPoll()

PostgresPollingStatusType PQconnectPoll ( PGconn conn)

Definition at line 2003 of file fe-connect.c.

References SockAddr::addr, pg_conn::addr_cur, pg_conn_host::addrlist, addrinfo::ai_addr, addrinfo::ai_addrlen, addrinfo::ai_family, addrinfo::ai_next, appendPQExpBuffer(), appendPQExpBufferChar(), appendPQExpBufferStr(), pg_conn::appname, pg_conn::asyncStatus, AUTH_REQ_MD5, AUTH_REQ_OK, pg_conn::auth_req_received, CHT_HOST_ADDRESS, connect, connectFailureMessage(), CONNECTION_AUTH_OK, CONNECTION_AWAITING_RESPONSE, CONNECTION_BAD, CONNECTION_CHECK_WRITABLE, CONNECTION_CONSUME, CONNECTION_MADE, CONNECTION_NEEDED, CONNECTION_OK, CONNECTION_SETENV, CONNECTION_SSL_STARTUP, CONNECTION_STARTED, connectNoDelay(), pg_conn::connhost, PQExpBufferData::data, EINPROGRESS, EINTR, EnvironmentOptions, ERRCODE_APPNAME_UNKNOWN, pg_conn::errorMessage, EWOULDBLOCK, pg_conn::fbappname, free, getpeereid(), pg_conn_host::host, pg_conn_host::hostaddr, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, IS_AF_UNIX, pg_conn::laddr, PQExpBufferData::len, libpq_gettext, pg_conn::nconnhost, NEGOTIATE_SSL_CODE, pg_conn::next_eo, PG_DIAG_SQLSTATE, pg_fe_sendauth(), pg_hton32, PG_PROTOCOL, PG_PROTOCOL_MAJOR, pg_set_noblock(), PGASYNC_BUSY, PGINVALID_SOCKET, pgpassfileWarning(), PGRES_FATAL_ERROR, PGRES_POLLING_FAILED, PGRES_POLLING_OK, PGRES_POLLING_READING, PGRES_POLLING_WRITING, PGRES_TUPLES_OK, pg_conn_host::port, pqBuildStartupPacket2(), pqBuildStartupPacket3(), pqCheckInBufferSpace(), PQclear(), PQconsumeInput(), pqDropConnection(), pqFlush(), pqGetc(), pqGetErrorNotice3(), pqGetInt(), pqGetpwuid(), PQgetResult(), pqGets_append(), PQgetvalue(), PQisBusy(), PQntuples(), pqPacketSend(), pqReadData(), PQresultErrorField(), PQresultStatus(), pqsecure_initialize(), pqsecure_open_client(), PQsendQuery(), pqSetenvPoll(), pqStrerror(), printfPQExpBuffer(), pg_conn::pversion, pg_conn::raddr, release_all_addrinfo(), pg_conn::requirepeer, restoreErrorMessage(), pg_result::resultStatus, SockAddr::salen, saveErrorMessage(), pg_conn::send_appname, sendTerminateConn(), pg_conn::setenv_state, SETENV_STATE_CLIENT_ENCODING_SEND, setKeepalivesCount(), setKeepalivesIdle(), setKeepalivesInterval(), pg_conn::sigpipe_flag, pg_conn::sigpipe_so, pg_conn::sock, SOCK_ERRNO, SOCK_STRERROR, socket, pg_conn::ssl_in_use, pg_conn::sslmode, pg_conn::status, STATUS_OK, pg_conn::target_session_attrs, termPQExpBuffer(), pg_conn_host::type, useKeepalives(), _internalPQconninfoOption::val, and pg_conn::whichhost.

Referenced by connectDBComplete(), connectDBStart(), libpqrcv_connect(), and PQresetPoll().

2004 {
2005  PGresult *res;
2006  char sebuf[256];
2007  int optval;
2008  PQExpBufferData savedMessage;
2009 
2010  if (conn == NULL)
2011  return PGRES_POLLING_FAILED;
2012 
2013  /* Get the new data */
2014  switch (conn->status)
2015  {
2016  /*
2017  * We really shouldn't have been polled in these two cases, but we
2018  * can handle it.
2019  */
2020  case CONNECTION_BAD:
2021  return PGRES_POLLING_FAILED;
2022  case CONNECTION_OK:
2023  return PGRES_POLLING_OK;
2024 
2025  /* These are reading states */
2027  case CONNECTION_AUTH_OK:
2028  {
2029  /* Load waiting data */
2030  int n = pqReadData(conn);
2031 
2032  if (n < 0)
2033  goto error_return;
2034  if (n == 0)
2035  return PGRES_POLLING_READING;
2036 
2037  break;
2038  }
2039 
2040  /* These are writing states, so we just proceed. */
2041  case CONNECTION_STARTED:
2042  case CONNECTION_MADE:
2043  break;
2044 
2045  /* We allow pqSetenvPoll to decide whether to proceed. */
2046  case CONNECTION_SETENV:
2047  break;
2048 
2049  /* Special cases: proceed without waiting. */
2051  case CONNECTION_NEEDED:
2053  case CONNECTION_CONSUME:
2054  break;
2055 
2056  default:
2058  libpq_gettext(
2059  "invalid connection state, "
2060  "probably indicative of memory corruption\n"
2061  ));
2062  goto error_return;
2063  }
2064 
2065 
2066 keep_going: /* We will come back to here until there is
2067  * nothing left to do. */
2068  switch (conn->status)
2069  {
2070  case CONNECTION_NEEDED:
2071  {
2072  /*
2073  * Try to initiate a connection to one of the addresses
2074  * returned by pg_getaddrinfo_all(). conn->addr_cur is the
2075  * next one to try. We fail when we run out of addresses.
2076  */
2077  for (;;)
2078  {
2079  struct addrinfo *addr_cur;
2080 
2081  /*
2082  * Advance to next possible host, if we've tried all of
2083  * the addresses for the current host.
2084  */
2085  if (conn->addr_cur == NULL)
2086  {
2087  if (++conn->whichhost >= conn->nconnhost)
2088  {
2089  conn->whichhost = 0;
2090  break;
2091  }
2092  conn->addr_cur =
2093  conn->connhost[conn->whichhost].addrlist;
2094  }
2095 
2096  /* Remember current address for possible error msg */
2097  addr_cur = conn->addr_cur;
2098  memcpy(&conn->raddr.addr, addr_cur->ai_addr,
2099  addr_cur->ai_addrlen);
2100  conn->raddr.salen = addr_cur->ai_addrlen;
2101 
2102  conn->sock = socket(addr_cur->ai_family, SOCK_STREAM, 0);
2103  if (conn->sock == PGINVALID_SOCKET)
2104  {
2105  /*
2106  * ignore socket() failure if we have more addresses
2107  * to try
2108  */
2109  if (addr_cur->ai_next != NULL ||
2110  conn->whichhost + 1 < conn->nconnhost)
2111  {
2112  conn->addr_cur = addr_cur->ai_next;
2113  continue;
2114  }
2116  libpq_gettext("could not create socket: %s\n"),
2117  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2118  break;
2119  }
2120 
2121  /*
2122  * Select socket options: no delay of outgoing data for
2123  * TCP sockets, nonblock mode, close-on-exec. Fail if any
2124  * of this fails.
2125  */
2126  if (!IS_AF_UNIX(addr_cur->ai_family))
2127  {
2128  if (!connectNoDelay(conn))
2129  {
2130  pqDropConnection(conn, true);
2131  conn->addr_cur = addr_cur->ai_next;
2132  continue;
2133  }
2134  }
2135  if (!pg_set_noblock(conn->sock))
2136  {
2138  libpq_gettext("could not set socket to nonblocking mode: %s\n"),
2139  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2140  pqDropConnection(conn, true);
2141  conn->addr_cur = addr_cur->ai_next;
2142  continue;
2143  }
2144 
2145 #ifdef F_SETFD
2146  if (fcntl(conn->sock, F_SETFD, FD_CLOEXEC) == -1)
2147  {
2149  libpq_gettext("could not set socket to close-on-exec mode: %s\n"),
2150  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2151  pqDropConnection(conn, true);
2152  conn->addr_cur = addr_cur->ai_next;
2153  continue;
2154  }
2155 #endif /* F_SETFD */
2156 
2157  if (!IS_AF_UNIX(addr_cur->ai_family))
2158  {
2159 #ifndef WIN32
2160  int on = 1;
2161 #endif
2162  int usekeepalives = useKeepalives(conn);
2163  int err = 0;
2164 
2165  if (usekeepalives < 0)
2166  {
2168  libpq_gettext("keepalives parameter must be an integer\n"));
2169  err = 1;
2170  }
2171  else if (usekeepalives == 0)
2172  {
2173  /* Do nothing */
2174  }
2175 #ifndef WIN32
2176  else if (setsockopt(conn->sock,
2177  SOL_SOCKET, SO_KEEPALIVE,
2178  (char *) &on, sizeof(on)) < 0)
2179  {
2181  libpq_gettext("setsockopt(%s) failed: %s\n"),
2182  "SO_KEEPALIVE",
2183  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2184  err = 1;
2185  }
2186  else if (!setKeepalivesIdle(conn)
2187  || !setKeepalivesInterval(conn)
2188  || !setKeepalivesCount(conn))
2189  err = 1;
2190 #else /* WIN32 */
2191 #ifdef SIO_KEEPALIVE_VALS
2192  else if (!setKeepalivesWin32(conn))
2193  err = 1;
2194 #endif /* SIO_KEEPALIVE_VALS */
2195 #endif /* WIN32 */
2196 
2197  if (err)
2198  {
2199  pqDropConnection(conn, true);
2200  conn->addr_cur = addr_cur->ai_next;
2201  continue;
2202  }
2203  }
2204 
2205  /*----------
2206  * We have three methods of blocking SIGPIPE during
2207  * send() calls to this socket:
2208  *
2209  * - setsockopt(sock, SO_NOSIGPIPE)
2210  * - send(sock, ..., MSG_NOSIGNAL)
2211  * - setting the signal mask to SIG_IGN during send()
2212  *
2213  * The third method requires three syscalls per send,
2214  * so we prefer either of the first two, but they are
2215  * less portable. The state is tracked in the following
2216  * members of PGconn:
2217  *
2218  * conn->sigpipe_so - we have set up SO_NOSIGPIPE
2219  * conn->sigpipe_flag - we're specifying MSG_NOSIGNAL
2220  *
2221  * If we can use SO_NOSIGPIPE, then set sigpipe_so here
2222  * and we're done. Otherwise, set sigpipe_flag so that
2223  * we will try MSG_NOSIGNAL on sends. If we get an error
2224  * with MSG_NOSIGNAL, we'll clear that flag and revert to
2225  * signal masking.
2226  *----------
2227  */
2228  conn->sigpipe_so = false;
2229 #ifdef MSG_NOSIGNAL
2230  conn->sigpipe_flag = true;
2231 #else
2232  conn->sigpipe_flag = false;
2233 #endif /* MSG_NOSIGNAL */
2234 
2235 #ifdef SO_NOSIGPIPE
2236  optval = 1;
2237  if (setsockopt(conn->sock, SOL_SOCKET, SO_NOSIGPIPE,
2238  (char *) &optval, sizeof(optval)) == 0)
2239  {
2240  conn->sigpipe_so = true;
2241  conn->sigpipe_flag = false;
2242  }
2243 #endif /* SO_NOSIGPIPE */
2244 
2245  /*
2246  * Start/make connection. This should not block, since we
2247  * are in nonblock mode. If it does, well, too bad.
2248  */
2249  if (connect(conn->sock, addr_cur->ai_addr,
2250  addr_cur->ai_addrlen) < 0)
2251  {
2252  if (SOCK_ERRNO == EINPROGRESS ||
2253 #ifdef WIN32
2254  SOCK_ERRNO == EWOULDBLOCK ||
2255 #endif
2256  SOCK_ERRNO == EINTR)
2257  {
2258  /*
2259  * This is fine - we're in non-blocking mode, and
2260  * the connection is in progress. Tell caller to
2261  * wait for write-ready on socket.
2262  */
2263  conn->status = CONNECTION_STARTED;
2264  return PGRES_POLLING_WRITING;
2265  }
2266  /* otherwise, trouble */
2267  }
2268  else
2269  {
2270  /*
2271  * Hm, we're connected already --- seems the "nonblock
2272  * connection" wasn't. Advance the state machine and
2273  * go do the next stuff.
2274  */
2275  conn->status = CONNECTION_STARTED;
2276  goto keep_going;
2277  }
2278 
2279  /*
2280  * This connection failed --- set up error report, then
2281  * close socket (do it this way in case close() affects
2282  * the value of errno...). We will ignore the connect()
2283  * failure and keep going if there are more addresses.
2284  */
2286  pqDropConnection(conn, true);
2287 
2288  /*
2289  * Try the next address, if any.
2290  */
2291  conn->addr_cur = addr_cur->ai_next;
2292  } /* loop over addresses */
2293 
2294  /*
2295  * Oops, no more addresses. An appropriate error message is
2296  * already set up, so just set the right status.
2297  */
2298  goto error_return;
2299  }
2300 
2301  case CONNECTION_STARTED:
2302  {
2303  ACCEPT_TYPE_ARG3 optlen = sizeof(optval);
2304 
2305  /*
2306  * Write ready, since we've made it here, so the connection
2307  * has been made ... or has failed.
2308  */
2309 
2310  /*
2311  * Now check (using getsockopt) that there is not an error
2312  * state waiting for us on the socket.
2313  */
2314 
2315  if (getsockopt(conn->sock, SOL_SOCKET, SO_ERROR,
2316  (char *) &optval, &optlen) == -1)
2317  {
2319  libpq_gettext("could not get socket error status: %s\n"),
2320  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2321  goto error_return;
2322  }
2323  else if (optval != 0)
2324  {
2325  /*
2326  * When using a nonblocking connect, we will typically see
2327  * connect failures at this point, so provide a friendly
2328  * error message.
2329  */
2330  connectFailureMessage(conn, optval);
2331  pqDropConnection(conn, true);
2332 
2333  /*
2334  * If more addresses remain, keep trying, just as in the
2335  * case where connect() returned failure immediately.
2336  */
2337  if (conn->addr_cur->ai_next != NULL ||
2338  conn->whichhost + 1 < conn->nconnhost)
2339  {
2340  conn->addr_cur = conn->addr_cur->ai_next;
2341  conn->status = CONNECTION_NEEDED;
2342  goto keep_going;
2343  }
2344  goto error_return;
2345  }
2346 
2347  /* Fill in the client address */
2348  conn->laddr.salen = sizeof(conn->laddr.addr);
2349  if (getsockname(conn->sock,
2350  (struct sockaddr *) &conn->laddr.addr,
2351  &conn->laddr.salen) < 0)
2352  {
2354  libpq_gettext("could not get client address from socket: %s\n"),
2355  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2356  goto error_return;
2357  }
2358 
2359  /*
2360  * Make sure we can write before advancing to next step.
2361  */
2362  conn->status = CONNECTION_MADE;
2363  return PGRES_POLLING_WRITING;
2364  }
2365 
2366  case CONNECTION_MADE:
2367  {
2368  char *startpacket;
2369  int packetlen;
2370 
2371 #ifdef HAVE_UNIX_SOCKETS
2372 
2373  /*
2374  * Implement requirepeer check, if requested and it's a
2375  * Unix-domain socket.
2376  */
2377  if (conn->requirepeer && conn->requirepeer[0] &&
2378  IS_AF_UNIX(conn->raddr.addr.ss_family))
2379  {
2380  char pwdbuf[BUFSIZ];
2381  struct passwd pass_buf;
2382  struct passwd *pass;
2383  int passerr;
2384  uid_t uid;
2385  gid_t gid;
2386 
2387  errno = 0;
2388  if (getpeereid(conn->sock, &uid, &gid) != 0)
2389  {
2390  /*
2391  * Provide special error message if getpeereid is a
2392  * stub
2393  */
2394  if (errno == ENOSYS)
2396  libpq_gettext("requirepeer parameter is not supported on this platform\n"));
2397  else
2399  libpq_gettext("could not get peer credentials: %s\n"),
2400  pqStrerror(errno, sebuf, sizeof(sebuf)));
2401  goto error_return;
2402  }
2403 
2404  passerr = pqGetpwuid(uid, &pass_buf, pwdbuf, sizeof(pwdbuf), &pass);
2405  if (pass == NULL)
2406  {
2407  if (passerr != 0)
2409  libpq_gettext("could not look up local user ID %d: %s\n"),
2410  (int) uid,
2411  pqStrerror(passerr, sebuf, sizeof(sebuf)));
2412  else
2414  libpq_gettext("local user with ID %d does not exist\n"),
2415  (int) uid);
2416  goto error_return;
2417  }
2418 
2419  if (strcmp(pass->pw_name, conn->requirepeer) != 0)
2420  {
2422  libpq_gettext("requirepeer specifies \"%s\", but actual peer user name is \"%s\"\n"),
2423  conn->requirepeer, pass->pw_name);
2424  goto error_return;
2425  }
2426  }
2427 #endif /* HAVE_UNIX_SOCKETS */
2428 
2429 #ifdef USE_SSL
2430 
2431  /*
2432  * If SSL is enabled and we haven't already got it running,
2433  * request it instead of sending the startup message.
2434  */
2435  if (IS_AF_UNIX(conn->raddr.addr.ss_family))
2436  {
2437  /* Don't bother requesting SSL over a Unix socket */
2438  conn->allow_ssl_try = false;
2439  }
2440  if (conn->allow_ssl_try && !conn->wait_ssl_try &&
2441  !conn->ssl_in_use)
2442  {
2443  ProtocolVersion pv;
2444 
2445  /*
2446  * Send the SSL request packet.
2447  *
2448  * Theoretically, this could block, but it really
2449  * shouldn't since we only got here if the socket is
2450  * write-ready.
2451  */
2453  if (pqPacketSend(conn, 0, &pv, sizeof(pv)) != STATUS_OK)
2454  {
2456  libpq_gettext("could not send SSL negotiation packet: %s\n"),
2457  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2458  goto error_return;
2459  }
2460  /* Ok, wait for response */
2462  return PGRES_POLLING_READING;
2463  }
2464 #endif /* USE_SSL */
2465 
2466  /*
2467  * Build the startup packet.
2468  */
2469  if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
2470  startpacket = pqBuildStartupPacket3(conn, &packetlen,
2472  else
2473  startpacket = pqBuildStartupPacket2(conn, &packetlen,
2475  if (!startpacket)
2476  {
2477  /*
2478  * will not appendbuffer here, since it's likely to also
2479  * run out of memory
2480  */
2482  libpq_gettext("out of memory\n"));
2483  goto error_return;
2484  }
2485 
2486  /*
2487  * Send the startup packet.
2488  *
2489  * Theoretically, this could block, but it really shouldn't
2490  * since we only got here if the socket is write-ready.
2491  */
2492  if (pqPacketSend(conn, 0, startpacket, packetlen) != STATUS_OK)
2493  {
2495  libpq_gettext("could not send startup packet: %s\n"),
2496  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2497  free(startpacket);
2498  goto error_return;
2499  }
2500 
2501  free(startpacket);
2502 
2504  return PGRES_POLLING_READING;
2505  }
2506 
2507  /*
2508  * Handle SSL negotiation: wait for postmaster messages and
2509  * respond as necessary.
2510  */
2512  {
2513 #ifdef USE_SSL
2514  PostgresPollingStatusType pollres;
2515 
2516  /*
2517  * On first time through, get the postmaster's response to our
2518  * SSL negotiation packet.
2519  */
2520  if (!conn->ssl_in_use)
2521  {
2522  /*
2523  * We use pqReadData here since it has the logic to
2524  * distinguish no-data-yet from connection closure. Since
2525  * conn->ssl isn't set, a plain recv() will occur.
2526  */
2527  char SSLok;
2528  int rdresult;
2529 
2530  rdresult = pqReadData(conn);
2531  if (rdresult < 0)
2532  {
2533  /* errorMessage is already filled in */
2534  goto error_return;
2535  }
2536  if (rdresult == 0)
2537  {
2538  /* caller failed to wait for data */
2539  return PGRES_POLLING_READING;
2540  }
2541  if (pqGetc(&SSLok, conn) < 0)
2542  {
2543  /* should not happen really */
2544  return PGRES_POLLING_READING;
2545  }
2546  if (SSLok == 'S')
2547  {
2548  /* mark byte consumed */
2549  conn->inStart = conn->inCursor;
2550  /* Set up global SSL state if required */
2551  if (pqsecure_initialize(conn) != 0)
2552  goto error_return;
2553  }
2554  else if (SSLok == 'N')
2555  {
2556  /* mark byte consumed */
2557  conn->inStart = conn->inCursor;
2558  /* OK to do without SSL? */
2559  if (conn->sslmode[0] == 'r' || /* "require" */
2560  conn->sslmode[0] == 'v') /* "verify-ca" or
2561  * "verify-full" */
2562  {
2563  /* Require SSL, but server does not want it */
2565  libpq_gettext("server does not support SSL, but SSL was required\n"));
2566  goto error_return;
2567  }
2568  /* Otherwise, proceed with normal startup */
2569  conn->allow_ssl_try = false;
2570  conn->status = CONNECTION_MADE;
2571  return PGRES_POLLING_WRITING;
2572  }
2573  else if (SSLok == 'E')
2574  {
2575  /*
2576  * Server failure of some sort, such as failure to
2577  * fork a backend process. We need to process and
2578  * report the error message, which might be formatted
2579  * according to either protocol 2 or protocol 3.
2580  * Rather than duplicate the code for that, we flip
2581  * into AWAITING_RESPONSE state and let the code there
2582  * deal with it. Note we have *not* consumed the "E"
2583  * byte here.
2584  */
2586  goto keep_going;
2587  }
2588  else
2589  {
2591  libpq_gettext("received invalid response to SSL negotiation: %c\n"),
2592  SSLok);
2593  goto error_return;
2594  }
2595  }
2596 
2597  /*
2598  * Begin or continue the SSL negotiation process.
2599  */
2600  pollres = pqsecure_open_client(conn);
2601  if (pollres == PGRES_POLLING_OK)
2602  {
2603  /* SSL handshake done, ready to send startup packet */
2604  conn->status = CONNECTION_MADE;
2605  return PGRES_POLLING_WRITING;
2606  }
2607  if (pollres == PGRES_POLLING_FAILED)
2608  {
2609  /*
2610  * Failed ... if sslmode is "prefer" then do a non-SSL
2611  * retry
2612  */
2613  if (conn->sslmode[0] == 'p' /* "prefer" */
2614  && conn->allow_ssl_try /* redundant? */
2615  && !conn->wait_ssl_try) /* redundant? */
2616  {
2617  /* only retry once */
2618  conn->allow_ssl_try = false;
2619  /* Must drop the old connection */
2620  pqDropConnection(conn, true);
2621  conn->status = CONNECTION_NEEDED;
2622  goto keep_going;
2623  }
2624  }
2625  return pollres;
2626 #else /* !USE_SSL */
2627  /* can't get here */
2628  goto error_return;
2629 #endif /* USE_SSL */
2630  }
2631 
2632  /*
2633  * Handle authentication exchange: wait for postmaster messages
2634  * and respond as necessary.
2635  */
2637  {
2638  char beresp;
2639  int msgLength;
2640  int avail;
2641  AuthRequest areq;
2642  int res;
2643 
2644  /*
2645  * Scan the message from current point (note that if we find
2646  * the message is incomplete, we will return without advancing
2647  * inStart, and resume here next time).
2648  */
2649  conn->inCursor = conn->inStart;
2650 
2651  /* Read type byte */
2652  if (pqGetc(&beresp, conn))
2653  {
2654  /* We'll come back when there is more data */
2655  return PGRES_POLLING_READING;
2656  }
2657 
2658  /*
2659  * Validate message type: we expect only an authentication
2660  * request or an error here. Anything else probably means
2661  * it's not Postgres on the other end at all.
2662  */
2663  if (!(beresp == 'R' || beresp == 'E'))
2664  {
2666  libpq_gettext(
2667  "expected authentication request from "
2668  "server, but received %c\n"),
2669  beresp);
2670  goto error_return;
2671  }
2672 
2673  if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
2674  {
2675  /* Read message length word */
2676  if (pqGetInt(&msgLength, 4, conn))
2677  {
2678  /* We'll come back when there is more data */
2679  return PGRES_POLLING_READING;
2680  }
2681  }
2682  else
2683  {
2684  /* Set phony message length to disable checks below */
2685  msgLength = 8;
2686  }
2687 
2688  /*
2689  * Try to validate message length before using it.
2690  * Authentication requests can't be very large, although GSS
2691  * auth requests may not be that small. Errors can be a
2692  * little larger, but not huge. If we see a large apparent
2693  * length in an error, it means we're really talking to a
2694  * pre-3.0-protocol server; cope.
2695  */
2696  if (beresp == 'R' && (msgLength < 8 || msgLength > 2000))
2697  {
2699  libpq_gettext(
2700  "expected authentication request from "
2701  "server, but received %c\n"),
2702  beresp);
2703  goto error_return;
2704  }
2705 
2706  if (beresp == 'E' && (msgLength < 8 || msgLength > 30000))
2707  {
2708  /* Handle error from a pre-3.0 server */
2709  conn->inCursor = conn->inStart + 1; /* reread data */
2710  if (pqGets_append(&conn->errorMessage, conn))
2711  {
2712  /* We'll come back when there is more data */
2713  return PGRES_POLLING_READING;
2714  }
2715  /* OK, we read the message; mark data consumed */
2716  conn->inStart = conn->inCursor;
2717 
2718  /*
2719  * The postmaster typically won't end its message with a
2720  * newline, so add one to conform to libpq conventions.
2721  */
2722  appendPQExpBufferChar(&conn->errorMessage, '\n');
2723 
2724  /*
2725  * If we tried to open the connection in 3.0 protocol,
2726  * fall back to 2.0 protocol.
2727  */
2728  if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
2729  {
2730  conn->pversion = PG_PROTOCOL(2, 0);
2731  /* Must drop the old connection */
2732  pqDropConnection(conn, true);
2733  conn->status = CONNECTION_NEEDED;
2734  goto keep_going;
2735  }
2736 
2737  goto error_return;
2738  }
2739 
2740  /*
2741  * Can't process if message body isn't all here yet.
2742  *
2743  * (In protocol 2.0 case, we are assuming messages carry at
2744  * least 4 bytes of data.)
2745  */
2746  msgLength -= 4;
2747  avail = conn->inEnd - conn->inCursor;
2748  if (avail < msgLength)
2749  {
2750  /*
2751  * Before returning, try to enlarge the input buffer if
2752  * needed to hold the whole message; see notes in
2753  * pqParseInput3.
2754  */
2755  if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength,
2756  conn))
2757  goto error_return;
2758  /* We'll come back when there is more data */
2759  return PGRES_POLLING_READING;
2760  }
2761 
2762  /* Handle errors. */
2763  if (beresp == 'E')
2764  {
2765  if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
2766  {
2767  if (pqGetErrorNotice3(conn, true))
2768  {
2769  /* We'll come back when there is more data */
2770  return PGRES_POLLING_READING;
2771  }
2772  }
2773  else
2774  {
2775  if (pqGets_append(&conn->errorMessage, conn))
2776  {
2777  /* We'll come back when there is more data */
2778  return PGRES_POLLING_READING;
2779  }
2780  }
2781  /* OK, we read the message; mark data consumed */
2782  conn->inStart = conn->inCursor;
2783 
2784 #ifdef USE_SSL
2785 
2786  /*
2787  * if sslmode is "allow" and we haven't tried an SSL
2788  * connection already, then retry with an SSL connection
2789  */
2790  if (conn->sslmode[0] == 'a' /* "allow" */
2791  && !conn->ssl_in_use
2792  && conn->allow_ssl_try
2793  && conn->wait_ssl_try)
2794  {
2795  /* only retry once */
2796  conn->wait_ssl_try = false;
2797  /* Must drop the old connection */
2798  pqDropConnection(conn, true);
2799  conn->status = CONNECTION_NEEDED;
2800  goto keep_going;
2801  }
2802 
2803  /*
2804  * if sslmode is "prefer" and we're in an SSL connection,
2805  * then do a non-SSL retry
2806  */
2807  if (conn->sslmode[0] == 'p' /* "prefer" */
2808  && conn->allow_ssl_try
2809  && !conn->wait_ssl_try) /* redundant? */
2810  {
2811  /* only retry once */
2812  conn->allow_ssl_try = false;
2813  /* Must drop the old connection */
2814  pqDropConnection(conn, true);
2815  conn->status = CONNECTION_NEEDED;
2816  goto keep_going;
2817  }
2818 #endif
2819 
2820  goto error_return;
2821  }
2822 
2823  /* It is an authentication request. */
2824  conn->auth_req_received = true;
2825 
2826  /* Get the type of request. */
2827  if (pqGetInt((int *) &areq, 4, conn))
2828  {
2829  /* We'll come back when there are more data */
2830  return PGRES_POLLING_READING;
2831  }
2832  msgLength -= 4;
2833 
2834  /*
2835  * Ensure the password salt is in the input buffer, if it's an
2836  * MD5 request. All the other authentication methods that
2837  * contain extra data in the authentication request are only
2838  * supported in protocol version 3, in which case we already
2839  * read the whole message above.
2840  */
2841  if (areq == AUTH_REQ_MD5 && PG_PROTOCOL_MAJOR(conn->pversion) < 3)
2842  {
2843  msgLength += 4;
2844 
2845  avail = conn->inEnd - conn->inCursor;
2846  if (avail < 4)
2847  {
2848  /*
2849  * Before returning, try to enlarge the input buffer
2850  * if needed to hold the whole message; see notes in
2851  * pqParseInput3.
2852  */
2853  if (pqCheckInBufferSpace(conn->inCursor + (size_t) 4,
2854  conn))
2855  goto error_return;
2856  /* We'll come back when there is more data */
2857  return PGRES_POLLING_READING;
2858  }
2859  }
2860 
2861  /*
2862  * Process the rest of the authentication request message, and
2863  * respond to it if necessary.
2864  *
2865  * Note that conn->pghost must be non-NULL if we are going to
2866  * avoid the Kerberos code doing a hostname look-up.
2867  */
2868  res = pg_fe_sendauth(areq, msgLength, conn);
2869  conn->errorMessage.len = strlen(conn->errorMessage.data);
2870 
2871  /* OK, we have processed the message; mark data consumed */
2872  conn->inStart = conn->inCursor;
2873 
2874  if (res != STATUS_OK)
2875  goto error_return;
2876 
2877  /*
2878  * Just make sure that any data sent by pg_fe_sendauth is
2879  * flushed out. Although this theoretically could block, it
2880  * really shouldn't since we don't send large auth responses.
2881  */
2882  if (pqFlush(conn))
2883  goto error_return;
2884 
2885  if (areq == AUTH_REQ_OK)
2886  {
2887  /* We are done with authentication exchange */
2888  conn->status = CONNECTION_AUTH_OK;
2889 
2890  /*
2891  * Set asyncStatus so that PQgetResult will think that
2892  * what comes back next is the result of a query. See
2893  * below.
2894  */
2895  conn->asyncStatus = PGASYNC_BUSY;
2896  }
2897 
2898  /* Look to see if we have more data yet. */
2899  goto keep_going;
2900  }
2901 
2902  case CONNECTION_AUTH_OK:
2903  {
2904  /*
2905  * Now we expect to hear from the backend. A ReadyForQuery
2906  * message indicates that startup is successful, but we might
2907  * also get an Error message indicating failure. (Notice
2908  * messages indicating nonfatal warnings are also allowed by
2909  * the protocol, as are ParameterStatus and BackendKeyData
2910  * messages.) Easiest way to handle this is to let
2911  * PQgetResult() read the messages. We just have to fake it
2912  * out about the state of the connection, by setting
2913  * asyncStatus = PGASYNC_BUSY (done above).
2914  */
2915 
2916  if (PQisBusy(conn))
2917  return PGRES_POLLING_READING;
2918 
2919  res = PQgetResult(conn);
2920 
2921  /*
2922  * NULL return indicating we have gone to IDLE state is
2923  * expected
2924  */
2925  if (res)
2926  {
2927  if (res->resultStatus != PGRES_FATAL_ERROR)
2929  libpq_gettext("unexpected message from server during startup\n"));
2930  else if (conn->send_appname &&
2931  (conn->appname || conn->fbappname))
2932  {
2933  /*
2934  * If we tried to send application_name, check to see
2935  * if the error is about that --- pre-9.0 servers will
2936  * reject it at this stage of the process. If so,
2937  * close the connection and retry without sending
2938  * application_name. We could possibly get a false
2939  * SQLSTATE match here and retry uselessly, but there
2940  * seems no great harm in that; we'll just get the
2941  * same error again if it's unrelated.
2942  */
2943  const char *sqlstate;
2944 
2945  sqlstate = PQresultErrorField(res, PG_DIAG_SQLSTATE);
2946  if (sqlstate &&
2947  strcmp(sqlstate, ERRCODE_APPNAME_UNKNOWN) == 0)
2948  {
2949  PQclear(res);
2950  conn->send_appname = false;
2951  /* Must drop the old connection */
2952  pqDropConnection(conn, true);
2953  conn->status = CONNECTION_NEEDED;
2954  goto keep_going;
2955  }
2956  }
2957 
2958  /*
2959  * if the resultStatus is FATAL, then conn->errorMessage
2960  * already has a copy of the error; needn't copy it back.
2961  * But add a newline if it's not there already, since
2962  * postmaster error messages may not have one.
2963  */
2964  if (conn->errorMessage.len <= 0 ||
2965  conn->errorMessage.data[conn->errorMessage.len - 1] != '\n')
2966  appendPQExpBufferChar(&conn->errorMessage, '\n');
2967  PQclear(res);
2968  goto error_return;
2969  }
2970 
2971  /* Fire up post-connection housekeeping if needed */
2972  if (PG_PROTOCOL_MAJOR(conn->pversion) < 3)
2973  {
2974  conn->status = CONNECTION_SETENV;
2976  conn->next_eo = EnvironmentOptions;
2977  return PGRES_POLLING_WRITING;
2978  }
2979 
2980  /*
2981  * If a read-write connection is required, see if we have one.
2982  */
2983  if (conn->target_session_attrs != NULL &&
2984  strcmp(conn->target_session_attrs, "read-write") == 0)
2985  {
2986  /*
2987  * We are yet to make a connection. Save all existing
2988  * error messages until we make a successful connection
2989  * state. This is important because PQsendQuery is going
2990  * to reset conn->errorMessage and we will lose error
2991  * messages related to previous hosts we have tried to
2992  * connect and failed.
2993  */
2994  if (!saveErrorMessage(conn, &savedMessage))
2995  goto error_return;
2996 
2997  conn->status = CONNECTION_OK;
2998  if (!PQsendQuery(conn,
2999  "SHOW transaction_read_only"))
3000  {
3001  restoreErrorMessage(conn, &savedMessage);
3002  goto error_return;
3003  }
3005  restoreErrorMessage(conn, &savedMessage);
3006  return PGRES_POLLING_READING;
3007  }
3008 
3009  /* We can release the address lists now. */
3010  release_all_addrinfo(conn);
3011 
3012  /* We are open for business! */
3013  conn->status = CONNECTION_OK;
3014  return PGRES_POLLING_OK;
3015  }
3016 
3017  case CONNECTION_SETENV:
3018 
3019  /*
3020  * Do post-connection housekeeping (only needed in protocol 2.0).
3021  *
3022  * We pretend that the connection is OK for the duration of these
3023  * queries.
3024  */
3025  conn->status = CONNECTION_OK;
3026 
3027  switch (pqSetenvPoll(conn))
3028  {
3029  case PGRES_POLLING_OK: /* Success */
3030  break;
3031 
3032  case PGRES_POLLING_READING: /* Still going */
3033  conn->status = CONNECTION_SETENV;
3034  return PGRES_POLLING_READING;
3035 
3036  case PGRES_POLLING_WRITING: /* Still going */
3037  conn->status = CONNECTION_SETENV;
3038  return PGRES_POLLING_WRITING;
3039 
3040  default:
3041  goto error_return;
3042  }
3043 
3044  /*
3045  * If a read-write connection is requested check for same.
3046  */
3047  if (conn->target_session_attrs != NULL &&
3048  strcmp(conn->target_session_attrs, "read-write") == 0)
3049  {
3050  if (!saveErrorMessage(conn, &savedMessage))
3051  goto error_return;
3052 
3053  conn->status = CONNECTION_OK;
3054  if (!PQsendQuery(conn,
3055  "SHOW transaction_read_only"))
3056  {
3057  restoreErrorMessage(conn, &savedMessage);
3058  goto error_return;
3059  }
3061  restoreErrorMessage(conn, &savedMessage);
3062  return PGRES_POLLING_READING;
3063  }
3064 
3065  /* We can release the address lists now. */
3066  release_all_addrinfo(conn);
3067 
3068  /* We are open for business! */
3069  conn->status = CONNECTION_OK;
3070  return PGRES_POLLING_OK;
3071 
3072  case CONNECTION_CONSUME:
3073  {
3074  conn->status = CONNECTION_OK;
3075  if (!PQconsumeInput(conn))
3076  goto error_return;
3077 
3078  if (PQisBusy(conn))
3079  {
3080  conn->status = CONNECTION_CONSUME;
3081  restoreErrorMessage(conn, &savedMessage);
3082  return PGRES_POLLING_READING;
3083  }
3084 
3085  /*
3086  * Call PQgetResult() again to consume NULL result.
3087  */
3088  res = PQgetResult(conn);
3089  if (res != NULL)
3090  {
3091  PQclear(res);
3092  conn->status = CONNECTION_CONSUME;
3093  goto keep_going;
3094  }
3095 
3096  /* We are open for business! */
3097  conn->status = CONNECTION_OK;
3098  return PGRES_POLLING_OK;
3099  }
3101  {
3102  const char *displayed_host;
3103  const char *displayed_port;
3104 
3105  if (!saveErrorMessage(conn, &savedMessage))
3106  goto error_return;
3107 
3108  conn->status = CONNECTION_OK;
3109  if (!PQconsumeInput(conn))
3110  {
3111  restoreErrorMessage(conn, &savedMessage);
3112  goto error_return;
3113  }
3114 
3115  if (PQisBusy(conn))
3116  {
3118  restoreErrorMessage(conn, &savedMessage);
3119  return PGRES_POLLING_READING;
3120  }
3121 
3122  res = PQgetResult(conn);
3123  if (res && (PQresultStatus(res) == PGRES_TUPLES_OK) &&
3124  PQntuples(res) == 1)
3125  {
3126  char *val;
3127 
3128  val = PQgetvalue(res, 0, 0);
3129  if (strncmp(val, "on", 2) == 0)
3130  {
3131  const char *displayed_host;
3132  const char *displayed_port;
3133 
3134  if (conn->connhost[conn->whichhost].type == CHT_HOST_ADDRESS)
3135  displayed_host = conn->connhost[conn->whichhost].hostaddr;
3136  else
3137  displayed_host = conn->connhost[conn->whichhost].host;
3138  displayed_port = conn->connhost[conn->whichhost].port;
3139  if (displayed_port == NULL || displayed_port[0] == '\0')
3140  displayed_port = DEF_PGPORT_STR;
3141 
3142  PQclear(res);
3143  restoreErrorMessage(conn, &savedMessage);
3144 
3145  /* Not writable; close connection. */
3147  libpq_gettext("could not make a writable "
3148  "connection to server "
3149  "\"%s:%s\"\n"),
3150  displayed_host, displayed_port);
3151  conn->status = CONNECTION_OK;
3152  sendTerminateConn(conn);
3153  pqDropConnection(conn, true);
3154 
3155  /* Skip any remaining addresses for this host. */
3156  conn->addr_cur = NULL;
3157  if (conn->whichhost + 1 < conn->nconnhost)
3158  {
3159  conn->status = CONNECTION_NEEDED;
3160  goto keep_going;
3161  }
3162 
3163  /* No more addresses to try. So we fail. */
3164  goto error_return;
3165  }
3166  PQclear(res);
3167  termPQExpBuffer(&savedMessage);
3168 
3169  /* We can release the address lists now. */
3170  release_all_addrinfo(conn);
3171 
3172  /*
3173  * Finish reading any remaining messages before being
3174  * considered as ready.
3175  */
3176  conn->status = CONNECTION_CONSUME;
3177  goto keep_going;
3178  }
3179 
3180  /*
3181  * Something went wrong with "SHOW transaction_read_only". We
3182  * should try next addresses.
3183  */
3184  if (res)
3185  PQclear(res);
3186  restoreErrorMessage(conn, &savedMessage);
3187 
3188  if (conn->connhost[conn->whichhost].type == CHT_HOST_ADDRESS)
3189  displayed_host = conn->connhost[conn->whichhost].hostaddr;
3190  else
3191  displayed_host = conn->connhost[conn->whichhost].host;
3192  displayed_port = conn->connhost[conn->whichhost].port;
3193  if (displayed_port == NULL || displayed_port[0] == '\0')
3194  displayed_port = DEF_PGPORT_STR;
3196  libpq_gettext("test \"SHOW transaction_read_only\" failed "
3197  "on server \"%s:%s\"\n"),
3198  displayed_host, displayed_port);
3199  conn->status = CONNECTION_OK;
3200  sendTerminateConn(conn);
3201  pqDropConnection(conn, true);
3202 
3203  if (conn->addr_cur->ai_next != NULL ||
3204  conn->whichhost + 1 < conn->nconnhost)
3205  {
3206  conn->addr_cur = conn->addr_cur->ai_next;
3207  conn->status = CONNECTION_NEEDED;
3208  goto keep_going;
3209  }
3210 
3211  /* No more addresses to try. So we fail. */
3212  goto error_return;
3213  }
3214 
3215  default:
3217  libpq_gettext("invalid connection state %d, "
3218  "probably indicative of memory corruption\n"),
3219  conn->status);
3220  goto error_return;
3221  }
3222 
3223  /* Unreachable */
3224 
3225 error_return:
3226 
3227  pgpassfileWarning(conn);
3228 
3229  /*
3230  * We used to close the socket at this point, but that makes it awkward
3231  * for those above us if they wish to remove this socket from their own
3232  * records (an fd_set for example). We'll just have this socket closed
3233  * when PQfinish is called (which is compulsory even after an error, since
3234  * the connection structure must be freed).
3235  */
3236  conn->status = CONNECTION_BAD;
3237  return PGRES_POLLING_FAILED;
3238 }
int pqFlush(PGconn *conn)
Definition: fe-misc.c:961
bool sigpipe_flag
Definition: libpq-int.h:411
int inEnd
Definition: libpq-int.h:434
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
int inStart
Definition: libpq-int.h:432
struct addrinfo * addr_cur
Definition: libpq-int.h:414
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3118
static int connectNoDelay(PGconn *conn)
Definition: fe-connect.c:1397
int pg_fe_sendauth(AuthRequest areq, int payloadlen, PGconn *conn)
Definition: fe-auth.c:836
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:128
int getpeereid(int sock, uid_t *uid, gid_t *gid)
Definition: getpeereid.c:35
bool sigpipe_so
Definition: libpq-int.h:410
char * pqBuildStartupPacket2(PGconn *conn, int *packetlen, const PQEnvironmentOption *options)
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
#define AUTH_REQ_OK
Definition: pqcomm.h:165
int pqCheckInBufferSpace(size_t bytes_needed, PGconn *conn)
Definition: fe-misc.c:408
static void pgpassfileWarning(PGconn *conn)
Definition: fe-connect.c:6507
char * requirepeer
Definition: libpq-int.h:359
char * host
Definition: libpq-int.h:308
struct sockaddr_storage addr
Definition: pqcomm.h:64
char * pqStrerror(int errnum, char *strerrbuf, size_t buflen)
Definition: thread.c:61
static void release_all_addrinfo(PGconn *conn)
Definition: fe-connect.c:3530
static int setKeepalivesIdle(PGconn *conn)
Definition: fe-connect.c:1539
int pqGetInt(int *result, size_t bytes, PGconn *conn)
Definition: fe-misc.c:267
static bool saveErrorMessage(PGconn *conn, PQExpBuffer savedMessage)
Definition: fe-connect.c:1947
#define connect(s, name, namelen)
Definition: win32_port.h:446
static void sendTerminateConn(PGconn *conn)
Definition: fe-connect.c:3558
void pqDropConnection(PGconn *conn, bool flushInput)
Definition: fe-connect.c:431
#define PG_PROTOCOL_MAJOR(v)
Definition: pqcomm.h:104
int PQntuples(const PGresult *res)
Definition: fe-exec.c:2724
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:57
uint32 AuthRequest
Definition: pqcomm.h:179
#define AUTH_REQ_MD5
Definition: pqcomm.h:170
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:2647
pg_conn_host_type type
Definition: libpq-int.h:307
PostgresPollingStatusType pqSetenvPoll(PGconn *conn)
Definition: fe-protocol2.c:49