GNUnet  0.10.x
configuration.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2006, 2007, 2008, 2009, 2013 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19 */
20 
27 #include "platform.h"
28 #include "gnunet_crypto_lib.h"
29 #include "gnunet_strings_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 
41 {
42 
46  struct ConfigEntry *next;
47 
51  char *key;
52 
56  char *val;
57 };
58 
59 
64 {
69 
74 
78  char *name;
79 };
80 
81 
86 {
91 
97  int dirty;
98 
99 };
100 
101 
107 {
109 
111 };
112 
113 
121 {
122  return GNUNET_new (struct GNUNET_CONFIGURATION_Handle);
123 }
124 
125 
131 void
133 {
134  struct ConfigSection *sec;
135 
136  while (NULL != (sec = cfg->sections))
138  GNUNET_free (cfg);
139 }
140 
141 
153 int
156  void *cb_cls)
157 {
159  int ret;
160 
162  if (GNUNET_OK !=
164  filename))
165  {
166  GNUNET_break (0);
168  return GNUNET_SYSERR;
169  }
170  ret = cb (cb_cls,
171  cfg);
173  return ret;
174 }
175 
176 
188 int
190  const char *mem,
191  size_t size,
192  const char *basedir)
193 {
194  char *line;
195  char *line_orig;
196  size_t line_size;
197  char *pos;
198  unsigned int nr;
199  size_t r_bytes;
200  size_t to_read;
201  size_t i;
202  int emptyline;
203  int ret;
204  char *section;
205  char *eq;
206  char *tag;
207  char *value;
208 
209  ret = GNUNET_OK;
210  section = GNUNET_strdup ("");
211  nr = 0;
212  r_bytes = 0;
213  line_orig = NULL;
214  while (r_bytes < size)
215  {
216  GNUNET_free_non_null (line_orig);
217  /* fgets-like behaviour on buffer */
218  to_read = size - r_bytes;
219  pos = memchr (&mem[r_bytes], '\n', to_read);
220  if (NULL == pos)
221  {
222  line_orig = GNUNET_strndup (&mem[r_bytes], line_size = to_read);
223  r_bytes += line_size;
224  }
225  else
226  {
227  line_orig = GNUNET_strndup (&mem[r_bytes], line_size = (pos - &mem[r_bytes]));
228  r_bytes += line_size + 1;
229  }
230  line = line_orig;
231  /* increment line number */
232  nr++;
233  /* tabs and '\r' are whitespace */
234  emptyline = GNUNET_YES;
235  for (i = 0; i < line_size; i++)
236  {
237  if (line[i] == '\t')
238  line[i] = ' ';
239  if (line[i] == '\r')
240  line[i] = ' ';
241  if (' ' != line[i])
242  emptyline = GNUNET_NO;
243  }
244  /* ignore empty lines */
245  if (GNUNET_YES == emptyline)
246  continue;
247 
248  /* remove tailing whitespace */
249  for (i = line_size - 1; (i >= 1) && (isspace ((unsigned char) line[i]));i--)
250  line[i] = '\0';
251 
252  /* remove leading whitespace */
253  for (; line[0] != '\0' && (isspace ((unsigned char) line[0])); line++);
254 
255  /* ignore comments */
256  if ( ('#' == line[0]) || ('%' == line[0]) )
257  continue;
258 
259  /* handle special "@INLINE@" directive */
260  if (0 == strncasecmp (line,
261  "@INLINE@ ",
262  strlen ("@INLINE@ ")))
263  {
264  /* @INLINE@ value */
265  value = &line[strlen ("@INLINE@ ")];
266  if (NULL != basedir)
267  {
268  char *fn;
269 
270  GNUNET_asprintf (&fn,
271  "%s/%s",
272  basedir,
273  value);
274  if (GNUNET_OK !=
276  fn))
277  {
278  GNUNET_free (fn);
279  ret = GNUNET_SYSERR; /* failed to parse included config */
280  break;
281  }
282  GNUNET_free (fn);
283  }
284  else
285  {
287  "Ignoring parsing @INLINE@ configurations, not allowed!\n");
288  ret = GNUNET_SYSERR;
289  break;
290  }
291  continue;
292  }
293  if ( ('[' == line[0]) && (']' == line[line_size - 1]) )
294  {
295  /* [value] */
296  line[line_size - 1] = '\0';
297  value = &line[1];
298  GNUNET_free (section);
299  section = GNUNET_strdup (value);
300  continue;
301  }
302  if (NULL != (eq = strchr (line, '=')))
303  {
304  /* tag = value */
305  tag = GNUNET_strndup (line, eq - line);
306  /* remove tailing whitespace */
307  for (i = strlen (tag) - 1; (i >= 1) && (isspace ((unsigned char) tag[i]));i--)
308  tag[i] = '\0';
309 
310  /* Strip whitespace */
311  value = eq + 1;
312  while (isspace ((unsigned char) value[0]))
313  value++;
314  for (i = strlen (value) - 1; (i >= 1) && (isspace ((unsigned char) value[i]));i--)
315  value[i] = '\0';
316 
317  /* remove quotes */
318  i = 0;
319  if ( ('"' == value[0]) &&
320  ('"' == value[strlen (value) - 1]) )
321  {
322  value[strlen (value) - 1] = '\0';
323  value++;
324  }
325  GNUNET_CONFIGURATION_set_value_string (cfg, section, tag, &value[i]);
326  GNUNET_free (tag);
327  continue;
328  }
329  /* parse error */
331  _("Syntax error while deserializing in line %u\n"),
332  nr);
333  ret = GNUNET_SYSERR;
334  break;
335  }
336  GNUNET_free_non_null (line_orig);
337  GNUNET_free (section);
338  GNUNET_assert ( (GNUNET_OK != ret) || (r_bytes == size) );
339  return ret;
340 }
341 
342 
351 int
353  const char *filename)
354 {
355  uint64_t fs64;
356  size_t fs;
357  char *fn;
358  char *mem;
359  char *endsep;
360  int dirty;
361  int ret;
362  ssize_t sret;
363 
364  fn = GNUNET_STRINGS_filename_expand (filename);
366  "Asked to parse config file `%s'\n",
367  fn);
368  if (NULL == fn)
369  return GNUNET_SYSERR;
370  dirty = cfg->dirty; /* back up value! */
371  if (GNUNET_SYSERR ==
373  &fs64,
374  GNUNET_YES,
375  GNUNET_YES))
376  {
378  "Error while determining the file size of `%s'\n",
379  fn);
380  GNUNET_free (fn);
381  return GNUNET_SYSERR;
382  }
383  if (fs64 > SIZE_MAX)
384  {
385  GNUNET_break (0); /* File size is more than the heap size */
386  GNUNET_free (fn);
387  return GNUNET_SYSERR;
388  }
389  fs = fs64;
390  mem = GNUNET_malloc (fs);
391  sret = GNUNET_DISK_fn_read (fn,
392  mem,
393  fs);
394  if ( (sret < 0) ||
395  (fs != (size_t) sret) )
396  {
398  _("Error while reading file `%s'\n"),
399  fn);
400  GNUNET_free (fn);
401  GNUNET_free (mem);
402  return GNUNET_SYSERR;
403  }
405  "Deserializing contents of file `%s'\n",
406  fn);
407  endsep = strrchr (fn, (int) '/');
408  if (NULL != endsep)
409  *endsep = '\0';
411  mem,
412  fs,
413  fn);
414  GNUNET_free (fn);
415  GNUNET_free (mem);
416  /* restore dirty flag - anything we set in the meantime
417  * came from disk */
418  cfg->dirty = dirty;
419  return ret;
420 }
421 
422 
430 int
432 {
433  return cfg->dirty;
434 }
435 
436 
445 char *
447  size_t *size)
448 {
449  struct ConfigSection *sec;
450  struct ConfigEntry *ent;
451  char *mem;
452  char *cbuf;
453  char *val;
454  char *pos;
455  int len;
456  size_t m_size;
457  size_t c_size;
458 
459  /* Pass1 : calculate the buffer size required */
460  m_size = 0;
461  for (sec = cfg->sections; NULL != sec; sec = sec->next)
462  {
463  /* For each section we need to add 3 charaters: {'[',']','\n'} */
464  m_size += strlen (sec->name) + 3;
465  for (ent = sec->entries; NULL != ent; ent = ent->next)
466  {
467  if (NULL != ent->val)
468  {
469  /* if val has any '\n' then they occupy +1 character as '\n'->'\\','n' */
470  pos = ent->val;
471  while (NULL != (pos = strstr (pos, "\n")))
472  {
473  m_size++;
474  pos++;
475  }
476  /* For each key = value pair we need to add 4 characters (2
477  spaces and 1 equal-to character and 1 new line) */
478  m_size += strlen (ent->key) + strlen (ent->val) + 4;
479  }
480  }
481  /* A new line after section end */
482  m_size++;
483  }
484 
485  /* Pass2: Allocate memory and write the configuration to it */
486  mem = GNUNET_malloc (m_size);
487  sec = cfg->sections;
488  c_size = 0;
489  *size = c_size;
490  while (NULL != sec)
491  {
492  len = GNUNET_asprintf (&cbuf, "[%s]\n", sec->name);
493  GNUNET_assert (0 < len);
494  GNUNET_memcpy (mem + c_size, cbuf, len);
495  c_size += len;
496  GNUNET_free (cbuf);
497  for (ent = sec->entries; NULL != ent; ent = ent->next)
498  {
499  if (NULL != ent->val)
500  {
501  val = GNUNET_malloc (strlen (ent->val) * 2 + 1);
502  strcpy (val, ent->val);
503  while (NULL != (pos = strstr (val, "\n")))
504  {
505  memmove (&pos[2], &pos[1], strlen (&pos[1]));
506  pos[0] = '\\';
507  pos[1] = 'n';
508  }
509  len = GNUNET_asprintf (&cbuf, "%s = %s\n", ent->key, val);
510  GNUNET_free (val);
511  GNUNET_memcpy (mem + c_size, cbuf, len);
512  c_size += len;
513  GNUNET_free (cbuf);
514  }
515  }
516  GNUNET_memcpy (mem + c_size, "\n", 1);
517  c_size ++;
518  sec = sec->next;
519  }
520  GNUNET_assert (c_size == m_size);
521  *size = c_size;
522  return mem;
523 }
524 
525 
533 int
535  const char *filename)
536 {
537  char *fn;
538  char *cfg_buf;
539  size_t size;
540  ssize_t sret;
541 
542  fn = GNUNET_STRINGS_filename_expand (filename);
543  if (fn == NULL)
544  return GNUNET_SYSERR;
546  {
547  GNUNET_free (fn);
548  return GNUNET_SYSERR;
549  }
550  cfg_buf = GNUNET_CONFIGURATION_serialize (cfg, &size);
551  sret = GNUNET_DISK_fn_write (fn, cfg_buf, size,
556  if ( (sret < 0) ||
557  (size != (size_t) sret) )
558  {
559  GNUNET_free (fn);
560  GNUNET_free (cfg_buf);
562  "Writing configuration to file `%s' failed\n",
563  filename);
564  cfg->dirty = GNUNET_SYSERR; /* last write failed */
565  return GNUNET_SYSERR;
566  }
567  GNUNET_free (fn);
568  GNUNET_free (cfg_buf);
569  cfg->dirty = GNUNET_NO; /* last write succeeded */
570  return GNUNET_OK;
571 }
572 
573 
581 void
584  void *iter_cls)
585 {
586  struct ConfigSection *spos;
587  struct ConfigEntry *epos;
588 
589  for (spos = cfg->sections; NULL != spos; spos = spos->next)
590  for (epos = spos->entries; NULL != epos; epos = epos->next)
591  if (NULL != epos->val)
592  iter (iter_cls, spos->name, epos->key, epos->val);
593 }
594 
595 
604 void
607  const char *section,
609  void *iter_cls)
610 {
611  struct ConfigSection *spos;
612  struct ConfigEntry *epos;
613 
614  spos = cfg->sections;
615  while ((spos != NULL) && (0 != strcasecmp (spos->name, section)))
616  spos = spos->next;
617  if (NULL == spos)
618  return;
619  for (epos = spos->entries; NULL != epos; epos = epos->next)
620  if (NULL != epos->val)
621  iter (iter_cls, spos->name, epos->key, epos->val);
622 }
623 
624 
632 void
635  void *iter_cls)
636 {
637  struct ConfigSection *spos;
638  struct ConfigSection *next;
639 
640  next = cfg->sections;
641  while (next != NULL)
642  {
643  spos = next;
644  next = spos->next;
645  iter (iter_cls, spos->name);
646  }
647 }
648 
649 
656 void
658  const char *section)
659 {
660  struct ConfigSection *spos;
661  struct ConfigSection *prev;
662  struct ConfigEntry *ent;
663 
664  prev = NULL;
665  spos = cfg->sections;
666  while (NULL != spos)
667  {
668  if (0 == strcasecmp (section, spos->name))
669  {
670  if (NULL == prev)
671  cfg->sections = spos->next;
672  else
673  prev->next = spos->next;
674  while (NULL != (ent = spos->entries))
675  {
676  spos->entries = ent->next;
677  GNUNET_free (ent->key);
678  GNUNET_free_non_null (ent->val);
679  GNUNET_free (ent);
680  cfg->dirty = GNUNET_YES;
681  }
682  GNUNET_free (spos->name);
683  GNUNET_free (spos);
684  return;
685  }
686  prev = spos;
687  spos = spos->next;
688  }
689 }
690 
691 
701 static void
702 copy_entry (void *cls,
703  const char *section,
704  const char *option,
705  const char *value)
706 {
707  struct GNUNET_CONFIGURATION_Handle *dst = cls;
708 
709  GNUNET_CONFIGURATION_set_value_string (dst, section, option, value);
710 }
711 
712 
721 {
723 
726  return ret;
727 }
728 
729 
737 static struct ConfigSection *
739  const char *section)
740 {
741  struct ConfigSection *pos;
742 
743  pos = cfg->sections;
744  while ((pos != NULL) && (0 != strcasecmp (section, pos->name)))
745  pos = pos->next;
746  return pos;
747 }
748 
749 
758 static struct ConfigEntry *
760  const char *section,
761  const char *key)
762 {
763  struct ConfigSection *sec;
764  struct ConfigEntry *pos;
765 
766  if (NULL == (sec = find_section (cfg, section)))
767  return NULL;
768  pos = sec->entries;
769  while ((pos != NULL) && (0 != strcasecmp (key, pos->key)))
770  pos = pos->next;
771  return pos;
772 }
773 
774 
785 static void
786 compare_entries (void *cls,
787  const char *section,
788  const char *option,
789  const char *value)
790 {
791  struct DiffHandle *dh = cls;
792  struct ConfigEntry *entNew;
793 
794  entNew = find_entry (dh->cfg_default, section, option);
795  if ( (NULL != entNew) &&
796  (NULL != entNew->val) &&
797  (0 == strcmp (entNew->val, value)) )
798  return;
799  GNUNET_CONFIGURATION_set_value_string (dh->cfgDiff, section, option, value);
800 }
801 
802 
812  const struct GNUNET_CONFIGURATION_Handle *cfg_new)
813 {
814  struct DiffHandle diffHandle;
815 
816  diffHandle.cfgDiff = GNUNET_CONFIGURATION_create ();
817  diffHandle.cfg_default = cfg_default;
818  GNUNET_CONFIGURATION_iterate (cfg_new, &compare_entries, &diffHandle);
819  return diffHandle.cfgDiff;
820 }
821 
822 
831 int
833  *cfg_default,
834  const struct GNUNET_CONFIGURATION_Handle
835  *cfg_new, const char *filename)
836 {
837  int ret;
838  struct GNUNET_CONFIGURATION_Handle *diff;
839 
840  diff = GNUNET_CONFIGURATION_get_diff (cfg_default, cfg_new);
841  ret = GNUNET_CONFIGURATION_write (diff, filename);
843  return ret;
844 }
845 
846 
855 void
857  const char *section, const char *option,
858  const char *value)
859 {
860  struct ConfigSection *sec;
861  struct ConfigEntry *e;
862  char *nv;
863 
864  e = find_entry (cfg, section, option);
865  if (NULL != e)
866  {
867  if (NULL == value)
868  {
870  e->val = NULL;
871  }
872  else
873  {
874  nv = GNUNET_strdup (value);
876  e->val = nv;
877  }
878  return;
879  }
880  sec = find_section (cfg, section);
881  if (sec == NULL)
882  {
883  sec = GNUNET_new (struct ConfigSection);
884  sec->name = GNUNET_strdup (section);
885  sec->next = cfg->sections;
886  cfg->sections = sec;
887  }
888  e = GNUNET_new (struct ConfigEntry);
889  e->key = GNUNET_strdup (option);
890  e->val = GNUNET_strdup (value);
891  e->next = sec->entries;
892  sec->entries = e;
893 }
894 
895 
904 void
906  const char *section,
907  const char *option,
908  unsigned long long number)
909 {
910  char s[64];
911 
912  GNUNET_snprintf (s,
913  64,
914  "%llu",
915  number);
917  section,
918  option,
919  s);
920 }
921 
922 
932 int
934  const char *section,
935  const char *option,
936  unsigned long long *number)
937 {
938  struct ConfigEntry *e;
939  char dummy[2];
940 
941  if (NULL == (e = find_entry (cfg, section, option)))
942  return GNUNET_SYSERR;
943  if (NULL == e->val)
944  return GNUNET_SYSERR;
945  if (1 != SSCANF (e->val,
946  "%llu%1s",
947  number,
948  dummy))
949  return GNUNET_SYSERR;
950  return GNUNET_OK;
951 }
952 
953 
963 int
965  const char *section,
966  const char *option,
967  float *number)
968 {
969  struct ConfigEntry *e;
970  char dummy[2];
971 
972  if (NULL == (e = find_entry (cfg, section, option)))
973  return GNUNET_SYSERR;
974  if (NULL == e->val)
975  return GNUNET_SYSERR;
976  if (1 != SSCANF (e->val,
977  "%f%1s",
978  number,
979  dummy))
980  return GNUNET_SYSERR;
981  return GNUNET_OK;
982 }
983 
984 
985 
995 int
997  const char *section,
998  const char *option,
999  struct GNUNET_TIME_Relative *time)
1000 {
1001  struct ConfigEntry *e;
1002  int ret;
1003 
1004  if (NULL == (e = find_entry (cfg,
1005  section,
1006  option)))
1007  return GNUNET_SYSERR;
1008  if (NULL == e->val)
1009  return GNUNET_SYSERR;
1011  time);
1012  if (GNUNET_OK != ret)
1014  section,
1015  option,
1016  _("Not a valid relative time specification"));
1017  return ret;
1018 }
1019 
1020 
1030 int
1032  const char *section,
1033  const char *option,
1034  unsigned long long *size)
1035 {
1036  struct ConfigEntry *e;
1037 
1038  if (NULL == (e = find_entry (cfg, section, option)))
1039  return GNUNET_SYSERR;
1040  if (NULL == e->val)
1041  return GNUNET_SYSERR;
1042  return GNUNET_STRINGS_fancy_size_to_bytes (e->val, size);
1043 }
1044 
1045 
1056 int
1058  const char *section,
1059  const char *option,
1060  char **value)
1061 {
1062  struct ConfigEntry *e;
1063 
1064  if ( (NULL == (e = find_entry (cfg, section, option))) ||
1065  (NULL == e->val) )
1066  {
1067  *value = NULL;
1068  return GNUNET_SYSERR;
1069  }
1070  *value = GNUNET_strdup (e->val);
1071  return GNUNET_OK;
1072 }
1073 
1074 
1087 int
1089  const char *section,
1090  const char *option,
1091  const char *const *choices,
1092  const char **value)
1093 {
1094  struct ConfigEntry *e;
1095  unsigned int i;
1096 
1097  if (NULL == (e = find_entry (cfg, section, option)))
1098  return GNUNET_SYSERR;
1099  for (i = 0; NULL != choices[i]; i++)
1100  if (0 == strcasecmp (choices[i], e->val))
1101  break;
1102  if (NULL == choices[i])
1103  {
1105  _("Configuration value '%s' for '%s'"
1106  " in section '%s' is not in set of legal choices\n"),
1107  e->val,
1108  option,
1109  section);
1110  return GNUNET_SYSERR;
1111  }
1112  *value = choices[i];
1113  return GNUNET_OK;
1114 }
1115 
1116 
1129 int
1131  const char *section,
1132  const char *option,
1133  void *buf,
1134  size_t buf_size)
1135 {
1136  char *enc;
1137  int res;
1138  size_t data_size;
1139 
1140  if (GNUNET_OK !=
1142  section,
1143  option,
1144  &enc)))
1145  return res;
1146  data_size = (strlen (enc) * 5) / 8;
1147  if (data_size != buf_size)
1148  {
1149  GNUNET_free (enc);
1150  return GNUNET_SYSERR;
1151  }
1152  if (GNUNET_OK !=
1154  strlen (enc),
1155  buf, buf_size))
1156  {
1157  GNUNET_free (enc);
1158  return GNUNET_SYSERR;
1159  }
1160  GNUNET_free (enc);
1161  return GNUNET_OK;
1162 }
1163 
1164 
1173 int
1175  const char *section,
1176  const char *option)
1177 {
1178  struct ConfigEntry *e;
1179 
1180  if ((NULL == (e = find_entry (cfg, section, option))) || (NULL == e->val))
1181  return GNUNET_NO;
1182  return GNUNET_YES;
1183 }
1184 
1185 
1201 static char *
1203  char *orig,
1204  unsigned int depth)
1205 {
1206  int i;
1207  char *prefix;
1208  char *result;
1209  char *start;
1210  const char *post;
1211  const char *env;
1212  char *def;
1213  char *end;
1214  unsigned int lopen;
1215  char erased_char;
1216  char *erased_pos;
1217  size_t len;
1218 
1219  if (NULL == orig)
1220  return NULL;
1221  if (depth > 128)
1222  {
1224  _("Recursive expansion suspected, aborting $-expansion for term `%s'\n"),
1225  orig);
1226  return orig;
1227  }
1229  "Asked to $-expand %s\n",
1230  orig);
1231  if ('$' != orig[0])
1232  {
1234  "Doesn't start with $ - not expanding\n");
1235  return orig;
1236  }
1237  erased_char = 0;
1238  erased_pos = NULL;
1239  if ('{' == orig[1])
1240  {
1241  start = &orig[2];
1242  lopen = 1;
1243  end = &orig[1];
1244  while (lopen > 0)
1245  {
1246  end++;
1247  switch (*end)
1248  {
1249  case '}':
1250  lopen--;
1251  break;
1252  case '{':
1253  lopen++;
1254  break;
1255  case '\0':
1257  _("Missing closing `%s' in option `%s'\n"),
1258  "}",
1259  orig);
1260  return orig;
1261  default:
1262  break;
1263  }
1264  }
1265  erased_char = *end;
1266  erased_pos = end;
1267  *end = '\0';
1268  post = end + 1;
1269  def = strchr (orig, ':');
1270  if (NULL != def)
1271  {
1272  *def = '\0';
1273  def++;
1274  if ( ('-' == *def) ||
1275  ('=' == *def) )
1276  def++;
1277  def = GNUNET_strdup (def);
1278  }
1279  }
1280  else
1281  {
1282  start = &orig[1];
1283  def = NULL;
1284  i = 0;
1285  while ( (orig[i] != '/') &&
1286  (orig[i] != '\\') &&
1287  (orig[i] != '\0') &&
1288  (orig[i] != ' ') )
1289  i++;
1290  if (orig[i] == '\0')
1291  {
1292  post = "";
1293  }
1294  else
1295  {
1296  erased_char = orig[i];
1297  erased_pos = &orig[i];
1298  orig[i] = '\0';
1299  post = &orig[i + 1];
1300  }
1301  }
1303  "Split into `%s' and `%s' with default %s\n",
1304  start,
1305  post,
1306  def);
1307  if (GNUNET_OK !=
1309  "PATHS",
1310  start,
1311  &prefix))
1312  {
1313  if (NULL == (env = getenv (start)))
1314  {
1315  /* try default */
1316  def = expand_dollar (cfg, def, depth + 1);
1317  env = def;
1318  }
1319  if (NULL == env)
1320  {
1321  start = GNUNET_strdup (start);
1322  if (erased_pos)
1323  *erased_pos = erased_char;
1325  _("Failed to expand `%s' in `%s' as it is neither found in [PATHS] nor defined as an environmental variable\n"),
1326  start, orig);
1327  GNUNET_free (start);
1328  return orig;
1329  }
1330  prefix = GNUNET_strdup (env);
1331  }
1332  prefix = GNUNET_CONFIGURATION_expand_dollar (cfg, prefix);
1333  if ( (erased_pos) && ('}' != erased_char) )
1334  {
1335  len = strlen (prefix) + 1;
1336  prefix = GNUNET_realloc (prefix, len + 1);
1337  prefix[len - 1] = erased_char;
1338  prefix[len] = '\0';
1339  }
1340  result = GNUNET_malloc (strlen (prefix) + strlen (post) + 1);
1341  strcpy (result, prefix);
1342  strcat (result, post);
1343  GNUNET_free_non_null (def);
1344  GNUNET_free (prefix);
1345  GNUNET_free (orig);
1346  return result;
1347 }
1348 
1349 
1366 char *
1368  char *orig)
1369 {
1370  char *dup;
1371  size_t i;
1372  size_t len;
1373 
1374  for (i = 0; '\0' != orig[i]; i++)
1375  {
1376  if ('$' != orig[i])
1377  continue;
1378  dup = GNUNET_strdup (orig + i);
1379  dup = expand_dollar (cfg, dup, 0);
1380  len = strlen (dup) + 1;
1381  orig = GNUNET_realloc (orig, i + len);
1382  GNUNET_memcpy (orig + i, dup, len);
1383  GNUNET_free (dup);
1384  }
1385  return orig;
1386 }
1387 
1388 
1399 int
1401  const char *section,
1402  const char *option,
1403  char **value)
1404 {
1405  char *tmp;
1406 
1407  if (GNUNET_OK !=
1408  GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &tmp))
1409  {
1411  "Failed to retrieve filename\n");
1412  *value = NULL;
1413  return GNUNET_SYSERR;
1414  }
1415  tmp = GNUNET_CONFIGURATION_expand_dollar (cfg, tmp);
1416  *value = GNUNET_STRINGS_filename_expand (tmp);
1417  GNUNET_free (tmp);
1418  if (*value == NULL)
1419  return GNUNET_SYSERR;
1420  return GNUNET_OK;
1421 }
1422 
1423 
1433 int
1435  const char *section,
1436  const char *option)
1437 {
1438  static const char *yesno[] = { "YES", "NO", NULL };
1439  const char *val;
1440  int ret;
1441 
1442  ret =
1443  GNUNET_CONFIGURATION_get_value_choice (cfg, section, option, yesno, &val);
1444  if (ret == GNUNET_SYSERR)
1445  return ret;
1446  if (val == yesno[0])
1447  return GNUNET_YES;
1448  return GNUNET_NO;
1449 }
1450 
1451 
1462 int
1464  const char *section,
1465  const char *option,
1467  void *cb_cls)
1468 {
1469  char *list;
1470  char *pos;
1471  char *end;
1472  char old;
1473  int ret;
1474 
1475  if (GNUNET_OK !=
1476  GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &list))
1477  return 0;
1478  GNUNET_assert (list != NULL);
1479  ret = 0;
1480  pos = list;
1481  while (1)
1482  {
1483  while (pos[0] == ' ')
1484  pos++;
1485  if (strlen (pos) == 0)
1486  break;
1487  end = pos + 1;
1488  while ((end[0] != ' ') && (end[0] != '\0'))
1489  {
1490  if (end[0] == '\\')
1491  {
1492  switch (end[1])
1493  {
1494  case '\\':
1495  case ' ':
1496  memmove (end, &end[1], strlen (&end[1]) + 1);
1497  case '\0':
1498  /* illegal, but just keep it */
1499  break;
1500  default:
1501  /* illegal, but just ignore that there was a '/' */
1502  break;
1503  }
1504  }
1505  end++;
1506  }
1507  old = end[0];
1508  end[0] = '\0';
1509  if (strlen (pos) > 0)
1510  {
1511  ret++;
1512  if ((cb != NULL) && (GNUNET_OK != cb (cb_cls, pos)))
1513  {
1514  ret = GNUNET_SYSERR;
1515  break;
1516  }
1517  }
1518  if (old == '\0')
1519  break;
1520  pos = end + 1;
1521  }
1522  GNUNET_free (list);
1523  return ret;
1524 }
1525 
1526 
1533 static char *
1534 escape_name (const char *value)
1535 {
1536  char *escaped;
1537  const char *rpos;
1538  char *wpos;
1539 
1540  escaped = GNUNET_malloc (strlen (value) * 2 + 1);
1541  memset (escaped, 0, strlen (value) * 2 + 1);
1542  rpos = value;
1543  wpos = escaped;
1544  while (rpos[0] != '\0')
1545  {
1546  switch (rpos[0])
1547  {
1548  case '\\':
1549  case ' ':
1550  wpos[0] = '\\';
1551  wpos[1] = rpos[0];
1552  wpos += 2;
1553  break;
1554  default:
1555  wpos[0] = rpos[0];
1556  wpos++;
1557  }
1558  rpos++;
1559  }
1560  return escaped;
1561 }
1562 
1563 
1571 static int
1572 test_match (void *cls, const char *fn)
1573 {
1574  const char *of = cls;
1575 
1576  return (0 == strcmp (of, fn)) ? GNUNET_SYSERR : GNUNET_OK;
1577 }
1578 
1579 
1592 int
1594  const char *section,
1595  const char *option,
1596  const char *value)
1597 {
1598  char *escaped;
1599  char *old;
1600  char *nw;
1601 
1602  if (GNUNET_SYSERR ==
1603  GNUNET_CONFIGURATION_iterate_value_filenames (cfg, section, option,
1604  &test_match,
1605  (void *) value))
1606  return GNUNET_NO; /* already exists */
1607  if (GNUNET_OK !=
1608  GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &old))
1609  old = GNUNET_strdup ("");
1610  escaped = escape_name (value);
1611  nw = GNUNET_malloc (strlen (old) + strlen (escaped) + 2);
1612  strcpy (nw, old);
1613  if (strlen (old) > 0)
1614  strcat (nw, " ");
1615  strcat (nw, escaped);
1616  GNUNET_CONFIGURATION_set_value_string (cfg, section, option, nw);
1617  GNUNET_free (old);
1618  GNUNET_free (nw);
1619  GNUNET_free (escaped);
1620  return GNUNET_OK;
1621 }
1622 
1623 
1636 int
1638  *cfg, const char *section,
1639  const char *option,
1640  const char *value)
1641 {
1642  char *list;
1643  char *pos;
1644  char *end;
1645  char *match;
1646  char old;
1647 
1648  if (GNUNET_OK !=
1649  GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &list))
1650  return GNUNET_NO;
1651  match = escape_name (value);
1652  pos = list;
1653  while (1)
1654  {
1655  while (pos[0] == ' ')
1656  pos++;
1657  if (strlen (pos) == 0)
1658  break;
1659  end = pos + 1;
1660  while ((end[0] != ' ') && (end[0] != '\0'))
1661  {
1662  if (end[0] == '\\')
1663  {
1664  switch (end[1])
1665  {
1666  case '\\':
1667  case ' ':
1668  end++;
1669  break;
1670  case '\0':
1671  /* illegal, but just keep it */
1672  break;
1673  default:
1674  /* illegal, but just ignore that there was a '/' */
1675  break;
1676  }
1677  }
1678  end++;
1679  }
1680  old = end[0];
1681  end[0] = '\0';
1682  if (0 == strcmp (pos, match))
1683  {
1684  if (old != '\0')
1685  memmove (pos, &end[1], strlen (&end[1]) + 1);
1686  else
1687  {
1688  if (pos != list)
1689  pos[-1] = '\0';
1690  else
1691  pos[0] = '\0';
1692  }
1693  GNUNET_CONFIGURATION_set_value_string (cfg, section, option, list);
1694  GNUNET_free (list);
1695  GNUNET_free (match);
1696  return GNUNET_OK;
1697  }
1698  if (old == '\0')
1699  break;
1700  end[0] = old;
1701  pos = end + 1;
1702  }
1703  GNUNET_free (list);
1704  GNUNET_free (match);
1705  return GNUNET_NO;
1706 }
1707 
1708 
1718 static int
1719 parse_configuration_file (void *cls, const char *filename)
1720 {
1721  struct GNUNET_CONFIGURATION_Handle *cfg = cls;
1722  char * ext;
1723  int ret;
1724 
1725  /* Examine file extension */
1726  ext = strrchr (filename, '.');
1727  if ((NULL == ext) || (0 != strcmp (ext, ".conf")))
1728  {
1730  "Skipping file `%s'\n",
1731  filename);
1732  return GNUNET_OK;
1733  }
1734 
1735  ret = GNUNET_CONFIGURATION_parse (cfg, filename);
1736  return ret;
1737 }
1738 
1739 
1748 int
1750  const char *defaults_d)
1751 {
1752  if (GNUNET_SYSERR ==
1753  GNUNET_DISK_directory_scan (defaults_d,
1755  cfg))
1756  return GNUNET_SYSERR; /* no configuration at all found */
1757  return GNUNET_OK;
1758 }
1759 
1760 
1761 /* end of configuration.c */
void(* GNUNET_CONFIGURATION_Section_Iterator)(void *cls, const char *section)
Function to iterate over section.
int 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.
int dirty
Modification indication since last save GNUNET_NO if clean, GNUNET_YES if dirty, GNUNET_SYSERR on err...
Definition: configuration.c:97
int 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.
static int end
Set if we are to shutdown all services (including ARM).
Definition: gnunet-arm.c:34
static struct in_addr dummy
Target "dummy" address.
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.
static char * escape_name(const char *value)
FIXME.
int GNUNET_CONFIGURATION_write(struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename)
Write configuration file.
int GNUNET_snprintf(char *buf, size_t size, const char *format,...)
Like snprintf, just aborts if the buffer is of insufficient size.
void GNUNET_CONFIGURATION_iterate(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_CONFIGURATION_Iterator iter, void *iter_cls)
Iterate over all options in the configuration.
static int start
Set if we are to start default services (including ARM).
Definition: gnunet-arm.c:39
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...
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct ConfigEntry * entries
entries in the section
Definition: configuration.c:73
int 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:353
int 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.
int 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.
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.
static struct Experiment * e
int GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:833
void(* GNUNET_CONFIGURATION_Iterator)(void *cls, const char *section, const char *option, const char *value)
Function to iterate over options.
int 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:317
#define GNUNET_NO
Definition: gnunet_common.h:81
configuration entry
Definition: configuration.c:40
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_create()
Create a GNUNET_CONFIGURATION_Handle.
int 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...
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.
int GNUNET_DISK_directory_scan(const char *dir_name, GNUNET_FileNameCallback callback, void *callback_cls)
Scan a directory for files.
Definition: disk.c:1233
static struct ConfigEntry * find_entry(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *key)
Find an entry from a configuration.
static int ret
Final status code.
Definition: gnunet-arm.c:89
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define SIZE_MAX
Definition: platform.h:250
ssize_t GNUNET_DISK_fn_write(const char *fn, const void *buffer, size_t n, enum GNUNET_DISK_AccessPermissions mode)
Write a buffer to a file.
Definition: disk.c:1203
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct GNUNET_CONFIGURATION_Handle * cfgDiff
int GNUNET_CONFIGURATION_load(struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename)
Load configuration.
#define _(String)
GNU gettext support macro.
Definition: platform.h:208
static char * section
Name of the section.
Definition: gnunet-config.c:33
static int test_match(void *cls, const char *fn)
FIXME.
int(* GNUNET_CONFIGURATION_Callback)(void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
Signature of a function to be run with a configuration.
char * name
name of the section
Definition: configuration.c:78
cryptographic primitives for GNUnet
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
int 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.
#define GNUNET_memcpy(dst, src, n)
static char * line
Desired phone line (string to be converted to a hash).
static struct ConfigSection * find_section(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section)
Find a section entry from a configuration.
static char * value
Value of the record to add/remove.
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.
static char * fn
Filename of the unique file.
#define GNUNET_realloc(ptr, size)
Wrapper around realloc.
int 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.
int GNUNET_CONFIGURATION_is_dirty(const struct GNUNET_CONFIGURATION_Handle *cfg)
Test if there are configuration options that were changed since the last save.
int 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.
void GNUNET_CONFIGURATION_remove_section(struct GNUNET_CONFIGURATION_Handle *cfg, const char *section)
Remove the given section and all options in it.
void GNUNET_CONFIGURATION_destroy(struct GNUNET_CONFIGURATION_Handle *cfg)
Destroy configuration object.
static char * option
Name of the option.
Definition: gnunet-config.c:38
static char buf[2048]
static char * filename
static int result
Global testing status.
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.
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 void copy_entry(void *cls, const char *section, const char *option, const char *value)
Copy a configuration value to the given target configuration.
struct ConfigSection * sections
Configuration sections.
Definition: configuration.c:90
int(* GNUNET_FileNameCallback)(void *cls, const char *filename)
Function called with a filename.
#define LOG(kind,...)
Definition: configuration.c:33
int 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.
int GNUNET_CONFIGURATION_load_from(struct GNUNET_CONFIGURATION_Handle *cfg, const char *defaults_d)
Load default configuration.
static int res
int 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.
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: gnunet-arm.c:104
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
static unsigned int size
Size of the "table".
Definition: peer.c:67
struct ConfigEntry * next
This is a linked list.
Definition: configuration.c:46
configuration section
Definition: configuration.c:63
char * GNUNET_STRINGS_filename_expand(const char *fil)
Complete filename (a la shell) from abbrevition.
Definition: strings.c:602
char * getenv()
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
Used for diffing a configuration object against the default one.
static struct GNUNET_FS_Handle * fs
Handle to FS service.
Definition: gnunet-fs.c:36
int 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:289
struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_dup(const struct GNUNET_CONFIGURATION_Handle *cfg)
Duplicate an existing configuration object.
char * GNUNET_CONFIGURATION_serialize(const struct GNUNET_CONFIGURATION_Handle *cfg, size_t *size)
Serializes the given configuration.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
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.
#define SSCANF
Definition: plibc.h:691
configuration data
Definition: configuration.c:85
char * key
key for this entry
Definition: configuration.c:51
static OpusEncoder * enc
OPUS encoder.
void GNUNET_CONFIGURATION_iterate_sections(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_CONFIGURATION_Section_Iterator iter, void *iter_cls)
Iterate over all sections in the configuration.
#define GNUNET_log(kind,...)
int 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 a string.
static int parse_configuration_file(void *cls, const char *filename)
Wrapper around GNUNET_CONFIGURATION_parse.
const struct GNUNET_CONFIGURATION_Handle * cfg_default
#define GNUNET_YES
Definition: gnunet_common.h:80
int GNUNET_CONFIGURATION_deserialize(struct GNUNET_CONFIGURATION_Handle *cfg, const char *mem, size_t size, const char *basedir)
De-serializes configuration.
int 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.
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...
int 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".
static size_t data_size
Number of bytes in data.
struct ConfigSection * next
This is a linked list.
Definition: configuration.c:68
int GNUNET_CONFIGURATION_parse_and_run(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 int list
Set if we should print a list of currently running services.
Definition: gnunet-arm.c:64
int 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. ...
#define GNUNET_malloc(size)
Wrapper around malloc.
int 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:1021
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:1019
char * val
current, commited value
Definition: configuration.c:56
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...