uncrustify as demanded.
[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 /* end of gnunet-config.c */