⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fe-connect.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
/*------------------------------------------------------------------------- * * fe-connect.c *	  functions related to setting up a connection to the backend * * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.323.2.2 2006/05/21 20:19:44 tgl Exp $ * *------------------------------------------------------------------------- */#include "postgres_fe.h"#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <ctype.h>#include <time.h>#ifndef WIN32_CLIENT_ONLY#include <unistd.h>#endif#ifndef HAVE_STRDUP#include "strdup.h"#endif#include "libpq-fe.h"#include "libpq-int.h"#include "fe-auth.h"#include "pg_config_paths.h"#ifdef WIN32#include "win32.h"#ifdef _WIN32_IE#undef _WIN32_IE#endif#define _WIN32_IE 0x0500#ifdef near#undef near#endif#define near#include <shlobj.h>#else#include <sys/socket.h>#include <netdb.h>#include <netinet/in.h>#ifdef HAVE_NETINET_TCP_H#include <netinet/tcp.h>#endif#include <arpa/inet.h>#endif#ifdef ENABLE_THREAD_SAFETY#ifdef WIN32#include "pthread-win32.h"#else#include <pthread.h>#endif#endif#include "libpq/ip.h"#include "mb/pg_wchar.h"#ifndef FD_CLOEXEC#define FD_CLOEXEC 1#endif#ifndef WIN32#define PGPASSFILE ".pgpass"#else#define PGPASSFILE "pgpass.conf"#endif/* fall back options if they are not specified by arguments or defined   by environment variables */#define DefaultHost		"localhost"#define DefaultTty		""#define DefaultOption	""#define DefaultAuthtype		  ""#define DefaultPassword		  ""#ifdef USE_SSL#define DefaultSSLMode	"prefer"#else#define DefaultSSLMode	"disable"#endif/* ---------- * Definition of the conninfo parameters and their fallback resources. * * If Environment-Var and Compiled-in are specified as NULL, no * fallback is available. If after all no value can be determined * for an option, an error is returned. * * The value for the username is treated specially in conninfo_parse. * If the Compiled-in resource is specified as a NULL value, the * user is determined by pg_fe_getauthname(). * * The Label and Disp-Char entries are provided for applications that * want to use PQconndefaults() to create a generic database connection * dialog. Disp-Char is defined as follows: *		""		Normal input field *		"*"		Password field - hide value *		"D"		Debug option - don't show by default * * PQconninfoOptions[] is a constant static array that we use to initialize * a dynamically allocated working copy.  All the "val" fields in * PQconninfoOptions[] *must* be NULL.	In a working copy, non-null "val" * fields point to malloc'd strings that should be freed when the working * array is freed (see PQconninfoFree). * ---------- */static const PQconninfoOption PQconninfoOptions[] = {	/*	 * "authtype" is no longer used, so mark it "don't show".  We keep it in	 * the array so as not to reject conninfo strings from old apps that might	 * still try to set it.	 */	{"authtype", "PGAUTHTYPE", DefaultAuthtype, NULL,	"Database-Authtype", "D", 20},	{"service", "PGSERVICE", NULL, NULL,	"Database-Service", "", 20},	{"user", "PGUSER", NULL, NULL,	"Database-User", "", 20},	{"password", "PGPASSWORD", NULL, NULL,	"Database-Password", "*", 20},	{"connect_timeout", "PGCONNECT_TIMEOUT", NULL, NULL,	"Connect-timeout", "", 10}, /* strlen(INT32_MAX) == 10 */	{"dbname", "PGDATABASE", NULL, NULL,	"Database-Name", "", 20},	{"host", "PGHOST", NULL, NULL,	"Database-Host", "", 40},	{"hostaddr", "PGHOSTADDR", NULL, NULL,	"Database-Host-IP-Address", "", 45},	{"port", "PGPORT", DEF_PGPORT_STR, NULL,	"Database-Port", "", 6},	/*	 * "tty" is no longer used either, but keep it present for backwards	 * compatibility.	 */	{"tty", "PGTTY", DefaultTty, NULL,	"Backend-Debug-TTY", "D", 40},	{"options", "PGOPTIONS", DefaultOption, NULL,	"Backend-Debug-Options", "D", 40},#ifdef USE_SSL	/*	 * "requiressl" is deprecated, its purpose having been taken over by	 * "sslmode". It remains for backwards compatibility.	 */	{"requiressl", "PGREQUIRESSL", "0", NULL,	"Require-SSL", "D", 1},#endif	/*	 * "sslmode" option is allowed even without client SSL support because the	 * client can still handle SSL modes "disable" and "allow".	 */	{"sslmode", "PGSSLMODE", DefaultSSLMode, NULL,	"SSL-Mode", "", 8},			/* sizeof("disable") == 8 */#ifdef KRB5	/* Kerberos authentication supports specifying the service name */	{"krbsrvname", "PGKRBSRVNAME", PG_KRB_SRVNAM, NULL,	"Kerberos-service-name", "", 20},#endif	/* Terminating entry --- MUST BE LAST */	{NULL, NULL, NULL, NULL,	NULL, NULL, 0}};static const PQEnvironmentOption EnvironmentOptions[] ={	/* common user-interface settings */	{		"PGDATESTYLE", "datestyle"	},	{		"PGTZ", "timezone"	},	{		"PGCLIENTENCODING", "client_encoding"	},	/* internal performance-related settings */	{		"PGGEQO", "geqo"	},	{		NULL, NULL	}};static bool connectOptions1(PGconn *conn, const char *conninfo);static bool connectOptions2(PGconn *conn);static int	connectDBStart(PGconn *conn);static int	connectDBComplete(PGconn *conn);static PGconn *makeEmptyPGconn(void);static void freePGconn(PGconn *conn);static void closePGconn(PGconn *conn);static PQconninfoOption *conninfo_parse(const char *conninfo,			   PQExpBuffer errorMessage);static char *conninfo_getval(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 char *pwdfMatchesString(char *buf, char *token);static char *PasswordFromFile(char *hostname, char *port, char *dbname,				 char *username);static void default_threadlock(int acquire);/* global variable because fe-auth.c needs to access it */pgthreadlock_t pg_g_threadlock = default_threadlock;/* *		Connecting to a Database * * There are now four different ways a user of this API can connect to the * database.  Two are not recommended for use in new code, because of their * lack of extensibility with respect to the passing of options to the * backend.  These are PQsetdb and PQsetdbLogin (the former now being a macro * to the latter). * * If it is desired to connect in a synchronous (blocking) manner, use the * function PQconnectdb. * * To connect in an asynchronous (non-blocking) manner, use the functions * PQconnectStart, and PQconnectPoll. * * Internally, the static functions connectDBStart, connectDBComplete * are part of the connection procedure. *//* *		PQconnectdb * * establishes a connection to a postgres backend through the postmaster * using connection information in a string. * * The conninfo string is a white-separated list of * *	   option = value * * definitions. Value might be a single value containing no whitespaces or * a single quoted string. If a single quote should appear anywhere in * the value, it must be escaped with a backslash like \' * * Returns a PGconn* which is needed for all subsequent libpq calls, or NULL * if a memory allocation failed. * If the status field of the connection returned is CONNECTION_BAD, * then some fields may be null'ed out instead of having valid values. * * You should call PQfinish (if conn is not NULL) regardless of whether this * call succeeded. */PGconn *PQconnectdb(const char *conninfo){	PGconn	   *conn = PQconnectStart(conninfo);	if (conn && conn->status != CONNECTION_BAD)		(void) connectDBComplete(conn);	return conn;}/* *		PQconnectStart * * Begins the establishment of a connection to a postgres backend through the * postmaster using connection information in a string. * * See comment for PQconnectdb for the definition of the string format. * * Returns a PGconn*.  If NULL is returned, a malloc error has occurred, and * you should not attempt to proceed with this connection.	If the status * field of the connection returned is CONNECTION_BAD, an error has * occurred. In this case you should call PQfinish on the result, (perhaps * inspecting the error message first).  Other fields of the structure may not * be valid if that occurs.  If the status field is not CONNECTION_BAD, then * this stage has succeeded - call PQconnectPoll, using select(2) to see when * this is necessary. * * See PQconnectPoll for more info. */PGconn *PQconnectStart(const char *conninfo){	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;}/* *		connectOptions1 * * Internal subroutine to set up connection parameters given an already- * created PGconn and a conninfo string.  Derived settings should be * processed by calling connectOptions2 next.  (We split them because * PQsetdbLogin overrides defaults in between.) * * Returns true if OK, false if trouble (in which case errorMessage is set * and so is conn->status). */static boolconnectOptions1(PGconn *conn, const char *conninfo){	PQconninfoOption *connOptions;	char	   *tmp;	/*	 * Parse the conninfo string	 */	connOptions = conninfo_parse(conninfo, &conn->errorMessage);	if (connOptions == NULL)	{		conn->status = CONNECTION_BAD;		/* errorMessage is already set */		return false;	}	/*	 * 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...	 */	tmp = conninfo_getval(connOptions, "hostaddr");	conn->pghostaddr = tmp ? strdup(tmp) : NULL;	tmp = conninfo_getval(connOptions, "host");	conn->pghost = tmp ? strdup(tmp) : NULL;	tmp = conninfo_getval(connOptions, "port");	conn->pgport = tmp ? strdup(tmp) : NULL;	tmp = conninfo_getval(connOptions, "tty");	conn->pgtty = tmp ? strdup(tmp) : NULL;	tmp = conninfo_getval(connOptions, "options");	conn->pgoptions = tmp ? strdup(tmp) : NULL;	tmp = conninfo_getval(connOptions, "dbname");	conn->dbName = tmp ? strdup(tmp) : NULL;	tmp = conninfo_getval(connOptions, "user");	conn->pguser = tmp ? strdup(tmp) : NULL;	tmp = conninfo_getval(connOptions, "password");	conn->pgpass = tmp ? strdup(tmp) : NULL;	tmp = conninfo_getval(connOptions, "connect_timeout");	conn->connect_timeout = tmp ? strdup(tmp) : NULL;	tmp = conninfo_getval(connOptions, "sslmode");	conn->sslmode = tmp ? strdup(tmp) : NULL;#ifdef USE_SSL	tmp = conninfo_getval(connOptions, "requiressl");	if (tmp && tmp[0] == '1')	{		/* here warn that the requiressl option is deprecated? */		if (conn->sslmode)			free(conn->sslmode);		conn->sslmode = strdup("require");	}#endif#ifdef KRB5	tmp = conninfo_getval(connOptions, "krbsrvname");	conn->krbsrvname = tmp ? strdup(tmp) : NULL;#endif	/*	 * Free the option info - all is in conn now	 */	PQconninfoFree(connOptions);	return true;}/* *		connectOptions2 * * Compute derived connection options after absorbing all user-supplied info. * * Returns true if OK, false if trouble (in which case errorMessage is set * and so is conn->status). */static boolconnectOptions2(PGconn *conn){	/*	 * 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);	}	/*	 * 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)		{			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" */				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);	return true;}/* *		PQconndefaults * * Parse an empty string like PQconnectdb() would do and return the * working connection options array. * * Using this function, an application may determine all possible options * and their current default values. * * NOTE: as of PostgreSQL 7.0, the returned array is dynamically allocated

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -