PostgreSQL Source Code  git master
libpq-int.h File Reference
#include "libpq-events.h"
#include <netdb.h>
#include <sys/socket.h>
#include <time.h>
#include <pthread.h>
#include <signal.h>
#include "libpq/pqcomm.h"
#include "fe-auth-sasl.h"
#include "pqexpbuffer.h"
#include "common/pg_prng.h"
Include dependency graph for libpq-int.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

union  pgresult_data
 
struct  pgresParamDesc
 
struct  pgresAttValue
 
struct  pgMessageField
 
struct  PGNoticeHooks
 
struct  PGEvent
 
struct  pg_result
 
struct  PQEnvironmentOption
 
struct  pgParameterStatus
 
struct  pgLobjfuncs
 
struct  pgDataValue
 
struct  PGcmdQueueEntry
 
struct  pg_conn_host
 
struct  pg_conn
 

Macros

#define CMDSTATUS_LEN   64 /* should match COMPLETION_TAG_BUFSIZE */
 
#define NULL_LEN   (-1) /* pg_result len for NULL value */
 
#define ENC_ERROR   0
 
#define ENC_PLAINTEXT   0x01
 
#define ENC_GSSAPI   0x02
 
#define ENC_SSL   0x04
 
#define AUTH_RESPONSE_GSS   'G'
 
#define AUTH_RESPONSE_PASSWORD   'P'
 
#define AUTH_RESPONSE_SASL_INITIAL   'I'
 
#define AUTH_RESPONSE_SASL   'S'
 
#define pglock_thread()   pg_g_threadlock(true)
 
#define pgunlock_thread()   pg_g_threadlock(false)
 
#define pqClearConnErrorState(conn)
 
#define pgHavePendingResult(conn)    ((conn)->result != NULL || (conn)->error_result)
 
#define pqIsnonblocking(conn)   ((conn)->nonblocking)
 
#define OUTBUFFER_THRESHOLD   65536
 
#define libpq_gettext(x)   (x)
 
#define libpq_ngettext(s, p, n)   ((n) == 1 ? (s) : (p))
 
#define SOCK_ERRNO   errno
 
#define SOCK_STRERROR   strerror_r
 
#define SOCK_ERRNO_SET(e)   (errno = (e))
 

Typedefs

typedef union pgresult_data PGresult_data
 
typedef struct pgresParamDesc PGresParamDesc
 
typedef struct pgresAttValue PGresAttValue
 
typedef struct pgMessageField PGMessageField
 
typedef struct PGEvent PGEvent
 
typedef struct PQEnvironmentOption PQEnvironmentOption
 
typedef struct pgParameterStatus pgParameterStatus
 
typedef struct pgLobjfuncs PGlobjfuncs
 
typedef struct pgDataValue PGdataValue
 
typedef enum pg_conn_host_type pg_conn_host_type
 
typedef struct PGcmdQueueEntry PGcmdQueueEntry
 
typedef struct pg_conn_host pg_conn_host
 

Enumerations

enum  PGAsyncStatusType {
  PGASYNC_IDLE , PGASYNC_BUSY , PGASYNC_READY , PGASYNC_READY_MORE ,
  PGASYNC_COPY_IN , PGASYNC_COPY_OUT , PGASYNC_COPY_BOTH , PGASYNC_PIPELINE_IDLE
}
 
enum  PGTargetServerType {
  SERVER_TYPE_ANY = 0 , SERVER_TYPE_READ_WRITE , SERVER_TYPE_READ_ONLY , SERVER_TYPE_PRIMARY ,
  SERVER_TYPE_STANDBY , SERVER_TYPE_PREFER_STANDBY , SERVER_TYPE_PREFER_STANDBY_PASS2
}
 
enum  PGLoadBalanceType { LOAD_BALANCE_DISABLE = 0 , LOAD_BALANCE_RANDOM }
 
enum  PGTernaryBool { PG_BOOL_UNKNOWN = 0 , PG_BOOL_YES , PG_BOOL_NO }
 
enum  pg_conn_host_type { CHT_HOST_NAME , CHT_HOST_ADDRESS , CHT_UNIX_SOCKET }
 
enum  PGQueryClass {
  PGQUERY_SIMPLE , PGQUERY_EXTENDED , PGQUERY_PREPARE , PGQUERY_DESCRIBE ,
  PGQUERY_SYNC , PGQUERY_CLOSE
}
 

Functions

void pqDropConnection (PGconn *conn, bool flushInput)
 
bool pqConnectOptions2 (PGconn *conn)
 
int pqConnectDBStart (PGconn *conn)
 
int pqConnectDBComplete (PGconn *conn)
 
PGconnpqMakeEmptyPGconn (void)
 
void pqReleaseConnHosts (PGconn *conn)
 
void pqClosePGconn (PGconn *conn)
 
int pqPacketSend (PGconn *conn, char pack_type, const void *buf, size_t buf_len)
 
bool pqGetHomeDirectory (char *buf, int bufsize)
 
bool pqCopyPGconn (PGconn *srcConn, PGconn *dstConn)
 
bool pqParseIntParam (const char *value, int *result, PGconn *conn, const char *context)
 
void pqSetResultError (PGresult *res, PQExpBuffer errorMessage, int offset)
 
void * pqResultAlloc (PGresult *res, size_t nBytes, bool isBinary)
 
char * pqResultStrdup (PGresult *res, const char *str)
 
void pqClearAsyncResult (PGconn *conn)
 
void pqSaveErrorResult (PGconn *conn)
 
PGresultpqPrepareAsyncResult (PGconn *conn)
 
void pqInternalNotice (const PGNoticeHooks *hooks, const char *fmt,...) pg_attribute_printf(2
 
void void pqSaveMessageField (PGresult *res, char code, const char *value)
 
void pqSaveParameterStatus (PGconn *conn, const char *name, const char *value)
 
int pqRowProcessor (PGconn *conn, const char **errmsgp)
 
void pqCommandQueueAdvance (PGconn *conn, bool isReadyForQuery, bool gotSync)
 
int PQsendQueryContinue (PGconn *conn, const char *query)
 
char * pqBuildStartupPacket3 (PGconn *conn, int *packetlen, const PQEnvironmentOption *options)
 
void pqParseInput3 (PGconn *conn)
 
int pqGetErrorNotice3 (PGconn *conn, bool isError)
 
void pqBuildErrorMessage3 (PQExpBuffer msg, const PGresult *res, PGVerbosity verbosity, PGContextVisibility show_context)
 
int pqGetNegotiateProtocolVersion3 (PGconn *conn)
 
int pqGetCopyData3 (PGconn *conn, char **buffer, int async)
 
int pqGetline3 (PGconn *conn, char *s, int maxlen)
 
int pqGetlineAsync3 (PGconn *conn, char *buffer, int bufsize)
 
int pqEndcopy3 (PGconn *conn)
 
PGresultpqFunctionCall3 (PGconn *conn, Oid fnid, int *result_buf, int *actual_result_len, int result_is_int, const PQArgBlock *args, int nargs)
 
int pqCheckOutBufferSpace (size_t bytes_needed, PGconn *conn)
 
int pqCheckInBufferSpace (size_t bytes_needed, PGconn *conn)
 
void pqParseDone (PGconn *conn, int newInStart)
 
int pqGetc (char *result, PGconn *conn)
 
int pqPutc (char c, PGconn *conn)
 
int pqGets (PQExpBuffer buf, PGconn *conn)
 
int pqGets_append (PQExpBuffer buf, PGconn *conn)
 
int pqPuts (const char *s, PGconn *conn)
 
int pqGetnchar (char *s, size_t len, PGconn *conn)
 
int pqSkipnchar (size_t len, PGconn *conn)
 
int pqPutnchar (const char *s, size_t len, PGconn *conn)
 
int pqGetInt (int *result, size_t bytes, PGconn *conn)
 
int pqPutInt (int value, size_t bytes, PGconn *conn)
 
int pqPutMsgStart (char msg_type, PGconn *conn)
 
int pqPutMsgEnd (PGconn *conn)
 
int pqReadData (PGconn *conn)
 
int pqFlush (PGconn *conn)
 
int pqWait (int forRead, int forWrite, PGconn *conn)
 
int pqWaitTimed (int forRead, int forWrite, PGconn *conn, pg_usec_time_t end_time)
 
int pqReadReady (PGconn *conn)
 
int pqWriteReady (PGconn *conn)
 
PostgresPollingStatusType pqsecure_open_client (PGconn *)
 
void pqsecure_close (PGconn *)
 
ssize_t pqsecure_read (PGconn *, void *ptr, size_t len)
 
ssize_t pqsecure_write (PGconn *, const void *ptr, size_t len)
 
ssize_t pqsecure_raw_read (PGconn *, void *ptr, size_t len)
 
ssize_t pqsecure_raw_write (PGconn *, const void *ptr, size_t len)
 
int pq_block_sigpipe (sigset_t *osigset, bool *sigpipe_pending)
 
void pq_reset_sigpipe (sigset_t *osigset, bool sigpipe_pending, bool got_epipe)
 
PostgresPollingStatusType pgtls_open_client (PGconn *conn)
 
void pgtls_close (PGconn *conn)
 
ssize_t pgtls_read (PGconn *conn, void *ptr, size_t len)
 
bool pgtls_read_pending (PGconn *conn)
 
ssize_t pgtls_write (PGconn *conn, const void *ptr, size_t len)
 
char * pgtls_get_peer_certificate_hash (PGconn *conn, size_t *len)
 
int pgtls_verify_peer_name_matches_certificate_guts (PGconn *conn, int *names_examined, char **first_name)
 
void pqTraceOutputMessage (PGconn *conn, const char *message, bool toServer)
 
void pqTraceOutputNoTypeByteMessage (PGconn *conn, const char *message)
 
void pqTraceOutputCharResponse (PGconn *conn, const char *responseType, char response)
 
void libpq_append_error (PQExpBuffer errorMessage, const char *fmt,...) pg_attribute_printf(2
 
void void libpq_append_conn_error (PGconn *conn, const char *fmt,...) pg_attribute_printf(2
 

Variables

char *const pgresStatus []
 
pgthreadlock_t pg_g_threadlock
 

Macro Definition Documentation

◆ AUTH_RESPONSE_GSS

#define AUTH_RESPONSE_GSS   'G'

Definition at line 341 of file libpq-int.h.

◆ AUTH_RESPONSE_PASSWORD

#define AUTH_RESPONSE_PASSWORD   'P'

Definition at line 342 of file libpq-int.h.

◆ AUTH_RESPONSE_SASL

#define AUTH_RESPONSE_SASL   'S'

Definition at line 344 of file libpq-int.h.

◆ AUTH_RESPONSE_SASL_INITIAL

#define AUTH_RESPONSE_SASL_INITIAL   'I'

Definition at line 343 of file libpq-int.h.

◆ CMDSTATUS_LEN

#define CMDSTATUS_LEN   64 /* should match COMPLETION_TAG_BUFSIZE */

Definition at line 89 of file libpq-int.h.

◆ ENC_ERROR

#define ENC_ERROR   0

Definition at line 235 of file libpq-int.h.

◆ ENC_GSSAPI

#define ENC_GSSAPI   0x02

Definition at line 237 of file libpq-int.h.

◆ ENC_PLAINTEXT

#define ENC_PLAINTEXT   0x01

Definition at line 236 of file libpq-int.h.

◆ ENC_SSL

#define ENC_SSL   0x04

Definition at line 238 of file libpq-int.h.

◆ libpq_gettext

#define libpq_gettext (   x)    (x)

Definition at line 906 of file libpq-int.h.

◆ libpq_ngettext

#define libpq_ngettext (   s,
  p,
 
)    ((n) == 1 ? (s) : (p))

Definition at line 907 of file libpq-int.h.

◆ NULL_LEN

#define NULL_LEN   (-1) /* pg_result len for NULL value */

Definition at line 136 of file libpq-int.h.

◆ OUTBUFFER_THRESHOLD

#define OUTBUFFER_THRESHOLD   65536

Definition at line 900 of file libpq-int.h.

◆ pgHavePendingResult

#define pgHavePendingResult (   conn)     ((conn)->result != NULL || (conn)->error_result)

Definition at line 888 of file libpq-int.h.

◆ pglock_thread

#define pglock_thread ( )    pg_g_threadlock(true)

Definition at line 704 of file libpq-int.h.

◆ pgunlock_thread

#define pgunlock_thread ( )    pg_g_threadlock(false)

Definition at line 705 of file libpq-int.h.

◆ pqClearConnErrorState

#define pqClearConnErrorState (   conn)
Value:
(resetPQExpBuffer(&(conn)->errorMessage), \
(conn)->errorReported = 0)
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:146
PGconn * conn
Definition: streamutil.c:55

Definition at line 879 of file libpq-int.h.

◆ pqIsnonblocking

#define pqIsnonblocking (   conn)    ((conn)->nonblocking)

Definition at line 895 of file libpq-int.h.

◆ SOCK_ERRNO

#define SOCK_ERRNO   errno

Definition at line 927 of file libpq-int.h.

◆ SOCK_ERRNO_SET

#define SOCK_ERRNO_SET (   e)    (errno = (e))

Definition at line 929 of file libpq-int.h.

◆ SOCK_STRERROR

#define SOCK_STRERROR   strerror_r

Definition at line 928 of file libpq-int.h.

Typedef Documentation

◆ pg_conn_host

typedef struct pg_conn_host pg_conn_host

◆ pg_conn_host_type

◆ PGcmdQueueEntry

◆ PGdataValue

typedef struct pgDataValue PGdataValue

◆ PGEvent

typedef struct PGEvent PGEvent

◆ PGlobjfuncs

typedef struct pgLobjfuncs PGlobjfuncs

◆ PGMessageField

◆ pgParameterStatus

◆ PGresAttValue

typedef struct pgresAttValue PGresAttValue

◆ PGresParamDesc

◆ PGresult_data

Definition at line 1 of file libpq-int.h.

◆ PQEnvironmentOption

Enumeration Type Documentation

◆ pg_conn_host_type

Enumerator
CHT_HOST_NAME 
CHT_HOST_ADDRESS 
CHT_UNIX_SOCKET 

Definition at line 313 of file libpq-int.h.

314 {
pg_conn_host_type
Definition: libpq-int.h:314
@ CHT_UNIX_SOCKET
Definition: libpq-int.h:317
@ CHT_HOST_ADDRESS
Definition: libpq-int.h:316
@ CHT_HOST_NAME
Definition: libpq-int.h:315

◆ PGAsyncStatusType

Enumerator
PGASYNC_IDLE 
PGASYNC_BUSY 
PGASYNC_READY 
PGASYNC_READY_MORE 
PGASYNC_COPY_IN 
PGASYNC_COPY_OUT 
PGASYNC_COPY_BOTH 
PGASYNC_PIPELINE_IDLE 

Definition at line 219 of file libpq-int.h.

220 {
221  PGASYNC_IDLE, /* nothing's happening, dude */
222  PGASYNC_BUSY, /* query in progress */
223  PGASYNC_READY, /* query done, waiting for client to fetch
224  * result */
225  PGASYNC_READY_MORE, /* query done, waiting for client to fetch
226  * result, more results expected from this
227  * query */
228  PGASYNC_COPY_IN, /* Copy In data transfer in progress */
229  PGASYNC_COPY_OUT, /* Copy Out data transfer in progress */
230  PGASYNC_COPY_BOTH, /* Copy In/Out data transfer in progress */
231  PGASYNC_PIPELINE_IDLE, /* "Idle" between commands in pipeline mode */
PGAsyncStatusType
Definition: libpq-int.h:220
@ PGASYNC_COPY_OUT
Definition: libpq-int.h:229
@ PGASYNC_READY_MORE
Definition: libpq-int.h:225
@ PGASYNC_READY
Definition: libpq-int.h:223
@ PGASYNC_COPY_BOTH
Definition: libpq-int.h:230
@ PGASYNC_IDLE
Definition: libpq-int.h:221
@ PGASYNC_COPY_IN
Definition: libpq-int.h:228
@ PGASYNC_BUSY
Definition: libpq-int.h:222
@ PGASYNC_PIPELINE_IDLE
Definition: libpq-int.h:231

◆ PGLoadBalanceType

Enumerator
LOAD_BALANCE_DISABLE 
LOAD_BALANCE_RANDOM 

Definition at line 253 of file libpq-int.h.

254 {
255  LOAD_BALANCE_DISABLE = 0, /* Use the existing host order (default) */
256  LOAD_BALANCE_RANDOM, /* Randomly shuffle the hosts */
PGLoadBalanceType
Definition: libpq-int.h:254
@ LOAD_BALANCE_DISABLE
Definition: libpq-int.h:255
@ LOAD_BALANCE_RANDOM
Definition: libpq-int.h:256

◆ PGQueryClass

Enumerator
PGQUERY_SIMPLE 
PGQUERY_EXTENDED 
PGQUERY_PREPARE 
PGQUERY_DESCRIBE 
PGQUERY_SYNC 
PGQUERY_CLOSE 

Definition at line 324 of file libpq-int.h.

325 {
326  PGQUERY_SIMPLE, /* simple Query protocol (PQexec) */
327  PGQUERY_EXTENDED, /* full Extended protocol (PQexecParams) */
328  PGQUERY_PREPARE, /* Parse only (PQprepare) */
329  PGQUERY_DESCRIBE, /* Describe Statement or Portal */
330  PGQUERY_SYNC, /* Sync (at end of a pipeline) */
331  PGQUERY_CLOSE /* Close Statement or Portal */
332 } PGQueryClass;
PGQueryClass
Definition: libpq-int.h:325
@ PGQUERY_SIMPLE
Definition: libpq-int.h:326
@ PGQUERY_SYNC
Definition: libpq-int.h:330
@ PGQUERY_EXTENDED
Definition: libpq-int.h:327
@ PGQUERY_DESCRIBE
Definition: libpq-int.h:329
@ PGQUERY_CLOSE
Definition: libpq-int.h:331
@ PGQUERY_PREPARE
Definition: libpq-int.h:328

◆ PGTargetServerType

Enumerator
SERVER_TYPE_ANY 
SERVER_TYPE_READ_WRITE 
SERVER_TYPE_READ_ONLY 
SERVER_TYPE_PRIMARY 
SERVER_TYPE_STANDBY 
SERVER_TYPE_PREFER_STANDBY 
SERVER_TYPE_PREFER_STANDBY_PASS2 

Definition at line 241 of file libpq-int.h.

242 {
243  SERVER_TYPE_ANY = 0, /* Any server (default) */
244  SERVER_TYPE_READ_WRITE, /* Read-write server */
245  SERVER_TYPE_READ_ONLY, /* Read-only server */
246  SERVER_TYPE_PRIMARY, /* Primary server */
247  SERVER_TYPE_STANDBY, /* Standby server */
248  SERVER_TYPE_PREFER_STANDBY, /* Prefer standby server */
249  SERVER_TYPE_PREFER_STANDBY_PASS2 /* second pass - behaves same as ANY */
PGTargetServerType
Definition: libpq-int.h:242
@ SERVER_TYPE_STANDBY
Definition: libpq-int.h:247
@ SERVER_TYPE_PRIMARY
Definition: libpq-int.h:246
@ SERVER_TYPE_ANY
Definition: libpq-int.h:243
@ SERVER_TYPE_READ_WRITE
Definition: libpq-int.h:244
@ SERVER_TYPE_PREFER_STANDBY_PASS2
Definition: libpq-int.h:249
@ SERVER_TYPE_PREFER_STANDBY
Definition: libpq-int.h:248
@ SERVER_TYPE_READ_ONLY
Definition: libpq-int.h:245

◆ PGTernaryBool

Enumerator
PG_BOOL_UNKNOWN 
PG_BOOL_YES 
PG_BOOL_NO 

Definition at line 260 of file libpq-int.h.

261 {
262  PG_BOOL_UNKNOWN = 0, /* Currently unknown */
263  PG_BOOL_YES, /* Yes (true) */
264  PG_BOOL_NO /* No (false) */
265 } PGTernaryBool;
PGTernaryBool
Definition: libpq-int.h:261
@ PG_BOOL_YES
Definition: libpq-int.h:263
@ PG_BOOL_NO
Definition: libpq-int.h:264
@ PG_BOOL_UNKNOWN
Definition: libpq-int.h:262

Function Documentation

◆ libpq_append_conn_error()

void void libpq_append_conn_error ( PGconn conn,
const char *  fmt,
  ... 
)

◆ libpq_append_error()

void libpq_append_error ( PQExpBuffer  errorMessage,
const char *  fmt,
  ... 
)

◆ pgtls_close()

void pgtls_close ( PGconn conn)

Definition at line 1440 of file fe-secure-openssl.c.

1441 {
1442  if (conn->ssl_in_use)
1443  {
1444  if (conn->ssl)
1445  {
1446  /*
1447  * We can't destroy everything SSL-related here due to the
1448  * possible later calls to OpenSSL routines which may need our
1449  * thread callbacks, so set a flag here and check at the end.
1450  */
1451 
1452  SSL_shutdown(conn->ssl);
1453  SSL_free(conn->ssl);
1454  conn->ssl = NULL;
1455  conn->ssl_in_use = false;
1456  conn->ssl_handshake_started = false;
1457  }
1458 
1459  if (conn->peer)
1460  {
1461  X509_free(conn->peer);
1462  conn->peer = NULL;
1463  }
1464 
1465 #ifdef USE_SSL_ENGINE
1466  if (conn->engine)
1467  {
1468  ENGINE_finish(conn->engine);
1469  ENGINE_free(conn->engine);
1470  conn->engine = NULL;
1471  }
1472 #endif
1473  }
1474 }
bool ssl_handshake_started
Definition: libpq-int.h:581
bool ssl_in_use
Definition: libpq-int.h:580

References conn, pg_conn::ssl_handshake_started, and pg_conn::ssl_in_use.

Referenced by open_client_SSL(), pgtls_open_client(), and pqsecure_close().

◆ pgtls_get_peer_certificate_hash()

char* pgtls_get_peer_certificate_hash ( PGconn conn,
size_t *  len 
)

Definition at line 339 of file fe-secure-openssl.c.

340 {
341  X509 *peer_cert;
342  const EVP_MD *algo_type;
343  unsigned char hash[EVP_MAX_MD_SIZE]; /* size for SHA-512 */
344  unsigned int hash_size;
345  int algo_nid;
346  char *cert_hash;
347 
348  *len = 0;
349 
350  if (!conn->peer)
351  return NULL;
352 
353  peer_cert = conn->peer;
354 
355  /*
356  * Get the signature algorithm of the certificate to determine the hash
357  * algorithm to use for the result. Prefer X509_get_signature_info(),
358  * introduced in OpenSSL 1.1.1, which can handle RSA-PSS signatures.
359  */
360 #if HAVE_X509_GET_SIGNATURE_INFO
361  if (!X509_get_signature_info(peer_cert, &algo_nid, NULL, NULL, NULL))
362 #else
363  if (!OBJ_find_sigid_algs(X509_get_signature_nid(peer_cert),
364  &algo_nid, NULL))
365 #endif
366  {
367  libpq_append_conn_error(conn, "could not determine server certificate signature algorithm");
368  return NULL;
369  }
370 
371  /*
372  * The TLS server's certificate bytes need to be hashed with SHA-256 if
373  * its signature algorithm is MD5 or SHA-1 as per RFC 5929
374  * (https://tools.ietf.org/html/rfc5929#section-4.1). If something else
375  * is used, the same hash as the signature algorithm is used.
376  */
377  switch (algo_nid)
378  {
379  case NID_md5:
380  case NID_sha1:
381  algo_type = EVP_sha256();
382  break;
383  default:
384  algo_type = EVP_get_digestbynid(algo_nid);
385  if (algo_type == NULL)
386  {
387  libpq_append_conn_error(conn, "could not find digest for NID %s",
388  OBJ_nid2sn(algo_nid));
389  return NULL;
390  }
391  break;
392  }
393 
394  if (!X509_digest(peer_cert, algo_type, hash, &hash_size))
395  {
396  libpq_append_conn_error(conn, "could not generate peer certificate hash");
397  return NULL;
398  }
399 
400  /* save result */
401  cert_hash = malloc(hash_size);
402  if (cert_hash == NULL)
403  {
404  libpq_append_conn_error(conn, "out of memory");
405  return NULL;
406  }
407  memcpy(cert_hash, hash, hash_size);
408  *len = hash_size;
409 
410  return cert_hash;
411 }
void libpq_append_conn_error(PGconn *conn, const char *fmt,...)
Definition: fe-misc.c:1372
#define malloc(a)
Definition: header.h:50
const void size_t len
static unsigned hash(unsigned *uv, int n)
Definition: rege_dfa.c:715

References conn, hash(), len, libpq_append_conn_error(), and malloc.

Referenced by build_client_final_message().

◆ pgtls_open_client()

PostgresPollingStatusType pgtls_open_client ( PGconn conn)

Definition at line 95 of file fe-secure-openssl.c.

96 {
97  /* First time through? */
98  if (conn->ssl == NULL)
99  {
100  /*
101  * Create a connection-specific SSL object, and load client
102  * certificate, private key, and trusted CA certs.
103  */
104  if (initialize_SSL(conn) != 0)
105  {
106  /* initialize_SSL already put a message in conn->errorMessage */
107  pgtls_close(conn);
108  return PGRES_POLLING_FAILED;
109  }
110  }
111 
112  /* Begin or continue the actual handshake */
113  return open_client_SSL(conn);
114 }
static int initialize_SSL(PGconn *conn)
static PostgresPollingStatusType open_client_SSL(PGconn *conn)
void pgtls_close(PGconn *conn)
@ PGRES_POLLING_FAILED
Definition: libpq-fe.h:110

References conn, initialize_SSL(), open_client_SSL(), PGRES_POLLING_FAILED, and pgtls_close().

Referenced by pqsecure_open_client().

◆ pgtls_read()

ssize_t pgtls_read ( PGconn conn,
void *  ptr,
size_t  len 
)

Definition at line 117 of file fe-secure-openssl.c.

118 {
119  ssize_t n;
120  int result_errno = 0;
121  char sebuf[PG_STRERROR_R_BUFLEN];
122  int err;
123  unsigned long ecode;
124 
125 rloop:
126 
127  /*
128  * Prepare to call SSL_get_error() by clearing thread's OpenSSL error
129  * queue. In general, the current thread's error queue must be empty
130  * before the TLS/SSL I/O operation is attempted, or SSL_get_error() will
131  * not work reliably. Since the possibility exists that other OpenSSL
132  * clients running in the same thread but not under our control will fail
133  * to call ERR_get_error() themselves (after their own I/O operations),
134  * pro-actively clear the per-thread error queue now.
135  */
136  SOCK_ERRNO_SET(0);
137  ERR_clear_error();
138  n = SSL_read(conn->ssl, ptr, len);
139  err = SSL_get_error(conn->ssl, n);
140 
141  /*
142  * Other clients of OpenSSL may fail to call ERR_get_error(), but we
143  * always do, so as to not cause problems for OpenSSL clients that don't
144  * call ERR_clear_error() defensively. Be sure that this happens by
145  * calling now. SSL_get_error() relies on the OpenSSL per-thread error
146  * queue being intact, so this is the earliest possible point
147  * ERR_get_error() may be called.
148  */
149  ecode = (err != SSL_ERROR_NONE || n < 0) ? ERR_get_error() : 0;
150  switch (err)
151  {
152  case SSL_ERROR_NONE:
153  if (n < 0)
154  {
155  /* Not supposed to happen, so we don't translate the msg */
157  "SSL_read failed but did not provide error information\n");
158  /* assume the connection is broken */
159  result_errno = ECONNRESET;
160  }
161  break;
162  case SSL_ERROR_WANT_READ:
163  n = 0;
164  break;
165  case SSL_ERROR_WANT_WRITE:
166 
167  /*
168  * Returning 0 here would cause caller to wait for read-ready,
169  * which is not correct since what SSL wants is wait for
170  * write-ready. The former could get us stuck in an infinite
171  * wait, so don't risk it; busy-loop instead.
172  */
173  goto rloop;
174  case SSL_ERROR_SYSCALL:
175  if (n < 0 && SOCK_ERRNO != 0)
176  {
177  result_errno = SOCK_ERRNO;
178  if (result_errno == EPIPE ||
179  result_errno == ECONNRESET)
180  libpq_append_conn_error(conn, "server closed the connection unexpectedly\n"
181  "\tThis probably means the server terminated abnormally\n"
182  "\tbefore or while processing the request.");
183  else
184  libpq_append_conn_error(conn, "SSL SYSCALL error: %s",
185  SOCK_STRERROR(result_errno,
186  sebuf, sizeof(sebuf)));
187  }
188  else
189  {
190  libpq_append_conn_error(conn, "SSL SYSCALL error: EOF detected");
191  /* assume the connection is broken */
192  result_errno = ECONNRESET;
193  n = -1;
194  }
195  break;
196  case SSL_ERROR_SSL:
197  {
198  char *errm = SSLerrmessage(ecode);
199 
200  libpq_append_conn_error(conn, "SSL error: %s", errm);
201  SSLerrfree(errm);
202  /* assume the connection is broken */
203  result_errno = ECONNRESET;
204  n = -1;
205  break;
206  }
207  case SSL_ERROR_ZERO_RETURN:
208 
209  /*
210  * Per OpenSSL documentation, this error code is only returned for
211  * a clean connection closure, so we should not report it as a
212  * server crash.
213  */
214  libpq_append_conn_error(conn, "SSL connection has been closed unexpectedly");
215  result_errno = ECONNRESET;
216  n = -1;
217  break;
218  default:
219  libpq_append_conn_error(conn, "unrecognized SSL error code: %d", err);
220  /* assume the connection is broken */
221  result_errno = ECONNRESET;
222  n = -1;
223  break;
224  }
225 
226  /* ensure we return the intended errno to caller */
227  SOCK_ERRNO_SET(result_errno);
228 
229  return n;
230 }
void err(int eval, const char *fmt,...)
Definition: err.c:43
static void SSLerrfree(char *buf)
static char * SSLerrmessage(unsigned long ecode)
#define SOCK_STRERROR
Definition: libpq-int.h:928
#define SOCK_ERRNO
Definition: libpq-int.h:927
#define SOCK_ERRNO_SET(e)
Definition: libpq-int.h:929
#define PG_STRERROR_R_BUFLEN
Definition: port.h:256
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:367
PQExpBufferData errorMessage
Definition: libpq-int.h:643
#define ECONNRESET
Definition: win32_port.h:384

References appendPQExpBufferStr(), conn, ECONNRESET, err(), pg_conn::errorMessage, len, libpq_append_conn_error(), PG_STRERROR_R_BUFLEN, SOCK_ERRNO, SOCK_ERRNO_SET, SOCK_STRERROR, SSLerrfree(), and SSLerrmessage().

Referenced by pqsecure_read().

◆ pgtls_read_pending()

bool pgtls_read_pending ( PGconn conn)

Definition at line 233 of file fe-secure-openssl.c.

234 {
235  return SSL_pending(conn->ssl) > 0;
236 }

References conn.

Referenced by pqSocketCheck().

◆ pgtls_verify_peer_name_matches_certificate_guts()

int pgtls_verify_peer_name_matches_certificate_guts ( PGconn conn,
int *  names_examined,
char **  first_name 
)

Definition at line 543 of file fe-secure-openssl.c.

546 {
547  STACK_OF(GENERAL_NAME) * peer_san;
548  int i;
549  int rc = 0;
550  char *host = conn->connhost[conn->whichhost].host;
551  int host_type;
552  bool check_cn = true;
553 
554  Assert(host && host[0]); /* should be guaranteed by caller */
555 
556  /*
557  * We try to match the NSS behavior here, which is a slight departure from
558  * the spec but seems to make more intuitive sense:
559  *
560  * If connhost contains a DNS name, and the certificate's SANs contain any
561  * dNSName entries, then we'll ignore the Subject Common Name entirely;
562  * otherwise, we fall back to checking the CN. (This behavior matches the
563  * RFC.)
564  *
565  * If connhost contains an IP address, and the SANs contain iPAddress
566  * entries, we again ignore the CN. Otherwise, we allow the CN to match,
567  * EVEN IF there is a dNSName in the SANs. (RFC 6125 prohibits this: "A
568  * client MUST NOT seek a match for a reference identifier of CN-ID if the
569  * presented identifiers include a DNS-ID, SRV-ID, URI-ID, or any
570  * application-specific identifier types supported by the client.")
571  *
572  * NOTE: Prior versions of libpq did not consider iPAddress entries at
573  * all, so this new behavior might break a certificate that has different
574  * IP addresses in the Subject CN and the SANs.
575  */
576  if (is_ip_address(host))
577  host_type = GEN_IPADD;
578  else
579  host_type = GEN_DNS;
580 
581  /*
582  * First, get the Subject Alternative Names (SANs) from the certificate,
583  * and compare them against the originally given hostname.
584  */
585  peer_san = (STACK_OF(GENERAL_NAME) *)
586  X509_get_ext_d2i(conn->peer, NID_subject_alt_name, NULL, NULL);
587 
588  if (peer_san)
589  {
590  int san_len = sk_GENERAL_NAME_num(peer_san);
591 
592  for (i = 0; i < san_len; i++)
593  {
594  const GENERAL_NAME *name = sk_GENERAL_NAME_value(peer_san, i);
595  char *alt_name = NULL;
596 
597  if (name->type == host_type)
598  {
599  /*
600  * This SAN is of the same type (IP or DNS) as our host name,
601  * so don't allow a fallback check of the CN.
602  */
603  check_cn = false;
604  }
605 
606  if (name->type == GEN_DNS)
607  {
608  (*names_examined)++;
610  name->d.dNSName,
611  &alt_name);
612  }
613  else if (name->type == GEN_IPADD)
614  {
615  (*names_examined)++;
617  name->d.iPAddress,
618  &alt_name);
619  }
620 
621  if (alt_name)
622  {
623  if (!*first_name)
624  *first_name = alt_name;
625  else
626  free(alt_name);
627  }
628 
629  if (rc != 0)
630  {
631  /*
632  * Either we hit an error or a match, and either way we should
633  * not fall back to the CN.
634  */
635  check_cn = false;
636  break;
637  }
638  }
639  sk_GENERAL_NAME_pop_free(peer_san, GENERAL_NAME_free);
640  }
641 
642  /*
643  * If there is no subjectAltName extension of the matching type, check the
644  * Common Name.
645  *
646  * (Per RFC 2818 and RFC 6125, if the subjectAltName extension of type
647  * dNSName is present, the CN must be ignored. We break this rule if host
648  * is an IP address; see the comment above.)
649  */
650  if (check_cn)
651  {
652  X509_NAME *subject_name;
653 
654  subject_name = X509_get_subject_name(conn->peer);
655  if (subject_name != NULL)
656  {
657  int cn_index;
658 
659  cn_index = X509_NAME_get_index_by_NID(subject_name,
660  NID_commonName, -1);
661  if (cn_index >= 0)
662  {
663  char *common_name = NULL;
664 
665  (*names_examined)++;
667  X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subject_name, cn_index)),
668  &common_name);
669 
670  if (common_name)
671  {
672  if (!*first_name)
673  *first_name = common_name;
674  else
675  free(common_name);
676  }
677  }
678  }
679  }
680 
681  return rc;
682 }
#define Assert(condition)
Definition: c.h:849
static int openssl_verify_peer_name_matches_certificate_name(PGconn *conn, ASN1_STRING *name_entry, char **store_name)
static int openssl_verify_peer_name_matches_certificate_ip(PGconn *conn, ASN1_OCTET_STRING *addr_entry, char **store_name)
static bool is_ip_address(const char *host)
#define free(a)
Definition: header.h:65
int i
Definition: isn.c:73
char * host
Definition: libpq-int.h:364
int whichhost
Definition: libpq-int.h:467
pg_conn_host * connhost
Definition: libpq-int.h:468
const char * name

References Assert, conn, pg_conn::connhost, free, pg_conn_host::host, i, is_ip_address(), name, openssl_verify_peer_name_matches_certificate_ip(), openssl_verify_peer_name_matches_certificate_name(), and pg_conn::whichhost.

Referenced by pq_verify_peer_name_matches_certificate().

◆ pgtls_write()

ssize_t pgtls_write ( PGconn conn,
const void *  ptr,
size_t  len 
)

Definition at line 239 of file fe-secure-openssl.c.

240 {
241  ssize_t n;
242  int result_errno = 0;
243  char sebuf[PG_STRERROR_R_BUFLEN];
244  int err;
245  unsigned long ecode;
246 
247  SOCK_ERRNO_SET(0);
248  ERR_clear_error();
249  n = SSL_write(conn->ssl, ptr, len);
250  err = SSL_get_error(conn->ssl, n);
251  ecode = (err != SSL_ERROR_NONE || n < 0) ? ERR_get_error() : 0;
252  switch (err)
253  {
254  case SSL_ERROR_NONE:
255  if (n < 0)
256  {
257  /* Not supposed to happen, so we don't translate the msg */
259  "SSL_write failed but did not provide error information\n");
260  /* assume the connection is broken */
261  result_errno = ECONNRESET;
262  }
263  break;
264  case SSL_ERROR_WANT_READ:
265 
266  /*
267  * Returning 0 here causes caller to wait for write-ready, which
268  * is not really the right thing, but it's the best we can do.
269  */
270  n = 0;
271  break;
272  case SSL_ERROR_WANT_WRITE:
273  n = 0;
274  break;
275  case SSL_ERROR_SYSCALL:
276 
277  /*
278  * If errno is still zero then assume it's a read EOF situation,
279  * and report EOF. (This seems possible because SSL_write can
280  * also do reads.)
281  */
282  if (n < 0 && SOCK_ERRNO != 0)
283  {
284  result_errno = SOCK_ERRNO;
285  if (result_errno == EPIPE || result_errno == ECONNRESET)
286  libpq_append_conn_error(conn, "server closed the connection unexpectedly\n"
287  "\tThis probably means the server terminated abnormally\n"
288  "\tbefore or while processing the request.");
289  else
290  libpq_append_conn_error(conn, "SSL SYSCALL error: %s",
291  SOCK_STRERROR(result_errno,
292  sebuf, sizeof(sebuf)));
293  }
294  else
295  {
296  libpq_append_conn_error(conn, "SSL SYSCALL error: EOF detected");
297  /* assume the connection is broken */
298  result_errno = ECONNRESET;
299  n = -1;
300  }
301  break;
302  case SSL_ERROR_SSL:
303  {
304  char *errm = SSLerrmessage(ecode);
305 
306  libpq_append_conn_error(conn, "SSL error: %s", errm);
307  SSLerrfree(errm);
308  /* assume the connection is broken */
309  result_errno = ECONNRESET;
310  n = -1;
311  break;
312  }
313  case SSL_ERROR_ZERO_RETURN:
314 
315  /*
316  * Per OpenSSL documentation, this error code is only returned for
317  * a clean connection closure, so we should not report it as a
318  * server crash.
319  */
320  libpq_append_conn_error(conn, "SSL connection has been closed unexpectedly");
321  result_errno = ECONNRESET;
322  n = -1;
323  break;
324  default:
325  libpq_append_conn_error(conn, "unrecognized SSL error code: %d", err);
326  /* assume the connection is broken */
327  result_errno = ECONNRESET;
328  n = -1;
329  break;
330  }
331 
332  /* ensure we return the intended errno to caller */
333  SOCK_ERRNO_SET(result_errno);
334 
335  return n;
336 }

References appendPQExpBufferStr(), conn, ECONNRESET, err(), pg_conn::errorMessage, len, libpq_append_conn_error(), PG_STRERROR_R_BUFLEN, SOCK_ERRNO, SOCK_ERRNO_SET, SOCK_STRERROR, SSLerrfree(), and SSLerrmessage().

Referenced by pqsecure_write().

◆ pq_block_sigpipe()

int pq_block_sigpipe ( sigset_t *  osigset,
bool sigpipe_pending 
)

Definition at line 504 of file fe-secure.c.

505 {
506  sigset_t sigpipe_sigset;
507  sigset_t sigset;
508 
509  sigemptyset(&sigpipe_sigset);
510  sigaddset(&sigpipe_sigset, SIGPIPE);
511 
512  /* Block SIGPIPE and save previous mask for later reset */
513  SOCK_ERRNO_SET(pthread_sigmask(SIG_BLOCK, &sigpipe_sigset, osigset));
514  if (SOCK_ERRNO)
515  return -1;
516 
517  /* We can have a pending SIGPIPE only if it was blocked before */
518  if (sigismember(osigset, SIGPIPE))
519  {
520  /* Is there a pending SIGPIPE? */
521  if (sigpending(&sigset) != 0)
522  return -1;
523 
524  if (sigismember(&sigset, SIGPIPE))
525  *sigpipe_pending = true;
526  else
527  *sigpipe_pending = false;
528  }
529  else
530  *sigpipe_pending = false;
531 
532  return 0;
533 }
#define SIGPIPE
Definition: win32_port.h:173

References SIGPIPE, SOCK_ERRNO, and SOCK_ERRNO_SET.

Referenced by PQprint().

◆ pq_reset_sigpipe()

void pq_reset_sigpipe ( sigset_t *  osigset,
bool  sigpipe_pending,
bool  got_epipe 
)

Definition at line 554 of file fe-secure.c.

555 {
556  int save_errno = SOCK_ERRNO;
557  int signo;
558  sigset_t sigset;
559 
560  /* Clear SIGPIPE only if none was pending */
561  if (got_epipe && !sigpipe_pending)
562  {
563  if (sigpending(&sigset) == 0 &&
564  sigismember(&sigset, SIGPIPE))
565  {
566  sigset_t sigpipe_sigset;
567 
568  sigemptyset(&sigpipe_sigset);
569  sigaddset(&sigpipe_sigset, SIGPIPE);
570 
571  sigwait(&sigpipe_sigset, &signo);
572  }
573  }
574 
575  /* Restore saved block mask */
576  pthread_sigmask(SIG_SETMASK, osigset, NULL);
577 
578  SOCK_ERRNO_SET(save_errno);
579 }

References SIGPIPE, SOCK_ERRNO, and SOCK_ERRNO_SET.

Referenced by PQprint().

◆ pqBuildErrorMessage3()

void pqBuildErrorMessage3 ( PQExpBuffer  msg,
const PGresult res,
PGVerbosity  verbosity,
PGContextVisibility  show_context 
)

Definition at line 1010 of file fe-protocol3.c.

1012 {
1013  const char *val;
1014  const char *querytext = NULL;
1015  int querypos = 0;
1016 
1017  /* If we couldn't allocate a PGresult, just say "out of memory" */
1018  if (res == NULL)
1019  {
1020  appendPQExpBufferStr(msg, libpq_gettext("out of memory\n"));
1021  return;
1022  }
1023 
1024  /*
1025  * If we don't have any broken-down fields, just return the base message.
1026  * This mainly applies if we're given a libpq-generated error result.
1027  */
1028  if (res->errFields == NULL)
1029  {
1030  if (res->errMsg && res->errMsg[0])
1032  else
1033  appendPQExpBufferStr(msg, libpq_gettext("no error message available\n"));
1034  return;
1035  }
1036 
1037  /* Else build error message from relevant fields */
1039  if (val)
1040  appendPQExpBuffer(msg, "%s: ", val);
1041 
1042  if (verbosity == PQERRORS_SQLSTATE)
1043  {
1044  /*
1045  * If we have a SQLSTATE, print that and nothing else. If not (which
1046  * shouldn't happen for server-generated errors, but might possibly
1047  * happen for libpq-generated ones), fall back to TERSE format, as
1048  * that seems better than printing nothing at all.
1049  */
1051  if (val)
1052  {
1053  appendPQExpBuffer(msg, "%s\n", val);
1054  return;
1055  }
1056  verbosity = PQERRORS_TERSE;
1057  }
1058 
1059  if (verbosity == PQERRORS_VERBOSE)
1060  {
1062  if (val)
1063  appendPQExpBuffer(msg, "%s: ", val);
1064  }
1066  if (val)
1067  appendPQExpBufferStr(msg, val);
1069  if (val)
1070  {
1071  if (verbosity != PQERRORS_TERSE && res->errQuery != NULL)
1072  {
1073  /* emit position as a syntax cursor display */
1074  querytext = res->errQuery;
1075  querypos = atoi(val);
1076  }
1077  else
1078  {
1079  /* emit position as text addition to primary message */
1080  /* translator: %s represents a digit string */
1081  appendPQExpBuffer(msg, libpq_gettext(" at character %s"),
1082  val);
1083  }
1084  }
1085  else
1086  {
1088  if (val)
1089  {
1091  if (verbosity != PQERRORS_TERSE && querytext != NULL)
1092  {
1093  /* emit position as a syntax cursor display */
1094  querypos = atoi(val);
1095  }
1096  else
1097  {
1098  /* emit position as text addition to primary message */
1099  /* translator: %s represents a digit string */
1100  appendPQExpBuffer(msg, libpq_gettext(" at character %s"),
1101  val);
1102  }
1103  }
1104  }
1105  appendPQExpBufferChar(msg, '\n');
1106  if (verbosity != PQERRORS_TERSE)
1107  {
1108  if (querytext && querypos > 0)
1109  reportErrorPosition(msg, querytext, querypos,
1110  res->client_encoding);
1112  if (val)
1113  appendPQExpBuffer(msg, libpq_gettext("DETAIL: %s\n"), val);
1115  if (val)
1116  appendPQExpBuffer(msg, libpq_gettext("HINT: %s\n"), val);
1118  if (val)
1119  appendPQExpBuffer(msg, libpq_gettext("QUERY: %s\n"), val);
1120  if (show_context == PQSHOW_CONTEXT_ALWAYS ||
1121  (show_context == PQSHOW_CONTEXT_ERRORS &&
1123  {
1125  if (val)
1126  appendPQExpBuffer(msg, libpq_gettext("CONTEXT: %s\n"),
1127  val);
1128  }
1129  }
1130  if (verbosity == PQERRORS_VERBOSE)
1131  {
1133  if (val)
1134  appendPQExpBuffer(msg,
1135  libpq_gettext("SCHEMA NAME: %s\n"), val);
1137  if (val)
1138  appendPQExpBuffer(msg,
1139  libpq_gettext("TABLE NAME: %s\n"), val);
1141  if (val)
1142  appendPQExpBuffer(msg,
1143  libpq_gettext("COLUMN NAME: %s\n"), val);
1145  if (val)
1146  appendPQExpBuffer(msg,
1147  libpq_gettext("DATATYPE NAME: %s\n"), val);
1149  if (val)
1150  appendPQExpBuffer(msg,
1151  libpq_gettext("CONSTRAINT NAME: %s\n"), val);
1152  }
1153  if (verbosity == PQERRORS_VERBOSE)
1154  {
1155  const char *valf;
1156  const char *vall;
1157 
1161  if (val || valf || vall)
1162  {
1163  appendPQExpBufferStr(msg, libpq_gettext("LOCATION: "));
1164  if (val)
1165  appendPQExpBuffer(msg, libpq_gettext("%s, "), val);
1166  if (valf && vall) /* unlikely we'd have just one */
1167  appendPQExpBuffer(msg, libpq_gettext("%s:%s"),
1168  valf, vall);
1169  appendPQExpBufferChar(msg, '\n');
1170  }
1171  }
1172 }
char * PQresultErrorField(const PGresult *res, int fieldcode)
Definition: fe-exec.c:3466
static void reportErrorPosition(PQExpBuffer msg, const char *query, int loc, int encoding)
long val
Definition: informix.c:689
@ PGRES_FATAL_ERROR
Definition: libpq-fe.h:131
@ PQSHOW_CONTEXT_ALWAYS
Definition: libpq-fe.h:161
@ PQSHOW_CONTEXT_ERRORS
Definition: libpq-fe.h:160
@ PQERRORS_VERBOSE
Definition: libpq-fe.h:153
@ PQERRORS_TERSE
Definition: libpq-fe.h:151
@ PQERRORS_SQLSTATE
Definition: libpq-fe.h:154
#define libpq_gettext(x)
Definition: libpq-int.h:906
#define PG_DIAG_INTERNAL_QUERY
Definition: postgres_ext.h:62
#define PG_DIAG_SCHEMA_NAME
Definition: postgres_ext.h:64
#define PG_DIAG_CONSTRAINT_NAME
Definition: postgres_ext.h:68
#define PG_DIAG_DATATYPE_NAME
Definition: postgres_ext.h:67
#define PG_DIAG_SOURCE_LINE
Definition: postgres_ext.h:70
#define PG_DIAG_STATEMENT_POSITION
Definition: postgres_ext.h:60
#define PG_DIAG_SOURCE_FILE
Definition: postgres_ext.h:69
#define PG_DIAG_MESSAGE_HINT
Definition: postgres_ext.h:59
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:56
#define PG_DIAG_TABLE_NAME
Definition: postgres_ext.h:65
#define PG_DIAG_MESSAGE_PRIMARY
Definition: postgres_ext.h:57
#define PG_DIAG_COLUMN_NAME
Definition: postgres_ext.h:66
#define PG_DIAG_MESSAGE_DETAIL
Definition: postgres_ext.h:58
#define PG_DIAG_CONTEXT
Definition: postgres_ext.h:63
#define PG_DIAG_SEVERITY
Definition: postgres_ext.h:54
#define PG_DIAG_SOURCE_FUNCTION
Definition: postgres_ext.h:71
#define PG_DIAG_INTERNAL_POSITION
Definition: postgres_ext.h:61
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:265
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:378
char * errMsg
Definition: libpq-int.h:199
PGMessageField * errFields
Definition: libpq-int.h:200
ExecStatusType resultStatus
Definition: libpq-int.h:180
char * errQuery
Definition: libpq-int.h:201
int client_encoding
Definition: libpq-int.h:192

References appendPQExpBuffer(), appendPQExpBufferChar(), appendPQExpBufferStr(), pg_result::client_encoding, pg_result::errFields, pg_result::errMsg, pg_result::errQuery, libpq_gettext, PG_DIAG_COLUMN_NAME, PG_DIAG_CONSTRAINT_NAME, PG_DIAG_CONTEXT, PG_DIAG_DATATYPE_NAME, PG_DIAG_INTERNAL_POSITION, PG_DIAG_INTERNAL_QUERY, PG_DIAG_MESSAGE_DETAIL, PG_DIAG_MESSAGE_HINT, PG_DIAG_MESSAGE_PRIMARY, PG_DIAG_SCHEMA_NAME, PG_DIAG_SEVERITY, PG_DIAG_SOURCE_FILE, PG_DIAG_SOURCE_FUNCTION, PG_DIAG_SOURCE_LINE, PG_DIAG_SQLSTATE, PG_DIAG_STATEMENT_POSITION, PG_DIAG_TABLE_NAME, PGRES_FATAL_ERROR, PQERRORS_SQLSTATE, PQERRORS_TERSE, PQERRORS_VERBOSE, PQresultErrorField(), PQSHOW_CONTEXT_ALWAYS, PQSHOW_CONTEXT_ERRORS, reportErrorPosition(), res, pg_result::resultStatus, and val.

Referenced by pqGetErrorNotice3(), and PQresultVerboseErrorMessage().

◆ pqBuildStartupPacket3()

char* pqBuildStartupPacket3 ( PGconn conn,
int *  packetlen,
const PQEnvironmentOption options 
)

Definition at line 2231 of file fe-protocol3.c.

2233 {
2234  char *startpacket;
2235 
2236  *packetlen = build_startup_packet(conn, NULL, options);
2237  startpacket = (char *) malloc(*packetlen);
2238  if (!startpacket)
2239  return NULL;
2240  *packetlen = build_startup_packet(conn, startpacket, options);
2241  return startpacket;
2242 }
static int build_startup_packet(const PGconn *conn, char *packet, const PQEnvironmentOption *options)

References build_startup_packet(), conn, and malloc.

Referenced by PQconnectPoll().

◆ pqCheckInBufferSpace()

int pqCheckInBufferSpace ( size_t  bytes_needed,
PGconn conn 
)

Definition at line 351 of file fe-misc.c.

352 {
353  int newsize = conn->inBufSize;
354  char *newbuf;
355 
356  /* Quick exit if we have enough space */
357  if (bytes_needed <= (size_t) newsize)
358  return 0;
359 
360  /*
361  * Before concluding that we need to enlarge the buffer, left-justify
362  * whatever is in it and recheck. The caller's value of bytes_needed
363  * includes any data to the left of inStart, but we can delete that in
364  * preference to enlarging the buffer. It's slightly ugly to have this
365  * function do this, but it's better than making callers worry about it.
366  */
367  bytes_needed -= conn->inStart;
368 
369  if (conn->inStart < conn->inEnd)
370  {
371  if (conn->inStart > 0)
372  {
373  memmove(conn->inBuffer, conn->inBuffer + conn->inStart,
374  conn->inEnd - conn->inStart);
375  conn->inEnd -= conn->inStart;
376  conn->inCursor -= conn->inStart;
377  conn->inStart = 0;
378  }
379  }
380  else
381  {
382  /* buffer is logically empty, reset it */
383  conn->inStart = conn->inCursor = conn->inEnd = 0;
384  }
385 
386  /* Recheck whether we have enough space */
387  if (bytes_needed <= (size_t) newsize)
388  return 0;
389 
390  /*
391  * If we need to enlarge the buffer, we first try to double it in size; if
392  * that doesn't work, enlarge in multiples of 8K. This avoids thrashing
393  * the malloc pool by repeated small enlargements.
394  *
395  * Note: tests for newsize > 0 are to catch integer overflow.
396  */
397  do
398  {
399  newsize *= 2;
400  } while (newsize > 0 && bytes_needed > (size_t) newsize);
401 
402  if (newsize > 0 && bytes_needed <= (size_t) newsize)
403  {
404  newbuf = realloc(conn->inBuffer, newsize);
405  if (newbuf)
406  {
407  /* realloc succeeded */
408  conn->inBuffer = newbuf;
409  conn->inBufSize = newsize;
410  return 0;
411  }
412  }
413 
414  newsize = conn->inBufSize;
415  do
416  {
417  newsize += 8192;
418  } while (newsize > 0 && bytes_needed > (size_t) newsize);
419 
420  if (newsize > 0 && bytes_needed <= (size_t) newsize)
421  {
422  newbuf = realloc(conn->inBuffer, newsize);
423  if (newbuf)
424  {
425  /* realloc succeeded */
426  conn->inBuffer = newbuf;
427  conn->inBufSize = newsize;
428  return 0;
429  }
430  }
431 
432  /* realloc failed. Probably out of memory */
434  "cannot allocate memory for input buffer\n");
435  return EOF;
436 }
#define realloc(a, b)
Definition: header.h:60
char * inBuffer
Definition: libpq-int.h:536
int inCursor
Definition: libpq-int.h:539
int inEnd
Definition: libpq-int.h:540
int inBufSize
Definition: libpq-int.h:537
int inStart
Definition: libpq-int.h:538

References appendPQExpBufferStr(), conn, pg_conn::errorMessage, pg_conn::inBuffer, pg_conn::inBufSize, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, and realloc.

Referenced by getCopyDataMessage(), PQconnectPoll(), pqFunctionCall3(), pqParseInput3(), and pqReadData().

◆ pqCheckOutBufferSpace()

int pqCheckOutBufferSpace ( size_t  bytes_needed,
PGconn conn 
)

Definition at line 287 of file fe-misc.c.

288 {
289  int newsize = conn->outBufSize;
290  char *newbuf;
291 
292  /* Quick exit if we have enough space */
293  if (bytes_needed <= (size_t) newsize)
294  return 0;
295 
296  /*
297  * If we need to enlarge the buffer, we first try to double it in size; if
298  * that doesn't work, enlarge in multiples of 8K. This avoids thrashing
299  * the malloc pool by repeated small enlargements.
300  *
301  * Note: tests for newsize > 0 are to catch integer overflow.
302  */
303  do
304  {
305  newsize *= 2;
306  } while (newsize > 0 && bytes_needed > (size_t) newsize);
307 
308  if (newsize > 0 && bytes_needed <= (size_t) newsize)
309  {
310  newbuf = realloc(conn->outBuffer, newsize);
311  if (newbuf)
312  {
313  /* realloc succeeded */
314  conn->outBuffer = newbuf;
315  conn->outBufSize = newsize;
316  return 0;
317  }
318  }
319 
320  newsize = conn->outBufSize;
321  do
322  {
323  newsize += 8192;
324  } while (newsize > 0 && bytes_needed > (size_t) newsize);
325 
326  if (newsize > 0 && bytes_needed <= (size_t) newsize)
327  {
328  newbuf = realloc(conn->outBuffer, newsize);
329  if (newbuf)
330  {
331  /* realloc succeeded */
332  conn->outBuffer = newbuf;
333  conn->outBufSize = newsize;
334  return 0;
335  }
336  }
337 
338  /* realloc failed. Probably out of memory */
340  "cannot allocate memory for output buffer\n");
341  return EOF;
342 }
int outBufSize
Definition: libpq-int.h:544
char * outBuffer
Definition: libpq-int.h:543

References appendPQExpBufferStr(), conn, pg_conn::errorMessage, pg_conn::outBuffer, pg_conn::outBufSize, and realloc.

Referenced by PQputCopyData(), pqPutMsgBytes(), and pqPutMsgStart().

◆ pqClearAsyncResult()

void pqClearAsyncResult ( PGconn conn)

Definition at line 779 of file fe-exec.c.

780 {
781  PQclear(conn->result);
782  conn->result = NULL;
783  conn->error_result = false;
785  conn->saved_result = NULL;
786 }
void PQclear(PGresult *res)
Definition: fe-exec.c:721
PGresult * result
Definition: libpq-int.h:566
PGresult * saved_result
Definition: libpq-int.h:568
bool error_result
Definition: libpq-int.h:567

References conn, pg_conn::error_result, PQclear(), pg_conn::result, and pg_conn::saved_result.

Referenced by getAnotherTuple(), getParamDescriptions(), getRowDescriptions(), pqClosePGconn(), PQconnectPoll(), pqGetErrorNotice3(), pqPipelineProcessQueue(), pqSaveErrorResult(), and PQsendQueryStart().

◆ pqClosePGconn()

void pqClosePGconn ( PGconn conn)

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

4848 {
4849  /*
4850  * If possible, send Terminate message to close the connection politely.
4851  */
4853 
4854  /*
4855  * Must reset the blocking status so a possible reconnect will work.
4856  *
4857  * Don't call PQsetnonblocking() because it will fail if it's unable to
4858  * flush the connection.
4859  */
4860  conn->nonblocking = false;
4861 
4862  /*
4863  * Close the connection, reset all transient state, flush I/O buffers.
4864  * Note that this includes clearing conn's error state; we're no longer
4865  * interested in any failures associated with the old connection, and we
4866  * want a clean slate for any new connection attempt.
4867  */
4868  pqDropConnection(conn, true);
4869  conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just absent */
4873  pqClearAsyncResult(conn); /* deallocate result */
4875 
4876  /*
4877  * Release addrinfo, but since cancel requests never change their addrinfo
4878  * we don't do that. Otherwise we would have to rebuild it during a
4879  * PQcancelReset.
4880  */
4881  if (!conn->cancelRequest)
4883 
4884  /* Reset all state obtained from server, too */
4886 }
void pqDropConnection(PGconn *conn, bool flushInput)
Definition: fe-connect.c:472
static void sendTerminateConn(PGconn *conn)
Definition: fe-connect.c:4813
static void release_conn_addrinfo(PGconn *conn)
Definition: fe-connect.c:4799
static void pqDropServerData(PGconn *conn)
Definition: fe-connect.c:585
void pqClearAsyncResult(PGconn *conn)
Definition: fe-exec.c:779
@ CONNECTION_BAD
Definition: libpq-fe.h:82
@ PQTRANS_IDLE
Definition: libpq-fe.h:142
@ PQ_PIPELINE_OFF
Definition: libpq-fe.h:182
#define pqClearConnErrorState(conn)
Definition: libpq-int.h:879
PGTransactionStatusType xactStatus
Definition: libpq-int.h:450
bool cancelRequest
Definition: libpq-int.h:431
bool nonblocking
Definition: libpq-int.h:453
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:449
PGpipelineStatus pipelineStatus
Definition: libpq-int.h:455
ConnStatusType status
Definition: libpq-int.h:448

References pg_conn::asyncStatus, pg_conn::cancelRequest, conn, CONNECTION_BAD, pg_conn::nonblocking, PGASYNC_IDLE, pg_conn::pipelineStatus, PQ_PIPELINE_OFF, pqClearAsyncResult(), pqClearConnErrorState, pqDropConnection(), pqDropServerData(), PQTRANS_IDLE, release_conn_addrinfo(), sendTerminateConn(), pg_conn::status, and pg_conn::xactStatus.

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

◆ pqCommandQueueAdvance()

void pqCommandQueueAdvance ( PGconn conn,
bool  isReadyForQuery,
bool  gotSync 
)

Definition at line 3142 of file fe-exec.c.

3143 {
3144  PGcmdQueueEntry *prevquery;
3145 
3146  if (conn->cmd_queue_head == NULL)
3147  return;
3148 
3149  /*
3150  * If processing a query of simple query protocol, we only advance the
3151  * queue when we receive the ReadyForQuery message for it.
3152  */
3153  if (conn->cmd_queue_head->queryclass == PGQUERY_SIMPLE && !isReadyForQuery)
3154  return;
3155 
3156  /*
3157  * If we're waiting for a SYNC, don't advance the queue until we get one.
3158  */
3159  if (conn->cmd_queue_head->queryclass == PGQUERY_SYNC && !gotSync)
3160  return;
3161 
3162  /* delink element from queue */
3163  prevquery = conn->cmd_queue_head;
3165 
3166  /* If the queue is now empty, reset the tail too */
3167  if (conn->cmd_queue_head == NULL)
3168  conn->cmd_queue_tail = NULL;
3169 
3170  /* and make the queue element recyclable */
3171  prevquery->next = NULL;
3172  pqRecycleCmdQueueEntry(conn, prevquery);
3173 }
static void pqRecycleCmdQueueEntry(PGconn *conn, PGcmdQueueEntry *entry)
Definition: fe-exec.c:1386
PGQueryClass queryclass
Definition: libpq-int.h:351
struct PGcmdQueueEntry * next
Definition: libpq-int.h:353
PGcmdQueueEntry * cmd_queue_tail
Definition: libpq-int.h:476
PGcmdQueueEntry * cmd_queue_head
Definition: libpq-int.h:475

References pg_conn::cmd_queue_head, pg_conn::cmd_queue_tail, conn, PGcmdQueueEntry::next, PGQUERY_SIMPLE, PGQUERY_SYNC, pqRecycleCmdQueueEntry(), and PGcmdQueueEntry::queryclass.

Referenced by PQgetResult(), and pqParseInput3().

◆ pqConnectDBComplete()

int pqConnectDBComplete ( PGconn conn)

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

2472 {
2474  pg_usec_time_t end_time = -1;
2475  int timeout = 0;
2476  int last_whichhost = -2; /* certainly different from whichhost */
2477  int last_whichaddr = -2; /* certainly different from whichaddr */
2478 
2479  if (conn == NULL || conn->status == CONNECTION_BAD)
2480  return 0;
2481 
2482  /*
2483  * Set up a time limit, if connect_timeout is greater than zero.
2484  */
2485  if (conn->connect_timeout != NULL)
2486  {
2487  if (!pqParseIntParam(conn->connect_timeout, &timeout, conn,
2488  "connect_timeout"))
2489  {
2490  /* mark the connection as bad to report the parsing failure */
2492  return 0;
2493  }
2494  }
2495 
2496  for (;;)
2497  {
2498  int ret = 0;
2499 
2500  /*
2501  * (Re)start the connect_timeout timer if it's active and we are
2502  * considering a different host than we were last time through. If
2503  * we've already succeeded, though, needn't recalculate.
2504  */
2505  if (flag != PGRES_POLLING_OK &&
2506  timeout > 0 &&
2507  (conn->whichhost != last_whichhost ||
2508  conn->whichaddr != last_whichaddr))
2509  {
2510  end_time = PQgetCurrentTimeUSec() + (pg_usec_time_t) timeout * 1000000;
2511  last_whichhost = conn->whichhost;
2512  last_whichaddr = conn->whichaddr;
2513  }
2514 
2515  /*
2516  * Wait, if necessary. Note that the initial state (just after
2517  * PQconnectStart) is to wait for the socket to select for writing.
2518  */
2519  switch (flag)
2520  {
2521  case PGRES_POLLING_OK:
2522  return 1; /* success! */
2523 
2524  case PGRES_POLLING_READING:
2525  ret = pqWaitTimed(1, 0, conn, end_time);
2526  if (ret == -1)
2527  {
2528  /* hard failure, eg select() problem, aborts everything */
2530  return 0;
2531  }
2532  break;
2533 
2534  case PGRES_POLLING_WRITING:
2535  ret = pqWaitTimed(0, 1, conn, end_time);
2536  if (ret == -1)
2537  {
2538  /* hard failure, eg select() problem, aborts everything */
2540  return 0;
2541  }
2542  break;
2543 
2544  default:
2545  /* Just in case we failed to set it in PQconnectPoll */
2547  return 0;
2548  }
2549 
2550  if (ret == 1) /* connect_timeout elapsed */
2551  {
2552  /*
2553  * Give up on current server/address, try the next one.
2554  */
2555  conn->try_next_addr = true;
2557  }
2558 
2559  /*
2560  * Now try to advance the state machine.
2561  */
2562  if (conn->cancelRequest)
2564  else
2565  flag = PQconnectPoll(conn);
2566  }
2567 }
PostgresPollingStatusType PQcancelPoll(PGcancelConn *cancelConn)
Definition: fe-cancel.c:207
PostgresPollingStatusType PQconnectPoll(PGconn *conn)
Definition: fe-connect.c:2597
bool pqParseIntParam(const char *value, int *result, PGconn *conn, const char *context)
Definition: fe-connect.c:7768
pg_usec_time_t PQgetCurrentTimeUSec(void)
Definition: fe-misc.c:1200
int pqWaitTimed(int forRead, int forWrite, PGconn *conn, pg_usec_time_t end_time)
Definition: fe-misc.c:1009
@ CONNECTION_NEEDED
Definition: libpq-fe.h:97
PostgresPollingStatusType
Definition: libpq-fe.h:109
@ PGRES_POLLING_OK
Definition: libpq-fe.h:113
@ PGRES_POLLING_READING
Definition: libpq-fe.h:111
@ PGRES_POLLING_WRITING
Definition: libpq-fe.h:112
pg_int64 pg_usec_time_t
Definition: libpq-fe.h:226
static int64 end_time
Definition: pgbench.c:175
int whichaddr
Definition: libpq-int.h:516
char * connect_timeout
Definition: libpq-int.h:389
bool try_next_addr
Definition: libpq-int.h:513
char * flag(int b)
Definition: test-ctype.c:33

References pg_conn::cancelRequest, conn, pg_conn::connect_timeout, CONNECTION_BAD, CONNECTION_NEEDED, end_time, flag(), PGRES_POLLING_OK, PGRES_POLLING_READING, PGRES_POLLING_WRITING, PQcancelPoll(), PQconnectPoll(), PQgetCurrentTimeUSec(), pqParseIntParam(), pqWaitTimed(), pg_conn::status, pg_conn::try_next_addr, pg_conn::whichaddr, and pg_conn::whichhost.

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

◆ pqConnectDBStart()

int pqConnectDBStart ( PGconn conn)

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

2394 {
2395  if (!conn)
2396  return 0;
2397 
2398  if (!conn->options_valid)
2399  goto connect_errReturn;
2400 
2401  /*
2402  * Check for bad linking to backend-internal versions of src/common
2403  * functions (see comments in link-canary.c for the reason we need this).
2404  * Nobody but developers should see this message, so we don't bother
2405  * translating it.
2406  */
2408  {
2410  "libpq is incorrectly linked to backend functions\n");
2411  goto connect_errReturn;
2412  }
2413 
2414  /* Ensure our buffers are empty */
2415  conn->inStart = conn->inCursor = conn->inEnd = 0;
2416  conn->outCount = 0;
2417 
2418  /*
2419  * Set up to try to connect to the first host. (Setting whichhost = -1 is
2420  * a bit of a cheat, but PQconnectPoll will advance it to 0 before
2421  * anything else looks at it.)
2422  *
2423  * Cancel requests are special though, they should only try one host and
2424  * address, and these fields have already been set up in PQcancelCreate,
2425  * so leave these fields alone for cancel requests.
2426  */
2427  if (!conn->cancelRequest)
2428  {
2429  conn->whichhost = -1;
2430  conn->try_next_host = true;
2431  conn->try_next_addr = false;
2432  }
2433 
2435 
2436  /* Also reset the target_server_type state if needed */
2439 
2440  /*
2441  * The code for processing CONNECTION_NEEDED state is in PQconnectPoll(),
2442  * so that it can easily be re-executed if needed again during the
2443  * asynchronous startup process. However, we must run it once here,
2444  * because callers expect a success return from this routine to mean that
2445  * we are in PGRES_POLLING_WRITING connection state.
2446  */
2448  return 1;
2449 
2450 connect_errReturn:
2451 
2452  /*
2453  * If we managed to open a socket, close it immediately rather than
2454  * waiting till PQfinish. (The application cannot have gotten the socket
2455  * from PQsocket yet, so this doesn't risk breaking anything.)
2456  */
2457  pqDropConnection(conn, true);
2459  return 0;
2460 }
bool try_next_host
Definition: libpq-int.h:514
bool options_valid
Definition: libpq-int.h:452
PGTargetServerType target_server_type
Definition: libpq-int.h:510
int outCount
Definition: libpq-int.h:545

References appendPQExpBufferStr(), pg_conn::cancelRequest, conn, CONNECTION_BAD, CONNECTION_NEEDED, pg_conn::errorMessage, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, pg_conn::options_valid, pg_conn::outCount, pg_link_canary_is_frontend(), PGRES_POLLING_WRITING, PQconnectPoll(), pqDropConnection(), SERVER_TYPE_PREFER_STANDBY, SERVER_TYPE_PREFER_STANDBY_PASS2, pg_conn::status, pg_conn::target_server_type, pg_conn::try_next_addr, pg_conn::try_next_host, and pg_conn::whichhost.

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

◆ pqConnectOptions2()

bool pqConnectOptions2 ( PGconn conn)

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

1122 {
1123  int i;
1124 
1125  /*
1126  * Allocate memory for details about each host to which we might possibly
1127  * try to connect. For that, count the number of elements in the hostaddr
1128  * or host options. If neither is given, assume one host.
1129  */
1130  conn->whichhost = 0;
1131  if (conn->pghostaddr && conn->pghostaddr[0] != '\0')
1133  else if (conn->pghost && conn->pghost[0] != '\0')
1135  else
1136  conn->nconnhost = 1;
1137  conn->connhost = (pg_conn_host *)
1138  calloc(conn->nconnhost, sizeof(pg_conn_host));
1139  if (conn->connhost == NULL)
1140  goto oom_error;
1141 
1142  /*
1143  * We now have one pg_conn_host structure per possible host. Fill in the
1144  * host and hostaddr fields for each, by splitting the parameter strings.
1145  */
1146  if (conn->pghostaddr != NULL && conn->pghostaddr[0] != '\0')
1147  {
1148  char *s = conn->pghostaddr;
1149  bool more = true;
1150 
1151  for (i = 0; i < conn->nconnhost && more; i++)
1152  {
1154  if (conn->connhost[i].hostaddr == NULL)
1155  goto oom_error;
1156  }
1157 
1158  /*
1159  * If hostaddr was given, the array was allocated according to the
1160  * number of elements in the hostaddr list, so it really should be the
1161  * right size.
1162  */
1163  Assert(!more);
1164  Assert(i == conn->nconnhost);
1165  }
1166 
1167  if (conn->pghost != NULL && conn->pghost[0] != '\0')
1168  {
1169  char *s = conn->pghost;
1170  bool more = true;
1171 
1172  for (i = 0; i < conn->nconnhost && more; i++)
1173  {
1175  if (conn->connhost[i].host == NULL)
1176  goto oom_error;
1177  }
1178 
1179  /* Check for wrong number of host items. */
1180  if (more || i != conn->nconnhost)
1181  {
1183  libpq_append_conn_error(conn, "could not match %d host names to %d hostaddr values",
1185  return false;
1186  }
1187  }
1188 
1189  /*
1190  * Now, for each host slot, identify the type of address spec, and fill in
1191  * the default address if nothing was given.
1192  */
1193  for (i = 0; i < conn->nconnhost; i++)
1194  {
1195  pg_conn_host *ch = &conn->connhost[i];
1196 
1197  if (ch->hostaddr != NULL && ch->hostaddr[0] != '\0')
1198  ch->type = CHT_HOST_ADDRESS;
1199  else if (ch->host != NULL && ch->host[0] != '\0')
1200  {
1201  ch->type = CHT_HOST_NAME;
1202  if (is_unixsock_path(ch->host))
1203  ch->type = CHT_UNIX_SOCKET;
1204  }
1205  else
1206  {
1207  free(ch->host);
1208 
1209  /*
1210  * This bit selects the default host location. If you change
1211  * this, see also pg_regress.
1212  */
1213  if (DEFAULT_PGSOCKET_DIR[0])
1214  {
1215  ch->host = strdup(DEFAULT_PGSOCKET_DIR);
1216  ch->type = CHT_UNIX_SOCKET;
1217  }
1218  else
1219  {
1220  ch->host = strdup(DefaultHost);
1221  ch->type = CHT_HOST_NAME;
1222  }
1223  if (ch->host == NULL)
1224  goto oom_error;
1225  }
1226  }
1227 
1228  /*
1229  * Next, work out the port number corresponding to each host name.
1230  *
1231  * Note: unlike the above for host names, this could leave the port fields
1232  * as null or empty strings. We will substitute DEF_PGPORT whenever we
1233  * read such a port field.
1234  */
1235  if (conn->pgport != NULL && conn->pgport[0] != '\0')
1236  {
1237  char *s = conn->pgport;
1238  bool more = true;
1239 
1240  for (i = 0; i < conn->nconnhost && more; i++)
1241  {
1243  if (conn->connhost[i].port == NULL)
1244  goto oom_error;
1245  }
1246 
1247  /*
1248  * If exactly one port was given, use it for every host. Otherwise,
1249  * there must be exactly as many ports as there were hosts.
1250  */
1251  if (i == 1 && !more)
1252  {
1253  for (i = 1; i < conn->nconnhost; i++)
1254  {
1255  conn->connhost[i].port = strdup(conn->connhost[0].port);
1256  if (conn->connhost[i].port == NULL)
1257  goto oom_error;
1258  }
1259  }
1260  else if (more || i != conn->nconnhost)
1261  {
1263  libpq_append_conn_error(conn, "could not match %d port numbers to %d hosts",
1265  return false;
1266  }
1267  }
1268 
1269  /*
1270  * If user name was not given, fetch it. (Most likely, the fetch will
1271  * fail, since the only way we get here is if pg_fe_getauthname() failed
1272  * during conninfo_add_defaults(). But now we want an error message.)
1273  */
1274  if (conn->pguser == NULL || conn->pguser[0] == '\0')
1275  {
1276  free(conn->pguser);
1278  if (!conn->pguser)
1279  {
1281  return false;
1282  }
1283  }
1284 
1285  /*
1286  * If database name was not given, default it to equal user name
1287  */
1288  if (conn->dbName == NULL || conn->dbName[0] == '\0')
1289  {
1290  free(conn->dbName);
1291  conn->dbName = strdup(conn->pguser);
1292  if (!conn->dbName)
1293  goto oom_error;
1294  }
1295 
1296  /*
1297  * If password was not given, try to look it up in password file. Note
1298  * that the result might be different for each host/port pair.
1299  */
1300  if (conn->pgpass == NULL || conn->pgpass[0] == '\0')
1301  {
1302  /* If password file wasn't specified, use ~/PGPASSFILE */
1303  if (conn->pgpassfile == NULL || conn->pgpassfile[0] == '\0')
1304  {
1305  char homedir[MAXPGPATH];
1306 
1307  if (pqGetHomeDirectory(homedir, sizeof(homedir)))
1308  {
1309  free(conn->pgpassfile);
1311  if (!conn->pgpassfile)
1312  goto oom_error;
1313  snprintf(conn->pgpassfile, MAXPGPATH, "%s/%s",
1314  homedir, PGPASSFILE);
1315  }
1316  }
1317 
1318  if (conn->pgpassfile != NULL && conn->pgpassfile[0] != '\0')
1319  {
1320  for (i = 0; i < conn->nconnhost; i++)
1321  {
1322  /*
1323  * Try to get a password for this host from file. We use host
1324  * for the hostname search key if given, else hostaddr (at
1325  * least one of them is guaranteed nonempty by now).
1326  */
1327  const char *pwhost = conn->connhost[i].host;
1328 
1329  if (pwhost == NULL || pwhost[0] == '\0')
1330  pwhost = conn->connhost[i].hostaddr;
1331 
1332  conn->connhost[i].password =
1333  passwordFromFile(pwhost,
1334  conn->connhost[i].port,
1335  conn->dbName,
1336  conn->pguser,
1337  conn->pgpassfile);
1338  }
1339  }
1340  }
1341 
1342  /*
1343  * parse and validate require_auth option
1344  */
1345  if (conn->require_auth && conn->require_auth[0])
1346  {
1347  char *s = conn->require_auth;
1348  bool first,
1349  more;
1350  bool negated = false;
1351 
1352  /*
1353  * By default, start from an empty set of allowed options and add to
1354  * it.
1355  */
1356  conn->auth_required = true;
1358 
1359  for (first = true, more = true; more; first = false)
1360  {
1361  char *method,
1362  *part;
1363  uint32 bits;
1364 
1365  part = parse_comma_separated_list(&s, &more);
1366  if (part == NULL)
1367  goto oom_error;
1368 
1369  /*
1370  * Check for negation, e.g. '!password'. If one element is
1371  * negated, they all have to be.
1372  */
1373  method = part;
1374  if (*method == '!')
1375  {
1376  if (first)
1377  {
1378  /*
1379  * Switch to a permissive set of allowed options, and
1380  * subtract from it.
1381  */
1382  conn->auth_required = false;
1383  conn->allowed_auth_methods = -1;
1384  }
1385  else if (!negated)
1386  {
1388  libpq_append_conn_error(conn, "negative require_auth method \"%s\" cannot be mixed with non-negative methods",
1389  method);
1390 
1391  free(part);
1392  return false;
1393  }
1394 
1395  negated = true;
1396  method++;
1397  }
1398  else if (negated)
1399  {
1401  libpq_append_conn_error(conn, "require_auth method \"%s\" cannot be mixed with negative methods",
1402  method);
1403 
1404  free(part);
1405  return false;
1406  }
1407 
1408  if (strcmp(method, "password") == 0)
1409  {
1410  bits = (1 << AUTH_REQ_PASSWORD);
1411  }
1412  else if (strcmp(method, "md5") == 0)
1413  {
1414  bits = (1 << AUTH_REQ_MD5);
1415  }
1416  else if (strcmp(method, "gss") == 0)
1417  {
1418  bits = (1 << AUTH_REQ_GSS);
1419  bits |= (1 << AUTH_REQ_GSS_CONT);
1420  }
1421  else if (strcmp(method, "sspi") == 0)
1422  {
1423  bits = (1 << AUTH_REQ_SSPI);
1424  bits |= (1 << AUTH_REQ_GSS_CONT);
1425  }
1426  else if (strcmp(method, "scram-sha-256") == 0)
1427  {
1428  /* This currently assumes that SCRAM is the only SASL method. */
1429  bits = (1 << AUTH_REQ_SASL);
1430  bits |= (1 << AUTH_REQ_SASL_CONT);
1431  bits |= (1 << AUTH_REQ_SASL_FIN);
1432  }
1433  else if (strcmp(method, "none") == 0)
1434  {
1435  /*
1436  * Special case: let the user explicitly allow (or disallow)
1437  * connections where the server does not send an explicit
1438  * authentication challenge, such as "trust" and "cert" auth.
1439  */
1440  if (negated) /* "!none" */
1441  {
1442  if (conn->auth_required)
1443  goto duplicate;
1444 
1445  conn->auth_required = true;
1446  }
1447  else /* "none" */
1448  {
1449  if (!conn->auth_required)
1450  goto duplicate;
1451 
1452  conn->auth_required = false;
1453  }
1454 
1455  free(part);
1456  continue; /* avoid the bitmask manipulation below */
1457  }
1458  else
1459  {
1461  libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1462  "require_auth", method);
1463 
1464  free(part);
1465  return false;
1466  }
1467 
1468  /* Update the bitmask. */
1469  if (negated)
1470  {
1471  if ((conn->allowed_auth_methods & bits) == 0)
1472  goto duplicate;
1473 
1474  conn->allowed_auth_methods &= ~bits;
1475  }
1476  else
1477  {
1478  if ((conn->allowed_auth_methods & bits) == bits)
1479  goto duplicate;
1480 
1481  conn->allowed_auth_methods |= bits;
1482  }
1483 
1484  free(part);
1485  continue;
1486 
1487  duplicate:
1488 
1489  /*
1490  * A duplicated method probably indicates a typo in a setting
1491  * where typos are extremely risky.
1492  */
1494  libpq_append_conn_error(conn, "require_auth method \"%s\" is specified more than once",
1495  part);
1496 
1497  free(part);
1498  return false;
1499  }
1500  }
1501 
1502  /*
1503  * validate channel_binding option
1504  */
1505  if (conn->channel_binding)
1506  {
1507  if (strcmp(conn->channel_binding, "disable") != 0
1508  && strcmp(conn->channel_binding, "prefer") != 0
1509  && strcmp(conn->channel_binding, "require") != 0)
1510  {
1512  libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1513  "channel_binding", conn->channel_binding);
1514  return false;
1515  }
1516  }
1517  else
1518  {
1520  if (!conn->channel_binding)
1521  goto oom_error;
1522  }
1523 
1524 #ifndef USE_SSL
1525 
1526  /*
1527  * sslrootcert=system is not supported. Since setting this changes the
1528  * default sslmode, check this _before_ we validate sslmode, to avoid
1529  * confusing the user with errors for an option they may not have set.
1530  */
1531  if (conn->sslrootcert
1532  && strcmp(conn->sslrootcert, "system") == 0)
1533  {
1535  libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in",
1536  "sslrootcert", conn->sslrootcert);
1537  return false;
1538  }
1539 #endif
1540 
1541  /*
1542  * validate sslmode option
1543  */
1544  if (conn->sslmode)
1545  {
1546  if (strcmp(conn->sslmode, "disable") != 0
1547  && strcmp(conn->sslmode, "allow") != 0
1548  && strcmp(conn->sslmode, "prefer") != 0
1549  && strcmp(conn->sslmode, "require") != 0
1550  && strcmp(conn->sslmode, "verify-ca") != 0
1551  && strcmp(conn->sslmode, "verify-full") != 0)
1552  {
1554  libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1555  "sslmode", conn->sslmode);
1556  return false;
1557  }
1558 
1559 #ifndef USE_SSL
1560  switch (conn->sslmode[0])
1561  {
1562  case 'a': /* "allow" */
1563  case 'p': /* "prefer" */
1564 
1565  /*
1566  * warn user that an SSL connection will never be negotiated
1567  * since SSL was not compiled in?
1568  */
1569  break;
1570 
1571  case 'r': /* "require" */
1572  case 'v': /* "verify-ca" or "verify-full" */
1574  libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in",
1575  "sslmode", conn->sslmode);
1576  return false;
1577  }
1578 #endif
1579  }
1580  else
1581  {
1582  conn->sslmode = strdup(DefaultSSLMode);
1583  if (!conn->sslmode)
1584  goto oom_error;
1585  }
1586 
1587  /*
1588  * validate sslnegotiation option, default is "postgres" for the postgres
1589  * style negotiated connection with an extra round trip but more options.
1590  */
1591  if (conn->sslnegotiation)
1592  {
1593  if (strcmp(conn->sslnegotiation, "postgres") != 0
1594  && strcmp(conn->sslnegotiation, "direct") != 0)
1595  {
1597  libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1598  "sslnegotiation", conn->sslnegotiation);
1599  return false;
1600  }
1601 
1602 #ifndef USE_SSL
1603  if (conn->sslnegotiation[0] != 'p')
1604  {
1606  libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in",
1607  "sslnegotiation", conn->sslnegotiation);
1608  return false;
1609  }
1610 #endif
1611 
1612  /*
1613  * Don't allow direct SSL negotiation with sslmode='prefer', because
1614  * that poses a risk of unintentional fallback to plaintext connection
1615  * when connecting to a pre-v17 server that does not support direct
1616  * SSL connections. To keep things simple, don't allow it with
1617  * sslmode='allow' or sslmode='disable' either. If a user goes through
1618  * the trouble of setting sslnegotiation='direct', they probably
1619  * intend to use SSL, and sslmode=disable or allow is probably a user
1620  * user mistake anyway.
1621  */
1622  if (conn->sslnegotiation[0] == 'd' &&
1623  conn->sslmode[0] != 'r' && conn->sslmode[0] != 'v')
1624  {
1626  libpq_append_conn_error(conn, "weak sslmode \"%s\" may not be used with sslnegotiation=direct (use \"require\", \"verify-ca\", or \"verify-full\")",
1627  conn->sslmode);
1628  return false;
1629  }
1630  }
1631  else
1632  {
1634  if (!conn->sslnegotiation)
1635  goto oom_error;
1636  }
1637 
1638 #ifdef USE_SSL
1639 
1640  /*
1641  * If sslrootcert=system, make sure our chosen sslmode is compatible.
1642  */
1643  if (conn->sslrootcert
1644  && strcmp(conn->sslrootcert, "system") == 0
1645  && strcmp(conn->sslmode, "verify-full") != 0)
1646  {
1648  libpq_append_conn_error(conn, "weak sslmode \"%s\" may not be used with sslrootcert=system (use \"verify-full\")",
1649  conn->sslmode);
1650  return false;
1651  }
1652 #endif
1653 
1654  /*
1655  * Validate TLS protocol versions for ssl_min_protocol_version and
1656  * ssl_max_protocol_version.
1657  */
1659  {
1661  libpq_append_conn_error(conn, "invalid \"%s\" value: \"%s\"",
1662  "ssl_min_protocol_version",
1664  return false;
1665  }
1667  {
1669  libpq_append_conn_error(conn, "invalid \"%s\" value: \"%s\"",
1670  "ssl_max_protocol_version",
1672  return false;
1673  }
1674 
1675  /*
1676  * Check if the range of SSL protocols defined is correct. This is done
1677  * at this early step because this is independent of the SSL
1678  * implementation used, and this avoids unnecessary cycles with an
1679  * already-built SSL context when the connection is being established, as
1680  * it would be doomed anyway.
1681  */
1684  {
1686  libpq_append_conn_error(conn, "invalid SSL protocol version range");
1687  return false;
1688  }
1689 
1690  /*
1691  * validate sslcertmode option
1692  */
1693  if (conn->sslcertmode)
1694  {
1695  if (strcmp(conn->sslcertmode, "disable") != 0 &&
1696  strcmp(conn->sslcertmode, "allow") != 0 &&
1697  strcmp(conn->sslcertmode, "require") != 0)
1698  {
1700  libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1701  "sslcertmode", conn->sslcertmode);
1702  return false;
1703  }
1704 #ifndef USE_SSL
1705  if (strcmp(conn->sslcertmode, "require") == 0)
1706  {
1708  libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in",
1709  "sslcertmode", conn->sslcertmode);
1710  return false;
1711  }
1712 #endif
1713 #ifndef HAVE_SSL_CTX_SET_CERT_CB
1714 
1715  /*
1716  * Without a certificate callback, the current implementation can't
1717  * figure out if a certificate was actually requested, so "require" is
1718  * useless.
1719  */
1720  if (strcmp(conn->sslcertmode, "require") == 0)
1721  {
1723  libpq_append_conn_error(conn, "%s value \"%s\" is not supported (check OpenSSL version)",
1724  "sslcertmode", conn->sslcertmode);
1725  return false;
1726  }
1727 #endif
1728  }
1729  else
1730  {
1731  conn->sslcertmode = strdup(DefaultSSLCertMode);
1732  if (!conn->sslcertmode)
1733  goto oom_error;
1734  }
1735 
1736  /*
1737  * validate gssencmode option
1738  */
1739  if (conn->gssencmode)
1740  {
1741  if (strcmp(conn->gssencmode, "disable") != 0 &&
1742  strcmp(conn->gssencmode, "prefer") != 0 &&
1743  strcmp(conn->gssencmode, "require") != 0)
1744  {
1746  libpq_append_conn_error(conn, "invalid %s value: \"%s\"", "gssencmode", conn->gssencmode);
1747  return false;
1748  }
1749 #ifndef ENABLE_GSS
1750  if (strcmp(conn->gssencmode, "require") == 0)
1751  {
1753  libpq_append_conn_error(conn, "gssencmode value \"%s\" invalid when GSSAPI support is not compiled in",
1754  conn->gssencmode);
1755  return false;
1756  }
1757 #endif
1758  }
1759  else
1760  {
1761  conn->gssencmode = strdup(DefaultGSSMode);
1762  if (!conn->gssencmode)
1763  goto oom_error;
1764  }
1765 
1766  /*
1767  * validate target_session_attrs option, and set target_server_type
1768  */
1770  {
1771  if (strcmp(conn->target_session_attrs, "any") == 0)
1773  else if (strcmp(conn->target_session_attrs, "read-write") == 0)
1775  else if (strcmp(conn->target_session_attrs, "read-only") == 0)
1777  else if (strcmp(conn->target_session_attrs, "primary") == 0)
1779  else if (strcmp(conn->target_session_attrs, "standby") == 0)
1781  else if (strcmp(conn->target_session_attrs, "prefer-standby") == 0)
1783  else
1784  {
1786  libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1787  "target_session_attrs",
1789  return false;
1790  }
1791  }
1792  else
1794 
1795  /*
1796  * validate load_balance_hosts option, and set load_balance_type
1797  */
1798  if (conn->load_balance_hosts)
1799  {
1800  if (strcmp(conn->load_balance_hosts, "disable") == 0)
1802  else if (strcmp(conn->load_balance_hosts, "random") == 0)
1804  else
1805  {
1807  libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1808  "load_balance_hosts",
1810  return false;
1811  }
1812  }
1813  else
1815 
1817  {
1819 
1820  /*
1821  * This is the "inside-out" variant of the Fisher-Yates shuffle
1822  * algorithm. Notionally, we append each new value to the array and
1823  * then swap it with a randomly-chosen array element (possibly
1824  * including itself, else we fail to generate permutations with the
1825  * last integer last). The swap step can be optimized by combining it
1826  * with the insertion.
1827  */
1828  for (i = 1; i < conn->nconnhost; i++)
1829  {
1830  int j = pg_prng_uint64_range(&conn->prng_state, 0, i);
1831  pg_conn_host temp = conn->connhost[j];
1832 
1833  conn->connhost[j] = conn->connhost[i];
1834  conn->connhost[i] = temp;
1835  }
1836  }
1837 
1838  /*
1839  * Resolve special "auto" client_encoding from the locale
1840  */
1842  strcmp(conn->client_encoding_initial, "auto") == 0)
1843  {
1847  goto oom_error;
1848  }
1849 
1850  /*
1851  * Only if we get this far is it appropriate to try to connect. (We need a
1852  * state flag, rather than just the boolean result of this function, in
1853  * case someone tries to PQreset() the PGconn.)
1854  */
1855  conn->options_valid = true;
1856 
1857  return true;
1858 
1859 oom_error:
1861  libpq_append_conn_error(conn, "out of memory");
1862  return false;
1863 }
unsigned int uint32
Definition: c.h:506
char * pg_fe_getauthname(PQExpBuffer errorMessage)
Definition: fe-auth.c:1255
#define DefaultHost
Definition: fe-connect.c:117
static char * passwordFromFile(const char *hostname, const char *port, const char *dbname, const char *username, const char *pgpassfile)
Definition: fe-connect.c:7478
static bool sslVerifyProtocolRange(const char *min, const char *max)
Definition: fe-connect.c:7674
static void libpq_prng_init(PGconn *conn)
Definition: fe-connect.c:1094
bool pqGetHomeDirectory(char *buf, int bufsize)
Definition: fe-connect.c:7727
#define DefaultSSLMode
Definition: fe-connect.c:130
#define DefaultGSSMode
Definition: fe-connect.c:138
static int count_comma_separated_elems(const char *input)
Definition: fe-connect.c:1035
#define DefaultChannelBinding
Definition: fe-connect.c:122
static bool sslVerifyProtocolVersion(const char *version)
Definition: fe-connect.c:7648
static char * parse_comma_separated_list(char **startptr, bool *more)
Definition: fe-connect.c:1059
#define DefaultSSLNegotiation
Definition: fe-connect.c:133
#define PGPASSFILE
Definition: fe-connect.c:76
#define DefaultSSLCertMode
Definition: fe-connect.c:131
#define calloc(a, b)
Definition: header.h:55
int j
Definition: isn.c:74
#define MAXPGPATH
#define DEFAULT_PGSOCKET_DIR
uint64 pg_prng_uint64_range(pg_prng_state *state, uint64 rmin, uint64 rmax)
Definition: pg_prng.c:144
#define pg_encoding_to_char
Definition: pg_wchar.h:630
#define snprintf
Definition: port.h:238
int pg_get_encoding_from_locale(const char *ctype, bool write_message)
Definition: chklocale.c:301
static bool is_unixsock_path(const char *path)
Definition: pqcomm.h:67
#define AUTH_REQ_SSPI
Definition: protocol.h:83
#define AUTH_REQ_SASL_CONT
Definition: protocol.h:85
#define AUTH_REQ_GSS
Definition: protocol.h:81
#define AUTH_REQ_MD5
Definition: protocol.h:79
#define AUTH_REQ_PASSWORD
Definition: protocol.h:77
#define AUTH_REQ_GSS_CONT
Definition: protocol.h:82
#define AUTH_REQ_SASL
Definition: protocol.h:84
#define AUTH_REQ_SASL_FIN
Definition: protocol.h:86
char * password
Definition: libpq-int.h:367
char * port
Definition: libpq-int.h:366
char * hostaddr
Definition: libpq-int.h:365
pg_conn_host_type type
Definition: libpq-int.h:363
char * sslrootcert
Definition: libpq-int.h:415
char * sslnegotiation
Definition: libpq-int.h:409
int nconnhost
Definition: libpq-int.h:466
char * require_auth
Definition: libpq-int.h:428
char * channel_binding
Definition: libpq-int.h:400
char * pghost
Definition: libpq-int.h:379
char * ssl_max_protocol_version
Definition: libpq-int.h:426
char * pgpass
Definition: libpq-int.h:398
char * dbName
Definition: libpq-int.h:395
char * sslcertmode
Definition: libpq-int.h:414
uint32 allowed_auth_methods
Definition: libpq-int.h:501
char * target_session_attrs
Definition: libpq-int.h:427
bool auth_required
Definition: libpq-int.h:499
char * load_balance_hosts
Definition: libpq-int.h:429
char * pguser
Definition: libpq-int.h:397
char * client_encoding_initial
Definition: libpq-int.h:391
char * sslmode
Definition: libpq-int.h:408
pg_prng_state prng_state
Definition: libpq-int.h:532
char * ssl_min_protocol_version
Definition: libpq-int.h:425
char * gssencmode
Definition: libpq-int.h:420
char * pghostaddr
Definition: libpq-int.h:383
char * pgpassfile
Definition: libpq-int.h:399
PGLoadBalanceType load_balance_type
Definition: libpq-int.h:511
char * pgport
Definition: libpq-int.h:387

References pg_conn::allowed_auth_methods, Assert, AUTH_REQ_GSS, AUTH_REQ_GSS_CONT, AUTH_REQ_MD5, AUTH_REQ_PASSWORD, AUTH_REQ_SASL, AUTH_REQ_SASL_CONT, AUTH_REQ_SASL_FIN, AUTH_REQ_SSPI, pg_conn::auth_required, calloc, pg_conn::channel_binding, CHT_HOST_ADDRESS, CHT_HOST_NAME, CHT_UNIX_SOCKET, pg_conn::client_encoding_initial, conn, CONNECTION_BAD, pg_conn::connhost, count_comma_separated_elems(), pg_conn::dbName, DEFAULT_PGSOCKET_DIR, DefaultChannelBinding, DefaultGSSMode, DefaultHost, DefaultSSLCertMode, DefaultSSLMode, DefaultSSLNegotiation, pg_conn::errorMessage, free, pg_conn::gssencmode, pg_conn_host::host, pg_conn_host::hostaddr, i, is_unixsock_path(), j, libpq_append_conn_error(), libpq_prng_init(), LOAD_BALANCE_DISABLE, pg_conn::load_balance_hosts, LOAD_BALANCE_RANDOM, pg_conn::load_balance_type, 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_prng_uint64_range(), pg_conn::pghost, pg_conn::pghostaddr, pg_conn::pgpass, PGPASSFILE, pg_conn::pgpassfile, pg_conn::pgport, pg_conn::pguser, pg_conn_host::port, pqGetHomeDirectory(), pg_conn::prng_state, pg_conn::require_auth, SERVER_TYPE_ANY, SERVER_TYPE_PREFER_STANDBY, SERVER_TYPE_PRIMARY, SERVER_TYPE_READ_ONLY, SERVER_TYPE_READ_WRITE, SERVER_TYPE_STANDBY, snprintf, pg_conn::ssl_max_protocol_version, pg_conn::ssl_min_protocol_version, pg_conn::sslcertmode, pg_conn::sslmode, pg_conn::sslnegotiation, pg_conn::sslrootcert, sslVerifyProtocolRange(), sslVerifyProtocolVersion(), pg_conn::status, pg_conn::target_server_type, pg_conn::target_session_attrs, pg_conn_host::type, and pg_conn::whichhost.

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

◆ pqCopyPGconn()

bool pqCopyPGconn ( PGconn srcConn,
PGconn dstConn 
)

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

958 {
960 
961  /* copy over connection options */
962  for (option = PQconninfoOptions; option->keyword; option++)
963  {
964  if (option->connofs >= 0)
965  {
966  const char **tmp = (const char **) ((char *) srcConn + option->connofs);
967 
968  if (*tmp)
969  {
970  char **dstConnmember = (char **) ((char *) dstConn + option->connofs);
971 
972  if (*dstConnmember)
973  free(*dstConnmember);
974  *dstConnmember = strdup(*tmp);
975  if (*dstConnmember == NULL)
976  {
977  libpq_append_conn_error(dstConn, "out of memory");
978  return false;
979  }
980  }
981  }
982  }
983  return true;
984 }
static const internalPQconninfoOption PQconninfoOptions[]
Definition: fe-connect.c:191

References free, libpq_append_conn_error(), and PQconninfoOptions.

Referenced by PQcancelCreate().

◆ pqDropConnection()

void pqDropConnection ( PGconn conn,
bool  flushInput 
)

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

473 {
474  /* Drop any SSL state */
476 
477  /* Close the socket itself */
478  if (conn->sock != PGINVALID_SOCKET)
481 
482  /* Optionally discard any unread data */
483  if (flushInput)
484  conn->inStart = conn->inCursor = conn->inEnd = 0;
485 
486  /* Always discard any unsent data */
487  conn->outCount = 0;
488 
489  /* Likewise, discard any pending pipelined commands */
493  conn->cmd_queue_recycle = NULL;
494 
495  /* Free authentication/encryption state */
496 #ifdef ENABLE_GSS
497  {
498  OM_uint32 min_s;
499 
500  if (conn->gcred != GSS_C_NO_CREDENTIAL)
501  {
502  gss_release_cred(&min_s, &conn->gcred);
503  conn->gcred = GSS_C_NO_CREDENTIAL;
504  }
505  if (conn->gctx)
506  gss_delete_sec_context(&min_s, &conn->gctx, GSS_C_NO_BUFFER);
507  if (conn->gtarg_nam)
508  gss_release_name(&min_s, &conn->gtarg_nam);
509  if (conn->gss_SendBuffer)
510  {
511  free(conn->gss_SendBuffer);
512  conn->gss_SendBuffer = NULL;
513  }
514  if (conn->gss_RecvBuffer)
515  {
516  free(conn->gss_RecvBuffer);
517  conn->gss_RecvBuffer = NULL;
518  }
519  if (conn->gss_ResultBuffer)
520  {
521  free(conn->gss_ResultBuffer);
522  conn->gss_ResultBuffer = NULL;
523  }
524  conn->gssenc = false;
525  }
526 #endif
527 #ifdef ENABLE_SSPI
528  if (conn->sspitarget)
529  {
530  free(conn->sspitarget);
531  conn->sspitarget = NULL;
532  }
533  if (conn->sspicred)
534  {
535  FreeCredentialsHandle(conn->sspicred);
536  free(conn->sspicred);
537  conn->sspicred = NULL;
538  }
539  if (conn->sspictx)
540  {
541  DeleteSecurityContext(conn->sspictx);
542  free(conn->sspictx);
543  conn->sspictx = NULL;
544  }
545  conn->usesspi = 0;
546 #endif
547  if (conn->sasl_state)
548  {
550  conn->sasl_state = NULL;
551  }
552 }
static void pqFreeCommandQueue(PGcmdQueueEntry *queue)
Definition: fe-connect.c:559
void pqsecure_close(PGconn *conn)
Definition: fe-secure.c:152
#define PGINVALID_SOCKET
Definition: port.h:31
#define closesocket
Definition: port.h:349
pgsocket sock
Definition: libpq-int.h:485
const pg_fe_sasl_mech * sasl
Definition: libpq-int.h:571
PGcmdQueueEntry * cmd_queue_recycle
Definition: libpq-int.h:482
void * sasl_state
Definition: libpq-int.h:572
void(* free)(void *state)
Definition: fe-auth-sasl.h:140

References closesocket, pg_conn::cmd_queue_head, pg_conn::cmd_queue_recycle, pg_conn::cmd_queue_tail, conn, free, pg_fe_sasl_mech::free, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, pg_conn::outCount, PGINVALID_SOCKET, pqFreeCommandQueue(), pqsecure_close(), pg_conn::sasl, pg_conn::sasl_state, and pg_conn::sock.

Referenced by handleSyncLoss(), pqClosePGconn(), pqConnectDBStart(), PQconnectPoll(), and pqReadData().

◆ pqEndcopy3()

int pqEndcopy3 ( PGconn conn)

Definition at line 1908 of file fe-protocol3.c.

1909 {
1910  PGresult *result;
1911 
1912  if (conn->asyncStatus != PGASYNC_COPY_IN &&
1915  {
1916  libpq_append_conn_error(conn, "no COPY in progress");
1917  return 1;
1918  }
1919 
1920  /* Send the CopyDone message if needed */
1921  if (conn->asyncStatus == PGASYNC_COPY_IN ||
1923  {
1924  if (pqPutMsgStart(PqMsg_CopyDone, conn) < 0 ||
1925  pqPutMsgEnd(conn) < 0)
1926  return 1;
1927 
1928  /*
1929  * If we sent the COPY command in extended-query mode, we must issue a
1930  * Sync as well.
1931  */
1932  if (conn->cmd_queue_head &&
1934  {
1935  if (pqPutMsgStart(PqMsg_Sync, conn) < 0 ||
1936  pqPutMsgEnd(conn) < 0)
1937  return 1;
1938  }
1939  }
1940 
1941  /*
1942  * make sure no data is waiting to be sent, abort if we are non-blocking
1943  * and the flush fails
1944  */
1945  if (pqFlush(conn) && pqIsnonblocking(conn))
1946  return 1;
1947 
1948  /* Return to active duty */
1950 
1951  /*
1952  * Non blocking connections may have to abort at this point. If everyone
1953  * played the game there should be no problem, but in error scenarios the
1954  * expected messages may not have arrived yet. (We are assuming that the
1955  * backend's packetizing will ensure that CommandComplete arrives along
1956  * with the CopyDone; are there corner cases where that doesn't happen?)
1957  */
1958  if (pqIsnonblocking(conn) && PQisBusy(conn))
1959  return 1;
1960 
1961  /* Wait for the completion response */
1962  result = PQgetResult(conn);
1963 
1964  /* Expecting a successful result */
1965  if (result && result->resultStatus == PGRES_COMMAND_OK)
1966  {
1967  PQclear(result);
1968  return 0;
1969  }
1970 
1971  /*
1972  * Trouble. For backwards-compatibility reasons, we issue the error
1973  * message as if it were a notice (would be nice to get rid of this
1974  * silliness, but too many apps probably don't handle errors from
1975  * PQendcopy reasonably). Note that the app can still obtain the error
1976  * status from the PGconn object.
1977  */
1978  if (conn->errorMessage.len > 0)
1979  {
1980  /* We have to strip the trailing newline ... pain in neck... */
1981  char svLast = conn->errorMessage.data[conn->errorMessage.len - 1];
1982 
1983  if (svLast == '\n')
1984  conn->errorMessage.data[conn->errorMessage.len - 1] = '\0';
1986  conn->errorMessage.data[conn->errorMessage.len - 1] = svLast;
1987  }
1988 
1989  PQclear(result);
1990 
1991  return 1;
1992 }
void pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
Definition: fe-exec.c:938
int PQisBusy(PGconn *conn)
Definition: fe-exec.c:2031
PGresult * PQgetResult(PGconn *conn)
Definition: fe-exec.c:2062
int pqFlush(PGconn *conn)
Definition: fe-misc.c:968
int pqPutMsgStart(char msg_type, PGconn *conn)
Definition: fe-misc.c:473
int pqPutMsgEnd(PGconn *conn)
Definition: fe-misc.c:532
@ PGRES_COMMAND_OK
Definition: libpq-fe.h:120
#define pqIsnonblocking(conn)
Definition: libpq-int.h:895
#define PqMsg_CopyDone
Definition: protocol.h:64
#define PqMsg_Sync
Definition: protocol.h:27
PGNoticeHooks noticeHooks
Definition: libpq-int.h:440

References pg_conn::asyncStatus, pg_conn::cmd_queue_head, conn, PQExpBufferData::data, pg_conn::errorMessage, PQExpBufferData::len, libpq_append_conn_error(), pg_conn::noticeHooks, PGASYNC_BUSY, PGASYNC_COPY_BOTH, PGASYNC_COPY_IN, PGASYNC_COPY_OUT, PGQUERY_SIMPLE, PGRES_COMMAND_OK, PQclear(), pqFlush(), PQgetResult(), pqInternalNotice(), PQisBusy(), pqIsnonblocking, PqMsg_CopyDone, PqMsg_Sync, pqPutMsgEnd(), pqPutMsgStart(), PGcmdQueueEntry::queryclass, and pg_result::resultStatus.

Referenced by PQendcopy().

◆ pqFlush()

int pqFlush ( PGconn conn)

Definition at line 968 of file fe-misc.c.

969 {
970  if (conn->outCount > 0)
971  {
972  if (conn->Pfdebug)
973  fflush(conn->Pfdebug);
974 
975  return pqSendSome(conn, conn->outCount);
976  }
977 
978  return 0;
979 }
static int pqSendSome(PGconn *conn, int len)
Definition: fe-misc.c:799
static void const char fflush(stdout)
FILE * Pfdebug
Definition: libpq-int.h:436

References conn, fflush(), pg_conn::outCount, pg_conn::Pfdebug, and pqSendSome().

Referenced by pg_SASL_init(), PQconnectPoll(), PQconsumeInput(), pqEndcopy3(), PQexitPipelineMode(), PQflush(), pqFunctionCall3(), PQgetResult(), pqPacketSend(), pqPipelineFlush(), pqPipelineSyncInternal(), PQputCopyData(), PQputCopyEnd(), PQsendQueryInternal(), PQsetnonblocking(), and sendTerminateConn().

◆ pqFunctionCall3()

PGresult* pqFunctionCall3 ( PGconn conn,
Oid  fnid,
int *  result_buf,
int *  actual_result_len,
int  result_is_int,
const PQArgBlock args,
int  nargs 
)

Definition at line 2001 of file fe-protocol3.c.

2005 {
2006  bool needInput = false;
2008  char id;
2009  int msgLength;
2010  int avail;
2011  int i;
2012 
2013  /* already validated by PQfn */
2015 
2016  /* PQfn already validated connection state */
2017 
2019  pqPutInt(fnid, 4, conn) < 0 || /* function id */
2020  pqPutInt(1, 2, conn) < 0 || /* # of format codes */
2021  pqPutInt(1, 2, conn) < 0 || /* format code: BINARY */
2022  pqPutInt(nargs, 2, conn) < 0) /* # of args */
2023  {
2024  /* error message should be set up already */
2025  return NULL;
2026  }
2027 
2028  for (i = 0; i < nargs; ++i)
2029  { /* len.int4 + contents */
2030  if (pqPutInt(args[i].len, 4, conn))
2031  return NULL;
2032  if (args[i].len == -1)
2033  continue; /* it's NULL */
2034 
2035  if (args[i].isint)
2036  {
2037  if (pqPutInt(args[i].u.integer, args[i].len, conn))
2038  return NULL;
2039  }
2040  else
2041  {
2042  if (pqPutnchar((char *) args[i].u.ptr, args[i].len, conn))
2043  return NULL;
2044  }
2045  }
2046 
2047  if (pqPutInt(1, 2, conn) < 0) /* result format code: BINARY */
2048  return NULL;
2049 
2050  if (pqPutMsgEnd(conn) < 0 ||
2051  pqFlush(conn))
2052  return NULL;
2053 
2054  for (;;)
2055  {
2056  if (needInput)
2057  {
2058  /* Wait for some data to arrive (or for the channel to close) */
2059  if (pqWait(true, false, conn) ||
2060  pqReadData(conn) < 0)
2061  break;
2062  }
2063 
2064  /*
2065  * Scan the message. If we run out of data, loop around to try again.
2066  */
2067  needInput = true;
2068 
2069  conn->inCursor = conn->inStart;
2070  if (pqGetc(&id, conn))
2071  continue;
2072  if (pqGetInt(&msgLength, 4, conn))
2073  continue;
2074 
2075  /*
2076  * Try to validate message type/length here. A length less than 4 is
2077  * definitely broken. Large lengths should only be believed for a few
2078  * message types.
2079  */
2080  if (msgLength < 4)
2081  {
2082  handleSyncLoss(conn, id, msgLength);
2083  break;
2084  }
2085  if (msgLength > 30000 && !VALID_LONG_MESSAGE_TYPE(id))
2086  {
2087  handleSyncLoss(conn, id, msgLength);
2088  break;
2089  }
2090 
2091  /*
2092  * Can't process if message body isn't all here yet.
2093  */
2094  msgLength -= 4;
2095  avail = conn->inEnd - conn->inCursor;
2096  if (avail < msgLength)
2097  {
2098  /*
2099  * Before looping, enlarge the input buffer if needed to hold the
2100  * whole message. See notes in parseInput.
2101  */
2102  if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength,
2103  conn))
2104  {
2105  /*
2106  * XXX add some better recovery code... plan is to skip over
2107  * the message using its length, then report an error. For the
2108  * moment, just treat this like loss of sync (which indeed it
2109  * might be!)
2110  */
2111  handleSyncLoss(conn, id, msgLength);
2112  break;
2113  }
2114  continue;
2115  }
2116 
2117  /*
2118  * We should see V or E response to the command, but might get N
2119  * and/or A notices first. We also need to swallow the final Z before
2120  * returning.
2121  */
2122  switch (id)
2123  {
2124  case 'V': /* function result */
2125  if (pqGetInt(actual_result_len, 4, conn))
2126  continue;
2127  if (*actual_result_len != -1)
2128  {
2129  if (result_is_int)
2130  {
2131  if (pqGetInt(result_buf, *actual_result_len, conn))
2132  continue;
2133  }
2134  else
2135  {
2136  if (pqGetnchar((char *) result_buf,
2137  *actual_result_len,
2138  conn))
2139  continue;
2140  }
2141  }
2142  /* correctly finished function result message */
2143  status = PGRES_COMMAND_OK;
2144  break;
2145  case 'E': /* error return */
2146  if (pqGetErrorNotice3(conn, true))
2147  continue;
2148  status = PGRES_FATAL_ERROR;
2149  break;
2150  case 'A': /* notify message */
2151  /* handle notify and go back to processing return values */
2152  if (getNotify(conn))
2153  continue;
2154  break;
2155  case 'N': /* notice */
2156  /* handle notice and go back to processing return values */
2157  if (pqGetErrorNotice3(conn, false))
2158  continue;
2159  break;
2160  case 'Z': /* backend is ready for new query */
2161  if (getReadyForQuery(conn))
2162  continue;
2163 
2164  /* consume the message */
2165  pqParseDone(conn, conn->inStart + 5 + msgLength);
2166 
2167  /*
2168  * If we already have a result object (probably an error), use
2169  * that. Otherwise, if we saw a function result message,
2170  * report COMMAND_OK. Otherwise, the backend violated the
2171  * protocol, so complain.
2172  */
2173  if (!pgHavePendingResult(conn))
2174  {
2175  if (status == PGRES_COMMAND_OK)
2176  {
2177  conn->result = PQmakeEmptyPGresult(conn, status);
2178  if (!conn->result)
2179  {
2180  libpq_append_conn_error(conn, "out of memory");
2182  }
2183  }
2184  else
2185  {
2186  libpq_append_conn_error(conn, "protocol error: no function result");
2188  }
2189  }
2190  /* and we're out */
2191  return pqPrepareAsyncResult(conn);
2192  case 'S': /* parameter status */
2193  if (getParameterStatus(conn))
2194  continue;
2195  break;
2196  default:
2197  /* The backend violates the protocol. */
2198  libpq_append_conn_error(conn, "protocol error: id=0x%x", id);
2200 
2201  /*
2202  * We can't call parsing done due to the protocol violation
2203  * (so message tracing wouldn't work), but trust the specified
2204  * message length as what to skip.
2205  */
2206  conn->inStart += 5 + msgLength;
2207  return pqPrepareAsyncResult(conn);
2208  }
2209 
2210  /* Completed parsing this message, keep going */
2211  pqParseDone(conn, conn->inStart + 5 + msgLength);
2212  needInput = false;
2213  }
2214 
2215  /*
2216  * We fall out of the loop only upon failing to read data.
2217  * conn->errorMessage has been set by pqWait or pqReadData. We want to
2218  * append it to any already-received error message.
2219  */
2221  return pqPrepareAsyncResult(conn);
2222 }
void pqSaveErrorResult(PGconn *conn)
Definition: fe-exec.c:803
PGresult * PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
Definition: fe-exec.c:159
PGresult * pqPrepareAsyncResult(PGconn *conn)
Definition: fe-exec.c:851
int pqReadData(PGconn *conn)
Definition: fe-misc.c:580
int pqPutInt(int value, size_t bytes, PGconn *conn)
Definition: fe-misc.c:253
void pqParseDone(PGconn *conn, int newInStart)
Definition: fe-misc.c:443
int pqGetc(char *result, PGconn *conn)
Definition: fe-misc.c:77
int pqGetInt(int *result, size_t bytes, PGconn *conn)
Definition: fe-misc.c:216
int pqGetnchar(char *s, size_t len, PGconn *conn)
Definition: fe-misc.c:165
int pqWait(int forRead, int forWrite, PGconn *conn)
Definition: fe-misc.c:993
int pqCheckInBufferSpace(size_t bytes_needed, PGconn *conn)
Definition: fe-misc.c:351
int pqPutnchar(const char *s, size_t len, PGconn *conn)
Definition: fe-misc.c:202
static int getNotify(PGconn *conn)
static int getParameterStatus(PGconn *conn)
#define VALID_LONG_MESSAGE_TYPE(id)
Definition: fe-protocol3.c:36
static void handleSyncLoss(PGconn *conn, char id, int msgLength)
Definition: fe-protocol3.c:479
static int getReadyForQuery(PGconn *conn)
int pqGetErrorNotice3(PGconn *conn, bool isError)
Definition: fe-protocol3.c:878
ExecStatusType
Definition: libpq-fe.h:118
#define pgHavePendingResult(conn)
Definition: libpq-int.h:888
#define PqMsg_FunctionCall
Definition: protocol.h:23

References generate_unaccent_rules::args, Assert, conn, getNotify(), getParameterStatus(), getReadyForQuery(), handleSyncLoss(), i, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, len, libpq_append_conn_error(), pgHavePendingResult, PGRES_COMMAND_OK, PGRES_FATAL_ERROR, pg_conn::pipelineStatus, PQ_PIPELINE_OFF, pqCheckInBufferSpace(), pqFlush(), pqGetc(), pqGetErrorNotice3(), pqGetInt(), pqGetnchar(), PQmakeEmptyPGresult(), PqMsg_FunctionCall, pqParseDone(), pqPrepareAsyncResult(), pqPutInt(), pqPutMsgEnd(), pqPutMsgStart(), pqPutnchar(), pqReadData(), pqSaveErrorResult(), pqWait(), pg_conn::result, and VALID_LONG_MESSAGE_TYPE.

Referenced by PQfn().

◆ pqGetc()

int pqGetc ( char *  result,
PGconn conn 
)

Definition at line 77 of file fe-misc.c.

78 {
79  if (conn->inCursor >= conn->inEnd)
80  return EOF;
81 
82  *result = conn->inBuffer[conn->inCursor++];
83 
84  return 0;
85 }

References conn, pg_conn::inBuffer, pg_conn::inCursor, and pg_conn::inEnd.

Referenced by getCopyDataMessage(), getCopyStart(), getReadyForQuery(), PQconnectPoll(), pqFunctionCall3(), pqGetErrorNotice3(), and pqParseInput3().

◆ pqGetCopyData3()

int pqGetCopyData3 ( PGconn conn,
char **  buffer,
int  async 
)

Definition at line 1743 of file fe-protocol3.c.

1744 {
1745  int msgLength;
1746 
1747  for (;;)
1748  {
1749  /*
1750  * Collect the next input message. To make life simpler for async
1751  * callers, we keep returning 0 until the next message is fully
1752  * available, even if it is not Copy Data.
1753  */
1754  msgLength = getCopyDataMessage(conn);
1755  if (msgLength < 0)
1756  return msgLength; /* end-of-copy or error */
1757  if (msgLength == 0)
1758  {
1759  /* Don't block if async read requested */
1760  if (async)
1761  return 0;
1762  /* Need to load more data */
1763  if (pqWait(true, false, conn) ||
1764  pqReadData(conn) < 0)
1765  return -2;
1766  continue;
1767  }
1768 
1769  /*
1770  * Drop zero-length messages (shouldn't happen anyway). Otherwise
1771  * pass the data back to the caller.
1772  */
1773  msgLength -= 4;
1774  if (msgLength > 0)
1775  {
1776  *buffer = (char *) malloc(msgLength + 1);
1777  if (*buffer == NULL)
1778  {
1779  libpq_append_conn_error(conn, "out of memory");
1780  return -2;
1781  }
1782  memcpy(*buffer, &conn->inBuffer[conn->inCursor], msgLength);
1783  (*buffer)[msgLength] = '\0'; /* Add terminating null */
1784 
1785  /* Mark message consumed */
1786  pqParseDone(conn, conn->inCursor + msgLength);
1787 
1788  return msgLength;
1789  }
1790 
1791  /* Empty, so drop it and loop around for another */
1793  }
1794 }
static int getCopyDataMessage(PGconn *conn)

References conn, getCopyDataMessage(), pg_conn::inBuffer, pg_conn::inCursor, libpq_append_conn_error(), malloc, pqParseDone(), pqReadData(), and pqWait().

Referenced by PQgetCopyData().

◆ pqGetErrorNotice3()

int pqGetErrorNotice3 ( PGconn conn,
bool  isError 
)

Definition at line 878 of file fe-protocol3.c.

879 {
880  PGresult *res = NULL;
881  bool have_position = false;
882  PQExpBufferData workBuf;
883  char id;
884 
885  /* If in pipeline mode, set error indicator for it */
886  if (isError && conn->pipelineStatus != PQ_PIPELINE_OFF)
888 
889  /*
890  * If this is an error message, pre-emptively clear any incomplete query
891  * result we may have. We'd just throw it away below anyway, and
892  * releasing it before collecting the error might avoid out-of-memory.
893  */
894  if (isError)
896 
897  /*
898  * Since the fields might be pretty long, we create a temporary
899  * PQExpBuffer rather than using conn->workBuffer. workBuffer is intended
900  * for stuff that is expected to be short. We shouldn't use
901  * conn->errorMessage either, since this might be only a notice.
902  */
903  initPQExpBuffer(&workBuf);
904 
905  /*
906  * Make a PGresult to hold the accumulated fields. We temporarily lie
907  * about the result status, so that PQmakeEmptyPGresult doesn't uselessly
908  * copy conn->errorMessage.
909  *
910  * NB: This allocation can fail, if you run out of memory. The rest of the
911  * function handles that gracefully, and we still try to set the error
912  * message as the connection's error message.
913  */
915  if (res)
917 
918  /*
919  * Read the fields and save into res.
920  *
921  * While at it, save the SQLSTATE in conn->last_sqlstate, and note whether
922  * we saw a PG_DIAG_STATEMENT_POSITION field.
923  */
924  for (;;)
925  {
926  if (pqGetc(&id, conn))
927  goto fail;
928  if (id == '\0')
929  break; /* terminator found */
930  if (pqGets(&workBuf, conn))
931  goto fail;
932  pqSaveMessageField(res, id, workBuf.data);
933  if (id == PG_DIAG_SQLSTATE)
934  strlcpy(conn->last_sqlstate, workBuf.data,
935  sizeof(conn->last_sqlstate));
936  else if (id == PG_DIAG_STATEMENT_POSITION)
937  have_position = true;
938  }
939 
940  /*
941  * Save the active query text, if any, into res as well; but only if we
942  * might need it for an error cursor display, which is only true if there
943  * is a PG_DIAG_STATEMENT_POSITION field.
944  */
945  if (have_position && res && conn->cmd_queue_head && conn->cmd_queue_head->query)
947 
948  /*
949  * Now build the "overall" error message for PQresultErrorMessage.
950  */
951  resetPQExpBuffer(&workBuf);
953 
954  /*
955  * Either save error as current async result, or just emit the notice.
956  */
957  if (isError)
958  {
959  pqClearAsyncResult(conn); /* redundant, but be safe */
960  if (res)
961  {
962  pqSetResultError(res, &workBuf, 0);
963  conn->result = res;
964  }
965  else
966  {
967  /* Fall back to using the internal-error processing paths */
968  conn->error_result = true;
969  }
970 
971  if (PQExpBufferDataBroken(workBuf))
972  libpq_append_conn_error(conn, "out of memory");
973  else
975  }
976  else
977  {
978  /* if we couldn't allocate the result set, just discard the NOTICE */
979  if (res)
980  {
981  /*
982  * We can cheat a little here and not copy the message. But if we
983  * were unlucky enough to run out of memory while filling workBuf,
984  * insert "out of memory", as in pqSetResultError.
985  */
986  if (PQExpBufferDataBroken(workBuf))
987  res->errMsg = libpq_gettext("out of memory\n");
988  else
989  res->errMsg = workBuf.data;
990  if (res->noticeHooks.noticeRec != NULL)
992  PQclear(res);
993  }
994  }
995 
996  termPQExpBuffer(&workBuf);
997  return 0;
998 
999 fail:
1000  PQclear(res);
1001  termPQExpBuffer(&workBuf);
1002  return EOF;
1003 }
void pqSaveMessageField(PGresult *res, char code, const char *value)
Definition: fe-exec.c:1060
void pqSetResultError(PGresult *res, PQExpBuffer errorMessage, int offset)
Definition: fe-exec.c:692
char * pqResultStrdup(PGresult *res, const char *str)
Definition: fe-exec.c:675
int pqGets(PQExpBuffer buf, PGconn *conn)
Definition: fe-misc.c:136
void pqBuildErrorMessage3(PQExpBuffer msg, const PGresult *res, PGVerbosity verbosity, PGContextVisibility show_context)
@ PGRES_EMPTY_QUERY
Definition: libpq-fe.h:119
@ PGRES_NONFATAL_ERROR
Definition: libpq-fe.h:130
@ PQ_PIPELINE_ABORTED
Definition: libpq-fe.h:184
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:90
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:129
#define PQExpBufferDataBroken(buf)
Definition: pqexpbuffer.h:67
PQnoticeReceiver noticeRec
Definition: libpq-int.h:155
void * noticeRecArg
Definition: libpq-int.h:156
PGVerbosity verbosity
Definition: libpq-int.h:529
char last_sqlstate[6]
Definition: libpq-int.h:451
PGContextVisibility show_context
Definition: libpq-int.h:530
PGNoticeHooks noticeHooks
Definition: libpq-int.h:189

References appendPQExpBufferStr(), pg_conn::cmd_queue_head, conn, PQExpBufferData::data, pg_result::errMsg, pg_conn::error_result, pg_conn::errorMessage, pg_result::errQuery, initPQExpBuffer(), pg_conn::last_sqlstate, libpq_append_conn_error(), libpq_gettext, pg_result::noticeHooks, PGNoticeHooks::noticeRec, PGNoticeHooks::noticeRecArg, PG_DIAG_SQLSTATE, PG_DIAG_STATEMENT_POSITION, PGRES_EMPTY_QUERY, PGRES_FATAL_ERROR, PGRES_NONFATAL_ERROR, pg_conn::pipelineStatus, PQ_PIPELINE_ABORTED, PQ_PIPELINE_OFF, pqBuildErrorMessage3(), PQclear(), pqClearAsyncResult(), PQExpBufferDataBroken, pqGetc(), pqGets(), PQmakeEmptyPGresult(), pqResultStrdup(), pqSaveMessageField(), pqSetResultError(), PGcmdQueueEntry::query, res, resetPQExpBuffer(), pg_conn::result, pg_result::resultStatus, pg_conn::show_context, strlcpy(), termPQExpBuffer(), and pg_conn::verbosity.

Referenced by getCopyDataMessage(), PQconnectPoll(), pqFunctionCall3(), and pqParseInput3().

◆ pqGetHomeDirectory()

bool pqGetHomeDirectory ( char *  buf,
int  bufsize 
)

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

7728 {
7729 #ifndef WIN32
7730  const char *home;
7731 
7732  home = getenv("HOME");
7733  if (home && home[0])
7734  {
7735  strlcpy(buf, home, bufsize);
7736  return true;
7737  }
7738  else
7739  {
7740  struct passwd pwbuf;
7741  struct passwd *pw;
7742  char tmpbuf[1024];
7743  int rc;
7744 
7745  rc = getpwuid_r(geteuid(), &pwbuf, tmpbuf, sizeof tmpbuf, &pw);
7746  if (rc != 0 || !pw)
7747  return false;
7748  strlcpy(buf, pw->pw_dir, bufsize);
7749  return true;
7750  }
7751 #else
7752  char tmppath[MAX_PATH];
7753 
7754  ZeroMemory(tmppath, sizeof(tmppath));
7755  if (SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, tmppath) != S_OK)
7756  return false;
7757  snprintf(buf, bufsize, "%s/postgresql", tmppath);
7758  return true;
7759 #endif
7760 }
#define bufsize
Definition: indent_globs.h:36
static char * buf
Definition: pg_test_fsync.c:73
static StringInfoData tmpbuf
Definition: walsender.c:170

References buf, bufsize, snprintf, strlcpy(), and tmpbuf.

Referenced by initialize_SSL(), parseServiceInfo(), and pqConnectOptions2().

◆ pqGetInt()

int pqGetInt ( int *  result,
size_t  bytes,
PGconn conn 
)

Definition at line 216 of file fe-misc.c.

217 {
218  uint16 tmp2;
219  uint32 tmp4;
220 
221  switch (bytes)
222  {
223  case 2:
224  if (conn->inCursor + 2 > conn->inEnd)
225  return EOF;
226  memcpy(&tmp2, conn->inBuffer + conn->inCursor, 2);
227  conn->inCursor += 2;
228  *result = (int) pg_ntoh16(tmp2);
229  break;
230  case 4:
231  if (conn->inCursor + 4 > conn->inEnd)
232  return EOF;
233  memcpy(&tmp4, conn->inBuffer + conn->inCursor, 4);
234  conn->inCursor += 4;
235  *result = (int) pg_ntoh32(tmp4);
236  break;
237  default:
239  "integer of size %lu not supported by pqGetInt",
240  (unsigned long) bytes);
241  return EOF;
242  }
243 
244  return 0;
245 }
unsigned short uint16
Definition: c.h:505
#define pg_ntoh32(x)
Definition: pg_bswap.h:125
#define pg_ntoh16(x)
Definition: pg_bswap.h:124

References conn, pg_conn::inBuffer, pg_conn::inCursor, pg_conn::inEnd, pg_conn::noticeHooks, pg_ntoh16, pg_ntoh32, and pqInternalNotice().

Referenced by getAnotherTuple(), getCopyDataMessage(), getCopyStart(), getNotify(), getParamDescriptions(), getRowDescriptions(), PQconnectPoll(), pqFunctionCall3(), pqGetNegotiateProtocolVersion3(), and pqParseInput3().

◆ pqGetline3()

int pqGetline3 ( PGconn conn,
char *  s,
int  maxlen 
)

Definition at line 1802 of file fe-protocol3.c.

1803 {
1804  int status;
1805 
1806  if (conn->sock == PGINVALID_SOCKET ||
1810  {
1811  libpq_append_conn_error(conn, "PQgetline: not doing text COPY OUT");
1812  *s = '\0';
1813  return EOF;
1814  }
1815 
1816  while ((status = PQgetlineAsync(conn, s, maxlen - 1)) == 0)
1817  {
1818  /* need to load more data */
1819  if (pqWait(true, false, conn) ||
1820  pqReadData(conn) < 0)
1821  {
1822  *s = '\0';
1823  return EOF;
1824  }
1825  }
1826 
1827  if (status < 0)
1828  {
1829  /* End of copy detected; gin up old-style terminator */
1830  strcpy(s, "\\.");
1831  return 0;
1832  }
1833 
1834  /* Add null terminator, and strip trailing \n if present */
1835  if (s[status - 1] == '\n')
1836  {
1837  s[status - 1] = '\0';
1838  return 0;
1839  }
1840  else
1841  {
1842  s[status] = '\0';
1843  return 1;
1844  }
1845 }
int PQgetlineAsync(PGconn *conn, char *buffer, int bufsize)
Definition: fe-exec.c:2901
char copy_is_binary
Definition: libpq-int.h:460

References pg_conn::asyncStatus, conn, pg_conn::copy_is_binary, libpq_append_conn_error(), PGASYNC_COPY_BOTH, PGASYNC_COPY_OUT, PGINVALID_SOCKET, PQgetlineAsync(), pqReadData(), pqWait(), and pg_conn::sock.

Referenced by PQgetline().

◆ pqGetlineAsync3()

int pqGetlineAsync3 ( PGconn conn,
char *  buffer,
int  bufsize 
)

Definition at line 1853 of file fe-protocol3.c.

1854 {
1855  int msgLength;
1856  int avail;
1857 
1860  return -1; /* we are not doing a copy... */
1861 
1862  /*
1863  * Recognize the next input message. To make life simpler for async
1864  * callers, we keep returning 0 until the next message is fully available
1865  * even if it is not Copy Data. This should keep PQendcopy from blocking.
1866  * (Note: unlike pqGetCopyData3, we do not change asyncStatus here.)
1867  */
1868  msgLength = getCopyDataMessage(conn);
1869  if (msgLength < 0)
1870  return -1; /* end-of-copy or error */
1871  if (msgLength == 0)
1872  return 0; /* no data yet */
1873 
1874  /*
1875  * Move data from libpq's buffer to the caller's. In the case where a
1876  * prior call found the caller's buffer too small, we use
1877  * conn->copy_already_done to remember how much of the row was already
1878  * returned to the caller.
1879  */
1881  avail = msgLength - 4 - conn->copy_already_done;
1882  if (avail <= bufsize)
1883  {
1884  /* Able to consume the whole message */
1885  memcpy(buffer, &conn->inBuffer[conn->inCursor], avail);
1886  /* Mark message consumed */
1887  conn->inStart = conn->inCursor + avail;
1888  /* Reset state for next time */
1889  conn->copy_already_done = 0;
1890  return avail;
1891  }
1892  else
1893  {
1894  /* We must return a partial message */
1895  memcpy(buffer, &conn->inBuffer[conn->inCursor], bufsize);
1896  /* The message is NOT consumed from libpq's buffer */
1898  return bufsize;
1899  }
1900 }
int copy_already_done
Definition: libpq-int.h:461

References pg_conn::asyncStatus, bufsize, conn, pg_conn::copy_already_done, getCopyDataMessage(), pg_conn::inBuffer, pg_conn::inCursor, pg_conn::inStart, PGASYNC_COPY_BOTH, and PGASYNC_COPY_OUT.

Referenced by PQgetlineAsync().

◆ pqGetnchar()

int pqGetnchar ( char *  s,
size_t  len,
PGconn conn 
)

Definition at line 165 of file fe-misc.c.

166 {
167  if (len > (size_t) (conn->inEnd - conn->inCursor))
168  return EOF;
169 
170  memcpy(s, conn->inBuffer + conn->inCursor, len);
171  /* no terminating null */
172 
173  conn->inCursor += len;
174 
175  return 0;
176 }

References conn, pg_conn::inBuffer, pg_conn::inCursor, pg_conn::inEnd, and len.

Referenced by pg_password_sendauth(), pg_SASL_continue(), and pqFunctionCall3().

◆ pqGetNegotiateProtocolVersion3()

int pqGetNegotiateProtocolVersion3 ( PGconn conn)

Definition at line 1408 of file fe-protocol3.c.

1409 {
1410  int tmp;
1411  ProtocolVersion their_version;
1412  int num;
1414 
1415  if (pqGetInt(&tmp, 4, conn) != 0)
1416  return EOF;
1417  their_version = tmp;
1418 
1419  if (pqGetInt(&num, 4, conn) != 0)
1420  return EOF;
1421 
1422  initPQExpBuffer(&buf);
1423  for (int i = 0; i < num; i++)
1424  {
1425  if (pqGets(&conn->workBuffer, conn))
1426  {
1427  termPQExpBuffer(&buf);
1428  return EOF;
1429  }
1430  if (buf.len > 0)
1431  appendPQExpBufferChar(&buf, ' ');
1433  }
1434 
1435  if (their_version < conn->pversion)
1436  libpq_append_conn_error(conn, "protocol version not supported by server: client uses %u.%u, server supports up to %u.%u",
1438  PG_PROTOCOL_MAJOR(their_version), PG_PROTOCOL_MINOR(their_version));
1439  if (num > 0)
1440  {
1442  libpq_ngettext("protocol extension not supported by server: %s",
1443  "protocol extensions not supported by server: %s", num),
1444  buf.data);
1446  }
1447 
1448  /* neither -- server shouldn't have sent it */
1449  if (!(their_version < conn->pversion) && !(num > 0))
1450  libpq_append_conn_error(conn, "invalid %s message", "NegotiateProtocolVersion");
1451 
1452  termPQExpBuffer(&buf);
1453  return 0;
1454 }
#define libpq_ngettext(s, p, n)
Definition: libpq-int.h:907
#define PG_PROTOCOL_MAJOR(v)
Definition: pqcomm.h:87
uint32 ProtocolVersion
Definition: pqcomm.h:100
#define PG_PROTOCOL_MINOR(v)
Definition: pqcomm.h:88
ProtocolVersion pversion
Definition: libpq-int.h:489
PQExpBufferData workBuffer
Definition: libpq-int.h:647

References appendPQExpBuffer(), appendPQExpBufferChar(), appendPQExpBufferStr(), buf, conn, PQExpBufferData::data, pg_conn::errorMessage, i, initPQExpBuffer(), libpq_append_conn_error(), libpq_ngettext, PG_PROTOCOL_MAJOR, PG_PROTOCOL_MINOR, pqGetInt(), pqGets(), pg_conn::pversion, termPQExpBuffer(), and pg_conn::workBuffer.

Referenced by PQconnectPoll().

◆ pqGets()

int pqGets ( PQExpBuffer  buf,
PGconn conn 
)

Definition at line 136 of file fe-misc.c.

137 {
138  return pqGets_internal(buf, conn, true);
139 }
static int pqGets_internal(PQExpBuffer buf, PGconn *conn, bool resetbuffer)
Definition: fe-misc.c:109

References buf, conn, and pqGets_internal().

Referenced by getNotify(), getParameterStatus(), getRowDescriptions(), pg_SASL_init(), pqGetErrorNotice3(), pqGetNegotiateProtocolVersion3(), and pqParseInput3().

◆ pqGets_append()

int pqGets_append ( PQExpBuffer  buf,
PGconn conn 
)

Definition at line 142 of file fe-misc.c.

143 {
144  return pqGets_internal(buf, conn, false);
145 }

References buf, conn, and pqGets_internal().

Referenced by PQconnectPoll().

◆ pqInternalNotice()

void pqInternalNotice ( const PGNoticeHooks hooks,
const char *  fmt,
  ... 
)

◆ pqMakeEmptyPGconn()

PGconn* pqMakeEmptyPGconn ( void  )

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

4551 {
4552  PGconn *conn;
4553 
4554 #ifdef WIN32
4555 
4556  /*
4557  * Make sure socket support is up and running in this process.
4558  *
4559  * Note: the Windows documentation says that we should eventually do a
4560  * matching WSACleanup() call, but experience suggests that that is at
4561  * least as likely to cause problems as fix them. So we don't.
4562  */
4563  static bool wsastartup_done = false;
4564 
4565  if (!wsastartup_done)
4566  {
4567  WSADATA wsaData;
4568 
4569  if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
4570  return NULL;
4571  wsastartup_done = true;
4572  }
4573 
4574  /* Forget any earlier error */
4575  WSASetLastError(0);
4576 #endif /* WIN32 */
4577 
4578  conn = (PGconn *) malloc(sizeof(PGconn));
4579  if (conn == NULL)
4580  return conn;
4581 
4582  /* Zero all pointers and booleans */
4583  MemSet(conn, 0, sizeof(PGconn));
4584 
4585  /* install default notice hooks */
4588 
4593  conn->options_valid = false;
4594  conn->nonblocking = false;
4596  conn->std_strings = false; /* unless server says differently */
4603  conn->Pfdebug = NULL;
4604 
4605  /*
4606  * We try to send at least 8K at a time, which is the usual size of pipe
4607  * buffers on Unix systems. That way, when we are sending a large amount
4608  * of data, we avoid incurring extra kernel context swaps for partial
4609  * bufferloads. The output buffer is initially made 16K in size, and we
4610  * try to dump it after accumulating 8K.
4611  *
4612  * With the same goal of minimizing context swaps, the input buffer will
4613  * be enlarged anytime it has less than 8K free, so we initially allocate
4614  * twice that.
4615  */
4616  conn->inBufSize = 16 * 1024;
4617  conn->inBuffer = (char *) malloc(conn->inBufSize);
4618  conn->outBufSize = 16 * 1024;
4619  conn->outBuffer = (char *) malloc(conn->outBufSize);
4620  conn->rowBufLen = 32;
4621  conn->rowBuf = (PGdataValue *) malloc(conn->rowBufLen * sizeof(PGdataValue));
4624 
4625  if (conn->inBuffer == NULL ||
4626  conn->outBuffer == NULL ||
4627  conn->rowBuf == NULL ||
4630  {
4631  /* out of memory already :-( */
4632  freePGconn(conn);
4633  conn = NULL;
4634  }
4635 
4636  return conn;
4637 }
#define MemSet(start, val, len)
Definition: c.h:1011
static void defaultNoticeReceiver(void *arg, const PGresult *res)
Definition: fe-connect.c:7414
static void defaultNoticeProcessor(void *arg, const char *message)
Definition: fe-connect.c:7429
static void freePGconn(PGconn *conn)
Definition: fe-connect.c:4649
@ PQERRORS_DEFAULT
Definition: libpq-fe.h:152
@ PG_SQL_ASCII
Definition: pg_wchar.h:226
#define PQExpBufferBroken(str)
Definition: pqexpbuffer.h:59
#define SCRAM_SHA_256_DEFAULT_ITERATIONS
Definition: scram-common.h:50
PQnoticeProcessor noticeProc
Definition: libpq-int.h:157
PGdataValue * rowBuf
Definition: libpq-int.h:553
bool std_strings
Definition: libpq-int.h:526
PGTernaryBool in_hot_standby
Definition: libpq-int.h:528
int client_encoding
Definition: libpq-int.h:525
PGTernaryBool default_transaction_read_only
Definition: libpq-int.h:527
int rowBufLen
Definition: libpq-int.h:554
int scram_sha_256_iterations
Definition: libpq-int.h:573

References pg_conn::asyncStatus, pg_conn::client_encoding, conn, CONNECTION_BAD, pg_conn::default_transaction_read_only, defaultNoticeProcessor(), defaultNoticeReceiver(), pg_conn::errorMessage, freePGconn(), pg_conn::in_hot_standby, 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::Pfdebug, PG_BOOL_UNKNOWN, PG_SQL_ASCII, PGASYNC_IDLE, PGINVALID_SOCKET, pg_conn::pipelineStatus, PQ_PIPELINE_OFF, PQERRORS_DEFAULT, PQExpBufferBroken, PQSHOW_CONTEXT_ERRORS, PQTRANS_IDLE, pg_conn::rowBuf, pg_conn::rowBufLen, SCRAM_SHA_256_DEFAULT_ITERATIONS, pg_conn::scram_sha_256_iterations, pg_conn::show_context, pg_conn::sock, pg_conn::status, pg_conn::std_strings, pg_conn::verbosity, pg_conn::workBuffer, and pg_conn::xactStatus.

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

◆ pqPacketSend()

int pqPacketSend ( PGconn conn,
char  pack_type,
const void *  buf,
size_t  buf_len 
)

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

5003 {
5004  /* Start the message. */
5005  if (pqPutMsgStart(pack_type, conn))
5006  return STATUS_ERROR;
5007 
5008  /* Send the message body. */
5009  if (pqPutnchar(buf, buf_len, conn))
5010  return STATUS_ERROR;
5011 
5012  /* Finish the message. */
5013  if (pqPutMsgEnd(conn))
5014  return STATUS_ERROR;
5015 
5016  /* Flush to ensure backend gets it. */
5017  if (pqFlush(conn))
5018  return STATUS_ERROR;
5019 
5020  return STATUS_OK;
5021 }
#define STATUS_OK
Definition: c.h:1160
#define STATUS_ERROR
Definition: c.h:1161

References buf, conn, pqFlush(), pqPutMsgEnd(), pqPutMsgStart(), pqPutnchar(), STATUS_ERROR, and STATUS_OK.

Referenced by pg_password_sendauth(), pg_SASL_continue(), and PQconnectPoll().

◆ pqParseDone()

void pqParseDone ( PGconn conn,
int  newInStart 
)

Definition at line 443 of file fe-misc.c.

444 {
445  /* trace server-to-client message */
446  if (conn->Pfdebug)
448 
449  /* Mark message as done */
450  conn->inStart = newInStart;
451 }
void pqTraceOutputMessage(PGconn *conn, const char *message, bool toServer)
Definition: fe-trace.c:618

References conn, pg_conn::inBuffer, pg_conn::inStart, pg_conn::Pfdebug, and pqTraceOutputMessage().

Referenced by getCopyDataMessage(), PQconnectPoll(), pqFunctionCall3(), pqGetCopyData3(), and pqParseInput3().

◆ pqParseInput3()

void pqParseInput3 ( PGconn conn)

Definition at line 66 of file fe-protocol3.c.

67 {
68  char id;
69  int msgLength;
70  int avail;
71 
72  /*
73  * Loop to parse successive complete messages available in the buffer.
74  */
75  for (;;)
76  {
77  /*
78  * Try to read a message. First get the type code and length. Return
79  * if not enough data.
80  */
82  if (pqGetc(&id, conn))
83  return;
84  if (pqGetInt(&msgLength, 4, conn))
85  return;
86 
87  /*
88  * Try to validate message type/length here. A length less than 4 is
89  * definitely broken. Large lengths should only be believed for a few
90  * message types.
91  */
92  if (msgLength < 4)
93  {
94  handleSyncLoss(conn, id, msgLength);
95  return;
96  }
97  if (msgLength > 30000 && !VALID_LONG_MESSAGE_TYPE(id))
98  {
99  handleSyncLoss(conn, id, msgLength);
100  return;
101  }
102 
103  /*
104  * Can't process if message body isn't all here yet.
105  */
106  msgLength -= 4;
107  avail = conn->inEnd - conn->inCursor;
108  if (avail < msgLength)
109  {
110  /*
111  * Before returning, enlarge the input buffer if needed to hold
112  * the whole message. This is better than leaving it to
113  * pqReadData because we can avoid multiple cycles of realloc()
114  * when the message is large; also, we can implement a reasonable
115  * recovery strategy if we are unable to make the buffer big
116  * enough.
117  */
118  if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength,
119  conn))
120  {
121  /*
122  * XXX add some better recovery code... plan is to skip over
123  * the message using its length, then report an error. For the
124  * moment, just treat this like loss of sync (which indeed it
125  * might be!)
126  */
127  handleSyncLoss(conn, id, msgLength);
128  }
129  return;
130  }
131 
132  /*
133  * NOTIFY and NOTICE messages can happen in any state; always process
134  * them right away.
135  *
136  * Most other messages should only be processed while in BUSY state.
137  * (In particular, in READY state we hold off further parsing until
138  * the application collects the current PGresult.)
139  *
140  * However, if the state is IDLE then we got trouble; we need to deal
141  * with the unexpected message somehow.
142  *
143  * ParameterStatus ('S') messages are a special case: in IDLE state we
144  * must process 'em (this case could happen if a new value was adopted
145  * from config file due to SIGHUP), but otherwise we hold off until
146  * BUSY state.
147  */
148  if (id == PqMsg_NotificationResponse)
149  {
150  if (getNotify(conn))
151  return;
152  }
153  else if (id == PqMsg_NoticeResponse)
154  {
155  if (pqGetErrorNotice3(conn, false))
156  return;
157  }
158  else if (conn->asyncStatus != PGASYNC_BUSY)
159  {
160  /* If not IDLE state, just wait ... */
161  if (conn->asyncStatus != PGASYNC_IDLE)
162  return;
163 
164  /*
165  * Unexpected message in IDLE state; need to recover somehow.
166  * ERROR messages are handled using the notice processor;
167  * ParameterStatus is handled normally; anything else is just
168  * dropped on the floor after displaying a suitable warning
169  * notice. (An ERROR is very possibly the backend telling us why
170  * it is about to close the connection, so we don't want to just
171  * discard it...)
172  */
173  if (id == PqMsg_ErrorResponse)
174  {
175  if (pqGetErrorNotice3(conn, false /* treat as notice */ ))
176  return;
177  }
178  else if (id == PqMsg_ParameterStatus)
179  {
181  return;
182  }
183  else
184  {
185  /* Any other case is unexpected and we summarily skip it */
187  "message type 0x%02x arrived from server while idle",
188  id);
189  /* Discard the unexpected message */
190  conn->inCursor += msgLength;
191  }
192  }
193  else
194  {
195  /*
196  * In BUSY state, we can process everything.
197  */
198  switch (id)
199  {
201  if (pqGets(&conn->workBuffer, conn))
202  return;
204  {
207  if (!conn->result)
208  {
209  libpq_append_conn_error(conn, "out of memory");
211  }
212  }
213  if (conn->result)
215  CMDSTATUS_LEN);
217  break;
218  case PqMsg_ErrorResponse:
219  if (pqGetErrorNotice3(conn, true))
220  return;
222  break;
223  case PqMsg_ReadyForQuery:
224  if (getReadyForQuery(conn))
225  return;
227  {
230  if (!conn->result)
231  {
232  libpq_append_conn_error(conn, "out of memory");
234  }
235  else
236  {
239  }
240  }
241  else
242  {
243  /* Advance the command queue and set us idle */
244  pqCommandQueueAdvance(conn, true, false);
246  }
247  break;
250  {
253  if (!conn->result)
254  {
255  libpq_append_conn_error(conn, "out of memory");
257  }
258  }
260  break;
261  case PqMsg_ParseComplete:
262  /* If we're doing PQprepare, we're done; else ignore */
263  if (conn->cmd_queue_head &&
265  {
267  {
270  if (!conn->result)
271  {
272  libpq_append_conn_error(conn, "out of memory");
274  }
275  }
277  }
278  break;
279  case PqMsg_BindComplete:
280  /* Nothing to do for this message type */
281  break;
282  case PqMsg_CloseComplete:
283  /* If we're doing PQsendClose, we're done; else ignore */
284  if (conn->cmd_queue_head &&
286  {
288  {
291  if (!conn->result)
292  {
293  libpq_append_conn_error(conn, "out of memory");
295  }
296  }
298  }
299  break;
302  return;
303  break;
305 
306  /*
307  * This is expected only during backend startup, but it's
308  * just as easy to handle it as part of the main loop.
309  * Save the data and continue processing.
310  */
311  if (pqGetInt(&(conn->be_pid), 4, conn))
312  return;
313  if (pqGetInt(&(conn->be_key), 4, conn))
314  return;
315  break;
317  if (conn->error_result ||
318  (conn->result != NULL &&
320  {
321  /*
322  * We've already choked for some reason. Just discard
323  * the data till we get to the end of the query.
324  */
325  conn->inCursor += msgLength;
326  }
327  else if (conn->result == NULL ||
328  (conn->cmd_queue_head &&
330  {
331  /* First 'T' in a query sequence */
332  if (getRowDescriptions(conn, msgLength))
333  return;
334  }
335  else
336  {
337  /*
338  * A new 'T' message is treated as the start of
339  * another PGresult. (It is not clear that this is
340  * really possible with the current backend.) We stop
341  * parsing until the application accepts the current
342  * result.
343  */
345  return;
346  }
347  break;
348  case PqMsg_NoData:
349 
350  /*
351  * NoData indicates that we will not be seeing a
352  * RowDescription message because the statement or portal
353  * inquired about doesn't return rows.
354  *
355  * If we're doing a Describe, we have to pass something
356  * back to the client, so set up a COMMAND_OK result,
357  * instead of PGRES_TUPLES_OK. Otherwise we can just
358  * ignore this message.
359  */
360  if (conn->cmd_queue_head &&
362  {
364  {
367  if (!conn->result)
368  {
369  libpq_append_conn_error(conn, "out of memory");
371  }
372  }
374  }
375  break;
377  if (getParamDescriptions(conn, msgLength))
378  return;
379  break;
380  case PqMsg_DataRow:
381  if (conn->result != NULL &&
384  {
385  /* Read another tuple of a normal query response */
386  if (getAnotherTuple(conn, msgLength))
387  return;
388  }
389  else if (conn->error_result ||
390  (conn->result != NULL &&
392  {
393  /*
394  * We've already choked for some reason. Just discard
395  * tuples till we get to the end of the query.
396  */
397  conn->inCursor += msgLength;
398  }
399  else
400  {
401  /* Set up to report error at end of query */
402  libpq_append_conn_error(conn, "server sent data (\"D\" message) without prior row description (\"T\" message)");
404  /* Discard the unexpected message */
405  conn->inCursor += msgLength;
406  }
407  break;
410  return;
412  break;
415  return;
417  conn->copy_already_done = 0;
418  break;
421  return;
423  conn->copy_already_done = 0;
424  break;
425  case PqMsg_CopyData:
426 
427  /*
428  * If we see Copy Data, just silently drop it. This would
429  * only occur if application exits COPY OUT mode too
430  * early.
431  */
432  conn->inCursor += msgLength;
433  break;
434  case PqMsg_CopyDone:
435 
436  /*
437  * If we see Copy Done, just silently drop it. This is
438  * the normal case during PQendcopy. We will keep
439  * swallowing data, expecting to see command-complete for
440  * the COPY command.
441  */
442  break;
443  default:
444  libpq_append_conn_error(conn, "unexpected response from server; first received character was \"%c\"", id);
445  /* build an error result holding the error message */
447  /* not sure if we will see more, so go to ready state */
449  /* Discard the unexpected message */
450  conn->inCursor += msgLength;
451  break;
452  } /* switch on protocol character */
453  }
454  /* Successfully consumed this message */
455  if (conn->inCursor == conn->inStart + 5 + msgLength)
456  {
457  /* Normal case: parsing agrees with specified length */
459  }
460  else
461  {
462  /* Trouble --- report it */
463  libpq_append_conn_error(conn, "message contents do not agree with length in message type \"%c\"", id);
464  /* build an error result holding the error message */
467  /* trust the specified message length as what to skip */
468  conn->inStart += 5 + msgLength;
469  }
470  }
471 }
void pqCommandQueueAdvance(PGconn *conn, bool isReadyForQuery, bool gotSync)
Definition: fe-exec.c:3142
static int getAnotherTuple(PGconn *conn, int msgLength)
Definition: fe-protocol3.c:758
static int getRowDescriptions(PGconn *conn, int msgLength)
Definition: fe-protocol3.c:499
static int getCopyStart(PGconn *conn, ExecStatusType copytype)
static int getParamDescriptions(PGconn *conn, int msgLength)
Definition: fe-protocol3.c:670
@ PGRES_COPY_IN
Definition: libpq-fe.h:127
@ PGRES_COPY_BOTH
Definition: libpq-fe.h:132
@ PGRES_TUPLES_CHUNK
Definition: libpq-fe.h:137
@ PGRES_COPY_OUT
Definition: libpq-fe.h:126
@ PGRES_PIPELINE_SYNC
Definition: libpq-fe.h:134
@ PGRES_TUPLES_OK
Definition: libpq-fe.h:123
@ PQ_PIPELINE_ON
Definition: libpq-fe.h:183
#define CMDSTATUS_LEN
Definition: libpq-int.h:89
#define PqMsg_CloseComplete
Definition: protocol.h:40
#define PqMsg_NotificationResponse
Definition: protocol.h:41
#define PqMsg_BindComplete
Definition: protocol.h:39
#define PqMsg_CopyData
Definition: protocol.h:65
#define PqMsg_ParameterDescription
Definition: protocol.h:58
#define PqMsg_ReadyForQuery
Definition: protocol.h:55
#define PqMsg_CopyInResponse
Definition: protocol.h:45
#define PqMsg_EmptyQueryResponse
Definition: protocol.h:47
#define PqMsg_RowDescription
Definition: protocol.h:52
#define PqMsg_CopyBothResponse
Definition: protocol.h:54
#define PqMsg_ParameterStatus
Definition: protocol.h:51
#define PqMsg_NoData
Definition: protocol.h:56
#define PqMsg_BackendKeyData
Definition: protocol.h:48
#define PqMsg_CommandComplete
Definition: protocol.h:42
#define PqMsg_ErrorResponse
Definition: protocol.h:44
#define PqMsg_DataRow
Definition: protocol.h:43
#define PqMsg_NoticeResponse
Definition: protocol.h:49
#define PqMsg_CopyOutResponse
Definition: protocol.h:46
#define PqMsg_ParseComplete
Definition: protocol.h:38
int be_pid
Definition: libpq-int.h:522
int be_key
Definition: libpq-int.h:523
char cmdStatus[CMDSTATUS_LEN]
Definition: libpq-int.h:181

References pg_conn::asyncStatus, pg_conn::be_key, pg_conn::be_pid, pg_conn::cmd_queue_head, pg_result::cmdStatus, CMDSTATUS_LEN, conn, pg_conn::copy_already_done, PQExpBufferData::data, pg_conn::error_result, getAnotherTuple(), getCopyStart(), getNotify(), getParamDescriptions(), getParameterStatus(), getReadyForQuery(), getRowDescriptions(), handleSyncLoss(), pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, libpq_append_conn_error(), pg_conn::noticeHooks, PGASYNC_BUSY, PGASYNC_COPY_BOTH, PGASYNC_COPY_IN, PGASYNC_COPY_OUT, PGASYNC_IDLE, PGASYNC_READY, pgHavePendingResult, PGQUERY_CLOSE, PGQUERY_DESCRIBE, PGQUERY_PREPARE, PGRES_COMMAND_OK, PGRES_COPY_BOTH, PGRES_COPY_IN, PGRES_COPY_OUT, PGRES_EMPTY_QUERY, PGRES_FATAL_ERROR, PGRES_PIPELINE_SYNC, PGRES_TUPLES_CHUNK, PGRES_TUPLES_OK, pg_conn::pipelineStatus, PQ_PIPELINE_OFF, PQ_PIPELINE_ON, pqCheckInBufferSpace(), pqCommandQueueAdvance(), pqGetc(), pqGetErrorNotice3(), pqGetInt(), pqGets(), pqInternalNotice(), PQmakeEmptyPGresult(), PqMsg_BackendKeyData, PqMsg_BindComplete, PqMsg_CloseComplete, PqMsg_CommandComplete, PqMsg_CopyBothResponse, PqMsg_CopyData, PqMsg_CopyDone, PqMsg_CopyInResponse, PqMsg_CopyOutResponse, PqMsg_DataRow, PqMsg_EmptyQueryResponse, PqMsg_ErrorResponse, PqMsg_NoData, PqMsg_NoticeResponse, PqMsg_NotificationResponse, PqMsg_ParameterDescription, PqMsg_ParameterStatus, PqMsg_ParseComplete, PqMsg_ReadyForQuery, PqMsg_RowDescription, pqParseDone(), pqSaveErrorResult(), PGcmdQueueEntry::queryclass, pg_conn::result, pg_result::resultStatus, strlcpy(), VALID_LONG_MESSAGE_TYPE, and pg_conn::workBuffer.

Referenced by parseInput().

◆ pqParseIntParam()

bool pqParseIntParam ( const char *  value,
int *  result,
PGconn conn,
const char *  context 
)

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

7770 {
7771  char *end;
7772  long numval;
7773 
7774  Assert(value != NULL);
7775 
7776  *result = 0;
7777 
7778  /* strtol(3) skips leading whitespaces */
7779  errno = 0;
7780  numval = strtol(value, &end, 10);
7781 
7782  /*
7783  * If no progress was done during the parsing or an error happened, fail.
7784  * This tests properly for overflows of the result.
7785  */
7786  if (value == end || errno != 0 || numval != (int) numval)
7787  goto error;
7788 
7789  /*
7790  * Skip any trailing whitespace; if anything but whitespace remains before
7791  * the terminating character, fail
7792  */
7793  while (*end != '\0' && isspace((unsigned char) *end))
7794  end++;
7795 
7796  if (*end != '\0')
7797  goto error;
7798 
7799  *result = numval;
7800  return true;
7801 
7802 error:
7803  libpq_append_conn_error(conn, "invalid integer value \"%s\" for connection option \"%s\"",
7804  value, context);
7805  return false;
7806 }
static struct @157 value
tree context
Definition: radixtree.h:1835
static void error(void)
Definition: sql-dyntest.c:147

References Assert, conn, context, error(), libpq_append_conn_error(), and value.

Referenced by pqConnectDBComplete(), PQconnectPoll(), PQgetCancel(), setKeepalivesCount(), setKeepalivesIdle(), setKeepalivesInterval(), setTCPUserTimeout(), and useKeepalives().

◆ pqPrepareAsyncResult()

PGresult* pqPrepareAsyncResult ( PGconn conn)

Definition at line 851 of file fe-exec.c.

852 {
853  PGresult *res;
854 
855  res = conn->result;
856  if (res)
857  {
858  /*
859  * If the pre-existing result is an ERROR (presumably something
860  * received from the server), assume that it represents whatever is in
861  * conn->errorMessage, and advance errorReported.
862  */
865  }
866  else
867  {
868  /*
869  * We get here after internal-to-libpq errors. We should probably
870  * always have error_result = true, but if we don't, gin up some error
871  * text.
872  */
873  if (!conn->error_result)
874  libpq_append_conn_error(conn, "no error text available");
875 
876  /* Paranoia: be sure errorReported offset is sane */
877  if (conn->errorReported < 0 ||
879  conn->errorReported = 0;
880 
881  /*
882  * Make a PGresult struct for the error. We temporarily lie about the
883  * result status, so that PQmakeEmptyPGresult doesn't uselessly copy
884  * all of conn->errorMessage.
885  */
887  if (res)
888  {
889  /*
890  * Report whatever new error text we have, and advance
891  * errorReported.
892  */
896  }
897  else
898  {
899  /*
900  * Ouch, not enough memory for a PGresult. Fortunately, we have a
901  * card up our sleeve: we can use the static OOM_result. Casting
902  * away const here is a bit ugly, but it seems best to declare
903  * OOM_result as const, in hopes it will be allocated in read-only
904  * storage.
905  */
907 
908  /*
909  * Don't advance errorReported. Perhaps we'll be able to report
910  * the text later.
911  */
912  }
913  }
914 
915  /*
916  * Replace conn->result with saved_result, if any. In the normal case
917  * there isn't a saved result and we're just dropping ownership of the
918  * current result. In partial-result mode this restores the situation to
919  * what it was before we created the current partial result.
920  */
922  conn->error_result = false; /* saved_result is never an error */
923  conn->saved_result = NULL;
924 
925  return res;
926 }
#define unconstify(underlying_type, expr)
Definition: c.h:1236
static const PGresult OOM_result
Definition: fe-exec.c:49
int errorReported
Definition: libpq-int.h:644

References conn, pg_conn::error_result, pg_conn::errorMessage, pg_conn::errorReported, PQExpBufferData::len, libpq_append_conn_error(), OOM_result, PGRES_EMPTY_QUERY, PGRES_FATAL_ERROR, PQmakeEmptyPGresult(), pqSetResultError(), res, pg_conn::result, pg_result::resultStatus, pg_conn::saved_result, and unconstify.

Referenced by getCopyResult(), pqFunctionCall3(), and PQgetResult().

◆ pqPutc()

int pqPutc ( char  c,
PGconn conn 
)

Definition at line 92 of file fe-misc.c.

93 {
94  if (pqPutMsgBytes(&c, 1, conn))
95  return EOF;
96 
97  return 0;
98 }
static int pqPutMsgBytes(const void *buf, size_t len, PGconn *conn)
Definition: fe-misc.c:509
char * c

References conn, and pqPutMsgBytes().

Referenced by PQsendQueryGuts(), and PQsendTypedCommand().

◆ pqPutInt()

int pqPutInt ( int  value,
size_t  bytes,
PGconn conn 
)

Definition at line 253 of file fe-misc.c.

254 {
255  uint16 tmp2;
256  uint32 tmp4;
257 
258  switch (bytes)
259  {
260  case 2:
261  tmp2 = pg_hton16((uint16) value);
262  if (pqPutMsgBytes((const char *) &tmp2, 2, conn))
263  return EOF;
264  break;
265  case 4:
266  tmp4 = pg_hton32((uint32) value);
267  if (pqPutMsgBytes((const char *) &tmp4, 4, conn))
268  return EOF;
269  break;
270  default:
272  "integer of size %lu not supported by pqPutInt",
273  (unsigned long) bytes);
274  return EOF;
275  }
276 
277  return 0;
278 }
#define pg_hton32(x)
Definition: pg_bswap.h:121
#define pg_hton16(x)
Definition: pg_bswap.h:120

References conn, pg_conn::noticeHooks, pg_hton16, pg_hton32, pqInternalNotice(), pqPutMsgBytes(), and value.

Referenced by pg_SASL_init(), pqFunctionCall3(), PQsendPrepare(), and PQsendQueryGuts().

◆ pqPutMsgEnd()

int pqPutMsgEnd ( PGconn conn)

Definition at line 532 of file fe-misc.c.

533 {
534  /* Fill in length word if needed */
535  if (conn->outMsgStart >= 0)
536  {
537  uint32 msgLen = conn->outMsgEnd - conn->outMsgStart;
538 
539  msgLen = pg_hton32(msgLen);
540  memcpy(conn->outBuffer + conn->outMsgStart, &msgLen, 4);
541  }
542 
543  /* trace client-to-server message */
544  if (conn->Pfdebug)
545  {
546  if (conn->outCount < conn->outMsgStart)
548  else
551  }
552 
553  /* Make message eligible to send */
555 
556  if (conn->outCount >= 8192)
557  {
558  int toSend = conn->outCount - (conn->outCount % 8192);
559 
560  if (pqSendSome(conn, toSend) < 0)
561  return EOF;
562  /* in nonblock mode, don't complain if unable to send it all */
563  }
564 
565  return 0;
566 }
void pqTraceOutputNoTypeByteMessage(PGconn *conn, const char *message)
Definition: fe-trace.c:835
int outMsgStart
Definition: libpq-int.h:548
int outMsgEnd
Definition: libpq-int.h:550

References conn, pg_conn::outBuffer, pg_conn::outCount, pg_conn::outMsgEnd, pg_conn::outMsgStart, pg_conn::Pfdebug, pg_hton32, pqSendSome(), pqTraceOutputMessage(), and pqTraceOutputNoTypeByteMessage().

Referenced by pg_SASL_init(), pqEndcopy3(), pqFunctionCall3(), pqPacketSend(), pqPipelineSyncInternal(), PQputCopyData(), PQputCopyEnd(), PQsendFlushRequest(), PQsendPrepare(), PQsendQueryGuts(), PQsendQueryInternal(), PQsendTypedCommand(), and sendTerminateConn().

◆ pqPutMsgStart()

int pqPutMsgStart ( char  msg_type,
PGconn conn 
)

Definition at line 473 of file fe-misc.c.

474 {
475  int lenPos;
476  int endPos;
477 
478  /* allow room for message type byte */
479  if (msg_type)
480  endPos = conn->outCount + 1;
481  else
482  endPos = conn->outCount;
483 
484  /* do we want a length word? */
485  lenPos = endPos;
486  /* allow room for message length */
487  endPos += 4;
488 
489  /* make sure there is room for message header */
490  if (pqCheckOutBufferSpace(endPos, conn))
491  return EOF;
492  /* okay, save the message type byte if any */
493  if (msg_type)
494  conn->outBuffer[conn->outCount] = msg_type;
495  /* set up the message pointers */
496  conn->outMsgStart = lenPos;
497  conn->outMsgEnd = endPos;
498  /* length word, if needed, will be filled in by pqPutMsgEnd */
499 
500  return 0;
501 }
int pqCheckOutBufferSpace(size_t bytes_needed, PGconn *conn)
Definition: fe-misc.c:287

References conn, pg_conn::outBuffer, pg_conn::outCount, pg_conn::outMsgEnd, pg_conn::outMsgStart, and pqCheckOutBufferSpace().

Referenced by pg_SASL_init(), pqEndcopy3(), pqFunctionCall3(), pqPacketSend(), pqPipelineSyncInternal(), PQputCopyData(), PQputCopyEnd(), PQsendFlushRequest(), PQsendPrepare(), PQsendQueryGuts(), PQsendQueryInternal(), PQsendTypedCommand(), and sendTerminateConn().

◆ pqPutnchar()

int pqPutnchar ( const char *  s,
size_t  len,
PGconn conn 
)

Definition at line 202 of file fe-misc.c.

203 {
204  if (pqPutMsgBytes(s, len, conn))
205  return EOF;
206 
207  return 0;
208 }

References conn, len, and pqPutMsgBytes().

Referenced by pg_SASL_init(), pqFunctionCall3(), pqPacketSend(), PQputCopyData(), and PQsendQueryGuts().

◆ pqPuts()

int pqPuts ( const char *  s,
PGconn conn 
)

Definition at line 152 of file fe-misc.c.

153 {
154  if (pqPutMsgBytes(s, strlen(s) + 1, conn))
155  return EOF;
156 
157  return 0;
158 }

References conn, and pqPutMsgBytes().

Referenced by pg_SASL_init(), PQputCopyEnd(), PQsendPrepare(), PQsendQueryGuts(), PQsendQueryInternal(), and PQsendTypedCommand().

◆ pqReadData()

int pqReadData ( PGconn conn)

Definition at line 580 of file fe-misc.c.

581 {
582  int someread = 0;
583  int nread;
584 
585  if (conn->sock == PGINVALID_SOCKET)
586  {
587  libpq_append_conn_error(conn, "connection not open");
588  return -1;
589  }
590 
591  /* Left-justify any data in the buffer to make room */
592  if (conn->inStart < conn->inEnd)
593  {
594  if (conn->inStart > 0)
595  {
596  memmove(conn->inBuffer, conn->inBuffer + conn->inStart,
597  conn->inEnd - conn->inStart);
598  conn->inEnd -= conn->inStart;
599  conn->inCursor -= conn->inStart;
600  conn->inStart = 0;
601  }
602  }
603  else
604  {
605  /* buffer is logically empty, reset it */
606  conn->inStart = conn->inCursor = conn->inEnd = 0;
607  }
608 
609  /*
610  * If the buffer is fairly full, enlarge it. We need to be able to enlarge
611  * the buffer in case a single message exceeds the initial buffer size. We
612  * enlarge before filling the buffer entirely so as to avoid asking the
613  * kernel for a partial packet. The magic constant here should be large
614  * enough for a TCP packet or Unix pipe bufferload. 8K is the usual pipe
615  * buffer size, so...
616  */
617  if (conn->inBufSize - conn->inEnd < 8192)
618  {
619  if (pqCheckInBufferSpace(conn->inEnd + (size_t) 8192, conn))
620  {
621  /*
622  * We don't insist that the enlarge worked, but we need some room
623  */
624  if (conn->inBufSize - conn->inEnd < 100)
625  return -1; /* errorMessage already set */
626  }
627  }
628 
629  /* OK, try to read some data */
630 retry3:
631  nread = pqsecure_read(conn, conn->inBuffer + conn->inEnd,
632  conn->inBufSize - conn->inEnd);
633  if (nread < 0)
634  {
635  switch (SOCK_ERRNO)
636  {
637  case EINTR:
638  goto retry3;
639 
640  /* Some systems return EAGAIN/EWOULDBLOCK for no data */
641 #ifdef EAGAIN
642  case EAGAIN:
643  return someread;
644 #endif
645 #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
646  case EWOULDBLOCK:
647  return someread;
648 #endif
649 
650  /* We might get ECONNRESET etc here if connection failed */
652  goto definitelyFailed;
653 
654  default:
655  /* pqsecure_read set the error message for us */
656  return -1;
657  }
658  }
659  if (nread > 0)
660  {
661  conn->inEnd += nread;
662 
663  /*
664  * Hack to deal with the fact that some kernels will only give us back
665  * 1 packet per recv() call, even if we asked for more and there is
666  * more available. If it looks like we are reading a long message,
667  * loop back to recv() again immediately, until we run out of data or
668  * buffer space. Without this, the block-and-restart behavior of
669  * libpq's higher levels leads to O(N^2) performance on long messages.
670  *
671  * Since we left-justified the data above, conn->inEnd gives the
672  * amount of data already read in the current message. We consider
673  * the message "long" once we have acquired 32k ...
674  */
675  if (conn->inEnd > 32768 &&
676  (conn->inBufSize - conn->inEnd) >= 8192)
677  {
678  someread = 1;
679  goto retry3;
680  }
681  return 1;
682  }
683 
684  if (someread)
685  return 1; /* got a zero read after successful tries */
686 
687  /*
688  * A return value of 0 could mean just that no data is now available, or
689  * it could mean EOF --- that is, the server has closed the connection.
690  * Since we have the socket in nonblock mode, the only way to tell the
691  * difference is to see if select() is saying that the file is ready.
692  * Grumble. Fortunately, we don't expect this path to be taken much,
693  * since in normal practice we should not be trying to read data unless
694  * the file selected for reading already.
695  *
696  * In SSL mode it's even worse: SSL_read() could say WANT_READ and then
697  * data could arrive before we make the pqReadReady() test, but the second
698  * SSL_read() could still say WANT_READ because the data received was not
699  * a complete SSL record. So we must play dumb and assume there is more
700  * data, relying on the SSL layer to detect true EOF.
701  */
702 
703 #ifdef USE_SSL
704  if (conn->ssl_in_use)
705  return 0;
706 #endif
707 
708  switch (pqReadReady(conn))
709  {
710  case 0:
711  /* definitely no data available */
712  return 0;
713  case 1:
714  /* ready for read */
715  break;
716  default:
717  /* we override pqReadReady's message with something more useful */
718  goto definitelyEOF;
719  }
720 
721  /*
722  * Still not sure that it's EOF, because some data could have just
723  * arrived.
724  */
725 retry4:
726  nread = pqsecure_read(conn, conn->inBuffer + conn->inEnd,
727  conn->inBufSize - conn->inEnd);
728  if (nread < 0)
729  {
730  switch (SOCK_ERRNO)
731  {
732  case EINTR:
733  goto retry4;
734 
735  /* Some systems return EAGAIN/EWOULDBLOCK for no data */
736 #ifdef EAGAIN
737  case EAGAIN:
738  return 0;
739 #endif
740 #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
741  case EWOULDBLOCK:
742  return 0;
743 #endif
744 
745  /* We might get ECONNRESET etc here if connection failed */
747  goto definitelyFailed;
748 
749  default:
750  /* pqsecure_read set the error message for us */
751  return -1;
752  }
753  }
754  if (nread > 0)
755  {
756  conn->inEnd += nread;
757  return 1;
758  }
759 
760  /*
761  * OK, we are getting a zero read even though select() says ready. This
762  * means the connection has been closed. Cope.
763  */
764 definitelyEOF:
765  libpq_append_conn_error(conn, "server closed the connection unexpectedly\n"
766  "\tThis probably means the server terminated abnormally\n"
767  "\tbefore or while processing the request.");
768 
769  /* Come here if lower-level code already set a suitable errorMessage */
770 definitelyFailed:
771  /* Do *not* drop any already-read data; caller still wants it */
772  pqDropConnection(conn, false);
773  conn->status = CONNECTION_BAD; /* No more connection to backend */
774  return -1;
775 }
int pqReadReady(PGconn *conn)
Definition: fe-misc.c:1032
ssize_t pqsecure_read(PGconn *conn, void *ptr, size_t len)
Definition: fe-secure.c:167
#define ALL_CONNECTION_FAILURE_ERRNOS
Definition: port.h:121
#define EINTR
Definition: win32_port.h:374
#define EWOULDBLOCK
Definition: win32_port.h:380
#define EAGAIN
Definition: win32_port.h:372

References ALL_CONNECTION_FAILURE_ERRNOS, conn, CONNECTION_BAD, EAGAIN, EINTR, EWOULDBLOCK, pg_conn::inBuffer, pg_conn::inBufSize, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, libpq_append_conn_error(), PGINVALID_SOCKET, pqCheckInBufferSpace(), pqDropConnection(), pqReadReady(), pqsecure_read(), pg_conn::sock, SOCK_ERRNO, pg_conn::ssl_in_use, and pg_conn::status.

Referenced by PQcancelPoll(), PQconnectPoll(), PQconsumeInput(), pqFunctionCall3(), pqGetCopyData3(), pqGetline3(), PQgetResult(), and pqSendSome().

◆ pqReadReady()

int pqReadReady ( PGconn conn)

Definition at line 1032 of file fe-misc.c.

1033 {
1034  return pqSocketCheck(conn, 1, 0, 0);
1035 }
static int pqSocketCheck(PGconn *conn, int forRead, int forWrite, pg_usec_time_t end_time)
Definition: fe-misc.c:1056

References conn, and pqSocketCheck().

Referenced by gss_read(), and pqReadData().

◆ pqReleaseConnHosts()

void pqReleaseConnHosts ( PGconn conn)

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

4732 {
4733  if (conn->connhost)
4734  {
4735  for (int i = 0; i < conn->nconnhost; ++i)
4736  {
4737  free(conn->connhost[i].host);
4739  free(conn->connhost[i].port);
4740  if (conn->connhost[i].password != NULL)
4741  {
4743  strlen(conn->connhost[i].password));
4745  }
4746  }
4747  free(conn->connhost);
4748  }
4749 }
void explicit_bzero(void *buf, size_t len)

References conn, pg_conn::connhost, explicit_bzero(), free, pg_conn_host::host, pg_conn_host::hostaddr, i, pg_conn::nconnhost, pg_conn_host::password, and pg_conn_host::port.

Referenced by freePGconn(), and PQcancelCreate().

◆ pqResultAlloc()

void* pqResultAlloc ( PGresult res,
size_t  nBytes,
bool  isBinary 
)

Definition at line 563 of file fe-exec.c.

564 {
565  char *space;
566  PGresult_data *block;
567 
568  if (!res)
569  return NULL;
570 
571  if (nBytes <= 0)
572  return res->null_field;
573 
574  /*
575  * If alignment is needed, round up the current position to an alignment
576  * boundary.
577  */
578  if (isBinary)
579  {
580  int offset = res->curOffset % PGRESULT_ALIGN_BOUNDARY;
581 
582  if (offset)
583  {
586  }
587  }
588 
589  /* If there's enough space in the current block, no problem. */
590  if (nBytes <= (size_t) res->spaceLeft)
591  {
592  space = res->curBlock->space + res->curOffset;
593  res->curOffset += nBytes;
594  res->spaceLeft -= nBytes;
595  return space;
596  }
597 
598  /*
599  * If the requested object is very large, give it its own block; this
600  * avoids wasting what might be most of the current block to start a new
601  * block. (We'd have to special-case requests bigger than the block size
602  * anyway.) The object is always given binary alignment in this case.
603  */
604  if (nBytes >= PGRESULT_SEP_ALLOC_THRESHOLD)
605  {
606  size_t alloc_size = nBytes + PGRESULT_BLOCK_OVERHEAD;
607 
608  block = (PGresult_data *) malloc(alloc_size);
609  if (!block)
610  return NULL;
611  res->memorySize += alloc_size;
612  space = block->space + PGRESULT_BLOCK_OVERHEAD;
613  if (res->curBlock)
614  {
615  /*
616  * Tuck special block below the active block, so that we don't
617  * have to waste the free space in the active block.
618  */
619  block->next = res->curBlock->next;
620  res->curBlock->next = block;
621  }
622  else
623  {
624  /* Must set up the new block as the first active block. */
625  block->next = NULL;
626  res->curBlock = block;
627  res->spaceLeft = 0; /* be sure it's marked full */
628  }
629  return space;
630  }
631 
632  /* Otherwise, start a new block. */
634  if (!block)
635  return NULL;
637  block->next = res->curBlock;
638  res->curBlock = block;
639  if (isBinary)
640  {
641  /* object needs full alignment */
644  }
645  else
646  {
647  /* we can cram it right after the overhead pointer */
648  res->curOffset = sizeof(PGresult_data);
650  }
651 
652  space = block->space + res->curOffset;
653  res->curOffset += nBytes;
654  res->spaceLeft -= nBytes;
655  return space;
656 }
#define PGRESULT_DATA_BLOCKSIZE
Definition: fe-exec.c:142
#define PGRESULT_BLOCK_OVERHEAD
Definition: fe-exec.c:144
#define PGRESULT_SEP_ALLOC_THRESHOLD
Definition: fe-exec.c:145
#define PGRESULT_ALIGN_BOUNDARY
Definition: fe-exec.c:143
union pgresult_data PGresult_data
Definition: libpq-int.h:104
size_t memorySize
Definition: libpq-int.h:215
int curOffset
Definition: libpq-int.h:212
char null_field[1]
Definition: libpq-int.h:204
int spaceLeft
Definition: libpq-int.h:213
PGresult_data * curBlock
Definition: libpq-int.h:211
PGresult_data * next
Definition: libpq-int.h:108
char space[1]
Definition: libpq-int.h:109

References pg_result::curBlock, pg_result::curOffset, malloc, pg_result::memorySize, pgresult_data::next, pg_result::null_field, PGRESULT_ALIGN_BOUNDARY, PGRESULT_BLOCK_OVERHEAD, PGRESULT_DATA_BLOCKSIZE, PGRESULT_SEP_ALLOC_THRESHOLD, res, pgresult_data::space, and pg_result::spaceLeft.

Referenced by getCopyStart(), getParamDescriptions(), getRowDescriptions(), pqInternalNotice(), PQresultAlloc(), pqResultStrdup(), pqRowProcessor(), pqSaveMessageField(), and PQsetvalue().

◆ pqResultStrdup()

char* pqResultStrdup ( PGresult res,
const char *  str 
)

Definition at line 675 of file fe-exec.c.

676 {
677  char *space = (char *) pqResultAlloc(res, strlen(str) + 1, false);
678 
679  if (space)
680  strcpy(space, str);
681  return space;
682 }
void * pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary)
Definition: fe-exec.c:563
const char * str

References pqResultAlloc(), res, and str.

Referenced by getRowDescriptions(), pqGetErrorNotice3(), PQsetResultAttrs(), and pqSetResultError().

◆ pqRowProcessor()

int pqRowProcessor ( PGconn conn,
const char **  errmsgp 
)

Definition at line 1206 of file fe-exec.c.

1207 {
1208  PGresult *res = conn->result;
1209  int nfields = res->numAttributes;
1210  const PGdataValue *columns = conn->rowBuf;
1211  PGresAttValue *tup;
1212  int i;
1213 
1214  /*
1215  * In partial-result mode, if we don't already have a partial PGresult
1216  * then make one by cloning conn->result (which should hold the correct
1217  * result metadata by now). Then the original conn->result is moved over
1218  * to saved_result so that we can re-use it as a reference for future
1219  * partial results. The saved result will become active again after
1220  * pqPrepareAsyncResult() returns the partial result to the application.
1221  */
1222  if (conn->partialResMode && conn->saved_result == NULL)
1223  {
1224  /* Copy everything that should be in the result at this point */
1225  res = PQcopyResult(res,
1228  if (!res)
1229  return 0;
1230  /* Change result status to appropriate special value */
1232  /* And stash it as the active result */
1234  conn->result = res;
1235  }
1236 
1237  /*
1238  * Basically we just allocate space in the PGresult for each field and
1239  * copy the data over.
1240  *
1241  * Note: on malloc failure, we return 0 leaving *errmsgp still NULL, which
1242  * caller will take to mean "out of memory". This is preferable to trying
1243  * to set up such a message here, because evidently there's not enough
1244  * memory for gettext() to do anything.
1245  */
1246  tup = (PGresAttValue *)
1247  pqResultAlloc(res, nfields * sizeof(PGresAttValue), true);
1248  if (tup == NULL)
1249  return 0;
1250 
1251  for (i = 0; i < nfields; i++)
1252  {
1253  int clen = columns[i].len;
1254 
1255  if (clen < 0)
1256  {
1257  /* null field */
1258  tup[i].len = NULL_LEN;
1259  tup[i].value = res->null_field;
1260  }
1261  else
1262  {
1263  bool isbinary = (res->attDescs[i].format != 0);
1264  char *val;
1265 
1266  val = (char *) pqResultAlloc(res, clen + 1, isbinary);
1267  if (val == NULL)
1268  return 0;
1269 
1270  /* copy and zero-terminate the data (even if it's binary) */
1271  memcpy(val, columns[i].value, clen);
1272  val[clen] = '\0';
1273 
1274  tup[i].len = clen;
1275  tup[i].value = val;
1276  }
1277  }
1278 
1279  /* And add the tuple to the PGresult's tuple array */
1280  if (!pqAddTuple(res, tup, errmsgp))
1281  return 0;
1282 
1283  /*
1284  * Success. In partial-result mode, if we have enough rows then make the
1285  * result available to the client immediately.
1286  */
1289 
1290  return 1;
1291 }
PGresult * PQcopyResult(const PGresult *src, int flags)
Definition: fe-exec.c:318
static bool pqAddTuple(PGresult *res, PGresAttValue *tup, const char **errmsgp)
Definition: fe-exec.c:993
@ PGRES_SINGLE_TUPLE
Definition: libpq-fe.h:133
#define PG_COPYRES_ATTRS
Definition: libpq-fe.h:66
#define PG_COPYRES_EVENTS
Definition: libpq-fe.h:68
#define PG_COPYRES_NOTICEHOOKS
Definition: libpq-fe.h:69
#define NULL_LEN
Definition: libpq-int.h:136
int maxChunkSize
Definition: libpq-int.h:458
bool singleRowMode
Definition: libpq-int.h:457
bool partialResMode
Definition: libpq-int.h:456
int ntups
Definition: libpq-int.h:172
PGresAttDesc * attDescs
Definition: libpq-int.h:174
int numAttributes
Definition: libpq-int.h:173
char * value
Definition: libpq-int.h:141

References pg_conn::asyncStatus, pg_result::attDescs, conn, pgresAttDesc::format, i, pgresAttValue::len, pgDataValue::len, pg_conn::maxChunkSize, pg_result::ntups, pg_result::null_field, NULL_LEN, pg_result::numAttributes, pg_conn::partialResMode, PG_COPYRES_ATTRS, PG_COPYRES_EVENTS, PG_COPYRES_NOTICEHOOKS, PGASYNC_READY_MORE, PGRES_SINGLE_TUPLE, PGRES_TUPLES_CHUNK, pqAddTuple(), PQcopyResult(), pqResultAlloc(), res, pg_conn::result, pg_result::resultStatus, pg_conn::rowBuf, pg_conn::saved_result, pg_conn::singleRowMode, val, value, and pgresAttValue::value.

Referenced by getAnotherTuple().

◆ pqSaveErrorResult()

void pqSaveErrorResult ( PGconn conn)

Definition at line 803 of file fe-exec.c.

804 {
805  /* Drop any pending result ... */
807  /* ... and set flag to remember to make an error result later */
808  conn->error_result = true;
809 }

References conn, pg_conn::error_result, and pqClearAsyncResult().

Referenced by getAnotherTuple(), getCopyResult(), getParamDescriptions(), getRowDescriptions(), handleSyncLoss(), pqFunctionCall3(), PQgetResult(), pqParseInput3(), pqPipelineProcessQueue(), and pqSaveWriteError().

◆ pqSaveMessageField()

void void pqSaveMessageField ( PGresult res,
char  code,
const char *  value 
)

Definition at line 1060 of file fe-exec.c.

1061 {
1062  PGMessageField *pfield;
1063 
1064  pfield = (PGMessageField *)
1066  offsetof(PGMessageField, contents) +
1067  strlen(value) + 1,
1068  true);
1069  if (!pfield)
1070  return; /* out of memory? */
1071  pfield->code = code;
1072  strcpy(pfield->contents, value);
1073  pfield->next = res->errFields;
1074  res->errFields = pfield;
1075 }
struct pgMessageField * next
Definition: libpq-int.h:147
char contents[FLEXIBLE_ARRAY_MEMBER]
Definition: libpq-int.h:149

References pgMessageField::code, pgMessageField::contents, pg_result::errFields, pgMessageField::next, pqResultAlloc(), res, and value.

Referenced by pqGetErrorNotice3(), and pqInternalNotice().

◆ pqSaveParameterStatus()

void pqSaveParameterStatus ( PGconn conn,
const char *  name,
const char *  value 
)

Definition at line 1081 of file fe-exec.c.

1082 {
1083  pgParameterStatus *pstatus;
1084  pgParameterStatus *prev;
1085 
1086  /*
1087  * Forget any old information about the parameter
1088  */
1089  for (pstatus = conn->pstatus, prev = NULL;
1090  pstatus != NULL;
1091  prev = pstatus, pstatus = pstatus->next)
1092  {
1093  if (strcmp(pstatus->name, name) == 0)
1094  {
1095  if (prev)
1096  prev->next = pstatus->next;
1097  else
1098  conn->pstatus = pstatus->next;
1099  free(pstatus); /* frees name and value strings too */
1100  break;
1101  }
1102  }
1103 
1104  /*
1105  * Store new info as a single malloc block
1106  */
1107  pstatus = (pgParameterStatus *) malloc(sizeof(pgParameterStatus) +
1108  strlen(name) + strlen(value) + 2);
1109  if (pstatus)
1110  {
1111  char *ptr;
1112 
1113  ptr = ((char *) pstatus) + sizeof(pgParameterStatus);
1114  pstatus->name = ptr;
1115  strcpy(ptr, name);
1116  ptr += strlen(name) + 1;
1117  pstatus->value = ptr;
1118  strcpy(ptr, value);
1119  pstatus->next = conn->pstatus;
1120  conn->pstatus = pstatus;
1121  }
1122 
1123  /*
1124  * Save values of settings that are of interest to libpq in fields of the
1125  * PGconn object. We keep client_encoding and standard_conforming_strings
1126  * in static variables as well, so that PQescapeString and PQescapeBytea
1127  * can behave somewhat sanely (at least in single-connection-using
1128  * programs).
1129  */
1130  if (strcmp(name, "client_encoding") == 0)
1131  {
1133  /* if we don't recognize the encoding name, fall back to SQL_ASCII */
1134  if (conn->client_encoding < 0)
1137  }
1138  else if (strcmp(name, "standard_conforming_strings") == 0)
1139  {
1140  conn->std_strings = (strcmp(value, "on") == 0);
1142  }
1143  else if (strcmp(name, "server_version") == 0)
1144  {
1145  /* We convert the server version to numeric form. */
1146  int cnt;
1147  int vmaj,
1148  vmin,
1149  vrev;
1150 
1151  cnt = sscanf(value, "%d.%d.%d", &vmaj, &vmin, &vrev);
1152 
1153  if (cnt == 3)
1154  {
1155  /* old style, e.g. 9.6.1 */
1156  conn->sversion = (100 * vmaj + vmin) * 100 + vrev;
1157  }
1158  else if (cnt == 2)
1159  {
1160  if (vmaj >= 10)
1161  {
1162  /* new style, e.g. 10.1 */
1163  conn->sversion = 100 * 100 * vmaj + vmin;
1164  }
1165  else
1166  {
1167  /* old style without minor version, e.g. 9.6devel */
1168  conn->sversion = (100 * vmaj + vmin) * 100;
1169  }
1170  }
1171  else if (cnt == 1)
1172  {
1173  /* new style without minor version, e.g. 10devel */
1174  conn->sversion = 100 * 100 * vmaj;
1175  }
1176  else
1177  conn->sversion = 0; /* unknown */
1178  }
1179  else if (strcmp(name, "default_transaction_read_only") == 0)
1180  {
1182  (strcmp(value, "on") == 0) ? PG_BOOL_YES : PG_BOOL_NO;
1183  }
1184  else if (strcmp(name, "in_hot_standby") == 0)
1185  {
1186  conn->in_hot_standby =
1187  (strcmp(value, "on") == 0) ? PG_BOOL_YES : PG_BOOL_NO;
1188  }
1189  else if (strcmp(name, "scram_iterations") == 0)
1190  {
1192  }
1193 }
static bool static_std_strings
Definition: fe-exec.c:60
static int static_client_encoding
Definition: fe-exec.c:59
struct pgParameterStatus pgParameterStatus
#define pg_char_to_encoding
Definition: pg_wchar.h:629
struct pgParameterStatus * next
Definition: libpq-int.h:277
int sversion
Definition: libpq-int.h:490
pgParameterStatus * pstatus
Definition: libpq-int.h:524

References pg_conn::client_encoding, conn, pg_conn::default_transaction_read_only, free, pg_conn::in_hot_standby, malloc, name, pgParameterStatus::name, pgParameterStatus::next, PG_BOOL_NO, PG_BOOL_YES, pg_char_to_encoding, PG_SQL_ASCII, pg_conn::pstatus, pg_conn::scram_sha_256_iterations, static_client_encoding, static_std_strings, pg_conn::std_strings, pg_conn::sversion, value, and pgParameterStatus::value.

Referenced by getParameterStatus().

◆ pqsecure_close()

void pqsecure_close ( PGconn conn)

Definition at line 152 of file fe-secure.c.

153 {
154 #ifdef USE_SSL
155  pgtls_close(conn);
156 #endif
157 }

References conn, and pgtls_close().

Referenced by pqDropConnection().

◆ pqsecure_open_client()

PostgresPollingStatusType pqsecure_open_client ( PGconn conn)

Definition at line 138 of file fe-secure.c.

139 {
140 #ifdef USE_SSL
141  return pgtls_open_client(conn);
142 #else
143  /* shouldn't get here */
144  return PGRES_POLLING_FAILED;
145 #endif
146 }
PostgresPollingStatusType pgtls_open_client(PGconn *conn)

References conn, PGRES_POLLING_FAILED, and pgtls_open_client().

Referenced by PQconnectPoll().

◆ pqsecure_raw_read()

ssize_t pqsecure_raw_read ( PGconn conn,
void *  ptr,
size_t  len 
)

Definition at line 193 of file fe-secure.c.

194 {
195  ssize_t n;
196  int result_errno = 0;
197  char sebuf[PG_STRERROR_R_BUFLEN];
198 
199  SOCK_ERRNO_SET(0);
200 
201  n = recv(conn->sock, ptr, len, 0);
202 
203  if (n < 0)
204  {
205  result_errno = SOCK_ERRNO;
206 
207  /* Set error message if appropriate */
208  switch (result_errno)
209  {
210 #ifdef EAGAIN
211  case EAGAIN:
212 #endif
213 #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
214  case EWOULDBLOCK:
215 #endif
216  case EINTR:
217  /* no error message, caller is expected to retry */
218  break;
219 
220  case EPIPE:
221  case ECONNRESET:
222  libpq_append_conn_error(conn, "server closed the connection unexpectedly\n"
223  "\tThis probably means the server terminated abnormally\n"
224  "\tbefore or while processing the request.");
225  break;
226 
227  case 0:
228  /* If errno didn't get set, treat it as regular EOF */
229  n = 0;
230  break;
231 
232  default:
233  libpq_append_conn_error(conn, "could not receive data from server: %s",
234  SOCK_STRERROR(result_errno,
235  sebuf, sizeof(sebuf)));
236  break;
237  }
238  }
239 
240  /* ensure we return the intended errno to caller */
241  SOCK_ERRNO_SET(result_errno);
242 
243  return n;
244 }
#define recv(s, buf, len, flags)
Definition: win32_port.h:514

References conn, EAGAIN, ECONNRESET, EINTR, EWOULDBLOCK, len, libpq_append_conn_error(), PG_STRERROR_R_BUFLEN, recv, pg_conn::sock, SOCK_ERRNO, SOCK_ERRNO_SET, and SOCK_STRERROR.

Referenced by gss_read(), pg_GSS_read(), pgconn_bio_read(), and pqsecure_read().

◆ pqsecure_raw_write()

ssize_t pqsecure_raw_write ( PGconn conn,
const void *  ptr,
size_t  len 
)

Definition at line 316 of file fe-secure.c.

317 {
318  ssize_t n;
319  int flags = 0;
320  int result_errno = 0;
321  char msgbuf[1024];
322  char sebuf[PG_STRERROR_R_BUFLEN];
323 
324  DECLARE_SIGPIPE_INFO(spinfo);
325 
326  /*
327  * If we already had a write failure, we will never again try to send data
328  * on that connection. Even if the kernel would let us, we've probably
329  * lost message boundary sync with the server. conn->write_failed
330  * therefore persists until the connection is reset, and we just discard
331  * all data presented to be written.
332  */
333  if (conn->write_failed)
334  return len;
335 
336 #ifdef MSG_NOSIGNAL
337  if (conn->sigpipe_flag)
338  flags |= MSG_NOSIGNAL;
339 
340 retry_masked:
341 #endif /* MSG_NOSIGNAL */
342 
343  DISABLE_SIGPIPE(conn, spinfo, return -1);
344 
345  n = send(conn->sock, ptr, len, flags);
346 
347  if (n < 0)
348  {
349  result_errno = SOCK_ERRNO;
350 
351  /*
352  * If we see an EINVAL, it may be because MSG_NOSIGNAL isn't available
353  * on this machine. So, clear sigpipe_flag so we don't try the flag
354  * again, and retry the send().
355  */
356 #ifdef MSG_NOSIGNAL
357  if (flags != 0 && result_errno == EINVAL)
358  {
359  conn->sigpipe_flag = false;
360  flags = 0;
361  goto retry_masked;
362  }
363 #endif /* MSG_NOSIGNAL */
364 
365  /* Set error message if appropriate */
366  switch (result_errno)
367  {
368 #ifdef EAGAIN
369  case EAGAIN:
370 #endif
371 #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
372  case EWOULDBLOCK:
373 #endif
374  case EINTR:
375  /* no error message, caller is expected to retry */
376  break;
377 
378  case EPIPE:
379  /* Set flag for EPIPE */
380  REMEMBER_EPIPE(spinfo, true);
381 
382  /* FALL THRU */
383 
384  case ECONNRESET:
385  conn->write_failed = true;
386  /* Store error message in conn->write_err_msg, if possible */
387  /* (strdup failure is OK, we'll cope later) */
388  snprintf(msgbuf, sizeof(msgbuf),
389  libpq_gettext("server closed the connection unexpectedly\n"
390  "\tThis probably means the server terminated abnormally\n"
391  "\tbefore or while processing the request."));
392  /* keep newline out of translated string */
393  strlcat(msgbuf, "\n", sizeof(msgbuf));
394  conn->write_err_msg = strdup(msgbuf);
395  /* Now claim the write succeeded */
396  n = len;
397  break;
398 
399  default:
400  conn->write_failed = true;
401  /* Store error message in conn->write_err_msg, if possible */
402  /* (strdup failure is OK, we'll cope later) */
403  snprintf(msgbuf, sizeof(msgbuf),
404  libpq_gettext("could not send data to server: %s"),
405  SOCK_STRERROR(result_errno,
406  sebuf, sizeof(sebuf)));
407  /* keep newline out of translated string */
408  strlcat(msgbuf, "\n", sizeof(msgbuf));
409  conn->write_err_msg = strdup(msgbuf);
410  /* Now claim the write succeeded */
411  n = len;
412  break;
413  }
414  }
415 
416  RESTORE_SIGPIPE(conn, spinfo);
417 
418  /* ensure we return the intended errno to caller */
419  SOCK_ERRNO_SET(result_errno);
420 
421  return n;
422 }
#define REMEMBER_EPIPE(spinfo, cond)
Definition: fe-secure.c:77
#define DISABLE_SIGPIPE(conn, spinfo, failaction)
Definition: fe-secure.c:66
#define DECLARE_SIGPIPE_INFO(spinfo)
Definition: fe-secure.c:64
#define RESTORE_SIGPIPE(conn, spinfo)
Definition: fe-secure.c:83
size_t strlcat(char *dst, const char *src, size_t siz)
Definition: strlcat.c:33
char * write_err_msg
Definition: libpq-int.h:497
bool sigpipe_flag
Definition: libpq-int.h:495
bool write_failed
Definition: libpq-int.h:496
#define send(s, buf, len, flags)
Definition: win32_port.h:515

References conn, DECLARE_SIGPIPE_INFO, DISABLE_SIGPIPE, EAGAIN, ECONNRESET, EINTR, EWOULDBLOCK, len, libpq_gettext, PG_STRERROR_R_BUFLEN, REMEMBER_EPIPE, RESTORE_SIGPIPE, send, pg_conn::sigpipe_flag, snprintf, pg_conn::sock, SOCK_ERRNO, SOCK_ERRNO_SET, SOCK_STRERROR, strlcat(), pg_conn::write_err_msg, and pg_conn::write_failed.

Referenced by pg_GSS_write(), pgconn_bio_write(), pqsecure_open_gss(), and pqsecure_write().

◆ pqsecure_read()

ssize_t pqsecure_read ( PGconn conn,
void *  ptr,
size_t  len 
)

Definition at line 167 of file fe-secure.c.

168 {
169  ssize_t n;
170 
171 #ifdef USE_SSL
172  if (conn->ssl_in_use)
173  {
174  n = pgtls_read(conn, ptr, len);
175  }
176  else
177 #endif
178 #ifdef ENABLE_GSS
179  if (conn->gssenc)
180  {
181  n = pg_GSS_read(conn, ptr, len);
182  }
183  else
184 #endif
185  {
186  n = pqsecure_raw_read(conn, ptr, len);
187  }
188 
189  return n;
190 }
ssize_t pg_GSS_read(PGconn *conn, void *ptr, size_t len)
ssize_t pgtls_read(PGconn *conn, void *ptr, size_t len)
ssize_t pqsecure_raw_read(PGconn *conn, void *ptr, size_t len)
Definition: fe-secure.c:193

References conn, len, pg_GSS_read(), pgtls_read(), pqsecure_raw_read(), and pg_conn::ssl_in_use.

Referenced by pqReadData().

◆ pqsecure_write()

ssize_t pqsecure_write ( PGconn conn,
const void *  ptr,
size_t  len 
)

Definition at line 267 of file fe-secure.c.

268 {
269  ssize_t n;
270 
271 #ifdef USE_SSL
272  if (conn->ssl_in_use)
273  {
274  n = pgtls_write(conn, ptr, len);
275  }
276  else
277 #endif
278 #ifdef ENABLE_GSS
279  if (conn->gssenc)
280  {
281  n = pg_GSS_write(conn, ptr, len);
282  }
283  else
284 #endif
285  {
286  n = pqsecure_raw_write(conn, ptr, len);
287  }
288 
289  return n;
290 }
ssize_t pg_GSS_write(PGconn *conn, const void *ptr, size_t len)
ssize_t pgtls_write(PGconn *conn, const void *ptr, size_t len)
ssize_t pqsecure_raw_write(PGconn *conn, const void *ptr, size_t len)
Definition: fe-secure.c:316

References conn, len, pg_GSS_write(), pgtls_write(), pqsecure_raw_write(), and pg_conn::ssl_in_use.

Referenced by pqSendSome().

◆ PQsendQueryContinue()

int PQsendQueryContinue ( PGconn conn,
const char *  query 
)

Definition at line 1422 of file fe-exec.c.

1423 {
1424  return PQsendQueryInternal(conn, query, false);
1425 }
static int PQsendQueryInternal(PGconn *conn, const char *query, bool newQuery)
Definition: fe-exec.c:1428

References conn, and PQsendQueryInternal().

Referenced by PQconnectPoll().

◆ pqSetResultError()

void pqSetResultError ( PGresult res,
PQExpBuffer  errorMessage,
int  offset 
)

Definition at line 692 of file fe-exec.c.

693 {
694  char *msg;
695 
696  if (!res)
697  return;
698 
699  /*
700  * We handle two OOM scenarios here. The errorMessage buffer might be
701  * marked "broken" due to having previously failed to allocate enough
702  * memory for the message, or it might be fine but pqResultStrdup fails
703  * and returns NULL. In either case, just make res->errMsg point directly
704  * at a constant "out of memory" string.
705  */
706  if (!PQExpBufferBroken(errorMessage))
707  msg = pqResultStrdup(res, errorMessage->data + offset);
708  else
709  msg = NULL;
710  if (msg)
711  res->errMsg = msg;
712  else
713  res->errMsg = libpq_gettext("out of memory\n");
714 }

References PQExpBufferData::data, pg_result::errMsg, libpq_gettext, PQExpBufferBroken, pqResultStrdup(), and res.

Referenced by pqGetErrorNotice3(), PQmakeEmptyPGresult(), and pqPrepareAsyncResult().

◆ pqSkipnchar()

int pqSkipnchar ( size_t  len,
PGconn conn 
)

Definition at line 187 of file fe-misc.c.

188 {
189  if (len > (size_t) (conn->inEnd - conn->inCursor))
190  return EOF;
191 
192  conn->inCursor += len;
193 
194  return 0;
195 }

References conn, pg_conn::inCursor, pg_conn::inEnd, and len.

Referenced by getAnotherTuple().

◆ pqTraceOutputCharResponse()

void pqTraceOutputCharResponse ( PGconn conn,
const char *  responseType,
char  response 
)

Definition at line 909 of file fe-trace.c.

911 {
913  {
914  char timestr[128];
915 
916  pqTraceFormatTimestamp(timestr, sizeof(timestr));
917  fprintf(conn->Pfdebug, "%s\t", timestr);
918  }
919 
920  fprintf(conn->Pfdebug, "B\t1\t%s\t %c\n", responseType, response);
921 }
static void pqTraceFormatTimestamp(char *timestr, size_t ts_len)
Definition: fe-trace.c:80
#define PQTRACE_SUPPRESS_TIMESTAMPS
Definition: libpq-fe.h:466
#define fprintf
Definition: port.h:242
int traceFlags
Definition: libpq-int.h:437

References conn, fprintf, pg_conn::Pfdebug, PQTRACE_SUPPRESS_TIMESTAMPS, pqTraceFormatTimestamp(), and pg_conn::traceFlags.

Referenced by PQconnectPoll().

◆ pqTraceOutputMessage()

void pqTraceOutputMessage ( PGconn conn,
const char *  message,
bool  toServer 
)

Definition at line 618 of file fe-trace.c.

619 {
620  char id;
621  int length;
622  char *prefix = toServer ? "F" : "B";
623  int logCursor = 0;
624  bool regress;
625 
627  {
628  char timestr[128];
629 
630  pqTraceFormatTimestamp(timestr, sizeof(timestr));
631  fprintf(conn->Pfdebug, "%s\t", timestr);
632  }
633  regress = (conn->traceFlags & PQTRACE_REGRESS_MODE) != 0;
634 
635  id = message[logCursor++];
636 
637  memcpy(&length, message + logCursor, 4);
638  length = (int) pg_ntoh32(length);
639  logCursor += 4;
640 
641  /*
642  * In regress mode, suppress the length of ErrorResponse and
643  * NoticeResponse. The F (file name), L (line number) and R (routine
644  * name) fields can change as server code is modified, and if their
645  * lengths differ from the originals, that would break tests.
646  */
647  if (regress && !toServer && (id == PqMsg_ErrorResponse || id == PqMsg_NoticeResponse))
648  fprintf(conn->Pfdebug, "%s\tNN\t", prefix);
649  else
650  fprintf(conn->Pfdebug, "%s\t%d\t", prefix, length);
651 
652  switch (id)
653  {
654  case PqMsg_ParseComplete:
655  fprintf(conn->Pfdebug, "ParseComplete");
656  /* No message content */
657  break;
658  case PqMsg_BindComplete:
659  fprintf(conn->Pfdebug, "BindComplete");
660  /* No message content */
661  break;
662  case PqMsg_CloseComplete:
663  fprintf(conn->Pfdebug, "CloseComplete");
664  /* No message content */
665  break;
667  pqTraceOutput_NotificationResponse(conn->Pfdebug, message, &logCursor, regress);
668  break;
669  case PqMsg_Bind:
670  pqTraceOutput_Bind(conn->Pfdebug, message, &logCursor);
671  break;
672  case PqMsg_CopyDone:
673  fprintf(conn->Pfdebug, "CopyDone");
674  /* No message content */
675  break;
677  /* Close(F) and CommandComplete(B) use the same identifier. */
679  if (toServer)
680  pqTraceOutput_Close(conn->Pfdebug, message, &logCursor);
681  else
682  pqTraceOutput_CommandComplete(conn->Pfdebug, message, &logCursor);
683  break;
684  case PqMsg_CopyData:
685  pqTraceOutput_CopyData(conn->Pfdebug, message, &logCursor,
686  length, regress);
687  break;
688  case PqMsg_Describe:
689  /* Describe(F) and DataRow(B) use the same identifier. */
691  if (toServer)
692  pqTraceOutput_Describe(conn->Pfdebug, message, &logCursor);
693  else
694  pqTraceOutput_DataRow(conn->Pfdebug, message, &logCursor);
695  break;
696  case PqMsg_Execute:
697  /* Execute(F) and ErrorResponse(B) use the same identifier. */
699  if (toServer)
700  pqTraceOutput_Execute(conn->Pfdebug, message, &logCursor, regress);
701  else
702  pqTraceOutput_ErrorResponse(conn->Pfdebug, message, &logCursor, regress);
703  break;
704  case PqMsg_CopyFail:
705  pqTraceOutput_CopyFail(conn->Pfdebug, message, &logCursor);
706  break;
707  case PqMsg_GSSResponse:
711 
712  /*
713  * These messages share a common type byte, so we discriminate by
714  * having the code store the auth type separately.
715  */
716  switch (conn->current_auth_response)
717  {
718  case AUTH_RESPONSE_GSS:
720  &logCursor, length, regress);
721  break;
724  &logCursor);
725  break;
728  &logCursor, regress);
729  break;
730  case AUTH_RESPONSE_SASL:
732  &logCursor, length, regress);
733  break;
734  default:
735  fprintf(conn->Pfdebug, "UnknownAuthenticationResponse");
736  break;
737  }
738  conn->current_auth_response = '\0';
739  break;
740  case PqMsg_FunctionCall:
741  pqTraceOutput_FunctionCall(conn->Pfdebug, message, &logCursor, regress);
742  break;
744  pqTraceOutput_CopyInResponse(conn->Pfdebug, message, &logCursor);
745  break;
746  case PqMsg_Flush:
747  /* Flush(F) and CopyOutResponse(B) use the same identifier */
749  if (toServer)
750  fprintf(conn->Pfdebug, "Flush"); /* no message content */
751  else
752  pqTraceOutput_CopyOutResponse(conn->Pfdebug, message, &logCursor);
753  break;
755  fprintf(conn->Pfdebug, "EmptyQueryResponse");
756  /* No message content */
757  break;
759  pqTraceOutput_BackendKeyData(conn->Pfdebug, message, &logCursor, regress);
760  break;
761  case PqMsg_NoData:
762  fprintf(conn->Pfdebug, "NoData");
763  /* No message content */
764  break;
766  pqTraceOutput_NoticeResponse(conn->Pfdebug, message, &logCursor, regress);
767  break;
768  case PqMsg_Parse:
769  pqTraceOutput_Parse(conn->Pfdebug, message, &logCursor, regress);
770  break;
771  case PqMsg_Query:
772  pqTraceOutput_Query(conn->Pfdebug, message, &logCursor);
773  break;
775  pqTraceOutput_Authentication(conn->Pfdebug, message, &logCursor,
776  length, regress);
777  break;
779  fprintf(conn->Pfdebug, "PortalSuspended");
780  /* No message content */
781  break;
782  case PqMsg_Sync:
783  /* ParameterStatus(B) and Sync(F) use the same identifier */
785  if (toServer)
786  fprintf(conn->Pfdebug, "Sync"); /* no message content */
787  else
788  pqTraceOutput_ParameterStatus(conn->Pfdebug, message, &logCursor);
789  break;
791  pqTraceOutput_ParameterDescription(conn->Pfdebug, message, &logCursor, regress);
792  break;
794  pqTraceOutput_RowDescription(conn->Pfdebug, message, &logCursor, regress);
795  break;
797  pqTraceOutput_NegotiateProtocolVersion(conn->Pfdebug, message, &logCursor);
798  break;
800  pqTraceOutput_FunctionCallResponse(conn->Pfdebug, message, &logCursor);
801  break;
803  pqTraceOutput_CopyBothResponse(conn->Pfdebug, message, &logCursor, length);
804  break;
805  case PqMsg_Terminate:
806  fprintf(conn->Pfdebug, "Terminate");
807  /* No message content */
808  break;
809  case PqMsg_ReadyForQuery:
810  pqTraceOutput_ReadyForQuery(conn->Pfdebug, message, &logCursor);
811  break;
812  default:
813  fprintf(conn->Pfdebug, "Unknown message: %02x", id);
814  break;
815  }
816 
817  fputc('\n', conn->Pfdebug);
818 
819  /*
820  * Verify the printing routine did it right. Note that the one-byte
821  * message identifier is not included in the length, but our cursor does
822  * include it.
823  */
824  if (logCursor - 1 != length)
826  "mismatched message length: consumed %d, expected %d\n",
827  logCursor - 1, length);
828 }
static void pqTraceOutput_RowDescription(FILE *f, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:559
static void pqTraceOutput_GSSResponse(FILE *f, const char *message, int *cursor, int length, bool regress)
Definition: fe-trace.c:367
static void pqTraceOutput_FunctionCall(FILE *f, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:403
static void pqTraceOutput_CopyInResponse(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:429
static void pqTraceOutput_BackendKeyData(FILE *f, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:455
static void pqTraceOutput_Authentication(FILE *f, const char *message, int *cursor, int length, bool suppress)
Definition: fe-trace.c:484
static void pqTraceOutput_Parse(FILE *f, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:463
static void pqTraceOutput_NoticeResponse(FILE *f, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:346
static void pqTraceOutput_ParameterDescription(FILE *f, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:547
static void pqTraceOutput_DataRow(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:293
static void pqTraceOutput_SASLResponse(FILE *f, const char *message, int *cursor, int length, bool regress)
Definition: fe-trace.c:395
static void pqTraceOutput_Query(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:477
static void pqTraceOutput_CopyData(FILE *f, const char *message, int *cursor, int length, bool suppress)
Definition: fe-trace.c:285
static void pqTraceOutput_SASLInitialResponse(FILE *f, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:382
static void pqTraceOutput_NegotiateProtocolVersion(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:579
static void pqTraceOutput_CopyBothResponse(FILE *f, const char *message, int *cursor, int length)
Definition: fe-trace.c:598
static void pqTraceOutput_Bind(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:240
static void pqTraceOutput_ErrorResponse(FILE *f, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:340
static void pqTraceOutput_Close(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:270
static void pqTraceOutput_Describe(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:311
static void pqTraceOutput_NotificationResponse(FILE *f, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:231
static void pqTraceOutput_CommandComplete(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:278
static void pqTraceOutput_ParameterStatus(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:539
static void pqTraceOutput_Execute(FILE *f, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:352
static void pqTraceOutput_CopyOutResponse(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:442
static void pqTraceOutput_ReadyForQuery(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:608
static void pqTraceOutput_CopyFail(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:360
static void pqTraceOutput_PasswordMessage(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:375
static void pqTraceOutput_FunctionCallResponse(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:587
#define PQTRACE_REGRESS_MODE
Definition: libpq-fe.h:468
#define AUTH_RESPONSE_PASSWORD
Definition: libpq-int.h:342
#define AUTH_RESPONSE_SASL
Definition: libpq-int.h:344
#define AUTH_RESPONSE_SASL_INITIAL
Definition: libpq-int.h:343
#define AUTH_RESPONSE_GSS
Definition: libpq-int.h:341
#define PqMsg_GSSResponse
Definition: protocol.h:30
#define PqMsg_SASLResponse
Definition: protocol.h:33
#define PqMsg_Describe
Definition: protocol.h:21
#define PqMsg_FunctionCallResponse
Definition: protocol.h:53
#define PqMsg_SASLInitialResponse
Definition: protocol.h:32
#define PqMsg_AuthenticationRequest
Definition: protocol.h:50
#define PqMsg_NegotiateProtocolVersion
Definition: protocol.h:59
#define PqMsg_PortalSuspended
Definition: protocol.h:57
#define PqMsg_Parse
Definition: protocol.h:25
#define PqMsg_Bind
Definition: protocol.h:19
#define PqMsg_PasswordMessage
Definition: protocol.h:31
#define PqMsg_CopyFail
Definition: protocol.h:29
#define PqMsg_Flush
Definition: protocol.h:24
#define PqMsg_Query
Definition: protocol.h:26
#define PqMsg_Terminate
Definition: protocol.h:28
#define PqMsg_Execute
Definition: protocol.h:22
#define PqMsg_Close
Definition: protocol.h:20
char current_auth_response
Definition: libpq-int.h:505

References Assert, AUTH_RESPONSE_GSS, AUTH_RESPONSE_PASSWORD, AUTH_RESPONSE_SASL, AUTH_RESPONSE_SASL_INITIAL, conn, pg_conn::current_auth_response, fprintf, pg_conn::Pfdebug, pg_ntoh32, PqMsg_AuthenticationRequest, PqMsg_BackendKeyData, PqMsg_Bind, PqMsg_BindComplete, PqMsg_Close, PqMsg_CloseComplete, PqMsg_CommandComplete, PqMsg_CopyBothResponse, PqMsg_CopyData, PqMsg_CopyDone, PqMsg_CopyFail, PqMsg_CopyInResponse, PqMsg_CopyOutResponse, PqMsg_DataRow, PqMsg_Describe, PqMsg_EmptyQueryResponse, PqMsg_ErrorResponse, PqMsg_Execute, PqMsg_Flush, PqMsg_FunctionCall, PqMsg_FunctionCallResponse, PqMsg_GSSResponse, PqMsg_NegotiateProtocolVersion, PqMsg_NoData, PqMsg_NoticeResponse, PqMsg_NotificationResponse, PqMsg_ParameterDescription, PqMsg_ParameterStatus, PqMsg_Parse, PqMsg_ParseComplete, PqMsg_PasswordMessage, PqMsg_PortalSuspended, PqMsg_Query, PqMsg_ReadyForQuery, PqMsg_RowDescription, PqMsg_SASLInitialResponse, PqMsg_SASLResponse, PqMsg_Sync, PqMsg_Terminate, PQTRACE_REGRESS_MODE, PQTRACE_SUPPRESS_TIMESTAMPS, pqTraceFormatTimestamp(), pqTraceOutput_Authentication(), pqTraceOutput_BackendKeyData(), pqTraceOutput_Bind(), pqTraceOutput_Close(), pqTraceOutput_CommandComplete(), pqTraceOutput_CopyBothResponse(), pqTraceOutput_CopyData(), pqTraceOutput_CopyFail(), pqTraceOutput_CopyInResponse(), pqTraceOutput_CopyOutResponse(), pqTraceOutput_DataRow(), pqTraceOutput_Describe(), pqTraceOutput_ErrorResponse(), pqTraceOutput_Execute(), pqTraceOutput_FunctionCall(), pqTraceOutput_FunctionCallResponse(), pqTraceOutput_GSSResponse(), pqTraceOutput_NegotiateProtocolVersion(), pqTraceOutput_NoticeResponse(), pqTraceOutput_NotificationResponse(), pqTraceOutput_ParameterDescription(), pqTraceOutput_ParameterStatus(), pqTraceOutput_Parse(), pqTraceOutput_PasswordMessage(), pqTraceOutput_Query(), pqTraceOutput_ReadyForQuery(), pqTraceOutput_RowDescription(), pqTraceOutput_SASLInitialResponse(), pqTraceOutput_SASLResponse(), and pg_conn::traceFlags.

Referenced by pg_password_sendauth(), pg_SASL_continue(), pg_SASL_init(), pqParseDone(), and pqPutMsgEnd().

◆ pqTraceOutputNoTypeByteMessage()

void pqTraceOutputNoTypeByteMessage ( PGconn conn,
const char *  message 
)

Definition at line 835 of file fe-trace.c.

836 {
837  int length;
838  int version;
839  bool regress;
840  int logCursor = 0;
841 
842  regress = (conn->traceFlags & PQTRACE_REGRESS_MODE) != 0;
843 
845  {
846  char timestr[128];
847 
848  pqTraceFormatTimestamp(timestr, sizeof(timestr));
849  fprintf(conn->Pfdebug, "%s\t", timestr);
850  }
851 
852  memcpy(&length, message + logCursor, 4);
853  length = (int) pg_ntoh32(length);
854  logCursor += 4;
855 
856  fprintf(conn->Pfdebug, "F\t%d\t", length);
857 
858  if (length < 8)
859  {
860  fprintf(conn->Pfdebug, "Unknown message\n");
861  return;
862  }
863 
864  memcpy(&version, message + logCursor, 4);
865  version = (int) pg_ntoh32(version);
866 
867  if (version == CANCEL_REQUEST_CODE && length >= 16)
868  {
869  fprintf(conn->Pfdebug, "CancelRequest\t");
870  pqTraceOutputInt16(conn->Pfdebug, message, &logCursor);
871  pqTraceOutputInt16(conn->Pfdebug, message, &logCursor);
872  pqTraceOutputInt32(conn->Pfdebug, message, &logCursor, regress);
873  pqTraceOutputInt32(conn->Pfdebug, message, &logCursor, regress);
874  }
875  else if (version == NEGOTIATE_SSL_CODE)
876  {
877  fprintf(conn->Pfdebug, "SSLRequest\t");
878  pqTraceOutputInt16(conn->Pfdebug, message, &logCursor);
879  pqTraceOutputInt16(conn->Pfdebug, message, &logCursor);
880  }
881  else if (version == NEGOTIATE_GSS_CODE)
882  {
883  fprintf(conn->Pfdebug, "GSSENCRequest\t");
884  pqTraceOutputInt16(conn->Pfdebug, message, &logCursor);
885  pqTraceOutputInt16(conn->Pfdebug, message, &logCursor);
886  }
887  else
888  {
889  fprintf(conn->Pfdebug, "StartupMessage\t");
890  pqTraceOutputInt16(conn->Pfdebug, message, &logCursor);
891  pqTraceOutputInt16(conn->Pfdebug, message, &logCursor);
892  while (message[logCursor] != '\0')
893  {
894  /* XXX should we suppress anything in regress mode? */
895  pqTraceOutputString(conn->Pfdebug, message, &logCursor, false);
896  pqTraceOutputString(conn->Pfdebug, message, &logCursor, false);
897  }
898  }
899 
900  fputc('\n', conn->Pfdebug);
901 }
static void pqTraceOutputString(FILE *pfdebug, const char *data, int *cursor, bool suppress)
Definition: fe-trace.c:166
static int pqTraceOutputInt16(FILE *pfdebug, const char *data, int *cursor)
Definition: fe-trace.c:126
static int pqTraceOutputInt32(FILE *pfdebug, const char *data, int *cursor, bool suppress)
Definition: fe-trace.c:145
#define CANCEL_REQUEST_CODE
Definition: pqcomm.h:133
#define NEGOTIATE_GSS_CODE
Definition: pqcomm.h:168
#define NEGOTIATE_SSL_CODE
Definition: pqcomm.h:167

References CANCEL_REQUEST_CODE, conn, fprintf, NEGOTIATE_GSS_CODE, NEGOTIATE_SSL_CODE, pg_conn::Pfdebug, pg_ntoh32, PQTRACE_REGRESS_MODE, PQTRACE_SUPPRESS_TIMESTAMPS, pqTraceFormatTimestamp(), pqTraceOutputInt16(), pqTraceOutputInt32(), pqTraceOutputString(), and pg_conn::traceFlags.

Referenced by pqPutMsgEnd().

◆ pqWait()

int pqWait ( int  forRead,
int  forWrite,
PGconn conn 
)

Definition at line 993 of file fe-misc.c.

994 {
995  return pqWaitTimed(forRead, forWrite, conn, -1);
996 }

References conn, and pqWaitTimed().

Referenced by pqFunctionCall3(), pqGetCopyData3(), pqGetline3(), PQgetResult(), and pqSendSome().

◆ pqWaitTimed()

int pqWaitTimed ( int  forRead,
int  forWrite,
PGconn conn,
pg_usec_time_t  end_time 
)

Definition at line 1009 of file fe-misc.c.

1010 {
1011  int result;
1012 
1013  result = pqSocketCheck(conn, forRead, forWrite, end_time);
1014 
1015  if (result < 0)
1016  return -1; /* errorMessage is already set */
1017 
1018  if (result == 0)
1019  {
1020  libpq_append_conn_error(conn, "timeout expired");
1021  return 1;
1022  }
1023 
1024  return 0;
1025 }

References conn, end_time, libpq_append_conn_error(), and pqSocketCheck().

Referenced by pqConnectDBComplete(), and pqWait().

◆ pqWriteReady()

int pqWriteReady ( PGconn conn)

Definition at line 1042 of file fe-misc.c.

1043 {
1044  return pqSocketCheck(conn, 0, 1, 0);
1045 }

References conn, and pqSocketCheck().

Variable Documentation

◆ pg_g_threadlock

pgthreadlock_t pg_g_threadlock
extern

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

Referenced by PQregisterThreadLock().

◆ pgresStatus

char* const pgresStatus[]
extern

Definition at line 32 of file fe-exec.c.

Referenced by PQresStatus().