LCOV - code coverage report
Current view: top level - src/interfaces/libpq - fe-connect.c (source / functions) Hit Total Coverage
Test: PostgreSQL 15devel Lines: 1320 2531 52.2 %
Date: 2021-12-04 23:09:10 Functions: 85 101 84.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * fe-connect.c
       4             :  *    functions related to setting up a connection to the backend
       5             :  *
       6             :  * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  *
      10             :  * IDENTIFICATION
      11             :  *    src/interfaces/libpq/fe-connect.c
      12             :  *
      13             :  *-------------------------------------------------------------------------
      14             :  */
      15             : 
      16             : #include "postgres_fe.h"
      17             : 
      18             : #include <sys/stat.h>
      19             : #include <fcntl.h>
      20             : #include <ctype.h>
      21             : #include <time.h>
      22             : #include <unistd.h>
      23             : 
      24             : #include "common/ip.h"
      25             : #include "common/link-canary.h"
      26             : #include "common/scram-common.h"
      27             : #include "common/string.h"
      28             : #include "fe-auth.h"
      29             : #include "libpq-fe.h"
      30             : #include "libpq-int.h"
      31             : #include "mb/pg_wchar.h"
      32             : #include "pg_config_paths.h"
      33             : #include "port/pg_bswap.h"
      34             : 
      35             : #ifdef WIN32
      36             : #include "win32.h"
      37             : #ifdef _WIN32_IE
      38             : #undef _WIN32_IE
      39             : #endif
      40             : #define _WIN32_IE 0x0500
      41             : #ifdef near
      42             : #undef near
      43             : #endif
      44             : #define near
      45             : #include <shlobj.h>
      46             : #ifdef _MSC_VER                 /* mstcpip.h is missing on mingw */
      47             : #include <mstcpip.h>
      48             : #endif
      49             : #else
      50             : #include <sys/socket.h>
      51             : #include <netdb.h>
      52             : #include <netinet/in.h>
      53             : #ifdef HAVE_NETINET_TCP_H
      54             : #include <netinet/tcp.h>
      55             : #endif
      56             : #endif
      57             : 
      58             : #ifdef ENABLE_THREAD_SAFETY
      59             : #ifdef WIN32
      60             : #include "pthread-win32.h"
      61             : #else
      62             : #include <pthread.h>
      63             : #endif
      64             : #endif
      65             : 
      66             : #ifdef USE_LDAP
      67             : #ifdef WIN32
      68             : #include <winldap.h>
      69             : #else
      70             : /* OpenLDAP deprecates RFC 1823, but we want standard conformance */
      71             : #define LDAP_DEPRECATED 1
      72             : #include <ldap.h>
      73             : typedef struct timeval LDAP_TIMEVAL;
      74             : #endif
      75             : static int  ldapServiceLookup(const char *purl, PQconninfoOption *options,
      76             :                               PQExpBuffer errorMessage);
      77             : #endif
      78             : 
      79             : #ifndef WIN32
      80             : #define PGPASSFILE ".pgpass"
      81             : #else
      82             : #define PGPASSFILE "pgpass.conf"
      83             : #endif
      84             : 
      85             : /*
      86             :  * Pre-9.0 servers will return this SQLSTATE if asked to set
      87             :  * application_name in a startup packet.  We hard-wire the value rather
      88             :  * than looking into errcodes.h since it reflects historical behavior
      89             :  * rather than that of the current code.
      90             :  */
      91             : #define ERRCODE_APPNAME_UNKNOWN "42704"
      92             : 
      93             : /* This is part of the protocol so just define it */
      94             : #define ERRCODE_INVALID_PASSWORD "28P01"
      95             : /* This too */
      96             : #define ERRCODE_CANNOT_CONNECT_NOW "57P03"
      97             : 
      98             : /*
      99             :  * Cope with the various platform-specific ways to spell TCP keepalive socket
     100             :  * options.  This doesn't cover Windows, which as usual does its own thing.
     101             :  */
     102             : #if defined(TCP_KEEPIDLE)
     103             : /* TCP_KEEPIDLE is the name of this option on Linux and *BSD */
     104             : #define PG_TCP_KEEPALIVE_IDLE TCP_KEEPIDLE
     105             : #define PG_TCP_KEEPALIVE_IDLE_STR "TCP_KEEPIDLE"
     106             : #elif defined(TCP_KEEPALIVE_THRESHOLD)
     107             : /* TCP_KEEPALIVE_THRESHOLD is the name of this option on Solaris >= 11 */
     108             : #define PG_TCP_KEEPALIVE_IDLE TCP_KEEPALIVE_THRESHOLD
     109             : #define PG_TCP_KEEPALIVE_IDLE_STR "TCP_KEEPALIVE_THRESHOLD"
     110             : #elif defined(TCP_KEEPALIVE) && defined(__darwin__)
     111             : /* TCP_KEEPALIVE is the name of this option on macOS */
     112             : /* Caution: Solaris has this symbol but it means something different */
     113             : #define PG_TCP_KEEPALIVE_IDLE TCP_KEEPALIVE
     114             : #define PG_TCP_KEEPALIVE_IDLE_STR "TCP_KEEPALIVE"
     115             : #endif
     116             : 
     117             : /*
     118             :  * fall back options if they are not specified by arguments or defined
     119             :  * by environment variables
     120             :  */
     121             : #define DefaultHost     "localhost"
     122             : #define DefaultOption   ""
     123             : #ifdef USE_SSL
     124             : #define DefaultChannelBinding   "prefer"
     125             : #else
     126             : #define DefaultChannelBinding   "disable"
     127             : #endif
     128             : #define DefaultTargetSessionAttrs   "any"
     129             : #ifdef USE_SSL
     130             : #define DefaultSSLMode "prefer"
     131             : #else
     132             : #define DefaultSSLMode  "disable"
     133             : #endif
     134             : #ifdef ENABLE_GSS
     135             : #include "fe-gssapi-common.h"
     136             : #define DefaultGSSMode "prefer"
     137             : #else
     138             : #define DefaultGSSMode "disable"
     139             : #endif
     140             : 
     141             : /* ----------
     142             :  * Definition of the conninfo parameters and their fallback resources.
     143             :  *
     144             :  * If Environment-Var and Compiled-in are specified as NULL, no
     145             :  * fallback is available. If after all no value can be determined
     146             :  * for an option, an error is returned.
     147             :  *
     148             :  * The value for the username is treated specially in conninfo_add_defaults.
     149             :  * If the value is not obtained any other way, the username is determined
     150             :  * by pg_fe_getauthname().
     151             :  *
     152             :  * The Label and Disp-Char entries are provided for applications that
     153             :  * want to use PQconndefaults() to create a generic database connection
     154             :  * dialog. Disp-Char is defined as follows:
     155             :  *      ""        Normal input field
     156             :  *      "*"       Password field - hide value
     157             :  *      "D"       Debug option - don't show by default
     158             :  *
     159             :  * PQconninfoOptions[] is a constant static array that we use to initialize
     160             :  * a dynamically allocated working copy.  All the "val" fields in
     161             :  * PQconninfoOptions[] *must* be NULL.  In a working copy, non-null "val"
     162             :  * fields point to malloc'd strings that should be freed when the working
     163             :  * array is freed (see PQconninfoFree).
     164             :  *
     165             :  * The first part of each struct is identical to the one in libpq-fe.h,
     166             :  * which is required since we memcpy() data between the two!
     167             :  * ----------
     168             :  */
     169             : typedef struct _internalPQconninfoOption
     170             : {
     171             :     char       *keyword;        /* The keyword of the option            */
     172             :     char       *envvar;         /* Fallback environment variable name   */
     173             :     char       *compiled;       /* Fallback compiled in default value   */
     174             :     char       *val;            /* Option's current value, or NULL      */
     175             :     char       *label;          /* Label for field in connect dialog    */
     176             :     char       *dispchar;       /* Indicates how to display this field in a
     177             :                                  * connect dialog. Values are: "" Display
     178             :                                  * entered value as is "*" Password field -
     179             :                                  * hide value "D"  Debug option - don't show
     180             :                                  * by default */
     181             :     int         dispsize;       /* Field size in characters for dialog  */
     182             :     /* ---
     183             :      * Anything above this comment must be synchronized with
     184             :      * PQconninfoOption in libpq-fe.h, since we memcpy() data
     185             :      * between them!
     186             :      * ---
     187             :      */
     188             :     off_t       connofs;        /* Offset into PGconn struct, -1 if not there */
     189             : } internalPQconninfoOption;
     190             : 
     191             : static const internalPQconninfoOption PQconninfoOptions[] = {
     192             :     {"service", "PGSERVICE", NULL, NULL,
     193             :     "Database-Service", "", 20, -1},
     194             : 
     195             :     {"user", "PGUSER", NULL, NULL,
     196             :         "Database-User", "", 20,
     197             :     offsetof(struct pg_conn, pguser)},
     198             : 
     199             :     {"password", "PGPASSWORD", NULL, NULL,
     200             :         "Database-Password", "*", 20,
     201             :     offsetof(struct pg_conn, pgpass)},
     202             : 
     203             :     {"passfile", "PGPASSFILE", NULL, NULL,
     204             :         "Database-Password-File", "", 64,
     205             :     offsetof(struct pg_conn, pgpassfile)},
     206             : 
     207             :     {"channel_binding", "PGCHANNELBINDING", DefaultChannelBinding, NULL,
     208             :         "Channel-Binding", "", 8,   /* sizeof("require") == 8 */
     209             :     offsetof(struct pg_conn, channel_binding)},
     210             : 
     211             :     {"connect_timeout", "PGCONNECT_TIMEOUT", NULL, NULL,
     212             :         "Connect-timeout", "", 10,  /* strlen(INT32_MAX) == 10 */
     213             :     offsetof(struct pg_conn, connect_timeout)},
     214             : 
     215             :     {"dbname", "PGDATABASE", NULL, NULL,
     216             :         "Database-Name", "", 20,
     217             :     offsetof(struct pg_conn, dbName)},
     218             : 
     219             :     {"host", "PGHOST", NULL, NULL,
     220             :         "Database-Host", "", 40,
     221             :     offsetof(struct pg_conn, pghost)},
     222             : 
     223             :     {"hostaddr", "PGHOSTADDR", NULL, NULL,
     224             :         "Database-Host-IP-Address", "", 45,
     225             :     offsetof(struct pg_conn, pghostaddr)},
     226             : 
     227             :     {"port", "PGPORT", DEF_PGPORT_STR, NULL,
     228             :         "Database-Port", "", 6,
     229             :     offsetof(struct pg_conn, pgport)},
     230             : 
     231             :     {"client_encoding", "PGCLIENTENCODING", NULL, NULL,
     232             :         "Client-Encoding", "", 10,
     233             :     offsetof(struct pg_conn, client_encoding_initial)},
     234             : 
     235             :     {"options", "PGOPTIONS", DefaultOption, NULL,
     236             :         "Backend-Options", "", 40,
     237             :     offsetof(struct pg_conn, pgoptions)},
     238             : 
     239             :     {"application_name", "PGAPPNAME", NULL, NULL,
     240             :         "Application-Name", "", 64,
     241             :     offsetof(struct pg_conn, appname)},
     242             : 
     243             :     {"fallback_application_name", NULL, NULL, NULL,
     244             :         "Fallback-Application-Name", "", 64,
     245             :     offsetof(struct pg_conn, fbappname)},
     246             : 
     247             :     {"keepalives", NULL, NULL, NULL,
     248             :         "TCP-Keepalives", "", 1,    /* should be just '0' or '1' */
     249             :     offsetof(struct pg_conn, keepalives)},
     250             : 
     251             :     {"keepalives_idle", NULL, NULL, NULL,
     252             :         "TCP-Keepalives-Idle", "", 10,  /* strlen(INT32_MAX) == 10 */
     253             :     offsetof(struct pg_conn, keepalives_idle)},
     254             : 
     255             :     {"keepalives_interval", NULL, NULL, NULL,
     256             :         "TCP-Keepalives-Interval", "", 10,  /* strlen(INT32_MAX) == 10 */
     257             :     offsetof(struct pg_conn, keepalives_interval)},
     258             : 
     259             :     {"keepalives_count", NULL, NULL, NULL,
     260             :         "TCP-Keepalives-Count", "", 10, /* strlen(INT32_MAX) == 10 */
     261             :     offsetof(struct pg_conn, keepalives_count)},
     262             : 
     263             :     {"tcp_user_timeout", NULL, NULL, NULL,
     264             :         "TCP-User-Timeout", "", 10, /* strlen(INT32_MAX) == 10 */
     265             :     offsetof(struct pg_conn, pgtcp_user_timeout)},
     266             : 
     267             :     /*
     268             :      * ssl options are allowed even without client SSL support because the
     269             :      * client can still handle SSL modes "disable" and "allow". Other
     270             :      * parameters have no effect on non-SSL connections, so there is no reason
     271             :      * to exclude them since none of them are mandatory.
     272             :      */
     273             :     {"sslmode", "PGSSLMODE", DefaultSSLMode, NULL,
     274             :         "SSL-Mode", "", 12,     /* sizeof("verify-full") == 12 */
     275             :     offsetof(struct pg_conn, sslmode)},
     276             : 
     277             :     {"sslcompression", "PGSSLCOMPRESSION", "0", NULL,
     278             :         "SSL-Compression", "", 1,
     279             :     offsetof(struct pg_conn, sslcompression)},
     280             : 
     281             :     {"sslcert", "PGSSLCERT", NULL, NULL,
     282             :         "SSL-Client-Cert", "", 64,
     283             :     offsetof(struct pg_conn, sslcert)},
     284             : 
     285             :     {"sslkey", "PGSSLKEY", NULL, NULL,
     286             :         "SSL-Client-Key", "", 64,
     287             :     offsetof(struct pg_conn, sslkey)},
     288             : 
     289             :     {"sslpassword", NULL, NULL, NULL,
     290             :         "SSL-Client-Key-Password", "*", 20,
     291             :     offsetof(struct pg_conn, sslpassword)},
     292             : 
     293             :     {"sslrootcert", "PGSSLROOTCERT", NULL, NULL,
     294             :         "SSL-Root-Certificate", "", 64,
     295             :     offsetof(struct pg_conn, sslrootcert)},
     296             : 
     297             :     {"sslcrl", "PGSSLCRL", NULL, NULL,
     298             :         "SSL-Revocation-List", "", 64,
     299             :     offsetof(struct pg_conn, sslcrl)},
     300             : 
     301             :     {"sslcrldir", "PGSSLCRLDIR", NULL, NULL,
     302             :         "SSL-Revocation-List-Dir", "", 64,
     303             :     offsetof(struct pg_conn, sslcrldir)},
     304             : 
     305             :     {"sslsni", "PGSSLSNI", "1", NULL,
     306             :         "SSL-SNI", "", 1,
     307             :     offsetof(struct pg_conn, sslsni)},
     308             : 
     309             :     {"requirepeer", "PGREQUIREPEER", NULL, NULL,
     310             :         "Require-Peer", "", 10,
     311             :     offsetof(struct pg_conn, requirepeer)},
     312             : 
     313             :     {"ssl_min_protocol_version", "PGSSLMINPROTOCOLVERSION", "TLSv1.2", NULL,
     314             :         "SSL-Minimum-Protocol-Version", "", 8,  /* sizeof("TLSv1.x") == 8 */
     315             :     offsetof(struct pg_conn, ssl_min_protocol_version)},
     316             : 
     317             :     {"ssl_max_protocol_version", "PGSSLMAXPROTOCOLVERSION", NULL, NULL,
     318             :         "SSL-Maximum-Protocol-Version", "", 8,  /* sizeof("TLSv1.x") == 8 */
     319             :     offsetof(struct pg_conn, ssl_max_protocol_version)},
     320             : 
     321             :     /*
     322             :      * As with SSL, all GSS options are exposed even in builds that don't have
     323             :      * support.
     324             :      */
     325             :     {"gssencmode", "PGGSSENCMODE", DefaultGSSMode, NULL,
     326             :         "GSSENC-Mode", "", 8,   /* sizeof("disable") == 8 */
     327             :     offsetof(struct pg_conn, gssencmode)},
     328             : 
     329             :     /* Kerberos and GSSAPI authentication support specifying the service name */
     330             :     {"krbsrvname", "PGKRBSRVNAME", PG_KRB_SRVNAM, NULL,
     331             :         "Kerberos-service-name", "", 20,
     332             :     offsetof(struct pg_conn, krbsrvname)},
     333             : 
     334             :     {"gsslib", "PGGSSLIB", NULL, NULL,
     335             :         "GSS-library", "", 7,   /* sizeof("gssapi") == 7 */
     336             :     offsetof(struct pg_conn, gsslib)},
     337             : 
     338             :     {"replication", NULL, NULL, NULL,
     339             :         "Replication", "D", 5,
     340             :     offsetof(struct pg_conn, replication)},
     341             : 
     342             :     {"target_session_attrs", "PGTARGETSESSIONATTRS",
     343             :         DefaultTargetSessionAttrs, NULL,
     344             :         "Target-Session-Attrs", "", 15, /* sizeof("prefer-standby") = 15 */
     345             :     offsetof(struct pg_conn, target_session_attrs)},
     346             : 
     347             :     /* Terminating entry --- MUST BE LAST */
     348             :     {NULL, NULL, NULL, NULL,
     349             :     NULL, NULL, 0}
     350             : };
     351             : 
     352             : static const PQEnvironmentOption EnvironmentOptions[] =
     353             : {
     354             :     /* common user-interface settings */
     355             :     {
     356             :         "PGDATESTYLE", "datestyle"
     357             :     },
     358             :     {
     359             :         "PGTZ", "timezone"
     360             :     },
     361             :     /* internal performance-related settings */
     362             :     {
     363             :         "PGGEQO", "geqo"
     364             :     },
     365             :     {
     366             :         NULL, NULL
     367             :     }
     368             : };
     369             : 
     370             : /* The connection URI must start with either of the following designators: */
     371             : static const char uri_designator[] = "postgresql://";
     372             : static const char short_uri_designator[] = "postgres://";
     373             : 
     374             : static bool connectOptions1(PGconn *conn, const char *conninfo);
     375             : static bool connectOptions2(PGconn *conn);
     376             : static int  connectDBStart(PGconn *conn);
     377             : static int  connectDBComplete(PGconn *conn);
     378             : static PGPing internal_ping(PGconn *conn);
     379             : static PGconn *makeEmptyPGconn(void);
     380             : static bool fillPGconn(PGconn *conn, PQconninfoOption *connOptions);
     381             : static void freePGconn(PGconn *conn);
     382             : static void closePGconn(PGconn *conn);
     383             : static void release_conn_addrinfo(PGconn *conn);
     384             : static void sendTerminateConn(PGconn *conn);
     385             : static PQconninfoOption *conninfo_init(PQExpBuffer errorMessage);
     386             : static PQconninfoOption *parse_connection_string(const char *conninfo,
     387             :                                                  PQExpBuffer errorMessage, bool use_defaults);
     388             : static int  uri_prefix_length(const char *connstr);
     389             : static bool recognized_connection_string(const char *connstr);
     390             : static PQconninfoOption *conninfo_parse(const char *conninfo,
     391             :                                         PQExpBuffer errorMessage, bool use_defaults);
     392             : static PQconninfoOption *conninfo_array_parse(const char *const *keywords,
     393             :                                               const char *const *values, PQExpBuffer errorMessage,
     394             :                                               bool use_defaults, int expand_dbname);
     395             : static bool conninfo_add_defaults(PQconninfoOption *options,
     396             :                                   PQExpBuffer errorMessage);
     397             : static PQconninfoOption *conninfo_uri_parse(const char *uri,
     398             :                                             PQExpBuffer errorMessage, bool use_defaults);
     399             : static bool conninfo_uri_parse_options(PQconninfoOption *options,
     400             :                                        const char *uri, PQExpBuffer errorMessage);
     401             : static bool conninfo_uri_parse_params(char *params,
     402             :                                       PQconninfoOption *connOptions,
     403             :                                       PQExpBuffer errorMessage);
     404             : static char *conninfo_uri_decode(const char *str, PQExpBuffer errorMessage);
     405             : static bool get_hexdigit(char digit, int *value);
     406             : static const char *conninfo_getval(PQconninfoOption *connOptions,
     407             :                                    const char *keyword);
     408             : static PQconninfoOption *conninfo_storeval(PQconninfoOption *connOptions,
     409             :                                            const char *keyword, const char *value,
     410             :                                            PQExpBuffer errorMessage, bool ignoreMissing, bool uri_decode);
     411             : static PQconninfoOption *conninfo_find(PQconninfoOption *connOptions,
     412             :                                        const char *keyword);
     413             : static void defaultNoticeReceiver(void *arg, const PGresult *res);
     414             : static void defaultNoticeProcessor(void *arg, const char *message);
     415             : static int  parseServiceInfo(PQconninfoOption *options,
     416             :                              PQExpBuffer errorMessage);
     417             : static int  parseServiceFile(const char *serviceFile,
     418             :                              const char *service,
     419             :                              PQconninfoOption *options,
     420             :                              PQExpBuffer errorMessage,
     421             :                              bool *group_found);
     422             : static char *pwdfMatchesString(char *buf, const char *token);
     423             : static char *passwordFromFile(const char *hostname, const char *port, const char *dbname,
     424             :                               const char *username, const char *pgpassfile);
     425             : static void pgpassfileWarning(PGconn *conn);
     426             : static void default_threadlock(int acquire);
     427             : static bool sslVerifyProtocolVersion(const char *version);
     428             : static bool sslVerifyProtocolRange(const char *min, const char *max);
     429             : 
     430             : 
     431             : /* global variable because fe-auth.c needs to access it */
     432             : pgthreadlock_t pg_g_threadlock = default_threadlock;
     433             : 
     434             : 
     435             : /*
     436             :  *      pqDropConnection
     437             :  *
     438             :  * Close any physical connection to the server, and reset associated
     439             :  * state inside the connection object.  We don't release state that
     440             :  * would be needed to reconnect, though, nor local state that might still
     441             :  * be useful later.
     442             :  *
     443             :  * We can always flush the output buffer, since there's no longer any hope
     444             :  * of sending that data.  However, unprocessed input data might still be
     445             :  * valuable, so the caller must tell us whether to flush that or not.
     446             :  */
     447             : void
     448       25518 : pqDropConnection(PGconn *conn, bool flushInput)
     449             : {
     450             :     /* Drop any SSL state */
     451       25518 :     pqsecure_close(conn);
     452             : 
     453             :     /* Close the socket itself */
     454       25518 :     if (conn->sock != PGINVALID_SOCKET)
     455       12462 :         closesocket(conn->sock);
     456       25518 :     conn->sock = PGINVALID_SOCKET;
     457             : 
     458             :     /* Optionally discard any unread data */
     459       25518 :     if (flushInput)
     460       25386 :         conn->inStart = conn->inCursor = conn->inEnd = 0;
     461             : 
     462             :     /* Always discard any unsent data */
     463       25518 :     conn->outCount = 0;
     464             : 
     465             :     /* Free authentication/encryption state */
     466             : #ifdef ENABLE_GSS
     467             :     {
     468             :         OM_uint32   min_s;
     469             : 
     470             :         if (conn->gcred != GSS_C_NO_CREDENTIAL)
     471             :         {
     472             :             gss_release_cred(&min_s, &conn->gcred);
     473             :             conn->gcred = GSS_C_NO_CREDENTIAL;
     474             :         }
     475             :         if (conn->gctx)
     476             :             gss_delete_sec_context(&min_s, &conn->gctx, GSS_C_NO_BUFFER);
     477             :         if (conn->gtarg_nam)
     478             :             gss_release_name(&min_s, &conn->gtarg_nam);
     479             :         if (conn->gss_SendBuffer)
     480             :         {
     481             :             free(conn->gss_SendBuffer);
     482             :             conn->gss_SendBuffer = NULL;
     483             :         }
     484             :         if (conn->gss_RecvBuffer)
     485             :         {
     486             :             free(conn->gss_RecvBuffer);
     487             :             conn->gss_RecvBuffer = NULL;
     488             :         }
     489             :         if (conn->gss_ResultBuffer)
     490             :         {
     491             :             free(conn->gss_ResultBuffer);
     492             :             conn->gss_ResultBuffer = NULL;
     493             :         }
     494             :         conn->gssenc = false;
     495             :     }
     496             : #endif
     497             : #ifdef ENABLE_SSPI
     498             :     if (conn->sspitarget)
     499             :     {
     500             :         free(conn->sspitarget);
     501             :         conn->sspitarget = NULL;
     502             :     }
     503             :     if (conn->sspicred)
     504             :     {
     505             :         FreeCredentialsHandle(conn->sspicred);
     506             :         free(conn->sspicred);
     507             :         conn->sspicred = NULL;
     508             :     }
     509             :     if (conn->sspictx)
     510             :     {
     511             :         DeleteSecurityContext(conn->sspictx);
     512             :         free(conn->sspictx);
     513             :         conn->sspictx = NULL;
     514             :     }
     515             :     conn->usesspi = 0;
     516             : #endif
     517       25518 :     if (conn->sasl_state)
     518             :     {
     519          40 :         conn->sasl->free(conn->sasl_state);
     520          40 :         conn->sasl_state = NULL;
     521             :     }
     522       25518 : }
     523             : 
     524             : /*
     525             :  * pqFreeCommandQueue
     526             :  * Free all the entries of PGcmdQueueEntry queue passed.
     527             :  */
     528             : static void
     529       50064 : pqFreeCommandQueue(PGcmdQueueEntry *queue)
     530             : {
     531       63408 :     while (queue != NULL)
     532             :     {
     533       13344 :         PGcmdQueueEntry *cur = queue;
     534             : 
     535       13344 :         queue = cur->next;
     536       13344 :         if (cur->query)
     537         784 :             free(cur->query);
     538       13344 :         free(cur);
     539             :     }
     540       50064 : }
     541             : 
     542             : /*
     543             :  *      pqDropServerData
     544             :  *
     545             :  * Clear all connection state data that was received from (or deduced about)
     546             :  * the server.  This is essential to do between connection attempts to
     547             :  * different servers, else we may incorrectly hold over some data from the
     548             :  * old server.
     549             :  *
     550             :  * It would be better to merge this into pqDropConnection, perhaps, but
     551             :  * right now we cannot because that function is called immediately on
     552             :  * detection of connection loss (cf. pqReadData, for instance).  This data
     553             :  * should be kept until we are actually starting a new connection.
     554             :  */
     555             : static void
     556       25032 : pqDropServerData(PGconn *conn)
     557             : {
     558             :     PGnotify   *notify;
     559             :     pgParameterStatus *pstatus;
     560             : 
     561             :     /* Forget pending notifies */
     562       25032 :     notify = conn->notifyHead;
     563       25032 :     while (notify != NULL)
     564             :     {
     565           0 :         PGnotify   *prev = notify;
     566             : 
     567           0 :         notify = notify->next;
     568           0 :         free(prev);
     569             :     }
     570       25032 :     conn->notifyHead = conn->notifyTail = NULL;
     571             : 
     572       25032 :     pqFreeCommandQueue(conn->cmd_queue_head);
     573       25032 :     conn->cmd_queue_head = conn->cmd_queue_tail = NULL;
     574             : 
     575       25032 :     pqFreeCommandQueue(conn->cmd_queue_recycle);
     576       25032 :     conn->cmd_queue_recycle = NULL;
     577             : 
     578             :     /* Reset ParameterStatus data, as well as variables deduced from it */
     579       25032 :     pstatus = conn->pstatus;
     580      180252 :     while (pstatus != NULL)
     581             :     {
     582      155220 :         pgParameterStatus *prev = pstatus;
     583             : 
     584      155220 :         pstatus = pstatus->next;
     585      155220 :         free(prev);
     586             :     }
     587       25032 :     conn->pstatus = NULL;
     588       25032 :     conn->client_encoding = PG_SQL_ASCII;
     589       25032 :     conn->std_strings = false;
     590       25032 :     conn->default_transaction_read_only = PG_BOOL_UNKNOWN;
     591       25032 :     conn->in_hot_standby = PG_BOOL_UNKNOWN;
     592       25032 :     conn->sversion = 0;
     593             : 
     594             :     /* Drop large-object lookup data */
     595       25032 :     if (conn->lobjfuncs)
     596          52 :         free(conn->lobjfuncs);
     597       25032 :     conn->lobjfuncs = NULL;
     598             : 
     599             :     /* Reset assorted other per-connection state */
     600       25032 :     conn->last_sqlstate[0] = '\0';
     601       25032 :     conn->auth_req_received = false;
     602       25032 :     conn->password_needed = false;
     603       25032 :     conn->write_failed = false;
     604       25032 :     if (conn->write_err_msg)
     605          12 :         free(conn->write_err_msg);
     606       25032 :     conn->write_err_msg = NULL;
     607       25032 :     conn->be_pid = 0;
     608       25032 :     conn->be_key = 0;
     609       25032 : }
     610             : 
     611             : 
     612             : /*
     613             :  *      Connecting to a Database
     614             :  *
     615             :  * There are now six different ways a user of this API can connect to the
     616             :  * database.  Two are not recommended for use in new code, because of their
     617             :  * lack of extensibility with respect to the passing of options to the
     618             :  * backend.  These are PQsetdb and PQsetdbLogin (the former now being a macro
     619             :  * to the latter).
     620             :  *
     621             :  * If it is desired to connect in a synchronous (blocking) manner, use the
     622             :  * function PQconnectdb or PQconnectdbParams. The former accepts a string of
     623             :  * option = value pairs (or a URI) which must be parsed; the latter takes two
     624             :  * NULL terminated arrays instead.
     625             :  *
     626             :  * To connect in an asynchronous (non-blocking) manner, use the functions
     627             :  * PQconnectStart or PQconnectStartParams (which differ in the same way as
     628             :  * PQconnectdb and PQconnectdbParams) and PQconnectPoll.
     629             :  *
     630             :  * Internally, the static functions connectDBStart, connectDBComplete
     631             :  * are part of the connection procedure.
     632             :  */
     633             : 
     634             : /*
     635             :  *      PQconnectdbParams
     636             :  *
     637             :  * establishes a connection to a postgres backend through the postmaster
     638             :  * using connection information in two arrays.
     639             :  *
     640             :  * The keywords array is defined as
     641             :  *
     642             :  *     const char *params[] = {"option1", "option2", NULL}
     643             :  *
     644             :  * The values array is defined as
     645             :  *
     646             :  *     const char *values[] = {"value1", "value2", NULL}
     647             :  *
     648             :  * Returns a PGconn* which is needed for all subsequent libpq calls, or NULL
     649             :  * if a memory allocation failed.
     650             :  * If the status field of the connection returned is CONNECTION_BAD,
     651             :  * then some fields may be null'ed out instead of having valid values.
     652             :  *
     653             :  * You should call PQfinish (if conn is not NULL) regardless of whether this
     654             :  * call succeeded.
     655             :  */
     656             : PGconn *
     657       11006 : PQconnectdbParams(const char *const *keywords,
     658             :                   const char *const *values,
     659             :                   int expand_dbname)
     660             : {
     661       11006 :     PGconn     *conn = PQconnectStartParams(keywords, values, expand_dbname);
     662             : 
     663       11006 :     if (conn && conn->status != CONNECTION_BAD)
     664       10734 :         (void) connectDBComplete(conn);
     665             : 
     666       11006 :     return conn;
     667             : 
     668             : }
     669             : 
     670             : /*
     671             :  *      PQpingParams
     672             :  *
     673             :  * check server status, accepting parameters identical to PQconnectdbParams
     674             :  */
     675             : PGPing
     676           4 : PQpingParams(const char *const *keywords,
     677             :              const char *const *values,
     678             :              int expand_dbname)
     679             : {
     680           4 :     PGconn     *conn = PQconnectStartParams(keywords, values, expand_dbname);
     681             :     PGPing      ret;
     682             : 
     683           4 :     ret = internal_ping(conn);
     684           4 :     PQfinish(conn);
     685             : 
     686           4 :     return ret;
     687             : }
     688             : 
     689             : /*
     690             :  *      PQconnectdb
     691             :  *
     692             :  * establishes a connection to a postgres backend through the postmaster
     693             :  * using connection information in a string.
     694             :  *
     695             :  * The conninfo string is either a whitespace-separated list of
     696             :  *
     697             :  *     option = value
     698             :  *
     699             :  * definitions or a URI (refer to the documentation for details.) Value
     700             :  * might be a single value containing no whitespaces or a single quoted
     701             :  * string. If a single quote should appear anywhere in the value, it must be
     702             :  * escaped with a backslash like \'
     703             :  *
     704             :  * Returns a PGconn* which is needed for all subsequent libpq calls, or NULL
     705             :  * if a memory allocation failed.
     706             :  * If the status field of the connection returned is CONNECTION_BAD,
     707             :  * then some fields may be null'ed out instead of having valid values.
     708             :  *
     709             :  * You should call PQfinish (if conn is not NULL) regardless of whether this
     710             :  * call succeeded.
     711             :  */
     712             : PGconn *
     713         964 : PQconnectdb(const char *conninfo)
     714             : {
     715         964 :     PGconn     *conn = PQconnectStart(conninfo);
     716             : 
     717         964 :     if (conn && conn->status != CONNECTION_BAD)
     718         960 :         (void) connectDBComplete(conn);
     719             : 
     720         964 :     return conn;
     721             : }
     722             : 
     723             : /*
     724             :  *      PQping
     725             :  *
     726             :  * check server status, accepting parameters identical to PQconnectdb
     727             :  */
     728             : PGPing
     729           0 : PQping(const char *conninfo)
     730             : {
     731           0 :     PGconn     *conn = PQconnectStart(conninfo);
     732             :     PGPing      ret;
     733             : 
     734           0 :     ret = internal_ping(conn);
     735           0 :     PQfinish(conn);
     736             : 
     737           0 :     return ret;
     738             : }
     739             : 
     740             : /*
     741             :  *      PQconnectStartParams
     742             :  *
     743             :  * Begins the establishment of a connection to a postgres backend through the
     744             :  * postmaster using connection information in a struct.
     745             :  *
     746             :  * See comment for PQconnectdbParams for the definition of the string format.
     747             :  *
     748             :  * Returns a PGconn*.  If NULL is returned, a malloc error has occurred, and
     749             :  * you should not attempt to proceed with this connection.  If the status
     750             :  * field of the connection returned is CONNECTION_BAD, an error has
     751             :  * occurred. In this case you should call PQfinish on the result, (perhaps
     752             :  * inspecting the error message first).  Other fields of the structure may not
     753             :  * be valid if that occurs.  If the status field is not CONNECTION_BAD, then
     754             :  * this stage has succeeded - call PQconnectPoll, using select(2) to see when
     755             :  * this is necessary.
     756             :  *
     757             :  * See PQconnectPoll for more info.
     758             :  */
     759             : PGconn *
     760       11710 : PQconnectStartParams(const char *const *keywords,
     761             :                      const char *const *values,
     762             :                      int expand_dbname)
     763             : {
     764             :     PGconn     *conn;
     765             :     PQconninfoOption *connOptions;
     766             : 
     767             :     /*
     768             :      * Allocate memory for the conn structure.  Note that we also expect this
     769             :      * to initialize conn->errorMessage to empty.  All subsequent steps during
     770             :      * connection initialization will only append to that buffer.
     771             :      */
     772       11710 :     conn = makeEmptyPGconn();
     773       11710 :     if (conn == NULL)
     774           0 :         return NULL;
     775             : 
     776             :     /*
     777             :      * Parse the conninfo arrays
     778             :      */
     779       11710 :     connOptions = conninfo_array_parse(keywords, values,
     780             :                                        &conn->errorMessage,
     781             :                                        true, expand_dbname);
     782       11710 :     if (connOptions == NULL)
     783             :     {
     784           0 :         conn->status = CONNECTION_BAD;
     785             :         /* errorMessage is already set */
     786           0 :         return conn;
     787             :     }
     788             : 
     789             :     /*
     790             :      * Move option values into conn structure
     791             :      */
     792       11710 :     if (!fillPGconn(conn, connOptions))
     793             :     {
     794           0 :         PQconninfoFree(connOptions);
     795           0 :         return conn;
     796             :     }
     797             : 
     798             :     /*
     799             :      * Free the option info - all is in conn now
     800             :      */
     801       11710 :     PQconninfoFree(connOptions);
     802             : 
     803             :     /*
     804             :      * Compute derived options
     805             :      */
     806       11710 :     if (!connectOptions2(conn))
     807           8 :         return conn;
     808             : 
     809             :     /*
     810             :      * Connect to the database
     811             :      */
     812       11702 :     if (!connectDBStart(conn))
     813             :     {
     814             :         /* Just in case we failed to set it in connectDBStart */
     815         354 :         conn->status = CONNECTION_BAD;
     816             :     }
     817             : 
     818       11702 :     return conn;
     819             : }
     820             : 
     821             : /*
     822             :  *      PQconnectStart
     823             :  *
     824             :  * Begins the establishment of a connection to a postgres backend through the
     825             :  * postmaster using connection information in a string.
     826             :  *
     827             :  * See comment for PQconnectdb for the definition of the string format.
     828             :  *
     829             :  * Returns a PGconn*.  If NULL is returned, a malloc error has occurred, and
     830             :  * you should not attempt to proceed with this connection.  If the status
     831             :  * field of the connection returned is CONNECTION_BAD, an error has
     832             :  * occurred. In this case you should call PQfinish on the result, (perhaps
     833             :  * inspecting the error message first).  Other fields of the structure may not
     834             :  * be valid if that occurs.  If the status field is not CONNECTION_BAD, then
     835             :  * this stage has succeeded - call PQconnectPoll, using select(2) to see when
     836             :  * this is necessary.
     837             :  *
     838             :  * See PQconnectPoll for more info.
     839             :  */
     840             : PGconn *
     841         964 : PQconnectStart(const char *conninfo)
     842             : {
     843             :     PGconn     *conn;
     844             : 
     845             :     /*
     846             :      * Allocate memory for the conn structure.  Note that we also expect this
     847             :      * to initialize conn->errorMessage to empty.  All subsequent steps during
     848             :      * connection initialization will only append to that buffer.
     849             :      */
     850         964 :     conn = makeEmptyPGconn();
     851         964 :     if (conn == NULL)
     852           0 :         return NULL;
     853             : 
     854             :     /*
     855             :      * Parse the conninfo string
     856             :      */
     857         964 :     if (!connectOptions1(conn, conninfo))
     858           4 :         return conn;
     859             : 
     860             :     /*
     861             :      * Compute derived options
     862             :      */
     863         960 :     if (!connectOptions2(conn))
     864           0 :         return conn;
     865             : 
     866             :     /*
     867             :      * Connect to the database
     868             :      */
     869         960 :     if (!connectDBStart(conn))
     870             :     {
     871             :         /* Just in case we failed to set it in connectDBStart */
     872           0 :         conn->status = CONNECTION_BAD;
     873             :     }
     874             : 
     875         960 :     return conn;
     876             : }
     877             : 
     878             : /*
     879             :  * Move option values into conn structure
     880             :  *
     881             :  * Don't put anything cute here --- intelligence should be in
     882             :  * connectOptions2 ...
     883             :  *
     884             :  * Returns true on success. On failure, returns false and sets error message.
     885             :  */
     886             : static bool
     887       12670 : fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
     888             : {
     889             :     const internalPQconninfoOption *option;
     890             : 
     891      468790 :     for (option = PQconninfoOptions; option->keyword; option++)
     892             :     {
     893      456120 :         if (option->connofs >= 0)
     894             :         {
     895      443450 :             const char *tmp = conninfo_getval(connOptions, option->keyword);
     896             : 
     897      443450 :             if (tmp)
     898             :             {
     899      191342 :                 char      **connmember = (char **) ((char *) conn + option->connofs);
     900             : 
     901      191342 :                 if (*connmember)
     902           0 :                     free(*connmember);
     903      191342 :                 *connmember = strdup(tmp);
     904      191342 :                 if (*connmember == NULL)
     905             :                 {
     906           0 :                     appendPQExpBufferStr(&conn->errorMessage,
     907           0 :                                          libpq_gettext("out of memory\n"));
     908           0 :                     return false;
     909             :                 }
     910             :             }
     911             :         }
     912             :     }
     913             : 
     914       12670 :     return true;
     915             : }
     916             : 
     917             : /*
     918             :  *      connectOptions1
     919             :  *
     920             :  * Internal subroutine to set up connection parameters given an already-
     921             :  * created PGconn and a conninfo string.  Derived settings should be
     922             :  * processed by calling connectOptions2 next.  (We split them because
     923             :  * PQsetdbLogin overrides defaults in between.)
     924             :  *
     925             :  * Returns true if OK, false if trouble (in which case errorMessage is set
     926             :  * and so is conn->status).
     927             :  */
     928             : static bool
     929         964 : connectOptions1(PGconn *conn, const char *conninfo)
     930             : {
     931             :     PQconninfoOption *connOptions;
     932             : 
     933             :     /*
     934             :      * Parse the conninfo string
     935             :      */
     936         964 :     connOptions = parse_connection_string(conninfo, &conn->errorMessage, true);
     937         964 :     if (connOptions == NULL)
     938             :     {
     939           4 :         conn->status = CONNECTION_BAD;
     940             :         /* errorMessage is already set */
     941           4 :         return false;
     942             :     }
     943             : 
     944             :     /*
     945             :      * Move option values into conn structure
     946             :      */
     947         960 :     if (!fillPGconn(conn, connOptions))
     948             :     {
     949           0 :         conn->status = CONNECTION_BAD;
     950           0 :         PQconninfoFree(connOptions);
     951           0 :         return false;
     952             :     }
     953             : 
     954             :     /*
     955             :      * Free the option info - all is in conn now
     956             :      */
     957         960 :     PQconninfoFree(connOptions);
     958             : 
     959         960 :     return true;
     960             : }
     961             : 
     962             : /*
     963             :  * Count the number of elements in a simple comma-separated list.
     964             :  */
     965             : static int
     966       12670 : count_comma_separated_elems(const char *input)
     967             : {
     968             :     int         n;
     969             : 
     970       12670 :     n = 1;
     971      231888 :     for (; *input != '\0'; input++)
     972             :     {
     973      219218 :         if (*input == ',')
     974          34 :             n++;
     975             :     }
     976             : 
     977       12670 :     return n;
     978             : }
     979             : 
     980             : /*
     981             :  * Parse a simple comma-separated list.
     982             :  *
     983             :  * On each call, returns a malloc'd copy of the next element, and sets *more
     984             :  * to indicate whether there are any more elements in the list after this,
     985             :  * and updates *startptr to point to the next element, if any.
     986             :  *
     987             :  * On out of memory, returns NULL.
     988             :  */
     989             : static char *
     990       25570 : parse_comma_separated_list(char **startptr, bool *more)
     991             : {
     992             :     char       *p;
     993       25570 :     char       *s = *startptr;
     994             :     char       *e;
     995             :     int         len;
     996             : 
     997             :     /*
     998             :      * Search for the end of the current element; a comma or end-of-string
     999             :      * acts as a terminator.
    1000             :      */
    1001       25570 :     e = s;
    1002      311728 :     while (*e != '\0' && *e != ',')
    1003      286158 :         ++e;
    1004       25570 :     *more = (*e == ',');
    1005             : 
    1006       25570 :     len = e - s;
    1007       25570 :     p = (char *) malloc(sizeof(char) * (len + 1));
    1008       25570 :     if (p)
    1009             :     {
    1010       25570 :         memcpy(p, s, len);
    1011       25570 :         p[len] = '\0';
    1012             :     }
    1013       25570 :     *startptr = e + 1;
    1014             : 
    1015       25570 :     return p;
    1016             : }
    1017             : 
    1018             : /*
    1019             :  *      connectOptions2
    1020             :  *
    1021             :  * Compute derived connection options after absorbing all user-supplied info.
    1022             :  *
    1023             :  * Returns true if OK, false if trouble (in which case errorMessage is set
    1024             :  * and so is conn->status).
    1025             :  */
    1026             : static bool
    1027       12670 : connectOptions2(PGconn *conn)
    1028             : {
    1029             :     int         i;
    1030             : 
    1031             :     /*
    1032             :      * Allocate memory for details about each host to which we might possibly
    1033             :      * try to connect.  For that, count the number of elements in the hostaddr
    1034             :      * or host options.  If neither is given, assume one host.
    1035             :      */
    1036       12670 :     conn->whichhost = 0;
    1037       12670 :     if (conn->pghostaddr && conn->pghostaddr[0] != '\0')
    1038         162 :         conn->nconnhost = count_comma_separated_elems(conn->pghostaddr);
    1039       12508 :     else if (conn->pghost && conn->pghost[0] != '\0')
    1040       12508 :         conn->nconnhost = count_comma_separated_elems(conn->pghost);
    1041             :     else
    1042           0 :         conn->nconnhost = 1;
    1043       12670 :     conn->connhost = (pg_conn_host *)
    1044       12670 :         calloc(conn->nconnhost, sizeof(pg_conn_host));
    1045       12670 :     if (conn->connhost == NULL)
    1046           0 :         goto oom_error;
    1047             : 
    1048             :     /*
    1049             :      * We now have one pg_conn_host structure per possible host.  Fill in the
    1050             :      * host and hostaddr fields for each, by splitting the parameter strings.
    1051             :      */
    1052       12670 :     if (conn->pghostaddr != NULL && conn->pghostaddr[0] != '\0')
    1053             :     {
    1054         162 :         char       *s = conn->pghostaddr;
    1055         162 :         bool        more = true;
    1056             : 
    1057         324 :         for (i = 0; i < conn->nconnhost && more; i++)
    1058             :         {
    1059         162 :             conn->connhost[i].hostaddr = parse_comma_separated_list(&s, &more);
    1060         162 :             if (conn->connhost[i].hostaddr == NULL)
    1061           0 :                 goto oom_error;
    1062             :         }
    1063             : 
    1064             :         /*
    1065             :          * If hostaddr was given, the array was allocated according to the
    1066             :          * number of elements in the hostaddr list, so it really should be the
    1067             :          * right size.
    1068             :          */
    1069             :         Assert(!more);
    1070             :         Assert(i == conn->nconnhost);
    1071             :     }
    1072             : 
    1073       12670 :     if (conn->pghost != NULL && conn->pghost[0] != '\0')
    1074             :     {
    1075       12670 :         char       *s = conn->pghost;
    1076       12670 :         bool        more = true;
    1077             : 
    1078       25374 :         for (i = 0; i < conn->nconnhost && more; i++)
    1079             :         {
    1080       12704 :             conn->connhost[i].host = parse_comma_separated_list(&s, &more);
    1081       12704 :             if (conn->connhost[i].host == NULL)
    1082           0 :                 goto oom_error;
    1083             :         }
    1084             : 
    1085             :         /* Check for wrong number of host items. */
    1086       12670 :         if (more || i != conn->nconnhost)
    1087             :         {
    1088           0 :             conn->status = CONNECTION_BAD;
    1089           0 :             appendPQExpBuffer(&conn->errorMessage,
    1090           0 :                               libpq_gettext("could not match %d host names to %d hostaddr values\n"),
    1091           0 :                               count_comma_separated_elems(conn->pghost), conn->nconnhost);
    1092           0 :             return false;
    1093             :         }
    1094             :     }
    1095             : 
    1096             :     /*
    1097             :      * Now, for each host slot, identify the type of address spec, and fill in
    1098             :      * the default address if nothing was given.
    1099             :      */
    1100       25374 :     for (i = 0; i < conn->nconnhost; i++)
    1101             :     {
    1102       12704 :         pg_conn_host *ch = &conn->connhost[i];
    1103             : 
    1104       12704 :         if (ch->hostaddr != NULL && ch->hostaddr[0] != '\0')
    1105         162 :             ch->type = CHT_HOST_ADDRESS;
    1106       12542 :         else if (ch->host != NULL && ch->host[0] != '\0')
    1107             :         {
    1108       12542 :             ch->type = CHT_HOST_NAME;
    1109             : #ifdef HAVE_UNIX_SOCKETS
    1110       12542 :             if (is_unixsock_path(ch->host))
    1111       12254 :                 ch->type = CHT_UNIX_SOCKET;
    1112             : #endif
    1113             :         }
    1114             :         else
    1115             :         {
    1116           0 :             if (ch->host)
    1117           0 :                 free(ch->host);
    1118             : #ifdef HAVE_UNIX_SOCKETS
    1119           0 :             if (DEFAULT_PGSOCKET_DIR[0])
    1120             :             {
    1121           0 :                 ch->host = strdup(DEFAULT_PGSOCKET_DIR);
    1122           0 :                 ch->type = CHT_UNIX_SOCKET;
    1123             :             }
    1124             :             else
    1125             : #endif
    1126             :             {
    1127           0 :                 ch->host = strdup(DefaultHost);
    1128           0 :                 ch->type = CHT_HOST_NAME;
    1129             :             }
    1130           0 :             if (ch->host == NULL)
    1131           0 :                 goto oom_error;
    1132             :         }
    1133             :     }
    1134             : 
    1135             :     /*
    1136             :      * Next, work out the port number corresponding to each host name.
    1137             :      *
    1138             :      * Note: unlike the above for host names, this could leave the port fields
    1139             :      * as null or empty strings.  We will substitute DEF_PGPORT whenever we
    1140             :      * read such a port field.
    1141             :      */
    1142       12670 :     if (conn->pgport != NULL && conn->pgport[0] != '\0')
    1143             :     {
    1144       12670 :         char       *s = conn->pgport;
    1145       12670 :         bool        more = true;
    1146             : 
    1147       25374 :         for (i = 0; i < conn->nconnhost && more; i++)
    1148             :         {
    1149       12704 :             conn->connhost[i].port = parse_comma_separated_list(&s, &more);
    1150       12704 :             if (conn->connhost[i].port == NULL)
    1151           0 :                 goto oom_error;
    1152             :         }
    1153             : 
    1154             :         /*
    1155             :          * If exactly one port was given, use it for every host.  Otherwise,
    1156             :          * there must be exactly as many ports as there were hosts.
    1157             :          */
    1158       12670 :         if (i == 1 && !more)
    1159             :         {
    1160       12636 :             for (i = 1; i < conn->nconnhost; i++)
    1161             :             {
    1162           0 :                 conn->connhost[i].port = strdup(conn->connhost[0].port);
    1163           0 :                 if (conn->connhost[i].port == NULL)
    1164           0 :                     goto oom_error;
    1165             :             }
    1166             :         }
    1167          34 :         else if (more || i != conn->nconnhost)
    1168             :         {
    1169           0 :             conn->status = CONNECTION_BAD;
    1170           0 :             appendPQExpBuffer(&conn->errorMessage,
    1171           0 :                               libpq_gettext("could not match %d port numbers to %d hosts\n"),
    1172           0 :                               count_comma_separated_elems(conn->pgport), conn->nconnhost);
    1173           0 :             return false;
    1174             :         }
    1175             :     }
    1176             : 
    1177             :     /*
    1178             :      * If user name was not given, fetch it.  (Most likely, the fetch will
    1179             :      * fail, since the only way we get here is if pg_fe_getauthname() failed
    1180             :      * during conninfo_add_defaults().  But now we want an error message.)
    1181             :      */
    1182       12670 :     if (conn->pguser == NULL || conn->pguser[0] == '\0')
    1183             :     {
    1184           0 :         if (conn->pguser)
    1185           0 :             free(conn->pguser);
    1186           0 :         conn->pguser = pg_fe_getauthname(&conn->errorMessage);
    1187           0 :         if (!conn->pguser)
    1188             :         {
    1189           0 :             conn->status = CONNECTION_BAD;
    1190           0 :             return false;
    1191             :         }
    1192             :     }
    1193             : 
    1194             :     /*
    1195             :      * If database name was not given, default it to equal user name
    1196             :      */
    1197       12670 :     if (conn->dbName == NULL || conn->dbName[0] == '\0')
    1198             :     {
    1199          10 :         if (conn->dbName)
    1200           2 :             free(conn->dbName);
    1201          10 :         conn->dbName = strdup(conn->pguser);
    1202          10 :         if (!conn->dbName)
    1203           0 :             goto oom_error;
    1204             :     }
    1205             : 
    1206             :     /*
    1207             :      * If password was not given, try to look it up in password file.  Note
    1208             :      * that the result might be different for each host/port pair.
    1209             :      */
    1210       12670 :     if (conn->pgpass == NULL || conn->pgpass[0] == '\0')
    1211             :     {
    1212             :         /* If password file wasn't specified, use ~/PGPASSFILE */
    1213       12524 :         if (conn->pgpassfile == NULL || conn->pgpassfile[0] == '\0')
    1214             :         {
    1215             :             char        homedir[MAXPGPATH];
    1216             : 
    1217       12332 :             if (pqGetHomeDirectory(homedir, sizeof(homedir)))
    1218             :             {
    1219       12332 :                 if (conn->pgpassfile)
    1220           0 :                     free(conn->pgpassfile);
    1221       12332 :                 conn->pgpassfile = malloc(MAXPGPATH);
    1222       12332 :                 if (!conn->pgpassfile)
    1223           0 :                     goto oom_error;
    1224       12332 :                 snprintf(conn->pgpassfile, MAXPGPATH, "%s/%s",
    1225             :                          homedir, PGPASSFILE);
    1226             :             }
    1227             :         }
    1228             : 
    1229       12524 :         if (conn->pgpassfile != NULL && conn->pgpassfile[0] != '\0')
    1230             :         {
    1231       25082 :             for (i = 0; i < conn->nconnhost; i++)
    1232             :             {
    1233             :                 /*
    1234             :                  * Try to get a password for this host from file.  We use host
    1235             :                  * for the hostname search key if given, else hostaddr (at
    1236             :                  * least one of them is guaranteed nonempty by now).
    1237             :                  */
    1238       12558 :                 const char *pwhost = conn->connhost[i].host;
    1239             : 
    1240       12558 :                 if (pwhost == NULL || pwhost[0] == '\0')
    1241           0 :                     pwhost = conn->connhost[i].hostaddr;
    1242             : 
    1243       12558 :                 conn->connhost[i].password =
    1244       12558 :                     passwordFromFile(pwhost,
    1245       12558 :                                      conn->connhost[i].port,
    1246       12558 :                                      conn->dbName,
    1247       12558 :                                      conn->pguser,
    1248       12558 :                                      conn->pgpassfile);
    1249             :             }
    1250             :         }
    1251             :     }
    1252             : 
    1253             :     /*
    1254             :      * validate channel_binding option
    1255             :      */
    1256       12670 :     if (conn->channel_binding)
    1257             :     {
    1258       12670 :         if (strcmp(conn->channel_binding, "disable") != 0
    1259       12668 :             && strcmp(conn->channel_binding, "prefer") != 0
    1260          12 :             && strcmp(conn->channel_binding, "require") != 0)
    1261             :         {
    1262           2 :             conn->status = CONNECTION_BAD;
    1263           2 :             appendPQExpBuffer(&conn->errorMessage,
    1264           2 :                               libpq_gettext("invalid %s value: \"%s\"\n"),
    1265             :                               "channel_binding", conn->channel_binding);
    1266           2 :             return false;
    1267             :         }
    1268             :     }
    1269             :     else
    1270             :     {
    1271           0 :         conn->channel_binding = strdup(DefaultChannelBinding);
    1272           0 :         if (!conn->channel_binding)
    1273           0 :             goto oom_error;
    1274             :     }
    1275             : 
    1276             :     /*
    1277             :      * validate sslmode option
    1278             :      */
    1279       12668 :     if (conn->sslmode)
    1280             :     {
    1281       12668 :         if (strcmp(conn->sslmode, "disable") != 0
    1282       12652 :             && strcmp(conn->sslmode, "allow") != 0
    1283       12652 :             && strcmp(conn->sslmode, "prefer") != 0
    1284         150 :             && strcmp(conn->sslmode, "require") != 0
    1285          64 :             && strcmp(conn->sslmode, "verify-ca") != 0
    1286          32 :             && strcmp(conn->sslmode, "verify-full") != 0)
    1287             :         {
    1288           0 :             conn->status = CONNECTION_BAD;
    1289           0 :             appendPQExpBuffer(&conn->errorMessage,
    1290           0 :                               libpq_gettext("invalid %s value: \"%s\"\n"),
    1291             :                               "sslmode", conn->sslmode);
    1292           0 :             return false;
    1293             :         }
    1294             : 
    1295             : #ifndef USE_SSL
    1296             :         switch (conn->sslmode[0])
    1297             :         {
    1298             :             case 'a':           /* "allow" */
    1299             :             case 'p':           /* "prefer" */
    1300             : 
    1301             :                 /*
    1302             :                  * warn user that an SSL connection will never be negotiated
    1303             :                  * since SSL was not compiled in?
    1304             :                  */
    1305             :                 break;
    1306             : 
    1307             :             case 'r':           /* "require" */
    1308             :             case 'v':           /* "verify-ca" or "verify-full" */
    1309             :                 conn->status = CONNECTION_BAD;
    1310             :                 appendPQExpBuffer(&conn->errorMessage,
    1311             :                                   libpq_gettext("sslmode value \"%s\" invalid when SSL support is not compiled in\n"),
    1312             :                                   conn->sslmode);
    1313             :                 return false;
    1314             :         }
    1315             : #endif
    1316             :     }
    1317             :     else
    1318             :     {
    1319           0 :         conn->sslmode = strdup(DefaultSSLMode);
    1320           0 :         if (!conn->sslmode)
    1321           0 :             goto oom_error;
    1322             :     }
    1323             : 
    1324             :     /*
    1325             :      * Validate TLS protocol versions for ssl_min_protocol_version and
    1326             :      * ssl_max_protocol_version.
    1327             :      */
    1328       12668 :     if (!sslVerifyProtocolVersion(conn->ssl_min_protocol_version))
    1329             :     {
    1330           2 :         conn->status = CONNECTION_BAD;
    1331           2 :         appendPQExpBuffer(&conn->errorMessage,
    1332           2 :                           libpq_gettext("invalid %s value: \"%s\"\n"),
    1333             :                           "ssl_min_protocol_version",
    1334             :                           conn->ssl_min_protocol_version);
    1335           2 :         return false;
    1336             :     }
    1337       12666 :     if (!sslVerifyProtocolVersion(conn->ssl_max_protocol_version))
    1338             :     {
    1339           2 :         conn->status = CONNECTION_BAD;
    1340           2 :         appendPQExpBuffer(&conn->errorMessage,
    1341           2 :                           libpq_gettext("invalid %s value: \"%s\"\n"),
    1342             :                           "ssl_max_protocol_version",
    1343             :                           conn->ssl_max_protocol_version);
    1344           2 :         return false;
    1345             :     }
    1346             : 
    1347             :     /*
    1348             :      * Check if the range of SSL protocols defined is correct.  This is done
    1349             :      * at this early step because this is independent of the SSL
    1350             :      * implementation used, and this avoids unnecessary cycles with an
    1351             :      * already-built SSL context when the connection is being established, as
    1352             :      * it would be doomed anyway.
    1353             :      */
    1354       12664 :     if (!sslVerifyProtocolRange(conn->ssl_min_protocol_version,
    1355       12664 :                                 conn->ssl_max_protocol_version))
    1356             :     {
    1357           2 :         conn->status = CONNECTION_BAD;
    1358           2 :         appendPQExpBufferStr(&conn->errorMessage,
    1359           2 :                              libpq_gettext("invalid SSL protocol version range\n"));
    1360           2 :         return false;
    1361             :     }
    1362             : 
    1363             :     /*
    1364             :      * validate gssencmode option
    1365             :      */
    1366       12662 :     if (conn->gssencmode)
    1367             :     {
    1368       12662 :         if (strcmp(conn->gssencmode, "disable") != 0 &&
    1369           0 :             strcmp(conn->gssencmode, "prefer") != 0 &&
    1370           0 :             strcmp(conn->gssencmode, "require") != 0)
    1371             :         {
    1372           0 :             conn->status = CONNECTION_BAD;
    1373           0 :             appendPQExpBuffer(&conn->errorMessage,
    1374           0 :                               libpq_gettext("invalid %s value: \"%s\"\n"),
    1375             :                               "gssencmode",
    1376             :                               conn->gssencmode);
    1377           0 :             return false;
    1378             :         }
    1379             : #ifndef ENABLE_GSS
    1380       12662 :         if (strcmp(conn->gssencmode, "require") == 0)
    1381             :         {
    1382           0 :             conn->status = CONNECTION_BAD;
    1383           0 :             appendPQExpBuffer(&conn->errorMessage,
    1384           0 :                               libpq_gettext("gssencmode value \"%s\" invalid when GSSAPI support is not compiled in\n"),
    1385             :                               conn->gssencmode);
    1386           0 :             return false;
    1387             :         }
    1388             : #endif
    1389             :     }
    1390             :     else
    1391             :     {
    1392           0 :         conn->gssencmode = strdup(DefaultGSSMode);
    1393           0 :         if (!conn->gssencmode)
    1394           0 :             goto oom_error;
    1395             :     }
    1396             : 
    1397             :     /*
    1398             :      * validate target_session_attrs option, and set target_server_type
    1399             :      */
    1400       12662 :     if (conn->target_session_attrs)
    1401             :     {
    1402       12662 :         if (strcmp(conn->target_session_attrs, "any") == 0)
    1403       12632 :             conn->target_server_type = SERVER_TYPE_ANY;
    1404          30 :         else if (strcmp(conn->target_session_attrs, "read-write") == 0)
    1405           6 :             conn->target_server_type = SERVER_TYPE_READ_WRITE;
    1406          24 :         else if (strcmp(conn->target_session_attrs, "read-only") == 0)
    1407           6 :             conn->target_server_type = SERVER_TYPE_READ_ONLY;
    1408          18 :         else if (strcmp(conn->target_session_attrs, "primary") == 0)
    1409           6 :             conn->target_server_type = SERVER_TYPE_PRIMARY;
    1410          12 :         else if (strcmp(conn->target_session_attrs, "standby") == 0)
    1411           6 :             conn->target_server_type = SERVER_TYPE_STANDBY;
    1412           6 :         else if (strcmp(conn->target_session_attrs, "prefer-standby") == 0)
    1413           6 :             conn->target_server_type = SERVER_TYPE_PREFER_STANDBY;
    1414             :         else
    1415             :         {
    1416           0 :             conn->status = CONNECTION_BAD;
    1417           0 :             appendPQExpBuffer(&conn->errorMessage,
    1418           0 :                               libpq_gettext("invalid %s value: \"%s\"\n"),
    1419             :                               "target_session_attrs",
    1420             :                               conn->target_session_attrs);
    1421           0 :             return false;
    1422             :         }
    1423             :     }
    1424             :     else
    1425           0 :         conn->target_server_type = SERVER_TYPE_ANY;
    1426             : 
    1427             :     /*
    1428             :      * Resolve special "auto" client_encoding from the locale
    1429             :      */
    1430       12662 :     if (conn->client_encoding_initial &&
    1431        1284 :         strcmp(conn->client_encoding_initial, "auto") == 0)
    1432             :     {
    1433           2 :         free(conn->client_encoding_initial);
    1434           2 :         conn->client_encoding_initial = strdup(pg_encoding_to_char(pg_get_encoding_from_locale(NULL, true)));
    1435           2 :         if (!conn->client_encoding_initial)
    1436           0 :             goto oom_error;
    1437             :     }
    1438             : 
    1439             :     /*
    1440             :      * Only if we get this far is it appropriate to try to connect. (We need a
    1441             :      * state flag, rather than just the boolean result of this function, in
    1442             :      * case someone tries to PQreset() the PGconn.)
    1443             :      */
    1444       12662 :     conn->options_valid = true;
    1445             : 
    1446       12662 :     return true;
    1447             : 
    1448           0 : oom_error:
    1449           0 :     conn->status = CONNECTION_BAD;
    1450           0 :     appendPQExpBufferStr(&conn->errorMessage,
    1451           0 :                          libpq_gettext("out of memory\n"));
    1452           0 :     return false;
    1453             : }
    1454             : 
    1455             : /*
    1456             :  *      PQconndefaults
    1457             :  *
    1458             :  * Construct a default connection options array, which identifies all the
    1459             :  * available options and shows any default values that are available from the
    1460             :  * environment etc.  On error (eg out of memory), NULL is returned.
    1461             :  *
    1462             :  * Using this function, an application may determine all possible options
    1463             :  * and their current default values.
    1464             :  *
    1465             :  * NOTE: as of PostgreSQL 7.0, the returned array is dynamically allocated
    1466             :  * and should be freed when no longer needed via PQconninfoFree().  (In prior
    1467             :  * versions, the returned array was static, but that's not thread-safe.)
    1468             :  * Pre-7.0 applications that use this function will see a small memory leak
    1469             :  * until they are updated to call PQconninfoFree.
    1470             :  */
    1471             : PQconninfoOption *
    1472          22 : PQconndefaults(void)
    1473             : {
    1474             :     PQExpBufferData errorBuf;
    1475             :     PQconninfoOption *connOptions;
    1476             : 
    1477             :     /* We don't actually report any errors here, but callees want a buffer */
    1478          22 :     initPQExpBuffer(&errorBuf);
    1479          22 :     if (PQExpBufferDataBroken(errorBuf))
    1480           0 :         return NULL;            /* out of memory already :-( */
    1481             : 
    1482          22 :     connOptions = conninfo_init(&errorBuf);
    1483          22 :     if (connOptions != NULL)
    1484             :     {
    1485             :         /* pass NULL errorBuf to ignore errors */
    1486          22 :         if (!conninfo_add_defaults(connOptions, NULL))
    1487             :         {
    1488           0 :             PQconninfoFree(connOptions);
    1489           0 :             connOptions = NULL;
    1490             :         }
    1491             :     }
    1492             : 
    1493          22 :     termPQExpBuffer(&errorBuf);
    1494          22 :     return connOptions;
    1495             : }
    1496             : 
    1497             : /* ----------------
    1498             :  *      PQsetdbLogin
    1499             :  *
    1500             :  * establishes a connection to a postgres backend through the postmaster
    1501             :  * at the specified host and port.
    1502             :  *
    1503             :  * returns a PGconn* which is needed for all subsequent libpq calls
    1504             :  *
    1505             :  * if the status field of the connection returned is CONNECTION_BAD,
    1506             :  * then only the errorMessage is likely to be useful.
    1507             :  * ----------------
    1508             :  */
    1509             : PGconn *
    1510           0 : PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions,
    1511             :              const char *pgtty, const char *dbName, const char *login,
    1512             :              const char *pwd)
    1513             : {
    1514             :     PGconn     *conn;
    1515             : 
    1516             :     /*
    1517             :      * Allocate memory for the conn structure.  Note that we also expect this
    1518             :      * to initialize conn->errorMessage to empty.  All subsequent steps during
    1519             :      * connection initialization will only append to that buffer.
    1520             :      */
    1521           0 :     conn = makeEmptyPGconn();
    1522           0 :     if (conn == NULL)
    1523           0 :         return NULL;
    1524             : 
    1525             :     /*
    1526             :      * If the dbName parameter contains what looks like a connection string,
    1527             :      * parse it into conn struct using connectOptions1.
    1528             :      */
    1529           0 :     if (dbName && recognized_connection_string(dbName))
    1530             :     {
    1531           0 :         if (!connectOptions1(conn, dbName))
    1532           0 :             return conn;
    1533             :     }
    1534             :     else
    1535             :     {
    1536             :         /*
    1537             :          * Old-style path: first, parse an empty conninfo string in order to
    1538             :          * set up the same defaults that PQconnectdb() would use.
    1539             :          */
    1540           0 :         if (!connectOptions1(conn, ""))
    1541           0 :             return conn;
    1542             : 
    1543             :         /* Insert dbName parameter value into struct */
    1544           0 :         if (dbName && dbName[0] != '\0')
    1545             :         {
    1546           0 :             if (conn->dbName)
    1547           0 :                 free(conn->dbName);
    1548           0 :             conn->dbName = strdup(dbName);
    1549           0 :             if (!conn->dbName)
    1550           0 :                 goto oom_error;
    1551             :         }
    1552             :     }
    1553             : 
    1554             :     /*
    1555             :      * Insert remaining parameters into struct, overriding defaults (as well
    1556             :      * as any conflicting data from dbName taken as a conninfo).
    1557             :      */
    1558           0 :     if (pghost && pghost[0] != '\0')
    1559             :     {
    1560           0 :         if (conn->pghost)
    1561           0 :             free(conn->pghost);
    1562           0 :         conn->pghost = strdup(pghost);
    1563           0 :         if (!conn->pghost)
    1564           0 :             goto oom_error;
    1565             :     }
    1566             : 
    1567           0 :     if (pgport && pgport[0] != '\0')
    1568             :     {
    1569           0 :         if (conn->pgport)
    1570           0 :             free(conn->pgport);
    1571           0 :         conn->pgport = strdup(pgport);
    1572           0 :         if (!conn->pgport)
    1573           0 :             goto oom_error;
    1574             :     }
    1575             : 
    1576           0 :     if (pgoptions && pgoptions[0] != '\0')
    1577             :     {
    1578           0 :         if (conn->pgoptions)
    1579           0 :             free(conn->pgoptions);
    1580           0 :         conn->pgoptions = strdup(pgoptions);
    1581           0 :         if (!conn->pgoptions)
    1582           0 :             goto oom_error;
    1583             :     }
    1584             : 
    1585           0 :     if (login && login[0] != '\0')
    1586             :     {
    1587           0 :         if (conn->pguser)
    1588           0 :             free(conn->pguser);
    1589           0 :         conn->pguser = strdup(login);
    1590           0 :         if (!conn->pguser)
    1591           0 :             goto oom_error;
    1592             :     }
    1593             : 
    1594           0 :     if (pwd && pwd[0] != '\0')
    1595             :     {
    1596           0 :         if (conn->pgpass)
    1597           0 :             free(conn->pgpass);
    1598           0 :         conn->pgpass = strdup(pwd);
    1599           0 :         if (!conn->pgpass)
    1600           0 :             goto oom_error;
    1601             :     }
    1602             : 
    1603             :     /*
    1604             :      * Compute derived options
    1605             :      */
    1606           0 :     if (!connectOptions2(conn))
    1607           0 :         return conn;
    1608             : 
    1609             :     /*
    1610             :      * Connect to the database
    1611             :      */
    1612           0 :     if (connectDBStart(conn))
    1613           0 :         (void) connectDBComplete(conn);
    1614             : 
    1615           0 :     return conn;
    1616             : 
    1617           0 : oom_error:
    1618           0 :     conn->status = CONNECTION_BAD;
    1619           0 :     appendPQExpBufferStr(&conn->errorMessage,
    1620           0 :                          libpq_gettext("out of memory\n"));
    1621           0 :     return conn;
    1622             : }
    1623             : 
    1624             : 
    1625             : /* ----------
    1626             :  * connectNoDelay -
    1627             :  * Sets the TCP_NODELAY socket option.
    1628             :  * Returns 1 if successful, 0 if not.
    1629             :  * ----------
    1630             :  */
    1631             : static int
    1632         446 : connectNoDelay(PGconn *conn)
    1633             : {
    1634             : #ifdef  TCP_NODELAY
    1635         446 :     int         on = 1;
    1636             : 
    1637         446 :     if (setsockopt(conn->sock, IPPROTO_TCP, TCP_NODELAY,
    1638             :                    (char *) &on,
    1639             :                    sizeof(on)) < 0)
    1640             :     {
    1641             :         char        sebuf[PG_STRERROR_R_BUFLEN];
    1642             : 
    1643           0 :         appendPQExpBuffer(&conn->errorMessage,
    1644           0 :                           libpq_gettext("could not set socket to TCP no delay mode: %s\n"),
    1645           0 :                           SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
    1646           0 :         return 0;
    1647             :     }
    1648             : #endif
    1649             : 
    1650         446 :     return 1;
    1651             : }
    1652             : 
    1653             : /* ----------
    1654             :  * Write currently connected IP address into host_addr (of len host_addr_len).
    1655             :  * If unable to, set it to the empty string.
    1656             :  * ----------
    1657             :  */
    1658             : static void
    1659       12688 : getHostaddr(PGconn *conn, char *host_addr, int host_addr_len)
    1660             : {
    1661       12688 :     struct sockaddr_storage *addr = &conn->raddr.addr;
    1662             : 
    1663       12688 :     if (addr->ss_family == AF_INET)
    1664             :     {
    1665         160 :         if (pg_inet_net_ntop(AF_INET,
    1666         160 :                              &((struct sockaddr_in *) addr)->sin_addr.s_addr,
    1667             :                              32,
    1668             :                              host_addr, host_addr_len) == NULL)
    1669           0 :             host_addr[0] = '\0';
    1670             :     }
    1671             : #ifdef HAVE_IPV6
    1672       12528 :     else if (addr->ss_family == AF_INET6)
    1673             :     {
    1674         286 :         if (pg_inet_net_ntop(AF_INET6,
    1675         286 :                              &((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr,
    1676             :                              128,
    1677             :                              host_addr, host_addr_len) == NULL)
    1678           0 :             host_addr[0] = '\0';
    1679             :     }
    1680             : #endif
    1681             :     else
    1682       12242 :         host_addr[0] = '\0';
    1683       12688 : }
    1684             : 
    1685             : /*
    1686             :  * emitHostIdentityInfo -
    1687             :  * Speculatively append "connection to server so-and-so failed: " to
    1688             :  * conn->errorMessage once we've identified the current connection target
    1689             :  * address.  This ensures that any subsequent error message will be properly
    1690             :  * attributed to the server we couldn't connect to.  conn->raddr must be
    1691             :  * valid, and the result of getHostaddr() must be supplied.
    1692             :  */
    1693             : static void
    1694       12688 : emitHostIdentityInfo(PGconn *conn, const char *host_addr)
    1695             : {
    1696             : #ifdef HAVE_UNIX_SOCKETS
    1697       12688 :     if (IS_AF_UNIX(conn->raddr.addr.ss_family))
    1698             :     {
    1699             :         char        service[NI_MAXHOST];
    1700             : 
    1701       12242 :         pg_getnameinfo_all(&conn->raddr.addr, conn->raddr.salen,
    1702             :                            NULL, 0,
    1703             :                            service, sizeof(service),
    1704             :                            NI_NUMERICSERV);
    1705       12242 :         appendPQExpBuffer(&conn->errorMessage,
    1706       12242 :                           libpq_gettext("connection to server on socket \"%s\" failed: "),
    1707             :                           service);
    1708             :     }
    1709             :     else
    1710             : #endif                          /* HAVE_UNIX_SOCKETS */
    1711             :     {
    1712             :         const char *displayed_host;
    1713             :         const char *displayed_port;
    1714             : 
    1715             :         /* To which host and port were we actually connecting? */
    1716         446 :         if (conn->connhost[conn->whichhost].type == CHT_HOST_ADDRESS)
    1717         154 :             displayed_host = conn->connhost[conn->whichhost].hostaddr;
    1718             :         else
    1719         292 :             displayed_host = conn->connhost[conn->whichhost].host;
    1720         446 :         displayed_port = conn->connhost[conn->whichhost].port;
    1721         446 :         if (displayed_port == NULL || displayed_port[0] == '\0')
    1722           0 :             displayed_port = DEF_PGPORT_STR;
    1723             : 
    1724             :         /*
    1725             :          * If the user did not supply an IP address using 'hostaddr', and
    1726             :          * 'host' was missing or does not match our lookup, display the
    1727             :          * looked-up IP address.
    1728             :          */
    1729         446 :         if (conn->connhost[conn->whichhost].type != CHT_HOST_ADDRESS &&
    1730         292 :             host_addr[0] &&
    1731         292 :             strcmp(displayed_host, host_addr) != 0)
    1732         290 :             appendPQExpBuffer(&conn->errorMessage,
    1733         290 :                               libpq_gettext("connection to server at \"%s\" (%s), port %s failed: "),
    1734             :                               displayed_host, host_addr,
    1735             :                               displayed_port);
    1736             :         else
    1737         156 :             appendPQExpBuffer(&conn->errorMessage,
    1738         156 :                               libpq_gettext("connection to server at \"%s\", port %s failed: "),
    1739             :                               displayed_host,
    1740             :                               displayed_port);
    1741             :     }
    1742       12688 : }
    1743             : 
    1744             : /* ----------
    1745             :  * connectFailureMessage -
    1746             :  * create a friendly error message on connection failure,
    1747             :  * using the given errno value.  Use this for error cases that
    1748             :  * imply that there's no server there.
    1749             :  * ----------
    1750             :  */
    1751             : static void
    1752         364 : connectFailureMessage(PGconn *conn, int errorno)
    1753             : {
    1754             :     char        sebuf[PG_STRERROR_R_BUFLEN];
    1755             : 
    1756         364 :     appendPQExpBuffer(&conn->errorMessage,
    1757             :                       "%s\n",
    1758             :                       SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)));
    1759             : 
    1760             : #ifdef HAVE_UNIX_SOCKETS
    1761         364 :     if (IS_AF_UNIX(conn->raddr.addr.ss_family))
    1762         354 :         appendPQExpBufferStr(&conn->errorMessage,
    1763         354 :                              libpq_gettext("\tIs the server running locally and accepting connections on that socket?\n"));
    1764             :     else
    1765             : #endif
    1766          10 :         appendPQExpBufferStr(&conn->errorMessage,
    1767          10 :                              libpq_gettext("\tIs the server running on that host and accepting TCP/IP connections?\n"));
    1768         364 : }
    1769             : 
    1770             : /*
    1771             :  * Should we use keepalives?  Returns 1 if yes, 0 if no, and -1 if
    1772             :  * conn->keepalives is set to a value which is not parseable as an
    1773             :  * integer.
    1774             :  */
    1775             : static int
    1776         446 : useKeepalives(PGconn *conn)
    1777             : {
    1778             :     char       *ep;
    1779             :     int         val;
    1780             : 
    1781         446 :     if (conn->keepalives == NULL)
    1782         446 :         return 1;
    1783           0 :     val = strtol(conn->keepalives, &ep, 10);
    1784           0 :     if (*ep)
    1785           0 :         return -1;
    1786           0 :     return val != 0 ? 1 : 0;
    1787             : }
    1788             : 
    1789             : /*
    1790             :  * Parse and try to interpret "value" as an integer value, and if successful,
    1791             :  * store it in *result, complaining if there is any trailing garbage or an
    1792             :  * overflow.  This allows any number of leading and trailing whitespaces.
    1793             :  */
    1794             : static bool
    1795       12692 : parse_int_param(const char *value, int *result, PGconn *conn,
    1796             :                 const char *context)
    1797             : {
    1798             :     char       *end;
    1799             :     long        numval;
    1800             : 
    1801             :     Assert(value != NULL);
    1802             : 
    1803       12692 :     *result = 0;
    1804             : 
    1805             :     /* strtol(3) skips leading whitespaces */
    1806       12692 :     errno = 0;
    1807       12692 :     numval = strtol(value, &end, 10);
    1808             : 
    1809             :     /*
    1810             :      * If no progress was done during the parsing or an error happened, fail.
    1811             :      * This tests properly for overflows of the result.
    1812             :      */
    1813       12692 :     if (value == end || errno != 0 || numval != (int) numval)
    1814           0 :         goto error;
    1815             : 
    1816             :     /*
    1817             :      * Skip any trailing whitespace; if anything but whitespace remains before
    1818             :      * the terminating character, fail
    1819             :      */
    1820       12696 :     while (*end != '\0' && isspace((unsigned char) *end))
    1821           4 :         end++;
    1822             : 
    1823       12692 :     if (*end != '\0')
    1824           0 :         goto error;
    1825             : 
    1826       12692 :     *result = numval;
    1827       12692 :     return true;
    1828             : 
    1829           0 : error:
    1830           0 :     appendPQExpBuffer(&conn->errorMessage,
    1831           0 :                       libpq_gettext("invalid integer value \"%s\" for connection option \"%s\"\n"),
    1832             :                       value, context);
    1833           0 :     return false;
    1834             : }
    1835             : 
    1836             : #ifndef WIN32
    1837             : /*
    1838             :  * Set the keepalive idle timer.
    1839             :  */
    1840             : static int
    1841         446 : setKeepalivesIdle(PGconn *conn)
    1842             : {
    1843             :     int         idle;
    1844             : 
    1845         446 :     if (conn->keepalives_idle == NULL)
    1846         446 :         return 1;
    1847             : 
    1848           0 :     if (!parse_int_param(conn->keepalives_idle, &idle, conn,
    1849             :                          "keepalives_idle"))
    1850           0 :         return 0;
    1851           0 :     if (idle < 0)
    1852           0 :         idle = 0;
    1853             : 
    1854             : #ifdef PG_TCP_KEEPALIVE_IDLE
    1855           0 :     if (setsockopt(conn->sock, IPPROTO_TCP, PG_TCP_KEEPALIVE_IDLE,
    1856             :                    (char *) &idle, sizeof(idle)) < 0)
    1857             :     {
    1858             :         char        sebuf[PG_STRERROR_R_BUFLEN];
    1859             : 
    1860           0 :         appendPQExpBuffer(&conn->errorMessage,
    1861           0 :                           libpq_gettext("%s(%s) failed: %s\n"),
    1862             :                           "setsockopt",
    1863             :                           PG_TCP_KEEPALIVE_IDLE_STR,
    1864           0 :                           SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
    1865           0 :         return 0;
    1866             :     }
    1867             : #endif
    1868             : 
    1869           0 :     return 1;
    1870             : }
    1871             : 
    1872             : /*
    1873             :  * Set the keepalive interval.
    1874             :  */
    1875             : static int
    1876         446 : setKeepalivesInterval(PGconn *conn)
    1877             : {
    1878             :     int         interval;
    1879             : 
    1880         446 :     if (conn->keepalives_interval == NULL)
    1881         446 :         return 1;
    1882             : 
    1883           0 :     if (!parse_int_param(conn->keepalives_interval, &interval, conn,
    1884             :                          "keepalives_interval"))
    1885           0 :         return 0;
    1886           0 :     if (interval < 0)
    1887           0 :         interval = 0;
    1888             : 
    1889             : #ifdef TCP_KEEPINTVL
    1890           0 :     if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPINTVL,
    1891             :                    (char *) &interval, sizeof(interval)) < 0)
    1892             :     {
    1893             :         char        sebuf[PG_STRERROR_R_BUFLEN];
    1894             : 
    1895           0 :         appendPQExpBuffer(&conn->errorMessage,
    1896           0 :                           libpq_gettext("%s(%s) failed: %s\n"),
    1897             :                           "setsockopt",
    1898             :                           "TCP_KEEPINTVL",
    1899           0 :                           SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
    1900           0 :         return 0;
    1901             :     }
    1902             : #endif
    1903             : 
    1904           0 :     return 1;
    1905             : }
    1906             : 
    1907             : /*
    1908             :  * Set the count of lost keepalive packets that will trigger a connection
    1909             :  * break.
    1910             :  */
    1911             : static int
    1912         446 : setKeepalivesCount(PGconn *conn)
    1913             : {
    1914             :     int         count;
    1915             : 
    1916         446 :     if (conn->keepalives_count == NULL)
    1917         446 :         return 1;
    1918             : 
    1919           0 :     if (!parse_int_param(conn->keepalives_count, &count, conn,
    1920             :                          "keepalives_count"))
    1921           0 :         return 0;
    1922           0 :     if (count < 0)
    1923           0 :         count = 0;
    1924             : 
    1925             : #ifdef TCP_KEEPCNT
    1926           0 :     if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPCNT,
    1927             :                    (char *) &count, sizeof(count)) < 0)
    1928             :     {
    1929             :         char        sebuf[PG_STRERROR_R_BUFLEN];
    1930             : 
    1931           0 :         appendPQExpBuffer(&conn->errorMessage,
    1932           0 :                           libpq_gettext("%s(%s) failed: %s\n"),
    1933             :                           "setsockopt",
    1934             :                           "TCP_KEEPCNT",
    1935           0 :                           SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
    1936           0 :         return 0;
    1937             :     }
    1938             : #endif
    1939             : 
    1940           0 :     return 1;
    1941             : }
    1942             : #else                           /* WIN32 */
    1943             : #ifdef SIO_KEEPALIVE_VALS
    1944             : /*
    1945             :  * Enable keepalives and set the keepalive values on Win32,
    1946             :  * where they are always set in one batch.
    1947             :  */
    1948             : static int
    1949             : setKeepalivesWin32(PGconn *conn)
    1950             : {
    1951             :     struct tcp_keepalive ka;
    1952             :     DWORD       retsize;
    1953             :     int         idle = 0;
    1954             :     int         interval = 0;
    1955             : 
    1956             :     if (conn->keepalives_idle &&
    1957             :         !parse_int_param(conn->keepalives_idle, &idle, conn,
    1958             :                          "keepalives_idle"))
    1959             :         return 0;
    1960             :     if (idle <= 0)
    1961             :         idle = 2 * 60 * 60;     /* 2 hours = default */
    1962             : 
    1963             :     if (conn->keepalives_interval &&
    1964             :         !parse_int_param(conn->keepalives_interval, &interval, conn,
    1965             :                          "keepalives_interval"))
    1966             :         return 0;
    1967             :     if (interval <= 0)
    1968             :         interval = 1;           /* 1 second = default */
    1969             : 
    1970             :     ka.onoff = 1;
    1971             :     ka.keepalivetime = idle * 1000;
    1972             :     ka.keepaliveinterval = interval * 1000;
    1973             : 
    1974             :     if (WSAIoctl(conn->sock,
    1975             :                  SIO_KEEPALIVE_VALS,
    1976             :                  (LPVOID) &ka,
    1977             :                  sizeof(ka),
    1978             :                  NULL,
    1979             :                  0,
    1980             :                  &retsize,
    1981             :                  NULL,
    1982             :                  NULL)
    1983             :         != 0)
    1984             :     {
    1985             :         appendPQExpBuffer(&conn->errorMessage,
    1986             :                           libpq_gettext("%s(%s) failed: error code %d\n"),
    1987             :                           "WSAIoctl", "SIO_KEEPALIVE_VALS",
    1988             :                           WSAGetLastError());
    1989             :         return 0;
    1990             :     }
    1991             :     return 1;
    1992             : }
    1993             : #endif                          /* SIO_KEEPALIVE_VALS */
    1994             : #endif                          /* WIN32 */
    1995             : 
    1996             : /*
    1997             :  * Set the TCP user timeout.
    1998             :  */
    1999             : static int
    2000         446 : setTCPUserTimeout(PGconn *conn)
    2001             : {
    2002             :     int         timeout;
    2003             : 
    2004         446 :     if (conn->pgtcp_user_timeout == NULL)
    2005         446 :         return 1;
    2006             : 
    2007           0 :     if (!parse_int_param(conn->pgtcp_user_timeout, &timeout, conn,
    2008             :                          "tcp_user_timeout"))
    2009           0 :         return 0;
    2010             : 
    2011           0 :     if (timeout < 0)
    2012           0 :         timeout = 0;
    2013             : 
    2014             : #ifdef TCP_USER_TIMEOUT
    2015           0 :     if (setsockopt(conn->sock, IPPROTO_TCP, TCP_USER_TIMEOUT,
    2016             :                    (char *) &timeout, sizeof(timeout)) < 0)
    2017             :     {
    2018             :         char        sebuf[256];
    2019             : 
    2020           0 :         appendPQExpBuffer(&conn->errorMessage,
    2021           0 :                           libpq_gettext("%s(%s) failed: %s\n"),
    2022             :                           "setsockopt",
    2023             :                           "TCP_USER_TIMEOUT",
    2024           0 :                           SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
    2025           0 :         return 0;
    2026             :     }
    2027             : #endif
    2028             : 
    2029           0 :     return 1;
    2030             : }
    2031             : 
    2032             : /* ----------
    2033             :  * connectDBStart -
    2034             :  *      Begin the process of making a connection to the backend.
    2035             :  *
    2036             :  * Returns 1 if successful, 0 if not.
    2037             :  * ----------
    2038             :  */
    2039             : static int
    2040       12662 : connectDBStart(PGconn *conn)
    2041             : {
    2042       12662 :     if (!conn)
    2043           0 :         return 0;
    2044             : 
    2045       12662 :     if (!conn->options_valid)
    2046           0 :         goto connect_errReturn;
    2047             : 
    2048             :     /*
    2049             :      * Check for bad linking to backend-internal versions of src/common
    2050             :      * functions (see comments in link-canary.c for the reason we need this).
    2051             :      * Nobody but developers should see this message, so we don't bother
    2052             :      * translating it.
    2053             :      */
    2054       12662 :     if (!pg_link_canary_is_frontend())
    2055             :     {
    2056           0 :         appendPQExpBufferStr(&conn->errorMessage,
    2057             :                              "libpq is incorrectly linked to backend functions\n");
    2058           0 :         goto connect_errReturn;
    2059             :     }
    2060             : 
    2061             :     /* Ensure our buffers are empty */
    2062       12662 :     conn->inStart = conn->inCursor = conn->inEnd = 0;
    2063       12662 :     conn->outCount = 0;
    2064             : 
    2065             :     /*
    2066             :      * Set up to try to connect to the first host.  (Setting whichhost = -1 is
    2067             :      * a bit of a cheat, but PQconnectPoll will advance it to 0 before
    2068             :      * anything else looks at it.)
    2069             :      */
    2070       12662 :     conn->whichhost = -1;
    2071       12662 :     conn->try_next_addr = false;
    2072       12662 :     conn->try_next_host = true;
    2073       12662 :     conn->status = CONNECTION_NEEDED;
    2074             : 
    2075             :     /* Also reset the target_server_type state if needed */
    2076       12662 :     if (conn->target_server_type == SERVER_TYPE_PREFER_STANDBY_PASS2)
    2077           0 :         conn->target_server_type = SERVER_TYPE_PREFER_STANDBY;
    2078             : 
    2079             :     /*
    2080             :      * The code for processing CONNECTION_NEEDED state is in PQconnectPoll(),
    2081             :      * so that it can easily be re-executed if needed again during the
    2082             :      * asynchronous startup process.  However, we must run it once here,
    2083             :      * because callers expect a success return from this routine to mean that
    2084             :      * we are in PGRES_POLLING_WRITING connection state.
    2085             :      */
    2086       12662 :     if (PQconnectPoll(conn) == PGRES_POLLING_WRITING)
    2087       12308 :         return 1;
    2088             : 
    2089         354 : connect_errReturn:
    2090             : 
    2091             :     /*
    2092             :      * If we managed to open a socket, close it immediately rather than
    2093             :      * waiting till PQfinish.  (The application cannot have gotten the socket
    2094             :      * from PQsocket yet, so this doesn't risk breaking anything.)
    2095             :      */
    2096         354 :     pqDropConnection(conn, true);
    2097         354 :     conn->status = CONNECTION_BAD;
    2098         354 :     return 0;
    2099             : }
    2100             : 
    2101             : 
    2102             : /*
    2103             :  *      connectDBComplete
    2104             :  *
    2105             :  * Block and complete a connection.
    2106             :  *
    2107             :  * Returns 1 on success, 0 on failure.
    2108             :  */
    2109             : static int
    2110       11696 : connectDBComplete(PGconn *conn)
    2111             : {
    2112       11696 :     PostgresPollingStatusType flag = PGRES_POLLING_WRITING;
    2113       11696 :     time_t      finish_time = ((time_t) -1);
    2114       11696 :     int         timeout = 0;
    2115       11696 :     int         last_whichhost = -2;    /* certainly different from whichhost */
    2116       11696 :     struct addrinfo *last_addr_cur = NULL;
    2117             : 
    2118       11696 :     if (conn == NULL || conn->status == CONNECTION_BAD)
    2119           0 :         return 0;
    2120             : 
    2121             :     /*
    2122             :      * Set up a time limit, if connect_timeout isn't zero.
    2123             :      */
    2124       11696 :     if (conn->connect_timeout != NULL)
    2125             :     {
    2126           8 :         if (!parse_int_param(conn->connect_timeout, &timeout, conn,
    2127             :                              "connect_timeout"))
    2128             :         {
    2129             :             /* mark the connection as bad to report the parsing failure */
    2130           0 :             conn->status = CONNECTION_BAD;
    2131           0 :             return 0;
    2132             :         }
    2133             : 
    2134           8 :         if (timeout > 0)
    2135             :         {
    2136             :             /*
    2137             :              * Rounding could cause connection to fail unexpectedly quickly;
    2138             :              * to prevent possibly waiting hardly-at-all, insist on at least
    2139             :              * two seconds.
    2140             :              */
    2141           8 :             if (timeout < 2)
    2142           0 :                 timeout = 2;
    2143             :         }
    2144             :         else                    /* negative means 0 */
    2145           0 :             timeout = 0;
    2146             :     }
    2147             : 
    2148             :     for (;;)
    2149       25240 :     {
    2150       36936 :         int         ret = 0;
    2151             : 
    2152             :         /*
    2153             :          * (Re)start the connect_timeout timer if it's active and we are
    2154             :          * considering a different host than we were last time through.  If
    2155             :          * we've already succeeded, though, needn't recalculate.
    2156             :          */
    2157       36936 :         if (flag != PGRES_POLLING_OK &&
    2158       25400 :             timeout > 0 &&
    2159          28 :             (conn->whichhost != last_whichhost ||
    2160          20 :              conn->addr_cur != last_addr_cur))
    2161             :         {
    2162           8 :             finish_time = time(NULL) + timeout;
    2163           8 :             last_whichhost = conn->whichhost;
    2164           8 :             last_addr_cur = conn->addr_cur;
    2165             :         }
    2166             : 
    2167             :         /*
    2168             :          * Wait, if necessary.  Note that the initial state (just after
    2169             :          * PQconnectStart) is to wait for the socket to select for writing.
    2170             :          */
    2171       36936 :         switch (flag)
    2172             :         {
    2173       11536 :             case PGRES_POLLING_OK:
    2174       11536 :                 return 1;       /* success! */
    2175             : 
    2176       12686 :             case PGRES_POLLING_READING:
    2177       12686 :                 ret = pqWaitTimed(1, 0, conn, finish_time);
    2178       12686 :                 if (ret == -1)
    2179             :                 {
    2180             :                     /* hard failure, eg select() problem, aborts everything */
    2181           0 :                     conn->status = CONNECTION_BAD;
    2182           0 :                     return 0;
    2183             :                 }
    2184       12686 :                 break;
    2185             : 
    2186       12554 :             case PGRES_POLLING_WRITING:
    2187       12554 :                 ret = pqWaitTimed(0, 1, conn, finish_time);
    2188       12554 :                 if (ret == -1)
    2189             :                 {
    2190             :                     /* hard failure, eg select() problem, aborts everything */
    2191           0 :                     conn->status = CONNECTION_BAD;
    2192           0 :                     return 0;
    2193             :                 }
    2194       12554 :                 break;
    2195             : 
    2196         160 :             default:
    2197             :                 /* Just in case we failed to set it in PQconnectPoll */
    2198         160 :                 conn->status = CONNECTION_BAD;
    2199         160 :                 return 0;
    2200             :         }
    2201             : 
    2202       25240 :         if (ret == 1)           /* connect_timeout elapsed */
    2203             :         {
    2204             :             /*
    2205             :              * Give up on current server/address, try the next one.
    2206             :              */
    2207           0 :             conn->try_next_addr = true;
    2208           0 :             conn->status = CONNECTION_NEEDED;
    2209             :         }
    2210             : 
    2211             :         /*
    2212             :          * Now try to advance the state machine.
    2213             :          */
    2214       25240 :         flag = PQconnectPoll(conn);
    2215             :     }
    2216             : }
    2217             : 
    2218             : /* ----------------
    2219             :  *      PQconnectPoll
    2220             :  *
    2221             :  * Poll an asynchronous connection.
    2222             :  *
    2223             :  * Returns a PostgresPollingStatusType.
    2224             :  * Before calling this function, use select(2) to determine when data
    2225             :  * has arrived..
    2226             :  *
    2227             :  * You must call PQfinish whether or not this fails.
    2228             :  *
    2229             :  * This function and PQconnectStart are intended to allow connections to be
    2230             :  * made without blocking the execution of your program on remote I/O. However,
    2231             :  * there are a number of caveats:
    2232             :  *
    2233             :  *   o  If you call PQtrace, ensure that the stream object into which you trace
    2234             :  *      will not block.
    2235             :  *   o  If you do not supply an IP address for the remote host (i.e. you
    2236             :  *      supply a host name instead) then PQconnectStart will block on
    2237             :  *      gethostbyname.  You will be fine if using Unix sockets (i.e. by
    2238             :  *      supplying neither a host name nor a host address).
    2239             :  *   o  If your backend wants to use Kerberos authentication then you must
    2240             :  *      supply both a host name and a host address, otherwise this function
    2241             :  *      may block on gethostname.
    2242             :  *
    2243             :  * ----------------
    2244             :  */
    2245             : PostgresPollingStatusType
    2246       39126 : PQconnectPoll(PGconn *conn)
    2247             : {
    2248       39126 :     bool        reset_connection_state_machine = false;
    2249       39126 :     bool        need_new_connection = false;
    2250             :     PGresult   *res;
    2251             :     char        sebuf[PG_STRERROR_R_BUFLEN];
    2252             :     int         optval;
    2253             : 
    2254       39126 :     if (conn == NULL)
    2255           0 :         return PGRES_POLLING_FAILED;
    2256             : 
    2257             :     /* Get the new data */
    2258       39126 :     switch (conn->status)
    2259             :     {
    2260             :             /*
    2261             :              * We really shouldn't have been polled in these two cases, but we
    2262             :              * can handle it.
    2263             :              */
    2264           0 :         case CONNECTION_BAD:
    2265           0 :             return PGRES_POLLING_FAILED;
    2266           0 :         case CONNECTION_OK:
    2267           0 :             return PGRES_POLLING_OK;
    2268             : 
    2269             :             /* These are reading states */
    2270       12576 :         case CONNECTION_AWAITING_RESPONSE:
    2271             :         case CONNECTION_AUTH_OK:
    2272             :         case CONNECTION_CHECK_WRITABLE:
    2273             :         case CONNECTION_CONSUME:
    2274             :         case CONNECTION_CHECK_STANDBY:
    2275             :             {
    2276             :                 /* Load waiting data */
    2277       12576 :                 int         n = pqReadData(conn);
    2278             : 
    2279       12576 :                 if (n < 0)
    2280           8 :                     goto error_return;
    2281       12568 :                 if (n == 0)
    2282         156 :                     return PGRES_POLLING_READING;
    2283             : 
    2284       12412 :                 break;
    2285             :             }
    2286             : 
    2287             :             /* These are writing states, so we just proceed. */
    2288       13166 :         case CONNECTION_STARTED:
    2289             :         case CONNECTION_MADE:
    2290       13166 :             break;
    2291             : 
    2292             :             /* Special cases: proceed without waiting. */
    2293       13384 :         case CONNECTION_SSL_STARTUP:
    2294             :         case CONNECTION_NEEDED:
    2295             :         case CONNECTION_GSS_STARTUP:
    2296             :         case CONNECTION_CHECK_TARGET:
    2297       13384 :             break;
    2298             : 
    2299           0 :         default:
    2300           0 :             appendPQExpBufferStr(&conn->errorMessage,
    2301           0 :                                  libpq_gettext("invalid connection state, probably indicative of memory corruption\n"));
    2302           0 :             goto error_return;
    2303             :     }
    2304             : 
    2305             : 
    2306       38962 : keep_going:                     /* We will come back to here until there is
    2307             :                                  * nothing left to do. */
    2308             : 
    2309             :     /* Time to advance to next address, or next host if no more addresses? */
    2310       75796 :     if (conn->try_next_addr)
    2311             :     {
    2312         364 :         if (conn->addr_cur && conn->addr_cur->ai_next)
    2313             :         {
    2314           4 :             conn->addr_cur = conn->addr_cur->ai_next;
    2315           4 :             reset_connection_state_machine = true;
    2316             :         }
    2317             :         else
    2318         360 :             conn->try_next_host = true;
    2319         364 :         conn->try_next_addr = false;
    2320             :     }
    2321             : 
    2322             :     /* Time to advance to next connhost[] entry? */
    2323       75796 :     if (conn->try_next_host)
    2324             :     {
    2325             :         pg_conn_host *ch;
    2326             :         struct addrinfo hint;
    2327             :         int         thisport;
    2328             :         int         ret;
    2329             :         char        portstr[MAXPGPATH];
    2330             : 
    2331       13088 :         if (conn->whichhost + 1 < conn->nconnhost)
    2332       12682 :             conn->whichhost++;
    2333             :         else
    2334             :         {
    2335             :             /*
    2336             :              * Oops, no more hosts.
    2337             :              *
    2338             :              * If we are trying to connect in "prefer-standby" mode, then drop
    2339             :              * the standby requirement and start over.
    2340             :              *
    2341             :              * Otherwise, an appropriate error message is already set up, so
    2342             :              * we just need to set the right status.
    2343             :              */
    2344         406 :             if (conn->target_server_type == SERVER_TYPE_PREFER_STANDBY &&
    2345           2 :                 conn->nconnhost > 0)
    2346             :             {
    2347           2 :                 conn->target_server_type = SERVER_TYPE_PREFER_STANDBY_PASS2;
    2348           2 :                 conn->whichhost = 0;
    2349             :             }
    2350             :             else
    2351         404 :                 goto error_return;
    2352             :         }
    2353             : 
    2354             :         /* Drop any address info for previous host */
    2355       12684 :         release_conn_addrinfo(conn);
    2356             : 
    2357             :         /*
    2358             :          * Look up info for the new host.  On failure, log the problem in
    2359             :          * conn->errorMessage, then loop around to try the next host.  (Note
    2360             :          * we don't clear try_next_host until we've succeeded.)
    2361             :          */
    2362       12684 :         ch = &conn->connhost[conn->whichhost];
    2363             : 
    2364             :         /* Initialize hint structure */
    2365       88788 :         MemSet(&hint, 0, sizeof(hint));
    2366       12684 :         hint.ai_socktype = SOCK_STREAM;
    2367       12684 :         conn->addrlist_family = hint.ai_family = AF_UNSPEC;
    2368             : 
    2369             :         /* Figure out the port number we're going to use. */
    2370       12684 :         if (ch->port == NULL || ch->port[0] == '\0')
    2371           0 :             thisport = DEF_PGPORT;
    2372             :         else
    2373             :         {
    2374       12684 :             if (!parse_int_param(ch->port, &thisport, conn, "port"))
    2375           0 :                 goto error_return;
    2376             : 
    2377       12684 :             if (thisport < 1 || thisport > 65535)
    2378             :             {
    2379           0 :                 appendPQExpBuffer(&conn->errorMessage,
    2380           0 :                                   libpq_gettext("invalid port number: \"%s\"\n"),
    2381             :                                   ch->port);
    2382           0 :                 goto keep_going;
    2383             :             }
    2384             :         }
    2385       12684 :         snprintf(portstr, sizeof(portstr), "%d", thisport);
    2386             : 
    2387             :         /* Use pg_getaddrinfo_all() to resolve the address */
    2388       12684 :         switch (ch->type)
    2389             :         {
    2390         288 :             case CHT_HOST_NAME:
    2391         288 :                 ret = pg_getaddrinfo_all(ch->host, portstr, &hint,
    2392             :                                          &conn->addrlist);
    2393         288 :                 if (ret || !conn->addrlist)
    2394             :                 {
    2395           0 :                     appendPQExpBuffer(&conn->errorMessage,
    2396           0 :                                       libpq_gettext("could not translate host name \"%s\" to address: %s\n"),
    2397             :                                       ch->host, gai_strerror(ret));
    2398           0 :                     goto keep_going;
    2399             :                 }
    2400         288 :                 break;
    2401             : 
    2402         154 :             case CHT_HOST_ADDRESS:
    2403         154 :                 hint.ai_flags = AI_NUMERICHOST;
    2404         154 :                 ret = pg_getaddrinfo_all(ch->hostaddr, portstr, &hint,
    2405             :                                          &conn->addrlist);
    2406         154 :                 if (ret || !conn->addrlist)
    2407             :                 {
    2408           0 :                     appendPQExpBuffer(&conn->errorMessage,
    2409           0 :                                       libpq_gettext("could not parse network address \"%s\": %s\n"),
    2410             :                                       ch->hostaddr, gai_strerror(ret));
    2411           0 :                     goto keep_going;
    2412             :                 }
    2413         154 :                 break;
    2414             : 
    2415       12242 :             case CHT_UNIX_SOCKET:
    2416             : #ifdef HAVE_UNIX_SOCKETS
    2417       12242 :                 conn->addrlist_family = hint.ai_family = AF_UNIX;
    2418       12242 :                 UNIXSOCK_PATH(portstr, thisport, ch->host);
    2419       12242 :                 if (strlen(portstr) >= UNIXSOCK_PATH_BUFLEN)
    2420             :                 {
    2421           0 :                     appendPQExpBuffer(&conn->errorMessage,
    2422           0 :                                       libpq_gettext("Unix-domain socket path \"%s\" is too long (maximum %d bytes)\n"),
    2423             :                                       portstr,
    2424             :                                       (int) (UNIXSOCK_PATH_BUFLEN - 1));
    2425           0 :                     goto keep_going;
    2426             :                 }
    2427             : 
    2428             :                 /*
    2429             :                  * NULL hostname tells pg_getaddrinfo_all to parse the service
    2430             :                  * name as a Unix-domain socket path.
    2431             :                  */
    2432       12242 :                 ret = pg_getaddrinfo_all(NULL, portstr, &hint,
    2433             :                                          &conn->addrlist);
    2434       12242 :                 if (ret || !conn->addrlist)
    2435             :                 {
    2436           0 :                     appendPQExpBuffer(&conn->errorMessage,
    2437           0 :                                       libpq_gettext("could not translate Unix-domain socket path \"%s\" to address: %s\n"),
    2438             :                                       portstr, gai_strerror(ret));
    2439           0 :                     goto keep_going;
    2440             :                 }
    2441             : #else
    2442             :                 Assert(false);
    2443             : #endif
    2444       12242 :                 break;
    2445             :         }
    2446             : 
    2447             :         /* OK, scan this addrlist for a working server address */
    2448       12684 :         conn->addr_cur = conn->addrlist;
    2449       12684 :         reset_connection_state_machine = true;
    2450       12684 :         conn->try_next_host = false;
    2451             :     }
    2452             : 
    2453             :     /* Reset connection state machine? */
    2454       75392 :     if (reset_connection_state_machine)
    2455             :     {
    2456             :         /*
    2457             :          * (Re) initialize our connection control variables for a set of
    2458             :          * connection attempts to a single server address.  These variables
    2459             :          * must persist across individual connection attempts, but we must
    2460             :          * reset them when we start to consider a new server.
    2461             :          */
    2462       12688 :         conn->pversion = PG_PROTOCOL(3, 0);
    2463       12688 :         conn->send_appname = true;
    2464             : #ifdef USE_SSL
    2465             :         /* initialize these values based on SSL mode */
    2466       12688 :         conn->allow_ssl_try = (conn->sslmode[0] != 'd');  /* "disable" */
    2467       12688 :         conn->wait_ssl_try = (conn->sslmode[0] == 'a'); /* "allow" */
    2468             : #endif
    2469             : #ifdef ENABLE_GSS
    2470             :         conn->try_gss = (conn->gssencmode[0] != 'd'); /* "disable" */
    2471             : #endif
    2472             : 
    2473       12688 :         reset_connection_state_machine = false;
    2474       12688 :         need_new_connection = true;
    2475             :     }
    2476             : 
    2477             :     /* Force a new connection (perhaps to the same server as before)? */
    2478       75392 :     if (need_new_connection)
    2479             :     {
    2480             :         /* Drop any existing connection */
    2481       12688 :         pqDropConnection(conn, true);
    2482             : 
    2483             :         /* Reset all state obtained from old server */
    2484       12688 :         pqDropServerData(conn);
    2485             : 
    2486             :         /* Drop any PGresult we might have, too */
    2487       12688 :         conn->asyncStatus = PGASYNC_IDLE;
    2488       12688 :         conn->xactStatus = PQTRANS_IDLE;
    2489       12688 :         conn->pipelineStatus = PQ_PIPELINE_OFF;
    2490       12688 :         pqClearAsyncResult(conn);
    2491             : 
    2492             :         /* Reset conn->status to put the state machine in the right state */
    2493       12688 :         conn->status = CONNECTION_NEEDED;
    2494             : 
    2495       12688 :         need_new_connection = false;
    2496             :     }
    2497             : 
    2498             :     /* Now try to advance the state machine for this connection */
    2499       75392 :     switch (conn->status)
    2500             :     {
    2501       12688 :         case CONNECTION_NEEDED:
    2502             :             {
    2503             :                 /*
    2504             :                  * Try to initiate a connection to one of the addresses
    2505             :                  * returned by pg_getaddrinfo_all().  conn->addr_cur is the
    2506             :                  * next one to try.
    2507             :                  *
    2508             :                  * The extra level of braces here is historical.  It's not
    2509             :                  * worth reindenting this whole switch case to remove 'em.
    2510             :                  */
    2511             :                 {
    2512       12688 :                     struct addrinfo *addr_cur = conn->addr_cur;
    2513             :                     char        host_addr[NI_MAXHOST];
    2514             : 
    2515             :                     /*
    2516             :                      * Advance to next possible host, if we've tried all of
    2517             :                      * the addresses for the current host.
    2518             :                      */
    2519       12688 :                     if (addr_cur == NULL)
    2520             :                     {
    2521           0 :                         conn->try_next_host = true;
    2522       12242 :                         goto keep_going;
    2523             :                     }
    2524             : 
    2525             :                     /* Remember current address for possible use later */
    2526       12688 :                     memcpy(&conn->raddr.addr, addr_cur->ai_addr,
    2527       12688 :                            addr_cur->ai_addrlen);
    2528       12688 :                     conn->raddr.salen = addr_cur->ai_addrlen;
    2529             : 
    2530             :                     /*
    2531             :                      * Set connip, too.  Note we purposely ignore strdup
    2532             :                      * failure; not a big problem if it fails.
    2533             :                      */
    2534       12688 :                     if (conn->connip != NULL)
    2535             :                     {
    2536           4 :                         free(conn->connip);
    2537           4 :                         conn->connip = NULL;
    2538             :                     }
    2539       12688 :                     getHostaddr(conn, host_addr, NI_MAXHOST);
    2540       12688 :                     if (host_addr[0])
    2541         446 :                         conn->connip = strdup(host_addr);
    2542             : 
    2543             :                     /* Try to create the socket */
    2544       12688 :                     conn->sock = socket(addr_cur->ai_family, SOCK_STREAM, 0);
    2545       12688 :                     if (conn->sock == PGINVALID_SOCKET)
    2546             :                     {
    2547           0 :                         int         errorno = SOCK_ERRNO;
    2548             : 
    2549             :                         /*
    2550             :                          * Silently ignore socket() failure if we have more
    2551             :                          * addresses to try; this reduces useless chatter in
    2552             :                          * cases where the address list includes both IPv4 and
    2553             :                          * IPv6 but kernel only accepts one family.
    2554             :                          */
    2555           0 :                         if (addr_cur->ai_next != NULL ||
    2556           0 :                             conn->whichhost + 1 < conn->nconnhost)
    2557             :                         {
    2558           0 :                             conn->try_next_addr = true;
    2559           0 :                             goto keep_going;
    2560             :                         }
    2561           0 :                         emitHostIdentityInfo(conn, host_addr);
    2562           0 :                         appendPQExpBuffer(&conn->errorMessage,
    2563           0 :                                           libpq_gettext("could not create socket: %s\n"),
    2564             :                                           SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)));
    2565           0 :                         goto error_return;
    2566             :                     }
    2567             : 
    2568             :                     /*
    2569             :                      * Once we've identified a target address, all errors
    2570             :                      * except the preceding socket()-failure case should be
    2571             :                      * prefixed with host-identity information.  (If the
    2572             :                      * connection succeeds, the contents of conn->errorMessage
    2573             :                      * won't matter, so this is harmless.)
    2574             :                      */
    2575       12688 :                     emitHostIdentityInfo(conn, host_addr);
    2576             : 
    2577             :                     /*
    2578             :                      * Select socket options: no delay of outgoing data for
    2579             :                      * TCP sockets, nonblock mode, close-on-exec.  Try the
    2580             :                      * next address if any of this fails.
    2581             :                      */
    2582       12688 :                     if (!IS_AF_UNIX(addr_cur->ai_family))
    2583             :                     {
    2584         446 :                         if (!connectNoDelay(conn))
    2585             :                         {
    2586             :                             /* error message already created */
    2587           0 :                             conn->try_next_addr = true;
    2588           0 :                             goto keep_going;
    2589             :                         }
    2590             :                     }
    2591       12688 :                     if (!pg_set_noblock(conn->sock))
    2592             :                     {
    2593           0 :                         appendPQExpBuffer(&conn->errorMessage,
    2594           0 :                                           libpq_gettext("could not set socket to nonblocking mode: %s\n"),
    2595           0 :                                           SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
    2596           0 :                         conn->try_next_addr = true;
    2597           0 :                         goto keep_going;
    2598             :                     }
    2599             : 
    2600             : #ifdef F_SETFD
    2601       12688 :                     if (fcntl(conn->sock, F_SETFD, FD_CLOEXEC) == -1)
    2602             :                     {
    2603           0 :                         appendPQExpBuffer(&conn->errorMessage,
    2604           0 :                                           libpq_gettext("could not set socket to close-on-exec mode: %s\n"),
    2605           0 :                                           SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
    2606           0 :                         conn->try_next_addr = true;
    2607           0 :                         goto keep_going;
    2608             :                     }
    2609             : #endif                          /* F_SETFD */
    2610             : 
    2611       12688 :                     if (!IS_AF_UNIX(addr_cur->ai_family))
    2612             :                     {
    2613             : #ifndef WIN32
    2614         446 :                         int         on = 1;
    2615             : #endif
    2616         446 :                         int         usekeepalives = useKeepalives(conn);
    2617         446 :                         int         err = 0;
    2618             : 
    2619         446 :                         if (usekeepalives < 0)
    2620             :                         {
    2621           0 :                             appendPQExpBufferStr(&conn->errorMessage,
    2622           0 :                                                  libpq_gettext("keepalives parameter must be an integer\n"));
    2623           0 :                             err = 1;
    2624             :                         }
    2625         446 :                         else if (usekeepalives == 0)
    2626             :                         {
    2627             :                             /* Do nothing */
    2628             :                         }
    2629             : #ifndef WIN32
    2630         446 :                         else if (setsockopt(conn->sock,
    2631             :                                             SOL_SOCKET, SO_KEEPALIVE,
    2632             :                                             (char *) &on, sizeof(on)) < 0)
    2633             :                         {
    2634           0 :                             appendPQExpBuffer(&conn->errorMessage,
    2635           0 :                                               libpq_gettext("%s(%s) failed: %s\n"),
    2636             :                                               "setsockopt",
    2637             :                                               "SO_KEEPALIVE",
    2638           0 :                                               SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
    2639           0 :                             err = 1;
    2640             :                         }
    2641         446 :                         else if (!setKeepalivesIdle(conn)
    2642         446 :                                  || !setKeepalivesInterval(conn)
    2643         446 :                                  || !setKeepalivesCount(conn))
    2644           0 :                             err = 1;
    2645             : #else                           /* WIN32 */
    2646             : #ifdef SIO_KEEPALIVE_VALS
    2647             :                         else if (!setKeepalivesWin32(conn))
    2648             :                             err = 1;
    2649             : #endif                          /* SIO_KEEPALIVE_VALS */
    2650             : #endif                          /* WIN32 */
    2651         446 :                         else if (!setTCPUserTimeout(conn))
    2652           0 :                             err = 1;
    2653             : 
    2654         446 :                         if (err)
    2655             :                         {
    2656           0 :                             conn->try_next_addr = true;
    2657           0 :                             goto keep_going;
    2658             :                         }
    2659             :                     }
    2660             : 
    2661             :                     /*----------
    2662             :                      * We have three methods of blocking SIGPIPE during
    2663             :                      * send() calls to this socket:
    2664             :                      *
    2665             :                      *  - setsockopt(sock, SO_NOSIGPIPE)
    2666             :                      *  - send(sock, ..., MSG_NOSIGNAL)
    2667             :                      *  - setting the signal mask to SIG_IGN during send()
    2668             :                      *
    2669             :                      * The third method requires three syscalls per send,
    2670             :                      * so we prefer either of the first two, but they are
    2671             :                      * less portable.  The state is tracked in the following
    2672             :                      * members of PGconn:
    2673             :                      *
    2674             :                      * conn->sigpipe_so      - we have set up SO_NOSIGPIPE
    2675             :                      * conn->sigpipe_flag    - we're specifying MSG_NOSIGNAL
    2676             :                      *
    2677             :                      * If we can use SO_NOSIGPIPE, then set sigpipe_so here
    2678             :                      * and we're done.  Otherwise, set sigpipe_flag so that
    2679             :                      * we will try MSG_NOSIGNAL on sends.  If we get an error
    2680             :                      * with MSG_NOSIGNAL, we'll clear that flag and revert to
    2681             :                      * signal masking.
    2682             :                      *----------
    2683             :                      */
    2684       12688 :                     conn->sigpipe_so = false;
    2685             : #ifdef MSG_NOSIGNAL
    2686       12688 :                     conn->sigpipe_flag = true;
    2687             : #else
    2688             :                     conn->sigpipe_flag = false;
    2689             : #endif                          /* MSG_NOSIGNAL */
    2690             : 
    2691             : #ifdef SO_NOSIGPIPE
    2692             :                     optval = 1;
    2693             :                     if (setsockopt(conn->sock, SOL_SOCKET, SO_NOSIGPIPE,
    2694             :                                    (char *) &optval, sizeof(optval)) == 0)
    2695             :                     {
    2696             :                         conn->sigpipe_so = true;
    2697             :                         conn->sigpipe_flag = false;
    2698             :                     }
    2699             : #endif                          /* SO_NOSIGPIPE */
    2700             : 
    2701             :                     /*
    2702             :                      * Start/make connection.  This should not block, since we
    2703             :                      * are in nonblock mode.  If it does, well, too bad.
    2704             :                      */
    2705       12688 :                     if (connect(conn->sock, addr_cur->ai_addr,
    2706             :                                 addr_cur->ai_addrlen) < 0)
    2707             :                     {
    2708         800 :                         if (SOCK_ERRNO == EINPROGRESS ||
    2709             : #ifdef WIN32
    2710             :                             SOCK_ERRNO == EWOULDBLOCK ||
    2711             : #endif
    2712         354 :                             SOCK_ERRNO == EINTR)
    2713             :                         {
    2714             :                             /*
    2715             :                              * This is fine - we're in non-blocking mode, and
    2716             :                              * the connection is in progress.  Tell caller to
    2717             :                              * wait for write-ready on socket.
    2718             :                              */
    2719         446 :                             conn->status = CONNECTION_STARTED;
    2720         446 :                             return PGRES_POLLING_WRITING;
    2721             :                         }
    2722             :                         /* otherwise, trouble */
    2723             :                     }
    2724             :                     else
    2725             :                     {
    2726             :                         /*
    2727             :                          * Hm, we're connected already --- seems the "nonblock
    2728             :                          * connection" wasn't.  Advance the state machine and
    2729             :                          * go do the next stuff.
    2730             :                          */
    2731       11888 :                         conn->status = CONNECTION_STARTED;
    2732       11888 :                         goto keep_going;
    2733             :                     }
    2734             : 
    2735             :                     /*
    2736             :                      * This connection failed.  Add the error report to
    2737             :                      * conn->errorMessage, then try the next address if any.
    2738             :                      */
    2739         354 :                     connectFailureMessage(conn, SOCK_ERRNO);
    2740         354 :                     conn->try_next_addr = true;
    2741         354 :                     goto keep_going;
    2742             :                 }
    2743             :             }
    2744             : 
    2745       12334 :         case CONNECTION_STARTED:
    2746             :             {
    2747       12334 :                 socklen_t   optlen = sizeof(optval);
    2748             : 
    2749             :                 /*
    2750             :                  * Write ready, since we've made it here, so the connection
    2751             :                  * has been made ... or has failed.
    2752             :                  */
    2753             : 
    2754             :                 /*
    2755             :                  * Now check (using getsockopt) that there is not an error
    2756             :                  * state waiting for us on the socket.
    2757             :                  */
    2758             : 
    2759       12334 :                 if (getsockopt(conn->sock, SOL_SOCKET, SO_ERROR,
    2760             :                                (char *) &optval, &optlen) == -1)
    2761             :                 {
    2762           0 :                     appendPQExpBuffer(&conn->errorMessage,
    2763           0 :                                       libpq_gettext("could not get socket error status: %s\n"),
    2764           0 :                                       SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
    2765           0 :                     goto error_return;
    2766             :                 }
    2767       12334 :                 else if (optval != 0)
    2768             :                 {
    2769             :                     /*
    2770             :                      * When using a nonblocking connect, we will typically see
    2771             :                      * connect failures at this point, so provide a friendly
    2772             :                      * error message.
    2773             :                      */
    2774          10 :                     connectFailureMessage(conn, optval);
    2775             : 
    2776             :                     /*
    2777             :                      * Try the next address if any, just as in the case where
    2778             :                      * connect() returned failure immediately.
    2779             :                      */
    2780          10 :                     conn->try_next_addr = true;
    2781          10 :                     goto keep_going;
    2782             :                 }
    2783             : 
    2784             :                 /* Fill in the client address */
    2785       12324 :                 conn->laddr.salen = sizeof(conn->laddr.addr);
    2786       12324 :                 if (getsockname(conn->sock,
    2787       12324 :                                 (struct sockaddr *) &conn->laddr.addr,
    2788             :                                 &conn->laddr.salen) < 0)
    2789             :                 {
    2790           0 :                     appendPQExpBuffer(&conn->errorMessage,
    2791           0 :                                       libpq_gettext("could not get client address from socket: %s\n"),
    2792           0 :                                       SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
    2793           0 :                     goto error_return;
    2794             :                 }
    2795             : 
    2796             :                 /*
    2797             :                  * Make sure we can write before advancing to next step.
    2798             :                  */
    2799       12324 :                 conn->status = CONNECTION_MADE;
    2800       12324 :                 return PGRES_POLLING_WRITING;
    2801             :             }
    2802             : 
    2803       12720 :         case CONNECTION_MADE:
    2804             :             {
    2805             :                 char       *startpacket;
    2806             :                 int         packetlen;
    2807             : 
    2808             :                 /*
    2809             :                  * Implement requirepeer check, if requested and it's a
    2810             :                  * Unix-domain socket.
    2811             :                  */
    2812       12720 :                 if (conn->requirepeer && conn->requirepeer[0] &&
    2813           0 :                     IS_AF_UNIX(conn->raddr.addr.ss_family))
    2814             :                 {
    2815             : #ifndef WIN32
    2816             :                     char        pwdbuf[BUFSIZ];
    2817             :                     struct passwd pass_buf;
    2818             :                     struct passwd *pass;
    2819             :                     int         passerr;
    2820             : #endif
    2821             :                     uid_t       uid;
    2822             :                     gid_t       gid;
    2823             : 
    2824           0 :                     errno = 0;
    2825           0 :                     if (getpeereid(conn->sock, &uid, &gid) != 0)
    2826             :                     {
    2827             :                         /*
    2828             :                          * Provide special error message if getpeereid is a
    2829             :                          * stub
    2830             :                          */
    2831           0 :                         if (errno == ENOSYS)
    2832           0 :                             appendPQExpBufferStr(&conn->errorMessage,
    2833           0 :                                                  libpq_gettext("requirepeer parameter is not supported on this platform\n"));
    2834             :                         else
    2835           0 :                             appendPQExpBuffer(&conn->errorMessage,
    2836           0 :                                               libpq_gettext("could not get peer credentials: %s\n"),
    2837           0 :                                               strerror_r(errno, sebuf, sizeof(sebuf)));
    2838           0 :                         goto error_return;
    2839             :                     }
    2840             : 
    2841             : #ifndef WIN32
    2842           0 :                     passerr = pqGetpwuid(uid, &pass_buf, pwdbuf, sizeof(pwdbuf), &pass);
    2843           0 :                     if (pass == NULL)
    2844             :                     {
    2845           0 :                         if (passerr != 0)
    2846           0 :                             appendPQExpBuffer(&conn->errorMessage,
    2847           0 :                                               libpq_gettext("could not look up local user ID %d: %s\n"),
    2848             :                                               (int) uid,
    2849             :                                               strerror_r(passerr, sebuf, sizeof(sebuf)));
    2850             :                         else
    2851           0 :                             appendPQExpBuffer(&conn->errorMessage,
    2852           0 :                                               libpq_gettext("local user with ID %d does not exist\n"),
    2853             :                                               (int) uid);
    2854           0 :                         goto error_return;
    2855             :                     }
    2856             : 
    2857           0 :                     if (strcmp(pass->pw_name, conn->requirepeer) != 0)
    2858             :                     {
    2859           0 :                         appendPQExpBuffer(&conn->errorMessage,
    2860           0 :                                           libpq_gettext("requirepeer specifies \"%s\", but actual peer user name is \"%s\"\n"),
    2861           0 :                                           conn->requirepeer, pass->pw_name);
    2862           0 :                         goto error_return;
    2863             :                     }
    2864             : #else                           /* WIN32 */
    2865             :                     /* should have failed with ENOSYS above */
    2866             :                     Assert(false);
    2867             : #endif                          /* WIN32 */
    2868             :                 }
    2869             : 
    2870       12720 :                 if (IS_AF_UNIX(conn->raddr.addr.ss_family))
    2871             :                 {
    2872             :                     /* Don't request SSL or GSSAPI over Unix sockets */
    2873             : #ifdef USE_SSL
    2874       11888 :                     conn->allow_ssl_try = false;
    2875             : #endif
    2876             : #ifdef ENABLE_GSS
    2877             :                     conn->try_gss = false;
    2878             : #endif
    2879             :                 }
    2880             : 
    2881             : #ifdef ENABLE_GSS
    2882             : 
    2883             :                 /*
    2884             :                  * If GSSAPI encryption is enabled, then call
    2885             :                  * pg_GSS_have_cred_cache() which will return true if we can
    2886             :                  * acquire credentials (and give us a handle to use in
    2887             :                  * conn->gcred), and then send a packet to the server asking
    2888             :                  * for GSSAPI Encryption (and skip past SSL negotiation and
    2889             :                  * regular startup below).
    2890             :                  */
    2891             :                 if (conn->try_gss && !conn->gctx)
    2892             :                     conn->try_gss = pg_GSS_have_cred_cache(&conn->gcred);
    2893             :                 if (conn->try_gss && !conn->gctx)
    2894             :                 {
    2895             :                     ProtocolVersion pv = pg_hton32(NEGOTIATE_GSS_CODE);
    2896             : 
    2897             :                     if (pqPacketSend(conn, 0, &pv, sizeof(pv)) != STATUS_OK)
    2898             :                     {
    2899             :                         appendPQExpBuffer(&conn->errorMessage,
    2900             :                                           libpq_gettext("could not send GSSAPI negotiation packet: %s\n"),
    2901             :                                           SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
    2902             :                         goto error_return;
    2903             :                     }
    2904             : 
    2905             :                     /* Ok, wait for response */
    2906             :                     conn->status = CONNECTION_GSS_STARTUP;
    2907             :                     return PGRES_POLLING_READING;
    2908             :                 }
    2909             :                 else if (!conn->gctx && conn->gssencmode[0] == 'r')
    2910             :                 {
    2911             :                     appendPQExpBufferStr(&conn->errorMessage,
    2912             :                                          libpq_gettext("GSSAPI encryption required but was impossible (possibly no credential cache, no server support, or using a local socket)\n"));
    2913             :                     goto error_return;
    2914             :                 }
    2915             : #endif
    2916             : 
    2917             : #ifdef USE_SSL
    2918             : 
    2919             :                 /*
    2920             :                  * Enable the libcrypto callbacks before checking if SSL needs
    2921             :                  * to be done.  This is done before sending the startup packet
    2922             :                  * as depending on the type of authentication done, like MD5
    2923             :                  * or SCRAM that use cryptohashes, the callbacks would be
    2924             :                  * required even without a SSL connection
    2925             :                  */
    2926       12720 :                 if (pqsecure_initialize(conn, false, true) < 0)
    2927           0 :                     goto error_return;
    2928             : 
    2929             :                 /*
    2930             :                  * If SSL is enabled and we haven't already got encryption of
    2931             :                  * some sort running, request SSL instead of sending the
    2932             :                  * startup message.
    2933             :                  */
    2934       12720 :                 if (conn->allow_ssl_try && !conn->wait_ssl_try &&
    2935         548 :                     !conn->ssl_in_use
    2936             : #ifdef ENABLE_GSS
    2937             :                     && !conn->gssenc
    2938             : #endif
    2939             :                     )
    2940             :                 {
    2941             :                     ProtocolVersion pv;
    2942             : 
    2943             :                     /*
    2944             :                      * Send the SSL request packet.
    2945             :                      *
    2946             :                      * Theoretically, this could block, but it really
    2947             :                      * shouldn't since we only got here if the socket is
    2948             :                      * write-ready.
    2949             :                      */
    2950         434 :                     pv = pg_hton32(NEGOTIATE_SSL_CODE);
    2951         434 :                     if (pqPacketSend(conn, 0, &pv, sizeof(pv)) != STATUS_OK)
    2952             :                     {
    2953           0 :                         appendPQExpBuffer(&conn->errorMessage,
    2954           0 :                                           libpq_gettext("could not send SSL negotiation packet: %s\n"),
    2955           0 :                                           SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
    2956           0 :                         goto error_return;
    2957             :                     }
    2958             :                     /* Ok, wait for response */
    2959         434 :                     conn->status = CONNECTION_SSL_STARTUP;
    2960         434 :                     return PGRES_POLLING_READING;
    2961             :                 }
    2962             : #endif                          /* USE_SSL */
    2963             : 
    2964             :                 /*
    2965             :                  * Build the startup packet.
    2966             :                  */
    2967       12286 :                 startpacket = pqBuildStartupPacket3(conn, &packetlen,
    2968             :                                                     EnvironmentOptions);
    2969       12286 :                 if (!startpacket)
    2970             :                 {
    2971           0 :                     appendPQExpBufferStr(&conn->errorMessage,
    2972           0 :                                          libpq_gettext("out of memory\n"));
    2973           0 :                     goto error_return;
    2974             :                 }
    2975             : 
    2976             :                 /*
    2977             :                  * Send the startup packet.
    2978             :                  *
    2979             :                  * Theoretically, this could block, but it really shouldn't
    2980             :                  * since we only got here if the socket is write-ready.
    2981             :                  */
    2982       12286 :                 if (pqPacketSend(conn, 0, startpacket, packetlen) != STATUS_OK)
    2983             :                 {
    2984           0 :                     appendPQExpBuffer(&conn->errorMessage,
    2985           0 :                                       libpq_gettext("could not send startup packet: %s\n"),
    2986           0 :                                       SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
    2987           0 :                     free(startpacket);
    2988           0 :                     goto error_return;
    2989             :                 }
    2990             : 
    2991       12286 :                 free(startpacket);
    2992             : 
    2993       12286 :                 conn->status = CONNECTION_AWAITING_RESPONSE;
    2994       12286 :                 return PGRES_POLLING_READING;
    2995             :             }
    2996             : 
    2997             :             /*
    2998             :              * Handle SSL negotiation: wait for postmaster messages and
    2999             :              * respond as necessary.
    3000             :              */
    3001         722 :         case CONNECTION_SSL_STARTUP:
    3002             :             {
    3003             : #ifdef USE_SSL
    3004             :                 PostgresPollingStatusType pollres;
    3005             : 
    3006             :                 /*
    3007             :                  * On first time through, get the postmaster's response to our
    3008             :                  * SSL negotiation packet.
    3009             :                  */
    3010         722 :                 if (!conn->ssl_in_use)
    3011             :                 {
    3012             :                     /*
    3013             :                      * We use pqReadData here since it has the logic to
    3014             :                      * distinguish no-data-yet from connection closure. Since
    3015             :                      * conn->ssl isn't set, a plain recv() will occur.
    3016             :                      */
    3017             :                     char        SSLok;
    3018             :                     int         rdresult;
    3019             : 
    3020         434 :                     rdresult = pqReadData(conn);
    3021         434 :                     if (rdresult < 0)
    3022             :                     {
    3023             :                         /* errorMessage is already filled in */
    3024           0 :                         goto error_return;
    3025             :                     }
    3026         434 :                     if (rdresult == 0)
    3027             :                     {
    3028             :                         /* caller failed to wait for data */
    3029         282 :                         return PGRES_POLLING_READING;
    3030             :                     }
    3031         434 :                     if (pqGetc(&SSLok, conn) < 0)
    3032             :                     {
    3033             :                         /* should not happen really */
    3034           0 :                         return PGRES_POLLING_READING;
    3035             :                     }
    3036         434 :                     if (SSLok == 'S')
    3037             :                     {
    3038             :                         /* mark byte consumed */
    3039         152 :                         conn->inStart = conn->inCursor;
    3040             : 
    3041             :                         /*
    3042             :                          * Set up global SSL state if required.  The crypto
    3043             :                          * state has already been set if libpq took care of
    3044             :                          * doing that, so there is no need to make that happen
    3045             :                          * again.
    3046             :                          */
    3047         152 :                         if (pqsecure_initialize(conn, true, false) != 0)
    3048           0 :                             goto error_return;
    3049             :                     }
    3050         282 :                     else if (SSLok == 'N')
    3051             :                     {
    3052             :                         /* mark byte consumed */
    3053         282 :                         conn->inStart = conn->inCursor;
    3054             :                         /* OK to do without SSL? */
    3055         282 :                         if (conn->sslmode[0] == 'r' ||   /* "require" */
    3056         282 :                             conn->sslmode[0] == 'v') /* "verify-ca" or
    3057             :                                                          * "verify-full" */
    3058             :                         {
    3059             :                             /* Require SSL, but server does not want it */
    3060           0 :                             appendPQExpBufferStr(&conn->errorMessage,
    3061           0 :                                                  libpq_gettext("server does not support SSL, but SSL was required\n"));
    3062           0 :                             goto error_return;
    3063             :                         }
    3064             :                         /* Otherwise, proceed with normal startup */
    3065         282 :                         conn->allow_ssl_try = false;
    3066             :                         /* We can proceed using this connection */
    3067         282 :                         conn->status = CONNECTION_MADE;
    3068         282 :                         return PGRES_POLLING_WRITING;
    3069             :                     }
    3070           0 :                     else if (SSLok == 'E')
    3071             :                     {
    3072             :                         /*
    3073             :                          * Server failure of some sort, such as failure to
    3074             :                          * fork a backend process.  We need to process and
    3075             :                          * report the error message, which might be formatted
    3076             :                          * according to either protocol 2 or protocol 3.
    3077             :                          * Rather than duplicate the code for that, we flip
    3078             :                          * into AWAITING_RESPONSE state and let the code there
    3079             :                          * deal with it.  Note we have *not* consumed the "E"
    3080             :                          * byte here.
    3081             :                          */
    3082           0 :                         conn->status = CONNECTION_AWAITING_RESPONSE;
    3083           0 :                         goto keep_going;
    3084             :                     }
    3085             :                     else
    3086             :                     {
    3087           0 :                         appendPQExpBuffer(&conn->errorMessage,
    3088           0 :                                           libpq_gettext("received invalid response to SSL negotiation: %c\n"),
    3089             :                                           SSLok);
    3090           0 :                         goto error_return;
    3091             :                     }
    3092             :                 }
    3093             : 
    3094             :                 /*
    3095             :                  * Begin or continue the SSL negotiation process.
    3096             :                  */
    3097         440 :                 pollres = pqsecure_open_client(conn);
    3098         440 :                 if (pollres == PGRES_POLLING_OK)
    3099             :                 {
    3100             :                     /*
    3101             :                      * At this point we should have no data already buffered.
    3102             :                      * If we do, it was received before we performed the SSL
    3103             :                      * handshake, so it wasn't encrypted and indeed may have
    3104             :                      * been injected by a man-in-the-middle.
    3105             :                      */
    3106         114 :                     if (conn->inCursor != conn->inEnd)
    3107             :                     {
    3108           0 :                         appendPQExpBufferStr(&conn->errorMessage,
    3109           0 :                                              libpq_gettext("received unencrypted data after SSL response\n"));
    3110           0 :                         goto error_return;
    3111             :                     }
    3112             : 
    3113             :                     /* SSL handshake done, ready to send startup packet */
    3114         114 :                     conn->status = CONNECTION_MADE;
    3115         114 :                     return PGRES_POLLING_WRITING;
    3116             :                 }
    3117         326 :                 if (pollres == PGRES_POLLING_FAILED)
    3118             :                 {
    3119             :                     /*
    3120             :                      * Failed ... if sslmode is "prefer" then do a non-SSL
    3121             :                      * retry
    3122             :                      */
    3123          38 :                     if (conn->sslmode[0] == 'p' /* "prefer" */
    3124           0 :                         && conn->allow_ssl_try   /* redundant? */
    3125           0 :                         && !conn->wait_ssl_try) /* redundant? */
    3126             :                     {
    3127             :                         /* only retry once */
    3128           0 :                         conn->allow_ssl_try = false;
    3129           0 :                         need_new_connection = true;
    3130           0 :                         goto keep_going;
    3131             :                     }
    3132             :                     /* Else it's a hard failure */
    3133          38 :                     goto error_return;
    3134             :                 }
    3135             :                 /* Else, return POLLING_READING or POLLING_WRITING status */
    3136         288 :                 return pollres;
    3137             : #else                           /* !USE_SSL */
    3138             :                 /* can't get here */
    3139             :                 goto error_return;
    3140             : #endif                          /* USE_SSL */
    3141             :             }
    3142             : 
    3143           0 :         case CONNECTION_GSS_STARTUP:
    3144             :             {
    3145             : #ifdef ENABLE_GSS
    3146             :                 PostgresPollingStatusType pollres;
    3147             : 
    3148             :                 /*
    3149             :                  * If we haven't yet, get the postmaster's response to our
    3150             :                  * negotiation packet
    3151             :                  */
    3152             :                 if (conn->try_gss && !conn->gctx)
    3153             :                 {
    3154             :                     char        gss_ok;
    3155             :                     int         rdresult = pqReadData(conn);
    3156             : 
    3157             :                     if (rdresult < 0)
    3158             :                         /* pqReadData fills in error message */
    3159             :                         goto error_return;
    3160             :                     else if (rdresult == 0)
    3161             :                         /* caller failed to wait for data */
    3162             :                         return PGRES_POLLING_READING;
    3163             :                     if (pqGetc(&gss_ok, conn) < 0)
    3164             :                         /* shouldn't happen... */
    3165             :                         return PGRES_POLLING_READING;
    3166             : 
    3167             :                     if (gss_ok == 'E')
    3168             :                     {
    3169             :                         /*
    3170             :                          * Server failure of some sort.  Assume it's a
    3171             :                          * protocol version support failure, and let's see if
    3172             :                          * we can't recover (if it's not, we'll get a better
    3173             :                          * error message on retry).  Server gets fussy if we
    3174             :                          * don't hang up the socket, though.
    3175             :                          */
    3176             :                         conn->try_gss = false;
    3177             :                         need_new_connection = true;
    3178             :                         goto keep_going;
    3179             :                     }
    3180             : 
    3181             :                     /* mark byte consumed */
    3182             :                     conn->inStart = conn->inCursor;
    3183             : 
    3184             :                     if (gss_ok == 'N')
    3185             :                     {
    3186             :                         /* Server doesn't want GSSAPI; fall back if we can */
    3187             :                         if (conn->gssencmode[0] == 'r')
    3188             :                         {
    3189             :                             appendPQExpBufferStr(&conn->errorMessage,
    3190             :                                                  libpq_gettext("server doesn't support GSSAPI encryption, but it was required\n"));
    3191             :                             goto error_return;
    3192             :                         }
    3193             : 
    3194             :                         conn->try_gss = false;
    3195             :                         /* We can proceed using this connection */
    3196             :                         conn->status = CONNECTION_MADE;
    3197             :                         return PGRES_POLLING_WRITING;
    3198             :                     }
    3199             :                     else if (gss_ok != 'G')
    3200             :                     {
    3201             :                         appendPQExpBuffer(&conn->errorMessage,
    3202             :                                           libpq_gettext("received invalid response to GSSAPI negotiation: %c\n"),
    3203             :                                           gss_ok);
    3204             :                         goto error_return;
    3205             :                     }
    3206             :                 }
    3207             : 
    3208             :                 /* Begin or continue GSSAPI negotiation */
    3209             :                 pollres = pqsecure_open_gss(conn);
    3210             :                 if (pollres == PGRES_POLLING_OK)
    3211             :                 {
    3212             :                     /*
    3213             :                      * At this point we should have no data already buffered.
    3214             :                      * If we do, it was received before we performed the GSS
    3215             :                      * handshake, so it wasn't encrypted and indeed may have
    3216             :                      * been injected by a man-in-the-middle.
    3217             :                      */
    3218             :                     if (conn->inCursor != conn->inEnd)
    3219             :                     {
    3220             :                         appendPQExpBufferStr(&conn->errorMessage,
    3221             :                                              libpq_gettext("received unencrypted data after GSSAPI encryption response\n"));
    3222             :                         goto error_return;
    3223             :                     }
    3224             : 
    3225             :                     /* All set for startup packet */
    3226             :                     conn->status = CONNECTION_MADE;
    3227             :                     return PGRES_POLLING_WRITING;
    3228             :                 }
    3229             :                 else if (pollres == PGRES_POLLING_FAILED &&
    3230             :                          conn->gssencmode[0] == 'p')
    3231             :                 {
    3232             :                     /*
    3233             :                      * We failed, but we can retry on "prefer".  Have to drop
    3234             :                      * the current connection to do so, though.
    3235             :                      */
    3236             :                     conn->try_gss = false;
    3237             :                     need_new_connection = true;
    3238             :                     goto keep_going;
    3239             :                 }
    3240             :                 return pollres;
    3241             : #else                           /* !ENABLE_GSS */
    3242             :                 /* unreachable */
    3243           0 :                 goto error_return;
    3244             : #endif                          /* ENABLE_GSS */
    3245             :             }
    3246             : 
    3247             :             /*
    3248             :              * Handle authentication exchange: wait for postmaster messages
    3249             :              * and respond as necessary.
    3250             :              */
    3251       12574 :         case CONNECTION_AWAITING_RESPONSE:
    3252             :             {
    3253             :                 char        beresp;
    3254             :                 int         msgLength;
    3255             :                 int         avail;
    3256             :                 AuthRequest areq;
    3257             :                 int         res;
    3258             : 
    3259             :                 /*
    3260             :                  * Scan the message from current point (note that if we find
    3261             :                  * the message is incomplete, we will return without advancing
    3262             :                  * inStart, and resume here next time).
    3263             :                  */
    3264       12574 :                 conn->inCursor = conn->inStart;
    3265             : 
    3266             :                 /* Read type byte */
    3267       12574 :                 if (pqGetc(&beresp, conn))
    3268             :                 {
    3269             :                     /* We'll come back when there is more data */
    3270         134 :                     return PGRES_POLLING_READING;
    3271             :                 }
    3272             : 
    3273             :                 /*
    3274             :                  * Validate message type: we expect only an authentication
    3275             :                  * request or an error here.  Anything else probably means
    3276             :                  * it's not Postgres on the other end at all.
    3277             :                  */
    3278       12440 :                 if (!(beresp == 'R' || beresp == 'E'))
    3279             :                 {
    3280           0 :                     appendPQExpBuffer(&conn->errorMessage,
    3281           0 :                                       libpq_gettext("expected authentication request from server, but received %c\n"),
    3282             :                                       beresp);
    3283          54 :                     goto error_return;
    3284             :                 }
    3285             : 
    3286             :                 /* Read message length word */
    3287       12440 :                 if (pqGetInt(&msgLength, 4, conn))
    3288             :                 {
    3289             :                     /* We'll come back when there is more data */
    3290           0 :                     return PGRES_POLLING_READING;
    3291             :                 }
    3292             : 
    3293             :                 /*
    3294             :                  * Try to validate message length before using it.
    3295             :                  * Authentication requests can't be very large, although GSS
    3296             :                  * auth requests may not be that small.  Errors can be a
    3297             :                  * little larger, but not huge.  If we see a large apparent
    3298             :                  * length in an error, it means we're really talking to a
    3299             :                  * pre-3.0-protocol server; cope.  (Before version 14, the
    3300             :                  * server also used the old protocol for errors that happened
    3301             :                  * before processing the startup packet.)
    3302             :                  */
    3303       12440 :                 if (beresp == 'R' && (msgLength < 8 || msgLength > 2000))
    3304             :                 {
    3305           0 :                     appendPQExpBuffer(&conn->errorMessage,
    3306           0 :                                       libpq_gettext("expected authentication request from server, but received %c\n"),
    3307             :                                       beresp);
    3308           0 :                     goto error_return;
    3309             :                 }
    3310             : 
    3311       12440 :                 if (beresp == 'E' && (msgLength < 8 || msgLength > 30000))
    3312             :                 {
    3313             :                     /* Handle error from a pre-3.0 server */
    3314           0 :                     conn->inCursor = conn->inStart + 1; /* reread data */
    3315           0 :                     if (pqGets_append(&conn->errorMessage, conn))
    3316             :                     {
    3317             :                         /* We'll come back when there is more data */
    3318           0 :                         return PGRES_POLLING_READING;
    3319             :                     }
    3320             :                     /* OK, we read the message; mark data consumed */
    3321           0 :                     conn->inStart = conn->inCursor;
    3322             : 
    3323             :                     /*
    3324             :                      * Before 7.2, the postmaster didn't always end its
    3325             :                      * messages with a newline, so add one if needed to
    3326             :                      * conform to libpq conventions.
    3327             :                      */
    3328           0 :                     if (conn->errorMessage.len == 0 ||
    3329           0 :                         conn->errorMessage.data[conn->errorMessage.len - 1] != '\n')
    3330             :                     {
    3331           0 :                         appendPQExpBufferChar(&conn->errorMessage, '\n');
    3332             :                     }
    3333             : 
    3334           0 :                     goto error_return;
    3335             :                 }
    3336             : 
    3337             :                 /*
    3338             :                  * Can't process if message body isn't all here yet.
    3339             :                  */
    3340       12440 :                 msgLength -= 4;
    3341       12440 :                 avail = conn->inEnd - conn->inCursor;
    3342       12440 :                 if (avail < msgLength)
    3343             :                 {
    3344             :                     /*
    3345             :                      * Before returning, try to enlarge the input buffer if
    3346             :                      * needed to hold the whole message; see notes in
    3347             :                      * pqParseInput3.
    3348             :                      */
    3349           0 :                     if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength,
    3350             :                                              conn))
    3351           0 :                         goto error_return;
    3352             :                     /* We'll come back when there is more data */
    3353           0 :                     return PGRES_POLLING_READING;
    3354             :                 }
    3355             : 
    3356             :                 /* Handle errors. */
    3357       12440 :                 if (beresp == 'E')
    3358             :                 {
    3359          80 :                     if (pqGetErrorNotice3(conn, true))
    3360             :                     {
    3361             :                         /* We'll come back when there is more data */
    3362           0 :                         return PGRES_POLLING_READING;
    3363             :                     }
    3364             :                     /* OK, we read the message; mark data consumed */
    3365          80 :                     conn->inStart = conn->inCursor;
    3366             : 
    3367             :                     /*
    3368             :                      * If error is "cannot connect now", try the next host if
    3369             :                      * any (but we don't want to consider additional addresses
    3370             :                      * for this host, nor is there much point in changing SSL
    3371             :                      * or GSS mode).  This is helpful when dealing with
    3372             :                      * standby servers that might not be in hot-standby state.
    3373             :                      */
    3374          80 :                     if (strcmp(conn->last_sqlstate,
    3375             :                                ERRCODE_CANNOT_CONNECT_NOW) == 0)
    3376             :                     {
    3377          36 :                         conn->try_next_host = true;
    3378       12386 :                         goto keep_going;
    3379             :                     }
    3380             : 
    3381             :                     /* Check to see if we should mention pgpassfile */
    3382          44 :                     pgpassfileWarning(conn);
    3383             : 
    3384             : #ifdef ENABLE_GSS
    3385             : 
    3386             :                     /*
    3387             :                      * If gssencmode is "prefer" and we're using GSSAPI, retry
    3388             :                      * without it.
    3389             :                      */
    3390             :                     if (conn->gssenc && conn->gssencmode[0] == 'p')
    3391             :                     {
    3392             :                         /* only retry once */
    3393             :                         conn->try_gss = false;
    3394             :                         need_new_connection = true;
    3395             :                         goto keep_going;
    3396             :                     }
    3397             : #endif
    3398             : 
    3399             : #ifdef USE_SSL
    3400             : 
    3401             :                     /*
    3402             :                      * if sslmode is "allow" and we haven't tried an SSL
    3403             :                      * connection already, then retry with an SSL connection
    3404             :                      */
    3405          44 :                     if (conn->sslmode[0] == 'a' /* "allow" */
    3406           0 :                         && !conn->ssl_in_use
    3407           0 :                         && conn->allow_ssl_try
    3408           0 :                         && conn->wait_ssl_try)
    3409             :                     {
    3410             :                         /* only retry once */
    3411           0 :                         conn->wait_ssl_try = false;
    3412           0 :                         need_new_connection = true;
    3413           0 :                         goto keep_going;
    3414             :                     }
    3415             : 
    3416             :                     /*
    3417             :                      * if sslmode is "prefer" and we're in an SSL connection,
    3418             :                      * then do a non-SSL retry
    3419             :                      */
    3420          44 :                     if (conn->sslmode[0] == 'p' /* "prefer" */
    3421          36 :                         && conn->ssl_in_use
    3422           0 :                         && conn->allow_ssl_try   /* redundant? */
    3423           0 :                         && !conn->wait_ssl_try) /* redundant? */
    3424             :                     {
    3425             :                         /* only retry once */
    3426           0 :                         conn->allow_ssl_try = false;
    3427           0 :                         need_new_connection = true;
    3428           0 :                         goto keep_going;
    3429             :                     }
    3430             : #endif
    3431             : 
    3432          44 :                     goto error_return;
    3433             :                 }
    3434             : 
    3435             :                 /* It is an authentication request. */
    3436       12360 :                 conn->auth_req_received = true;
    3437             : 
    3438             :                 /* Get the type of request. */
    3439       12360 :                 if (pqGetInt((int *) &areq, 4, conn))
    3440             :                 {
    3441             :                     /* We'll come back when there are more data */
    3442           0 :                     return PGRES_POLLING_READING;
    3443             :                 }
    3444       12360 :                 msgLength -= 4;
    3445             : 
    3446             :                 /*
    3447             :                  * Process the rest of the authentication request message, and
    3448             :                  * respond to it if necessary.
    3449             :                  *
    3450             :                  * Note that conn->pghost must be non-NULL if we are going to
    3451             :                  * avoid the Kerberos code doing a hostname look-up.
    3452             :                  */
    3453       12360 :                 res = pg_fe_sendauth(areq, msgLength, conn);
    3454             : 
    3455             :                 /* OK, we have processed the message; mark data consumed */
    3456       12360 :                 conn->inStart = conn->inCursor;
    3457             : 
    3458       12360 :                 if (res != STATUS_OK)
    3459          10 :                     goto error_return;
    3460             : 
    3461             :                 /*
    3462             :                  * Just make sure that any data sent by pg_fe_sendauth is
    3463             :                  * flushed out.  Although this theoretically could block, it
    3464             :                  * really shouldn't since we don't send large auth responses.
    3465             :                  */
    3466       12350 :                 if (pqFlush(conn))
    3467           0 :                     goto error_return;
    3468             : 
    3469       12350 :                 if (areq == AUTH_REQ_OK)
    3470             :                 {
    3471             :                     /* We are done with authentication exchange */
    3472       12188 :                     conn->status = CONNECTION_AUTH_OK;
    3473             : 
    3474             :                     /*
    3475             :                      * Set asyncStatus so that PQgetResult will think that
    3476             :                      * what comes back next is the result of a query.  See
    3477             :                      * below.
    3478             :                      */
    3479       12188 :                     conn->asyncStatus = PGASYNC_BUSY;
    3480             :                 }
    3481             : 
    3482             :                 /* Look to see if we have more data yet. */
    3483       12350 :                 goto keep_going;
    3484             :             }
    3485             : 
    3486       12188 :         case CONNECTION_AUTH_OK:
    3487             :             {
    3488             :                 /*
    3489             :                  * Now we expect to hear from the backend. A ReadyForQuery
    3490             :                  * message indicates that startup is successful, but we might
    3491             :                  * also get an Error message indicating failure. (Notice
    3492             :                  * messages indicating nonfatal warnings are also allowed by
    3493             :                  * the protocol, as are ParameterStatus and BackendKeyData
    3494             :                  * messages.) Easiest way to handle this is to let
    3495             :                  * PQgetResult() read the messages. We just have to fake it
    3496             :                  * out about the state of the connection, by setting
    3497             :                  * asyncStatus = PGASYNC_BUSY (done above).
    3498             :                  */
    3499             : 
    3500       12188 :                 if (PQisBusy(conn))
    3501           0 :                     return PGRES_POLLING_READING;
    3502             : 
    3503       12188 :                 res = PQgetResult(conn);
    3504             : 
    3505             :                 /*
    3506             :                  * NULL return indicating we have gone to IDLE state is
    3507             :                  * expected
    3508             :                  */
    3509       12188 :                 if (res)
    3510             :                 {
    3511          22 :                     if (res->resultStatus != PGRES_FATAL_ERROR)
    3512           0 :                         appendPQExpBufferStr(&conn->errorMessage,
    3513           0 :                                              libpq_gettext("unexpected message from server during startup\n"));
    3514          22 :                     else if (conn->send_appname &&
    3515          22 :                              (conn->appname || conn->fbappname))
    3516             :                     {
    3517             :                         /*
    3518             :                          * If we tried to send application_name, check to see
    3519             :                          * if the error is about that --- pre-9.0 servers will
    3520             :                          * reject it at this stage of the process.  If so,
    3521             :                          * close the connection and retry without sending
    3522             :                          * application_name.  We could possibly get a false
    3523             :                          * SQLSTATE match here and retry uselessly, but there
    3524             :                          * seems no great harm in that; we'll just get the
    3525             :                          * same error again if it's unrelated.
    3526             :                          */
    3527             :                         const char *sqlstate;
    3528             : 
    3529          22 :                         sqlstate = PQresultErrorField(res, PG_DIAG_SQLSTATE);
    3530          22 :                         if (sqlstate &&
    3531          22 :                             strcmp(sqlstate, ERRCODE_APPNAME_UNKNOWN) == 0)
    3532             :                         {
    3533           0 :                             PQclear(res);
    3534           0 :                             conn->send_appname = false;
    3535           0 :                             need_new_connection = true;
    3536           0 :                             goto keep_going;
    3537             :                         }
    3538             :                     }
    3539             : 
    3540             :                     /*
    3541             :                      * if the resultStatus is FATAL, then conn->errorMessage
    3542             :                      * already has a copy of the error; needn't copy it back.
    3543             :                      * But add a newline if it's not there already, since
    3544             :                      * postmaster error messages may not have one.
    3545             :                      */
    3546          22 :                     if (conn->errorMessage.len <= 0 ||
    3547          22 :                         conn->errorMessage.data[conn->errorMessage.len - 1] != '\n')
    3548           0 :                         appendPQExpBufferChar(&conn->errorMessage, '\n');
    3549          22 :                     PQclear(res);
    3550          22 :                     goto error_return;
    3551             :                 }
    3552             : 
    3553             :                 /* Almost there now ... */
    3554       12166 :                 conn->status = CONNECTION_CHECK_TARGET;
    3555       12166 :                 goto keep_going;
    3556             :             }
    3557             : 
    3558       12166 :         case CONNECTION_CHECK_TARGET:
    3559             :             {
    3560             :                 /*
    3561             :                  * If a read-write, read-only, primary, or standby connection
    3562             :                  * is required, see if we have one.
    3563             :                  */
    3564       12166 :                 if (conn->target_server_type == SERVER_TYPE_READ_WRITE ||
    3565       12156 :                     conn->target_server_type == SERVER_TYPE_READ_ONLY)
    3566           8 :                 {
    3567             :                     bool        read_only_server;
    3568             : 
    3569             :                     /*
    3570             :                      * If the server didn't report
    3571             :                      * "default_transaction_read_only" or "in_hot_standby" at
    3572             :                      * startup, we must determine its state by sending the
    3573             :                      * query "SHOW transaction_read_only".  This GUC exists in
    3574             :                      * all server versions that support 3.0 protocol.
    3575             :                      */
    3576          20 :                     if (conn->default_transaction_read_only == PG_BOOL_UNKNOWN ||
    3577          20 :                         conn->in_hot_standby == PG_BOOL_UNKNOWN)
    3578             :                     {
    3579             :                         /*
    3580             :                          * We use PQsendQueryContinue so that
    3581             :                          * conn->errorMessage does not get cleared.  We need
    3582             :                          * to preserve any error messages related to previous
    3583             :                          * hosts we have tried and failed to connect to.
    3584             :                          */
    3585           0 :                         conn->status = CONNECTION_OK;
    3586           0 :                         if (!PQsendQueryContinue(conn,
    3587             :                                                  "SHOW transaction_read_only"))
    3588           0 :                             goto error_return;
    3589             :                         /* We'll return to this state when we have the answer */
    3590           0 :                         conn->status = CONNECTION_CHECK_WRITABLE;
    3591           0 :                         return PGRES_POLLING_READING;
    3592             :                     }
    3593             : 
    3594             :                     /* OK, we can make the test */
    3595          20 :                     read_only_server =
    3596          40 :                         (conn->default_transaction_read_only == PG_BOOL_YES ||
    3597          20 :                          conn->in_hot_standby == PG_BOOL_YES);
    3598             : 
    3599          20 :                     if ((conn->target_server_type == SERVER_TYPE_READ_WRITE) ?
    3600             :                         read_only_server : !read_only_server)
    3601             :                     {
    3602             :                         /* Wrong server state, reject and try the next host */
    3603          12 :                         if (conn->target_server_type == SERVER_TYPE_READ_WRITE)
    3604           6 :                             appendPQExpBufferStr(&conn->errorMessage,
    3605           6 :                                                  libpq_gettext("session is read-only\n"));
    3606             :                         else
    3607           6 :                             appendPQExpBufferStr(&conn->errorMessage,
    3608           6 :                                                  libpq_gettext("session is not read-only\n"));
    3609             : 
    3610             :                         /* Close connection politely. */
    3611          12 :                         conn->status = CONNECTION_OK;
    3612          12 :                         sendTerminateConn(conn);
    3613             : 
    3614             :                         /*
    3615             :                          * Try next host if any, but we don't want to consider
    3616             :                          * additional addresses for this host.
    3617             :                          */
    3618          12 :                         conn->try_next_host = true;
    3619          12 :                         goto keep_going;
    3620             :                     }
    3621             :                 }
    3622       12146 :                 else if (conn->target_server_type == SERVER_TYPE_PRIMARY ||
    3623       12136 :                          conn->target_server_type == SERVER_TYPE_STANDBY ||
    3624       12126 :                          conn->target_server_type == SERVER_TYPE_PREFER_STANDBY)
    3625             :                 {
    3626             :                     /*
    3627             :                      * If the server didn't report "in_hot_standby" at
    3628             :                      * startup, we must determine its state by sending the
    3629             :                      * query "SELECT pg_catalog.pg_is_in_recovery()".  Servers
    3630             :                      * before 9.0 don't have that function, but by the same
    3631             :                      * token they don't have any standby mode, so we may just
    3632             :                      * assume the result.
    3633             :                      */
    3634          30 :                     if (conn->sversion < 90000)
    3635           0 :                         conn->in_hot_standby = PG_BOOL_NO;
    3636             : 
    3637          30 :                     if (conn->in_hot_standby == PG_BOOL_UNKNOWN)
    3638             :                     {
    3639             :                         /*
    3640             :                          * We use PQsendQueryContinue so that
    3641             :                          * conn->errorMessage does not get cleared.  We need
    3642             :                          * to preserve any error messages related to previous
    3643             :                          * hosts we have tried and failed to connect to.
    3644             :                          */
    3645           0 :                         conn->status = CONNECTION_OK;
    3646           0 :                         if (!PQsendQueryContinue(conn,
    3647             :                                                  "SELECT pg_catalog.pg_is_in_recovery()"))
    3648           0 :                             goto error_return;
    3649             :                         /* We'll return to this state when we have the answer */
    3650           0 :                         conn->status = CONNECTION_CHECK_STANDBY;
    3651           0 :                         return PGRES_POLLING_READING;
    3652             :                     }
    3653             : 
    3654             :                     /* OK, we can make the test */
    3655          60 :                     if ((conn->target_server_type == SERVER_TYPE_PRIMARY) ?
    3656          10 :                         (conn->in_hot_standby == PG_BOOL_YES) :
    3657          20 :                         (conn->in_hot_standby == PG_BOOL_NO))
    3658             :                     {
    3659             :                         /* Wrong server state, reject and try the next host */
    3660          18 :                         if (conn->target_server_type == SERVER_TYPE_PRIMARY)
    3661           6 :                             appendPQExpBufferStr(&conn->errorMessage,
    3662           6 :                                                  libpq_gettext("server is in hot standby mode\n"));
    3663             :                         else
    3664          12 :                             appendPQExpBufferStr(&conn->errorMessage,
    3665          12 :                                                  libpq_gettext("server is not in hot standby mode\n"));
    3666             : 
    3667             :                         /* Close connection politely. */
    3668          18 :                         conn->status = CONNECTION_OK;
    3669          18 :                         sendTerminateConn(conn);
    3670             : 
    3671             :                         /*
    3672             :                          * Try next host if any, but we don't want to consider
    3673             :                          * additional addresses for this host.
    3674             :                          */
    3675          18 :                         conn->try_next_host = true;
    3676          18 :                         goto keep_going;
    3677             :                     }
    3678             :                 }
    3679             : 
    3680             :                 /* We can release the address list now. */
    3681       12136 :                 release_conn_addrinfo(conn);
    3682             : 
    3683             :                 /*
    3684             :                  * Contents of conn->errorMessage are no longer interesting
    3685             :                  * (and it seems some clients expect it to be empty after a
    3686             :                  * successful connection).
    3687             :                  */
    3688       12136 :                 resetPQExpBuffer(&conn->errorMessage);
    3689             : 
    3690             :                 /* We are open for business! */
    3691       12136 :                 conn->status = CONNECTION_OK;
    3692       12136 :                 return PGRES_POLLING_OK;
    3693             :             }
    3694             : 
    3695           0 :         case CONNECTION_CONSUME:
    3696             :             {
    3697             :                 /*
    3698             :                  * This state just makes sure the connection is idle after
    3699             :                  * we've obtained the result of a SHOW or SELECT query.  Once
    3700             :                  * we're clear, return to CONNECTION_CHECK_TARGET state to
    3701             :                  * decide what to do next.  We must transiently set status =
    3702             :                  * CONNECTION_OK in order to use the result-consuming
    3703             :                  * subroutines.
    3704             :                  */
    3705           0 :                 conn->status = CONNECTION_OK;
    3706           0 :                 if (!PQconsumeInput(conn))
    3707           0 :                     goto error_return;
    3708             : 
    3709           0 :                 if (PQisBusy(conn))
    3710             :                 {
    3711           0 :                     conn->status = CONNECTION_CONSUME;
    3712           0 :                     return PGRES_POLLING_READING;
    3713             :                 }
    3714             : 
    3715             :                 /* Call PQgetResult() again until we get a NULL result */
    3716           0 :                 res = PQgetResult(conn);
    3717           0 :                 if (res != NULL)
    3718             :                 {
    3719           0 :                     PQclear(res);
    3720           0 :                     conn->status = CONNECTION_CONSUME;
    3721           0 :                     return PGRES_POLLING_READING;
    3722             :                 }
    3723             : 
    3724           0 :                 conn->status = CONNECTION_CHECK_TARGET;
    3725           0 :                 goto keep_going;
    3726             :             }
    3727             : 
    3728           0 :         case CONNECTION_CHECK_WRITABLE:
    3729             :             {
    3730             :                 /*
    3731             :                  * Waiting for result of "SHOW transaction_read_only".  We
    3732             :                  * must transiently set status = CONNECTION_OK in order to use
    3733             :                  * the result-consuming subroutines.
    3734             :                  */
    3735           0 :                 conn->status = CONNECTION_OK;
    3736           0 :                 if (!PQconsumeInput(conn))
    3737           0 :                     goto error_return;
    3738             : 
    3739           0 :                 if (PQisBusy(conn))
    3740             :                 {
    3741           0 :                     conn->status = CONNECTION_CHECK_WRITABLE;
    3742           0 :                     return PGRES_POLLING_READING;
    3743             :                 }
    3744             : 
    3745           0 :                 res = PQgetResult(conn);
    3746           0 :                 if (res && PQresultStatus(res) == PGRES_TUPLES_OK &&
    3747           0 :                     PQntuples(res) == 1)
    3748             :                 {
    3749           0 :                     char       *val = PQgetvalue(res, 0, 0);
    3750             : 
    3751             :                     /*
    3752             :                      * "transaction_read_only = on" proves that at least one
    3753             :                      * of default_transaction_read_only and in_hot_standby is
    3754             :                      * on, but we don't actually know which.  We don't care
    3755             :                      * though for the purpose of identifying a read-only
    3756             :                      * session, so satisfy the CONNECTION_CHECK_TARGET code by
    3757             :                      * claiming they are both on.  On the other hand, if it's
    3758             :                      * a read-write session, they are certainly both off.
    3759             :                      */
    3760           0 :                     if (strncmp(val, "on", 2) == 0)
    3761             :                     {
    3762           0 :                         conn->default_transaction_read_only = PG_BOOL_YES;
    3763           0 :                         conn->in_hot_standby = PG_BOOL_YES;
    3764             :                     }
    3765             :                     else
    3766             :                     {
    3767           0 :                         conn->default_transaction_read_only = PG_BOOL_NO;
    3768           0 :                         conn->in_hot_standby = PG_BOOL_NO;
    3769             :                     }
    3770           0 :                     PQclear(res);
    3771             : 
    3772             :                     /* Finish reading messages before continuing */
    3773           0 :                     conn->status = CONNECTION_CONSUME;
    3774           0 :                     goto keep_going;
    3775             :                 }
    3776             : 
    3777             :                 /* Something went wrong with "SHOW transaction_read_only". */
    3778           0 :                 if (res)
    3779           0 :                     PQclear(res);
    3780             : 
    3781             :                 /* Append error report to conn->errorMessage. */
    3782           0 :                 appendPQExpBuffer(&conn->errorMessage,
    3783           0 :                                   libpq_gettext("\"%s\" failed\n"),
    3784             :                                   "SHOW transaction_read_only");
    3785             : 
    3786             :                 /* Close connection politely. */
    3787           0 :                 conn->status = CONNECTION_OK;
    3788           0 :                 sendTerminateConn(conn);
    3789             : 
    3790             :                 /* Try next host. */
    3791           0 :                 conn->try_next_host = true;
    3792           0 :                 goto keep_going;
    3793             :             }
    3794             : 
    3795           0 :         case CONNECTION_CHECK_STANDBY:
    3796             :             {
    3797             :                 /*
    3798             :                  * Waiting for result of "SELECT pg_is_in_recovery()".  We
    3799             :                  * must transiently set status = CONNECTION_OK in order to use
    3800             :                  * the result-consuming subroutines.
    3801             :                  */
    3802           0 :                 conn->status = CONNECTION_OK;
    3803           0 :                 if (!PQconsumeInput(conn))
    3804           0 :                     goto error_return;
    3805             : 
    3806           0 :                 if (PQisBusy(conn))
    3807             :                 {
    3808           0 :                     conn->status = CONNECTION_CHECK_STANDBY;
    3809           0 :                     return PGRES_POLLING_READING;
    3810             :                 }
    3811             : 
    3812           0 :                 res = PQgetResult(conn);
    3813           0 :                 if (res && PQresultStatus(res) == PGRES_TUPLES_OK &&
    3814           0 :                     PQntuples(res) == 1)
    3815             :                 {
    3816           0 :                     char       *val = PQgetvalue(res, 0, 0);
    3817             : 
    3818           0 :                     if (strncmp(val, "t", 1) == 0)
    3819           0 :                         conn->in_hot_standby = PG_BOOL_YES;
    3820             :                     else
    3821           0 :                         conn->in_hot_standby = PG_BOOL_NO;
    3822           0 :                     PQclear(res);
    3823             : 
    3824             :                     /* Finish reading messages before continuing */
    3825           0 :                     conn->status = CONNECTION_CONSUME;
    3826           0 :                     goto keep_going;
    3827             :                 }
    3828             : 
    3829             :                 /* Something went wrong with "SELECT pg_is_in_recovery()". */
    3830           0 :                 if (res)
    3831           0 :                     PQclear(res);
    3832             : 
    3833             :                 /* Append error report to conn->errorMessage. */
    3834           0 :                 appendPQExpBuffer(&conn->errorMessage,
    3835           0 :                                   libpq_gettext("\"%s\" failed\n"),
    3836             :                                   "SELECT pg_is_in_recovery()");
    3837             : 
    3838             :                 /* Close connection politely. */
    3839           0 :                 conn->status = CONNECTION_OK;
    3840           0 :                 sendTerminateConn(conn);
    3841             : 
    3842             :                 /* Try next host. */
    3843           0 :                 conn->try_next_host = true;
    3844           0 :                 goto keep_going;
    3845             :             }
    3846             : 
    3847           0 :         default:
    3848           0 :             appendPQExpBuffer(&conn->errorMessage,
    3849           0 :                               libpq_gettext("invalid connection state %d, "
    3850             :                                             "probably indicative of memory corruption\n"),
    3851           0 :                               conn->status);
    3852           0 :             goto error_return;
    3853             :     }
    3854             : 
    3855             :     /* Unreachable */
    3856             : 
    3857         526 : error_return:
    3858             : 
    3859             :     /*
    3860             :      * We used to close the socket at this point, but that makes it awkward
    3861             :      * for those above us if they wish to remove this socket from their own
    3862             :      * records (an fd_set for example).  We'll just have this socket closed
    3863             :      * when PQfinish is called (which is compulsory even after an error, since
    3864             :      * the connection structure must be freed).
    3865             :      */
    3866         526 :     conn->status = CONNECTION_BAD;
    3867         526 :     return PGRES_POLLING_FAILED;
    3868             : }
    3869             : 
    3870             : 
    3871             : /*
    3872             :  * internal_ping
    3873             :  *      Determine if a server is running and if we can connect to it.
    3874             :  *
    3875             :  * The argument is a connection that's been started, but not completed.
    3876             :  */
    3877             : static PGPing
    3878           4 : internal_ping(PGconn *conn)
    3879             : {
    3880             :     /* Say "no attempt" if we never got to PQconnectPoll */
    3881           4 :     if (!conn || !conn->options_valid)
    3882           0 :         return PQPING_NO_ATTEMPT;
    3883             : 
    3884             :     /* Attempt to complete the connection */
    3885           4 :     if (conn->status != CONNECTION_BAD)
    3886           2 :         (void) connectDBComplete(conn);
    3887             : 
    3888             :     /* Definitely OK if we succeeded */
    3889           4 :     if (conn->status != CONNECTION_BAD)
    3890           2 :         return PQPING_OK;
    3891             : 
    3892             :     /*
    3893             :      * Here begins the interesting part of "ping": determine the cause of the
    3894             :      * failure in sufficient detail to decide what to return.  We do not want
    3895             :      * to report that the server is not up just because we didn't have a valid
    3896             :      * password, for example.  In fact, any sort of authentication request
    3897             :      * implies the server is up.  (We need this check since the libpq side of
    3898             :      * things might have pulled the plug on the connection before getting an
    3899             :      * error as such from the postmaster.)
    3900             :      */
    3901           2 :     if (conn->auth_req_received)
    3902           0 :         return PQPING_OK;
    3903             : 
    3904             :     /*
    3905             :      * If we failed to get any ERROR response from the postmaster, report
    3906             :      * PQPING_NO_RESPONSE.  This result could be somewhat misleading for a
    3907             :      * pre-7.4 server, since it won't send back a SQLSTATE, but those are long
    3908             :      * out of support.  Another corner case where the server could return a
    3909             :      * failure without a SQLSTATE is fork failure, but PQPING_NO_RESPONSE
    3910             :      * isn't totally unreasonable for that anyway.  We expect that every other
    3911             :      * failure case in a modern server will produce a report with a SQLSTATE.
    3912             :      *
    3913             :      * NOTE: whenever we get around to making libpq generate SQLSTATEs for
    3914             :      * client-side errors, we should either not store those into
    3915             :      * last_sqlstate, or add an extra flag so we can tell client-side errors
    3916             :      * apart from server-side ones.
    3917             :      */
    3918           2 :     if (strlen(conn->last_sqlstate) != 5)
    3919           2 :         return PQPING_NO_RESPONSE;
    3920             : 
    3921             :     /*
    3922             :      * Report PQPING_REJECT if server says it's not accepting connections. (We
    3923             :      * distinguish this case mainly for the convenience of pg_ctl.)
    3924             :      */
    3925           0 :     if (strcmp(conn->last_sqlstate, ERRCODE_CANNOT_CONNECT_NOW) == 0)
    3926           0 :         return PQPING_REJECT;
    3927             : 
    3928             :     /*
    3929             :      * Any other SQLSTATE can be taken to indicate that the server is up.
    3930             :      * Presumably it didn't like our username, password, or database name; or
    3931             :      * perhaps it had some transient failure, but that should not be taken as
    3932             :      * meaning "it's down".
    3933             :      */
    3934           0 :     return PQPING_OK;
    3935             : }
    3936             : 
    3937             : 
    3938             : /*
    3939             :  * makeEmptyPGconn
    3940             :  *   - create a PGconn data structure with (as yet) no interesting data
    3941             :  */
    3942             : static PGconn *
    3943       12674 : makeEmptyPGconn(void)
    3944             : {
    3945             :     PGconn     *conn;
    3946             : 
    3947             : #ifdef WIN32
    3948             : 
    3949             :     /*
    3950             :      * Make sure socket support is up and running in this process.
    3951             :      *
    3952             :      * Note: the Windows documentation says that we should eventually do a
    3953             :      * matching WSACleanup() call, but experience suggests that that is at
    3954             :      * least as likely to cause problems as fix them.  So we don't.
    3955             :      */
    3956             :     static bool wsastartup_done = false;
    3957             : 
    3958             :     if (!wsastartup_done)
    3959             :     {
    3960             :         WSADATA     wsaData;
    3961             : 
    3962             :         if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    3963             :             return NULL;
    3964             :         wsastartup_done = true;
    3965             :     }
    3966             : 
    3967             :     /* Forget any earlier error */
    3968             :     WSASetLastError(0);
    3969             : #endif                          /* WIN32 */
    3970             : 
    3971       12674 :     conn = (PGconn *) malloc(sizeof(PGconn));
    3972       12674 :     if (conn == NULL)
    3973           0 :         return conn;
    3974             : 
    3975             :     /* Zero all pointers and booleans */
    3976     1609598 :     MemSet(conn, 0, sizeof(PGconn));
    3977             : 
    3978             :     /* install default notice hooks */
    3979       12674 :     conn->noticeHooks.noticeRec = defaultNoticeReceiver;
    3980       12674 :     conn->noticeHooks.noticeProc = defaultNoticeProcessor;
    3981             : 
    3982       12674 :     conn->status = CONNECTION_BAD;
    3983       12674 :     conn->asyncStatus = PGASYNC_IDLE;
    3984       12674 :     conn->pipelineStatus = PQ_PIPELINE_OFF;
    3985       12674 :     conn->xactStatus = PQTRANS_IDLE;
    3986       12674 :     conn->options_valid = false;
    3987       12674 :     conn->nonblocking = false;
    3988       12674 :     conn->client_encoding = PG_SQL_ASCII;
    3989       12674 :     conn->std_strings = false;   /* unless server says differently */
    3990       12674 :     conn->default_transaction_read_only = PG_BOOL_UNKNOWN;
    3991       12674 :     conn->in_hot_standby = PG_BOOL_UNKNOWN;
    3992       12674 :     conn->verbosity = PQERRORS_DEFAULT;
    3993       12674 :     conn->show_context = PQSHOW_CONTEXT_ERRORS;
    3994       12674 :     conn->sock = PGINVALID_SOCKET;
    3995       12674 :     conn->Pfdebug = NULL;
    3996             : 
    3997             :     /*
    3998             :      * We try to send at least 8K at a time, which is the usual size of pipe
    3999             :      * buffers on Unix systems.  That way, when we are sending a large amount
    4000             :      * of data, we avoid incurring extra kernel context swaps for partial
    4001             :      * bufferloads.  The output buffer is initially made 16K in size, and we
    4002             :      * try to dump it after accumulating 8K.
    4003             :      *
    4004             :      * With the same goal of minimizing context swaps, the input buffer will
    4005             :      * be enlarged anytime it has less than 8K free, so we initially allocate
    4006             :      * twice that.
    4007             :      */
    4008       12674 :     conn->inBufSize = 16 * 1024;
    4009       12674 :     conn->inBuffer = (char *) malloc(conn->inBufSize);
    4010       12674 :     conn->outBufSize = 16 * 1024;
    4011       12674 :     conn->outBuffer = (char *) malloc(conn->outBufSize);
    4012       12674 :     conn->rowBufLen = 32;
    4013       12674 :     conn->rowBuf = (PGdataValue *) malloc(conn->rowBufLen * sizeof(PGdataValue));
    4014       12674 :     initPQExpBuffer(&conn->errorMessage);
    4015       12674 :     initPQExpBuffer(&conn->workBuffer);
    4016             : 
    4017       12674 :     if (conn->inBuffer == NULL ||
    4018       12674 :         conn->outBuffer == NULL ||
    4019       12674 :         conn->rowBuf == NULL ||
    4020       12674 :         PQExpBufferBroken(&conn->errorMessage) ||
    4021       12674 :         PQExpBufferBroken(&conn->workBuffer))
    4022             :     {
    4023             :         /* out of memory already :-( */
    4024           0 :         freePGconn(conn);
    4025           0 :         conn = NULL;
    4026             :     }
    4027             : 
    4028       12674 :     return conn;
    4029             : }
    4030             : 
    4031             : /*
    4032             :  * freePGconn
    4033             :  *   - free an idle (closed) PGconn data structure
    4034             :  *
    4035             :  * NOTE: this should not overlap any functionality with closePGconn().
    4036             :  * Clearing/resetting of transient state belongs there; what we do here is
    4037             :  * release data that is to be held for the life of the PGconn structure.
    4038             :  * If a value ought to be cleared/freed during PQreset(), do it there not here.
    4039             :  */
    4040             : static void
    4041       12344 : freePGconn(PGconn *conn)
    4042             : {
    4043             :     int         i;
    4044             : 
    4045             :     /* let any event procs clean up their state data */
    4046       12344 :     for (i = 0; i < conn->nEvents; i++)
    4047             :     {
    4048             :         PGEventConnDestroy evt;
    4049             : 
    4050           0 :         evt.conn = conn;
    4051           0 :         (void) conn->events[i].proc(PGEVT_CONNDESTROY, &evt,
    4052           0 :                                     conn->events[i].passThrough);
    4053           0 :         free(conn->events[i].name);
    4054             :     }
    4055             : 
    4056             :     /* clean up pg_conn_host structures */
    4057       12344 :     if (conn->connhost != NULL)
    4058             :     {
    4059       24714 :         for (i = 0; i < conn->nconnhost; ++i)
    4060             :         {
    4061       12374 :             if (conn->connhost[i].host != NULL)
    4062       12374 :                 free(conn->connhost[i].host);
    4063       12374 :             if (conn->connhost[i].hostaddr != NULL)
    4064         162 :                 free(conn->connhost[i].hostaddr);
    4065       12374 :             if (conn->connhost[i].port != NULL)
    4066       12374 :                 free(conn->connhost[i].port);
    4067       12374 :             if (conn->connhost[i].password != NULL)
    4068             :             {
    4069           4 :                 explicit_bzero(conn->connhost[i].password, strlen(conn->connhost[i].password));
    4070           4 :                 free(conn->connhost[i].password);
    4071             :             }
    4072             :         }
    4073       12340 :         free(conn->connhost);
    4074             :     }
    4075             : 
    4076       12344 :     if (conn->client_encoding_initial)
    4077        1248 :         free(conn->client_encoding_initial);
    4078       12344 :     if (conn->events)
    4079           0 :         free(conn->events);
    4080       12344 :     if (conn->pghost)
    4081       12340 :         free(conn->pghost);
    4082       12344 :     if (conn->pghostaddr)
    4083         162 :         free(conn->pghostaddr);
    4084       12344 :     if (conn->pgport)
    4085       12340 :         free(conn->pgport);
    4086       12344 :     if (conn->connect_timeout)
    4087          10 :         free(conn->connect_timeout);
    4088       12344 :     if (conn->pgtcp_user_timeout)
    4089           0 :         free(conn->pgtcp_user_timeout);
    4090       12344 :     if (conn->pgoptions)
    4091       12340 :         free(conn->pgoptions);
    4092       12344 :     if (conn->appname)
    4093       11612 :         free(conn->appname);
    4094       12344 :     if (conn->fbappname)
    4095       10878 :         free(conn->fbappname);
    4096       12344 :     if (conn->dbName)
    4097       12340 :         free(conn->dbName);
    4098       12344 :     if (conn->replication)
    4099        1148 :         free(conn->replication);
    4100       12344 :     if (conn->pguser)
    4101       12340 :         free(conn->pguser);
    4102       12344 :     if (conn->pgpass)
    4103             :     {
    4104         144 :         explicit_bzero(conn->pgpass, strlen(conn->pgpass));
    4105         144 :         free(conn->pgpass);
    4106             :     }
    4107       12344 :     if (conn->pgpassfile)
    4108       12196 :         free(conn->pgpassfile);
    4109       12344 :     if (conn->channel_binding)
    4110       12340 :         free(conn->channel_binding);
    4111       12344 :     if (conn->keepalives)
    4112           0 :         free(conn->keepalives);
    4113       12344 :     if (conn->keepalives_idle)
    4114           0 :         free(conn->keepalives_idle);
    4115       12344 :     if (conn->keepalives_interval)
    4116           0 :         free(conn->keepalives_interval);
    4117       12344 :     if (conn->keepalives_count)
    4118           0 :         free(conn->keepalives_count);
    4119       12344 :     if (conn->sslmode)
    4120       12340 :         free(conn->sslmode);
    4121       12344 :     if (conn->sslcert)
    4122         158 :         free(conn->sslcert);
    4123       12344 :     if (conn->sslkey)
    4124          62 :         free(conn->sslkey);
    4125       12344 :     if (conn->sslpassword)
    4126             :     {
    4127           6 :         explicit_bzero(conn->sslpassword, strlen(conn->sslpassword));
    4128           6 :         free(conn->sslpassword);
    4129             :     }
    4130       12344 :     if (conn->sslrootcert)
    4131         160 :         free(conn->sslrootcert);
    4132       12344 :     if (conn->sslcrl)
    4133           8 :         free(conn->sslcrl);
    4134       12344 :     if (conn->sslcrldir)
    4135           6 :         free(conn->sslcrldir);
    4136       12344 :     if (conn->sslcompression)
    4137       12340 :         free(conn->sslcompression);
    4138       12344 :     if (conn->sslsni)
    4139       12340 :         free(conn->sslsni);
    4140       12344 :     if (conn->requirepeer)
    4141           0 :         free(conn->requirepeer);
    4142       12344 :     if (conn->ssl_min_protocol_version)
    4143       12340 :         free(conn->ssl_min_protocol_version);
    4144       12344 :     if (conn->ssl_max_protocol_version)
    4145           8 :         free(conn->ssl_max_protocol_version);
    4146       12344 :     if (conn->gssencmode)
    4147       12340 :         free(conn->gssencmode);
    4148       12344 :     if (conn->krbsrvname)
    4149       12340 :         free(conn->krbsrvname);
    4150       12344 :     if (conn->gsslib)
    4151           0 :         free(conn->gsslib);
    4152       12344 :     if (conn->connip)
    4153         430 :         free(conn->connip);
    4154             :     /* Note that conn->Pfdebug is not ours to close or free */
    4155       12344 :     if (conn->write_err_msg)
    4156           0 :         free(conn->write_err_msg);
    4157       12344 :     if (conn->inBuffer)
    4158       12344 :         free(conn->inBuffer);
    4159       12344 :     if (conn->outBuffer)
    4160       12344 :         free(conn->outBuffer);
    4161       12344 :     if (conn->rowBuf)
    4162       12344 :         free(conn->rowBuf);
    4163       12344 :     if (conn->target_session_attrs)
    4164       12340 :         free(conn->target_session_attrs);
    4165       12344 :     termPQExpBuffer(&conn->errorMessage);
    4166       12344 :     termPQExpBuffer(&conn->workBuffer);
    4167             : 
    4168       12344 :     free(conn);
    4169       12344 : }
    4170             : 
    4171             : /*
    4172             :  * release_conn_addrinfo
    4173             :  *   - Free any addrinfo list in the PGconn.
    4174             :  */
    4175             : static void
    4176       37164 : release_conn_addrinfo(PGconn *conn)
    4177             : {
    4178       37164 :     if (conn->addrlist)
    4179             :     {
    4180       12580 :         pg_freeaddrinfo_all(conn->addrlist_family, conn->addrlist);
    4181       12580 :         conn->addrlist = NULL;
    4182       12580 :         conn->addr_cur = NULL;   /* for safety */
    4183             :     }
    4184       37164 : }
    4185             : 
    4186             : /*
    4187             :  * sendTerminateConn
    4188             :  *   - Send a terminate message to backend.
    4189             :  */
    4190             : static void
    4191       12374 : sendTerminateConn(PGconn *conn)
    4192             : {
    4193             :     /*
    4194             :      * Note that the protocol doesn't allow us to send Terminate messages
    4195             :      * during the startup phase.
    4196             :      */
    4197       12374 :     if (conn->sock != PGINVALID_SOCKET && conn->status == CONNECTION_OK)
    4198             :     {
    4199             :         /*
    4200             :          * Try to send "close connection" message to backend. Ignore any
    4201             :          * error.
    4202             :          */
    4203       11832 :         pqPutMsgStart('X', conn);
    4204       11832 :         pqPutMsgEnd(conn);
    4205       11832 :         (void) pqFlush(conn);
    4206             :     }
    4207       12374 : }
    4208             : 
    4209             : /*
    4210             :  * closePGconn
    4211             :  *   - properly close a connection to the backend
    4212             :  *
    4213             :  * This should reset or release all transient state, but NOT the connection
    4214             :  * parameters.  On exit, the PGconn should be in condition to start a fresh
    4215             :  * connection with the same parameters (see PQreset()).
    4216             :  */
    4217             : static void
    4218       12344 : closePGconn(PGconn *conn)
    4219             : {
    4220             :     /*
    4221             :      * If possible, send Terminate message to close the connection politely.
    4222             :      */
    4223       12344 :     sendTerminateConn(conn);
    4224             : 
    4225             :     /*
    4226             :      * Must reset the blocking status so a possible reconnect will work.
    4227             :      *
    4228             :      * Don't call PQsetnonblocking() because it will fail if it's unable to
    4229             :      * flush the connection.
    4230             :      */
    4231       12344 :     conn->nonblocking = false;
    4232             : 
    4233             :     /*
    4234             :      * Close the connection, reset all transient state, flush I/O buffers.
    4235             :      * Note that this includes clearing conn->errorMessage; we're no longer
    4236             :      * interested in any failures associated with the old connection, and we
    4237             :      * want a clean slate for any new connection attempt.
    4238             :      */
    4239       12344 :     pqDropConnection(conn, true);
    4240       12344 :     conn->status = CONNECTION_BAD;   /* Well, not really _bad_ - just absent */
    4241       12344 :     conn->asyncStatus = PGASYNC_IDLE;
    4242       12344 :     conn->xactStatus = PQTRANS_IDLE;
    4243       12344 :     conn->pipelineStatus = PQ_PIPELINE_OFF;
    4244       12344 :     pqClearAsyncResult(conn);   /* deallocate result */
    4245       12344 :     resetPQExpBuffer(&conn->errorMessage);
    4246       12344 :     release_conn_addrinfo(conn);
    4247             : 
    4248             :     /* Reset all state obtained from server, too */
    4249       12344 :     pqDropServerData(conn);
    4250       12344 : }
    4251             : 
    4252             : /*
    4253             :  * PQfinish: properly close a connection to the backend. Also frees
    4254             :  * the PGconn data structure so it shouldn't be re-used after this.
    4255             :  */
    4256             : void
    4257       12344 : PQfinish(PGconn *conn)
    4258             : {
    4259       12344 :     if (conn)
    4260             :     {
    4261       12344 :         closePGconn(conn);
    4262       12344 :         freePGconn(conn);
    4263             :     }
    4264       12344 : }
    4265             : 
    4266             : /*
    4267             :  * PQreset: resets the connection to the backend by closing the
    4268             :  * existing connection and creating a new one.
    4269             :  */
    4270             : void
    4271           0 : PQreset(PGconn *conn)
    4272             : {
    4273           0 :     if (conn)
    4274             :     {
    4275           0 :         closePGconn(conn);
    4276             : 
    4277           0 :         if (connectDBStart(conn) && connectDBComplete(conn))
    4278             :         {
    4279             :             /*
    4280             :              * Notify event procs of successful reset.  We treat an event proc
    4281             :              * failure as disabling the connection ... good idea?
    4282             :              */
    4283             :             int         i;
    4284             : 
    4285           0 :             for (i = 0; i < conn->nEvents; i++)
    4286             :             {
    4287             :                 PGEventConnReset evt;
    4288             : 
    4289           0 :                 evt.conn = conn;
    4290           0 :                 if (!conn->events[i].proc(PGEVT_CONNRESET, &evt,
    4291           0 :                                           conn->events[i].passThrough))
    4292             :                 {
    4293           0 :                     conn->status = CONNECTION_BAD;
    4294           0 :                     appendPQExpBuffer(&conn->errorMessage,
    4295           0 :                                       libpq_gettext("PGEventProc \"%s\" failed during PGEVT_CONNRESET event\n"),
    4296           0 :                                       conn->events[i].name);
    4297           0 :                     break;
    4298             :                 }
    4299             :             }
    4300             :         }
    4301             :     }
    4302           0 : }
    4303             : 
    4304             : 
    4305             : /*
    4306             :  * PQresetStart:
    4307             :  * resets the connection to the backend
    4308             :  * closes the existing connection and makes a new one
    4309             :  * Returns 1 on success, 0 on failure.
    4310             :  */
    4311             : int
    4312           0 : PQresetStart(PGconn *conn)
    4313             : {
    4314           0 :     if (conn)
    4315             :     {
    4316           0 :         closePGconn(conn);
    4317             : 
    4318           0 :         return connectDBStart(conn);
    4319             :     }
    4320             : 
    4321           0 :     return 0;
    4322             : }
    4323             : 
    4324             : 
    4325             : /*
    4326             :  * PQresetPoll:
    4327             :  * resets the connection to the backend
    4328             :  * closes the existing connection and makes a new one
    4329             :  */
    4330             : PostgresPollingStatusType
    4331           0 : PQresetPoll(PGconn *conn)
    4332             : {
    4333           0 :     if (conn)
    4334             :     {
    4335           0 :         PostgresPollingStatusType status = PQconnectPoll(conn);
    4336             : 
    4337           0 :         if (status == PGRES_POLLING_OK)
    4338             :         {
    4339             :             /*
    4340             :              * Notify event procs of successful reset.  We treat an event proc
    4341             :              * failure as disabling the connection ... good idea?
    4342             :              */
    4343             :             int         i;
    4344             : 
    4345           0 :             for (i = 0; i < conn->nEvents; i++)
    4346             :             {
    4347             :                 PGEventConnReset evt;
    4348             : 
    4349           0 :                 evt.conn = conn;
    4350           0 :                 if (!conn->events[i].proc(PGEVT_CONNRESET, &evt,
    4351           0 :                                           conn->events[i].passThrough))
    4352             :                 {
    4353           0 :                     conn->status = CONNECTION_BAD;
    4354           0 :                     appendPQExpBuffer(&conn->errorMessage,
    4355           0 :                                       libpq_gettext("PGEventProc \"%s\" failed during PGEVT_CONNRESET event\n"),
    4356           0 :                                       conn->events[i].name);
    4357           0 :                     return PGRES_POLLING_FAILED;
    4358             :                 }
    4359             :             }
    4360             :         }
    4361             : 
    4362           0 :         return status;
    4363             :     }
    4364             : 
    4365           0 :     return PGRES_POLLING_FAILED;
    4366             : }
    4367             : 
    4368             : /*
    4369             :  * PQgetCancel: get a PGcancel structure corresponding to a connection.
    4370             :  *
    4371             :  * A copy is needed to be able to cancel a running query from a different
    4372             :  * thread. If the same structure is used all structure members would have
    4373             :  * to be individually locked (if the entire structure was locked, it would
    4374             :  * be impossible to cancel a synchronous query because the structure would
    4375             :  * have to stay locked for the duration of the query).
    4376             :  */
    4377             : PGcancel *
    4378      216904 : PQgetCancel(PGconn *conn)
    4379             : {
    4380             :     PGcancel   *cancel;
    4381             : 
    4382      216904 :     if (!conn)
    4383          28 :         return NULL;
    4384             : 
    4385      216876 :     if (conn->sock == PGINVALID_SOCKET)
    4386           0 :         return NULL;
    4387             : 
    4388      216876 :     cancel = malloc(sizeof(PGcancel));
    4389      216876 :     if (cancel == NULL)
    4390           0 :         return NULL;
    4391             : 
    4392      216876 :     memcpy(&cancel->raddr, &conn->raddr, sizeof(SockAddr));
    4393      216876 :     cancel->be_pid = conn->be_pid;
    4394      216876 :     cancel->be_key = conn->be_key;
    4395             : 
    4396      216876 :     return cancel;
    4397             : }
    4398             : 
    4399             : /* PQfreeCancel: free a cancel structure */
    4400             : void
    4401      216876 : PQfreeCancel(PGcancel *cancel)
    4402             : {
    4403      216876 :     if (cancel)
    4404      216876 :         free(cancel);
    4405      216876 : }
    4406             : 
    4407             : 
    4408             : /*
    4409             :  * PQcancel and PQrequestCancel: attempt to request cancellation of the
    4410             :  * current operation.
    4411             :  *
    4412             :  * The return value is true if the cancel request was successfully
    4413             :  * dispatched, false if not (in which case an error message is available).
    4414             :  * Note: successful dispatch is no guarantee that there will be any effect at
    4415             :  * the backend.  The application must read the operation result as usual.
    4416             :  *
    4417             :  * CAUTION: we want this routine to be safely callable from a signal handler
    4418             :  * (for example, an application might want to call it in a SIGINT handler).
    4419             :  * This means we cannot use any C library routine that might be non-reentrant.
    4420             :  * malloc/free are often non-reentrant, and anything that might call them is
    4421             :  * just as dangerous.  We avoid sprintf here for that reason.  Building up
    4422             :  * error messages with strcpy/strcat is tedious but should be quite safe.
    4423             :  * We also save/restore errno in case the signal handler support doesn't.
    4424             :  *
    4425             :  * internal_cancel() is an internal helper function to make code-sharing
    4426             :  * between the two versions of the cancel function possible.
    4427             :  */
    4428             : static int
    4429           4 : internal_cancel(SockAddr *raddr, int be_pid, int be_key,
    4430             :                 char *errbuf, int errbufsize)
    4431             : {
    4432           4 :     int         save_errno = SOCK_ERRNO;
    4433           4 :     pgsocket    tmpsock = PGINVALID_SOCKET;
    4434             :     char        sebuf[PG_STRERROR_R_BUFLEN];
    4435             :     int         maxlen;
    4436             :     struct
    4437             :     {
    4438             :         uint32      packetlen;
    4439             :         CancelRequestPacket cp;
    4440             :     }           crp;
    4441             : 
    4442             :     /*
    4443             :      * We need to open a temporary connection to the postmaster. Do this with
    4444             :      * only kernel calls.
    4445             :      */
    4446           4 :     if ((tmpsock = socket(raddr->addr.ss_family, SOCK_STREAM, 0)) == PGINVALID_SOCKET)
    4447             :     {
    4448           0 :         strlcpy(errbuf, "PQcancel() -- socket() failed: ", errbufsize);
    4449           0 :         goto cancel_errReturn;
    4450             :     }
    4451           4 : retry3:
    4452           4 :     if (connect(tmpsock, (struct sockaddr *) &raddr->addr,
    4453             :                 raddr->salen) < 0)
    4454             :     {
    4455           0 :         if (SOCK_ERRNO == EINTR)
    4456             :             /* Interrupted system call - we'll just try again */
    4457           0 :             goto retry3;
    4458           0 :         strlcpy(errbuf, "PQcancel() -- connect() failed: ", errbufsize);
    4459           0 :         goto cancel_errReturn;
    4460             :     }
    4461             : 
    4462             :     /*
    4463             :      * We needn't set nonblocking I/O or NODELAY options here.
    4464             :      */
    4465             : 
    4466             :     /* Create and send the cancel request packet. */
    4467             : 
    4468           4 :     crp.packetlen = pg_hton32((uint32) sizeof(crp));
    4469           4 :     crp.cp.cancelRequestCode = (MsgType) pg_hton32(CANCEL_REQUEST_CODE);
    4470           4 :     crp.cp.backendPID = pg_hton32(be_pid);
    4471           4 :     crp.cp.cancelAuthCode = pg_hton32(be_key);
    4472             : 
    4473           4 : retry4:
    4474           4 :     if (send(tmpsock, (char *) &crp, sizeof(crp), 0) != (int) sizeof(crp))
    4475             :     {
    4476           0 :         if (SOCK_ERRNO == EINTR)
    4477             :             /* Interrupted system call - we'll just try again */
    4478           0 :             goto retry4;
    4479           0 :         strlcpy(errbuf, "PQcancel() -- send() failed: ", errbufsize);
    4480           0 :         goto cancel_errReturn;
    4481             :     }
    4482             : 
    4483             :     /*
    4484             :      * Wait for the postmaster to close the connection, which indicates that
    4485             :      * it's processed the request.  Without this delay, we might issue another
    4486             :      * command only to find that our cancel zaps that command instead of the
    4487             :      * one we thought we were canceling.  Note we don't actually expect this
    4488             :      * read to obtain any data, we are just waiting for EOF to be signaled.
    4489             :      */
    4490           4 : retry5:
    4491           4 :     if (recv(tmpsock, (char *) &crp, 1, 0) < 0)
    4492             :     {
    4493           0 :         if (SOCK_ERRNO == EINTR)
    4494             :             /* Interrupted system call - we'll just try again */
    4495           0 :             goto retry5;
    4496             :         /* we ignore other error conditions */
    4497             :     }
    4498             : 
    4499             :     /* All done */
    4500           4 :     closesocket(tmpsock);
    4501           4 :     SOCK_ERRNO_SET(save_errno);
    4502           4 :     return true;
    4503             : 
    4504           0 : cancel_errReturn:
    4505             : 
    4506             :     /*
    4507             :      * Make sure we don't overflow the error buffer. Leave space for the \n at
    4508             :      * the end, and for the terminating zero.
    4509             :      */
    4510           0 :     maxlen = errbufsize - strlen(errbuf) - 2;
    4511           0 :     if (maxlen >= 0)
    4512             :     {
    4513           0 :         strncat(errbuf, SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)),
    4514             :                 maxlen);
    4515           0 :         strcat(errbuf, "\n");
    4516             :     }
    4517           0 :     if (tmpsock != PGINVALID_SOCKET)
    4518           0 :         closesocket(tmpsock);
    4519           0 :     SOCK_ERRNO_SET(save_errno);
    4520           0 :     return false;
    4521             : }
    4522             : 
    4523             : /*
    4524             :  * PQcancel: request query cancel
    4525             :  *
    4526             :  * Returns true if able to send the cancel request, false if not.
    4527             :  *
    4528             :  * On failure, an error message is stored in *errbuf, which must be of size
    4529             :  * errbufsize (recommended size is 256 bytes).  *errbuf is not changed on
    4530             :  * success return.
    4531             :  */
    4532             : int
    4533           4 : PQcancel(PGcancel *cancel, char *errbuf, int errbufsize)
    4534             : {
    4535           4 :     if (!cancel)
    4536             :     {
    4537           0 :         strlcpy(errbuf, "PQcancel() -- no cancel object supplied", errbufsize);
    4538           0 :         return false;
    4539             :     }
    4540             : 
    4541           4 :     return internal_cancel(&cancel->raddr, cancel->be_pid, cancel->be_key,
    4542             :                            errbuf, errbufsize);
    4543             : }
    4544             : 
    4545             : /*
    4546             :  * PQrequestCancel: old, not thread-safe function for requesting query cancel
    4547             :  *
    4548             :  * Returns true if able to send the cancel request, false if not.
    4549             :  *
    4550             :  * On failure, the error message is saved in conn->errorMessage; this means
    4551             :  * that this can't be used when there might be other active operations on
    4552             :  * the connection object.
    4553             :  *
    4554             :  * NOTE: error messages will be cut off at the current size of the
    4555             :  * error message buffer, since we dare not try to expand conn->errorMessage!
    4556             :  */
    4557             : int
    4558           0 : PQrequestCancel(PGconn *conn)
    4559             : {
    4560             :     int         r;
    4561             : 
    4562             :     /* Check we have an open connection */
    4563           0 :     if (!conn)
    4564           0 :         return false;
    4565             : 
    4566           0 :     if (conn->sock == PGINVALID_SOCKET)
    4567             :     {
    4568           0 :         strlcpy(conn->errorMessage.data,
    4569             :                 "PQrequestCancel() -- connection is not open\n",
    4570             :                 conn->errorMessage.maxlen);
    4571           0 :         conn->errorMessage.len = strlen(conn->errorMessage.data);
    4572             : 
    4573           0 :         return false;
    4574             :     }
    4575             : 
    4576           0 :     r = internal_cancel(&conn->raddr, conn->be_pid, conn->be_key,
    4577           0 :                         conn->errorMessage.data, conn->errorMessage.maxlen);
    4578             : 
    4579           0 :     if (!r)
    4580           0 :         conn->errorMessage.len = strlen(conn->errorMessage.data);
    4581             : 
    4582           0 :     return r;
    4583             : }
    4584             : 
    4585             : 
    4586             : /*
    4587             :  * pqPacketSend() -- convenience routine to send a message to server.
    4588             :  *
    4589             :  * pack_type: the single-byte message type code.  (Pass zero for startup
    4590             :  * packets, which have no message type code.)
    4591             :  *
    4592             :  * buf, buf_len: contents of message.  The given length includes only what
    4593             :  * is in buf; the message type and message length fields are added here.
    4594             :  *
    4595             :  * RETURNS: STATUS_ERROR if the write fails, STATUS_OK otherwise.
    4596             :  * SIDE_EFFECTS: may block.
    4597             :  */
    4598             : int
    4599       12814 : pqPacketSend(PGconn *conn, char pack_type,
    4600             :              const void *buf, size_t buf_len)
    4601             : {
    4602             :     /* Start the message. */
    4603       12814 :     if (pqPutMsgStart(pack_type, conn))
    4604           0 :         return STATUS_ERROR;
    4605             : 
    4606             :     /* Send the message body. */
    4607       12814 :     if (pqPutnchar(buf, buf_len, conn))
    4608           0 :         return STATUS_ERROR;
    4609             : 
    4610             :     /* Finish the message. */
    4611       12814 :     if (pqPutMsgEnd(conn))
    4612           0 :         return STATUS_ERROR;
    4613             : 
    4614             :     /* Flush to ensure backend gets it. */
    4615       12814 :     if (pqFlush(conn))
    4616           0 :         return STATUS_ERROR;
    4617             : 
    4618       12814 :     return STATUS_OK;
    4619             : }
    4620             : 
    4621             : #ifdef USE_LDAP
    4622             : 
    4623             : #define LDAP_URL    "ldap://"
    4624             : #define LDAP_DEF_PORT   389
    4625             : #define PGLDAP_TIMEOUT 2
    4626             : 
    4627             : #define ld_is_sp_tab(x) ((x) == ' ' || (x) == '\t')
    4628             : #define ld_is_nl_cr(x) ((x) == '\r' || (x) == '\n')
    4629             : 
    4630             : 
    4631             : /*
    4632             :  *      ldapServiceLookup
    4633             :  *
    4634             :  * Search the LDAP URL passed as first argument, treat the result as a
    4635             :  * string of connection options that are parsed and added to the array of
    4636             :  * options passed as second argument.
    4637             :  *
    4638             :  * LDAP URLs must conform to RFC 1959 without escape sequences.
    4639             :  *  ldap://host:port/dn?attributes?scope?filter?extensions
    4640             :  *
    4641             :  * Returns
    4642             :  *  0 if the lookup was successful,
    4643             :  *  1 if the connection to the LDAP server could be established but
    4644             :  *    the search was unsuccessful,
    4645             :  *  2 if a connection could not be established, and
    4646             :  *  3 if a fatal error occurred.
    4647             :  *
    4648             :  * An error message is appended to *errorMessage for return codes 1 and 3.
    4649             :  */
    4650             : static int
    4651           2 : ldapServiceLookup(const char *purl, PQconninfoOption *options,
    4652             :                   PQExpBuffer errorMessage)
    4653             : {
    4654           2 :     int         port = LDAP_DEF_PORT,
    4655             :                 scope,
    4656             :                 rc,
    4657             :                 size,
    4658             :                 state,
    4659             :                 oldstate,
    4660             :                 i;
    4661             : #ifndef WIN32
    4662             :     int         msgid;
    4663             : #endif
    4664             :     bool        found_keyword;
    4665             :     char       *url,
    4666             :                *hostname,
    4667             :                *portstr,
    4668             :                *endptr,
    4669             :                *dn,
    4670             :                *scopestr,
    4671             :                *filter,
    4672             :                *result,
    4673             :                *p,
    4674           2 :                *p1 = NULL,
    4675           2 :                *optname = NULL,
    4676           2 :                *optval = NULL;
    4677           2 :     char       *attrs[2] = {NULL, NULL};
    4678           2 :     LDAP       *ld = NULL;
    4679             :     LDAPMessage *res,
    4680             :                *entry;
    4681             :     struct berval **values;
    4682           2 :     LDAP_TIMEVAL time = {PGLDAP_TIMEOUT, 0};
    4683             : 
    4684           2 :     if ((url = strdup(purl)) == NULL)
    4685             :     {
    4686           0 :         appendPQExpBufferStr(errorMessage, libpq_gettext("out of memory\n"));
    4687           0 :         return 3;
    4688             :     }
    4689             : 
    4690             :     /*
    4691             :      * Parse URL components, check for correctness.  Basically, url has '\0'
    4692             :      * placed at component boundaries and variables are pointed at each
    4693             :      * component.
    4694             :      */
    4695             : 
    4696           2 :     if (pg_strncasecmp(url, LDAP_URL, strlen(LDAP_URL)) != 0)
    4697             :     {
    4698           0 :         appendPQExpBuffer(errorMessage,
    4699           0 :                           libpq_gettext("invalid LDAP URL \"%s\": scheme must be ldap://\n"), purl);
    4700           0 :         free(url);
    4701           0 :         return 3;
    4702             :     }
    4703             : 
    4704             :     /* hostname */
    4705           2 :     hostname = url + strlen(LDAP_URL);
    4706           2 :     if (*hostname == '/')       /* no hostname? */
    4707           0 :         hostname = DefaultHost; /* the default */
    4708             : 
    4709             :     /* dn, "distinguished name" */
    4710           2 :     p = strchr(url + strlen(LDAP_URL), '/');
    4711           2 :     if (p == NULL || *(p + 1) == '\0' || *(p + 1) == '?')
    4712             :     {
    4713           0 :         appendPQExpBuffer(errorMessage,
    4714           0 :                           libpq_gettext("invalid LDAP URL \"%s\": missing distinguished name\n"),
    4715             :                           purl);
    4716           0 :         free(url);
    4717           0 :         return 3;
    4718             :     }
    4719           2 :     *p = '\0';                  /* terminate hostname */
    4720           2 :     dn = p + 1;
    4721             : 
    4722             :     /* attribute */
    4723           2 :     if ((p = strchr(dn, '?')) == NULL || *(p + 1) == '\0' || *(p + 1) == '?')
    4724             :     {
    4725           0 :         appendPQExpBuffer(errorMessage,
    4726           0 :                           libpq_gettext("invalid LDAP URL \"%s\": must have exactly one attribute\n"),
    4727             :                           purl);
    4728           0 :         free(url);
    4729           0 :         return 3;
    4730             :     }
    4731           2 :     *p = '\0';
    4732           2 :     attrs[0] = p + 1;
    4733             : 
    4734             :     /* scope */
    4735           2 :     if ((p = strchr(attrs[0], '?')) == NULL || *(p + 1) == '\0' || *(p + 1) == '?')
    4736             :     {
    4737           0 :         appendPQExpBuffer(errorMessage,
    4738           0 :                           libpq_gettext("invalid LDAP URL \"%s\": must have search scope (base/one/sub)\n"),
    4739             :                           purl);
    4740           0 :         free(url);
    4741           0 :         return 3;
    4742             :     }
    4743           2 :     *p = '\0';
    4744           2 :     scopestr = p + 1;
    4745             : 
    4746             :     /* filter */
    4747           2 :     if ((p = strchr(scopestr, '?')) == NULL || *(p + 1) == '\0' || *(p + 1) == '?')
    4748             :     {
    4749           0 :         appendPQExpBuffer(errorMessage,
    4750           0 :                           libpq_gettext("invalid LDAP URL \"%s\": no filter\n"),
    4751             :                           purl);
    4752           0 :         free(url);
    4753           0 :         return 3;
    4754             :     }
    4755           2 :     *p = '\0';
    4756           2 :     filter = p + 1;
    4757           2 :     if ((p = strchr(filter, '?')) != NULL)
    4758           0 :         *p = '\0';
    4759             : 
    4760             :     /* port number? */
    4761           2 :     if ((p1 = strchr(hostname, ':')) != NULL)
    4762             :     {
    4763             :         long        lport;
    4764             : 
    4765           2 :         *p1 = '\0';
    4766           2 :         portstr = p1 + 1;
    4767           2 :         errno = 0;
    4768           2 :         lport = strtol(portstr, &endptr, 10);
    4769           2 :         if (*portstr == '\0' || *endptr != '\0' || errno || lport < 0 || lport > 65535)
    4770             :         {
    4771           0 :             appendPQExpBuffer(errorMessage,
    4772           0 :                               libpq_gettext("invalid LDAP URL \"%s\": invalid port number\n"),
    4773             :                               purl);
    4774           0 :             free(url);
    4775           0 :             return 3;
    4776             :         }
    4777           2 :         port = (int) lport;
    4778             :     }
    4779             : 
    4780             :     /* Allow only one attribute */
    4781           2 :     if (strchr(attrs[0], ',') != NULL)
    4782             :     {
    4783           0 :         appendPQExpBuffer(errorMessage,
    4784           0 :                           libpq_gettext("invalid LDAP URL \"%s\": must have exactly one attribute\n"),
    4785             :                           purl);
    4786           0 :         free(url);
    4787           0 :         return 3;
    4788             :     }
    4789             : 
    4790             :     /* set scope */
    4791           2 :     if (pg_strcasecmp(scopestr, "base") == 0)
    4792           0 :         scope = LDAP_SCOPE_BASE;
    4793           2 :     else if (pg_strcasecmp(scopestr, "one") == 0)
    4794           2 :         scope = LDAP_SCOPE_ONELEVEL;
    4795           0 :     else if (pg_strcasecmp(scopestr, "sub") == 0)
    4796           0 :         scope = LDAP_SCOPE_SUBTREE;
    4797             :     else
    4798             :     {
    4799           0 :         appendPQExpBuffer(errorMessage,
    4800           0 :                           libpq_gettext("invalid LDAP URL \"%s\": must have search scope (base/one/sub)\n"),
    4801             :                           purl);
    4802           0 :         free(url);
    4803           0 :         return 3;
    4804             :     }
    4805             : 
    4806             :     /* initialize LDAP structure */
    4807           2 :     if ((ld = ldap_init(hostname, port)) == NULL)
    4808             :     {
    4809           0 :         appendPQExpBufferStr(errorMessage,
    4810           0 :                              libpq_gettext("could not create LDAP structure\n"));
    4811           0 :         free(url);
    4812           0 :         return 3;
    4813             :     }
    4814             : 
    4815             :     /*
    4816             :      * Perform an explicit anonymous bind.
    4817             :      *
    4818             :      * LDAP does not require that an anonymous bind is performed explicitly,
    4819             :      * but we want to distinguish between the case where LDAP bind does not
    4820             :      * succeed within PGLDAP_TIMEOUT seconds (return 2 to continue parsing the
    4821             :      * service control file) and the case where querying the LDAP server fails
    4822             :      * (return 1 to end parsing).
    4823             :      *
    4824             :      * Unfortunately there is no way of setting a timeout that works for both
    4825             :      * Windows and OpenLDAP.
    4826             :      */
    4827             : #ifdef WIN32
    4828             :     /* the nonstandard ldap_connect function performs an anonymous bind */
    4829             :     if (ldap_connect(ld, &time) != LDAP_SUCCESS)
    4830             :     {
    4831             :         /* error or timeout in ldap_connect */
    4832             :         free(url);
    4833             :         ldap_unbind(ld);
    4834             :         return 2;
    4835             :     }
    4836             : #else                           /* !WIN32 */
    4837             :     /* in OpenLDAP, use the LDAP_OPT_NETWORK_TIMEOUT option */
    4838           2 :     if (ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &time) != LDAP_SUCCESS)
    4839             :     {
    4840           0 :         free(url);
    4841           0 :         ldap_unbind(ld);
    4842           0 :         return 3;
    4843             :     }
    4844             : 
    4845             :     /* anonymous bind */
    4846           2 :     if ((msgid = ldap_simple_bind(ld, NULL, NULL)) == -1)
    4847             :     {
    4848             :         /* error or network timeout */
    4849           2 :         free(url);
    4850           2 :         ldap_unbind(ld);
    4851           2 :         return 2;
    4852             :     }
    4853             : 
    4854             :     /* wait some time for the connection to succeed */
    4855           0 :     res = NULL;
    4856           0 :     if ((rc = ldap_result(ld, msgid, LDAP_MSG_ALL, &time, &res)) == -1 ||
    4857           0 :         res == NULL)
    4858             :     {
    4859             :         /* error or timeout */
    4860           0 :         if (res != NULL)
    4861           0 :             ldap_msgfree(res);
    4862           0 :         free(url);
    4863           0 :         ldap_unbind(ld);
    4864           0 :         return 2;
    4865             :     }
    4866           0 :     ldap_msgfree(res);
    4867             : 
    4868             :     /* reset timeout */
    4869           0 :     time.tv_sec = -1;
    4870           0 :     if (ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &time) != LDAP_SUCCESS)
    4871             :     {
    4872           0 :         free(url);
    4873           0 :         ldap_unbind(ld);
    4874           0 :         return 3;
    4875             :     }
    4876             : #endif                          /* WIN32 */
    4877             : 
    4878             :     /* search */
    4879           0 :     res = NULL;
    4880           0 :     if ((rc = ldap_search_st(ld, dn, scope, filter, attrs, 0, &time, &res))
    4881             :         != LDAP_SUCCESS)
    4882             :     {
    4883           0 :         if (res != NULL)
    4884           0 :             ldap_msgfree(res);
    4885           0 :         appendPQExpBuffer(errorMessage,
    4886           0 :                           libpq_gettext("lookup on LDAP server failed: %s\n"),
    4887             :                           ldap_err2string(rc));
    4888           0 :         ldap_unbind(ld);
    4889           0 :         free(url);
    4890           0 :         return 1;
    4891             :     }
    4892             : 
    4893             :     /* complain if there was not exactly one result */
    4894           0 :     if ((rc = ldap_count_entries(ld, res)) != 1)
    4895             :     {
    4896           0 :         appendPQExpBufferStr(errorMessage,
    4897           0 :                              rc ? libpq_gettext("more than one entry found on LDAP lookup\n")
    4898           0 :                              : libpq_gettext("no entry found on LDAP lookup\n"));
    4899           0 :         ldap_msgfree(res);
    4900           0 :         ldap_unbind(ld);
    4901           0 :         free(url);
    4902           0 :         return 1;
    4903             :     }
    4904             : 
    4905             :     /* get entry */
    4906           0 :     if ((entry = ldap_first_entry(ld, res)) == NULL)
    4907             :     {
    4908             :         /* should never happen */
    4909           0 :         appendPQExpBufferStr(errorMessage,
    4910           0 :                              libpq_gettext("no entry found on LDAP lookup\n"));
    4911           0 :         ldap_msgfree(res);
    4912           0 :         ldap_unbind(ld);
    4913           0 :         free(url);
    4914           0 :         return 1;
    4915             :     }
    4916             : 
    4917             :     /* get values */
    4918           0 :     if ((values = ldap_get_values_len(ld, entry, attrs[0])) == NULL)
    4919             :     {
    4920           0 :         appendPQExpBufferStr(errorMessage,
    4921           0 :                              libpq_gettext("attribute has no values on LDAP lookup\n"));
    4922           0 :         ldap_msgfree(res);
    4923           0 :         ldap_unbind(ld);
    4924           0 :         free(url);
    4925           0 :         return 1;
    4926             :     }
    4927             : 
    4928           0 :     ldap_msgfree(res);
    4929           0 :     free(url);
    4930             : 
    4931           0 :     if (values[0] == NULL)
    4932             :     {
    4933           0 :         appendPQExpBufferStr(errorMessage,
    4934           0 :                              libpq_gettext("attribute has no values on LDAP lookup\n"));
    4935           0 :         ldap_value_free_len(values);
    4936           0 :         ldap_unbind(ld);
    4937           0 :         return 1;
    4938             :     }
    4939             : 
    4940             :     /* concatenate values into a single string with newline terminators */
    4941           0 :     size = 1;                   /* for the trailing null */
    4942           0 :     for (i = 0; values[i] != NULL; i++)
    4943           0 :         size += values[i]->bv_len + 1;
    4944           0 :     if ((result = malloc(size)) == NULL)
    4945             :     {
    4946           0 :         appendPQExpBufferStr(errorMessage,
    4947           0 :                              libpq_gettext("out of memory\n"));
    4948           0 :         ldap_value_free_len(values);
    4949           0 :         ldap_unbind(ld);
    4950           0 :         return 3;
    4951             :     }
    4952           0 :     p = result;
    4953           0 :     for (i = 0; values[i] != NULL; i++)
    4954             :     {
    4955           0 :         memcpy(p, values[i]->bv_val, values[i]->bv_len);
    4956           0 :         p += values[i]->bv_len;
    4957           0 :         *(p++) = '\n';
    4958             :     }
    4959           0 :     *p = '\0';
    4960             : 
    4961           0 :     ldap_value_free_len(values);
    4962           0 :     ldap_unbind(ld);
    4963             : 
    4964             :     /* parse result string */
    4965           0 :     oldstate = state = 0;
    4966           0 :     for (p = result; *p != '\0'; ++p)
    4967             :     {
    4968           0 :         switch (state)
    4969             :         {
    4970           0 :             case 0:             /* between entries */
    4971           0 :                 if (!ld_is_sp_tab(*p) && !ld_is_nl_cr(*p))
    4972             :                 {
    4973           0 :                     optname = p;
    4974           0 :                     state = 1;
    4975             :                 }
    4976           0 :                 break;
    4977           0 :             case 1:             /* in option name */
    4978           0 :                 if (ld_is_sp_tab(*p))
    4979             :                 {
    4980           0 :                     *p = '\0';
    4981           0 :                     state = 2;
    4982             :                 }
    4983           0 :                 else if (ld_is_nl_cr(*p))
    4984             :                 {
    4985           0 :                     appendPQExpBuffer(errorMessage,
    4986           0 :                                       libpq_gettext("missing \"=\" after \"%s\" in connection info string\n"),
    4987             :                                       optname);
    4988           0 :                     free(result);
    4989           0 :                     return 3;
    4990             :                 }
    4991           0 :                 else if (*p == '=')
    4992             :                 {
    4993           0 :                     *p = '\0';
    4994           0 :                     state = 3;
    4995             :                 }
    4996           0 :                 break;
    4997           0 :             case 2:             /* after option name */
    4998           0 :                 if (*p == '=')
    4999             :                 {
    5000           0 :                     state = 3;
    5001             :                 }
    5002           0 :                 else if (!ld_is_sp_tab(*p))
    5003             :                 {
    5004           0 :                     appendPQExpBuffer(errorMessage,
    5005           0 :                                       libpq_gettext("missing \"=\" after \"%s\" in connection info string\n"),
    5006             :                                       optname);
    5007           0 :                     free(result);
    5008           0 :                     return 3;
    5009             :                 }
    5010           0 :                 break;
    5011           0 :             case 3:             /* before option value */
    5012           0 :                 if (*p == '\'')
    5013             :                 {
    5014           0 :                     optval = p + 1;
    5015           0 :                     p1 = p + 1;
    5016           0 :                     state = 5;
    5017             :                 }
    5018           0 :                 else if (ld_is_nl_cr(*p))
    5019             :                 {
    5020           0 :                     optval = optname + strlen(optname); /* empty */
    5021           0 :                     state = 0;
    5022             :                 }
    5023           0 :                 else if (!ld_is_sp_tab(*p))
    5024             :                 {
    5025           0 :                     optval = p;
    5026           0 :                     state = 4;
    5027             :                 }
    5028           0 :                 break;
    5029           0 :             case 4:             /* in unquoted option value */
    5030           0 :                 if (ld_is_sp_tab(*p) || ld_is_nl_cr(*p))
    5031             :                 {
    5032           0 :                     *p = '\0';
    5033           0 :                     state = 0;
    5034             :                 }
    5035           0 :                 break;
    5036           0 :             case 5:             /* in quoted option value */
    5037           0 :                 if (*p == '\'')
    5038             :                 {
    5039           0 :                     *p1 = '\0';
    5040           0 :                     state = 0;
    5041             :                 }
    5042           0 :                 else if (*p == '\\')
    5043           0 :                     state = 6;
    5044             :                 else
    5045           0 :                     *(p1++) = *p;
    5046           0 :                 break;
    5047           0 :             case 6:             /* in quoted option value after escape */
    5048           0 :                 *(p1++) = *p;
    5049           0 :                 state = 5;
    5050           0 :                 break;
    5051             :         }
    5052             : 
    5053           0 :         if (state == 0 && oldstate != 0)
    5054             :         {
    5055           0 :             found_keyword = false;
    5056           0 :             for (i = 0; options[i].keyword; i++)
    5057             :             {
    5058           0 :                 if (strcmp(options[i].keyword, optname) == 0)
    5059             :                 {
    5060           0 :                     if (options[i].val == NULL)
    5061             :                     {
    5062           0 :                         options[i].val = strdup(optval);
    5063           0 :                         if (!options[i].val)
    5064             :                         {
    5065           0 :                             appendPQExpBufferStr(errorMessage,
    5066           0 :                                                  libpq_gettext("out of memory\n"));
    5067           0 :                             free(result);
    5068           0 :                             return 3;
    5069             :                         }
    5070             :                     }
    5071           0 :                     found_keyword = true;
    5072           0 :                     break;
    5073             :                 }
    5074             :             }
    5075           0 :             if (!found_keyword)
    5076             :             {
    5077           0 :                 appendPQExpBuffer(errorMessage,
    5078           0 :                                   libpq_gettext("invalid connection option \"%s\"\n"),
    5079             :                                   optname);
    5080           0 :                 free(result);
    5081           0 :                 return 1;
    5082             :             }
    5083           0 :             optname = NULL;
    5084           0 :             optval = NULL;
    5085             :         }
    5086           0 :         oldstate = state;
    5087             :     }
    5088             : 
    5089           0 :     free(result);
    5090             : 
    5091           0 :     if (state == 5 || state == 6)
    5092             :     {
    5093           0 :         appendPQExpBufferStr(errorMessage,
    5094           0 :                              libpq_gettext("unterminated quoted string in connection info string\n"));
    5095           0 :         return 3;
    5096             :     }
    5097             : 
    5098           0 :     return 0;
    5099             : }
    5100             : 
    5101             : #endif                          /* USE_LDAP */
    5102             : 
    5103             : /*
    5104             :  * parseServiceInfo: if a service name has been given, look it up and absorb
    5105             :  * connection options from it into *options.
    5106             :  *
    5107             :  * Returns 0 on success, nonzero on failure.  On failure, if errorMessage
    5108             :  * isn't null, also store an error message there.  (Note: the only reason
    5109             :  * this function and related ones don't dump core on errorMessage == NULL
    5110             :  * is the undocumented fact that printfPQExpBuffer does nothing when passed
    5111             :  * a null PQExpBuffer pointer.)
    5112             :  */
    5113             : static int
    5114       12692 : parseServiceInfo(PQconninfoOption *options, PQExpBuffer errorMessage)
    5115             : {
    5116       12692 :     const char *service = conninfo_getval(options, "service");
    5117             :     char        serviceFile[MAXPGPATH];
    5118             :     char       *env;
    5119       12692 :     bool        group_found = false;
    5120             :     int         status;
    5121             :     struct stat stat_buf;
    5122             : 
    5123             :     /*
    5124             :      * We have to special-case the environment variable PGSERVICE here, since
    5125             :      * this is and should be called before inserting environment defaults for
    5126             :      * other connection options.
    5127             :      */
    5128       12692 :     if (service == NULL)
    5129       12690 :         service = getenv("PGSERVICE");
    5130             : 
    5131             :     /* If no service name given, nothing to do */
    5132       12692 :     if (service == NULL)
    5133       12690 :         return 0;
    5134             : 
    5135             :     /*
    5136             :      * Try PGSERVICEFILE if specified, else try ~/.pg_service.conf (if that
    5137             :      * exists).
    5138             :      */
    5139           2 :     if ((env = getenv("PGSERVICEFILE")) != NULL)
    5140           2 :         strlcpy(serviceFile, env, sizeof(serviceFile));
    5141             :     else
    5142             :     {
    5143             :         char        homedir[MAXPGPATH];
    5144             : 
    5145           0 :         if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
    5146           0 :             goto next_file;
    5147           0 :         snprintf(serviceFile, MAXPGPATH, "%s/%s", homedir, ".pg_service.conf");
    5148           0 :         if (stat(serviceFile, &stat_buf) != 0)
    5149           0 :             goto next_file;
    5150             :     }
    5151             : 
    5152           2 :     status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
    5153           2 :     if (group_found || status != 0)
    5154           2 :         return status;
    5155             : 
    5156           0 : next_file:
    5157             : 
    5158             :     /*
    5159             :      * This could be used by any application so we can't use the binary
    5160             :      * location to find our config files.
    5161             :      */
    5162           0 :     snprintf(serviceFile, MAXPGPATH, "%s/pg_service.conf",
    5163           0 :              getenv("PGSYSCONFDIR") ? getenv("PGSYSCONFDIR") : SYSCONFDIR);
    5164           0 :     if (stat(serviceFile, &stat_buf) != 0)
    5165           0 :         goto last_file;
    5166             : 
    5167           0 :     status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
    5168           0 :     if (status != 0)
    5169           0 :         return status;
    5170             : 
    5171           0 : last_file:
    5172           0 :     if (!group_found)
    5173             :     {
    5174           0 :         appendPQExpBuffer(errorMessage,
    5175           0 :                           libpq_gettext("definition of service \"%s\" not found\n"), service);
    5176           0 :         return 3;
    5177             :     }
    5178             : 
    5179           0 :     return 0;
    5180             : }
    5181             : 
    5182             : static int
    5183           2 : parseServiceFile(const char *serviceFile,
    5184             :                  const char *service,
    5185             :                  PQconninfoOption *options,
    5186             :                  PQExpBuffer errorMessage,
    5187             :                  bool *group_found)
    5188             : {
    5189           2 :     int         result = 0,
    5190           2 :                 linenr = 0,
    5191             :                 i;
    5192             :     FILE       *f;
    5193             :     char       *line;
    5194             :     char        buf[1024];
    5195             : 
    5196           2 :     *group_found = false;
    5197             : 
    5198           2 :     f = fopen(serviceFile, "r");
    5199           2 :     if (f == NULL)
    5200             :     {
    5201           0 :         appendPQExpBuffer(errorMessage, libpq_gettext("service file \"%s\" not found\n"),
    5202             :                           serviceFile);
    5203           0 :         return 1;
    5204             :     }
    5205             : 
    5206          16 :     while ((line = fgets(buf, sizeof(buf), f)) != NULL)
    5207             :     {
    5208             :         int         len;
    5209             : 
    5210          14 :         linenr++;
    5211             : 
    5212          14 :         if (strlen(line) >= sizeof(buf) - 1)
    5213             :         {
    5214           0 :             appendPQExpBuffer(errorMessage,
    5215           0 :                               libpq_gettext("line %d too long in service file \"%s\"\n"),
    5216             :                               linenr,
    5217             :                               serviceFile);
    5218           0 :             result = 2;
    5219           0 :             goto exit;
    5220             :         }
    5221             : 
    5222             :         /* ignore whitespace at end of line, especially the newline */
    5223          14 :         len = strlen(line);
    5224          28 :         while (len > 0 && isspace((unsigned char) line[len - 1]))
    5225          14 :             line[--len] = '\0';
    5226             : 
    5227             :         /* ignore leading whitespace too */
    5228          14 :         while (*line && isspace((unsigned char) line[0]))
    5229           0 :             line++;
    5230             : 
    5231             :         /* ignore comments and empty lines */
    5232          14 :         if (line[0] == '\0' || line[0] == '#')
    5233          10 :             continue;
    5234             : 
    5235             :         /* Check for right groupname */
    5236           4 :         if (line[0] == '[')
    5237             :         {
    5238           2 :             if (*group_found)
    5239             :             {
    5240             :                 /* end of desired group reached; return success */
    5241           0 :                 goto exit;
    5242             :             }
    5243             : 
    5244           2 :             if (strncmp(line + 1, service, strlen(service)) == 0 &&
    5245           2 :                 line[strlen(service) + 1] == ']')
    5246           2 :                 *group_found = true;
    5247             :             else
    5248           0 :                 *group_found = false;
    5249             :         }
    5250             :         else
    5251             :         {
    5252           2 :             if (*group_found)
    5253             :             {
    5254             :                 /*
    5255             :                  * Finally, we are in the right group and can parse the line
    5256             :                  */
    5257             :                 char       *key,
    5258             :                            *val;
    5259             :                 bool        found_keyword;
    5260             : 
    5261             : #ifdef USE_LDAP
    5262           2 :                 if (strncmp(line, "ldap", 4) == 0)
    5263             :                 {
    5264           2 :                     int         rc = ldapServiceLookup(line, options, errorMessage);
    5265             : 
    5266             :                     /* if rc = 2, go on reading for fallback */
    5267           2 :                     switch (rc)
    5268             :                     {
    5269           0 :                         case 0:
    5270           0 :                             goto exit;
    5271           0 :                         case 1:
    5272             :                         case 3:
    5273           0 :                             result = 3;
    5274           0 :                             goto exit;
    5275           2 :                         case 2:
    5276           2 :                             continue;
    5277             :                     }
    5278             :                 }
    5279             : #endif
    5280             : 
    5281           0 :                 key = line;
    5282           0 :                 val = strchr(line, '=');
    5283           0 :                 if (val == NULL)
    5284             :                 {
    5285           0 :                     appendPQExpBuffer(errorMessage,
    5286           0 :                                       libpq_gettext("syntax error in service file \"%s\", line %d\n"),
    5287             :                                       serviceFile,
    5288             :                                       linenr);
    5289           0 :                     result = 3;
    5290           0 :                     goto exit;
    5291             :                 }
    5292           0 :                 *val++ = '\0';
    5293             : 
    5294           0 :                 if (strcmp(key, "service") == 0)
    5295             :                 {
    5296           0 :                     appendPQExpBuffer(errorMessage,
    5297           0 :                                       libpq_gettext("nested service specifications not supported in service file \"%s\", line %d\n"),
    5298             :                                       serviceFile,
    5299             :                                       linenr);
    5300           0 :                     result = 3;
    5301           0 :                     goto exit;
    5302             :                 }
    5303             : 
    5304             :                 /*
    5305             :                  * Set the parameter --- but don't override any previous
    5306             :                  * explicit setting.
    5307             :                  */
    5308           0 :                 found_keyword = false;
    5309           0 :                 for (i = 0; options[i].keyword; i++)
    5310             :                 {
    5311           0 :                     if (strcmp(options[i].keyword, key) == 0)
    5312             :                     {
    5313           0 :                         if (options[i].val == NULL)
    5314           0 :                             options[i].val = strdup(val);
    5315           0 :                         if (!options[i].val)
    5316             :                         {
    5317           0 :                             appendPQExpBufferStr(errorMessage,
    5318           0 :                                                  libpq_gettext("out of memory\n"));
    5319           0 :                             result = 3;
    5320           0 :                             goto exit;
    5321             :                         }
    5322           0 :                         found_keyword = true;
    5323           0 :                         break;
    5324             :                     }
    5325             :                 }
    5326             : 
    5327           0 :                 if (!found_keyword)
    5328             :                 {
    5329           0 :                     appendPQExpBuffer(errorMessage,
    5330           0 :                                       libpq_gettext("syntax error in service file \"%s\", line %d\n"),
    5331             :                                       serviceFile,
    5332             :                                       linenr);
    5333           0 :                     result = 3;
    5334           0 :                     goto exit;
    5335             :                 }
    5336             :             }
    5337             :         }
    5338             :     }
    5339             : 
    5340           2 : exit:
    5341           2 :     fclose(f);
    5342             : 
    5343           2 :     return result;
    5344             : }
    5345             : 
    5346             : 
    5347             : /*
    5348             :  *      PQconninfoParse
    5349             :  *
    5350             :  * Parse a string like PQconnectdb() would do and return the
    5351             :  * resulting connection options array.  NULL is returned on failure.
    5352             :  * The result contains only options specified directly in the string,
    5353             :  * not any possible default values.
    5354             :  *
    5355             :  * If errmsg isn't NULL, *errmsg is set to NULL on success, or a malloc'd
    5356             :  * string on failure (use PQfreemem to free it).  In out-of-memory conditions
    5357             :  * both *errmsg and the result could be NULL.
    5358             :  *
    5359             :  * NOTE: the returned array is dynamically allocated and should
    5360             :  * be freed when no longer needed via PQconninfoFree().
    5361             :  */
    5362             : PQconninfoOption *
    5363         188 : PQconninfoParse(const char *conninfo, char **errmsg)
    5364             : {
    5365             :     PQExpBufferData errorBuf;
    5366             :     PQconninfoOption *connOptions;
    5367             : 
    5368         188 :     if (errmsg)
    5369         186 :         *errmsg = NULL;         /* default */
    5370         188 :     initPQExpBuffer(&errorBuf);
    5371         188 :     if (PQExpBufferDataBroken(errorBuf))
    5372           0 :         return NULL;            /* out of memory already :-( */
    5373         188 :     connOptions = parse_connection_string(conninfo, &errorBuf, false);
    5374         188 :     if (connOptions == NULL && errmsg)
    5375           8 :         *errmsg = errorBuf.data;
    5376             :     else
    5377         180 :         termPQExpBuffer(&errorBuf);
    5378         188 :     return connOptions;
    5379             : }
    5380             : 
    5381             : /*
    5382             :  * Build a working copy of the constant PQconninfoOptions array.
    5383             :  */
    5384             : static PQconninfoOption *
    5385       20342 : conninfo_init(PQExpBuffer errorMessage)
    5386             : {
    5387             :     PQconninfoOption *options;
    5388             :     PQconninfoOption *opt_dest;
    5389             :     const internalPQconninfoOption *cur_opt;
    5390             : 
    5391             :     /*
    5392             :      * Get enough memory for all options in PQconninfoOptions, even if some
    5393             :      * end up being filtered out.
    5394             :      */
    5395       20342 :     options = (PQconninfoOption *) malloc(sizeof(PQconninfoOption) * sizeof(PQconninfoOptions) / sizeof(PQconninfoOptions[0]));
    5396       20342 :     if (options == NULL)
    5397             :     {
    5398           0 :         appendPQExpBufferStr(errorMessage,
    5399           0 :                              libpq_gettext("out of memory\n"));
    5400           0 :         return NULL;
    5401             :     }
    5402       20342 :     opt_dest = options;
    5403             : 
    5404      752654 :     for (cur_opt = PQconninfoOptions; cur_opt->keyword; cur_opt++)
    5405             :     {
    5406             :         /* Only copy the public part of the struct, not the full internal */
    5407      732312 :         memcpy(opt_dest, cur_opt, sizeof(PQconninfoOption));
    5408      732312 :         opt_dest++;
    5409             :     }
    5410      162736 :     MemSet(opt_dest, 0, sizeof(PQconninfoOption));
    5411             : 
    5412       20342 :     return options;
    5413             : }
    5414             : 
    5415             : /*
    5416             :  * Connection string parser
    5417             :  *
    5418             :  * Returns a malloc'd PQconninfoOption array, if parsing is successful.
    5419             :  * Otherwise, NULL is returned and an error message is added to errorMessage.
    5420             :  *
    5421             :  * If use_defaults is true, default values are filled in (from a service file,
    5422             :  * environment variables, etc).
    5423             :  */
    5424             : static PQconninfoOption *
    5425        8254 : parse_connection_string(const char *connstr, PQExpBuffer errorMessage,
    5426             :                         bool use_defaults)
    5427             : {
    5428             :     /* Parse as URI if connection string matches URI prefix */
    5429        8254 :     if (uri_prefix_length(connstr) != 0)
    5430           0 :         return conninfo_uri_parse(connstr, errorMessage, use_defaults);
    5431             : 
    5432             :     /* Parse as default otherwise */
    5433        8254 :     return conninfo_parse(connstr, errorMessage, use_defaults);
    5434             : }
    5435             : 
    5436             : /*
    5437             :  * Checks if connection string starts with either of the valid URI prefix
    5438             :  * designators.
    5439             :  *
    5440             :  * Returns the URI prefix length, 0 if the string doesn't contain a URI prefix.
    5441             :  *
    5442             :  * XXX this is duplicated in psql/common.c.
    5443             :  */
    5444             : static int
    5445       19150 : uri_prefix_length(const char *connstr)
    5446             : {
    5447       19150 :     if (strncmp(connstr, uri_designator,
    5448             :                 sizeof(uri_designator) - 1) == 0)
    5449           0 :         return sizeof(uri_designator) - 1;
    5450             : 
    5451       19150 :     if (strncmp(connstr, short_uri_designator,
    5452             :                 sizeof(short_uri_designator) - 1) == 0)
    5453           0 :         return sizeof(short_uri_designator) - 1;
    5454             : 
    5455       19150 :     return 0;
    5456             : }
    5457             : 
    5458             : /*
    5459             :  * Recognized connection string either starts with a valid URI prefix or
    5460             :  * contains a "=" in it.
    5461             :  *
    5462             :  * Must be consistent with parse_connection_string: anything for which this
    5463             :  * returns true should at least look like it's parseable by that routine.
    5464             :  *
    5465             :  * XXX this is duplicated in psql/common.c
    5466             :  */
    5467             : static bool
    5468       10896 : recognized_connection_string(const char *connstr)
    5469             : {
    5470       10896 :     return uri_prefix_length(connstr) != 0 || strchr(connstr, '=') != NULL;
    5471             : }
    5472             : 
    5473             : /*
    5474             :  * Subroutine for parse_connection_string
    5475             :  *
    5476             :  * Deal with a string containing key=value pairs.
    5477             :  */
    5478             : static PQconninfoOption *
    5479        8254 : conninfo_parse(const char *conninfo, PQExpBuffer errorMessage,
    5480             :                bool use_defaults)
    5481             : {
    5482             :     char       *pname;
    5483             :     char       *pval;
    5484             :     char       *buf;
    5485             :     char       *cp;
    5486             :     char       *cp2;
    5487             :     PQconninfoOption *options;
    5488             : 
    5489             :     /* Make a working copy of PQconninfoOptions */
    5490        8254 :     options = conninfo_init(errorMessage);
    5491        8254 :     if (options == NULL)
    5492           0 :         return NULL;
    5493             : 
    5494             :     /* Need a modifiable copy of the input string */
    5495        8254 :     if ((buf = strdup(conninfo)) == NULL)
    5496             :     {
    5497           0 :         appendPQExpBufferStr(errorMessage,
    5498           0 :                              libpq_gettext("out of memory\n"));
    5499           0 :         PQconninfoFree(options);
    5500           0 :         return NULL;
    5501             :     }
    5502        8254 :     cp = buf;
    5503             : 
    5504       31730 :     while (*cp)
    5505             :     {
    5506             :         /* Skip blanks before the parameter name */
    5507       23488 :         if (isspace((unsigned char) *cp))
    5508             :         {
    5509         162 :             cp++;
    5510         162 :             continue;
    5511             :         }
    5512             : 
    5513             :         /* Get the parameter name */
    5514       23326 :         pname = cp;
    5515      137962 :         while (*cp)
    5516             :         {
    5517      137950 :             if (*cp == '=')
    5518       23314 :                 break;
    5519      114636 :             if (isspace((unsigned char) *cp))
    5520             :             {
    5521           0 :                 *cp++ = '\0';
    5522           0 :                 while (*cp)
    5523             :                 {
    5524           0 :                     if (!isspace((unsigned char) *cp))
    5525           0 :                         break;
    5526           0 :                     cp++;
    5527             :                 }
    5528           0 :                 break;
    5529             :             }
    5530      114636 :             cp++;
    5531             :         }
    5532             : 
    5533             :         /* Check that there is a following '=' */
    5534       23326 :         if (*cp != '=')
    5535             :         {
    5536          12 :             appendPQExpBuffer(errorMessage,
    5537          12 :                               libpq_gettext("missing \"=\" after \"%s\" in connection info string\n"),
    5538             :                               pname);
    5539          12 :             PQconninfoFree(options);
    5540          12 :             free(buf);
    5541          12 :             return NULL;
    5542             :         }
    5543       23314 :         *cp++ = '\0';
    5544             : 
    5545             :         /* Skip blanks after the '=' */
    5546       23314 :         while (*cp)
    5547             :         {
    5548       23314 :             if (!isspace((unsigned char) *cp))
    5549       23314 :                 break;
    5550           0 :             cp++;
    5551             :         }
    5552             : 
    5553             :         /* Get the parameter value */
    5554       23314 :         pval = cp;
    5555             : 
    5556       23314 :         if (*cp != '\'')
    5557             :         {
    5558       17000 :             cp2 = pval;
    5559      199910 :             while (*cp)
    5560             :             {
    5561      197894 :                 if (isspace((unsigned char) *cp))
    5562             :                 {
    5563       14984 :                     *cp++ = '\0';
    5564       14984 :                     break;
    5565             :                 }
    5566      182910 :                 if (*cp == '\\')
    5567             :                 {
    5568           0 :                     cp++;
    5569           0 :                     if (*cp != '\0')
    5570           0 :                         *cp2++ = *cp++;
    5571             :                 }
    5572             :                 else
    5573      182910 :                     *cp2++ = *cp++;
    5574             :             }
    5575       17000 :             *cp2 = '\0';
    5576             :         }
    5577             :         else
    5578             :         {
    5579        6314 :             cp2 = pval;
    5580        6314 :             cp++;
    5581             :             for (;;)
    5582             :             {
    5583       66424 :                 if (*cp == '\0')
    5584             :                 {
    5585           0 :                     appendPQExpBufferStr(errorMessage,
    5586           0 :                                          libpq_gettext("unterminated quoted string in connection info string\n"));
    5587           0 :                     PQconninfoFree(options);
    5588           0 :                     free(buf);
    5589           0 :                     return NULL;
    5590             :                 }
    5591       66424 :                 if (*cp == '\\')
    5592             :                 {
    5593         202 :                     cp++;
    5594         202 :                     if (*cp != '\0')
    5595         202 :                         *cp2++ = *cp++;
    5596         202 :                     continue;
    5597             :                 }
    5598       66222 :                 if (*cp == '\'')
    5599             :                 {
    5600        6314 :                     *cp2 = '\0';
    5601        6314 :                     cp++;
    5602        6314 :                     break;
    5603             :                 }
    5604       59908 :                 *cp2++ = *cp++;
    5605             :             }
    5606             :         }
    5607             : 
    5608             :         /*
    5609             :          * Now that we have the name and the value, store the record.
    5610             :          */
    5611       23314 :         if (!conninfo_storeval(options, pname, pval, errorMessage, false, false))
    5612             :         {
    5613           0 :             PQconninfoFree(options);
    5614           0 :             free(buf);
    5615           0 :             return NULL;
    5616             :         }
    5617             :     }
    5618             : 
    5619             :     /* Done with the modifiable input string */
    5620        8242 :     free(buf);
    5621             : 
    5622             :     /*
    5623             :      * Add in defaults if the caller wants that.
    5624             :      */
    5625        8242 :     if (use_defaults)
    5626             :     {
    5627         960 :         if (!conninfo_add_defaults(options, errorMessage))
    5628             :         {
    5629           0 :             PQconninfoFree(options);
    5630           0 :             return NULL;
    5631             :         }
    5632             :     }
    5633             : 
    5634        8242 :     return options;
    5635             : }
    5636             : 
    5637             : /*
    5638             :  * Conninfo array parser routine
    5639             :  *
    5640             :  * If successful, a malloc'd PQconninfoOption array is returned.
    5641             :  * If not successful, NULL is returned and an error message is
    5642             :  * appended to errorMessage.
    5643             :  * Defaults are supplied (from a service file, environment variables, etc)
    5644             :  * for unspecified options, but only if use_defaults is true.
    5645             :  *
    5646             :  * If expand_dbname is non-zero, and the value passed for the first occurrence
    5647             :  * of "dbname" keyword is a connection string (as indicated by
    5648             :  * recognized_connection_string) then parse and process it, overriding any
    5649             :  * previously processed conflicting keywords. Subsequent keywords will take
    5650             :  * precedence, however. In-tree programs generally specify expand_dbname=true,
    5651             :  * so command-line arguments naming a database can use a connection string.
    5652             :  * Some code acquires arbitrary database names from known-literal sources like
    5653             :  * PQdb(), PQconninfoParse() and pg_database.datname.  When connecting to such
    5654             :  * a database, in-tree code first wraps the name in a connection string.
    5655             :  */
    5656             : static PQconninfoOption *
    5657       11710 : conninfo_array_parse(const char *const *keywords, const char *const *values,
    5658             :                      PQExpBuffer errorMessage, bool use_defaults,
    5659             :                      int expand_dbname)
    5660             : {
    5661             :     PQconninfoOption *options;
    5662       11710 :     PQconninfoOption *dbname_options = NULL;
    5663             :     PQconninfoOption *option;
    5664       11710 :     int         i = 0;
    5665             : 
    5666             :     /*
    5667             :      * If expand_dbname is non-zero, check keyword "dbname" to see if val is
    5668             :      * actually a recognized connection string.
    5669             :      */
    5670       49846 :     while (expand_dbname && keywords[i])
    5671             :     {
    5672       49032 :         const char *pname = keywords[i];
    5673       49032 :         const char *pvalue = values[i];
    5674             : 
    5675             :         /* first find "dbname" if any */
    5676       49032 :         if (strcmp(pname, "dbname") == 0 && pvalue)
    5677             :         {
    5678             :             /*
    5679             :              * If value is a connection string, parse it, but do not use
    5680             :              * defaults here -- those get picked up later. We only want to
    5681             :              * override for those parameters actually passed.
    5682             :              */
    5683       10896 :             if (recognized_connection_string(pvalue))
    5684             :             {
    5685        7102 :                 dbname_options = parse_connection_string(pvalue, errorMessage, false);
    5686        7102 :                 if (dbname_options == NULL)
    5687           0 :                     return NULL;
    5688             :             }
    5689       10896 :             break;
    5690             :         }
    5691       38136 :         ++i;
    5692             :     }
    5693             : 
    5694             :     /* Make a working copy of PQconninfoOptions */
    5695       11710 :     options = conninfo_init(errorMessage);
    5696       11710 :     if (options == NULL)
    5697             :     {
    5698           0 :         PQconninfoFree(dbname_options);
    5699           0 :         return NULL;
    5700             :     }
    5701             : 
    5702             :     /* Parse the keywords/values arrays */
    5703       11710 :     i = 0;
    5704       87184 :     while (keywords[i])
    5705             :     {
    5706       75474 :         const char *pname = keywords[i];
    5707       75474 :         const char *pvalue = values[i];
    5708             : 
    5709       75474 :         if (pvalue != NULL && pvalue[0] != '\0')
    5710             :         {
    5711             :             /* Search for the param record */
    5712      357780 :             for (option = options; option->keyword != NULL; option++)
    5713             :             {
    5714      357780 :                 if (strcmp(option->keyword, pname) == 0)
    5715       29520 :                     break;
    5716             :             }
    5717             : 
    5718             :             /* Check for invalid connection option */
    5719       29520 :             if (option->keyword == NULL)
    5720             :             {
    5721           0 :                 appendPQExpBuffer(errorMessage,
    5722           0 :                                   libpq_gettext("invalid connection option \"%s\"\n"),
    5723             :                                   pname);
    5724           0 :                 PQconninfoFree(options);
    5725           0 :                 PQconninfoFree(dbname_options);
    5726           0 :                 return NULL;
    5727             :             }
    5728             : 
    5729             :             /*
    5730             :              * If we are on the first dbname parameter, and we have a parsed
    5731             :              * connection string, copy those parameters across, overriding any
    5732             :              * existing previous settings.
    5733             :              */
    5734       29520 :             if (strcmp(pname, "dbname") == 0 && dbname_options)
    5735        7102 :             {
    5736             :                 PQconninfoOption *str_option;
    5737             : 
    5738      262774 :                 for (str_option = dbname_options; str_option->keyword != NULL; str_option++)
    5739             :                 {
    5740      255672 :                     if (str_option->val != NULL)
    5741             :                     {
    5742             :                         int         k;
    5743             : 
    5744      188658 :                         for (k = 0; options[k].keyword; k++)
    5745             :                         {
    5746      188658 :                             if (strcmp(options[k].keyword, str_option->keyword) == 0)
    5747             :                             {
    5748       21530 :                                 if (options[k].val)
    5749           0 :                                     free(options[k].val);
    5750       21530 :                                 options[k].val = strdup(str_option->val);
    5751       21530 :                                 if (!options[k].val)
    5752             :                                 {
    5753           0 :                                     appendPQExpBufferStr(errorMessage,
    5754           0 :                                                          libpq_gettext("out of memory\n"));
    5755           0 :                                     PQconninfoFree(options);
    5756           0 :                                     PQconninfoFree(dbname_options);
    5757           0 :                                     return NULL;
    5758             :                                 }
    5759       21530 :                                 break;
    5760             :                             }
    5761             :                         }
    5762             :                     }
    5763             :                 }
    5764             : 
    5765             :                 /*
    5766             :                  * Forget the parsed connection string, so that any subsequent
    5767             :                  * dbname parameters will not be expanded.
    5768             :                  */
    5769        7102 :                 PQconninfoFree(dbname_options);
    5770        7102 :                 dbname_options = NULL;
    5771             :             }
    5772             :             else
    5773             :             {
    5774             :                 /*
    5775             :                  * Store the value, overriding previous settings
    5776             :                  */
    5777       22418 :                 if (option->val)
    5778         190 :                     free(option->val);
    5779       22418 :                 option->val = strdup(pvalue);
    5780       22418 :                 if (!option->val)
    5781             :                 {
    5782           0 :                     appendPQExpBufferStr(errorMessage,
    5783           0 :                                          libpq_gettext("out of memory\n"));
    5784           0 :                     PQconninfoFree(options);
    5785           0 :                     PQconninfoFree(dbname_options);
    5786           0 :                     return NULL;
    5787             :                 }
    5788             :             }
    5789             :         }
    5790       75474 :         ++i;
    5791             :     }
    5792       11710 :     PQconninfoFree(dbname_options);
    5793             : 
    5794             :     /*
    5795             :      * Add in defaults if the caller wants that.
    5796             :      */
    5797       11710 :     if (use_defaults)
    5798             :     {
    5799       11710 :         if (!conninfo_add_defaults(options, errorMessage))
    5800             :         {
    5801           0 :             PQconninfoFree(options);
    5802           0 :             return NULL;
    5803             :         }
    5804             :     }
    5805             : 
    5806       11710 :     return options;
    5807             : }
    5808             : 
    5809             : /*
    5810             :  * Add the default values for any unspecified options to the connection
    5811             :  * options array.
    5812             :  *
    5813             :  * Defaults are obtained from a service file, environment variables, etc.
    5814             :  *
    5815             :  * Returns true if successful, otherwise false; errorMessage, if supplied,
    5816             :  * is filled in upon failure.  Note that failure to locate a default value
    5817             :  * is not an error condition here --- we just leave the option's value as
    5818             :  * NULL.
    5819             :  */
    5820             : static bool
    5821       12692 : conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
    5822             : {
    5823             :     PQconninfoOption *option;
    5824             :     char       *tmp;
    5825             : 
    5826             :     /*
    5827             :      * If there's a service spec, use it to obtain any not-explicitly-given
    5828             :      * parameters.  Ignore error if no error message buffer is passed because
    5829             :      * there is no way to pass back the failure message.
    5830             :      */
    5831       12692 :     if (parseServiceInfo(options, errorMessage) != 0 && errorMessage)
    5832           0 :         return false;
    5833             : 
    5834             :     /*
    5835             :      * Get the fallback resources for parameters not specified in the conninfo
    5836             :      * string nor the service.
    5837             :      */
    5838      469604 :     for (option = options; option->keyword != NULL; option++)
    5839             :     {
    5840      456912 :         if (option->val != NULL)
    5841       45162 :             continue;           /* Value was in conninfo or service */
    5842             : 
    5843             :         /*
    5844             :          * Try to get the environment variable fallback
    5845             :          */
    5846      411750 :         if (option->envvar != NULL)
    5847             :         {
    5848      322816 :             if ((tmp = getenv(option->envvar)) != NULL)
    5849             :             {
    5850       26298 :                 option->val = strdup(tmp);
    5851       26298 :                 if (!option->val)
    5852             :                 {
    5853           0 :                     if (errorMessage)
    5854           0 :                         appendPQExpBufferStr(errorMessage,
    5855           0 :                                              libpq_gettext("out of memory\n"));
    5856           0 :                     return false;
    5857             :                 }
    5858       26298 :                 continue;
    5859             :             }
    5860             :         }
    5861             : 
    5862             :         /*
    5863             :          * Interpret the deprecated PGREQUIRESSL environment variable.  Per
    5864             :          * tradition, translate values starting with "1" to sslmode=require,
    5865             :          * and ignore other values.  Given both PGREQUIRESSL=1 and PGSSLMODE,
    5866             :          * PGSSLMODE takes precedence; the opposite was true before v9.3.
    5867             :          */
    5868      385452 :         if (strcmp(option->keyword, "sslmode") == 0)
    5869             :         {
    5870       12338 :             const char *requiresslenv = getenv("PGREQUIRESSL");
    5871             : 
    5872       12338 :             if (requiresslenv != NULL && requiresslenv[0] == '1')
    5873             :             {
    5874           0 :                 option->val = strdup("require");
    5875           0 :                 if (!option->val)
    5876             :                 {
    5877           0 :                     if (errorMessage)
    5878           0 :                         appendPQExpBufferStr(errorMessage,
    5879           0 :                                              libpq_gettext("out of memory\n"));
    5880           0 :                     return false;
    5881             :                 }
    5882           0 :                 continue;
    5883             :             }
    5884             :         }
    5885             : 
    5886             :         /*
    5887             :          * No environment variable specified or the variable isn't set - try
    5888             :          * compiled-in default
    5889             :          */
    5890      385452 :         if (option->compiled != NULL)
    5891             :         {
    5892      108280 :             option->val = strdup(option->compiled);
    5893      108280 :             if (!option->val)
    5894             :             {
    5895           0 :                 if (errorMessage)
    5896           0 :                     appendPQExpBufferStr(errorMessage,
    5897           0 :                                          libpq_gettext("out of memory\n"));
    5898           0 :                 return false;
    5899             :             }
    5900      108280 :             continue;
    5901             :         }
    5902             : 
    5903             :         /*
    5904             :          * Special handling for "user" option.  Note that if pg_fe_getauthname
    5905             :          * fails, we just leave the value as NULL; there's no need for this to
    5906             :          * be an error condition if the caller provides a user name.  The only
    5907             :          * reason we do this now at all is so that callers of PQconndefaults
    5908             :          * will see a correct default (barring error, of course).
    5909             :          */
    5910      277172 :         if (strcmp(option->keyword, "user") == 0)
    5911             :         {
    5912       11892 :             option->val = pg_fe_getauthname(NULL);
    5913       11892 :             continue;
    5914             :         }
    5915             :     }
    5916             : 
    5917       12692 :     return true;
    5918             : }
    5919             : 
    5920             : /*
    5921             :  * Subroutine for parse_connection_string
    5922             :  *
    5923             :  * Deal with a URI connection string.
    5924             :  */
    5925             : static PQconninfoOption *
    5926           0 : conninfo_uri_parse(const char *uri, PQExpBuffer errorMessage,
    5927             :                    bool use_defaults)
    5928             : {
    5929             :     PQconninfoOption *options;
    5930             : 
    5931             :     /* Make a working copy of PQconninfoOptions */
    5932           0 :     options = conninfo_init(errorMessage);
    5933           0 :     if (options == NULL)
    5934           0 :         return NULL;
    5935             : 
    5936           0 :     if (!conninfo_uri_parse_options(options, uri, errorMessage))
    5937             :     {
    5938           0 :         PQconninfoFree(options);
    5939           0 :         return NULL;
    5940             :     }
    5941             : 
    5942             :     /*
    5943             :      * Add in defaults if the caller wants that.
    5944             :      */
    5945           0 :     if (use_defaults)
    5946             :     {
    5947           0 :         if (!conninfo_add_defaults(options, errorMessage))
    5948             :         {
    5949           0 :             PQconninfoFree(options);
    5950           0 :             return NULL;
    5951             :         }
    5952             :     }
    5953             : 
    5954           0 :     return options;
    5955             : }
    5956             : 
    5957             : /*
    5958             :  * conninfo_uri_parse_options
    5959             :  *      Actual URI parser.
    5960             :  *
    5961             :  * If successful, returns true while the options array is filled with parsed
    5962             :  * options from the URI.
    5963             :  * If not successful, returns false and fills errorMessage accordingly.
    5964             :  *
    5965             :  * Parses the connection URI string in 'uri' according to the URI syntax (RFC
    5966             :  * 3986):
    5967             :  *
    5968             :  * postgresql://[user[:password]@][netloc][:port][/dbname][?param1=value1&...]
    5969             :  *
    5970             :  * where "netloc" is a hostname, an IPv4 address, or an IPv6 address surrounded
    5971             :  * by literal square brackets.  As an extension, we also allow multiple
    5972             :  * netloc[:port] specifications, separated by commas:
    5973             :  *
    5974             :  * postgresql://[user[:password]@][netloc][:port][,...][/dbname][?param1=value1&...]
    5975             :  *
    5976             :  * Any of the URI parts might use percent-encoding (%xy).
    5977             :  */
    5978             : static bool
    5979           0 : conninfo_uri_parse_options(PQconninfoOption *options, const char *uri,
    5980             :                            PQExpBuffer errorMessage)
    5981             : {
    5982             :     int         prefix_len;
    5983             :     char       *p;
    5984           0 :     char       *buf = NULL;
    5985             :     char       *start;
    5986           0 :     char        prevchar = '\0';
    5987           0 :     char       *user = NULL;
    5988           0 :     char       *host = NULL;
    5989           0 :     bool        retval = false;
    5990             :     PQExpBufferData hostbuf;
    5991             :     PQExpBufferData portbuf;
    5992             : 
    5993           0 :     initPQExpBuffer(&hostbuf);
    5994           0 :     initPQExpBuffer(&portbuf);
    5995           0 :     if (PQExpBufferDataBroken(hostbuf) || PQExpBufferDataBroken(portbuf))
    5996             :     {
    5997           0 :         appendPQExpBufferStr(errorMessage,
    5998           0 :                              libpq_gettext("out of memory\n"));
    5999           0 :         goto cleanup;
    6000             :     }
    6001             : 
    6002             :     /* need a modifiable copy of the input URI */
    6003           0 :     buf = strdup(uri);
    6004           0 :     if (buf == NULL)
    6005             :     {
    6006           0 :         appendPQExpBufferStr(errorMessage,
    6007           0 :                              libpq_gettext("out of memory\n"));
    6008           0 :         goto cleanup;
    6009             :     }
    6010           0 :     start = buf;
    6011             : 
    6012             :     /* Skip the URI prefix */
    6013           0 :     prefix_len = uri_prefix_length(uri);
    6014           0 :     if (prefix_len == 0)
    6015             :     {
    6016             :         /* Should never happen */
    6017           0 :         appendPQExpBuffer(errorMessage,
    6018           0 :                           libpq_gettext("invalid URI propagated to internal parser routine: \"%s\"\n"),
    6019             :                           uri);
    6020           0 :         goto cleanup;
    6021             :     }
    6022           0 :     start += prefix_len;
    6023           0 :     p = start;
    6024             : 
    6025             :     /* Look ahead for possible user credentials designator */
    6026           0 :     while (*p && *p != '@' && *p != '/')
    6027           0 :         ++p;
    6028           0 :     if (*p == '@')
    6029             :     {
    6030             :         /*
    6031             :          * Found username/password designator, so URI should be of the form
    6032             :          * "scheme://user[:password]@[netloc]".
    6033             :          */
    6034           0 :         user = start;
    6035             : 
    6036           0 :         p = user;
    6037           0 :         while (*p != ':' && *p != '@')
    6038           0 :             ++p;
    6039             : 
    6040             :         /* Save last char and cut off at end of user name */
    6041           0 :         prevchar = *p;
    6042           0 :         *p = '\0';
    6043             : 
    6044           0 :         if (*user &&
    6045           0 :             !conninfo_storeval(options, "user", user,
    6046             :                                errorMessage, false, true))
    6047           0 :             goto cleanup;
    6048             : 
    6049           0 :         if (prevchar == ':')
    6050             :         {
    6051           0 :             const char *password = p + 1;
    6052             : 
    6053           0 :             while (*p != '@')
    6054           0 :                 ++p;
    6055           0 :             *p = '\0';
    6056             : 
    6057           0 :             if (*password &&
    6058           0 :                 !conninfo_storeval(options, "password", password,
    6059             :                                    errorMessage, false, true))
    6060           0 :                 goto cleanup;
    6061             :         }
    6062             : 
    6063             :         /* Advance past end of parsed user name or password token */
    6064           0 :         ++p;
    6065             :     }
    6066             :     else
    6067             :     {
    6068             :         /*
    6069             :          * No username/password designator found.  Reset to start of URI.
    6070             :          */
    6071           0 :         p = start;
    6072             :     }
    6073             : 
    6074             :     /*
    6075             :      * There may be multiple netloc[:port] pairs, each separated from the next
    6076             :      * by a comma.  When we initially enter this loop, "p" has been
    6077             :      * incremented past optional URI credential information at this point and
    6078             :      * now points at the "netloc" part of the URI.  On subsequent loop
    6079             :      * iterations, "p" has been incremented past the comma separator and now
    6080             :      * points at the start of the next "netloc".
    6081             :      */
    6082             :     for (;;)
    6083             :     {
    6084             :         /*
    6085             :          * Look for IPv6 address.
    6086             :          */
    6087           0 :         if (*p == '[')
    6088             :         {
    6089           0 :             host = ++p;
    6090           0 :             while (*p && *p != ']')
    6091           0 :                 ++p;
    6092           0 :             if (!*p)
    6093             :             {
    6094           0 :                 appendPQExpBuffer(errorMessage,
    6095           0 :                                   libpq_gettext("end of string reached when looking for matching \"]\" in IPv6 host address in URI: \"%s\"\n"),
    6096             :                                   uri);
    6097           0 :                 goto cleanup;
    6098             :             }
    6099           0 :             if (p == host)
    6100             :             {
    6101           0 :                 appendPQExpBuffer(errorMessage,
    6102           0 :                                   libpq_gettext("IPv6 host address may not be empty in URI: \"%s\"\n"),
    6103             :                                   uri);
    6104           0 :                 goto cleanup;
    6105             :             }
    6106             : 
    6107             :             /* Cut off the bracket and advance */
    6108           0 :             *(p++) = '\0';
    6109             : 
    6110             :             /*
    6111             :              * The address may be followed by a port specifier or a slash or a
    6112             :              * query or a separator comma.
    6113             :              */
    6114           0 :             if (*p && *p != ':' && *p != '/' && *p != '?' && *p != ',')
    6115             :             {
    6116           0 :                 appendPQExpBuffer(errorMessage,
    6117           0 :                                   libpq_gettext("unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): \"%s\"\n"),
    6118           0 :                                   *p, (int) (p - buf + 1), uri);
    6119           0 :                 goto cleanup;
    6120             :             }
    6121             :         }
    6122             :         else
    6123             :         {
    6124             :             /* not an IPv6 address: DNS-named or IPv4 netloc */
    6125           0 :             host = p;
    6126             : 
    6127             :             /*
    6128             :              * Look for port specifier (colon) or end of host specifier
    6129             :              * (slash) or query (question mark) or host separator (comma).
    6130             :              */
    6131           0 :             while (*p && *p != ':' && *p != '/' && *p != '?' && *p != ',')
    6132           0 :                 ++p;
    6133             :         }
    6134             : 
    6135             :         /* Save the hostname terminator before we null it */
    6136           0 :         prevchar = *p;
    6137           0 :         *p = '\0';
    6138             : 
    6139           0 :         appendPQExpBufferStr(&hostbuf, host);
    6140             : 
    6141           0 :         if (prevchar == ':')
    6142             :         {
    6143           0 :             const char *port = ++p; /* advance past host terminator */
    6144             : 
    6145           0 :             while (*p && *p != '/' && *p != '?' && *p != ',')
    6146           0 :                 ++p;
    6147             : 
    6148           0 :             prevchar = *p;
    6149           0 :             *p = '\0';
    6150             : 
    6151           0 :             appendPQExpBufferStr(&portbuf, port);
    6152             :         }
    6153             : 
    6154           0 :         if (prevchar != ',')
    6155           0 :             break;
    6156           0 :         ++p;                    /* advance past comma separator */
    6157           0 :         appendPQExpBufferChar(&hostbuf, ',');
    6158           0 :         appendPQExpBufferChar(&portbuf, ',');
    6159             :     }
    6160             : 
    6161             :     /* Save final values for host and port. */
    6162           0 :     if (PQExpBufferDataBroken(hostbuf) || PQExpBufferDataBroken(portbuf))
    6163           0 :         goto cleanup;
    6164           0 :     if (hostbuf.data[0] &&
    6165           0 :         !conninfo_storeval(options, "host", hostbuf.data,
    6166             :                            errorMessage, false, true))
    6167           0 :         goto cleanup;
    6168           0 :     if (portbuf.data[0] &&
    6169           0 :         !conninfo_storeval(options, "port", portbuf.data,
    6170             :                            errorMessage, false, true))
    6171           0 :         goto cleanup;
    6172             : 
    6173           0 :     if (prevchar && prevchar != '?')
    6174             :     {
    6175           0 :         const char *dbname = ++p;   /* advance past host terminator */
    6176             : 
    6177             :         /* Look for query parameters */
    6178           0 :         while (*p && *p != '?')
    6179           0 :             ++p;
    6180             : 
    6181           0 :         prevchar = *p;
    6182           0 :         *p = '\0';
    6183             : 
    6184             :         /*
    6185             :          * Avoid setting dbname to an empty string, as it forces the default
    6186             :          * value (username) and ignores $PGDATABASE, as opposed to not setting
    6187             :          * it at all.
    6188             :          */
    6189           0 :         if (*dbname &&
    6190           0 :             !conninfo_storeval(options, "dbname", dbname,
    6191             :                                errorMessage, false, true))
    6192           0 :             goto cleanup;
    6193             :     }
    6194             : 
    6195           0 :     if (prevchar)
    6196             :     {
    6197           0 :         ++p;                    /* advance past terminator */
    6198             : 
    6199           0 :         if (!conninfo_uri_parse_params(p, options, errorMessage))
    6200           0 :             goto cleanup;
    6201             :     }
    6202             : 
    6203             :     /* everything parsed okay */
    6204           0 :     retval = true;
    6205             : 
    6206           0 : cleanup:
    6207           0 :     termPQExpBuffer(&hostbuf);
    6208           0 :     termPQExpBuffer(&portbuf);
    6209           0 :     if (buf)
    6210           0 :         free(buf);
    6211           0 :     return retval;
    6212             : }
    6213             : 
    6214             : /*
    6215             :  * Connection URI parameters parser routine
    6216             :  *
    6217             :  * If successful, returns true while connOptions is filled with parsed
    6218             :  * parameters.  Otherwise, returns false and fills errorMessage appropriately.
    6219             :  *
    6220             :  * Destructively modifies 'params' buffer.
    6221             :  */
    6222             : static bool
    6223           0 : conninfo_uri_parse_params(char *params,
    6224             :                           PQconninfoOption *connOptions,
    6225             :                           PQExpBuffer errorMessage)
    6226             : {
    6227           0 :     while (*params)
    6228             :     {
    6229           0 :         char       *keyword = params;
    6230           0 :         char       *value = NULL;
    6231           0 :         char       *p = params;
    6232           0 :         bool        malloced = false;
    6233             :         int         oldmsglen;
    6234             : 
    6235             :         /*
    6236             :          * Scan the params string for '=' and '&', marking the end of keyword
    6237             :          * and value respectively.
    6238             :          */
    6239             :         for (;;)
    6240             :         {
    6241           0 :             if (*p == '=')
    6242             :             {
    6243             :                 /* Was there '=' already? */
    6244           0 :                 if (value != NULL)
    6245             :                 {
    6246           0 :                     appendPQExpBuffer(errorMessage,
    6247           0 :                                       libpq_gettext("extra key/value separator \"=\" in URI query parameter: \"%s\"\n"),
    6248             :                                       keyword);
    6249           0 :                     return false;
    6250             :                 }
    6251             :                 /* Cut off keyword, advance to value */
    6252           0 :                 *p++ = '\0';
    6253           0 :                 value = p;
    6254             :             }
    6255           0 :             else if (*p == '&' || *p == '\0')
    6256             :             {
    6257             :                 /*
    6258             :                  * If not at the end, cut off value and advance; leave p
    6259             :                  * pointing to start of the next parameter, if any.
    6260             :                  */
    6261           0 :                 if (*p != '\0')
    6262           0 :                     *p++ = '\0';
    6263             :                 /* Was there '=' at all? */
    6264           0 :                 if (value == NULL)
    6265             :                 {
    6266           0 :                     appendPQExpBuffer(errorMessage,
    6267           0 :                                       libpq_gettext("missing key/value separator \"=\" in URI query parameter: \"%s\"\n"),
    6268             :                                       keyword);
    6269           0 :                     return false;
    6270             :                 }
    6271             :                 /* Got keyword and value, go process them. */
    6272           0 :                 break;
    6273             :             }
    6274             :             else
    6275           0 :                 ++p;            /* Advance over all other bytes. */
    6276             :         }
    6277             : 
    6278           0 :         keyword = conninfo_uri_decode(keyword, errorMessage);
    6279           0 :         if (keyword == NULL)
    6280             :         {
    6281             :             /* conninfo_uri_decode already set an error message */
    6282           0 :             return false;
    6283             :         }
    6284           0 :         value = conninfo_uri_decode(value, errorMessage);
    6285           0 :         if (value == NULL)
    6286             :         {
    6287             :             /* conninfo_uri_decode already set an error message */
    6288           0 :             free(keyword);
    6289           0 :             return false;
    6290             :         }
    6291           0 :         malloced = true;
    6292             : 
    6293             :         /*
    6294             :          * Special keyword handling for improved JDBC compatibility.
    6295             :          */
    6296           0 :         if (strcmp(keyword, "ssl") == 0 &&
    6297           0 :             strcmp(value, "true") == 0)
    6298             :         {
    6299           0 :             free(keyword);
    6300           0 :             free(value);
    6301           0 :             malloced = false;
    6302             : 
    6303           0 :             keyword = "sslmode";
    6304           0 :             value = "require";
    6305             :         }
    6306             : 
    6307             :         /*
    6308             :          * Store the value if the corresponding option exists; ignore
    6309             :          * otherwise.  At this point both keyword and value are not
    6310             :          * URI-encoded.
    6311             :          */
    6312           0 :         oldmsglen = errorMessage->len;
    6313           0 :         if (!conninfo_storeval(connOptions, keyword, value,
    6314             :                                errorMessage, true, false))
    6315             :         {
    6316             :             /* Insert generic message if conninfo_storeval didn't give one. */
    6317           0 :             if (errorMessage->len == oldmsglen)
    6318           0 :                 appendPQExpBuffer(errorMessage,
    6319           0 :                                   libpq_gettext("invalid URI query parameter: \"%s\"\n"),
    6320             :                                   keyword);
    6321             :             /* And fail. */
    6322           0 :             if (malloced)
    6323             :             {
    6324           0 :                 free(keyword);
    6325           0 :                 free(value);
    6326             :             }
    6327           0 :             return false;
    6328             :         }
    6329             : 
    6330           0 :         if (malloced)
    6331             :         {
    6332           0 :             free(keyword);
    6333           0 :             free(value);
    6334             :         }
    6335             : 
    6336             :         /* Proceed to next key=value pair, if any */
    6337           0 :         params = p;
    6338             :     }
    6339             : 
    6340           0 :     return true;
    6341             : }
    6342             : 
    6343             : /*
    6344             :  * Connection URI decoder routine
    6345             :  *
    6346             :  * If successful, returns the malloc'd decoded string.
    6347             :  * If not successful, returns NULL and fills errorMessage accordingly.
    6348             :  *
    6349             :  * The string is decoded by replacing any percent-encoded tokens with
    6350             :  * corresponding characters, while preserving any non-encoded characters.  A
    6351             :  * percent-encoded token is a character triplet: a percent sign, followed by a
    6352             :  * pair of hexadecimal digits (0-9A-F), where lower- and upper-case letters are
    6353             :  * treated identically.
    6354             :  */
    6355             : static char *
    6356           0 : conninfo_uri_decode(const char *str, PQExpBuffer errorMessage)
    6357             : {
    6358             :     char       *buf;
    6359             :     char       *p;
    6360           0 :     const char *q = str;
    6361             : 
    6362           0 :     buf = malloc(strlen(str) + 1);
    6363           0 :     if (buf == NULL)
    6364             :     {
    6365           0 :         appendPQExpBufferStr(errorMessage, libpq_gettext("out of memory\n"));
    6366           0 :         return NULL;
    6367             :     }
    6368           0 :     p = buf;
    6369             : 
    6370             :     for (;;)
    6371             :     {
    6372           0 :         if (*q != '%')
    6373             :         {
    6374             :             /* copy and check for NUL terminator */
    6375           0 :             if (!(*(p++) = *(q++)))
    6376           0 :                 break;
    6377             :         }
    6378             :         else
    6379             :         {
    6380             :             int         hi;
    6381             :             int         lo;
    6382             :             int         c;
    6383             : 
    6384           0 :             ++q;                /* skip the percent sign itself */
    6385             : 
    6386             :             /*
    6387             :              * Possible EOL will be caught by the first call to
    6388             :              * get_hexdigit(), so we never dereference an invalid q pointer.
    6389             :              */
    6390           0 :             if (!(get_hexdigit(*q++, &hi) && get_hexdigit(*q++, &lo)))
    6391             :             {
    6392           0 :                 appendPQExpBuffer(errorMessage,
    6393           0 :                                   libpq_gettext("invalid percent-encoded token: \"%s\"\n"),
    6394             :                                   str);
    6395           0 :                 free(buf);
    6396           0 :                 return NULL;
    6397             :             }
    6398             : 
    6399           0 :             c = (hi << 4) | lo;
    6400           0 :             if (c == 0)
    6401             :             {
    6402           0 :                 appendPQExpBuffer(errorMessage,
    6403           0 :                                   libpq_gettext("forbidden value %%00 in percent-encoded value: \"%s\"\n"),
    6404             :                                   str);
    6405           0 :                 free(buf);
    6406           0 :                 return NULL;
    6407             :             }
    6408           0 :             *(p++) = c;
    6409             :         }
    6410             :     }
    6411             : 
    6412           0 :     return buf;
    6413             : }
    6414             : 
    6415             : /*
    6416             :  * Convert hexadecimal digit character to its integer value.
    6417             :  *
    6418             :  * If successful, returns true and value is filled with digit's base 16 value.
    6419             :  * If not successful, returns false.
    6420             :  *
    6421             :  * Lower- and upper-case letters in the range A-F are treated identically.
    6422             :  */
    6423             : static bool
    6424           0 : get_hexdigit(char digit, int *value)
    6425             : {
    6426           0 :     if ('0' <= digit && digit <= '9')
    6427           0 :         *value = digit - '0';
    6428           0 :     else if ('A' <= digit && digit <= 'F')
    6429           0 :         *value = digit - 'A' + 10;
    6430           0 :     else if ('a' <= digit && digit <= 'f')
    6431           0 :         *value = digit - 'a' + 10;
    6432             :     else
    6433           0 :         return false;
    6434             : 
    6435           0 :     return true;
    6436             : }
    6437             : 
    6438             : /*
    6439             :  * Find an option value corresponding to the keyword in the connOptions array.
    6440             :  *
    6441             :  * If successful, returns a pointer to the corresponding option's value.
    6442             :  * If not successful, returns NULL.
    6443             :  */
    6444             : static const char *
    6445      456142 : conninfo_getval(PQconninfoOption *connOptions,
    6446             :                 const char *keyword)
    6447             : {
    6448             :     PQconninfoOption *option;
    6449             : 
    6450      456142 :     option = conninfo_find(connOptions, keyword);
    6451             : 
    6452      456142 :     return option ? option->val : NULL;
    6453             : }
    6454             : 
    6455             : /*
    6456             :  * Store a (new) value for an option corresponding to the keyword in
    6457             :  * connOptions array.
    6458             :  *
    6459             :  * If uri_decode is true, the value is URI-decoded.  The keyword is always
    6460             :  * assumed to be non URI-encoded.
    6461             :  *
    6462             :  * If successful, returns a pointer to the corresponding PQconninfoOption,
    6463             :  * which value is replaced with a strdup'd copy of the passed value string.
    6464             :  * The existing value for the option is free'd before replacing, if any.
    6465             :  *
    6466             :  * If not successful, returns NULL and fills errorMessage accordingly.
    6467             :  * However, if the reason of failure is an invalid keyword being passed and
    6468             :  * ignoreMissing is true, errorMessage will be left untouched.
    6469             :  */
    6470             : static PQconninfoOption *
    6471       29030 : conninfo_storeval(PQconninfoOption *connOptions,
    6472             :                   const char *keyword, const char *value,
    6473             :                   PQExpBuffer errorMessage, bool ignoreMissing,
    6474             :                   bool uri_decode)
    6475             : {
    6476             :     PQconninfoOption *option;
    6477             :     char       *value_copy;
    6478             : 
    6479             :     /*
    6480             :      * For backwards compatibility, requiressl=1 gets translated to
    6481             :      * sslmode=require, and requiressl=0 gets translated to sslmode=prefer
    6482             :      * (which is the default for sslmode).
    6483             :      */
    6484       29030 :     if (strcmp(keyword, "requiressl") == 0)
    6485             :     {
    6486           0 :         keyword = "sslmode";
    6487           0 :         if (value[0] == '1')
    6488           0 :             value = "require";
    6489             :         else
    6490           0 :             value = "prefer";
    6491             :     }
    6492             : 
    6493       29030 :     option = conninfo_find(connOptions, keyword);
    6494       29030 :     if (option == NULL)
    6495             :     {
    6496           0 :         if (!ignoreMissing)
    6497           0 :             appendPQExpBuffer(errorMessage,
    6498           0 :                               libpq_gettext("invalid connection option \"%s\"\n"),
    6499             :                               keyword);
    6500           0 :         return NULL;
    6501             :     }
    6502             : 
    6503       29030 :     if (uri_decode)
    6504             :     {
    6505           0 :         value_copy = conninfo_uri_decode(value, errorMessage);
    6506           0 :         if (value_copy == NULL)
    6507             :             /* conninfo_uri_decode already set an error message */
    6508           0 :             return NULL;
    6509             :     }
    6510             :     else
    6511             :     {
    6512       29030 :         value_copy = strdup(value);
    6513       29030 :         if (value_copy == NULL)
    6514             :         {
    6515           0 :             appendPQExpBufferStr(errorMessage, libpq_gettext("out of memory\n"));
    6516           0 :             return NULL;
    6517             :         }
    6518             :     }
    6519             : 
    6520       29030 :     if (option->val)
    6521          10 :         free(option->val);
    6522       29030 :     option->val = value_copy;
    6523             : 
    6524       29030 :     return option;
    6525             : }
    6526             : 
    6527             : /*
    6528             :  * Find a PQconninfoOption option corresponding to the keyword in the
    6529             :  * connOptions array.
    6530             :  *
    6531             :  * If successful, returns a pointer to the corresponding PQconninfoOption
    6532             :  * structure.
    6533             :  * If not successful, returns NULL.
    6534             :  */
    6535             : static PQconninfoOption *
    6536      485172 : conninfo_find(PQconninfoOption *connOptions, const char *keyword)
    6537             : {
    6538             :     PQconninfoOption *option;
    6539             : 
    6540     8741658 :     for (option = connOptions; option->keyword != NULL; option++)
    6541             :     {
    6542     8741658 :         if (strcmp(option->keyword, keyword) == 0)
    6543      485172 :             return option;
    6544             :     }
    6545             : 
    6546           0 :     return NULL;
    6547             : }
    6548             : 
    6549             : 
    6550             : /*
    6551             :  * Return the connection options used for the connection
    6552             :  */
    6553             : PQconninfoOption *
    6554         356 : PQconninfo(PGconn *conn)
    6555             : {
    6556             :     PQExpBufferData errorBuf;
    6557             :     PQconninfoOption *connOptions;
    6558             : 
    6559         356 :     if (conn == NULL)
    6560           0 :         return NULL;
    6561             : 
    6562             :     /*
    6563             :      * We don't actually report any errors here, but callees want a buffer,
    6564             :      * and we prefer not to trash the conn's errorMessage.
    6565             :      */
    6566         356 :     initPQExpBuffer(&errorBuf);
    6567         356 :     if (PQExpBufferDataBroken(errorBuf))
    6568           0 :         return NULL;            /* out of memory already :-( */
    6569             : 
    6570         356 :     connOptions = conninfo_init(&errorBuf);
    6571             : 
    6572         356 :     if (connOptions != NULL)
    6573             :     {
    6574             :         const internalPQconninfoOption *option;
    6575             : 
    6576       13172 :         for (option = PQconninfoOptions; option->keyword; option++)
    6577             :         {
    6578             :             char      **connmember;
    6579             : 
    6580       12816 :             if (option->connofs < 0)
    6581         356 :                 continue;
    6582             : 
    6583       12460 :             connmember = (char **) ((char *) conn + option->connofs);
    6584             : 
    6585       12460 :             if (*connmember)
    6586        5716 :                 conninfo_storeval(connOptions, option->keyword, *connmember,
    6587             :                                   &errorBuf, true, false);
    6588             :         }
    6589             :     }
    6590             : 
    6591         356 :     termPQExpBuffer(&errorBuf);
    6592             : 
    6593         356 :     return connOptions;
    6594             : }
    6595             : 
    6596             : 
    6597             : void
    6598       32032 : PQconninfoFree(PQconninfoOption *connOptions)
    6599             : {
    6600             :     PQconninfoOption *option;
    6601             : 
    6602       32032 :     if (connOptions == NULL)
    6603       11710 :         return;
    6604             : 
    6605      751914 :     for (option = connOptions; option->keyword != NULL; option++)
    6606             :     {
    6607      731592 :         if (option->val != NULL)
    6608      218984 :             free(option->val);
    6609             :     }
    6610       20322 :     free(connOptions);
    6611             : }
    6612             : 
    6613             : 
    6614             : /* =========== accessor functions for PGconn ========= */
    6615             : char *
    6616       19748 : PQdb(const PGconn *conn)
    6617             : {
    6618       19748 :     if (!conn)
    6619           2 :         return NULL;
    6620       19746 :     return conn->dbName;
    6621             : }
    6622             : 
    6623             : char *
    6624        8048 : PQuser(const PGconn *conn)
    6625             : {
    6626        8048 :     if (!conn)
    6627           0 :         return NULL;
    6628        8048 :     return conn->pguser;
    6629             : }
    6630             : 
    6631             : char *
    6632         416 : PQpass(const PGconn *conn)
    6633             : {
    6634         416 :     char       *password = NULL;
    6635             : 
    6636         416 :     if (!conn)
    6637           0 :         return NULL;
    6638         416 :     if (conn->connhost != NULL)
    6639         416 :         password = conn->connhost[conn->whichhost].password;
    6640         416 :     if (password == NULL)
    6641         416 :         password = conn->pgpass;
    6642             :     /* Historically we've returned "" not NULL for no password specified */
    6643         416 :     if (password == NULL)
    6644         374 :         password = "";
    6645         416 :     return password;
    6646             : }
    6647             : 
    6648             : char *
    6649        8228 : PQhost(const PGconn *conn)
    6650             : {
    6651        8228 :     if (!conn)
    6652           0 :         return NULL;
    6653             : 
    6654        8228 :     if (conn->connhost != NULL)
    6655             :     {
    6656             :         /*
    6657             :          * Return the verbatim host value provided by user, or hostaddr in its
    6658             :          * lack.
    6659             :          */
    6660        8228 :         if (conn->connhost[conn->whichhost].host != NULL &&
    6661        8228 :             conn->connhost[conn->whichhost].host[0] != '\0')
    6662        8228 :             return conn->connhost[conn->whichhost].host;
    6663           0 :         else if (conn->connhost[conn->whichhost].hostaddr != NULL &&
    6664           0 :                  conn->connhost[conn->whichhost].hostaddr[0] != '\0')
    6665           0 :             return conn->connhost[conn->whichhost].hostaddr;
    6666             :     }
    6667             : 
    6668           0 :     return "";
    6669             : }
    6670             : 
    6671             : char *
    6672           0 : PQhostaddr(const PGconn *conn)
    6673             : {
    6674           0 :     if (!conn)
    6675           0 :         return NULL;
    6676             : 
    6677             :     /* Return the parsed IP address */
    6678           0 :     if (conn->connhost != NULL && conn->connip != NULL)
    6679           0 :         return conn->connip;
    6680             : 
    6681           0 :     return "";
    6682             : }
    6683             : 
    6684             : char *
    6685        8228 : PQport(const PGconn *conn)
    6686             : {
    6687        8228 :     if (!conn)
    6688           0 :         return NULL;
    6689             : 
    6690        8228 :     if (conn->connhost != NULL)
    6691        8228 :         return conn->connhost[conn->whichhost].port;
    6692             : 
    6693           0 :     return "";
    6694             : }
    6695             : 
    6696             : /*
    6697             :  * No longer does anything, but the function remains for API backwards
    6698             :  * compatibility.
    6699             :  */
    6700             : char *
    6701           0 : PQtty(const PGconn *conn)
    6702             : {
    6703           0 :     if (!conn)
    6704           0 :         return NULL;
    6705           0 :     return "";
    6706             : }
    6707             : 
    6708             : char *
    6709           0 : PQoptions(const PGconn *conn)
    6710             : {
    6711           0 :     if (!conn)
    6712           0 :         return NULL;
    6713           0 :     return conn->pgoptions;
    6714             : }
    6715             : 
    6716             : ConnStatusType
    6717       47998 : PQstatus(const PGconn *conn)
    6718             : {
    6719       47998 :     if (!conn)
    6720           0 :         return CONNECTION_BAD;
    6721       47998 :     return conn->status;
    6722             : }
    6723             : 
    6724             : PGTransactionStatusType
    6725      197094 : PQtransactionStatus(const PGconn *conn)
    6726             : {
    6727      197094 :     if (!conn || conn->status != CONNECTION_OK)
    6728           0 :         return PQTRANS_UNKNOWN;
    6729      197094 :     if (conn->asyncStatus != PGASYNC_IDLE)
    6730           4 :         return PQTRANS_ACTIVE;
    6731      197090 :     return conn->xactStatus;
    6732             : }
    6733             : 
    6734             : const char *
    6735      364402 : PQparameterStatus(const PGconn *conn, const char *paramName)
    6736             : {
    6737             :     const pgParameterStatus *pstatus;
    6738             : 
    6739      364402 :     if (!conn || !paramName)
    6740           0 :         return NULL;
    6741      841248 :     for (pstatus = conn->pstatus; pstatus != NULL; pstatus = pstatus->next)
    6742             :     {
    6743      841248 :         if (strcmp(pstatus->name, paramName) == 0)
    6744      364402 :             return pstatus->value;
    6745             :     }
    6746           0 :     return NULL;
    6747             : }
    6748             : 
    6749             : int
    6750           0 : PQprotocolVersion(const PGconn *conn)
    6751             : {
    6752           0 :     if (!conn)
    6753           0 :         return 0;
    6754           0 :     if (conn->status == CONNECTION_BAD)
    6755           0 :         return 0;
    6756           0 :     return PG_PROTOCOL_MAJOR(conn->pversion);
    6757             : }
    6758             : 
    6759             : int
    6760       20880 : PQserverVersion(const PGconn *conn)
    6761             : {
    6762       20880 :     if (!conn)
    6763           0 :         return 0;
    6764       20880 :     if (conn->status == CONNECTION_BAD)
    6765           0 :         return 0;
    6766       20880 :     return conn->sversion;
    6767             : }
    6768             : 
    6769             : char *
    6770       21200 : PQerrorMessage(const PGconn *conn)
    6771             : {
    6772       21200 :     if (!conn)
    6773           0 :         return libpq_gettext("connection pointer is NULL\n");
    6774             : 
    6775             :     /*
    6776             :      * The errorMessage buffer might be marked "broken" due to having
    6777             :      * previously failed to allocate enough memory for the message.  In that
    6778             :      * case, tell the application we ran out of memory.
    6779             :      */
    6780       21200 :     if (PQExpBufferBroken(&conn->errorMessage))
    6781           0 :         return libpq_gettext("out of memory\n");
    6782             : 
    6783       21200 :     return conn->errorMessage.data;
    6784             : }
    6785             : 
    6786             : /*
    6787             :  * In Windows, socket values are unsigned, and an invalid socket value
    6788             :  * (INVALID_SOCKET) is ~0, which equals -1 in comparisons (with no compiler
    6789             :  * warning). Ideally we would return an unsigned value for PQsocket() on
    6790             :  * Windows, but that would cause the function's return value to differ from
    6791             :  * Unix, so we just return -1 for invalid sockets.
    6792             :  * http://msdn.microsoft.com/en-us/library/windows/desktop/cc507522%28v=vs.85%29.aspx
    6793             :  * http://stackoverflow.com/questions/10817252/why-is-invalid-socket-defined-as-0-in-winsock2-h-c
    6794             :  */
    6795             : int
    6796      249732 : PQsocket(const PGconn *conn)
    6797             : {
    6798      249732 :     if (!conn)
    6799           0 :         return -1;
    6800      249732 :     return (conn->sock != PGINVALID_SOCKET) ? conn->sock : -1;
    6801             : }
    6802             : 
    6803             : int
    6804        1074 : PQbackendPID(const PGconn *conn)
    6805             : {
    6806        1074 :     if (!conn || conn->status != CONNECTION_OK)
    6807           0 :         return 0;
    6808        1074 :     return conn->be_pid;
    6809             : }
    6810             : 
    6811             : PGpipelineStatus
    6812       30596 : PQpipelineStatus(const PGconn *conn)
    6813             : {
    6814       30596 :     if (!conn)
    6815           0 :         return PQ_PIPELINE_OFF;
    6816             : 
    6817       30596 :     return conn->pipelineStatus;
    6818             : }
    6819             : 
    6820             : int
    6821         416 : PQconnectionNeedsPassword(const PGconn *conn)
    6822             : {
    6823             :     char       *password;
    6824             : 
    6825         416 :     if (!conn)
    6826           0 :         return false;
    6827         416 :     password = PQpass(conn);
    6828         416 :     if (conn->password_needed &&
    6829          34 :         (password == NULL || password[0] == '\0'))
    6830           2 :         return true;
    6831             :     else
    6832         414 :         return false;
    6833             : }
    6834             : 
    6835             : int
    6836         294 : PQconnectionUsedPassword(const PGconn *conn)
    6837             : {
    6838         294 :     if (!conn)
    6839           0 :         return false;
    6840         294 :     if (conn->password_needed)
    6841           0 :         return true;
    6842             :     else
    6843         294 :         return false;
    6844             : }
    6845             : 
    6846             : int
    6847      193978 : PQclientEncoding(const PGconn *conn)
    6848             : {
    6849      193978 :     if (!conn || conn->status != CONNECTION_OK)
    6850           0 :         return -1;
    6851      193978 :     return conn->client_encoding;
    6852             : }
    6853             : 
    6854             : int
    6855          20 : PQsetClientEncoding(PGconn *conn, const char *encoding)
    6856             : {
    6857             :     char        qbuf[128];
    6858             :     static const char query[] = "set client_encoding to '%s'";
    6859             :     PGresult   *res;
    6860             :     int         status;
    6861             : 
    6862          20 :     if (!conn || conn->status != CONNECTION_OK)
    6863           0 :         return -1;
    6864             : 
    6865          20 :     if (!encoding)
    6866           0 :         return -1;
    6867             : 
    6868             :     /* Resolve special "auto" value from the locale */
    6869          20 :     if (strcmp(encoding, "auto") == 0)
    6870           0 :         encoding = pg_encoding_to_char(pg_get_encoding_from_locale(NULL, true));
    6871             : 
    6872             :     /* check query buffer overflow */
    6873          20 :     if (sizeof(qbuf) < (sizeof(query) + strlen(encoding)))
    6874           0 :         return -1;
    6875             : 
    6876             :     /* ok, now send a query */
    6877          20 :     sprintf(qbuf, query, encoding);
    6878          20 :     res = PQexec(conn, qbuf);
    6879             : 
    6880          20 :     if (res == NULL)
    6881           0 :         return -1;
    6882          20 :     if (res->resultStatus != PGRES_COMMAND_OK)
    6883           0 :         status = -1;
    6884             :     else
    6885             :     {
    6886             :         /*
    6887             :          * We rely on the backend to report the parameter value, and we'll
    6888             :          * change state at that time.
    6889             :          */
    6890          20 :         status = 0;             /* everything is ok */
    6891             :     }
    6892          20 :     PQclear(res);
    6893          20 :     return status;
    6894             : }
    6895             : 
    6896             : PGVerbosity
    6897        8096 : PQsetErrorVerbosity(PGconn *conn, PGVerbosity verbosity)
    6898             : {
    6899             :     PGVerbosity old;
    6900             : 
    6901        8096 :     if (!conn)
    6902           0 :         return PQERRORS_DEFAULT;
    6903        8096 :     old = conn->verbosity;
    6904        8096 :     conn->verbosity = verbosity;
    6905        8096 :     return old;
    6906             : }
    6907             : 
    6908             : PGContextVisibility
    6909        8062 : PQsetErrorContextVisibility(PGconn *conn, PGContextVisibility show_context)
    6910             : {
    6911             :     PGContextVisibility old;
    6912             : 
    6913        8062 :     if (!conn)
    6914           0 :         return PQSHOW_CONTEXT_ERRORS;
    6915        8062 :     old = conn->show_context;
    6916        8062 :     conn->show_context = show_context;
    6917        8062 :     return old;
    6918             : }
    6919             : 
    6920             : PQnoticeReceiver
    6921         514 : PQsetNoticeReceiver(PGconn *conn, PQnoticeReceiver proc, void *arg)
    6922             : {
    6923             :     PQnoticeReceiver old;
    6924             : 
    6925         514 :     if (conn == NULL)
    6926           0 :         return NULL;
    6927             : 
    6928         514 :     old = conn->noticeHooks.noticeRec;
    6929         514 :     if (proc)
    6930             :     {
    6931         514 :         conn->noticeHooks.noticeRec = proc;
    6932         514 :         conn->noticeHooks.noticeRecArg = arg;
    6933             :     }
    6934         514 :     return old;
    6935             : }
    6936             : 
    6937             : PQnoticeProcessor
    6938        9096 : PQsetNoticeProcessor(PGconn *conn, PQnoticeProcessor proc, void *arg)
    6939             : {
    6940             :     PQnoticeProcessor old;
    6941             : 
    6942        9096 :     if (conn == NULL)
    6943           0 :         return NULL;
    6944             : 
    6945        9096 :     old = conn->noticeHooks.noticeProc;
    6946        9096 :     if (proc)
    6947             :     {
    6948        9096 :         conn->noticeHooks.noticeProc = proc;
    6949        9096 :         conn->noticeHooks.noticeProcArg = arg;
    6950             :     }
    6951        9096 :     return old;
    6952             : }
    6953             : 
    6954             : /*
    6955             :  * The default notice message receiver just gets the standard notice text
    6956             :  * and sends it to the notice processor.  This two-level setup exists
    6957             :  * mostly for backwards compatibility; perhaps we should deprecate use of
    6958             :  * PQsetNoticeProcessor?
    6959             :  */
    6960             : static void
    6961       14272 : defaultNoticeReceiver(void *arg, const PGresult *res)
    6962             : {
    6963             :     (void) arg;                 /* not used */
    6964       14272 :     if (res->noticeHooks.noticeProc != NULL)
    6965       14272 :         res->noticeHooks.noticeProc(res->noticeHooks.noticeProcArg,
    6966       14272 :                                     PQresultErrorMessage(res));
    6967       14272 : }
    6968             : 
    6969             : /*
    6970             :  * The default notice message processor just prints the
    6971             :  * message on stderr.  Applications can override this if they
    6972             :  * want the messages to go elsewhere (a window, for example).
    6973             :  * Note that simply discarding notices is probably a bad idea.
    6974             :  */
    6975             : static void
    6976          88 : defaultNoticeProcessor(void *arg, const char *message)
    6977             : {
    6978             :     (void) arg;                 /* not used */
    6979             :     /* Note: we expect the supplied string to end with a newline already. */
    6980          88 :     fprintf(stderr, "%s", message);
    6981          88 : }
    6982             : 
    6983             : /*
    6984             :  * returns a pointer to the next token or NULL if the current
    6985             :  * token doesn't match
    6986             :  */
    6987             : static char *
    6988          32 : pwdfMatchesString(char *buf, const char *token)
    6989             : {
    6990             :     char       *tbuf;
    6991             :     const char *ttok;
    6992          32 :     bool        bslash = false;
    6993             : 
    6994          32 :     if (buf == NULL || token == NULL)
    6995           0 :         return NULL;
    6996          32 :     tbuf = buf;
    6997          32 :     ttok = token;
    6998          32 :     if (tbuf[0] == '*' && tbuf[1] == ':')
    6999          18 :         return tbuf + 2;
    7000          98 :     while (*tbuf != 0)
    7001             :     {
    7002          98 :         if (*tbuf == '\\' && !bslash)
    7003             :         {
    7004           0 :             tbuf++;
    7005           0 :             bslash = true;
    7006             :         }
    7007          98 :         if (*tbuf == ':' && *ttok == 0 && !bslash)
    7008          10 :             return tbuf + 1;
    7009          88 :         bslash = false;
    7010          88 :         if (*ttok == 0)
    7011           0 :             return NULL;
    7012          88 :         if (*tbuf == *ttok)
    7013             :         {
    7014          84 :             tbuf++;
    7015          84 :             ttok++;
    7016             :         }
    7017             :         else
    7018           4 :             return NULL;
    7019             :     }
    7020           0 :     return NULL;
    7021             : }
    7022             : 
    7023             : /* Get a password from the password file. Return value is malloc'd. */
    7024             : static char *
    7025       12558 : passwordFromFile(const char *hostname, const char *port, const char *dbname,
    7026             :                  const char *username, const char *pgpassfile)
    7027             : {
    7028             :     FILE       *fp;
    7029             :     struct stat stat_buf;
    7030             :     PQExpBufferData buf;
    7031             : 
    7032       12558 :     if (dbname == NULL || dbname[0] == '\0')
    7033           0 :         return NULL;
    7034             : 
    7035       12558 :     if (username == NULL || username[0] == '\0')
    7036           0 :         return NULL;
    7037             : 
    7038             :     /* 'localhost' matches pghost of '' or the default socket directory */
    7039       12558 :     if (hostname == NULL || hostname[0] == '\0')
    7040           0 :         hostname = DefaultHost;
    7041       12558 :     else if (is_unixsock_path(hostname))
    7042             : 
    7043             :         /*
    7044             :          * We should probably use canonicalize_path(), but then we have to
    7045             :          * bring path.c into libpq, and it doesn't seem worth it.
    7046             :          */
    7047       12210 :         if (strcmp(hostname, DEFAULT_PGSOCKET_DIR) == 0)
    7048           0 :             hostname = DefaultHost;
    7049             : 
    7050       12558 :     if (port == NULL || port[0] == '\0')
    7051           0 :         port = DEF_PGPORT_STR;
    7052             : 
    7053             :     /* If password file cannot be opened, ignore it. */
    7054       12558 :     if (stat(pgpassfile, &stat_buf) != 0)
    7055       12552 :         return NULL;
    7056             : 
    7057             : #ifndef WIN32
    7058           6 :     if (!S_ISREG(stat_buf.st_mode))
    7059             :     {
    7060           0 :         fprintf(stderr,
    7061           0 :                 libpq_gettext("WARNING: password file \"%s\" is not a plain file\n"),
    7062             :                 pgpassfile);
    7063           0 :         return NULL;
    7064             :     }
    7065             : 
    7066             :     /* If password file is insecure, alert the user and ignore it. */
    7067           6 :     if (stat_buf.st_mode & (S_IRWXG | S_IRWXO))
    7068             :     {
    7069           0 :         fprintf(stderr,
    7070           0 :                 libpq_gettext("WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n"),
    7071             :                 pgpassfile);
    7072           0 :         return NULL;
    7073             :     }
    7074             : #else
    7075             : 
    7076             :     /*
    7077             :      * On Win32, the directory is protected, so we don't have to check the
    7078             :      * file.
    7079             :      */
    7080             : #endif
    7081             : 
    7082           6 :     fp = fopen(pgpassfile, "r");
    7083           6 :     if (fp == NULL)
    7084           0 :         return NULL;
    7085             : 
    7086             :     /* Use an expansible buffer to accommodate any reasonable line length */
    7087           6 :     initPQExpBuffer(&buf);
    7088             : 
    7089          30 :     while (!feof(fp) && !ferror(fp))
    7090             :     {
    7091             :         /* Make sure there's a reasonable amount of room in the buffer */
    7092          30 :         if (!enlargePQExpBuffer(&buf, 128))
    7093           0 :             break;
    7094             : 
    7095             :         /* Read some data, appending it to what we already have */
    7096          30 :         if (fgets(buf.data + buf.len, buf.maxlen - buf.len, fp) == NULL)
    7097           2 :             break;
    7098          28 :         buf.len += strlen(buf.data + buf.len);
    7099             : 
    7100             :         /* If we don't yet have a whole line, loop around to read more */
    7101          28 :         if (!(buf.len > 0 && buf.data[buf.len - 1] == '\n') && !feof(fp))
    7102           6 :             continue;
    7103             : 
    7104             :         /* ignore comments */
    7105          22 :         if (buf.data[0] != '#')
    7106             :         {
    7107          16 :             char       *t = buf.data;
    7108             :             int         len;
    7109             : 
    7110             :             /* strip trailing newline and carriage return */
    7111          16 :             len = pg_strip_crlf(t);
    7112             : 
    7113          24 :             if (len > 0 &&
    7114          16 :                 (t = pwdfMatchesString(t, hostname)) != NULL &&
    7115          16 :                 (t = pwdfMatchesString(t, port)) != NULL &&
    7116          16 :                 (t = pwdfMatchesString(t, dbname)) != NULL &&
    7117           8 :                 (t = pwdfMatchesString(t, username)) != NULL)
    7118             :             {
    7119             :                 /* Found a match. */
    7120             :                 char       *ret,
    7121             :                            *p1,
    7122             :                            *p2;
    7123             : 
    7124           4 :                 ret = strdup(t);
    7125             : 
    7126           4 :                 fclose(fp);
    7127           4 :                 explicit_bzero(buf.data, buf.maxlen);
    7128           4 :                 termPQExpBuffer(&buf);
    7129             : 
    7130           4 :                 if (!ret)
    7131             :                 {
    7132             :                     /* Out of memory. XXX: an error message would be nice. */
    7133           0 :                     return NULL;
    7134             :                 }
    7135             : 
    7136             :                 /* De-escape password. */
    7137          20 :                 for (p1 = p2 = ret; *p1 != ':' && *p1 != '\0'; ++p1, ++p2)
    7138             :                 {
    7139          16 :                     if (*p1 == '\\' && p1[1] != '\0')
    7140           2 :                         ++p1;
    7141          16 :                     *p2 = *p1;
    7142             :                 }
    7143           4 :                 *p2 = '\0';
    7144             : 
    7145           4 :                 return ret;
    7146             :             }
    7147             :         }
    7148             : 
    7149             :         /* No match, reset buffer to prepare for next line. */
    7150          18 :         buf.len = 0;
    7151             :     }
    7152             : 
    7153           2 :     fclose(fp);
    7154           2 :     explicit_bzero(buf.data, buf.maxlen);
    7155           2 :     termPQExpBuffer(&buf);
    7156           2 :     return NULL;
    7157             : }
    7158             : 
    7159             : 
    7160             : /*
    7161             :  *  If the connection failed due to bad password, we should mention
    7162             :  *  if we got the password from the pgpassfile.
    7163             :  */
    7164             : static void
    7165          44 : pgpassfileWarning(PGconn *conn)
    7166             : {
    7167             :     /* If it was 'invalid authorization', add pgpassfile mention */
    7168             :     /* only works with >= 9.0 servers */
    7169          44 :     if (conn->password_needed &&
    7170          32 :         conn->connhost[conn->whichhost].password != NULL &&
    7171           0 :         conn->result)
    7172             :     {
    7173           0 :         const char *sqlstate = PQresultErrorField(conn->result,
    7174             :                                                   PG_DIAG_SQLSTATE);
    7175             : 
    7176           0 :         if (sqlstate && strcmp(sqlstate, ERRCODE_INVALID_PASSWORD) == 0)
    7177           0 :             appendPQExpBuffer(&conn->errorMessage,
    7178           0 :                               libpq_gettext("password retrieved from file \"%s\"\n"),
    7179             :                               conn->pgpassfile);
    7180             :     }
    7181          44 : }
    7182             : 
    7183             : /*
    7184             :  * Check if the SSL protocol value given in input is valid or not.
    7185             :  * This is used as a sanity check routine for the connection parameters
    7186             :  * ssl_min_protocol_version and ssl_max_protocol_version.
    7187             :  */
    7188             : static bool
    7189       25334 : sslVerifyProtocolVersion(const char *version)
    7190             : {
    7191             :     /*
    7192             :      * An empty string and a NULL value are considered valid as it is
    7193             :      * equivalent to ignoring the parameter.
    7194             :      */
    7195       25334 :     if (!version || strlen(version) == 0)
    7196       12658 :         return true;
    7197             : 
    7198       25352 :     if (pg_strcasecmp(version, "TLSv1") == 0 ||
    7199       25350 :         pg_strcasecmp(version, "TLSv1.1") == 0 ||
    7200       12678 :         pg_strcasecmp(version, "TLSv1.2") == 0 ||
    7201           4 :         pg_strcasecmp(version, "TLSv1.3") == 0)
    7202       12672 :         return true;
    7203             : 
    7204             :     /* anything else is wrong */
    7205           4 :     return false;
    7206             : }
    7207             : 
    7208             : 
    7209             : /*
    7210             :  * Ensure that the SSL protocol range given in input is correct.  The check
    7211             :  * is performed on the input string to keep it TLS backend agnostic.  Input
    7212             :  * to this function is expected verified with sslVerifyProtocolVersion().
    7213             :  */
    7214             : static bool
    7215       12664 : sslVerifyProtocolRange(const char *min, const char *max)
    7216             : {
    7217             :     Assert(sslVerifyProtocolVersion(min) &&
    7218             :            sslVerifyProtocolVersion(max));
    7219             : 
    7220             :     /* If at least one of the bounds is not set, the range is valid */
    7221       12664 :     if (min == NULL || max == NULL || strlen(min) == 0 || strlen(max) == 0)
    7222       12658 :         return true;
    7223             : 
    7224             :     /*
    7225             :      * If the minimum version is the lowest one we accept, then all options
    7226             :      * for the maximum are valid.
    7227             :      */
    7228           6 :     if (pg_strcasecmp(min, "TLSv1") == 0)
    7229           0 :         return true;
    7230             : 
    7231             :     /*
    7232             :      * The minimum bound is valid, and cannot be TLSv1, so using TLSv1 for the
    7233             :      * maximum is incorrect.
    7234             :      */
    7235           6 :     if (pg_strcasecmp(max, "TLSv1") == 0)
    7236           0 :         return false;
    7237             : 
    7238             :     /*
    7239             :      * At this point we know that we have a mix of TLSv1.1 through 1.3
    7240             :      * versions.
    7241             :      */
    7242           6 :     if (pg_strcasecmp(min, max) > 0)
    7243           2 :         return false;
    7244             : 
    7245           4 :     return true;
    7246             : }
    7247             : 
    7248             : 
    7249             : /*
    7250             :  * Obtain user's home directory, return in given buffer
    7251             :  *
    7252             :  * On Unix, this actually returns the user's home directory.  On Windows
    7253             :  * it returns the PostgreSQL-specific application data folder.
    7254             :  *
    7255             :  * This is essentially the same as get_home_path(), but we don't use that
    7256             :  * because we don't want to pull path.c into libpq (it pollutes application
    7257             :  * namespace).
    7258             :  *
    7259             :  * Returns true on success, false on failure to obtain the directory name.
    7260             :  *
    7261             :  * CAUTION: although in most situations failure is unexpected, there are users
    7262             :  * who like to run applications in a home-directory-less environment.  On
    7263             :  * failure, you almost certainly DO NOT want to report an error.  Just act as
    7264             :  * though whatever file you were hoping to find in the home directory isn't
    7265             :  * there (which it isn't).
    7266             :  */
    7267             : bool
    7268       12484 : pqGetHomeDirectory(char *buf, int bufsize)
    7269             : {
    7270             : #ifndef WIN32
    7271             :     char        pwdbuf[BUFSIZ];
    7272             :     struct passwd pwdstr;
    7273       12484 :     struct passwd *pwd = NULL;
    7274             : 
    7275       12484 :     (void) pqGetpwuid(geteuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd);
    7276       12484 :     if (pwd == NULL)
    7277           0 :         return false;
    7278       12484 :     strlcpy(buf, pwd->pw_dir, bufsize);
    7279       12484 :     return true;
    7280             : #else
    7281             :     char        tmppath[MAX_PATH];
    7282             : 
    7283             :     ZeroMemory(tmppath, sizeof(tmppath));
    7284             :     if (SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, tmppath) != S_OK)
    7285             :         return false;
    7286             :     snprintf(buf, bufsize, "%s/postgresql", tmppath);
    7287             :     return true;
    7288             : #endif
    7289             : }
    7290             : 
    7291             : /*
    7292             :  * To keep the API consistent, the locking stubs are always provided, even
    7293             :  * if they are not required.
    7294             :  *
    7295             :  * Since we neglected to provide any error-return convention in the
    7296             :  * pgthreadlock_t API, we can't do much except Assert upon failure of any
    7297             :  * mutex primitive.  Fortunately, such failures appear to be nonexistent in
    7298             :  * the field.
    7299             :  */
    7300             : 
    7301             : static void
    7302       23784 : default_threadlock(int acquire)
    7303             : {
    7304             : #ifdef ENABLE_THREAD_SAFETY
    7305             : #ifndef WIN32
    7306             :     static pthread_mutex_t singlethread_lock = PTHREAD_MUTEX_INITIALIZER;
    7307             : #else
    7308             :     static pthread_mutex_t singlethread_lock = NULL;
    7309             :     static long mutex_initlock = 0;
    7310             : 
    7311             :     if (singlethread_lock == NULL)
    7312             :     {
    7313             :         while (InterlockedExchange(&mutex_initlock, 1) == 1)
    7314             :              /* loop, another thread own the lock */ ;
    7315             :         if (singlethread_lock == NULL)
    7316             :         {
    7317             :             if (pthread_mutex_init(&singlethread_lock, NULL))
    7318             :                 Assert(false);
    7319             :         }
    7320             :         InterlockedExchange(&mutex_initlock, 0);
    7321             :     }
    7322             : #endif
    7323       23784 :     if (acquire)
    7324             :     {
    7325       11892 :         if (pthread_mutex_lock(&singlethread_lock))
    7326             :             Assert(false);
    7327             :     }
    7328             :     else
    7329             :     {
    7330       11892 :         if (pthread_mutex_unlock(&singlethread_lock))
    7331             :             Assert(false);
    7332             :     }
    7333             : #endif
    7334       23784 : }
    7335             : 
    7336             : pgthreadlock_t
    7337           0 : PQregisterThreadLock(pgthreadlock_t newhandler)
    7338             : {
    7339           0 :     pgthreadlock_t prev = pg_g_threadlock;
    7340             : 
    7341           0 :     if (newhandler)
    7342           0 :         pg_g_threadlock = newhandler;
    7343             :     else
    7344           0 :         pg_g_threadlock = default_threadlock;
    7345             : 
    7346           0 :     return prev;
    7347             : }

Generated by: LCOV version 1.14