diff options
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/Makefile.am | 10 | ||||
-rw-r--r-- | src/util/client.c | 1 | ||||
-rw-r--r-- | src/util/common_logging.c | 4 | ||||
-rw-r--r-- | src/util/configuration.c | 1096 | ||||
-rw-r--r-- | src/util/configuration_helper.c | 302 | ||||
-rw-r--r-- | src/util/configuration_loader.c | 91 | ||||
-rw-r--r-- | src/util/crypto_hkdf.c | 6 | ||||
-rw-r--r-- | src/util/disk.c | 194 | ||||
-rw-r--r-- | src/util/gnunet-config.c | 318 | ||||
-rw-r--r-- | src/util/network.c | 30 | ||||
-rw-r--r-- | src/util/os_installation.c | 2 | ||||
-rw-r--r-- | src/util/os_priority.c | 14 | ||||
-rw-r--r-- | src/util/plugin.c | 6 | ||||
-rw-r--r-- | src/util/program.c | 89 | ||||
-rw-r--r-- | src/util/strings.c | 2 | ||||
-rw-r--r-- | src/util/test_plugin.c | 52 | ||||
-rw-r--r-- | src/util/test_plugin_plug.c | 5 |
17 files changed, 1614 insertions, 608 deletions
diff --git a/src/util/Makefile.am b/src/util/Makefile.am index e720112be..a3a77073e 100644 --- a/src/util/Makefile.am +++ b/src/util/Makefile.am | |||
@@ -49,7 +49,7 @@ 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 \ | 52 | configuration_helper.c \ |
53 | consttime_memcmp.c \ | 53 | consttime_memcmp.c \ |
54 | container_bloomfilter.c \ | 54 | container_bloomfilter.c \ |
55 | container_heap.c \ | 55 | container_heap.c \ |
@@ -243,11 +243,11 @@ gnunet_qr_LDADD = \ | |||
243 | gnunet_qr_LDFLAGS= -lzbar | 243 | gnunet_qr_LDFLAGS= -lzbar |
244 | 244 | ||
245 | plugin_LTLIBRARIES = \ | 245 | plugin_LTLIBRARIES = \ |
246 | libgnunet_plugin_test.la | 246 | libgnunet_plugin_utiltest.la |
247 | 247 | ||
248 | libgnunet_plugin_test_la_SOURCES = \ | 248 | libgnunet_plugin_utiltest_la_SOURCES = \ |
249 | test_plugin_plug.c | 249 | test_plugin_plug.c |
250 | libgnunet_plugin_test_la_LDFLAGS = \ | 250 | libgnunet_plugin_utiltest_la_LDFLAGS = \ |
251 | $(GN_PLUGIN_LDFLAGS) | 251 | $(GN_PLUGIN_LDFLAGS) |
252 | 252 | ||
253 | if HAVE_BENCHMARKS | 253 | if HAVE_BENCHMARKS |
@@ -362,8 +362,6 @@ test_os_start_process_SOURCES = \ | |||
362 | test_os_start_process.c | 362 | test_os_start_process.c |
363 | test_os_start_process_LDADD = \ | 363 | test_os_start_process_LDADD = \ |
364 | libgnunetutil.la | 364 | libgnunetutil.la |
365 | test_os_start_process_DEPENDENCIES = \ | ||
366 | libgnunetutil.la | ||
367 | 365 | ||
368 | test_client_nc_SOURCES = \ | 366 | test_client_nc_SOURCES = \ |
369 | test_client.c | 367 | test_client.c |
diff --git a/src/util/client.c b/src/util/client.c index afd2fe900..4e5eca32a 100644 --- a/src/util/client.c +++ b/src/util/client.c | |||
@@ -745,6 +745,7 @@ test_service_configuration (const char *service_name, | |||
745 | service_name, | 745 | service_name, |
746 | "UNIXPATH", | 746 | "UNIXPATH", |
747 | _ ("not a valid filename")); | 747 | _ ("not a valid filename")); |
748 | GNUNET_free (unixpath); | ||
748 | return GNUNET_SYSERR; /* UNIXPATH specified but invalid! */ | 749 | return GNUNET_SYSERR; /* UNIXPATH specified but invalid! */ |
749 | } | 750 | } |
750 | GNUNET_free (unixpath); | 751 | GNUNET_free (unixpath); |
diff --git a/src/util/common_logging.c b/src/util/common_logging.c index 48cc6fe3b..cba37cd2f 100644 --- a/src/util/common_logging.c +++ b/src/util/common_logging.c | |||
@@ -1014,8 +1014,10 @@ mylog (enum GNUNET_ErrorType kind, | |||
1014 | } | 1014 | } |
1015 | else | 1015 | else |
1016 | { | 1016 | { |
1017 | if (0 == strftime (date2, DATE_STR_SIZE, "%b %d %H:%M:%S-%%06u", tmptr)) | 1017 | /* RFC 3339 timestamp, with snprintf placeholder for microseconds */ |
1018 | if (0 == strftime (date2, DATE_STR_SIZE, "%Y-%m-%dT%H:%M:%S.%%06u%z", tmptr)) | ||
1018 | abort (); | 1019 | abort (); |
1020 | /* Fill in microseconds */ | ||
1019 | if (0 > snprintf (date, sizeof(date), date2, timeofday.tv_usec)) | 1021 | if (0 > snprintf (date, sizeof(date), date2, timeofday.tv_usec)) |
1020 | abort (); | 1022 | abort (); |
1021 | } | 1023 | } |
diff --git a/src/util/configuration.c b/src/util/configuration.c index d0090ae53..09a3a7d93 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 | ||
@@ -75,6 +87,62 @@ struct ConfigSection | |||
75 | * name of the section | 87 | * name of the section |
76 | */ | 88 | */ |
77 | char *name; | 89 | char *name; |
90 | |||
91 | /** | ||
92 | * Is the configuration section marked as inaccessible? | ||
93 | * | ||
94 | * This can happen if the section name is used in an @inline-secret@ | ||
95 | * directive, but the referenced file can't be found or accessed. | ||
96 | */ | ||
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 | |||
120 | struct 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; | ||
78 | }; | 146 | }; |
79 | 147 | ||
80 | 148 | ||
@@ -89,11 +157,48 @@ struct GNUNET_CONFIGURATION_Handle | |||
89 | struct ConfigSection *sections; | 157 | struct ConfigSection *sections; |
90 | 158 | ||
91 | /** | 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 | /** | ||
92 | * Modification indication since last save | 180 | * Modification indication since last save |
93 | * #GNUNET_NO if clean, #GNUNET_YES if dirty, | 181 | * #GNUNET_NO if clean, #GNUNET_YES if dirty, |
94 | * #GNUNET_SYSERR on error (i.e. last save failed) | 182 | * #GNUNET_SYSERR on error (i.e. last save failed) |
95 | */ | 183 | */ |
96 | enum GNUNET_GenericReturnValue dirty; | 184 | enum GNUNET_GenericReturnValue dirty; |
185 | |||
186 | /** | ||
187 | * Was the configuration ever loaded via GNUNET_CONFIGURATION_load? | ||
188 | */ | ||
189 | bool load_called; | ||
190 | |||
191 | /** | ||
192 | * Name of the entry point configuration file. | ||
193 | */ | ||
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; | ||
97 | }; | 202 | }; |
98 | 203 | ||
99 | 204 | ||
@@ -109,6 +214,14 @@ struct DiffHandle | |||
109 | }; | 214 | }; |
110 | 215 | ||
111 | 216 | ||
217 | void | ||
218 | GNUNET_CONFIGURATION_enable_diagnostics (struct | ||
219 | GNUNET_CONFIGURATION_Handle *cfg) | ||
220 | { | ||
221 | cfg->diagnostics = true; | ||
222 | } | ||
223 | |||
224 | |||
112 | struct GNUNET_CONFIGURATION_Handle * | 225 | struct GNUNET_CONFIGURATION_Handle * |
113 | GNUNET_CONFIGURATION_create () | 226 | GNUNET_CONFIGURATION_create () |
114 | { | 227 | { |
@@ -198,9 +311,20 @@ void | |||
198 | GNUNET_CONFIGURATION_destroy (struct GNUNET_CONFIGURATION_Handle *cfg) | 311 | GNUNET_CONFIGURATION_destroy (struct GNUNET_CONFIGURATION_Handle *cfg) |
199 | { | 312 | { |
200 | struct ConfigSection *sec; | 313 | struct ConfigSection *sec; |
314 | struct ConfigFile *cf; | ||
201 | 315 | ||
202 | while (NULL != (sec = cfg->sections)) | 316 | while (NULL != (sec = cfg->sections)) |
203 | 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 | GNUNET_free (cf); | ||
326 | } | ||
327 | GNUNET_free (cfg->main_filename); | ||
204 | GNUNET_free (cfg); | 328 | GNUNET_free (cfg); |
205 | } | 329 | } |
206 | 330 | ||
@@ -214,7 +338,9 @@ GNUNET_CONFIGURATION_parse_and_run (const char *filename, | |||
214 | enum GNUNET_GenericReturnValue ret; | 338 | enum GNUNET_GenericReturnValue ret; |
215 | 339 | ||
216 | cfg = GNUNET_CONFIGURATION_create (); | 340 | cfg = GNUNET_CONFIGURATION_create (); |
217 | if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, filename)) | 341 | if (GNUNET_OK != |
342 | GNUNET_CONFIGURATION_load (cfg, | ||
343 | filename)) | ||
218 | { | 344 | { |
219 | GNUNET_break (0); | 345 | GNUNET_break (0); |
220 | GNUNET_CONFIGURATION_destroy (cfg); | 346 | GNUNET_CONFIGURATION_destroy (cfg); |
@@ -226,34 +352,381 @@ GNUNET_CONFIGURATION_parse_and_run (const char *filename, | |||
226 | } | 352 | } |
227 | 353 | ||
228 | 354 | ||
355 | /** | ||
356 | * Closure to collect_files_cb. | ||
357 | */ | ||
358 | struct CollectFilesContext | ||
359 | { | ||
360 | /** | ||
361 | * Collected files from globbing. | ||
362 | */ | ||
363 | char **files; | ||
364 | |||
365 | /** | ||
366 | * Size of the files array. | ||
367 | */ | ||
368 | unsigned int files_length; | ||
369 | }; | ||
370 | |||
371 | |||
372 | /** | ||
373 | * Function called with a filename. | ||
374 | * | ||
375 | * @param cls closure | ||
376 | * @param filename complete filename (absolute path) | ||
377 | * @return #GNUNET_OK to continue to iterate, | ||
378 | * #GNUNET_NO to stop iteration with no error, | ||
379 | * #GNUNET_SYSERR to abort iteration with error! | ||
380 | */ | ||
381 | static int | ||
382 | collect_files_cb (void *cls, | ||
383 | const char *filename) | ||
384 | { | ||
385 | struct CollectFilesContext *igc = cls; | ||
386 | |||
387 | GNUNET_array_append (igc->files, | ||
388 | igc->files_length, | ||
389 | GNUNET_strdup (filename)); | ||
390 | return GNUNET_OK; | ||
391 | } | ||
392 | |||
393 | |||
394 | /** | ||
395 | * Find a section entry from a configuration. | ||
396 | * | ||
397 | * @param cfg configuration to search in | ||
398 | * @param section name of the section to look for | ||
399 | * @return matching entry, NULL if not found | ||
400 | */ | ||
401 | static struct ConfigSection * | ||
402 | find_section (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
403 | const char *section) | ||
404 | { | ||
405 | struct ConfigSection *pos; | ||
406 | |||
407 | pos = cfg->sections; | ||
408 | while ((pos != NULL) && (0 != strcasecmp (section, pos->name))) | ||
409 | pos = pos->next; | ||
410 | return pos; | ||
411 | } | ||
412 | |||
413 | |||
414 | static int | ||
415 | pstrcmp (const void *a, const void *b) | ||
416 | { | ||
417 | return strcmp (*((const char **) a), *((const char **) b)); | ||
418 | } | ||
419 | |||
420 | |||
421 | /** | ||
422 | * Handle an inline directive. | ||
423 | * | ||
424 | * @returns #GNUNET_SYSERR on error, #GNUNET_OK otherwise | ||
425 | */ | ||
426 | enum GNUNET_GenericReturnValue | ||
427 | handle_inline (struct GNUNET_CONFIGURATION_Handle *cfg, | ||
428 | const char *path_or_glob, | ||
429 | bool path_is_glob, | ||
430 | const char *restrict_section, | ||
431 | const char *source_filename, | ||
432 | unsigned int source_lineno) | ||
433 | { | ||
434 | char *inline_path = NULL; | ||
435 | struct GNUNET_CONFIGURATION_Handle *other_cfg = NULL; | ||
436 | struct CollectFilesContext igc = { | ||
437 | .files = NULL, | ||
438 | .files_length = 0, | ||
439 | }; | ||
440 | enum GNUNET_GenericReturnValue fun_ret; | ||
441 | unsigned int old_nest_level = cfg->current_nest_level++; | ||
442 | |||
443 | /* We support the section restriction only for non-globs */ | ||
444 | GNUNET_assert (! (path_is_glob && (NULL != restrict_section))); | ||
445 | |||
446 | if (NULL == source_filename) | ||
447 | { | ||
448 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
449 | "Refusing to parse inline configurations, " | ||
450 | "not allowed without source filename!\n"); | ||
451 | fun_ret = GNUNET_SYSERR; | ||
452 | goto cleanup; | ||
453 | } | ||
454 | |||
455 | if ('/' == *path_or_glob) | ||
456 | inline_path = GNUNET_strdup (path_or_glob); | ||
457 | else | ||
458 | { | ||
459 | /* We compute the canonical, absolute path first, | ||
460 | so that relative imports resolve properly with symlinked | ||
461 | config files. */ | ||
462 | char *source_realpath; | ||
463 | char *endsep; | ||
464 | |||
465 | source_realpath = realpath (source_filename, | ||
466 | NULL); | ||
467 | if (NULL == source_realpath) | ||
468 | { | ||
469 | /* Couldn't even resolve path of base dir. */ | ||
470 | GNUNET_break (0); | ||
471 | /* failed to parse included config */ | ||
472 | fun_ret = GNUNET_SYSERR; | ||
473 | goto cleanup; | ||
474 | } | ||
475 | endsep = strrchr (source_realpath, '/'); | ||
476 | GNUNET_assert (NULL != endsep); | ||
477 | *endsep = '\0'; | ||
478 | GNUNET_asprintf (&inline_path, | ||
479 | "%s/%s", | ||
480 | source_realpath, | ||
481 | path_or_glob); | ||
482 | free (source_realpath); | ||
483 | } | ||
484 | |||
485 | if (path_is_glob) | ||
486 | { | ||
487 | int nret; | ||
488 | |||
489 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
490 | "processing config glob '%s'\n", | ||
491 | inline_path); | ||
492 | |||
493 | nret = GNUNET_DISK_glob (inline_path, collect_files_cb, &igc); | ||
494 | if (-1 == nret) | ||
495 | { | ||
496 | fun_ret = GNUNET_SYSERR; | ||
497 | goto cleanup; | ||
498 | } | ||
499 | GNUNET_assert (nret == igc.files_length); | ||
500 | qsort (igc.files, igc.files_length, sizeof (char *), pstrcmp); | ||
501 | for (int i = 0; i < nret; i++) | ||
502 | { | ||
503 | if (GNUNET_OK != | ||
504 | GNUNET_CONFIGURATION_parse (cfg, | ||
505 | igc.files[i])) | ||
506 | { | ||
507 | fun_ret = GNUNET_SYSERR; | ||
508 | goto cleanup; | ||
509 | } | ||
510 | } | ||
511 | fun_ret = GNUNET_OK; | ||
512 | } | ||
513 | else if (NULL != restrict_section) | ||
514 | { | ||
515 | enum GNUNET_GenericReturnValue inner_ret; | ||
516 | struct ConfigSection *cs; | ||
517 | struct ConfigFile *cf = GNUNET_new (struct ConfigFile); | ||
518 | |||
519 | inner_ret = GNUNET_DISK_file_test_read (inline_path); | ||
520 | |||
521 | cs = find_section (cfg, restrict_section); | ||
522 | |||
523 | if (NULL == cs) | ||
524 | { | ||
525 | cs = GNUNET_new (struct ConfigSection); | ||
526 | cs->name = GNUNET_strdup (restrict_section); | ||
527 | cs->next = cfg->sections; | ||
528 | cfg->sections = cs; | ||
529 | cs->entries = NULL; | ||
530 | } | ||
531 | if (cfg->diagnostics) | ||
532 | { | ||
533 | char *sfn = GNUNET_STRINGS_filename_expand (inline_path); | ||
534 | struct stat istat; | ||
535 | |||
536 | cs->hint_secret_filename = sfn; | ||
537 | if (0 == stat (sfn, &istat)) | ||
538 | { | ||
539 | struct passwd *pw = getpwuid (istat.st_uid); | ||
540 | struct group *gr = getgrgid (istat.st_gid); | ||
541 | char *pwname = (NULL == pw) ? "<unknown>" : pw->pw_name; | ||
542 | char *grname = (NULL == gr) ? "<unknown>" : gr->gr_name; | ||
543 | |||
544 | GNUNET_asprintf (&cs->hint_secret_stat, | ||
545 | "%s:%s %o", | ||
546 | pwname, | ||
547 | grname, | ||
548 | istat.st_mode); | ||
549 | } | ||
550 | else | ||
551 | { | ||
552 | cs->hint_secret_stat = GNUNET_strdup ("<can't stat file>"); | ||
553 | } | ||
554 | if (source_filename) | ||
555 | { | ||
556 | /* Possible that this secret section has been inlined before */ | ||
557 | GNUNET_free (cs->hint_inlined_from_filename); | ||
558 | cs->hint_inlined_from_filename = GNUNET_strdup (source_filename); | ||
559 | cs->hint_inlined_from_line = source_lineno; | ||
560 | } | ||
561 | } | ||
562 | |||
563 | /* Put file in the load list for diagnostics, even if we can't access it. */ | ||
564 | { | ||
565 | cf->level = cfg->current_nest_level; | ||
566 | cf->source_filename = GNUNET_strdup (inline_path); | ||
567 | cf->hint_restrict_section = GNUNET_strdup (restrict_section); | ||
568 | GNUNET_CONTAINER_DLL_insert_tail (cfg->loaded_files_head, | ||
569 | cfg->loaded_files_tail, | ||
570 | cf); | ||
571 | } | ||
572 | |||
573 | if (GNUNET_OK != inner_ret) | ||
574 | { | ||
575 | cs->inaccessible = true; | ||
576 | cf->hint_inaccessible = true; | ||
577 | /* File can't be accessed, but that's okay. */ | ||
578 | fun_ret = GNUNET_OK; | ||
579 | goto cleanup; | ||
580 | } | ||
581 | |||
582 | other_cfg = GNUNET_CONFIGURATION_create (); | ||
583 | other_cfg->restrict_section = restrict_section; | ||
584 | inner_ret = GNUNET_CONFIGURATION_parse (other_cfg, | ||
585 | inline_path); | ||
586 | if (GNUNET_OK != inner_ret) | ||
587 | { | ||
588 | cf->hint_inaccessible = true; | ||
589 | fun_ret = inner_ret; | ||
590 | goto cleanup; | ||
591 | } | ||
592 | |||
593 | cs = find_section (other_cfg, restrict_section); | ||
594 | if (NULL == cs) | ||
595 | { | ||
596 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
597 | "Configuration file '%s' loaded with @inline-secret@ " | ||
598 | "does not contain section '%s'.\n", | ||
599 | inline_path, | ||
600 | restrict_section); | ||
601 | /* Inlined onfiguration is accessible but doesn't contain any values. | ||
602 | We treat this as if the inlined section was empty, and do not | ||
603 | consider it an error. */ | ||
604 | fun_ret = GNUNET_OK; | ||
605 | goto cleanup; | ||
606 | } | ||
607 | for (struct ConfigEntry *ce = cs->entries; | ||
608 | NULL != ce; | ||
609 | ce = ce->next) | ||
610 | GNUNET_CONFIGURATION_set_value_string (cfg, | ||
611 | restrict_section, | ||
612 | ce->key, | ||
613 | ce->val); | ||
614 | fun_ret = GNUNET_OK; | ||
615 | } | ||
616 | else if (GNUNET_OK != | ||
617 | GNUNET_CONFIGURATION_parse (cfg, | ||
618 | inline_path)) | ||
619 | { | ||
620 | fun_ret = GNUNET_SYSERR; | ||
621 | goto cleanup; | ||
622 | } | ||
623 | else | ||
624 | { | ||
625 | fun_ret = GNUNET_OK; | ||
626 | } | ||
627 | cleanup: | ||
628 | cfg->current_nest_level = old_nest_level; | ||
629 | if (NULL != other_cfg) | ||
630 | GNUNET_CONFIGURATION_destroy (other_cfg); | ||
631 | GNUNET_free (inline_path); | ||
632 | if (igc.files_length > 0) | ||
633 | { | ||
634 | for (size_t i = 0; i < igc.files_length; i++) | ||
635 | GNUNET_free (igc.files[i]); | ||
636 | GNUNET_array_grow (igc.files, igc.files_length, 0); | ||
637 | } | ||
638 | return fun_ret; | ||
639 | } | ||
640 | |||
641 | |||
642 | /** | ||
643 | * Find an entry from a configuration. | ||
644 | * | ||
645 | * @param cfg handle to the configuration | ||
646 | * @param section section the option is in | ||
647 | * @param key the option | ||
648 | * @return matching entry, NULL if not found | ||
649 | */ | ||
650 | static struct ConfigEntry * | ||
651 | find_entry (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
652 | const char *section, | ||
653 | const char *key) | ||
654 | { | ||
655 | struct ConfigSection *sec; | ||
656 | struct ConfigEntry *pos; | ||
657 | |||
658 | if (NULL == (sec = find_section (cfg, section))) | ||
659 | return NULL; | ||
660 | if (sec->inaccessible) | ||
661 | { | ||
662 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
663 | "Section '%s' is marked as inaccessible, because the configuration " | ||
664 | " file that contains the section can't be read. Attempts to use " | ||
665 | "option '%s' will fail.\n", | ||
666 | section, | ||
667 | key); | ||
668 | return NULL; | ||
669 | } | ||
670 | pos = sec->entries; | ||
671 | while ((pos != NULL) && (0 != strcasecmp (key, pos->key))) | ||
672 | pos = pos->next; | ||
673 | return pos; | ||
674 | } | ||
675 | |||
676 | |||
677 | /** | ||
678 | * Set a configuration hint. | ||
679 | * | ||
680 | * @param cfg configuration handle | ||
681 | * @param section section | ||
682 | * @param option config option | ||
683 | * @param hint_filename | ||
684 | * @param hint_line | ||
685 | */ | ||
686 | static void | ||
687 | set_entry_hint (struct GNUNET_CONFIGURATION_Handle *cfg, | ||
688 | const char *section, | ||
689 | const char *option, | ||
690 | const char *hint_filename, | ||
691 | unsigned int hint_line) | ||
692 | { | ||
693 | struct ConfigEntry *e = find_entry (cfg, section, option); | ||
694 | if (! cfg->diagnostics) | ||
695 | return; | ||
696 | if (! e) | ||
697 | return; | ||
698 | e->hint_filename = GNUNET_strdup (hint_filename); | ||
699 | e->hint_lineno = hint_line; | ||
700 | } | ||
701 | |||
702 | |||
229 | enum GNUNET_GenericReturnValue | 703 | enum GNUNET_GenericReturnValue |
230 | GNUNET_CONFIGURATION_deserialize (struct GNUNET_CONFIGURATION_Handle *cfg, | 704 | GNUNET_CONFIGURATION_deserialize (struct GNUNET_CONFIGURATION_Handle *cfg, |
231 | const char *mem, | 705 | const char *mem, |
232 | size_t size, | 706 | size_t size, |
233 | const char *basedir) | 707 | const char *source_filename) |
234 | { | 708 | { |
235 | char *line; | ||
236 | char *line_orig; | ||
237 | size_t line_size; | 709 | size_t line_size; |
238 | char *pos; | ||
239 | unsigned int nr; | 710 | unsigned int nr; |
240 | size_t r_bytes; | 711 | size_t r_bytes; |
241 | size_t to_read; | 712 | size_t to_read; |
242 | size_t i; | ||
243 | int emptyline; | ||
244 | enum GNUNET_GenericReturnValue ret; | 713 | enum GNUNET_GenericReturnValue ret; |
245 | char *section; | 714 | char *section; |
246 | char *eq; | 715 | char *eq; |
247 | char *tag; | 716 | char *tag; |
248 | char *value; | 717 | char *value; |
718 | char *line_orig = NULL; | ||
249 | 719 | ||
250 | ret = GNUNET_OK; | 720 | ret = GNUNET_OK; |
251 | section = GNUNET_strdup (""); | 721 | section = NULL; |
252 | nr = 0; | 722 | nr = 0; |
253 | r_bytes = 0; | 723 | r_bytes = 0; |
254 | line_orig = NULL; | ||
255 | while (r_bytes < size) | 724 | while (r_bytes < size) |
256 | { | 725 | { |
726 | char *pos; | ||
727 | char *line; | ||
728 | bool emptyline; | ||
729 | |||
257 | GNUNET_free (line_orig); | 730 | GNUNET_free (line_orig); |
258 | /* fgets-like behaviour on buffer */ | 731 | /* fgets-like behaviour on buffer */ |
259 | to_read = size - r_bytes; | 732 | to_read = size - r_bytes; |
@@ -275,7 +748,7 @@ GNUNET_CONFIGURATION_deserialize (struct GNUNET_CONFIGURATION_Handle *cfg, | |||
275 | nr++; | 748 | nr++; |
276 | /* tabs and '\r' are whitespace */ | 749 | /* tabs and '\r' are whitespace */ |
277 | emptyline = GNUNET_YES; | 750 | emptyline = GNUNET_YES; |
278 | for (i = 0; i < line_size; i++) | 751 | for (size_t i = 0; i < line_size; i++) |
279 | { | 752 | { |
280 | if (line[i] == '\t') | 753 | if (line[i] == '\t') |
281 | line[i] = ' '; | 754 | line[i] = ' '; |
@@ -289,7 +762,7 @@ GNUNET_CONFIGURATION_deserialize (struct GNUNET_CONFIGURATION_Handle *cfg, | |||
289 | continue; | 762 | continue; |
290 | 763 | ||
291 | /* remove tailing whitespace */ | 764 | /* remove tailing whitespace */ |
292 | for (i = line_size - 1; | 765 | for (size_t i = line_size - 1; |
293 | (i >= 1) && (isspace ((unsigned char) line[i])); | 766 | (i >= 1) && (isspace ((unsigned char) line[i])); |
294 | i--) | 767 | i--) |
295 | line[i] = '\0'; | 768 | line[i] = '\0'; |
@@ -303,50 +776,113 @@ GNUNET_CONFIGURATION_deserialize (struct GNUNET_CONFIGURATION_Handle *cfg, | |||
303 | ('%' == line[0]) ) | 776 | ('%' == line[0]) ) |
304 | continue; | 777 | continue; |
305 | 778 | ||
306 | /* handle special "@INLINE@" directive */ | 779 | /* Handle special directives. */ |
307 | if (0 == strncasecmp (line, | 780 | if ('@' == line[0]) |
308 | "@INLINE@ ", | ||
309 | strlen ("@INLINE@ "))) | ||
310 | { | 781 | { |
311 | /* @INLINE@ value */ | 782 | char *end = strchr (line + 1, '@'); |
312 | value = &line[strlen ("@INLINE@ ")]; | 783 | char *directive; |
313 | if (NULL != basedir) | 784 | enum GNUNET_GenericReturnValue directive_ret; |
785 | |||
786 | if (NULL != cfg->restrict_section) | ||
314 | { | 787 | { |
315 | if ('/' == *value) | 788 | LOG (GNUNET_ERROR_TYPE_WARNING, |
316 | { | 789 | _ ( |
317 | if (GNUNET_OK != | 790 | "Illegal directive in line %u (parsing restricted section %s)\n"), |
318 | GNUNET_CONFIGURATION_parse (cfg, | 791 | nr, |
319 | value)) | 792 | cfg->restrict_section); |
320 | { | 793 | ret = GNUNET_SYSERR; |
321 | ret = GNUNET_SYSERR; /* failed to parse included config */ | 794 | break; |
322 | break; | 795 | } |
323 | } | 796 | |
324 | } | 797 | if (NULL == end) |
325 | else | 798 | { |
799 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
800 | _ ("Bad directive in line %u\n"), | ||
801 | nr); | ||
802 | ret = GNUNET_SYSERR; | ||
803 | break; | ||
804 | } | ||
805 | *end = '\0'; | ||
806 | directive = line + 1; | ||
807 | |||
808 | if (0 == strcasecmp (directive, "INLINE")) | ||
809 | { | ||
810 | const char *path = end + 1; | ||
811 | |||
812 | /* Skip space before path */ | ||
813 | for (; isspace (*path); path++) | ||
814 | ; | ||
815 | |||
816 | directive_ret = handle_inline (cfg, | ||
817 | path, | ||
818 | false, | ||
819 | NULL, | ||
820 | source_filename, | ||
821 | nr); | ||
822 | } | ||
823 | else if (0 == strcasecmp (directive, "INLINE-MATCHING")) | ||
824 | { | ||
825 | const char *path = end + 1; | ||
826 | |||
827 | /* Skip space before path */ | ||
828 | for (; isspace (*path); path++) | ||
829 | ; | ||
830 | |||
831 | directive_ret = handle_inline (cfg, | ||
832 | path, | ||
833 | true, | ||
834 | NULL, | ||
835 | source_filename, | ||
836 | nr); | ||
837 | } | ||
838 | else if (0 == strcasecmp (directive, "INLINE-SECRET")) | ||
839 | { | ||
840 | char *secname = end + 1; | ||
841 | char *secname_end; | ||
842 | const char *path; | ||
843 | |||
844 | /* Skip space before secname */ | ||
845 | for (; isspace (*secname); secname++) | ||
846 | ; | ||
847 | |||
848 | secname_end = strchr (secname, ' '); | ||
849 | |||
850 | if (NULL == secname_end) | ||
326 | { | 851 | { |
327 | char *fn; | 852 | LOG (GNUNET_ERROR_TYPE_WARNING, |
328 | 853 | _ ("Bad inline-secret directive in line %u\n"), | |
329 | GNUNET_asprintf (&fn, "%s/%s", | 854 | nr); |
330 | basedir, | 855 | ret = GNUNET_SYSERR; |
331 | value); | 856 | break; |
332 | if (GNUNET_OK != | ||
333 | GNUNET_CONFIGURATION_parse (cfg, | ||
334 | fn)) | ||
335 | { | ||
336 | GNUNET_free (fn); | ||
337 | ret = GNUNET_SYSERR; /* failed to parse included config */ | ||
338 | break; | ||
339 | } | ||
340 | GNUNET_free (fn); | ||
341 | } | 857 | } |
858 | *secname_end = '\0'; | ||
859 | path = secname_end + 1; | ||
860 | |||
861 | /* Skip space before path */ | ||
862 | for (; isspace (*path); path++) | ||
863 | ; | ||
864 | |||
865 | directive_ret = handle_inline (cfg, | ||
866 | path, | ||
867 | false, | ||
868 | secname, | ||
869 | source_filename, | ||
870 | nr); | ||
342 | } | 871 | } |
343 | else | 872 | else |
344 | { | 873 | { |
345 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 874 | LOG (GNUNET_ERROR_TYPE_WARNING, |
346 | "Ignoring parsing @INLINE@ configurations, not allowed!\n"); | 875 | _ ("Unknown or malformed directive '%s' in line %u\n"), |
876 | directive, | ||
877 | nr); | ||
347 | ret = GNUNET_SYSERR; | 878 | ret = GNUNET_SYSERR; |
348 | break; | 879 | break; |
349 | } | 880 | } |
881 | if (GNUNET_OK != directive_ret) | ||
882 | { | ||
883 | ret = directive_ret; | ||
884 | break; | ||
885 | } | ||
350 | continue; | 886 | continue; |
351 | } | 887 | } |
352 | if (('[' == line[0]) && (']' == line[line_size - 1])) | 888 | if (('[' == line[0]) && (']' == line[line_size - 1])) |
@@ -360,10 +896,23 @@ GNUNET_CONFIGURATION_deserialize (struct GNUNET_CONFIGURATION_Handle *cfg, | |||
360 | } | 896 | } |
361 | if (NULL != (eq = strchr (line, '='))) | 897 | if (NULL != (eq = strchr (line, '='))) |
362 | { | 898 | { |
899 | size_t i; | ||
900 | |||
901 | if (NULL == section) | ||
902 | { | ||
903 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
904 | _ ( | ||
905 | "Syntax error while deserializing in line %u (option without section)\n"), | ||
906 | nr); | ||
907 | ret = GNUNET_SYSERR; | ||
908 | break; | ||
909 | } | ||
910 | |||
363 | /* tag = value */ | 911 | /* tag = value */ |
364 | tag = GNUNET_strndup (line, eq - line); | 912 | tag = GNUNET_strndup (line, eq - line); |
365 | /* remove tailing whitespace */ | 913 | /* remove tailing whitespace */ |
366 | for (i = strlen (tag) - 1; (i >= 1) && (isspace ((unsigned char) tag[i])); | 914 | for (i = strlen (tag) - 1; |
915 | (i >= 1) && (isspace ((unsigned char) tag[i])); | ||
367 | i--) | 916 | i--) |
368 | tag[i] = '\0'; | 917 | tag[i] = '\0'; |
369 | 918 | ||
@@ -384,6 +933,14 @@ GNUNET_CONFIGURATION_deserialize (struct GNUNET_CONFIGURATION_Handle *cfg, | |||
384 | value++; | 933 | value++; |
385 | } | 934 | } |
386 | GNUNET_CONFIGURATION_set_value_string (cfg, section, tag, &value[i]); | 935 | GNUNET_CONFIGURATION_set_value_string (cfg, section, tag, &value[i]); |
936 | if (cfg->diagnostics) | ||
937 | { | ||
938 | set_entry_hint (cfg, | ||
939 | section, | ||
940 | tag, | ||
941 | source_filename ? source_filename : "<input>", | ||
942 | nr); | ||
943 | } | ||
387 | GNUNET_free (tag); | 944 | GNUNET_free (tag); |
388 | continue; | 945 | continue; |
389 | } | 946 | } |
@@ -410,7 +967,6 @@ GNUNET_CONFIGURATION_parse (struct GNUNET_CONFIGURATION_Handle *cfg, | |||
410 | size_t fs; | 967 | size_t fs; |
411 | char *fn; | 968 | char *fn; |
412 | char *mem; | 969 | char *mem; |
413 | char *endsep; | ||
414 | int dirty; | 970 | int dirty; |
415 | enum GNUNET_GenericReturnValue ret; | 971 | enum GNUNET_GenericReturnValue ret; |
416 | ssize_t sret; | 972 | ssize_t sret; |
@@ -419,6 +975,56 @@ GNUNET_CONFIGURATION_parse (struct GNUNET_CONFIGURATION_Handle *cfg, | |||
419 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to parse config file `%s'\n", fn); | 975 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to parse config file `%s'\n", fn); |
420 | if (NULL == fn) | 976 | if (NULL == fn) |
421 | return GNUNET_SYSERR; | 977 | return GNUNET_SYSERR; |
978 | |||
979 | |||
980 | /* Check for cycles */ | ||
981 | { | ||
982 | unsigned int lvl = cfg->current_nest_level; | ||
983 | struct ConfigFile *cf = cfg->loaded_files_tail; | ||
984 | struct ConfigFile *parent = NULL; | ||
985 | |||
986 | |||
987 | for (; NULL != cf; parent = cf, cf = cf->prev) | ||
988 | { | ||
989 | /* Check parents based on level, skipping children of siblings. */ | ||
990 | if (cf->level >= lvl) | ||
991 | continue; | ||
992 | lvl = cf->level; | ||
993 | if ( (NULL == cf->source_filename) || (NULL == filename)) | ||
994 | continue; | ||
995 | if (0 == strcmp (cf->source_filename, filename)) | ||
996 | { | ||
997 | if (NULL == parent) | ||
998 | { | ||
999 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1000 | "Forbidden direct cyclic configuration import (%s -> %s)\n", | ||
1001 | cf->source_filename, | ||
1002 | filename); | ||
1003 | } | ||
1004 | else | ||
1005 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1006 | "Forbidden indirect cyclic configuration import (%s -> ... -> %s -> %s)\n", | ||
1007 | cf->source_filename, | ||
1008 | parent->source_filename, | ||
1009 | filename); | ||
1010 | GNUNET_free (fn); | ||
1011 | return GNUNET_SYSERR; | ||
1012 | } | ||
1013 | } | ||
1014 | |||
1015 | } | ||
1016 | |||
1017 | /* Keep track of loaded files.*/ | ||
1018 | { | ||
1019 | struct ConfigFile *cf = GNUNET_new (struct ConfigFile); | ||
1020 | |||
1021 | cf->level = cfg->current_nest_level; | ||
1022 | cf->source_filename = GNUNET_strdup (filename ? filename : "<input>"); | ||
1023 | GNUNET_CONTAINER_DLL_insert_tail (cfg->loaded_files_head, | ||
1024 | cfg->loaded_files_tail, | ||
1025 | cf); | ||
1026 | } | ||
1027 | |||
422 | dirty = cfg->dirty; /* back up value! */ | 1028 | dirty = cfg->dirty; /* back up value! */ |
423 | if (GNUNET_SYSERR == | 1029 | if (GNUNET_SYSERR == |
424 | GNUNET_DISK_file_size (fn, &fs64, GNUNET_YES, GNUNET_YES)) | 1030 | GNUNET_DISK_file_size (fn, &fs64, GNUNET_YES, GNUNET_YES)) |
@@ -446,14 +1052,11 @@ GNUNET_CONFIGURATION_parse (struct GNUNET_CONFIGURATION_Handle *cfg, | |||
446 | return GNUNET_SYSERR; | 1052 | return GNUNET_SYSERR; |
447 | } | 1053 | } |
448 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Deserializing contents of file `%s'\n", fn); | 1054 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Deserializing contents of file `%s'\n", fn); |
449 | endsep = strrchr (fn, (int) '/'); | ||
450 | if (NULL != endsep) | ||
451 | *endsep = '\0'; | ||
452 | ret = GNUNET_CONFIGURATION_deserialize (cfg, | 1055 | ret = GNUNET_CONFIGURATION_deserialize (cfg, |
453 | mem, | 1056 | mem, |
454 | fs, | 1057 | fs, |
455 | fn); | 1058 | fn); |
456 | if (GNUNET_OK != ret) | 1059 | if (GNUNET_SYSERR == ret) |
457 | { | 1060 | { |
458 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 1061 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
459 | _ ("Failed to parse configuration file `%s'\n"), | 1062 | _ ("Failed to parse configuration file `%s'\n"), |
@@ -527,6 +1130,8 @@ GNUNET_CONFIGURATION_serialize (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
527 | NULL != sec; | 1130 | NULL != sec; |
528 | sec = sec->next) | 1131 | sec = sec->next) |
529 | { | 1132 | { |
1133 | if (sec->inaccessible) | ||
1134 | continue; | ||
530 | /* For each section we need to add 3 characters: {'[',']','\n'} */ | 1135 | /* For each section we need to add 3 characters: {'[',']','\n'} */ |
531 | m_size += strlen (sec->name) + 3; | 1136 | m_size += strlen (sec->name) + 3; |
532 | for (struct ConfigEntry *ent = sec->entries; | 1137 | for (struct ConfigEntry *ent = sec->entries; |
@@ -606,6 +1211,117 @@ GNUNET_CONFIGURATION_serialize (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
606 | } | 1211 | } |
607 | 1212 | ||
608 | 1213 | ||
1214 | char * | ||
1215 | GNUNET_CONFIGURATION_serialize_diagnostics (const struct | ||
1216 | GNUNET_CONFIGURATION_Handle *cfg) | ||
1217 | { | ||
1218 | struct GNUNET_Buffer buf = { 0 }; | ||
1219 | |||
1220 | GNUNET_buffer_write_fstr (&buf, | ||
1221 | "#\n# Configuration file diagnostics\n#\n"); | ||
1222 | GNUNET_buffer_write_fstr (&buf, | ||
1223 | "# Entry point: %s\n", | ||
1224 | cfg->main_filename ? cfg->main_filename : | ||
1225 | "<none>"); | ||
1226 | GNUNET_buffer_write_fstr (&buf, | ||
1227 | "#\n# Files Loaded:\n"); | ||
1228 | |||
1229 | for (struct ConfigFile *cfil = cfg->loaded_files_head; | ||
1230 | NULL != cfil; | ||
1231 | cfil = cfil->next) | ||
1232 | { | ||
1233 | GNUNET_buffer_write_fstr (&buf, | ||
1234 | "# "); | ||
1235 | for (unsigned int i = 0; i < cfil->level; i++) | ||
1236 | GNUNET_buffer_write_fstr (&buf, | ||
1237 | "+"); | ||
1238 | if (0 != cfil->level) | ||
1239 | GNUNET_buffer_write_fstr (&buf, | ||
1240 | " "); | ||
1241 | |||
1242 | GNUNET_buffer_write_fstr (&buf, | ||
1243 | "%s", | ||
1244 | cfil->source_filename); | ||
1245 | |||
1246 | if (NULL != cfil->hint_restrict_section) | ||
1247 | GNUNET_buffer_write_fstr (&buf, | ||
1248 | " (%s secret section %s)", | ||
1249 | cfil->hint_inaccessible | ||
1250 | ? "inaccessible" | ||
1251 | : "loaded", | ||
1252 | cfil->hint_restrict_section); | ||
1253 | |||
1254 | GNUNET_buffer_write_str (&buf, | ||
1255 | "\n"); | ||
1256 | } | ||
1257 | |||
1258 | GNUNET_buffer_write_fstr (&buf, | ||
1259 | "#\n\n"); | ||
1260 | |||
1261 | for (struct ConfigSection *sec = cfg->sections; | ||
1262 | NULL != sec; | ||
1263 | sec = sec->next) | ||
1264 | { | ||
1265 | if (sec->hint_secret_filename) | ||
1266 | GNUNET_buffer_write_fstr (&buf, | ||
1267 | "# secret section from %s\n# secret file stat %s\n", | ||
1268 | sec->hint_secret_filename, | ||
1269 | sec->hint_secret_stat); | ||
1270 | if (sec->hint_inlined_from_filename) | ||
1271 | { | ||
1272 | GNUNET_buffer_write_fstr (&buf, | ||
1273 | "# inlined from %s:%u\n", | ||
1274 | sec->hint_inlined_from_filename, | ||
1275 | sec->hint_inlined_from_line); | ||
1276 | } | ||
1277 | GNUNET_buffer_write_fstr (&buf, | ||
1278 | "[%s]\n\n", | ||
1279 | sec->name); | ||
1280 | if (sec->inaccessible) | ||
1281 | { | ||
1282 | GNUNET_buffer_write_fstr (&buf, | ||
1283 | "# <section contents inaccessible>\n\n\n"); | ||
1284 | continue; | ||
1285 | } | ||
1286 | for (struct ConfigEntry *ent = sec->entries; | ||
1287 | NULL != ent; | ||
1288 | ent = ent->next) | ||
1289 | { | ||
1290 | if (do_skip (sec->name, | ||
1291 | ent->key)) | ||
1292 | continue; | ||
1293 | if (NULL != ent->val) | ||
1294 | { | ||
1295 | char *pos; | ||
1296 | char *val = GNUNET_malloc (strlen (ent->val) * 2 + 1); | ||
1297 | strcpy (val, ent->val); | ||
1298 | while (NULL != (pos = strstr (val, "\n"))) | ||
1299 | { | ||
1300 | memmove (&pos[2], &pos[1], strlen (&pos[1])); | ||
1301 | pos[0] = '\\'; | ||
1302 | pos[1] = 'n'; | ||
1303 | } | ||
1304 | if (NULL != ent->hint_filename) | ||
1305 | { | ||
1306 | GNUNET_buffer_write_fstr (&buf, | ||
1307 | "# %s:%u\n", | ||
1308 | ent->hint_filename, | ||
1309 | ent->hint_lineno); | ||
1310 | } | ||
1311 | GNUNET_buffer_write_fstr (&buf, | ||
1312 | "%s = %s\n", | ||
1313 | ent->key, | ||
1314 | val); | ||
1315 | GNUNET_free (val); | ||
1316 | } | ||
1317 | GNUNET_buffer_write_str (&buf, "\n"); | ||
1318 | } | ||
1319 | GNUNET_buffer_write_str (&buf, "\n"); | ||
1320 | } | ||
1321 | return GNUNET_buffer_reap_str (&buf); | ||
1322 | } | ||
1323 | |||
1324 | |||
609 | enum GNUNET_GenericReturnValue | 1325 | enum GNUNET_GenericReturnValue |
610 | GNUNET_CONFIGURATION_write (struct GNUNET_CONFIGURATION_Handle *cfg, | 1326 | GNUNET_CONFIGURATION_write (struct GNUNET_CONFIGURATION_Handle *cfg, |
611 | const char *filename) | 1327 | const char *filename) |
@@ -700,6 +1416,14 @@ GNUNET_CONFIGURATION_iterate_section_values ( | |||
700 | spos = spos->next; | 1416 | spos = spos->next; |
701 | if (NULL == spos) | 1417 | if (NULL == spos) |
702 | return; | 1418 | return; |
1419 | if (spos->inaccessible) | ||
1420 | { | ||
1421 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1422 | "Section '%s' is marked as inaccessible, because the configuration " | ||
1423 | " file that contains the section can't be read.\n", | ||
1424 | section); | ||
1425 | return; | ||
1426 | } | ||
703 | for (epos = spos->entries; NULL != epos; epos = epos->next) | 1427 | for (epos = spos->entries; NULL != epos; epos = epos->next) |
704 | if (NULL != epos->val) | 1428 | if (NULL != epos->val) |
705 | iter (iter_cls, spos->name, epos->key, epos->val); | 1429 | iter (iter_cls, spos->name, epos->key, epos->val); |
@@ -748,10 +1472,14 @@ GNUNET_CONFIGURATION_remove_section (struct GNUNET_CONFIGURATION_Handle *cfg, | |||
748 | spos->entries = ent->next; | 1472 | spos->entries = ent->next; |
749 | GNUNET_free (ent->key); | 1473 | GNUNET_free (ent->key); |
750 | GNUNET_free (ent->val); | 1474 | GNUNET_free (ent->val); |
1475 | GNUNET_free (ent->hint_filename); | ||
751 | GNUNET_free (ent); | 1476 | GNUNET_free (ent); |
752 | cfg->dirty = GNUNET_YES; | 1477 | cfg->dirty = GNUNET_YES; |
753 | } | 1478 | } |
754 | GNUNET_free (spos->name); | 1479 | GNUNET_free (spos->name); |
1480 | GNUNET_free (spos->hint_secret_filename); | ||
1481 | GNUNET_free (spos->hint_secret_stat); | ||
1482 | GNUNET_free (spos->hint_inlined_from_filename); | ||
755 | GNUNET_free (spos); | 1483 | GNUNET_free (spos); |
756 | return; | 1484 | return; |
757 | } | 1485 | } |
@@ -794,51 +1522,6 @@ GNUNET_CONFIGURATION_dup (const struct GNUNET_CONFIGURATION_Handle *cfg) | |||
794 | 1522 | ||
795 | 1523 | ||
796 | /** | 1524 | /** |
797 | * Find a section entry from a configuration. | ||
798 | * | ||
799 | * @param cfg configuration to search in | ||
800 | * @param section name of the section to look for | ||
801 | * @return matching entry, NULL if not found | ||
802 | */ | ||
803 | static struct ConfigSection * | ||
804 | find_section (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
805 | const char *section) | ||
806 | { | ||
807 | struct ConfigSection *pos; | ||
808 | |||
809 | pos = cfg->sections; | ||
810 | while ((pos != NULL) && (0 != strcasecmp (section, pos->name))) | ||
811 | pos = pos->next; | ||
812 | return pos; | ||
813 | } | ||
814 | |||
815 | |||
816 | /** | ||
817 | * Find an entry from a configuration. | ||
818 | * | ||
819 | * @param cfg handle to the configuration | ||
820 | * @param section section the option is in | ||
821 | * @param key the option | ||
822 | * @return matching entry, NULL if not found | ||
823 | */ | ||
824 | static struct ConfigEntry * | ||
825 | find_entry (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
826 | const char *section, | ||
827 | const char *key) | ||
828 | { | ||
829 | struct ConfigSection *sec; | ||
830 | struct ConfigEntry *pos; | ||
831 | |||
832 | if (NULL == (sec = find_section (cfg, section))) | ||
833 | return NULL; | ||
834 | pos = sec->entries; | ||
835 | while ((pos != NULL) && (0 != strcasecmp (key, pos->key))) | ||
836 | pos = pos->next; | ||
837 | return pos; | ||
838 | } | ||
839 | |||
840 | |||
841 | /** | ||
842 | * A callback function, compares entries from two configurations | 1525 | * A callback function, compares entries from two configurations |
843 | * (default against a new configuration) and write the diffs in a | 1526 | * (default against a new configuration) and write the diffs in a |
844 | * diff-configuration object (the callback object). | 1527 | * diff-configuration object (the callback object). |
@@ -1601,41 +2284,93 @@ GNUNET_CONFIGURATION_remove_value_filename ( | |||
1601 | } | 2284 | } |
1602 | 2285 | ||
1603 | 2286 | ||
1604 | /** | 2287 | enum GNUNET_GenericReturnValue |
1605 | * Wrapper around #GNUNET_CONFIGURATION_parse. Called on each | 2288 | GNUNET_CONFIGURATION_load_from (struct GNUNET_CONFIGURATION_Handle *cfg, |
1606 | * file in a directory, we trigger parsing on those files that | 2289 | const char *defaults_d) |
1607 | * end with ".conf". | ||
1608 | * | ||
1609 | * @param cls the cfg | ||
1610 | * @param filename file to parse | ||
1611 | * @return #GNUNET_OK on success | ||
1612 | */ | ||
1613 | static enum GNUNET_GenericReturnValue | ||
1614 | parse_configuration_file (void *cls, const char *filename) | ||
1615 | { | 2290 | { |
1616 | struct GNUNET_CONFIGURATION_Handle *cfg = cls; | 2291 | struct CollectFilesContext files_context = { |
1617 | char *ext; | 2292 | .files = NULL, |
2293 | .files_length = 0, | ||
2294 | }; | ||
2295 | enum GNUNET_GenericReturnValue fun_ret; | ||
1618 | 2296 | ||
1619 | /* Examine file extension */ | 2297 | if (GNUNET_SYSERR == |
1620 | ext = strrchr (filename, '.'); | 2298 | GNUNET_DISK_directory_scan (defaults_d, &collect_files_cb, |
1621 | if ((NULL == ext) || (0 != strcmp (ext, ".conf"))) | 2299 | &files_context)) |
2300 | return GNUNET_SYSERR; /* no configuration at all found */ | ||
2301 | qsort (files_context.files, | ||
2302 | files_context.files_length, | ||
2303 | sizeof (char *), | ||
2304 | pstrcmp); | ||
2305 | for (unsigned int i = 0; i < files_context.files_length; i++) | ||
1622 | { | 2306 | { |
1623 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Skipping file `%s'\n", filename); | 2307 | char *ext; |
1624 | return GNUNET_OK; | 2308 | const char *filename = files_context.files[i]; |
1625 | } | ||
1626 | 2309 | ||
1627 | return GNUNET_CONFIGURATION_parse (cfg, filename); | 2310 | /* Examine file extension */ |
2311 | ext = strrchr (filename, '.'); | ||
2312 | if ((NULL == ext) || (0 != strcmp (ext, ".conf"))) | ||
2313 | { | ||
2314 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Skipping file `%s'\n", filename); | ||
2315 | fun_ret = GNUNET_OK; | ||
2316 | goto cleanup; | ||
2317 | } | ||
2318 | fun_ret = GNUNET_CONFIGURATION_parse (cfg, filename); | ||
2319 | if (fun_ret != GNUNET_OK) | ||
2320 | break; | ||
2321 | } | ||
2322 | cleanup: | ||
2323 | if (files_context.files_length > 0) | ||
2324 | { | ||
2325 | for (size_t i = 0; i < files_context.files_length; i++) | ||
2326 | GNUNET_free (files_context.files[i]); | ||
2327 | GNUNET_array_grow (files_context.files, | ||
2328 | files_context.files_length, | ||
2329 | 0); | ||
2330 | } | ||
2331 | return fun_ret; | ||
1628 | } | 2332 | } |
1629 | 2333 | ||
1630 | 2334 | ||
1631 | enum GNUNET_GenericReturnValue | 2335 | char * |
1632 | GNUNET_CONFIGURATION_load_from (struct GNUNET_CONFIGURATION_Handle *cfg, | 2336 | GNUNET_CONFIGURATION_default_filename (void) |
1633 | const char *defaults_d) | ||
1634 | { | 2337 | { |
1635 | if (GNUNET_SYSERR == | 2338 | char *cfg_fn; |
1636 | GNUNET_DISK_directory_scan (defaults_d, &parse_configuration_file, cfg)) | 2339 | const struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get (); |
1637 | return GNUNET_SYSERR; /* no configuration at all found */ | 2340 | const char *xdg = getenv ("XDG_CONFIG_HOME"); |
1638 | return GNUNET_OK; | 2341 | |
2342 | if (NULL != xdg) | ||
2343 | GNUNET_asprintf (&cfg_fn, | ||
2344 | "%s%s%s", | ||
2345 | xdg, | ||
2346 | DIR_SEPARATOR_STR, | ||
2347 | pd->config_file); | ||
2348 | else | ||
2349 | cfg_fn = GNUNET_strdup (pd->user_config_file); | ||
2350 | |||
2351 | if (GNUNET_OK == GNUNET_DISK_file_test_read (cfg_fn)) | ||
2352 | return cfg_fn; | ||
2353 | GNUNET_free (cfg_fn); | ||
2354 | |||
2355 | /* Fall back to /etc/ for the default configuration. | ||
2356 | Should be okay to use forward slashes here. */ | ||
2357 | |||
2358 | GNUNET_asprintf (&cfg_fn, | ||
2359 | "/etc/%s", | ||
2360 | pd->config_file); | ||
2361 | if (GNUNET_OK == GNUNET_DISK_file_test_read (cfg_fn)) | ||
2362 | return cfg_fn; | ||
2363 | GNUNET_free (cfg_fn); | ||
2364 | |||
2365 | GNUNET_asprintf (&cfg_fn, | ||
2366 | "/etc/%s/%s", | ||
2367 | pd->project_dirname, | ||
2368 | pd->config_file); | ||
2369 | if (GNUNET_OK == GNUNET_DISK_file_test_read (cfg_fn)) | ||
2370 | return cfg_fn; | ||
2371 | |||
2372 | GNUNET_free (cfg_fn); | ||
2373 | return NULL; | ||
1639 | } | 2374 | } |
1640 | 2375 | ||
1641 | 2376 | ||
@@ -1648,12 +2383,47 @@ GNUNET_CONFIGURATION_default (void) | |||
1648 | char *cfgname = NULL; | 2383 | char *cfgname = NULL; |
1649 | struct GNUNET_CONFIGURATION_Handle *cfg; | 2384 | struct GNUNET_CONFIGURATION_Handle *cfg; |
1650 | 2385 | ||
2386 | /* FIXME: Why are we doing this? Needs some commentary! */ | ||
1651 | GNUNET_OS_init (dpd); | 2387 | GNUNET_OS_init (dpd); |
2388 | |||
1652 | cfg = GNUNET_CONFIGURATION_create (); | 2389 | cfg = GNUNET_CONFIGURATION_create (); |
2390 | |||
2391 | /* First, try user configuration. */ | ||
1653 | if (NULL != xdg) | 2392 | if (NULL != xdg) |
1654 | GNUNET_asprintf (&cfgname, "%s/%s", xdg, pd->config_file); | 2393 | GNUNET_asprintf (&cfgname, "%s/%s", xdg, pd->config_file); |
1655 | else | 2394 | else |
1656 | cfgname = GNUNET_strdup (pd->user_config_file); | 2395 | cfgname = GNUNET_strdup (pd->user_config_file); |
2396 | |||
2397 | /* If user config doesn't exist, try in | ||
2398 | /etc/<projdir>/<cfgfile> and /etc/<cfgfile> */ | ||
2399 | if (GNUNET_OK != GNUNET_DISK_file_test (cfgname)) | ||
2400 | { | ||
2401 | GNUNET_free (cfgname); | ||
2402 | GNUNET_asprintf (&cfgname, "/etc/%s", pd->config_file); | ||
2403 | } | ||
2404 | if (GNUNET_OK != GNUNET_DISK_file_test (cfgname)) | ||
2405 | { | ||
2406 | GNUNET_free (cfgname); | ||
2407 | GNUNET_asprintf (&cfgname, | ||
2408 | "/etc/%s/%s", | ||
2409 | pd->project_dirname, | ||
2410 | pd->config_file); | ||
2411 | } | ||
2412 | if (GNUNET_OK != GNUNET_DISK_file_test (cfgname)) | ||
2413 | { | ||
2414 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
2415 | "Unable to top-level configuration file.\n"); | ||
2416 | GNUNET_OS_init (pd); | ||
2417 | GNUNET_CONFIGURATION_destroy (cfg); | ||
2418 | GNUNET_free (cfgname); | ||
2419 | return NULL; | ||
2420 | } | ||
2421 | |||
2422 | /* We found a configuration file that looks good, try to load it. */ | ||
2423 | |||
2424 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2425 | "Loading top-level configuration from '%s'\n", | ||
2426 | cfgname); | ||
1657 | if (GNUNET_OK != | 2427 | if (GNUNET_OK != |
1658 | GNUNET_CONFIGURATION_load (cfg, cfgname)) | 2428 | GNUNET_CONFIGURATION_load (cfg, cfgname)) |
1659 | { | 2429 | { |
@@ -1668,4 +2438,84 @@ GNUNET_CONFIGURATION_default (void) | |||
1668 | } | 2438 | } |
1669 | 2439 | ||
1670 | 2440 | ||
2441 | /** | ||
2442 | * Load configuration (starts with defaults, then loads | ||
2443 | * system-specific configuration). | ||
2444 | * | ||
2445 | * @param cfg configuration to update | ||
2446 | * @param filename name of the configuration file, NULL to load defaults | ||
2447 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on error | ||
2448 | */ | ||
2449 | int | ||
2450 | GNUNET_CONFIGURATION_load (struct GNUNET_CONFIGURATION_Handle *cfg, | ||
2451 | const char *filename) | ||
2452 | { | ||
2453 | char *baseconfig; | ||
2454 | const char *base_config_varname; | ||
2455 | |||
2456 | if (cfg->load_called) | ||
2457 | { | ||
2458 | /* FIXME: Make this a GNUNET_assert later */ | ||
2459 | GNUNET_break (0); | ||
2460 | GNUNET_free (cfg->main_filename); | ||
2461 | } | ||
2462 | cfg->load_called = true; | ||
2463 | if (NULL != filename) | ||
2464 | { | ||
2465 | GNUNET_free (cfg->main_filename); | ||
2466 | cfg->main_filename = GNUNET_strdup (filename); | ||
2467 | } | ||
2468 | |||
2469 | base_config_varname = GNUNET_OS_project_data_get ()->base_config_varname; | ||
2470 | |||
2471 | if ((NULL != base_config_varname) | ||
2472 | && (NULL != (baseconfig = getenv (base_config_varname)))) | ||
2473 | { | ||
2474 | baseconfig = GNUNET_strdup (baseconfig); | ||
2475 | } | ||
2476 | else | ||
2477 | { | ||
2478 | char *ipath; | ||
2479 | |||
2480 | ipath = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR); | ||
2481 | if (NULL == ipath) | ||
2482 | { | ||
2483 | GNUNET_break (0); | ||
2484 | return GNUNET_SYSERR; | ||
2485 | } | ||
2486 | GNUNET_asprintf (&baseconfig, "%s%s", ipath, "config.d"); | ||
2487 | GNUNET_free (ipath); | ||
2488 | } | ||
2489 | |||
2490 | char *dname = GNUNET_STRINGS_filename_expand (baseconfig); | ||
2491 | GNUNET_free (baseconfig); | ||
2492 | |||
2493 | if ((GNUNET_YES == GNUNET_DISK_directory_test (dname, GNUNET_YES)) && | ||
2494 | (GNUNET_SYSERR == GNUNET_CONFIGURATION_load_from (cfg, dname))) | ||
2495 | { | ||
2496 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
2497 | "Failed to load base configuration from '%s'\n", | ||
2498 | filename); | ||
2499 | GNUNET_free (dname); | ||
2500 | return GNUNET_SYSERR; /* no configuration at all found */ | ||
2501 | } | ||
2502 | GNUNET_free (dname); | ||
2503 | if ((NULL != filename) && | ||
2504 | (GNUNET_OK != GNUNET_CONFIGURATION_parse (cfg, filename))) | ||
2505 | { | ||
2506 | /* specified configuration not found */ | ||
2507 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
2508 | "Failed to load configuration from file '%s'\n", | ||
2509 | filename); | ||
2510 | return GNUNET_SYSERR; | ||
2511 | } | ||
2512 | if (((GNUNET_YES != | ||
2513 | GNUNET_CONFIGURATION_have_value (cfg, "PATHS", "DEFAULTCONFIG"))) && | ||
2514 | (filename != NULL)) | ||
2515 | GNUNET_CONFIGURATION_set_value_string (cfg, "PATHS", "DEFAULTCONFIG", | ||
2516 | filename); | ||
2517 | return GNUNET_OK; | ||
2518 | } | ||
2519 | |||
2520 | |||
1671 | /* end of configuration.c */ | 2521 | /* end of configuration.c */ |
diff --git a/src/util/configuration_helper.c b/src/util/configuration_helper.c new file mode 100644 index 000000000..8f995ec03 --- /dev/null +++ b/src/util/configuration_helper.c | |||
@@ -0,0 +1,302 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2006, 2007, 2008, 2009, 2013, 2020, 2021 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 | * @file src/util/configuration_helper.c | ||
22 | * @brief helper logic for gnunet-config | ||
23 | * @author Christian Grothoff | ||
24 | */ | ||
25 | #include "platform.h" | ||
26 | #include "gnunet_util_lib.h" | ||
27 | |||
28 | /** | ||
29 | * Print each option in a given section as a filename. | ||
30 | * | ||
31 | * @param cls closure | ||
32 | * @param section name of the section | ||
33 | * @param option name of the option | ||
34 | * @param value value of the option | ||
35 | */ | ||
36 | static void | ||
37 | print_filename_option (void *cls, | ||
38 | const char *section, | ||
39 | const char *option, | ||
40 | const char *value) | ||
41 | { | ||
42 | const struct GNUNET_CONFIGURATION_Handle *cfg = cls; | ||
43 | |||
44 | char *value_fn; | ||
45 | char *fn; | ||
46 | |||
47 | GNUNET_assert (GNUNET_OK == | ||
48 | GNUNET_CONFIGURATION_get_value_filename (cfg, | ||
49 | section, | ||
50 | option, | ||
51 | &value_fn)); | ||
52 | fn = GNUNET_STRINGS_filename_expand (value_fn); | ||
53 | if (NULL == fn) | ||
54 | fn = value_fn; | ||
55 | else | ||
56 | GNUNET_free (value_fn); | ||
57 | fprintf (stdout, | ||
58 | "%s = %s\n", | ||
59 | option, | ||
60 | fn); | ||
61 | GNUNET_free (fn); | ||
62 | } | ||
63 | |||
64 | |||
65 | /** | ||
66 | * Print each option in a given section. | ||
67 | * | ||
68 | * @param cls closure | ||
69 | * @param section name of the section | ||
70 | * @param option name of the option | ||
71 | * @param value value of the option | ||
72 | */ | ||
73 | static void | ||
74 | print_option (void *cls, | ||
75 | const char *section, | ||
76 | const char *option, | ||
77 | const char *value) | ||
78 | { | ||
79 | (void) cls; | ||
80 | (void) section; | ||
81 | |||
82 | fprintf (stdout, | ||
83 | "%s = %s\n", | ||
84 | option, | ||
85 | value); | ||
86 | } | ||
87 | |||
88 | |||
89 | /** | ||
90 | * Print out given section name. | ||
91 | * | ||
92 | * @param cls unused | ||
93 | * @param section a section in the configuration file | ||
94 | */ | ||
95 | static void | ||
96 | print_section_name (void *cls, | ||
97 | const char *section) | ||
98 | { | ||
99 | (void) cls; | ||
100 | fprintf (stdout, | ||
101 | "%s\n", | ||
102 | section); | ||
103 | } | ||
104 | |||
105 | |||
106 | void | ||
107 | GNUNET_CONFIGURATION_config_tool_run ( | ||
108 | void *cls, | ||
109 | char *const *args, | ||
110 | const char *cfgfile, | ||
111 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
112 | { | ||
113 | struct GNUNET_CONFIGURATION_ConfigSettings *cs = cls; | ||
114 | struct GNUNET_CONFIGURATION_Handle *out = NULL; | ||
115 | struct GNUNET_CONFIGURATION_Handle *ncfg = NULL; | ||
116 | |||
117 | (void) args; | ||
118 | if (cs->diagnostics) | ||
119 | { | ||
120 | /* Re-parse the configuration with diagnostics enabled. */ | ||
121 | ncfg = GNUNET_CONFIGURATION_create (); | ||
122 | GNUNET_CONFIGURATION_enable_diagnostics (ncfg); | ||
123 | GNUNET_CONFIGURATION_load (ncfg, | ||
124 | cfgfile); | ||
125 | cfg = ncfg; | ||
126 | } | ||
127 | |||
128 | if (cs->full) | ||
129 | cs->rewrite = GNUNET_YES; | ||
130 | if (cs->list_sections) | ||
131 | { | ||
132 | fprintf (stderr, | ||
133 | _ ("The following sections are available:\n")); | ||
134 | GNUNET_CONFIGURATION_iterate_sections (cfg, | ||
135 | &print_section_name, | ||
136 | NULL); | ||
137 | return; | ||
138 | } | ||
139 | if ( (! cs->rewrite) && | ||
140 | (NULL == cs->section) ) | ||
141 | { | ||
142 | char *serialization; | ||
143 | |||
144 | if (! cs->diagnostics) | ||
145 | { | ||
146 | fprintf (stderr, | ||
147 | _ ("%s, %s or %s argument is required\n"), | ||
148 | "--section", | ||
149 | "--list-sections", | ||
150 | "--diagnostics"); | ||
151 | cs->global_ret = EXIT_INVALIDARGUMENT; | ||
152 | return; | ||
153 | } | ||
154 | serialization = GNUNET_CONFIGURATION_serialize_diagnostics (cfg); | ||
155 | fprintf (stdout, | ||
156 | "%s", | ||
157 | serialization); | ||
158 | GNUNET_free (serialization); | ||
159 | } | ||
160 | else if ( (NULL != cs->section) && | ||
161 | (NULL == cs->value) ) | ||
162 | { | ||
163 | if (NULL == cs->option) | ||
164 | { | ||
165 | GNUNET_CONFIGURATION_iterate_section_values ( | ||
166 | cfg, | ||
167 | cs->section, | ||
168 | cs->is_filename | ||
169 | ? &print_filename_option | ||
170 | : &print_option, | ||
171 | (void *) cfg); | ||
172 | } | ||
173 | else | ||
174 | { | ||
175 | char *value; | ||
176 | |||
177 | if (cs->is_filename) | ||
178 | { | ||
179 | if (GNUNET_OK != | ||
180 | GNUNET_CONFIGURATION_get_value_filename (cfg, | ||
181 | cs->section, | ||
182 | cs->option, | ||
183 | &value)) | ||
184 | { | ||
185 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, | ||
186 | cs->section, | ||
187 | cs->option); | ||
188 | cs->global_ret = EXIT_NOTCONFIGURED; | ||
189 | return; | ||
190 | } | ||
191 | } | ||
192 | else | ||
193 | { | ||
194 | if (GNUNET_OK != | ||
195 | GNUNET_CONFIGURATION_get_value_string (cfg, | ||
196 | cs->section, | ||
197 | cs->option, | ||
198 | &value)) | ||
199 | { | ||
200 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, | ||
201 | cs->section, | ||
202 | cs->option); | ||
203 | cs->global_ret = EXIT_NOTCONFIGURED; | ||
204 | return; | ||
205 | } | ||
206 | } | ||
207 | fprintf (stdout, | ||
208 | "%s\n", | ||
209 | value); | ||
210 | GNUNET_free (value); | ||
211 | } | ||
212 | } | ||
213 | else if (NULL != cs->section) | ||
214 | { | ||
215 | if (NULL == cs->option) | ||
216 | { | ||
217 | fprintf (stderr, | ||
218 | _ ("--option argument required to set value\n")); | ||
219 | cs->global_ret = EXIT_INVALIDARGUMENT; | ||
220 | return; | ||
221 | } | ||
222 | out = GNUNET_CONFIGURATION_dup (cfg); | ||
223 | GNUNET_CONFIGURATION_set_value_string (out, | ||
224 | cs->section, | ||
225 | cs->option, | ||
226 | cs->value); | ||
227 | cs->rewrite = GNUNET_YES; | ||
228 | } | ||
229 | if (cs->rewrite) | ||
230 | { | ||
231 | char *cfg_fn = NULL; | ||
232 | |||
233 | if (NULL == out) | ||
234 | out = GNUNET_CONFIGURATION_dup (cfg); | ||
235 | |||
236 | if (NULL == cfgfile) | ||
237 | { | ||
238 | const char *xdg = getenv ("XDG_CONFIG_HOME"); | ||
239 | |||
240 | if (NULL != xdg) | ||
241 | GNUNET_asprintf (&cfg_fn, | ||
242 | "%s%s%s", | ||
243 | xdg, | ||
244 | DIR_SEPARATOR_STR, | ||
245 | GNUNET_OS_project_data_get ()->config_file); | ||
246 | else | ||
247 | cfg_fn = GNUNET_strdup ( | ||
248 | GNUNET_OS_project_data_get ()->user_config_file); | ||
249 | cfgfile = cfg_fn; | ||
250 | } | ||
251 | |||
252 | if (! cs->full) | ||
253 | { | ||
254 | struct GNUNET_CONFIGURATION_Handle *def; | ||
255 | |||
256 | def = GNUNET_CONFIGURATION_create (); | ||
257 | if (GNUNET_OK != | ||
258 | GNUNET_CONFIGURATION_load (def, | ||
259 | NULL)) | ||
260 | { | ||
261 | fprintf (stderr, | ||
262 | _ ("failed to load configuration defaults")); | ||
263 | cs->global_ret = 1; | ||
264 | GNUNET_CONFIGURATION_destroy (def); | ||
265 | GNUNET_CONFIGURATION_destroy (out); | ||
266 | GNUNET_free (cfg_fn); | ||
267 | return; | ||
268 | } | ||
269 | if (GNUNET_OK != | ||
270 | GNUNET_CONFIGURATION_write_diffs (def, | ||
271 | out, | ||
272 | cfgfile)) | ||
273 | cs->global_ret = 2; | ||
274 | GNUNET_CONFIGURATION_destroy (def); | ||
275 | } | ||
276 | else | ||
277 | { | ||
278 | if (GNUNET_OK != | ||
279 | GNUNET_CONFIGURATION_write (out, | ||
280 | cfgfile)) | ||
281 | cs->global_ret = 2; | ||
282 | } | ||
283 | GNUNET_free (cfg_fn); | ||
284 | } | ||
285 | if (NULL != out) | ||
286 | GNUNET_CONFIGURATION_destroy (out); | ||
287 | if (NULL != ncfg) | ||
288 | GNUNET_CONFIGURATION_destroy (ncfg); | ||
289 | } | ||
290 | |||
291 | |||
292 | void | ||
293 | GNUNET_CONFIGURATION_config_settings_free ( | ||
294 | struct GNUNET_CONFIGURATION_ConfigSettings *cs) | ||
295 | { | ||
296 | GNUNET_free (cs->option); | ||
297 | GNUNET_free (cs->section); | ||
298 | GNUNET_free (cs->value); | ||
299 | } | ||
300 | |||
301 | |||
302 | /* end of configuration_helper.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 | */ | ||
41 | int | ||
42 | GNUNET_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/crypto_hkdf.c b/src/util/crypto_hkdf.c index 86a814b12..7270b87b6 100644 --- a/src/util/crypto_hkdf.c +++ b/src/util/crypto_hkdf.c | |||
@@ -77,7 +77,11 @@ static const void * | |||
77 | doHMAC (gcry_md_hd_t mac, const void *key, size_t key_len, const void *buf, | 77 | doHMAC (gcry_md_hd_t mac, const void *key, size_t key_len, const void *buf, |
78 | size_t buf_len) | 78 | size_t buf_len) |
79 | { | 79 | { |
80 | gcry_md_setkey (mac, key, key_len); | 80 | if (GPG_ERR_NO_ERROR != gcry_md_setkey (mac, key, key_len)) |
81 | { | ||
82 | GNUNET_break (0); | ||
83 | return NULL; | ||
84 | } | ||
81 | gcry_md_write (mac, buf, buf_len); | 85 | gcry_md_write (mac, buf, buf_len); |
82 | 86 | ||
83 | return (const void *) gcry_md_read (mac, 0); | 87 | return (const void *) gcry_md_read (mac, 0); |
diff --git a/src/util/disk.c b/src/util/disk.c index 3bafe311d..2efb52d46 100644 --- a/src/util/disk.c +++ b/src/util/disk.c | |||
@@ -432,9 +432,15 @@ GNUNET_DISK_directory_test (const char *fil, int is_readable) | |||
432 | return GNUNET_YES; | 432 | return GNUNET_YES; |
433 | } | 433 | } |
434 | 434 | ||
435 | 435 | /** | |
436 | enum GNUNET_GenericReturnValue | 436 | * Check if fil can be accessed using amode. |
437 | GNUNET_DISK_file_test (const char *fil) | 437 | * |
438 | * @param fil file to check for | ||
439 | * @param amode access mode | ||
440 | * @returns GNUnet error code | ||
441 | */ | ||
442 | static enum GNUNET_GenericReturnValue | ||
443 | file_test_internal (const char *fil, int amode) | ||
438 | { | 444 | { |
439 | struct stat filestat; | 445 | struct stat filestat; |
440 | int ret; | 446 | int ret; |
@@ -449,7 +455,7 @@ GNUNET_DISK_file_test (const char *fil) | |||
449 | { | 455 | { |
450 | if (errno != ENOENT) | 456 | if (errno != ENOENT) |
451 | { | 457 | { |
452 | LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "stat", rdir); | 458 | LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_DEBUG, "stat", rdir); |
453 | GNUNET_free (rdir); | 459 | GNUNET_free (rdir); |
454 | return GNUNET_SYSERR; | 460 | return GNUNET_SYSERR; |
455 | } | 461 | } |
@@ -461,9 +467,9 @@ GNUNET_DISK_file_test (const char *fil) | |||
461 | GNUNET_free (rdir); | 467 | GNUNET_free (rdir); |
462 | return GNUNET_NO; | 468 | return GNUNET_NO; |
463 | } | 469 | } |
464 | if (access (rdir, F_OK) < 0) | 470 | if (access (rdir, amode) < 0) |
465 | { | 471 | { |
466 | LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "access", rdir); | 472 | LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_DEBUG, "access", rdir); |
467 | GNUNET_free (rdir); | 473 | GNUNET_free (rdir); |
468 | return GNUNET_SYSERR; | 474 | return GNUNET_SYSERR; |
469 | } | 475 | } |
@@ -473,6 +479,20 @@ GNUNET_DISK_file_test (const char *fil) | |||
473 | 479 | ||
474 | 480 | ||
475 | enum GNUNET_GenericReturnValue | 481 | enum GNUNET_GenericReturnValue |
482 | GNUNET_DISK_file_test (const char *fil) | ||
483 | { | ||
484 | return file_test_internal (fil, F_OK); | ||
485 | } | ||
486 | |||
487 | |||
488 | enum GNUNET_GenericReturnValue | ||
489 | GNUNET_DISK_file_test_read (const char *fil) | ||
490 | { | ||
491 | return file_test_internal (fil, R_OK); | ||
492 | } | ||
493 | |||
494 | |||
495 | enum GNUNET_GenericReturnValue | ||
476 | GNUNET_DISK_directory_create (const char *dir) | 496 | GNUNET_DISK_directory_create (const char *dir) |
477 | { | 497 | { |
478 | char *rdir; | 498 | char *rdir; |
@@ -882,6 +902,166 @@ GNUNET_DISK_directory_scan (const char *dir_name, | |||
882 | return count; | 902 | return count; |
883 | } | 903 | } |
884 | 904 | ||
905 | /** | ||
906 | * Check for a simple wildcard match. | ||
907 | * Only asterisks are allowed. | ||
908 | * Asterisks match everything, including slashes. | ||
909 | * | ||
910 | * @param pattern pattern with wildcards | ||
911 | * @param str string to match against | ||
912 | * @returns true on match, false otherwise | ||
913 | */ | ||
914 | static bool | ||
915 | glob_match (const char *pattern, const char *str) | ||
916 | { | ||
917 | /* Position in the input string */ | ||
918 | const char *str_pos = str; | ||
919 | /* Position in the pattern */ | ||
920 | const char *pat_pos = pattern; | ||
921 | /* Backtrack position in string */ | ||
922 | const char *str_bt = NULL; | ||
923 | /* Backtrack position in pattern */ | ||
924 | const char *pat_bt = NULL; | ||
925 | |||
926 | for (;;) | ||
927 | { | ||
928 | if (*pat_pos == '*') | ||
929 | { | ||
930 | str_bt = str_pos; | ||
931 | pat_bt = pat_pos++; | ||
932 | } | ||
933 | else if (*pat_pos == *str_pos) | ||
934 | { | ||
935 | if ('\0' == *pat_pos) | ||
936 | return true; | ||
937 | str_pos++; | ||
938 | pat_pos++; | ||
939 | } | ||
940 | else | ||
941 | { | ||
942 | if (NULL == str_bt) | ||
943 | return false; | ||
944 | /* Backtrack to match one more | ||
945 | character as part of the asterisk. */ | ||
946 | str_pos = str_bt + 1; | ||
947 | if ('\0' == *str_pos) | ||
948 | return false; | ||
949 | pat_pos = pat_bt; | ||
950 | } | ||
951 | } | ||
952 | } | ||
953 | |||
954 | struct GlobClosure | ||
955 | { | ||
956 | const char *glob; | ||
957 | GNUNET_FileNameCallback cb; | ||
958 | void *cls; | ||
959 | |||
960 | /** | ||
961 | * Number of files that actually matched the glob pattern. | ||
962 | */ | ||
963 | int nres; | ||
964 | }; | ||
965 | |||
966 | /** | ||
967 | * Function called with a filename. | ||
968 | * | ||
969 | * @param cls closure | ||
970 | * @param filename complete filename (absolute path) | ||
971 | * @return #GNUNET_OK to continue to iterate, | ||
972 | * #GNUNET_NO to stop iteration with no error, | ||
973 | * #GNUNET_SYSERR to abort iteration with error! | ||
974 | */ | ||
975 | static enum GNUNET_GenericReturnValue | ||
976 | glob_cb (void *cls, | ||
977 | const char *filename) | ||
978 | { | ||
979 | struct GlobClosure *gc = cls; | ||
980 | const char *fn; | ||
981 | |||
982 | fn = strrchr (filename, DIR_SEPARATOR); | ||
983 | fn = (NULL == fn) ? filename : (fn + 1); | ||
984 | |||
985 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
986 | "checking glob '%s' against '%s'\n", | ||
987 | gc->glob, | ||
988 | fn); | ||
989 | |||
990 | if (glob_match (gc->glob, fn)) | ||
991 | { | ||
992 | enum GNUNET_GenericReturnValue cbret; | ||
993 | |||
994 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
995 | "found glob match '%s'\n", | ||
996 | filename); | ||
997 | gc->nres++; | ||
998 | cbret = gc->cb (gc->cls, filename); | ||
999 | if (GNUNET_OK != cbret) | ||
1000 | return cbret; | ||
1001 | } | ||
1002 | return GNUNET_OK; | ||
1003 | } | ||
1004 | |||
1005 | |||
1006 | int | ||
1007 | GNUNET_DISK_glob (const char *glob_pattern, | ||
1008 | GNUNET_FileNameCallback callback, | ||
1009 | void *callback_cls) | ||
1010 | { | ||
1011 | char *mypat = GNUNET_strdup (glob_pattern); | ||
1012 | char *sep; | ||
1013 | int ret; | ||
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 | GNUNET_free (mypat); | ||
1024 | return -1; | ||
1025 | } | ||
1026 | |||
1027 | sep = strrchr (mypat, DIR_SEPARATOR); | ||
1028 | if (NULL == sep) | ||
1029 | { | ||
1030 | GNUNET_free (mypat); | ||
1031 | return -1; | ||
1032 | } | ||
1033 | |||
1034 | *sep = '\0'; | ||
1035 | |||
1036 | if (NULL != strchr (mypat, '*')) | ||
1037 | { | ||
1038 | GNUNET_free (mypat); | ||
1039 | GNUNET_break (0); | ||
1040 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1041 | "glob pattern may only contain '*' in the final path component\n"); | ||
1042 | return -1; | ||
1043 | } | ||
1044 | |||
1045 | { | ||
1046 | struct GlobClosure gc = { | ||
1047 | .glob = sep + 1, | ||
1048 | .cb = callback, | ||
1049 | .cls = callback_cls, | ||
1050 | .nres = 0, | ||
1051 | }; | ||
1052 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1053 | "scanning directory '%s' for glob matches on '%s'\n", | ||
1054 | mypat, | ||
1055 | gc.glob); | ||
1056 | ret = GNUNET_DISK_directory_scan (mypat, | ||
1057 | glob_cb, | ||
1058 | &gc | ||
1059 | ); | ||
1060 | GNUNET_free (mypat); | ||
1061 | return (ret < 0) ? ret : gc.nres; | ||
1062 | } | ||
1063 | } | ||
1064 | |||
885 | 1065 | ||
886 | /** | 1066 | /** |
887 | * Function that removes the given directory by calling | 1067 | * Function that removes the given directory by calling |
@@ -997,7 +1177,7 @@ GNUNET_DISK_file_copy (const char *src, | |||
997 | GNUNET_DISK_file_close (in); | 1177 | GNUNET_DISK_file_close (in); |
998 | GNUNET_DISK_file_close (out); | 1178 | GNUNET_DISK_file_close (out); |
999 | return GNUNET_OK; | 1179 | return GNUNET_OK; |
1000 | FAIL: | 1180 | FAIL: |
1001 | GNUNET_free (buf); | 1181 | GNUNET_free (buf); |
1002 | GNUNET_DISK_file_close (in); | 1182 | GNUNET_DISK_file_close (in); |
1003 | GNUNET_DISK_file_close (out); | 1183 | GNUNET_DISK_file_close (out); |
diff --git a/src/util/gnunet-config.c b/src/util/gnunet-config.c index 11682daea..a195d6014 100644 --- a/src/util/gnunet-config.c +++ b/src/util/gnunet-config.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | Copyright (C) 2012 GNUnet e.V. | 3 | Copyright (C) 2012-2021 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software: you can redistribute it and/or modify it | 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 | 6 | under the terms of the GNU Affero General Public License as published |
@@ -28,51 +28,12 @@ | |||
28 | 28 | ||
29 | 29 | ||
30 | /** | 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 | 31 | * Backend to check if the respective plugin is |
47 | * loadable. NULL if no check is to be performed. | 32 | * loadable. NULL if no check is to be performed. |
48 | * The value is the "basename" of the plugin to load. | 33 | * The value is the "basename" of the plugin to load. |
49 | */ | 34 | */ |
50 | static char *backend_check; | 35 | static char *backend_check; |
51 | 36 | ||
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 write out the configuration file, even if no value was changed? | ||
69 | */ | ||
70 | static int rewrite; | ||
71 | |||
72 | /** | ||
73 | * Should the generated configuration file contain the whole configuration? | ||
74 | */ | ||
75 | static int full; | ||
76 | 37 | ||
77 | /** | 38 | /** |
78 | * If printing the value of CFLAGS has been requested. | 39 | * If printing the value of CFLAGS has been requested. |
@@ -92,64 +53,11 @@ static int prefix; | |||
92 | 53 | ||
93 | /** | 54 | /** |
94 | * Print each option in a given section. | 55 | * Print each option in a given section. |
56 | * Main task to run to perform operations typical for | ||
57 | * gnunet-config as per the configuration settings | ||
58 | * given in @a cls. | ||
95 | * | 59 | * |
96 | * @param cls closure | 60 | * @param cls closure with the `struct GNUNET_CONFIGURATION_ConfigSettings` |
97 | * @param section name of the section | ||
98 | * @param option name of the option | ||
99 | * @param value value of the option | ||
100 | */ | ||
101 | static void | ||
102 | print_option (void *cls, | ||
103 | const char *section, | ||
104 | const char *option, | ||
105 | const char *value) | ||
106 | { | ||
107 | const struct GNUNET_CONFIGURATION_Handle *cfg = cls; | ||
108 | |||
109 | (void) section; | ||
110 | if (is_filename) | ||
111 | { | ||
112 | char *value_fn; | ||
113 | char *fn; | ||
114 | |||
115 | GNUNET_assert (GNUNET_OK == | ||
116 | GNUNET_CONFIGURATION_get_value_filename (cfg, | ||
117 | section, | ||
118 | option, | ||
119 | &value_fn)); | ||
120 | fn = GNUNET_STRINGS_filename_expand (value_fn); | ||
121 | if (NULL == fn) | ||
122 | fn = value_fn; | ||
123 | else | ||
124 | GNUNET_free (value_fn); | ||
125 | fprintf (stdout, "%s = %s\n", option, fn); | ||
126 | GNUNET_free (fn); | ||
127 | } | ||
128 | else | ||
129 | { | ||
130 | fprintf (stdout, "%s = %s\n", option, value); | ||
131 | } | ||
132 | } | ||
133 | |||
134 | |||
135 | /** | ||
136 | * Print out given section name. | ||
137 | * | ||
138 | * @param cls unused | ||
139 | * @param section a section in the configuration file | ||
140 | */ | ||
141 | static void | ||
142 | print_section_name (void *cls, const char *section) | ||
143 | { | ||
144 | (void) cls; | ||
145 | fprintf (stdout, "%s\n", section); | ||
146 | } | ||
147 | |||
148 | |||
149 | /** | ||
150 | * Main function that will be run by the scheduler. | ||
151 | * | ||
152 | * @param cls closure | ||
153 | * @param args remaining command-line arguments | 61 | * @param args remaining command-line arguments |
154 | * @param cfgfile name of the configuration file used (for saving, | 62 | * @param cfgfile name of the configuration file used (for saving, |
155 | * can be NULL!) | 63 | * can be NULL!) |
@@ -161,10 +69,8 @@ run (void *cls, | |||
161 | const char *cfgfile, | 69 | const char *cfgfile, |
162 | const struct GNUNET_CONFIGURATION_Handle *cfg) | 70 | const struct GNUNET_CONFIGURATION_Handle *cfg) |
163 | { | 71 | { |
164 | struct GNUNET_CONFIGURATION_Handle *out = NULL; | 72 | struct GNUNET_CONFIGURATION_ConfigSettings *cs = cls; |
165 | 73 | ||
166 | (void) cls; | ||
167 | (void) args; | ||
168 | if (1 == cflags || 1 == libs || 1 == prefix) | 74 | if (1 == cflags || 1 == libs || 1 == prefix) |
169 | { | 75 | { |
170 | char *prefixdir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_PREFIX); | 76 | char *prefixdir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_PREFIX); |
@@ -192,153 +98,15 @@ run (void *cls, | |||
192 | GNUNET_asprintf (&name, | 98 | GNUNET_asprintf (&name, |
193 | "libgnunet_plugin_%s", | 99 | "libgnunet_plugin_%s", |
194 | backend_check); | 100 | backend_check); |
195 | global_ret = (GNUNET_OK == | 101 | cs->global_ret = (GNUNET_OK == |
196 | GNUNET_PLUGIN_test (name)) ? 0 : 77; | 102 | GNUNET_PLUGIN_test (name)) ? 0 : 77; |
197 | GNUNET_free (name); | 103 | GNUNET_free (name); |
198 | return; | 104 | return; |
199 | } | 105 | } |
200 | if (full) | 106 | GNUNET_CONFIGURATION_config_tool_run (cs, |
201 | rewrite = GNUNET_YES; | 107 | args, |
202 | if (list_sections) | 108 | cfgfile, |
203 | { | 109 | cfg); |
204 | fprintf (stderr, | ||
205 | _ ("The following sections are available:\n")); | ||
206 | GNUNET_CONFIGURATION_iterate_sections (cfg, | ||
207 | &print_section_name, | ||
208 | NULL); | ||
209 | return; | ||
210 | } | ||
211 | if ( (! rewrite) && | ||
212 | (NULL == section) ) | ||
213 | { | ||
214 | fprintf (stderr, | ||
215 | _ ("%s or %s argument is required\n"), | ||
216 | "--section", | ||
217 | "--list-sections"); | ||
218 | global_ret = 1; | ||
219 | return; | ||
220 | } | ||
221 | |||
222 | if ( (NULL != section) && | ||
223 | (NULL == value) ) | ||
224 | { | ||
225 | if (NULL == option) | ||
226 | { | ||
227 | GNUNET_CONFIGURATION_iterate_section_values (cfg, | ||
228 | section, | ||
229 | &print_option, | ||
230 | (void *) cfg); | ||
231 | } | ||
232 | else | ||
233 | { | ||
234 | if (is_filename) | ||
235 | { | ||
236 | if (GNUNET_OK != | ||
237 | GNUNET_CONFIGURATION_get_value_filename (cfg, | ||
238 | section, | ||
239 | option, | ||
240 | &value)) | ||
241 | { | ||
242 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, | ||
243 | section, | ||
244 | option); | ||
245 | global_ret = 3; | ||
246 | return; | ||
247 | } | ||
248 | } | ||
249 | else | ||
250 | { | ||
251 | if (GNUNET_OK != | ||
252 | GNUNET_CONFIGURATION_get_value_string (cfg, | ||
253 | section, | ||
254 | option, | ||
255 | &value)) | ||
256 | { | ||
257 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, | ||
258 | section, | ||
259 | option); | ||
260 | global_ret = 3; | ||
261 | return; | ||
262 | } | ||
263 | } | ||
264 | fprintf (stdout, | ||
265 | "%s\n", | ||
266 | value); | ||
267 | } | ||
268 | } | ||
269 | else if (NULL != section) | ||
270 | { | ||
271 | if (NULL == option) | ||
272 | { | ||
273 | fprintf (stderr, | ||
274 | _ ("--option argument required to set value\n")); | ||
275 | global_ret = 1; | ||
276 | return; | ||
277 | } | ||
278 | out = GNUNET_CONFIGURATION_dup (cfg); | ||
279 | GNUNET_CONFIGURATION_set_value_string (out, | ||
280 | section, | ||
281 | option, | ||
282 | value); | ||
283 | rewrite = GNUNET_YES; | ||
284 | } | ||
285 | if (rewrite) | ||
286 | { | ||
287 | char *cfg_fn = NULL; | ||
288 | |||
289 | if (NULL == out) | ||
290 | out = GNUNET_CONFIGURATION_dup (cfg); | ||
291 | |||
292 | if (NULL == cfgfile) | ||
293 | { | ||
294 | const char *xdg = getenv ("XDG_CONFIG_HOME"); | ||
295 | if (NULL != xdg) | ||
296 | GNUNET_asprintf (&cfg_fn, | ||
297 | "%s%s%s", | ||
298 | xdg, | ||
299 | DIR_SEPARATOR_STR, | ||
300 | GNUNET_OS_project_data_get ()->config_file); | ||
301 | else | ||
302 | cfg_fn = GNUNET_strdup ( | ||
303 | GNUNET_OS_project_data_get ()->user_config_file); | ||
304 | cfgfile = cfg_fn; | ||
305 | } | ||
306 | |||
307 | if (! full) | ||
308 | { | ||
309 | struct GNUNET_CONFIGURATION_Handle *def; | ||
310 | |||
311 | def = GNUNET_CONFIGURATION_create (); | ||
312 | if (GNUNET_OK != | ||
313 | GNUNET_CONFIGURATION_load (def, | ||
314 | NULL)) | ||
315 | { | ||
316 | fprintf (stderr, | ||
317 | _ ("failed to load configuration defaults")); | ||
318 | global_ret = 1; | ||
319 | GNUNET_CONFIGURATION_destroy (def); | ||
320 | GNUNET_CONFIGURATION_destroy (out); | ||
321 | GNUNET_free (cfg_fn); | ||
322 | return; | ||
323 | } | ||
324 | if (GNUNET_OK != | ||
325 | GNUNET_CONFIGURATION_write_diffs (def, | ||
326 | out, | ||
327 | cfgfile)) | ||
328 | global_ret = 2; | ||
329 | GNUNET_CONFIGURATION_destroy (def); | ||
330 | } | ||
331 | else | ||
332 | { | ||
333 | if (GNUNET_OK != | ||
334 | GNUNET_CONFIGURATION_write (out, | ||
335 | cfgfile)) | ||
336 | global_ret = 2; | ||
337 | } | ||
338 | GNUNET_free (cfg_fn); | ||
339 | } | ||
340 | if (NULL != out) | ||
341 | GNUNET_CONFIGURATION_destroy (out); | ||
342 | } | 110 | } |
343 | 111 | ||
344 | 112 | ||
@@ -350,8 +118,13 @@ run (void *cls, | |||
350 | * @return 0 ok, 1 on error | 118 | * @return 0 ok, 1 on error |
351 | */ | 119 | */ |
352 | int | 120 | int |
353 | main (int argc, char *const *argv) | 121 | main (int argc, |
122 | char *const *argv) | ||
354 | { | 123 | { |
124 | struct GNUNET_CONFIGURATION_ConfigSettings cs = { | ||
125 | .api_version = GNUNET_UTIL_VERSION, | ||
126 | .global_ret = EXIT_SUCCESS | ||
127 | }; | ||
355 | struct GNUNET_GETOPT_CommandLineOption options[] = { | 128 | struct GNUNET_GETOPT_CommandLineOption options[] = { |
356 | GNUNET_GETOPT_option_exclusive ( | 129 | GNUNET_GETOPT_option_exclusive ( |
357 | GNUNET_GETOPT_option_string ( | 130 | GNUNET_GETOPT_option_string ( |
@@ -361,44 +134,6 @@ main (int argc, char *const *argv) | |||
361 | gettext_noop ( | 134 | gettext_noop ( |
362 | "test if the current installation supports the specified BACKEND"), | 135 | "test if the current installation supports the specified BACKEND"), |
363 | &backend_check)), | 136 | &backend_check)), |
364 | GNUNET_GETOPT_option_flag ( | ||
365 | 'F', | ||
366 | "full", | ||
367 | gettext_noop ( | ||
368 | "write the full configuration file, including default values"), | ||
369 | &full), | ||
370 | GNUNET_GETOPT_option_flag ( | ||
371 | 'f', | ||
372 | "filename", | ||
373 | gettext_noop ("interpret option value as a filename (with $-expansion)"), | ||
374 | &is_filename), | ||
375 | GNUNET_GETOPT_option_string ('o', | ||
376 | "option", | ||
377 | "OPTION", | ||
378 | gettext_noop ("name of the option to access"), | ||
379 | &option), | ||
380 | GNUNET_GETOPT_option_flag ( | ||
381 | 'r', | ||
382 | "rewrite", | ||
383 | gettext_noop ( | ||
384 | "rewrite the configuration file, even if nothing changed"), | ||
385 | &rewrite), | ||
386 | GNUNET_GETOPT_option_flag ('S', | ||
387 | "list-sections", | ||
388 | gettext_noop ( | ||
389 | "print available configuration sections"), | ||
390 | &list_sections), | ||
391 | GNUNET_GETOPT_option_string ('s', | ||
392 | "section", | ||
393 | "SECTION", | ||
394 | gettext_noop ( | ||
395 | "name of the section to access"), | ||
396 | §ion), | ||
397 | GNUNET_GETOPT_option_string ('V', | ||
398 | "value", | ||
399 | "VALUE", | ||
400 | gettext_noop ("value to set"), | ||
401 | &value), | ||
402 | GNUNET_GETOPT_option_flag ('C', | 137 | GNUNET_GETOPT_option_flag ('C', |
403 | "cflags", | 138 | "cflags", |
404 | gettext_noop ( | 139 | gettext_noop ( |
@@ -414,15 +149,15 @@ main (int argc, char *const *argv) | |||
414 | gettext_noop ( | 149 | gettext_noop ( |
415 | "Provide the path under which GNUnet was installed"), | 150 | "Provide the path under which GNUnet was installed"), |
416 | &prefix), | 151 | &prefix), |
152 | GNUNET_CONFIGURATION_CONFIG_OPTIONS (&cs), | ||
417 | GNUNET_GETOPT_OPTION_END | 153 | GNUNET_GETOPT_OPTION_END |
418 | }; | 154 | }; |
419 | int ret; | 155 | enum GNUNET_GenericReturnValue ret; |
420 | 156 | ||
421 | if (GNUNET_OK != | 157 | if (GNUNET_OK != |
422 | GNUNET_STRINGS_get_utf8_args (argc, argv, | 158 | GNUNET_STRINGS_get_utf8_args (argc, argv, |
423 | &argc, &argv)) | 159 | &argc, &argv)) |
424 | return 2; | 160 | return EXIT_FAILURE; |
425 | |||
426 | ret = | 161 | ret = |
427 | GNUNET_PROGRAM_run (argc, | 162 | GNUNET_PROGRAM_run (argc, |
428 | argv, | 163 | argv, |
@@ -430,11 +165,14 @@ main (int argc, char *const *argv) | |||
430 | gettext_noop ("Manipulate GNUnet configuration files"), | 165 | gettext_noop ("Manipulate GNUnet configuration files"), |
431 | options, | 166 | options, |
432 | &run, | 167 | &run, |
433 | NULL); | 168 | &cs); |
434 | GNUNET_free_nz ((void *) argv); | 169 | GNUNET_free_nz ((void *) argv); |
435 | if (GNUNET_OK == ret) | 170 | GNUNET_CONFIGURATION_config_settings_free (&cs); |
436 | return global_ret; | 171 | if (GNUNET_NO == ret) |
437 | return ret; | 172 | return 0; |
173 | if (GNUNET_SYSERR == ret) | ||
174 | return EXIT_INVALIDARGUMENT; | ||
175 | return cs.global_ret; | ||
438 | } | 176 | } |
439 | 177 | ||
440 | 178 | ||
diff --git a/src/util/network.c b/src/util/network.c index e771a9834..014701e02 100644 --- a/src/util/network.c +++ b/src/util/network.c | |||
@@ -122,7 +122,7 @@ GNUNET_NETWORK_test_pf (int pf) | |||
122 | } | 122 | } |
123 | else | 123 | else |
124 | { | 124 | { |
125 | close (s); | 125 | GNUNET_break (0 == close (s)); |
126 | ret = GNUNET_OK; | 126 | ret = GNUNET_OK; |
127 | } | 127 | } |
128 | switch (pf) | 128 | switch (pf) |
@@ -506,15 +506,15 @@ GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc, | |||
506 | #endif | 506 | #endif |
507 | if (AF_UNIX == address->sa_family) | 507 | if (AF_UNIX == address->sa_family) |
508 | GNUNET_NETWORK_unix_precheck ((const struct sockaddr_un *) address); | 508 | GNUNET_NETWORK_unix_precheck ((const struct sockaddr_un *) address); |
509 | |||
509 | { | 510 | { |
510 | const int on = 1; | 511 | const int on = 1; |
511 | 512 | ||
512 | /* This is required here for TCP sockets, but only on UNIX */ | 513 | if ( (SOCK_STREAM == desc->type) && |
513 | if ((SOCK_STREAM == desc->type) && | 514 | (0 != setsockopt (desc->fd, |
514 | (0 != setsockopt (desc->fd, | 515 | SOL_SOCKET, |
515 | SOL_SOCKET, | 516 | SO_REUSEADDR, |
516 | SO_REUSEADDR, | 517 | &on, sizeof(on))) ) |
517 | &on, sizeof(on)))) | ||
518 | LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, | 518 | LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, |
519 | "setsockopt"); | 519 | "setsockopt"); |
520 | } | 520 | } |
@@ -883,15 +883,13 @@ GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Handle *fd, | |||
883 | const void *option_value, | 883 | const void *option_value, |
884 | socklen_t option_len) | 884 | socklen_t option_len) |
885 | { | 885 | { |
886 | int ret; | 886 | return (0 == setsockopt (fd->fd, |
887 | 887 | level, | |
888 | ret = setsockopt (fd->fd, | 888 | option_name, |
889 | level, | 889 | option_value, |
890 | option_name, | 890 | option_len)) |
891 | option_value, | 891 | ? GNUNET_OK |
892 | option_len); | 892 | : GNUNET_SYSERR; |
893 | |||
894 | return ret == 0 ? GNUNET_OK : GNUNET_SYSERR; | ||
895 | } | 893 | } |
896 | 894 | ||
897 | 895 | ||
diff --git a/src/util/os_installation.c b/src/util/os_installation.c index 02d4d439d..f15e1871a 100644 --- a/src/util/os_installation.c +++ b/src/util/os_installation.c | |||
@@ -68,7 +68,7 @@ static const struct GNUNET_OS_ProjectData default_pd = { | |||
68 | .config_file = "gnunet.conf", | 68 | .config_file = "gnunet.conf", |
69 | .user_config_file = "~/.config/gnunet.conf", | 69 | .user_config_file = "~/.config/gnunet.conf", |
70 | .is_gnu = 1, | 70 | .is_gnu = 1, |
71 | .gettext_domain = PACKAGE, | 71 | .gettext_domain = "gnunet", |
72 | .gettext_path = NULL, | 72 | .gettext_path = NULL, |
73 | .agpl_url = GNUNET_AGPL_URL, | 73 | .agpl_url = GNUNET_AGPL_URL, |
74 | }; | 74 | }; |
diff --git a/src/util/os_priority.c b/src/util/os_priority.c index 1ed9bcbf7..08320b291 100644 --- a/src/util/os_priority.c +++ b/src/util/os_priority.c | |||
@@ -47,7 +47,6 @@ struct GNUNET_OS_Process | |||
47 | */ | 47 | */ |
48 | pid_t pid; | 48 | pid_t pid; |
49 | 49 | ||
50 | |||
51 | /** | 50 | /** |
52 | * Pipe we use to signal the process. | 51 | * Pipe we use to signal the process. |
53 | * NULL if unused, or if process was deemed uncontrollable. | 52 | * NULL if unused, or if process was deemed uncontrollable. |
@@ -301,7 +300,8 @@ GNUNET_OS_process_destroy (struct GNUNET_OS_Process *proc) | |||
301 | * @param flags open flags (O_RDONLY, O_WRONLY) | 300 | * @param flags open flags (O_RDONLY, O_WRONLY) |
302 | */ | 301 | */ |
303 | static void | 302 | static void |
304 | open_dev_null (int target_fd, int flags) | 303 | open_dev_null (int target_fd, |
304 | int flags) | ||
305 | { | 305 | { |
306 | int fd; | 306 | int fd; |
307 | 307 | ||
@@ -316,7 +316,7 @@ open_dev_null (int target_fd, int flags) | |||
316 | if (-1 == dup2 (fd, target_fd)) | 316 | if (-1 == dup2 (fd, target_fd)) |
317 | { | 317 | { |
318 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "dup2"); | 318 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "dup2"); |
319 | (void) close (fd); | 319 | GNUNET_break (0 == close (fd)); |
320 | return; | 320 | return; |
321 | } | 321 | } |
322 | GNUNET_break (0 == close (fd)); | 322 | GNUNET_break (0 == close (fd)); |
@@ -395,7 +395,7 @@ start_process (enum GNUNET_OS_InheritStdioFlags std_inheritance, | |||
395 | if (NULL != childpipe_write) | 395 | if (NULL != childpipe_write) |
396 | GNUNET_DISK_file_close (childpipe_write); | 396 | GNUNET_DISK_file_close (childpipe_write); |
397 | if (0 <= dup_childpipe_read_fd) | 397 | if (0 <= dup_childpipe_read_fd) |
398 | close (dup_childpipe_read_fd); | 398 | GNUNET_break (0 == close (dup_childpipe_read_fd)); |
399 | return NULL; | 399 | return NULL; |
400 | } | 400 | } |
401 | childpipe_read_fd = dup_childpipe_read_fd; | 401 | childpipe_read_fd = dup_childpipe_read_fd; |
@@ -474,7 +474,7 @@ start_process (enum GNUNET_OS_InheritStdioFlags std_inheritance, | |||
474 | if (NULL != childpipe_write) | 474 | if (NULL != childpipe_write) |
475 | GNUNET_DISK_file_close (childpipe_write); | 475 | GNUNET_DISK_file_close (childpipe_write); |
476 | if (0 <= childpipe_read_fd) | 476 | if (0 <= childpipe_read_fd) |
477 | close (childpipe_read_fd); | 477 | GNUNET_break (0 == close (childpipe_read_fd)); |
478 | errno = eno; | 478 | errno = eno; |
479 | return NULL; | 479 | return NULL; |
480 | } | 480 | } |
@@ -486,7 +486,7 @@ start_process (enum GNUNET_OS_InheritStdioFlags std_inheritance, | |||
486 | gnunet_proc->control_pipe = childpipe_write; | 486 | gnunet_proc->control_pipe = childpipe_write; |
487 | if (0 != (std_inheritance & GNUNET_OS_USE_PIPE_CONTROL)) | 487 | if (0 != (std_inheritance & GNUNET_OS_USE_PIPE_CONTROL)) |
488 | { | 488 | { |
489 | close (childpipe_read_fd); | 489 | GNUNET_break (0 == close (childpipe_read_fd)); |
490 | } | 490 | } |
491 | GNUNET_array_grow (lscp, ls, 0); | 491 | GNUNET_array_grow (lscp, ls, 0); |
492 | return gnunet_proc; | 492 | return gnunet_proc; |
@@ -564,7 +564,7 @@ start_process (enum GNUNET_OS_InheritStdioFlags std_inheritance, | |||
564 | { | 564 | { |
565 | /* Bury any existing FD, no matter what; they should all be closed | 565 | /* Bury any existing FD, no matter what; they should all be closed |
566 | * on exec anyway and the important ones have been dup'ed away */ | 566 | * on exec anyway and the important ones have been dup'ed away */ |
567 | (void) close (tgt); | 567 | GNUNET_break (0 == close (tgt)); |
568 | GNUNET_assert (-1 != dup2 (lscp[i], tgt)); | 568 | GNUNET_assert (-1 != dup2 (lscp[i], tgt)); |
569 | } | 569 | } |
570 | /* unset close-on-exec flag */ | 570 | /* unset close-on-exec flag */ |
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..b9da14572 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,12 +241,26 @@ GNUNET_PROGRAM_run2 (int argc, | |||
251 | } | 241 | } |
252 | if (NULL != cc.cfgfile) | 242 | if (NULL != cc.cfgfile) |
253 | { | 243 | { |
254 | if ((GNUNET_YES != GNUNET_DISK_file_test (cc.cfgfile)) || | 244 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
255 | (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, cc.cfgfile))) | 245 | "Loading configuration from entry point specified as option (%s)\n", |
246 | cc.cfgfile); | ||
247 | if (GNUNET_YES != | ||
248 | GNUNET_DISK_file_test (cc.cfgfile)) | ||
256 | { | 249 | { |
257 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 250 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
258 | _ ( | 251 | _ ("Unreadable configuration file `%s', exiting ...\n"), |
259 | "Unreadable or malformed configuration file `%s', exit ...\n"), | 252 | cc.cfgfile); |
253 | ret = GNUNET_SYSERR; | ||
254 | GNUNET_free (allopts); | ||
255 | GNUNET_free (lpfx); | ||
256 | goto cleanup; | ||
257 | } | ||
258 | if (GNUNET_SYSERR == | ||
259 | GNUNET_CONFIGURATION_load (cfg, | ||
260 | cc.cfgfile)) | ||
261 | { | ||
262 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
263 | _ ("Malformed configuration file `%s', exiting ...\n"), | ||
260 | cc.cfgfile); | 264 | cc.cfgfile); |
261 | ret = GNUNET_SYSERR; | 265 | ret = GNUNET_SYSERR; |
262 | GNUNET_free (allopts); | 266 | GNUNET_free (allopts); |
@@ -266,34 +270,31 @@ GNUNET_PROGRAM_run2 (int argc, | |||
266 | } | 270 | } |
267 | else | 271 | else |
268 | { | 272 | { |
269 | if ((NULL != cfg_fn) && (GNUNET_YES == GNUNET_DISK_file_test (cfg_fn))) | 273 | if ( (NULL != cfg_fn) && |
274 | (GNUNET_YES != | ||
275 | GNUNET_DISK_file_test (cfg_fn)) ) | ||
270 | { | 276 | { |
271 | if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, cfg_fn)) | 277 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
272 | { | 278 | _ ("Unreadable configuration file `%s'. Exiting ...\n"), |
273 | GNUNET_log ( | 279 | cfg_fn); |
274 | GNUNET_ERROR_TYPE_ERROR, | 280 | ret = GNUNET_SYSERR; |
275 | _ ( | 281 | GNUNET_free (allopts); |
276 | "Unreadable or malformed default configuration file `%s', exit ...\n"), | 282 | GNUNET_free (lpfx); |
277 | cfg_fn); | 283 | goto cleanup; |
278 | ret = GNUNET_SYSERR; | ||
279 | GNUNET_free (allopts); | ||
280 | GNUNET_free (lpfx); | ||
281 | goto cleanup; | ||
282 | } | ||
283 | } | 284 | } |
284 | else if (NULL != cfg_fn) | 285 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
286 | "Loading configuration from entry point `%s'\n", | ||
287 | cc.cfgfile); | ||
288 | if (GNUNET_SYSERR == | ||
289 | GNUNET_CONFIGURATION_load (cfg, | ||
290 | cfg_fn)) | ||
285 | { | 291 | { |
286 | GNUNET_free (cfg_fn); | 292 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
287 | cfg_fn = NULL; | 293 | _ ("Malformed configuration. Exiting ...\n")); |
288 | if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, NULL)) | 294 | ret = GNUNET_SYSERR; |
289 | { | 295 | GNUNET_free (allopts); |
290 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 296 | GNUNET_free (lpfx); |
291 | _ ("Unreadable or malformed configuration, exit ...\n")); | 297 | goto cleanup; |
292 | ret = GNUNET_SYSERR; | ||
293 | GNUNET_free (allopts); | ||
294 | GNUNET_free (lpfx); | ||
295 | goto cleanup; | ||
296 | } | ||
297 | } | 298 | } |
298 | } | 299 | } |
299 | GNUNET_free (allopts); | 300 | GNUNET_free (allopts); |
diff --git a/src/util/strings.c b/src/util/strings.c index 24335e444..673915888 100644 --- a/src/util/strings.c +++ b/src/util/strings.c | |||
@@ -1600,7 +1600,7 @@ GNUNET_STRINGS_base64_encode (const void *in, | |||
1600 | char *opt; | 1600 | char *opt; |
1601 | 1601 | ||
1602 | ret = 0; | 1602 | ret = 0; |
1603 | GNUNET_assert (len / 4 < SIZE_MAX); | 1603 | GNUNET_assert (len < SIZE_MAX / 4 * 3 ); |
1604 | opt = GNUNET_malloc (2 + (len * 4 / 3) + 8); | 1604 | opt = GNUNET_malloc (2 + (len * 4 / 3) + 8); |
1605 | for (size_t i = 0; i < len; ++i) | 1605 | for (size_t i = 0; i < len; ++i) |
1606 | { | 1606 | { |
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 | ||
28 | static void | 28 | static void |
29 | test_cb (void *cls, const char *libname, void *lib_ret) | 29 | test_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 | |||
26 | void * | 27 | void * |
27 | libgnunet_plugin_test_init (void *arg) | 28 | libgnunet_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 | ||
35 | void * | 36 | void * |
36 | libgnunet_plugin_test_done (void *arg) | 37 | libgnunet_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"); |