[PATCH] consolidated locale/client charset update
"Craig A. Berry" <[email protected]>
| Newsgroups | gmane.comp.db.tds.freetds |
|---|---|
| Message-ID | <[email protected]> |
The attached patch completes the client charset handling changes we've had in progress for a couple weeks now. It includes changes previously submitted but not yet applied as well some new changes. It makes sense to look at it all together as one integral set of changes. Here's what it does: 1.) Completely removes client charset handling from locales.conf processing, including removing the client_charset field from the TDSLOCALE structure. This is obviously a binary incompatibility and should trigger relevant policies about when it can ship and so forth. 2.) Sets the client charset based on the current locale in tds_alloc_connection(), essentially moving logic to there from tds_alloc_locale(). 3.) In tds_iconv_info_init(), reports problems getting a canonical charset without using the nonexistent canonical name that it failed to look up. 4.) Modifies tsql so that it does not hard-wire the client charset to whatever the current locale says it is. It now lets the library default it to that, but it can be overridden by either freetds.conf or by the newly implemented -J command line option. Of course the freetds.conf setting works for any application, not just tsql. Affected files: % lsdiff -s charset_update.patch ! include/tds.h ! src/apps/tsql.c ! src/tds/iconv.c ! src/tds/locale.c ! src/tds/mem.c ________________________________________ Craig A. Berry mailto:[email protected] "... getting out of a sonnet is much more difficult than getting in." Brad Leithauser _______________________________________________ FreeTDS mailing list [email protected] http://lists.ibiblio.org/mailman/listinfo/freetds
charset_update.patch
(application/octet-stream, 8 KB)
--- include/tds.h;-0 Sat Apr 10 09:29:36 2010
+++ include/tds.h Thu May 27 09:43:38 2010
@@ -908,7 +908,6 @@ typedef struct tds_locale
{
char *language;
char *server_charset;
- char *client_charset;
char *date_fmt;
} TDSLOCALE;
--- src/apps/tsql.c;-0 Thu Apr 8 03:19:16 2010
+++ src/apps/tsql.c Thu May 27 15:40:38 2010
@@ -297,7 +297,8 @@ static void
tsql_print_usage(const char *progname)
{
fprintf(stderr,
- "Usage:\t%s [-S <server> | -H <hostname> -p <port>] -U <username> [-P <password>] [-I <config file>] [-o <options>] [-t delim] [-r delim] [-D database]\n"
+ "Usage:\t%s [-S <server> | -H <hostname> -p <port>] -U <username> [-P <password>]\n"
+ "\t\t[-I <config file>] [-J <client charset>] [-o <options>] [-t delim] [-r delim] [-D database]\n"
"\t%s -C\n"
"Options:\n"
"\tf\tDo not print footer\n"
@@ -402,23 +403,10 @@ populate_login(TDSLOGIN * login, int arg
char *confile = NULL;
int port = 0;
int opt;
- const char *locale = NULL;
const char *charset = NULL;
char *opt_flags_str = NULL;
- setlocale(LC_ALL, "");
- locale = setlocale(LC_ALL, NULL);
-
-#if HAVE_LOCALE_CHARSET
- charset = locale_charset();
-#endif
-#if HAVE_NL_LANGINFO && defined(CODESET)
- if (!charset)
- charset = nl_langinfo(CODESET);
-#endif
-
-
- while ((opt = getopt(argc, argv, "H:S:I:P:U:p:Co:t:r:D:Lv")) != -1) {
+ while ((opt = getopt(argc, argv, "H:S:I:J:P:U:p:Co:t:r:D:Lv")) != -1) {
switch (opt) {
case 't':
opt_col_term = strdup(optarg);
@@ -452,6 +440,9 @@ populate_login(TDSLOGIN * login, int arg
free(confile);
confile = strdup(optarg);
break;
+ case 'J':
+ charset = strdup(optarg);
+ break;
case 'p':
port = atoi(optarg);
break;
@@ -495,16 +486,6 @@ populate_login(TDSLOGIN * login, int arg
}
}
-
- if (locale)
- if (!QUIET) printf("locale is \"%s\"\n", locale);
- if (charset) {
- if (!QUIET) printf("locale charset is \"%s\"\n", charset);
- } else {
- charset = "ISO-8859-1";
- if (!QUIET) printf("using default charset \"%s\"\n", charset);
- }
-
if ((global_opt_flags & OPT_INSTANCES) && hostname) {
static const char template[] = "%s.instances";
char ip[24] = {'\0'};
@@ -582,7 +563,7 @@ populate_login(TDSLOGIN * login, int arg
tds_set_app(login, "TSQL");
tds_set_library(login, "TDS-Library");
tds_set_server(login, servername);
- tds_set_client_charset(login, charset);
+ if (charset) tds_set_client_charset(login, charset);
tds_set_language(login, "us_english");
tds_set_passwd(login, password);
if (confile) {
@@ -595,7 +576,7 @@ populate_login(TDSLOGIN * login, int arg
tds_set_library(login, "TDS-Library");
tds_set_server(login, hostname);
tds_set_port(login, port);
- tds_set_client_charset(login, charset);
+ if (charset) tds_set_client_charset(login, charset);
tds_set_language(login, "us_english");
tds_set_passwd(login, password);
}
@@ -681,6 +662,8 @@ main(int argc, char **argv)
pid_t timer_pid = 0;
int pipes[2];
#endif
+ const char *locale = NULL;
+ const char *charset = NULL;
istty = isatty(0);
@@ -710,6 +693,32 @@ main(int argc, char **argv)
tds_set_parent(tds, NULL);
connection = tds_read_config_info(tds, login, context->locale);
+ setlocale(LC_ALL, "");
+ locale = setlocale(LC_ALL, NULL);
+
+#if HAVE_LOCALE_CHARSET
+ charset = locale_charset();
+#endif
+#if HAVE_NL_LANGINFO && defined(CODESET)
+ if (!charset)
+ charset = nl_langinfo(CODESET);
+#endif
+
+ if (locale)
+ if (!QUIET) printf("locale is \"%s\"\n", locale);
+ if (charset) {
+ if (!QUIET) printf("locale charset is \"%s\"\n", charset);
+ }
+
+ if (tds_dstr_isempty(&connection->client_charset)) {
+ if (!charset)
+ charset = "ISO-8859-1";
+
+ tds_set_client_charset(login, charset);
+ tds_dstr_dup(&connection->client_charset, &login->client_charset);
+ }
+ if (!QUIET) printf("using default charset \"%s\"\n", tds_dstr_cstr(&connection->client_charset));
+
if (opt_default_db) {
tds_dstr_copy(&connection->database, opt_default_db);
if (!QUIET) fprintf(stderr, "Default database being set to %s\n", opt_default_db);
--- src/tds/iconv.c;-0 Mon Feb 8 06:16:43 2010
+++ src/tds/iconv.c Thu May 27 17:10:48 2010
@@ -440,12 +440,12 @@ tds_iconv_info_init(TDSICONV * char_conv
server_canonical = tds_canonical_charset(server_name);
if (client_canonical < 0) {
- tdsdump_log(TDS_DBG_FUNC, "tds_iconv_info_init: client charset name \"%s\" unrecognized\n", client->name);
+ tdsdump_log(TDS_DBG_FUNC, "tds_iconv_info_init: client charset name \"%s\" unrecognized\n", client_name);
return 0;
}
if (server_canonical < 0) {
- tdsdump_log(TDS_DBG_FUNC, "tds_iconv_info_init: server charset name \"%s\" unrecognized\n", client->name);
+ tdsdump_log(TDS_DBG_FUNC, "tds_iconv_info_init: server charset name \"%s\" unrecognized\n", server_name);
return 0;
}
--- src/tds/locale.c;-0 Tue Oct 16 10:12:22 2007
+++ src/tds/locale.c Thu May 27 10:05:49 2010
@@ -22,6 +22,10 @@
#include <config.h>
#endif
+#if HAVE_LOCALE_H
+#include <locale.h>
+#endif
+
#include <stdarg.h>
#include <stdio.h>
#include <ctype.h>
@@ -68,12 +72,16 @@ tds_get_locale(void)
if (in) {
tds_read_conf_section(in, "default", tds_parse_locale, locale);
+#if HAVE_LOCALE_H
+ setlocale(LC_ALL, "");
+ s = setlocale(LC_ALL, NULL);
+#else
s = getenv("LANG");
+#endif
if (s && s[0]) {
int found;
char buf[128];
const char *strip = "@._";
- const char *charset = NULL;
/* do not change environment !!! */
tds_strlcpy(buf, s, sizeof(buf));
@@ -96,19 +104,13 @@ tds_get_locale(void)
if (!s)
continue;
*s = 0;
- if (*strip == '.')
- charset = s+1;
rewind(in);
found = tds_read_conf_section(in, buf, tds_parse_locale, locale);
}
- /* charset specified in LANG ?? */
- if (charset) {
- free(locale->client_charset);
- locale->client_charset = strdup(charset);
- }
}
+
fclose(in);
}
return locale;
--- src/tds/mem.c;-0 Sun May 2 06:52:13 2010
+++ src/tds/mem.c Thu May 27 13:46:22 2010
@@ -690,35 +690,9 @@ TDSLOCALE *
tds_alloc_locale(void)
{
TDSLOCALE *locale;
-#if !(HAVE_NL_LANGINFO && defined(CODESET))
- char *lc_all;
-#endif
TEST_MALLOC(locale, TDSLOCALE);
-#if HAVE_NL_LANGINFO && defined(CODESET)
- locale->client_charset = strdup(nl_langinfo(CODESET));
-#else
- locale->client_charset = strdup("ISO-8859-1");
- if (!locale->client_charset)
- goto Cleanup;
-
- if ((lc_all = strdup(setlocale(LC_ALL, NULL))) == NULL)
- goto Cleanup;
-
- if (strtok(lc_all, ".")) {
- char *encoding = strtok(NULL, "@");
- if (encoding) {
- free(locale->client_charset);
- locale->client_charset = strdup(encoding);
- }
- }
- free(lc_all);
-#endif
- if (!locale->client_charset)
- goto Cleanup;
- tdsdump_log(TDS_DBG_FUNC, "tds_alloc_locale(): initialized locale to \"%s\"\n", locale->client_charset? locale->client_charset : "NULL");
-
return locale;
Cleanup:
@@ -832,6 +806,9 @@ tds_alloc_connection(TDSLOCALE * locale)
{
TDSCONNECTION *connection;
char hostname[128];
+#if !(HAVE_NL_LANGINFO && defined(CODESET))
+ char *lc_all;
+#endif
TEST_MALLOC(connection, TDSCONNECTION);
tds_dstr_init(&connection->server_name);
@@ -854,9 +831,28 @@ tds_alloc_connection(TDSLOCALE * locale)
goto Cleanup;
connection->tds_version = TDS_DEFAULT_VERSION;
connection->block_size = 0;
- /* TODO use system default ?? */
+
+ setlocale(LC_ALL, "");
+#if HAVE_NL_LANGINFO && defined(CODESET)
+ if (!tds_dstr_copy(&connection->client_charset, nl_langinfo(CODESET)))
+ goto Cleanup;;
+#else
if (!tds_dstr_copy(&connection->client_charset, "ISO-8859-1"))
goto Cleanup;
+
+ if ((lc_all = strdup(setlocale(LC_ALL, NULL))) == NULL)
+ goto Cleanup;
+
+ if (strtok(lc_all, ".")) {
+ char *encoding = strtok(NULL, "@");
+ if (encoding) {
+ if (!tds_dstr_copy(&connection->client_charset, encoding))
+ goto Cleanup;
+ }
+ }
+ free(lc_all);
+#endif
+
if (locale) {
if (locale->language)
if (!tds_dstr_copy(&connection->language, locale->language))
@@ -1154,7 +1150,6 @@ tds_free_locale(TDSLOCALE * locale)
free(locale->language);
free(locale->server_charset);
free(locale->date_fmt);
- free(locale->client_charset);
free(locale);
}