PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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 343 of file libpq-int.h.

◆ AUTH_RESPONSE_PASSWORD

#define AUTH_RESPONSE_PASSWORD   'P'

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

◆ AUTH_RESPONSE_SASL

#define AUTH_RESPONSE_SASL   'S'

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

◆ AUTH_RESPONSE_SASL_INITIAL

#define AUTH_RESPONSE_SASL_INITIAL   'I'

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

◆ CMDSTATUS_LEN

#define CMDSTATUS_LEN   64 /* should match COMPLETION_TAG_BUFSIZE */

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

◆ ENC_ERROR

#define ENC_ERROR   0

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

◆ ENC_GSSAPI

#define ENC_GSSAPI   0x02

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

◆ ENC_PLAINTEXT

#define ENC_PLAINTEXT   0x01

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

◆ ENC_SSL

#define ENC_SSL   0x04

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

◆ libpq_gettext

#define libpq_gettext (   x)    (x)

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

◆ libpq_ngettext

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

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

◆ NULL_LEN

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

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

◆ OUTBUFFER_THRESHOLD

#define OUTBUFFER_THRESHOLD   65536

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

◆ pgHavePendingResult

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

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

◆ pglock_thread

#define pglock_thread ( )    pg_g_threadlock(true)

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

◆ pgunlock_thread

#define pgunlock_thread ( )    pg_g_threadlock(false)

Definition at line 714 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:53

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

◆ pqIsnonblocking

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

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

◆ SOCK_ERRNO

#define SOCK_ERRNO   errno

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

◆ SOCK_ERRNO_SET

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

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

◆ SOCK_STRERROR

#define SOCK_STRERROR   strerror_r

Definition at line 937 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 106 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 315 of file libpq-int.h.

316{
pg_conn_host_type
Definition: libpq-int.h:316
@ CHT_UNIX_SOCKET
Definition: libpq-int.h:319
@ CHT_HOST_ADDRESS
Definition: libpq-int.h:318
@ CHT_HOST_NAME
Definition: libpq-int.h:317

◆ 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 221 of file libpq-int.h.

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

◆ PGLoadBalanceType

Enumerator
LOAD_BALANCE_DISABLE 
LOAD_BALANCE_RANDOM 

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

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

◆ PGQueryClass

Enumerator
PGQUERY_SIMPLE 
PGQUERY_EXTENDED 
PGQUERY_PREPARE 
PGQUERY_DESCRIBE 
PGQUERY_SYNC 
PGQUERY_CLOSE 

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

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

◆ 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 243 of file libpq-int.h.

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

◆ PGTernaryBool

Enumerator
PG_BOOL_UNKNOWN 
PG_BOOL_YES 
PG_BOOL_NO 

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

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

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:590
bool ssl_in_use
Definition: libpq-int.h:589

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 */
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
125rloop:
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 */
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:937
#define SOCK_ERRNO
Definition: libpq-int.h:936
#define SOCK_ERRNO_SET(e)
Definition: libpq-int.h:938
#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:652
#define ECONNRESET
Definition: win32_port.h:374

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:815
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:72
char * host
Definition: libpq-int.h:366
int whichhost
Definition: libpq-int.h:472
pg_conn_host * connhost
Definition: libpq-int.h:473
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
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:163

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)
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,
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)
1135 libpq_gettext("SCHEMA NAME: %s\n"), val);
1137 if (val)
1139 libpq_gettext("TABLE NAME: %s\n"), val);
1141 if (val)
1143 libpq_gettext("COLUMN NAME: %s\n"), val);
1145 if (val)
1147 libpq_gettext("DATATYPE NAME: %s\n"), val);
1149 if (val)
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:915
#define PG_DIAG_INTERNAL_QUERY
Definition: postgres_ext.h:63
#define PG_DIAG_SCHEMA_NAME
Definition: postgres_ext.h:65
#define PG_DIAG_CONSTRAINT_NAME
Definition: postgres_ext.h:69
#define PG_DIAG_DATATYPE_NAME
Definition: postgres_ext.h:68
#define PG_DIAG_SOURCE_LINE
Definition: postgres_ext.h:71
#define PG_DIAG_STATEMENT_POSITION
Definition: postgres_ext.h:61
#define PG_DIAG_SOURCE_FILE
Definition: postgres_ext.h:70
#define PG_DIAG_MESSAGE_HINT
Definition: postgres_ext.h:60
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:57
#define PG_DIAG_TABLE_NAME
Definition: postgres_ext.h:66
#define PG_DIAG_MESSAGE_PRIMARY
Definition: postgres_ext.h:58
#define PG_DIAG_COLUMN_NAME
Definition: postgres_ext.h:67
#define PG_DIAG_MESSAGE_DETAIL
Definition: postgres_ext.h:59
#define PG_DIAG_CONTEXT
Definition: postgres_ext.h:64
#define PG_DIAG_SEVERITY
Definition: postgres_ext.h:55
#define PG_DIAG_SOURCE_FUNCTION
Definition: postgres_ext.h:72
#define PG_DIAG_INTERNAL_POSITION
Definition: postgres_ext.h:62
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:201
PGMessageField * errFields
Definition: libpq-int.h:202
ExecStatusType resultStatus
Definition: libpq-int.h:182
char * errQuery
Definition: libpq-int.h:203
int client_encoding
Definition: libpq-int.h:194

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;
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:545
int inCursor
Definition: libpq-int.h:548
int inEnd
Definition: libpq-int.h:549
int inBufSize
Definition: libpq-int.h:546
int inStart
Definition: libpq-int.h:547

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:553
char * outBuffer
Definition: libpq-int.h:552

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{
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:575
PGresult * saved_result
Definition: libpq-int.h:577
bool error_result
Definition: libpq-int.h:576

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

4894{
4895 /*
4896 * If possible, send Terminate message to close the connection politely.
4897 */
4899
4900 /*
4901 * Must reset the blocking status so a possible reconnect will work.
4902 *
4903 * Don't call PQsetnonblocking() because it will fail if it's unable to
4904 * flush the connection.
4905 */
4906 conn->nonblocking = false;
4907
4908 /*
4909 * Close the connection, reset all transient state, flush I/O buffers.
4910 * Note that this includes clearing conn's error state; we're no longer
4911 * interested in any failures associated with the old connection, and we
4912 * want a clean slate for any new connection attempt.
4913 */
4914 pqDropConnection(conn, true);
4915 conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just absent */
4919 pqClearAsyncResult(conn); /* deallocate result */
4921
4922 /*
4923 * Release addrinfo, but since cancel requests never change their addrinfo
4924 * we don't do that. Otherwise we would have to rebuild it during a
4925 * PQcancelReset.
4926 */
4927 if (!conn->cancelRequest)
4929
4930 /* Reset all state obtained from server, too */
4932}
void pqDropConnection(PGconn *conn, bool flushInput)
Definition: fe-connect.c:480
static void sendTerminateConn(PGconn *conn)
Definition: fe-connect.c:4859
static void release_conn_addrinfo(PGconn *conn)
Definition: fe-connect.c:4845
static void pqDropServerData(PGconn *conn)
Definition: fe-connect.c:593
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:888
PGTransactionStatusType xactStatus
Definition: libpq-int.h:455
bool cancelRequest
Definition: libpq-int.h:436
bool nonblocking
Definition: libpq-int.h:458
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:454
PGpipelineStatus pipelineStatus
Definition: libpq-int.h:460
ConnStatusType status
Definition: libpq-int.h:453

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:353
struct PGcmdQueueEntry * next
Definition: libpq-int.h:355
PGcmdQueueEntry * cmd_queue_tail
Definition: libpq-int.h:481
PGcmdQueueEntry * cmd_queue_head
Definition: libpq-int.h:480

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

2530{
2533 int timeout = 0;
2534 int last_whichhost = -2; /* certainly different from whichhost */
2535 int last_whichaddr = -2; /* certainly different from whichaddr */
2536
2537 if (conn == NULL || conn->status == CONNECTION_BAD)
2538 return 0;
2539
2540 /*
2541 * Set up a time limit, if connect_timeout is greater than zero.
2542 */
2543 if (conn->connect_timeout != NULL)
2544 {
2545 if (!pqParseIntParam(conn->connect_timeout, &timeout, conn,
2546 "connect_timeout"))
2547 {
2548 /* mark the connection as bad to report the parsing failure */
2550 return 0;
2551 }
2552 }
2553
2554 for (;;)
2555 {
2556 int ret = 0;
2557
2558 /*
2559 * (Re)start the connect_timeout timer if it's active and we are
2560 * considering a different host than we were last time through. If
2561 * we've already succeeded, though, needn't recalculate.
2562 */
2563 if (flag != PGRES_POLLING_OK &&
2564 timeout > 0 &&
2565 (conn->whichhost != last_whichhost ||
2566 conn->whichaddr != last_whichaddr))
2567 {
2568 end_time = PQgetCurrentTimeUSec() + (pg_usec_time_t) timeout * 1000000;
2569 last_whichhost = conn->whichhost;
2570 last_whichaddr = conn->whichaddr;
2571 }
2572
2573 /*
2574 * Wait, if necessary. Note that the initial state (just after
2575 * PQconnectStart) is to wait for the socket to select for writing.
2576 */
2577 switch (flag)
2578 {
2579 case PGRES_POLLING_OK:
2580 return 1; /* success! */
2581
2583 ret = pqWaitTimed(1, 0, conn, end_time);
2584 if (ret == -1)
2585 {
2586 /* hard failure, eg select() problem, aborts everything */
2588 return 0;
2589 }
2590 break;
2591
2593 ret = pqWaitTimed(0, 1, conn, end_time);
2594 if (ret == -1)
2595 {
2596 /* hard failure, eg select() problem, aborts everything */
2598 return 0;
2599 }
2600 break;
2601
2602 default:
2603 /* Just in case we failed to set it in PQconnectPoll */
2605 return 0;
2606 }
2607
2608 if (ret == 1) /* connect_timeout elapsed */
2609 {
2610 /*
2611 * Give up on current server/address, try the next one.
2612 */
2613 conn->try_next_addr = true;
2615 }
2616
2617 /*
2618 * Now try to advance the state machine.
2619 */
2620 if (conn->cancelRequest)
2622 else
2624 }
2625}
PostgresPollingStatusType PQcancelPoll(PGcancelConn *cancelConn)
Definition: fe-cancel.c:207
PostgresPollingStatusType PQconnectPoll(PGconn *conn)
Definition: fe-connect.c:2655
bool pqParseIntParam(const char *value, int *result, PGconn *conn, const char *context)
Definition: fe-connect.c:7824
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:521
char * connect_timeout
Definition: libpq-int.h:391
bool try_next_addr
Definition: libpq-int.h:518
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 2451 of file fe-connect.c.

2452{
2453 if (!conn)
2454 return 0;
2455
2456 if (!conn->options_valid)
2457 goto connect_errReturn;
2458
2459 /*
2460 * Check for bad linking to backend-internal versions of src/common
2461 * functions (see comments in link-canary.c for the reason we need this).
2462 * Nobody but developers should see this message, so we don't bother
2463 * translating it.
2464 */
2466 {
2468 "libpq is incorrectly linked to backend functions\n");
2469 goto connect_errReturn;
2470 }
2471
2472 /* Ensure our buffers are empty */
2473 conn->inStart = conn->inCursor = conn->inEnd = 0;
2474 conn->outCount = 0;
2475
2476 /*
2477 * Set up to try to connect to the first host. (Setting whichhost = -1 is
2478 * a bit of a cheat, but PQconnectPoll will advance it to 0 before
2479 * anything else looks at it.)
2480 *
2481 * Cancel requests are special though, they should only try one host and
2482 * address, and these fields have already been set up in PQcancelCreate,
2483 * so leave these fields alone for cancel requests.
2484 */
2485 if (!conn->cancelRequest)
2486 {
2487 conn->whichhost = -1;
2488 conn->try_next_host = true;
2489 conn->try_next_addr = false;
2490 }
2491
2493
2494 /* Also reset the target_server_type state if needed */
2497
2498 /*
2499 * The code for processing CONNECTION_NEEDED state is in PQconnectPoll(),
2500 * so that it can easily be re-executed if needed again during the
2501 * asynchronous startup process. However, we must run it once here,
2502 * because callers expect a success return from this routine to mean that
2503 * we are in PGRES_POLLING_WRITING connection state.
2504 */
2506 return 1;
2507
2508connect_errReturn:
2509
2510 /*
2511 * If we managed to open a socket, close it immediately rather than
2512 * waiting till PQfinish. (The application cannot have gotten the socket
2513 * from PQsocket yet, so this doesn't risk breaking anything.)
2514 */
2515 pqDropConnection(conn, true);
2517 return 0;
2518}
bool try_next_host
Definition: libpq-int.h:519
bool options_valid
Definition: libpq-int.h:457
PGTargetServerType target_server_type
Definition: libpq-int.h:515
int outCount
Definition: libpq-int.h:554

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

1130{
1131 int i;
1132
1133 /*
1134 * Allocate memory for details about each host to which we might possibly
1135 * try to connect. For that, count the number of elements in the hostaddr
1136 * or host options. If neither is given, assume one host.
1137 */
1138 conn->whichhost = 0;
1139 if (conn->pghostaddr && conn->pghostaddr[0] != '\0')
1141 else if (conn->pghost && conn->pghost[0] != '\0')
1143 else
1144 conn->nconnhost = 1;
1146 calloc(conn->nconnhost, sizeof(pg_conn_host));
1147 if (conn->connhost == NULL)
1148 goto oom_error;
1149
1150 /*
1151 * We now have one pg_conn_host structure per possible host. Fill in the
1152 * host and hostaddr fields for each, by splitting the parameter strings.
1153 */
1154 if (conn->pghostaddr != NULL && conn->pghostaddr[0] != '\0')
1155 {
1156 char *s = conn->pghostaddr;
1157 bool more = true;
1158
1159 for (i = 0; i < conn->nconnhost && more; i++)
1160 {
1162 if (conn->connhost[i].hostaddr == NULL)
1163 goto oom_error;
1164 }
1165
1166 /*
1167 * If hostaddr was given, the array was allocated according to the
1168 * number of elements in the hostaddr list, so it really should be the
1169 * right size.
1170 */
1171 Assert(!more);
1172 Assert(i == conn->nconnhost);
1173 }
1174
1175 if (conn->pghost != NULL && conn->pghost[0] != '\0')
1176 {
1177 char *s = conn->pghost;
1178 bool more = true;
1179
1180 for (i = 0; i < conn->nconnhost && more; i++)
1181 {
1183 if (conn->connhost[i].host == NULL)
1184 goto oom_error;
1185 }
1186
1187 /* Check for wrong number of host items. */
1188 if (more || i != conn->nconnhost)
1189 {
1191 libpq_append_conn_error(conn, "could not match %d host names to %d hostaddr values",
1193 return false;
1194 }
1195 }
1196
1197 /*
1198 * Now, for each host slot, identify the type of address spec, and fill in
1199 * the default address if nothing was given.
1200 */
1201 for (i = 0; i < conn->nconnhost; i++)
1202 {
1203 pg_conn_host *ch = &conn->connhost[i];
1204
1205 if (ch->hostaddr != NULL && ch->hostaddr[0] != '\0')
1206 ch->type = CHT_HOST_ADDRESS;
1207 else if (ch->host != NULL && ch->host[0] != '\0')
1208 {
1209 ch->type = CHT_HOST_NAME;
1210 if (is_unixsock_path(ch->host))
1211 ch->type = CHT_UNIX_SOCKET;
1212 }
1213 else
1214 {
1215 free(ch->host);
1216
1217 /*
1218 * This bit selects the default host location. If you change
1219 * this, see also pg_regress.
1220 */
1221 if (DEFAULT_PGSOCKET_DIR[0])
1222 {
1223 ch->host = strdup(DEFAULT_PGSOCKET_DIR);
1224 ch->type = CHT_UNIX_SOCKET;
1225 }
1226 else
1227 {
1228 ch->host = strdup(DefaultHost);
1229 ch->type = CHT_HOST_NAME;
1230 }
1231 if (ch->host == NULL)
1232 goto oom_error;
1233 }
1234 }
1235
1236 /*
1237 * Next, work out the port number corresponding to each host name.
1238 *
1239 * Note: unlike the above for host names, this could leave the port fields
1240 * as null or empty strings. We will substitute DEF_PGPORT whenever we
1241 * read such a port field.
1242 */
1243 if (conn->pgport != NULL && conn->pgport[0] != '\0')
1244 {
1245 char *s = conn->pgport;
1246 bool more = true;
1247
1248 for (i = 0; i < conn->nconnhost && more; i++)
1249 {
1251 if (conn->connhost[i].port == NULL)
1252 goto oom_error;
1253 }
1254
1255 /*
1256 * If exactly one port was given, use it for every host. Otherwise,
1257 * there must be exactly as many ports as there were hosts.
1258 */
1259 if (i == 1 && !more)
1260 {
1261 for (i = 1; i < conn->nconnhost; i++)
1262 {
1263 conn->connhost[i].port = strdup(conn->connhost[0].port);
1264 if (conn->connhost[i].port == NULL)
1265 goto oom_error;
1266 }
1267 }
1268 else if (more || i != conn->nconnhost)
1269 {
1271 libpq_append_conn_error(conn, "could not match %d port numbers to %d hosts",
1273 return false;
1274 }
1275 }
1276
1277 /*
1278 * If user name was not given, fetch it. (Most likely, the fetch will
1279 * fail, since the only way we get here is if pg_fe_getauthname() failed
1280 * during conninfo_add_defaults(). But now we want an error message.)
1281 */
1282 if (conn->pguser == NULL || conn->pguser[0] == '\0')
1283 {
1284 free(conn->pguser);
1286 if (!conn->pguser)
1287 {
1289 return false;
1290 }
1291 }
1292
1293 /*
1294 * If database name was not given, default it to equal user name
1295 */
1296 if (conn->dbName == NULL || conn->dbName[0] == '\0')
1297 {
1298 free(conn->dbName);
1299 conn->dbName = strdup(conn->pguser);
1300 if (!conn->dbName)
1301 goto oom_error;
1302 }
1303
1304 /*
1305 * If password was not given, try to look it up in password file. Note
1306 * that the result might be different for each host/port pair.
1307 */
1308 if (conn->pgpass == NULL || conn->pgpass[0] == '\0')
1309 {
1310 /* If password file wasn't specified, use ~/PGPASSFILE */
1311 if (conn->pgpassfile == NULL || conn->pgpassfile[0] == '\0')
1312 {
1313 char homedir[MAXPGPATH];
1314
1315 if (pqGetHomeDirectory(homedir, sizeof(homedir)))
1316 {
1319 if (!conn->pgpassfile)
1320 goto oom_error;
1321 snprintf(conn->pgpassfile, MAXPGPATH, "%s/%s",
1322 homedir, PGPASSFILE);
1323 }
1324 }
1325
1326 if (conn->pgpassfile != NULL && conn->pgpassfile[0] != '\0')
1327 {
1328 for (i = 0; i < conn->nconnhost; i++)
1329 {
1330 /*
1331 * Try to get a password for this host from file. We use host
1332 * for the hostname search key if given, else hostaddr (at
1333 * least one of them is guaranteed nonempty by now).
1334 */
1335 const char *pwhost = conn->connhost[i].host;
1336
1337 if (pwhost == NULL || pwhost[0] == '\0')
1338 pwhost = conn->connhost[i].hostaddr;
1339
1341 passwordFromFile(pwhost,
1342 conn->connhost[i].port,
1343 conn->dbName,
1344 conn->pguser,
1345 conn->pgpassfile);
1346 }
1347 }
1348 }
1349
1350 /*
1351 * parse and validate require_auth option
1352 */
1353 if (conn->require_auth && conn->require_auth[0])
1354 {
1355 char *s = conn->require_auth;
1356 bool first,
1357 more;
1358 bool negated = false;
1359
1360 /*
1361 * By default, start from an empty set of allowed options and add to
1362 * it.
1363 */
1364 conn->auth_required = true;
1366
1367 for (first = true, more = true; more; first = false)
1368 {
1369 char *method,
1370 *part;
1371 uint32 bits;
1372
1373 part = parse_comma_separated_list(&s, &more);
1374 if (part == NULL)
1375 goto oom_error;
1376
1377 /*
1378 * Check for negation, e.g. '!password'. If one element is
1379 * negated, they all have to be.
1380 */
1381 method = part;
1382 if (*method == '!')
1383 {
1384 if (first)
1385 {
1386 /*
1387 * Switch to a permissive set of allowed options, and
1388 * subtract from it.
1389 */
1390 conn->auth_required = false;
1392 }
1393 else if (!negated)
1394 {
1396 libpq_append_conn_error(conn, "negative require_auth method \"%s\" cannot be mixed with non-negative methods",
1397 method);
1398
1399 free(part);
1400 return false;
1401 }
1402
1403 negated = true;
1404 method++;
1405 }
1406 else if (negated)
1407 {
1409 libpq_append_conn_error(conn, "require_auth method \"%s\" cannot be mixed with negative methods",
1410 method);
1411
1412 free(part);
1413 return false;
1414 }
1415
1416 if (strcmp(method, "password") == 0)
1417 {
1418 bits = (1 << AUTH_REQ_PASSWORD);
1419 }
1420 else if (strcmp(method, "md5") == 0)
1421 {
1422 bits = (1 << AUTH_REQ_MD5);
1423 }
1424 else if (strcmp(method, "gss") == 0)
1425 {
1426 bits = (1 << AUTH_REQ_GSS);
1427 bits |= (1 << AUTH_REQ_GSS_CONT);
1428 }
1429 else if (strcmp(method, "sspi") == 0)
1430 {
1431 bits = (1 << AUTH_REQ_SSPI);
1432 bits |= (1 << AUTH_REQ_GSS_CONT);
1433 }
1434 else if (strcmp(method, "scram-sha-256") == 0)
1435 {
1436 /* This currently assumes that SCRAM is the only SASL method. */
1437 bits = (1 << AUTH_REQ_SASL);
1438 bits |= (1 << AUTH_REQ_SASL_CONT);
1439 bits |= (1 << AUTH_REQ_SASL_FIN);
1440 }
1441 else if (strcmp(method, "none") == 0)
1442 {
1443 /*
1444 * Special case: let the user explicitly allow (or disallow)
1445 * connections where the server does not send an explicit
1446 * authentication challenge, such as "trust" and "cert" auth.
1447 */
1448 if (negated) /* "!none" */
1449 {
1450 if (conn->auth_required)
1451 goto duplicate;
1452
1453 conn->auth_required = true;
1454 }
1455 else /* "none" */
1456 {
1457 if (!conn->auth_required)
1458 goto duplicate;
1459
1460 conn->auth_required = false;
1461 }
1462
1463 free(part);
1464 continue; /* avoid the bitmask manipulation below */
1465 }
1466 else
1467 {
1469 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1470 "require_auth", method);
1471
1472 free(part);
1473 return false;
1474 }
1475
1476 /* Update the bitmask. */
1477 if (negated)
1478 {
1479 if ((conn->allowed_auth_methods & bits) == 0)
1480 goto duplicate;
1481
1482 conn->allowed_auth_methods &= ~bits;
1483 }
1484 else
1485 {
1486 if ((conn->allowed_auth_methods & bits) == bits)
1487 goto duplicate;
1488
1489 conn->allowed_auth_methods |= bits;
1490 }
1491
1492 free(part);
1493 continue;
1494
1495 duplicate:
1496
1497 /*
1498 * A duplicated method probably indicates a typo in a setting
1499 * where typos are extremely risky.
1500 */
1502 libpq_append_conn_error(conn, "require_auth method \"%s\" is specified more than once",
1503 part);
1504
1505 free(part);
1506 return false;
1507 }
1508 }
1509
1510 /*
1511 * validate channel_binding option
1512 */
1513 if (conn->channel_binding)
1514 {
1515 if (strcmp(conn->channel_binding, "disable") != 0
1516 && strcmp(conn->channel_binding, "prefer") != 0
1517 && strcmp(conn->channel_binding, "require") != 0)
1518 {
1520 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1521 "channel_binding", conn->channel_binding);
1522 return false;
1523 }
1524 }
1525 else
1526 {
1528 if (!conn->channel_binding)
1529 goto oom_error;
1530 }
1531
1532#ifndef USE_SSL
1533
1534 /*
1535 * sslrootcert=system is not supported. Since setting this changes the
1536 * default sslmode, check this _before_ we validate sslmode, to avoid
1537 * confusing the user with errors for an option they may not have set.
1538 */
1539 if (conn->sslrootcert
1540 && strcmp(conn->sslrootcert, "system") == 0)
1541 {
1543 libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in",
1544 "sslrootcert", conn->sslrootcert);
1545 return false;
1546 }
1547#endif
1548
1549 /*
1550 * validate sslmode option
1551 */
1552 if (conn->sslmode)
1553 {
1554 if (strcmp(conn->sslmode, "disable") != 0
1555 && strcmp(conn->sslmode, "allow") != 0
1556 && strcmp(conn->sslmode, "prefer") != 0
1557 && strcmp(conn->sslmode, "require") != 0
1558 && strcmp(conn->sslmode, "verify-ca") != 0
1559 && strcmp(conn->sslmode, "verify-full") != 0)
1560 {
1562 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1563 "sslmode", conn->sslmode);
1564 return false;
1565 }
1566
1567#ifndef USE_SSL
1568 switch (conn->sslmode[0])
1569 {
1570 case 'a': /* "allow" */
1571 case 'p': /* "prefer" */
1572
1573 /*
1574 * warn user that an SSL connection will never be negotiated
1575 * since SSL was not compiled in?
1576 */
1577 break;
1578
1579 case 'r': /* "require" */
1580 case 'v': /* "verify-ca" or "verify-full" */
1582 libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in",
1583 "sslmode", conn->sslmode);
1584 return false;
1585 }
1586#endif
1587 }
1588 else
1589 {
1590 conn->sslmode = strdup(DefaultSSLMode);
1591 if (!conn->sslmode)
1592 goto oom_error;
1593 }
1594
1595 /*
1596 * validate sslnegotiation option, default is "postgres" for the postgres
1597 * style negotiated connection with an extra round trip but more options.
1598 */
1599 if (conn->sslnegotiation)
1600 {
1601 if (strcmp(conn->sslnegotiation, "postgres") != 0
1602 && strcmp(conn->sslnegotiation, "direct") != 0)
1603 {
1605 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1606 "sslnegotiation", conn->sslnegotiation);
1607 return false;
1608 }
1609
1610#ifndef USE_SSL
1611 if (conn->sslnegotiation[0] != 'p')
1612 {
1614 libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in",
1615 "sslnegotiation", conn->sslnegotiation);
1616 return false;
1617 }
1618#endif
1619
1620 /*
1621 * Don't allow direct SSL negotiation with sslmode='prefer', because
1622 * that poses a risk of unintentional fallback to plaintext connection
1623 * when connecting to a pre-v17 server that does not support direct
1624 * SSL connections. To keep things simple, don't allow it with
1625 * sslmode='allow' or sslmode='disable' either. If a user goes through
1626 * the trouble of setting sslnegotiation='direct', they probably
1627 * intend to use SSL, and sslmode=disable or allow is probably a user
1628 * user mistake anyway.
1629 */
1630 if (conn->sslnegotiation[0] == 'd' &&
1631 conn->sslmode[0] != 'r' && conn->sslmode[0] != 'v')
1632 {
1634 libpq_append_conn_error(conn, "weak sslmode \"%s\" may not be used with sslnegotiation=direct (use \"require\", \"verify-ca\", or \"verify-full\")",
1635 conn->sslmode);
1636 return false;
1637 }
1638 }
1639 else
1640 {
1642 if (!conn->sslnegotiation)
1643 goto oom_error;
1644 }
1645
1646#ifdef USE_SSL
1647
1648 /*
1649 * If sslrootcert=system, make sure our chosen sslmode is compatible.
1650 */
1651 if (conn->sslrootcert
1652 && strcmp(conn->sslrootcert, "system") == 0
1653 && strcmp(conn->sslmode, "verify-full") != 0)
1654 {
1656 libpq_append_conn_error(conn, "weak sslmode \"%s\" may not be used with sslrootcert=system (use \"verify-full\")",
1657 conn->sslmode);
1658 return false;
1659 }
1660#endif
1661
1662 /*
1663 * Validate TLS protocol versions for ssl_min_protocol_version and
1664 * ssl_max_protocol_version.
1665 */
1667 {
1669 libpq_append_conn_error(conn, "invalid \"%s\" value: \"%s\"",
1670 "ssl_min_protocol_version",
1672 return false;
1673 }
1675 {
1677 libpq_append_conn_error(conn, "invalid \"%s\" value: \"%s\"",
1678 "ssl_max_protocol_version",
1680 return false;
1681 }
1682
1683 /*
1684 * Check if the range of SSL protocols defined is correct. This is done
1685 * at this early step because this is independent of the SSL
1686 * implementation used, and this avoids unnecessary cycles with an
1687 * already-built SSL context when the connection is being established, as
1688 * it would be doomed anyway.
1689 */
1692 {
1694 libpq_append_conn_error(conn, "invalid SSL protocol version range");
1695 return false;
1696 }
1697
1698 /*
1699 * validate sslcertmode option
1700 */
1701 if (conn->sslcertmode)
1702 {
1703 if (strcmp(conn->sslcertmode, "disable") != 0 &&
1704 strcmp(conn->sslcertmode, "allow") != 0 &&
1705 strcmp(conn->sslcertmode, "require") != 0)
1706 {
1708 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1709 "sslcertmode", conn->sslcertmode);
1710 return false;
1711 }
1712#ifndef USE_SSL
1713 if (strcmp(conn->sslcertmode, "require") == 0)
1714 {
1716 libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in",
1717 "sslcertmode", conn->sslcertmode);
1718 return false;
1719 }
1720#endif
1721#ifndef HAVE_SSL_CTX_SET_CERT_CB
1722
1723 /*
1724 * Without a certificate callback, the current implementation can't
1725 * figure out if a certificate was actually requested, so "require" is
1726 * useless.
1727 */
1728 if (strcmp(conn->sslcertmode, "require") == 0)
1729 {
1731 libpq_append_conn_error(conn, "%s value \"%s\" is not supported (check OpenSSL version)",
1732 "sslcertmode", conn->sslcertmode);
1733 return false;
1734 }
1735#endif
1736 }
1737 else
1738 {
1740 if (!conn->sslcertmode)
1741 goto oom_error;
1742 }
1743
1744 /*
1745 * validate gssencmode option
1746 */
1747 if (conn->gssencmode)
1748 {
1749 if (strcmp(conn->gssencmode, "disable") != 0 &&
1750 strcmp(conn->gssencmode, "prefer") != 0 &&
1751 strcmp(conn->gssencmode, "require") != 0)
1752 {
1754 libpq_append_conn_error(conn, "invalid %s value: \"%s\"", "gssencmode", conn->gssencmode);
1755 return false;
1756 }
1757#ifndef ENABLE_GSS
1758 if (strcmp(conn->gssencmode, "require") == 0)
1759 {
1761 libpq_append_conn_error(conn, "gssencmode value \"%s\" invalid when GSSAPI support is not compiled in",
1762 conn->gssencmode);
1763 return false;
1764 }
1765#endif
1766 }
1767 else
1768 {
1769 conn->gssencmode = strdup(DefaultGSSMode);
1770 if (!conn->gssencmode)
1771 goto oom_error;
1772 }
1773
1774 /*
1775 * validate target_session_attrs option, and set target_server_type
1776 */
1778 {
1779 if (strcmp(conn->target_session_attrs, "any") == 0)
1781 else if (strcmp(conn->target_session_attrs, "read-write") == 0)
1783 else if (strcmp(conn->target_session_attrs, "read-only") == 0)
1785 else if (strcmp(conn->target_session_attrs, "primary") == 0)
1787 else if (strcmp(conn->target_session_attrs, "standby") == 0)
1789 else if (strcmp(conn->target_session_attrs, "prefer-standby") == 0)
1791 else
1792 {
1794 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1795 "target_session_attrs",
1797 return false;
1798 }
1799 }
1800 else
1802
1804 {
1805 int len;
1806
1810 goto oom_error;
1813 if (len < 0)
1814 {
1815 libpq_append_conn_error(conn, "invalid SCRAM client key");
1817 return false;
1818 }
1819 if (len != SCRAM_MAX_KEY_LEN)
1820 {
1821 libpq_append_conn_error(conn, "invalid SCRAM client key length: %d", len);
1823 return false;
1824 }
1826 }
1827
1829 {
1830 int len;
1831
1835 goto oom_error;
1838 if (len < 0)
1839 {
1840 libpq_append_conn_error(conn, "invalid SCRAM server key");
1842 return false;
1843 }
1844 if (len != SCRAM_MAX_KEY_LEN)
1845 {
1846 libpq_append_conn_error(conn, "invalid SCRAM server key length: %d", len);
1848 return false;
1849 }
1851 }
1852
1853 /*
1854 * validate load_balance_hosts option, and set load_balance_type
1855 */
1857 {
1858 if (strcmp(conn->load_balance_hosts, "disable") == 0)
1860 else if (strcmp(conn->load_balance_hosts, "random") == 0)
1862 else
1863 {
1865 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1866 "load_balance_hosts",
1868 return false;
1869 }
1870 }
1871 else
1873
1875 {
1877
1878 /*
1879 * This is the "inside-out" variant of the Fisher-Yates shuffle
1880 * algorithm. Notionally, we append each new value to the array and
1881 * then swap it with a randomly-chosen array element (possibly
1882 * including itself, else we fail to generate permutations with the
1883 * last integer last). The swap step can be optimized by combining it
1884 * with the insertion.
1885 */
1886 for (i = 1; i < conn->nconnhost; i++)
1887 {
1888 int j = pg_prng_uint64_range(&conn->prng_state, 0, i);
1889 pg_conn_host temp = conn->connhost[j];
1890
1891 conn->connhost[j] = conn->connhost[i];
1892 conn->connhost[i] = temp;
1893 }
1894 }
1895
1896 /*
1897 * Resolve special "auto" client_encoding from the locale
1898 */
1900 strcmp(conn->client_encoding_initial, "auto") == 0)
1901 {
1905 goto oom_error;
1906 }
1907
1908 /*
1909 * Only if we get this far is it appropriate to try to connect. (We need a
1910 * state flag, rather than just the boolean result of this function, in
1911 * case someone tries to PQreset() the PGconn.)
1912 */
1913 conn->options_valid = true;
1914
1915 return true;
1916
1917oom_error:
1919 libpq_append_conn_error(conn, "out of memory");
1920 return false;
1921}
int pg_b64_decode(const char *src, int len, char *dst, int dstlen)
Definition: base64.c:116
int pg_b64_dec_len(int srclen)
Definition: base64.c:239
uint32_t uint32
Definition: c.h:488
char * pg_fe_getauthname(PQExpBuffer errorMessage)
Definition: fe-auth.c:1255
#define DefaultHost
Definition: fe-connect.c:118
static char * passwordFromFile(const char *hostname, const char *port, const char *dbname, const char *username, const char *pgpassfile)
Definition: fe-connect.c:7534
static bool sslVerifyProtocolRange(const char *min, const char *max)
Definition: fe-connect.c:7730
static void libpq_prng_init(PGconn *conn)
Definition: fe-connect.c:1102
bool pqGetHomeDirectory(char *buf, int bufsize)
Definition: fe-connect.c:7783
#define DefaultSSLMode
Definition: fe-connect.c:131
#define DefaultGSSMode
Definition: fe-connect.c:139
static int count_comma_separated_elems(const char *input)
Definition: fe-connect.c:1043
#define DefaultChannelBinding
Definition: fe-connect.c:123
static bool sslVerifyProtocolVersion(const char *version)
Definition: fe-connect.c:7704
#define DefaultSSLNegotiation
Definition: fe-connect.c:134
#define PGPASSFILE
Definition: fe-connect.c:77
#define DefaultSSLCertMode
Definition: fe-connect.c:132
static char * parse_comma_separated_list(char **startptr, bool *more)
Definition: fe-connect.c:1067
#define calloc(a, b)
Definition: header.h:55
int j
Definition: isn.c:73
#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
#define SCRAM_MAX_KEY_LEN
Definition: scram-common.h:30
char * password
Definition: libpq-int.h:369
char * port
Definition: libpq-int.h:368
char * hostaddr
Definition: libpq-int.h:367
pg_conn_host_type type
Definition: libpq-int.h:365
char * sslrootcert
Definition: libpq-int.h:418
char * sslnegotiation
Definition: libpq-int.h:412
int nconnhost
Definition: libpq-int.h:471
char * require_auth
Definition: libpq-int.h:431
char * channel_binding
Definition: libpq-int.h:403
void * scram_server_key_binary
Definition: libpq-int.h:528
char * pghost
Definition: libpq-int.h:381
size_t scram_client_key_len
Definition: libpq-int.h:525
char * ssl_max_protocol_version
Definition: libpq-int.h:429
char * pgpass
Definition: libpq-int.h:401
char * dbName
Definition: libpq-int.h:397
char * sslcertmode
Definition: libpq-int.h:417
uint32 allowed_auth_methods
Definition: libpq-int.h:506
char * target_session_attrs
Definition: libpq-int.h:430
bool auth_required
Definition: libpq-int.h:504
char * load_balance_hosts
Definition: libpq-int.h:432
char * pguser
Definition: libpq-int.h:400
char * client_encoding_initial
Definition: libpq-int.h:393
char * sslmode
Definition: libpq-int.h:411
pg_prng_state prng_state
Definition: libpq-int.h:541
char * ssl_min_protocol_version
Definition: libpq-int.h:428
char * gssencmode
Definition: libpq-int.h:423
char * scram_server_key
Definition: libpq-int.h:434
char * pghostaddr
Definition: libpq-int.h:385
void * scram_client_key_binary
Definition: libpq-int.h:526
char * scram_client_key
Definition: libpq-int.h:433
char * pgpassfile
Definition: libpq-int.h:402
PGLoadBalanceType load_balance_type
Definition: libpq-int.h:516
size_t scram_server_key_len
Definition: libpq-int.h:527
char * pgport
Definition: libpq-int.h:389

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, len, 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_b64_dec_len(), pg_b64_decode(), 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, pg_conn::scram_client_key, pg_conn::scram_client_key_binary, pg_conn::scram_client_key_len, SCRAM_MAX_KEY_LEN, pg_conn::scram_server_key, pg_conn::scram_server_key_binary, pg_conn::scram_server_key_len, 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 965 of file fe-connect.c.

966{
968
969 /* copy over connection options */
970 for (option = PQconninfoOptions; option->keyword; option++)
971 {
972 if (option->connofs >= 0)
973 {
974 const char **tmp = (const char **) ((char *) srcConn + option->connofs);
975
976 if (*tmp)
977 {
978 char **dstConnmember = (char **) ((char *) dstConn + option->connofs);
979
980 if (*dstConnmember)
981 free(*dstConnmember);
982 *dstConnmember = strdup(*tmp);
983 if (*dstConnmember == NULL)
984 {
985 libpq_append_conn_error(dstConn, "out of memory");
986 return false;
987 }
988 }
989 }
990 }
991 return true;
992}
static const internalPQconninfoOption PQconninfoOptions[]
Definition: fe-connect.c:192

References free, libpq_append_conn_error(), and PQconninfoOptions.

Referenced by PQcancelCreate().

◆ pqDropConnection()

void pqDropConnection ( PGconn conn,
bool  flushInput 
)

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

481{
482 /* Drop any SSL state */
484
485 /* Close the socket itself */
486 if (conn->sock != PGINVALID_SOCKET)
489
490 /* Optionally discard any unread data */
491 if (flushInput)
492 conn->inStart = conn->inCursor = conn->inEnd = 0;
493
494 /* Always discard any unsent data */
495 conn->outCount = 0;
496
497 /* Likewise, discard any pending pipelined commands */
501 conn->cmd_queue_recycle = NULL;
502
503 /* Free authentication/encryption state */
504#ifdef ENABLE_GSS
505 {
506 OM_uint32 min_s;
507
508 if (conn->gcred != GSS_C_NO_CREDENTIAL)
509 {
510 gss_release_cred(&min_s, &conn->gcred);
511 conn->gcred = GSS_C_NO_CREDENTIAL;
512 }
513 if (conn->gctx)
514 gss_delete_sec_context(&min_s, &conn->gctx, GSS_C_NO_BUFFER);
515 if (conn->gtarg_nam)
516 gss_release_name(&min_s, &conn->gtarg_nam);
517 if (conn->gss_SendBuffer)
518 {
519 free(conn->gss_SendBuffer);
520 conn->gss_SendBuffer = NULL;
521 }
522 if (conn->gss_RecvBuffer)
523 {
524 free(conn->gss_RecvBuffer);
525 conn->gss_RecvBuffer = NULL;
526 }
527 if (conn->gss_ResultBuffer)
528 {
529 free(conn->gss_ResultBuffer);
530 conn->gss_ResultBuffer = NULL;
531 }
532 conn->gssenc = false;
533 }
534#endif
535#ifdef ENABLE_SSPI
536 if (conn->sspitarget)
537 {
538 free(conn->sspitarget);
539 conn->sspitarget = NULL;
540 }
541 if (conn->sspicred)
542 {
543 FreeCredentialsHandle(conn->sspicred);
544 free(conn->sspicred);
545 conn->sspicred = NULL;
546 }
547 if (conn->sspictx)
548 {
549 DeleteSecurityContext(conn->sspictx);
550 free(conn->sspictx);
551 conn->sspictx = NULL;
552 }
553 conn->usesspi = 0;
554#endif
555 if (conn->sasl_state)
556 {
558 conn->sasl_state = NULL;
559 }
560}
static void pqFreeCommandQueue(PGcmdQueueEntry *queue)
Definition: fe-connect.c:567
void pqsecure_close(PGconn *conn)
Definition: fe-secure.c:152
#define PGINVALID_SOCKET
Definition: port.h:31
#define closesocket
Definition: port.h:376
pgsocket sock
Definition: libpq-int.h:490
const pg_fe_sasl_mech * sasl
Definition: libpq-int.h:580
PGcmdQueueEntry * cmd_queue_recycle
Definition: libpq-int.h:487
void * sasl_state
Definition: libpq-int.h:581
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
1915 {
1916 libpq_append_conn_error(conn, "no COPY in progress");
1917 return 1;
1918 }
1919
1920 /* Send the CopyDone message if needed */
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 */
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 */
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}
PGresult * PQgetResult(PGconn *conn)
Definition: fe-exec.c:2062
void pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
Definition: fe-exec.c:938
int PQisBusy(PGconn *conn)
Definition: fe-exec.c:2031
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:904
#define PqMsg_CopyDone
Definition: protocol.h:64
#define PqMsg_Sync
Definition: protocol.h:27
PGNoticeHooks noticeHooks
Definition: libpq-int.h:445

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)
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:441

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
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 */
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 */
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 */
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}
PGresult * pqPrepareAsyncResult(PGconn *conn)
Definition: fe-exec.c:851
void pqSaveErrorResult(PGconn *conn)
Definition: fe-exec.c:803
PGresult * PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
Definition: fe-exec.c:159
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:897
#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
999fail:
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:157
void * noticeRecArg
Definition: libpq-int.h:158
PGVerbosity verbosity
Definition: libpq-int.h:538
char last_sqlstate[6]
Definition: libpq-int.h:456
PGContextVisibility show_context
Definition: libpq-int.h:539
PGNoticeHooks noticeHooks
Definition: libpq-int.h:191

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

7784{
7785#ifndef WIN32
7786 const char *home;
7787
7788 home = getenv("HOME");
7789 if (home && home[0])
7790 {
7791 strlcpy(buf, home, bufsize);
7792 return true;
7793 }
7794 else
7795 {
7796 struct passwd pwbuf;
7797 struct passwd *pw;
7798 char tmpbuf[1024];
7799 int rc;
7800
7801 rc = getpwuid_r(geteuid(), &pwbuf, tmpbuf, sizeof tmpbuf, &pw);
7802 if (rc != 0 || !pw)
7803 return false;
7804 strlcpy(buf, pw->pw_dir, bufsize);
7805 return true;
7806 }
7807#else
7808 char tmppath[MAX_PATH];
7809
7810 ZeroMemory(tmppath, sizeof(tmppath));
7811 if (SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, tmppath) != S_OK)
7812 return false;
7813 snprintf(buf, bufsize, "%s/postgresql", tmppath);
7814 return true;
7815#endif
7816}
#define bufsize
Definition: indent_globs.h:36
static char * buf
Definition: pg_test_fsync.c:72
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}
uint16_t uint16
Definition: c.h:487
#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:465

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 */
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:466

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
1423 for (int i = 0; i < num; i++)
1424 {
1425 if (pqGets(&conn->workBuffer, conn))
1426 {
1428 return EOF;
1429 }
1430 if (buf.len > 0)
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
1453 return 0;
1454}
#define libpq_ngettext(s, p, n)
Definition: libpq-int.h:916
#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:494
PQExpBufferData workBuffer
Definition: libpq-int.h:656

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

4595{
4596 PGconn *conn;
4597
4598#ifdef WIN32
4599
4600 /*
4601 * Make sure socket support is up and running in this process.
4602 *
4603 * Note: the Windows documentation says that we should eventually do a
4604 * matching WSACleanup() call, but experience suggests that that is at
4605 * least as likely to cause problems as fix them. So we don't.
4606 */
4607 static bool wsastartup_done = false;
4608
4609 if (!wsastartup_done)
4610 {
4611 WSADATA wsaData;
4612
4613 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
4614 return NULL;
4615 wsastartup_done = true;
4616 }
4617
4618 /* Forget any earlier error */
4619 WSASetLastError(0);
4620#endif /* WIN32 */
4621
4622 conn = (PGconn *) malloc(sizeof(PGconn));
4623 if (conn == NULL)
4624 return conn;
4625
4626 /* Zero all pointers and booleans */
4627 MemSet(conn, 0, sizeof(PGconn));
4628
4629 /* install default notice hooks */
4632
4637 conn->options_valid = false;
4638 conn->nonblocking = false;
4640 conn->std_strings = false; /* unless server says differently */
4647 conn->Pfdebug = NULL;
4648
4649 /*
4650 * We try to send at least 8K at a time, which is the usual size of pipe
4651 * buffers on Unix systems. That way, when we are sending a large amount
4652 * of data, we avoid incurring extra kernel context swaps for partial
4653 * bufferloads. The output buffer is initially made 16K in size, and we
4654 * try to dump it after accumulating 8K.
4655 *
4656 * With the same goal of minimizing context swaps, the input buffer will
4657 * be enlarged anytime it has less than 8K free, so we initially allocate
4658 * twice that.
4659 */
4660 conn->inBufSize = 16 * 1024;
4661 conn->inBuffer = (char *) malloc(conn->inBufSize);
4662 conn->outBufSize = 16 * 1024;
4663 conn->outBuffer = (char *) malloc(conn->outBufSize);
4664 conn->rowBufLen = 32;
4668
4669 if (conn->inBuffer == NULL ||
4670 conn->outBuffer == NULL ||
4671 conn->rowBuf == NULL ||
4674 {
4675 /* out of memory already :-( */
4677 conn = NULL;
4678 }
4679
4680 return conn;
4681}
#define MemSet(start, val, len)
Definition: c.h:977
static void defaultNoticeReceiver(void *arg, const PGresult *res)
Definition: fe-connect.c:7470
static void defaultNoticeProcessor(void *arg, const char *message)
Definition: fe-connect.c:7485
static void freePGconn(PGconn *conn)
Definition: fe-connect.c:4693
@ 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:159
PGdataValue * rowBuf
Definition: libpq-int.h:562
bool std_strings
Definition: libpq-int.h:535
PGTernaryBool in_hot_standby
Definition: libpq-int.h:537
int client_encoding
Definition: libpq-int.h:534
PGTernaryBool default_transaction_read_only
Definition: libpq-int.h:536
int rowBufLen
Definition: libpq-int.h:563
int scram_sha_256_iterations
Definition: libpq-int.h:582

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

5049{
5050 /* Start the message. */
5051 if (pqPutMsgStart(pack_type, conn))
5052 return STATUS_ERROR;
5053
5054 /* Send the message body. */
5055 if (pqPutnchar(buf, buf_len, conn))
5056 return STATUS_ERROR;
5057
5058 /* Finish the message. */
5059 if (pqPutMsgEnd(conn))
5060 return STATUS_ERROR;
5061
5062 /* Flush to ensure backend gets it. */
5063 if (pqFlush(conn))
5064 return STATUS_ERROR;
5065
5066 return STATUS_OK;
5067}
#define STATUS_OK
Definition: c.h:1126
#define STATUS_ERROR
Definition: c.h:1127

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 */
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 ... */
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)
217 break;
219 if (pqGetErrorNotice3(conn, true))
220 return;
222 break;
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;
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;
280 /* Nothing to do for this message type */
281 break;
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 ||
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;
418 break;
421 return;
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:91
#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:531
int be_key
Definition: libpq-int.h:532
char cmdStatus[CMDSTATUS_LEN]
Definition: libpq-int.h:183

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

7826{
7827 char *end;
7828 long numval;
7829
7830 Assert(value != NULL);
7831
7832 *result = 0;
7833
7834 /* strtol(3) skips leading whitespaces */
7835 errno = 0;
7836 numval = strtol(value, &end, 10);
7837
7838 /*
7839 * If no progress was done during the parsing or an error happened, fail.
7840 * This tests properly for overflows of the result.
7841 */
7842 if (value == end || errno != 0 || numval != (int) numval)
7843 goto error;
7844
7845 /*
7846 * Skip any trailing whitespace; if anything but whitespace remains before
7847 * the terminating character, fail
7848 */
7849 while (*end != '\0' && isspace((unsigned char) *end))
7850 end++;
7851
7852 if (*end != '\0')
7853 goto error;
7854
7855 *result = numval;
7856 return true;
7857
7858error:
7859 libpq_append_conn_error(conn, "invalid integer value \"%s\" for connection option \"%s\"",
7860 value, context);
7861 return false;
7862}
static struct @162 value
static void error(void)
Definition: sql-dyntest.c:147

References Assert, conn, 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:1202
static const PGresult OOM_result
Definition: fe-exec.c:49
int errorReported
Definition: libpq-int.h:653

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 {
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:557
int outMsgEnd
Definition: libpq-int.h:559

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;
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 */
630retry3:
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 */
725retry4:
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 */
764definitelyEOF:
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 */
770definitelyFailed:
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:364
#define EWOULDBLOCK
Definition: win32_port.h:370
#define EAGAIN
Definition: win32_port.h:362

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

4778{
4779 if (conn->connhost)
4780 {
4781 for (int i = 0; i < conn->nconnhost; ++i)
4782 {
4783 free(conn->connhost[i].host);
4785 free(conn->connhost[i].port);
4786 if (conn->connhost[i].password != NULL)
4787 {
4789 strlen(conn->connhost[i].password));
4791 }
4792 }
4793 free(conn->connhost);
4794 }
4795}
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:106
size_t memorySize
Definition: libpq-int.h:217
int curOffset
Definition: libpq-int.h:214
char null_field[1]
Definition: libpq-int.h:206
int spaceLeft
Definition: libpq-int.h:215
PGresult_data * curBlock
Definition: libpq-int.h:213
PGresult_data * next
Definition: libpq-int.h:110
char space[1]
Definition: libpq-int.h:111

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 */
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:138
int maxChunkSize
Definition: libpq-int.h:463
bool singleRowMode
Definition: libpq-int.h:462
bool partialResMode
Definition: libpq-int.h:461
int ntups
Definition: libpq-int.h:174
PGresAttDesc * attDescs
Definition: libpq-int.h:176
int numAttributes
Definition: libpq-int.h:175
char * value
Definition: libpq-int.h:143

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:149
char contents[FLEXIBLE_ARRAY_MEMBER]
Definition: libpq-int.h:151

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 {
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:279
int sversion
Definition: libpq-int.h:495
pgParameterStatus * pstatus
Definition: libpq-int.h:533

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
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 */
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
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:504

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
340retry_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:502
bool sigpipe_flag
Definition: libpq-int.h:500
bool write_failed
Definition: libpq-int.h:501
#define send(s, buf, len, flags)
Definition: win32_port.h:505

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}
#define fprintf(file, fmt, msg)
Definition: cubescan.l:21
static void pqTraceFormatTimestamp(char *timestr, size_t ts_len)
Definition: fe-trace.c:80
#define PQTRACE_SUPPRESS_TIMESTAMPS
Definition: libpq-fe.h:467
int traceFlags
Definition: libpq-int.h:442

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 {
655 fprintf(conn->Pfdebug, "ParseComplete");
656 /* No message content */
657 break;
659 fprintf(conn->Pfdebug, "BindComplete");
660 /* No message content */
661 break;
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;
711
712 /*
713 * These messages share a common type byte, so we discriminate by
714 * having the code store the auth type separately.
715 */
717 {
720 &logCursor, length, regress);
721 break;
724 &logCursor);
725 break;
728 &logCursor, regress);
729 break;
732 &logCursor, length, regress);
733 break;
734 default:
735 fprintf(conn->Pfdebug, "UnknownAuthenticationResponse");
736 break;
737 }
739 break;
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;
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;
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:469
#define AUTH_RESPONSE_PASSWORD
Definition: libpq-int.h:344
#define AUTH_RESPONSE_SASL
Definition: libpq-int.h:346
#define AUTH_RESPONSE_SASL_INITIAL
Definition: libpq-int.h:345
#define AUTH_RESPONSE_GSS
Definition: libpq-int.h:343
#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:510

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 464 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().