aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authort3sserakt <t3ss@posteo.de>2021-07-30 14:54:23 +0200
committert3sserakt <t3ss@posteo.de>2021-07-30 14:54:23 +0200
commit6d4120e96a52cbd38fb761b03485303b5000215a (patch)
treef87edf470ec9778076233245361f3434f3d08f14
parent4748af6e8e04347ceaeec09ccdfc04d740fa65f0 (diff)
parente84ea6f9f1718298486a088832c87479bd6e9572 (diff)
downloadgnunet-6d4120e96a52cbd38fb761b03485303b5000215a.tar.gz
gnunet-6d4120e96a52cbd38fb761b03485303b5000215a.zip
:Merge branch 'master' of ssh://gnunet.org/gnunet
-rw-r--r--debian/changelog12
-rw-r--r--src/ats-tests/Makefile.am1
-rw-r--r--src/consensus/Makefile.am1
-rw-r--r--src/dht/Makefile.am1
-rw-r--r--src/fs/Makefile.am1
-rw-r--r--src/include/gnunet_configuration_lib.h35
-rw-r--r--src/json/Makefile.am7
-rw-r--r--src/json/json_pack.c6
-rw-r--r--src/nse/Makefile.am1
-rw-r--r--src/regex/Makefile.am1
-rw-r--r--src/secretsharing/Makefile.am1
-rw-r--r--src/testbed/Makefile.am2
-rw-r--r--src/transport/Makefile.am28
-rw-r--r--src/util/Makefile.am7
-rw-r--r--src/util/configuration.c804
-rw-r--r--src/util/configuration_loader.c91
-rw-r--r--src/util/disk.c34
-rw-r--r--src/util/gnunet-config.c51
-rw-r--r--src/util/plugin.c6
-rw-r--r--src/util/program.c31
-rw-r--r--src/util/test_plugin.c52
-rw-r--r--src/util/test_plugin_plug.c5
22 files changed, 876 insertions, 302 deletions
diff --git a/debian/changelog b/debian/changelog
index 79aeb5ae9..a8888ff89 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,15 @@
1gnunet (0.14.1-8) unstable; urgency=low
2
3 * Allow configuration entry point to fall back to /etc/.
4
5 -- Florian Dold <florian@dold.me> Thu, 29 Jul 2021 15:03:08 +0200
6
7gnunet (0.14.1-7) unstable; urgency=low
8
9 * Implement new configuration directives and diagnostics.
10
11 -- Florian Dold <florian@dold.me> Wed, 28 Jul 2021 21:23:36 +0200
12
1gnunet (0.14.1-6) unstable; urgency=low 13gnunet (0.14.1-6) unstable; urgency=low
2 14
3 * Fix path resolution of inlined config files. 15 * Fix path resolution of inlined config files.
diff --git a/src/ats-tests/Makefile.am b/src/ats-tests/Makefile.am
index 543fed287..d515d3e17 100644
--- a/src/ats-tests/Makefile.am
+++ b/src/ats-tests/Makefile.am
@@ -61,6 +61,7 @@ gnunet_ats_sim_SOURCES = \
61gnunet_ats_sim_LDADD = \ 61gnunet_ats_sim_LDADD = \
62 $(top_builddir)/src/util/libgnunetutil.la \ 62 $(top_builddir)/src/util/libgnunetutil.la \
63 $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ 63 $(top_builddir)/src/ats-tests/libgnunetatstesting.la \
64 $(top_builddir)/src/testing/libgnunettesting.la \
64 $(top_builddir)/src/testbed/libgnunettestbed.la \ 65 $(top_builddir)/src/testbed/libgnunettestbed.la \
65 $(top_builddir)/src/ats/libgnunetats.la \ 66 $(top_builddir)/src/ats/libgnunetats.la \
66 $(top_builddir)/src/core/libgnunetcore.la \ 67 $(top_builddir)/src/core/libgnunetcore.la \
diff --git a/src/consensus/Makefile.am b/src/consensus/Makefile.am
index 24e685fb9..cf1d32e74 100644
--- a/src/consensus/Makefile.am
+++ b/src/consensus/Makefile.am
@@ -40,6 +40,7 @@ gnunet_consensus_profiler_SOURCES = \
40gnunet_consensus_profiler_LDADD = \ 40gnunet_consensus_profiler_LDADD = \
41 $(top_builddir)/src/util/libgnunetutil.la \ 41 $(top_builddir)/src/util/libgnunetutil.la \
42 libgnunetconsensus.la \ 42 libgnunetconsensus.la \
43 $(top_builddir)/src/testing/libgnunettesting.la \
43 $(top_builddir)/src/testbed/libgnunettestbed.la \ 44 $(top_builddir)/src/testbed/libgnunettestbed.la \
44 $(GN_LIBINTL) 45 $(GN_LIBINTL)
45 46
diff --git a/src/dht/Makefile.am b/src/dht/Makefile.am
index 2182d1c7f..919eca438 100644
--- a/src/dht/Makefile.am
+++ b/src/dht/Makefile.am
@@ -112,6 +112,7 @@ gnunet_dht_profiler_LDADD = \
112 libgnunetdht.la \ 112 libgnunetdht.la \
113 $(top_builddir)/src/core/libgnunetcore.la \ 113 $(top_builddir)/src/core/libgnunetcore.la \
114 $(top_builddir)/src/util/libgnunetutil.la \ 114 $(top_builddir)/src/util/libgnunetutil.la \
115 $(top_builddir)/src/testing/libgnunettesting.la \
115 $(top_builddir)/src/testbed/libgnunettestbed.la 116 $(top_builddir)/src/testbed/libgnunettestbed.la
116gnunet_dht_profiler_LDFLAGS = \ 117gnunet_dht_profiler_LDFLAGS = \
117 $(GN_LIBINTL) 118 $(GN_LIBINTL)
diff --git a/src/fs/Makefile.am b/src/fs/Makefile.am
index 25590c6f7..2400d412e 100644
--- a/src/fs/Makefile.am
+++ b/src/fs/Makefile.am
@@ -105,6 +105,7 @@ endif
105gnunet_fs_profiler_SOURCES = \ 105gnunet_fs_profiler_SOURCES = \
106 gnunet-fs-profiler.c 106 gnunet-fs-profiler.c
107gnunet_fs_profiler_LDADD = \ 107gnunet_fs_profiler_LDADD = \
108 $(top_builddir)/src/testing/libgnunettesting.la \
108 $(top_builddir)/src/testbed/libgnunettestbed.la \ 109 $(top_builddir)/src/testbed/libgnunettestbed.la \
109 $(top_builddir)/src/util/libgnunetutil.la \ 110 $(top_builddir)/src/util/libgnunetutil.la \
110 $(GN_LIBINTL) 111 $(GN_LIBINTL)
diff --git a/src/include/gnunet_configuration_lib.h b/src/include/gnunet_configuration_lib.h
index 68ed570a3..02e656196 100644
--- a/src/include/gnunet_configuration_lib.h
+++ b/src/include/gnunet_configuration_lib.h
@@ -113,6 +113,18 @@ GNUNET_CONFIGURATION_default (void);
113 113
114 114
115/** 115/**
116 * Return the filename of the default configuration filename
117 * that is used when no explicit configuration entry point
118 * has been specified.
119 *
120 * @returns NULL if no default configuration file can be located,
121 * a newly allocated string otherwise
122 */
123char *
124GNUNET_CONFIGURATION_default_filename (void);
125
126
127/**
116 * Parse a configuration file, add all of the options in the 128 * Parse a configuration file, add all of the options in the
117 * file to the configuration environment. 129 * file to the configuration environment.
118 * 130 *
@@ -139,6 +151,19 @@ GNUNET_CONFIGURATION_serialize (const struct GNUNET_CONFIGURATION_Handle *cfg,
139 151
140 152
141/** 153/**
154 * Serializes the given configuration with diagnostics information.
155 * Diagnostics information will only be available if diagnostics
156 * have been enabled before parsing.
157 *
158 * @param cfg configuration to serialize
159 * @return the memory block where the serialized configuration is
160 * present. This memory should be freed by the caller
161 */
162char *
163GNUNET_CONFIGURATION_serialize_diagnostics (const struct
164 GNUNET_CONFIGURATION_Handle *cfg);
165
166/**
142 * De-serializes configuration 167 * De-serializes configuration
143 * 168 *
144 * @param cfg configuration to update 169 * @param cfg configuration to update
@@ -234,6 +259,16 @@ GNUNET_CONFIGURATION_parse_and_run (const char *filename,
234 GNUNET_CONFIGURATION_Callback cb, 259 GNUNET_CONFIGURATION_Callback cb,
235 void *cb_cls); 260 void *cb_cls);
236 261
262/**
263 * Enable extra diagnostics. Will produce more log output
264 * and allocate more memory.
265 *
266 * @param cfg configuration handle
267 */
268void
269GNUNET_CONFIGURATION_enable_diagnostics (struct
270 GNUNET_CONFIGURATION_Handle *cfg);
271
237 272
238/** 273/**
239 * Function to iterate over options. 274 * Function to iterate over options.
diff --git a/src/json/Makefile.am b/src/json/Makefile.am
index 3c19f96bf..2e97cecb9 100644
--- a/src/json/Makefile.am
+++ b/src/json/Makefile.am
@@ -13,7 +13,9 @@ libgnunetjson_la_LDFLAGS = \
13 $(GN_LIBINTL) \ 13 $(GN_LIBINTL) \
14 -version-info 0:0:0 \ 14 -version-info 0:0:0 \
15 -no-undefined 15 -no-undefined
16libgnunetjson_la_CFLAGS = $(MHD_CFLAGS) $(AM_CFLAGS) 16libgnunetjson_la_CFLAGS = \
17 $(MHD_CFLAGS) \
18 $(AM_CFLAGS)
17libgnunetjson_la_SOURCES = \ 19libgnunetjson_la_SOURCES = \
18 json.c \ 20 json.c \
19 json_generator.c \ 21 json_generator.c \
@@ -26,9 +28,6 @@ libgnunetjson_la_LIBADD = \
26 $(MHD_LIBS) \ 28 $(MHD_LIBS) \
27 $(XLIB) \ 29 $(XLIB) \
28 $(Z_LIBS) 30 $(Z_LIBS)
29libgnunetjson_la_DEPENDENCIES = \
30 $(top_builddir)/src/util/libgnunetutil.la
31
32 31
33check_PROGRAMS = \ 32check_PROGRAMS = \
34 test_json \ 33 test_json \
diff --git a/src/json/json_pack.c b/src/json/json_pack.c
index 20db47cd4..d86baff41 100644
--- a/src/json/json_pack.c
+++ b/src/json/json_pack.c
@@ -109,7 +109,7 @@ GNUNET_JSON_pack_uint64 (const char *name,
109 }; 109 };
110 110
111#if JSON_INTEGER_IS_LONG_LONG 111#if JSON_INTEGER_IS_LONG_LONG
112 GNUNET_assert (num <= LONG_LONG_MAX); 112 GNUNET_assert (num <= LLONG_MAX);
113#else 113#else
114 GNUNET_assert (num <= LONG_MAX); 114 GNUNET_assert (num <= LONG_MAX);
115#endif 115#endif
@@ -127,8 +127,8 @@ GNUNET_JSON_pack_int64 (const char *name,
127 }; 127 };
128 128
129#if JSON_INTEGER_IS_LONG_LONG 129#if JSON_INTEGER_IS_LONG_LONG
130 GNUNET_assert (num <= LONG_LONG_MAX); 130 GNUNET_assert (num <= LLONG_MAX);
131 GNUNET_assert (num >= LONG_LONG_MIN); 131 GNUNET_assert (num >= LLONG_MIN);
132#else 132#else
133 GNUNET_assert (num <= LONG_MAX); 133 GNUNET_assert (num <= LONG_MAX);
134 GNUNET_assert (num >= LONG_MIN); 134 GNUNET_assert (num >= LONG_MIN);
diff --git a/src/nse/Makefile.am b/src/nse/Makefile.am
index 85ae4d3be..824aa10d4 100644
--- a/src/nse/Makefile.am
+++ b/src/nse/Makefile.am
@@ -47,6 +47,7 @@ gnunet_nse_profiler_LDADD = -lm \
47 libgnunetnse.la \ 47 libgnunetnse.la \
48 $(top_builddir)/src/util/libgnunetutil.la \ 48 $(top_builddir)/src/util/libgnunetutil.la \
49 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 49 $(top_builddir)/src/statistics/libgnunetstatistics.la \
50 $(top_builddir)/src/testing/libgnunettesting.la \
50 $(top_builddir)/src/testbed/libgnunettestbed.la \ 51 $(top_builddir)/src/testbed/libgnunettestbed.la \
51 $(GN_LIBINTL) 52 $(GN_LIBINTL)
52 53
diff --git a/src/regex/Makefile.am b/src/regex/Makefile.am
index 13413f242..0b55d134f 100644
--- a/src/regex/Makefile.am
+++ b/src/regex/Makefile.am
@@ -126,6 +126,7 @@ gnunet_regex_profiler_SOURCES = \
126 gnunet-regex-profiler.c 126 gnunet-regex-profiler.c
127gnunet_regex_profiler_LDADD = -lm \ 127gnunet_regex_profiler_LDADD = -lm \
128 $(top_builddir)/src/arm/libgnunetarm.la \ 128 $(top_builddir)/src/arm/libgnunetarm.la \
129 $(top_builddir)/src/testing/libgnunettesting.la \
129 $(top_builddir)/src/testbed/libgnunettestbed.la \ 130 $(top_builddir)/src/testbed/libgnunettestbed.la \
130 libgnunetregex_internal.a \ 131 libgnunetregex_internal.a \
131 $(top_builddir)/src/dht/libgnunetdht.la \ 132 $(top_builddir)/src/dht/libgnunetdht.la \
diff --git a/src/secretsharing/Makefile.am b/src/secretsharing/Makefile.am
index 787cfa0c1..9ae6e7892 100644
--- a/src/secretsharing/Makefile.am
+++ b/src/secretsharing/Makefile.am
@@ -24,6 +24,7 @@ gnunet_secretsharing_profiler_SOURCES = \
24 gnunet-secretsharing-profiler.c 24 gnunet-secretsharing-profiler.c
25gnunet_secretsharing_profiler_LDADD = \ 25gnunet_secretsharing_profiler_LDADD = \
26 libgnunetsecretsharing.la \ 26 libgnunetsecretsharing.la \
27 $(top_builddir)/src/testing/libgnunettesting.la \
27 $(top_builddir)/src/testbed/libgnunettestbed.la \ 28 $(top_builddir)/src/testbed/libgnunettestbed.la \
28 $(top_builddir)/src/util/libgnunetutil.la \ 29 $(top_builddir)/src/util/libgnunetutil.la \
29 $(GN_LIBINTL) 30 $(GN_LIBINTL)
diff --git a/src/testbed/Makefile.am b/src/testbed/Makefile.am
index 347d16007..b4b2cff97 100644
--- a/src/testbed/Makefile.am
+++ b/src/testbed/Makefile.am
@@ -76,6 +76,7 @@ gnunet_service_testbed_LDADD = $(XLIB) \
76gnunet_testbed_profiler_SOURCES = \ 76gnunet_testbed_profiler_SOURCES = \
77 gnunet-testbed-profiler.c 77 gnunet-testbed-profiler.c
78gnunet_testbed_profiler_LDADD = $(XLIB) \ 78gnunet_testbed_profiler_LDADD = $(XLIB) \
79 $(top_builddir)/src/testing/libgnunettesting.la \
79 $(top_builddir)/src/util/libgnunetutil.la \ 80 $(top_builddir)/src/util/libgnunetutil.la \
80 libgnunettestbed.la 81 libgnunettestbed.la
81gnunet_testbed_profiler_LDFLAGS = \ 82gnunet_testbed_profiler_LDFLAGS = \
@@ -169,6 +170,7 @@ libgnunettestbed_la_LDFLAGS = \
169 170
170generate_underlay_topology_SOURCES = generate-underlay-topology.c 171generate_underlay_topology_SOURCES = generate-underlay-topology.c
171generate_underlay_topology_LDADD = $(XLIB) \ 172generate_underlay_topology_LDADD = $(XLIB) \
173 $(top_builddir)/src/testing/libgnunettesting.la \
172 $(top_builddir)/src/util/libgnunetutil.la \ 174 $(top_builddir)/src/util/libgnunetutil.la \
173 libgnunettestbed.la \ 175 libgnunettestbed.la \
174 $(LTLIBINTL) -lsqlite3 176 $(LTLIBINTL) -lsqlite3
diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am
index e19ebd8e9..55a338729 100644
--- a/src/transport/Makefile.am
+++ b/src/transport/Makefile.am
@@ -398,20 +398,20 @@ plugin_LTLIBRARIES = \
398 $(HTTP_SERVER_PLUGIN_LA) \ 398 $(HTTP_SERVER_PLUGIN_LA) \
399 $(HTTPS_SERVER_PLUGIN_LA) \ 399 $(HTTPS_SERVER_PLUGIN_LA) \
400 $(WLAN_PLUGIN_LA) \ 400 $(WLAN_PLUGIN_LA) \
401 $(BT_PLUGIN_LA) \ 401 $(BT_PLUGIN_LA)
402 libgnunet_plugin_cmd_simple_send.la 402# libgnunet_plugin_cmd_simple_send.la
403 403
404libgnunet_plugin_cmd_simple_send_la_SOURCES = \ 404#libgnunet_plugin_cmd_simple_send_la_SOURCES = \
405 plugin_cmd_simple_send.c 405# plugin_cmd_simple_send.c
406libgnunet_plugin_cmd_simple_send_la_LIBADD = \ 406#libgnunet_plugin_cmd_simple_send_la_LIBADD = \
407 $(top_builddir)/src/util/libgnunetutil.la \ 407# $(top_builddir)/src/util/libgnunetutil.la \
408 $(top_builddir)/src/testing/libgnunettesting.la \ 408# $(top_builddir)/src/testing/libgnunettesting.la \
409 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 409# $(top_builddir)/src/statistics/libgnunetstatistics.la \
410 $(top_builddir)/src/testbed/libgnunettestbed.la \ 410# $(top_builddir)/src/testbed/libgnunettestbed.la \
411 libgnunettransporttesting2.la \ 411# libgnunettransporttesting2.la \
412 $(LTLIBINTL) 412# $(LTLIBINTL)
413libgnunet_plugin_cmd_simple_send_la_LDFLAGS = \ 413#libgnunet_plugin_cmd_simple_send_la_LDFLAGS = \
414 $(GN_PLUGIN_LDFLAGS) 414# $(GN_PLUGIN_LDFLAGS)
415 415
416if HAVE_EXPERIMENTAL 416if HAVE_EXPERIMENTAL
417plugin_LTLIBRARIES += libgnunet_plugin_transport_udp.la 417plugin_LTLIBRARIES += libgnunet_plugin_transport_udp.la
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index e720112be..89d040a0c 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -49,7 +49,6 @@ libgnunetutil_la_SOURCES = \
49 common_endian.c \ 49 common_endian.c \
50 common_logging.c \ 50 common_logging.c \
51 configuration.c \ 51 configuration.c \
52 configuration_loader.c \
53 consttime_memcmp.c \ 52 consttime_memcmp.c \
54 container_bloomfilter.c \ 53 container_bloomfilter.c \
55 container_heap.c \ 54 container_heap.c \
@@ -243,11 +242,11 @@ gnunet_qr_LDADD = \
243gnunet_qr_LDFLAGS= -lzbar 242gnunet_qr_LDFLAGS= -lzbar
244 243
245plugin_LTLIBRARIES = \ 244plugin_LTLIBRARIES = \
246 libgnunet_plugin_test.la 245 libgnunet_plugin_utiltest.la
247 246
248libgnunet_plugin_test_la_SOURCES = \ 247libgnunet_plugin_utiltest_la_SOURCES = \
249 test_plugin_plug.c 248 test_plugin_plug.c
250libgnunet_plugin_test_la_LDFLAGS = \ 249libgnunet_plugin_utiltest_la_LDFLAGS = \
251 $(GN_PLUGIN_LDFLAGS) 250 $(GN_PLUGIN_LDFLAGS)
252 251
253if HAVE_BENCHMARKS 252if HAVE_BENCHMARKS
diff --git a/src/util/configuration.c b/src/util/configuration.c
index 06938be67..e515c7c46 100644
--- a/src/util/configuration.c
+++ b/src/util/configuration.c
@@ -28,6 +28,8 @@
28#include "gnunet_os_lib.h" 28#include "gnunet_os_lib.h"
29#include "gnunet_configuration_lib.h" 29#include "gnunet_configuration_lib.h"
30#include "gnunet_disk_lib.h" 30#include "gnunet_disk_lib.h"
31#include "gnunet_buffer_lib.h"
32#include "gnunet_container_lib.h"
31 33
32#define LOG(kind, ...) GNUNET_log_from (kind, "util", __VA_ARGS__) 34#define LOG(kind, ...) GNUNET_log_from (kind, "util", __VA_ARGS__)
33 35
@@ -53,6 +55,16 @@ struct ConfigEntry
53 * current, committed value 55 * current, committed value
54 */ 56 */
55 char *val; 57 char *val;
58
59 /**
60 * Diagnostics information for the filename.
61 */
62 char *hint_filename;
63
64 /**
65 * Diagnostics information for the line number.
66 */
67 unsigned int hint_lineno;
56}; 68};
57 69
58 70
@@ -83,6 +95,54 @@ struct ConfigSection
83 * directive, but the referenced file can't be found or accessed. 95 * directive, but the referenced file can't be found or accessed.
84 */ 96 */
85 bool inaccessible; 97 bool inaccessible;
98
99 /**
100 * Diagnostics hint for the secret file.
101 */
102 char *hint_secret_filename;
103
104 /**
105 * Extra information regarding permissions of the secret file.
106 */
107 char *hint_secret_stat;
108
109 /**
110 * For secret sections: Where was this inlined from?
111 */
112 char *hint_inlined_from_filename;
113
114 /**
115 * For secret sections: Where was this inlined from?
116 */
117 unsigned int hint_inlined_from_line;
118};
119
120struct ConfigFile
121{
122 /**
123 * Source filename.
124 */
125 char *source_filename;
126
127 /**
128 * Level in the tree of loaded config files.
129 */
130 unsigned int level;
131
132 struct ConfigFile *prev;
133
134 struct ConfigFile *next;
135
136 /**
137 * Was this configuration file parsed via
138 * @inline-secret@?
139 */
140 char *hint_restrict_section;
141
142 /**
143 * Was this configuration file inaccessible?
144 */
145 bool hint_inaccessible;
86}; 146};
87 147
88 148
@@ -97,6 +157,26 @@ struct GNUNET_CONFIGURATION_Handle
97 struct ConfigSection *sections; 157 struct ConfigSection *sections;
98 158
99 /** 159 /**
160 * Linked list of loaded files.
161 */
162 struct ConfigFile *loaded_files_head;
163
164 /**
165 * Linked list of loaded files.
166 */
167 struct ConfigFile *loaded_files_tail;
168
169 /**
170 * Current nesting level of file loading.
171 */
172 unsigned int current_nest_level;
173
174 /**
175 * Enable diagnostics.
176 */
177 bool diagnostics;
178
179 /**
100 * Modification indication since last save 180 * Modification indication since last save
101 * #GNUNET_NO if clean, #GNUNET_YES if dirty, 181 * #GNUNET_NO if clean, #GNUNET_YES if dirty,
102 * #GNUNET_SYSERR on error (i.e. last save failed) 182 * #GNUNET_SYSERR on error (i.e. last save failed)
@@ -104,9 +184,21 @@ struct GNUNET_CONFIGURATION_Handle
104 enum GNUNET_GenericReturnValue dirty; 184 enum GNUNET_GenericReturnValue dirty;
105 185
106 /** 186 /**
187 * Was the configuration ever loaded via GNUNET_CONFIGURATION_load?
188 */
189 bool load_called;
190
191 /**
107 * Name of the entry point configuration file. 192 * Name of the entry point configuration file.
108 */ 193 */
109 char *main_filename; 194 char *main_filename;
195
196 /**
197 * When parsing into this configuration, and this value
198 * is non-NULL, only parse sections of the same name,
199 * and ban import statements.
200 */
201 const char *restrict_section;
110}; 202};
111 203
112 204
@@ -122,6 +214,14 @@ struct DiffHandle
122}; 214};
123 215
124 216
217void
218GNUNET_CONFIGURATION_enable_diagnostics (struct
219 GNUNET_CONFIGURATION_Handle *cfg)
220{
221 cfg->diagnostics = true;
222}
223
224
125struct GNUNET_CONFIGURATION_Handle * 225struct GNUNET_CONFIGURATION_Handle *
126GNUNET_CONFIGURATION_create () 226GNUNET_CONFIGURATION_create ()
127{ 227{
@@ -211,9 +311,18 @@ void
211GNUNET_CONFIGURATION_destroy (struct GNUNET_CONFIGURATION_Handle *cfg) 311GNUNET_CONFIGURATION_destroy (struct GNUNET_CONFIGURATION_Handle *cfg)
212{ 312{
213 struct ConfigSection *sec; 313 struct ConfigSection *sec;
314 struct ConfigFile *cf;
214 315
215 while (NULL != (sec = cfg->sections)) 316 while (NULL != (sec = cfg->sections))
216 GNUNET_CONFIGURATION_remove_section (cfg, sec->name); 317 GNUNET_CONFIGURATION_remove_section (cfg, sec->name);
318 while (NULL != (cf = cfg->loaded_files_head))
319 {
320 GNUNET_free (cf->hint_restrict_section);
321 GNUNET_free (cf->source_filename);
322 GNUNET_CONTAINER_DLL_remove (cfg->loaded_files_head,
323 cfg->loaded_files_tail,
324 cf);
325 }
217 GNUNET_free (cfg); 326 GNUNET_free (cfg);
218} 327}
219 328
@@ -240,14 +349,19 @@ GNUNET_CONFIGURATION_parse_and_run (const char *filename,
240 349
241 350
242/** 351/**
243 * Closure to inline_glob_cb. 352 * Closure to collect_files_cb.
244 */ 353 */
245struct InlineGlobClosure 354struct CollectFilesContext
246{ 355{
247 /** 356 /**
248 * Configuration to read inlined configuration into. 357 * Collected files from globbing.
249 */ 358 */
250 struct GNUNET_CONFIGURATION_Handle *cfg; 359 char **files;
360
361 /**
362 * Size of the files array.
363 */
364 unsigned int files_length;
251}; 365};
252 366
253 367
@@ -261,21 +375,14 @@ struct InlineGlobClosure
261 * #GNUNET_SYSERR to abort iteration with error! 375 * #GNUNET_SYSERR to abort iteration with error!
262 */ 376 */
263static int 377static int
264inline_glob_cb (void *cls, 378collect_files_cb (void *cls,
265 const char *filename) 379 const char *filename)
266{ 380{
267 struct InlineGlobClosure *igc = cls; 381 struct CollectFilesContext *igc = cls;
268 382
269 LOG (GNUNET_ERROR_TYPE_DEBUG, 383 GNUNET_array_append (igc->files,
270 "Reading globbed config file '%s'\n", 384 igc->files_length,
271 filename); 385 GNUNET_strdup (filename));
272
273 if (GNUNET_OK !=
274 GNUNET_CONFIGURATION_parse (igc->cfg,
275 filename))
276 {
277 return GNUNET_SYSERR;
278 }
279 return GNUNET_OK; 386 return GNUNET_OK;
280} 387}
281 388
@@ -300,24 +407,10 @@ find_section (const struct GNUNET_CONFIGURATION_Handle *cfg,
300} 407}
301 408
302 409
303static void 410static int
304set_section_inaccessible (struct GNUNET_CONFIGURATION_Handle *cfg, 411pstrcmp (const void *a, const void *b)
305 const char *section)
306{ 412{
307 struct ConfigSection *sec; 413 return strcmp (*((const char **) a), *((const char **) b));
308
309 sec = find_section (cfg, section);
310
311 if (NULL == sec)
312 {
313 sec = GNUNET_new (struct ConfigSection);
314 sec->name = GNUNET_strdup (section);
315 sec->next = cfg->sections;
316 cfg->sections = sec;
317 sec->entries = NULL;
318 }
319
320 sec->inaccessible = true;
321} 414}
322 415
323 416
@@ -331,9 +424,17 @@ handle_inline (struct GNUNET_CONFIGURATION_Handle *cfg,
331 const char *path_or_glob, 424 const char *path_or_glob,
332 bool path_is_glob, 425 bool path_is_glob,
333 const char *restrict_section, 426 const char *restrict_section,
334 const char *source_filename) 427 const char *source_filename,
428 unsigned int source_lineno)
335{ 429{
336 char *inline_path; 430 char *inline_path;
431 struct GNUNET_CONFIGURATION_Handle *other_cfg = NULL;
432 struct CollectFilesContext igc = {
433 .files = NULL,
434 .files_length = 0,
435 };
436 enum GNUNET_GenericReturnValue fun_ret;
437 unsigned int old_nest_level = cfg->current_nest_level++;
337 438
338 /* We support the section restriction only for non-globs */ 439 /* We support the section restriction only for non-globs */
339 GNUNET_assert (! (path_is_glob && (NULL != restrict_section))); 440 GNUNET_assert (! (path_is_glob && (NULL != restrict_section)));
@@ -343,8 +444,10 @@ handle_inline (struct GNUNET_CONFIGURATION_Handle *cfg,
343 LOG (GNUNET_ERROR_TYPE_DEBUG, 444 LOG (GNUNET_ERROR_TYPE_DEBUG,
344 "Refusing to parse inline configurations, " 445 "Refusing to parse inline configurations, "
345 "not allowed without source filename!\n"); 446 "not allowed without source filename!\n");
346 return GNUNET_SYSERR; 447 fun_ret = GNUNET_SYSERR;
448 goto cleanup;
347 } 449 }
450
348 if ('/' == *path_or_glob) 451 if ('/' == *path_or_glob)
349 inline_path = GNUNET_strdup (path_or_glob); 452 inline_path = GNUNET_strdup (path_or_glob);
350 else 453 else
@@ -362,7 +465,8 @@ handle_inline (struct GNUNET_CONFIGURATION_Handle *cfg,
362 /* Couldn't even resolve path of base dir. */ 465 /* Couldn't even resolve path of base dir. */
363 GNUNET_break (0); 466 GNUNET_break (0);
364 /* failed to parse included config */ 467 /* failed to parse included config */
365 return GNUNET_SYSERR; 468 fun_ret = GNUNET_SYSERR;
469 goto cleanup;
366 } 470 }
367 endsep = strrchr (source_realpath, '/'); 471 endsep = strrchr (source_realpath, '/');
368 GNUNET_assert (NULL != endsep); 472 GNUNET_assert (NULL != endsep);
@@ -373,46 +477,113 @@ handle_inline (struct GNUNET_CONFIGURATION_Handle *cfg,
373 path_or_glob); 477 path_or_glob);
374 free (source_realpath); 478 free (source_realpath);
375 } 479 }
480
376 if (path_is_glob) 481 if (path_is_glob)
377 { 482 {
378 int nret; 483 int nret;
379 struct InlineGlobClosure igc = {
380 .cfg = cfg,
381 };
382 484
383 LOG (GNUNET_ERROR_TYPE_DEBUG, 485 LOG (GNUNET_ERROR_TYPE_DEBUG,
384 "processing config glob '%s'\n", 486 "processing config glob '%s'\n",
385 inline_path); 487 inline_path);
386 488
387 nret = GNUNET_DISK_glob (inline_path, inline_glob_cb, &igc); 489 nret = GNUNET_DISK_glob (inline_path, collect_files_cb, &igc);
388 if (-1 == nret) 490 if (-1 == nret)
389 { 491 {
390 GNUNET_free (inline_path); 492 fun_ret = GNUNET_SYSERR;
391 return GNUNET_SYSERR; 493 goto cleanup;
494 }
495 GNUNET_assert (nret == igc.files_length);
496 qsort (igc.files, igc.files_length, sizeof (char *), pstrcmp);
497 for (int i = 0; i < nret; i++)
498 {
499 if (GNUNET_OK !=
500 GNUNET_CONFIGURATION_parse (cfg,
501 igc.files[i]))
502 {
503 fun_ret = GNUNET_SYSERR;
504 goto cleanup;
505 }
392 } 506 }
507 fun_ret = GNUNET_OK;
393 } 508 }
394 else if (NULL != restrict_section) 509 else if (NULL != restrict_section)
395 { 510 {
396 struct GNUNET_CONFIGURATION_Handle *other_cfg; 511 enum GNUNET_GenericReturnValue inner_ret;
397 enum GNUNET_GenericReturnValue fret;
398 struct ConfigSection *cs; 512 struct ConfigSection *cs;
513 struct ConfigFile *cf = GNUNET_new (struct ConfigFile);
399 514
400 fret = GNUNET_DISK_file_test_read (inline_path); 515 inner_ret = GNUNET_DISK_file_test_read (inline_path);
401 516
402 if (GNUNET_OK != fret) 517 cs = find_section (cfg, restrict_section);
518
519 if (NULL == cs)
403 { 520 {
404 set_section_inaccessible (cfg, restrict_section); 521 cs = GNUNET_new (struct ConfigSection);
405 GNUNET_free (inline_path); 522 cs->name = GNUNET_strdup (restrict_section);
406 return GNUNET_OK; 523 cs->next = cfg->sections;
524 cfg->sections = cs;
525 cs->entries = NULL;
526 }
527 if (cfg->diagnostics)
528 {
529 char *sfn = GNUNET_STRINGS_filename_expand (inline_path);
530 struct stat istat;
531
532 cs->hint_secret_filename = sfn;
533 if (0 == stat (sfn, &istat))
534 {
535 struct passwd *pw = getpwuid (istat.st_uid);
536 struct group *gr = getgrgid (istat.st_gid);
537 char *pwname = (NULL == pw) ? "<unknown>" : pw->pw_name;
538 char *grname = (NULL == gr) ? "<unknown>" : gr->gr_name;
539
540 GNUNET_asprintf (&cs->hint_secret_stat,
541 "%s:%s %o",
542 pwname,
543 grname,
544 istat.st_mode);
545 }
546 else
547 {
548 cs->hint_secret_stat = GNUNET_strdup ("<can't stat file>");
549 }
550 if (source_filename)
551 {
552 /* Possible that this secret section has been inlined before */
553 GNUNET_free (cs->hint_inlined_from_filename);
554 cs->hint_inlined_from_filename = GNUNET_strdup (source_filename);
555 cs->hint_inlined_from_line = source_lineno;
556 }
557 }
558
559 /* Put file in the load list for diagnostics, even if we can't access it. */
560 {
561 cf->level = cfg->current_nest_level;
562 cf->source_filename = GNUNET_strdup (inline_path);
563 cf->hint_restrict_section = GNUNET_strdup (restrict_section);
564 GNUNET_CONTAINER_DLL_insert_tail (cfg->loaded_files_head,
565 cfg->loaded_files_tail,
566 cf);
567 }
568
569 if (GNUNET_OK != inner_ret)
570 {
571 cs->inaccessible = true;
572 cf->hint_inaccessible = true;
573 /* File can't be accessed, but that's okay. */
574 fun_ret = GNUNET_OK;
575 goto cleanup;
407 } 576 }
408 577
409 other_cfg = GNUNET_CONFIGURATION_create (); 578 other_cfg = GNUNET_CONFIGURATION_create ();
410 if (GNUNET_OK != GNUNET_CONFIGURATION_parse (other_cfg, 579 other_cfg->restrict_section = restrict_section;
411 inline_path)) 580 inner_ret = GNUNET_CONFIGURATION_parse (other_cfg,
581 inline_path);
582 if (GNUNET_OK != inner_ret)
412 { 583 {
413 GNUNET_free (inline_path); 584 cf->hint_inaccessible = true;
414 GNUNET_CONFIGURATION_destroy (other_cfg); 585 fun_ret = inner_ret;
415 return GNUNET_SYSERR; 586 goto cleanup;
416 } 587 }
417 588
418 cs = find_section (other_cfg, restrict_section); 589 cs = find_section (other_cfg, restrict_section);
@@ -422,9 +593,8 @@ handle_inline (struct GNUNET_CONFIGURATION_Handle *cfg,
422 "inlined configuration '%s' does not contain section '%s'\n", 593 "inlined configuration '%s' does not contain section '%s'\n",
423 inline_path, 594 inline_path,
424 restrict_section); 595 restrict_section);
425 GNUNET_free (inline_path); 596 fun_ret = GNUNET_SYSERR;
426 GNUNET_free (other_cfg); 597 goto cleanup;
427 return GNUNET_SYSERR;
428 } 598 }
429 for (struct ConfigEntry *ce = cs->entries; 599 for (struct ConfigEntry *ce = cs->entries;
430 NULL != ce; 600 NULL != ce;
@@ -433,17 +603,92 @@ handle_inline (struct GNUNET_CONFIGURATION_Handle *cfg,
433 restrict_section, 603 restrict_section,
434 ce->key, 604 ce->key,
435 ce->val); 605 ce->val);
436 GNUNET_CONFIGURATION_destroy (other_cfg); 606 fun_ret = GNUNET_OK;
437 } 607 }
438 else if (GNUNET_OK != 608 else if (GNUNET_OK !=
439 GNUNET_CONFIGURATION_parse (cfg, 609 GNUNET_CONFIGURATION_parse (cfg,
440 inline_path)) 610 inline_path))
441 { 611 {
442 GNUNET_free (inline_path); 612 fun_ret = GNUNET_SYSERR;
443 return GNUNET_SYSERR; 613 goto cleanup;
444 } 614 }
615 else
616 {
617 fun_ret = GNUNET_OK;
618 }
619cleanup:
620 cfg->current_nest_level = old_nest_level;
621 if (NULL != other_cfg)
622 GNUNET_CONFIGURATION_destroy (other_cfg);
445 GNUNET_free (inline_path); 623 GNUNET_free (inline_path);
446 return GNUNET_OK; 624 if (igc.files_length > 0)
625 {
626 for (size_t i = 0; i < igc.files_length; i++)
627 GNUNET_free (igc.files[i]);
628 GNUNET_array_grow (igc.files, igc.files_length, 0);
629 }
630 return fun_ret;
631}
632
633
634/**
635 * Find an entry from a configuration.
636 *
637 * @param cfg handle to the configuration
638 * @param section section the option is in
639 * @param key the option
640 * @return matching entry, NULL if not found
641 */
642static struct ConfigEntry *
643find_entry (const struct GNUNET_CONFIGURATION_Handle *cfg,
644 const char *section,
645 const char *key)
646{
647 struct ConfigSection *sec;
648 struct ConfigEntry *pos;
649
650 if (NULL == (sec = find_section (cfg, section)))
651 return NULL;
652 if (sec->inaccessible)
653 {
654 LOG (GNUNET_ERROR_TYPE_WARNING,
655 "Section '%s' is marked as inaccessible, because the configuration "
656 " file that contains the section can't be read. Attempts to use "
657 "option '%s' will fail.\n",
658 section,
659 key);
660 return NULL;
661 }
662 pos = sec->entries;
663 while ((pos != NULL) && (0 != strcasecmp (key, pos->key)))
664 pos = pos->next;
665 return pos;
666}
667
668
669/**
670 * Set a configuration hint.
671 *
672 * @param cfg configuration handle
673 * @param section section
674 * @param option config option
675 * @param hint_filename
676 * @param hint_line
677 */
678static void
679set_entry_hint (struct GNUNET_CONFIGURATION_Handle *cfg,
680 const char *section,
681 const char *option,
682 const char *hint_filename,
683 unsigned int hint_line)
684{
685 struct ConfigEntry *e = find_entry (cfg, section, option);
686 if (! cfg->diagnostics)
687 return;
688 if (! e)
689 return;
690 e->hint_filename = GNUNET_strdup (hint_filename);
691 e->hint_lineno = hint_line;
447} 692}
448 693
449 694
@@ -530,6 +775,17 @@ GNUNET_CONFIGURATION_deserialize (struct GNUNET_CONFIGURATION_Handle *cfg,
530 char *directive; 775 char *directive;
531 enum GNUNET_GenericReturnValue directive_ret; 776 enum GNUNET_GenericReturnValue directive_ret;
532 777
778 if (NULL != cfg->restrict_section)
779 {
780 LOG (GNUNET_ERROR_TYPE_WARNING,
781 _ (
782 "Illegal directive in line %u (parsing restricted section %s)\n"),
783 nr,
784 cfg->restrict_section);
785 ret = GNUNET_SYSERR;
786 break;
787 }
788
533 if (NULL == end) 789 if (NULL == end)
534 { 790 {
535 LOG (GNUNET_ERROR_TYPE_WARNING, 791 LOG (GNUNET_ERROR_TYPE_WARNING,
@@ -553,7 +809,8 @@ GNUNET_CONFIGURATION_deserialize (struct GNUNET_CONFIGURATION_Handle *cfg,
553 path, 809 path,
554 false, 810 false,
555 NULL, 811 NULL,
556 source_filename); 812 source_filename,
813 nr);
557 } 814 }
558 else if (0 == strcasecmp (directive, "INLINE-MATCHING")) 815 else if (0 == strcasecmp (directive, "INLINE-MATCHING"))
559 { 816 {
@@ -567,7 +824,8 @@ GNUNET_CONFIGURATION_deserialize (struct GNUNET_CONFIGURATION_Handle *cfg,
567 path, 824 path,
568 true, 825 true,
569 NULL, 826 NULL,
570 source_filename); 827 source_filename,
828 nr);
571 } 829 }
572 else if (0 == strcasecmp (directive, "INLINE-SECRET")) 830 else if (0 == strcasecmp (directive, "INLINE-SECRET"))
573 { 831 {
@@ -600,7 +858,8 @@ GNUNET_CONFIGURATION_deserialize (struct GNUNET_CONFIGURATION_Handle *cfg,
600 path, 858 path,
601 false, 859 false,
602 secname, 860 secname,
603 source_filename); 861 source_filename,
862 nr);
604 } 863 }
605 else 864 else
606 { 865 {
@@ -613,11 +872,7 @@ GNUNET_CONFIGURATION_deserialize (struct GNUNET_CONFIGURATION_Handle *cfg,
613 } 872 }
614 if (GNUNET_OK != directive_ret) 873 if (GNUNET_OK != directive_ret)
615 { 874 {
616 LOG (GNUNET_ERROR_TYPE_WARNING, 875 ret = directive_ret;
617 _ ("Bad directive '%s' in line %u\n"),
618 directive,
619 nr);
620 ret = GNUNET_SYSERR;
621 break; 876 break;
622 } 877 }
623 continue; 878 continue;
@@ -660,6 +915,14 @@ GNUNET_CONFIGURATION_deserialize (struct GNUNET_CONFIGURATION_Handle *cfg,
660 value++; 915 value++;
661 } 916 }
662 GNUNET_CONFIGURATION_set_value_string (cfg, section, tag, &value[i]); 917 GNUNET_CONFIGURATION_set_value_string (cfg, section, tag, &value[i]);
918 if (cfg->diagnostics)
919 {
920 set_entry_hint (cfg,
921 section,
922 tag,
923 source_filename ? source_filename : "<input>",
924 nr);
925 }
663 GNUNET_free (tag); 926 GNUNET_free (tag);
664 continue; 927 continue;
665 } 928 }
@@ -694,6 +957,55 @@ GNUNET_CONFIGURATION_parse (struct GNUNET_CONFIGURATION_Handle *cfg,
694 LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to parse config file `%s'\n", fn); 957 LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to parse config file `%s'\n", fn);
695 if (NULL == fn) 958 if (NULL == fn)
696 return GNUNET_SYSERR; 959 return GNUNET_SYSERR;
960
961
962 /* Check for cycles */
963 {
964 unsigned int lvl = cfg->current_nest_level;
965 struct ConfigFile *cf = cfg->loaded_files_tail;
966 struct ConfigFile *parent = NULL;
967
968
969 for (; NULL != cf; parent = cf, cf = cf->prev)
970 {
971 /* Check parents based on level, skipping children of siblings. */
972 if (cf->level >= lvl)
973 continue;
974 lvl = cf->level;
975 if ( (NULL == cf->source_filename) || (NULL == filename))
976 continue;
977 if (0 == strcmp (cf->source_filename, filename))
978 {
979 if (NULL == parent)
980 {
981 LOG (GNUNET_ERROR_TYPE_ERROR,
982 "Forbidden direct cyclic configuration import (%s -> %s)\n",
983 cf->source_filename,
984 filename);
985 }
986 else
987 LOG (GNUNET_ERROR_TYPE_ERROR,
988 "Forbidden indirect cyclic configuration import (%s -> ... -> %s -> %s)\n",
989 cf->source_filename,
990 parent->source_filename,
991 filename);
992 return GNUNET_SYSERR;
993 }
994 }
995
996 }
997
998 /* Keep track of loaded files.*/
999 {
1000 struct ConfigFile *cf = GNUNET_new (struct ConfigFile);
1001
1002 cf->level = cfg->current_nest_level;
1003 cf->source_filename = GNUNET_strdup (filename ? filename : "<input>");
1004 GNUNET_CONTAINER_DLL_insert_tail (cfg->loaded_files_head,
1005 cfg->loaded_files_tail,
1006 cf);
1007 }
1008
697 dirty = cfg->dirty; /* back up value! */ 1009 dirty = cfg->dirty; /* back up value! */
698 if (GNUNET_SYSERR == 1010 if (GNUNET_SYSERR ==
699 GNUNET_DISK_file_size (fn, &fs64, GNUNET_YES, GNUNET_YES)) 1011 GNUNET_DISK_file_size (fn, &fs64, GNUNET_YES, GNUNET_YES))
@@ -725,7 +1037,7 @@ GNUNET_CONFIGURATION_parse (struct GNUNET_CONFIGURATION_Handle *cfg,
725 mem, 1037 mem,
726 fs, 1038 fs,
727 fn); 1039 fn);
728 if (GNUNET_OK != ret) 1040 if (GNUNET_SYSERR == ret)
729 { 1041 {
730 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1042 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
731 _ ("Failed to parse configuration file `%s'\n"), 1043 _ ("Failed to parse configuration file `%s'\n"),
@@ -799,6 +1111,8 @@ GNUNET_CONFIGURATION_serialize (const struct GNUNET_CONFIGURATION_Handle *cfg,
799 NULL != sec; 1111 NULL != sec;
800 sec = sec->next) 1112 sec = sec->next)
801 { 1113 {
1114 if (sec->inaccessible)
1115 continue;
802 /* For each section we need to add 3 characters: {'[',']','\n'} */ 1116 /* For each section we need to add 3 characters: {'[',']','\n'} */
803 m_size += strlen (sec->name) + 3; 1117 m_size += strlen (sec->name) + 3;
804 for (struct ConfigEntry *ent = sec->entries; 1118 for (struct ConfigEntry *ent = sec->entries;
@@ -878,6 +1192,117 @@ GNUNET_CONFIGURATION_serialize (const struct GNUNET_CONFIGURATION_Handle *cfg,
878} 1192}
879 1193
880 1194
1195char *
1196GNUNET_CONFIGURATION_serialize_diagnostics (const struct
1197 GNUNET_CONFIGURATION_Handle *cfg)
1198{
1199 struct GNUNET_Buffer buf = { 0 };
1200
1201 GNUNET_buffer_write_fstr (&buf,
1202 "#\n# Configuration file diagnostics\n#\n");
1203 GNUNET_buffer_write_fstr (&buf,
1204 "# Entry point: %s\n",
1205 cfg->main_filename ? cfg->main_filename :
1206 "<none>");
1207 GNUNET_buffer_write_fstr (&buf,
1208 "#\n# Files Loaded:\n");
1209
1210 for (struct ConfigFile *cfil = cfg->loaded_files_head;
1211 NULL != cfil;
1212 cfil = cfil->next)
1213 {
1214 GNUNET_buffer_write_fstr (&buf,
1215 "# ");
1216 for (unsigned int i = 0; i < cfil->level; i++)
1217 GNUNET_buffer_write_fstr (&buf,
1218 "+");
1219 if (0 != cfil->level)
1220 GNUNET_buffer_write_fstr (&buf,
1221 " ");
1222
1223 GNUNET_buffer_write_fstr (&buf,
1224 "%s",
1225 cfil->source_filename);
1226
1227 if (NULL != cfil->hint_restrict_section)
1228 GNUNET_buffer_write_fstr (&buf,
1229 " (%s secret section %s)",
1230 cfil->hint_inaccessible
1231 ? "inaccessible"
1232 : "loaded",
1233 cfil->hint_restrict_section);
1234
1235 GNUNET_buffer_write_str (&buf,
1236 "\n");
1237 }
1238
1239 GNUNET_buffer_write_fstr (&buf,
1240 "#\n\n");
1241
1242 for (struct ConfigSection *sec = cfg->sections;
1243 NULL != sec;
1244 sec = sec->next)
1245 {
1246 if (sec->hint_secret_filename)
1247 GNUNET_buffer_write_fstr (&buf,
1248 "# secret section from %s\n# secret file stat %s\n",
1249 sec->hint_secret_filename,
1250 sec->hint_secret_stat);
1251 if (sec->hint_inlined_from_filename)
1252 {
1253 GNUNET_buffer_write_fstr (&buf,
1254 "# inlined from %s:%u\n",
1255 sec->hint_inlined_from_filename,
1256 sec->hint_inlined_from_line);
1257 }
1258 GNUNET_buffer_write_fstr (&buf,
1259 "[%s]\n\n",
1260 sec->name);
1261 if (sec->inaccessible)
1262 {
1263 GNUNET_buffer_write_fstr (&buf,
1264 "# <section contents inaccessible>\n\n\n");
1265 continue;
1266 }
1267 for (struct ConfigEntry *ent = sec->entries;
1268 NULL != ent;
1269 ent = ent->next)
1270 {
1271 if (do_skip (sec->name,
1272 ent->key))
1273 continue;
1274 if (NULL != ent->val)
1275 {
1276 char *pos;
1277 char *val = GNUNET_malloc (strlen (ent->val) * 2 + 1);
1278 strcpy (val, ent->val);
1279 while (NULL != (pos = strstr (val, "\n")))
1280 {
1281 memmove (&pos[2], &pos[1], strlen (&pos[1]));
1282 pos[0] = '\\';
1283 pos[1] = 'n';
1284 }
1285 if (NULL != ent->hint_filename)
1286 {
1287 GNUNET_buffer_write_fstr (&buf,
1288 "# %s:%u\n",
1289 ent->hint_filename,
1290 ent->hint_lineno);
1291 }
1292 GNUNET_buffer_write_fstr (&buf,
1293 "%s = %s\n",
1294 ent->key,
1295 val);
1296 GNUNET_free (val);
1297 }
1298 GNUNET_buffer_write_str (&buf, "\n");
1299 }
1300 GNUNET_buffer_write_str (&buf, "\n");
1301 }
1302 return GNUNET_buffer_reap_str (&buf);
1303}
1304
1305
881enum GNUNET_GenericReturnValue 1306enum GNUNET_GenericReturnValue
882GNUNET_CONFIGURATION_write (struct GNUNET_CONFIGURATION_Handle *cfg, 1307GNUNET_CONFIGURATION_write (struct GNUNET_CONFIGURATION_Handle *cfg,
883 const char *filename) 1308 const char *filename)
@@ -1028,10 +1453,14 @@ GNUNET_CONFIGURATION_remove_section (struct GNUNET_CONFIGURATION_Handle *cfg,
1028 spos->entries = ent->next; 1453 spos->entries = ent->next;
1029 GNUNET_free (ent->key); 1454 GNUNET_free (ent->key);
1030 GNUNET_free (ent->val); 1455 GNUNET_free (ent->val);
1456 GNUNET_free (ent->hint_filename);
1031 GNUNET_free (ent); 1457 GNUNET_free (ent);
1032 cfg->dirty = GNUNET_YES; 1458 cfg->dirty = GNUNET_YES;
1033 } 1459 }
1034 GNUNET_free (spos->name); 1460 GNUNET_free (spos->name);
1461 GNUNET_free (spos->hint_secret_filename);
1462 GNUNET_free (spos->hint_secret_stat);
1463 GNUNET_free (spos->hint_inlined_from_filename);
1035 GNUNET_free (spos); 1464 GNUNET_free (spos);
1036 return; 1465 return;
1037 } 1466 }
@@ -1074,41 +1503,6 @@ GNUNET_CONFIGURATION_dup (const struct GNUNET_CONFIGURATION_Handle *cfg)
1074 1503
1075 1504
1076/** 1505/**
1077 * Find an entry from a configuration.
1078 *
1079 * @param cfg handle to the configuration
1080 * @param section section the option is in
1081 * @param key the option
1082 * @return matching entry, NULL if not found
1083 */
1084static struct ConfigEntry *
1085find_entry (const struct GNUNET_CONFIGURATION_Handle *cfg,
1086 const char *section,
1087 const char *key)
1088{
1089 struct ConfigSection *sec;
1090 struct ConfigEntry *pos;
1091
1092 if (NULL == (sec = find_section (cfg, section)))
1093 return NULL;
1094 if (sec->inaccessible)
1095 {
1096 LOG (GNUNET_ERROR_TYPE_WARNING,
1097 "Section '%s' is marked as inaccessible, because the configuration "
1098 " file that contains the section can't be read. Attempts to use "
1099 "option '%s' will fail.\n",
1100 section,
1101 key);
1102 return NULL;
1103 }
1104 pos = sec->entries;
1105 while ((pos != NULL) && (0 != strcasecmp (key, pos->key)))
1106 pos = pos->next;
1107 return pos;
1108}
1109
1110
1111/**
1112 * A callback function, compares entries from two configurations 1506 * A callback function, compares entries from two configurations
1113 * (default against a new configuration) and write the diffs in a 1507 * (default against a new configuration) and write the diffs in a
1114 * diff-configuration object (the callback object). 1508 * diff-configuration object (the callback object).
@@ -1871,41 +2265,104 @@ GNUNET_CONFIGURATION_remove_value_filename (
1871} 2265}
1872 2266
1873 2267
1874/** 2268enum GNUNET_GenericReturnValue
1875 * Wrapper around #GNUNET_CONFIGURATION_parse. Called on each 2269GNUNET_CONFIGURATION_load_from (struct GNUNET_CONFIGURATION_Handle *cfg,
1876 * file in a directory, we trigger parsing on those files that 2270 const char *defaults_d)
1877 * end with ".conf".
1878 *
1879 * @param cls the cfg
1880 * @param filename file to parse
1881 * @return #GNUNET_OK on success
1882 */
1883static enum GNUNET_GenericReturnValue
1884parse_configuration_file (void *cls, const char *filename)
1885{ 2271{
1886 struct GNUNET_CONFIGURATION_Handle *cfg = cls; 2272 struct CollectFilesContext files_context = {
1887 char *ext; 2273 .files = NULL,
2274 .files_length = 0,
2275 };
2276 enum GNUNET_GenericReturnValue fun_ret;
1888 2277
1889 /* Examine file extension */ 2278 if (GNUNET_SYSERR ==
1890 ext = strrchr (filename, '.'); 2279 GNUNET_DISK_directory_scan (defaults_d, &collect_files_cb,
1891 if ((NULL == ext) || (0 != strcmp (ext, ".conf"))) 2280 &files_context))
2281 return GNUNET_SYSERR; /* no configuration at all found */
2282 qsort (files_context.files,
2283 files_context.files_length,
2284 sizeof (char *),
2285 pstrcmp);
2286 for (unsigned int i = 0; i < files_context.files_length; i++)
1892 { 2287 {
1893 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Skipping file `%s'\n", filename); 2288 char *ext;
1894 return GNUNET_OK; 2289 const char *filename = files_context.files[i];
1895 }
1896 2290
1897 return GNUNET_CONFIGURATION_parse (cfg, filename); 2291 /* Examine file extension */
2292 ext = strrchr (filename, '.');
2293 if ((NULL == ext) || (0 != strcmp (ext, ".conf")))
2294 {
2295 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Skipping file `%s'\n", filename);
2296 fun_ret = GNUNET_OK;
2297 goto cleanup;
2298 }
2299 fun_ret = GNUNET_CONFIGURATION_parse (cfg, filename);
2300 if (fun_ret != GNUNET_OK)
2301 break;
2302 }
2303cleanup:
2304 if (files_context.files_length > 0)
2305 {
2306 for (size_t i = 0; i < files_context.files_length; i++)
2307 GNUNET_free (files_context.files[i]);
2308 GNUNET_array_grow (files_context.files,
2309 files_context.files_length,
2310 0);
2311 }
2312 return fun_ret;
1898} 2313}
1899 2314
1900 2315
1901enum GNUNET_GenericReturnValue 2316char *
1902GNUNET_CONFIGURATION_load_from (struct GNUNET_CONFIGURATION_Handle *cfg, 2317GNUNET_CONFIGURATION_default_filename (void)
1903 const char *defaults_d)
1904{ 2318{
1905 if (GNUNET_SYSERR == 2319 char *cfg_fn;
1906 GNUNET_DISK_directory_scan (defaults_d, &parse_configuration_file, cfg)) 2320 const struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get ();
1907 return GNUNET_SYSERR; /* no configuration at all found */ 2321 const char *xdg = getenv ("XDG_CONFIG_HOME");
1908 return GNUNET_OK; 2322
2323 if (NULL != xdg)
2324 GNUNET_asprintf (&cfg_fn,
2325 "%s%s%s",
2326 xdg,
2327 DIR_SEPARATOR_STR,
2328 pd->config_file);
2329 else
2330 cfg_fn = GNUNET_strdup (pd->user_config_file);
2331
2332 if (GNUNET_OK == GNUNET_DISK_file_test_read (cfg_fn))
2333 return cfg_fn;
2334
2335 GNUNET_free (cfg_fn);
2336
2337 /* Fall back to /etc/ for the default configuration.
2338 Should be okay to use forward slashes here. */
2339
2340 GNUNET_asprintf (&cfg_fn,
2341 "/etc/%s",
2342 pd->config_file);
2343
2344 if (GNUNET_OK == GNUNET_DISK_file_test_read (cfg_fn))
2345 return cfg_fn;
2346
2347 GNUNET_free (cfg_fn);
2348
2349 GNUNET_asprintf (&cfg_fn,
2350 "/etc/%s",
2351 pd->config_file);
2352
2353 if (GNUNET_OK == GNUNET_DISK_file_test_read (cfg_fn))
2354 return cfg_fn;
2355
2356 GNUNET_asprintf (&cfg_fn,
2357 "/etc/%s/%s",
2358 pd->project_dirname,
2359 pd->config_file);
2360
2361 if (GNUNET_OK == GNUNET_DISK_file_test_read (cfg_fn))
2362 return cfg_fn;
2363
2364 GNUNET_free (cfg_fn);
2365 return NULL;
1909} 2366}
1910 2367
1911 2368
@@ -1939,7 +2396,9 @@ GNUNET_CONFIGURATION_default (void)
1939 if (GNUNET_OK != GNUNET_DISK_file_test (cfgname)) 2396 if (GNUNET_OK != GNUNET_DISK_file_test (cfgname))
1940 { 2397 {
1941 GNUNET_free (cfgname); 2398 GNUNET_free (cfgname);
1942 GNUNET_asprintf (&cfgname, "/etc/%s/%s", pd->project_dirname, 2399 GNUNET_asprintf (&cfgname,
2400 "/etc/%s/%s",
2401 pd->project_dirname,
1943 pd->config_file); 2402 pd->config_file);
1944 } 2403 }
1945 if (GNUNET_OK != GNUNET_DISK_file_test (cfgname)) 2404 if (GNUNET_OK != GNUNET_DISK_file_test (cfgname))
@@ -1971,4 +2430,81 @@ GNUNET_CONFIGURATION_default (void)
1971} 2430}
1972 2431
1973 2432
2433/**
2434 * Load configuration (starts with defaults, then loads
2435 * system-specific configuration).
2436 *
2437 * @param cfg configuration to update
2438 * @param filename name of the configuration file, NULL to load defaults
2439 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
2440 */
2441int
2442GNUNET_CONFIGURATION_load (struct GNUNET_CONFIGURATION_Handle *cfg,
2443 const char *filename)
2444{
2445 char *baseconfig;
2446 const char *base_config_varname;
2447
2448 if (cfg->load_called)
2449 {
2450 /* FIXME: Make this a GNUNET_assert later */
2451 GNUNET_break (0);
2452 GNUNET_free (cfg->main_filename);
2453 }
2454 cfg->load_called = true;
2455 if (NULL != filename)
2456 cfg->main_filename = GNUNET_strdup (filename);
2457
2458 base_config_varname = GNUNET_OS_project_data_get ()->base_config_varname;
2459
2460 if ((NULL != base_config_varname)
2461 && (NULL != (baseconfig = getenv (base_config_varname))))
2462 {
2463 baseconfig = GNUNET_strdup (baseconfig);
2464 }
2465 else
2466 {
2467 char *ipath;
2468
2469 ipath = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR);
2470 if (NULL == ipath)
2471 {
2472 GNUNET_break (0);
2473 return GNUNET_SYSERR;
2474 }
2475 GNUNET_asprintf (&baseconfig, "%s%s", ipath, "config.d");
2476 GNUNET_free (ipath);
2477 }
2478
2479 char *dname = GNUNET_STRINGS_filename_expand (baseconfig);
2480 GNUNET_free (baseconfig);
2481
2482 if ((GNUNET_YES == GNUNET_DISK_directory_test (dname, GNUNET_YES)) &&
2483 (GNUNET_SYSERR == GNUNET_CONFIGURATION_load_from (cfg, dname)))
2484 {
2485 LOG (GNUNET_ERROR_TYPE_WARNING,
2486 "Failed to load base configuration from '%s'\n",
2487 filename);
2488 GNUNET_free (dname);
2489 return GNUNET_SYSERR; /* no configuration at all found */
2490 }
2491 GNUNET_free (dname);
2492 if ((NULL != filename) &&
2493 (GNUNET_OK != GNUNET_CONFIGURATION_parse (cfg, filename)))
2494 {
2495 /* specified configuration not found */
2496 LOG (GNUNET_ERROR_TYPE_WARNING,
2497 "Failed to load configuration from file '%s'\n",
2498 filename);
2499 return GNUNET_SYSERR;
2500 }
2501 if (((GNUNET_YES !=
2502 GNUNET_CONFIGURATION_have_value (cfg, "PATHS", "DEFAULTCONFIG"))) &&
2503 (filename != NULL))
2504 GNUNET_CONFIGURATION_set_value_string (cfg, "PATHS", "DEFAULTCONFIG",
2505 filename);
2506 return GNUNET_OK;
2507}
2508
2509
1974/* end of configuration.c */ 2510/* end of configuration.c */
diff --git a/src/util/configuration_loader.c b/src/util/configuration_loader.c
deleted file mode 100644
index a59477b25..000000000
--- a/src/util/configuration_loader.c
+++ /dev/null
@@ -1,91 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2006, 2007, 2008, 2009, 2013 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 src/util/configuration_loader.c
23 * @brief configuration loading
24 * @author Christian Grothoff
25 */
26
27#include "platform.h"
28#include "gnunet_util_lib.h"
29
30#define LOG(kind, ...) GNUNET_log_from (kind, "util-configuration", __VA_ARGS__)
31
32
33/**
34 * Load configuration (starts with defaults, then loads
35 * system-specific configuration).
36 *
37 * @param cfg configuration to update
38 * @param filename name of the configuration file, NULL to load defaults
39 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
40 */
41int
42GNUNET_CONFIGURATION_load (struct GNUNET_CONFIGURATION_Handle *cfg,
43 const char *filename)
44{
45 char *baseconfig;
46 const char *base_config_varname;
47
48 base_config_varname = GNUNET_OS_project_data_get ()->base_config_varname;
49
50 if (NULL != base_config_varname
51 && NULL != (baseconfig = getenv (base_config_varname)))
52 {
53 baseconfig = GNUNET_strdup (baseconfig);
54 }
55 else
56 {
57 char *ipath;
58
59 ipath = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR);
60 if (NULL == ipath)
61 return GNUNET_SYSERR;
62 GNUNET_asprintf (&baseconfig, "%s%s", ipath, "config.d");
63 GNUNET_free (ipath);
64 }
65
66 char *dname = GNUNET_STRINGS_filename_expand (baseconfig);
67 GNUNET_free (baseconfig);
68
69 if (GNUNET_YES == GNUNET_DISK_directory_test (dname, GNUNET_YES) &&
70 GNUNET_SYSERR == GNUNET_CONFIGURATION_load_from (cfg, dname))
71 {
72 GNUNET_free (dname);
73 return GNUNET_SYSERR; /* no configuration at all found */
74 }
75 GNUNET_free (dname);
76 if ((NULL != filename) &&
77 (GNUNET_OK != GNUNET_CONFIGURATION_parse (cfg, filename)))
78 {
79 /* specified configuration not found */
80 return GNUNET_SYSERR;
81 }
82 if (((GNUNET_YES !=
83 GNUNET_CONFIGURATION_have_value (cfg, "PATHS", "DEFAULTCONFIG"))) &&
84 (filename != NULL))
85 GNUNET_CONFIGURATION_set_value_string (cfg, "PATHS", "DEFAULTCONFIG",
86 filename);
87 return GNUNET_OK;
88}
89
90
91/* end of configuration_loader.c */
diff --git a/src/util/disk.c b/src/util/disk.c
index f68b32db5..ada35249f 100644
--- a/src/util/disk.c
+++ b/src/util/disk.c
@@ -434,7 +434,7 @@ GNUNET_DISK_directory_test (const char *fil, int is_readable)
434 434
435/** 435/**
436 * Check if fil can be accessed using amode. 436 * Check if fil can be accessed using amode.
437 * 437 *
438 * @param fil file to check for 438 * @param fil file to check for
439 * @param amode access mode 439 * @param amode access mode
440 * @returns GNUnet error code 440 * @returns GNUnet error code
@@ -455,7 +455,7 @@ file_test_internal (const char *fil, int amode)
455 { 455 {
456 if (errno != ENOENT) 456 if (errno != ENOENT)
457 { 457 {
458 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "stat", rdir); 458 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_DEBUG, "stat", rdir);
459 GNUNET_free (rdir); 459 GNUNET_free (rdir);
460 return GNUNET_SYSERR; 460 return GNUNET_SYSERR;
461 } 461 }
@@ -469,7 +469,7 @@ file_test_internal (const char *fil, int amode)
469 } 469 }
470 if (access (rdir, amode) < 0) 470 if (access (rdir, amode) < 0)
471 { 471 {
472 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "access", rdir); 472 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_DEBUG, "access", rdir);
473 GNUNET_free (rdir); 473 GNUNET_free (rdir);
474 return GNUNET_SYSERR; 474 return GNUNET_SYSERR;
475 } 475 }
@@ -956,6 +956,11 @@ struct GlobClosure
956 const char *glob; 956 const char *glob;
957 GNUNET_FileNameCallback cb; 957 GNUNET_FileNameCallback cb;
958 void *cls; 958 void *cls;
959
960 /**
961 * Number of files that actually matched the glob pattern.
962 */
963 int nres;
959}; 964};
960 965
961/** 966/**
@@ -984,10 +989,15 @@ glob_cb (void *cls,
984 989
985 if (glob_match (gc->glob, fn)) 990 if (glob_match (gc->glob, fn))
986 { 991 {
992 enum GNUNET_GenericReturnValue cbret;
993
987 LOG (GNUNET_ERROR_TYPE_DEBUG, 994 LOG (GNUNET_ERROR_TYPE_DEBUG,
988 "found glob match '%s'\n", 995 "found glob match '%s'\n",
989 filename); 996 filename);
990 gc->cb (gc->cls, filename); 997 gc->nres++;
998 cbret = gc->cb (gc->cls, filename);
999 if (GNUNET_OK != cbret)
1000 return cbret;
991 } 1001 }
992 return GNUNET_OK; 1002 return GNUNET_OK;
993} 1003}
@@ -1002,6 +1012,17 @@ GNUNET_DISK_glob (const char *glob_pattern,
1002 char *sep; 1012 char *sep;
1003 int ret; 1013 int ret;
1004 1014
1015 if ( (NULL != strrchr (glob_pattern, '+')) ||
1016 (NULL != strrchr (glob_pattern, '[')) ||
1017 (NULL != strrchr (glob_pattern, '+')) ||
1018 (NULL != strrchr (glob_pattern, '~')) )
1019 {
1020 LOG (GNUNET_ERROR_TYPE_ERROR,
1021 "unsupported glob pattern: '%s'\n",
1022 glob_pattern);
1023 return -1;
1024 }
1025
1005 sep = strrchr (mypat, DIR_SEPARATOR); 1026 sep = strrchr (mypat, DIR_SEPARATOR);
1006 if (NULL == sep) 1027 if (NULL == sep)
1007 { 1028 {
@@ -1025,6 +1046,7 @@ GNUNET_DISK_glob (const char *glob_pattern,
1025 .glob = sep + 1, 1046 .glob = sep + 1,
1026 .cb = callback, 1047 .cb = callback,
1027 .cls = callback_cls, 1048 .cls = callback_cls,
1049 .nres = 0,
1028 }; 1050 };
1029 LOG (GNUNET_ERROR_TYPE_DEBUG, 1051 LOG (GNUNET_ERROR_TYPE_DEBUG,
1030 "scanning directory '%s' for glob matches on '%s'\n", 1052 "scanning directory '%s' for glob matches on '%s'\n",
@@ -1034,9 +1056,9 @@ GNUNET_DISK_glob (const char *glob_pattern,
1034 glob_cb, 1056 glob_cb,
1035 &gc 1057 &gc
1036 ); 1058 );
1059 GNUNET_free (mypat);
1060 return (ret < 0) ? ret : gc.nres;
1037 } 1061 }
1038 GNUNET_free (mypat);
1039 return ret;
1040} 1062}
1041 1063
1042 1064
diff --git a/src/util/gnunet-config.c b/src/util/gnunet-config.c
index 3932ff1bf..807df0d74 100644
--- a/src/util/gnunet-config.c
+++ b/src/util/gnunet-config.c
@@ -70,6 +70,12 @@ static int global_ret;
70static int rewrite; 70static int rewrite;
71 71
72/** 72/**
73 * Should we give extra diagnostics?
74 */
75static int diagnostics;
76
77
78/**
73 * Should the generated configuration file contain the whole configuration? 79 * Should the generated configuration file contain the whole configuration?
74 */ 80 */
75static int full; 81static int full;
@@ -162,6 +168,17 @@ run (void *cls,
162 GNUNET_free (name); 168 GNUNET_free (name);
163 return; 169 return;
164 } 170 }
171
172 if (diagnostics)
173 {
174 struct GNUNET_CONFIGURATION_Handle *ncfg;
175 /* Re-parse the configuration with diagnostics enabled. */
176 ncfg = GNUNET_CONFIGURATION_create ();
177 GNUNET_CONFIGURATION_enable_diagnostics (ncfg);
178 GNUNET_CONFIGURATION_load (ncfg, cfgfile);
179 cfg = ncfg;
180 }
181
165 if (full) 182 if (full)
166 rewrite = GNUNET_YES; 183 rewrite = GNUNET_YES;
167 if (list_sections) 184 if (list_sections)
@@ -176,16 +193,26 @@ run (void *cls,
176 if ( (! rewrite) && 193 if ( (! rewrite) &&
177 (NULL == section) ) 194 (NULL == section) )
178 { 195 {
179 fprintf (stderr, 196 char *serialization;
180 _ ("%s or %s argument is required\n"),
181 "--section",
182 "--list-sections");
183 global_ret = 1;
184 return;
185 }
186 197
187 if ( (NULL != section) && 198 if (! diagnostics)
188 (NULL == value) ) 199 {
200 fprintf (stderr,
201 _ ("%s, %s or %s argument is required\n"),
202 "--section",
203 "--list-sections",
204 "--diagnostics");
205 global_ret = 1;
206 return;
207 }
208 serialization = GNUNET_CONFIGURATION_serialize_diagnostics (cfg);
209 fprintf (stdout,
210 "%s",
211 serialization);
212 GNUNET_free (serialization);
213 }
214 else if ( (NULL != section) &&
215 (NULL == value) )
189 { 216 {
190 if (NULL == option) 217 if (NULL == option)
191 { 218 {
@@ -348,6 +375,12 @@ main (int argc, char *const *argv)
348 gettext_noop ( 375 gettext_noop (
349 "rewrite the configuration file, even if nothing changed"), 376 "rewrite the configuration file, even if nothing changed"),
350 &rewrite), 377 &rewrite),
378 GNUNET_GETOPT_option_flag (
379 'd',
380 "diagnostics",
381 gettext_noop (
382 "output extra diagnostics"),
383 &diagnostics),
351 GNUNET_GETOPT_option_flag ('S', 384 GNUNET_GETOPT_option_flag ('S',
352 "list-sections", 385 "list-sections",
353 gettext_noop ( 386 gettext_noop (
diff --git a/src/util/plugin.c b/src/util/plugin.c
index feb661f24..39874a588 100644
--- a/src/util/plugin.c
+++ b/src/util/plugin.c
@@ -447,8 +447,12 @@ GNUNET_PLUGIN_load_all_in_context (const struct GNUNET_OS_ProjectData *ctx,
447 void *cb_cls) 447 void *cb_cls)
448{ 448{
449 const struct GNUNET_OS_ProjectData *cpd = GNUNET_OS_project_data_get (); 449 const struct GNUNET_OS_ProjectData *cpd = GNUNET_OS_project_data_get ();
450
450 GNUNET_OS_init (ctx); 451 GNUNET_OS_init (ctx);
451 GNUNET_PLUGIN_load_all (basename, arg, cb, cb_cls); 452 GNUNET_PLUGIN_load_all (basename,
453 arg,
454 cb,
455 cb_cls);
452 GNUNET_OS_init (cpd); 456 GNUNET_OS_init (cpd);
453} 457}
454 458
diff --git a/src/util/program.c b/src/util/program.c
index e34b37370..a79e07d19 100644
--- a/src/util/program.c
+++ b/src/util/program.c
@@ -140,7 +140,6 @@ GNUNET_PROGRAM_run2 (int argc,
140 char *loglev; 140 char *loglev;
141 char *logfile; 141 char *logfile;
142 char *cfg_fn; 142 char *cfg_fn;
143 const char *xdg;
144 enum GNUNET_GenericReturnValue ret; 143 enum GNUNET_GenericReturnValue ret;
145 int iret; 144 int iret;
146 unsigned int cnt; 145 unsigned int cnt;
@@ -149,12 +148,13 @@ GNUNET_PROGRAM_run2 (int argc,
149 long long clock_offset; 148 long long clock_offset;
150 struct GNUNET_CONFIGURATION_Handle *cfg; 149 struct GNUNET_CONFIGURATION_Handle *cfg;
151 const struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get (); 150 const struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get ();
152 struct GNUNET_GETOPT_CommandLineOption defoptions[] = 151 struct GNUNET_GETOPT_CommandLineOption defoptions[] = {
153 { GNUNET_GETOPT_option_cfgfile (&cc.cfgfile), 152 GNUNET_GETOPT_option_cfgfile (&cc.cfgfile),
154 GNUNET_GETOPT_option_help (binaryHelp), 153 GNUNET_GETOPT_option_help (binaryHelp),
155 GNUNET_GETOPT_option_loglevel (&loglev), 154 GNUNET_GETOPT_option_loglevel (&loglev),
156 GNUNET_GETOPT_option_logfile (&logfile), 155 GNUNET_GETOPT_option_logfile (&logfile),
157 GNUNET_GETOPT_option_version (pd->version) }; 156 GNUNET_GETOPT_option_version (pd->version)
157 };
158 struct GNUNET_GETOPT_CommandLineOption *allopts; 158 struct GNUNET_GETOPT_CommandLineOption *allopts;
159 const char *gargs; 159 const char *gargs;
160 char *lpfx; 160 char *lpfx;
@@ -219,17 +219,7 @@ GNUNET_PROGRAM_run2 (int argc,
219 &cmd_sorter); 219 &cmd_sorter);
220 loglev = NULL; 220 loglev = NULL;
221 if ((NULL != pd->config_file) && (NULL != pd->user_config_file)) 221 if ((NULL != pd->config_file) && (NULL != pd->user_config_file))
222 { 222 cfg_fn = GNUNET_CONFIGURATION_default_filename ();
223 xdg = getenv ("XDG_CONFIG_HOME");
224 if (NULL != xdg)
225 GNUNET_asprintf (&cfg_fn,
226 "%s%s%s",
227 xdg,
228 DIR_SEPARATOR_STR,
229 pd->config_file);
230 else
231 cfg_fn = GNUNET_strdup (pd->user_config_file);
232 }
233 else 223 else
234 cfg_fn = NULL; 224 cfg_fn = NULL;
235 lpfx = GNUNET_strdup (binaryName); 225 lpfx = GNUNET_strdup (binaryName);
@@ -251,6 +241,9 @@ GNUNET_PROGRAM_run2 (int argc,
251 } 241 }
252 if (NULL != cc.cfgfile) 242 if (NULL != cc.cfgfile)
253 { 243 {
244 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
245 "Loading configuration from entry point specified as option (%s)\n",
246 cc.cfgfile);
254 if ((GNUNET_YES != GNUNET_DISK_file_test (cc.cfgfile)) || 247 if ((GNUNET_YES != GNUNET_DISK_file_test (cc.cfgfile)) ||
255 (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, cc.cfgfile))) 248 (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, cc.cfgfile)))
256 { 249 {
@@ -266,6 +259,9 @@ GNUNET_PROGRAM_run2 (int argc,
266 } 259 }
267 else 260 else
268 { 261 {
262 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
263 "Loading configuration default entry point (%s)\n",
264 cc.cfgfile);
269 if ((NULL != cfg_fn) && (GNUNET_YES == GNUNET_DISK_file_test (cfg_fn))) 265 if ((NULL != cfg_fn) && (GNUNET_YES == GNUNET_DISK_file_test (cfg_fn)))
270 { 266 {
271 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, cfg_fn)) 267 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, cfg_fn))
@@ -283,8 +279,9 @@ GNUNET_PROGRAM_run2 (int argc,
283 } 279 }
284 else if (NULL != cfg_fn) 280 else if (NULL != cfg_fn)
285 { 281 {
282 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
283 "Loading configuration without entry point\n");
286 GNUNET_free (cfg_fn); 284 GNUNET_free (cfg_fn);
287 cfg_fn = NULL;
288 if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, NULL)) 285 if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, NULL))
289 { 286 {
290 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 287 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -349,7 +346,7 @@ GNUNET_PROGRAM_run2 (int argc,
349 cc.task (cc.task_cls, cc.args, cc.cfgfile, cc.cfg); 346 cc.task (cc.task_cls, cc.args, cc.cfgfile, cc.cfg);
350 } 347 }
351 ret = GNUNET_OK; 348 ret = GNUNET_OK;
352cleanup: 349 cleanup:
353 GNUNET_CONFIGURATION_destroy (cfg); 350 GNUNET_CONFIGURATION_destroy (cfg);
354 GNUNET_free (cc.cfgfile); 351 GNUNET_free (cc.cfgfile);
355 GNUNET_free (cfg_fn); 352 GNUNET_free (cfg_fn);
diff --git a/src/util/test_plugin.c b/src/util/test_plugin.c
index c0eb717d6..e739d17c9 100644
--- a/src/util/test_plugin.c
+++ b/src/util/test_plugin.c
@@ -26,15 +26,22 @@
26 26
27 27
28static void 28static void
29test_cb (void *cls, const char *libname, void *lib_ret) 29test_cb (void *cls,
30 const char *libname,
31 void *lib_ret)
30{ 32{
31 void *ret; 33 const char *test_cls = cls;
34 char *ret;
32 35
33 GNUNET_assert (0 == strcmp (cls, "test")); 36 GNUNET_assert (0 == strcmp (test_cls,
34 GNUNET_assert (0 == strcmp (lib_ret, "Hello")); 37 "test-closure"));
35 ret = GNUNET_PLUGIN_unload (libname, "out"); 38 GNUNET_assert (0 == strcmp (lib_ret,
39 "Hello"));
40 ret = GNUNET_PLUGIN_unload (libname,
41 "out");
36 GNUNET_assert (NULL != ret); 42 GNUNET_assert (NULL != ret);
37 GNUNET_assert (0 == strcmp (ret, "World")); 43 GNUNET_assert (0 == strcmp (ret,
44 "World"));
38 free (ret); 45 free (ret);
39} 46}
40 47
@@ -44,24 +51,35 @@ main (int argc, char *argv[])
44{ 51{
45 void *ret; 52 void *ret;
46 53
47 GNUNET_log_setup ("test-plugin", "WARNING", NULL); 54 GNUNET_log_setup ("test-plugin",
48 GNUNET_log_skip (1, GNUNET_NO); 55 "WARNING",
49 ret = GNUNET_PLUGIN_load ("libgnunet_plugin_missing", NULL); 56 NULL);
57 GNUNET_log_skip (1,
58 GNUNET_NO);
59 ret = GNUNET_PLUGIN_load ("libgnunet_plugin_missing",
60 NULL);
50 GNUNET_log_skip (0, GNUNET_NO); 61 GNUNET_log_skip (0, GNUNET_NO);
51 if (ret != NULL) 62 if (NULL != ret)
52 return 1; 63 return 1;
53 ret = GNUNET_PLUGIN_load ("libgnunet_plugin_test", "in"); 64 ret = GNUNET_PLUGIN_load ("libgnunet_plugin_utiltest",
54 if (ret == NULL) 65 "in");
66 if (NULL == ret)
55 return 1; 67 return 1;
56 if (0 != strcmp (ret, "Hello")) 68 if (0 != strcmp (ret,
69 "Hello"))
57 return 2; 70 return 2;
58 ret = GNUNET_PLUGIN_unload ("libgnunet_plugin_test", "out"); 71 ret = GNUNET_PLUGIN_unload ("libgnunet_plugin_utiltest",
59 if (ret == NULL) 72 "out");
73 if (NULL == ret)
60 return 3; 74 return 3;
61 if (0 != strcmp (ret, "World")) 75 if (0 != strcmp (ret,
76 "World"))
62 return 4; 77 return 4;
63 free (ret); 78 free (ret);
64 GNUNET_PLUGIN_load_all ("libgnunet_plugin_tes", "in", &test_cb, "test"); 79 GNUNET_PLUGIN_load_all ("libgnunet_plugin_utiltes",
80 "in",
81 &test_cb,
82 "test-closure");
65 return 0; 83 return 0;
66} 84}
67 85
diff --git a/src/util/test_plugin_plug.c b/src/util/test_plugin_plug.c
index 39c8774b1..bfaad52e8 100644
--- a/src/util/test_plugin_plug.c
+++ b/src/util/test_plugin_plug.c
@@ -23,8 +23,9 @@
23 */ 23 */
24#include "platform.h" 24#include "platform.h"
25 25
26
26void * 27void *
27libgnunet_plugin_test_init (void *arg) 28libgnunet_plugin_utiltest_init (void *arg)
28{ 29{
29 if (0 == strcmp (arg, "in")) 30 if (0 == strcmp (arg, "in"))
30 return "Hello"; 31 return "Hello";
@@ -33,7 +34,7 @@ libgnunet_plugin_test_init (void *arg)
33 34
34 35
35void * 36void *
36libgnunet_plugin_test_done (void *arg) 37libgnunet_plugin_utiltest_done (void *arg)
37{ 38{
38 if (0 == strcmp (arg, "out")) 39 if (0 == strcmp (arg, "out"))
39 return strdup ("World"); 40 return strdup ("World");