GnuCash  4.11-243-g1cac132214+
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 <string.h>
26 #include "gnc-environment.h"
27 #include "gnc-path.h"
28 
29 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  gchar *expanded = NULL;
37 
38  if (!param)
39  return NULL;
40 
41  /* Set an initial return value, so we can always use g_strconcat below) */
42  result = g_strdup ("x");
43 
44  /* Look for matching pairs of { and }. Anything in between should be expanded */
45  search_start = param;
46  opening_brace = g_strstr_len (search_start, -1, "{");
47  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  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  if (opening_brace > search_start)
63  {
64  gchar *prefix = g_strndup (search_start, opening_brace - search_start);
65 
66  tmp = g_strconcat (result, prefix, NULL);
67  g_free (result);
68  result = tmp;
69  g_free (prefix);
70  }
71 
72  /* Expand the variable we found and append it to the result */
73  to_expand = g_strndup (opening_brace + 1, closing_brace - opening_brace - 1);
74  env_val = g_getenv (to_expand);
75  tmp = g_strconcat (result, env_val, NULL);
76  g_free (result);
77  result = tmp;
78  g_free (to_expand);
79 
80  /* Look for matching pairs of { and }. Anything in between should be expanded */
81  search_start = closing_brace + 1;
82  opening_brace = g_strstr_len (search_start, -1, "{");
83  closing_brace = g_strstr_len (search_start, -1, "}");
84  }
85 
86  /* No more braces found, append the remaining characters */
87  tmp = g_strconcat (result, search_start, NULL);
88  g_free (result);
89  result = tmp;
90 
91  /* Remove the "x" from our result */
92  if (g_strcmp0 (result, "x"))
93  expanded = g_strdup (result + 1);
94  g_free (result);
95 
96  return expanded;
97 }
98 
99 static void
100 gnc_environment_parse_one (const gchar *env_path)
101 {
102  GKeyFile *keyfile = g_key_file_new();
103  gchar **env_vars;
104  gsize param_count;
105  gint i;
106  gboolean got_keyfile;
107 
108  got_keyfile = g_key_file_load_from_file (keyfile, env_path, G_KEY_FILE_NONE, NULL);
109  if ( !got_keyfile )
110  {
111  g_key_file_free(keyfile);
112  return;
113  }
114 
115  /* Read the environment overrides and apply them */
116  env_vars = g_key_file_get_keys(keyfile, "Variables", &param_count, NULL);
117  for ( i = 0; i < param_count; i++ )
118  {
119  gchar **val_list;
120  gsize val_count;
121  gint j;
122  gchar *new_val = NULL, *tmp_val;
123 
124  /* For each variable, read its new value, optionally expand it and set/unset it */
125  val_list = g_key_file_get_string_list (keyfile, "Variables",
126  env_vars[i], &val_count,
127  NULL);
128  if ( val_count == 0 )
129  g_unsetenv (env_vars[i]);
130  else
131  {
132  /* Set an initial return value, so we can always use g_build_path below) */
133  tmp_val = g_strdup ("x");
134  for ( j = 0; j < val_count; j++ )
135  {
136  gchar *expanded = environment_expand (val_list[j]);
137  if (expanded && strlen(expanded))
138  {
139  new_val = g_build_path (G_SEARCHPATH_SEPARATOR_S, tmp_val, expanded, NULL);
140  g_free (tmp_val);
141  g_free(expanded);
142  tmp_val = new_val;
143  }
144  }
145  g_strfreev (val_list);
146 
147  /* Remove the "x" from our result */
148  if (g_strcmp0 (tmp_val, "x"))
149  {
150  new_val = g_strdup (tmp_val + sizeof (G_SEARCHPATH_SEPARATOR_S));
151  g_free (tmp_val);
152  }
153  if (!g_setenv (env_vars[i], new_val, TRUE))
154  g_warning ("Couldn't properly override environment variable \"%s\". "
155  "This may lead to unexpected results", env_vars[i]);
156  g_free(new_val);
157  }
158  }
159 
160  g_strfreev(env_vars);
161  g_key_file_free(keyfile);
162 }
163 
164 void
166 {
167  gchar *config_path;
168  gchar *env_path;
169  gchar *env_parm;
170 
171  /* Export default parameters to the environment */
172  env_parm = gnc_path_get_prefix();
173  if (!g_setenv("GNC_HOME", env_parm, FALSE))
174  g_warning ("Couldn't set/override environment variable GNC_HOME.");
175  g_free (env_parm);
176  env_parm = gnc_path_get_bindir();
177  if (!g_setenv("GNC_BIN", env_parm, FALSE))
178  g_warning ("Couldn't set/override environment variable GNC_BIN.");
179  g_free (env_parm);
180  env_parm = gnc_path_get_pkglibdir();
181  if (!g_setenv("GNC_LIB", env_parm, FALSE))
182  g_warning ("Couldn't set/override environment variable GNC_LIB.");
183  g_free (env_parm);
184  env_parm = gnc_path_get_pkgdatadir();
185  if (!g_setenv("GNC_DATA", env_parm, FALSE))
186  g_warning ("Couldn't set/override environment variable GNC_DATA.");
187  g_free (env_parm);
188  env_parm = gnc_path_get_pkgsysconfdir();
189  if (!g_setenv("GNC_CONF", env_parm, FALSE))
190  g_warning ("Couldn't set/override environment variable GNC_CONF.");
191  g_free (env_parm);
192  env_parm = gnc_path_get_libdir();
193  if (!g_setenv("SYS_LIB", env_parm, FALSE))
194  g_warning ("Couldn't set/override environment variable SYS_LIB.");
195  g_free (env_parm);
196 
197  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  env_path = g_build_filename (config_path, "environment", NULL);
210  gnc_environment_parse_one(env_path);
211  g_free (env_path);
212 
213  /* Parse local overrides for this file */
214  env_path = g_build_filename (config_path, "environment.local", NULL);
215  gnc_environment_parse_one(env_path);
216  g_free (env_path);
217  g_free (config_path);
218 }
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...