GNUnet 0.28.1-dev.2-13-g57ceb9dfb
 
Loading...
Searching...
No Matches
configuration.c File Reference
#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet_configuration_lib.h"
Include dependency graph for configuration.c:

Go to the source code of this file.

Data Structures

struct  ConfigEntry
 configuration entry More...
 
struct  ConfigSection
 configuration section More...
 
struct  ConfigFile
 
struct  GNUNET_CONFIGURATION_Handle
 configuration data More...
 
struct  DiffHandle
 Used for diffing a configuration object against the default one. More...
 
struct  CollectFilesContext
 Closure to collect_files_cb. More...
 

Macros

#define LOG(kind, ...)   GNUNET_log_from (kind, "util", __VA_ARGS__)
 
#define LOG_STRERROR_FILE(kind, syscall, filename)    GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
 

Functions

void GNUNET_CONFIGURATION_enable_diagnostics (struct GNUNET_CONFIGURATION_Handle *cfg)
 Enable extra diagnostics.
 
struct GNUNET_CONFIGURATION_HandleGNUNET_CONFIGURATION_create (const struct GNUNET_OS_ProjectData *pd)
 Create a new configuration object.
 
void GNUNET_CONFIGURATION_destroy (struct GNUNET_CONFIGURATION_Handle *cfg)
 Destroy configuration object.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_parse_and_run (const struct GNUNET_OS_ProjectData *pd, const char *filename, GNUNET_CONFIGURATION_Callback cb, void *cb_cls)
 Parse a configuration file filename and run the function cb with the resulting configuration object.
 
static enum GNUNET_GenericReturnValue collect_files_cb (void *cls, const char *filename)
 Function called with a filename.
 
static struct ConfigSectionfind_section (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section)
 Find a section entry from a configuration.
 
static int pstrcmp (const void *a, const void *b)
 
static enum GNUNET_GenericReturnValue handle_inline (struct GNUNET_CONFIGURATION_Handle *cfg, const char *path_or_glob, bool path_is_glob, const char *restrict_section, const char *source_filename, unsigned int source_lineno)
 Handle an inline directive.
 
static struct ConfigEntryfind_entry (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *key)
 Find an entry from a configuration.
 
static void set_entry_hint (struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *hint_filename, unsigned int hint_line)
 Set a configuration hint.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_deserialize (struct GNUNET_CONFIGURATION_Handle *cfg, const char *mem, size_t size, const char *source_filename)
 De-serializes configuration.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_parse (struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename)
 Parse a configuration file, add all of the options in the file to the configuration environment.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_is_dirty (const struct GNUNET_CONFIGURATION_Handle *cfg)
 Test if there are configuration options that were changed since the last save.
 
static bool do_skip (const char *sec, const char *key)
 Should we skip this configuration entry when serializing?
 
char * GNUNET_CONFIGURATION_serialize (const struct GNUNET_CONFIGURATION_Handle *cfg, size_t *size)
 Serializes the given configuration.
 
static void dump_os_ipk (const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_Buffer *buf, enum GNUNET_OS_InstallationPathKind ipk)
 Dump an os installation path to a buffer.
 
char * GNUNET_CONFIGURATION_serialize_diagnostics (const struct GNUNET_CONFIGURATION_Handle *cfg)
 Serializes the given configuration with diagnostics information.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_write (struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename)
 Write configuration file.
 
void GNUNET_CONFIGURATION_iterate (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_CONFIGURATION_Iterator iter, void *iter_cls)
 Iterate over all options in the configuration.
 
void GNUNET_CONFIGURATION_iterate_section_values (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, GNUNET_CONFIGURATION_Iterator iter, void *iter_cls)
 Iterate over values of a section in the configuration.
 
void GNUNET_CONFIGURATION_iterate_sections (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_CONFIGURATION_SectionIterator iter, void *iter_cls)
 Iterate over all sections in the configuration.
 
void GNUNET_CONFIGURATION_remove_section (struct GNUNET_CONFIGURATION_Handle *cfg, const char *section)
 Remove the given section and all options in it.
 
static void copy_entry (void *cls, const char *section, const char *option, const char *value)
 Copy a configuration value to the given target configuration.
 
struct GNUNET_CONFIGURATION_HandleGNUNET_CONFIGURATION_dup (const struct GNUNET_CONFIGURATION_Handle *cfg)
 Duplicate an existing configuration object.
 
static void compare_entries (void *cls, const char *section, const char *option, const char *value)
 A callback function, compares entries from two configurations (default against a new configuration) and write the diffs in a diff-configuration object (the callback object).
 
struct GNUNET_CONFIGURATION_HandleGNUNET_CONFIGURATION_get_diff (const struct GNUNET_CONFIGURATION_Handle *cfg_default, const struct GNUNET_CONFIGURATION_Handle *cfg_new)
 Compute configuration with only entries that have been changed.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_write_diffs (const struct GNUNET_CONFIGURATION_Handle *cfg_default, const struct GNUNET_CONFIGURATION_Handle *cfg_new, const char *filename)
 Write only configuration entries that have been changed to configuration file.
 
void GNUNET_CONFIGURATION_set_value_string (struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *value)
 Set a configuration value that should be a string.
 
void GNUNET_CONFIGURATION_set_value_number (struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long number)
 Set a configuration value that should be a number.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_number (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
 Get a configuration value that should be a number.
 
void GNUNET_CONFIGURATION_set_value_float (struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, float number)
 Set a configuration value that should be a float.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_float (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, float *number)
 Get a configuration value that should be a floating point number.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_time (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, struct GNUNET_TIME_Relative *time)
 Get a configuration value that should be a relative time.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_size (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *size)
 Get a configuration value that should be a size in bytes.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_string (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
 Get a configuration value that should be a string.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_choice (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *const *choices, const char **value)
 Get a configuration value that should be in a set of predefined strings.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_data (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, void *buf, size_t buf_size)
 Get Crockford32-encoded fixed-size binary data from a configuration.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_have_value (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
 Test if we have a value for a particular option.
 
static char * expand_dollar (const struct GNUNET_CONFIGURATION_Handle *cfg, char *orig, unsigned int depth)
 Expand an expression of the form "$FOO/BAR" to "DIRECTORY/BAR" where either in the "PATHS" section or the environment "FOO" is set to "DIRECTORY".
 
char * GNUNET_CONFIGURATION_expand_dollar (const struct GNUNET_CONFIGURATION_Handle *cfg, char *orig)
 Expand an expression of the form "$FOO/BAR" to "DIRECTORY/BAR" where either in the "PATHS" section or the environment "FOO" is set to "DIRECTORY".
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_filename (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
 Get a configuration value that should be the name of a file or directory.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
 Get a configuration value that should be in a set of "YES" or "NO".
 
int GNUNET_CONFIGURATION_iterate_value_filenames (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, GNUNET_FileNameCallback cb, void *cb_cls)
 Iterate over the set of filenames stored in a configuration value.
 
static char * escape_name (const char *value)
 FIXME.
 
static enum GNUNET_GenericReturnValue test_match (void *cls, const char *fn)
 FIXME.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_append_value_filename (struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *value)
 Append a filename to a configuration value that represents a list of filenames.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_remove_value_filename (struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *value)
 Remove a filename from a configuration value that represents a list of filenames.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_load_from (struct GNUNET_CONFIGURATION_Handle *cfg, const char *defaults_d)
 Load default configuration.
 
char * GNUNET_CONFIGURATION_default_filename (const struct GNUNET_OS_ProjectData *pd)
 Return the filename of the default configuration filename that is used when no explicit configuration entry point has been specified.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_load (struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename)
 Load configuration.
 
static void print_filename_option (void *cls, const char *section, const char *option, const char *value)
 Print each option in a given section as a filename.
 
static void print_option (void *cls, const char *section, const char *option, const char *value)
 Print each option in a given section.
 
static void print_section_name (void *cls, const char *section)
 Print out given section name.
 
void GNUNET_CONFIGURATION_config_tool_run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
 Main task to run to perform operations typical for gnunet-config as per the configuration settings given in cls.
 
void GNUNET_CONFIGURATION_config_settings_free (struct GNUNET_CONFIGURATION_ConfigSettings *cs)
 Free resources associated with cs.
 
const struct GNUNET_OS_ProjectDataGNUNET_CONFIGURATION_get_project_data (const struct GNUNET_CONFIGURATION_Handle *cfg)
 Return the project data associated with this configuration.
 
char * GNUNET_CONFIGURATION_get_suid_binary_path (const struct GNUNET_OS_ProjectData *pd, const struct GNUNET_CONFIGURATION_Handle *cfg, const char *progname)
 Given the name of a helper, service or daemon binary construct the full path to the binary using the SUID_BINARY_PATH in the PATHS section of the configuration.
 

Macro Definition Documentation

◆ LOG

#define LOG (   kind,
  ... 
)    GNUNET_log_from (kind, "util", __VA_ARGS__)

Definition at line 30 of file configuration.c.

◆ LOG_STRERROR_FILE

#define LOG_STRERROR_FILE (   kind,
  syscall,
  filename 
)     GNUNET_log_from_strerror_file (kind, "util", syscall, filename)

Definition at line 32 of file configuration.c.

38{
42 struct ConfigEntry *next;
43
47 char *key;
48
52 char *val;
53
57 char *hint_filename;
58
62 unsigned int hint_lineno;
63};
64
65
69struct ConfigSection
70{
74 struct ConfigSection *next;
75
79 struct ConfigEntry *entries;
80
84 char *name;
85
92 bool inaccessible;
93
98
102 char *hint_secret_stat;
103
108
112 unsigned int hint_inlined_from_line;
113};
114
115struct ConfigFile
116{
120 char *source_filename;
121
125 unsigned int level;
126
127 struct ConfigFile *prev;
128
129 struct ConfigFile *next;
130
136
141};
142
143
148{
152 struct ConfigSection *sections;
153
158
163
167 const struct GNUNET_OS_ProjectData *pd;
168
172 unsigned int current_nest_level;
173
177 bool diagnostics;
178
185
189 bool load_called;
190
194 char *main_filename;
195
201 const char *restrict_section;
202};
203
204
209struct DiffHandle
210{
212
214};
215
216
217void
220{
221 cfg->diagnostics = true;
222}
223
224
227{
229 char *p;
230
232 cfg->pd = pd;
233 /* make certain values from the project data available
234 as PATHS */
237 if (NULL != p)
238 {
240 "PATHS",
241 "DATADIR",
242 p);
243 GNUNET_free (p);
244 }
247 if (NULL != p)
248 {
250 "PATHS",
251 "LIBDIR",
252 p);
253 GNUNET_free (p);
254 }
257 if (NULL != p)
258 {
260 "PATHS",
261 "BINDIR",
262 p);
263 GNUNET_free (p);
264 }
267 if (NULL != p)
268 {
270 "PATHS",
271 "PREFIX",
272 p);
273 GNUNET_free (p);
274 }
277 if (NULL != p)
278 {
280 "PATHS",
281 "LOCALEDIR",
282 p);
283 GNUNET_free (p);
284 }
287 if (NULL != p)
288 {
290 "PATHS",
291 "ICONDIR",
292 p);
293 GNUNET_free (p);
294 }
297 if (NULL != p)
298 {
300 "PATHS",
301 "DOCDIR",
302 p);
303 GNUNET_free (p);
304 }
307 if (NULL != p)
308 {
310 "PATHS",
311 "LIBEXECDIR",
312 p);
313 GNUNET_free (p);
314 }
315 return cfg;
316}
317
318
319void
321{
322 struct ConfigSection *sec;
323 struct ConfigFile *cf;
324
325 while (NULL != (sec = cfg->sections))
327 while (NULL != (cf = cfg->loaded_files_head))
328 {
333 cf);
334 GNUNET_free (cf);
335 }
338}
339
340
343 const char *filename,
345 void *cb_cls)
346{
349
351 if (GNUNET_OK !=
353 filename))
354 {
355 GNUNET_break (0);
357 return GNUNET_SYSERR;
358 }
359 ret = cb (cb_cls,
360 cfg);
362 return ret;
363}
364
365
370{
374 char **files;
375
379 unsigned int files_length;
380};
381
382
393collect_files_cb (void *cls,
394 const char *filename)
395{
396 struct CollectFilesContext *igc = cls;
397
399 igc->files_length,
401 return GNUNET_OK;
402}
403
404
412static struct ConfigSection *
414 const char *section)
415{
416 struct ConfigSection *pos;
417
418 if (NULL == cfg)
419 return NULL;
420 pos = cfg->sections;
421 while ( (NULL != pos) &&
422 (0 != strcasecmp (section,
423 pos->name)) )
424 pos = pos->next;
425 return pos;
426}
427
428
429static int
430pstrcmp (const void *a,
431 const void *b)
432{
433 return strcmp (*((const char **) a),
434 *((const char **) b));
435}
436
437
445 const char *path_or_glob,
446 bool path_is_glob,
447 const char *restrict_section,
448 const char *source_filename,
449 unsigned int source_lineno)
450{
451 char *inline_path = NULL;
452 struct GNUNET_CONFIGURATION_Handle *other_cfg = NULL;
453 struct CollectFilesContext igc = {
454 .files = NULL,
455 .files_length = 0,
456 };
457 enum GNUNET_GenericReturnValue fun_ret;
458 unsigned int old_nest_level = cfg->current_nest_level++;
459
460 /* We support the section restriction only for non-globs */
461 GNUNET_assert (! (path_is_glob && (NULL != restrict_section)));
462
463 if (NULL == source_filename)
464 {
466 "Refusing to parse inline configurations, "
467 "not allowed without source filename!\n");
468 fun_ret = GNUNET_SYSERR;
469 goto cleanup;
470 }
471
472 if ('/' == *path_or_glob)
473 inline_path = GNUNET_strdup (path_or_glob);
474 else
475 {
476 /* We compute the canonical, absolute path first,
477 so that relative imports resolve properly with symlinked
478 config files. */
479 char *source_realpath;
480 char *endsep;
481
482 source_realpath = realpath (source_filename,
483 NULL);
484 if (NULL == source_realpath)
485 {
486 /* Couldn't even resolve path of base dir. */
487 GNUNET_break (0);
488 /* failed to parse included config */
489 fun_ret = GNUNET_SYSERR;
490 goto cleanup;
491 }
492 endsep = strrchr (source_realpath, '/');
493 GNUNET_assert (NULL != endsep);
494 *endsep = '\0';
495 GNUNET_asprintf (&inline_path,
496 "%s/%s",
497 source_realpath,
498 path_or_glob);
499 free (source_realpath);
500 }
501
502 if (path_is_glob)
503 {
504 int nret;
505
507 "processing config glob '%s'\n",
508 inline_path);
509
510 nret = GNUNET_DISK_glob (inline_path,
512 &igc);
513 if (-1 == nret)
514 {
515 fun_ret = GNUNET_SYSERR;
516 goto cleanup;
517 }
518 GNUNET_assert (nret == igc.files_length);
519 qsort (igc.files,
520 igc.files_length,
521 sizeof (char *),
522 &pstrcmp);
523 for (int i = 0; i < nret; i++)
524 {
525 if (GNUNET_OK !=
527 igc.files[i]))
528 {
529 fun_ret = GNUNET_SYSERR;
530 goto cleanup;
531 }
532 }
533 fun_ret = GNUNET_OK;
534 }
535 else if (NULL != restrict_section)
536 {
537 enum GNUNET_GenericReturnValue inner_ret;
538 struct ConfigSection *cs;
539 struct ConfigFile *cf = GNUNET_new (struct ConfigFile);
540
541 inner_ret = GNUNET_DISK_file_test_read (inline_path);
542
543 cs = find_section (cfg, restrict_section);
544
545 if (NULL == cs)
546 {
547 cs = GNUNET_new (struct ConfigSection);
548 cs->name = GNUNET_strdup (restrict_section);
549 cs->next = cfg->sections;
550 cfg->sections = cs;
551 cs->entries = NULL;
552 }
553 if (cfg->diagnostics)
554 {
555 const char *pwname;
556 const char *grname;
557 char *sfn = GNUNET_STRINGS_filename_expand (inline_path);
558 struct stat istat;
559
560 cs->hint_secret_filename = sfn;
561 if (0 == stat (sfn, &istat))
562 {
563 struct passwd *pw = getpwuid (istat.st_uid);
564 struct group *gr = getgrgid (istat.st_gid);
565 pwname = (NULL == pw) ? "<unknown>" : pw->pw_name;
566 grname = (NULL == gr) ? "<unknown>" : gr->gr_name;
567
569 "%s:%s %o",
570 pwname,
571 grname,
572 istat.st_mode);
573 }
574 else
575 {
576 cs->hint_secret_stat = GNUNET_strdup ("<can't stat file>");
577 }
578 if (source_filename)
579 {
580 /* Possible that this secret section has been inlined before */
582 cs->hint_inlined_from_filename = GNUNET_strdup (source_filename);
583 cs->hint_inlined_from_line = source_lineno;
584 }
585 }
586
587 /* Put file in the load list for diagnostics, even if we can't access it. */
588 {
590 cf->source_filename = GNUNET_strdup (inline_path);
591 cf->hint_restrict_section = GNUNET_strdup (restrict_section);
594 cf);
595 }
596
597 if (GNUNET_OK != inner_ret)
598 {
599 cs->inaccessible = true;
600 cf->hint_inaccessible = true;
601 /* File can't be accessed, but that's okay. */
602 fun_ret = GNUNET_OK;
603 goto cleanup;
604 }
605
606 other_cfg = GNUNET_CONFIGURATION_create (cfg->pd);
607 other_cfg->restrict_section = restrict_section;
608 inner_ret = GNUNET_CONFIGURATION_parse (other_cfg,
609 inline_path);
610 if (GNUNET_OK != inner_ret)
611 {
612 cf->hint_inaccessible = true;
613 fun_ret = inner_ret;
614 goto cleanup;
615 }
616
617 cs = find_section (other_cfg,
618 restrict_section);
619 if (NULL == cs)
620 {
622 "Configuration file '%s' loaded with @inline-secret@ "
623 "does not contain section '%s'.\n",
624 inline_path,
625 restrict_section);
626 /* Inlined configuration is accessible but doesn't contain any values.
627 We treat this as if the inlined section was empty, and do not
628 consider it an error. */
629 fun_ret = GNUNET_OK;
630 goto cleanup;
631 }
632 for (struct ConfigEntry *ce = cs->entries;
633 NULL != ce;
634 ce = ce->next)
636 restrict_section,
637 ce->key,
638 ce->val);
639 fun_ret = GNUNET_OK;
640 }
641 else if (GNUNET_OK !=
643 inline_path))
644 {
645 fun_ret = GNUNET_SYSERR;
646 goto cleanup;
647 }
648 else
649 {
650 fun_ret = GNUNET_OK;
651 }
652cleanup:
653 cfg->current_nest_level = old_nest_level;
654 if (NULL != other_cfg)
656 GNUNET_free (inline_path);
657 if (igc.files_length > 0)
658 {
659 for (size_t i = 0; i < igc.files_length; i++)
660 GNUNET_free (igc.files[i]);
662 }
663 return fun_ret;
664}
665
666
675static struct ConfigEntry *
677 const char *section,
678 const char *key)
679{
680 struct ConfigSection *sec;
681
682 if (NULL == (sec = find_section (cfg,
683 section)))
684 return NULL;
685 for (struct ConfigEntry *pos = sec->entries;
686 pos != NULL;
687 pos = pos->next)
688 if (0 == strcasecmp (key,
689 pos->key))
690 return pos;
691 if (sec->inaccessible)
692 {
694 "Section '%s' is marked as inaccessible, because the configuration "
695 "file that contains the section can't be read. Attempts to use "
696 "option '%s' will fail.\n",
697 section,
698 key);
699 return NULL;
700 }
701 return NULL;
702}
703
704
714static void
716 const char *section,
717 const char *option,
718 const char *hint_filename,
719 unsigned int hint_line)
720{
721 struct ConfigEntry *e = find_entry (cfg, section, option);
722 if (! cfg->diagnostics)
723 return;
724 if (! e)
725 return;
727 e->hint_lineno = hint_line;
728}
729
730
733 const char *mem,
734 size_t size,
735 const char *source_filename)
736{
737 size_t line_size;
738 unsigned int nr;
739 size_t r_bytes;
740 size_t to_read;
742 char *section;
743 char *eq;
744 char *tag;
745 char *value;
746 char *line_orig = NULL;
747
748 ret = GNUNET_OK;
749 section = NULL;
750 nr = 0;
751 r_bytes = 0;
752 while (r_bytes < size)
753 {
754 const char *pos;
755 char *line;
756 bool emptyline;
757
758 GNUNET_free (line_orig);
759 /* fgets-like behaviour on buffer */
760 to_read = size - r_bytes;
761 pos = memchr (&mem[r_bytes], '\n', to_read);
762 if (NULL == pos)
763 {
764 line_orig = GNUNET_strndup (&mem[r_bytes],
765 line_size = to_read);
766 r_bytes += line_size;
767 }
768 else
769 {
770 line_orig = GNUNET_strndup (&mem[r_bytes],
771 line_size = (pos - &mem[r_bytes]));
772 r_bytes += line_size + 1;
773 }
774 line = line_orig;
775 /* increment line number */
776 nr++;
777 /* tabs and '\r' are whitespace */
778 emptyline = GNUNET_YES;
779 for (size_t i = 0; i < line_size; i++)
780 {
781 if (line[i] == '\t')
782 line[i] = ' ';
783 if (line[i] == '\r')
784 line[i] = ' ';
785 if (' ' != line[i])
786 emptyline = GNUNET_NO;
787 }
788 /* ignore empty lines */
789 if (GNUNET_YES == emptyline)
790 continue;
791
792 /* remove tailing whitespace */
793 for (size_t i = line_size - 1;
794 (i >= 1) && (isspace ((unsigned char) line[i]));
795 i--)
796 line[i] = '\0';
797
798 /* remove leading whitespace */
799 for (; line[0] != '\0' && (isspace ((unsigned char) line[0])); line++)
800 ;
801
802 /* ignore comments */
803 if ( ('#' == line[0]) ||
804 ('%' == line[0]) )
805 continue;
806
807 /* Handle special directives. */
808 if ('@' == line[0])
809 {
810 char *end = strchr (line + 1, '@');
811 char *directive;
812 enum GNUNET_GenericReturnValue directive_ret;
813
814 if (NULL != cfg->restrict_section)
815 {
817 "Illegal directive in line %u (parsing restricted section %s)\n",
818 nr,
821 break;
822 }
823
824 if (NULL == end)
825 {
827 "Bad directive in line %u\n",
828 nr);
830 break;
831 }
832 *end = '\0';
833 directive = line + 1;
834
835 if (0 == strcasecmp (directive,
836 "INLINE"))
837 {
838 const char *path = end + 1;
839
840 /* Skip space before path */
841 for (; isspace (*path); path++)
842 ;
843
844 directive_ret = handle_inline (cfg,
845 path,
846 false,
847 NULL,
848 source_filename,
849 nr);
850 }
851 else if (0 == strcasecmp (directive,
852 "INLINE-MATCHING"))
853 {
854 const char *path = end + 1;
855
856 /* Skip space before path */
857 for (; isspace (*path); path++)
858 ;
859
860 directive_ret = handle_inline (cfg,
861 path,
862 true,
863 NULL,
864 source_filename,
865 nr);
866 }
867 else if (0 == strcasecmp (directive,
868 "INLINE-SECRET"))
869 {
870 char *secname = end + 1;
871 char *secname_end;
872 const char *path;
873
874 /* Skip space before secname */
875 for (; isspace (*secname); secname++)
876 ;
877
878 secname_end = strchr (secname, ' ');
879
880 if (NULL == secname_end)
881 {
883 "Bad inline-secret directive in line %u\n",
884 nr);
886 break;
887 }
888 *secname_end = '\0';
889 path = secname_end + 1;
890
891 /* Skip space before path */
892 for (; isspace (*path); path++)
893 ;
894
895 directive_ret = handle_inline (cfg,
896 path,
897 false,
898 secname,
899 source_filename,
900 nr);
901 }
902 else
903 {
905 "Unknown or malformed directive '%s' in line %u\n",
906 directive,
907 nr);
909 break;
910 }
911 if (GNUNET_OK != directive_ret)
912 {
913 ret = directive_ret;
914 break;
915 }
916 continue;
917 }
918 if ( ('[' == line[0]) &&
919 (']' == line[line_size - 1]) )
920 {
921 /* [value] */
922 line[line_size - 1] = '\0';
923 value = &line[1];
924 GNUNET_free (section);
925 section = GNUNET_strdup (value);
926 continue;
927 }
928 if (NULL != (eq = strchr (line, '=')))
929 {
930
931 if (NULL == section)
932 {
934 "Syntax error while deserializing in line %u (option without section)\n",
935 nr);
937 break;
938 }
939
940 /* tag = value */
941 tag = GNUNET_strndup (line, eq - line);
942 /* remove tailing whitespace */
943 for (int i = strlen (tag) - 1;
944 (i >= 1) && (isspace ((unsigned char) tag[i]));
945 i--)
946 tag[i] = '\0';
947
948 /* Strip whitespace */
949 value = eq + 1;
950 while (isspace ((unsigned char) value[0]))
951 value++;
952 for (int i = strlen (value) - 1;
953 (i >= 1) && (isspace ((unsigned char) value[i]));
954 i--)
955 value[i] = '\0';
956
957 /* remove quotes */
958 if ( ('"' == value[0]) &&
959 ('"' == value[strlen (value) - 1]) )
960 {
961 value[strlen (value) - 1] = '\0';
962 value++;
963 }
965 section,
966 tag,
967 value);
968 if (cfg->diagnostics)
969 {
971 section,
972 tag,
973 source_filename
974 ? source_filename
975 : "<input>",
976 nr);
977 }
978 GNUNET_free (tag);
979 continue;
980 }
981 /* parse error */
983 "Syntax error while deserializing in line %u\n",
984 nr);
986 break;
987 }
988 GNUNET_free (line_orig);
989 GNUNET_free (section);
990 GNUNET_assert ( (GNUNET_OK != ret) ||
991 (r_bytes == size) );
992 return ret;
993}
994
995
998 const char *filename)
999{
1000 uint64_t fs64;
1001 size_t fs;
1002 char *fn;
1003 char *mem;
1004 int dirty;
1006 ssize_t sret;
1007
1010 "Asked to parse config file `%s'\n",
1011 fn);
1012 if (NULL == fn)
1013 return GNUNET_SYSERR;
1014
1015
1016 /* Check for cycles */
1017 {
1018 unsigned int lvl = cfg->current_nest_level;
1019 struct ConfigFile *cf = cfg->loaded_files_tail;
1020 struct ConfigFile *parent = NULL;
1021
1022
1023 for (; NULL != cf; parent = cf, cf = cf->prev)
1024 {
1025 /* Check parents based on level, skipping children of siblings. */
1026 if (cf->level >= lvl)
1027 continue;
1028 lvl = cf->level;
1029 if ( (NULL == cf->source_filename) ||
1030 (NULL == filename) )
1031 continue;
1032 if (0 == strcmp (cf->source_filename,
1033 filename))
1034 {
1035 if (NULL == parent)
1036 {
1038 "Forbidden direct cyclic configuration import (%s -> %s)\n",
1039 cf->source_filename,
1040 filename);
1041 }
1042 else
1044 "Forbidden indirect cyclic configuration import (%s -> ... -> %s -> %s)\n",
1045 cf->source_filename,
1046 parent->source_filename,
1047 filename);
1048 GNUNET_free (fn);
1049 return GNUNET_SYSERR;
1050 }
1051 }
1052
1053 }
1054
1055 /* Keep track of loaded files.*/
1056 {
1057 struct ConfigFile *cf = GNUNET_new (struct ConfigFile);
1058
1060 cf->source_filename = GNUNET_strdup (filename ? filename : "<input>");
1063 cf);
1064 }
1065
1066 dirty = cfg->dirty; /* back up value! */
1067 if (GNUNET_SYSERR ==
1069 &fs64,
1070 GNUNET_NO,
1071 GNUNET_YES))
1072 {
1074 "Error while determining the file size of `%s'\n",
1075 fn);
1076 GNUNET_free (fn);
1077 return GNUNET_SYSERR;
1078 }
1079 if (fs64 > SIZE_MAX)
1080 {
1081 GNUNET_break (0); /* File size is more than the heap size */
1082 GNUNET_free (fn);
1083 return GNUNET_SYSERR;
1084 }
1085 fs = fs64;
1086 mem = GNUNET_malloc (fs);
1087 sret = GNUNET_DISK_fn_read (fn,
1088 mem,
1089 fs);
1090 if ((sret < 0) || (fs != (size_t) sret))
1091 {
1093 "Error while reading file `%s'\n",
1094 fn);
1095 GNUNET_free (fn);
1096 GNUNET_free (mem);
1097 return GNUNET_SYSERR;
1098 }
1100 "Deserializing contents of file `%s'\n",
1101 fn);
1103 mem,
1104 fs,
1105 fn);
1106 if (GNUNET_SYSERR == ret)
1107 {
1109 _ ("Failed to parse configuration file `%s'\n"),
1110 fn);
1111 }
1112 GNUNET_free (fn);
1113 GNUNET_free (mem);
1114 /* restore dirty flag - anything we set in the meantime
1115 * came from disk */
1116 cfg->dirty = dirty;
1117 return ret;
1118}
1119
1120
1123{
1124 return cfg->dirty;
1125}
1126
1127
1135static bool
1136do_skip (const char *sec,
1137 const char *key)
1138{
1139 if (0 != strcasecmp ("PATHS",
1140 sec))
1141 return false;
1142 return ( (0 == strcasecmp ("DATADIR",
1143 key)) ||
1144 (0 == strcasecmp ("LIBDIR",
1145 key)) ||
1146 (0 == strcasecmp ("BINDIR",
1147 key)) ||
1148 (0 == strcasecmp ("PREFIX",
1149 key)) ||
1150 (0 == strcasecmp ("LOCALEDIR",
1151 key)) ||
1152 (0 == strcasecmp ("ICONDIR",
1153 key)) ||
1154 (0 == strcasecmp ("DOCDIR",
1155 key)) ||
1156 (0 == strcasecmp ("DEFAULTCONFIG",
1157 key)) ||
1158 (0 == strcasecmp ("LIBEXECDIR",
1159 key)) );
1160}
1161
1162
1163char *
1165 size_t *size)
1166{
1167 char *mem;
1168 char *cbuf;
1169 char *val;
1170 char *pos;
1171 size_t m_size;
1172 size_t c_size;
1173
1174 /* Pass1 : calculate the buffer size required */
1175 m_size = 0;
1176 for (struct ConfigSection *sec = cfg->sections;
1177 NULL != sec;
1178 sec = sec->next)
1179 {
1180 if (sec->inaccessible && (NULL == sec->entries))
1181 continue;
1182 /* For each section we need to add 3 characters: {'[',']','\n'} */
1183 m_size += strlen (sec->name) + 3;
1184 for (struct ConfigEntry *ent = sec->entries;
1185 NULL != ent;
1186 ent = ent->next)
1187 {
1188 if (do_skip (sec->name,
1189 ent->key))
1190 continue;
1191 if (NULL != ent->val)
1192 {
1193 /* if val has any '\n' then they occupy +1 character as '\n'->'\\','n' */
1194 pos = ent->val;
1195 while (NULL != (pos = strstr (pos, "\n")))
1196 {
1197 m_size++;
1198 pos++;
1199 }
1200 /* For each key = value pair we need to add 4 characters (2
1201 spaces and 1 equal-to character and 1 new line) */
1202 m_size += strlen (ent->key) + strlen (ent->val) + 4;
1203 }
1204 }
1205 /* A new line after section end */
1206 m_size++;
1207 }
1208
1209 /* Pass2: Allocate memory and write the configuration to it */
1210 mem = GNUNET_malloc (m_size);
1211 c_size = 0;
1212 *size = c_size;
1213 for (struct ConfigSection *sec = cfg->sections;
1214 NULL != sec;
1215 sec = sec->next)
1216 {
1217 int len;
1218
1219 len = GNUNET_asprintf (&cbuf,
1220 "[%s]\n",
1221 sec->name);
1222 GNUNET_assert (0 < len);
1223 GNUNET_memcpy (mem + c_size,
1224 cbuf,
1225 len);
1226 c_size += len;
1227 GNUNET_free (cbuf);
1228 for (struct ConfigEntry *ent = sec->entries;
1229 NULL != ent;
1230 ent = ent->next)
1231 {
1232 if (do_skip (sec->name,
1233 ent->key))
1234 continue;
1235 if (NULL != ent->val)
1236 {
1237 val = GNUNET_malloc (strlen (ent->val) * 2 + 1);
1238 strcpy (val, ent->val);
1239 while (NULL != (pos = strstr (val, "\n")))
1240 {
1241 memmove (&pos[2], &pos[1], strlen (&pos[1]));
1242 pos[0] = '\\';
1243 pos[1] = 'n';
1244 }
1245 len = GNUNET_asprintf (&cbuf, "%s = %s\n", ent->key, val);
1246 GNUNET_free (val);
1247 GNUNET_memcpy (mem + c_size, cbuf, len);
1248 c_size += len;
1249 GNUNET_free (cbuf);
1250 }
1251 }
1252 GNUNET_memcpy (mem + c_size, "\n", 1);
1253 c_size++;
1254 }
1255 GNUNET_assert (c_size == m_size);
1256 *size = c_size;
1257 return mem;
1258}
1259
1260
1269static void
1271 const struct GNUNET_CONFIGURATION_Handle *cfg,
1272 struct GNUNET_Buffer *buf,
1274{
1276 ipk);
1277 const char *ipkname;
1278 switch (ipk)
1279 {
1281 ipkname = "IPK_DATADIR";
1282 break;
1284 ipkname = "IPK_BINDIR";
1285 break;
1287 ipkname = "IPK_LIBDIR";
1288 break;
1290 ipkname = "IPK_PREFIX";
1292 ipkname = "IPK_LOCALEDIR";
1293 break;
1295 ipkname = "IPK_ICONDIR";
1297 ipkname = "IPK_DOCDIR";
1298 break;
1300 ipkname = "IPK_LIBEXECDIR";
1301 break;
1303 ipkname = "IPK_SELF_PREFIX";
1304 break;
1305 default:
1306 ipkname = "??";
1307 break;
1308 }
1310 "# %s = %s\n",
1311 ipkname,
1312 v);
1313 GNUNET_free (v);
1314}
1315
1316
1317char *
1319 const struct GNUNET_CONFIGURATION_Handle *cfg)
1320{
1321 struct GNUNET_Buffer buf = { 0 };
1322
1324 "#\n# Configuration file diagnostics\n#\n");
1326 "# Entry point: %s\n",
1328 "<none>");
1330 "#\n# Files Loaded:\n");
1331
1332 for (struct ConfigFile *cfil = cfg->loaded_files_head;
1333 NULL != cfil;
1334 cfil = cfil->next)
1335 {
1337 "# ");
1338 for (unsigned int i = 0; i < cfil->level; i++)
1340 "+");
1341 if (0 != cfil->level)
1343 " ");
1344
1346 "%s",
1347 cfil->source_filename);
1348
1349 if (NULL != cfil->hint_restrict_section)
1351 " (%s secret section %s)",
1352 cfil->hint_inaccessible
1353 ? "inaccessible"
1354 : "loaded",
1355 cfil->hint_restrict_section);
1356
1358 "\n");
1359 }
1360
1362 "#\n# Installation paths:\n");
1363
1373
1374
1376 "#\n\n");
1377
1378 for (struct ConfigSection *sec = cfg->sections;
1379 NULL != sec;
1380 sec = sec->next)
1381 {
1382 if (sec->hint_secret_filename)
1384 "# secret section from %s\n# secret file stat %s\n",
1385 sec->hint_secret_filename,
1386 sec->hint_secret_stat);
1387 if (sec->hint_inlined_from_filename)
1388 {
1390 "# inlined from %s:%u\n",
1391 sec->hint_inlined_from_filename,
1392 sec->hint_inlined_from_line);
1393 }
1395 "[%s]\n\n",
1396 sec->name);
1397 if (sec->inaccessible && (NULL == sec->entries))
1398 {
1400 "# <section contents inaccessible>\n\n\n");
1401 continue;
1402 }
1403 for (struct ConfigEntry *ent = sec->entries;
1404 NULL != ent;
1405 ent = ent->next)
1406 {
1407 if (do_skip (sec->name,
1408 ent->key))
1409 continue;
1410 if (NULL != ent->val)
1411 {
1412 char *pos;
1413 char *val = GNUNET_malloc (strlen (ent->val) * 2 + 1);
1414 strcpy (val, ent->val);
1415 while (NULL != (pos = strstr (val, "\n")))
1416 {
1417 memmove (&pos[2], &pos[1], strlen (&pos[1]));
1418 pos[0] = '\\';
1419 pos[1] = 'n';
1420 }
1421 if (NULL != ent->hint_filename)
1422 {
1424 "# %s:%u\n",
1425 ent->hint_filename,
1426 ent->hint_lineno);
1427 }
1429 "%s = %s\n",
1430 ent->key,
1431 val);
1432 GNUNET_free (val);
1433 }
1434 GNUNET_buffer_write_str (&buf, "\n");
1435 }
1436 if (sec->inaccessible)
1437 {
1439 "# <additional section contents inaccessible>\n\n\n");
1440 continue;
1441 }
1442
1443 GNUNET_buffer_write_str (&buf, "\n");
1444 }
1445 return GNUNET_buffer_reap_str (&buf);
1446}
1447
1448
1452 const char *filename)
1453{
1454 char *fn;
1455 char *tfn;
1456 char *cfg_buf;
1457 size_t size;
1458
1460 if (fn == NULL)
1461 return GNUNET_SYSERR;
1463 {
1464 GNUNET_free (fn);
1465 return GNUNET_SYSERR;
1466 }
1467 {
1468 /* If @a filename is a symlink, replace what it points at, the way
1469 truncating it in place used to. */
1470 char *rfn = realpath (fn,
1471 NULL);
1472
1473 if (NULL != rfn)
1474 {
1475 GNUNET_free (fn);
1476 fn = GNUNET_strdup (rfn);
1477 free (rfn);
1478 }
1479 }
1481 &size);
1482 /* Never rewrite the configuration in place: opening it with O_TRUNC leaves
1483 it observably empty until we have written the new contents, and anyone
1484 parsing the file in that instant -- say a daemon that was just started
1485 with this very configuration -- reads a truncated file and fails. So
1486 write a sibling file and rename(2) it over the target; readers then
1487 always see either the complete old or the complete new configuration. */
1488 GNUNET_asprintf (&tfn,
1489 "%s.%u.tmp",
1490 fn,
1491 (unsigned int) getpid ());
1492 {
1493 struct GNUNET_DISK_FileHandle *h;
1494
1495 h = GNUNET_DISK_file_open (tfn,
1503 if (NULL == h)
1504 {
1505 GNUNET_free (tfn);
1506 GNUNET_free (fn);
1507 GNUNET_free (cfg_buf);
1508 return GNUNET_SYSERR;
1509 }
1510 if (((ssize_t) size) !=
1512 cfg_buf,
1513 size))
1514 {
1516 "write",
1517 tfn);
1519 (void) unlink (tfn);
1520 GNUNET_free (tfn);
1521 GNUNET_free (fn);
1522 GNUNET_free (cfg_buf);
1523 cfg->dirty = GNUNET_SYSERR; /* last write failed */
1524 return GNUNET_SYSERR;
1525 }
1526 /* Get the contents onto the disk before the rename publishes them, so
1527 that a crash cannot leave an empty configuration behind. */
1528 (void) GNUNET_DISK_file_sync (h);
1531 }
1532 {
1533 struct stat sbuf;
1534
1535 /* rename(2) replaces the inode, so carry over the permissions of the
1536 configuration we are about to replace (we just created @a tfn). */
1537 if ( (0 == stat (fn,
1538 &sbuf)) &&
1539 (0 != chmod (tfn,
1540 sbuf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO))) )
1542 "chmod",
1543 tfn);
1544 }
1545 if (0 != rename (tfn,
1546 fn))
1547 {
1549 "rename",
1550 fn);
1551 (void) unlink (tfn);
1552 GNUNET_free (tfn);
1553 GNUNET_free (fn);
1554 GNUNET_free (cfg_buf);
1555 cfg->dirty = GNUNET_SYSERR; /* last write failed */
1556 return GNUNET_SYSERR;
1557 }
1558 GNUNET_free (tfn);
1559 GNUNET_free (fn);
1560 GNUNET_free (cfg_buf);
1561 cfg->dirty = GNUNET_NO; /* last write succeeded */
1562 return GNUNET_OK;
1563}
1564
1565
1566void
1568 const struct GNUNET_CONFIGURATION_Handle *cfg,
1570 void *iter_cls)
1571{
1572 for (struct ConfigSection *spos = cfg->sections;
1573 NULL != spos;
1574 spos = spos->next)
1575 for (struct ConfigEntry *epos = spos->entries;
1576 NULL != epos;
1577 epos = epos->next)
1578 if (NULL != epos->val)
1579 iter (iter_cls,
1580 spos->name,
1581 epos->key,
1582 epos->val);
1583}
1584
1585
1586void
1588 const struct GNUNET_CONFIGURATION_Handle *cfg,
1589 const char *section,
1591 void *iter_cls)
1592{
1593 struct ConfigSection *spos;
1594
1595 spos = cfg->sections;
1596 while ((spos != NULL) && (0 != strcasecmp (spos->name, section)))
1597 spos = spos->next;
1598 if (NULL == spos)
1599 return;
1600 for (struct ConfigEntry *epos = spos->entries;
1601 NULL != epos;
1602 epos = epos->next)
1603 if (NULL != epos->val)
1604 iter (iter_cls,
1605 spos->name,
1606 epos->key,
1607 epos->val);
1608 if (spos->inaccessible)
1609 {
1611 "Section '%s' is marked as inaccessible, because a configuration "
1612 "file that contains the section can't be read.\n",
1613 section);
1614 return;
1615 }
1616}
1617
1618
1619void
1621 const struct GNUNET_CONFIGURATION_Handle *cfg,
1623 void *iter_cls)
1624{
1625 struct ConfigSection *spos;
1626 struct ConfigSection *next;
1627
1628 next = cfg->sections;
1629 while (NULL != next)
1630 {
1631 spos = next;
1632 next = spos->next;
1633 if (spos->inaccessible && (NULL == spos->entries))
1634 continue;
1635 iter (iter_cls,
1636 spos->name);
1637 }
1638}
1639
1640
1641void
1643 const char *section)
1644{
1645 struct ConfigSection *spos;
1646 struct ConfigSection *prev;
1647 struct ConfigEntry *ent;
1648
1649 prev = NULL;
1650 spos = cfg->sections;
1651 while (NULL != spos)
1652 {
1653 if (0 == strcasecmp (section,
1654 spos->name))
1655 {
1656 if (NULL == prev)
1657 cfg->sections = spos->next;
1658 else
1659 prev->next = spos->next;
1660 while (NULL != (ent = spos->entries))
1661 {
1662 spos->entries = ent->next;
1663 GNUNET_free (ent->key);
1664 GNUNET_free (ent->val);
1666 GNUNET_free (ent);
1667 cfg->dirty = GNUNET_YES;
1668 }
1669 GNUNET_free (spos->name);
1673 GNUNET_free (spos);
1674 return;
1675 }
1676 prev = spos;
1677 spos = spos->next;
1678 }
1679}
1680
1681
1691static void
1692copy_entry (void *cls,
1693 const char *section,
1694 const char *option,
1695 const char *value)
1696{
1697 struct GNUNET_CONFIGURATION_Handle *dst = cls;
1698
1700 section,
1701 option,
1702 value);
1703}
1704
1705
1708 const struct GNUNET_CONFIGURATION_Handle *cfg)
1709{
1711
1714 &copy_entry,
1715 ret);
1716 return ret;
1717}
1718
1719
1730static void
1731compare_entries (void *cls,
1732 const char *section,
1733 const char *option,
1734 const char *value)
1735{
1736 struct DiffHandle *dh = cls;
1737 struct ConfigEntry *entNew;
1738
1739 entNew = find_entry (dh->cfg_default, section, option);
1740 if ((NULL != entNew) && (NULL != entNew->val) &&
1741 (0 == strcmp (entNew->val, value)))
1742 return;
1744 section,
1745 option,
1746 value);
1747}
1748
1749
1752 const struct GNUNET_CONFIGURATION_Handle *cfg_default,
1753 const struct GNUNET_CONFIGURATION_Handle *cfg_new)
1754{
1755 struct DiffHandle diffHandle;
1756
1757 GNUNET_break (cfg_default->pd == cfg_new->pd);
1758 diffHandle.cfgDiff = GNUNET_CONFIGURATION_create (cfg_new->pd);
1759 diffHandle.cfg_default = cfg_default;
1762 &diffHandle);
1763 return diffHandle.cfgDiff;
1764}
1765
1766
1770 const struct GNUNET_CONFIGURATION_Handle *cfg_new,
1771 const char *filename)
1772{
1773 int ret;
1774 struct GNUNET_CONFIGURATION_Handle *diff;
1775
1776 diff = GNUNET_CONFIGURATION_get_diff (cfg_default, cfg_new);
1779 return ret;
1780}
1781
1782
1783void
1786 const char *section,
1787 const char *option,
1788 const char *value)
1789{
1790 struct ConfigSection *sec;
1791 struct ConfigEntry *e;
1792 char *nv;
1793
1794 e = find_entry (cfg, section, option);
1795 if (NULL != e)
1796 {
1797 if (NULL == value)
1798 {
1799 GNUNET_free (e->val);
1800 e->val = NULL;
1801 }
1802 else
1803 {
1804 nv = GNUNET_strdup (value);
1805 GNUNET_free (e->val);
1806 e->val = nv;
1807 }
1808 return;
1809 }
1810 sec = find_section (cfg, section);
1811 if (sec == NULL)
1812 {
1813 sec = GNUNET_new (struct ConfigSection);
1814 sec->name = GNUNET_strdup (section);
1815 sec->next = cfg->sections;
1816 cfg->sections = sec;
1817 }
1818 e = GNUNET_new (struct ConfigEntry);
1819 e->key = GNUNET_strdup (option);
1820 e->val = GNUNET_strdup (value);
1821 e->next = sec->entries;
1822 sec->entries = e;
1823}
1824
1825
1826void
1828 const char *section,
1829 const char *option,
1830 unsigned long long number)
1831{
1832 char s[64];
1833
1834 GNUNET_snprintf (s,
1835 64,
1836 "%llu",
1837 number);
1839 section,
1840 option,
1841 s);
1842}
1843
1844
1847 const struct GNUNET_CONFIGURATION_Handle *cfg,
1848 const char *section,
1849 const char *option,
1850 unsigned long long *number)
1851{
1852 struct ConfigEntry *e;
1853 char dummy[2];
1854
1855 if (NULL == (e = find_entry (cfg,
1856 section,
1857 option)))
1858 return GNUNET_NO;
1859 if (NULL == e->val)
1860 return GNUNET_NO;
1861 if (1 != sscanf (e->val,
1862 "%llu%1s",
1863 number,
1864 dummy))
1865 return GNUNET_SYSERR;
1866 return GNUNET_OK;
1867}
1868
1869
1870void
1872 const char *section,
1873 const char *option,
1874 float number)
1875{
1876 char s[64];
1877
1878 /* See: #9369 */
1879 const locale_t cl = newlocale (LC_NUMERIC_MASK,
1880 "C",
1881 (locale_t) 0);
1882 locale_t old_locale = uselocale (cl);
1883 GNUNET_snprintf (s,
1884 64,
1885 "%f",
1886 (double) number);
1887 uselocale (old_locale);
1889 section,
1890 option,
1891 s);
1892}
1893
1894
1897 const struct GNUNET_CONFIGURATION_Handle *cfg,
1898 const char *section,
1899 const char *option,
1900 float *number)
1901{
1902 struct ConfigEntry *e;
1903 char dummy[2];
1904
1905 if (NULL == (e = find_entry (cfg,
1906 section,
1907 option)))
1908 return GNUNET_NO;
1909 if (NULL == e->val)
1910 return GNUNET_NO;
1911 /* See #9369 */
1912 {
1913 const locale_t cl = newlocale (LC_NUMERIC_MASK,
1914 "C",
1915 (locale_t) 0);
1916 locale_t old_locale = uselocale (cl);
1917
1918 if (1 != sscanf (e->val,
1919 "%f%1s",
1920 number,
1921 dummy))
1922 return GNUNET_SYSERR;
1923 uselocale (old_locale);
1924 }
1925 return GNUNET_OK;
1926}
1927
1928
1931 const struct GNUNET_CONFIGURATION_Handle *cfg,
1932 const char *section,
1933 const char *option,
1934 struct GNUNET_TIME_Relative *time)
1935{
1936 struct ConfigEntry *e;
1937 int ret;
1938
1939 if (NULL == (e = find_entry (cfg,
1940 section,
1941 option)))
1942 return GNUNET_NO;
1943 if (NULL == e->val)
1944 return GNUNET_NO;
1946 time);
1947 if (GNUNET_OK != ret)
1949 section,
1950 option,
1951 _ ("Not a valid relative time specification"));
1952 return ret;
1953}
1954
1955
1958 const struct GNUNET_CONFIGURATION_Handle *cfg,
1959 const char *section,
1960 const char *option,
1961 unsigned long long *size)
1962{
1963 struct ConfigEntry *e;
1964
1965 if (NULL == (e = find_entry (cfg,
1966 section,
1967 option)))
1968 return GNUNET_NO;
1969 if (NULL == e->val)
1970 return GNUNET_NO;
1972 size);
1973}
1974
1975
1988 const struct GNUNET_CONFIGURATION_Handle *cfg,
1989 const char *section,
1990 const char *option,
1991 char **value)
1992{
1993 struct ConfigEntry *e;
1994
1995 if ( (NULL == (e = find_entry (cfg,
1996 section,
1997 option))) ||
1998 (NULL == e->val) )
1999 {
2000 *value = NULL;
2001 return GNUNET_NO;
2002 }
2003 *value = GNUNET_strdup (e->val);
2004 return GNUNET_OK;
2005}
2006
2007
2010 const struct GNUNET_CONFIGURATION_Handle *cfg,
2011 const char *section,
2012 const char *option,
2013 const char *const *choices,
2014 const char **value)
2015{
2016 struct ConfigEntry *e;
2017 unsigned int i;
2018
2019 if (NULL == (e = find_entry (cfg,
2020 section,
2021 option)))
2022 return GNUNET_NO;
2023 for (i = 0; NULL != choices[i]; i++)
2024 if (0 == strcasecmp (choices[i], e->val))
2025 break;
2026 if (NULL == choices[i])
2027 {
2029 _ ("Configuration value '%s' for '%s'"
2030 " in section '%s' is not in set of legal choices\n"),
2031 e->val,
2032 option,
2033 section);
2034 return GNUNET_SYSERR;
2035 }
2036 *value = choices[i];
2037 return GNUNET_OK;
2038}
2039
2040
2043 const char *section,
2044 const char *option,
2045 void *buf,
2046 size_t buf_size)
2047{
2048 char *enc;
2049 int res;
2050 size_t data_size;
2051
2052 if (GNUNET_OK !=
2053 (res =
2055 section,
2056 option,
2057 &enc)))
2058 return res;
2059 data_size = (strlen (enc) * 5) / 8;
2060 if (data_size != buf_size)
2061 {
2062 GNUNET_free (enc);
2063 return GNUNET_SYSERR;
2064 }
2065 if (GNUNET_OK !=
2067 strlen (enc),
2068 buf,
2069 buf_size))
2070 {
2071 GNUNET_free (enc);
2072 return GNUNET_SYSERR;
2073 }
2074 GNUNET_free (enc);
2075 return GNUNET_OK;
2076}
2077
2078
2081 const char *section,
2082 const char *option)
2083{
2084 struct ConfigEntry *e;
2085
2086 if ( (NULL == (e = find_entry (cfg,
2087 section,
2088 option))) ||
2089 (NULL == e->val) )
2090 return GNUNET_NO;
2091 return GNUNET_YES;
2092}
2093
2094
2110static char *
2112 char *orig,
2113 unsigned int depth)
2114{
2115 char *prefix;
2116 char *result;
2117 char *start;
2118 const char *post;
2119 const char *env;
2120 char *def;
2121 char *end;
2122 unsigned int lopen;
2123 char erased_char;
2124 char *erased_pos;
2125 size_t len;
2126
2127 if (NULL == orig)
2128 return NULL;
2129 if (depth > 128)
2130 {
2132 "Recursive expansion suspected, aborting $-expansion for term `%s'\n",
2133 orig);
2134 return orig;
2135 }
2137 "Asked to $-expand %s\n",
2138 orig);
2139 if ('$' != orig[0])
2140 {
2142 "Doesn't start with $ - not expanding\n");
2143 return orig;
2144 }
2145 erased_char = 0;
2146 erased_pos = NULL;
2147 if ('{' == orig[1])
2148 {
2149 start = &orig[2];
2150 lopen = 1;
2151 end = &orig[1];
2152 while (lopen > 0)
2153 {
2154 end++;
2155 switch (*end)
2156 {
2157 case '}':
2158 lopen--;
2159 break;
2160
2161 case '{':
2162 lopen++;
2163 break;
2164
2165 case '\0':
2167 "Missing closing `}' in option `%s'\n",
2168 orig);
2169 return orig;
2170
2171 default:
2172 break;
2173 }
2174 }
2175 erased_char = *end;
2176 erased_pos = end;
2177 *end = '\0';
2178 post = end + 1;
2179 def = strchr (orig, ':');
2180 if (NULL != def)
2181 {
2182 *def = '\0';
2183 def++;
2184 if (('-' == *def) || ('=' == *def))
2185 def++;
2186 def = GNUNET_strdup (def);
2187 }
2188 }
2189 else
2190 {
2191 int i;
2192
2193 start = &orig[1];
2194 def = NULL;
2195 i = 0;
2196 while ( (orig[i] != '/') &&
2197 (orig[i] != '\\') &&
2198 (orig[i] != '\0') &&
2199 (orig[i] != ' ') )
2200 i++;
2201 if (orig[i] == '\0')
2202 {
2203 post = "";
2204 }
2205 else
2206 {
2207 erased_char = orig[i];
2208 erased_pos = &orig[i];
2209 orig[i] = '\0';
2210 post = &orig[i + 1];
2211 }
2212 }
2214 "Split into `%s' and `%s' with default %s\n",
2215 start,
2216 post,
2217 def);
2218 if (GNUNET_OK !=
2220 "PATHS",
2221 start,
2222 &prefix))
2223 {
2224 if (NULL == (env = getenv (start)))
2225 {
2226 /* try default */
2227 def = expand_dollar (cfg,
2228 def,
2229 depth + 1);
2230 env = def;
2231 }
2232 if (NULL == env)
2233 {
2235 if (erased_pos)
2236 *erased_pos = erased_char;
2238 "Failed to expand `%s' in `%s' as it is neither found in [PATHS] nor defined as an environmental variable\n",
2239 start,
2240 orig);
2242 return orig;
2243 }
2245 }
2247 prefix);
2248 if ((erased_pos) && ('}' != erased_char))
2249 {
2250 len = strlen (prefix) + 1;
2251 prefix = GNUNET_realloc (prefix, len + 1);
2252 prefix[len - 1] = erased_char;
2253 prefix[len] = '\0';
2254 }
2255 result = GNUNET_malloc (strlen (prefix) + strlen (post) + 1);
2256 strcpy (result, prefix);
2257 strcat (result, post);
2258 GNUNET_free (def);
2260 GNUNET_free (orig);
2261 return result;
2262}
2263
2264
2265char *
2267 const struct GNUNET_CONFIGURATION_Handle *cfg,
2268 char *orig)
2269{
2270 char *dup;
2271 size_t i;
2272 size_t len;
2273
2274 for (i = 0; '\0' != orig[i]; i++)
2275 {
2276 if ('$' != orig[i])
2277 continue;
2278 dup = GNUNET_strdup (orig + i);
2279 dup = expand_dollar (cfg, dup, 0);
2280 GNUNET_assert (NULL != dup); /* make compiler happy */
2281 len = strlen (dup) + 1;
2282 orig = GNUNET_realloc (orig, i + len);
2283 GNUNET_memcpy (orig + i, dup, len);
2284 GNUNET_free (dup);
2285 }
2286 return orig;
2287}
2288
2289
2292 const struct GNUNET_CONFIGURATION_Handle *cfg,
2293 const char *section,
2294 const char *option,
2295 char **value)
2296{
2297 char *tmp;
2299
2301 section,
2302 option,
2303 &tmp);
2304 if (GNUNET_OK != ret)
2305 {
2307 "Failed to retrieve filename\n");
2308 *value = NULL;
2309 return ret;
2310 }
2312 tmp);
2314 GNUNET_free (tmp);
2315 if (*value == NULL)
2316 return GNUNET_SYSERR;
2317 return GNUNET_OK;
2318}
2319
2320
2323 const struct GNUNET_CONFIGURATION_Handle *cfg,
2324 const char *section,
2325 const char *option)
2326{
2327 static const char *yesno[] = {
2328 "YES",
2329 "NO",
2330 NULL
2331 };
2332 const char *val;
2334
2335 ret =
2337 section,
2338 option,
2339 yesno,
2340 &val);
2341 if (GNUNET_OK != ret)
2342 return ret;
2343 if (val == yesno[0])
2344 return GNUNET_YES;
2345 return GNUNET_NO;
2346}
2347
2348
2349int
2351 const struct GNUNET_CONFIGURATION_Handle *cfg,
2352 const char *section,
2353 const char *option,
2355 void *cb_cls)
2356{
2357 char *list;
2358 char *pos;
2359 char *end;
2360 char old;
2361 int ret;
2362
2363 if (GNUNET_OK !=
2365 section,
2366 option,
2367 &list))
2368 return 0;
2369 GNUNET_assert (list != NULL);
2370 ret = 0;
2371 pos = list;
2372 while (1)
2373 {
2374 while (pos[0] == ' ')
2375 pos++;
2376 if (strlen (pos) == 0)
2377 break;
2378 end = pos + 1;
2379 while ((end[0] != ' ') && (end[0] != '\0'))
2380 {
2381 if (end[0] == '\\')
2382 {
2383 switch (end[1])
2384 {
2385 case '\\':
2386 case ' ':
2387 memmove (end, &end[1], strlen (&end[1]) + 1);
2388
2389 case '\0':
2390 /* illegal, but just keep it */
2391 break;
2392
2393 default:
2394 /* illegal, but just ignore that there was a '/' */
2395 break;
2396 }
2397 }
2398 end++;
2399 }
2400 old = end[0];
2401 end[0] = '\0';
2402 if (strlen (pos) > 0)
2403 {
2404 ret++;
2405 if ( (NULL != cb) &&
2406 (GNUNET_OK != cb (cb_cls,
2407 pos)))
2408 {
2410 break;
2411 }
2412 }
2413 if (old == '\0')
2414 break;
2415 pos = end + 1;
2416 }
2417 GNUNET_free (list);
2418 return ret;
2419}
2420
2421
2428static char *
2429escape_name (const char *value)
2430{
2431 char *escaped;
2432 const char *rpos;
2433 char *wpos;
2434
2435 escaped = GNUNET_malloc (strlen (value) * 2 + 1);
2436 memset (escaped, 0, strlen (value) * 2 + 1);
2437 rpos = value;
2438 wpos = escaped;
2439 while (rpos[0] != '\0')
2440 {
2441 switch (rpos[0])
2442 {
2443 case '\\':
2444 case ' ':
2445 wpos[0] = '\\';
2446 wpos[1] = rpos[0];
2447 wpos += 2;
2448 break;
2449
2450 default:
2451 wpos[0] = rpos[0];
2452 wpos++;
2453 }
2454 rpos++;
2455 }
2456 return escaped;
2457}
2458
2459
2467static enum GNUNET_GenericReturnValue
2468test_match (void *cls,
2469 const char *fn)
2470{
2471 const char *of = cls;
2472
2473 return (0 == strcmp (of, fn))
2475 : GNUNET_OK;
2476}
2477
2478
2482 const char *section,
2483 const char *option,
2484 const char *value)
2485{
2486 char *escaped;
2487 char *old;
2488 char *nw;
2489
2490 if (GNUNET_SYSERR ==
2492 section,
2493 option,
2494 &test_match,
2495 (void *) value))
2496 return GNUNET_NO; /* already exists */
2497 if (GNUNET_OK !=
2498 GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &old))
2499 old = GNUNET_strdup ("");
2500 escaped = escape_name (value);
2501 nw = GNUNET_malloc (strlen (old) + strlen (escaped) + 2);
2502 strcpy (nw, old);
2503 if (strlen (old) > 0)
2504 strcat (nw, " ");
2505 strcat (nw, escaped);
2507 section,
2508 option,
2509 nw);
2510 GNUNET_free (old);
2511 GNUNET_free (nw);
2512 GNUNET_free (escaped);
2513 return GNUNET_OK;
2514}
2515
2516
2520 const char *section,
2521 const char *option,
2522 const char *value)
2523{
2524 char *list;
2525 char *pos;
2526 char *end;
2527 char *match;
2528 char old;
2529
2530 if (GNUNET_OK !=
2532 section,
2533 option,
2534 &list))
2535 return GNUNET_NO;
2536 match = escape_name (value);
2537 pos = list;
2538 while (1)
2539 {
2540 while (pos[0] == ' ')
2541 pos++;
2542 if (strlen (pos) == 0)
2543 break;
2544 end = pos + 1;
2545 while ((end[0] != ' ') && (end[0] != '\0'))
2546 {
2547 if (end[0] == '\\')
2548 {
2549 switch (end[1])
2550 {
2551 case '\\':
2552 case ' ':
2553 end++;
2554 break;
2555
2556 case '\0':
2557 /* illegal, but just keep it */
2558 break;
2559
2560 default:
2561 /* illegal, but just ignore that there was a '/' */
2562 break;
2563 }
2564 }
2565 end++;
2566 }
2567 old = end[0];
2568 end[0] = '\0';
2569 if (0 == strcmp (pos, match))
2570 {
2571 if (old != '\0')
2572 memmove (pos,
2573 &end[1],
2574 strlen (&end[1]) + 1);
2575 else
2576 {
2577 if (pos != list)
2578 pos[-1] = '\0';
2579 else
2580 pos[0] = '\0';
2581 }
2583 section,
2584 option,
2585 list);
2586 GNUNET_free (list);
2587 GNUNET_free (match);
2588 return GNUNET_OK;
2589 }
2590 if (old == '\0')
2591 break;
2592 end[0] = old;
2593 pos = end + 1;
2594 }
2595 GNUNET_free (list);
2596 GNUNET_free (match);
2597 return GNUNET_NO;
2598}
2599
2600
2604 const char *defaults_d)
2605{
2606 struct CollectFilesContext files_context = {
2607 .files = NULL,
2608 .files_length = 0,
2609 };
2610 enum GNUNET_GenericReturnValue fun_ret = GNUNET_NO;
2611
2612 if (GNUNET_SYSERR ==
2613 GNUNET_DISK_directory_scan (defaults_d,
2615 &files_context))
2616 return GNUNET_SYSERR; /* no configuration at all found */
2617 qsort (files_context.files,
2618 files_context.files_length,
2619 sizeof (char *),
2620 &pstrcmp);
2621 for (unsigned int i = 0; i < files_context.files_length; i++)
2622 {
2623 const char *ext;
2624 const char *filename = files_context.files[i];
2625
2626 /* Examine file extension */
2627 ext = strrchr (filename, '.');
2628 if ( (NULL == ext) ||
2629 (0 != strcmp (ext,
2630 ".conf")) )
2631 {
2633 "Skipping file `%s'\n",
2634 filename);
2635 fun_ret = GNUNET_OK;
2636 continue;
2637 }
2639 filename);
2640 if (fun_ret != GNUNET_OK)
2641 break;
2642 }
2643 if (files_context.files_length > 0)
2644 {
2645 for (size_t i = 0; i < files_context.files_length; i++)
2646 GNUNET_free (files_context.files[i]);
2647 GNUNET_array_grow (files_context.files,
2648 files_context.files_length,
2649 0);
2650 }
2651 return fun_ret;
2652}
2653
2654
2655char *
2657 const struct GNUNET_OS_ProjectData *pd)
2658{
2659 char *cfg_fn;
2660 const char *xdg = getenv ("XDG_CONFIG_HOME");
2661
2662 if (NULL != xdg)
2663 GNUNET_asprintf (&cfg_fn,
2664 "%s%s%s",
2665 xdg,
2667 pd->config_file);
2668 else
2669 cfg_fn = GNUNET_strdup (pd->user_config_file);
2670
2671 if (GNUNET_OK == GNUNET_DISK_file_test_read (cfg_fn))
2672 return cfg_fn;
2673 GNUNET_free (cfg_fn);
2674
2675 /* Fall back to /etc/ for the default configuration.
2676 Should be okay to use forward slashes here. */
2677
2678 GNUNET_asprintf (&cfg_fn,
2679 "/etc/%s",
2680 pd->config_file);
2681 if (GNUNET_OK ==
2683 return cfg_fn;
2684 GNUNET_free (cfg_fn);
2685
2686 GNUNET_asprintf (&cfg_fn,
2687 "/etc/%s/%s",
2688 pd->project_dirname,
2689 pd->config_file);
2690 if (GNUNET_OK ==
2692 return cfg_fn;
2693
2694 GNUNET_free (cfg_fn);
2695 return NULL;
2696}
2697
2698
2702 const char *filename)
2703{
2704 char *baseconfig;
2705 const char *base_config_varname;
2706
2707 if (cfg->load_called)
2708 {
2709 /* FIXME: Make this a GNUNET_assert later */
2710 GNUNET_break (0);
2712 }
2713 cfg->load_called = true;
2714 if (NULL != filename)
2715 {
2718 }
2719
2720 base_config_varname = cfg->pd->base_config_varname;
2721
2722 if ((NULL != base_config_varname)
2723 && (NULL != (baseconfig = getenv (base_config_varname))))
2724 {
2725 baseconfig = GNUNET_strdup (baseconfig);
2726 }
2727 else
2728 {
2729 char *ipath;
2730
2733 if (NULL == ipath)
2734 {
2735 GNUNET_break (0);
2736 return GNUNET_SYSERR;
2737 }
2738 GNUNET_asprintf (&baseconfig,
2739 "%s%s",
2740 ipath,
2741 "config.d");
2742 GNUNET_free (ipath);
2743 }
2744
2745 {
2746 char *dname = GNUNET_STRINGS_filename_expand (baseconfig);
2747
2748 GNUNET_free (baseconfig);
2749
2750 if ((GNUNET_YES ==
2752 GNUNET_YES)) &&
2753 (GNUNET_SYSERR ==
2755 dname)))
2756 {
2758 "Failed to load base configuration from '%s'\n",
2759 filename);
2760 GNUNET_free (dname);
2761 return GNUNET_SYSERR; /* no configuration at all found */
2762 }
2763 GNUNET_free (dname);
2764 }
2765 if ((NULL != filename) &&
2766 (GNUNET_OK !=
2768 filename)))
2769 {
2770 /* specified configuration not found */
2772 "Failed to load configuration from file '%s'\n",
2773 filename);
2774 return GNUNET_SYSERR;
2775 }
2776 if (((GNUNET_YES !=
2778 "PATHS",
2779 "DEFAULTCONFIG"))) &&
2780 (filename != NULL))
2782 "PATHS",
2783 "DEFAULTCONFIG",
2784 filename);
2785 return GNUNET_OK;
2786}
2787
2788
2797static void
2798print_filename_option (void *cls,
2799 const char *section,
2800 const char *option,
2801 const char *value)
2802{
2803 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
2804
2805 char *value_fn;
2806 char *fn;
2807
2810 section,
2811 option,
2812 &value_fn));
2813 fn = GNUNET_STRINGS_filename_expand (value_fn);
2814 if (NULL == fn)
2815 fn = value_fn;
2816 else
2817 GNUNET_free (value_fn);
2818 fprintf (stdout,
2819 "%s = %s\n",
2820 option,
2821 fn);
2822 GNUNET_free (fn);
2823}
2824
2825
2834static void
2835print_option (void *cls,
2836 const char *section,
2837 const char *option,
2838 const char *value)
2839{
2840 (void) cls;
2841 (void) section;
2842
2843 fprintf (stdout,
2844 "%s = %s\n",
2845 option,
2846 value);
2847}
2848
2849
2856static void
2857print_section_name (void *cls,
2858 const char *section)
2859{
2860 (void) cls;
2861 fprintf (stdout,
2862 "%s\n",
2863 section);
2864}
2865
2866
2867void
2869 void *cls,
2870 char *const *args,
2871 const char *cfgfile,
2872 const struct GNUNET_CONFIGURATION_Handle *cfg)
2873{
2874 struct GNUNET_CONFIGURATION_ConfigSettings *cs = cls;
2875 struct GNUNET_CONFIGURATION_Handle *out = NULL;
2876 struct GNUNET_CONFIGURATION_Handle *ncfg = NULL;
2877
2878 (void) args;
2879 if (cs->diagnostics)
2880 {
2881 /* Re-parse the configuration with diagnostics enabled. */
2884 if (GNUNET_OK !=
2886 cfgfile))
2887 {
2888 fprintf (stderr,
2889 _ ("Failed to load config file `%s'"),
2890 cfgfile);
2891 return;
2892 }
2893 cfg = ncfg;
2894 }
2895
2896 if (cs->full)
2897 cs->rewrite = GNUNET_YES;
2898 if (cs->list_sections)
2899 {
2900 fprintf (stderr,
2901 _ ("The following sections are available:\n"));
2904 NULL);
2905 return;
2906 }
2907 if ( (! cs->rewrite) &&
2908 (NULL == cs->section) )
2909 {
2910 char *serialization;
2911
2912 if (! cs->diagnostics)
2913 {
2914 fprintf (stderr,
2915 _ ("%s, %s or %s argument is required\n"),
2916 "--section",
2917 "--list-sections",
2918 "--diagnostics");
2920 return;
2921 }
2923 fprintf (stdout,
2924 "%s",
2925 serialization);
2926 GNUNET_free (serialization);
2927 }
2928 else if ( (NULL != cs->section) &&
2929 (NULL == cs->value) )
2930 {
2931 if (NULL == cs->option)
2932 {
2934 cfg,
2935 cs->section,
2936 cs->is_filename
2938 : &print_option,
2939 (void *) cfg);
2940 }
2941 else
2942 {
2943 char *value;
2944
2945 if (cs->is_filename)
2946 {
2947 if (GNUNET_OK !=
2949 cs->section,
2950 cs->option,
2951 &value))
2952 {
2954 cs->section,
2955 cs->option);
2957 return;
2958 }
2959 }
2960 else
2961 {
2962 if (GNUNET_OK !=
2964 cs->section,
2965 cs->option,
2966 &value))
2967 {
2969 cs->section,
2970 cs->option);
2972 return;
2973 }
2974 }
2975 fprintf (stdout,
2976 "%s\n",
2977 value);
2979 }
2980 }
2981 else if (NULL != cs->section)
2982 {
2983 if (NULL == cs->option)
2984 {
2985 fprintf (stderr,
2986 _ ("--option argument required to set value\n"));
2988 return;
2989 }
2992 cs->section,
2993 cs->option,
2994 cs->value);
2995 cs->rewrite = GNUNET_YES;
2996 }
2997 if (cs->rewrite)
2998 {
2999 char *cfg_fn = NULL;
3000
3001 if (NULL == out)
3003
3004 if (NULL == cfgfile)
3005 {
3006 const char *xdg = getenv ("XDG_CONFIG_HOME");
3007
3008 if (NULL != xdg)
3009 GNUNET_asprintf (&cfg_fn,
3010 "%s%s%s",
3011 xdg,
3013 cfg->pd->config_file);
3014 else
3015 cfg_fn = GNUNET_strdup (cfg->pd->user_config_file);
3016 cfgfile = cfg_fn;
3017 }
3018
3019 if (! cs->full)
3020 {
3021 struct GNUNET_CONFIGURATION_Handle *def;
3022
3024 if (GNUNET_OK !=
3026 NULL))
3027 {
3028 fprintf (stderr,
3029 _ ("failed to load configuration defaults"));
3030 cs->global_ret = 1;
3033 GNUNET_free (cfg_fn);
3034 return;
3035 }
3036 if (GNUNET_OK !=
3038 out,
3039 cfgfile))
3040 cs->global_ret = 2;
3042 }
3043 else
3044 {
3045 if (GNUNET_OK !=
3047 cfgfile))
3048 cs->global_ret = 2;
3049 }
3050 GNUNET_free (cfg_fn);
3051 }
3052 if (NULL != out)
3054 if (NULL != ncfg)
3056}
3057
3058
3059void
3062{
3063 GNUNET_free (cs->option);
3064 GNUNET_free (cs->section);
3065 GNUNET_free (cs->value);
3066}
3067
3068
3069const struct GNUNET_OS_ProjectData *
3071 const struct GNUNET_CONFIGURATION_Handle *cfg)
3072{
3073 return cfg->pd;
3074}
3075
3076
3077char *
3079 pd,
3080 const struct
3082 const char *progname)
3083{
3084 static char *cache;
3085 char *binary = NULL;
3086 char *path = NULL;
3087 size_t path_len;
3088
3089 if (GNUNET_YES ==
3091 GNUNET_NO,
3092 NULL,
3093 NULL))
3094 {
3095 return GNUNET_strdup (progname);
3096 }
3097 if (NULL != cache)
3098 path = cache;
3099 else
3101 "PATHS",
3102 "SUID_BINARY_PATH",
3103 &path);
3104 if ( (NULL == path) ||
3105 (0 == strlen (path)) )
3106 {
3107 if (NULL != path)
3108 GNUNET_free (path);
3109 cache = NULL;
3111 progname);
3112 }
3113 path_len = strlen (path);
3114 GNUNET_asprintf (&binary,
3115 "%s%s%s",
3116 path,
3117 (path[path_len - 1] == DIR_SEPARATOR) ? ""
3119 progname);
3120 cache = path;
3121 return binary;
3122}
3123
3124
3125/* end of configuration.c */
struct GNUNET_MQ_Envelope * env
Definition 005.c:1
static bool do_skip(const char *sec, const char *key)
Should we skip this configuration entry when serializing?
static void print_filename_option(void *cls, const char *section, const char *option, const char *value)
Print each option in a given section as a filename.
static struct ConfigEntry * find_entry(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *key)
Find an entry from a configuration.
static enum GNUNET_GenericReturnValue handle_inline(struct GNUNET_CONFIGURATION_Handle *cfg, const char *path_or_glob, bool path_is_glob, const char *restrict_section, const char *source_filename, unsigned int source_lineno)
Handle an inline directive.
static void print_section_name(void *cls, const char *section)
Print out given section name.
static char * escape_name(const char *value)
FIXME.
static void compare_entries(void *cls, const char *section, const char *option, const char *value)
A callback function, compares entries from two configurations (default against a new configuration) a...
static enum GNUNET_GenericReturnValue test_match(void *cls, const char *fn)
FIXME.
static struct ConfigSection * find_section(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section)
Find a section entry from a configuration.
static int pstrcmp(const void *a, const void *b)
static char * expand_dollar(const struct GNUNET_CONFIGURATION_Handle *cfg, char *orig, unsigned int depth)
Expand an expression of the form "$FOO/BAR" to "DIRECTORY/BAR" where either in the "PATHS" section or...
static enum GNUNET_GenericReturnValue collect_files_cb(void *cls, const char *filename)
Function called with a filename.
#define LOG(kind,...)
static void copy_entry(void *cls, const char *section, const char *option, const char *value)
Copy a configuration value to the given target configuration.
static void print_option(void *cls, const char *section, const char *option, const char *value)
Print each option in a given section.
static void dump_os_ipk(const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_Buffer *buf, enum GNUNET_OS_InstallationPathKind ipk)
Dump an os installation path to a buffer.
static void set_entry_hint(struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *hint_filename, unsigned int hint_line)
Set a configuration hint.
char * getenv()
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition gnunet-arm.c:98
static int start
Set if we are to start default services (including ARM).
Definition gnunet-arm.c:38
static int list
Set if we should print a list of currently running services.
Definition gnunet-arm.c:68
static int ret
Final status code.
Definition gnunet-arm.c:93
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition gnunet-arm.c:108
static int end
Set if we are to shutdown all services (including ARM).
Definition gnunet-arm.c:33
static int prefix
If printing the value of PREFIX has been requested.
static char * line
Desired phone line (string to be converted to a hash).
struct GNUNET_HashCode key
The key used in the DHT.
static char * filename
static struct GNUNET_FS_Handle * fs
Handle to FS service.
Definition gnunet-fs.c:35
static OpusEncoder * enc
OPUS encoder.
static struct in_addr dummy
Target "dummy" address of the packet we pretend to respond to.
static char * res
Currently read line or NULL on EOF.
static char * value
Value of the record to add/remove.
static size_t data_size
Number of bytes in data.
static int result
Global testing status.
static void cleanup()
Cleanup task.
static struct GNUNET_Process * p
Helper process we started.
Definition gnunet-uri.c:38
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_data(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, void *buf, size_t buf_size)
Get Crockford32-encoded fixed-size binary data from a configuration.
struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_create(const struct GNUNET_OS_ProjectData *pd)
Create a new configuration object.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_is_dirty(const struct GNUNET_CONFIGURATION_Handle *cfg)
Test if there are configuration options that were changed since the last save.
void GNUNET_CONFIGURATION_set_value_string(struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *value)
Set a configuration value that should be a string.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_append_value_filename(struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *value)
Append a filename to a configuration value that represents a list of filenames.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
void GNUNET_CONFIGURATION_remove_section(struct GNUNET_CONFIGURATION_Handle *cfg, const char *section)
Remove the given section and all options in it.
enum GNUNET_GenericReturnValue(* GNUNET_CONFIGURATION_Callback)(void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
Signature of a function to be run with a configuration.
struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_dup(const struct GNUNET_CONFIGURATION_Handle *cfg)
Duplicate an existing configuration object.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
void GNUNET_CONFIGURATION_iterate_sections(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_CONFIGURATION_SectionIterator iter, void *iter_cls)
Iterate over all sections in the configuration.
void GNUNET_CONFIGURATION_destroy(struct GNUNET_CONFIGURATION_Handle *cfg)
Destroy configuration object.
char * GNUNET_CONFIGURATION_get_suid_binary_path(const struct GNUNET_OS_ProjectData *pd, const struct GNUNET_CONFIGURATION_Handle *cfg, const char *progname)
Given the name of a helper, service or daemon binary construct the full path to the binary using the ...
void GNUNET_CONFIGURATION_config_settings_free(struct GNUNET_CONFIGURATION_ConfigSettings *cs)
Free resources associated with cs.
void GNUNET_CONFIGURATION_iterate(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_CONFIGURATION_Iterator iter, void *iter_cls)
Iterate over all options in the configuration.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_remove_value_filename(struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *value)
Remove a filename from a configuration value that represents a list of filenames.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_parse_and_run(const struct GNUNET_OS_ProjectData *pd, const char *filename, GNUNET_CONFIGURATION_Callback cb, void *cb_cls)
Parse a configuration file filename and run the function cb with the resulting configuration object.
void GNUNET_CONFIGURATION_config_tool_run(void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
Main task to run to perform operations typical for gnunet-config as per the configuration settings gi...
void(* GNUNET_CONFIGURATION_SectionIterator)(void *cls, const char *section)
Function to iterate over all configuration sections.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_deserialize(struct GNUNET_CONFIGURATION_Handle *cfg, const char *mem, size_t size, const char *source_filename)
De-serializes configuration.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_size(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *size)
Get a configuration value that should be a size in bytes.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
char * GNUNET_CONFIGURATION_serialize(const struct GNUNET_CONFIGURATION_Handle *cfg, size_t *size)
Serializes the given configuration.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_time(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, struct GNUNET_TIME_Relative *time)
Get a configuration value that should be a relative time.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
void GNUNET_CONFIGURATION_set_value_number(struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long number)
Set a configuration value that should be a number.
char * GNUNET_CONFIGURATION_default_filename(const struct GNUNET_OS_ProjectData *pd)
Return the filename of the default configuration filename that is used when no explicit configuration...
char * GNUNET_CONFIGURATION_expand_dollar(const struct GNUNET_CONFIGURATION_Handle *cfg, char *orig)
Expand an expression of the form "$FOO/BAR" to "DIRECTORY/BAR" where either in the "PATHS" section or...
void GNUNET_CONFIGURATION_set_value_float(struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, float number)
Set a configuration value that should be a float.
const struct GNUNET_OS_ProjectData * GNUNET_CONFIGURATION_get_project_data(const struct GNUNET_CONFIGURATION_Handle *cfg)
Return the project data associated with this configuration.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_load(struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename)
Load configuration.
struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_get_diff(const struct GNUNET_CONFIGURATION_Handle *cfg_default, const struct GNUNET_CONFIGURATION_Handle *cfg_new)
Compute configuration with only entries that have been changed.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_parse(struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename)
Parse a configuration file, add all of the options in the file to the configuration environment.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_float(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, float *number)
Get a configuration value that should be a floating point number.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_load_from(struct GNUNET_CONFIGURATION_Handle *cfg, const char *defaults_d)
Load default configuration.
int GNUNET_CONFIGURATION_iterate_value_filenames(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, GNUNET_FileNameCallback cb, void *cb_cls)
Iterate over the set of filenames stored in a configuration value.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_have_value(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Test if we have a value for a particular option.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_choice(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *const *choices, const char **value)
Get a configuration value that should be in a set of predefined strings.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_write(struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename)
Write configuration file.
void(* GNUNET_CONFIGURATION_Iterator)(void *cls, const char *section, const char *option, const char *value)
Function to iterate over options.
void GNUNET_CONFIGURATION_iterate_section_values(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, GNUNET_CONFIGURATION_Iterator iter, void *iter_cls)
Iterate over values of a section in the configuration.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_write_diffs(const struct GNUNET_CONFIGURATION_Handle *cfg_default, const struct GNUNET_CONFIGURATION_Handle *cfg_new, const char *filename)
Write only configuration entries that have been changed to configuration file.
char * GNUNET_CONFIGURATION_serialize_diagnostics(const struct GNUNET_CONFIGURATION_Handle *cfg)
Serializes the given configuration with diagnostics information.
void GNUNET_CONFIGURATION_enable_diagnostics(struct GNUNET_CONFIGURATION_Handle *cfg)
Enable extra diagnostics.
struct GNUNET_DISK_FileHandle * GNUNET_DISK_file_open(const char *fn, enum GNUNET_DISK_OpenFlags flags, enum GNUNET_DISK_AccessPermissions perm)
Open a file.
Definition disk.c:1308
int GNUNET_DISK_glob(const char *glob_pattern, GNUNET_FileNameCallback callback, void *callback_cls)
Find all files matching a glob pattern.
Definition disk.c:1063
ssize_t GNUNET_DISK_file_write(const struct GNUNET_DISK_FileHandle *h, const void *buffer, size_t n)
Write a buffer to a file.
Definition disk.c:745
enum GNUNET_GenericReturnValue GNUNET_DISK_file_test_read(const char *fil)
Check that fil corresponds to a filename and the file has read permissions.
Definition disk.c:565
enum GNUNET_GenericReturnValue GNUNET_DISK_file_size(const char *filename, uint64_t *size, int include_symbolic_links, int single_file_mode)
Get the size of the file (or directory) of the given file (in bytes).
Definition disk.c:235
enum GNUNET_GenericReturnValue GNUNET_DISK_file_sync(const struct GNUNET_DISK_FileHandle *h)
Write file changes to disk.
Definition disk.c:1507
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_test(const char *fil, int is_readable)
Test if fil is a directory and listable.
Definition disk.c:466
enum GNUNET_GenericReturnValue GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition disk.c:1386
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition disk.c:664
ssize_t GNUNET_DISK_fn_read(const char *fn, void *result, size_t len)
Read the contents of a binary file into a buffer.
Definition disk.c:720
int GNUNET_DISK_directory_scan(const char *dir_name, GNUNET_FileNameCallback callback, void *callback_cls)
Scan a directory for files.
Definition disk.c:881
@ GNUNET_DISK_OPEN_WRITE
Open the file for writing.
@ GNUNET_DISK_OPEN_TRUNCATE
Truncate file if it exists.
@ GNUNET_DISK_OPEN_CREATE
Create file if it doesn't exist.
@ GNUNET_DISK_PERM_USER_READ
Owner can read.
@ GNUNET_DISK_PERM_GROUP_READ
Group can read.
@ GNUNET_DISK_PERM_GROUP_WRITE
Group can write.
@ GNUNET_DISK_PERM_USER_WRITE
Owner can write.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
enum GNUNET_GenericReturnValue(* GNUNET_FileNameCallback)(void *cls, const char *filename)
Function called with a filename.
#define GNUNET_log(kind,...)
char * GNUNET_buffer_reap_str(struct GNUNET_Buffer *buf)
Clear the buffer and return the string it contained.
Definition buffer.c:89
void GNUNET_buffer_write_fstr(struct GNUNET_Buffer *buf, const char *fmt,...) __attribute__((format(printf
Write a 0-terminated formatted string to a buffer, excluding the 0-terminator.
void GNUNET_buffer_write_str(struct GNUNET_Buffer *buf, const char *str)
Write a 0-terminated string to a buffer, excluding the 0-terminator.
Definition buffer.c:77
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
void GNUNET_log_config_invalid(enum GNUNET_ErrorType kind, const char *section, const char *option, const char *required)
Log error message about invalid configuration option value.
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
int GNUNET_snprintf(char *buf, size_t size, const char *format,...) __attribute__((format(printf
Like snprintf, just aborts if the buffer is of insufficient size.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_realloc(ptr, size)
Wrapper around realloc.
#define GNUNET_array_append(arr, len, element)
Append an element to an array (growing the array by one).
#define GNUNET_free(ptr)
Wrapper around free.
char * GNUNET_OS_installation_get_path(const struct GNUNET_OS_ProjectData *pd, enum GNUNET_OS_InstallationPathKind dirkind)
Get the path to a specific GNUnet installation directory or, with GNUNET_OS_IPK_SELF_PREFIX,...
GNUNET_OS_InstallationPathKind
Possible installation paths to request.
char * GNUNET_OS_get_libexec_binary_path(const struct GNUNET_OS_ProjectData *pd, const char *progname)
Given the name of a gnunet-helper, gnunet-service or gnunet-daemon binary, try to prefix it with the ...
@ GNUNET_OS_IPK_SELF_PREFIX
Return the installation directory of this application, not the one of the overall GNUnet installation...
@ GNUNET_OS_IPK_ICONDIR
Return the prefix of the path with application icons (share/icons/).
@ GNUNET_OS_IPK_DATADIR
Return the directory where data is installed (share/gnunet/)
@ GNUNET_OS_IPK_DOCDIR
Return the prefix of the path with documentation files, including the license (share/doc/gnunet/).
@ GNUNET_OS_IPK_LOCALEDIR
Return the directory where translations are installed (share/locale/)
@ GNUNET_OS_IPK_LIBDIR
Return the directory where libraries are installed.
@ GNUNET_OS_IPK_PREFIX
Return the "PREFIX" directory given to configure.
@ GNUNET_OS_IPK_BINDIR
Return the directory where the program binaries are installed.
@ GNUNET_OS_IPK_LIBEXECDIR
Return the directory where helper binaries are installed (lib/gnunet/libexec/)
char * GNUNET_STRINGS_filename_expand(const char *fil)
Complete filename (a la shell) from abbrevition.
Definition strings.c:531
enum GNUNET_GenericReturnValue GNUNET_STRINGS_string_to_data(const char *enc, size_t enclen, void *out, size_t out_size)
Convert CrockfordBase32 encoding back to data.
Definition strings.c:843
enum GNUNET_GenericReturnValue GNUNET_STRINGS_path_is_absolute(const char *filename, int can_be_uri, int *r_is_uri, char **r_uri_scheme)
Check whether filename is absolute or not, and if it's an URI.
Definition strings.c:1012
enum GNUNET_GenericReturnValue GNUNET_STRINGS_fancy_time_to_relative(const char *fancy_time, struct GNUNET_TIME_Relative *rtime)
Convert a given fancy human-readable time to our internal representation.
Definition strings.c:259
enum GNUNET_GenericReturnValue GNUNET_STRINGS_fancy_size_to_bytes(const char *fancy_size, unsigned long long *size)
Convert a given fancy human-readable size to bytes.
Definition strings.c:235
static unsigned int size
Size of the "table".
Definition peer.c:68
#define DIR_SEPARATOR
Definition platform.h:166
#define DIR_SEPARATOR_STR
Definition platform.h:167
#define _(String)
GNU gettext support macro.
Definition platform.h:179
#define SIZE_MAX
Definition platform.h:213
#define EXIT_INVALIDARGUMENT
Definition platform.h:258
#define EXIT_NOTCONFIGURED
Definition platform.h:274
uint32_t number
Closure to collect_files_cb.
char ** files
Collected files from globbing.
unsigned int files_length
Size of the files array.
configuration entry
char * hint_filename
Diagnostics information for the filename.
struct ConfigEntry * next
This is a linked list.
char * key
key for this entry
unsigned int hint_lineno
Diagnostics information for the line number.
char * val
current, committed value
char * hint_restrict_section
Was this configuration file parsed via @inline-secret@?
struct ConfigFile * next
char * source_filename
Source filename.
bool hint_inaccessible
Was this configuration file inaccessible?
struct ConfigFile * prev
unsigned int level
Level in the tree of loaded config files.
configuration section
char * name
name of the section
char * hint_inlined_from_filename
For secret sections: Where was this inlined from?
struct ConfigEntry * entries
entries in the section
bool inaccessible
Is the configuration section marked as inaccessible?
struct ConfigSection * next
This is a linked list.
char * hint_secret_filename
Diagnostics hint for the secret file.
unsigned int hint_inlined_from_line
For secret sections: Where was this inlined from?
char * hint_secret_stat
Extra information regarding permissions of the secret file.
Used for diffing a configuration object against the default one.
const struct GNUNET_CONFIGURATION_Handle * cfg_default
struct GNUNET_CONFIGURATION_Handle * cfgDiff
Dynamically growing buffer.
Closure for GNUNET_CONFIGURATION_config_tool_run() with settings for what should be done with the con...
int full
Should the generated configuration file contain the whole configuration?
int global_ret
Return value from the operation, to be returned from 'main'.
int diagnostics
Should we give extra diagnostics?
int list_sections
Whether to show the sections.
int rewrite
Should we write out the configuration file, even if no value was changed?
int is_filename
Treat option as a filename.
struct ConfigFile * loaded_files_tail
Linked list of loaded files.
bool load_called
Was the configuration ever loaded via GNUNET_CONFIGURATION_load?
unsigned int current_nest_level
Current nesting level of file loading.
const struct GNUNET_OS_ProjectData * pd
Project data for this configuration object.
struct ConfigSection * sections
Configuration sections.
struct ConfigFile * loaded_files_head
Linked list of loaded files.
char * main_filename
Name of the entry point configuration file.
enum GNUNET_GenericReturnValue dirty
Modification indication since last save GNUNET_NO if clean, GNUNET_YES if dirty, GNUNET_SYSERR on err...
bool diagnostics
Enable diagnostics.
const char * restrict_section
When parsing into this configuration, and this value is non-NULL, only parse sections of the same nam...
Handle used to access files (and pipes).
Project-specific data used to help the OS subsystem find installation paths.
const char * base_config_varname
Name of an environment variable that can be used to override the location from which default configur...
const char * project_dirname
Name of the project that is used in the "libexec" prefix, For example, "gnunet".
const char * user_config_file
Configuration file name to use (if $XDG_CONFIG_HOME is not set).
const char * config_file
Configuration file name (in $XDG_CONFIG_HOME) to use.
Time for relative time used by GNUnet, in microseconds.

Function Documentation

◆ collect_files_cb()

static enum GNUNET_GenericReturnValue collect_files_cb ( void *  cls,
const char *  filename 
)
static

Function called with a filename.

Parameters
clsclosure
filenamecomplete filename (absolute path)
Returns
GNUNET_OK to continue to iterate, GNUNET_NO to stop iteration with no error, GNUNET_SYSERR to abort iteration with error!

Definition at line 394 of file configuration.c.

396{
397 struct CollectFilesContext *igc = cls;
398
400 igc->files_length,
402 return GNUNET_OK;
403}

References filename, CollectFilesContext::files, CollectFilesContext::files_length, GNUNET_array_append, GNUNET_OK, and GNUNET_strdup.

Referenced by GNUNET_CONFIGURATION_load_from(), and handle_inline().

Here is the caller graph for this function:

◆ find_section()

static struct ConfigSection * find_section ( const struct GNUNET_CONFIGURATION_Handle cfg,
const char *  section 
)
static

Find a section entry from a configuration.

Parameters
cfgconfiguration to search in
sectionname of the section to look for
Returns
matching entry, NULL if not found

Definition at line 414 of file configuration.c.

416{
417 struct ConfigSection *pos;
418
419 if (NULL == cfg)
420 return NULL;
421 pos = cfg->sections;
422 while ( (NULL != pos) &&
423 (0 != strcasecmp (section,
424 pos->name)) )
425 pos = pos->next;
426 return pos;
427}

References cfg, ConfigSection::name, ConfigSection::next, and GNUNET_CONFIGURATION_Handle::sections.

Referenced by find_entry(), GNUNET_CONFIGURATION_set_value_string(), and handle_inline().

Here is the caller graph for this function:

◆ pstrcmp()

static int pstrcmp ( const void *  a,
const void *  b 
)
static

Definition at line 431 of file configuration.c.

433{
434 return strcmp (*((const char **) a),
435 *((const char **) b));
436}

Referenced by GNUNET_CONFIGURATION_load_from(), and handle_inline().

Here is the caller graph for this function:

◆ handle_inline()

static enum GNUNET_GenericReturnValue handle_inline ( struct GNUNET_CONFIGURATION_Handle cfg,
const char *  path_or_glob,
bool  path_is_glob,
const char *  restrict_section,
const char *  source_filename,
unsigned int  source_lineno 
)
static

Handle an inline directive.

Returns
GNUNET_SYSERR on error, GNUNET_OK otherwise

Definition at line 445 of file configuration.c.

451{
452 char *inline_path = NULL;
453 struct GNUNET_CONFIGURATION_Handle *other_cfg = NULL;
454 struct CollectFilesContext igc = {
455 .files = NULL,
456 .files_length = 0,
457 };
458 enum GNUNET_GenericReturnValue fun_ret;
459 unsigned int old_nest_level = cfg->current_nest_level++;
460
461 /* We support the section restriction only for non-globs */
462 GNUNET_assert (! (path_is_glob && (NULL != restrict_section)));
463
464 if (NULL == source_filename)
465 {
467 "Refusing to parse inline configurations, "
468 "not allowed without source filename!\n");
469 fun_ret = GNUNET_SYSERR;
470 goto cleanup;
471 }
472
473 if ('/' == *path_or_glob)
474 inline_path = GNUNET_strdup (path_or_glob);
475 else
476 {
477 /* We compute the canonical, absolute path first,
478 so that relative imports resolve properly with symlinked
479 config files. */
480 char *source_realpath;
481 char *endsep;
482
483 source_realpath = realpath (source_filename,
484 NULL);
485 if (NULL == source_realpath)
486 {
487 /* Couldn't even resolve path of base dir. */
488 GNUNET_break (0);
489 /* failed to parse included config */
490 fun_ret = GNUNET_SYSERR;
491 goto cleanup;
492 }
493 endsep = strrchr (source_realpath, '/');
494 GNUNET_assert (NULL != endsep);
495 *endsep = '\0';
496 GNUNET_asprintf (&inline_path,
497 "%s/%s",
498 source_realpath,
499 path_or_glob);
500 free (source_realpath);
501 }
502
503 if (path_is_glob)
504 {
505 int nret;
506
508 "processing config glob '%s'\n",
509 inline_path);
510
511 nret = GNUNET_DISK_glob (inline_path,
513 &igc);
514 if (-1 == nret)
515 {
516 fun_ret = GNUNET_SYSERR;
517 goto cleanup;
518 }
519 GNUNET_assert (nret == igc.files_length);
520 qsort (igc.files,
521 igc.files_length,
522 sizeof (char *),
523 &pstrcmp);
524 for (int i = 0; i < nret; i++)
525 {
526 if (GNUNET_OK !=
528 igc.files[i]))
529 {
530 fun_ret = GNUNET_SYSERR;
531 goto cleanup;
532 }
533 }
534 fun_ret = GNUNET_OK;
535 }
536 else if (NULL != restrict_section)
537 {
538 enum GNUNET_GenericReturnValue inner_ret;
539 struct ConfigSection *cs;
540 struct ConfigFile *cf = GNUNET_new (struct ConfigFile);
541
542 inner_ret = GNUNET_DISK_file_test_read (inline_path);
543
544 cs = find_section (cfg, restrict_section);
545
546 if (NULL == cs)
547 {
548 cs = GNUNET_new (struct ConfigSection);
549 cs->name = GNUNET_strdup (restrict_section);
550 cs->next = cfg->sections;
551 cfg->sections = cs;
552 cs->entries = NULL;
553 }
554 if (cfg->diagnostics)
555 {
556 const char *pwname;
557 const char *grname;
558 char *sfn = GNUNET_STRINGS_filename_expand (inline_path);
559 struct stat istat;
560
561 cs->hint_secret_filename = sfn;
562 if (0 == stat (sfn, &istat))
563 {
564 struct passwd *pw = getpwuid (istat.st_uid);
565 struct group *gr = getgrgid (istat.st_gid);
566 pwname = (NULL == pw) ? "<unknown>" : pw->pw_name;
567 grname = (NULL == gr) ? "<unknown>" : gr->gr_name;
568
570 "%s:%s %o",
571 pwname,
572 grname,
573 istat.st_mode);
574 }
575 else
576 {
577 cs->hint_secret_stat = GNUNET_strdup ("<can't stat file>");
578 }
579 if (source_filename)
580 {
581 /* Possible that this secret section has been inlined before */
583 cs->hint_inlined_from_filename = GNUNET_strdup (source_filename);
584 cs->hint_inlined_from_line = source_lineno;
585 }
586 }
587
588 /* Put file in the load list for diagnostics, even if we can't access it. */
589 {
591 cf->source_filename = GNUNET_strdup (inline_path);
592 cf->hint_restrict_section = GNUNET_strdup (restrict_section);
595 cf);
596 }
597
598 if (GNUNET_OK != inner_ret)
599 {
600 cs->inaccessible = true;
601 cf->hint_inaccessible = true;
602 /* File can't be accessed, but that's okay. */
603 fun_ret = GNUNET_OK;
604 goto cleanup;
605 }
606
607 other_cfg = GNUNET_CONFIGURATION_create (cfg->pd);
608 other_cfg->restrict_section = restrict_section;
609 inner_ret = GNUNET_CONFIGURATION_parse (other_cfg,
610 inline_path);
611 if (GNUNET_OK != inner_ret)
612 {
613 cf->hint_inaccessible = true;
614 fun_ret = inner_ret;
615 goto cleanup;
616 }
617
618 cs = find_section (other_cfg,
619 restrict_section);
620 if (NULL == cs)
621 {
623 "Configuration file '%s' loaded with @inline-secret@ "
624 "does not contain section '%s'.\n",
625 inline_path,
626 restrict_section);
627 /* Inlined configuration is accessible but doesn't contain any values.
628 We treat this as if the inlined section was empty, and do not
629 consider it an error. */
630 fun_ret = GNUNET_OK;
631 goto cleanup;
632 }
633 for (struct ConfigEntry *ce = cs->entries;
634 NULL != ce;
635 ce = ce->next)
637 restrict_section,
638 ce->key,
639 ce->val);
640 fun_ret = GNUNET_OK;
641 }
642 else if (GNUNET_OK !=
644 inline_path))
645 {
646 fun_ret = GNUNET_SYSERR;
647 goto cleanup;
648 }
649 else
650 {
651 fun_ret = GNUNET_OK;
652 }
653cleanup:
654 cfg->current_nest_level = old_nest_level;
655 if (NULL != other_cfg)
657 GNUNET_free (inline_path);
658 if (igc.files_length > 0)
659 {
660 for (size_t i = 0; i < igc.files_length; i++)
661 GNUNET_free (igc.files[i]);
663 }
664 return fun_ret;
665}

References cfg, cleanup(), collect_files_cb(), GNUNET_CONFIGURATION_Handle::current_nest_level, GNUNET_CONFIGURATION_Handle::diagnostics, ConfigSection::entries, CollectFilesContext::files, CollectFilesContext::files_length, find_section(), GNUNET_array_grow, GNUNET_asprintf(), GNUNET_assert, GNUNET_break, GNUNET_CONFIGURATION_create(), GNUNET_CONFIGURATION_destroy(), GNUNET_CONFIGURATION_parse(), GNUNET_CONFIGURATION_set_value_string(), GNUNET_CONTAINER_DLL_insert_tail, GNUNET_DISK_file_test_read(), GNUNET_DISK_glob(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_free, GNUNET_new, GNUNET_OK, GNUNET_strdup, GNUNET_STRINGS_filename_expand(), GNUNET_SYSERR, ConfigFile::hint_inaccessible, ConfigSection::hint_inlined_from_filename, ConfigSection::hint_inlined_from_line, ConfigFile::hint_restrict_section, ConfigSection::hint_secret_filename, ConfigSection::hint_secret_stat, ConfigSection::inaccessible, ConfigFile::level, GNUNET_CONFIGURATION_Handle::loaded_files_head, GNUNET_CONFIGURATION_Handle::loaded_files_tail, LOG, ConfigSection::name, ConfigSection::next, GNUNET_CONFIGURATION_Handle::pd, pstrcmp(), GNUNET_CONFIGURATION_Handle::restrict_section, GNUNET_CONFIGURATION_Handle::sections, and ConfigFile::source_filename.

Referenced by GNUNET_CONFIGURATION_deserialize().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_entry()

static struct ConfigEntry * find_entry ( const struct GNUNET_CONFIGURATION_Handle cfg,
const char *  section,
const char *  key 
)
static

Find an entry from a configuration.

Parameters
cfghandle to the configuration
sectionsection the option is in
keythe option
Returns
matching entry, NULL if not found

Definition at line 677 of file configuration.c.

680{
681 struct ConfigSection *sec;
682
683 if (NULL == (sec = find_section (cfg,
684 section)))
685 return NULL;
686 for (struct ConfigEntry *pos = sec->entries;
687 pos != NULL;
688 pos = pos->next)
689 if (0 == strcasecmp (key,
690 pos->key))
691 return pos;
692 if (sec->inaccessible)
693 {
695 "Section '%s' is marked as inaccessible, because the configuration "
696 "file that contains the section can't be read. Attempts to use "
697 "option '%s' will fail.\n",
698 section,
699 key);
700 return NULL;
701 }
702 return NULL;
703}

References cfg, ConfigSection::entries, find_section(), GNUNET_ERROR_TYPE_WARNING, ConfigSection::inaccessible, key, and LOG.

Referenced by compare_entries(), GNUNET_CONFIGURATION_get_value_choice(), GNUNET_CONFIGURATION_get_value_float(), GNUNET_CONFIGURATION_get_value_number(), GNUNET_CONFIGURATION_get_value_size(), GNUNET_CONFIGURATION_get_value_string(), GNUNET_CONFIGURATION_get_value_time(), GNUNET_CONFIGURATION_have_value(), GNUNET_CONFIGURATION_set_value_string(), and set_entry_hint().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_entry_hint()

static void set_entry_hint ( struct GNUNET_CONFIGURATION_Handle cfg,
const char *  section,
const char *  option,
const char *  hint_filename,
unsigned int  hint_line 
)
static

Set a configuration hint.

Parameters
cfgconfiguration handle
sectionsection
optionconfig option
hint_filename
hint_line

Definition at line 716 of file configuration.c.

721{
722 struct ConfigEntry *e = find_entry (cfg, section, option);
723 if (! cfg->diagnostics)
724 return;
725 if (! e)
726 return;
728 e->hint_lineno = hint_line;
729}

References cfg, GNUNET_CONFIGURATION_Handle::diagnostics, find_entry(), GNUNET_strdup, ConfigEntry::hint_filename, and ConfigEntry::hint_lineno.

Referenced by GNUNET_CONFIGURATION_deserialize().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ do_skip()

static bool do_skip ( const char *  sec,
const char *  key 
)
static

Should we skip this configuration entry when serializing?

Parameters
secsection name
keykey
Returns
true if we should skip it

Definition at line 1137 of file configuration.c.

1139{
1140 if (0 != strcasecmp ("PATHS",
1141 sec))
1142 return false;
1143 return ( (0 == strcasecmp ("DATADIR",
1144 key)) ||
1145 (0 == strcasecmp ("LIBDIR",
1146 key)) ||
1147 (0 == strcasecmp ("BINDIR",
1148 key)) ||
1149 (0 == strcasecmp ("PREFIX",
1150 key)) ||
1151 (0 == strcasecmp ("LOCALEDIR",
1152 key)) ||
1153 (0 == strcasecmp ("ICONDIR",
1154 key)) ||
1155 (0 == strcasecmp ("DOCDIR",
1156 key)) ||
1157 (0 == strcasecmp ("DEFAULTCONFIG",
1158 key)) ||
1159 (0 == strcasecmp ("LIBEXECDIR",
1160 key)) );
1161}

References key.

Referenced by GNUNET_CONFIGURATION_serialize(), and GNUNET_CONFIGURATION_serialize_diagnostics().

Here is the caller graph for this function:

◆ dump_os_ipk()

static void dump_os_ipk ( const struct GNUNET_CONFIGURATION_Handle cfg,
struct GNUNET_Buffer buf,
enum GNUNET_OS_InstallationPathKind  ipk 
)
static

Dump an os installation path to a buffer.

Parameters
cfgconfiguration
bufbuffer to write to
ipkwhich path to print

Definition at line 1271 of file configuration.c.

1275{
1277 ipk);
1278 const char *ipkname;
1279 switch (ipk)
1280 {
1282 ipkname = "IPK_DATADIR";
1283 break;
1285 ipkname = "IPK_BINDIR";
1286 break;
1288 ipkname = "IPK_LIBDIR";
1289 break;
1291 ipkname = "IPK_PREFIX";
1293 ipkname = "IPK_LOCALEDIR";
1294 break;
1296 ipkname = "IPK_ICONDIR";
1298 ipkname = "IPK_DOCDIR";
1299 break;
1301 ipkname = "IPK_LIBEXECDIR";
1302 break;
1304 ipkname = "IPK_SELF_PREFIX";
1305 break;
1306 default:
1307 ipkname = "??";
1308 break;
1309 }
1311 "# %s = %s\n",
1312 ipkname,
1313 v);
1314 GNUNET_free (v);
1315}

References cfg, GNUNET_buffer_write_fstr(), GNUNET_free, GNUNET_OS_installation_get_path(), GNUNET_OS_IPK_BINDIR, GNUNET_OS_IPK_DATADIR, GNUNET_OS_IPK_DOCDIR, GNUNET_OS_IPK_ICONDIR, GNUNET_OS_IPK_LIBDIR, GNUNET_OS_IPK_LIBEXECDIR, GNUNET_OS_IPK_LOCALEDIR, GNUNET_OS_IPK_PREFIX, GNUNET_OS_IPK_SELF_PREFIX, and GNUNET_CONFIGURATION_Handle::pd.

Referenced by GNUNET_CONFIGURATION_serialize_diagnostics().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ copy_entry()

static void copy_entry ( void *  cls,
const char *  section,
const char *  option,
const char *  value 
)
static

Copy a configuration value to the given target configuration.

Overwrites existing entries.

Parameters
clsthe destination configuration (struct GNUNET_CONFIGURATION_Handle *)
sectionsection for the value
optionoption name of the value
valuevalue to copy

Definition at line 1693 of file configuration.c.

1697{
1698 struct GNUNET_CONFIGURATION_Handle *dst = cls;
1699
1701 section,
1702 option,
1703 value);
1704}

References GNUNET_CONFIGURATION_set_value_string(), and value.

Referenced by GNUNET_CONFIGURATION_dup().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ compare_entries()

static void compare_entries ( void *  cls,
const char *  section,
const char *  option,
const char *  value 
)
static

A callback function, compares entries from two configurations (default against a new configuration) and write the diffs in a diff-configuration object (the callback object).

Parameters
clsthe diff configuration (struct DiffHandle *)
sectionsection for the value (of the default conf.)
optionoption name of the value (of the default conf.)
valuevalue to copy (of the default conf.)

Definition at line 1732 of file configuration.c.

1736{
1737 struct DiffHandle *dh = cls;
1738 struct ConfigEntry *entNew;
1739
1740 entNew = find_entry (dh->cfg_default, section, option);
1741 if ((NULL != entNew) && (NULL != entNew->val) &&
1742 (0 == strcmp (entNew->val, value)))
1743 return;
1745 section,
1746 option,
1747 value);
1748}

References DiffHandle::cfg_default, DiffHandle::cfgDiff, find_entry(), GNUNET_CONFIGURATION_set_value_string(), ConfigEntry::val, and value.

Referenced by GNUNET_CONFIGURATION_get_diff().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ expand_dollar()

static char * expand_dollar ( const struct GNUNET_CONFIGURATION_Handle cfg,
char *  orig,
unsigned int  depth 
)
static

Expand an expression of the form "$FOO/BAR" to "DIRECTORY/BAR" where either in the "PATHS" section or the environment "FOO" is set to "DIRECTORY".

We also support default expansion, i.e. ${VARIABLE:-default} will expand to $VARIABLE if VARIABLE is set in PATHS or the environment, and otherwise to "default". Note that "default" itself can also be a $-expression, thus "${VAR1:-{$VAR2}}" will expand to VAR1 and if that is not defined to VAR2.

Parameters
cfgconfiguration to use for path expansion
origstring to $-expand (will be freed!)
depthrecursion depth, used to detect recursive expansions
Returns
$-expanded string, never NULL unless orig was NULL

Definition at line 2112 of file configuration.c.

2115{
2116 char *prefix;
2117 char *result;
2118 char *start;
2119 const char *post;
2120 const char *env;
2121 char *def;
2122 char *end;
2123 unsigned int lopen;
2124 char erased_char;
2125 char *erased_pos;
2126 size_t len;
2127
2128 if (NULL == orig)
2129 return NULL;
2130 if (depth > 128)
2131 {
2133 "Recursive expansion suspected, aborting $-expansion for term `%s'\n",
2134 orig);
2135 return orig;
2136 }
2138 "Asked to $-expand %s\n",
2139 orig);
2140 if ('$' != orig[0])
2141 {
2143 "Doesn't start with $ - not expanding\n");
2144 return orig;
2145 }
2146 erased_char = 0;
2147 erased_pos = NULL;
2148 if ('{' == orig[1])
2149 {
2150 start = &orig[2];
2151 lopen = 1;
2152 end = &orig[1];
2153 while (lopen > 0)
2154 {
2155 end++;
2156 switch (*end)
2157 {
2158 case '}':
2159 lopen--;
2160 break;
2161
2162 case '{':
2163 lopen++;
2164 break;
2165
2166 case '\0':
2168 "Missing closing `}' in option `%s'\n",
2169 orig);
2170 return orig;
2171
2172 default:
2173 break;
2174 }
2175 }
2176 erased_char = *end;
2177 erased_pos = end;
2178 *end = '\0';
2179 post = end + 1;
2180 def = strchr (orig, ':');
2181 if (NULL != def)
2182 {
2183 *def = '\0';
2184 def++;
2185 if (('-' == *def) || ('=' == *def))
2186 def++;
2187 def = GNUNET_strdup (def);
2188 }
2189 }
2190 else
2191 {
2192 int i;
2193
2194 start = &orig[1];
2195 def = NULL;
2196 i = 0;
2197 while ( (orig[i] != '/') &&
2198 (orig[i] != '\\') &&
2199 (orig[i] != '\0') &&
2200 (orig[i] != ' ') )
2201 i++;
2202 if (orig[i] == '\0')
2203 {
2204 post = "";
2205 }
2206 else
2207 {
2208 erased_char = orig[i];
2209 erased_pos = &orig[i];
2210 orig[i] = '\0';
2211 post = &orig[i + 1];
2212 }
2213 }
2215 "Split into `%s' and `%s' with default %s\n",
2216 start,
2217 post,
2218 def);
2219 if (GNUNET_OK !=
2221 "PATHS",
2222 start,
2223 &prefix))
2224 {
2225 if (NULL == (env = getenv (start)))
2226 {
2227 /* try default */
2228 def = expand_dollar (cfg,
2229 def,
2230 depth + 1);
2231 env = def;
2232 }
2233 if (NULL == env)
2234 {
2236 if (erased_pos)
2237 *erased_pos = erased_char;
2239 "Failed to expand `%s' in `%s' as it is neither found in [PATHS] nor defined as an environmental variable\n",
2240 start,
2241 orig);
2243 return orig;
2244 }
2246 }
2248 prefix);
2249 if ((erased_pos) && ('}' != erased_char))
2250 {
2251 len = strlen (prefix) + 1;
2252 prefix = GNUNET_realloc (prefix, len + 1);
2253 prefix[len - 1] = erased_char;
2254 prefix[len] = '\0';
2255 }
2256 result = GNUNET_malloc (strlen (prefix) + strlen (post) + 1);
2257 strcpy (result, prefix);
2258 strcat (result, post);
2259 GNUNET_free (def);
2261 GNUNET_free (orig);
2262 return result;
2263}

References cfg, end, env, expand_dollar(), getenv(), GNUNET_CONFIGURATION_expand_dollar(), GNUNET_CONFIGURATION_get_value_string(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_malloc, GNUNET_OK, GNUNET_realloc, GNUNET_strdup, LOG, prefix, result, and start.

Referenced by expand_dollar(), and GNUNET_CONFIGURATION_expand_dollar().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ escape_name()

static char * escape_name ( const char *  value)
static

FIXME.

Parameters
valueFIXME
Returns
FIXME

Definition at line 2430 of file configuration.c.

2431{
2432 char *escaped;
2433 const char *rpos;
2434 char *wpos;
2435
2436 escaped = GNUNET_malloc (strlen (value) * 2 + 1);
2437 memset (escaped, 0, strlen (value) * 2 + 1);
2438 rpos = value;
2439 wpos = escaped;
2440 while (rpos[0] != '\0')
2441 {
2442 switch (rpos[0])
2443 {
2444 case '\\':
2445 case ' ':
2446 wpos[0] = '\\';
2447 wpos[1] = rpos[0];
2448 wpos += 2;
2449 break;
2450
2451 default:
2452 wpos[0] = rpos[0];
2453 wpos++;
2454 }
2455 rpos++;
2456 }
2457 return escaped;
2458}

References GNUNET_malloc, and value.

Referenced by GNUNET_CONFIGURATION_append_value_filename(), and GNUNET_CONFIGURATION_remove_value_filename().

Here is the caller graph for this function:

◆ test_match()

static enum GNUNET_GenericReturnValue test_match ( void *  cls,
const char *  fn 
)
static

FIXME.

Parameters
clsstring we compare with (const char*)
fnfilename we are currently looking at
Returns
GNUNET_OK if the names do not match, GNUNET_SYSERR if they do

Definition at line 2469 of file configuration.c.

2471{
2472 const char *of = cls;
2473
2474 return (0 == strcmp (of, fn))
2476 : GNUNET_OK;
2477}

References GNUNET_OK, and GNUNET_SYSERR.

Referenced by GNUNET_CONFIGURATION_append_value_filename().

Here is the caller graph for this function:

◆ print_filename_option()

static void print_filename_option ( void *  cls,
const char *  section,
const char *  option,
const char *  value 
)
static

Print each option in a given section as a filename.

Parameters
clsclosure
sectionname of the section
optionname of the option
valuevalue of the option

Definition at line 2799 of file configuration.c.

2803{
2804 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
2805
2806 char *value_fn;
2807 char *fn;
2808
2811 section,
2812 option,
2813 &value_fn));
2814 fn = GNUNET_STRINGS_filename_expand (value_fn);
2815 if (NULL == fn)
2816 fn = value_fn;
2817 else
2818 GNUNET_free (value_fn);
2819 fprintf (stdout,
2820 "%s = %s\n",
2821 option,
2822 fn);
2823 GNUNET_free (fn);
2824}

References cfg, GNUNET_assert, GNUNET_CONFIGURATION_get_value_filename(), GNUNET_free, GNUNET_OK, and GNUNET_STRINGS_filename_expand().

Referenced by GNUNET_CONFIGURATION_config_tool_run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ print_option()

static void print_option ( void *  cls,
const char *  section,
const char *  option,
const char *  value 
)
static

Print each option in a given section.

Parameters
clsclosure
sectionname of the section
optionname of the option
valuevalue of the option

Definition at line 2836 of file configuration.c.

2840{
2841 (void) cls;
2842 (void) section;
2843
2844 fprintf (stdout,
2845 "%s = %s\n",
2846 option,
2847 value);
2848}

References value.

Referenced by GNUNET_CONFIGURATION_config_tool_run().

Here is the caller graph for this function:

◆ print_section_name()

static void print_section_name ( void *  cls,
const char *  section 
)
static

Print out given section name.

Parameters
clsunused
sectiona section in the configuration file

Definition at line 2858 of file configuration.c.

2860{
2861 (void) cls;
2862 fprintf (stdout,
2863 "%s\n",
2864 section);
2865}

Referenced by GNUNET_CONFIGURATION_config_tool_run().

Here is the caller graph for this function: