📄 config.c
字号:
/* FreeTDS - Library of routines accessing Sybase and Microsoft databases * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Brian Bruns * Copyright (C) 2006, 2007 Frediano Ziglio * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */#if HAVE_CONFIG_H#include <config.h>#endif#include <stdarg.h>#include <stdio.h>#if HAVE_ERRNO_H#include <errno.h>#endif /* HAVE_ERRNO_H */#include <assert.h>#include <ctype.h>#if HAVE_STDLIB_H#include <stdlib.h>#endif /* HAVE_STDLIB_H */#if HAVE_STRING_H#include <string.h>#endif /* HAVE_STRING_H */#if HAVE_UNISTD_H#include <unistd.h>#endif /* HAVE_UNISTD_H */#if HAVE_NETDB_H#include <netdb.h>#endif /* HAVE_NETDB_H */#if HAVE_SYS_SOCKET_H#include <sys/socket.h>#endif /* HAVE_SYS_SOCKET_H */#if HAVE_SYS_TYPES_H#include <sys/types.h>#endif /* HAVE_SYS_TYPES_H */#if HAVE_NETINET_IN_H#include <netinet/in.h>#endif /* HAVE_NETINET_IN_H */#if HAVE_ARPA_INET_H#include <arpa/inet.h>#endif /* HAVE_ARPA_INET_H */#ifdef WIN32#include <process.h>#endif#include "tds.h"#include "tds_configs.h"#include "tdsstring.h"#include "replacements.h"#ifdef DMALLOC#include <dmalloc.h>#endifTDS_RCSID(var, "$Id: config.c,v 1.132 2007/12/23 21:12:02 jklowden Exp $");static void tds_config_login(TDSCONNECTION * connection, TDSLOGIN * login);static void tds_config_env_tdsdump(TDSCONNECTION * connection);static void tds_config_env_tdsver(TDSCONNECTION * connection);static void tds_config_env_tdsport(TDSCONNECTION * connection);static void tds_config_env_tdshost(TDSCONNECTION * connection);static int tds_read_conf_sections(FILE * in, const char *server, TDSCONNECTION * connection);static void tds_parse_conf_section(const char *option, const char *value, void *param);static void tds_read_interfaces(const char *server, TDSCONNECTION * connection);static int tds_config_boolean(const char *value);static int parse_server_name_for_port(TDSCONNECTION * connection, TDSLOGIN * login);static int tds_lookup_port(const char *portname);static void tds_config_encryption(const char * value, TDSCONNECTION * connection);extern int tds_g_append_mode;static char *interf_file = NULL;#define TDS_ISSPACE(c) isspace((unsigned char ) (c))#if !defined(WIN32) && !defined(DOS32X) const char STD_DATETIME_FMT[] = "%b %e %Y %I:%M%p";static const char pid_config_logpath[] = "/tmp/tdsconfig.log.%d";static const char freetds_conf[] = "%s/etc/freetds.conf";static const char location[] = "(from $FREETDS/etc)";static const char pid_logpath[] = "/tmp/freetds.log.%d";static const char interfaces_path[] = "/etc/freetds";#else const char STD_DATETIME_FMT[] = "%b %d %Y %I:%M%p"; /* msvcr80.dll does not support %e */static const char pid_config_logpath[] = "c:\\tdsconfig.log.%d";static const char freetds_conf [] = "%s\\freetds.conf";static const char location[] = "(from $FREETDS)";static const char pid_logpath[] = "c:\\freetds.log.%d";static const char interfaces_path[] = "c:\\";#endif/** * \ingroup libtds * \defgroup config Configuration * Handle reading of configuration *//** * \addtogroup config * @{ *//** * tds_read_config_info() will fill the tds connection structure based on configuration * information gathered in the following order: * 1) Program specified in TDSLOGIN structure * 2) The environment variables TDSVER, TDSDUMP, TDSPORT, TDSQUERY, TDSHOST * 3) A config file with the following search order: * a) a readable file specified by environment variable FREETDSCONF * b) a readable file in ~/.freetds.conf * c) a readable file in $prefix/etc/freetds.conf * 3) ~/.interfaces if exists * 4) $SYBASE/interfaces if exists * 5) TDS_DEF_* default values * * .tdsrc and freetds.conf have been added to make the package easier to * integration with various Linux and *BSD distributions. */TDSCONNECTION *tds_read_config_info(TDSSOCKET * tds, TDSLOGIN * login, TDSLOCALE * locale){ TDSCONNECTION *connection; char *s; char *path; pid_t pid; int opened = 0; /* allocate a new structure with hard coded and build-time defaults */ connection = tds_alloc_connection(locale); if (!connection) return NULL; s = getenv("TDSDUMPCONFIG"); if (s) { if (*s) { opened = tdsdump_open(s); } else { pid = getpid(); if (asprintf(&path, pid_config_logpath, pid) >= 0) { if (*path) { opened = tdsdump_open(path); } free(path); } } } tdsdump_log(TDS_DBG_INFO1, "Getting connection information for [%s].\n", tds_dstr_cstr(&login->server_name)); /* (The server name is set in login.c.) */ if (parse_server_name_for_port(connection, login)) { tdsdump_log(TDS_DBG_INFO1, "Parsed servername, now %s on %d.\n", tds_dstr_cstr(&connection->server_name), login->port); } /* Read the config files. */ tdsdump_log(TDS_DBG_INFO1, "Attempting to read conf files.\n"); if (!tds_read_conf_file(connection, tds_dstr_cstr(&login->server_name))) { /* fallback to interfaces file */ tdsdump_log(TDS_DBG_INFO1, "Failed in reading conf file. Trying interface files.\n"); tds_read_interfaces(tds_dstr_cstr(&login->server_name), connection); } /* Override config file settings with environment variables. */ tds_fix_connection(connection); /* And finally apply anything from the login structure */ tds_config_login(connection, login); if (opened) { tdsdump_log(TDS_DBG_INFO1, "Final connection parameters:\n"); tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "server_name", tds_dstr_cstr(&connection->server_name)); tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "port", connection->port); tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "major_version", (int)connection->major_version); tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "minor_version", (int)connection->minor_version); tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "block_size", connection->block_size); tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "language", tds_dstr_cstr(&connection->language)); tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "server_charset", tds_dstr_cstr(&connection->server_charset)); tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "connect_timeout", connection->connect_timeout); tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "client_host_name", tds_dstr_cstr(&connection->client_host_name)); tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "app_name", tds_dstr_cstr(&connection->app_name)); tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "user_name", tds_dstr_cstr(&connection->user_name)); /* tdsdump_log(TDS_DBG_PASSWD, "\t%20s = %s\n", "password", tds_dstr_cstr(&connection->password)); (no such flag yet) */ tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "library", tds_dstr_cstr(&connection->library)); tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "bulk_copy", (int)connection->bulk_copy); tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "suppress_language", (int)connection->suppress_language); tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "encrypt level", (int)connection->encryption_level); tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "query_timeout", connection->query_timeout); /* tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "capabilities", tds_dstr_cstr(&connection->capabilities)); (not null terminated) */ tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "client_charset", tds_dstr_cstr(&connection->client_charset)); tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "ip_addr", tds_dstr_cstr(&connection->ip_addr)); tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "instance_name", tds_dstr_cstr(&connection->instance_name)); tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "database", tds_dstr_cstr(&connection->database)); tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "dump_file", tds_dstr_cstr(&connection->dump_file)); tdsdump_log(TDS_DBG_INFO1, "\t%20s = %x\n", "debug_flags", connection->debug_flags); tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "text_size", connection->text_size); tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "broken_dates", connection->broken_dates); tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "broken_money", connection->broken_money); tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "emul_little_endian", connection->emul_little_endian); tdsdump_close(); } return connection;}/** * Fix configuration after reading it. * Currently this read some environment variables and replace some options. */voidtds_fix_connection(TDSCONNECTION * connection){ /* Now check the environment variables */ tds_config_env_tdsver(connection); tds_config_env_tdsdump(connection); tds_config_env_tdsport(connection); tds_config_env_tdshost(connection);}static inttds_try_conf_file(const char *path, const char *how, const char *server, TDSCONNECTION * connection){ int found = 0; FILE *in; if ((in = fopen(path, "r")) != NULL) { tdsdump_log(TDS_DBG_INFO1, "Found conf file '%s' %s.\n", path, how); found = tds_read_conf_sections(in, server, connection); if (found) { tdsdump_log(TDS_DBG_INFO1, "Success: [%s] defined in %s.\n", server, path); } else { tdsdump_log(TDS_DBG_INFO2, "[%s] not found.\n", server); } fclose(in); } return found;}/** * Return filename from HOME directory * @return allocated string or NULL if error */static char *tds_get_home_file(const char *file){ char *home, *path; home = tds_get_homedir(); if (!home) return NULL; if (asprintf(&path, "%s" TDS_SDIR_SEPARATOR "%s", home, file) < 0) path = NULL; free(home); return path;}/** * Read configuration info for given server * return 0 on error * @param connection where to store configuration * @param server section of file configuration that hold * configuration for a server */inttds_read_conf_file(TDSCONNECTION * connection, const char *server){ char *path = NULL; char *eptr = NULL; int found = 0; if (interf_file) { found = tds_try_conf_file(interf_file, "set programmatically", server, connection); } /* FREETDSCONF env var, pkleef@openlinksw.com 01/21/02 */ if (!found) { path = getenv("FREETDSCONF"); if (path) { found = tds_try_conf_file(path, "(from $FREETDSCONF)", server, connection); } else { tdsdump_log(TDS_DBG_INFO2, "... $FREETDSCONF not set. Trying $FREETDS/etc.\n"); } } /* FREETDS env var, Bill Thompson 16/07/03 */ if (!found) { eptr = getenv("FREETDS"); if (eptr) { if (asprintf(&path, freetds_conf, eptr) >= 0) { found = tds_try_conf_file(path, location, server, connection); free(path); } } else { tdsdump_log(TDS_DBG_INFO2, "... $FREETDS not set. Trying $HOME.\n"); } } if (!found) { path = tds_get_home_file(".freetds.conf"); if (path) { found = tds_try_conf_file(path, "(.freetds.conf)", server, connection); free(path); } else { tdsdump_log(TDS_DBG_INFO2, "... Error getting ~/.freetds.conf. Trying %s.\n", FREETDS_SYSCONFFILE); } } if (!found) { found = tds_try_conf_file(FREETDS_SYSCONFFILE, "(default)", server, connection); } return found;}static inttds_read_conf_sections(FILE * in, const char *server, TDSCONNECTION * connection){ tds_read_conf_section(in, "global", tds_parse_conf_section, connection); rewind(in); return tds_read_conf_section(in, server, tds_parse_conf_section, connection);}static inttds_config_boolean(const char *value){ if (!strcmp(value, "yes") || !strcmp(value, "on") || !strcmp(value, "true") || !strcmp(value, "1")) return 1; if (!strcmp(value, "no") || !strcmp(value, "off") || !strcmp(value, "false") || !strcmp(value, "0")) return 0; tdsdump_log(TDS_DBG_INFO1, "UNRECOGNIZED boolean value: '%s'. Treating as 'no'.\n", value); return 0;}static voidtds_config_encryption(const char * value, TDSCONNECTION * connection){ TDS_ENCRYPTION_LEVEL lvl = TDS_ENCRYPTION_OFF; if (!strcasecmp(value, TDS_STR_ENCRYPTION_OFF)) ; else if (!strcasecmp(value, TDS_STR_ENCRYPTION_REQUEST)) lvl = TDS_ENCRYPTION_REQUEST; else if (!strcasecmp(value, TDS_STR_ENCRYPTION_REQUIRE)) lvl = TDS_ENCRYPTION_REQUIRE; else tdsdump_log(TDS_DBG_INFO1, "UNRECOGNIZED option value '%s'...ignoring.\n", value); connection->encryption_level = lvl;}/**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -