minor style fix
[oweals/gnunet.git] / src / util / configuration.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2006, 2007, 2008, 2009, 2013 GNUnet e.V.
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18      Boston, MA 02110-1301, USA.
19 */
20
21 /**
22  * @file src/util/configuration.c
23  * @brief configuration management
24  * @author Christian Grothoff
25  */
26
27 #include "platform.h"
28 #include "gnunet_crypto_lib.h"
29 #include "gnunet_strings_lib.h"
30 #include "gnunet_configuration_lib.h"
31 #include "gnunet_disk_lib.h"
32
33 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
34
35 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
36
37 /**
38  * @brief configuration entry
39  */
40 struct ConfigEntry
41 {
42
43   /**
44    * This is a linked list.
45    */
46   struct ConfigEntry *next;
47
48   /**
49    * key for this entry
50    */
51   char *key;
52
53   /**
54    * current, commited value
55    */
56   char *val;
57 };
58
59
60 /**
61  * @brief configuration section
62  */
63 struct ConfigSection
64 {
65   /**
66    * This is a linked list.
67    */
68   struct ConfigSection *next;
69
70   /**
71    * entries in the section
72    */
73   struct ConfigEntry *entries;
74
75   /**
76    * name of the section
77    */
78   char *name;
79 };
80
81
82 /**
83  * @brief configuration data
84  */
85 struct GNUNET_CONFIGURATION_Handle
86 {
87   /**
88    * Configuration sections.
89    */
90   struct ConfigSection *sections;
91
92   /**
93    * Modification indication since last save
94    * #GNUNET_NO if clean, #GNUNET_YES if dirty,
95    * #GNUNET_SYSERR on error (i.e. last save failed)
96    */
97   int dirty;
98
99 };
100
101
102 /**
103  * Used for diffing a configuration object against
104  * the default one
105  */
106 struct DiffHandle
107 {
108   const struct GNUNET_CONFIGURATION_Handle *cfg_default;
109
110   struct GNUNET_CONFIGURATION_Handle *cfgDiff;
111 };
112
113
114 /**
115  * Create a GNUNET_CONFIGURATION_Handle.
116  *
117  * @return fresh configuration object
118  */
119 struct GNUNET_CONFIGURATION_Handle *
120 GNUNET_CONFIGURATION_create ()
121 {
122   return GNUNET_new (struct GNUNET_CONFIGURATION_Handle);
123 }
124
125
126 /**
127  * Destroy configuration object.
128  *
129  * @param cfg configuration to destroy
130  */
131 void
132 GNUNET_CONFIGURATION_destroy (struct GNUNET_CONFIGURATION_Handle *cfg)
133 {
134   struct ConfigSection *sec;
135
136   while (NULL != (sec = cfg->sections))
137     GNUNET_CONFIGURATION_remove_section (cfg, sec->name);
138   GNUNET_free (cfg);
139 }
140
141
142 /**
143  * De-serializes configuration
144  *
145  * @param cfg configuration to update
146  * @param mem the memory block of serialized configuration
147  * @param size the size of the memory block
148  * @param basedir set to path from which we recursively load configuration
149  *          from inlined configurations; NULL if not and raise warnings
150  *          when we come across them
151  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
152  */
153 int
154 GNUNET_CONFIGURATION_deserialize (struct GNUNET_CONFIGURATION_Handle *cfg,
155                                   const char *mem,
156                                   size_t size,
157                                   const char *basedir)
158 {
159   char *line;
160   char *line_orig;
161   size_t line_size;
162   char *pos;
163   unsigned int nr;
164   size_t r_bytes;
165   size_t to_read;
166   size_t i;
167   int emptyline;
168   int ret;
169   char *section;
170   char *eq;
171   char *tag;
172   char *value;
173
174   ret = GNUNET_OK;
175   section = GNUNET_strdup ("");
176   nr = 0;
177   r_bytes = 0;
178   line_orig = NULL;
179   while (r_bytes < size)
180   {
181     GNUNET_free_non_null (line_orig);
182     /* fgets-like behaviour on buffer */
183     to_read = size - r_bytes;
184     pos = memchr (&mem[r_bytes], '\n', to_read);
185     if (NULL == pos)
186     {
187       line_orig = GNUNET_strndup (&mem[r_bytes], line_size = to_read);
188       r_bytes += line_size;
189     }
190     else
191     {
192       line_orig = GNUNET_strndup (&mem[r_bytes], line_size = (pos - &mem[r_bytes]));
193       r_bytes += line_size + 1;
194     }
195     line = line_orig;
196     /* increment line number */
197     nr++;
198     /* tabs and '\r' are whitespace */
199     emptyline = GNUNET_YES;
200     for (i = 0; i < line_size; i++)
201     {
202       if (line[i] == '\t')
203         line[i] = ' ';
204       if (line[i] == '\r')
205         line[i] = ' ';
206       if (' ' != line[i])
207         emptyline = GNUNET_NO;
208     }
209     /* ignore empty lines */
210     if (GNUNET_YES == emptyline)
211       continue;
212
213     /* remove tailing whitespace */
214     for (i = line_size - 1; (i >= 1) && (isspace ((unsigned char) line[i]));i--)
215       line[i] = '\0';
216
217     /* remove leading whitespace */
218     for (; line[0] != '\0' && (isspace ((unsigned char) line[0])); line++);
219
220     /* ignore comments */
221     if ( ('#' == line[0]) || ('%' == line[0]) )
222       continue;
223
224     /* handle special "@INLINE@" directive */
225     if (0 == strncasecmp (line,
226                           "@INLINE@ ",
227                           strlen ("@INLINE@ ")))
228     {
229       /* @INLINE@ value */
230       value = &line[strlen ("@INLINE@ ")];
231       if (NULL != basedir)
232       {
233         char *fn;
234
235         GNUNET_asprintf (&fn,
236                          "%s/%s",
237                          basedir,
238                          value);        
239         if (GNUNET_OK !=
240             GNUNET_CONFIGURATION_parse (cfg,
241                                         fn))
242         {
243           GNUNET_free (fn);
244           ret = GNUNET_SYSERR;    /* failed to parse included config */
245           break;
246         }
247         GNUNET_free (fn);
248       }
249       else
250       {
251         LOG (GNUNET_ERROR_TYPE_DEBUG,
252              "Ignoring parsing @INLINE@ configurations, not allowed!\n");
253         ret = GNUNET_SYSERR;
254         break;
255       }
256       continue;
257     }
258     if ( ('[' == line[0]) && (']' == line[line_size - 1]) )
259     {
260       /* [value] */
261       line[line_size - 1] = '\0';
262       value = &line[1];
263       GNUNET_free (section);
264       section = GNUNET_strdup (value);
265       continue;
266     }
267     if (NULL != (eq = strchr (line, '=')))
268     {
269       /* tag = value */
270       tag = GNUNET_strndup (line, eq - line);
271       /* remove tailing whitespace */
272       for (i = strlen (tag) - 1; (i >= 1) && (isspace ((unsigned char) tag[i]));i--)
273         tag[i] = '\0';
274
275       /* Strip whitespace */
276       value = eq + 1;
277       while (isspace ((unsigned char) value[0]))
278         value++;
279       for (i = strlen (value) - 1; (i >= 1) && (isspace ((unsigned char) value[i]));i--)
280         value[i] = '\0';
281
282       /* remove quotes */
283       i = 0;
284       if ( ('"' == value[0]) &&
285            ('"' == value[strlen (value) - 1]) )
286       {
287         value[strlen (value) - 1] = '\0';
288         value++;
289       }
290       GNUNET_CONFIGURATION_set_value_string (cfg, section, tag, &value[i]);
291       GNUNET_free (tag);
292       continue;
293     }
294     /* parse error */
295     LOG (GNUNET_ERROR_TYPE_WARNING,
296          _("Syntax error while deserializing in line %u\n"),
297          nr);
298     ret = GNUNET_SYSERR;
299     break;
300   }
301   GNUNET_free_non_null (line_orig);
302   GNUNET_free (section);
303   GNUNET_assert ( (GNUNET_OK != ret) || (r_bytes == size) );
304   return ret;
305 }
306
307
308 /**
309  * Parse a configuration file, add all of the options in the
310  * file to the configuration environment.
311  *
312  * @param cfg configuration to update
313  * @param filename name of the configuration file
314  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
315  */
316 int
317 GNUNET_CONFIGURATION_parse (struct GNUNET_CONFIGURATION_Handle *cfg,
318                             const char *filename)
319 {
320   uint64_t fs64;
321   size_t fs;
322   char *fn;
323   char *mem;
324   char *endsep;
325   int dirty;
326   int ret;
327
328   fn = GNUNET_STRINGS_filename_expand (filename);
329   LOG (GNUNET_ERROR_TYPE_DEBUG,
330        "Asked to parse config file `%s'\n",
331        fn);
332   if (NULL == fn)
333     return GNUNET_SYSERR;
334   dirty = cfg->dirty;           /* back up value! */
335   if (GNUNET_SYSERR ==
336       GNUNET_DISK_file_size (fn, &fs64, GNUNET_YES, GNUNET_YES))
337   {
338     LOG (GNUNET_ERROR_TYPE_WARNING,
339          "Error while determining the file size of `%s'\n",
340          fn);
341     GNUNET_free (fn);
342     return GNUNET_SYSERR;
343   }
344   if (fs64 > SIZE_MAX)
345   {
346     GNUNET_break (0);           /* File size is more than the heap size */
347     GNUNET_free (fn);
348     return GNUNET_SYSERR;
349   }
350   fs = fs64;
351   mem = GNUNET_malloc (fs);
352   if (fs != GNUNET_DISK_fn_read (fn, mem, fs))
353   {
354     LOG (GNUNET_ERROR_TYPE_WARNING,
355          _("Error while reading file `%s'\n"),
356          fn);
357     GNUNET_free (fn);
358     GNUNET_free (mem);
359     return GNUNET_SYSERR;
360   }
361   LOG (GNUNET_ERROR_TYPE_DEBUG,
362        "Deserializing contents of file `%s'\n",
363        fn);
364   endsep = strrchr (fn, (int) '/');
365   if (NULL != endsep)
366     *endsep = '\0';
367   ret = GNUNET_CONFIGURATION_deserialize (cfg,
368                                           mem,
369                                           fs,
370                                           fn);
371   GNUNET_free (fn);
372   GNUNET_free (mem);
373   /* restore dirty flag - anything we set in the meantime
374    * came from disk */
375   cfg->dirty = dirty;
376   return ret;
377 }
378
379
380 /**
381  * Test if there are configuration options that were
382  * changed since the last save.
383  *
384  * @param cfg configuration to inspect
385  * @return #GNUNET_NO if clean, #GNUNET_YES if dirty, #GNUNET_SYSERR on error (i.e. last save failed)
386  */
387 int
388 GNUNET_CONFIGURATION_is_dirty (const struct GNUNET_CONFIGURATION_Handle *cfg)
389 {
390   return cfg->dirty;
391 }
392
393
394 /**
395  * Serializes the given configuration.
396  *
397  * @param cfg configuration to serialize
398  * @param size will be set to the size of the serialized memory block
399  * @return the memory block where the serialized configuration is
400  *           present. This memory should be freed by the caller
401  */
402 char *
403 GNUNET_CONFIGURATION_serialize (const struct GNUNET_CONFIGURATION_Handle *cfg,
404                                 size_t *size)
405 {
406   struct ConfigSection *sec;
407   struct ConfigEntry *ent;
408   char *mem;
409   char *cbuf;
410   char *val;
411   char *pos;
412   int len;
413   size_t m_size;
414   size_t c_size;
415
416
417   /* Pass1 : calculate the buffer size required */
418   m_size = 0;
419   for (sec = cfg->sections; NULL != sec; sec = sec->next)
420   {
421     /* For each section we need to add 3 charaters: {'[',']','\n'} */
422     m_size += strlen (sec->name) + 3;
423     for (ent = sec->entries; NULL != ent; ent = ent->next)
424     {
425       if (NULL != ent->val)
426       {
427         /* if val has any '\n' then they occupy +1 character as '\n'->'\\','n' */
428         pos = ent->val;
429         while (NULL != (pos = strstr (pos, "\n")))
430         {
431           m_size++;
432           pos++;
433         }
434         /* For each key = value pair we need to add 4 characters (2
435            spaces and 1 equal-to character and 1 new line) */
436         m_size += strlen (ent->key) + strlen (ent->val) + 4;
437       }
438     }
439     /* A new line after section end */
440     m_size++;
441   }
442
443   /* Pass2: Allocate memory and write the configuration to it */
444   mem = GNUNET_malloc (m_size);
445   sec = cfg->sections;
446   c_size = 0;
447   *size = c_size;
448   while (NULL != sec)
449   {
450     len = GNUNET_asprintf (&cbuf, "[%s]\n", sec->name);
451     GNUNET_assert (0 < len);
452     GNUNET_memcpy (mem + c_size, cbuf, len);
453     c_size += len;
454     GNUNET_free (cbuf);
455     for (ent = sec->entries; NULL != ent; ent = ent->next)
456     {
457       if (NULL != ent->val)
458       {
459         val = GNUNET_malloc (strlen (ent->val) * 2 + 1);
460         strcpy (val, ent->val);
461         while (NULL != (pos = strstr (val, "\n")))
462         {
463           memmove (&pos[2], &pos[1], strlen (&pos[1]));
464           pos[0] = '\\';
465           pos[1] = 'n';
466         }
467         len = GNUNET_asprintf (&cbuf, "%s = %s\n", ent->key, val);
468         GNUNET_free (val);
469         GNUNET_memcpy (mem + c_size, cbuf, len);
470         c_size += len;
471         GNUNET_free (cbuf);
472       }
473     }
474     GNUNET_memcpy (mem + c_size, "\n", 1);
475     c_size ++;
476     sec = sec->next;
477   }
478   GNUNET_assert (c_size == m_size);
479   *size = c_size;
480   return mem;
481 }
482
483
484 /**
485  * Write configuration file.
486  *
487  * @param cfg configuration to write
488  * @param filename where to write the configuration
489  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
490  */
491 int
492 GNUNET_CONFIGURATION_write (struct GNUNET_CONFIGURATION_Handle *cfg,
493                             const char *filename)
494 {
495   char *fn;
496   char *cfg_buf;
497   size_t size;
498
499   fn = GNUNET_STRINGS_filename_expand (filename);
500   if (fn == NULL)
501     return GNUNET_SYSERR;
502   if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (fn))
503   {
504     GNUNET_free (fn);
505     return GNUNET_SYSERR;
506   }
507   cfg_buf = GNUNET_CONFIGURATION_serialize (cfg, &size);
508   if (size != GNUNET_DISK_fn_write (fn, cfg_buf, size,
509                                     GNUNET_DISK_PERM_USER_READ
510                                     | GNUNET_DISK_PERM_USER_WRITE
511                                     | GNUNET_DISK_PERM_GROUP_READ
512                                     | GNUNET_DISK_PERM_GROUP_WRITE))
513   {
514     GNUNET_free (fn);
515     GNUNET_free (cfg_buf);
516     LOG (GNUNET_ERROR_TYPE_WARNING,
517          "Writing configration to file `%s' failed\n",
518          filename);
519     cfg->dirty = GNUNET_SYSERR; /* last write failed */
520     return GNUNET_SYSERR;
521   }
522   GNUNET_free (fn);
523   GNUNET_free (cfg_buf);
524   cfg->dirty = GNUNET_NO;       /* last write succeeded */
525   return GNUNET_OK;
526 }
527
528
529 /**
530  * Iterate over all options in the configuration.
531  *
532  * @param cfg configuration to inspect
533  * @param iter function to call on each option
534  * @param iter_cls closure for @a iter
535  */
536 void
537 GNUNET_CONFIGURATION_iterate (const struct GNUNET_CONFIGURATION_Handle *cfg,
538                               GNUNET_CONFIGURATION_Iterator iter,
539                               void *iter_cls)
540 {
541   struct ConfigSection *spos;
542   struct ConfigEntry *epos;
543
544   for (spos = cfg->sections; NULL != spos; spos = spos->next)
545     for (epos = spos->entries; NULL != epos; epos = epos->next)
546       if (NULL != epos->val)
547         iter (iter_cls, spos->name, epos->key, epos->val);
548 }
549
550
551 /**
552  * Iterate over values of a section in the configuration.
553  *
554  * @param cfg configuration to inspect
555  * @param section the section
556  * @param iter function to call on each option
557  * @param iter_cls closure for @a iter
558  */
559 void
560 GNUNET_CONFIGURATION_iterate_section_values (const struct
561                                              GNUNET_CONFIGURATION_Handle *cfg,
562                                              const char *section,
563                                              GNUNET_CONFIGURATION_Iterator iter,
564                                              void *iter_cls)
565 {
566   struct ConfigSection *spos;
567   struct ConfigEntry *epos;
568
569   spos = cfg->sections;
570   while ((spos != NULL) && (0 != strcasecmp (spos->name, section)))
571     spos = spos->next;
572   if (NULL == spos)
573     return;
574   for (epos = spos->entries; NULL != epos; epos = epos->next)
575     if (NULL != epos->val)
576       iter (iter_cls, spos->name, epos->key, epos->val);
577 }
578
579
580 /**
581  * Iterate over all sections in the configuration.
582  *
583  * @param cfg configuration to inspect
584  * @param iter function to call on each section
585  * @param iter_cls closure for @a iter
586  */
587 void
588 GNUNET_CONFIGURATION_iterate_sections (const struct GNUNET_CONFIGURATION_Handle *cfg,
589                                        GNUNET_CONFIGURATION_Section_Iterator iter,
590                                        void *iter_cls)
591 {
592   struct ConfigSection *spos;
593   struct ConfigSection *next;
594
595   next = cfg->sections;
596   while (next != NULL)
597   {
598     spos = next;
599     next = spos->next;
600     iter (iter_cls, spos->name);
601   }
602 }
603
604
605 /**
606  * Remove the given section and all options in it.
607  *
608  * @param cfg configuration to inspect
609  * @param section name of the section to remove
610  */
611 void
612 GNUNET_CONFIGURATION_remove_section (struct GNUNET_CONFIGURATION_Handle *cfg,
613                                      const char *section)
614 {
615   struct ConfigSection *spos;
616   struct ConfigSection *prev;
617   struct ConfigEntry *ent;
618
619   prev = NULL;
620   spos = cfg->sections;
621   while (NULL != spos)
622   {
623     if (0 == strcasecmp (section, spos->name))
624     {
625       if (NULL == prev)
626         cfg->sections = spos->next;
627       else
628         prev->next = spos->next;
629       while (NULL != (ent = spos->entries))
630       {
631         spos->entries = ent->next;
632         GNUNET_free (ent->key);
633         GNUNET_free_non_null (ent->val);
634         GNUNET_free (ent);
635         cfg->dirty = GNUNET_YES;
636       }
637       GNUNET_free (spos->name);
638       GNUNET_free (spos);
639       return;
640     }
641     prev = spos;
642     spos = spos->next;
643   }
644 }
645
646
647 /**
648  * Copy a configuration value to the given target configuration.
649  * Overwrites existing entries.
650  *
651  * @param cls the destination configuration (`struct GNUNET_CONFIGURATION_Handle *`)
652  * @param section section for the value
653  * @param option option name of the value
654  * @param value value to copy
655  */
656 static void
657 copy_entry (void *cls,
658             const char *section,
659             const char *option,
660             const char *value)
661 {
662   struct GNUNET_CONFIGURATION_Handle *dst = cls;
663
664   GNUNET_CONFIGURATION_set_value_string (dst, section, option, value);
665 }
666
667
668 /**
669  * Duplicate an existing configuration object.
670  *
671  * @param cfg configuration to duplicate
672  * @return duplicate configuration
673  */
674 struct GNUNET_CONFIGURATION_Handle *
675 GNUNET_CONFIGURATION_dup (const struct GNUNET_CONFIGURATION_Handle *cfg)
676 {
677   struct GNUNET_CONFIGURATION_Handle *ret;
678
679   ret = GNUNET_CONFIGURATION_create ();
680   GNUNET_CONFIGURATION_iterate (cfg, &copy_entry, ret);
681   return ret;
682 }
683
684
685 /**
686  * Find a section entry from a configuration.
687  *
688  * @param cfg configuration to search in
689  * @param section name of the section to look for
690  * @return matching entry, NULL if not found
691  */
692 static struct ConfigSection *
693 find_section (const struct GNUNET_CONFIGURATION_Handle *cfg,
694               const char *section)
695 {
696   struct ConfigSection *pos;
697
698   pos = cfg->sections;
699   while ((pos != NULL) && (0 != strcasecmp (section, pos->name)))
700     pos = pos->next;
701   return pos;
702 }
703
704
705 /**
706  * Find an entry from a configuration.
707  *
708  * @param cfg handle to the configuration
709  * @param section section the option is in
710  * @param key the option
711  * @return matching entry, NULL if not found
712  */
713 static struct ConfigEntry *
714 find_entry (const struct GNUNET_CONFIGURATION_Handle *cfg,
715            const char *section,
716            const char *key)
717 {
718   struct ConfigSection *sec;
719   struct ConfigEntry *pos;
720
721   if (NULL == (sec = find_section (cfg, section)))
722     return NULL;
723   pos = sec->entries;
724   while ((pos != NULL) && (0 != strcasecmp (key, pos->key)))
725     pos = pos->next;
726   return pos;
727 }
728
729
730 /**
731  * A callback function, compares entries from two configurations
732  * (default against a new configuration) and write the diffs in a
733  * diff-configuration object (the callback object).
734  *
735  * @param cls the diff configuration (`struct DiffHandle *`)
736  * @param section section for the value (of the default conf.)
737  * @param option option name of the value (of the default conf.)
738  * @param value value to copy (of the default conf.)
739  */
740 static void
741 compare_entries (void *cls,
742                  const char *section,
743                  const char *option,
744                  const char *value)
745 {
746   struct DiffHandle *dh = cls;
747   struct ConfigEntry *entNew;
748
749   entNew = find_entry (dh->cfg_default, section, option);
750   if ( (NULL != entNew) &&
751        (NULL != entNew->val) &&
752        (0 == strcmp (entNew->val, value)) )
753     return;
754   GNUNET_CONFIGURATION_set_value_string (dh->cfgDiff, section, option, value);
755 }
756
757
758 /**
759  * Compute configuration with only entries that have been changed
760  *
761  * @param cfg_default original configuration
762  * @param cfg_new new configuration
763  * @return configuration with only the differences, never NULL
764  */
765 struct GNUNET_CONFIGURATION_Handle *
766 GNUNET_CONFIGURATION_get_diff (const struct GNUNET_CONFIGURATION_Handle *cfg_default,
767                                const struct GNUNET_CONFIGURATION_Handle *cfg_new)
768 {
769   struct DiffHandle diffHandle;
770
771   diffHandle.cfgDiff = GNUNET_CONFIGURATION_create ();
772   diffHandle.cfg_default = cfg_default;
773   GNUNET_CONFIGURATION_iterate (cfg_new, &compare_entries, &diffHandle);
774   return diffHandle.cfgDiff;
775 }
776
777
778 /**
779  * Write only configuration entries that have been changed to configuration file
780  *
781  * @param cfg_default default configuration
782  * @param cfg_new new configuration
783  * @param filename where to write the configuration diff between default and new
784  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
785  */
786 int
787 GNUNET_CONFIGURATION_write_diffs (const struct GNUNET_CONFIGURATION_Handle
788                                   *cfg_default,
789                                   const struct GNUNET_CONFIGURATION_Handle
790                                   *cfg_new, const char *filename)
791 {
792   int ret;
793   struct GNUNET_CONFIGURATION_Handle *diff;
794
795   diff = GNUNET_CONFIGURATION_get_diff (cfg_default, cfg_new);
796   ret = GNUNET_CONFIGURATION_write (diff, filename);
797   GNUNET_CONFIGURATION_destroy (diff);
798   return ret;
799 }
800
801
802 /**
803  * Set a configuration value that should be a string.
804  *
805  * @param cfg configuration to update
806  * @param section section of interest
807  * @param option option of interest
808  * @param value value to set
809  */
810 void
811 GNUNET_CONFIGURATION_set_value_string (struct GNUNET_CONFIGURATION_Handle *cfg,
812                                        const char *section, const char *option,
813                                        const char *value)
814 {
815   struct ConfigSection *sec;
816   struct ConfigEntry *e;
817   char *nv;
818
819   e = find_entry (cfg, section, option);
820   if (NULL != e)
821   {
822     if (NULL == value)
823     {
824       GNUNET_free_non_null (e->val);
825       e->val = NULL;
826     }
827     else
828     {
829       nv = GNUNET_strdup (value);
830       GNUNET_free_non_null (e->val);
831       e->val = nv;
832     }
833     return;
834   }
835   sec = find_section (cfg, section);
836   if (sec == NULL)
837   {
838     sec = GNUNET_new (struct ConfigSection);
839     sec->name = GNUNET_strdup (section);
840     sec->next = cfg->sections;
841     cfg->sections = sec;
842   }
843   e = GNUNET_new (struct ConfigEntry);
844   e->key = GNUNET_strdup (option);
845   e->val = GNUNET_strdup (value);
846   e->next = sec->entries;
847   sec->entries = e;
848 }
849
850
851 /**
852  * Set a configuration value that should be a number.
853  *
854  * @param cfg configuration to update
855  * @param section section of interest
856  * @param option option of interest
857  * @param number value to set
858  */
859 void
860 GNUNET_CONFIGURATION_set_value_number (struct GNUNET_CONFIGURATION_Handle *cfg,
861                                        const char *section, const char *option,
862                                        unsigned long long number)
863 {
864   char s[64];
865
866   GNUNET_snprintf (s, 64, "%llu", number);
867   GNUNET_CONFIGURATION_set_value_string (cfg, section, option, s);
868 }
869
870
871 /**
872  * Get a configuration value that should be a number.
873  *
874  * @param cfg configuration to inspect
875  * @param section section of interest
876  * @param option option of interest
877  * @param number where to store the numeric value of the option
878  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
879  */
880 int
881 GNUNET_CONFIGURATION_get_value_number (const struct GNUNET_CONFIGURATION_Handle
882                                        *cfg, const char *section,
883                                        const char *option,
884                                        unsigned long long *number)
885 {
886   struct ConfigEntry *e;
887
888   if (NULL == (e = find_entry (cfg, section, option)))
889     return GNUNET_SYSERR;
890   if (NULL == e->val)
891     return GNUNET_SYSERR;
892   if (1 != SSCANF (e->val, "%llu", number))
893     return GNUNET_SYSERR;
894   return GNUNET_OK;
895 }
896
897 /**
898  * Get a configuration value that should be a floating point number.
899  *
900  * @param cfg configuration to inspect
901  * @param section section of interest
902  * @param option option of interest
903  * @param number where to store the floating value of the option
904  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
905  */
906 int
907 GNUNET_CONFIGURATION_get_value_float  (const struct GNUNET_CONFIGURATION_Handle
908                                        *cfg, const char *section,
909                                        const char *option,
910                                        float *number)
911 {
912   struct ConfigEntry *e;
913
914   if (NULL == (e = find_entry (cfg, section, option)))
915     return GNUNET_SYSERR;
916   if (NULL == e->val)
917     return GNUNET_SYSERR;
918   if (1 != SSCANF (e->val, "%f", number))
919     return GNUNET_SYSERR;
920   return GNUNET_OK;
921 }
922
923
924
925 /**
926  * Get a configuration value that should be a relative time.
927  *
928  * @param cfg configuration to inspect
929  * @param section section of interest
930  * @param option option of interest
931  * @param time set to the time value stored in the configuration
932  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
933  */
934 int
935 GNUNET_CONFIGURATION_get_value_time (const struct GNUNET_CONFIGURATION_Handle *cfg,
936                                      const char *section,
937                                      const char *option,
938                                      struct GNUNET_TIME_Relative *time)
939 {
940   struct ConfigEntry *e;
941
942   if (NULL == (e = find_entry (cfg, section, option)))
943     return GNUNET_SYSERR;
944   if (NULL == e->val)
945     return GNUNET_SYSERR;
946   return GNUNET_STRINGS_fancy_time_to_relative (e->val, time);
947 }
948
949
950 /**
951  * Get a configuration value that should be a size in bytes.
952  *
953  * @param cfg configuration to inspect
954  * @param section section of interest
955  * @param option option of interest
956  * @param size set to the size in bytes as stored in the configuration
957  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
958  */
959 int
960 GNUNET_CONFIGURATION_get_value_size (const struct GNUNET_CONFIGURATION_Handle *cfg,
961                                      const char *section,
962                                      const char *option,
963                                      unsigned long long *size)
964 {
965   struct ConfigEntry *e;
966
967   if (NULL == (e = find_entry (cfg, section, option)))
968     return GNUNET_SYSERR;
969   if (NULL == e->val)
970     return GNUNET_SYSERR;
971   return GNUNET_STRINGS_fancy_size_to_bytes (e->val, size);
972 }
973
974
975 /**
976  * Get a configuration value that should be a string.
977  *
978  * @param cfg configuration to inspect
979  * @param section section of interest
980  * @param option option of interest
981  * @param value will be set to a freshly allocated configuration
982  *        value, or NULL if option is not specified
983  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
984  */
985 int
986 GNUNET_CONFIGURATION_get_value_string (const struct GNUNET_CONFIGURATION_Handle *cfg,
987                                        const char *section,
988                                        const char *option,
989                                        char **value)
990 {
991   struct ConfigEntry *e;
992
993   if ( (NULL == (e = find_entry (cfg, section, option))) ||
994        (NULL == e->val) )
995   {
996     *value = NULL;
997     return GNUNET_SYSERR;
998   }
999   *value = GNUNET_strdup (e->val);
1000   return GNUNET_OK;
1001 }
1002
1003
1004 /**
1005  * Get a configuration value that should be in a set of
1006  * predefined strings
1007  *
1008  * @param cfg configuration to inspect
1009  * @param section section of interest
1010  * @param option option of interest
1011  * @param choices NULL-terminated list of legal values
1012  * @param value will be set to an entry in the legal list,
1013  *        or NULL if option is not specified and no default given
1014  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1015  */
1016 int
1017 GNUNET_CONFIGURATION_get_value_choice (const struct GNUNET_CONFIGURATION_Handle *cfg,
1018                                        const char *section,
1019                                        const char *option,
1020                                        const char *const *choices,
1021                                        const char **value)
1022 {
1023   struct ConfigEntry *e;
1024   unsigned int i;
1025
1026   if (NULL == (e = find_entry (cfg, section, option)))
1027     return GNUNET_SYSERR;
1028   for (i = 0; NULL != choices[i]; i++)
1029     if (0 == strcasecmp (choices[i], e->val))
1030       break;
1031   if (NULL == choices[i])
1032   {
1033     LOG (GNUNET_ERROR_TYPE_ERROR,
1034          _("Configuration value '%s' for '%s'"
1035            " in section '%s' is not in set of legal choices\n"),
1036          e->val,
1037          option,
1038          section);
1039     return GNUNET_SYSERR;
1040   }
1041   *value = choices[i];
1042   return GNUNET_OK;
1043 }
1044
1045
1046 /**
1047  * Get crockford32-encoded fixed-size binary data from a configuration.
1048  *
1049  * @param cfg configuration to access
1050  * @param section section to access
1051  * @param option option to access
1052  * @param buf where to store the decoded binary result
1053  * @param buf_size exact number of bytes to store in @a buf
1054  * @return #GNUNET_OK on success
1055  *         #GNUNET_NO is the value does not exist
1056  *         #GNUNET_SYSERR on decoding error
1057  */
1058 int
1059 GNUNET_CONFIGURATION_get_data (const struct GNUNET_CONFIGURATION_Handle *cfg,
1060                                const char *section,
1061                                const char *option,
1062                                void *buf,
1063                                size_t buf_size)
1064 {
1065   char *enc;
1066   int res;
1067   size_t data_size;
1068
1069   if (GNUNET_OK !=
1070       (res = GNUNET_CONFIGURATION_get_value_string (cfg,
1071                                                     section,
1072                                                     option,
1073                                                     &enc)))
1074     return res;
1075   data_size = (strlen (enc) * 5) / 8;
1076   if (data_size != buf_size)
1077   {
1078     GNUNET_free (enc);
1079     return GNUNET_SYSERR;
1080   }
1081   if (GNUNET_OK !=
1082       GNUNET_STRINGS_string_to_data (enc,
1083                                      strlen (enc),
1084                                      buf, buf_size))
1085   {
1086     GNUNET_free (enc);
1087     return GNUNET_SYSERR;
1088   }
1089   GNUNET_free (enc);
1090   return GNUNET_OK;
1091 }
1092
1093
1094 /**
1095  * Test if we have a value for a particular option
1096  *
1097  * @param cfg configuration to inspect
1098  * @param section section of interest
1099  * @param option option of interest
1100  * @return #GNUNET_YES if so, #GNUNET_NO if not.
1101  */
1102 int
1103 GNUNET_CONFIGURATION_have_value (const struct GNUNET_CONFIGURATION_Handle *cfg,
1104                                  const char *section,
1105                                  const char *option)
1106 {
1107   struct ConfigEntry *e;
1108
1109   if ((NULL == (e = find_entry (cfg, section, option))) || (NULL == e->val))
1110     return GNUNET_NO;
1111   return GNUNET_YES;
1112 }
1113
1114
1115 /**
1116  * Expand an expression of the form "$FOO/BAR" to "DIRECTORY/BAR"
1117  * where either in the "PATHS" section or the environtment "FOO" is
1118  * set to "DIRECTORY".  We also support default expansion,
1119  * i.e. ${VARIABLE:-default} will expand to $VARIABLE if VARIABLE is
1120  * set in PATHS or the environment, and otherwise to "default".  Note
1121  * that "default" itself can also be a $-expression, thus
1122  * "${VAR1:-{$VAR2}}" will expand to VAR1 and if that is not defined
1123  * to VAR2.
1124  *
1125  * @param cfg configuration to use for path expansion
1126  * @param orig string to $-expand (will be freed!)
1127  * @param depth recursion depth, used to detect recursive expansions
1128  * @return $-expanded string
1129  */
1130 static char *
1131 expand_dollar (const struct GNUNET_CONFIGURATION_Handle *cfg,
1132                char *orig,
1133                unsigned int depth)
1134 {
1135   int i;
1136   char *prefix;
1137   char *result;
1138   char *start;
1139   const char *post;
1140   const char *env;
1141   char *def;
1142   char *end;
1143   unsigned int lopen;
1144   char erased_char;
1145   char *erased_pos;
1146   size_t len;
1147
1148   if (NULL == orig)
1149     return NULL;
1150   if (depth > 128)
1151   {
1152     LOG (GNUNET_ERROR_TYPE_WARNING,
1153          _("Recursive expansion suspected, aborting $-expansion for term `%s'\n"),
1154          orig);
1155     return orig;
1156   }
1157   LOG (GNUNET_ERROR_TYPE_DEBUG,
1158        "Asked to $-expand %s\n",
1159        orig);
1160   if ('$' != orig[0])
1161   {
1162     LOG (GNUNET_ERROR_TYPE_DEBUG,
1163          "Doesn't start with $ - not expanding\n");
1164     return orig;
1165   }
1166   erased_char = 0;
1167   erased_pos = NULL;
1168   if ('{' == orig[1])
1169   {
1170     start = &orig[2];
1171     lopen = 1;
1172     end = &orig[1];
1173     while (lopen > 0)
1174     {
1175       end++;
1176       switch (*end)
1177       {
1178       case '}':
1179         lopen--;
1180         break;
1181       case '{':
1182         lopen++;
1183         break;
1184       case '\0':
1185         LOG (GNUNET_ERROR_TYPE_WARNING,
1186              _("Missing closing `%s' in option `%s'\n"),
1187              "}",
1188              orig);
1189         return orig;
1190       default:
1191         break;
1192       }
1193     }
1194     erased_char = *end;
1195     erased_pos = end;
1196     *end = '\0';
1197     post = end + 1;
1198     def = strchr (orig, ':');
1199     if (NULL != def)
1200     {
1201       *def = '\0';
1202       def++;
1203       if ( ('-' == *def) ||
1204            ('=' == *def) )
1205         def++;
1206       def = GNUNET_strdup (def);
1207     }
1208   }
1209   else
1210   {
1211     start = &orig[1];
1212     def = NULL;
1213     i = 0;
1214     while ( (orig[i] != '/') &&
1215             (orig[i] != '\\') &&
1216             (orig[i] != '\0')  &&
1217             (orig[i] != ' ') )
1218       i++;
1219     if (orig[i] == '\0')
1220     {
1221       post = "";
1222     }
1223     else
1224     {
1225       erased_char = orig[i];
1226       erased_pos = &orig[i];
1227       orig[i] = '\0';
1228       post = &orig[i + 1];
1229     }
1230   }
1231   LOG (GNUNET_ERROR_TYPE_DEBUG,
1232        "Split into `%s' and `%s' with default %s\n",
1233        start,
1234        post,
1235        def);
1236   if (GNUNET_OK !=
1237       GNUNET_CONFIGURATION_get_value_string (cfg,
1238                                              "PATHS",
1239                                              start,
1240                                              &prefix))
1241   {
1242     if (NULL == (env = getenv (start)))
1243     {
1244       /* try default */
1245       def = expand_dollar (cfg, def, depth + 1);
1246       env = def;
1247     }
1248     if (NULL == env)
1249     {
1250       start = GNUNET_strdup (start);
1251       if (erased_pos)
1252         *erased_pos = erased_char;
1253       LOG (GNUNET_ERROR_TYPE_WARNING,
1254            _("Failed to expand `%s' in `%s' as it is neither found in [PATHS] nor defined as an environmental variable\n"),
1255            start, orig);
1256       GNUNET_free (start);
1257       return orig;
1258     }
1259     prefix = GNUNET_strdup (env);
1260   }
1261   prefix = GNUNET_CONFIGURATION_expand_dollar (cfg, prefix);
1262   if ( (erased_pos) && ('}' != erased_char) )
1263   {
1264     len = strlen (prefix) + 1;
1265     prefix = GNUNET_realloc (prefix, len + 1);
1266     prefix[len - 1] = erased_char;
1267     prefix[len] = '\0';
1268   }
1269   result = GNUNET_malloc (strlen (prefix) + strlen (post) + 1);
1270   strcpy (result, prefix);
1271   strcat (result, post);
1272   GNUNET_free_non_null (def);
1273   GNUNET_free (prefix);
1274   GNUNET_free (orig);
1275   return result;
1276 }
1277
1278
1279 /**
1280  * Expand an expression of the form "$FOO/BAR" to "DIRECTORY/BAR"
1281  * where either in the "PATHS" section or the environtment "FOO" is
1282  * set to "DIRECTORY".  We also support default expansion,
1283  * i.e. ${VARIABLE:-default} will expand to $VARIABLE if VARIABLE is
1284  * set in PATHS or the environment, and otherwise to "default".  Note
1285  * that "default" itself can also be a $-expression, thus
1286  * "${VAR1:-{$VAR2}}" will expand to VAR1 and if that is not defined
1287  * to VAR2.
1288  *
1289  * @param cfg configuration to use for path expansion
1290  * @param orig string to $-expand (will be freed!).  Note that multiple
1291  *          $-expressions can be present in this string.  They will all be
1292  *          $-expanded.
1293  * @return $-expanded string
1294  */
1295 char *
1296 GNUNET_CONFIGURATION_expand_dollar (const struct GNUNET_CONFIGURATION_Handle *cfg,
1297                                     char *orig)
1298 {
1299   char *dup;
1300   size_t i;
1301   size_t len;
1302
1303   for (i = 0; '\0' != orig[i]; i++)
1304   {
1305     if ('$' != orig[i])
1306       continue;
1307     dup = GNUNET_strdup (orig + i);
1308     dup = expand_dollar (cfg, dup, 0);
1309     len = strlen (dup) + 1;
1310     orig = GNUNET_realloc (orig, i + len);
1311     GNUNET_memcpy (orig + i, dup, len);
1312     GNUNET_free (dup);
1313   }
1314   return orig;
1315 }
1316
1317
1318 /**
1319  * Get a configuration value that should be a string.
1320  *
1321  * @param cfg configuration to inspect
1322  * @param section section of interest
1323  * @param option option of interest
1324  * @param value will be set to a freshly allocated configuration
1325  *        value, or NULL if option is not specified
1326  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1327  */
1328 int
1329 GNUNET_CONFIGURATION_get_value_filename (const struct GNUNET_CONFIGURATION_Handle *cfg,
1330                                          const char *section,
1331                                          const char *option,
1332                                          char **value)
1333 {
1334   char *tmp;
1335
1336   if (GNUNET_OK !=
1337       GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &tmp))
1338   {
1339     LOG (GNUNET_ERROR_TYPE_DEBUG,
1340          "Failed to retrieve filename\n");
1341     *value = NULL;
1342     return GNUNET_SYSERR;
1343   }
1344   tmp = GNUNET_CONFIGURATION_expand_dollar (cfg, tmp);
1345   *value = GNUNET_STRINGS_filename_expand (tmp);
1346   GNUNET_free (tmp);
1347   if (*value == NULL)
1348     return GNUNET_SYSERR;
1349   return GNUNET_OK;
1350 }
1351
1352
1353 /**
1354  * Get a configuration value that should be in a set of
1355  * "YES" or "NO".
1356  *
1357  * @param cfg configuration to inspect
1358  * @param section section of interest
1359  * @param option option of interest
1360  * @return #GNUNET_YES, #GNUNET_NO or #GNUNET_SYSERR
1361  */
1362 int
1363 GNUNET_CONFIGURATION_get_value_yesno (const struct GNUNET_CONFIGURATION_Handle *cfg,
1364                                       const char *section,
1365                                       const char *option)
1366 {
1367   static const char *yesno[] = { "YES", "NO", NULL };
1368   const char *val;
1369   int ret;
1370
1371   ret =
1372       GNUNET_CONFIGURATION_get_value_choice (cfg, section, option, yesno, &val);
1373   if (ret == GNUNET_SYSERR)
1374     return ret;
1375   if (val == yesno[0])
1376     return GNUNET_YES;
1377   return GNUNET_NO;
1378 }
1379
1380
1381 /**
1382  * Iterate over the set of filenames stored in a configuration value.
1383  *
1384  * @param cfg configuration to inspect
1385  * @param section section of interest
1386  * @param option option of interest
1387  * @param cb function to call on each filename
1388  * @param cb_cls closure for @a cb
1389  * @return number of filenames iterated over, -1 on error
1390  */
1391 int
1392 GNUNET_CONFIGURATION_iterate_value_filenames (const struct GNUNET_CONFIGURATION_Handle *cfg,
1393                                               const char *section,
1394                                               const char *option,
1395                                               GNUNET_FileNameCallback cb,
1396                                               void *cb_cls)
1397 {
1398   char *list;
1399   char *pos;
1400   char *end;
1401   char old;
1402   int ret;
1403
1404   if (GNUNET_OK !=
1405       GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &list))
1406     return 0;
1407   GNUNET_assert (list != NULL);
1408   ret = 0;
1409   pos = list;
1410   while (1)
1411   {
1412     while (pos[0] == ' ')
1413       pos++;
1414     if (strlen (pos) == 0)
1415       break;
1416     end = pos + 1;
1417     while ((end[0] != ' ') && (end[0] != '\0'))
1418     {
1419       if (end[0] == '\\')
1420       {
1421         switch (end[1])
1422         {
1423         case '\\':
1424         case ' ':
1425           memmove (end, &end[1], strlen (&end[1]) + 1);
1426         case '\0':
1427           /* illegal, but just keep it */
1428           break;
1429         default:
1430           /* illegal, but just ignore that there was a '/' */
1431           break;
1432         }
1433       }
1434       end++;
1435     }
1436     old = end[0];
1437     end[0] = '\0';
1438     if (strlen (pos) > 0)
1439     {
1440       ret++;
1441       if ((cb != NULL) && (GNUNET_OK != cb (cb_cls, pos)))
1442       {
1443         ret = GNUNET_SYSERR;
1444         break;
1445       }
1446     }
1447     if (old == '\0')
1448       break;
1449     pos = end + 1;
1450   }
1451   GNUNET_free (list);
1452   return ret;
1453 }
1454
1455
1456 /**
1457  * FIXME.
1458  *
1459  * @param value FIXME
1460  * @return FIXME
1461  */
1462 static char *
1463 escape_name (const char *value)
1464 {
1465   char *escaped;
1466   const char *rpos;
1467   char *wpos;
1468
1469   escaped = GNUNET_malloc (strlen (value) * 2 + 1);
1470   memset (escaped, 0, strlen (value) * 2 + 1);
1471   rpos = value;
1472   wpos = escaped;
1473   while (rpos[0] != '\0')
1474   {
1475     switch (rpos[0])
1476     {
1477     case '\\':
1478     case ' ':
1479       wpos[0] = '\\';
1480       wpos[1] = rpos[0];
1481       wpos += 2;
1482       break;
1483     default:
1484       wpos[0] = rpos[0];
1485       wpos++;
1486     }
1487     rpos++;
1488   }
1489   return escaped;
1490 }
1491
1492
1493 /**
1494  * FIXME.
1495  *
1496  * @param cls string we compare with (const char*)
1497  * @param fn filename we are currently looking at
1498  * @return #GNUNET_OK if the names do not match, #GNUNET_SYSERR if they do
1499  */
1500 static int
1501 test_match (void *cls, const char *fn)
1502 {
1503   const char *of = cls;
1504
1505   return (0 == strcmp (of, fn)) ? GNUNET_SYSERR : GNUNET_OK;
1506 }
1507
1508
1509 /**
1510  * Append a filename to a configuration value that
1511  * represents a list of filenames
1512  *
1513  * @param cfg configuration to update
1514  * @param section section of interest
1515  * @param option option of interest
1516  * @param value filename to append
1517  * @return #GNUNET_OK on success,
1518  *         #GNUNET_NO if the filename already in the list
1519  *         #GNUNET_SYSERR on error
1520  */
1521 int
1522 GNUNET_CONFIGURATION_append_value_filename (struct GNUNET_CONFIGURATION_Handle *cfg,
1523                                             const char *section,
1524                                             const char *option,
1525                                             const char *value)
1526 {
1527   char *escaped;
1528   char *old;
1529   char *nw;
1530
1531   if (GNUNET_SYSERR ==
1532       GNUNET_CONFIGURATION_iterate_value_filenames (cfg, section, option,
1533                                                     &test_match,
1534                                                     (void *) value))
1535     return GNUNET_NO;           /* already exists */
1536   if (GNUNET_OK !=
1537       GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &old))
1538     old = GNUNET_strdup ("");
1539   escaped = escape_name (value);
1540   nw = GNUNET_malloc (strlen (old) + strlen (escaped) + 2);
1541   strcpy (nw, old);
1542   if (strlen (old) > 0)
1543     strcat (nw, " ");
1544   strcat (nw, escaped);
1545   GNUNET_CONFIGURATION_set_value_string (cfg, section, option, nw);
1546   GNUNET_free (old);
1547   GNUNET_free (nw);
1548   GNUNET_free (escaped);
1549   return GNUNET_OK;
1550 }
1551
1552
1553 /**
1554  * Remove a filename from a configuration value that
1555  * represents a list of filenames
1556  *
1557  * @param cfg configuration to update
1558  * @param section section of interest
1559  * @param option option of interest
1560  * @param value filename to remove
1561  * @return #GNUNET_OK on success,
1562  *         #GNUNET_NO if the filename is not in the list,
1563  *         #GNUNET_SYSERR on error
1564  */
1565 int
1566 GNUNET_CONFIGURATION_remove_value_filename (struct GNUNET_CONFIGURATION_Handle
1567                                             *cfg, const char *section,
1568                                             const char *option,
1569                                             const char *value)
1570 {
1571   char *list;
1572   char *pos;
1573   char *end;
1574   char *match;
1575   char old;
1576
1577   if (GNUNET_OK !=
1578       GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &list))
1579     return GNUNET_NO;
1580   match = escape_name (value);
1581   pos = list;
1582   while (1)
1583   {
1584     while (pos[0] == ' ')
1585       pos++;
1586     if (strlen (pos) == 0)
1587       break;
1588     end = pos + 1;
1589     while ((end[0] != ' ') && (end[0] != '\0'))
1590     {
1591       if (end[0] == '\\')
1592       {
1593         switch (end[1])
1594         {
1595         case '\\':
1596         case ' ':
1597           end++;
1598           break;
1599         case '\0':
1600           /* illegal, but just keep it */
1601           break;
1602         default:
1603           /* illegal, but just ignore that there was a '/' */
1604           break;
1605         }
1606       }
1607       end++;
1608     }
1609     old = end[0];
1610     end[0] = '\0';
1611     if (0 == strcmp (pos, match))
1612     {
1613       if (old != '\0')
1614         memmove (pos, &end[1], strlen (&end[1]) + 1);
1615       else
1616       {
1617         if (pos != list)
1618           pos[-1] = '\0';
1619         else
1620           pos[0] = '\0';
1621       }
1622       GNUNET_CONFIGURATION_set_value_string (cfg, section, option, list);
1623       GNUNET_free (list);
1624       GNUNET_free (match);
1625       return GNUNET_OK;
1626     }
1627     if (old == '\0')
1628       break;
1629     end[0] = old;
1630     pos = end + 1;
1631   }
1632   GNUNET_free (list);
1633   GNUNET_free (match);
1634   return GNUNET_NO;
1635 }
1636
1637
1638 /**
1639  * Wrapper around #GNUNET_CONFIGURATION_parse.  Called on each
1640  * file in a directory, we trigger parsing on those files that
1641  * end with ".conf".
1642  *
1643  * @param cls the cfg
1644  * @param filename file to parse
1645  * @return #GNUNET_OK on success
1646  */
1647 static int
1648 parse_configuration_file (void *cls, const char *filename)
1649 {
1650   struct GNUNET_CONFIGURATION_Handle *cfg = cls;
1651   char * ext;
1652   int ret;
1653
1654   /* Examine file extension */
1655   ext = strrchr (filename, '.');
1656   if ((NULL == ext) || (0 != strcmp (ext, ".conf")))
1657   {
1658     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1659                 "Skipping file `%s'\n",
1660                 filename);
1661     return GNUNET_OK;
1662   }
1663
1664   ret = GNUNET_CONFIGURATION_parse (cfg, filename);
1665   return ret;
1666 }
1667
1668
1669 /**
1670  * Load default configuration.  This function will parse the
1671  * defaults from the given defaults_d directory.
1672  *
1673  * @param cfg configuration to update
1674  * @param defaults_d directory with the defaults
1675  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1676  */
1677 int
1678 GNUNET_CONFIGURATION_load_from (struct GNUNET_CONFIGURATION_Handle *cfg,
1679                                 const char *defaults_d)
1680 {
1681   if (GNUNET_SYSERR ==
1682       GNUNET_DISK_directory_scan (defaults_d, &parse_configuration_file, cfg))
1683     return GNUNET_SYSERR;       /* no configuration at all found */
1684   return GNUNET_OK;
1685 }
1686
1687
1688 /* end of configuration.c */