cfgfile.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. /*
  2. * cfgfile.c:
  3. *
  4. * Copyright (c) 2003 DecisionSoft Ltd.
  5. *
  6. */
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <errno.h>
  10. #include <stdlib.h>
  11. #include "stringmap.h"
  12. #include "iftop.h"
  13. #include "options.h"
  14. #include "cfgfile.h"
  15. #define CONFIG_TYPE_STRING 0
  16. #define CONFIG_TYPE_BOOL 1
  17. #define CONFIG_TYPE_INT 2
  18. #define MAX_CONFIG_LINE 2048
  19. char * config_directives[] = {
  20. "interface",
  21. "dns-resolution",
  22. "port-resolution",
  23. "filter-code",
  24. "show-bars",
  25. "promiscuous",
  26. "hide-source",
  27. "hide-destination",
  28. "use-bytes",
  29. "sort",
  30. "line-display",
  31. "show-totals",
  32. "log-scale",
  33. "max-bandwidth",
  34. "net-filter",
  35. "net-filter6",
  36. "link-local",
  37. "port-display",
  38. "timed-output",
  39. "no-curses",
  40. "num-lines",
  41. NULL
  42. };
  43. stringmap config;
  44. extern options_t options ;
  45. int is_cfgdirective_valid(const char *s) {
  46. int t;
  47. for (t = 0; config_directives[t] != NULL; t++)
  48. if (strcmp(s, config_directives[t]) == 0) return 1;
  49. return 0;
  50. }
  51. int config_init() {
  52. config = stringmap_new();
  53. return config != NULL;
  54. }
  55. /* read_config_file:
  56. * Read a configuration file consisting of key: value tuples, returning a
  57. * stringmap of the results. Prints errors to stderr, rather than using
  58. * syslog, since this file is called at program startup. Returns 1 on success
  59. * or 0 on failure. */
  60. int read_config_file(const char *f, int whinge) {
  61. int ret = 0;
  62. FILE *fp;
  63. char *line;
  64. int i = 1;
  65. line = xmalloc(MAX_CONFIG_LINE);
  66. fp = fopen(f, "rt");
  67. if (!fp) {
  68. if(whinge) fprintf(stderr, "%s: %s\n", f, strerror(errno));
  69. goto fail;
  70. }
  71. while (fgets(line, MAX_CONFIG_LINE, fp)) {
  72. char *key, *value, *r;
  73. for (r = line + strlen(line) - 1; r > line && *r == '\n'; *(r--) = 0);
  74. /* Get continuation lines. Ugly. */
  75. while (*(line + strlen(line) - 1) == '\\') {
  76. if (!fgets(line + strlen(line) - 1, MAX_CONFIG_LINE - strlen(line), fp))
  77. break;
  78. for (r = line + strlen(line) - 1; r > line && *r == '\n'; *(r--) = 0);
  79. }
  80. /* Strip comment. */
  81. key = strpbrk(line, "#\n");
  82. if (key) *key = 0;
  83. /* foo : bar baz quux
  84. * key^ ^value */
  85. key = line + strspn(line, " \t");
  86. value = strchr(line, ':');
  87. if (value) {
  88. /* foo : bar baz quux
  89. * key^ ^r ^value */
  90. ++value;
  91. r = key + strcspn(key, " \t:");
  92. if (r != key) {
  93. item *I;
  94. *r = 0;
  95. /* foo\0: bar baz quux
  96. * key^ ^value ^r */
  97. value += strspn(value, " \t");
  98. r = value + strlen(value) - 1;
  99. while (strchr(" \t", *r) && r > value) --r;
  100. *(r + 1) = 0;
  101. /* (Removed check for zero length value.) */
  102. /* Check that this is a valid key. */
  103. if (!is_cfgdirective_valid(key))
  104. fprintf(stderr, "%s:%d: warning: unknown directive \"%s\"\n", f, i, key);
  105. else if ((I = stringmap_insert(config, key, item_ptr(xstrdup(value)))))
  106. /* Don't warn of repeated directives, because they
  107. * may have been specified via the command line
  108. * Previous option takes precedence.
  109. */
  110. fprintf(stderr, "%s:%d: warning: repeated directive \"%s\"\n", f, i, key);
  111. }
  112. }
  113. memset(line, 0, MAX_CONFIG_LINE); /* security paranoia */
  114. ++i;
  115. }
  116. ret = 1;
  117. fail:
  118. if (fp) fclose(fp);
  119. if (line) xfree(line);
  120. return ret;
  121. }
  122. int config_get_int(const char *directive, int *value) {
  123. stringmap S;
  124. char *s, *t;
  125. if (!value) return -1;
  126. S = stringmap_find(config, directive);
  127. if (!S) return 0;
  128. s = (char*)S->d.v;
  129. if (!*s) return -1;
  130. errno = 0;
  131. *value = strtol(s, &t, 10);
  132. if (*t) return -1;
  133. return errno == ERANGE ? -1 : 1;
  134. }
  135. /* config_get_float:
  136. * Get an integer value from a config string. Returns 1 on success, -1 on
  137. * failure, or 0 if no value was found. */
  138. int config_get_float(const char *directive, float *value) {
  139. stringmap S;
  140. char *s, *t;
  141. if (!value) return -1;
  142. if (!(S = stringmap_find(config, directive)))
  143. return 0;
  144. s = (char*)S->d.v;
  145. if (!*s) return -1;
  146. errno = 0;
  147. *value = strtod(s, &t);
  148. if (*t) return -1;
  149. return errno == ERANGE ? -1 : 1;
  150. }
  151. /* config_get_string;
  152. * Get a string value from the config file. Returns NULL if it is not
  153. * present. */
  154. char *config_get_string(const char *directive) {
  155. stringmap S;
  156. S = stringmap_find(config, directive);
  157. if (S) return (char*)S->d.v;
  158. else return NULL;
  159. }
  160. /* config_get_bool:
  161. * Get a boolean value from the config file. Returns false if not present. */
  162. int config_get_bool(const char *directive) {
  163. char *s;
  164. s = config_get_string(directive);
  165. if (s && (strcmp(s, "yes") == 0 || strcmp(s, "true") == 0))
  166. return 1;
  167. else
  168. return 0;
  169. }
  170. /* config_get_enum:
  171. * Get an enumeration value from the config file. Returns false if not
  172. * present or an invalid value is found. */
  173. int config_get_enum(const char *directive, config_enumeration_type *enumeration, int *value) {
  174. char *s;
  175. config_enumeration_type *t;
  176. s = config_get_string(directive);
  177. if(s) {
  178. for(t = enumeration; t->name; t++) {
  179. if(strcmp(s,t->name) == 0) {
  180. *value = t->value;
  181. return 1;
  182. }
  183. }
  184. fprintf(stderr,"Invalid enumeration value \"%s\" for directive \"%s\"\n", s, directive);
  185. }
  186. return 0;
  187. }
  188. /* config_set_string; Sets a value in the config, possibly overriding
  189. * an existing value
  190. */
  191. void config_set_string(const char *directive, const char* s) {
  192. stringmap S;
  193. S = stringmap_find(config, directive);
  194. if (S) {
  195. xfree(S->d.v);
  196. S->d = item_ptr(xstrdup(s));
  197. }
  198. else {
  199. stringmap_insert(config, directive, item_ptr(xstrdup(s)));
  200. }
  201. }
  202. int read_config(char *file, int whinge_on_error) {
  203. return read_config_file(file, whinge_on_error);
  204. }