use NULL value in load_path_suffix to NOT load any files
[oweals/gnunet.git] / src / util / gnunet-config.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2012 GNUnet e.V.
4
5      GNUnet is free software: you can redistribute it and/or modify it
6      under the terms of the GNU Affero General Public License as published
7      by the Free Software Foundation, either version 3 of the License,
8      or (at your option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      Affero General Public License for more details.
14
15      You should have received a copy of the GNU Affero General Public License
16      along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18      SPDX-License-Identifier: AGPL3.0-or-later
19  */
20
21 /**
22  * @file util/gnunet-config.c
23  * @brief tool to access and manipulate GNUnet configuration files
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28
29
30 /**
31  * Name of the section
32  */
33 static char *section;
34
35 /**
36  * Name of the option
37  */
38 static char *option;
39
40 /**
41  * Value to set
42  */
43 static char *value;
44
45 /**
46  * Backend to check if the respective plugin is
47  * loadable. NULL if no check is to be performed.
48  * The value is the "basename" of the plugin to load.
49  */
50 static char *backend_check;
51
52 /**
53  * Treat option as a filename.
54  */
55 static int is_filename;
56
57 /**
58  * Whether to show the sections.
59  */
60 static int list_sections;
61
62 /**
63  * Return value from 'main'.
64  */
65 static int global_ret;
66
67 /**
68  * Should we generate a configuration file that is clean and
69  * only contains the deltas to the defaults?
70  */
71 static int rewrite;
72
73
74 /**
75  * Print each option in a given section.
76  *
77  * @param cls closure
78  * @param section name of the section
79  * @param option name of the option
80  * @param value value of the option
81  */
82 static void
83 print_option (void *cls,
84               const char *section,
85               const char *option,
86               const char *value)
87 {
88   const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
89
90   (void) section;
91   if (is_filename)
92   {
93     char *value_fn;
94     char *fn;
95
96     GNUNET_assert (GNUNET_OK ==
97                    GNUNET_CONFIGURATION_get_value_filename (cfg,
98                                                             section,
99                                                             option,
100                                                             &value_fn));
101     fn = GNUNET_STRINGS_filename_expand (value_fn);
102     if (NULL == fn)
103       fn = value_fn;
104     else
105       GNUNET_free (value_fn);
106     fprintf (stdout, "%s = %s\n", option, fn);
107     GNUNET_free (fn);
108   }
109   else
110   {
111     fprintf (stdout, "%s = %s\n", option, value);
112   }
113 }
114
115
116 /**
117  * Print out given section name.
118  *
119  * @param cls unused
120  * @param section a section in the configuration file
121  */
122 static void
123 print_section_name (void *cls, const char *section)
124 {
125   (void) cls;
126   fprintf (stdout, "%s\n", section);
127 }
128
129
130 /**
131  * Main function that will be run by the scheduler.
132  *
133  * @param cls closure
134  * @param args remaining command-line arguments
135  * @param cfgfile name of the configuration file used (for saving,
136  *                                                     can be NULL!)
137  * @param cfg configuration
138  */
139 static void
140 run (void *cls,
141      char *const *args,
142      const char *cfgfile,
143      const struct GNUNET_CONFIGURATION_Handle *cfg)
144 {
145   struct GNUNET_CONFIGURATION_Handle *out = NULL;
146   struct GNUNET_CONFIGURATION_Handle *diff = NULL;
147   char *cfg_fn;
148
149   (void) cls;
150   (void) args;
151   if (NULL != backend_check)
152   {
153     char *name;
154
155     GNUNET_asprintf (&name, "libgnunet_plugin_%s", backend_check);
156     global_ret = (GNUNET_OK == GNUNET_PLUGIN_test (name)) ? 0 : 77;
157     GNUNET_free (name);
158     return;
159   }
160   if (rewrite)
161   {
162     struct GNUNET_CONFIGURATION_Handle *def;
163
164     def = GNUNET_CONFIGURATION_create ();
165     if (GNUNET_OK != GNUNET_CONFIGURATION_load (def, NULL))
166     {
167       fprintf (stderr, _ ("failed to load configuration defaults"));
168       global_ret = 1;
169       return;
170     }
171     diff = GNUNET_CONFIGURATION_get_diff (def, cfg);
172     cfg = diff;
173   }
174   if (((! rewrite) && (NULL == section)) || list_sections)
175   {
176     if (! list_sections)
177     {
178       fprintf (stderr,
179                _ ("%s or %s argument is required\n"),
180                "--section",
181                "--list-sections");
182       global_ret = 1;
183     }
184     else
185     {
186       fprintf (stderr, _ ("The following sections are available:\n"));
187       GNUNET_CONFIGURATION_iterate_sections (cfg, &print_section_name, NULL);
188     }
189     goto cleanup;
190   }
191
192   if ((NULL != section) && (NULL == value))
193   {
194     if (NULL == option)
195     {
196       GNUNET_CONFIGURATION_iterate_section_values (cfg,
197                                                    section,
198                                                    &print_option,
199                                                    (void *) cfg);
200     }
201     else
202     {
203       if (is_filename)
204       {
205         if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg,
206                                                                   section,
207                                                                   option,
208                                                                   &value))
209         {
210           GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, section, option);
211           global_ret = 3;
212           goto cleanup;
213         }
214       }
215       else
216       {
217         if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg,
218                                                                 section,
219                                                                 option,
220                                                                 &value))
221         {
222           GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, section, option);
223           global_ret = 3;
224           goto cleanup;
225         }
226       }
227       fprintf (stdout, "%s\n", value);
228     }
229   }
230   else if (NULL != section)
231   {
232     if (NULL == option)
233     {
234       fprintf (stderr, _ ("--option argument required to set value\n"));
235       global_ret = 1;
236       goto cleanup;
237     }
238     out = GNUNET_CONFIGURATION_dup (cfg);
239     GNUNET_CONFIGURATION_set_value_string (out, section, option, value);
240   }
241   cfg_fn = NULL;
242   if (NULL == cfgfile)
243   {
244     const char *xdg = getenv ("XDG_CONFIG_HOME");
245     if (NULL != xdg)
246       GNUNET_asprintf (&cfg_fn,
247                        "%s%s%s",
248                        xdg,
249                        DIR_SEPARATOR_STR,
250                        GNUNET_OS_project_data_get ()->config_file);
251     else
252       cfg_fn = GNUNET_strdup (GNUNET_OS_project_data_get ()->user_config_file);
253     cfgfile = cfg_fn;
254   }
255   if ((NULL != diff) || (NULL != out))
256   {
257     if (GNUNET_OK !=
258         GNUNET_CONFIGURATION_write ((NULL == out) ? diff : out, cfgfile))
259       global_ret = 2;
260   }
261   GNUNET_free_non_null (cfg_fn);
262   if (NULL != out)
263     GNUNET_CONFIGURATION_destroy (out);
264 cleanup:
265   if (NULL != diff)
266     GNUNET_CONFIGURATION_destroy (diff);
267 }
268
269
270 /**
271  * Program to manipulate configuration files.
272  *
273  * @param argc number of arguments from the command line
274  * @param argv command line arguments
275  * @return 0 ok, 1 on error
276  */
277 int
278 main (int argc, char *const *argv)
279 {
280   struct GNUNET_GETOPT_CommandLineOption options[] =
281   { GNUNET_GETOPT_option_flag (
282       'f',
283       "filename",
284       gettext_noop ("interpret option value as a filename (with $-expansion)"),
285       &is_filename),
286     GNUNET_GETOPT_option_exclusive (GNUNET_GETOPT_option_string (
287                                       'b',
288                                       "supported-backend",
289                                       "BACKEND",
290                                       gettext_noop (
291                                         "test if the current installation supports the specified BACKEND"),
292                                       &backend_check)),
293     GNUNET_GETOPT_option_string ('s',
294                                  "section",
295                                  "SECTION",
296                                  gettext_noop (
297                                    "name of the section to access"),
298                                  &section),
299     GNUNET_GETOPT_option_string ('o',
300                                  "option",
301                                  "OPTION",
302                                  gettext_noop ("name of the option to access"),
303                                  &option),
304     GNUNET_GETOPT_option_string ('V',
305                                  "value",
306                                  "VALUE",
307                                  gettext_noop ("value to set"),
308                                  &value),
309     GNUNET_GETOPT_option_flag ('S',
310                                "list-sections",
311                                gettext_noop (
312                                  "print available configuration sections"),
313                                &list_sections),
314     GNUNET_GETOPT_option_flag (
315       'w',
316       "rewrite",
317       gettext_noop (
318         "write configuration file that only contains delta to defaults"),
319       &rewrite),
320     GNUNET_GETOPT_OPTION_END };
321   int ret;
322
323   if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
324     return 2;
325
326   ret =
327     GNUNET_PROGRAM_run (argc,
328                         argv,
329                         "gnunet-config [OPTIONS]",
330                         gettext_noop ("Manipulate GNUnet configuration files"),
331                         options,
332                         &run,
333                         NULL);
334   GNUNET_free ((void *) argv);
335   if (GNUNET_OK == ret)
336     return global_ret;
337   return ret;
338 }
339
340
341 /* end of gnunet-config.c */