GnuCash c935c2f+
Loading...
Searching...
No Matches
gnc-environment.c
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 <stdbool.h>
26#include <stdio.h>
27
28#include <string.h>
29#include "gnc-environment.h"
30#include "gnc-path.h"
31
32static gchar *environment_expand(gchar *param)
33{
34 gchar *search_start;
35 gchar *opening_brace;
36 gchar *closing_brace;
37 gchar *result;
38 gchar *tmp;
39 gchar *expanded = NULL;
40
41 if (!param)
42 return NULL;
43
44 /* Set an initial return value, so we can always use g_strconcat below) */
45 result = g_strdup ("x");
46
47 /* Look for matching pairs of { and }. Anything in between should be expanded */
48 search_start = param;
49 opening_brace = g_strstr_len (search_start, -1, "{");
50 closing_brace = g_strstr_len (search_start, -1, "}");
51
52 /* Note: the test on valid braces is fairly simple:
53 * * if no pair of opening/closing braces is found, no expansion occurs
54 * * braces can't be nested, this will give unexpected results
55 * * the string should contain no other braces than those used to mark
56 * expandable variables, or unexpected results will be returned.
57 */
58 while ( opening_brace && closing_brace && (closing_brace > opening_brace) )
59 {
60 /* Found a first matching pair */
61 gchar *to_expand;
62 const gchar *env_val;
63
64 /* If the string had characters before the opening {, copy them first */
65 if (opening_brace > search_start)
66 {
67 gchar *prefix = g_strndup (search_start, opening_brace - search_start);
68
69 tmp = g_strconcat (result, prefix, NULL);
70 g_free (result);
71 result = tmp;
72 g_free (prefix);
73 }
74
75 /* Expand the variable we found and append it to the result */
76 to_expand = g_strndup (opening_brace + 1, closing_brace - opening_brace - 1);
77 env_val = g_getenv (to_expand);
78 tmp = g_strconcat (result, env_val, NULL);
79 g_free (result);
80 result = tmp;
81 g_free (to_expand);
82
83 /* Look for matching pairs of { and }. Anything in between should be expanded */
84 search_start = closing_brace + 1;
85 opening_brace = g_strstr_len (search_start, -1, "{");
86 closing_brace = g_strstr_len (search_start, -1, "}");
87 }
88
89 /* No more braces found, append the remaining characters */
90 tmp = g_strconcat (result, search_start, NULL);
91 g_free (result);
92 result = tmp;
93
94 /* Remove the "x" from our result */
95 if (g_strcmp0 (result, "x"))
96 expanded = g_strdup (result + 1);
97 g_free (result);
98
99 return expanded;
100}
101
102static bool
103char_array_contains(const char **array, unsigned num_keys, const char *key)
104{
105 for (unsigned i = 0; i < num_keys; ++i)
106 {
107 if (strcmp(key, array[i]) == 0)
108 return true;
109 }
110 return false;
111}
112
113static void
114gnc_environment_parse_one (const gchar *env_path)
115{
116 GKeyFile *keyfile = g_key_file_new();
117 gchar **env_vars;
118 gsize param_count;
119 gint i;
120 gboolean got_keyfile;
121 const unsigned num_keys = 6;
122 const char *reserved_keys[] = {"GNC_HOME", "GNC_BIN", "GNC_LIB",
123 "GNC_DATA", "GNC_CONF", "SYS_LIB"};
124
125 got_keyfile = g_key_file_load_from_file (keyfile, env_path, G_KEY_FILE_NONE, NULL);
126 if ( !got_keyfile )
127 {
128 g_key_file_free(keyfile);
129 return;
130 }
131
132 /* Read the environment overrides and apply them */
133 env_vars = g_key_file_get_keys(keyfile, "Variables", &param_count, NULL);
134 for ( i = 0; i < param_count; i++ )
135 {
136 gchar **val_list;
137 gsize val_count;
138 gint j;
139 gchar *new_val = NULL, *tmp_val;
140 if (char_array_contains(reserved_keys, num_keys, env_vars[i]))
141 continue;
142
143 /* for each variable, read its new value, optionally expand it and set/unset it */
144 val_list = g_key_file_get_string_list (keyfile, "Variables",
145 env_vars[i], &val_count,
146 NULL);
147 if ( val_count == 0 )
148 g_unsetenv (env_vars[i]);
149 else
150 {
151 /* Set an initial return value, so we can always use g_build_path below) */
152 tmp_val = g_strdup ("x");
153 for ( j = 0; j < val_count; j++ )
154 {
155 gchar *expanded = environment_expand (val_list[j]);
156 if (expanded && strlen(expanded))
157 {
158 new_val = g_build_path (G_SEARCHPATH_SEPARATOR_S, tmp_val, expanded, NULL);
159 g_free (tmp_val);
160 g_free(expanded);
161 tmp_val = new_val;
162 }
163 }
164 g_strfreev (val_list);
165
166 /* Remove the "x" from our result */
167 if (g_strcmp0 (tmp_val, "x"))
168 {
169 new_val = g_strdup (tmp_val + sizeof (G_SEARCHPATH_SEPARATOR_S));
170 g_free (tmp_val);
171 }
172 if (!g_setenv (env_vars[i], new_val, TRUE))
173 g_warning ("Couldn't properly override environment variable \"%s\". "
174 "This may lead to unexpected results", env_vars[i]);
175 g_free(new_val);
176 }
177 }
178
179 g_strfreev(env_vars);
180 g_key_file_free(keyfile);
181}
182
183void
185{
186 gchar *config_path;
187 gchar *env_path;
188 gchar *env_parm;
189
190 /* Export default parameters to the environment */
191 env_parm = gnc_path_get_prefix();
192 if (!g_setenv("GNC_HOME", env_parm, TRUE))
193 g_warning ("Couldn't set/override environment variable GNC_HOME.");
194 g_free (env_parm);
195 env_parm = gnc_path_get_bindir();
196 if (!g_setenv("GNC_BIN", env_parm, TRUE))
197 g_warning ("Couldn't set/override environment variable GNC_BIN.");
198 g_free (env_parm);
199 env_parm = gnc_path_get_pkglibdir();
200 if (!g_setenv("GNC_LIB", env_parm, TRUE))
201 g_warning ("Couldn't set/override environment variable GNC_LIB.");
202 g_free (env_parm);
203 env_parm = gnc_path_get_pkgdatadir();
204 if (!g_setenv("GNC_DATA", env_parm, TRUE))
205 g_warning ("Couldn't set/override environment variable GNC_DATA.");
206 g_free (env_parm);
207 env_parm = gnc_path_get_pkgsysconfdir();
208 if (!g_setenv("GNC_CONF", env_parm, TRUE))
209 g_warning ("Couldn't set/override environment variable GNC_CONF.");
210 g_free (env_parm);
211 env_parm = gnc_path_get_libdir();
212 if (!g_setenv("SYS_LIB", env_parm, TRUE))
213 g_warning ("Couldn't set/override environment variable SYS_LIB.");
214 g_free (env_parm);
215
216 config_path = gnc_path_get_pkgsysconfdir();
217#ifdef G_OS_WIN32
218 {
219 /* unhide files without extension */
220 gchar *pathext = g_build_path(";", ".", g_getenv("PATHEXT"),
221 (gchar*) NULL);
222 g_setenv("PATHEXT", pathext, TRUE);
223 g_free(pathext);
224 }
225#endif
226
227 /* Parse the environment file that got installed with gnucash */
228 env_path = g_build_filename (config_path, "environment", NULL);
229 gnc_environment_parse_one(env_path);
230 g_free (env_path);
231
232 /* Parse local overrides for this file */
233 env_path = g_build_filename (config_path, "environment.local", NULL);
234 gnc_environment_parse_one(env_path);
235 g_free (env_path);
236 g_free (config_path);
237}
code to set up the environment for proper gnucash functioning.
void gnc_environment_setup(void)
Parse <prefix>/etc/gnucash/environment and set environment variables based on the contents of that fi...