1 /*
2  * Copyright (C) 2000 Reinhard Müller <reinhard@src.gnome.org>
3  * Copyright (C) 2000 - 2002 Rodrigo Moya <rodrigo@gnome-db.org>
4  * Copyright (C) 2001 Carlos Perelló Marín <carlos@gnome-db.org>
5  * Copyright (C) 2001 - 2011 Vivien Malerba <malerba@gnome-db.org>
6  * Copyright (C) 2002 Andrew Hill <andru@src.gnome.org>
7  * Copyright (C) 2002 - 2003 Gonzalo Paniagua Javier <gonzalo@gnome-db.org>
8  * Copyright (C) 2002 Xabier Rodriguez Calvar <xrcalvar@igalia.com>
9  * Copyright (C) 2002 Zbigniew Chyla <cyba@gnome.pl>
10  * Copyright (C) 2003 Laurent Sansonetti <laurent@datarescue.be>
11  * Copyright (C) 2006 - 2011 Murray Cumming <murrayc@murrayc.com>
12  * Copyright (C) 2007 Armin Burgmeier <armin@openismus.com>
13  * Copyright (C) 2008 Przemysław Grzegorczyk <pgrzegorczyk@gmail.com>
14  *
15  * This library is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU Lesser General Public
17  * License as published by the Free Software Foundation; either
18  * version 2 of the License, or (at your option) any later version.
19  *
20  * This library is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23  * Lesser General Public License for more details.
24  *
25  * You should have received a copy of the GNU Lesser General Public
26  * License along with this library; if not, write to the
27  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
28  * Boston, MA  02110-1301, USA.
29  */
30 
31 #include <glib.h>
32 #include <gmodule.h>
33 #include <libgda/libgda.h>
34 #include <glib/gi18n-lib.h>
35 #ifdef HAVE_LOCALE_H
36 #include <locale.h>
37 #endif
38 
39 #include <libgda/binreloc/gda-binreloc.h>
40 #include <sql-parser/gda-sql-parser.h>
41 #include <libgda/gda-types.h>
42 
43 /*
44  * global variables
45  *
46  * REM: to use them from another Windows DLL, they have to be declared like:
47  *     __declspec(dllimport) extern gchar *gda_numeric_locale;
48  *
49  * Better yet is to define the IMPORT macro as:
50  *
51  *     #ifdef G_OS_WIN32
52  *       #define IMPORT __declspec(dllimport)
53  *     #else
54  *       #define IMPORT
55  *     #endif
56  *     IMPORT extern gchar *gda_numeric_locale;
57  */
58 xmlDtdPtr       _gda_array_dtd = NULL;
59 xmlDtdPtr       gda_paramlist_dtd = NULL;
60 xmlDtdPtr       _gda_server_op_dtd = NULL;
61 
62 static gboolean numeric_locale_dyn = FALSE;
63 gchar          *gda_numeric_locale = "";
64 static gboolean lang_locale_dyn = FALSE;
65 gchar          *gda_lang_locale = "";
66 
67 /**
68  * gda_locale_changed:
69  *
70  * Call this function whenever the setlocale() function has been called
71  * to change the current locale; this function is first called by gda_init() so you
72  * don't need to call it if you have set the locale before calling gda_init().
73  *
74  * Failing to call this function after having changed the current locale may result
75  * in Libgda reverting to the previous set locale.
76  *
77  * Since: 4.2.3
78  */
79 void
gda_locale_changed(void)80 gda_locale_changed (void)
81 {
82 	/* free previous setting */
83 	if (numeric_locale_dyn)
84 		g_free (gda_numeric_locale);
85 	if (lang_locale_dyn)
86 		g_free (gda_lang_locale);
87 
88 	/* net new settings */
89 	gda_numeric_locale = setlocale (LC_NUMERIC, NULL);
90 	if (gda_numeric_locale) {
91 		numeric_locale_dyn = TRUE;
92 		gda_numeric_locale = g_strdup (gda_numeric_locale);
93 	}
94 	else {
95 		numeric_locale_dyn = FALSE;
96 		gda_numeric_locale = "";
97 	}
98 #ifdef HAVE_LC_MESSAGES
99         gda_lang_locale = setlocale (LC_MESSAGES, NULL);
100 #else
101         gda_lang_locale = setlocale (LC_CTYPE, NULL);
102 #endif
103 	if (gda_lang_locale) {
104 		lang_locale_dyn = TRUE;
105 		gda_lang_locale = g_strdup (gda_lang_locale);
106 	}
107 	else {
108 		lang_locale_dyn = FALSE;
109 		gda_lang_locale = "";
110 	}
111 }
112 
113 /**
114  * gda_init:
115  *
116  * Initializes the GDA library, must be called prior to any Libgda usage.
117  *
118  * Please note that if you call setlocale() to modify the current locale, you should also
119  * call gda_locale_changed() before using Libgda again.
120  */
121 void
gda_init(void)122 gda_init (void)
123 {
124 	static GMutex init_mutex;
125 	static gboolean initialized = FALSE;
126 
127 	GType type;
128 	gchar *file;
129 
130 	g_mutex_lock (&init_mutex);
131 	if (initialized) {
132 		g_mutex_unlock (&init_mutex);
133 		gda_log_error (_("Ignoring attempt to re-initialize GDA library."));
134 		return;
135 	}
136 
137 	file = gda_gbr_get_file_path (GDA_LOCALE_DIR, NULL);
138 	bindtextdomain (GETTEXT_PACKAGE, file);
139 	g_free (file);
140 	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
141 
142 #if GLIB_CHECK_VERSION(2,36,0)
143 #else
144 	g_type_init ();
145 #endif
146 
147 	if (!g_module_supported ())
148 		g_error (_("libgda needs GModule. Finishing..."));
149 
150 	/* create the required Gda types, to avoid multiple simultaneous type creation when
151 	 * multi threads are used */
152 	type = GDA_TYPE_NULL;
153 	g_assert (type);
154 	type = G_TYPE_DATE;
155 	g_assert (type);
156 	type = GDA_TYPE_BINARY;
157 	g_assert (type);
158 	type = GDA_TYPE_BLOB;
159 	g_assert (type);
160 	type = GDA_TYPE_GEOMETRIC_POINT;
161 	g_assert (type);
162 	type = GDA_TYPE_NUMERIC;
163 	g_assert (type);
164 	type = GDA_TYPE_SHORT;
165 	g_assert (type);
166 	type = GDA_TYPE_USHORT;
167 	g_assert (type);
168 	type = GDA_TYPE_TIME;
169 	g_assert (type);
170 	type = G_TYPE_DATE;
171 	g_assert (type);
172 	type = GDA_TYPE_TIMESTAMP;
173 	g_assert (type);
174 	type = G_TYPE_ERROR;
175 	g_assert (type);
176 
177 	/* force TZ init */
178 	tzset ();
179 
180 	/* acquire locale */
181 	gda_locale_changed ();
182 
183 	/* binreloc */
184 	gda_gbr_init ();
185 
186 	/* array DTD */
187 	_gda_array_dtd = NULL;
188 	file = gda_gbr_get_file_path (GDA_DATA_DIR, LIBGDA_ABI_NAME, "dtd", "libgda-array.dtd", NULL);
189 	if (g_file_test (file, G_FILE_TEST_EXISTS))
190 		_gda_array_dtd = xmlParseDTD (NULL, (xmlChar*)file);
191 
192 	if (!_gda_array_dtd) {
193 		if (g_getenv ("GDA_TOP_SRC_DIR")) {
194 			g_free (file);
195 			file = g_build_filename (g_getenv ("GDA_TOP_SRC_DIR"), "libgda", "libgda-array.dtd", NULL);
196 			_gda_array_dtd = xmlParseDTD (NULL, (xmlChar*)file);
197 		}
198 		if (!_gda_array_dtd)
199 			g_message (_("Could not parse '%s': "
200 				     "XML data import validation will not be performed (some weird errors may occur)"),
201 				   file);
202 	}
203 	if (_gda_array_dtd)
204 		_gda_array_dtd->name = xmlStrdup((xmlChar*) "gda_array");
205 	g_free (file);
206 
207 	/* paramlist DTD */
208 	gda_paramlist_dtd = NULL;
209 	file = gda_gbr_get_file_path (GDA_DATA_DIR, LIBGDA_ABI_NAME, "dtd", "libgda-paramlist.dtd", NULL);
210 	if (g_file_test (file, G_FILE_TEST_EXISTS))
211 		gda_paramlist_dtd = xmlParseDTD (NULL, (xmlChar*)file);
212 
213 	if (!gda_paramlist_dtd) {
214 		if (g_getenv ("GDA_TOP_SRC_DIR")) {
215 			g_free (file);
216 			file = g_build_filename (g_getenv ("GDA_TOP_SRC_DIR"), "libgda", "libgda-paramlist.dtd", NULL);
217 			gda_paramlist_dtd = xmlParseDTD (NULL, (xmlChar*)file);
218 		}
219 		if (!gda_paramlist_dtd)
220 			g_message (_("Could not parse '%s': "
221 				     "XML data import validation will not be performed (some weird errors may occur)"),
222 				   file);
223 	}
224 	if (gda_paramlist_dtd)
225 		gda_paramlist_dtd->name = xmlStrdup((xmlChar*) "data-set-spec");
226 	g_free (file);
227 
228 	/* server operation DTD */
229 	_gda_server_op_dtd = NULL;
230 	file = gda_gbr_get_file_path (GDA_DATA_DIR, LIBGDA_ABI_NAME, "dtd", "libgda-server-operation.dtd", NULL);
231 	if (g_file_test (file, G_FILE_TEST_EXISTS))
232 		_gda_server_op_dtd = xmlParseDTD (NULL, (xmlChar*)file);
233 
234 	if (!_gda_server_op_dtd) {
235 		if (g_getenv ("GDA_TOP_SRC_DIR")) {
236 			g_free (file);
237 			file = g_build_filename (g_getenv ("GDA_TOP_SRC_DIR"), "libgda", "libgda-server-operation.dtd", NULL);
238 			_gda_server_op_dtd = xmlParseDTD (NULL, (xmlChar*)file);
239 		}
240 		if (!_gda_server_op_dtd)
241 			g_message (_("Could not parse '%s': "
242 				     "Validation for XML files for server operations will not be performed (some weird errors may occur)"),
243 				   file);
244 	}
245 
246 	if (_gda_server_op_dtd)
247 		_gda_server_op_dtd->name = xmlStrdup((xmlChar*) "serv_op");
248 	g_free (file);
249 
250 	initialized = TRUE;
251 	g_mutex_unlock (&init_mutex);
252 }
253 
254 /**
255  * gda_get_application_exec_path:
256  * @app_name: the name of the application to find
257  *
258  * Find the path to the application identified by @app_name. For example if the application
259  * is "gda-sql", then calling this function will return
260  * "/your/prefix/bin/gda-sql-5.0" if Libgda is installed in
261  * the "/your/prefix" prefix (which would usually be "/usr"), and for the ABI version 5.0.
262  *
263  * Returns: (transfer full): the path as a new string, or %NULL if the application cannot be found
264  */
265 gchar *
gda_get_application_exec_path(const gchar * app_name)266 gda_get_application_exec_path (const gchar *app_name)
267 {
268         gchar *str;
269         gchar *fname;
270         g_return_val_if_fail (app_name, NULL);
271 
272         gda_gbr_init ();
273         fname = g_strdup_printf ("%s-%s", app_name, ABI_VERSION);
274         str = gda_gbr_get_file_path (GDA_BIN_DIR, fname, NULL);
275         g_free (fname);
276         if (!g_file_test (str, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_EXECUTABLE)) {
277                 g_free (str);
278                 str = NULL;
279         }
280 
281         return str;
282 }
283