Header And Logo

PostgreSQL
| The world's most advanced open source database.

Data Structures | Defines | Typedefs | Functions | Variables

fe-connect.c File Reference

#include "postgres_fe.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <ctype.h>
#include <time.h>
#include <unistd.h>
#include "libpq-fe.h"
#include "libpq-int.h"
#include "fe-auth.h"
#include "pg_config_paths.h"
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "libpq/ip.h"
#include "mb/pg_wchar.h"
Include dependency graph for fe-connect.c:

Go to the source code of this file.

Data Structures

struct  _internalPQconninfoOption

Defines

#define PGPASSFILE   ".pgpass"
#define ERRCODE_APPNAME_UNKNOWN   "42704"
#define ERRCODE_INVALID_PASSWORD   "28P01"
#define ERRCODE_CANNOT_CONNECT_NOW   "57P03"
#define DefaultHost   "localhost"
#define DefaultTty   ""
#define DefaultOption   ""
#define DefaultAuthtype   ""
#define DefaultPassword   ""
#define DefaultSSLMode   "disable"
#define MAXBUFSIZE   256
#define LINELEN   NAMEDATALEN*5

Typedefs

typedef struct
_internalPQconninfoOption 
internalPQconninfoOption

Functions

static bool connectOptions1 (PGconn *conn, const char *conninfo)
static bool connectOptions2 (PGconn *conn)
static int connectDBStart (PGconn *conn)
static int connectDBComplete (PGconn *conn)
static PGPing internal_ping (PGconn *conn)
static PGconnmakeEmptyPGconn (void)
static void fillPGconn (PGconn *conn, PQconninfoOption *connOptions)
static void freePGconn (PGconn *conn)
static void closePGconn (PGconn *conn)
static PQconninfoOptionconninfo_init (PQExpBuffer errorMessage)
static PQconninfoOptionparse_connection_string (const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
static int uri_prefix_length (const char *connstr)
static bool recognized_connection_string (const char *connstr)
static PQconninfoOptionconninfo_parse (const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
static PQconninfoOptionconninfo_array_parse (const char *const *keywords, const char *const *values, PQExpBuffer errorMessage, bool use_defaults, int expand_dbname)
static bool conninfo_add_defaults (PQconninfoOption *options, PQExpBuffer errorMessage)
static PQconninfoOptionconninfo_uri_parse (const char *uri, PQExpBuffer errorMessage, bool use_defaults)
static bool conninfo_uri_parse_options (PQconninfoOption *options, const char *uri, PQExpBuffer errorMessage)
static bool conninfo_uri_parse_params (char *params, PQconninfoOption *connOptions, PQExpBuffer errorMessage)
static char * conninfo_uri_decode (const char *str, PQExpBuffer errorMessage)
static bool get_hexdigit (char digit, int *value)
static const char * conninfo_getval (PQconninfoOption *connOptions, const char *keyword)
static PQconninfoOptionconninfo_storeval (PQconninfoOption *connOptions, const char *keyword, const char *value, PQExpBuffer errorMessage, bool ignoreMissing, bool uri_decode)
static PQconninfoOptionconninfo_find (PQconninfoOption *connOptions, const char *keyword)
static void defaultNoticeReceiver (void *arg, const PGresult *res)
static void defaultNoticeProcessor (void *arg, const char *message)
static int parseServiceInfo (PQconninfoOption *options, PQExpBuffer errorMessage)
static int parseServiceFile (const char *serviceFile, const char *service, PQconninfoOption *options, PQExpBuffer errorMessage, bool *group_found)
static char * pwdfMatchesString (char *buf, char *token)
static char * PasswordFromFile (char *hostname, char *port, char *dbname, char *username)
static bool getPgPassFilename (char *pgpassfile)
static void dot_pg_pass_warning (PGconn *conn)
static void default_threadlock (int acquire)
void pqDropConnection (PGconn *conn)
PGconnPQconnectdbParams (const char *const *keywords, const char *const *values, int expand_dbname)
PGPing PQpingParams (const char *const *keywords, const char *const *values, int expand_dbname)
PGconnPQconnectdb (const char *conninfo)
PGPing PQping (const char *conninfo)
PGconnPQconnectStartParams (const char *const *keywords, const char *const *values, int expand_dbname)
PGconnPQconnectStart (const char *conninfo)
PQconninfoOptionPQconndefaults (void)
PGconnPQsetdbLogin (const char *pghost, const char *pgport, const char *pgoptions, const char *pgtty, const char *dbName, const char *login, const char *pwd)
static int connectNoDelay (PGconn *conn)
static void connectFailureMessage (PGconn *conn, int errorno)
static int useKeepalives (PGconn *conn)
static int setKeepalivesIdle (PGconn *conn)
static int setKeepalivesInterval (PGconn *conn)
static int setKeepalivesCount (PGconn *conn)
PostgresPollingStatusType PQconnectPoll (PGconn *conn)
void PQfinish (PGconn *conn)
void PQreset (PGconn *conn)
int PQresetStart (PGconn *conn)
PostgresPollingStatusType PQresetPoll (PGconn *conn)
PGcancelPQgetCancel (PGconn *conn)
void PQfreeCancel (PGcancel *cancel)
static int internal_cancel (SockAddr *raddr, int be_pid, int be_key, char *errbuf, int errbufsize)
int PQcancel (PGcancel *cancel, char *errbuf, int errbufsize)
int PQrequestCancel (PGconn *conn)
int pqPacketSend (PGconn *conn, char pack_type, const void *buf, size_t buf_len)
PQconninfoOptionPQconninfoParse (const char *conninfo, char **errmsg)
PQconninfoOptionPQconninfo (PGconn *conn)
void PQconninfoFree (PQconninfoOption *connOptions)
char * PQdb (const PGconn *conn)
char * PQuser (const PGconn *conn)
char * PQpass (const PGconn *conn)
char * PQhost (const PGconn *conn)
char * PQport (const PGconn *conn)
char * PQtty (const PGconn *conn)
char * PQoptions (const PGconn *conn)
ConnStatusType PQstatus (const PGconn *conn)
PGTransactionStatusType PQtransactionStatus (const PGconn *conn)
const char * PQparameterStatus (const PGconn *conn, const char *paramName)
int PQprotocolVersion (const PGconn *conn)
int PQserverVersion (const PGconn *conn)
char * PQerrorMessage (const PGconn *conn)
int PQsocket (const PGconn *conn)
int PQbackendPID (const PGconn *conn)
int PQconnectionNeedsPassword (const PGconn *conn)
int PQconnectionUsedPassword (const PGconn *conn)
int PQclientEncoding (const PGconn *conn)
int PQsetClientEncoding (PGconn *conn, const char *encoding)
PGVerbosity PQsetErrorVerbosity (PGconn *conn, PGVerbosity verbosity)
void PQtrace (PGconn *conn, FILE *debug_port)
void PQuntrace (PGconn *conn)
PQnoticeReceiver PQsetNoticeReceiver (PGconn *conn, PQnoticeReceiver proc, void *arg)
PQnoticeProcessor PQsetNoticeProcessor (PGconn *conn, PQnoticeProcessor proc, void *arg)
bool pqGetHomeDirectory (char *buf, int bufsize)
pgthreadlock_t PQregisterThreadLock (pgthreadlock_t newhandler)

Variables

static const
internalPQconninfoOption 
PQconninfoOptions []
static const PQEnvironmentOption EnvironmentOptions []
static const char uri_designator [] = "postgresql://"
static const char short_uri_designator [] = "postgres://"
pgthreadlock_t pg_g_threadlock = default_threadlock

Define Documentation

#define DefaultAuthtype   ""

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

#define DefaultHost   "localhost"

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

#define DefaultOption   ""

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

#define DefaultPassword   ""

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

Referenced by connectOptions2().

#define DefaultSSLMode   "disable"

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

Referenced by connectOptions2().

#define DefaultTty   ""

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

#define ERRCODE_APPNAME_UNKNOWN   "42704"

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

Referenced by PQconnectPoll().

#define ERRCODE_CANNOT_CONNECT_NOW   "57P03"

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

Referenced by internal_ping(), and ProcessStartupPacket().

#define ERRCODE_INVALID_PASSWORD   "28P01"

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

Referenced by dot_pg_pass_warning().

#define LINELEN   NAMEDATALEN*5
#define MAXBUFSIZE   256

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

#define PGPASSFILE   ".pgpass"

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

Referenced by getPgPassFilename().


Typedef Documentation


Function Documentation

static void closePGconn ( PGconn conn  )  [static]

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

References pg_conn::addr_cur, pg_conn::addrlist, pg_conn::addrlist_family, pg_conn::asyncStatus, CONNECTION_OK, free, pg_conn::lobjfuncs, pgParameterStatus::next, pgNotify::next, pg_conn::nonblocking, pg_conn::notifyHead, pg_conn::notifyTail, NULL, pg_freeaddrinfo_all(), pqClearAsyncResult(), pqDropConnection(), pqFlush(), pqPutMsgEnd(), pqPutMsgStart(), pg_conn::pstatus, pg_conn::sock, and pg_conn::status.

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

{
    PGnotify   *notify;
    pgParameterStatus *pstatus;

    /*
     * Note that the protocol doesn't allow us to send Terminate messages
     * during the startup phase.
     */
    if (conn->sock >= 0 && conn->status == CONNECTION_OK)
    {
        /*
         * Try to send "close connection" message to backend. Ignore any
         * error.
         */
        pqPutMsgStart('X', false, conn);
        pqPutMsgEnd(conn);
        pqFlush(conn);
    }

    /*
     * Must reset the blocking status so a possible reconnect will work.
     *
     * Don't call PQsetnonblocking() because it will fail if it's unable to
     * flush the connection.
     */
    conn->nonblocking = FALSE;

    /*
     * Close the connection, reset all transient state, flush I/O buffers.
     */
    pqDropConnection(conn);
    conn->status = CONNECTION_BAD;      /* Well, not really _bad_ - just
                                         * absent */
    conn->asyncStatus = PGASYNC_IDLE;
    pqClearAsyncResult(conn);   /* deallocate result */
    pg_freeaddrinfo_all(conn->addrlist_family, conn->addrlist);
    conn->addrlist = NULL;
    conn->addr_cur = NULL;
    notify = conn->notifyHead;
    while (notify != NULL)
    {
        PGnotify   *prev = notify;

        notify = notify->next;
        free(prev);
    }
    conn->notifyHead = conn->notifyTail = NULL;
    pstatus = conn->pstatus;
    while (pstatus != NULL)
    {
        pgParameterStatus *prev = pstatus;

        pstatus = pstatus->next;
        free(prev);
    }
    conn->pstatus = NULL;
    if (conn->lobjfuncs)
        free(conn->lobjfuncs);
    conn->lobjfuncs = NULL;
#ifdef ENABLE_GSS
    {
        OM_uint32   min_s;

        if (conn->gctx)
            gss_delete_sec_context(&min_s, &conn->gctx, GSS_C_NO_BUFFER);
        if (conn->gtarg_nam)
            gss_release_name(&min_s, &conn->gtarg_nam);
        if (conn->ginbuf.length)
            gss_release_buffer(&min_s, &conn->ginbuf);
        if (conn->goutbuf.length)
            gss_release_buffer(&min_s, &conn->goutbuf);
    }
#endif
#ifdef ENABLE_SSPI
    if (conn->ginbuf.length)
        free(conn->ginbuf.value);
    conn->ginbuf.length = 0;
    conn->ginbuf.value = NULL;
    if (conn->sspitarget)
        free(conn->sspitarget);
    conn->sspitarget = NULL;
    if (conn->sspicred)
    {
        FreeCredentialsHandle(conn->sspicred);
        free(conn->sspicred);
        conn->sspicred = NULL;
    }
    if (conn->sspictx)
    {
        DeleteSecurityContext(conn->sspictx);
        free(conn->sspictx);
        conn->sspictx = NULL;
    }
#endif
}

static int connectDBComplete ( PGconn conn  )  [static]

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

References pg_conn::connect_timeout, CONNECTION_BAD, pg_conn::errorMessage, flag(), NULL, PGRES_POLLING_OK, PGRES_POLLING_READING, PGRES_POLLING_WRITING, PQconnectPoll(), pqWaitTimed(), resetPQExpBuffer(), and pg_conn::status.

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

{
    PostgresPollingStatusType flag = PGRES_POLLING_WRITING;
    time_t      finish_time = ((time_t) -1);

    if (conn == NULL || conn->status == CONNECTION_BAD)
        return 0;

    /*
     * Set up a time limit, if connect_timeout isn't zero.
     */
    if (conn->connect_timeout != NULL)
    {
        int         timeout = atoi(conn->connect_timeout);

        if (timeout > 0)
        {
            /*
             * Rounding could cause connection to fail; need at least 2 secs
             */
            if (timeout < 2)
                timeout = 2;
            /* calculate the finish time based on start + timeout */
            finish_time = time(NULL) + timeout;
        }
    }

    for (;;)
    {
        /*
         * Wait, if necessary.  Note that the initial state (just after
         * PQconnectStart) is to wait for the socket to select for writing.
         */
        switch (flag)
        {
            case PGRES_POLLING_OK:

                /*
                 * Reset stored error messages since we now have a working
                 * connection
                 */
                resetPQExpBuffer(&conn->errorMessage);
                return 1;       /* success! */

            case PGRES_POLLING_READING:
                if (pqWaitTimed(1, 0, conn, finish_time))
                {
                    conn->status = CONNECTION_BAD;
                    return 0;
                }
                break;

            case PGRES_POLLING_WRITING:
                if (pqWaitTimed(0, 1, conn, finish_time))
                {
                    conn->status = CONNECTION_BAD;
                    return 0;
                }
                break;

            default:
                /* Just in case we failed to set it in PQconnectPoll */
                conn->status = CONNECTION_BAD;
                return 0;
        }

        /*
         * Now try to advance the state machine.
         */
        flag = PQconnectPoll(conn);
    }
}

static int connectDBStart ( PGconn conn  )  [static]

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

References pg_conn::addr_cur, pg_conn::addrlist, pg_conn::addrlist_family, addrinfo::ai_family, addrinfo::ai_flags, addrinfo::ai_socktype, appendPQExpBuffer(), pg_conn::errorMessage, gai_strerror, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, libpq_gettext, MemSet, NULL, pg_conn::options_valid, pg_conn::outCount, pg_freeaddrinfo_all(), pg_getaddrinfo_all(), PG_PROTOCOL, pg_conn::pghost, pg_conn::pghostaddr, pg_conn::pgport, PGRES_POLLING_WRITING, pg_conn::pgunixsocket, PQconnectPoll(), pqDropConnection(), pg_conn::pversion, pg_conn::send_appname, snprintf(), pg_conn::sslmode, pg_conn::status, UNIXSOCK_PATH, and UNIXSOCK_PATH_BUFLEN.

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

{
    int         portnum;
    char        portstr[MAXPGPATH];
    struct addrinfo *addrs = NULL;
    struct addrinfo hint;
    const char *node;
    int         ret;

    if (!conn)
        return 0;

    if (!conn->options_valid)
        goto connect_errReturn;

    /* Ensure our buffers are empty */
    conn->inStart = conn->inCursor = conn->inEnd = 0;
    conn->outCount = 0;

    /*
     * Determine the parameters to pass to pg_getaddrinfo_all.
     */

    /* Initialize hint structure */
    MemSet(&hint, 0, sizeof(hint));
    hint.ai_socktype = SOCK_STREAM;
    hint.ai_family = AF_UNSPEC;

    /* Set up port number as a string */
    if (conn->pgport != NULL && conn->pgport[0] != '\0')
    {
        portnum = atoi(conn->pgport);
        if (portnum < 1 || portnum > 65535)
        {
            appendPQExpBuffer(&conn->errorMessage,
                              libpq_gettext("invalid port number: \"%s\"\n"),
                              conn->pgport);
            conn->options_valid = false;
            goto connect_errReturn;
        }
    }
    else
        portnum = DEF_PGPORT;
    snprintf(portstr, sizeof(portstr), "%d", portnum);

    if (conn->pghostaddr != NULL && conn->pghostaddr[0] != '\0')
    {
        /* Using pghostaddr avoids a hostname lookup */
        node = conn->pghostaddr;
        hint.ai_family = AF_UNSPEC;
        hint.ai_flags = AI_NUMERICHOST;
    }
    else if (conn->pghost != NULL && conn->pghost[0] != '\0')
    {
        /* Using pghost, so we have to look-up the hostname */
        node = conn->pghost;
        hint.ai_family = AF_UNSPEC;
    }
    else
    {
#ifdef HAVE_UNIX_SOCKETS
        /* pghostaddr and pghost are NULL, so use Unix domain socket */
        node = NULL;
        hint.ai_family = AF_UNIX;
        UNIXSOCK_PATH(portstr, portnum, conn->pgunixsocket);
        if (strlen(portstr) >= UNIXSOCK_PATH_BUFLEN)
        {
            appendPQExpBuffer(&conn->errorMessage,
                              libpq_gettext("Unix-domain socket path \"%s\" is too long (maximum %d bytes)\n"),
                                            portstr,
                                            (int) (UNIXSOCK_PATH_BUFLEN - 1));
            conn->options_valid = false;
            goto connect_errReturn;
        }
#else
        /* Without Unix sockets, default to localhost instead */
        node = DefaultHost;
        hint.ai_family = AF_UNSPEC;
#endif   /* HAVE_UNIX_SOCKETS */
    }

    /* Use pg_getaddrinfo_all() to resolve the address */
    ret = pg_getaddrinfo_all(node, portstr, &hint, &addrs);
    if (ret || !addrs)
    {
        if (node)
            appendPQExpBuffer(&conn->errorMessage,
                              libpq_gettext("could not translate host name \"%s\" to address: %s\n"),
                              node, gai_strerror(ret));
        else
            appendPQExpBuffer(&conn->errorMessage,
                              libpq_gettext("could not translate Unix-domain socket path \"%s\" to address: %s\n"),
                              portstr, gai_strerror(ret));
        if (addrs)
            pg_freeaddrinfo_all(hint.ai_family, addrs);
        conn->options_valid = false;
        goto connect_errReturn;
    }

#ifdef USE_SSL
    /* setup values based on SSL mode */
    if (conn->sslmode[0] == 'd')    /* "disable" */
        conn->allow_ssl_try = false;
    else if (conn->sslmode[0] == 'a')   /* "allow" */
        conn->wait_ssl_try = true;
#endif

    /*
     * Set up to try to connect, with protocol 3.0 as the first attempt.
     */
    conn->addrlist = addrs;
    conn->addr_cur = addrs;
    conn->addrlist_family = hint.ai_family;
    conn->pversion = PG_PROTOCOL(3, 0);
    conn->send_appname = true;
    conn->status = CONNECTION_NEEDED;

    /*
     * The code for processing CONNECTION_NEEDED state is in PQconnectPoll(),
     * so that it can easily be re-executed if needed again during the
     * asynchronous startup process.  However, we must run it once here,
     * because callers expect a success return from this routine to mean that
     * we are in PGRES_POLLING_WRITING connection state.
     */
    if (PQconnectPoll(conn) == PGRES_POLLING_WRITING)
        return 1;

connect_errReturn:
    pqDropConnection(conn);
    conn->status = CONNECTION_BAD;
    return 0;
}

static void connectFailureMessage ( PGconn conn,
int  errorno 
) [static]

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

References SockAddr::addr, appendPQExpBuffer(), pg_conn::errorMessage, inet_net_ntop(), IS_AF_UNIX, libpq_gettext, NI_MAXHOST, NI_NUMERICSERV, NULL, pg_getnameinfo_all(), pg_conn::pghost, pg_conn::pghostaddr, pg_conn::pgport, pg_conn::raddr, SockAddr::salen, SOCK_STRERROR, and strlcpy().

Referenced by PQconnectPoll().

{
    char        sebuf[256];

#ifdef HAVE_UNIX_SOCKETS
    if (IS_AF_UNIX(conn->raddr.addr.ss_family))
    {
        char        service[NI_MAXHOST];

        pg_getnameinfo_all(&conn->raddr.addr, conn->raddr.salen,
                           NULL, 0,
                           service, sizeof(service),
                           NI_NUMERICSERV);
        appendPQExpBuffer(&conn->errorMessage,
                          libpq_gettext("could not connect to server: %s\n"
                            "\tIs the server running locally and accepting\n"
                            "\tconnections on Unix domain socket \"%s\"?\n"),
                          SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),
                          service);
    }
    else
#endif   /* HAVE_UNIX_SOCKETS */
    {
        char        host_addr[NI_MAXHOST];
        const char *displayed_host;
        struct sockaddr_storage *addr = &conn->raddr.addr;

        /*
         * Optionally display the network address with the hostname. This is
         * useful to distinguish between IPv4 and IPv6 connections.
         */
        if (conn->pghostaddr != NULL)
            strlcpy(host_addr, conn->pghostaddr, NI_MAXHOST);
        else if (addr->ss_family == AF_INET)
        {
            if (inet_net_ntop(AF_INET,
                              &((struct sockaddr_in *) addr)->sin_addr.s_addr,
                              32,
                              host_addr, sizeof(host_addr)) == NULL)
                strcpy(host_addr, "???");
        }
#ifdef HAVE_IPV6
        else if (addr->ss_family == AF_INET6)
        {
            if (inet_net_ntop(AF_INET6,
                          &((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr,
                              128,
                              host_addr, sizeof(host_addr)) == NULL)
                strcpy(host_addr, "???");
        }
#endif
        else
            strcpy(host_addr, "???");

        if (conn->pghostaddr && conn->pghostaddr[0] != '\0')
            displayed_host = conn->pghostaddr;
        else if (conn->pghost && conn->pghost[0] != '\0')
            displayed_host = conn->pghost;
        else
            displayed_host = DefaultHost;

        /*
         * If the user did not supply an IP address using 'hostaddr', and
         * 'host' was missing or does not match our lookup, display the
         * looked-up IP address.
         */
        if ((conn->pghostaddr == NULL) &&
            (conn->pghost == NULL || strcmp(conn->pghost, host_addr) != 0))
            appendPQExpBuffer(&conn->errorMessage,
                            libpq_gettext("could not connect to server: %s\n"
                "\tIs the server running on host \"%s\" (%s) and accepting\n"
                                       "\tTCP/IP connections on port %s?\n"),
                              SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),
                              displayed_host,
                              host_addr,
                              conn->pgport);
        else
            appendPQExpBuffer(&conn->errorMessage,
                            libpq_gettext("could not connect to server: %s\n"
                     "\tIs the server running on host \"%s\" and accepting\n"
                                       "\tTCP/IP connections on port %s?\n"),
                              SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),
                              displayed_host,
                              conn->pgport);
    }
}

static int connectNoDelay ( PGconn conn  )  [static]

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

References appendPQExpBuffer(), pg_conn::errorMessage, libpq_gettext, pg_conn::sock, SOCK_ERRNO, and SOCK_STRERROR.

Referenced by PQconnectPoll().

{
#ifdef  TCP_NODELAY
    int         on = 1;

    if (setsockopt(conn->sock, IPPROTO_TCP, TCP_NODELAY,
                   (char *) &on,
                   sizeof(on)) < 0)
    {
        char        sebuf[256];

        appendPQExpBuffer(&conn->errorMessage,
            libpq_gettext("could not set socket to TCP no delay mode: %s\n"),
                          SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
        return 0;
    }
#endif

    return 1;
}

static bool connectOptions1 ( PGconn conn,
const char *  conninfo 
) [static]

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

References pg_conn::errorMessage, fillPGconn(), NULL, parse_connection_string(), PQconninfoFree(), and pg_conn::status.

Referenced by PQconnectStart(), and PQsetdbLogin().

{
    PQconninfoOption *connOptions;

    /*
     * Parse the conninfo string
     */
    connOptions = parse_connection_string(conninfo, &conn->errorMessage, true);
    if (connOptions == NULL)
    {
        conn->status = CONNECTION_BAD;
        /* errorMessage is already set */
        return false;
    }

    /*
     * Move option values into conn structure
     */
    fillPGconn(conn, connOptions);

    /*
     * Free the option info - all is in conn now
     */
    PQconninfoFree(connOptions);

    return true;
}

static bool connectOptions2 ( PGconn conn  )  [static]

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

References pg_conn::client_encoding_initial, pg_conn::dbName, DefaultPassword, DefaultSSLMode, pg_conn::dot_pgpass_used, pg_conn::errorMessage, free, is_absolute_path, libpq_gettext, NULL, pg_conn::options_valid, PasswordFromFile(), pg_encoding_to_char(), pg_get_encoding_from_locale(), pg_conn::pghost, pg_conn::pgpass, pg_conn::pgport, pg_conn::pgunixsocket, pg_conn::pguser, printfPQExpBuffer(), pg_conn::sslmode, and pg_conn::status.

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

{
    /*
     * If database name was not given, default it to equal user name
     */
    if ((conn->dbName == NULL || conn->dbName[0] == '\0')
        && conn->pguser != NULL)
    {
        if (conn->dbName)
            free(conn->dbName);
        conn->dbName = strdup(conn->pguser);
    }

    /*
     * Supply default password if none given
     */
    if (conn->pgpass == NULL || conn->pgpass[0] == '\0')
    {
        if (conn->pgpass)
            free(conn->pgpass);
        conn->pgpass = PasswordFromFile(conn->pghost, conn->pgport,
                                        conn->dbName, conn->pguser);
        if (conn->pgpass == NULL)
            conn->pgpass = strdup(DefaultPassword);
        else
            conn->dot_pgpass_used = true;
    }

    /*
     * Allow unix socket specification in the host name
     */
    if (conn->pghost && is_absolute_path(conn->pghost))
    {
        if (conn->pgunixsocket)
            free(conn->pgunixsocket);
        conn->pgunixsocket = conn->pghost;
        conn->pghost = NULL;
    }

    /*
     * validate sslmode option
     */
    if (conn->sslmode)
    {
        if (strcmp(conn->sslmode, "disable") != 0
            && strcmp(conn->sslmode, "allow") != 0
            && strcmp(conn->sslmode, "prefer") != 0
            && strcmp(conn->sslmode, "require") != 0
            && strcmp(conn->sslmode, "verify-ca") != 0
            && strcmp(conn->sslmode, "verify-full") != 0)
        {
            conn->status = CONNECTION_BAD;
            printfPQExpBuffer(&conn->errorMessage,
                            libpq_gettext("invalid sslmode value: \"%s\"\n"),
                              conn->sslmode);
            return false;
        }

#ifndef USE_SSL
        switch (conn->sslmode[0])
        {
            case 'a':           /* "allow" */
            case 'p':           /* "prefer" */

                /*
                 * warn user that an SSL connection will never be negotiated
                 * since SSL was not compiled in?
                 */
                break;

            case 'r':           /* "require" */
            case 'v':           /* "verify-ca" or "verify-full" */
                conn->status = CONNECTION_BAD;
                printfPQExpBuffer(&conn->errorMessage,
                                  libpq_gettext("sslmode value \"%s\" invalid when SSL support is not compiled in\n"),
                                  conn->sslmode);
                return false;
        }
#endif
    }
    else
        conn->sslmode = strdup(DefaultSSLMode);

    /*
     * Resolve special "auto" client_encoding from the locale
     */
    if (conn->client_encoding_initial &&
        strcmp(conn->client_encoding_initial, "auto") == 0)
    {
        free(conn->client_encoding_initial);
        conn->client_encoding_initial = strdup(pg_encoding_to_char(pg_get_encoding_from_locale(NULL, true)));
    }

    /*
     * Only if we get this far is it appropriate to try to connect. (We need a
     * state flag, rather than just the boolean result of this function, in
     * case someone tries to PQreset() the PGconn.)
     */
    conn->options_valid = true;

    return true;
}

static bool conninfo_add_defaults ( PQconninfoOption options,
PQExpBuffer  errorMessage 
) [static]

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

References _PQconninfoOption::compiled, _PQconninfoOption::envvar, _PQconninfoOption::keyword, libpq_gettext, NULL, parseServiceInfo(), pg_fe_getauthname(), printfPQExpBuffer(), and _PQconninfoOption::val.

Referenced by conninfo_array_parse(), conninfo_parse(), conninfo_uri_parse(), and PQconndefaults().

{
    PQconninfoOption *option;
    char       *tmp;

    /*
     * If there's a service spec, use it to obtain any not-explicitly-given
     * parameters.
     */
    if (parseServiceInfo(options, errorMessage) != 0)
        return false;

    /*
     * Get the fallback resources for parameters not specified in the conninfo
     * string nor the service.
     */
    for (option = options; option->keyword != NULL; option++)
    {
        if (option->val != NULL)
            continue;           /* Value was in conninfo or service */

        /*
         * Try to get the environment variable fallback
         */
        if (option->envvar != NULL)
        {
            if ((tmp = getenv(option->envvar)) != NULL)
            {
                option->val = strdup(tmp);
                if (!option->val)
                {
                    printfPQExpBuffer(errorMessage,
                                      libpq_gettext("out of memory\n"));
                    return false;
                }
                continue;
            }
        }

        /*
         * No environment variable specified or the variable isn't set - try
         * compiled-in default
         */
        if (option->compiled != NULL)
        {
            option->val = strdup(option->compiled);
            if (!option->val)
            {
                printfPQExpBuffer(errorMessage,
                                  libpq_gettext("out of memory\n"));
                return false;
            }
            continue;
        }

        /*
         * Special handling for "user" option
         */
        if (strcmp(option->keyword, "user") == 0)
        {
            option->val = pg_fe_getauthname(errorMessage);
            continue;
        }
    }

    return true;
}

static PQconninfoOption * conninfo_array_parse ( const char *const *  keywords,
const char *const *  values,
PQExpBuffer  errorMessage,
bool  use_defaults,
int  expand_dbname 
) [static]

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

References conninfo_add_defaults(), conninfo_init(), free, _PQconninfoOption::keyword, libpq_gettext, NULL, parse_connection_string(), PQconninfoFree(), printfPQExpBuffer(), recognized_connection_string(), val, and _PQconninfoOption::val.

Referenced by PQconnectStartParams().

{
    PQconninfoOption *options;
    PQconninfoOption *dbname_options = NULL;
    PQconninfoOption *option;
    int         i = 0;

    /*
     * If expand_dbname is non-zero, check keyword "dbname" to see if val is
     * actually a recognized connection string.
     */
    while (expand_dbname && keywords[i])
    {
        const char *pname = keywords[i];
        const char *pvalue = values[i];

        /* first find "dbname" if any */
        if (strcmp(pname, "dbname") == 0 && pvalue)
        {
            /*
             * If value is a connection string, parse it, but do not use
             * defaults here -- those get picked up later. We only want to
             * override for those parameters actually passed.
             */
            if (recognized_connection_string(pvalue))
            {
                dbname_options = parse_connection_string(pvalue, errorMessage, false);
                if (dbname_options == NULL)
                    return NULL;
            }
            break;
        }
        ++i;
    }

    /* Make a working copy of PQconninfoOptions */
    options = conninfo_init(errorMessage);
    if (options == NULL)
    {
        PQconninfoFree(dbname_options);
        return NULL;
    }

    /* Parse the keywords/values arrays */
    i = 0;
    while (keywords[i])
    {
        const char *pname = keywords[i];
        const char *pvalue = values[i];

        if (pvalue != NULL)
        {
            /* Search for the param record */
            for (option = options; option->keyword != NULL; option++)
            {
                if (strcmp(option->keyword, pname) == 0)
                    break;
            }

            /* Check for invalid connection option */
            if (option->keyword == NULL)
            {
                printfPQExpBuffer(errorMessage,
                         libpq_gettext("invalid connection option \"%s\"\n"),
                                  pname);
                PQconninfoFree(options);
                PQconninfoFree(dbname_options);
                return NULL;
            }

            /*
             * If we are on the dbname parameter, and we have a parsed
             * connection string, copy those parameters across, overriding any
             * existing previous settings.
             */
            if (strcmp(pname, "dbname") == 0 && dbname_options)
            {
                PQconninfoOption *str_option;

                for (str_option = dbname_options; str_option->keyword != NULL; str_option++)
                {
                    if (str_option->val != NULL)
                    {
                        int         k;

                        for (k = 0; options[k].keyword; k++)
                        {
                            if (strcmp(options[k].keyword, str_option->keyword) == 0)
                            {
                                if (options[k].val)
                                    free(options[k].val);
                                options[k].val = strdup(str_option->val);
                                break;
                            }
                        }
                    }
                }
            }
            else
            {
                /*
                 * Store the value, overriding previous settings
                 */
                if (option->val)
                    free(option->val);
                option->val = strdup(pvalue);
                if (!option->val)
                {
                    printfPQExpBuffer(errorMessage,
                                      libpq_gettext("out of memory\n"));
                    PQconninfoFree(options);
                    PQconninfoFree(dbname_options);
                    return NULL;
                }
            }
        }
        ++i;
    }
    PQconninfoFree(dbname_options);

    /*
     * Add in defaults if the caller wants that.
     */
    if (use_defaults)
    {
        if (!conninfo_add_defaults(options, errorMessage))
        {
            PQconninfoFree(options);
            return NULL;
        }
    }

    return options;
}

static PQconninfoOption * conninfo_find ( PQconninfoOption connOptions,
const char *  keyword 
) [static]

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

References _PQconninfoOption::keyword.

Referenced by conninfo_getval(), and conninfo_storeval().

{
    PQconninfoOption *option;

    for (option = connOptions; option->keyword != NULL; option++)
    {
        if (strcmp(option->keyword, keyword) == 0)
            return option;
    }

    return NULL;
}

static const char * conninfo_getval ( PQconninfoOption connOptions,
const char *  keyword 
) [static]

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

References conninfo_find(), and _PQconninfoOption::val.

Referenced by fillPGconn(), and parseServiceInfo().

{
    PQconninfoOption *option;

    option = conninfo_find(connOptions, keyword);

    return option ? option->val : NULL;
}

static PQconninfoOption * conninfo_init ( PQExpBuffer  errorMessage  )  [static]

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

References _internalPQconninfoOption::keyword, libpq_gettext, malloc, MemSet, NULL, and printfPQExpBuffer().

Referenced by conninfo_array_parse(), conninfo_parse(), conninfo_uri_parse(), PQconndefaults(), and PQconninfo().

{
    PQconninfoOption *options;
    PQconninfoOption *opt_dest;
    const internalPQconninfoOption *cur_opt;

    /*
     * Get enough memory for all options in PQconninfoOptions, even if some
     * end up being filtered out.
     */
    options = (PQconninfoOption *) malloc(sizeof(PQconninfoOption) * sizeof(PQconninfoOptions) / sizeof(PQconninfoOptions[0]));
    if (options == NULL)
    {
        printfPQExpBuffer(errorMessage,
                          libpq_gettext("out of memory\n"));
        return NULL;
    }
    opt_dest = options;

    for (cur_opt = PQconninfoOptions; cur_opt->keyword; cur_opt++)
    {
        /* Only copy the public part of the struct, not the full internal */
        memcpy(opt_dest, cur_opt, sizeof(PQconninfoOption));
        opt_dest++;
    }
    MemSet(opt_dest, 0, sizeof(PQconninfoOption));

    return options;
}

static PQconninfoOption * conninfo_parse ( const char *  conninfo,
PQExpBuffer  errorMessage,
bool  use_defaults 
) [static]

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

References buf, conninfo_add_defaults(), conninfo_init(), conninfo_storeval(), free, libpq_gettext, NULL, PQconninfoFree(), and printfPQExpBuffer().

Referenced by parse_connection_string().

{
    char       *pname;
    char       *pval;
    char       *buf;
    char       *cp;
    char       *cp2;
    PQconninfoOption *options;

    /* Make a working copy of PQconninfoOptions */
    options = conninfo_init(errorMessage);
    if (options == NULL)
        return NULL;

    /* Need a modifiable copy of the input string */
    if ((buf = strdup(conninfo)) == NULL)
    {
        printfPQExpBuffer(errorMessage,
                          libpq_gettext("out of memory\n"));
        PQconninfoFree(options);
        return NULL;
    }
    cp = buf;

    while (*cp)
    {
        /* Skip blanks before the parameter name */
        if (isspace((unsigned char) *cp))
        {
            cp++;
            continue;
        }

        /* Get the parameter name */
        pname = cp;
        while (*cp)
        {
            if (*cp == '=')
                break;
            if (isspace((unsigned char) *cp))
            {
                *cp++ = '\0';
                while (*cp)
                {
                    if (!isspace((unsigned char) *cp))
                        break;
                    cp++;
                }
                break;
            }
            cp++;
        }

        /* Check that there is a following '=' */
        if (*cp != '=')
        {
            printfPQExpBuffer(errorMessage,
                              libpq_gettext("missing \"=\" after \"%s\" in connection info string\n"),
                              pname);
            PQconninfoFree(options);
            free(buf);
            return NULL;
        }
        *cp++ = '\0';

        /* Skip blanks after the '=' */
        while (*cp)
        {
            if (!isspace((unsigned char) *cp))
                break;
            cp++;
        }

        /* Get the parameter value */
        pval = cp;

        if (*cp != '\'')
        {
            cp2 = pval;
            while (*cp)
            {
                if (isspace((unsigned char) *cp))
                {
                    *cp++ = '\0';
                    break;
                }
                if (*cp == '\\')
                {
                    cp++;
                    if (*cp != '\0')
                        *cp2++ = *cp++;
                }
                else
                    *cp2++ = *cp++;
            }
            *cp2 = '\0';
        }
        else
        {
            cp2 = pval;
            cp++;
            for (;;)
            {
                if (*cp == '\0')
                {
                    printfPQExpBuffer(errorMessage,
                                      libpq_gettext("unterminated quoted string in connection info string\n"));
                    PQconninfoFree(options);
                    free(buf);
                    return NULL;
                }
                if (*cp == '\\')
                {
                    cp++;
                    if (*cp != '\0')
                        *cp2++ = *cp++;
                    continue;
                }
                if (*cp == '\'')
                {
                    *cp2 = '\0';
                    cp++;
                    break;
                }
                *cp2++ = *cp++;
            }
        }

        /*
         * Now that we have the name and the value, store the record.
         */
        if (!conninfo_storeval(options, pname, pval, errorMessage, false, false))
        {
            PQconninfoFree(options);
            free(buf);
            return NULL;
        }
    }

    /* Done with the modifiable input string */
    free(buf);

    /*
     * Add in defaults if the caller wants that.
     */
    if (use_defaults)
    {
        if (!conninfo_add_defaults(options, errorMessage))
        {
            PQconninfoFree(options);
            return NULL;
        }
    }

    return options;
}

static PQconninfoOption * conninfo_storeval ( PQconninfoOption connOptions,
const char *  keyword,
const char *  value,
PQExpBuffer  errorMessage,
bool  ignoreMissing,
bool  uri_decode 
) [static]

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

References conninfo_find(), conninfo_uri_decode(), free, libpq_gettext, NULL, printfPQExpBuffer(), and _PQconninfoOption::val.

Referenced by conninfo_parse(), conninfo_uri_parse_options(), conninfo_uri_parse_params(), and PQconninfo().

{
    PQconninfoOption *option;
    char       *value_copy;

    /*
     * For backwards compatibility, requiressl=1 gets translated to
     * sslmode=require, and requiressl=0 gets translated to sslmode=prefer
     * (which is the default for sslmode).
     */
    if (strcmp(keyword, "requiressl") == 0)
    {
        keyword = "sslmode";
        if (value[0] == '1')
            value = "require";
        else
            value = "prefer";
    }

    option = conninfo_find(connOptions, keyword);
    if (option == NULL)
    {
        if (!ignoreMissing)
            printfPQExpBuffer(errorMessage,
                         libpq_gettext("invalid connection option \"%s\"\n"),
                              keyword);
        return NULL;
    }

    if (uri_decode)
    {
        value_copy = conninfo_uri_decode(value, errorMessage);
        if (value_copy == NULL)
            /* conninfo_uri_decode already set an error message */
            return NULL;
    }
    else
    {
        value_copy = strdup(value);

        if (value_copy == NULL)
        {
            printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n"));
            return NULL;
        }
    }

    if (option->val)
        free(option->val);
    option->val = value_copy;

    return option;
}

static char * conninfo_uri_decode ( const char *  str,
PQExpBuffer  errorMessage 
) [static]

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

References buf, free, get_hexdigit(), libpq_gettext, malloc, NULL, and printfPQExpBuffer().

Referenced by conninfo_storeval(), and conninfo_uri_parse_params().

{
    char       *buf = malloc(strlen(str) + 1);
    char       *p = buf;
    const char *q = str;

    if (buf == NULL)
    {
        printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n"));
        return NULL;
    }

    for (;;)
    {
        if (*q != '%')
        {
            /* copy and check for NUL terminator */
            if (!(*(p++) = *(q++)))
                break;
        }
        else
        {
            int         hi;
            int         lo;
            int         c;

            ++q;                /* skip the percent sign itself */

            /*
             * Possible EOL will be caught by the first call to
             * get_hexdigit(), so we never dereference an invalid q pointer.
             */
            if (!(get_hexdigit(*q++, &hi) && get_hexdigit(*q++, &lo)))
            {
                printfPQExpBuffer(errorMessage,
                    libpq_gettext("invalid percent-encoded token: \"%s\"\n"),
                                  str);
                free(buf);
                return NULL;
            }

            c = (hi << 4) | lo;
            if (c == 0)
            {
                printfPQExpBuffer(errorMessage,
                                  libpq_gettext("forbidden value %%00 in percent-encoded value: \"%s\"\n"),
                                  str);
                free(buf);
                return NULL;
            }
            *(p++) = c;
        }
    }

    return buf;
}

static PQconninfoOption * conninfo_uri_parse ( const char *  uri,
PQExpBuffer  errorMessage,
bool  use_defaults 
) [static]

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

References conninfo_add_defaults(), conninfo_init(), conninfo_uri_parse_options(), NULL, and PQconninfoFree().

Referenced by parse_connection_string().

{
    PQconninfoOption *options;

    /* Make a working copy of PQconninfoOptions */
    options = conninfo_init(errorMessage);
    if (options == NULL)
        return NULL;

    if (!conninfo_uri_parse_options(options, uri, errorMessage))
    {
        PQconninfoFree(options);
        return NULL;
    }

    /*
     * Add in defaults if the caller wants that.
     */
    if (use_defaults)
    {
        if (!conninfo_add_defaults(options, errorMessage))
        {
            PQconninfoFree(options);
            return NULL;
        }
    }

    return options;
}

static bool conninfo_uri_parse_options ( PQconninfoOption options,
const char *  uri,
PQExpBuffer  errorMessage 
) [static]

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

References buf, cleanup(), conninfo_storeval(), conninfo_uri_parse_params(), free, libpq_gettext, NULL, printfPQExpBuffer(), uri_prefix_length(), and user.

Referenced by conninfo_uri_parse().

{
    int         prefix_len;
    char       *p;
    char       *buf = strdup(uri);      /* need a modifiable copy of the input
                                         * URI */
    char       *start = buf;
    char        prevchar = '\0';
    char       *user = NULL;
    char       *host = NULL;
    bool        retval = false;

    if (buf == NULL)
    {
        printfPQExpBuffer(errorMessage,
                          libpq_gettext("out of memory\n"));
        return false;
    }

    /* Skip the URI prefix */
    prefix_len = uri_prefix_length(uri);
    if (prefix_len == 0)
    {
        /* Should never happen */
        printfPQExpBuffer(errorMessage,
                          libpq_gettext("invalid URI propagated to internal parser routine: \"%s\"\n"),
                          uri);
        goto cleanup;
    }
    start += prefix_len;
    p = start;

    /* Look ahead for possible user credentials designator */
    while (*p && *p != '@' && *p != '/')
        ++p;
    if (*p == '@')
    {
        /*
         * Found username/password designator, so URI should be of the form
         * "scheme://user[:password]@[netloc]".
         */
        user = start;

        p = user;
        while (*p != ':' && *p != '@')
            ++p;

        /* Save last char and cut off at end of user name */
        prevchar = *p;
        *p = '\0';

        if (*user &&
            !conninfo_storeval(options, "user", user,
                               errorMessage, false, true))
            goto cleanup;

        if (prevchar == ':')
        {
            const char *password = p + 1;

            while (*p != '@')
                ++p;
            *p = '\0';

            if (*password &&
                !conninfo_storeval(options, "password", password,
                                   errorMessage, false, true))
                goto cleanup;
        }

        /* Advance past end of parsed user name or password token */
        ++p;
    }
    else
    {
        /*
         * No username/password designator found.  Reset to start of URI.
         */
        p = start;
    }

    /*
     * "p" has been incremented past optional URI credential information at
     * this point and now points at the "netloc" part of the URI.
     *
     * Look for IPv6 address.
     */
    if (*p == '[')
    {
        host = ++p;
        while (*p && *p != ']')
            ++p;
        if (!*p)
        {
            printfPQExpBuffer(errorMessage,
                              libpq_gettext("end of string reached when looking for matching \"]\" in IPv6 host address in URI: \"%s\"\n"),
                              uri);
            goto cleanup;
        }
        if (p == host)
        {
            printfPQExpBuffer(errorMessage,
                              libpq_gettext("IPv6 host address may not be empty in URI: \"%s\"\n"),
                              uri);
            goto cleanup;
        }

        /* Cut off the bracket and advance */
        *(p++) = '\0';

        /*
         * The address may be followed by a port specifier or a slash or a
         * query.
         */
        if (*p && *p != ':' && *p != '/' && *p != '?')
        {
            printfPQExpBuffer(errorMessage,
                              libpq_gettext("unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): \"%s\"\n"),
                              *p, (int) (p - buf + 1), uri);
            goto cleanup;
        }
    }
    else
    {
        /* not an IPv6 address: DNS-named or IPv4 netloc */
        host = p;

        /*
         * Look for port specifier (colon) or end of host specifier (slash),
         * or query (question mark).
         */
        while (*p && *p != ':' && *p != '/' && *p != '?')
            ++p;
    }

    /* Save the hostname terminator before we null it */
    prevchar = *p;
    *p = '\0';

    if (*host &&
        !conninfo_storeval(options, "host", host,
                           errorMessage, false, true))
        goto cleanup;


    if (prevchar == ':')
    {
        const char *port = ++p; /* advance past host terminator */

        while (*p && *p != '/' && *p != '?')
            ++p;

        prevchar = *p;
        *p = '\0';

        if (*port &&
            !conninfo_storeval(options, "port", port,
                               errorMessage, false, true))
            goto cleanup;
    }

    if (prevchar && prevchar != '?')
    {
        const char *dbname = ++p;       /* advance past host terminator */

        /* Look for query parameters */
        while (*p && *p != '?')
            ++p;

        prevchar = *p;
        *p = '\0';

        /*
         * Avoid setting dbname to an empty string, as it forces the default
         * value (username) and ignores $PGDATABASE, as opposed to not setting
         * it at all.
         */
        if (*dbname &&
            !conninfo_storeval(options, "dbname", dbname,
                               errorMessage, false, true))
            goto cleanup;
    }

    if (prevchar)
    {
        ++p;                    /* advance past terminator */

        if (!conninfo_uri_parse_params(p, options, errorMessage))
            goto cleanup;
    }

    /* everything parsed okay */
    retval = true;

cleanup:
    free(buf);
    return retval;
}

static bool conninfo_uri_parse_params ( char *  params,
PQconninfoOption connOptions,
PQExpBuffer  errorMessage 
) [static]

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

References conninfo_storeval(), conninfo_uri_decode(), free, PQExpBufferData::len, libpq_gettext, NULL, printfPQExpBuffer(), and value.

Referenced by conninfo_uri_parse_options().

{
    while (*params)
    {
        char       *keyword = params;
        char       *value = NULL;
        char       *p = params;
        bool        malloced = false;

        /*
         * Scan the params string for '=' and '&', marking the end of keyword
         * and value respectively.
         */
        for (;;)
        {
            if (*p == '=')
            {
                /* Was there '=' already? */
                if (value != NULL)
                {
                    printfPQExpBuffer(errorMessage,
                                      libpq_gettext("extra key/value separator \"=\" in URI query parameter: \"%s\"\n"),
                                      params);
                    return false;
                }
                /* Cut off keyword, advance to value */
                *p = '\0';
                value = ++p;
            }
            else if (*p == '&' || *p == '\0')
            {
                char        prevchar;

                /* Cut off value, remember old value */
                prevchar = *p;
                *p = '\0';

                /* Was there '=' at all? */
                if (value == NULL)
                {
                    printfPQExpBuffer(errorMessage,
                                      libpq_gettext("missing key/value separator \"=\" in URI query parameter: \"%s\"\n"),
                                      params);
                    return false;
                }

                /*
                 * If not at the end, advance; now pointing to start of the
                 * next parameter, if any.
                 */
                if (prevchar != '\0')
                    ++p;
                break;
            }

            /* Advance, NUL is checked in the 'if' above */
            ++p;
        }

        keyword = conninfo_uri_decode(keyword, errorMessage);
        if (keyword == NULL)
        {
            /* conninfo_uri_decode already set an error message */
            return false;
        }
        value = conninfo_uri_decode(value, errorMessage);
        if (value == NULL)
        {
            /* conninfo_uri_decode already set an error message */
            free(keyword);
            return false;
        }
        malloced = true;

        /*
         * Special keyword handling for improved JDBC compatibility.
         */
        if (strcmp(keyword, "ssl") == 0 &&
            strcmp(value, "true") == 0)
        {
            free(keyword);
            free(value);
            malloced = false;

            keyword = "sslmode";
            value = "require";
        }

        /*
         * Store the value if the corresponding option exists; ignore
         * otherwise.  At this point both keyword and value are not
         * URI-encoded.
         */
        if (!conninfo_storeval(connOptions, keyword, value,
                               errorMessage, true, false))
        {
            /*
             * Check if there was a hard error when decoding or storing the
             * option.
             */
            if (errorMessage->len != 0)
            {
                if (malloced)
                {
                    free(keyword);
                    free(value);
                }
                return false;
            }

            printfPQExpBuffer(errorMessage,
                              libpq_gettext(
                                    "invalid URI query parameter: \"%s\"\n"),
                              keyword);
            if (malloced)
            {
                free(keyword);
                free(value);
            }
            return false;
        }
        if (malloced)
        {
            free(keyword);
            free(value);
        }

        /* Proceed to next key=value pair */
        params = p;
    }

    return true;
}

static void default_threadlock ( int  acquire  )  [static]

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

References NULL, pthread_mutex_init(), pthread_mutex_lock(), and pthread_mutex_unlock().

{
#ifdef ENABLE_THREAD_SAFETY
#ifndef WIN32
    static pthread_mutex_t singlethread_lock = PTHREAD_MUTEX_INITIALIZER;
#else
    static pthread_mutex_t singlethread_lock = NULL;
    static long mutex_initlock = 0;

    if (singlethread_lock == NULL)
    {
        while (InterlockedExchange(&mutex_initlock, 1) == 1)
             /* loop, another thread own the lock */ ;
        if (singlethread_lock == NULL)
        {
            if (pthread_mutex_init(&singlethread_lock, NULL))
                PGTHREAD_ERROR("failed to initialize mutex");
        }
        InterlockedExchange(&mutex_initlock, 0);
    }
#endif
    if (acquire)
    {
        if (pthread_mutex_lock(&singlethread_lock))
            PGTHREAD_ERROR("failed to lock mutex");
    }
    else
    {
        if (pthread_mutex_unlock(&singlethread_lock))
            PGTHREAD_ERROR("failed to unlock mutex");
    }
#endif
}

static void defaultNoticeProcessor ( void *  arg,
const char *  message 
) [static]

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

{
    (void) arg;                 /* not used */
    /* Note: we expect the supplied string to end with a newline already. */
    fprintf(stderr, "%s", message);
}

static void defaultNoticeReceiver ( void *  arg,
const PGresult res 
) [static]
static void dot_pg_pass_warning ( PGconn conn  )  [static]

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

References appendPQExpBuffer(), pg_conn::dot_pgpass_used, ERRCODE_INVALID_PASSWORD, pg_conn::errorMessage, getPgPassFilename(), libpq_gettext, pg_conn::password_needed, PG_DIAG_SQLSTATE, PQresultErrorField(), and pg_conn::result.

Referenced by PQconnectPoll().

{
    /* If it was 'invalid authorization', add .pgpass mention */
    /* only works with >= 9.0 servers */
    if (conn->dot_pgpass_used && conn->password_needed && conn->result &&
        strcmp(PQresultErrorField(conn->result, PG_DIAG_SQLSTATE),
               ERRCODE_INVALID_PASSWORD) == 0)
    {
        char        pgpassfile[MAXPGPATH];

        if (!getPgPassFilename(pgpassfile))
            return;
        appendPQExpBuffer(&conn->errorMessage,
                      libpq_gettext("password retrieved from file \"%s\"\n"),
                          pgpassfile);
    }
}

static void fillPGconn ( PGconn conn,
PQconninfoOption connOptions 
) [static]

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

References conninfo_getval(), _internalPQconninfoOption::connofs, free, and _internalPQconninfoOption::keyword.

Referenced by connectOptions1(), and PQconnectStartParams().

{
    const internalPQconninfoOption *option;

    /*
     * Move option values into conn structure
     *
     * Don't put anything cute here --- intelligence should be in
     * connectOptions2 ...
     *
     * XXX: probably worth checking strdup() return value here...
     */
    for (option = PQconninfoOptions; option->keyword; option++)
    {
        const char *tmp = conninfo_getval(connOptions, option->keyword);

        if (tmp && option->connofs >= 0)
        {
            char      **connmember = (char **) ((char *) conn + option->connofs);

            if (*connmember)
                free(*connmember);
            *connmember = tmp ? strdup(tmp) : NULL;
        }
    }
}

static void freePGconn ( PGconn conn  )  [static]

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

References pg_conn::appname, pg_conn::client_encoding_initial, PGEventConnDestroy::conn, pg_conn::connect_timeout, pg_conn::dbName, pg_conn::errorMessage, pg_conn::events, pg_conn::fbappname, free, i, pg_conn::inBuffer, pg_conn::keepalives, pg_conn::keepalives_count, pg_conn::keepalives_idle, pg_conn::keepalives_interval, pg_conn::last_query, PGEvent::name, pg_conn::nEvents, pg_conn::outBuffer, PGEvent::passThrough, PGEVT_CONNDESTROY, pg_conn::pghost, pg_conn::pghostaddr, pg_conn::pgoptions, pg_conn::pgpass, pg_conn::pgport, pg_conn::pgtty, pg_conn::pgunixsocket, pg_conn::pguser, PGEvent::proc, pg_conn::replication, pg_conn::requirepeer, pg_conn::rowBuf, pg_conn::sslcert, pg_conn::sslcompression, pg_conn::sslcrl, pg_conn::sslkey, pg_conn::sslmode, pg_conn::sslrootcert, termPQExpBuffer(), and pg_conn::workBuffer.

Referenced by makeEmptyPGconn(), and PQfinish().

{
    int         i;

    /* let any event procs clean up their state data */
    for (i = 0; i < conn->nEvents; i++)
    {
        PGEventConnDestroy evt;

        evt.conn = conn;
        (void) conn->events[i].proc(PGEVT_CONNDESTROY, &evt,
                                    conn->events[i].passThrough);
        free(conn->events[i].name);
    }

    if (conn->client_encoding_initial)
        free(conn->client_encoding_initial);
    if (conn->events)
        free(conn->events);
    if (conn->pghost)
        free(conn->pghost);
    if (conn->pghostaddr)
        free(conn->pghostaddr);
    if (conn->pgport)
        free(conn->pgport);
    if (conn->pgunixsocket)
        free(conn->pgunixsocket);
    if (conn->pgtty)
        free(conn->pgtty);
    if (conn->connect_timeout)
        free(conn->connect_timeout);
    if (conn->pgoptions)
        free(conn->pgoptions);
    if (conn->appname)
        free(conn->appname);
    if (conn->fbappname)
        free(conn->fbappname);
    if (conn->dbName)
        free(conn->dbName);
    if (conn->replication)
        free(conn->replication);
    if (conn->pguser)
        free(conn->pguser);
    if (conn->pgpass)
        free(conn->pgpass);
    if (conn->keepalives)
        free(conn->keepalives);
    if (conn->keepalives_idle)
        free(conn->keepalives_idle);
    if (conn->keepalives_interval)
        free(conn->keepalives_interval);
    if (conn->keepalives_count)
        free(conn->keepalives_count);
    if (conn->sslmode)
        free(conn->sslmode);
    if (conn->sslcert)
        free(conn->sslcert);
    if (conn->sslkey)
        free(conn->sslkey);
    if (conn->sslrootcert)
        free(conn->sslrootcert);
    if (conn->sslcrl)
        free(conn->sslcrl);
    if (conn->sslcompression)
        free(conn->sslcompression);
    if (conn->requirepeer)
        free(conn->requirepeer);
#if defined(KRB5) || defined(ENABLE_GSS) || defined(ENABLE_SSPI)
    if (conn->krbsrvname)
        free(conn->krbsrvname);
#endif
#if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
    if (conn->gsslib)
        free(conn->gsslib);
#endif
    /* Note that conn->Pfdebug is not ours to close or free */
    if (conn->last_query)
        free(conn->last_query);
    if (conn->inBuffer)
        free(conn->inBuffer);
    if (conn->outBuffer)
        free(conn->outBuffer);
    if (conn->rowBuf)
        free(conn->rowBuf);
    termPQExpBuffer(&conn->errorMessage);
    termPQExpBuffer(&conn->workBuffer);

    free(conn);

#ifdef WIN32
    WSACleanup();
#endif
}

static bool get_hexdigit ( char  digit,
int *  value 
) [static]

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

Referenced by conninfo_uri_decode().

{
    if ('0' <= digit && digit <= '9')
        *value = digit - '0';
    else if ('A' <= digit && digit <= 'F')
        *value = digit - 'A' + 10;
    else if ('a' <= digit && digit <= 'f')
        *value = digit - 'a' + 10;
    else
        return false;

    return true;
}

static bool getPgPassFilename ( char *  pgpassfile  )  [static]

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

References MAXPGPATH, NULL, PGPASSFILE, pqGetHomeDirectory(), snprintf(), and strlcpy().

Referenced by dot_pg_pass_warning(), and PasswordFromFile().

{
    char       *passfile_env;

    if ((passfile_env = getenv("PGPASSFILE")) != NULL)
        /* use the literal path from the environment, if set */
        strlcpy(pgpassfile, passfile_env, MAXPGPATH);
    else
    {
        char        homedir[MAXPGPATH];

        if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
            return false;
        snprintf(pgpassfile, MAXPGPATH, "%s/%s", homedir, PGPASSFILE);
    }
    return true;
}

static int internal_cancel ( SockAddr raddr,
int  be_pid,
int  be_key,
char *  errbuf,
int  errbufsize 
) [static]

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

References SockAddr::addr, CANCEL_REQUEST_CODE, closesocket, connect, EINTR, recv, SockAddr::salen, send, SOCK_ERRNO, SOCK_ERRNO_SET, SOCK_STRERROR, socket, and strlcpy().

Referenced by PQcancel(), and PQrequestCancel().

{
    int         save_errno = SOCK_ERRNO;
    int         tmpsock = -1;
    char        sebuf[256];
    int         maxlen;
    struct
    {
        uint32      packetlen;
        CancelRequestPacket cp;
    }           crp;

    /*
     * We need to open a temporary connection to the postmaster. Do this with
     * only kernel calls.
     */
    if ((tmpsock = socket(raddr->addr.ss_family, SOCK_STREAM, 0)) < 0)
    {
        strlcpy(errbuf, "PQcancel() -- socket() failed: ", errbufsize);
        goto cancel_errReturn;
    }
retry3:
    if (connect(tmpsock, (struct sockaddr *) & raddr->addr,
                raddr->salen) < 0)
    {
        if (SOCK_ERRNO == EINTR)
            /* Interrupted system call - we'll just try again */
            goto retry3;
        strlcpy(errbuf, "PQcancel() -- connect() failed: ", errbufsize);
        goto cancel_errReturn;
    }

    /*
     * We needn't set nonblocking I/O or NODELAY options here.
     */

    /* Create and send the cancel request packet. */

    crp.packetlen = htonl((uint32) sizeof(crp));
    crp.cp.cancelRequestCode = (MsgType) htonl(CANCEL_REQUEST_CODE);
    crp.cp.backendPID = htonl(be_pid);
    crp.cp.cancelAuthCode = htonl(be_key);

retry4:
    if (send(tmpsock, (char *) &crp, sizeof(crp), 0) != (int) sizeof(crp))
    {
        if (SOCK_ERRNO == EINTR)
            /* Interrupted system call - we'll just try again */
            goto retry4;
        strlcpy(errbuf, "PQcancel() -- send() failed: ", errbufsize);
        goto cancel_errReturn;
    }

    /*
     * Wait for the postmaster to close the connection, which indicates that
     * it's processed the request.  Without this delay, we might issue another
     * command only to find that our cancel zaps that command instead of the
     * one we thought we were canceling.  Note we don't actually expect this
     * read to obtain any data, we are just waiting for EOF to be signaled.
     */
retry5:
    if (recv(tmpsock, (char *) &crp, 1, 0) < 0)
    {
        if (SOCK_ERRNO == EINTR)
            /* Interrupted system call - we'll just try again */
            goto retry5;
        /* we ignore other error conditions */
    }

    /* All done */
    closesocket(tmpsock);
    SOCK_ERRNO_SET(save_errno);
    return TRUE;

cancel_errReturn:

    /*
     * Make sure we don't overflow the error buffer. Leave space for the \n at
     * the end, and for the terminating zero.
     */
    maxlen = errbufsize - strlen(errbuf) - 2;
    if (maxlen >= 0)
    {
        strncat(errbuf, SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)),
                maxlen);
        strcat(errbuf, "\n");
    }
    if (tmpsock >= 0)
        closesocket(tmpsock);
    SOCK_ERRNO_SET(save_errno);
    return FALSE;
}

static PGPing internal_ping ( PGconn conn  )  [static]

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

References pg_conn::auth_req_received, connectDBComplete(), CONNECTION_BAD, ERRCODE_CANNOT_CONNECT_NOW, pg_conn::last_sqlstate, pg_conn::options_valid, PQPING_NO_RESPONSE, PQPING_REJECT, and pg_conn::status.

Referenced by PQping(), and PQpingParams().

{
    /* Say "no attempt" if we never got to PQconnectPoll */
    if (!conn || !conn->options_valid)
        return PQPING_NO_ATTEMPT;

    /* Attempt to complete the connection */
    if (conn->status != CONNECTION_BAD)
        (void) connectDBComplete(conn);

    /* Definitely OK if we succeeded */
    if (conn->status != CONNECTION_BAD)
        return PQPING_OK;

    /*
     * Here begins the interesting part of "ping": determine the cause of the
     * failure in sufficient detail to decide what to return.  We do not want
     * to report that the server is not up just because we didn't have a valid
     * password, for example.  In fact, any sort of authentication request
     * implies the server is up.  (We need this check since the libpq side of
     * things might have pulled the plug on the connection before getting an
     * error as such from the postmaster.)
     */
    if (conn->auth_req_received)
        return PQPING_OK;

    /*
     * If we failed to get any ERROR response from the postmaster, report
     * PQPING_NO_RESPONSE.  This result could be somewhat misleading for a
     * pre-7.4 server, since it won't send back a SQLSTATE, but those are long
     * out of support.  Another corner case where the server could return a
     * failure without a SQLSTATE is fork failure, but NO_RESPONSE isn't
     * totally unreasonable for that anyway.  We expect that every other
     * failure case in a modern server will produce a report with a SQLSTATE.
     *
     * NOTE: whenever we get around to making libpq generate SQLSTATEs for
     * client-side errors, we should either not store those into
     * last_sqlstate, or add an extra flag so we can tell client-side errors
     * apart from server-side ones.
     */
    if (strlen(conn->last_sqlstate) != 5)
        return PQPING_NO_RESPONSE;

    /*
     * Report PQPING_REJECT if server says it's not accepting connections. (We
     * distinguish this case mainly for the convenience of pg_ctl.)
     */
    if (strcmp(conn->last_sqlstate, ERRCODE_CANNOT_CONNECT_NOW) == 0)
        return PQPING_REJECT;

    /*
     * Any other SQLSTATE can be taken to indicate that the server is up.
     * Presumably it didn't like our username, password, or database name; or
     * perhaps it had some transient failure, but that should not be taken as
     * meaning "it's down".
     */
    return PQPING_OK;
}

static PGconn * makeEmptyPGconn ( void   )  [static]

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

References pg_conn::asyncStatus, pg_conn::auth_req_received, pg_conn::client_encoding, pg_conn::dot_pgpass_used, pg_conn::errorMessage, freePGconn(), pg_conn::inBuffer, pg_conn::inBufSize, initPQExpBuffer(), malloc, MemSet, pg_conn::nonblocking, pg_conn::noticeHooks, PGNoticeHooks::noticeProc, PGNoticeHooks::noticeRec, NULL, pg_conn::options_valid, pg_conn::outBuffer, pg_conn::outBufSize, pg_conn::password_needed, PQExpBufferBroken, pg_conn::rowBuf, pg_conn::rowBufLen, pg_conn::setenv_state, pg_conn::sock, pg_conn::status, pg_conn::std_strings, pg_conn::verbosity, pg_conn::workBuffer, and pg_conn::xactStatus.

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

{
    PGconn     *conn;

#ifdef WIN32

    /*
     * Make sure socket support is up and running.
     */
    WSADATA     wsaData;

    if (WSAStartup(MAKEWORD(1, 1), &wsaData))
        return NULL;
    WSASetLastError(0);
#endif

    conn = (PGconn *) malloc(sizeof(PGconn));
    if (conn == NULL)
    {
#ifdef WIN32
        WSACleanup();
#endif
        return conn;
    }

    /* Zero all pointers and booleans */
    MemSet(conn, 0, sizeof(PGconn));

    /* install default notice hooks */
    conn->noticeHooks.noticeRec = defaultNoticeReceiver;
    conn->noticeHooks.noticeProc = defaultNoticeProcessor;

    conn->status = CONNECTION_BAD;
    conn->asyncStatus = PGASYNC_IDLE;
    conn->xactStatus = PQTRANS_IDLE;
    conn->options_valid = false;
    conn->nonblocking = false;
    conn->setenv_state = SETENV_STATE_IDLE;
    conn->client_encoding = PG_SQL_ASCII;
    conn->std_strings = false;  /* unless server says differently */
    conn->verbosity = PQERRORS_DEFAULT;
    conn->sock = -1;
    conn->auth_req_received = false;
    conn->password_needed = false;
    conn->dot_pgpass_used = false;
#ifdef USE_SSL
    conn->allow_ssl_try = true;
    conn->wait_ssl_try = false;
#endif

    /*
     * We try to send at least 8K at a time, which is the usual size of pipe
     * buffers on Unix systems.  That way, when we are sending a large amount
     * of data, we avoid incurring extra kernel context swaps for partial
     * bufferloads.  The output buffer is initially made 16K in size, and we
     * try to dump it after accumulating 8K.
     *
     * With the same goal of minimizing context swaps, the input buffer will
     * be enlarged anytime it has less than 8K free, so we initially allocate
     * twice that.
     */
    conn->inBufSize = 16 * 1024;
    conn->inBuffer = (char *) malloc(conn->inBufSize);
    conn->outBufSize = 16 * 1024;
    conn->outBuffer = (char *) malloc(conn->outBufSize);
    conn->rowBufLen = 32;
    conn->rowBuf = (PGdataValue *) malloc(conn->rowBufLen * sizeof(PGdataValue));
    initPQExpBuffer(&conn->errorMessage);
    initPQExpBuffer(&conn->workBuffer);

    if (conn->inBuffer == NULL ||
        conn->outBuffer == NULL ||
        conn->rowBuf == NULL ||
        PQExpBufferBroken(&conn->errorMessage) ||
        PQExpBufferBroken(&conn->workBuffer))
    {
        /* out of memory already :-( */
        freePGconn(conn);
        conn = NULL;
    }

    return conn;
}

static PQconninfoOption * parse_connection_string ( const char *  conninfo,
PQExpBuffer  errorMessage,
bool  use_defaults 
) [static]

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

References conninfo_parse(), conninfo_uri_parse(), and uri_prefix_length().

Referenced by connectOptions1(), conninfo_array_parse(), and PQconninfoParse().

{
    /* Parse as URI if connection string matches URI prefix */
    if (uri_prefix_length(connstr) != 0)
        return conninfo_uri_parse(connstr, errorMessage, use_defaults);

    /* Parse as default otherwise */
    return conninfo_parse(connstr, errorMessage, use_defaults);
}

static int parseServiceFile ( const char *  serviceFile,
const char *  service,
PQconninfoOption options,
PQExpBuffer  errorMessage,
bool group_found 
) [static]

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

References buf, _PQconninfoOption::keyword, libpq_gettext, NULL, printfPQExpBuffer(), _PQconninfoOption::val, and val.

Referenced by parseServiceInfo().

{
    int         linenr = 0,
                i;
    FILE       *f;
    char        buf[MAXBUFSIZE],
               *line;

    f = fopen(serviceFile, "r");
    if (f == NULL)
    {
        printfPQExpBuffer(errorMessage, libpq_gettext("service file \"%s\" not found\n"),
                          serviceFile);
        return 1;
    }

    while ((line = fgets(buf, sizeof(buf), f)) != NULL)
    {
        linenr++;

        if (strlen(line) >= sizeof(buf) - 1)
        {
            fclose(f);
            printfPQExpBuffer(errorMessage,
                  libpq_gettext("line %d too long in service file \"%s\"\n"),
                              linenr,
                              serviceFile);
            return 2;
        }

        /* ignore EOL at end of line */
        if (strlen(line) && line[strlen(line) - 1] == '\n')
            line[strlen(line) - 1] = 0;

        /* ignore leading blanks */
        while (*line && isspace((unsigned char) line[0]))
            line++;

        /* ignore comments and empty lines */
        if (strlen(line) == 0 || line[0] == '#')
            continue;

        /* Check for right groupname */
        if (line[0] == '[')
        {
            if (*group_found)
            {
                /* group info already read */
                fclose(f);
                return 0;
            }

            if (strncmp(line + 1, service, strlen(service)) == 0 &&
                line[strlen(service) + 1] == ']')
                *group_found = true;
            else
                *group_found = false;
        }
        else
        {
            if (*group_found)
            {
                /*
                 * Finally, we are in the right group and can parse the line
                 */
                char       *key,
                           *val;
                bool        found_keyword;

#ifdef USE_LDAP
                if (strncmp(line, "ldap", 4) == 0)
                {
                    int         rc = ldapServiceLookup(line, options, errorMessage);

                    /* if rc = 2, go on reading for fallback */
                    switch (rc)
                    {
                        case 0:
                            fclose(f);
                            return 0;
                        case 1:
                        case 3:
                            fclose(f);
                            return 3;
                        case 2:
                            continue;
                    }
                }
#endif

                key = line;
                val = strchr(line, '=');
                if (val == NULL)
                {
                    printfPQExpBuffer(errorMessage,
                                      libpq_gettext("syntax error in service file \"%s\", line %d\n"),
                                      serviceFile,
                                      linenr);
                    fclose(f);
                    return 3;
                }
                *val++ = '\0';

                /*
                 * Set the parameter --- but don't override any previous
                 * explicit setting.
                 */
                found_keyword = false;
                for (i = 0; options[i].keyword; i++)
                {
                    if (strcmp(options[i].keyword, key) == 0)
                    {
                        if (options[i].val == NULL)
                            options[i].val = strdup(val);
                        found_keyword = true;
                        break;
                    }
                }

                if (!found_keyword)
                {
                    printfPQExpBuffer(errorMessage,
                                      libpq_gettext("syntax error in service file \"%s\", line %d\n"),
                                      serviceFile,
                                      linenr);
                    fclose(f);
                    return 3;
                }
            }
        }
    }

    fclose(f);

    return 0;
}

static int parseServiceInfo ( PQconninfoOption options,
PQExpBuffer  errorMessage 
) [static]

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

References conninfo_getval(), libpq_gettext, MAXPGPATH, NULL, parseServiceFile(), pqGetHomeDirectory(), printfPQExpBuffer(), snprintf(), and strlcpy().

Referenced by conninfo_add_defaults().

{
    const char *service = conninfo_getval(options, "service");
    char        serviceFile[MAXPGPATH];
    char       *env;
    bool        group_found = false;
    int         status;
    struct stat stat_buf;

    /*
     * We have to special-case the environment variable PGSERVICE here, since
     * this is and should be called before inserting environment defaults for
     * other connection options.
     */
    if (service == NULL)
        service = getenv("PGSERVICE");

    if (service == NULL)
        return 0;

    if ((env = getenv("PGSERVICEFILE")) != NULL)
        strlcpy(serviceFile, env, sizeof(serviceFile));
    else
    {
        char        homedir[MAXPGPATH];

        if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
        {
            printfPQExpBuffer(errorMessage, libpq_gettext("could not get home directory to locate service definition file"));
            return 1;
        }
        snprintf(serviceFile, MAXPGPATH, "%s/%s", homedir, ".pg_service.conf");
        errno = 0;
        if (stat(serviceFile, &stat_buf) != 0 && errno == ENOENT)
            goto next_file;
    }

    status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
    if (group_found || status != 0)
        return status;

next_file:

    /*
     * This could be used by any application so we can't use the binary
     * location to find our config files.
     */
    snprintf(serviceFile, MAXPGPATH, "%s/pg_service.conf",
             getenv("PGSYSCONFDIR") ? getenv("PGSYSCONFDIR") : SYSCONFDIR);
    errno = 0;
    if (stat(serviceFile, &stat_buf) != 0 && errno == ENOENT)
        goto last_file;

    status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
    if (status != 0)
        return status;

last_file:
    if (!group_found)
    {
        printfPQExpBuffer(errorMessage,
         libpq_gettext("definition of service \"%s\" not found\n"), service);
        return 3;
    }

    return 0;
}

static char * PasswordFromFile ( char *  hostname,
char *  port,
char *  dbname,
char *  username 
) [static]

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

References buf, DEFAULT_PGSOCKET_DIR, getPgPassFilename(), is_absolute_path, libpq_gettext, NULL, pwdfMatchesString(), S_IRWXG, and S_IRWXO.

Referenced by connectOptions2().

{
    FILE       *fp;
    char        pgpassfile[MAXPGPATH];
    struct stat stat_buf;

#define LINELEN NAMEDATALEN*5
    char        buf[LINELEN];

    if (dbname == NULL || strlen(dbname) == 0)
        return NULL;

    if (username == NULL || strlen(username) == 0)
        return NULL;

    /* 'localhost' matches pghost of '' or the default socket directory */
    if (hostname == NULL)
        hostname = DefaultHost;
    else if (is_absolute_path(hostname))

        /*
         * We should probably use canonicalize_path(), but then we have to
         * bring path.c into libpq, and it doesn't seem worth it.
         */
        if (strcmp(hostname, DEFAULT_PGSOCKET_DIR) == 0)
            hostname = DefaultHost;

    if (port == NULL)
        port = DEF_PGPORT_STR;

    if (!getPgPassFilename(pgpassfile))
        return NULL;

    /* If password file cannot be opened, ignore it. */
    if (stat(pgpassfile, &stat_buf) != 0)
        return NULL;

#ifndef WIN32
    if (!S_ISREG(stat_buf.st_mode))
    {
        fprintf(stderr,
        libpq_gettext("WARNING: password file \"%s\" is not a plain file\n"),
                pgpassfile);
        return NULL;
    }

    /* If password file is insecure, alert the user and ignore it. */
    if (stat_buf.st_mode & (S_IRWXG | S_IRWXO))
    {
        fprintf(stderr,
                libpq_gettext("WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n"),
                pgpassfile);
        return NULL;
    }
#else

    /*
     * On Win32, the directory is protected, so we don't have to check the
     * file.
     */
#endif

    fp = fopen(pgpassfile, "r");
    if (fp == NULL)
        return NULL;

    while (!feof(fp) && !ferror(fp))
    {
        char       *t = buf,
                   *ret,
                   *p1,
                   *p2;
        int         len;

        if (fgets(buf, sizeof(buf), fp) == NULL)
            break;

        len = strlen(buf);
        if (len == 0)
            continue;

        /* Remove trailing newline */
        if (buf[len - 1] == '\n')
            buf[len - 1] = 0;

        if ((t = pwdfMatchesString(t, hostname)) == NULL ||
            (t = pwdfMatchesString(t, port)) == NULL ||
            (t = pwdfMatchesString(t, dbname)) == NULL ||
            (t = pwdfMatchesString(t, username)) == NULL)
            continue;
        ret = strdup(t);
        fclose(fp);

        /* De-escape password. */
        for (p1 = p2 = ret; *p1 != ':' && *p1 != '\0'; ++p1, ++p2)
        {
            if (*p1 == '\\' && p1[1] != '\0')
                ++p1;
            *p2 = *p1;
        }
        *p2 = '\0';

        return ret;
    }

    fclose(fp);
    return NULL;

#undef LINELEN
}

int PQbackendPID ( const PGconn conn  ) 

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

References pg_conn::be_pid, CONNECTION_OK, and pg_conn::status.

{
    if (!conn || conn->status != CONNECTION_OK)
        return 0;
    return conn->be_pid;
}

int PQcancel ( PGcancel cancel,
char *  errbuf,
int  errbufsize 
)

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

References pg_cancel::be_key, pg_cancel::be_pid, internal_cancel(), pg_cancel::raddr, and strlcpy().

Referenced by dblink_cancel_query(), DisconnectDatabase(), handle_sigint(), and run_permutation().

{
    if (!cancel)
    {
        strlcpy(errbuf, "PQcancel() -- no cancel object supplied", errbufsize);
        return FALSE;
    }

    return internal_cancel(&cancel->raddr, cancel->be_pid, cancel->be_key,
                           errbuf, errbufsize);
}

int PQclientEncoding ( const PGconn conn  ) 
PQconninfoOption* PQconndefaults ( void   ) 

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

References conninfo_add_defaults(), conninfo_init(), initPQExpBuffer(), NULL, PQconninfoFree(), PQExpBufferDataBroken, and termPQExpBuffer().

Referenced by check_pghost_envvar(), dblink_fdw_validator(), InitPgFdwOptions(), and main().

{
    PQExpBufferData errorBuf;
    PQconninfoOption *connOptions;

    /* We don't actually report any errors here, but callees want a buffer */
    initPQExpBuffer(&errorBuf);
    if (PQExpBufferDataBroken(errorBuf))
        return NULL;            /* out of memory already :-( */

    connOptions = conninfo_init(&errorBuf);
    if (connOptions != NULL)
    {
        if (!conninfo_add_defaults(connOptions, &errorBuf))
        {
            PQconninfoFree(connOptions);
            connOptions = NULL;
        }
    }

    termPQExpBuffer(&errorBuf);
    return connOptions;
}

PGconn* PQconnectdb ( const char *  conninfo  ) 

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

References conn, connectDBComplete(), CONNECTION_BAD, PQconnectStart(), and pg_conn::status.

Referenced by dblink_connect(), get_db_conn(), libpqrcv_connect(), and main().

{
    PGconn     *conn = PQconnectStart(conninfo);

    if (conn && conn->status != CONNECTION_BAD)
        (void) connectDBComplete(conn);

    return conn;
}

PGconn* PQconnectdbParams ( const char *const *  keywords,
const char *const *  values,
int  expand_dbname 
)
int PQconnectionNeedsPassword ( const PGconn conn  ) 

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

References NULL, pg_conn::password_needed, and pg_conn::pgpass.

Referenced by _connectDB(), ConnectDatabase(), connectDatabase(), do_connect(), doConnect(), GetConnection(), main(), sql_conn(), and vacuumlo().

{
    if (!conn)
        return false;
    if (conn->password_needed &&
        (conn->pgpass == NULL || conn->pgpass[0] == '\0'))
        return true;
    else
        return false;
}

int PQconnectionUsedPassword ( const PGconn conn  ) 

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

References pg_conn::password_needed.

Referenced by connect_pg_server(), and dblink_security_check().

{
    if (!conn)
        return false;
    if (conn->password_needed)
        return true;
    else
        return false;
}

PostgresPollingStatusType PQconnectPoll ( PGconn conn  ) 

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

References SockAddr::addr, pg_conn::addr_cur, pg_conn::addrlist, pg_conn::addrlist_family, addrinfo::ai_addr, addrinfo::ai_addrlen, addrinfo::ai_family, addrinfo::ai_next, appendPQExpBuffer(), appendPQExpBufferChar(), pg_conn::appname, pg_conn::asyncStatus, AUTH_REQ_GSS_CONT, AUTH_REQ_MD5, AUTH_REQ_OK, pg_conn::auth_req_received, connect, connectFailureMessage(), CONNECTION_AUTH_OK, CONNECTION_AWAITING_RESPONSE, CONNECTION_BAD, CONNECTION_MADE, CONNECTION_NEEDED, CONNECTION_OK, CONNECTION_SETENV, CONNECTION_SSL_STARTUP, CONNECTION_STARTED, connectNoDelay(), PQExpBufferData::data, dot_pg_pass_warning(), EINPROGRESS, EINTR, ERRCODE_APPNAME_UNKNOWN, pg_conn::errorMessage, EWOULDBLOCK, pg_conn::fbappname, free, getpeereid(), pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, IS_AF_UNIX, pg_conn::laddr, PQExpBufferData::len, libpq_gettext, malloc, pg_conn::md5Salt, NEGOTIATE_SSL_CODE, pg_conn::next_eo, NULL, PG_DIAG_SQLSTATE, pg_fe_sendauth(), pg_freeaddrinfo_all(), PG_PROTOCOL, PG_PROTOCOL_MAJOR, pg_set_noblock(), PGRES_FATAL_ERROR, PGRES_POLLING_FAILED, PGRES_POLLING_OK, PGRES_POLLING_READING, PGRES_POLLING_WRITING, pqBuildStartupPacket2(), pqBuildStartupPacket3(), pqCheckInBufferSpace(), PQclear(), pqDropConnection(), pqFlush(), pqGetc(), pqGetErrorNotice3(), pqGetInt(), pqGetnchar(), pqGetpwuid(), PQgetResult(), pqGets_append(), PQisBusy(), pqPacketSend(), pqReadData(), PQresultErrorField(), pqsecure_initialize(), pqsecure_open_client(), pqSetenvPoll(), pqStrerror(), printfPQExpBuffer(), pg_conn::pversion, pg_conn::raddr, pg_conn::requirepeer, pg_result::resultStatus, SockAddr::salen, pg_conn::send_appname, pg_conn::setenv_state, setKeepalivesCount(), setKeepalivesIdle(), setKeepalivesInterval(), pg_conn::sigpipe_flag, pg_conn::sigpipe_so, pg_conn::sock, SOCK_ERRNO, SOCK_STRERROR, socket, pg_conn::sslmode, pg_conn::status, STATUS_OK, and useKeepalives().

Referenced by connectDBComplete(), connectDBStart(), and PQresetPoll().

{
    PGresult   *res;
    char        sebuf[256];
    int         optval;

    if (conn == NULL)
        return PGRES_POLLING_FAILED;

    /* Get the new data */
    switch (conn->status)
    {
            /*
             * We really shouldn't have been polled in these two cases, but we
             * can handle it.
             */
        case CONNECTION_BAD:
            return PGRES_POLLING_FAILED;
        case CONNECTION_OK:
            return PGRES_POLLING_OK;

            /* These are reading states */
        case CONNECTION_AWAITING_RESPONSE:
        case CONNECTION_AUTH_OK:
            {
                /* Load waiting data */
                int         n = pqReadData(conn);

                if (n < 0)
                    goto error_return;
                if (n == 0)
                    return PGRES_POLLING_READING;

                break;
            }

            /* These are writing states, so we just proceed. */
        case CONNECTION_STARTED:
        case CONNECTION_MADE:
            break;

            /* We allow pqSetenvPoll to decide whether to proceed. */
        case CONNECTION_SETENV:
            break;

            /* Special cases: proceed without waiting. */
        case CONNECTION_SSL_STARTUP:
        case CONNECTION_NEEDED:
            break;

        default:
            appendPQExpBuffer(&conn->errorMessage,
                              libpq_gettext(
                                            "invalid connection state, "
                                 "probably indicative of memory corruption\n"
                                            ));
            goto error_return;
    }


keep_going:                     /* We will come back to here until there is
                                 * nothing left to do. */
    switch (conn->status)
    {
        case CONNECTION_NEEDED:
            {
                /*
                 * Try to initiate a connection to one of the addresses
                 * returned by pg_getaddrinfo_all().  conn->addr_cur is the
                 * next one to try. We fail when we run out of addresses.
                 */
                while (conn->addr_cur != NULL)
                {
                    struct addrinfo *addr_cur = conn->addr_cur;

                    /* Remember current address for possible error msg */
                    memcpy(&conn->raddr.addr, addr_cur->ai_addr,
                           addr_cur->ai_addrlen);
                    conn->raddr.salen = addr_cur->ai_addrlen;

                    /* Open a socket */
                    conn->sock = socket(addr_cur->ai_family, SOCK_STREAM, 0);
                    if (conn->sock < 0)
                    {
                        /*
                         * ignore socket() failure if we have more addresses
                         * to try
                         */
                        if (addr_cur->ai_next != NULL)
                        {
                            conn->addr_cur = addr_cur->ai_next;
                            continue;
                        }
                        appendPQExpBuffer(&conn->errorMessage,
                              libpq_gettext("could not create socket: %s\n"),
                            SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
                        break;
                    }

                    /*
                     * Select socket options: no delay of outgoing data for
                     * TCP sockets, nonblock mode, close-on-exec. Fail if any
                     * of this fails.
                     */
                    if (!IS_AF_UNIX(addr_cur->ai_family))
                    {
                        if (!connectNoDelay(conn))
                        {
                            pqDropConnection(conn);
                            conn->addr_cur = addr_cur->ai_next;
                            continue;
                        }
                    }
                    if (!pg_set_noblock(conn->sock))
                    {
                        appendPQExpBuffer(&conn->errorMessage,
                                          libpq_gettext("could not set socket to nonblocking mode: %s\n"),
                            SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
                        pqDropConnection(conn);
                        conn->addr_cur = addr_cur->ai_next;
                        continue;
                    }

#ifdef F_SETFD
                    if (fcntl(conn->sock, F_SETFD, FD_CLOEXEC) == -1)
                    {
                        appendPQExpBuffer(&conn->errorMessage,
                                          libpq_gettext("could not set socket to close-on-exec mode: %s\n"),
                            SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
                        pqDropConnection(conn);
                        conn->addr_cur = addr_cur->ai_next;
                        continue;
                    }
#endif   /* F_SETFD */

                    if (!IS_AF_UNIX(addr_cur->ai_family))
                    {
#ifndef WIN32
                        int         on = 1;
#endif
                        int         usekeepalives = useKeepalives(conn);
                        int         err = 0;

                        if (usekeepalives < 0)
                        {
                            appendPQExpBuffer(&conn->errorMessage,
                                              libpq_gettext("keepalives parameter must be an integer\n"));
                            err = 1;
                        }
                        else if (usekeepalives == 0)
                        {
                            /* Do nothing */
                        }
#ifndef WIN32
                        else if (setsockopt(conn->sock,
                                            SOL_SOCKET, SO_KEEPALIVE,
                                            (char *) &on, sizeof(on)) < 0)
                        {
                            appendPQExpBuffer(&conn->errorMessage,
                                              libpq_gettext("setsockopt(SO_KEEPALIVE) failed: %s\n"),
                            SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
                            err = 1;
                        }
                        else if (!setKeepalivesIdle(conn)
                                 || !setKeepalivesInterval(conn)
                                 || !setKeepalivesCount(conn))
                            err = 1;
#else                           /* WIN32 */
#ifdef SIO_KEEPALIVE_VALS
                        else if (!setKeepalivesWin32(conn))
                            err = 1;
#endif   /* SIO_KEEPALIVE_VALS */
#endif   /* WIN32 */

                        if (err)
                        {
                            pqDropConnection(conn);
                            conn->addr_cur = addr_cur->ai_next;
                            continue;
                        }
                    }

                    /*----------
                     * We have three methods of blocking SIGPIPE during
                     * send() calls to this socket:
                     *
                     *  - setsockopt(sock, SO_NOSIGPIPE)
                     *  - send(sock, ..., MSG_NOSIGNAL)
                     *  - setting the signal mask to SIG_IGN during send()
                     *
                     * The third method requires three syscalls per send,
                     * so we prefer either of the first two, but they are
                     * less portable.  The state is tracked in the following
                     * members of PGconn:
                     *
                     * conn->sigpipe_so     - we have set up SO_NOSIGPIPE
                     * conn->sigpipe_flag   - we're specifying MSG_NOSIGNAL
                     *
                     * If we can use SO_NOSIGPIPE, then set sigpipe_so here
                     * and we're done.  Otherwise, set sigpipe_flag so that
                     * we will try MSG_NOSIGNAL on sends.  If we get an error
                     * with MSG_NOSIGNAL, we'll clear that flag and revert to
                     * signal masking.
                     *----------
                     */
                    conn->sigpipe_so = false;
#ifdef MSG_NOSIGNAL
                    conn->sigpipe_flag = true;
#else
                    conn->sigpipe_flag = false;
#endif   /* MSG_NOSIGNAL */

#ifdef SO_NOSIGPIPE
                    optval = 1;
                    if (setsockopt(conn->sock, SOL_SOCKET, SO_NOSIGPIPE,
                                   (char *) &optval, sizeof(optval)) == 0)
                    {
                        conn->sigpipe_so = true;
                        conn->sigpipe_flag = false;
                    }
#endif   /* SO_NOSIGPIPE */

                    /*
                     * Start/make connection.  This should not block, since we
                     * are in nonblock mode.  If it does, well, too bad.
                     */
                    if (connect(conn->sock, addr_cur->ai_addr,
                                addr_cur->ai_addrlen) < 0)
                    {
                        if (SOCK_ERRNO == EINPROGRESS ||
                            SOCK_ERRNO == EWOULDBLOCK ||
                            SOCK_ERRNO == EINTR ||
                            SOCK_ERRNO == 0)
                        {
                            /*
                             * This is fine - we're in non-blocking mode, and
                             * the connection is in progress.  Tell caller to
                             * wait for write-ready on socket.
                             */
                            conn->status = CONNECTION_STARTED;
                            return PGRES_POLLING_WRITING;
                        }
                        /* otherwise, trouble */
                    }
                    else
                    {
                        /*
                         * Hm, we're connected already --- seems the "nonblock
                         * connection" wasn't.  Advance the state machine and
                         * go do the next stuff.
                         */
                        conn->status = CONNECTION_STARTED;
                        goto keep_going;
                    }

                    /*
                     * This connection failed --- set up error report, then
                     * close socket (do it this way in case close() affects
                     * the value of errno...).  We will ignore the connect()
                     * failure and keep going if there are more addresses.
                     */
                    connectFailureMessage(conn, SOCK_ERRNO);
                    pqDropConnection(conn);

                    /*
                     * Try the next address, if any.
                     */
                    conn->addr_cur = addr_cur->ai_next;
                }               /* loop over addresses */

                /*
                 * Ooops, no more addresses.  An appropriate error message is
                 * already set up, so just set the right status.
                 */
                goto error_return;
            }

        case CONNECTION_STARTED:
            {
                ACCEPT_TYPE_ARG3 optlen = sizeof(optval);

                /*
                 * Write ready, since we've made it here, so the connection
                 * has been made ... or has failed.
                 */

                /*
                 * Now check (using getsockopt) that there is not an error
                 * state waiting for us on the socket.
                 */

                if (getsockopt(conn->sock, SOL_SOCKET, SO_ERROR,
                               (char *) &optval, &optlen) == -1)
                {
                    appendPQExpBuffer(&conn->errorMessage,
                    libpq_gettext("could not get socket error status: %s\n"),
                            SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
                    goto error_return;
                }
                else if (optval != 0)
                {
                    /*
                     * When using a nonblocking connect, we will typically see
                     * connect failures at this point, so provide a friendly
                     * error message.
                     */
                    connectFailureMessage(conn, optval);
                    pqDropConnection(conn);

                    /*
                     * If more addresses remain, keep trying, just as in the
                     * case where connect() returned failure immediately.
                     */
                    if (conn->addr_cur->ai_next != NULL)
                    {
                        conn->addr_cur = conn->addr_cur->ai_next;
                        conn->status = CONNECTION_NEEDED;
                        goto keep_going;
                    }
                    goto error_return;
                }

                /* Fill in the client address */
                conn->laddr.salen = sizeof(conn->laddr.addr);
                if (getsockname(conn->sock,
                                (struct sockaddr *) & conn->laddr.addr,
                                &conn->laddr.salen) < 0)
                {
                    appendPQExpBuffer(&conn->errorMessage,
                                      libpq_gettext("could not get client address from socket: %s\n"),
                            SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
                    goto error_return;
                }

                /*
                 * Make sure we can write before advancing to next step.
                 */
                conn->status = CONNECTION_MADE;
                return PGRES_POLLING_WRITING;
            }

        case CONNECTION_MADE:
            {
                char       *startpacket;
                int         packetlen;

#ifdef HAVE_UNIX_SOCKETS

                /*
                 * Implement requirepeer check, if requested and it's a
                 * Unix-domain socket.
                 */
                if (conn->requirepeer && conn->requirepeer[0] &&
                    IS_AF_UNIX(conn->raddr.addr.ss_family))
                {
                    char        pwdbuf[BUFSIZ];
                    struct passwd pass_buf;
                    struct passwd *pass;
                    uid_t       uid;
                    gid_t       gid;

                    errno = 0;
                    if (getpeereid(conn->sock, &uid, &gid) != 0)
                    {
                        /*
                         * Provide special error message if getpeereid is a
                         * stub
                         */
                        if (errno == ENOSYS)
                            appendPQExpBuffer(&conn->errorMessage,
                                              libpq_gettext("requirepeer parameter is not supported on this platform\n"));
                        else
                            appendPQExpBuffer(&conn->errorMessage,
                                              libpq_gettext("could not get peer credentials: %s\n"),
                                    pqStrerror(errno, sebuf, sizeof(sebuf)));
                        goto error_return;
                    }

                    pqGetpwuid(uid, &pass_buf, pwdbuf, sizeof(pwdbuf), &pass);

                    if (pass == NULL)
                    {
                        appendPQExpBuffer(&conn->errorMessage,
                                          libpq_gettext("local user with ID %d does not exist\n"),
                                          (int) uid);
                        goto error_return;
                    }

                    if (strcmp(pass->pw_name, conn->requirepeer) != 0)
                    {
                        appendPQExpBuffer(&conn->errorMessage,
                                          libpq_gettext("requirepeer specifies \"%s\", but actual peer user name is \"%s\"\n"),
                                          conn->requirepeer, pass->pw_name);
                        goto error_return;
                    }
                }
#endif   /* HAVE_UNIX_SOCKETS */

#ifdef USE_SSL

                /*
                 * If SSL is enabled and we haven't already got it running,
                 * request it instead of sending the startup message.
                 */
                if (IS_AF_UNIX(conn->raddr.addr.ss_family))
                {
                    /* Don't bother requesting SSL over a Unix socket */
                    conn->allow_ssl_try = false;
                }
                if (conn->allow_ssl_try && !conn->wait_ssl_try &&
                    conn->ssl == NULL)
                {
                    ProtocolVersion pv;

                    /*
                     * Send the SSL request packet.
                     *
                     * Theoretically, this could block, but it really
                     * shouldn't since we only got here if the socket is
                     * write-ready.
                     */
                    pv = htonl(NEGOTIATE_SSL_CODE);
                    if (pqPacketSend(conn, 0, &pv, sizeof(pv)) != STATUS_OK)
                    {
                        appendPQExpBuffer(&conn->errorMessage,
                                          libpq_gettext("could not send SSL negotiation packet: %s\n"),
                            SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
                        goto error_return;
                    }
                    /* Ok, wait for response */
                    conn->status = CONNECTION_SSL_STARTUP;
                    return PGRES_POLLING_READING;
                }
#endif   /* USE_SSL */

                /*
                 * Build the startup packet.
                 */
                if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
                    startpacket = pqBuildStartupPacket3(conn, &packetlen,
                                                        EnvironmentOptions);
                else
                    startpacket = pqBuildStartupPacket2(conn, &packetlen,
                                                        EnvironmentOptions);
                if (!startpacket)
                {
                    /*
                     * will not appendbuffer here, since it's likely to also
                     * run out of memory
                     */
                    printfPQExpBuffer(&conn->errorMessage,
                                      libpq_gettext("out of memory\n"));
                    goto error_return;
                }

                /*
                 * Send the startup packet.
                 *
                 * Theoretically, this could block, but it really shouldn't
                 * since we only got here if the socket is write-ready.
                 */
                if (pqPacketSend(conn, 0, startpacket, packetlen) != STATUS_OK)
                {
                    appendPQExpBuffer(&conn->errorMessage,
                        libpq_gettext("could not send startup packet: %s\n"),
                            SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
                    free(startpacket);
                    goto error_return;
                }

                free(startpacket);

                conn->status = CONNECTION_AWAITING_RESPONSE;
                return PGRES_POLLING_READING;
            }

            /*
             * Handle SSL negotiation: wait for postmaster messages and
             * respond as necessary.
             */
        case CONNECTION_SSL_STARTUP:
            {
#ifdef USE_SSL
                PostgresPollingStatusType pollres;

                /*
                 * On first time through, get the postmaster's response to our
                 * SSL negotiation packet.
                 */
                if (conn->ssl == NULL)
                {
                    /*
                     * We use pqReadData here since it has the logic to
                     * distinguish no-data-yet from connection closure. Since
                     * conn->ssl isn't set, a plain recv() will occur.
                     */
                    char        SSLok;
                    int         rdresult;

                    rdresult = pqReadData(conn);
                    if (rdresult < 0)
                    {
                        /* errorMessage is already filled in */
                        goto error_return;
                    }
                    if (rdresult == 0)
                    {
                        /* caller failed to wait for data */
                        return PGRES_POLLING_READING;
                    }
                    if (pqGetc(&SSLok, conn) < 0)
                    {
                        /* should not happen really */
                        return PGRES_POLLING_READING;
                    }
                    if (SSLok == 'S')
                    {
                        /* mark byte consumed */
                        conn->inStart = conn->inCursor;
                        /* Set up global SSL state if required */
                        if (pqsecure_initialize(conn) != 0)
                            goto error_return;
                    }
                    else if (SSLok == 'N')
                    {
                        /* mark byte consumed */
                        conn->inStart = conn->inCursor;
                        /* OK to do without SSL? */
                        if (conn->sslmode[0] == 'r' ||  /* "require" */
                            conn->sslmode[0] == 'v')    /* "verify-ca" or
                                                         * "verify-full" */
                        {
                            /* Require SSL, but server does not want it */
                            appendPQExpBuffer(&conn->errorMessage,
                                              libpq_gettext("server does not support SSL, but SSL was required\n"));
                            goto error_return;
                        }
                        /* Otherwise, proceed with normal startup */
                        conn->allow_ssl_try = false;
                        conn->status = CONNECTION_MADE;
                        return PGRES_POLLING_WRITING;
                    }
                    else if (SSLok == 'E')
                    {
                        /*
                         * Server failure of some sort, such as failure to
                         * fork a backend process.  We need to process and
                         * report the error message, which might be formatted
                         * according to either protocol 2 or protocol 3.
                         * Rather than duplicate the code for that, we flip
                         * into AWAITING_RESPONSE state and let the code there
                         * deal with it.  Note we have *not* consumed the "E"
                         * byte here.
                         */
                        conn->status = CONNECTION_AWAITING_RESPONSE;
                        goto keep_going;
                    }
                    else
                    {
                        appendPQExpBuffer(&conn->errorMessage,
                                          libpq_gettext("received invalid response to SSL negotiation: %c\n"),
                                          SSLok);
                        goto error_return;
                    }
                }

                /*
                 * Begin or continue the SSL negotiation process.
                 */
                pollres = pqsecure_open_client(conn);
                if (pollres == PGRES_POLLING_OK)
                {
                    /* SSL handshake done, ready to send startup packet */
                    conn->status = CONNECTION_MADE;
                    return PGRES_POLLING_WRITING;
                }
                if (pollres == PGRES_POLLING_FAILED)
                {
                    /*
                     * Failed ... if sslmode is "prefer" then do a non-SSL
                     * retry
                     */
                    if (conn->sslmode[0] == 'p' /* "prefer" */
                        && conn->allow_ssl_try  /* redundant? */
                        && !conn->wait_ssl_try) /* redundant? */
                    {
                        /* only retry once */
                        conn->allow_ssl_try = false;
                        /* Must drop the old connection */
                        pqDropConnection(conn);
                        conn->status = CONNECTION_NEEDED;
                        goto keep_going;
                    }
                }
                return pollres;
#else                           /* !USE_SSL */
                /* can't get here */
                goto error_return;
#endif   /* USE_SSL */
            }

            /*
             * Handle authentication exchange: wait for postmaster messages
             * and respond as necessary.
             */
        case CONNECTION_AWAITING_RESPONSE:
            {
                char        beresp;
                int         msgLength;
                int         avail;
                AuthRequest areq;

                /*
                 * Scan the message from current point (note that if we find
                 * the message is incomplete, we will return without advancing
                 * inStart, and resume here next time).
                 */
                conn->inCursor = conn->inStart;

                /* Read type byte */
                if (pqGetc(&beresp, conn))
                {
                    /* We'll come back when there is more data */
                    return PGRES_POLLING_READING;
                }

                /*
                 * Validate message type: we expect only an authentication
                 * request or an error here.  Anything else probably means
                 * it's not Postgres on the other end at all.
                 */
                if (!(beresp == 'R' || beresp == 'E'))
                {
                    appendPQExpBuffer(&conn->errorMessage,
                                      libpq_gettext(
                                      "expected authentication request from "
                                                "server, but received %c\n"),
                                      beresp);
                    goto error_return;
                }

                if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
                {
                    /* Read message length word */
                    if (pqGetInt(&msgLength, 4, conn))
                    {
                        /* We'll come back when there is more data */
                        return PGRES_POLLING_READING;
                    }
                }
                else
                {
                    /* Set phony message length to disable checks below */
                    msgLength = 8;
                }

                /*
                 * Try to validate message length before using it.
                 * Authentication requests can't be very large, although GSS
                 * auth requests may not be that small.  Errors can be a
                 * little larger, but not huge.  If we see a large apparent
                 * length in an error, it means we're really talking to a
                 * pre-3.0-protocol server; cope.
                 */
                if (beresp == 'R' && (msgLength < 8 || msgLength > 2000))
                {
                    appendPQExpBuffer(&conn->errorMessage,
                                      libpq_gettext(
                                      "expected authentication request from "
                                                "server, but received %c\n"),
                                      beresp);
                    goto error_return;
                }

                if (beresp == 'E' && (msgLength < 8 || msgLength > 30000))
                {
                    /* Handle error from a pre-3.0 server */
                    conn->inCursor = conn->inStart + 1; /* reread data */
                    if (pqGets_append(&conn->errorMessage, conn))
                    {
                        /* We'll come back when there is more data */
                        return PGRES_POLLING_READING;
                    }
                    /* OK, we read the message; mark data consumed */
                    conn->inStart = conn->inCursor;

                    /*
                     * The postmaster typically won't end its message with a
                     * newline, so add one to conform to libpq conventions.
                     */
                    appendPQExpBufferChar(&conn->errorMessage, '\n');

                    /*
                     * If we tried to open the connection in 3.0 protocol,
                     * fall back to 2.0 protocol.
                     */
                    if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
                    {
                        conn->pversion = PG_PROTOCOL(2, 0);
                        /* Must drop the old connection */
                        pqDropConnection(conn);
                        conn->status = CONNECTION_NEEDED;
                        goto keep_going;
                    }

                    goto error_return;
                }

                /*
                 * Can't process if message body isn't all here yet.
                 *
                 * (In protocol 2.0 case, we are assuming messages carry at
                 * least 4 bytes of data.)
                 */
                msgLength -= 4;
                avail = conn->inEnd - conn->inCursor;
                if (avail < msgLength)
                {
                    /*
                     * Before returning, try to enlarge the input buffer if
                     * needed to hold the whole message; see notes in
                     * pqParseInput3.
                     */
                    if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength,
                                             conn))
                        goto error_return;
                    /* We'll come back when there is more data */
                    return PGRES_POLLING_READING;
                }

                /* Handle errors. */
                if (beresp == 'E')
                {
                    if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
                    {
                        if (pqGetErrorNotice3(conn, true))
                        {
                            /* We'll come back when there is more data */
                            return PGRES_POLLING_READING;
                        }
                    }
                    else
                    {
                        if (pqGets_append(&conn->errorMessage, conn))
                        {
                            /* We'll come back when there is more data */
                            return PGRES_POLLING_READING;
                        }
                    }
                    /* OK, we read the message; mark data consumed */
                    conn->inStart = conn->inCursor;

#ifdef USE_SSL

                    /*
                     * if sslmode is "allow" and we haven't tried an SSL
                     * connection already, then retry with an SSL connection
                     */
                    if (conn->sslmode[0] == 'a' /* "allow" */
                        && conn->ssl == NULL
                        && conn->allow_ssl_try
                        && conn->wait_ssl_try)
                    {
                        /* only retry once */
                        conn->wait_ssl_try = false;
                        /* Must drop the old connection */
                        pqDropConnection(conn);
                        conn->status = CONNECTION_NEEDED;
                        goto keep_going;
                    }

                    /*
                     * if sslmode is "prefer" and we're in an SSL connection,
                     * then do a non-SSL retry
                     */
                    if (conn->sslmode[0] == 'p' /* "prefer" */
                        && conn->allow_ssl_try
                        && !conn->wait_ssl_try) /* redundant? */
                    {
                        /* only retry once */
                        conn->allow_ssl_try = false;
                        /* Must drop the old connection */
                        pqDropConnection(conn);
                        conn->status = CONNECTION_NEEDED;
                        goto keep_going;
                    }
#endif

                    goto error_return;
                }

                /* It is an authentication request. */
                conn->auth_req_received = true;

                /* Get the type of request. */
                if (pqGetInt((int *) &areq, 4, conn))
                {
                    /* We'll come back when there are more data */
                    return PGRES_POLLING_READING;
                }

                /* Get the password salt if there is one. */
                if (areq == AUTH_REQ_MD5)
                {
                    if (pqGetnchar(conn->md5Salt,
                                   sizeof(conn->md5Salt), conn))
                    {
                        /* We'll come back when there are more data */
                        return PGRES_POLLING_READING;
                    }
                }
#if defined(ENABLE_GSS) || defined(ENABLE_SSPI)

                /*
                 * Continue GSSAPI/SSPI authentication
                 */
                if (areq == AUTH_REQ_GSS_CONT)
                {
                    int         llen = msgLength - 4;

                    /*
                     * We can be called repeatedly for the same buffer. Avoid
                     * re-allocating the buffer in this case - just re-use the
                     * old buffer.
                     */
                    if (llen != conn->ginbuf.length)
                    {
                        if (conn->ginbuf.value)
                            free(conn->ginbuf.value);

                        conn->ginbuf.length = llen;
                        conn->ginbuf.value = malloc(llen);
                        if (!conn->ginbuf.value)
                        {
                            printfPQExpBuffer(&conn->errorMessage,
                                              libpq_gettext("out of memory allocating GSSAPI buffer (%d)"),
                                              llen);
                            goto error_return;
                        }
                    }

                    if (pqGetnchar(conn->ginbuf.value, llen, conn))
                    {
                        /* We'll come back when there is more data. */
                        return PGRES_POLLING_READING;
                    }
                }
#endif

                /*
                 * OK, we successfully read the message; mark data consumed
                 */
                conn->inStart = conn->inCursor;

                /* Respond to the request if necessary. */

                /*
                 * Note that conn->pghost must be non-NULL if we are going to
                 * avoid the Kerberos code doing a hostname look-up.
                 */

                if (pg_fe_sendauth(areq, conn) != STATUS_OK)
                {
                    conn->errorMessage.len = strlen(conn->errorMessage.data);
                    goto error_return;
                }
                conn->errorMessage.len = strlen(conn->errorMessage.data);

                /*
                 * Just make sure that any data sent by pg_fe_sendauth is
                 * flushed out.  Although this theoretically could block, it
                 * really shouldn't since we don't send large auth responses.
                 */
                if (pqFlush(conn))
                    goto error_return;

                if (areq == AUTH_REQ_OK)
                {
                    /* We are done with authentication exchange */
                    conn->status = CONNECTION_AUTH_OK;

                    /*
                     * Set asyncStatus so that PQgetResult will think that
                     * what comes back next is the result of a query.  See
                     * below.
                     */
                    conn->asyncStatus = PGASYNC_BUSY;
                }

                /* Look to see if we have more data yet. */
                goto keep_going;
            }

        case CONNECTION_AUTH_OK:
            {
                /*
                 * Now we expect to hear from the backend. A ReadyForQuery
                 * message indicates that startup is successful, but we might
                 * also get an Error message indicating failure. (Notice
                 * messages indicating nonfatal warnings are also allowed by
                 * the protocol, as are ParameterStatus and BackendKeyData
                 * messages.) Easiest way to handle this is to let
                 * PQgetResult() read the messages. We just have to fake it
                 * out about the state of the connection, by setting
                 * asyncStatus = PGASYNC_BUSY (done above).
                 */

                if (PQisBusy(conn))
                    return PGRES_POLLING_READING;

                res = PQgetResult(conn);

                /*
                 * NULL return indicating we have gone to IDLE state is
                 * expected
                 */
                if (res)
                {
                    if (res->resultStatus != PGRES_FATAL_ERROR)
                        appendPQExpBuffer(&conn->errorMessage,
                                          libpq_gettext("unexpected message from server during startup\n"));
                    else if (conn->send_appname &&
                             (conn->appname || conn->fbappname))
                    {
                        /*
                         * If we tried to send application_name, check to see
                         * if the error is about that --- pre-9.0 servers will
                         * reject it at this stage of the process.  If so,
                         * close the connection and retry without sending
                         * application_name.  We could possibly get a false
                         * SQLSTATE match here and retry uselessly, but there
                         * seems no great harm in that; we'll just get the
                         * same error again if it's unrelated.
                         */
                        const char *sqlstate;

                        sqlstate = PQresultErrorField(res, PG_DIAG_SQLSTATE);
                        if (sqlstate &&
                            strcmp(sqlstate, ERRCODE_APPNAME_UNKNOWN) == 0)
                        {
                            PQclear(res);
                            conn->send_appname = false;
                            /* Must drop the old connection */
                            pqDropConnection(conn);
                            conn->status = CONNECTION_NEEDED;
                            goto keep_going;
                        }
                    }

                    /*
                     * if the resultStatus is FATAL, then conn->errorMessage
                     * already has a copy of the error; needn't copy it back.
                     * But add a newline if it's not there already, since
                     * postmaster error messages may not have one.
                     */
                    if (conn->errorMessage.len <= 0 ||
                        conn->errorMessage.data[conn->errorMessage.len - 1] != '\n')
                        appendPQExpBufferChar(&conn->errorMessage, '\n');
                    PQclear(res);
                    goto error_return;
                }

                /* We can release the address list now. */
                pg_freeaddrinfo_all(conn->addrlist_family, conn->addrlist);
                conn->addrlist = NULL;
                conn->addr_cur = NULL;

                /* Fire up post-connection housekeeping if needed */
                if (PG_PROTOCOL_MAJOR(conn->pversion) < 3)
                {
                    conn->status = CONNECTION_SETENV;
                    conn->setenv_state = SETENV_STATE_CLIENT_ENCODING_SEND;
                    conn->next_eo = EnvironmentOptions;
                    return PGRES_POLLING_WRITING;
                }

                /* Otherwise, we are open for business! */
                conn->status = CONNECTION_OK;
                return PGRES_POLLING_OK;
            }

        case CONNECTION_SETENV:

            /*
             * Do post-connection housekeeping (only needed in protocol 2.0).
             *
             * We pretend that the connection is OK for the duration of these
             * queries.
             */
            conn->status = CONNECTION_OK;

            switch (pqSetenvPoll(conn))
            {
                case PGRES_POLLING_OK:  /* Success */
                    break;

                case PGRES_POLLING_READING:     /* Still going */
                    conn->status = CONNECTION_SETENV;
                    return PGRES_POLLING_READING;

                case PGRES_POLLING_WRITING:     /* Still going */
                    conn->status = CONNECTION_SETENV;
                    return PGRES_POLLING_WRITING;

                default:
                    goto error_return;
            }

            /* We are open for business! */
            conn->status = CONNECTION_OK;
            return PGRES_POLLING_OK;

        default:
            appendPQExpBuffer(&conn->errorMessage,
                              libpq_gettext("invalid connection state %d, "
                               "probably indicative of memory corruption\n"),
                              conn->status);
            goto error_return;
    }

    /* Unreachable */

error_return:

    dot_pg_pass_warning(conn);

    /*
     * We used to close the socket at this point, but that makes it awkward
     * for those above us if they wish to remove this socket from their own
     * records (an fd_set for example).  We'll just have this socket closed
     * when PQfinish is called (which is compulsory even after an error, since
     * the connection structure must be freed).
     */
    conn->status = CONNECTION_BAD;
    return PGRES_POLLING_FAILED;
}

PGconn* PQconnectStart ( const char *  conninfo  ) 

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

References conn, connectDBStart(), connectOptions1(), connectOptions2(), makeEmptyPGconn(), NULL, and pg_conn::status.

Referenced by PQconnectdb(), and PQping().

{
    PGconn     *conn;

    /*
     * Allocate memory for the conn structure
     */
    conn = makeEmptyPGconn();
    if (conn == NULL)
        return NULL;

    /*
     * Parse the conninfo string
     */
    if (!connectOptions1(conn, conninfo))
        return conn;

    /*
     * Compute derived options
     */
    if (!connectOptions2(conn))
        return conn;

    /*
     * Connect to the database
     */
    if (!connectDBStart(conn))
    {
        /* Just in case we failed to set it in connectDBStart */
        conn->status = CONNECTION_BAD;
    }

    return conn;
}

PGconn* PQconnectStartParams ( const char *const *  keywords,
const char *const *  values,
int  expand_dbname 
)

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

References conn, connectDBStart(), connectOptions2(), conninfo_array_parse(), pg_conn::errorMessage, fillPGconn(), makeEmptyPGconn(), NULL, PQconninfoFree(), and pg_conn::status.

Referenced by PQconnectdbParams(), and PQpingParams().

{
    PGconn     *conn;
    PQconninfoOption *connOptions;

    /*
     * Allocate memory for the conn structure
     */
    conn = makeEmptyPGconn();
    if (conn == NULL)
        return NULL;

    /*
     * Parse the conninfo arrays
     */
    connOptions = conninfo_array_parse(keywords, values,
                                       &conn->errorMessage,
                                       true, expand_dbname);
    if (connOptions == NULL)
    {
        conn->status = CONNECTION_BAD;
        /* errorMessage is already set */
        return conn;
    }

    /*
     * Move option values into conn structure
     */
    fillPGconn(conn, connOptions);

    /*
     * Free the option info - all is in conn now
     */
    PQconninfoFree(connOptions);

    /*
     * Compute derived options
     */
    if (!connectOptions2(conn))
        return conn;

    /*
     * Connect to the database
     */
    if (!connectDBStart(conn))
    {
        /* Just in case we failed to set it in connectDBStart */
        conn->status = CONNECTION_BAD;
    }

    return conn;
}

PQconninfoOption* PQconninfo ( PGconn conn  ) 

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

References conninfo_init(), conninfo_storeval(), _internalPQconninfoOption::connofs, initPQExpBuffer(), _internalPQconninfoOption::keyword, NULL, PQExpBufferDataBroken, and termPQExpBuffer().

Referenced by GenerateRecoveryConf().

{
    PQExpBufferData errorBuf;
    PQconninfoOption *connOptions;

    if (conn == NULL)
        return NULL;

    /* We don't actually report any errors here, but callees want a buffer */
    initPQExpBuffer(&errorBuf);
    if (PQExpBufferDataBroken(errorBuf))
        return NULL;            /* out of memory already :-( */

    connOptions = conninfo_init(&errorBuf);

    if (connOptions != NULL)
    {
        const internalPQconninfoOption *option;

        for (option = PQconninfoOptions; option->keyword; option++)
        {
            char      **connmember;

            if (option->connofs < 0)
                continue;

            connmember = (char **) ((char *) conn + option->connofs);

            if (*connmember)
                conninfo_storeval(connOptions, option->keyword, *connmember,
                                  &errorBuf, true, false);
        }
    }

    termPQExpBuffer(&errorBuf);

    return connOptions;
}

void PQconninfoFree ( PQconninfoOption connOptions  ) 

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

References free, _PQconninfoOption::keyword, NULL, and _PQconninfoOption::val.

Referenced by check_pghost_envvar(), connectDatabase(), connectOptions1(), conninfo_array_parse(), conninfo_parse(), conninfo_uri_parse(), dblink_connstr_check(), GenerateRecoveryConf(), GetConnection(), main(), PQconndefaults(), and PQconnectStartParams().

{
    PQconninfoOption *option;

    if (connOptions == NULL)
        return;

    for (option = connOptions; option->keyword != NULL; option++)
    {
        if (option->val != NULL)
            free(option->val);
    }
    free(connOptions);
}

PQconninfoOption* PQconninfoParse ( const char *  conninfo,
char **  errmsg 
)

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

References PQExpBufferData::data, initPQExpBuffer(), NULL, parse_connection_string(), PQExpBufferDataBroken, and termPQExpBuffer().

Referenced by connectDatabase(), dblink_connstr_check(), GetConnection(), and main().

{
    PQExpBufferData errorBuf;
    PQconninfoOption *connOptions;

    if (errmsg)
        *errmsg = NULL;         /* default */
    initPQExpBuffer(&errorBuf);
    if (PQExpBufferDataBroken(errorBuf))
        return NULL;            /* out of memory already :-( */
    connOptions = parse_connection_string(conninfo, &errorBuf, false);
    if (connOptions == NULL && errmsg)
        *errmsg = errorBuf.data;
    else
        termPQExpBuffer(&errorBuf);
    return connOptions;
}

char* PQdb ( const PGconn conn  ) 
void pqDropConnection ( PGconn conn  ) 

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

References closesocket, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, pg_conn::outCount, pqsecure_close(), and pg_conn::sock.

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

{
    /* Drop any SSL state */
    pqsecure_close(conn);
    /* Close the socket itself */
    if (conn->sock >= 0)
        closesocket(conn->sock);
    conn->sock = -1;
    /* Discard any unread/unsent data */
    conn->inStart = conn->inCursor = conn->inEnd = 0;
    conn->outCount = 0;
}

char* PQerrorMessage ( const PGconn conn  ) 

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

References PQExpBufferData::data, pg_conn::errorMessage, and libpq_gettext.

Referenced by _connectDB(), _doSetSessionAuth(), _doSetWithOids(), _selectOutputSchema(), _selectTablespace(), AcceptResult(), BaseBackup(), check_conn(), check_loadable_libraries(), cluster_one_database(), connect_pg_server(), ConnectDatabase(), connectDatabase(), connectToServer(), dblink_connect(), dblink_error_message(), dblink_send_query(), die_on_query_failure(), do_connect(), do_lo_export(), do_lo_import(), do_lo_unlink(), doConnect(), doCustom(), dumpBlobs(), dumpTableData_copy(), ecpg_check_PQresult(), ecpg_raise_backend(), ECPGconnect(), EndDBCopyMode(), executeCommand(), executeQuery(), executeQueryOrDie(), ExecuteSqlCommand(), ExecuteSqlCommandBuf(), executeStatement(), GetConnection(), handleCopyIn(), handleCopyOut(), HandleCopyStream(), init(), libpqrcv_connect(), libpqrcv_endstreaming(), libpqrcv_identify_system(), libpqrcv_readtimelinehistoryfile(), libpqrcv_receive(), libpqrcv_send(), libpqrcv_startstreaming(), lockTableNoWait(), main(), my_truncate(), overwrite(), pickout(), PSQLexec(), ReceiveAndUnpackTarFile(), ReceiveTarFile(), ReceiveXlogStream(), reindex_one_database(), reindex_system_catalogs(), run_permutation(), sendFeedback(), SendQuery(), sql_conn(), sql_exec(), start_postmaster(), StartRestoreBlob(), storeQueryResult(), StreamLog(), try_complete_step(), vacuum_one_database(), and vacuumlo().

{
    if (!conn)
        return libpq_gettext("connection pointer is NULL\n");

    return conn->errorMessage.data;
}

void PQfinish ( PGconn conn  ) 

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

References closePGconn(), and freePGconn().

Referenced by _connectDB(), BaseBackup(), check_for_isn_and_int8_passing_mismatch(), check_for_prepared_transactions(), check_for_reg_data_type_usage(), check_is_super_user(), check_loadable_libraries(), CheckConnection(), clientDone(), cluster_all_databases(), cluster_one_database(), connect_pg_server(), ConnectDatabase(), connectDatabase(), connectToServer(), createNewConnection(), dblink_connect(), dblink_disconnect(), dblink_exec(), dblink_record_internal(), dblink_security_check(), disconnect_all(), DisconnectDatabase(), do_connect(), doConnect(), doCustom(), dumpCreateDB(), dumpTablespaces(), ecpg_finish(), executeCommand(), executeQuery(), executeQueryOrDie(), exit_nicely(), get_db_infos(), get_loadable_libraries(), get_pg_database_relfilenode(), get_rel_infos(), get_tablespace_paths(), GetConnection(), init(), install_support_functions_in_new_db(), libpqrcv_disconnect(), LogStreamerMain(), main(), new_9_0_populate_pg_largeobject_metadata(), old_8_3_check_for_name_data_type_usage(), old_8_3_check_for_tsquery_usage(), old_8_3_check_ltree_usage(), old_8_3_create_sequence_script(), old_8_3_invalidate_bpchar_pattern_ops_indexes(), old_8_3_invalidate_hash_gin_indexes(), old_8_3_rebuild_tsvector_tables(), pgfdw_xact_callback(), PQping(), PQpingParams(), ReconnectToServer(), reindex_all_databases(), reindex_one_database(), reindex_system_catalogs(), set_frozenxids(), set_locale_and_encoding(), sql_conn(), sql_exec(), start_postmaster(), StreamLog(), threadRun(), uninstall_support_functions_from_new_cluster(), vacuum_all_databases(), vacuum_one_database(), vacuumlo(), and WaitForCommands().

{
    if (conn)
    {
        closePGconn(conn);
        freePGconn(conn);
    }
}

void PQfreeCancel ( PGcancel cancel  ) 

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

References free.

Referenced by dblink_cancel_query(), DisconnectDatabase(), ResetCancelConn(), run_permutation(), and SetCancelConn().

{
    if (cancel)
        free(cancel);
}

PGcancel* PQgetCancel ( PGconn conn  ) 

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

References pg_conn::be_key, pg_cancel::be_key, pg_conn::be_pid, pg_cancel::be_pid, malloc, NULL, pg_conn::raddr, pg_cancel::raddr, and pg_conn::sock.

Referenced by dblink_cancel_query(), DisconnectDatabase(), run_permutation(), and SetCancelConn().

{
    PGcancel   *cancel;

    if (!conn)
        return NULL;

    if (conn->sock < 0)
        return NULL;

    cancel = malloc(sizeof(PGcancel));
    if (cancel == NULL)
        return NULL;

    memcpy(&cancel->raddr, &conn->raddr, sizeof(SockAddr));
    cancel->be_pid = conn->be_pid;
    cancel->be_key = conn->be_key;

    return cancel;
}

bool pqGetHomeDirectory ( char *  buf,
int  bufsize 
)

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

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

Referenced by getPgPassFilename(), and parseServiceInfo().

{
#ifndef WIN32
    char        pwdbuf[BUFSIZ];
    struct passwd pwdstr;
    struct passwd *pwd = NULL;

    if (pqGetpwuid(geteuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd) != 0)
        return false;
    strlcpy(buf, pwd->pw_dir, bufsize);
    return true;
#else
    char        tmppath[MAX_PATH];

    ZeroMemory(tmppath, sizeof(tmppath));
    if (SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, tmppath) != S_OK)
        return false;
    snprintf(buf, bufsize, "%s/postgresql", tmppath);
    return true;
#endif
}

char* PQhost ( const PGconn conn  ) 

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

References pg_conn::pghost, and pg_conn::pgunixsocket.

Referenced by _connectDB(), CloneArchive(), do_connect(), exec_command(), get_prompt(), and SyncVariables().

{
    if (!conn)
        return NULL;
    return conn->pghost ? conn->pghost : conn->pgunixsocket;
}

char* PQoptions ( const PGconn conn  ) 

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

References pg_conn::pgoptions.

{
    if (!conn)
        return NULL;
    return conn->pgoptions;
}

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

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

References pqFlush(), pqPutMsgEnd(), pqPutMsgStart(), and pqPutnchar().

Referenced by pg_password_sendauth(), and PQconnectPoll().

{
    /* Start the message. */
    if (pqPutMsgStart(pack_type, true, conn))
        return STATUS_ERROR;

    /* Send the message body. */
    if (pqPutnchar(buf, buf_len, conn))
        return STATUS_ERROR;

    /* Finish the message. */
    if (pqPutMsgEnd(conn))
        return STATUS_ERROR;

    /* Flush to ensure backend gets it. */
    if (pqFlush(conn))
        return STATUS_ERROR;

    return STATUS_OK;
}

const char* PQparameterStatus ( const PGconn conn,
const char *  paramName 
)

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

References pgParameterStatus::name, pgParameterStatus::next, NULL, pg_conn::pstatus, and pgParameterStatus::value.

Referenced by _check_database_version(), applyRemoteGucs(), BaseBackup(), CheckServerVersionForStreaming(), connectDatabase(), connection_warnings(), GetConnection(), is_superuser(), main(), session_username(), setup_connection(), and standard_strings().

{
    const pgParameterStatus *pstatus;

    if (!conn || !paramName)
        return NULL;
    for (pstatus = conn->pstatus; pstatus != NULL; pstatus = pstatus->next)
    {
        if (strcmp(pstatus->name, paramName) == 0)
            return pstatus->value;
    }
    return NULL;
}

char* PQpass ( const PGconn conn  ) 

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

References pg_conn::pgpass.

Referenced by do_connect().

{
    if (!conn)
        return NULL;
    return conn->pgpass;
}

PGPing PQping ( const char *  conninfo  ) 

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

References conn, internal_ping(), PQconnectStart(), and PQfinish().

Referenced by test_postmaster_connection().

{
    PGconn     *conn = PQconnectStart(conninfo);
    PGPing      ret;

    ret = internal_ping(conn);
    PQfinish(conn);

    return ret;
}

PGPing PQpingParams ( const char *const *  keywords,
const char *const *  values,
int  expand_dbname 
)

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

References conn, internal_ping(), PQconnectStartParams(), and PQfinish().

Referenced by main().

{
    PGconn     *conn = PQconnectStartParams(keywords, values, expand_dbname);
    PGPing      ret;

    ret = internal_ping(conn);
    PQfinish(conn);

    return ret;
}

char* PQport ( const PGconn conn  ) 

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

References pg_conn::pgport.

Referenced by _connectDB(), CloneArchive(), do_connect(), exec_command(), get_prompt(), and SyncVariables().

{
    if (!conn)
        return NULL;
    return conn->pgport;
}

int PQprotocolVersion ( const PGconn conn  ) 

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

References CONNECTION_BAD, PG_PROTOCOL_MAJOR, pg_conn::pversion, and pg_conn::status.

{
    if (!conn)
        return 0;
    if (conn->status == CONNECTION_BAD)
        return 0;
    return PG_PROTOCOL_MAJOR(conn->pversion);
}

pgthreadlock_t PQregisterThreadLock ( pgthreadlock_t  newhandler  ) 

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

References pg_g_threadlock.

{
    pgthreadlock_t prev = pg_g_threadlock;

    if (newhandler)
        pg_g_threadlock = newhandler;
    else
        pg_g_threadlock = default_threadlock;

    return prev;
}

int PQrequestCancel ( PGconn conn  ) 

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

References pg_conn::be_key, pg_conn::be_pid, PQExpBufferData::data, pg_conn::errorMessage, internal_cancel(), PQExpBufferData::len, PQExpBufferData::maxlen, pg_conn::raddr, pg_conn::sock, and strlcpy().

{
    int         r;

    /* Check we have an open connection */
    if (!conn)
        return FALSE;

    if (conn->sock < 0)
    {
        strlcpy(conn->errorMessage.data,
                "PQrequestCancel() -- connection is not open\n",
                conn->errorMessage.maxlen);
        conn->errorMessage.len = strlen(conn->errorMessage.data);

        return FALSE;
    }

    r = internal_cancel(&conn->raddr, conn->be_pid, conn->be_key,
                        conn->errorMessage.data, conn->errorMessage.maxlen);

    if (!r)
        conn->errorMessage.len = strlen(conn->errorMessage.data);

    return r;
}

void PQreset ( PGconn conn  ) 

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

References closePGconn(), PGEventConnReset::conn, connectDBComplete(), connectDBStart(), pg_conn::errorMessage, pg_conn::events, i, libpq_gettext, PGEvent::name, pg_conn::nEvents, PGEvent::passThrough, PGEVT_CONNRESET, printfPQExpBuffer(), PGEvent::proc, and pg_conn::status.

Referenced by CheckConnection(), and pqEndcopy2().

{
    if (conn)
    {
        closePGconn(conn);

        if (connectDBStart(conn) && connectDBComplete(conn))
        {
            /*
             * Notify event procs of successful reset.  We treat an event proc
             * failure as disabling the connection ... good idea?
             */
            int         i;

            for (i = 0; i < conn->nEvents; i++)
            {
                PGEventConnReset evt;

                evt.conn = conn;
                if (!conn->events[i].proc(PGEVT_CONNRESET, &evt,
                                          conn->events[i].passThrough))
                {
                    conn->status = CONNECTION_BAD;
                    printfPQExpBuffer(&conn->errorMessage,
                                      libpq_gettext("PGEventProc \"%s\" failed during PGEVT_CONNRESET event\n"),
                                      conn->events[i].name);
                    break;
                }
            }
        }
    }
}

PostgresPollingStatusType PQresetPoll ( PGconn conn  ) 

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

References PGEventConnReset::conn, pg_conn::errorMessage, pg_conn::events, i, libpq_gettext, PGEvent::name, pg_conn::nEvents, PGEvent::passThrough, PGEVT_CONNRESET, PGRES_POLLING_OK, PQconnectPoll(), printfPQExpBuffer(), PGEvent::proc, pg_conn::status, and status().

{
    if (conn)
    {
        PostgresPollingStatusType status = PQconnectPoll(conn);

        if (status == PGRES_POLLING_OK)
        {
            /*
             * Notify event procs of successful reset.  We treat an event proc
             * failure as disabling the connection ... good idea?
             */
            int         i;

            for (i = 0; i < conn->nEvents; i++)
            {
                PGEventConnReset evt;

                evt.conn = conn;
                if (!conn->events[i].proc(PGEVT_CONNRESET, &evt,
                                          conn->events[i].passThrough))
                {
                    conn->status = CONNECTION_BAD;
                    printfPQExpBuffer(&conn->errorMessage,
                                      libpq_gettext("PGEventProc \"%s\" failed during PGEVT_CONNRESET event\n"),
                                      conn->events[i].name);
                    return PGRES_POLLING_FAILED;
                }
            }
        }

        return status;
    }

    return PGRES_POLLING_FAILED;
}

int PQresetStart ( PGconn conn  ) 

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

References closePGconn(), and connectDBStart().

Referenced by pqEndcopy2().

{
    if (conn)
    {
        closePGconn(conn);

        return connectDBStart(conn);
    }

    return 0;
}

int PQserverVersion ( const PGconn conn  ) 
int PQsetClientEncoding ( PGconn conn,
const char *  encoding 
)

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

References CONNECTION_OK, NULL, pg_encoding_to_char(), pg_get_encoding_from_locale(), PG_PROTOCOL_MAJOR, PGRES_COMMAND_OK, PQclear(), PQexec(), pqSaveParameterStatus(), pg_conn::pversion, pg_result::resultStatus, and pg_conn::status.

Referenced by CloneArchive(), dblink_connect(), exec_command(), and setup_connection().

{
    char        qbuf[128];
    static const char query[] = "set client_encoding to '%s'";
    PGresult   *res;
    int         status;

    if (!conn || conn->status != CONNECTION_OK)
        return -1;

    if (!encoding)
        return -1;

    /* Resolve special "auto" value from the locale */
    if (strcmp(encoding, "auto") == 0)
        encoding = pg_encoding_to_char(pg_get_encoding_from_locale(NULL, true));

    /* check query buffer overflow */
    if (sizeof(qbuf) < (sizeof(query) + strlen(encoding)))
        return -1;

    /* ok, now send a query */
    sprintf(qbuf, query, encoding);
    res = PQexec(conn, qbuf);

    if (res == NULL)
        return -1;
    if (res->resultStatus != PGRES_COMMAND_OK)
        status = -1;
    else
    {
        /*
         * In protocol 2 we have to assume the setting will stick, and adjust
         * our state immediately.  In protocol 3 and up we can rely on the
         * backend to report the parameter value, and we'll change state at
         * that time.
         */
        if (PG_PROTOCOL_MAJOR(conn->pversion) < 3)
            pqSaveParameterStatus(conn, "client_encoding", encoding);
        status = 0;             /* everything is ok */
    }
    PQclear(res);
    return status;
}

PGconn* PQsetdbLogin ( const char *  pghost,
const char *  pgport,
const char *  pgoptions,
const char *  pgtty,
const char *  dbName,
const char *  login,
const char *  pwd 
)

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

References conn, connectDBComplete(), connectDBStart(), connectOptions1(), connectOptions2(), pg_conn::dbName, free, makeEmptyPGconn(), NULL, pg_conn::pghost, pg_conn::pgoptions, pg_conn::pgpass, pg_conn::pgport, pg_conn::pgtty, pg_conn::pguser, and recognized_connection_string().

{
    PGconn     *conn;

    /*
     * Allocate memory for the conn structure
     */
    conn = makeEmptyPGconn();
    if (conn == NULL)
        return NULL;

    /*
     * If the dbName parameter contains what looks like a connection string,
     * parse it into conn struct using connectOptions1.
     */
    if (dbName && recognized_connection_string(dbName))
    {
        if (!connectOptions1(conn, dbName))
            return conn;
    }
    else
    {
        /*
         * Old-style path: first, parse an empty conninfo string in order to
         * set up the same defaults that PQconnectdb() would use.
         */
        if (!connectOptions1(conn, ""))
            return conn;

        /* Insert dbName parameter value into struct */
        if (dbName && dbName[0] != '\0')
        {
            if (conn->dbName)
                free(conn->dbName);
            conn->dbName = strdup(dbName);
        }
    }

    /*
     * Insert remaining parameters into struct, overriding defaults (as well
     * as any conflicting data from dbName taken as a conninfo).
     */
    if (pghost && pghost[0] != '\0')
    {
        if (conn->pghost)
            free(conn->pghost);
        conn->pghost = strdup(pghost);
    }

    if (pgport && pgport[0] != '\0')
    {
        if (conn->pgport)
            free(conn->pgport);
        conn->pgport = strdup(pgport);
    }

    if (pgoptions && pgoptions[0] != '\0')
    {
        if (conn->pgoptions)
            free(conn->pgoptions);
        conn->pgoptions = strdup(pgoptions);
    }

    if (pgtty && pgtty[0] != '\0')
    {
        if (conn->pgtty)
            free(conn->pgtty);
        conn->pgtty = strdup(pgtty);
    }

    if (login && login[0] != '\0')
    {
        if (conn->pguser)
            free(conn->pguser);
        conn->pguser = strdup(login);
    }

    if (pwd && pwd[0] != '\0')
    {
        if (conn->pgpass)
            free(conn->pgpass);
        conn->pgpass = strdup(pwd);
    }

    /*
     * Compute derived options
     */
    if (!connectOptions2(conn))
        return conn;

    /*
     * Connect to the database
     */
    if (connectDBStart(conn))
        (void) connectDBComplete(conn);

    return conn;
}

PGVerbosity PQsetErrorVerbosity ( PGconn conn,
PGVerbosity  verbosity 
)

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

References pg_conn::verbosity.

Referenced by SyncVariables(), and verbosity_hook().

{
    PGVerbosity old;

    if (!conn)
        return PQERRORS_DEFAULT;
    old = conn->verbosity;
    conn->verbosity = verbosity;
    return old;
}

PQnoticeProcessor PQsetNoticeProcessor ( PGconn conn,
PQnoticeProcessor  proc,
void *  arg 
)

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

References pg_conn::noticeHooks, PGNoticeHooks::noticeProc, PGNoticeHooks::noticeProcArg, and NULL.

Referenced by _connectDB(), ConnectDatabase(), do_connect(), and main().

{
    PQnoticeProcessor old;

    if (conn == NULL)
        return NULL;

    old = conn->noticeHooks.noticeProc;
    if (proc)
    {
        conn->noticeHooks.noticeProc = proc;
        conn->noticeHooks.noticeProcArg = arg;
    }
    return old;
}

PQnoticeReceiver PQsetNoticeReceiver ( PGconn conn,
PQnoticeReceiver  proc,
void *  arg 
)

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

References pg_conn::noticeHooks, PGNoticeHooks::noticeRec, PGNoticeHooks::noticeRecArg, and NULL.

Referenced by ECPGconnect().

{
    PQnoticeReceiver old;

    if (conn == NULL)
        return NULL;

    old = conn->noticeHooks.noticeRec;
    if (proc)
    {
        conn->noticeHooks.noticeRec = proc;
        conn->noticeHooks.noticeRecArg = arg;
    }
    return old;
}

int PQsocket ( const PGconn conn  ) 

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

References pg_conn::sock.

Referenced by HandleCopyStream(), libpq_select(), main(), threadRun(), and try_complete_step().

{
    if (!conn)
        return -1;
    return conn->sock;
}

ConnStatusType PQstatus ( const PGconn conn  ) 
void PQtrace ( PGconn conn,
FILE *  debug_port 
)

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

References NULL, pg_conn::Pfdebug, and PQuntrace().

{
    if (conn == NULL)
        return;
    PQuntrace(conn);
    conn->Pfdebug = debug_port;
}

PGTransactionStatusType PQtransactionStatus ( const PGconn conn  ) 
char* PQtty ( const PGconn conn  ) 

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

References pg_conn::pgtty.

{
    if (!conn)
        return NULL;
    return conn->pgtty;
}

void PQuntrace ( PGconn conn  ) 

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

References NULL, and pg_conn::Pfdebug.

Referenced by PQtrace().

{
    if (conn == NULL)
        return;
    if (conn->Pfdebug)
    {
        fflush(conn->Pfdebug);
        conn->Pfdebug = NULL;
    }
}

char* PQuser ( const PGconn conn  ) 

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

References pg_conn::pguser.

Referenced by _connectDB(), CloneArchive(), do_connect(), exec_command(), get_prompt(), ReconnectToServer(), session_username(), and SyncVariables().

{
    if (!conn)
        return NULL;
    return conn->pguser;
}

static char * pwdfMatchesString ( char *  buf,
char *  token 
) [static]

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

References NULL.

Referenced by PasswordFromFile().

{
    char       *tbuf,
               *ttok;
    bool        bslash = false;

    if (buf == NULL || token == NULL)
        return NULL;
    tbuf = buf;
    ttok = token;
    if (tbuf[0] == '*' && tbuf[1] == ':')
        return tbuf + 2;
    while (*tbuf != 0)
    {
        if (*tbuf == '\\' && !bslash)
        {
            tbuf++;
            bslash = true;
        }
        if (*tbuf == ':' && *ttok == 0 && !bslash)
            return tbuf + 1;
        bslash = false;
        if (*ttok == 0)
            return NULL;
        if (*tbuf == *ttok)
        {
            tbuf++;
            ttok++;
        }
        else
            return NULL;
    }
    return NULL;
}

static bool recognized_connection_string ( const char *  connstr  )  [static]

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

References uri_prefix_length().

Referenced by conninfo_array_parse(), and PQsetdbLogin().

{
    return uri_prefix_length(connstr) != 0 || strchr(connstr, '=') != NULL;
}

static int setKeepalivesCount ( PGconn conn  )  [static]

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

References appendPQExpBuffer(), pg_conn::errorMessage, pg_conn::keepalives_count, libpq_gettext, NULL, pg_conn::sock, SOCK_ERRNO, and SOCK_STRERROR.

Referenced by PQconnectPoll().

{
    int         count;

    if (conn->keepalives_count == NULL)
        return 1;

    count = atoi(conn->keepalives_count);
    if (count < 0)
        count = 0;

#ifdef TCP_KEEPCNT
    if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPCNT,
                   (char *) &count, sizeof(count)) < 0)
    {
        char        sebuf[256];

        appendPQExpBuffer(&conn->errorMessage,
                       libpq_gettext("setsockopt(TCP_KEEPCNT) failed: %s\n"),
                          SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
        return 0;
    }
#endif

    return 1;
}

static int setKeepalivesIdle ( PGconn conn  )  [static]

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

References appendPQExpBuffer(), pg_conn::errorMessage, pg_conn::keepalives_idle, libpq_gettext, NULL, pg_conn::sock, SOCK_ERRNO, and SOCK_STRERROR.

Referenced by PQconnectPoll().

{
    int         idle;

    if (conn->keepalives_idle == NULL)
        return 1;

    idle = atoi(conn->keepalives_idle);
    if (idle < 0)
        idle = 0;

#ifdef TCP_KEEPIDLE
    if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPIDLE,
                   (char *) &idle, sizeof(idle)) < 0)
    {
        char        sebuf[256];

        appendPQExpBuffer(&conn->errorMessage,
                      libpq_gettext("setsockopt(TCP_KEEPIDLE) failed: %s\n"),
                          SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
        return 0;
    }
#else
#ifdef TCP_KEEPALIVE
    /* Darwin uses TCP_KEEPALIVE rather than TCP_KEEPIDLE */
    if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPALIVE,
                   (char *) &idle, sizeof(idle)) < 0)
    {
        char        sebuf[256];

        appendPQExpBuffer(&conn->errorMessage,
                     libpq_gettext("setsockopt(TCP_KEEPALIVE) failed: %s\n"),
                          SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
        return 0;
    }
#endif
#endif

    return 1;
}

static int setKeepalivesInterval ( PGconn conn  )  [static]

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

References appendPQExpBuffer(), pg_conn::errorMessage, pg_conn::keepalives_interval, libpq_gettext, NULL, pg_conn::sock, SOCK_ERRNO, and SOCK_STRERROR.

Referenced by PQconnectPoll().

{
    int         interval;

    if (conn->keepalives_interval == NULL)
        return 1;

    interval = atoi(conn->keepalives_interval);
    if (interval < 0)
        interval = 0;

#ifdef TCP_KEEPINTVL
    if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPINTVL,
                   (char *) &interval, sizeof(interval)) < 0)
    {
        char        sebuf[256];

        appendPQExpBuffer(&conn->errorMessage,
                     libpq_gettext("setsockopt(TCP_KEEPINTVL) failed: %s\n"),
                          SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
        return 0;
    }
#endif

    return 1;
}

static int uri_prefix_length ( const char *  connstr  )  [static]

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

References short_uri_designator, and uri_designator.

Referenced by conninfo_uri_parse_options(), parse_connection_string(), and recognized_connection_string().

{
    if (strncmp(connstr, uri_designator,
                sizeof(uri_designator) - 1) == 0)
        return sizeof(uri_designator) - 1;

    if (strncmp(connstr, short_uri_designator,
                sizeof(short_uri_designator) - 1) == 0)
        return sizeof(short_uri_designator) - 1;

    return 0;
}

static int useKeepalives ( PGconn conn  )  [static]

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

References pg_conn::keepalives, NULL, and val.

Referenced by PQconnectPoll().

{
    char       *ep;
    int         val;

    if (conn->keepalives == NULL)
        return 1;
    val = strtol(conn->keepalives, &ep, 10);
    if (*ep)
        return -1;
    return val != 0 ? 1 : 0;
}


Variable Documentation

Initial value:
{
    
    {
        "PGDATESTYLE", "datestyle"
    },
    {
        "PGTZ", "timezone"
    },
    
    {
        "PGGEQO", "geqo"
    },
    {
        NULL, NULL
    }
}

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

pgthreadlock_t pg_g_threadlock = default_threadlock

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

Referenced by PQregisterThreadLock().

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

const char short_uri_designator[] = "postgres://" [static]

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

Referenced by uri_prefix_length().

const char uri_designator[] = "postgresql://" [static]

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

Referenced by uri_prefix_length().