1 /*-------------------------------------------------------------------------
2  *
3  * libpq-int.h
4  *	  This file contains internal definitions meant to be used only by
5  *	  the frontend libpq library, not by applications that call it.
6  *
7  *	  An application can include this file if it wants to bypass the
8  *	  official API defined by libpq-fe.h, but code that does so is much
9  *	  more likely to break across PostgreSQL releases than code that uses
10  *	  only the official API.
11  *
12  * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
13  * Portions Copyright (c) 1994, Regents of the University of California
14  *
15  * src/interfaces/libpq/libpq-int.h
16  *
17  *-------------------------------------------------------------------------
18  */
19 
20 #ifndef LIBPQ_INT_H
21 #define LIBPQ_INT_H
22 
23 /* We assume libpq-fe.h has already been included. */
24 #include "postgres_fe.h"
25 #include "libpq-events.h"
26 
27 #include <time.h>
28 #include <sys/types.h>
29 #ifndef WIN32
30 #include <sys/time.h>
31 #endif
32 
33 #ifdef ENABLE_THREAD_SAFETY
34 #ifdef WIN32
35 #include "pthread-win32.h"
36 #else
37 #include <pthread.h>
38 #endif
39 #include <signal.h>
40 #endif
41 
42 /* include stuff common to fe and be */
43 #include "getaddrinfo.h"
44 #include "libpq/pqcomm.h"
45 /* include stuff found in fe only */
46 #include "pqexpbuffer.h"
47 
48 #ifdef ENABLE_GSS
49 #if defined(HAVE_GSSAPI_H)
50 #include <gssapi.h>
51 #else
52 #include <gssapi/gssapi.h>
53 #endif
54 #endif
55 
56 #ifdef ENABLE_SSPI
57 #define SECURITY_WIN32
58 #if defined(WIN32) && !defined(WIN32_ONLY_COMPILER)
59 #include <ntsecapi.h>
60 #endif
61 #include <security.h>
62 #undef SECURITY_WIN32
63 
64 #ifndef ENABLE_GSS
65 /*
66  * Define a fake structure compatible with GSSAPI on Unix.
67  */
68 typedef struct
69 {
70 	void	   *value;
71 	int			length;
72 } gss_buffer_desc;
73 #endif
74 #endif   /* ENABLE_SSPI */
75 
76 #ifdef USE_OPENSSL
77 #include <openssl/ssl.h>
78 #include <openssl/err.h>
79 
80 #if (OPENSSL_VERSION_NUMBER >= 0x00907000L) && !defined(OPENSSL_NO_ENGINE)
81 #define USE_SSL_ENGINE
82 #endif
83 #endif   /* USE_OPENSSL */
84 
85 /*
86  * POSTGRES backend dependent Constants.
87  */
88 #define CMDSTATUS_LEN 64		/* should match COMPLETION_TAG_BUFSIZE */
89 
90 /*
91  * PGresult and the subsidiary types PGresAttDesc, PGresAttValue
92  * represent the result of a query (or more precisely, of a single SQL
93  * command --- a query string given to PQexec can contain multiple commands).
94  * Note we assume that a single command can return at most one tuple group,
95  * hence there is no need for multiple descriptor sets.
96  */
97 
98 /* Subsidiary-storage management structure for PGresult.
99  * See space management routines in fe-exec.c for details.
100  * Note that space[k] refers to the k'th byte starting from the physical
101  * head of the block --- it's a union, not a struct!
102  */
103 typedef union pgresult_data PGresult_data;
104 
105 union pgresult_data
106 {
107 	PGresult_data *next;		/* link to next block, or NULL */
108 	char		space[1];		/* dummy for accessing block as bytes */
109 };
110 
111 /* Data about a single parameter of a prepared statement */
112 typedef struct pgresParamDesc
113 {
114 	Oid			typid;			/* type id */
115 } PGresParamDesc;
116 
117 /*
118  * Data for a single attribute of a single tuple
119  *
120  * We use char* for Attribute values.
121  *
122  * The value pointer always points to a null-terminated area; we add a
123  * null (zero) byte after whatever the backend sends us.  This is only
124  * particularly useful for text values ... with a binary value, the
125  * value might have embedded nulls, so the application can't use C string
126  * operators on it.  But we add a null anyway for consistency.
127  * Note that the value itself does not contain a length word.
128  *
129  * A NULL attribute is a special case in two ways: its len field is NULL_LEN
130  * and its value field points to null_field in the owning PGresult.  All the
131  * NULL attributes in a query result point to the same place (there's no need
132  * to store a null string separately for each one).
133  */
134 
135 #define NULL_LEN		(-1)	/* pg_result len for NULL value */
136 
137 typedef struct pgresAttValue
138 {
139 	int			len;			/* length in bytes of the value */
140 	char	   *value;			/* actual value, plus terminating zero byte */
141 } PGresAttValue;
142 
143 /* Typedef for message-field list entries */
144 typedef struct pgMessageField
145 {
146 	struct pgMessageField *next;	/* list link */
147 	char		code;			/* field code */
148 	char		contents[FLEXIBLE_ARRAY_MEMBER];		/* value, nul-terminated */
149 } PGMessageField;
150 
151 /* Fields needed for notice handling */
152 typedef struct
153 {
154 	PQnoticeReceiver noticeRec; /* notice message receiver */
155 	void	   *noticeRecArg;
156 	PQnoticeProcessor noticeProc;		/* notice message processor */
157 	void	   *noticeProcArg;
158 } PGNoticeHooks;
159 
160 typedef struct PGEvent
161 {
162 	PGEventProc proc;			/* the function to call on events */
163 	char	   *name;			/* used only for error messages */
164 	void	   *passThrough;	/* pointer supplied at registration time */
165 	void	   *data;			/* optional state (instance) data */
166 	bool		resultInitialized;		/* T if RESULTCREATE/COPY succeeded */
167 } PGEvent;
168 
169 struct pg_result
170 {
171 	int			ntups;
172 	int			numAttributes;
173 	PGresAttDesc *attDescs;
174 	PGresAttValue **tuples;		/* each PGresTuple is an array of
175 								 * PGresAttValue's */
176 	int			tupArrSize;		/* allocated size of tuples array */
177 	int			numParameters;
178 	PGresParamDesc *paramDescs;
179 	ExecStatusType resultStatus;
180 	char		cmdStatus[CMDSTATUS_LEN];		/* cmd status from the query */
181 	int			binary;			/* binary tuple values if binary == 1,
182 								 * otherwise text */
183 
184 	/*
185 	 * These fields are copied from the originating PGconn, so that operations
186 	 * on the PGresult don't have to reference the PGconn.
187 	 */
188 	PGNoticeHooks noticeHooks;
189 	PGEvent    *events;
190 	int			nEvents;
191 	int			client_encoding;	/* encoding id */
192 
193 	/*
194 	 * Error information (all NULL if not an error result).  errMsg is the
195 	 * "overall" error message returned by PQresultErrorMessage.  If we have
196 	 * per-field info then it is stored in a linked list.
197 	 */
198 	char	   *errMsg;			/* error message, or NULL if no error */
199 	PGMessageField *errFields;	/* message broken into fields */
200 	char	   *errQuery;		/* text of triggering query, if available */
201 
202 	/* All NULL attributes in the query result point to this null string */
203 	char		null_field[1];
204 
205 	/*
206 	 * Space management information.  Note that attDescs and error stuff, if
207 	 * not null, point into allocated blocks.  But tuples points to a
208 	 * separately malloc'd block, so that we can realloc it.
209 	 */
210 	PGresult_data *curBlock;	/* most recently allocated block */
211 	int			curOffset;		/* start offset of free space in block */
212 	int			spaceLeft;		/* number of free bytes remaining in block */
213 };
214 
215 /* PGAsyncStatusType defines the state of the query-execution state machine */
216 typedef enum
217 {
218 	PGASYNC_IDLE,				/* nothing's happening, dude */
219 	PGASYNC_BUSY,				/* query in progress */
220 	PGASYNC_READY,				/* result ready for PQgetResult */
221 	PGASYNC_COPY_IN,			/* Copy In data transfer in progress */
222 	PGASYNC_COPY_OUT,			/* Copy Out data transfer in progress */
223 	PGASYNC_COPY_BOTH			/* Copy In/Out data transfer in progress */
224 } PGAsyncStatusType;
225 
226 /* PGQueryClass tracks which query protocol we are now executing */
227 typedef enum
228 {
229 	PGQUERY_SIMPLE,				/* simple Query protocol (PQexec) */
230 	PGQUERY_EXTENDED,			/* full Extended protocol (PQexecParams) */
231 	PGQUERY_PREPARE,			/* Parse only (PQprepare) */
232 	PGQUERY_DESCRIBE			/* Describe Statement or Portal */
233 } PGQueryClass;
234 
235 /* PGSetenvStatusType defines the state of the PQSetenv state machine */
236 /* (this is used only for 2.0-protocol connections) */
237 typedef enum
238 {
239 	SETENV_STATE_CLIENT_ENCODING_SEND,	/* About to send an Environment Option */
240 	SETENV_STATE_CLIENT_ENCODING_WAIT,	/* Waiting for above send to complete */
241 	SETENV_STATE_OPTION_SEND,	/* About to send an Environment Option */
242 	SETENV_STATE_OPTION_WAIT,	/* Waiting for above send to complete */
243 	SETENV_STATE_QUERY1_SEND,	/* About to send a status query */
244 	SETENV_STATE_QUERY1_WAIT,	/* Waiting for query to complete */
245 	SETENV_STATE_QUERY2_SEND,	/* About to send a status query */
246 	SETENV_STATE_QUERY2_WAIT,	/* Waiting for query to complete */
247 	SETENV_STATE_IDLE
248 } PGSetenvStatusType;
249 
250 /* Typedef for the EnvironmentOptions[] array */
251 typedef struct PQEnvironmentOption
252 {
253 	const char *envName,		/* name of an environment variable */
254 			   *pgName;			/* name of corresponding SET variable */
255 } PQEnvironmentOption;
256 
257 /* Typedef for parameter-status list entries */
258 typedef struct pgParameterStatus
259 {
260 	struct pgParameterStatus *next;		/* list link */
261 	char	   *name;			/* parameter name */
262 	char	   *value;			/* parameter value */
263 	/* Note: name and value are stored in same malloc block as struct is */
264 } pgParameterStatus;
265 
266 /* large-object-access data ... allocated only if large-object code is used. */
267 typedef struct pgLobjfuncs
268 {
269 	Oid			fn_lo_open;		/* OID of backend function lo_open		*/
270 	Oid			fn_lo_close;	/* OID of backend function lo_close		*/
271 	Oid			fn_lo_creat;	/* OID of backend function lo_creat		*/
272 	Oid			fn_lo_create;	/* OID of backend function lo_create	*/
273 	Oid			fn_lo_unlink;	/* OID of backend function lo_unlink	*/
274 	Oid			fn_lo_lseek;	/* OID of backend function lo_lseek		*/
275 	Oid			fn_lo_lseek64;	/* OID of backend function lo_lseek64	*/
276 	Oid			fn_lo_tell;		/* OID of backend function lo_tell		*/
277 	Oid			fn_lo_tell64;	/* OID of backend function lo_tell64	*/
278 	Oid			fn_lo_truncate; /* OID of backend function lo_truncate	*/
279 	Oid			fn_lo_truncate64;		/* OID of function lo_truncate64 */
280 	Oid			fn_lo_read;		/* OID of backend function LOread		*/
281 	Oid			fn_lo_write;	/* OID of backend function LOwrite		*/
282 } PGlobjfuncs;
283 
284 /* PGdataValue represents a data field value being passed to a row processor.
285  * It could be either text or binary data; text data is not zero-terminated.
286  * A SQL NULL is represented by len < 0; then value is still valid but there
287  * are no data bytes there.
288  */
289 typedef struct pgDataValue
290 {
291 	int			len;			/* data length in bytes, or <0 if NULL */
292 	const char *value;			/* data value, without zero-termination */
293 } PGdataValue;
294 
295 /*
296  * PGconn stores all the state data associated with a single connection
297  * to a backend.
298  */
299 struct pg_conn
300 {
301 	/* Saved values of connection options */
302 	char	   *pghost;			/* the machine on which the server is running */
303 	char	   *pghostaddr;		/* the numeric IP address of the machine on
304 								 * which the server is running.  Takes
305 								 * precedence over above. */
306 	char	   *pgport;			/* the server's communication port number */
307 	char	   *pgunixsocket;	/* the directory of the server's Unix-domain
308 								 * socket; if NULL, use DEFAULT_PGSOCKET_DIR */
309 	char	   *pgtty;			/* tty on which the backend messages is
310 								 * displayed (OBSOLETE, NOT USED) */
311 	char	   *connect_timeout;	/* connection timeout (numeric string) */
312 	char	   *client_encoding_initial;		/* encoding to use */
313 	char	   *pgoptions;		/* options to start the backend with */
314 	char	   *appname;		/* application name */
315 	char	   *fbappname;		/* fallback application name */
316 	char	   *dbName;			/* database name */
317 	char	   *replication;	/* connect as the replication standby? */
318 	char	   *pguser;			/* Postgres username and password, if any */
319 	char	   *pgpass;
320 	char	   *keepalives;		/* use TCP keepalives? */
321 	char	   *keepalives_idle;	/* time between TCP keepalives */
322 	char	   *keepalives_interval;	/* time between TCP keepalive
323 										 * retransmits */
324 	char	   *keepalives_count;		/* maximum number of TCP keepalive
325 										 * retransmits */
326 	char	   *sslmode;		/* SSL mode (require,prefer,allow,disable) */
327 	char	   *sslcompression; /* SSL compression (0 or 1) */
328 	char	   *sslkey;			/* client key filename */
329 	char	   *sslcert;		/* client certificate filename */
330 	char	   *sslrootcert;	/* root certificate filename */
331 	char	   *sslcrl;			/* certificate revocation list filename */
332 	char	   *requirepeer;	/* required peer credentials for local sockets */
333 	char	   *krbsrvname;		/* Kerberos service name */
334 	char	   *gsslib;			/* What GSS library to use ("gssapi" or
335 								 * "sspi") */
336 
337 	/* Optional file to write trace info to */
338 	FILE	   *Pfdebug;
339 
340 	/* Callback procedures for notice message processing */
341 	PGNoticeHooks noticeHooks;
342 
343 	/* Event procs registered via PQregisterEventProc */
344 	PGEvent    *events;			/* expandable array of event data */
345 	int			nEvents;		/* number of active events */
346 	int			eventArraySize; /* allocated array size */
347 
348 	/* Status indicators */
349 	ConnStatusType status;
350 	PGAsyncStatusType asyncStatus;
351 	PGTransactionStatusType xactStatus; /* never changes to ACTIVE */
352 	PGQueryClass queryclass;
353 	char	   *last_query;		/* last SQL command, or NULL if unknown */
354 	char		last_sqlstate[6];		/* last reported SQLSTATE */
355 	bool		options_valid;	/* true if OK to attempt connection */
356 	bool		nonblocking;	/* whether this connection is using nonblock
357 								 * sending semantics */
358 	bool		singleRowMode;	/* return current query result row-by-row? */
359 	char		copy_is_binary; /* 1 = copy binary, 0 = copy text */
360 	int			copy_already_done;		/* # bytes already returned in COPY
361 										 * OUT */
362 	PGnotify   *notifyHead;		/* oldest unreported Notify msg */
363 	PGnotify   *notifyTail;		/* newest unreported Notify msg */
364 
365 	/* Connection data */
366 	/* See PQconnectPoll() for how we use 'int' and not 'pgsocket'. */
367 	pgsocket	sock;			/* FD for socket, PGINVALID_SOCKET if
368 								 * unconnected */
369 	SockAddr	laddr;			/* Local address */
370 	SockAddr	raddr;			/* Remote address */
371 	ProtocolVersion pversion;	/* FE/BE protocol version in use */
372 	int			sversion;		/* server version, e.g. 70401 for 7.4.1 */
373 	bool		auth_req_received;		/* true if any type of auth req
374 										 * received */
375 	bool		password_needed;	/* true if server demanded a password */
376 	bool		dot_pgpass_used;	/* true if used .pgpass */
377 	bool		sigpipe_so;		/* have we masked SIGPIPE via SO_NOSIGPIPE? */
378 	bool		sigpipe_flag;	/* can we mask SIGPIPE via MSG_NOSIGNAL? */
379 
380 	/* Transient state needed while establishing connection */
381 	bool		try_next_addr;	/* time to advance to next address? */
382 	bool		is_new_addr;	/* need to (re)initialize for new address? */
383 	struct addrinfo *addrlist;	/* list of possible backend addresses */
384 	struct addrinfo *addr_cur;	/* the one currently being tried */
385 	int			addrlist_family;	/* needed to know how to free addrlist */
386 	PGSetenvStatusType setenv_state;	/* for 2.0 protocol only */
387 	const PQEnvironmentOption *next_eo;
388 	bool		send_appname;	/* okay to send application_name? */
389 
390 	/* Miscellaneous stuff */
391 	int			be_pid;			/* PID of backend --- needed for cancels */
392 	int			be_key;			/* key of backend --- needed for cancels */
393 	char		md5Salt[4];		/* password salt received from backend */
394 	pgParameterStatus *pstatus; /* ParameterStatus data */
395 	int			client_encoding;	/* encoding id */
396 	bool		std_strings;	/* standard_conforming_strings */
397 	PGVerbosity verbosity;		/* error/notice message verbosity */
398 	PGContextVisibility show_context;	/* whether to show CONTEXT field */
399 	PGlobjfuncs *lobjfuncs;		/* private state for large-object access fns */
400 
401 	/* Buffer for data received from backend and not yet processed */
402 	char	   *inBuffer;		/* currently allocated buffer */
403 	int			inBufSize;		/* allocated size of buffer */
404 	int			inStart;		/* offset to first unconsumed data in buffer */
405 	int			inCursor;		/* next byte to tentatively consume */
406 	int			inEnd;			/* offset to first position after avail data */
407 
408 	/* Buffer for data not yet sent to backend */
409 	char	   *outBuffer;		/* currently allocated buffer */
410 	int			outBufSize;		/* allocated size of buffer */
411 	int			outCount;		/* number of chars waiting in buffer */
412 
413 	/* State for constructing messages in outBuffer */
414 	int			outMsgStart;	/* offset to msg start (length word); if -1,
415 								 * msg has no length word */
416 	int			outMsgEnd;		/* offset to msg end (so far) */
417 
418 	/* Row processor interface workspace */
419 	PGdataValue *rowBuf;		/* array for passing values to rowProcessor */
420 	int			rowBufLen;		/* number of entries allocated in rowBuf */
421 
422 	/* Status for asynchronous result construction */
423 	PGresult   *result;			/* result being constructed */
424 	PGresult   *next_result;	/* next result (used in single-row mode) */
425 
426 	/* Assorted state for SSL, GSS, etc */
427 
428 #ifdef USE_SSL
429 	bool		allow_ssl_try;	/* Allowed to try SSL negotiation */
430 	bool		wait_ssl_try;	/* Delay SSL negotiation until after
431 								 * attempting normal connection */
432 	bool		ssl_in_use;
433 #ifdef USE_OPENSSL
434 	SSL		   *ssl;			/* SSL status, if have SSL connection */
435 	X509	   *peer;			/* X509 cert of server */
436 #ifdef USE_SSL_ENGINE
437 	ENGINE	   *engine;			/* SSL engine, if any */
438 #else
439 	void	   *engine;			/* dummy field to keep struct the same if
440 								 * OpenSSL version changes */
441 #endif
442 #endif   /* USE_OPENSSL */
443 #endif   /* USE_SSL */
444 
445 #ifdef ENABLE_GSS
446 	gss_ctx_id_t gctx;			/* GSS context */
447 	gss_name_t	gtarg_nam;		/* GSS target name */
448 	gss_buffer_desc ginbuf;		/* GSS input token */
449 	gss_buffer_desc goutbuf;	/* GSS output token */
450 #endif
451 
452 #ifdef ENABLE_SSPI
453 #ifndef ENABLE_GSS
454 	gss_buffer_desc ginbuf;		/* GSS input token */
455 #endif
456 	CredHandle *sspicred;		/* SSPI credentials handle */
457 	CtxtHandle *sspictx;		/* SSPI context */
458 	char	   *sspitarget;		/* SSPI target name */
459 	int			usesspi;		/* Indicate if SSPI is in use on the
460 								 * connection */
461 #endif
462 
463 	/* Buffer for current error message */
464 	PQExpBufferData errorMessage;		/* expansible string */
465 
466 	/* Buffer for receiving various parts of messages */
467 	PQExpBufferData workBuffer; /* expansible string */
468 };
469 
470 /* PGcancel stores all data necessary to cancel a connection. A copy of this
471  * data is required to safely cancel a connection running on a different
472  * thread.
473  */
474 struct pg_cancel
475 {
476 	SockAddr	raddr;			/* Remote address */
477 	int			be_pid;			/* PID of backend --- needed for cancels */
478 	int			be_key;			/* key of backend --- needed for cancels */
479 };
480 
481 
482 /* String descriptions of the ExecStatusTypes.
483  * direct use of this array is deprecated; call PQresStatus() instead.
484  */
485 extern char *const pgresStatus[];
486 
487 
488 #ifdef USE_SSL
489 
490 #ifndef WIN32
491 #define USER_CERT_FILE		".postgresql/postgresql.crt"
492 #define USER_KEY_FILE		".postgresql/postgresql.key"
493 #define ROOT_CERT_FILE		".postgresql/root.crt"
494 #define ROOT_CRL_FILE		".postgresql/root.crl"
495 #else
496 /* On Windows, the "home" directory is already PostgreSQL-specific */
497 #define USER_CERT_FILE		"postgresql.crt"
498 #define USER_KEY_FILE		"postgresql.key"
499 #define ROOT_CERT_FILE		"root.crt"
500 #define ROOT_CRL_FILE		"root.crl"
501 #endif
502 
503 #endif   /* USE_SSL */
504 
505 /* ----------------
506  * Internal functions of libpq
507  * Functions declared here need to be visible across files of libpq,
508  * but are not intended to be called by applications.  We use the
509  * convention "pqXXX" for internal functions, vs. the "PQxxx" names
510  * used for application-visible routines.
511  * ----------------
512  */
513 
514 /* === in fe-connect.c === */
515 
516 extern void pqDropConnection(PGconn *conn, bool flushInput);
517 extern int pqPacketSend(PGconn *conn, char pack_type,
518 			 const void *buf, size_t buf_len);
519 extern bool pqGetHomeDirectory(char *buf, int bufsize);
520 
521 #ifdef ENABLE_THREAD_SAFETY
522 extern pgthreadlock_t pg_g_threadlock;
523 
524 #define PGTHREAD_ERROR(msg) \
525 	do { \
526 		fprintf(stderr, "%s\n", msg); \
527 		abort(); \
528 	} while (0)
529 
530 
531 #define pglock_thread()		pg_g_threadlock(true)
532 #define pgunlock_thread()	pg_g_threadlock(false)
533 #else
534 #define pglock_thread()		((void) 0)
535 #define pgunlock_thread()	((void) 0)
536 #endif
537 
538 /* === in fe-exec.c === */
539 
540 extern void pqSetResultError(PGresult *res, const char *msg);
541 extern void pqCatenateResultError(PGresult *res, const char *msg);
542 extern void *pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary);
543 extern char *pqResultStrdup(PGresult *res, const char *str);
544 extern void pqClearAsyncResult(PGconn *conn);
545 extern void pqSaveErrorResult(PGconn *conn);
546 extern PGresult *pqPrepareAsyncResult(PGconn *conn);
547 extern void pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...) pg_attribute_printf(2, 3);
548 extern void pqSaveMessageField(PGresult *res, char code,
549 				   const char *value);
550 extern void pqSaveParameterStatus(PGconn *conn, const char *name,
551 					  const char *value);
552 extern int	pqRowProcessor(PGconn *conn, const char **errmsgp);
553 extern void pqHandleSendFailure(PGconn *conn);
554 
555 /* === in fe-protocol2.c === */
556 
557 extern PostgresPollingStatusType pqSetenvPoll(PGconn *conn);
558 
559 extern char *pqBuildStartupPacket2(PGconn *conn, int *packetlen,
560 					  const PQEnvironmentOption *options);
561 extern void pqParseInput2(PGconn *conn);
562 extern int	pqGetCopyData2(PGconn *conn, char **buffer, int async);
563 extern int	pqGetline2(PGconn *conn, char *s, int maxlen);
564 extern int	pqGetlineAsync2(PGconn *conn, char *buffer, int bufsize);
565 extern int	pqEndcopy2(PGconn *conn);
566 extern PGresult *pqFunctionCall2(PGconn *conn, Oid fnid,
567 				int *result_buf, int *actual_result_len,
568 				int result_is_int,
569 				const PQArgBlock *args, int nargs);
570 
571 /* === in fe-protocol3.c === */
572 
573 extern char *pqBuildStartupPacket3(PGconn *conn, int *packetlen,
574 					  const PQEnvironmentOption *options);
575 extern void pqParseInput3(PGconn *conn);
576 extern int	pqGetErrorNotice3(PGconn *conn, bool isError);
577 extern void pqBuildErrorMessage3(PQExpBuffer msg, const PGresult *res,
578 					 PGVerbosity verbosity, PGContextVisibility show_context);
579 extern int	pqGetCopyData3(PGconn *conn, char **buffer, int async);
580 extern int	pqGetline3(PGconn *conn, char *s, int maxlen);
581 extern int	pqGetlineAsync3(PGconn *conn, char *buffer, int bufsize);
582 extern int	pqEndcopy3(PGconn *conn);
583 extern PGresult *pqFunctionCall3(PGconn *conn, Oid fnid,
584 				int *result_buf, int *actual_result_len,
585 				int result_is_int,
586 				const PQArgBlock *args, int nargs);
587 
588 /* === in fe-misc.c === */
589 
590  /*
591   * "Get" and "Put" routines return 0 if successful, EOF if not. Note that for
592   * Get, EOF merely means the buffer is exhausted, not that there is
593   * necessarily any error.
594   */
595 extern int	pqCheckOutBufferSpace(size_t bytes_needed, PGconn *conn);
596 extern int	pqCheckInBufferSpace(size_t bytes_needed, PGconn *conn);
597 extern int	pqGetc(char *result, PGconn *conn);
598 extern int	pqPutc(char c, PGconn *conn);
599 extern int	pqGets(PQExpBuffer buf, PGconn *conn);
600 extern int	pqGets_append(PQExpBuffer buf, PGconn *conn);
601 extern int	pqPuts(const char *s, PGconn *conn);
602 extern int	pqGetnchar(char *s, size_t len, PGconn *conn);
603 extern int	pqSkipnchar(size_t len, PGconn *conn);
604 extern int	pqPutnchar(const char *s, size_t len, PGconn *conn);
605 extern int	pqGetInt(int *result, size_t bytes, PGconn *conn);
606 extern int	pqPutInt(int value, size_t bytes, PGconn *conn);
607 extern int	pqPutMsgStart(char msg_type, bool force_len, PGconn *conn);
608 extern int	pqPutMsgEnd(PGconn *conn);
609 extern int	pqReadData(PGconn *conn);
610 extern int	pqFlush(PGconn *conn);
611 extern int	pqWait(int forRead, int forWrite, PGconn *conn);
612 extern int pqWaitTimed(int forRead, int forWrite, PGconn *conn,
613 			time_t finish_time);
614 extern int	pqReadReady(PGconn *conn);
615 extern int	pqWriteReady(PGconn *conn);
616 
617 /* === in fe-secure.c === */
618 
619 extern int	pqsecure_initialize(PGconn *);
620 extern void pqsecure_destroy(void);
621 extern PostgresPollingStatusType pqsecure_open_client(PGconn *);
622 extern void pqsecure_close(PGconn *);
623 extern ssize_t pqsecure_read(PGconn *, void *ptr, size_t len);
624 extern ssize_t pqsecure_write(PGconn *, const void *ptr, size_t len);
625 extern ssize_t pqsecure_raw_read(PGconn *, void *ptr, size_t len);
626 extern ssize_t pqsecure_raw_write(PGconn *, const void *ptr, size_t len);
627 
628 #if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
629 extern int	pq_block_sigpipe(sigset_t *osigset, bool *sigpipe_pending);
630 extern void pq_reset_sigpipe(sigset_t *osigset, bool sigpipe_pending,
631 				 bool got_epipe);
632 #endif
633 
634 /*
635  * The SSL implementation provides these functions (fe-secure-openssl.c)
636  */
637 extern void pgtls_init_library(bool do_ssl, int do_crypto);
638 extern int	pgtls_init(PGconn *conn);
639 extern PostgresPollingStatusType pgtls_open_client(PGconn *conn);
640 extern void pgtls_close(PGconn *conn);
641 extern ssize_t pgtls_read(PGconn *conn, void *ptr, size_t len);
642 extern bool pgtls_read_pending(PGconn *conn);
643 extern ssize_t pgtls_write(PGconn *conn, const void *ptr, size_t len);
644 
645 /*
646  * this is so that we can check if a connection is non-blocking internally
647  * without the overhead of a function call
648  */
649 #define pqIsnonblocking(conn)	((conn)->nonblocking)
650 
651 #ifdef ENABLE_NLS
652 extern char *libpq_gettext(const char *msgid) pg_attribute_format_arg(1);
653 extern char *libpq_ngettext(const char *msgid, const char *msgid_plural, unsigned long n) pg_attribute_format_arg(1) pg_attribute_format_arg(2);
654 #else
655 #define libpq_gettext(x) (x)
656 #define libpq_ngettext(s, p, n) ((n) == 1 ? (s) : (p))
657 #endif
658 
659 /*
660  * These macros are needed to let error-handling code be portable between
661  * Unix and Windows.  (ugh)
662  */
663 #ifdef WIN32
664 #define SOCK_ERRNO (WSAGetLastError())
665 #define SOCK_STRERROR winsock_strerror
666 #define SOCK_ERRNO_SET(e) WSASetLastError(e)
667 #else
668 #define SOCK_ERRNO errno
669 #define SOCK_STRERROR pqStrerror
670 #define SOCK_ERRNO_SET(e) (errno = (e))
671 #endif
672 
673 #endif   /* LIBPQ_INT_H */
674