Line data Source code
1 : /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
2 : * Copyright (C) 1998-1999 Brian Bruns
3 : * Copyright (C) 2005-2010 Frediano Ziglio
4 : *
5 : * This library is free software; you can redistribute it and/or
6 : * modify it under the terms of the GNU Library General Public
7 : * License as published by the Free Software Foundation; either
8 : * version 2 of the License, or (at your option) any later version.
9 : *
10 : * This library is distributed in the hope that it will be useful,
11 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 : * Library General Public License for more details.
14 : *
15 : * You should have received a copy of the GNU Library General Public
16 : * License along with this library; if not, write to the
17 : * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 : * Boston, MA 02111-1307, USA.
19 : */
20 :
21 : #include <config.h>
22 :
23 : #if HAVE_LOCALE_H
24 : #include <locale.h>
25 : #endif
26 :
27 : #include <stdarg.h>
28 : #include <stdio.h>
29 : #include <ctype.h>
30 :
31 : #if HAVE_STRING_H
32 : #include <string.h>
33 : #endif /* HAVE_STRING_H */
34 :
35 : #if HAVE_STDLIB_H
36 : #include <stdlib.h>
37 : #endif /* HAVE_STDLIB_H */
38 :
39 : #include <freetds/tds.h>
40 : #include <freetds/configs.h>
41 : #include <freetds/replacements.h>
42 :
43 : static bool tds_parse_locale(const char *option, const char *value, void *param);
44 :
45 : /**
46 : * Get locale information.
47 : * @return allocated structure with all information or NULL if error
48 : */
49 : TDSLOCALE *
50 2891 : tds_get_locale(void)
51 : {
52 : TDSLOCALE *locale;
53 : char *s;
54 : FILE *in;
55 :
56 : /* allocate a new structure with hard coded and build-time defaults */
57 2891 : locale = tds_alloc_locale();
58 2891 : if (!locale)
59 : return NULL;
60 :
61 2891 : tdsdump_log(TDS_DBG_INFO1, "Attempting to read locales.conf file\n");
62 :
63 2891 : in = tds_dir_open(FREETDS_LOCALECONFFILE, TDS_DIR("r"));
64 2891 : if (in) {
65 2891 : tds_read_conf_section(in, "default", tds_parse_locale, locale);
66 :
67 : #if HAVE_LOCALE_H
68 2891 : s = setlocale(LC_ALL, NULL);
69 : #else
70 : s = getenv("LANG");
71 : #endif
72 2891 : if (s && s[0]) {
73 : bool found;
74 : char buf[128];
75 2891 : const char *strip = "@._";
76 :
77 : /* do not change environment !!! */
78 2891 : strlcpy(buf, s, sizeof(buf));
79 :
80 : /* search full name */
81 2891 : rewind(in);
82 2891 : found = tds_read_conf_section(in, buf, tds_parse_locale, locale);
83 :
84 : /*
85 : * Here we try to strip some part of language in order to
86 : * catch similar language
87 : * LANG is composed by
88 : * language[_sublanguage][.charset][@modified]
89 : * ie it_IT@euro or it_IT.UTF-8 so we strip in order
90 : * modifier, charset and sublanguage
91 : * ie it_IT@euro -> it_IT -> it
92 : */
93 11564 : for (;!found && *strip; ++strip) {
94 8673 : s = strrchr(buf, *strip);
95 8673 : if (!s)
96 8649 : continue;
97 24 : *s = 0;
98 24 : rewind(in);
99 24 : found = tds_read_conf_section(in, buf, tds_parse_locale, locale);
100 : }
101 :
102 : }
103 :
104 :
105 2891 : fclose(in);
106 : }
107 : return locale;
108 : }
109 :
110 : static bool
111 5782 : tds_parse_locale(const char *option, const char *value, void *param)
112 : {
113 5782 : TDSLOCALE *locale = (TDSLOCALE *) param;
114 :
115 5782 : if (!strcmp(option, TDS_STR_CHARSET)) {
116 0 : free(locale->server_charset);
117 0 : locale->server_charset = strdup(value);
118 5782 : } else if (!strcmp(option, TDS_STR_LANGUAGE)) {
119 0 : free(locale->language);
120 0 : locale->language = strdup(value);
121 5782 : } else if (!strcmp(option, TDS_STR_DATETIMEFMT)) {
122 2891 : free(locale->datetime_fmt);
123 2891 : locale->datetime_fmt = strdup(value);
124 2891 : } else if (!strcmp(option, TDS_STR_DATEFMT)) {
125 0 : free(locale->date_fmt);
126 0 : locale->date_fmt = strdup(value);
127 2891 : } else if (!strcmp(option, TDS_STR_TIMEFMT)) {
128 2891 : free(locale->time_fmt);
129 2891 : locale->time_fmt = strdup(value);
130 : } else {
131 : return false;
132 : }
133 : return true;
134 : }
|