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

◆ DefaultHost

#define DefaultHost   "localhost"

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

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

◆ DefaultOption

#define DefaultOption   ""

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

◆ DefaultSSLMode

#define DefaultSSLMode   "disable"

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

Referenced by connectOptions2().

◆ DefaultTargetSessionAttrs

#define DefaultTargetSessionAttrs   "any"

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

◆ DefaultTty

#define DefaultTty   ""

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

◆ ERRCODE_APPNAME_UNKNOWN

#define ERRCODE_APPNAME_UNKNOWN   "42704"

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

Referenced by PQconnectPoll().

◆ ERRCODE_CANNOT_CONNECT_NOW

#define ERRCODE_CANNOT_CONNECT_NOW   "57P03"

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

Referenced by internal_ping(), and ProcessStartupPacket().

◆ ERRCODE_INVALID_PASSWORD

#define ERRCODE_INVALID_PASSWORD   "28P01"

Definition at line 93 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 4469 of file fe-connect.c.

Referenced by parseServiceFile().

◆ PGPASSFILE

#define PGPASSFILE   ".pgpass"

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

Referenced by connectOptions2().

Typedef Documentation

◆ internalPQconninfoOption

Function Documentation

◆ closePGconn()

static void closePGconn ( PGconn conn)
static

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

3577 {
3578  PGnotify *notify;
3579  pgParameterStatus *pstatus;
3580 
3581  sendTerminateConn(conn);
3582 
3583  /*
3584  * Must reset the blocking status so a possible reconnect will work.
3585  *
3586  * Don't call PQsetnonblocking() because it will fail if it's unable to
3587  * flush the connection.
3588  */
3589  conn->nonblocking = false;
3590 
3591  /*
3592  * Close the connection, reset all transient state, flush I/O buffers.
3593  */
3594  pqDropConnection(conn, true);
3595  conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just absent */
3596  conn->asyncStatus = PGASYNC_IDLE;
3597  pqClearAsyncResult(conn); /* deallocate result */
3599  release_all_addrinfo(conn);
3600 
3601  notify = conn->notifyHead;
3602  while (notify != NULL)
3603  {
3604  PGnotify *prev = notify;
3605 
3606  notify = notify->next;
3607  free(prev);
3608  }
3609  conn->notifyHead = conn->notifyTail = NULL;
3610  pstatus = conn->pstatus;
3611  while (pstatus != NULL)
3612  {
3613  pgParameterStatus *prev = pstatus;
3614 
3615  pstatus = pstatus->next;
3616  free(prev);
3617  }
3618  conn->pstatus = NULL;
3619  if (conn->lobjfuncs)
3620  free(conn->lobjfuncs);
3621  conn->lobjfuncs = NULL;
3622 }
static void release_all_addrinfo(PGconn *conn)
Definition: fe-connect.c:3521
PGnotify * notifyHead
Definition: libpq-int.h:391
void pqDropConnection(PGconn *conn, bool flushInput)
Definition: fe-connect.c:424
static void sendTerminateConn(PGconn *conn)
Definition: fe-connect.c:3549
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:380
pgParameterStatus * pstatus
Definition: libpq-int.h:421
struct pgNotify * next
Definition: libpq-fe.h:167
PQExpBufferData errorMessage
Definition: libpq-int.h:493
#define free(a)
Definition: header.h:65
struct pgParameterStatus * next
Definition: libpq-int.h:258
ConnStatusType status
Definition: libpq-int.h:379
PGnotify * notifyTail
Definition: libpq-int.h:392
bool nonblocking
Definition: libpq-int.h:386
void pqClearAsyncResult(PGconn *conn)
Definition: fe-exec.c:726
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:145
PGlobjfuncs * lobjfuncs
Definition: libpq-int.h:426

◆ connectDBComplete()

static int connectDBComplete ( PGconn conn)
static

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

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

◆ connectDBStart()

static int connectDBStart ( PGconn conn)
static

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

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

◆ connectFailureMessage()

static void connectFailureMessage ( PGconn conn,
int  errorno 
)
static

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

1419 {
1420  char sebuf[256];
1421 
1422 #ifdef HAVE_UNIX_SOCKETS
1423  if (IS_AF_UNIX(conn->raddr.addr.ss_family))
1424  {
1425  char service[NI_MAXHOST];
1426 
1427  pg_getnameinfo_all(&conn->raddr.addr, conn->raddr.salen,
1428  NULL, 0,
1429  service, sizeof(service),
1430  NI_NUMERICSERV);
1432  libpq_gettext("could not connect to server: %s\n"
1433  "\tIs the server running locally and accepting\n"
1434  "\tconnections on Unix domain socket \"%s\"?\n"),
1435  SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),
1436  service);
1437  }
1438  else
1439 #endif /* HAVE_UNIX_SOCKETS */
1440  {
1441  char host_addr[NI_MAXHOST];
1442  const char *displayed_host;
1443  const char *displayed_port;
1444  struct sockaddr_storage *addr = &conn->raddr.addr;
1445 
1446  /*
1447  * Optionally display the network address with the hostname. This is
1448  * useful to distinguish between IPv4 and IPv6 connections.
1449  */
1450  if (conn->connhost[conn->whichhost].type == CHT_HOST_ADDRESS)
1451  strlcpy(host_addr, conn->connhost[conn->whichhost].hostaddr, NI_MAXHOST);
1452  else if (addr->ss_family == AF_INET)
1453  {
1454  if (inet_net_ntop(AF_INET,
1455  &((struct sockaddr_in *) addr)->sin_addr.s_addr,
1456  32,
1457  host_addr, sizeof(host_addr)) == NULL)
1458  strcpy(host_addr, "???");
1459  }
1460 #ifdef HAVE_IPV6
1461  else if (addr->ss_family == AF_INET6)
1462  {
1463  if (inet_net_ntop(AF_INET6,
1464  &((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr,
1465  128,
1466  host_addr, sizeof(host_addr)) == NULL)
1467  strcpy(host_addr, "???");
1468  }
1469 #endif
1470  else
1471  strcpy(host_addr, "???");
1472 
1473  /* To which host and port were we actually connecting? */
1474  if (conn->connhost[conn->whichhost].type == CHT_HOST_ADDRESS)
1475  displayed_host = conn->connhost[conn->whichhost].hostaddr;
1476  else
1477  displayed_host = conn->connhost[conn->whichhost].host;
1478  displayed_port = conn->connhost[conn->whichhost].port;
1479  if (displayed_port == NULL || displayed_port[0] == '\0')
1480  displayed_port = DEF_PGPORT_STR;
1481 
1482  /*
1483  * If the user did not supply an IP address using 'hostaddr', and
1484  * 'host' was missing or does not match our lookup, display the
1485  * looked-up IP address.
1486  */
1487  if (conn->connhost[conn->whichhost].type != CHT_HOST_ADDRESS &&
1488  strcmp(displayed_host, host_addr) != 0)
1490  libpq_gettext("could not connect to server: %s\n"
1491  "\tIs the server running on host \"%s\" (%s) and accepting\n"
1492  "\tTCP/IP connections on port %s?\n"),
1493  SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),
1494  displayed_host,
1495  host_addr,
1496  displayed_port);
1497  else
1499  libpq_gettext("could not connect to server: %s\n"
1500  "\tIs the server running on host \"%s\" and accepting\n"
1501  "\tTCP/IP connections on port %s?\n"),
1502  SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),
1503  displayed_host,
1504  displayed_port);
1505  }
1506 }
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:699
#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:397
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:403
PQExpBufferData errorMessage
Definition: libpq-int.h:493
#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:396
#define libpq_gettext(x)
Definition: libpq-int.h:685

◆ connectNoDelay()

static int connectNoDelay ( PGconn conn)
static

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

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

Referenced by PQconnectPoll().

1391 {
1392 #ifdef TCP_NODELAY
1393  int on = 1;
1394 
1395  if (setsockopt(conn->sock, IPPROTO_TCP, TCP_NODELAY,
1396  (char *) &on,
1397  sizeof(on)) < 0)
1398  {
1399  char sebuf[256];
1400 
1402  libpq_gettext("could not set socket to TCP no delay mode: %s\n"),
1403  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
1404  return 0;
1405  }
1406 #endif
1407 
1408  return 1;
1409 }
#define SOCK_STRERROR
Definition: libpq-int.h:699
#define SOCK_ERRNO
Definition: libpq-int.h:698
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
pgsocket sock
Definition: libpq-int.h:400
PQExpBufferData errorMessage
Definition: libpq-int.h:493
#define libpq_gettext(x)
Definition: libpq-int.h:685

◆ connectOptions1()

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

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

798 {
799  PQconninfoOption *connOptions;
800 
801  /*
802  * Parse the conninfo string
803  */
804  connOptions = parse_connection_string(conninfo, &conn->errorMessage, true);
805  if (connOptions == NULL)
806  {
807  conn->status = CONNECTION_BAD;
808  /* errorMessage is already set */
809  return false;
810  }
811 
812  /*
813  * Move option values into conn structure
814  */
815  if (!fillPGconn(conn, connOptions))
816  {
817  conn->status = CONNECTION_BAD;
818  PQconninfoFree(connOptions);
819  return false;
820  }
821 
822  /*
823  * Free the option info - all is in conn now
824  */
825  PQconninfoFree(connOptions);
826 
827  return true;
828 }
static PQconninfoOption * parse_connection_string(const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:4788
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:5956
PQExpBufferData errorMessage
Definition: libpq-int.h:493
static bool fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
Definition: fe-connect.c:755
ConnStatusType status
Definition: libpq-int.h:379

◆ connectOptions2()

static bool connectOptions2 ( PGconn conn)
static

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

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

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

◆ 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 5020 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().

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

◆ conninfo_find()

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

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

References _PQconninfoOption::keyword.

Referenced by conninfo_getval(), and conninfo_storeval().

5898 {
5900 
5901  for (option = connOptions; option->keyword != NULL; option++)
5902  {
5903  if (strcmp(option->keyword, keyword) == 0)
5904  return option;
5905  }
5906 
5907  return NULL;
5908 }

◆ conninfo_getval()

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

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

References conninfo_find(), and _PQconninfoOption::val.

Referenced by fillPGconn(), and parseServiceInfo().

5808 {
5810 
5811  option = conninfo_find(connOptions, keyword);
5812 
5813  return option ? option->val : NULL;
5814 }
static PQconninfoOption * conninfo_find(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:5897

◆ conninfo_init()

static PQconninfoOption * conninfo_init ( PQExpBuffer  errorMessage)
static

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

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

◆ conninfo_parse()

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

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

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

◆ 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 5832 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().

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

◆ conninfo_uri_decode()

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

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

5718 {
5719  char *buf;
5720  char *p;
5721  const char *q = str;
5722 
5723  buf = malloc(strlen(str) + 1);
5724  if (buf == NULL)
5725  {
5726  printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n"));
5727  return NULL;
5728  }
5729  p = buf;
5730 
5731  for (;;)
5732  {
5733  if (*q != '%')
5734  {
5735  /* copy and check for NUL terminator */
5736  if (!(*(p++) = *(q++)))
5737  break;
5738  }
5739  else
5740  {
5741  int hi;
5742  int lo;
5743  int c;
5744 
5745  ++q; /* skip the percent sign itself */
5746 
5747  /*
5748  * Possible EOL will be caught by the first call to
5749  * get_hexdigit(), so we never dereference an invalid q pointer.
5750  */
5751  if (!(get_hexdigit(*q++, &hi) && get_hexdigit(*q++, &lo)))
5752  {
5753  printfPQExpBuffer(errorMessage,
5754  libpq_gettext("invalid percent-encoded token: \"%s\"\n"),
5755  str);
5756  free(buf);
5757  return NULL;
5758  }
5759 
5760  c = (hi << 4) | lo;
5761  if (c == 0)
5762  {
5763  printfPQExpBuffer(errorMessage,
5764  libpq_gettext("forbidden value %%00 in percent-encoded value: \"%s\"\n"),
5765  str);
5766  free(buf);
5767  return NULL;
5768  }
5769  *(p++) = c;
5770  }
5771  }
5772 
5773  return buf;
5774 }
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:5785
#define libpq_gettext(x)
Definition: libpq-int.h:685

◆ conninfo_uri_parse()

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

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

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

Referenced by parse_connection_string().

5291 {
5293 
5294  /* Make a working copy of PQconninfoOptions */
5295  options = conninfo_init(errorMessage);
5296  if (options == NULL)
5297  return NULL;
5298 
5299  if (!conninfo_uri_parse_options(options, uri, errorMessage))
5300  {
5301  PQconninfoFree(options);
5302  return NULL;
5303  }
5304 
5305  /*
5306  * Add in defaults if the caller wants that.
5307  */
5308  if (use_defaults)
5309  {
5310  if (!conninfo_add_defaults(options, errorMessage))
5311  {
5312  PQconninfoFree(options);
5313  return NULL;
5314  }
5315  }
5316 
5317  return options;
5318 }
static PQconninfoOption * conninfo_init(PQExpBuffer errorMessage)
Definition: fe-connect.c:4748
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:5956
static bool conninfo_uri_parse_options(PQconninfoOption *options, const char *uri, PQExpBuffer errorMessage)
Definition: fe-connect.c:5342
static char ** options
static bool conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5184

◆ conninfo_uri_parse_options()

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

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

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

◆ conninfo_uri_parse_params()

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

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

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

◆ count_comma_separated_elems()

static int count_comma_separated_elems ( const char *  input)
static

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

Referenced by connectOptions2().

835 {
836  int n;
837 
838  n = 1;
839  for (; *input != '\0'; input++)
840  {
841  if (*input == ',')
842  n++;
843  }
844 
845  return n;
846 }

◆ default_threadlock()

static void default_threadlock ( int  acquire)
static

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

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

Referenced by PQregisterThreadLock().

6563 {
6564 #ifdef ENABLE_THREAD_SAFETY
6565 #ifndef WIN32
6566  static pthread_mutex_t singlethread_lock = PTHREAD_MUTEX_INITIALIZER;
6567 #else
6568  static pthread_mutex_t singlethread_lock = NULL;
6569  static long mutex_initlock = 0;
6570 
6571  if (singlethread_lock == NULL)
6572  {
6573  while (InterlockedExchange(&mutex_initlock, 1) == 1)
6574  /* loop, another thread own the lock */ ;
6575  if (singlethread_lock == NULL)
6576  {
6577  if (pthread_mutex_init(&singlethread_lock, NULL))
6578  PGTHREAD_ERROR("failed to initialize mutex");
6579  }
6580  InterlockedExchange(&mutex_initlock, 0);
6581  }
6582 #endif
6583  if (acquire)
6584  {
6585  if (pthread_mutex_lock(&singlethread_lock))
6586  PGTHREAD_ERROR("failed to lock mutex");
6587  }
6588  else
6589  {
6590  if (pthread_mutex_unlock(&singlethread_lock))
6591  PGTHREAD_ERROR("failed to unlock mutex");
6592  }
6593 #endif
6594 }
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 6320 of file fe-connect.c.

Referenced by makeEmptyPGconn().

6321 {
6322  (void) arg; /* not used */
6323  /* Note: we expect the supplied string to end with a newline already. */
6324  fprintf(stderr, "%s", message);
6325 }
void * arg

◆ defaultNoticeReceiver()

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

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

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

Referenced by makeEmptyPGconn().

6306 {
6307  (void) arg; /* not used */
6308  if (res->noticeHooks.noticeProc != NULL)
6310  PQresultErrorMessage(res));
6311 }
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 755 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().

756 {
758 
759  for (option = PQconninfoOptions; option->keyword; option++)
760  {
761  if (option->connofs >= 0)
762  {
763  const char *tmp = conninfo_getval(connOptions, option->keyword);
764 
765  if (tmp)
766  {
767  char **connmember = (char **) ((char *) conn + option->connofs);
768 
769  if (*connmember)
770  free(*connmember);
771  *connmember = strdup(tmp);
772  if (*connmember == NULL)
773  {
775  libpq_gettext("out of memory\n"));
776  return false;
777  }
778  }
779  }
780  }
781 
782  return true;
783 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
static const internalPQconninfoOption PQconninfoOptions[]
Definition: fe-connect.c:181
PQExpBufferData errorMessage
Definition: libpq-int.h:493
#define free(a)
Definition: header.h:65
static const char * conninfo_getval(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:5806
#define libpq_gettext(x)
Definition: libpq-int.h:685

◆ freePGconn()

static void freePGconn ( PGconn conn)
static

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

References pg_conn::appname, pg_conn::client_encoding_initial, conn, PGEventConnDestroy::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::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().

3403 {
3404  int i;
3405 
3406  /* let any event procs clean up their state data */
3407  for (i = 0; i < conn->nEvents; i++)
3408  {
3409  PGEventConnDestroy evt;
3410 
3411  evt.conn = conn;
3412  (void) conn->events[i].proc(PGEVT_CONNDESTROY, &evt,
3413  conn->events[i].passThrough);
3414  free(conn->events[i].name);
3415  }
3416 
3417  /* clean up pg_conn_host structures */
3418  if (conn->connhost != NULL)
3419  {
3420  for (i = 0; i < conn->nconnhost; ++i)
3421  {
3422  if (conn->connhost[i].host != NULL)
3423  free(conn->connhost[i].host);
3424  if (conn->connhost[i].hostaddr != NULL)
3425  free(conn->connhost[i].hostaddr);
3426  if (conn->connhost[i].port != NULL)
3427  free(conn->connhost[i].port);
3428  if (conn->connhost[i].password != NULL)
3429  free(conn->connhost[i].password);
3430  }
3431  free(conn->connhost);
3432  }
3433 
3434  if (conn->client_encoding_initial)
3436  if (conn->events)
3437  free(conn->events);
3438  if (conn->pghost)
3439  free(conn->pghost);
3440  if (conn->pghostaddr)
3441  free(conn->pghostaddr);
3442  if (conn->pgport)
3443  free(conn->pgport);
3444  if (conn->pgtty)
3445  free(conn->pgtty);
3446  if (conn->connect_timeout)
3447  free(conn->connect_timeout);
3448  if (conn->pgoptions)
3449  free(conn->pgoptions);
3450  if (conn->appname)
3451  free(conn->appname);
3452  if (conn->fbappname)
3453  free(conn->fbappname);
3454  if (conn->dbName)
3455  free(conn->dbName);
3456  if (conn->replication)
3457  free(conn->replication);
3458  if (conn->pguser)
3459  free(conn->pguser);
3460  if (conn->pgpass)
3461  free(conn->pgpass);
3462  if (conn->pgpassfile)
3463  free(conn->pgpassfile);
3464  if (conn->keepalives)
3465  free(conn->keepalives);
3466  if (conn->keepalives_idle)
3467  free(conn->keepalives_idle);
3468  if (conn->keepalives_interval)
3469  free(conn->keepalives_interval);
3470  if (conn->keepalives_count)
3471  free(conn->keepalives_count);
3472  if (conn->sslmode)
3473  free(conn->sslmode);
3474  if (conn->sslcert)
3475  free(conn->sslcert);
3476  if (conn->sslkey)
3477  free(conn->sslkey);
3478  if (conn->sslrootcert)
3479  free(conn->sslrootcert);
3480  if (conn->sslcrl)
3481  free(conn->sslcrl);
3482  if (conn->sslcompression)
3483  free(conn->sslcompression);
3484  if (conn->requirepeer)
3485  free(conn->requirepeer);
3486 #if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
3487  if (conn->krbsrvname)
3488  free(conn->krbsrvname);
3489 #endif
3490 #if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
3491  if (conn->gsslib)
3492  free(conn->gsslib);
3493 #endif
3494  /* Note that conn->Pfdebug is not ours to close or free */
3495  if (conn->last_query)
3496  free(conn->last_query);
3497  if (conn->inBuffer)
3498  free(conn->inBuffer);
3499  if (conn->outBuffer)
3500  free(conn->outBuffer);
3501  if (conn->rowBuf)
3502  free(conn->rowBuf);
3503  if (conn->target_session_attrs)
3504  free(conn->target_session_attrs);
3505  termPQExpBuffer(&conn->errorMessage);
3506  termPQExpBuffer(&conn->workBuffer);
3507 
3508  free(conn);
3509 
3510 #ifdef WIN32
3511  WSACleanup();
3512 #endif
3513 }
PGEvent * events
Definition: libpq-int.h:374
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:496
char * requirepeer
Definition: libpq-int.h:358
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:354
char * sslcompression
Definition: libpq-int.h:353
PGconn * conn
Definition: streamutil.c:46
char * hostaddr
Definition: libpq-int.h:309
char * connect_timeout
Definition: libpq-int.h:336
pg_conn_host * connhost
Definition: libpq-int.h:397
char * keepalives_interval
Definition: libpq-int.h:348
char * appname
Definition: libpq-int.h:339
char * target_session_attrs
Definition: libpq-int.h:365
char * last_query
Definition: libpq-int.h:383
PGdataValue * rowBuf
Definition: libpq-int.h:446
char * pguser
Definition: libpq-int.h:343
char * inBuffer
Definition: libpq-int.h:429
char * sslmode
Definition: libpq-int.h:352
PQExpBufferData errorMessage
Definition: libpq-int.h:493
char * sslcert
Definition: libpq-int.h:355
#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:356
PGEventProc proc
Definition: libpq-int.h:160
char * outBuffer
Definition: libpq-int.h:436
char * pghostaddr
Definition: libpq-int.h:330
int nEvents
Definition: libpq-int.h:375
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:395
char * name
Definition: libpq-int.h:161
char * sslcrl
Definition: libpq-int.h:357
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 5785 of file fe-connect.c.

Referenced by conninfo_uri_decode().

5786 {
5787  if ('0' <= digit && digit <= '9')
5788  *value = digit - '0';
5789  else if ('A' <= digit && digit <= 'F')
5790  *value = digit - 'A' + 10;
5791  else if ('a' <= digit && digit <= 'f')
5792  *value = digit - 'a' + 10;
5793  else
5794  return false;
5795 
5796  return true;
5797 }
static struct @121 value

◆ internal_cancel()

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

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

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

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

◆ makeEmptyPGconn()

static PGconn * makeEmptyPGconn ( void  )
static

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

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

◆ parse_comma_separated_list()

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

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

References malloc.

Referenced by connectOptions2().

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

◆ parse_connection_string()

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

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

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

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

4790 {
4791  /* Parse as URI if connection string matches URI prefix */
4792  if (uri_prefix_length(connstr) != 0)
4793  return conninfo_uri_parse(connstr, errorMessage, use_defaults);
4794 
4795  /* Parse as default otherwise */
4796  return conninfo_parse(connstr, errorMessage, use_defaults);
4797 }
static PQconninfoOption * conninfo_parse(const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:4842
static int uri_prefix_length(const char *connstr)
Definition: fe-connect.c:4808
static PQconninfoOption * conninfo_uri_parse(const char *uri, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5289
static char * connstr
Definition: pg_dumpall.c:64

◆ parseServiceFile()

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

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

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

Referenced by parseServiceInfo().

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

◆ parseServiceInfo()

static int parseServiceInfo ( PQconninfoOption options,
PQExpBuffer  errorMessage 
)
static

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

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

Referenced by conninfo_add_defaults().

4483 {
4484  const char *service = conninfo_getval(options, "service");
4485  char serviceFile[MAXPGPATH];
4486  char *env;
4487  bool group_found = false;
4488  int status;
4489  struct stat stat_buf;
4490 
4491  /*
4492  * We have to special-case the environment variable PGSERVICE here, since
4493  * this is and should be called before inserting environment defaults for
4494  * other connection options.
4495  */
4496  if (service == NULL)
4497  service = getenv("PGSERVICE");
4498 
4499  /* If no service name given, nothing to do */
4500  if (service == NULL)
4501  return 0;
4502 
4503  /*
4504  * Try PGSERVICEFILE if specified, else try ~/.pg_service.conf (if that
4505  * exists).
4506  */
4507  if ((env = getenv("PGSERVICEFILE")) != NULL)
4508  strlcpy(serviceFile, env, sizeof(serviceFile));
4509  else
4510  {
4511  char homedir[MAXPGPATH];
4512 
4513  if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
4514  goto next_file;
4515  snprintf(serviceFile, MAXPGPATH, "%s/%s", homedir, ".pg_service.conf");
4516  if (stat(serviceFile, &stat_buf) != 0)
4517  goto next_file;
4518  }
4519 
4520  status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
4521  if (group_found || status != 0)
4522  return status;
4523 
4524 next_file:
4525 
4526  /*
4527  * This could be used by any application so we can't use the binary
4528  * location to find our config files.
4529  */
4530  snprintf(serviceFile, MAXPGPATH, "%s/pg_service.conf",
4531  getenv("PGSYSCONFDIR") ? getenv("PGSYSCONFDIR") : SYSCONFDIR);
4532  if (stat(serviceFile, &stat_buf) != 0)
4533  goto last_file;
4534 
4535  status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
4536  if (status != 0)
4537  return status;
4538 
4539 last_file:
4540  if (!group_found)
4541  {
4542  printfPQExpBuffer(errorMessage,
4543  libpq_gettext("definition of service \"%s\" not found\n"), service);
4544  return 3;
4545  }
4546 
4547  return 0;
4548 }
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:4551
static const char * conninfo_getval(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:5806
bool pqGetHomeDirectory(char *buf, int bufsize)
Definition: fe-connect.c:6533
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:685

◆ passwordFromFile()

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

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

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

◆ pgpassfileWarning()

static void pgpassfileWarning ( PGconn conn)
static

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

6498 {
6499  /* If it was 'invalid authorization', add pgpassfile mention */
6500  /* only works with >= 9.0 servers */
6501  if (conn->pgpassfile_used && conn->password_needed && conn->result)
6502  {
6503  const char *sqlstate = PQresultErrorField(conn->result,
6505 
6506  if (sqlstate && strcmp(sqlstate, ERRCODE_INVALID_PASSWORD) == 0)
6508  libpq_gettext("password retrieved from file \"%s\"\n"),
6509  conn->pgpassfile);
6510  }
6511 }
char * pgpassfile
Definition: libpq-int.h:345
bool password_needed
Definition: libpq-int.h:407
bool pgpassfile_used
Definition: libpq-int.h:408
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:57
PGresult * result
Definition: libpq-int.h:450
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
PQExpBufferData errorMessage
Definition: libpq-int.h:493
char * PQresultErrorField(const PGresult *res, int fieldcode)
Definition: fe-exec.c:2709
#define ERRCODE_INVALID_PASSWORD
Definition: fe-connect.c:93
#define libpq_gettext(x)
Definition: libpq-int.h:685

◆ PQbackendPID()

int PQbackendPID ( const PGconn conn)

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

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

Referenced by get_prompt(), and StartLogStreamer().

6133 {
6134  if (!conn || conn->status != CONNECTION_OK)
6135  return 0;
6136  return conn->be_pid;
6137 }
ConnStatusType status
Definition: libpq-int.h:379
int be_pid
Definition: libpq-int.h:419

◆ PQcancel()

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

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

3906 {
3907  if (!cancel)
3908  {
3909  strlcpy(errbuf, "PQcancel() -- no cancel object supplied", errbufsize);
3910  return false;
3911  }
3912 
3913  return internal_cancel(&cancel->raddr, cancel->be_pid, cancel->be_key,
3914  errbuf, errbufsize);
3915 }
static int internal_cancel(SockAddr *raddr, int be_pid, int be_key, char *errbuf, int errbufsize)
Definition: fe-connect.c:3801
int be_pid
Definition: libpq-int.h:506
int be_key
Definition: libpq-int.h:507
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
SockAddr raddr
Definition: libpq-int.h:505

◆ PQclientEncoding()

int PQclientEncoding ( const PGconn conn)

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

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

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

6167 {
6168  if (!conn || conn->status != CONNECTION_OK)
6169  return -1;
6170  return conn->client_encoding;
6171 }
ConnStatusType status
Definition: libpq-int.h:379
int client_encoding
Definition: libpq-int.h:422

◆ PQconndefaults()

PQconninfoOption* PQconndefaults ( void  )

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

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

◆ PQconnectdb()

PGconn* PQconnectdb ( const char *  conninfo)

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

586 {
587  PGconn *conn = PQconnectStart(conninfo);
588 
589  if (conn && conn->status != CONNECTION_BAD)
590  (void) connectDBComplete(conn);
591 
592  return conn;
593 }
PGconn * conn
Definition: streamutil.c:46
static int connectDBComplete(PGconn *conn)
Definition: fe-connect.c:1834
PGconn * PQconnectStart(const char *conninfo)
Definition: fe-connect.c:711
ConnStatusType status
Definition: libpq-int.h:379

◆ PQconnectdbParams()

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

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

532 {
533  PGconn *conn = PQconnectStartParams(keywords, values, expand_dbname);
534 
535  if (conn && conn->status != CONNECTION_BAD)
536  (void) connectDBComplete(conn);
537 
538  return conn;
539 
540 }
PGconn * conn
Definition: streamutil.c:46
static int connectDBComplete(PGconn *conn)
Definition: fe-connect.c:1834
ConnStatusType status
Definition: libpq-int.h:379
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:632

◆ PQconnectionNeedsPassword()

int PQconnectionNeedsPassword ( const PGconn conn)

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

6141 {
6142  char *password;
6143 
6144  if (!conn)
6145  return false;
6146  password = PQpass(conn);
6147  if (conn->password_needed &&
6148  (password == NULL || password[0] == '\0'))
6149  return true;
6150  else
6151  return false;
6152 }
static char password[100]
Definition: streamutil.c:45
bool password_needed
Definition: libpq-int.h:407
char * PQpass(const PGconn *conn)
Definition: fe-connect.c:5990

◆ PQconnectionUsedPassword()

int PQconnectionUsedPassword ( const PGconn conn)

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

References pg_conn::password_needed.

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

6156 {
6157  if (!conn)
6158  return false;
6159  if (conn->password_needed)
6160  return true;
6161  else
6162  return false;
6163 }
bool password_needed
Definition: libpq-int.h:407

◆ PQconnectPoll()

PostgresPollingStatusType PQconnectPoll ( PGconn conn)

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

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