Branch data Line data Source code
1 : : /*
2 : : * gnc-environment.c:
3 : : *
4 : : * Copyright (C) 2013 Geert Janssens <geert@kobaltwit.be>
5 : : *
6 : : * This program is free software; you can redistribute it and/or
7 : : * modify it under the terms of the GNU General Public License as
8 : : * published by the Free Software Foundation; either version 2 of
9 : : * the License, or (at your option) any later version.
10 : : *
11 : : * This program is distributed in the hope that it will be useful,
12 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : : * GNU General Public License for more details.
15 : : *
16 : : * You should have received a copy of the GNU General Public License
17 : : * along with this program; if not, contact:
18 : : *
19 : : * Free Software Foundation Voice: +1-617-542-5942
20 : : * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
21 : : * Boston, MA 02110-1301, USA gnu@gnu.org
22 : : */
23 : :
24 : : #include <glib.h>
25 : : #include <string.h>
26 : : #include "gnc-environment.h"
27 : : #include "gnc-path.h"
28 : :
29 : 24 : static gchar *environment_expand(gchar *param)
30 : : {
31 : : gchar *search_start;
32 : : gchar *opening_brace;
33 : : gchar *closing_brace;
34 : : gchar *result;
35 : : gchar *tmp;
36 : 24 : gchar *expanded = NULL;
37 : :
38 : 24 : if (!param)
39 : 0 : return NULL;
40 : :
41 : : /* Set an initial return value, so we can always use g_strconcat below) */
42 : 24 : result = g_strdup ("x");
43 : :
44 : : /* Look for matching pairs of { and }. Anything in between should be expanded */
45 : 24 : search_start = param;
46 : 24 : opening_brace = g_strstr_len (search_start, -1, "{");
47 : 24 : closing_brace = g_strstr_len (search_start, -1, "}");
48 : :
49 : : /* Note: the test on valid braces is fairly simple:
50 : : * * if no pair of opening/closing braces is found, no expansion occurs
51 : : * * braces can't be nested, this will give unexpected results
52 : : * * the string should contain no other braces than those used to mark
53 : : * expandable variables, or unexpected results will be returned.
54 : : */
55 : 44 : while ( opening_brace && closing_brace && (closing_brace > opening_brace) )
56 : : {
57 : : /* Found a first matching pair */
58 : : gchar *to_expand;
59 : : const gchar *env_val;
60 : :
61 : : /* If the string had characters before the opening {, copy them first */
62 : 20 : if (opening_brace > search_start)
63 : : {
64 : 0 : gchar *prefix = g_strndup (search_start, opening_brace - search_start);
65 : :
66 : 0 : tmp = g_strconcat (result, prefix, NULL);
67 : 0 : g_free (result);
68 : 0 : result = tmp;
69 : 0 : g_free (prefix);
70 : : }
71 : :
72 : : /* Expand the variable we found and append it to the result */
73 : 20 : to_expand = g_strndup (opening_brace + 1, closing_brace - opening_brace - 1);
74 : 20 : env_val = g_getenv (to_expand);
75 : 20 : tmp = g_strconcat (result, env_val, NULL);
76 : 20 : g_free (result);
77 : 20 : result = tmp;
78 : 20 : g_free (to_expand);
79 : :
80 : : /* Look for matching pairs of { and }. Anything in between should be expanded */
81 : 20 : search_start = closing_brace + 1;
82 : 20 : opening_brace = g_strstr_len (search_start, -1, "{");
83 : 20 : closing_brace = g_strstr_len (search_start, -1, "}");
84 : : }
85 : :
86 : : /* No more braces found, append the remaining characters */
87 : 24 : tmp = g_strconcat (result, search_start, NULL);
88 : 24 : g_free (result);
89 : 24 : result = tmp;
90 : :
91 : : /* Remove the "x" from our result */
92 : 24 : if (g_strcmp0 (result, "x"))
93 : 36 : expanded = g_strdup (result + 1);
94 : 24 : g_free (result);
95 : :
96 : 24 : return expanded;
97 : : }
98 : :
99 : : static void
100 : 2 : gnc_environment_parse_one (const gchar *env_path)
101 : : {
102 : 2 : GKeyFile *keyfile = g_key_file_new();
103 : : gchar **env_vars;
104 : : gsize param_count;
105 : : gint i;
106 : : gboolean got_keyfile;
107 : :
108 : 2 : got_keyfile = g_key_file_load_from_file (keyfile, env_path, G_KEY_FILE_NONE, NULL);
109 : 2 : if ( !got_keyfile )
110 : : {
111 : 1 : g_key_file_free(keyfile);
112 : 1 : return;
113 : : }
114 : :
115 : : /* Read the environment overrides and apply them */
116 : 1 : env_vars = g_key_file_get_keys(keyfile, "Variables", ¶m_count, NULL);
117 : 8 : for ( i = 0; i < param_count; i++ )
118 : : {
119 : : gchar **val_list;
120 : : gsize val_count;
121 : : gint j;
122 : 7 : gchar *new_val = NULL, *tmp_val;
123 : :
124 : : /* For each variable, read its new value, optionally expand it and set/unset it */
125 : 7 : val_list = g_key_file_get_string_list (keyfile, "Variables",
126 : 7 : env_vars[i], &val_count,
127 : : NULL);
128 : 7 : if ( val_count == 0 )
129 : 0 : g_unsetenv (env_vars[i]);
130 : : else
131 : : {
132 : : /* Set an initial return value, so we can always use g_build_path below) */
133 : 7 : tmp_val = g_strdup ("x");
134 : 31 : for ( j = 0; j < val_count; j++ )
135 : : {
136 : 24 : gchar *expanded = environment_expand (val_list[j]);
137 : 24 : if (expanded && strlen(expanded))
138 : : {
139 : 18 : new_val = g_build_path (G_SEARCHPATH_SEPARATOR_S, tmp_val, expanded, NULL);
140 : 18 : g_free (tmp_val);
141 : 18 : g_free(expanded);
142 : 18 : tmp_val = new_val;
143 : : }
144 : : }
145 : 7 : g_strfreev (val_list);
146 : :
147 : : /* Remove the "x" from our result */
148 : 7 : if (g_strcmp0 (tmp_val, "x"))
149 : : {
150 : 7 : new_val = g_strdup (tmp_val + sizeof (G_SEARCHPATH_SEPARATOR_S));
151 : 7 : g_free (tmp_val);
152 : : }
153 : 7 : if (!g_setenv (env_vars[i], new_val, TRUE))
154 : 0 : g_warning ("Couldn't properly override environment variable \"%s\". "
155 : : "This may lead to unexpected results", env_vars[i]);
156 : 7 : g_free(new_val);
157 : : }
158 : : }
159 : :
160 : 1 : g_strfreev(env_vars);
161 : 1 : g_key_file_free(keyfile);
162 : : }
163 : :
164 : : void
165 : 1 : gnc_environment_setup (void)
166 : : {
167 : : gchar *config_path;
168 : : gchar *env_path;
169 : : gchar *env_parm;
170 : :
171 : : /* Export default parameters to the environment */
172 : 1 : env_parm = gnc_path_get_prefix();
173 : 1 : if (!g_setenv("GNC_HOME", env_parm, FALSE))
174 : 0 : g_warning ("Couldn't set/override environment variable GNC_HOME.");
175 : 1 : g_free (env_parm);
176 : 1 : env_parm = gnc_path_get_bindir();
177 : 1 : if (!g_setenv("GNC_BIN", env_parm, FALSE))
178 : 0 : g_warning ("Couldn't set/override environment variable GNC_BIN.");
179 : 1 : g_free (env_parm);
180 : 1 : env_parm = gnc_path_get_pkglibdir();
181 : 1 : if (!g_setenv("GNC_LIB", env_parm, FALSE))
182 : 0 : g_warning ("Couldn't set/override environment variable GNC_LIB.");
183 : 1 : g_free (env_parm);
184 : 1 : env_parm = gnc_path_get_pkgdatadir();
185 : 1 : if (!g_setenv("GNC_DATA", env_parm, FALSE))
186 : 0 : g_warning ("Couldn't set/override environment variable GNC_DATA.");
187 : 1 : g_free (env_parm);
188 : 1 : env_parm = gnc_path_get_pkgsysconfdir();
189 : 1 : if (!g_setenv("GNC_CONF", env_parm, FALSE))
190 : 0 : g_warning ("Couldn't set/override environment variable GNC_CONF.");
191 : 1 : g_free (env_parm);
192 : 1 : env_parm = gnc_path_get_libdir();
193 : 1 : if (!g_setenv("SYS_LIB", env_parm, FALSE))
194 : 0 : g_warning ("Couldn't set/override environment variable SYS_LIB.");
195 : 1 : g_free (env_parm);
196 : :
197 : 1 : config_path = gnc_path_get_pkgsysconfdir();
198 : : #ifdef G_OS_WIN32
199 : : {
200 : : /* unhide files without extension */
201 : : gchar *pathext = g_build_path(";", ".", g_getenv("PATHEXT"),
202 : : (gchar*) NULL);
203 : : g_setenv("PATHEXT", pathext, TRUE);
204 : : g_free(pathext);
205 : : }
206 : : #endif
207 : :
208 : : /* Parse the environment file that got installed with gnucash */
209 : 1 : env_path = g_build_filename (config_path, "environment", NULL);
210 : 1 : gnc_environment_parse_one(env_path);
211 : 1 : g_free (env_path);
212 : :
213 : : /* Parse local overrides for this file */
214 : 1 : env_path = g_build_filename (config_path, "environment.local", NULL);
215 : 1 : gnc_environment_parse_one(env_path);
216 : 1 : g_free (env_path);
217 : 1 : g_free (config_path);
218 : 1 : }
|