PostgreSQL Source Code  git master
libpq-int.h File Reference
#include "libpq-events.h"
#include <time.h>
#include "getaddrinfo.h"
#include "libpq/pqcomm.h"
#include "pqexpbuffer.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  pg_conn_host
 
struct  pg_conn
 
struct  pg_cancel
 

Macros

#define CMDSTATUS_LEN   64 /* should match COMPLETION_TAG_BUFSIZE */
 
#define NULL_LEN   (-1) /* pg_result len for NULL value */
 
#define pglock_thread()   ((void) 0)
 
#define pgunlock_thread()   ((void) 0)
 
#define pqIsnonblocking(conn)   ((conn)->nonblocking)
 
#define libpq_gettext(x)   (x)
 
#define libpq_ngettext(s, p, n)   ((n) == 1 ? (s) : (p))
 
#define SOCK_ERRNO   errno
 
#define SOCK_STRERROR   pqStrerror
 
#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 pg_conn_host pg_conn_host
 

Enumerations

enum  PGAsyncStatusType {
  PGASYNC_IDLE, PGASYNC_BUSY, PGASYNC_READY, PGASYNC_COPY_IN,
  PGASYNC_COPY_OUT, PGASYNC_COPY_BOTH
}
 
enum  PGQueryClass { PGQUERY_SIMPLE, PGQUERY_EXTENDED, PGQUERY_PREPARE, PGQUERY_DESCRIBE }
 
enum  PGSetenvStatusType {
  SETENV_STATE_CLIENT_ENCODING_SEND, SETENV_STATE_CLIENT_ENCODING_WAIT, SETENV_STATE_OPTION_SEND, SETENV_STATE_OPTION_WAIT,
  SETENV_STATE_QUERY1_SEND, SETENV_STATE_QUERY1_WAIT, SETENV_STATE_QUERY2_SEND, SETENV_STATE_QUERY2_WAIT,
  SETENV_STATE_IDLE
}
 
enum  pg_conn_host_type { CHT_HOST_NAME, CHT_HOST_ADDRESS, CHT_UNIX_SOCKET }
 

Functions

void pqDropConnection (PGconn *conn, bool flushInput)
 
int pqPacketSend (PGconn *conn, char pack_type, const void *buf, size_t buf_len)
 
bool pqGetHomeDirectory (char *buf, int bufsize)
 
void pqSetResultError (PGresult *res, const char *msg)
 
void pqCatenateResultError (PGresult *res, const char *msg)
 
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 pqHandleSendFailure (PGconn *conn)
 
PostgresPollingStatusType pqSetenvPoll (PGconn *conn)
 
char * pqBuildStartupPacket2 (PGconn *conn, int *packetlen, const PQEnvironmentOption *options)
 
void pqParseInput2 (PGconn *conn)
 
int pqGetCopyData2 (PGconn *conn, char **buffer, int async)
 
int pqGetline2 (PGconn *conn, char *s, int maxlen)
 
int pqGetlineAsync2 (PGconn *conn, char *buffer, int bufsize)
 
int pqEndcopy2 (PGconn *conn)
 
PGresultpqFunctionCall2 (PGconn *conn, Oid fnid, int *result_buf, int *actual_result_len, int result_is_int, const PQArgBlock *args, int nargs)
 
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 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)
 
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, bool force_len, 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, time_t finish_time)
 
int pqReadReady (PGconn *conn)
 
int pqWriteReady (PGconn *conn)
 
int pqsecure_initialize (PGconn *)
 
void pqsecure_destroy (void)
 
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)
 
void pgtls_init_library (bool do_ssl, int do_crypto)
 
int pgtls_init (PGconn *conn)
 
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_finished (PGconn *conn, size_t *len)
 

Variables

char *const pgresStatus []
 

Macro Definition Documentation

◆ CMDSTATUS_LEN

#define CMDSTATUS_LEN   64 /* should match COMPLETION_TAG_BUFSIZE */

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

Referenced by pqParseInput2(), and pqParseInput3().

◆ libpq_gettext

#define libpq_gettext (   x)    (x)

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

Referenced by build_client_final_message(), build_client_first_message(), connectDBStart(), connectFailureMessage(), connectNoDelay(), connectOptions2(), conninfo_add_defaults(), conninfo_array_parse(), conninfo_init(), conninfo_parse(), conninfo_storeval(), conninfo_uri_decode(), conninfo_uri_parse_options(), conninfo_uri_parse_params(), do_field(), do_header(), fillPGconn(), getAnotherTuple(), getParamDescriptions(), getRowDescriptions(), handleSyncLoss(), initialize_SSL(), lo_create(), lo_export(), lo_import_internal(), lo_initialize(), lo_lseek64(), lo_read(), lo_tell64(), lo_truncate(), lo_truncate64(), lo_write(), open_client_SSL(), parseServiceFile(), parseServiceInfo(), passwordFromFile(), pg_fe_getauthname(), pg_fe_scram_exchange(), pg_fe_sendauth(), pg_local_sendauth(), pg_password_sendauth(), pg_SASL_continue(), pg_SASL_init(), pgpassfileWarning(), pgtls_read(), pgtls_write(), pqAddTuple(), pqBuildErrorMessage3(), PQconnectPoll(), PQdisplayTuples(), PQencryptPasswordConn(), pqEndcopy2(), pqEndcopy3(), PQenv2encoding(), PQerrorMessage(), PQescapeByteaInternal(), PQescapeInternal(), PQescapeStringInternal(), PQexecStart(), PQfn(), pqFunctionCall2(), pqFunctionCall3(), PQgetCopyData(), pqGetCopyData2(), pqGetCopyData3(), pqGetErrorNotice2(), pqGetErrorNotice3(), pqGetline3(), PQgetResult(), pqInternalNotice(), pqPacketSend(), pqParseInput2(), pqParseInput3(), PQprint(), PQprintTuples(), PQputCopyData(), PQputCopyEnd(), pqReadData(), PQreset(), PQresetPoll(), PQresStatus(), PQresultVerboseErrorMessage(), pqsecure_raw_read(), pqsecure_raw_write(), PQsendDescribe(), PQsendPrepare(), PQsendQuery(), PQsendQueryGuts(), PQsendQueryParams(), PQsendQueryPrepared(), PQsendQueryStart(), pqSendSome(), PQsetdbLogin(), pqSetenvPoll(), PQsetvalue(), pqSocketCheck(), pqWaitTimed(), read_attr_value(), read_server_final_message(), read_server_first_message(), reportErrorPosition(), saveErrorMessage(), setKeepalivesCount(), setKeepalivesIdle(), setKeepalivesInterval(), SSLerrmessage(), verify_peer_name_matches_certificate(), and verify_peer_name_matches_certificate_name().

◆ libpq_ngettext

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

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

Referenced by PQenv2encoding(), and verify_peer_name_matches_certificate().

◆ NULL_LEN

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

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

Referenced by getAnotherTuple(), PQgetisnull(), PQgetlength(), pqRowProcessor(), and PQsetvalue().

◆ pglock_thread

#define pglock_thread ( )    ((void) 0)

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

Referenced by pg_fe_getauthname(), pg_fe_sendauth(), and pg_frontend_random().

◆ pgunlock_thread

#define pgunlock_thread ( )    ((void) 0)

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

Referenced by pg_fe_getauthname(), pg_fe_sendauth(), and pg_frontend_random().

◆ pqIsnonblocking

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

◆ SOCK_ERRNO

◆ SOCK_ERRNO_SET

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

◆ SOCK_STRERROR

Typedef Documentation

◆ pg_conn_host

◆ pg_conn_host_type

◆ PGdataValue

◆ PGEvent

◆ PGlobjfuncs

◆ PGMessageField

◆ pgParameterStatus

◆ PGresAttValue

◆ PGresParamDesc

◆ PGresult_data

Definition at line 101 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 293 of file libpq-int.h.

◆ PGAsyncStatusType

Enumerator
PGASYNC_IDLE 
PGASYNC_BUSY 
PGASYNC_READY 
PGASYNC_COPY_IN 
PGASYNC_COPY_OUT 
PGASYNC_COPY_BOTH 

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

215 {
216  PGASYNC_IDLE, /* nothing's happening, dude */
217  PGASYNC_BUSY, /* query in progress */
218  PGASYNC_READY, /* result ready for PQgetResult */
219  PGASYNC_COPY_IN, /* Copy In data transfer in progress */
220  PGASYNC_COPY_OUT, /* Copy Out data transfer in progress */
221  PGASYNC_COPY_BOTH /* Copy In/Out data transfer in progress */
PGAsyncStatusType
Definition: libpq-int.h:214

◆ PGQueryClass

Enumerator
PGQUERY_SIMPLE 
PGQUERY_EXTENDED 
PGQUERY_PREPARE 
PGQUERY_DESCRIBE 

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

226 {
227  PGQUERY_SIMPLE, /* simple Query protocol (PQexec) */
228  PGQUERY_EXTENDED, /* full Extended protocol (PQexecParams) */
229  PGQUERY_PREPARE, /* Parse only (PQprepare) */
230  PGQUERY_DESCRIBE /* Describe Statement or Portal */
231 } PGQueryClass;
PGQueryClass
Definition: libpq-int.h:225

◆ PGSetenvStatusType

Enumerator
SETENV_STATE_CLIENT_ENCODING_SEND 
SETENV_STATE_CLIENT_ENCODING_WAIT 
SETENV_STATE_OPTION_SEND 
SETENV_STATE_OPTION_WAIT 
SETENV_STATE_QUERY1_SEND 
SETENV_STATE_QUERY1_WAIT 
SETENV_STATE_QUERY2_SEND 
SETENV_STATE_QUERY2_WAIT 
SETENV_STATE_IDLE 

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

236 {
237  SETENV_STATE_CLIENT_ENCODING_SEND, /* About to send an Environment Option */
238  SETENV_STATE_CLIENT_ENCODING_WAIT, /* Waiting for above send to complete */
239  SETENV_STATE_OPTION_SEND, /* About to send an Environment Option */
240  SETENV_STATE_OPTION_WAIT, /* Waiting for above send to complete */
241  SETENV_STATE_QUERY1_SEND, /* About to send a status query */
242  SETENV_STATE_QUERY1_WAIT, /* Waiting for query to complete */
243  SETENV_STATE_QUERY2_SEND, /* About to send a status query */
244  SETENV_STATE_QUERY2_WAIT, /* Waiting for query to complete */
PGSetenvStatusType
Definition: libpq-int.h:235

Function Documentation

◆ pgtls_close()

void pgtls_close ( PGconn conn)

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

References destroy_ssl_system(), and pg_conn::ssl_in_use.

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

1415 {
1416  bool destroy_needed = false;
1417 
1418  if (conn->ssl)
1419  {
1420  /*
1421  * We can't destroy everything SSL-related here due to the possible
1422  * later calls to OpenSSL routines which may need our thread
1423  * callbacks, so set a flag here and check at the end.
1424  */
1425  destroy_needed = true;
1426 
1427  SSL_shutdown(conn->ssl);
1428  SSL_free(conn->ssl);
1429  conn->ssl = NULL;
1430  conn->ssl_in_use = false;
1431  }
1432 
1433  if (conn->peer)
1434  {
1435  X509_free(conn->peer);
1436  conn->peer = NULL;
1437  }
1438 
1439 #ifdef USE_SSL_ENGINE
1440  if (conn->engine)
1441  {
1442  ENGINE_finish(conn->engine);
1443  ENGINE_free(conn->engine);
1444  conn->engine = NULL;
1445  }
1446 #endif
1447 
1448  /*
1449  * This will remove our SSL locking hooks, if this is the last SSL
1450  * connection, which means we must wait to call it until after all SSL
1451  * calls have been made, otherwise we can end up with a race condition and
1452  * possible deadlocks.
1453  *
1454  * See comments above destroy_ssl_system().
1455  */
1456  if (destroy_needed)
1458 }
bool ssl_in_use
Definition: libpq-int.h:457
static void destroy_ssl_system(void)

◆ pgtls_get_finished()

char* pgtls_get_finished ( PGconn conn,
size_t *  len 
)

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

References malloc.

Referenced by pg_SASL_init().

404 {
405  char dummy[1];
406  char *result;
407 
408  /*
409  * OpenSSL does not offer an API to get directly the length of the TLS
410  * Finished message sent, so first do a dummy call to grab this
411  * information and then do an allocation with the correct size.
412  */
413  *len = SSL_get_finished(conn->ssl, dummy, sizeof(dummy));
414  result = malloc(*len);
415  if (result == NULL)
416  return NULL;
417  (void) SSL_get_finished(conn->ssl, result, *len);
418 
419  return result;
420 }
#define malloc(a)
Definition: header.h:50

◆ pgtls_init()

int pgtls_init ( PGconn conn)

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

References free, i, malloc, pq_init_crypto_lib, pq_init_ssl_lib, pthread_mutex_init(), pthread_mutex_lock(), pthread_mutex_unlock(), and ssl_lib_initialized.

Referenced by pqsecure_initialize().

779 {
780 #ifdef ENABLE_THREAD_SAFETY
781 #ifdef WIN32
782  /* Also see similar code in fe-connect.c, default_threadlock() */
783  if (ssl_config_mutex == NULL)
784  {
785  while (InterlockedExchange(&win32_ssl_create_mutex, 1) == 1)
786  /* loop, another thread own the lock */ ;
787  if (ssl_config_mutex == NULL)
788  {
789  if (pthread_mutex_init(&ssl_config_mutex, NULL))
790  return -1;
791  }
792  InterlockedExchange(&win32_ssl_create_mutex, 0);
793  }
794 #endif
795  if (pthread_mutex_lock(&ssl_config_mutex))
796  return -1;
797 
798 #ifdef HAVE_CRYPTO_LOCK
799  if (pq_init_crypto_lib)
800  {
801  /*
802  * If necessary, set up an array to hold locks for libcrypto.
803  * libcrypto will tell us how big to make this array.
804  */
805  if (pq_lockarray == NULL)
806  {
807  int i;
808 
809  pq_lockarray = malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
810  if (!pq_lockarray)
811  {
812  pthread_mutex_unlock(&ssl_config_mutex);
813  return -1;
814  }
815  for (i = 0; i < CRYPTO_num_locks(); i++)
816  {
817  if (pthread_mutex_init(&pq_lockarray[i], NULL))
818  {
819  free(pq_lockarray);
820  pq_lockarray = NULL;
821  pthread_mutex_unlock(&ssl_config_mutex);
822  return -1;
823  }
824  }
825  }
826 
827  if (ssl_open_connections++ == 0)
828  {
829  /*
830  * These are only required for threaded libcrypto applications,
831  * but make sure we don't stomp on them if they're already set.
832  */
833  if (CRYPTO_get_id_callback() == NULL)
834  CRYPTO_set_id_callback(pq_threadidcallback);
835  if (CRYPTO_get_locking_callback() == NULL)
836  CRYPTO_set_locking_callback(pq_lockingcallback);
837  }
838  }
839 #endif /* HAVE_CRYPTO_LOCK */
840 #endif /* ENABLE_THREAD_SAFETY */
841 
842  if (!ssl_lib_initialized)
843  {
844  if (pq_init_ssl_lib)
845  {
846 #ifdef HAVE_OPENSSL_INIT_SSL
847  OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
848 #else
849  OPENSSL_config(NULL);
850  SSL_library_init();
851  SSL_load_error_strings();
852 #endif
853  }
854  ssl_lib_initialized = true;
855  }
856 
857 #ifdef ENABLE_THREAD_SAFETY
858  pthread_mutex_unlock(&ssl_config_mutex);
859 #endif
860  return 0;
861 }
static bool pq_init_ssl_lib
CRITICAL_SECTION * pthread_mutex_t
Definition: pthread-win32.h:8
int pthread_mutex_init(pthread_mutex_t *mp, void *attr)
Definition: pthread-win32.c:35
#define malloc(a)
Definition: header.h:50
int pthread_mutex_lock(pthread_mutex_t *mp)
Definition: pthread-win32.c:45
int pthread_mutex_unlock(pthread_mutex_t *mp)
Definition: pthread-win32.c:54
static bool pq_init_crypto_lib
#define free(a)
Definition: header.h:65
int i
static bool ssl_lib_initialized

◆ pgtls_init_library()

void pgtls_init_library ( bool  do_ssl,
int  do_crypto 
)

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

References pq_init_crypto_lib, and pq_init_ssl_lib.

Referenced by PQinitOpenSSL(), and PQinitSSL().

107 {
108 #ifdef ENABLE_THREAD_SAFETY
109 
110  /*
111  * Disallow changing the flags while we have open connections, else we'd
112  * get completely confused.
113  */
114  if (ssl_open_connections != 0)
115  return;
116 #endif
117 
118  pq_init_ssl_lib = do_ssl;
119  pq_init_crypto_lib = do_crypto;
120 }
static bool pq_init_ssl_lib
static bool pq_init_crypto_lib

◆ pgtls_open_client()

PostgresPollingStatusType pgtls_open_client ( PGconn conn)

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

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

Referenced by pqsecure_open_client().

127 {
128  /* First time through? */
129  if (conn->ssl == NULL)
130  {
131  /*
132  * Create a connection-specific SSL object, and load client
133  * certificate, private key, and trusted CA certs.
134  */
135  if (initialize_SSL(conn) != 0)
136  {
137  /* initialize_SSL already put a message in conn->errorMessage */
138  pgtls_close(conn);
139  return PGRES_POLLING_FAILED;
140  }
141  }
142 
143  /* Begin or continue the actual handshake */
144  return open_client_SSL(conn);
145 }
static PostgresPollingStatusType open_client_SSL(PGconn *)
static int initialize_SSL(PGconn *conn)
void pgtls_close(PGconn *conn)

◆ pgtls_read()

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

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

References ECONNRESET, pg_conn::errorMessage, libpq_gettext, printfPQExpBuffer(), SOCK_ERRNO, SOCK_ERRNO_SET, SOCK_STRERROR, SSLerrfree(), and SSLerrmessage().

Referenced by pqsecure_read().

165 {
166  ssize_t n;
167  int result_errno = 0;
168  char sebuf[256];
169  int err;
170  unsigned long ecode;
171 
172 rloop:
173 
174  /*
175  * Prepare to call SSL_get_error() by clearing thread's OpenSSL error
176  * queue. In general, the current thread's error queue must be empty
177  * before the TLS/SSL I/O operation is attempted, or SSL_get_error() will
178  * not work reliably. Since the possibility exists that other OpenSSL
179  * clients running in the same thread but not under our control will fail
180  * to call ERR_get_error() themselves (after their own I/O operations),
181  * pro-actively clear the per-thread error queue now.
182  */
183  SOCK_ERRNO_SET(0);
184  ERR_clear_error();
185  n = SSL_read(conn->ssl, ptr, len);
186  err = SSL_get_error(conn->ssl, n);
187 
188  /*
189  * Other clients of OpenSSL may fail to call ERR_get_error(), but we
190  * always do, so as to not cause problems for OpenSSL clients that don't
191  * call ERR_clear_error() defensively. Be sure that this happens by
192  * calling now. SSL_get_error() relies on the OpenSSL per-thread error
193  * queue being intact, so this is the earliest possible point
194  * ERR_get_error() may be called.
195  */
196  ecode = (err != SSL_ERROR_NONE || n < 0) ? ERR_get_error() : 0;
197  switch (err)
198  {
199  case SSL_ERROR_NONE:
200  if (n < 0)
201  {
202  /* Not supposed to happen, so we don't translate the msg */
204  "SSL_read failed but did not provide error information\n");
205  /* assume the connection is broken */
206  result_errno = ECONNRESET;
207  }
208  break;
209  case SSL_ERROR_WANT_READ:
210  n = 0;
211  break;
212  case SSL_ERROR_WANT_WRITE:
213 
214  /*
215  * Returning 0 here would cause caller to wait for read-ready,
216  * which is not correct since what SSL wants is wait for
217  * write-ready. The former could get us stuck in an infinite
218  * wait, so don't risk it; busy-loop instead.
219  */
220  goto rloop;
221  case SSL_ERROR_SYSCALL:
222  if (n < 0)
223  {
224  result_errno = SOCK_ERRNO;
225  if (result_errno == EPIPE ||
226  result_errno == ECONNRESET)
229  "server closed the connection unexpectedly\n"
230  "\tThis probably means the server terminated abnormally\n"
231  "\tbefore or while processing the request.\n"));
232  else
234  libpq_gettext("SSL SYSCALL error: %s\n"),
235  SOCK_STRERROR(result_errno,
236  sebuf, sizeof(sebuf)));
237  }
238  else
239  {
241  libpq_gettext("SSL SYSCALL error: EOF detected\n"));
242  /* assume the connection is broken */
243  result_errno = ECONNRESET;
244  n = -1;
245  }
246  break;
247  case SSL_ERROR_SSL:
248  {
249  char *errm = SSLerrmessage(ecode);
250 
252  libpq_gettext("SSL error: %s\n"), errm);
253  SSLerrfree(errm);
254  /* assume the connection is broken */
255  result_errno = ECONNRESET;
256  n = -1;
257  break;
258  }
259  case SSL_ERROR_ZERO_RETURN:
260 
261  /*
262  * Per OpenSSL documentation, this error code is only returned for
263  * a clean connection closure, so we should not report it as a
264  * server crash.
265  */
267  libpq_gettext("SSL connection has been closed unexpectedly\n"));
268  result_errno = ECONNRESET;
269  n = -1;
270  break;
271  default:
273  libpq_gettext("unrecognized SSL error code: %d\n"),
274  err);
275  /* assume the connection is broken */
276  result_errno = ECONNRESET;
277  n = -1;
278  break;
279  }
280 
281  /* ensure we return the intended errno to caller */
282  SOCK_ERRNO_SET(result_errno);
283 
284  return n;
285 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
#define SOCK_STRERROR
Definition: libpq-int.h:699
#define SOCK_ERRNO
Definition: libpq-int.h:698
#define SOCK_ERRNO_SET(e)
Definition: libpq-int.h:700
static void SSLerrfree(char *buf)
PQExpBufferData errorMessage
Definition: libpq-int.h:493
#define ECONNRESET
Definition: win32_port.h:344
static char * SSLerrmessage(unsigned long ecode)
#define libpq_gettext(x)
Definition: libpq-int.h:685

◆ pgtls_read_pending()

bool pgtls_read_pending ( PGconn conn)

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

Referenced by pqSocketCheck().

152 {
153  return SSL_pending(conn->ssl);
154 }

◆ pgtls_write()

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

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

References ECONNRESET, pg_conn::errorMessage, libpq_gettext, printfPQExpBuffer(), SOCK_ERRNO, SOCK_ERRNO_SET, SOCK_STRERROR, SSLerrfree(), and SSLerrmessage().

Referenced by pqsecure_write().

296 {
297  ssize_t n;
298  int result_errno = 0;
299  char sebuf[256];
300  int err;
301  unsigned long ecode;
302 
303  SOCK_ERRNO_SET(0);
304  ERR_clear_error();
305  n = SSL_write(conn->ssl, ptr, len);
306  err = SSL_get_error(conn->ssl, n);
307  ecode = (err != SSL_ERROR_NONE || n < 0) ? ERR_get_error() : 0;
308  switch (err)
309  {
310  case SSL_ERROR_NONE:
311  if (n < 0)
312  {
313  /* Not supposed to happen, so we don't translate the msg */
315  "SSL_write failed but did not provide error information\n");
316  /* assume the connection is broken */
317  result_errno = ECONNRESET;
318  }
319  break;
320  case SSL_ERROR_WANT_READ:
321 
322  /*
323  * Returning 0 here causes caller to wait for write-ready, which
324  * is not really the right thing, but it's the best we can do.
325  */
326  n = 0;
327  break;
328  case SSL_ERROR_WANT_WRITE:
329  n = 0;
330  break;
331  case SSL_ERROR_SYSCALL:
332  if (n < 0)
333  {
334  result_errno = SOCK_ERRNO;
335  if (result_errno == EPIPE || result_errno == ECONNRESET)
338  "server closed the connection unexpectedly\n"
339  "\tThis probably means the server terminated abnormally\n"
340  "\tbefore or while processing the request.\n"));
341  else
343  libpq_gettext("SSL SYSCALL error: %s\n"),
344  SOCK_STRERROR(result_errno,
345  sebuf, sizeof(sebuf)));
346  }
347  else
348  {
350  libpq_gettext("SSL SYSCALL error: EOF detected\n"));
351  /* assume the connection is broken */
352  result_errno = ECONNRESET;
353  n = -1;
354  }
355  break;
356  case SSL_ERROR_SSL:
357  {
358  char *errm = SSLerrmessage(ecode);
359 
361  libpq_gettext("SSL error: %s\n"), errm);
362  SSLerrfree(errm);
363  /* assume the connection is broken */
364  result_errno = ECONNRESET;
365  n = -1;
366  break;
367  }
368  case SSL_ERROR_ZERO_RETURN:
369 
370  /*
371  * Per OpenSSL documentation, this error code is only returned for
372  * a clean connection closure, so we should not report it as a
373  * server crash.
374  */
376  libpq_gettext("SSL connection has been closed unexpectedly\n"));
377  result_errno = ECONNRESET;
378  n = -1;
379  break;
380  default:
382  libpq_gettext("unrecognized SSL error code: %d\n"),
383  err);
384  /* assume the connection is broken */
385  result_errno = ECONNRESET;
386  n = -1;
387  break;
388  }
389 
390  /* ensure we return the intended errno to caller */
391  SOCK_ERRNO_SET(result_errno);
392 
393  return n;
394 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
#define SOCK_STRERROR
Definition: libpq-int.h:699
#define SOCK_ERRNO
Definition: libpq-int.h:698
#define SOCK_ERRNO_SET(e)
Definition: libpq-int.h:700
static void SSLerrfree(char *buf)
PQExpBufferData errorMessage
Definition: libpq-int.h:493
#define ECONNRESET
Definition: win32_port.h:344
static char * SSLerrmessage(unsigned long ecode)
#define libpq_gettext(x)
Definition: libpq-int.h:685

◆ pqBuildErrorMessage3()

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

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

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_TERSE, PQERRORS_VERBOSE, PQresultErrorField(), PQSHOW_CONTEXT_ALWAYS, PQSHOW_CONTEXT_ERRORS, reportErrorPosition(), pg_result::resultStatus, and val.

Referenced by pqGetErrorNotice3(), and PQresultVerboseErrorMessage().

983 {
984  const char *val;
985  const char *querytext = NULL;
986  int querypos = 0;
987 
988  /* If we couldn't allocate a PGresult, just say "out of memory" */
989  if (res == NULL)
990  {
991  appendPQExpBuffer(msg, libpq_gettext("out of memory\n"));
992  return;
993  }
994 
995  /*
996  * If we don't have any broken-down fields, just return the base message.
997  * This mainly applies if we're given a libpq-generated error result.
998  */
999  if (res->errFields == NULL)
1000  {
1001  if (res->errMsg && res->errMsg[0])
1002  appendPQExpBufferStr(msg, res->errMsg);
1003  else
1004  appendPQExpBuffer(msg, libpq_gettext("no error message available\n"));
1005  return;
1006  }
1007 
1008  /* Else build error message from relevant fields */
1010  if (val)
1011  appendPQExpBuffer(msg, "%s: ", val);
1012  if (verbosity == PQERRORS_VERBOSE)
1013  {
1015  if (val)
1016  appendPQExpBuffer(msg, "%s: ", val);
1017  }
1019  if (val)
1020  appendPQExpBufferStr(msg, val);
1022  if (val)
1023  {
1024  if (verbosity != PQERRORS_TERSE && res->errQuery != NULL)
1025  {
1026  /* emit position as a syntax cursor display */
1027  querytext = res->errQuery;
1028  querypos = atoi(val);
1029  }
1030  else
1031  {
1032  /* emit position as text addition to primary message */
1033  /* translator: %s represents a digit string */
1034  appendPQExpBuffer(msg, libpq_gettext(" at character %s"),
1035  val);
1036  }
1037  }
1038  else
1039  {
1041  if (val)
1042  {
1043  querytext = PQresultErrorField(res, PG_DIAG_INTERNAL_QUERY);
1044  if (verbosity != PQERRORS_TERSE && querytext != NULL)
1045  {
1046  /* emit position as a syntax cursor display */
1047  querypos = atoi(val);
1048  }
1049  else
1050  {
1051  /* emit position as text addition to primary message */
1052  /* translator: %s represents a digit string */
1053  appendPQExpBuffer(msg, libpq_gettext(" at character %s"),
1054  val);
1055  }
1056  }
1057  }
1058  appendPQExpBufferChar(msg, '\n');
1059  if (verbosity != PQERRORS_TERSE)
1060  {
1061  if (querytext && querypos > 0)
1062  reportErrorPosition(msg, querytext, querypos,
1063  res->client_encoding);
1065  if (val)
1066  appendPQExpBuffer(msg, libpq_gettext("DETAIL: %s\n"), val);
1068  if (val)
1069  appendPQExpBuffer(msg, libpq_gettext("HINT: %s\n"), val);
1071  if (val)
1072  appendPQExpBuffer(msg, libpq_gettext("QUERY: %s\n"), val);
1073  if (show_context == PQSHOW_CONTEXT_ALWAYS ||
1074  (show_context == PQSHOW_CONTEXT_ERRORS &&
1076  {
1077  val = PQresultErrorField(res, PG_DIAG_CONTEXT);
1078  if (val)
1079  appendPQExpBuffer(msg, libpq_gettext("CONTEXT: %s\n"),
1080  val);
1081  }
1082  }
1083  if (verbosity == PQERRORS_VERBOSE)
1084  {
1086  if (val)
1087  appendPQExpBuffer(msg,
1088  libpq_gettext("SCHEMA NAME: %s\n"), val);
1090  if (val)
1091  appendPQExpBuffer(msg,
1092  libpq_gettext("TABLE NAME: %s\n"), val);
1094  if (val)
1095  appendPQExpBuffer(msg,
1096  libpq_gettext("COLUMN NAME: %s\n"), val);
1098  if (val)
1099  appendPQExpBuffer(msg,
1100  libpq_gettext("DATATYPE NAME: %s\n"), val);
1102  if (val)
1103  appendPQExpBuffer(msg,
1104  libpq_gettext("CONSTRAINT NAME: %s\n"), val);
1105  }
1106  if (verbosity == PQERRORS_VERBOSE)
1107  {
1108  const char *valf;
1109  const char *vall;
1110 
1114  if (val || valf || vall)
1115  {
1116  appendPQExpBufferStr(msg, libpq_gettext("LOCATION: "));
1117  if (val)
1118  appendPQExpBuffer(msg, libpq_gettext("%s, "), val);
1119  if (valf && vall) /* unlikely we'd have just one */
1120  appendPQExpBuffer(msg, libpq_gettext("%s:%s"),
1121  valf, vall);
1122  appendPQExpBufferChar(msg, '\n');
1123  }
1124  }
1125 }
PGMessageField * errFields
Definition: libpq-int.h:197
#define PG_DIAG_MESSAGE_PRIMARY
Definition: postgres_ext.h:58
#define PG_DIAG_SCHEMA_NAME
Definition: postgres_ext.h:65
#define PG_DIAG_MESSAGE_DETAIL
Definition: postgres_ext.h:59
#define PG_DIAG_COLUMN_NAME
Definition: postgres_ext.h:67
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
#define PG_DIAG_TABLE_NAME
Definition: postgres_ext.h:66
#define PG_DIAG_SOURCE_LINE
Definition: postgres_ext.h:71
#define PG_DIAG_INTERNAL_POSITION
Definition: postgres_ext.h:62
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:57
char * errMsg
Definition: libpq-int.h:196
#define PG_DIAG_SOURCE_FILE
Definition: postgres_ext.h:70
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
static void reportErrorPosition(PQExpBuffer msg, const char *query, int loc, int encoding)
#define PG_DIAG_SEVERITY
Definition: postgres_ext.h:55
#define PG_DIAG_STATEMENT_POSITION
Definition: postgres_ext.h:61
char * errQuery
Definition: libpq-int.h:198
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:396
#define PG_DIAG_DATATYPE_NAME
Definition: postgres_ext.h:68
#define PG_DIAG_CONSTRAINT_NAME
Definition: postgres_ext.h:69
#define PG_DIAG_INTERNAL_QUERY
Definition: postgres_ext.h:63
#define PG_DIAG_MESSAGE_HINT
Definition: postgres_ext.h:60
char * PQresultErrorField(const PGresult *res, int fieldcode)
Definition: fe-exec.c:2709
#define PG_DIAG_SOURCE_FUNCTION
Definition: postgres_ext.h:72
ExecStatusType resultStatus
Definition: libpq-int.h:177
long val
Definition: informix.c:689
#define PG_DIAG_CONTEXT
Definition: postgres_ext.h:64
#define libpq_gettext(x)
Definition: libpq-int.h:685
int client_encoding
Definition: libpq-int.h:189

◆ pqBuildStartupPacket2()

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

Definition at line 1599 of file fe-protocol2.c.

References StartupPacket::database, pg_conn::dbName, malloc, MemSet, StartupPacket::options, pg_hton32, pg_conn::pgoptions, pg_conn::pgtty, pg_conn::pguser, StartupPacket::protoVersion, pg_conn::pversion, SM_DATABASE, SM_OPTIONS, SM_TTY, SM_USER, StartupPacket::tty, and StartupPacket::user.

Referenced by PQconnectPoll().

1601 {
1602  StartupPacket *startpacket;
1603 
1604  *packetlen = sizeof(StartupPacket);
1605  startpacket = (StartupPacket *) malloc(sizeof(StartupPacket));
1606  if (!startpacket)
1607  return NULL;
1608 
1609  MemSet(startpacket, 0, sizeof(StartupPacket));
1610 
1611  startpacket->protoVersion = pg_hton32(conn->pversion);
1612 
1613  /* strncpy is safe here: postmaster will handle full fields correctly */
1614  strncpy(startpacket->user, conn->pguser, SM_USER);
1615  strncpy(startpacket->database, conn->dbName, SM_DATABASE);
1616  strncpy(startpacket->tty, conn->pgtty, SM_TTY);
1617 
1618  if (conn->pgoptions)
1619  strncpy(startpacket->options, conn->pgoptions, SM_OPTIONS);
1620 
1621  return (char *) startpacket;
1622 }
char tty[SM_TTY]
Definition: pqcomm.h:149
struct StartupPacket StartupPacket
char * dbName
Definition: libpq-int.h:341
#define MemSet(start, val, len)
Definition: c.h:853
#define SM_USER
Definition: pqcomm.h:134
char options[SM_OPTIONS]
Definition: pqcomm.h:147
#define malloc(a)
Definition: header.h:50
#define SM_TTY
Definition: pqcomm.h:139
#define pg_hton32(x)
Definition: pg_bswap.h:121
char * pguser
Definition: libpq-int.h:343
char database[SM_DATABASE]
Definition: pqcomm.h:144
char * pgoptions
Definition: libpq-int.h:338
ProtocolVersion pversion
Definition: libpq-int.h:404
char user[SM_USER]
Definition: pqcomm.h:146
ProtocolVersion protoVersion
Definition: pqcomm.h:143
#define SM_OPTIONS
Definition: pqcomm.h:137
#define SM_DATABASE
Definition: pqcomm.h:133
char * pgtty
Definition: libpq-int.h:334

◆ pqBuildStartupPacket3()

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

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

References build_startup_packet(), and malloc.

Referenced by PQconnectPoll().

2119 {
2120  char *startpacket;
2121 
2122  *packetlen = build_startup_packet(conn, NULL, options);
2123  startpacket = (char *) malloc(*packetlen);
2124  if (!startpacket)
2125  return NULL;
2126  *packetlen = build_startup_packet(conn, startpacket, options);
2127  return startpacket;
2128 }
static int build_startup_packet(const PGconn *conn, char *packet, const PQEnvironmentOption *options)
#define malloc(a)
Definition: header.h:50

◆ pqCatenateResultError()

void pqCatenateResultError ( PGresult res,
const char *  msg 
)

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

References appendPQExpBufferStr(), PQExpBufferData::data, pg_result::errMsg, initPQExpBuffer(), pqSetResultError(), and termPQExpBuffer().

Referenced by PQexecFinish(), and pqSaveErrorResult().

653 {
654  PQExpBufferData errorBuf;
655 
656  if (!res || !msg)
657  return;
658  initPQExpBuffer(&errorBuf);
659  if (res->errMsg)
660  appendPQExpBufferStr(&errorBuf, res->errMsg);
661  appendPQExpBufferStr(&errorBuf, msg);
662  pqSetResultError(res, errorBuf.data);
663  termPQExpBuffer(&errorBuf);
664 }
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:128
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
char * errMsg
Definition: libpq-int.h:196
void pqSetResultError(PGresult *res, const char *msg)
Definition: fe-exec.c:637
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:89

◆ pqCheckInBufferSpace()

int pqCheckInBufferSpace ( size_t  bytes_needed,
PGconn conn 
)

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

References pg_conn::errorMessage, pg_conn::inBuffer, pg_conn::inBufSize, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, memmove, printfPQExpBuffer(), and realloc.

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

409 {
410  int newsize = conn->inBufSize;
411  char *newbuf;
412 
413  /* Quick exit if we have enough space */
414  if (bytes_needed <= (size_t) newsize)
415  return 0;
416 
417  /*
418  * Before concluding that we need to enlarge the buffer, left-justify
419  * whatever is in it and recheck. The caller's value of bytes_needed
420  * includes any data to the left of inStart, but we can delete that in
421  * preference to enlarging the buffer. It's slightly ugly to have this
422  * function do this, but it's better than making callers worry about it.
423  */
424  bytes_needed -= conn->inStart;
425 
426  if (conn->inStart < conn->inEnd)
427  {
428  if (conn->inStart > 0)
429  {
430  memmove(conn->inBuffer, conn->inBuffer + conn->inStart,
431  conn->inEnd - conn->inStart);
432  conn->inEnd -= conn->inStart;
433  conn->inCursor -= conn->inStart;
434  conn->inStart = 0;
435  }
436  }
437  else
438  {
439  /* buffer is logically empty, reset it */
440  conn->inStart = conn->inCursor = conn->inEnd = 0;
441  }
442 
443  /* Recheck whether we have enough space */
444  if (bytes_needed <= (size_t) newsize)
445  return 0;
446 
447  /*
448  * If we need to enlarge the buffer, we first try to double it in size; if
449  * that doesn't work, enlarge in multiples of 8K. This avoids thrashing
450  * the malloc pool by repeated small enlargements.
451  *
452  * Note: tests for newsize > 0 are to catch integer overflow.
453  */
454  do
455  {
456  newsize *= 2;
457  } while (newsize > 0 && bytes_needed > (size_t) newsize);
458 
459  if (newsize > 0 && bytes_needed <= (size_t) newsize)
460  {
461  newbuf = realloc(conn->inBuffer, newsize);
462  if (newbuf)
463  {
464  /* realloc succeeded */
465  conn->inBuffer = newbuf;
466  conn->inBufSize = newsize;
467  return 0;
468  }
469  }
470 
471  newsize = conn->inBufSize;
472  do
473  {
474  newsize += 8192;
475  } while (newsize > 0 && bytes_needed > (size_t) newsize);
476 
477  if (newsize > 0 && bytes_needed <= (size_t) newsize)
478  {
479  newbuf = realloc(conn->inBuffer, newsize);
480  if (newbuf)
481  {
482  /* realloc succeeded */
483  conn->inBuffer = newbuf;
484  conn->inBufSize = newsize;
485  return 0;
486  }
487  }
488 
489  /* realloc failed. Probably out of memory */
491  "cannot allocate memory for input buffer\n");
492  return EOF;
493 }
int inEnd
Definition: libpq-int.h:433
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
int inStart
Definition: libpq-int.h:431
int inBufSize
Definition: libpq-int.h:430
#define memmove(d, s, c)
Definition: c.h:1045
char * inBuffer
Definition: libpq-int.h:429
PQExpBufferData errorMessage
Definition: libpq-int.h:493
#define realloc(a, b)
Definition: header.h:60
int inCursor
Definition: libpq-int.h:432

◆ pqCheckOutBufferSpace()

int pqCheckOutBufferSpace ( size_t  bytes_needed,
PGconn conn 
)

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

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

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

345 {
346  int newsize = conn->outBufSize;
347  char *newbuf;
348 
349  /* Quick exit if we have enough space */
350  if (bytes_needed <= (size_t) newsize)
351  return 0;
352 
353  /*
354  * If we need to enlarge the buffer, we first try to double it in size; if
355  * that doesn't work, enlarge in multiples of 8K. This avoids thrashing
356  * the malloc pool by repeated small enlargements.
357  *
358  * Note: tests for newsize > 0 are to catch integer overflow.
359  */
360  do
361  {
362  newsize *= 2;
363  } while (newsize > 0 && bytes_needed > (size_t) newsize);
364 
365  if (newsize > 0 && bytes_needed <= (size_t) newsize)
366  {
367  newbuf = realloc(conn->outBuffer, newsize);
368  if (newbuf)
369  {
370  /* realloc succeeded */
371  conn->outBuffer = newbuf;
372  conn->outBufSize = newsize;
373  return 0;
374  }
375  }
376 
377  newsize = conn->outBufSize;
378  do
379  {
380  newsize += 8192;
381  } while (newsize > 0 && bytes_needed > (size_t) newsize);
382 
383  if (newsize > 0 && bytes_needed <= (size_t) newsize)
384  {
385  newbuf = realloc(conn->outBuffer, newsize);
386  if (newbuf)
387  {
388  /* realloc succeeded */
389  conn->outBuffer = newbuf;
390  conn->outBufSize = newsize;
391  return 0;
392  }
393  }
394 
395  /* realloc failed. Probably out of memory */
397  "cannot allocate memory for output buffer\n");
398  return EOF;
399 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
PQExpBufferData errorMessage
Definition: libpq-int.h:493
int outBufSize
Definition: libpq-int.h:437
#define realloc(a, b)
Definition: header.h:60
char * outBuffer
Definition: libpq-int.h:436

◆ pqClearAsyncResult()

void pqClearAsyncResult ( PGconn conn)

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

References pg_conn::next_result, PQclear(), and pg_conn::result.

Referenced by closePGconn(), getAnotherTuple(), getParamDescriptions(), getRowDescriptions(), pqGetErrorNotice2(), pqGetErrorNotice3(), pqSaveErrorResult(), and PQsendQueryStart().

727 {
728  if (conn->result)
729  PQclear(conn->result);
730  conn->result = NULL;
731  if (conn->next_result)
732  PQclear(conn->next_result);
733  conn->next_result = NULL;
734 }
PGresult * result
Definition: libpq-int.h:450
PGresult * next_result
Definition: libpq-int.h:451
void PQclear(PGresult *res)
Definition: fe-exec.c:671

◆ pqDropConnection()

void pqDropConnection ( PGconn conn,
bool  flushInput 
)

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

References closesocket, free, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, pg_conn::outCount, pg_fe_scram_free(), PGINVALID_SOCKET, pqsecure_close(), pg_conn::sasl_state, and pg_conn::sock.

Referenced by closePGconn(), connectDBComplete(), connectDBStart(), handleSyncLoss(), PQconnectPoll(), and pqReadData().

425 {
426  /* Drop any SSL state */
427  pqsecure_close(conn);
428 
429  /* Close the socket itself */
430  if (conn->sock != PGINVALID_SOCKET)
431  closesocket(conn->sock);
432  conn->sock = PGINVALID_SOCKET;
433 
434  /* Optionally discard any unread data */
435  if (flushInput)
436  conn->inStart = conn->inCursor = conn->inEnd = 0;
437 
438  /* Always discard any unsent data */
439  conn->outCount = 0;
440 
441  /* Free authentication state */
442 #ifdef ENABLE_GSS
443  {
444  OM_uint32 min_s;
445 
446  if (conn->gctx)
447  gss_delete_sec_context(&min_s, &conn->gctx, GSS_C_NO_BUFFER);
448  if (conn->gtarg_nam)
449  gss_release_name(&min_s, &conn->gtarg_nam);
450  }
451 #endif
452 #ifdef ENABLE_SSPI
453  if (conn->sspitarget)
454  {
455  free(conn->sspitarget);
456  conn->sspitarget = NULL;
457  }
458  if (conn->sspicred)
459  {
460  FreeCredentialsHandle(conn->sspicred);
461  free(conn->sspicred);
462  conn->sspicred = NULL;
463  }
464  if (conn->sspictx)
465  {
466  DeleteSecurityContext(conn->sspictx);
467  free(conn->sspictx);
468  conn->sspictx = NULL;
469  }
470  conn->usesspi = 0;
471 #endif
472  if (conn->sasl_state)
473  {
474  /*
475  * XXX: if support for more authentication mechanisms is added, this
476  * needs to call the right 'free' function.
477  */
479  conn->sasl_state = NULL;
480  }
481 }
int inEnd
Definition: libpq-int.h:433
int inStart
Definition: libpq-int.h:431
void pg_fe_scram_free(void *opaq)
#define closesocket
Definition: port.h:292
int outCount
Definition: libpq-int.h:438
void pqsecure_close(PGconn *conn)
Definition: fe-secure.c:189
void * sasl_state
Definition: libpq-int.h:454
pgsocket sock
Definition: libpq-int.h:400
#define PGINVALID_SOCKET
Definition: port.h:33
#define free(a)
Definition: header.h:65
int inCursor
Definition: libpq-int.h:432

◆ pqEndcopy2()

int pqEndcopy2 ( PGconn conn)

Definition at line 1343 of file fe-protocol2.c.

References pg_conn::asyncStatus, PQExpBufferData::data, pg_conn::errorMessage, PQExpBufferData::len, libpq_gettext, pg_conn::noticeHooks, PGASYNC_BUSY, PGASYNC_COPY_IN, PGASYNC_COPY_OUT, PGRES_COMMAND_OK, PQclear(), pqFlush(), PQgetResult(), pqInternalNotice(), PQisBusy(), pqIsnonblocking, PQreset(), PQresetStart(), printfPQExpBuffer(), resetPQExpBuffer(), and pg_result::resultStatus.

Referenced by PQendcopy().

1344 {
1345  PGresult *result;
1346 
1347  if (conn->asyncStatus != PGASYNC_COPY_IN &&
1348  conn->asyncStatus != PGASYNC_COPY_OUT)
1349  {
1351  libpq_gettext("no COPY in progress\n"));
1352  return 1;
1353  }
1354 
1355  /*
1356  * make sure no data is waiting to be sent, abort if we are non-blocking
1357  * and the flush fails
1358  */
1359  if (pqFlush(conn) && pqIsnonblocking(conn))
1360  return 1;
1361 
1362  /* non blocking connections may have to abort at this point. */
1363  if (pqIsnonblocking(conn) && PQisBusy(conn))
1364  return 1;
1365 
1366  /* Return to active duty */
1367  conn->asyncStatus = PGASYNC_BUSY;
1369 
1370  /* Wait for the completion response */
1371  result = PQgetResult(conn);
1372 
1373  /* Expecting a successful result */
1374  if (result && result->resultStatus == PGRES_COMMAND_OK)
1375  {
1376  PQclear(result);
1377  return 0;
1378  }
1379 
1380  /*
1381  * Trouble. For backwards-compatibility reasons, we issue the error
1382  * message as if it were a notice (would be nice to get rid of this
1383  * silliness, but too many apps probably don't handle errors from
1384  * PQendcopy reasonably). Note that the app can still obtain the error
1385  * status from the PGconn object.
1386  */
1387  if (conn->errorMessage.len > 0)
1388  {
1389  /* We have to strip the trailing newline ... pain in neck... */
1390  char svLast = conn->errorMessage.data[conn->errorMessage.len - 1];
1391 
1392  if (svLast == '\n')
1393  conn->errorMessage.data[conn->errorMessage.len - 1] = '\0';
1394  pqInternalNotice(&conn->noticeHooks, "%s", conn->errorMessage.data);
1395  conn->errorMessage.data[conn->errorMessage.len - 1] = svLast;
1396  }
1397 
1398  PQclear(result);
1399 
1400  /*
1401  * The worst case is that we've lost sync with the backend entirely due to
1402  * application screwup of the copy in/out protocol. To recover, reset the
1403  * connection (talk about using a sledgehammer...)
1404  */
1406  "lost synchronization with server, resetting connection");
1407 
1408  /*
1409  * Users doing non-blocking connections need to handle the reset
1410  * themselves, they'll need to check the connection status if we return an
1411  * error.
1412  */
1413  if (pqIsnonblocking(conn))
1414  PQresetStart(conn);
1415  else
1416  PQreset(conn);
1417 
1418  return 1;
1419 }
int pqFlush(PGconn *conn)
Definition: fe-misc.c:961
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
int PQresetStart(PGconn *conn)
Definition: fe-connect.c:3684
#define pqIsnonblocking(conn)
Definition: libpq-int.h:679
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:380
PGNoticeHooks noticeHooks
Definition: libpq-int.h:371
void pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
Definition: fe-exec.c:822
PQExpBufferData errorMessage
Definition: libpq-int.h:493
void PQclear(PGresult *res)
Definition: fe-exec.c:671
int PQisBusy(PGconn *conn)
Definition: fe-exec.c:1732
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:145
ExecStatusType resultStatus
Definition: libpq-int.h:177
PGresult * PQgetResult(PGconn *conn)
Definition: fe-exec.c:1753
#define libpq_gettext(x)
Definition: libpq-int.h:685
void PQreset(PGconn *conn)
Definition: fe-connect.c:3643

◆ pqEndcopy3()

int pqEndcopy3 ( PGconn conn)

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

References pg_conn::asyncStatus, PQExpBufferData::data, pg_conn::errorMessage, PQExpBufferData::len, libpq_gettext, 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, pqPutMsgEnd(), pqPutMsgStart(), printfPQExpBuffer(), pg_conn::queryclass, resetPQExpBuffer(), and pg_result::resultStatus.

Referenced by PQendcopy().

1808 {
1809  PGresult *result;
1810 
1811  if (conn->asyncStatus != PGASYNC_COPY_IN &&
1812  conn->asyncStatus != PGASYNC_COPY_OUT &&
1813  conn->asyncStatus != PGASYNC_COPY_BOTH)
1814  {
1816  libpq_gettext("no COPY in progress\n"));
1817  return 1;
1818  }
1819 
1820  /* Send the CopyDone message if needed */
1821  if (conn->asyncStatus == PGASYNC_COPY_IN ||
1822  conn->asyncStatus == PGASYNC_COPY_BOTH)
1823  {
1824  if (pqPutMsgStart('c', false, conn) < 0 ||
1825  pqPutMsgEnd(conn) < 0)
1826  return 1;
1827 
1828  /*
1829  * If we sent the COPY command in extended-query mode, we must issue a
1830  * Sync as well.
1831  */
1832  if (conn->queryclass != PGQUERY_SIMPLE)
1833  {
1834  if (pqPutMsgStart('S', false, conn) < 0 ||
1835  pqPutMsgEnd(conn) < 0)
1836  return 1;
1837  }
1838  }
1839 
1840  /*
1841  * make sure no data is waiting to be sent, abort if we are non-blocking
1842  * and the flush fails
1843  */
1844  if (pqFlush(conn) && pqIsnonblocking(conn))
1845  return 1;
1846 
1847  /* Return to active duty */
1848  conn->asyncStatus = PGASYNC_BUSY;
1850 
1851  /*
1852  * Non blocking connections may have to abort at this point. If everyone
1853  * played the game there should be no problem, but in error scenarios the
1854  * expected messages may not have arrived yet. (We are assuming that the
1855  * backend's packetizing will ensure that CommandComplete arrives along
1856  * with the CopyDone; are there corner cases where that doesn't happen?)
1857  */
1858  if (pqIsnonblocking(conn) && PQisBusy(conn))
1859  return 1;
1860 
1861  /* Wait for the completion response */
1862  result = PQgetResult(conn);
1863 
1864  /* Expecting a successful result */
1865  if (result && result->resultStatus == PGRES_COMMAND_OK)
1866  {
1867  PQclear(result);
1868  return 0;
1869  }
1870 
1871  /*
1872  * Trouble. For backwards-compatibility reasons, we issue the error
1873  * message as if it were a notice (would be nice to get rid of this
1874  * silliness, but too many apps probably don't handle errors from
1875  * PQendcopy reasonably). Note that the app can still obtain the error
1876  * status from the PGconn object.
1877  */
1878  if (conn->errorMessage.len > 0)
1879  {
1880  /* We have to strip the trailing newline ... pain in neck... */
1881  char svLast = conn->errorMessage.data[conn->errorMessage.len - 1];
1882 
1883  if (svLast == '\n')
1884  conn->errorMessage.data[conn->errorMessage.len - 1] = '\0';
1885  pqInternalNotice(&conn->noticeHooks, "%s", conn->errorMessage.data);
1886  conn->errorMessage.data[conn->errorMessage.len - 1] = svLast;
1887  }
1888 
1889  PQclear(result);
1890 
1891  return 1;
1892 }
int pqFlush(PGconn *conn)
Definition: fe-misc.c:961
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
#define pqIsnonblocking(conn)
Definition: libpq-int.h:679
PGQueryClass queryclass
Definition: libpq-int.h:382
int pqPutMsgStart(char msg_type, bool force_len, PGconn *conn)
Definition: fe-misc.c:519
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:380
PGNoticeHooks noticeHooks
Definition: libpq-int.h:371
void pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
Definition: fe-exec.c:822
PQExpBufferData errorMessage
Definition: libpq-int.h:493
void PQclear(PGresult *res)
Definition: fe-exec.c:671
int PQisBusy(PGconn *conn)
Definition: fe-exec.c:1732
int pqPutMsgEnd(PGconn *conn)
Definition: fe-misc.c:587
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:145
ExecStatusType resultStatus
Definition: libpq-int.h:177
PGresult * PQgetResult(PGconn *conn)
Definition: fe-exec.c:1753
#define libpq_gettext(x)
Definition: libpq-int.h:685

◆ pqFlush()

int pqFlush ( PGconn conn)

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

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

Referenced by pg_SASL_init(), PQconnectPoll(), PQconsumeInput(), pqEndcopy2(), pqEndcopy3(), PQflush(), pqFunctionCall2(), pqFunctionCall3(), PQgetResult(), pqPacketSend(), PQputCopyData(), PQputCopyEnd(), PQsendDescribe(), PQsendPrepare(), PQsendQuery(), PQsendQueryGuts(), PQsetnonblocking(), and sendTerminateConn().

962 {
963  if (conn->Pfdebug)
964  fflush(conn->Pfdebug);
965 
966  if (conn->outCount > 0)
967  return pqSendSome(conn, conn->outCount);
968 
969  return 0;
970 }
int outCount
Definition: libpq-int.h:438
FILE * Pfdebug
Definition: libpq-int.h:368
static int pqSendSome(PGconn *conn, int len)
Definition: fe-misc.c:829

◆ pqFunctionCall2()

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

Definition at line 1428 of file fe-protocol2.c.

References pg_conn::errorMessage, getNotify(), i, pg_conn::inCursor, pg_conn::inStart, PQArgBlock::integer, PQArgBlock::len, libpq_gettext, PGRES_COMMAND_OK, PGRES_FATAL_ERROR, pqFlush(), pqGetc(), pqGetErrorNotice2(), pqGetInt(), pqGetnchar(), pqHandleSendFailure(), PQmakeEmptyPGresult(), pqPrepareAsyncResult(), pqPutInt(), pqPutMsgEnd(), pqPutMsgStart(), pqPutnchar(), pqPuts(), pqReadData(), pqSaveErrorResult(), pqWait(), printfPQExpBuffer(), PQArgBlock::ptr, pg_conn::result, and status().

Referenced by PQfn().

1432 {
1433  bool needInput = false;
1435  char id;
1436  int i;
1437 
1438  /* PQfn already validated connection state */
1439 
1440  if (pqPutMsgStart('F', false, conn) < 0 || /* function call msg */
1441  pqPuts(" ", conn) < 0 || /* dummy string */
1442  pqPutInt(fnid, 4, conn) != 0 || /* function id */
1443  pqPutInt(nargs, 4, conn) != 0) /* # of args */
1444  {
1445  pqHandleSendFailure(conn);
1446  return NULL;
1447  }
1448 
1449  for (i = 0; i < nargs; ++i)
1450  { /* len.int4 + contents */
1451  if (pqPutInt(args[i].len, 4, conn))
1452  {
1453  pqHandleSendFailure(conn);
1454  return NULL;
1455  }
1456 
1457  if (args[i].isint)
1458  {
1459  if (pqPutInt(args[i].u.integer, 4, conn))
1460  {
1461  pqHandleSendFailure(conn);
1462  return NULL;
1463  }
1464  }
1465  else
1466  {
1467  if (pqPutnchar((char *) args[i].u.ptr, args[i].len, conn))
1468  {
1469  pqHandleSendFailure(conn);
1470  return NULL;
1471  }
1472  }
1473  }
1474 
1475  if (pqPutMsgEnd(conn) < 0 ||
1476  pqFlush(conn))
1477  {
1478  pqHandleSendFailure(conn);
1479  return NULL;
1480  }
1481 
1482  for (;;)
1483  {
1484  if (needInput)
1485  {
1486  /* Wait for some data to arrive (or for the channel to close) */
1487  if (pqWait(true, false, conn) ||
1488  pqReadData(conn) < 0)
1489  break;
1490  }
1491 
1492  /*
1493  * Scan the message. If we run out of data, loop around to try again.
1494  */
1495  conn->inCursor = conn->inStart;
1496  needInput = true;
1497 
1498  if (pqGetc(&id, conn))
1499  continue;
1500 
1501  /*
1502  * We should see V or E response to the command, but might get N
1503  * and/or A notices first. We also need to swallow the final Z before
1504  * returning.
1505  */
1506  switch (id)
1507  {
1508  case 'V': /* function result */
1509  if (pqGetc(&id, conn))
1510  continue;
1511  if (id == 'G')
1512  {
1513  /* function returned nonempty value */
1514  if (pqGetInt(actual_result_len, 4, conn))
1515  continue;
1516  if (result_is_int)
1517  {
1518  if (pqGetInt(result_buf, 4, conn))
1519  continue;
1520  }
1521  else
1522  {
1523  if (pqGetnchar((char *) result_buf,
1524  *actual_result_len,
1525  conn))
1526  continue;
1527  }
1528  if (pqGetc(&id, conn)) /* get the last '0' */
1529  continue;
1530  }
1531  if (id == '0')
1532  {
1533  /* correctly finished function result message */
1534  status = PGRES_COMMAND_OK;
1535  }
1536  else
1537  {
1538  /* The backend violates the protocol. */
1540  libpq_gettext("protocol error: id=0x%x\n"),
1541  id);
1542  pqSaveErrorResult(conn);
1543  conn->inStart = conn->inCursor;
1544  return pqPrepareAsyncResult(conn);
1545  }
1546  break;
1547  case 'E': /* error return */
1548  if (pqGetErrorNotice2(conn, true))
1549  continue;
1550  status = PGRES_FATAL_ERROR;
1551  break;
1552  case 'A': /* notify message */
1553  /* handle notify and go back to processing return values */
1554  if (getNotify(conn))
1555  continue;
1556  break;
1557  case 'N': /* notice */
1558  /* handle notice and go back to processing return values */
1559  if (pqGetErrorNotice2(conn, false))
1560  continue;
1561  break;
1562  case 'Z': /* backend is ready for new query */
1563  /* consume the message and exit */
1564  conn->inStart = conn->inCursor;
1565  /* if we saved a result object (probably an error), use it */
1566  if (conn->result)
1567  return pqPrepareAsyncResult(conn);
1568  return PQmakeEmptyPGresult(conn, status);
1569  default:
1570  /* The backend violates the protocol. */
1572  libpq_gettext("protocol error: id=0x%x\n"),
1573  id);
1574  pqSaveErrorResult(conn);
1575  conn->inStart = conn->inCursor;
1576  return pqPrepareAsyncResult(conn);
1577  }
1578  /* Completed this message, keep going */
1579  conn->inStart = conn->inCursor;
1580  needInput = false;
1581  }
1582 
1583  /*
1584  * We fall out of the loop only upon failing to read data.
1585  * conn->errorMessage has been set by pqWait or pqReadData. We want to
1586  * append it to any already-received error message.
1587  */
1588  pqSaveErrorResult(conn);
1589  return pqPrepareAsyncResult(conn);
1590 }
int pqFlush(PGconn *conn)
Definition: fe-misc.c:961
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
void pqHandleSendFailure(PGconn *conn)
Definition: fe-exec.c:1633
int inStart
Definition: libpq-int.h:431
int pqPutMsgStart(char msg_type, bool force_len, PGconn *conn)
Definition: fe-misc.c:519
int pqGetInt(int *result, size_t bytes, PGconn *conn)
Definition: fe-misc.c:267
ExecStatusType
Definition: libpq-fe.h:82
int pqGetnchar(char *s, size_t len, PGconn *conn)
Definition: fe-misc.c:195
PGresult * pqPrepareAsyncResult(PGconn *conn)
Definition: fe-exec.c:777
PGresult * result
Definition: libpq-int.h:450
int pqPutInt(int value, size_t bytes, PGconn *conn)
Definition: fe-misc.c:307
int pqReadData(PGconn *conn)
Definition: fe-misc.c:629
int pqWait(int forRead, int forWrite, PGconn *conn)
Definition: fe-misc.c:984
PGresult * PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
Definition: fe-exec.c:142
int pqPuts(const char *s, PGconn *conn)
Definition: fe-misc.c:179
int pqGetc(char *result, PGconn *conn)
Definition: fe-misc.c:94
static int getNotify(PGconn *conn)
PQExpBufferData errorMessage
Definition: libpq-int.h:493
int pqPutnchar(const char *s, size_t len, PGconn *conn)
Definition: fe-misc.c:246
int pqPutMsgEnd(PGconn *conn)
Definition: fe-misc.c:587
int i
void pqSaveErrorResult(PGconn *conn)
Definition: fe-exec.c:749
int inCursor
Definition: libpq-int.h:432
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
int * ptr
Definition: libpq-fe.h:226
#define libpq_gettext(x)
Definition: libpq-int.h:685
int integer
Definition: libpq-fe.h:227
static int pqGetErrorNotice2(PGconn *conn, bool isError)
Definition: fe-protocol2.c:962

◆ 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 1901 of file fe-protocol3.c.

References pg_conn::errorMessage, getNotify(), getParameterStatus(), getReadyForQuery(), handleSyncLoss(), i, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, PQArgBlock::integer, PQArgBlock::len, libpq_gettext, PGRES_COMMAND_OK, PGRES_FATAL_ERROR, pqCheckInBufferSpace(), pqFlush(), pqGetc(), pqGetErrorNotice3(), pqGetInt(), pqGetnchar(), pqHandleSendFailure(), PQmakeEmptyPGresult(), pqPrepareAsyncResult(), pqPutInt(), pqPutMsgEnd(), pqPutMsgStart(), pqPutnchar(), pqReadData(), pqSaveErrorResult(), pqWait(), printfPQExpBuffer(), PQArgBlock::ptr, pg_conn::result, status(), and VALID_LONG_MESSAGE_TYPE.

Referenced by PQfn().

1905 {
1906  bool needInput = false;
1908  char id;
1909  int msgLength;
1910  int avail;
1911  int i;
1912 
1913  /* PQfn already validated connection state */
1914 
1915  if (pqPutMsgStart('F', false, conn) < 0 || /* function call msg */
1916  pqPutInt(fnid, 4, conn) < 0 || /* function id */
1917  pqPutInt(1, 2, conn) < 0 || /* # of format codes */
1918  pqPutInt(1, 2, conn) < 0 || /* format code: BINARY */
1919  pqPutInt(nargs, 2, conn) < 0) /* # of args */
1920  {
1921  pqHandleSendFailure(conn);
1922  return NULL;
1923  }
1924 
1925  for (i = 0; i < nargs; ++i)
1926  { /* len.int4 + contents */
1927  if (pqPutInt(args[i].len, 4, conn))
1928  {
1929  pqHandleSendFailure(conn);
1930  return NULL;
1931  }
1932  if (args[i].len == -1)
1933  continue; /* it's NULL */
1934 
1935  if (args[i].isint)
1936  {
1937  if (pqPutInt(args[i].u.integer, args[i].len, conn))
1938  {
1939  pqHandleSendFailure(conn);
1940  return NULL;
1941  }
1942  }
1943  else
1944  {
1945  if (pqPutnchar((char *) args[i].u.ptr, args[i].len, conn))
1946  {
1947  pqHandleSendFailure(conn);
1948  return NULL;
1949  }
1950  }
1951  }
1952 
1953  if (pqPutInt(1, 2, conn) < 0) /* result format code: BINARY */
1954  {
1955  pqHandleSendFailure(conn);
1956  return NULL;
1957  }
1958 
1959  if (pqPutMsgEnd(conn) < 0 ||
1960  pqFlush(conn))
1961  {
1962  pqHandleSendFailure(conn);
1963  return NULL;
1964  }
1965 
1966  for (;;)
1967  {
1968  if (needInput)
1969  {
1970  /* Wait for some data to arrive (or for the channel to close) */
1971  if (pqWait(true, false, conn) ||
1972  pqReadData(conn) < 0)
1973  break;
1974  }
1975 
1976  /*
1977  * Scan the message. If we run out of data, loop around to try again.
1978  */
1979  needInput = true;
1980 
1981  conn->inCursor = conn->inStart;
1982  if (pqGetc(&id, conn))
1983  continue;
1984  if (pqGetInt(&msgLength, 4, conn))
1985  continue;
1986 
1987  /*
1988  * Try to validate message type/length here. A length less than 4 is
1989  * definitely broken. Large lengths should only be believed for a few
1990  * message types.
1991  */
1992  if (msgLength < 4)
1993  {
1994  handleSyncLoss(conn, id, msgLength);
1995  break;
1996  }
1997  if (msgLength > 30000 && !VALID_LONG_MESSAGE_TYPE(id))
1998  {
1999  handleSyncLoss(conn, id, msgLength);
2000  break;
2001  }
2002 
2003  /*
2004  * Can't process if message body isn't all here yet.
2005  */
2006  msgLength -= 4;
2007  avail = conn->inEnd - conn->inCursor;
2008  if (avail < msgLength)
2009  {
2010  /*
2011  * Before looping, enlarge the input buffer if needed to hold the
2012  * whole message. See notes in parseInput.
2013  */
2014  if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength,
2015  conn))
2016  {
2017  /*
2018  * XXX add some better recovery code... plan is to skip over
2019  * the message using its length, then report an error. For the
2020  * moment, just treat this like loss of sync (which indeed it
2021  * might be!)
2022  */
2023  handleSyncLoss(conn, id, msgLength);
2024  break;
2025  }
2026  continue;
2027  }
2028 
2029  /*
2030  * We should see V or E response to the command, but might get N
2031  * and/or A notices first. We also need to swallow the final Z before
2032  * returning.
2033  */
2034  switch (id)
2035  {
2036  case 'V': /* function result */
2037  if (pqGetInt(actual_result_len, 4, conn))
2038  continue;
2039  if (*actual_result_len != -1)
2040  {
2041  if (result_is_int)
2042  {
2043  if (pqGetInt(result_buf, *actual_result_len, conn))
2044  continue;
2045  }
2046  else
2047  {
2048  if (pqGetnchar((char *) result_buf,
2049  *actual_result_len,
2050  conn))
2051  continue;
2052  }
2053  }
2054  /* correctly finished function result message */
2055  status = PGRES_COMMAND_OK;
2056  break;
2057  case 'E': /* error return */
2058  if (pqGetErrorNotice3(conn, true))
2059  continue;
2060  status = PGRES_FATAL_ERROR;
2061  break;
2062  case 'A': /* notify message */
2063  /* handle notify and go back to processing return values */
2064  if (getNotify(conn))
2065  continue;
2066  break;
2067  case 'N': /* notice */
2068  /* handle notice and go back to processing return values */
2069  if (pqGetErrorNotice3(conn, false))
2070  continue;
2071  break;
2072  case 'Z': /* backend is ready for new query */
2073  if (getReadyForQuery(conn))
2074  continue;
2075  /* consume the message and exit */
2076  conn->inStart += 5 + msgLength;
2077  /* if we saved a result object (probably an error), use it */
2078  if (conn->result)
2079  return pqPrepareAsyncResult(conn);
2080  return PQmakeEmptyPGresult(conn, status);
2081  case 'S': /* parameter status */
2082  if (getParameterStatus(conn))
2083  continue;
2084  break;
2085  default:
2086  /* The backend violates the protocol. */
2088  libpq_gettext("protocol error: id=0x%x\n"),
2089  id);
2090  pqSaveErrorResult(conn);
2091  /* trust the specified message length as what to skip */
2092  conn->inStart += 5 + msgLength;
2093  return pqPrepareAsyncResult(conn);
2094  }
2095  /* Completed this message, keep going */
2096  /* trust the specified message length as what to skip */
2097  conn->inStart += 5 + msgLength;
2098  needInput = false;
2099  }
2100 
2101  /*
2102  * We fall out of the loop only upon failing to read data.
2103  * conn->errorMessage has been set by pqWait or pqReadData. We want to
2104  * append it to any already-received error message.
2105  */
2106  pqSaveErrorResult(conn);
2107  return pqPrepareAsyncResult(conn);
2108 }
int pqFlush(PGconn *conn)
Definition: fe-misc.c:961
int inEnd
Definition: libpq-int.h:433
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
void pqHandleSendFailure(PGconn *conn)
Definition: fe-exec.c:1633
int inStart
Definition: libpq-int.h:431
int pqCheckInBufferSpace(size_t bytes_needed, PGconn *conn)
Definition: fe-misc.c:408
int pqPutMsgStart(char msg_type, bool force_len, PGconn *conn)
Definition: fe-misc.c:519
int pqGetInt(int *result, size_t bytes, PGconn *conn)
Definition: fe-misc.c:267
ExecStatusType
Definition: libpq-fe.h:82
int pqGetnchar(char *s, size_t len, PGconn *conn)
Definition: fe-misc.c:195
PGresult * pqPrepareAsyncResult(PGconn *conn)
Definition: fe-exec.c:777
PGresult * result
Definition: libpq-int.h:450
int pqPutInt(int value, size_t bytes, PGconn *conn)
Definition: fe-misc.c:307
int pqGetErrorNotice3(PGconn *conn, bool isError)
Definition: fe-protocol3.c:875
int pqReadData(PGconn *conn)
Definition: fe-misc.c:629
int pqWait(int forRead, int forWrite, PGconn *conn)
Definition: fe-misc.c:984
PGresult * PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
Definition: fe-exec.c:142
int pqGetc(char *result, PGconn *conn)
Definition: fe-misc.c:94
#define VALID_LONG_MESSAGE_TYPE(id)
Definition: fe-protocol3.c:40
PQExpBufferData errorMessage
Definition: libpq-int.h:493
int pqPutnchar(const char *s, size_t len, PGconn *conn)
Definition: fe-misc.c:246
static int getReadyForQuery(PGconn *conn)
int pqPutMsgEnd(PGconn *conn)
Definition: fe-misc.c:587
static int getParameterStatus(PGconn *conn)
static int getNotify(PGconn *conn)
int i
static void handleSyncLoss(PGconn *conn, char id, int msgLength)
Definition: fe-protocol3.c:449
void pqSaveErrorResult(PGconn *conn)
Definition: fe-exec.c:749
int inCursor
Definition: libpq-int.h:432
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
int * ptr
Definition: libpq-fe.h:226
#define libpq_gettext(x)
Definition: libpq-int.h:685
int integer
Definition: libpq-fe.h:227

◆ pqGetc()

int pqGetc ( char *  result,
PGconn conn 
)

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

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

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

95 {
96  if (conn->inCursor >= conn->inEnd)
97  return EOF;
98 
99  *result = conn->inBuffer[conn->inCursor++];
100 
101  if (conn->Pfdebug)
102  fprintf(conn->Pfdebug, "From backend> %c\n", *result);
103 
104  return 0;
105 }
int inEnd
Definition: libpq-int.h:433
FILE * Pfdebug
Definition: libpq-int.h:368
char * inBuffer
Definition: libpq-int.h:429
int inCursor
Definition: libpq-int.h:432

◆ pqGetCopyData2()

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

Definition at line 1160 of file fe-protocol2.c.

References pg_conn::asyncStatus, pg_conn::errorMessage, pg_conn::inBuffer, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, libpq_gettext, malloc, PGASYNC_BUSY, pqReadData(), pqWait(), and printfPQExpBuffer().

Referenced by PQgetCopyData().

1161 {
1162  bool found;
1163  int msgLength;
1164 
1165  for (;;)
1166  {
1167  /*
1168  * Do we have a complete line of data?
1169  */
1170  conn->inCursor = conn->inStart;
1171  found = false;
1172  while (conn->inCursor < conn->inEnd)
1173  {
1174  char c = conn->inBuffer[conn->inCursor++];
1175 
1176  if (c == '\n')
1177  {
1178  found = true;
1179  break;
1180  }
1181  }
1182  if (!found)
1183  goto nodata;
1184  msgLength = conn->inCursor - conn->inStart;
1185 
1186  /*
1187  * If it's the end-of-data marker, consume it, exit COPY_OUT mode, and
1188  * let caller read status with PQgetResult().
1189  */
1190  if (msgLength == 3 &&
1191  strncmp(&conn->inBuffer[conn->inStart], "\\.\n", 3) == 0)
1192  {
1193  conn->inStart = conn->inCursor;
1194  conn->asyncStatus = PGASYNC_BUSY;
1195  return -1;
1196  }
1197 
1198  /*
1199  * Pass the line back to the caller.
1200  */
1201  *buffer = (char *) malloc(msgLength + 1);
1202  if (*buffer == NULL)
1203  {
1205  libpq_gettext("out of memory\n"));
1206  return -2;
1207  }
1208  memcpy(*buffer, &conn->inBuffer[conn->inStart], msgLength);
1209  (*buffer)[msgLength] = '\0'; /* Add terminating null */
1210 
1211  /* Mark message consumed */
1212  conn->inStart = conn->inCursor;
1213 
1214  return msgLength;
1215 
1216 nodata:
1217  /* Don't block if async read requested */
1218  if (async)
1219  return 0;
1220  /* Need to load more data */
1221  if (pqWait(true, false, conn) ||
1222  pqReadData(conn) < 0)
1223  return -2;
1224  }
1225 }
int inEnd
Definition: libpq-int.h:433
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
int inStart
Definition: libpq-int.h:431
#define malloc(a)
Definition: header.h:50
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:380
int pqReadData(PGconn *conn)
Definition: fe-misc.c:629
char * c
int pqWait(int forRead, int forWrite, PGconn *conn)
Definition: fe-misc.c:984
char * inBuffer
Definition: libpq-int.h:429
PQExpBufferData errorMessage
Definition: libpq-int.h:493
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
int inCursor
Definition: libpq-int.h:432
#define libpq_gettext(x)
Definition: libpq-int.h:685

◆ pqGetCopyData3()

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

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

References pg_conn::errorMessage, getCopyDataMessage(), pg_conn::inBuffer, pg_conn::inCursor, pg_conn::inStart, libpq_gettext, malloc, pqReadData(), pqWait(), and printfPQExpBuffer().

Referenced by PQgetCopyData().

1641 {
1642  int msgLength;
1643 
1644  for (;;)
1645  {
1646  /*
1647  * Collect the next input message. To make life simpler for async
1648  * callers, we keep returning 0 until the next message is fully
1649  * available, even if it is not Copy Data.
1650  */
1651  msgLength = getCopyDataMessage(conn);
1652  if (msgLength < 0)
1653  return msgLength; /* end-of-copy or error */
1654  if (msgLength == 0)
1655  {
1656  /* Don't block if async read requested */
1657  if (async)
1658  return 0;
1659  /* Need to load more data */
1660  if (pqWait(true, false, conn) ||
1661  pqReadData(conn) < 0)
1662  return -2;
1663  continue;
1664  }
1665 
1666  /*
1667  * Drop zero-length messages (shouldn't happen anyway). Otherwise
1668  * pass the data back to the caller.
1669  */
1670  msgLength -= 4;
1671  if (msgLength > 0)
1672  {
1673  *buffer = (char *) malloc(msgLength + 1);
1674  if (*buffer == NULL)
1675  {
1677  libpq_gettext("out of memory\n"));
1678  return -2;
1679  }
1680  memcpy(*buffer, &conn->inBuffer[conn->inCursor], msgLength);
1681  (*buffer)[msgLength] = '\0'; /* Add terminating null */
1682 
1683  /* Mark message consumed */
1684  conn->inStart = conn->inCursor + msgLength;
1685 
1686  return msgLength;
1687  }
1688 
1689  /* Empty, so drop it and loop around for another */
1690  conn->inStart = conn->inCursor;
1691  }
1692 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
int inStart
Definition: libpq-int.h:431
#define malloc(a)
Definition: header.h:50
int pqReadData(PGconn *conn)
Definition: fe-misc.c:629
int pqWait(int forRead, int forWrite, PGconn *conn)
Definition: fe-misc.c:984
char * inBuffer
Definition: libpq-int.h:429
static int getCopyDataMessage(PGconn *conn)
PQExpBufferData errorMessage
Definition: libpq-int.h:493
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
int inCursor
Definition: libpq-int.h:432
#define libpq_gettext(x)
Definition: libpq-int.h:685

◆ pqGetErrorNotice3()

int pqGetErrorNotice3 ( PGconn conn,
bool  isError 
)

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

References appendPQExpBufferStr(), PQExpBufferData::data, pg_result::errMsg, pg_conn::errorMessage, pg_result::errQuery, initPQExpBuffer(), pg_conn::last_query, pg_conn::last_sqlstate, 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, pqBuildErrorMessage3(), PQclear(), pqClearAsyncResult(), PQExpBufferDataBroken, pqGetc(), pqGets(), PQmakeEmptyPGresult(), pqResultStrdup(), pqSaveMessageField(), printfPQExpBuffer(), resetPQExpBuffer(), pg_conn::result, pg_result::resultStatus, pg_conn::show_context, strlcpy(), termPQExpBuffer(), and pg_conn::verbosity.

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

876 {
877  PGresult *res = NULL;
878  bool have_position = false;
879  PQExpBufferData workBuf;
880  char id;
881 
882  /*
883  * Since the fields might be pretty long, we create a temporary
884  * PQExpBuffer rather than using conn->workBuffer. workBuffer is intended
885  * for stuff that is expected to be short. We shouldn't use
886  * conn->errorMessage either, since this might be only a notice.
887  */
888  initPQExpBuffer(&workBuf);
889 
890  /*
891  * Make a PGresult to hold the accumulated fields. We temporarily lie
892  * about the result status, so that PQmakeEmptyPGresult doesn't uselessly
893  * copy conn->errorMessage.
894  *
895  * NB: This allocation can fail, if you run out of memory. The rest of the
896  * function handles that gracefully, and we still try to set the error
897  * message as the connection's error message.
898  */
900  if (res)
902 
903  /*
904  * Read the fields and save into res.
905  *
906  * While at it, save the SQLSTATE in conn->last_sqlstate, and note whether
907  * we saw a PG_DIAG_STATEMENT_POSITION field.
908  */
909  for (;;)
910  {
911  if (pqGetc(&id, conn))
912  goto fail;
913  if (id == '\0')
914  break; /* terminator found */
915  if (pqGets(&workBuf, conn))
916  goto fail;
917  pqSaveMessageField(res, id, workBuf.data);
918  if (id == PG_DIAG_SQLSTATE)
919  strlcpy(conn->last_sqlstate, workBuf.data,
920  sizeof(conn->last_sqlstate));
921  else if (id == PG_DIAG_STATEMENT_POSITION)
922  have_position = true;
923  }
924 
925  /*
926  * Save the active query text, if any, into res as well; but only if we
927  * might need it for an error cursor display, which is only true if there
928  * is a PG_DIAG_STATEMENT_POSITION field.
929  */
930  if (have_position && conn->last_query && res)
931  res->errQuery = pqResultStrdup(res, conn->last_query);
932 
933  /*
934  * Now build the "overall" error message for PQresultErrorMessage.
935  */
936  resetPQExpBuffer(&workBuf);
937  pqBuildErrorMessage3(&workBuf, res, conn->verbosity, conn->show_context);
938 
939  /*
940  * Either save error as current async result, or just emit the notice.
941  */
942  if (isError)
943  {
944  if (res)
945  res->errMsg = pqResultStrdup(res, workBuf.data);
946  pqClearAsyncResult(conn);
947  conn->result = res;
948  if (PQExpBufferDataBroken(workBuf))
950  libpq_gettext("out of memory"));
951  else
952  appendPQExpBufferStr(&conn->errorMessage, workBuf.data);
953  }
954  else
955  {
956  /* if we couldn't allocate the result set, just discard the NOTICE */
957  if (res)
958  {
959  /* We can cheat a little here and not copy the message. */
960  res->errMsg = workBuf.data;
961  if (res->noticeHooks.noticeRec != NULL)
963  PQclear(res);
964  }
965  }
966 
967  termPQExpBuffer(&workBuf);
968  return 0;
969 
970 fail:
971  PQclear(res);
972  termPQExpBuffer(&workBuf);
973  return EOF;
974 }
PGContextVisibility show_context
Definition: libpq-int.h:425
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
int pqGets(PQExpBuffer buf, PGconn *conn)
Definition: fe-misc.c:163
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:128
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:57
char * errMsg
Definition: libpq-int.h:196
PGresult * result
Definition: libpq-int.h:450
PGNoticeHooks noticeHooks
Definition: libpq-int.h:186
PGVerbosity verbosity
Definition: libpq-int.h:424
PQnoticeReceiver noticeRec
Definition: libpq-int.h:152
PGresult * PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
Definition: fe-exec.c:142
char * last_query
Definition: libpq-int.h:383
#define PG_DIAG_STATEMENT_POSITION
Definition: postgres_ext.h:61
char * errQuery
Definition: libpq-int.h:198
int pqGetc(char *result, PGconn *conn)
Definition: fe-misc.c:94
void pqSaveMessageField(PGresult *res, char code, const char *value)
Definition: fe-exec.c:942
PQExpBufferData errorMessage
Definition: libpq-int.h:493
void PQclear(PGresult *res)
Definition: fe-exec.c:671
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define PQExpBufferDataBroken(buf)
Definition: pqexpbuffer.h:67
void pqBuildErrorMessage3(PQExpBuffer msg, const PGresult *res, PGVerbosity verbosity, PGContextVisibility show_context)
Definition: fe-protocol3.c:981
void pqClearAsyncResult(PGconn *conn)
Definition: fe-exec.c:726
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:145
ExecStatusType resultStatus
Definition: libpq-int.h:177
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:89
#define libpq_gettext(x)
Definition: libpq-int.h:685
char * pqResultStrdup(PGresult *res, const char *str)
Definition: fe-exec.c:623
void * noticeRecArg
Definition: libpq-int.h:153
char last_sqlstate[6]
Definition: libpq-int.h:384

◆ pqGetHomeDirectory()

bool pqGetHomeDirectory ( char *  buf,
int  bufsize 
)

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

References pqGetpwuid(), snprintf(), and strlcpy().

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

6534 {
6535 #ifndef WIN32
6536  char pwdbuf[BUFSIZ];
6537  struct passwd pwdstr;
6538  struct passwd *pwd = NULL;
6539 
6540  (void) pqGetpwuid(geteuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd);
6541  if (pwd == NULL)
6542  return false;
6543  strlcpy(buf, pwd->pw_dir, bufsize);
6544  return true;
6545 #else
6546  char tmppath[MAX_PATH];
6547 
6548  ZeroMemory(tmppath, sizeof(tmppath));
6549  if (SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, tmppath) != S_OK)
6550  return false;
6551  snprintf(buf, bufsize, "%s/postgresql", tmppath);
6552  return true;
6553 #endif
6554 }
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
static char * buf
Definition: pg_test_fsync.c:67
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
int pqGetpwuid(uid_t uid, struct passwd *resultbuf, char *buffer, size_t buflen, struct passwd **result)
Definition: thread.c:95

◆ pqGetInt()

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

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

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

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

268 {
269  uint16 tmp2;
270  uint32 tmp4;
271 
272  switch (bytes)
273  {
274  case 2:
275  if (conn->inCursor + 2 > conn->inEnd)
276  return EOF;
277  memcpy(&tmp2, conn->inBuffer + conn->inCursor, 2);
278  conn->inCursor += 2;
279  *result = (int) pg_ntoh16(tmp2);
280  break;
281  case 4:
282  if (conn->inCursor + 4 > conn->inEnd)
283  return EOF;
284  memcpy(&tmp4, conn->inBuffer + conn->inCursor, 4);
285  conn->inCursor += 4;
286  *result = (int) pg_ntoh32(tmp4);
287  break;
288  default:
290  "integer of size %lu not supported by pqGetInt",
291  (unsigned long) bytes);
292  return EOF;
293  }
294 
295  if (conn->Pfdebug)
296  fprintf(conn->Pfdebug, "From backend (#%lu)> %d\n", (unsigned long) bytes, *result);
297 
298  return 0;
299 }
int inEnd
Definition: libpq-int.h:433
#define pg_ntoh16(x)
Definition: pg_bswap.h:124
FILE * Pfdebug
Definition: libpq-int.h:368
unsigned short uint16
Definition: c.h:295
#define pg_ntoh32(x)
Definition: pg_bswap.h:125
PGNoticeHooks noticeHooks
Definition: libpq-int.h:371
void pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
Definition: fe-exec.c:822
unsigned int uint32
Definition: c.h:296
char * inBuffer
Definition: libpq-int.h:429
int inCursor
Definition: libpq-int.h:432

◆ pqGetline2()

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

Definition at line 1234 of file fe-protocol2.c.

References pg_conn::asyncStatus, pg_conn::inBuffer, pg_conn::inEnd, pg_conn::inStart, PGASYNC_COPY_OUT, PGINVALID_SOCKET, pqReadData(), pqWait(), and pg_conn::sock.

Referenced by PQgetline().

1235 {
1236  int result = 1; /* return value if buffer overflows */
1237 
1238  if (conn->sock == PGINVALID_SOCKET ||
1239  conn->asyncStatus != PGASYNC_COPY_OUT)
1240  {
1241  *s = '\0';
1242  return EOF;
1243  }
1244 
1245  /*
1246  * Since this is a purely synchronous routine, we don't bother to maintain
1247  * conn->inCursor; there is no need to back up.
1248  */
1249  while (maxlen > 1)
1250  {
1251  if (conn->inStart < conn->inEnd)
1252  {
1253  char c = conn->inBuffer[conn->inStart++];
1254 
1255  if (c == '\n')
1256  {
1257  result = 0; /* success exit */
1258  break;
1259  }
1260  *s++ = c;
1261  maxlen--;
1262  }
1263  else
1264  {
1265  /* need to load more data */
1266  if (pqWait(true, false, conn) ||
1267  pqReadData(conn) < 0)
1268  {
1269  result = EOF;
1270  break;
1271  }
1272  }
1273  }
1274  *s = '\0';
1275 
1276  return result;
1277 }
int inEnd
Definition: libpq-int.h:433
int inStart
Definition: libpq-int.h:431
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:380
int pqReadData(PGconn *conn)
Definition: fe-misc.c:629
char * c
int pqWait(int forRead, int forWrite, PGconn *conn)
Definition: fe-misc.c:984
pgsocket sock
Definition: libpq-int.h:400
#define PGINVALID_SOCKET
Definition: port.h:33
char * inBuffer
Definition: libpq-int.h:429

◆ pqGetline3()

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

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

References pg_conn::asyncStatus, pg_conn::copy_is_binary, pg_conn::errorMessage, libpq_gettext, PGASYNC_COPY_BOTH, PGASYNC_COPY_OUT, PGINVALID_SOCKET, PQgetlineAsync(), pqReadData(), pqWait(), printfPQExpBuffer(), pg_conn::sock, and status().

Referenced by PQgetline().

1701 {
1702  int status;
1703 
1704  if (conn->sock == PGINVALID_SOCKET ||
1705  (conn->asyncStatus != PGASYNC_COPY_OUT &&
1706  conn->asyncStatus != PGASYNC_COPY_BOTH) ||
1707  conn->copy_is_binary)
1708  {
1710  libpq_gettext("PQgetline: not doing text COPY OUT\n"));
1711  *s = '\0';
1712  return EOF;
1713  }
1714 
1715  while ((status = PQgetlineAsync(conn, s, maxlen - 1)) == 0)
1716  {
1717  /* need to load more data */
1718  if (pqWait(true, false, conn) ||
1719  pqReadData(conn) < 0)
1720  {
1721  *s = '\0';
1722  return EOF;
1723  }
1724  }
1725 
1726  if (status < 0)
1727  {
1728  /* End of copy detected; gin up old-style terminator */
1729  strcpy(s, "\\.");
1730  return 0;
1731  }
1732 
1733  /* Add null terminator, and strip trailing \n if present */
1734  if (s[status - 1] == '\n')
1735  {
1736  s[status - 1] = '\0';
1737  return 0;
1738  }
1739  else
1740  {
1741  s[status] = '\0';
1742  return 1;
1743  }
1744 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
int PQgetlineAsync(PGconn *conn, char *buffer, int bufsize)
Definition: fe-exec.c:2520
char copy_is_binary
Definition: libpq-int.h:389
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:380
int pqReadData(PGconn *conn)
Definition: fe-misc.c:629
int pqWait(int forRead, int forWrite, PGconn *conn)
Definition: fe-misc.c:984
pgsocket sock
Definition: libpq-int.h:400
#define PGINVALID_SOCKET
Definition: port.h:33
PQExpBufferData errorMessage
Definition: libpq-int.h:493
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
#define libpq_gettext(x)
Definition: libpq-int.h:685

◆ pqGetlineAsync2()

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

Definition at line 1285 of file fe-protocol2.c.

References pg_conn::asyncStatus, pg_conn::inBuffer, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, and PGASYNC_COPY_OUT.

Referenced by PQgetlineAsync().

1286 {
1287  int avail;
1288 
1289  if (conn->asyncStatus != PGASYNC_COPY_OUT)
1290  return -1; /* we are not doing a copy... */
1291 
1292  /*
1293  * Move data from libpq's buffer to the caller's. We want to accept data
1294  * only in units of whole lines, not partial lines. This ensures that we
1295  * can recognize the terminator line "\\.\n". (Otherwise, if it happened
1296  * to cross a packet/buffer boundary, we might hand the first one or two
1297  * characters off to the caller, which we shouldn't.)
1298  */
1299 
1300  conn->inCursor = conn->inStart;
1301 
1302  avail = bufsize;
1303  while (avail > 0 && conn->inCursor < conn->inEnd)
1304  {
1305  char c = conn->inBuffer[conn->inCursor++];
1306 
1307  *buffer++ = c;
1308  --avail;
1309  if (c == '\n')
1310  {
1311  /* Got a complete line; mark the data removed from libpq */
1312  conn->inStart = conn->inCursor;
1313  /* Is it the endmarker line? */
1314  if (bufsize - avail == 3 && buffer[-3] == '\\' && buffer[-2] == '.')
1315  return -1;
1316  /* No, return the data line to the caller */
1317  return bufsize - avail;
1318  }
1319  }
1320 
1321  /*
1322  * We don't have a complete line. We'd prefer to leave it in libpq's
1323  * buffer until the rest arrives, but there is a special case: what if the
1324  * line is longer than the buffer the caller is offering us? In that case
1325  * we'd better hand over a partial line, else we'd get into an infinite
1326  * loop. Do this in a way that ensures we can't misrecognize a terminator
1327  * line later: leave last 3 characters in libpq buffer.
1328  */
1329  if (avail == 0 && bufsize > 3)
1330  {
1331  conn->inStart = conn->inCursor - 3;
1332  return bufsize - 3;
1333  }
1334  return 0;
1335 }
int inEnd
Definition: libpq-int.h:433
int inStart
Definition: libpq-int.h:431
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:380
char * c
char * inBuffer
Definition: libpq-int.h:429
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
int inCursor
Definition: libpq-int.h:432

◆ pqGetlineAsync3()

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

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

References pg_conn::asyncStatus, 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().

1753 {
1754  int msgLength;
1755  int avail;
1756 
1757  if (conn->asyncStatus != PGASYNC_COPY_OUT
1758  && conn->asyncStatus != PGASYNC_COPY_BOTH)
1759  return -1; /* we are not doing a copy... */
1760 
1761  /*
1762  * Recognize the next input message. To make life simpler for async
1763  * callers, we keep returning 0 until the next message is fully available
1764  * even if it is not Copy Data. This should keep PQendcopy from blocking.
1765  * (Note: unlike pqGetCopyData3, we do not change asyncStatus here.)
1766  */
1767  msgLength = getCopyDataMessage(conn);
1768  if (msgLength < 0)
1769  return -1; /* end-of-copy or error */
1770  if (msgLength == 0)
1771  return 0; /* no data yet */
1772 
1773  /*
1774  * Move data from libpq's buffer to the caller's. In the case where a
1775  * prior call found the caller's buffer too small, we use
1776  * conn->copy_already_done to remember how much of the row was already
1777  * returned to the caller.
1778  */
1779  conn->inCursor += conn->copy_already_done;
1780  avail = msgLength - 4 - conn->copy_already_done;
1781  if (avail <= bufsize)
1782  {
1783  /* Able to consume the whole message */
1784  memcpy(buffer, &conn->inBuffer[conn->inCursor], avail);
1785  /* Mark message consumed */
1786  conn->inStart = conn->inCursor + avail;
1787  /* Reset state for next time */
1788  conn->copy_already_done = 0;
1789  return avail;
1790  }
1791  else
1792  {
1793  /* We must return a partial message */
1794  memcpy(buffer, &conn->inBuffer[conn->inCursor], bufsize);
1795  /* The message is NOT consumed from libpq's buffer */
1796  conn->copy_already_done += bufsize;
1797  return bufsize;
1798  }
1799 }
int inStart
Definition: libpq-int.h:431
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:380
char * inBuffer
Definition: libpq-int.h:429
static int getCopyDataMessage(PGconn *conn)
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
int copy_already_done
Definition: libpq-int.h:390
int inCursor
Definition: libpq-int.h:432

◆ pqGetnchar()

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

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

References fputnbytes(), pg_conn::inBuffer, pg_conn::inCursor, pg_conn::inEnd, and pg_conn::Pfdebug.

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

196 {
197  if (len > (size_t) (conn->inEnd - conn->inCursor))
198  return EOF;
199 
200  memcpy(s, conn->inBuffer + conn->inCursor, len);
201  /* no terminating null */
202 
203  conn->inCursor += len;
204 
205  if (conn->Pfdebug)
206  {
207  fprintf(conn->Pfdebug, "From backend (%lu)> ", (unsigned long) len);
208  fputnbytes(conn->Pfdebug, s, len);
209  fprintf(conn->Pfdebug, "\n");
210  }
211 
212  return 0;
213 }
int inEnd
Definition: libpq-int.h:433
FILE * Pfdebug
Definition: libpq-int.h:368
char * inBuffer
Definition: libpq-int.h:429
static void fputnbytes(FILE *f, const char *str, size_t n)
Definition: fe-misc.c:79
int inCursor
Definition: libpq-int.h:432

◆ pqGets()

int pqGets ( PQExpBuffer  buf,
PGconn conn 
)

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

References pqGets_internal().

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

164 {
165  return pqGets_internal(buf, conn, true);
166 }
static int pqGets_internal(PQExpBuffer buf, PGconn *conn, bool resetbuffer)
Definition: fe-misc.c:132

◆ pqGets_append()

int pqGets_append ( PQExpBuffer  buf,
PGconn conn 
)

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

References pqGets_internal().

Referenced by PQconnectPoll().

170 {
171  return pqGets_internal(buf, conn, false);
172 }
static int pqGets_internal(PQExpBuffer buf, PGconn *conn, bool resetbuffer)
Definition: fe-misc.c:132

◆ pqHandleSendFailure()

void pqHandleSendFailure ( PGconn conn)

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

References parseInput(), and pqReadData().

Referenced by pqFunctionCall2(), pqFunctionCall3(), PQsendDescribe(), PQsendPrepare(), PQsendQuery(), and PQsendQueryGuts().

1634 {
1635  /*
1636  * Accept and parse any available input data, ignoring I/O errors. Note
1637  * that if pqReadData decides the backend has closed the channel, it will
1638  * close our side of the socket --- that's just what we want here.
1639  */
1640  while (pqReadData(conn) > 0)
1641  parseInput(conn);
1642 
1643  /*
1644  * Be sure to parse available input messages even if we read no data.
1645  * (Note: calling parseInput within the above loop isn't really necessary,
1646  * but it prevents buffer bloat if there's a lot of data available.)
1647  */
1648  parseInput(conn);
1649 }
int pqReadData(PGconn *conn)
Definition: fe-misc.c:629
static void parseInput(PGconn *conn)
Definition: fe-exec.c:1718

◆ pqInternalNotice()

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

◆ pqPacketSend()

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

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

References DefaultHost, free, hostname, i, _internalPQconninfoOption::keyword, _PQconninfoOption::keyword, libpq_gettext, malloc, pg_strcasecmp(), pg_strncasecmp(), port, pqFlush(), pqPutMsgEnd(), pqPutMsgStart(), pqPutnchar(), printfPQExpBuffer(), STATUS_ERROR, STATUS_OK, _internalPQconninfoOption::val, _PQconninfoOption::val, and values.

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

3976 {
3977  /* Start the message. */
3978  if (pqPutMsgStart(pack_type, true, conn))
3979  return STATUS_ERROR;
3980 
3981  /* Send the message body. */
3982  if (pqPutnchar(buf, buf_len, conn))
3983  return STATUS_ERROR;
3984 
3985  /* Finish the message. */
3986  if (pqPutMsgEnd(conn))
3987  return STATUS_ERROR;
3988 
3989  /* Flush to ensure backend gets it. */
3990  if (pqFlush(conn))
3991  return STATUS_ERROR;
3992 
3993  return STATUS_OK;
3994 }
int pqFlush(PGconn *conn)
Definition: fe-misc.c:961
int pqPutMsgStart(char msg_type, bool force_len, PGconn *conn)
Definition: fe-misc.c:519
#define STATUS_ERROR
Definition: c.h:954
static char * buf
Definition: pg_test_fsync.c:67
#define STATUS_OK
Definition: c.h:953
int pqPutnchar(const char *s, size_t len, PGconn *conn)
Definition: fe-misc.c:246
int pqPutMsgEnd(PGconn *conn)
Definition: fe-misc.c:587

◆ pqParseInput2()

void pqParseInput2 ( PGconn conn)

Definition at line 410 of file fe-protocol2.c.

References pg_conn::asyncStatus, pg_conn::be_key, pg_conn::be_pid, checkXactStatus(), pg_result::cmdStatus, CMDSTATUS_LEN, PQExpBufferData::data, pg_conn::errorMessage, getAnotherTuple(), getNotify(), getRowDescriptions(), pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, libpq_gettext, pg_conn::noticeHooks, PGASYNC_BUSY, PGASYNC_COPY_IN, PGASYNC_COPY_OUT, PGASYNC_IDLE, PGASYNC_READY, PGRES_COMMAND_OK, PGRES_EMPTY_QUERY, pqGetc(), pqGetErrorNotice2(), pqGetInt(), pqGets(), pqInternalNotice(), PQmakeEmptyPGresult(), pqSaveErrorResult(), printfPQExpBuffer(), pg_conn::result, strlcpy(), and pg_conn::workBuffer.

Referenced by parseInput().

411 {
412  char id;
413 
414  /*
415  * Loop to parse successive complete messages available in the buffer.
416  */
417  for (;;)
418  {
419  /*
420  * Quit if in COPY_OUT state: we expect raw data from the server until
421  * PQendcopy is called. Don't try to parse it according to the normal
422  * protocol. (This is bogus. The data lines ought to be part of the
423  * protocol and have identifying leading characters.)
424  */
425  if (conn->asyncStatus == PGASYNC_COPY_OUT)
426  return;
427 
428  /*
429  * OK to try to read a message type code.
430  */
431  conn->inCursor = conn->inStart;
432  if (pqGetc(&id, conn))
433  return;
434 
435  /*
436  * NOTIFY and NOTICE messages can happen in any state besides COPY
437  * OUT; always process them right away.
438  *
439  * Most other messages should only be processed while in BUSY state.
440  * (In particular, in READY state we hold off further parsing until
441  * the application collects the current PGresult.)
442  *
443  * However, if the state is IDLE then we got trouble; we need to deal
444  * with the unexpected message somehow.
445  */
446  if (id == 'A')
447  {
448  if (getNotify(conn))
449  return;
450  }
451  else if (id == 'N')
452  {
453  if (pqGetErrorNotice2(conn, false))
454  return;
455  }
456  else if (conn->asyncStatus != PGASYNC_BUSY)
457  {
458  /* If not IDLE state, just wait ... */
459  if (conn->asyncStatus != PGASYNC_IDLE)
460  return;
461 
462  /*
463  * Unexpected message in IDLE state; need to recover somehow.
464  * ERROR messages are displayed using the notice processor;
465  * anything else is just dropped on the floor after displaying a
466  * suitable warning notice. (An ERROR is very possibly the
467  * backend telling us why it is about to close the connection, so
468  * we don't want to just discard it...)
469  */
470  if (id == 'E')
471  {
472  if (pqGetErrorNotice2(conn, false /* treat as notice */ ))
473  return;
474  }
475  else
476  {
478  "message type 0x%02x arrived from server while idle",
479  id);
480  /* Discard the unexpected message; good idea?? */
481  conn->inStart = conn->inEnd;
482  break;
483  }
484  }
485  else
486  {
487  /*
488  * In BUSY state, we can process everything.
489  */
490  switch (id)
491  {
492  case 'C': /* command complete */
493  if (pqGets(&conn->workBuffer, conn))
494  return;
495  if (conn->result == NULL)
496  {
497  conn->result = PQmakeEmptyPGresult(conn,
499  if (!conn->result)
500  {
502  libpq_gettext("out of memory"));
503  pqSaveErrorResult(conn);
504  }
505  }
506  if (conn->result)
507  {
508  strlcpy(conn->result->cmdStatus, conn->workBuffer.data,
509  CMDSTATUS_LEN);
510  }
511  checkXactStatus(conn, conn->workBuffer.data);
512  conn->asyncStatus = PGASYNC_READY;
513  break;
514  case 'E': /* error return */
515  if (pqGetErrorNotice2(conn, true))
516  return;
517  conn->asyncStatus = PGASYNC_READY;
518  break;
519  case 'Z': /* backend is ready for new query */
520  conn->asyncStatus = PGASYNC_IDLE;
521  break;
522  case 'I': /* empty query */
523  /* read and throw away the closing '\0' */
524  if (pqGetc(&id, conn))
525  return;
526  if (id != '\0')
528  "unexpected character %c following empty query response (\"I\" message)",
529  id);
530  if (conn->result == NULL)
531  {
532  conn->result = PQmakeEmptyPGresult(conn,
534  if (!conn->result)
535  {
537  libpq_gettext("out of memory"));
538  pqSaveErrorResult(conn);
539  }
540  }
541  conn->asyncStatus = PGASYNC_READY;
542  break;
543  case 'K': /* secret key data from the backend */
544 
545  /*
546  * This is expected only during backend startup, but it's
547  * just as easy to handle it as part of the main loop.
548  * Save the data and continue processing.
549  */
550  if (pqGetInt(&(conn->be_pid), 4, conn))
551  return;
552  if (pqGetInt(&(conn->be_key), 4, conn))
553  return;
554  break;
555  case 'P': /* synchronous (normal) portal */
556  if (pqGets(&conn->workBuffer, conn))
557  return;
558  /* We pretty much ignore this message type... */
559  break;
560  case 'T': /* row descriptions (start of query results) */
561  if (conn->result == NULL)
562  {
563  /* First 'T' in a query sequence */
564  if (getRowDescriptions(conn))
565  return;
566  /* getRowDescriptions() moves inStart itself */
567  continue;
568  }
569  else
570  {
571  /*
572  * A new 'T' message is treated as the start of
573  * another PGresult. (It is not clear that this is
574  * really possible with the current backend.) We stop
575  * parsing until the application accepts the current
576  * result.
577  */
578  conn->asyncStatus = PGASYNC_READY;
579  return;
580  }
581  break;
582  case 'D': /* ASCII data tuple */
583  if (conn->result != NULL)
584  {
585  /* Read another tuple of a normal query response */
586  if (getAnotherTuple(conn, false))
587  return;
588  /* getAnotherTuple() moves inStart itself */
589  continue;
590  }
591  else
592  {
594  "server sent data (\"D\" message) without prior row description (\"T\" message)");
595  /* Discard the unexpected message; good idea?? */
596  conn->inStart = conn->inEnd;
597  return;
598  }
599  break;
600  case 'B': /* Binary data tuple */
601  if (conn->result != NULL)
602  {
603  /* Read another tuple of a normal query response */
604  if (getAnotherTuple(conn, true))
605  return;
606  /* getAnotherTuple() moves inStart itself */
607  continue;
608  }
609  else
610  {
612  "server sent binary data (\"B\" message) without prior row description (\"T\" message)");
613  /* Discard the unexpected message; good idea?? */
614  conn->inStart = conn->inEnd;
615  return;
616  }
617  break;
618  case 'G': /* Start Copy In */
620  break;
621  case 'H': /* Start Copy Out */
623  break;
624 
625  /*
626  * Don't need to process CopyBothResponse here because it
627  * never arrives from the server during protocol 2.0.
628  */
629  default:
632  "unexpected response from server; first received character was \"%c\"\n"),
633  id);
634  /* build an error result holding the error message */
635  pqSaveErrorResult(conn);
636  /* Discard the unexpected message; good idea?? */
637  conn->inStart = conn->inEnd;
638  conn->asyncStatus = PGASYNC_READY;
639  return;
640  } /* switch on protocol character */
641  }
642  /* Successfully consumed this message */
643  conn->inStart = conn->inCursor;
644  }
645 }
static void checkXactStatus(PGconn *conn, const char *cmdTag)
int inEnd
Definition: libpq-int.h:433
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
int inStart
Definition: libpq-int.h:431
static int getRowDescriptions(PGconn *conn)
Definition: fe-protocol2.c:658
int pqGets(PQExpBuffer buf, PGconn *conn)
Definition: fe-misc.c:163
PQExpBufferData workBuffer
Definition: libpq-int.h:496
int pqGetInt(int *result, size_t bytes, PGconn *conn)
Definition: fe-misc.c:267
#define CMDSTATUS_LEN
Definition: libpq-int.h:86
PGresult * result
Definition: libpq-int.h:450
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:380
PGNoticeHooks noticeHooks
Definition: libpq-int.h:371
static int getAnotherTuple(PGconn *conn, bool binary)
Definition: fe-protocol2.c:789
void pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
Definition: fe-exec.c:822
PGresult * PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
Definition: fe-exec.c:142
int pqGetc(char *result, PGconn *conn)
Definition: fe-misc.c:94
static int getNotify(PGconn *conn)
PQExpBufferData errorMessage
Definition: libpq-int.h:493
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
char cmdStatus[CMDSTATUS_LEN]
Definition: libpq-int.h:178
int be_key
Definition: libpq-int.h:420
void pqSaveErrorResult(PGconn *conn)
Definition: fe-exec.c:749
int inCursor
Definition: libpq-int.h:432
int be_pid
Definition: libpq-int.h:419
#define libpq_gettext(x)
Definition: libpq-int.h:685
static int pqGetErrorNotice2(PGconn *conn, bool isError)
Definition: fe-protocol2.c:962

◆ pqParseInput3()

void pqParseInput3 ( PGconn conn)

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

References pg_conn::asyncStatus, pg_conn::be_key, pg_conn::be_pid, pg_result::cmdStatus, CMDSTATUS_LEN, pg_conn::copy_already_done, PQExpBufferData::data, pg_conn::errorMessage, getAnotherTuple(), getCopyStart(), getNotify(), getParamDescriptions(), getParameterStatus(), getReadyForQuery(), getRowDescriptions(), handleSyncLoss(), pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, libpq_gettext, pg_conn::noticeHooks, PGASYNC_BUSY, PGASYNC_COPY_BOTH, PGASYNC_COPY_IN, PGASYNC_COPY_OUT, PGASYNC_IDLE, PGASYNC_READY, PGQUERY_DESCRIBE, PGQUERY_PREPARE, PGRES_COMMAND_OK, PGRES_COPY_BOTH, PGRES_COPY_IN, PGRES_COPY_OUT, PGRES_EMPTY_QUERY, PGRES_FATAL_ERROR, PGRES_TUPLES_OK, pqCheckInBufferSpace(), pqGetc(), pqGetErrorNotice3(), pqGetInt(), pqGets(), pqInternalNotice(), PQmakeEmptyPGresult(), pqSaveErrorResult(), printfPQExpBuffer(), pg_conn::queryclass, pg_conn::result, pg_result::resultStatus, strlcpy(), VALID_LONG_MESSAGE_TYPE, and pg_conn::workBuffer.

Referenced by parseInput().

66 {
67  char id;
68  int msgLength;
69  int avail;
70 
71  /*
72  * Loop to parse successive complete messages available in the buffer.
73  */
74  for (;;)
75  {
76  /*
77  * Try to read a message. First get the type code and length. Return
78  * if not enough data.
79  */
80  conn->inCursor = conn->inStart;
81  if (pqGetc(&id, conn))
82  return;
83  if (pqGetInt(&msgLength, 4, conn))
84  return;
85 
86  /*
87  * Try to validate message type/length here. A length less than 4 is
88  * definitely broken. Large lengths should only be believed for a few
89  * message types.
90  */
91  if (msgLength < 4)
92  {
93  handleSyncLoss(conn, id, msgLength);
94  return;
95  }
96  if (msgLength > 30000 && !VALID_LONG_MESSAGE_TYPE(id))
97  {
98  handleSyncLoss(conn, id, msgLength);
99  return;
100  }
101 
102  /*
103  * Can't process if message body isn't all here yet.
104  */
105  msgLength -= 4;
106  avail = conn->inEnd - conn->inCursor;
107  if (avail < msgLength)
108  {
109  /*
110  * Before returning, enlarge the input buffer if needed to hold
111  * the whole message. This is better than leaving it to
112  * pqReadData because we can avoid multiple cycles of realloc()
113  * when the message is large; also, we can implement a reasonable
114  * recovery strategy if we are unable to make the buffer big
115  * enough.
116  */
117  if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength,
118  conn))
119  {
120  /*
121  * XXX add some better recovery code... plan is to skip over
122  * the message using its length, then report an error. For the
123  * moment, just treat this like loss of sync (which indeed it
124  * might be!)
125  */
126  handleSyncLoss(conn, id, msgLength);
127  }
128  return;
129  }
130 
131  /*
132  * NOTIFY and NOTICE messages can happen in any state; always process
133  * them right away.
134  *
135  * Most other messages should only be processed while in BUSY state.
136  * (In particular, in READY state we hold off further parsing until
137  * the application collects the current PGresult.)
138  *
139  * However, if the state is IDLE then we got trouble; we need to deal
140  * with the unexpected message somehow.
141  *
142  * ParameterStatus ('S') messages are a special case: in IDLE state we
143  * must process 'em (this case could happen if a new value was adopted
144  * from config file due to SIGHUP), but otherwise we hold off until
145  * BUSY state.
146  */
147  if (id == 'A')
148  {
149  if (getNotify(conn))
150  return;
151  }
152  else if (id == 'N')
153  {
154  if (pqGetErrorNotice3(conn, false))
155  return;
156  }
157  else if (conn->asyncStatus != PGASYNC_BUSY)
158  {
159  /* If not IDLE state, just wait ... */
160  if (conn->asyncStatus != PGASYNC_IDLE)
161  return;
162 
163  /*
164  * Unexpected message in IDLE state; need to recover somehow.
165  * ERROR messages are handled using the notice processor;
166  * ParameterStatus is handled normally; anything else is just
167  * dropped on the floor after displaying a suitable warning
168  * notice. (An ERROR is very possibly the backend telling us why
169  * it is about to close the connection, so we don't want to just
170  * discard it...)
171  */
172  if (id == 'E')
173  {
174  if (pqGetErrorNotice3(conn, false /* treat as notice */ ))
175  return;
176  }
177  else if (id == 'S')
178  {
179  if (getParameterStatus(conn))
180  return;
181  }
182  else
183  {
185  "message type 0x%02x arrived from server while idle",
186  id);
187  /* Discard the unexpected message */
188  conn->inCursor += msgLength;
189  }
190  }
191  else
192  {
193  /*
194  * In BUSY state, we can process everything.
195  */
196  switch (id)
197  {
198  case 'C': /* command complete */
199  if (pqGets(&conn->workBuffer, conn))
200  return;
201  if (conn->result == NULL)
202  {
203  conn->result = PQmakeEmptyPGresult(conn,
205  if (!conn->result)
206  {
208  libpq_gettext("out of memory"));
209  pqSaveErrorResult(conn);
210  }
211  }
212  if (conn->result)
213  strlcpy(conn->result->cmdStatus, conn->workBuffer.data,
214  CMDSTATUS_LEN);
215  conn->asyncStatus = PGASYNC_READY;
216  break;
217  case 'E': /* error return */
218  if (pqGetErrorNotice3(conn, true))
219  return;
220  conn->asyncStatus = PGASYNC_READY;
221  break;
222  case 'Z': /* backend is ready for new query */
223  if (getReadyForQuery(conn))
224  return;
225  conn->asyncStatus = PGASYNC_IDLE;
226  break;
227  case 'I': /* empty query */
228  if (conn->result == NULL)
229  {
230  conn->result = PQmakeEmptyPGresult(conn,
232  if (!conn->result)
233  {
235  libpq_gettext("out of memory"));
236  pqSaveErrorResult(conn);
237  }
238  }
239  conn->asyncStatus = PGASYNC_READY;
240  break;
241  case '1': /* Parse Complete */
242  /* If we're doing PQprepare, we're done; else ignore */
243  if (conn->queryclass == PGQUERY_PREPARE)
244  {
245  if (conn->result == NULL)
246  {
247  conn->result = PQmakeEmptyPGresult(conn,
249  if (!conn->result)
250  {
252  libpq_gettext("out of memory"));
253  pqSaveErrorResult(conn);
254  }
255  }
256  conn->asyncStatus = PGASYNC_READY;
257  }
258  break;
259  case '2': /* Bind Complete */
260  case '3': /* Close Complete */
261  /* Nothing to do for these message types */
262  break;
263  case 'S': /* parameter status */
264  if (getParameterStatus(conn))
265  return;
266  break;
267  case 'K': /* secret key data from the backend */
268 
269  /*
270  * This is expected only during backend startup, but it's
271  * just as easy to handle it as part of the main loop.
272  * Save the data and continue processing.
273  */
274  if (pqGetInt(&(conn->be_pid), 4, conn))
275  return;
276  if (pqGetInt(&(conn->be_key), 4, conn))
277  return;
278  break;
279  case 'T': /* Row Description */
280  if (conn->result != NULL &&
282  {
283  /*
284  * We've already choked for some reason. Just discard
285  * the data till we get to the end of the query.
286  */
287  conn->inCursor += msgLength;
288  }
289  else if (conn->result == NULL ||
290  conn->queryclass == PGQUERY_DESCRIBE)
291  {
292  /* First 'T' in a query sequence */
293  if (getRowDescriptions(conn, msgLength))
294  return;
295  /* getRowDescriptions() moves inStart itself */
296  continue;
297  }
298  else
299  {
300  /*
301  * A new 'T' message is treated as the start of
302  * another PGresult. (It is not clear that this is
303  * really possible with the current backend.) We stop
304  * parsing until the application accepts the current
305  * result.
306  */
307  conn->asyncStatus = PGASYNC_READY;
308  return;
309  }
310  break;
311  case 'n': /* No Data */
312 
313  /*
314  * NoData indicates that we will not be seeing a
315  * RowDescription message because the statement or portal
316  * inquired about doesn't return rows.
317  *
318  * If we're doing a Describe, we have to pass something
319  * back to the client, so set up a COMMAND_OK result,
320  * instead of TUPLES_OK. Otherwise we can just ignore
321  * this message.
322  */
323  if (conn->queryclass == PGQUERY_DESCRIBE)
324  {
325  if (conn->result == NULL)
326  {
327  conn->result = PQmakeEmptyPGresult(conn,
329  if (!conn->result)
330  {
332  libpq_gettext("out of memory"));
333  pqSaveErrorResult(conn);
334  }
335  }
336  conn->asyncStatus = PGASYNC_READY;
337  }
338  break;
339  case 't': /* Parameter Description */
340  if (getParamDescriptions(conn, msgLength))
341  return;
342  /* getParamDescriptions() moves inStart itself */
343  continue;
344  case 'D': /* Data Row */
345  if (conn->result != NULL &&
347  {
348  /* Read another tuple of a normal query response */
349  if (getAnotherTuple(conn, msgLength))
350  return;
351  /* getAnotherTuple() moves inStart itself */
352  continue;
353  }
354  else if (conn->result != NULL &&
356  {
357  /*
358  * We've already choked for some reason. Just discard
359  * tuples till we get to the end of the query.
360  */
361  conn->inCursor += msgLength;
362  }
363  else
364  {
365  /* Set up to report error at end of query */
367  libpq_gettext("server sent data (\"D\" message) without prior row description (\"T\" message)\n"));
368  pqSaveErrorResult(conn);
369  /* Discard the unexpected message */
370  conn->inCursor += msgLength;
371  }
372  break;
373  case 'G': /* Start Copy In */
374  if (getCopyStart(conn, PGRES_COPY_IN))
375  return;
377  break;
378  case 'H': /* Start Copy Out */
379  if (getCopyStart(conn, PGRES_COPY_OUT))
380  return;
382  conn->copy_already_done = 0;
383  break;
384  case 'W': /* Start Copy Both */
385  if (getCopyStart(conn, PGRES_COPY_BOTH))
386  return;
388  conn->copy_already_done = 0;
389  break;
390  case 'd': /* Copy Data */
391 
392  /*
393  * If we see Copy Data, just silently drop it. This would
394  * only occur if application exits COPY OUT mode too
395  * early.
396  */
397  conn->inCursor += msgLength;
398  break;
399  case 'c': /* Copy Done */
400 
401  /*
402  * If we see Copy Done, just silently drop it. This is
403  * the normal case during PQendcopy. We will keep
404  * swallowing data, expecting to see command-complete for
405  * the COPY command.
406  */
407  break;
408  default:
411  "unexpected response from server; first received character was \"%c\"\n"),
412  id);
413  /* build an error result holding the error message */
414  pqSaveErrorResult(conn);
415  /* not sure if we will see more, so go to ready state */
416  conn->asyncStatus = PGASYNC_READY;
417  /* Discard the unexpected message */
418  conn->inCursor += msgLength;
419  break;
420  } /* switch on protocol character */
421  }
422  /* Successfully consumed this message */
423  if (conn->inCursor == conn->inStart + 5 + msgLength)
424  {
425  /* Normal case: parsing agrees with specified length */
426  conn->inStart = conn->inCursor;
427  }
428  else
429  {
430  /* Trouble --- report it */
432  libpq_gettext("message contents do not agree with length in message type \"%c\"\n"),
433  id);
434  /* build an error result holding the error message */
435  pqSaveErrorResult(conn);
436  conn->asyncStatus = PGASYNC_READY;
437  /* trust the specified message length as what to skip */
438  conn->inStart += 5 + msgLength;
439  }
440  }
441 }
int inEnd
Definition: libpq-int.h:433
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
int inStart
Definition: libpq-int.h:431
int pqGets(PQExpBuffer buf, PGconn *conn)
Definition: fe-misc.c:163
PQExpBufferData workBuffer
Definition: libpq-int.h:496
int pqCheckInBufferSpace(size_t bytes_needed, PGconn *conn)
Definition: fe-misc.c:408
PGQueryClass queryclass
Definition: libpq-int.h:382
int pqGetInt(int *result, size_t bytes, PGconn *conn)
Definition: fe-misc.c:267
static int getParamDescriptions(PGconn *conn, int msgLength)
Definition: fe-protocol3.c:650
#define CMDSTATUS_LEN
Definition: libpq-int.h:86
PGresult * result
Definition: libpq-int.h:450
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:380
static int getRowDescriptions(PGconn *conn, int msgLength)
Definition: fe-protocol3.c:472
int pqGetErrorNotice3(PGconn *conn, bool isError)
Definition: fe-protocol3.c:875
PGNoticeHooks noticeHooks
Definition: libpq-int.h:371
static int getAnotherTuple(PGconn *conn, int msgLength)
Definition: fe-protocol3.c:747
void pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
Definition: fe-exec.c:822
PGresult * PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
Definition: fe-exec.c:142
int pqGetc(char *result, PGconn *conn)
Definition: fe-misc.c:94
#define VALID_LONG_MESSAGE_TYPE(id)
Definition: fe-protocol3.c:40
PQExpBufferData errorMessage
Definition: libpq-int.h:493
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
static int getReadyForQuery(PGconn *conn)
static int getCopyStart(PGconn *conn, ExecStatusType copytype)
char cmdStatus[CMDSTATUS_LEN]
Definition: libpq-int.h:178
int be_key
Definition: libpq-int.h:420
int copy_already_done
Definition: libpq-int.h:390
static int getParameterStatus(PGconn *conn)
static int getNotify(PGconn *conn)
static void handleSyncLoss(PGconn *conn, char id, int msgLength)
Definition: fe-protocol3.c:449
void pqSaveErrorResult(PGconn *conn)
Definition: fe-exec.c:749
int inCursor
Definition: libpq-int.h:432
int be_pid
Definition: libpq-int.h:419
ExecStatusType resultStatus
Definition: libpq-int.h:177
#define libpq_gettext(x)
Definition: libpq-int.h:685

◆ pqPrepareAsyncResult()

PGresult* pqPrepareAsyncResult ( PGconn conn)

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

References appendPQExpBufferStr(), pg_conn::errorMessage, pg_conn::next_result, PGRES_FATAL_ERROR, PQmakeEmptyPGresult(), PQresultErrorMessage(), resetPQExpBuffer(), and pg_conn::result.

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

778 {
779  PGresult *res;
780 
781  /*
782  * conn->result is the PGresult to return. If it is NULL (which probably
783  * shouldn't happen) we assume there is an appropriate error message in
784  * conn->errorMessage.
785  */
786  res = conn->result;
787  if (!res)
789  else
790  {
791  /*
792  * Make sure PQerrorMessage agrees with result; it could be different
793  * if we have concatenated messages.
794  */
797  PQresultErrorMessage(res));
798  }
799 
800  /*
801  * Replace conn->result with next_result, if any. In the normal case
802  * there isn't a next result and we're just dropping ownership of the
803  * current result. In single-row mode this restores the situation to what
804  * it was before we created the current single-row result.
805  */
806  conn->result = conn->next_result;
807  conn->next_result = NULL;
808 
809  return res;
810 }
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
PGresult * result
Definition: libpq-int.h:450
PGresult * next_result
Definition: libpq-int.h:451
PGresult * PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
Definition: fe-exec.c:142
PQExpBufferData errorMessage
Definition: libpq-int.h:493
char * PQresultErrorMessage(const PGresult *res)
Definition: fe-exec.c:2663
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:145

◆ pqPutc()

int pqPutc ( char  c,
PGconn conn 
)

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

References pg_conn::Pfdebug, and pqPutMsgBytes().

Referenced by PQsendDescribe(), and PQsendQueryGuts().

113 {
114  if (pqPutMsgBytes(&c, 1, conn))
115  return EOF;
116 
117  if (conn->Pfdebug)
118  fprintf(conn->Pfdebug, "To backend> %c\n", c);
119 
120  return 0;
121 }
FILE * Pfdebug
Definition: libpq-int.h:368
static int pqPutMsgBytes(const void *buf, size_t len, PGconn *conn)
Definition: fe-misc.c:564
char * c

◆ pqPutInt()

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

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

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

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

308 {
309  uint16 tmp2;
310  uint32 tmp4;
311 
312  switch (bytes)
313  {
314  case 2:
315  tmp2 = pg_hton16((uint16) value);
316  if (pqPutMsgBytes((const char *) &tmp2, 2, conn))
317  return EOF;
318  break;
319  case 4:
320  tmp4 = pg_hton32((uint32) value);
321  if (pqPutMsgBytes((const char *) &tmp4, 4, conn))
322  return EOF;
323  break;
324  default:
326  "integer of size %lu not supported by pqPutInt",
327  (unsigned long) bytes);
328  return EOF;
329  }
330 
331  if (conn->Pfdebug)
332  fprintf(conn->Pfdebug, "To backend (%lu#)> %d\n", (unsigned long) bytes, value);
333 
334  return 0;
335 }
#define pg_hton16(x)
Definition: pg_bswap.h:120
FILE * Pfdebug
Definition: libpq-int.h:368
unsigned short uint16
Definition: c.h:295
#define pg_hton32(x)
Definition: pg_bswap.h:121
static struct @121 value
PGNoticeHooks noticeHooks
Definition: libpq-int.h:371
static int pqPutMsgBytes(const void *buf, size_t len, PGconn *conn)
Definition: fe-misc.c:564
void pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
Definition: fe-exec.c:822
unsigned int uint32
Definition: c.h:296

◆ pqPutMsgEnd()

int pqPutMsgEnd ( PGconn conn)

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

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

Referenced by pg_SASL_init(), pqEndcopy3(), pqFunctionCall2(), pqFunctionCall3(), pqPacketSend(), PQputCopyData(), PQputCopyEnd(), PQsendDescribe(), PQsendPrepare(), PQsendQuery(), PQsendQueryGuts(), and sendTerminateConn().

588 {
589  if (conn->Pfdebug)
590  fprintf(conn->Pfdebug, "To backend> Msg complete, length %u\n",
591  conn->outMsgEnd - conn->outCount);
592 
593  /* Fill in length word if needed */
594  if (conn->outMsgStart >= 0)
595  {
596  uint32 msgLen = conn->outMsgEnd - conn->outMsgStart;
597 
598  msgLen = pg_hton32(msgLen);
599  memcpy(conn->outBuffer + conn->outMsgStart, &msgLen, 4);
600  }
601 
602  /* Make message eligible to send */
603  conn->outCount = conn->outMsgEnd;
604 
605  if (conn->outCount >= 8192)
606  {
607  int toSend = conn->outCount - (conn->outCount % 8192);
608 
609  if (pqSendSome(conn, toSend) < 0)
610  return EOF;
611  /* in nonblock mode, don't complain if unable to send it all */
612  }
613 
614  return 0;
615 }
int outCount
Definition: libpq-int.h:438
int outMsgEnd
Definition: libpq-int.h:443
FILE * Pfdebug
Definition: libpq-int.h:368
#define pg_hton32(x)
Definition: pg_bswap.h:121
unsigned int uint32
Definition: c.h:296
int outMsgStart
Definition: libpq-int.h:441
char * outBuffer
Definition: libpq-int.h:436
static int pqSendSome(PGconn *conn, int len)
Definition: fe-misc.c:829

◆ pqPutMsgStart()

int pqPutMsgStart ( char  msg_type,
bool  force_len,
PGconn conn 
)

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

References pg_conn::outBuffer, pg_conn::outCount, pg_conn::outMsgEnd, pg_conn::outMsgStart, pg_conn::Pfdebug, PG_PROTOCOL_MAJOR, pqCheckOutBufferSpace(), and pg_conn::pversion.

Referenced by pg_SASL_init(), pqEndcopy3(), pqFunctionCall2(), pqFunctionCall3(), pqPacketSend(), PQputCopyData(), PQputCopyEnd(), PQsendDescribe(), PQsendPrepare(), PQsendQuery(), PQsendQueryGuts(), and sendTerminateConn().

520 {
521  int lenPos;
522  int endPos;
523 
524  /* allow room for message type byte */
525  if (msg_type)
526  endPos = conn->outCount + 1;
527  else
528  endPos = conn->outCount;
529 
530  /* do we want a length word? */
531  if (force_len || PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
532  {
533  lenPos = endPos;
534  /* allow room for message length */
535  endPos += 4;
536  }
537  else
538  lenPos = -1;
539 
540  /* make sure there is room for message header */
541  if (pqCheckOutBufferSpace(endPos, conn))
542  return EOF;
543  /* okay, save the message type byte if any */
544  if (msg_type)
545  conn->outBuffer[conn->outCount] = msg_type;
546  /* set up the message pointers */
547  conn->outMsgStart = lenPos;
548  conn->outMsgEnd = endPos;
549  /* length word, if needed, will be filled in by pqPutMsgEnd */
550 
551  if (conn->Pfdebug)
552  fprintf(conn->Pfdebug, "To backend> Msg %c\n",
553  msg_type ? msg_type : ' ');
554 
555  return 0;
556 }
int pqCheckOutBufferSpace(size_t bytes_needed, PGconn *conn)
Definition: fe-misc.c:344
int outCount
Definition: libpq-int.h:438
int outMsgEnd
Definition: libpq-int.h:443
#define PG_PROTOCOL_MAJOR(v)
Definition: pqcomm.h:104
FILE * Pfdebug
Definition: libpq-int.h:368
int outMsgStart
Definition: libpq-int.h:441
ProtocolVersion pversion
Definition: libpq-int.h:404
char * outBuffer
Definition: libpq-int.h:436

◆ pqPutnchar()

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

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

References fputnbytes(), pg_conn::Pfdebug, and pqPutMsgBytes().

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

247 {
248  if (pqPutMsgBytes(s, len, conn))
249  return EOF;
250 
251  if (conn->Pfdebug)
252  {
253  fprintf(conn->Pfdebug, "To backend> ");
254  fputnbytes(conn->Pfdebug, s, len);
255  fprintf(conn->Pfdebug, "\n");
256  }
257 
258  return 0;
259 }
FILE * Pfdebug
Definition: libpq-int.h:368
static int pqPutMsgBytes(const void *buf, size_t len, PGconn *conn)
Definition: fe-misc.c:564
static void fputnbytes(FILE *f, const char *str, size_t n)
Definition: fe-misc.c:79

◆ pqPuts()

int pqPuts ( const char *  s,
PGconn conn 
)

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

References pg_conn::Pfdebug, and pqPutMsgBytes().

Referenced by pg_SASL_init(), pqFunctionCall2(), PQputCopyEnd(), PQsendDescribe(), PQsendPrepare(), PQsendQuery(), and PQsendQueryGuts().

180 {
181  if (pqPutMsgBytes(s, strlen(s) + 1, conn))
182  return EOF;
183 
184  if (conn->Pfdebug)
185  fprintf(conn->Pfdebug, "To backend> \"%s\"\n", s);
186 
187  return 0;
188 }
FILE * Pfdebug
Definition: libpq-int.h:368
static int pqPutMsgBytes(const void *buf, size_t len, PGconn *conn)
Definition: fe-misc.c:564

◆ pqReadData()

int pqReadData ( PGconn conn)

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

References CONNECTION_BAD, EAGAIN, ECONNRESET, EINTR, pg_conn::errorMessage, EWOULDBLOCK, pg_conn::inBuffer, pg_conn::inBufSize, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, libpq_gettext, memmove, PGINVALID_SOCKET, pqCheckInBufferSpace(), pqDropConnection(), pqReadReady(), pqsecure_read(), printfPQExpBuffer(), pg_conn::sock, SOCK_ERRNO, pg_conn::ssl_in_use, and pg_conn::status.

Referenced by PQconnectPoll(), PQconsumeInput(), pqFunctionCall2(), pqFunctionCall3(), pqGetCopyData2(), pqGetCopyData3(), pqGetline2(), pqGetline3(), PQgetResult(), pqHandleSendFailure(), pqSendSome(), and pqSetenvPoll().

630 {
631  int someread = 0;
632  int nread;
633 
634  if (conn->sock == PGINVALID_SOCKET)
635  {
637  libpq_gettext("connection not open\n"));
638  return -1;
639  }
640 
641  /* Left-justify any data in the buffer to make room */
642  if (conn->inStart < conn->inEnd)
643  {
644  if (conn->inStart > 0)
645  {
646  memmove(conn->inBuffer, conn->inBuffer + conn->inStart,
647  conn->inEnd - conn->inStart);
648  conn->inEnd -= conn->inStart;
649  conn->inCursor -= conn->inStart;
650  conn->inStart = 0;
651  }
652  }
653  else
654  {
655  /* buffer is logically empty, reset it */
656  conn->inStart = conn->inCursor = conn->inEnd = 0;
657  }
658 
659  /*
660  * If the buffer is fairly full, enlarge it. We need to be able to enlarge
661  * the buffer in case a single message exceeds the initial buffer size. We
662  * enlarge before filling the buffer entirely so as to avoid asking the
663  * kernel for a partial packet. The magic constant here should be large
664  * enough for a TCP packet or Unix pipe bufferload. 8K is the usual pipe
665  * buffer size, so...
666  */
667  if (conn->inBufSize - conn->inEnd < 8192)
668  {
669  if (pqCheckInBufferSpace(conn->inEnd + (size_t) 8192, conn))
670  {
671  /*
672  * We don't insist that the enlarge worked, but we need some room
673  */
674  if (conn->inBufSize - conn->inEnd < 100)
675  return -1; /* errorMessage already set */
676  }
677  }
678 
679  /* OK, try to read some data */
680 retry3:
681  nread = pqsecure_read(conn, conn->inBuffer + conn->inEnd,
682  conn->inBufSize - conn->inEnd);
683  if (nread < 0)
684  {
685  if (SOCK_ERRNO == EINTR)
686  goto retry3;
687  /* Some systems return EAGAIN/EWOULDBLOCK for no data */
688 #ifdef EAGAIN
689  if (SOCK_ERRNO == EAGAIN)
690  return someread;
691 #endif
692 #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
693  if (SOCK_ERRNO == EWOULDBLOCK)
694  return someread;
695 #endif
696  /* We might get ECONNRESET here if using TCP and backend died */
697 #ifdef ECONNRESET
698  if (SOCK_ERRNO == ECONNRESET)
699  goto definitelyFailed;
700 #endif
701  /* pqsecure_read set the error message for us */
702  return -1;
703  }
704  if (nread > 0)
705  {
706  conn->inEnd += nread;
707 
708  /*
709  * Hack to deal with the fact that some kernels will only give us back
710  * 1 packet per recv() call, even if we asked for more and there is
711  * more available. If it looks like we are reading a long message,
712  * loop back to recv() again immediately, until we run out of data or
713  * buffer space. Without this, the block-and-restart behavior of
714  * libpq's higher levels leads to O(N^2) performance on long messages.
715  *
716  * Since we left-justified the data above, conn->inEnd gives the
717  * amount of data already read in the current message. We consider
718  * the message "long" once we have acquired 32k ...
719  */
720  if (conn->inEnd > 32768 &&
721  (conn->inBufSize - conn->inEnd) >= 8192)
722  {
723  someread = 1;
724  goto retry3;
725  }
726  return 1;
727  }
728 
729  if (someread)
730  return 1; /* got a zero read after successful tries */
731 
732  /*
733  * A return value of 0 could mean just that no data is now available, or
734  * it could mean EOF --- that is, the server has closed the connection.
735  * Since we have the socket in nonblock mode, the only way to tell the
736  * difference is to see if select() is saying that the file is ready.
737  * Grumble. Fortunately, we don't expect this path to be taken much,
738  * since in normal practice we should not be trying to read data unless
739  * the file selected for reading already.
740  *
741  * In SSL mode it's even worse: SSL_read() could say WANT_READ and then
742  * data could arrive before we make the pqReadReady() test, but the second
743  * SSL_read() could still say WANT_READ because the data received was not
744  * a complete SSL record. So we must play dumb and assume there is more
745  * data, relying on the SSL layer to detect true EOF.
746  */
747 
748 #ifdef USE_SSL
749  if (conn->ssl_in_use)
750  return 0;
751 #endif
752 
753  switch (pqReadReady(conn))
754  {
755  case 0:
756  /* definitely no data available */
757  return 0;
758  case 1:
759  /* ready for read */
760  break;
761  default:
762  /* we override pqReadReady's message with something more useful */
763  goto definitelyEOF;
764  }
765 
766  /*
767  * Still not sure that it's EOF, because some data could have just
768  * arrived.
769  */
770 retry4:
771  nread = pqsecure_read(conn, conn->inBuffer + conn->inEnd,
772  conn->inBufSize - conn->inEnd);
773  if (nread < 0)
774  {
775  if (SOCK_ERRNO == EINTR)
776  goto retry4;
777  /* Some systems return EAGAIN/EWOULDBLOCK for no data */
778 #ifdef EAGAIN
779  if (SOCK_ERRNO == EAGAIN)
780  return 0;
781 #endif
782 #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
783  if (SOCK_ERRNO == EWOULDBLOCK)
784  return 0;
785 #endif
786  /* We might get ECONNRESET here if using TCP and backend died */
787 #ifdef ECONNRESET
788  if (SOCK_ERRNO == ECONNRESET)
789  goto definitelyFailed;
790 #endif
791  /* pqsecure_read set the error message for us */
792  return -1;
793  }
794  if (nread > 0)
795  {
796  conn->inEnd += nread;
797  return 1;
798  }
799 
800  /*
801  * OK, we are getting a zero read even though select() says ready. This
802  * means the connection has been closed. Cope.
803  */
804 definitelyEOF:
807  "server closed the connection unexpectedly\n"
808  "\tThis probably means the server terminated abnormally\n"
809  "\tbefore or while processing the request.\n"));
810 
811  /* Come here if lower-level code already set a suitable errorMessage */
812 definitelyFailed:
813  /* Do *not* drop any already-read data; caller still wants it */
814  pqDropConnection(conn, false);
815  conn->status = CONNECTION_BAD; /* No more connection to backend */
816  return -1;
817 }
int inEnd
Definition: libpq-int.h:433
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
int inStart
Definition: libpq-int.h:431
int pqReadReady(PGconn *conn)
Definition: fe-misc.c:1021
#define EAGAIN
Definition: win32_port.h:332
int pqCheckInBufferSpace(size_t bytes_needed, PGconn *conn)
Definition: fe-misc.c:408
ssize_t pqsecure_read(PGconn *conn, void *ptr, size_t len)
Definition: fe-secure.c:205
void pqDropConnection(PGconn *conn, bool flushInput)
Definition: fe-connect.c:424
#define SOCK_ERRNO
Definition: libpq-int.h:698
int inBufSize
Definition: libpq-int.h:430
bool ssl_in_use
Definition: libpq-int.h:457
#define memmove(d, s, c)
Definition: c.h:1045
pgsocket sock
Definition: libpq-int.h:400
#define PGINVALID_SOCKET
Definition: port.h:33
char * inBuffer
Definition: libpq-int.h:429
PQExpBufferData errorMessage
Definition: libpq-int.h:493
ConnStatusType status
Definition: libpq-int.h:379
#define ECONNRESET
Definition: win32_port.h:344
#define EWOULDBLOCK
Definition: win32_port.h:340
int inCursor
Definition: libpq-int.h:432
#define EINTR
Definition: win32_port.h:334
#define libpq_gettext(x)
Definition: libpq-int.h:685

◆ pqReadReady()

int pqReadReady ( PGconn conn)

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

References pqSocketCheck().

Referenced by pqReadData().

1022 {
1023  return pqSocketCheck(conn, 1, 0, (time_t) 0);
1024 }
static int pqSocketCheck(PGconn *conn, int forRead, int forWrite, time_t end_time)
Definition: fe-misc.c:1045

◆ pqResultAlloc()

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

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

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

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

528 {
529  char *space;
530  PGresult_data *block;
531 
532  if (!res)
533  return NULL;
534 
535  if (nBytes <= 0)
536  return res->null_field;
537 
538  /*
539  * If alignment is needed, round up the current position to an alignment
540  * boundary.
541  */
542  if (isBinary)
543  {
544  int offset = res->curOffset % PGRESULT_ALIGN_BOUNDARY;
545 
546  if (offset)
547  {
548  res->curOffset += PGRESULT_ALIGN_BOUNDARY - offset;
549  res->spaceLeft -= PGRESULT_ALIGN_BOUNDARY - offset;
550  }
551  }
552 
553  /* If there's enough space in the current block, no problem. */
554  if (nBytes <= (size_t) res->spaceLeft)
555  {
556  space = res->curBlock->space + res->curOffset;
557  res->curOffset += nBytes;
558  res->spaceLeft -= nBytes;
559  return space;
560  }
561 
562  /*
563  * If the requested object is very large, give it its own block; this
564  * avoids wasting what might be most of the current block to start a new
565  * block. (We'd have to special-case requests bigger than the block size
566  * anyway.) The object is always given binary alignment in this case.
567  */
568  if (nBytes >= PGRESULT_SEP_ALLOC_THRESHOLD)
569  {
570  block = (PGresult_data *) malloc(nBytes + PGRESULT_BLOCK_OVERHEAD);
571  if (!block)
572  return NULL;
573  space = block->space + PGRESULT_BLOCK_OVERHEAD;
574  if (res->curBlock)
575  {
576  /*
577  * Tuck special block below the active block, so that we don't
578  * have to waste the free space in the active block.
579  */
580  block->next = res->curBlock->next;
581  res->curBlock->next = block;
582  }
583  else
584  {
585  /* Must set up the new block as the first active block. */
586  block->next = NULL;
587  res->curBlock = block;
588  res->spaceLeft = 0; /* be sure it's marked full */
589  }
590  return space;
591  }
592 
593  /* Otherwise, start a new block. */
595  if (!block)
596  return NULL;
597  block->next = res->curBlock;
598  res->curBlock = block;
599  if (isBinary)
600  {
601  /* object needs full alignment */
604  }
605  else
606  {
607  /* we can cram it right after the overhead pointer */
608  res->curOffset = sizeof(PGresult_data);
610  }
611 
612  space = block->space + res->curOffset;
613  res->curOffset += nBytes;
614  res->spaceLeft -= nBytes;
615  return space;
616 }
char space[1]
Definition: libpq-int.h:106
PGresult_data * next
Definition: libpq-int.h:105
union pgresult_data PGresult_data
Definition: libpq-int.h:101
int spaceLeft
Definition: libpq-int.h:210
char null_field[1]
Definition: libpq-int.h:201
#define malloc(a)
Definition: header.h:50
#define PGRESULT_ALIGN_BOUNDARY
Definition: fe-exec.c:130
int curOffset
Definition: libpq-int.h:209
#define PGRESULT_BLOCK_OVERHEAD
Definition: fe-exec.c:131
PGresult_data * curBlock
Definition: libpq-int.h:208
#define PGRESULT_SEP_ALLOC_THRESHOLD
Definition: fe-exec.c:132
#define PGRESULT_DATA_BLOCKSIZE
Definition: fe-exec.c:129

◆ pqResultStrdup()

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

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

References pqResultAlloc().

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

624 {
625  char *space = (char *) pqResultAlloc(res, strlen(str) + 1, false);
626 
627  if (space)
628  strcpy(space, str);
629  return space;
630 }
void * pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary)
Definition: fe-exec.c:527

◆ pqRowProcessor()

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

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

References pg_conn::asyncStatus, pg_result::attDescs, pgresAttDesc::format, i, pgresAttValue::len, pgDataValue::len, pg_conn::next_result, pg_result::null_field, NULL_LEN, pg_result::numAttributes, PG_COPYRES_ATTRS, PG_COPYRES_EVENTS, PG_COPYRES_NOTICEHOOKS, PGASYNC_READY, PGRES_SINGLE_TUPLE, pqAddTuple(), PQclear(), PQcopyResult(), pqResultAlloc(), pg_conn::result, pg_result::resultStatus, pg_conn::rowBuf, pg_conn::singleRowMode, val, pgresAttValue::value, and value.

Referenced by getAnotherTuple().

1082 {
1083  PGresult *res = conn->result;
1084  int nfields = res->numAttributes;
1085  const PGdataValue *columns = conn->rowBuf;
1086  PGresAttValue *tup;
1087  int i;
1088 
1089  /*
1090  * In single-row mode, make a new PGresult that will hold just this one
1091  * row; the original conn->result is left unchanged so that it can be used
1092  * again as the template for future rows.
1093  */
1094  if (conn->singleRowMode)
1095  {
1096  /* Copy everything that should be in the result at this point */
1097  res = PQcopyResult(res,
1100  if (!res)
1101  return 0;
1102  }
1103 
1104  /*
1105  * Basically we just allocate space in the PGresult for each field and
1106  * copy the data over.
1107  *
1108  * Note: on malloc failure, we return 0 leaving *errmsgp still NULL, which
1109  * caller will take to mean "out of memory". This is preferable to trying
1110  * to set up such a message here, because evidently there's not enough
1111  * memory for gettext() to do anything.
1112  */
1113  tup = (PGresAttValue *)
1114  pqResultAlloc(res, nfields * sizeof(PGresAttValue), true);
1115  if (tup == NULL)
1116  goto fail;
1117 
1118  for (i = 0; i < nfields; i++)
1119  {
1120  int clen = columns[i].len;
1121 
1122  if (clen < 0)
1123  {
1124  /* null field */
1125  tup[i].len = NULL_LEN;
1126  tup[i].value = res->null_field;
1127  }
1128  else
1129  {
1130  bool isbinary = (res->attDescs[i].format != 0);
1131  char *val;
1132 
1133  val = (char *) pqResultAlloc(res, clen + 1, isbinary);
1134  if (val == NULL)
1135  goto fail;
1136 
1137  /* copy and zero-terminate the data (even if it's binary) */
1138  memcpy(val, columns[i].value, clen);
1139  val[clen] = '\0';
1140 
1141  tup[i].len = clen;
1142  tup[i].value = val;
1143  }
1144  }
1145 
1146  /* And add the tuple to the PGresult's tuple array */
1147  if (!pqAddTuple(res, tup, errmsgp))
1148  goto fail;
1149 
1150  /*
1151  * Success. In single-row mode, make the result available to the client
1152  * immediately.
1153  */
1154  if (conn->singleRowMode)
1155  {
1156  /* Change result status to special single-row value */
1158  /* Stash old result for re-use later */
1159  conn->next_result = conn->result;
1160  conn->result = res;
1161  /* And mark the result ready to return */
1162  conn->asyncStatus = PGASYNC_READY;
1163  }
1164 
1165  return 1;
1166 
1167 fail:
1168  /* release locally allocated PGresult, if we made one */
1169  if (res != conn->result)
1170  PQclear(res);
1171  return 0;
1172 }
bool singleRowMode
Definition: libpq-int.h:388
PGresult * PQcopyResult(const PGresult *src, int flags)
Definition: fe-exec.c:293
#define NULL_LEN
Definition: libpq-int.h:133
char null_field[1]
Definition: libpq-int.h:201
PGresAttDesc * attDescs
Definition: libpq-int.h:171
PGresult * result
Definition: libpq-int.h:450
PGresult * next_result
Definition: libpq-int.h:451
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:380
#define PG_COPYRES_EVENTS
Definition: libpq-fe.h:36
static bool pqAddTuple(PGresult *res, PGresAttValue *tup, const char **errmsgp)
Definition: fe-exec.c:877
#define PG_COPYRES_NOTICEHOOKS
Definition: libpq-fe.h:37
static struct @121 value
PGdataValue * rowBuf
Definition: libpq-int.h:446
int numAttributes
Definition: libpq-int.h:170
#define PG_COPYRES_ATTRS
Definition: libpq-fe.h:34
void PQclear(PGresult *res)
Definition: fe-exec.c:671
void * pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary)
Definition: fe-exec.c:527
int i
char * value
Definition: libpq-int.h:138
ExecStatusType resultStatus
Definition: libpq-int.h:177
long val
Definition: informix.c:689

◆ pqSaveErrorResult()

void pqSaveErrorResult ( PGconn conn)

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

References PQExpBufferData::data, pg_result::errMsg, pg_conn::errorMessage, PGRES_FATAL_ERROR, pqCatenateResultError(), pqClearAsyncResult(), PQmakeEmptyPGresult(), pg_conn::result, and pg_result::resultStatus.

Referenced by getAnotherTuple(), getCopyResult(), getParamDescriptions(), getRowDescriptions(), handleSyncLoss(), pqFunctionCall2(), pqFunctionCall3(), PQgetResult(), pqParseInput2(), and pqParseInput3().

750 {
751  /*
752  * If no old async result, just let PQmakeEmptyPGresult make one. Likewise
753  * if old result is not an error message.
754  */
755  if (conn->result == NULL ||
757  conn->result->errMsg == NULL)
758  {
759  pqClearAsyncResult(conn);
761  }
762  else
763  {
764  /* Else, concatenate error message to existing async result. */
766  }
767 }
char * errMsg
Definition: libpq-int.h:196
PGresult * result
Definition: libpq-int.h:450
PGresult * PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
Definition: fe-exec.c:142
PQExpBufferData errorMessage
Definition: libpq-int.h:493
void pqCatenateResultError(PGresult *res, const char *msg)
Definition: fe-exec.c:652
void pqClearAsyncResult(PGconn *conn)
Definition: fe-exec.c:726
ExecStatusType resultStatus
Definition: libpq-int.h:177

◆ pqSaveMessageField()

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

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

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

Referenced by pqGetErrorNotice2(), pqGetErrorNotice3(), and pqInternalNotice().

943 {
944  PGMessageField *pfield;
945 
946  pfield = (PGMessageField *)
947  pqResultAlloc(res,
948  offsetof(PGMessageField, contents) +
949  strlen(value) + 1,
950  true);
951  if (!pfield)
952  return; /* out of memory? */
953  pfield->code = code;
954  strcpy(pfield->contents, value);
955  pfield->next = res->errFields;
956  res->errFields = pfield;
957 }
PGMessageField * errFields
Definition: libpq-int.h:197
struct pgMessageField * next
Definition: libpq-int.h:144
static struct @121 value
void * pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary)
Definition: fe-exec.c:527
char contents[FLEXIBLE_ARRAY_MEMBER]
Definition: libpq-int.h:146
#define offsetof(type, field)
Definition: c.h:593

◆ pqSaveParameterStatus()

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

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

References pg_conn::client_encoding, free, malloc, pgParameterStatus::name, pgParameterStatus::next, pg_conn::Pfdebug, pg_char_to_encoding(), PG_SQL_ASCII, pg_conn::pstatus, static_client_encoding, static_std_strings, pg_conn::std_strings, pg_conn::sversion, and pgParameterStatus::value.

Referenced by getParameterStatus(), PQsetClientEncoding(), and pqSetenvPoll().

964 {
965  pgParameterStatus *pstatus;
966  pgParameterStatus *prev;
967 
968  if (conn->Pfdebug)
969  fprintf(conn->Pfdebug, "pqSaveParameterStatus: '%s' = '%s'\n",
970  name, value);
971 
972  /*
973  * Forget any old information about the parameter
974  */
975  for (pstatus = conn->pstatus, prev = NULL;
976  pstatus != NULL;
977  prev = pstatus, pstatus = pstatus->next)
978  {
979  if (strcmp(pstatus->name, name) == 0)
980  {
981  if (prev)
982  prev->next = pstatus->next;
983  else
984  conn->pstatus = pstatus->next;
985  free(pstatus); /* frees name and value strings too */
986  break;
987  }
988  }
989 
990  /*
991  * Store new info as a single malloc block
992  */
993  pstatus = (pgParameterStatus *) malloc(sizeof(pgParameterStatus) +
994  strlen(name) + strlen(value) + 2);
995  if (pstatus)
996  {
997  char *ptr;
998 
999  ptr = ((char *) pstatus) + sizeof(pgParameterStatus);
1000  pstatus->name = ptr;
1001  strcpy(ptr, name);
1002  ptr += strlen(name) + 1;
1003  pstatus->value = ptr;
1004  strcpy(ptr, value);
1005  pstatus->next = conn->pstatus;
1006  conn->pstatus = pstatus;
1007  }
1008 
1009  /*
1010  * Special hacks: remember client_encoding and
1011  * standard_conforming_strings, and convert server version to a numeric
1012  * form. We keep the first two of these in static variables as well, so
1013  * that PQescapeString and PQescapeBytea can behave somewhat sanely (at
1014  * least in single-connection-using programs).
1015  */
1016  if (strcmp(name, "client_encoding") == 0)
1017  {
1019  /* if we don't recognize the encoding name, fall back to SQL_ASCII */
1020  if (conn->client_encoding < 0)
1021  conn->client_encoding = PG_SQL_ASCII;
1023  }
1024  else if (strcmp(name, "standard_conforming_strings") == 0)
1025  {
1026  conn->std_strings = (strcmp(value, "on") == 0);
1028  }
1029  else if (strcmp(name, "server_version") == 0)
1030  {
1031  int cnt;
1032  int vmaj,
1033  vmin,
1034  vrev;
1035 
1036  cnt = sscanf(value, "%d.%d.%d", &vmaj, &vmin, &vrev);
1037 
1038  if (cnt == 3)
1039  {
1040  /* old style, e.g. 9.6.1 */
1041  conn->sversion = (100 * vmaj + vmin) * 100 + vrev;
1042  }
1043  else if (cnt == 2)
1044  {
1045  if (vmaj >= 10)
1046  {
1047  /* new style, e.g. 10.1 */
1048  conn->sversion = 100 * 100 * vmaj + vmin;
1049  }
1050  else
1051  {
1052  /* old style without minor version, e.g. 9.6devel */
1053  conn->sversion = (100 * vmaj + vmin) * 100;
1054  }
1055  }
1056  else if (cnt == 1)
1057  {
1058  /* new style without minor version, e.g. 10devel */
1059  conn->sversion = 100 * 100 * vmaj;
1060  }
1061  else
1062  conn->sversion = 0; /* unknown */
1063  }
1064 }
static bool static_std_strings
Definition: fe-exec.c:51
int pg_char_to_encoding(const char *name)
Definition: encnames.c:551
FILE * Pfdebug
Definition: libpq-int.h:368
#define malloc(a)
Definition: header.h:50
int sversion
Definition: libpq-int.h:405
struct pgParameterStatus pgParameterStatus
static struct @121 value
static int static_client_encoding
Definition: fe-exec.c:50
pgParameterStatus * pstatus
Definition: libpq-int.h:421
bool std_strings
Definition: libpq-int.h:423
#define free(a)
Definition: header.h:65
struct pgParameterStatus * next
Definition: libpq-int.h:258
const char * name
Definition: encode.c:521
int client_encoding
Definition: libpq-int.h:422

◆ pqsecure_close()

void pqsecure_close ( PGconn )

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

References pgtls_close(), and pg_conn::ssl_in_use.

Referenced by pqDropConnection().

190 {
191 #ifdef USE_SSL
192  if (conn->ssl_in_use)
193  pgtls_close(conn);
194 #endif
195 }
PGconn * conn
Definition: streamutil.c:46
bool ssl_in_use
Definition: libpq-int.h:457
void pgtls_close(PGconn *conn)

◆ pqsecure_destroy()

void pqsecure_destroy ( void  )

◆ pqsecure_initialize()

int pqsecure_initialize ( PGconn )

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

References pgtls_init().

Referenced by PQconnectPoll().

161 {
162  int r = 0;
163 
164 #ifdef USE_SSL
165  r = pgtls_init(conn);
166 #endif
167 
168  return r;
169 }
PGconn * conn
Definition: streamutil.c:46
int pgtls_init(PGconn *conn)

◆ pqsecure_open_client()

PostgresPollingStatusType pqsecure_open_client ( PGconn )

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

References PGRES_POLLING_FAILED, and pgtls_open_client().

Referenced by PQconnectPoll().

176 {
177 #ifdef USE_SSL
178  return pgtls_open_client(conn);
179 #else
180  /* shouldn't get here */
181  return PGRES_POLLING_FAILED;
182 #endif
183 }
PostgresPollingStatusType pgtls_open_client(PGconn *conn)
PGconn * conn
Definition: streamutil.c:46

◆ pqsecure_raw_read()

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

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

References EAGAIN, ECONNRESET, EINTR, pg_conn::errorMessage, EWOULDBLOCK, libpq_gettext, printfPQExpBuffer(), recv, pg_conn::sock, SOCK_ERRNO, SOCK_ERRNO_SET, and SOCK_STRERROR.

Referenced by my_sock_read(), and pqsecure_read().

225 {
226  ssize_t n;
227  int result_errno = 0;
228  char sebuf[256];
229 
230  n = recv(conn->sock, ptr, len, 0);
231 
232  if (n < 0)
233  {
234  result_errno = SOCK_ERRNO;
235 
236  /* Set error message if appropriate */
237  switch (result_errno)
238  {
239 #ifdef EAGAIN
240  case EAGAIN:
241 #endif
242 #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
243  case EWOULDBLOCK:
244 #endif
245  case EINTR:
246  /* no error message, caller is expected to retry */
247  break;
248 
249 #ifdef ECONNRESET
250  case ECONNRESET:
253  "server closed the connection unexpectedly\n"
254  "\tThis probably means the server terminated abnormally\n"
255  "\tbefore or while processing the request.\n"));
256  break;
257 #endif
258 
259  default:
261  libpq_gettext("could not receive data from server: %s\n"),
262  SOCK_STRERROR(result_errno,
263  sebuf, sizeof(sebuf)));
264  break;
265  }
266  }
267 
268  /* ensure we return the intended errno to caller */
269  SOCK_ERRNO_SET(result_errno);
270 
271  return n;
272 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
#define EAGAIN
Definition: win32_port.h:332
#define recv(s, buf, len, flags)
Definition: win32_port.h:448
#define SOCK_STRERROR
Definition: libpq-int.h:699
#define SOCK_ERRNO
Definition: libpq-int.h:698
PGconn * conn
Definition: streamutil.c:46
#define SOCK_ERRNO_SET(e)
Definition: libpq-int.h:700
pgsocket sock
Definition: libpq-int.h:400
PQExpBufferData errorMessage
Definition: libpq-int.h:493
#define ECONNRESET
Definition: win32_port.h:344
#define EWOULDBLOCK
Definition: win32_port.h:340
#define EINTR
Definition: win32_port.h:334
#define libpq_gettext(x)
Definition: libpq-int.h:685

◆ pqsecure_raw_write()

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

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

References DECLARE_SIGPIPE_INFO, DISABLE_SIGPIPE, EAGAIN, ECONNRESET, EINTR, pg_conn::errorMessage, EWOULDBLOCK, libpq_gettext, printfPQExpBuffer(), REMEMBER_EPIPE, RESTORE_SIGPIPE, send, pg_conn::sigpipe_flag, pg_conn::sock, SOCK_ERRNO, SOCK_ERRNO_SET, and SOCK_STRERROR.

Referenced by my_sock_write(), and pqsecure_write().

302 {
303  ssize_t n;
304  int flags = 0;
305  int result_errno = 0;
306  char sebuf[256];
307 
308  DECLARE_SIGPIPE_INFO(spinfo);
309 
310 #ifdef MSG_NOSIGNAL
311  if (conn->sigpipe_flag)
312  flags |= MSG_NOSIGNAL;
313 
314 retry_masked:
315 #endif /* MSG_NOSIGNAL */
316 
317  DISABLE_SIGPIPE(conn, spinfo, return -1);
318 
319  n = send(conn->sock, ptr, len, flags);
320 
321  if (n < 0)
322  {
323  result_errno = SOCK_ERRNO;
324 
325  /*
326  * If we see an EINVAL, it may be because MSG_NOSIGNAL isn't available
327  * on this machine. So, clear sigpipe_flag so we don't try the flag
328  * again, and retry the send().
329  */
330 #ifdef MSG_NOSIGNAL
331  if (flags != 0 && result_errno == EINVAL)
332  {
333  conn->sigpipe_flag = false;
334  flags = 0;
335  goto retry_masked;
336  }
337 #endif /* MSG_NOSIGNAL */
338 
339  /* Set error message if appropriate */
340  switch (result_errno)
341  {
342 #ifdef EAGAIN
343  case EAGAIN:
344 #endif
345 #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
346  case EWOULDBLOCK:
347 #endif
348  case EINTR:
349  /* no error message, caller is expected to retry */
350  break;
351 
352  case EPIPE:
353  /* Set flag for EPIPE */
354  REMEMBER_EPIPE(spinfo, true);
355  /* FALL THRU */
356 
357 #ifdef ECONNRESET
358  case ECONNRESET:
359 #endif
362  "server closed the connection unexpectedly\n"
363  "\tThis probably means the server terminated abnormally\n"
364  "\tbefore or while processing the request.\n"));
365  break;
366 
367  default:
369  libpq_gettext("could not send data to server: %s\n"),
370  SOCK_STRERROR(result_errno,
371  sebuf, sizeof(sebuf)));
372  break;
373  }
374  }
375 
376  RESTORE_SIGPIPE(conn, spinfo);
377 
378  /* ensure we return the intended errno to caller */
379  SOCK_ERRNO_SET(result_errno);
380 
381  return n;
382 }
bool sigpipe_flag
Definition: libpq-int.h:410
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
#define EAGAIN
Definition: win32_port.h:332
#define DECLARE_SIGPIPE_INFO(spinfo)
Definition: fe-secure.c:103
#define SOCK_STRERROR
Definition: libpq-int.h:699
#define SOCK_ERRNO
Definition: libpq-int.h:698
PGconn * conn
Definition: streamutil.c:46
#define RESTORE_SIGPIPE(conn, spinfo)
Definition: fe-secure.c:113
#define SOCK_ERRNO_SET(e)
Definition: libpq-int.h:700
pgsocket sock
Definition: libpq-int.h:400
#define REMEMBER_EPIPE(spinfo, cond)
Definition: fe-secure.c:111
PQExpBufferData errorMessage
Definition: libpq-int.h:493
#define ECONNRESET
Definition: win32_port.h:344
#define EWOULDBLOCK
Definition: win32_port.h:340
#define DISABLE_SIGPIPE(conn, spinfo, failaction)
Definition: fe-secure.c:105
#define EINTR
Definition: win32_port.h:334
#define libpq_gettext(x)
Definition: libpq-int.h:685
#define send(s, buf, len, flags)
Definition: win32_port.h:449

◆ pqsecure_read()

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

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

References pgtls_read(), pqsecure_raw_read(), and pg_conn::ssl_in_use.

Referenced by pqReadData().

206 {
207  ssize_t n;
208 
209 #ifdef USE_SSL
210  if (conn->ssl_in_use)
211  {
212  n = pgtls_read(conn, ptr, len);
213  }
214  else
215 #endif
216  {
217  n = pqsecure_raw_read(conn, ptr, len);
218  }
219 
220  return n;
221 }
ssize_t pqsecure_raw_read(PGconn *conn, void *ptr, size_t len)
Definition: fe-secure.c:224
PGconn * conn
Definition: streamutil.c:46
bool ssl_in_use
Definition: libpq-int.h:457
ssize_t pgtls_read(PGconn *conn, void *ptr, size_t len)

◆ pqsecure_write()

ssize_t pqsecure_write (