confreader.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /* vim: tabstop=4 shiftwidth=4 noexpandtab
  2. * This file is part of ToaruOS and is released under the terms
  3. * of the NCSA / University of Illinois License - see LICENSE.md
  4. * Copyright (C) 2018 K. Lange
  5. *
  6. * Configuration File Reader
  7. *
  8. * Reads an implementation of the INI "standard". Note that INI
  9. * isn't actually a standard. We support the following:
  10. * - ; comments
  11. * - foo=bar keyword assignment
  12. * - [sections]
  13. */
  14. #include <stdio.h>
  15. #include <toaru/hashmap.h>
  16. #include <toaru/confreader.h>
  17. #define TRACE_APP_NAME "confreader"
  18. #define TRACE(...)
  19. //#include <toaru/trace.h>
  20. static void free_hashmap(void * h) {
  21. hashmap_free(h);
  22. free(h);
  23. }
  24. static int write_section(FILE * f, hashmap_t * section) {
  25. list_t * keys = hashmap_keys(section);
  26. foreach(node, keys) {
  27. char * key = (char*)node->value;
  28. char * value = hashmap_get(section, key);
  29. fprintf(f, "%s=%s\n", key, value);
  30. }
  31. list_free(keys);
  32. free(keys);
  33. return 0;
  34. }
  35. int confreader_write(confreader_t * config, const char * file) {
  36. FILE * f = fopen(file, "w");
  37. if (!f) return 1;
  38. hashmap_t * base = hashmap_get(config->sections, "");
  39. if (base) {
  40. write_section(f, base);
  41. }
  42. list_t * sections = hashmap_keys(config->sections);
  43. foreach(node, sections) {
  44. char * section = (char*)node->value;
  45. if (strcmp(section,"")) {
  46. hashmap_t * data = hashmap_get(config->sections, section);
  47. fprintf(f, "[%s]\n", section);
  48. write_section(f, data);
  49. }
  50. }
  51. return 0;
  52. }
  53. confreader_t * confreader_create_empty(void) {
  54. confreader_t * out = malloc(sizeof(confreader_t));
  55. out->sections = hashmap_create(10);
  56. return out;
  57. }
  58. confreader_t * confreader_load(const char * file) {
  59. FILE * f = fopen(file, "r");
  60. if (!f) return NULL;
  61. confreader_t * out = confreader_create_empty();
  62. hashmap_t * current_section = hashmap_create(10);
  63. current_section->hash_val_free = free_hashmap;
  64. hashmap_set(out->sections, "", current_section);
  65. if (!f) {
  66. /* File does not exist, no configuration values, but continue normally. */
  67. return out;
  68. }
  69. char tmp[1024];
  70. char tmp2[1024];
  71. while (!feof(f)) {
  72. char c = fgetc(f);
  73. tmp[0] = '\0';
  74. tmp2[0] = '\0';
  75. if (c == ';') {
  76. TRACE("Comment");
  77. while (!feof(f) && fgetc(f) != '\n');
  78. TRACE("Done");
  79. } else if (c == '\n' || c == EOF) {
  80. TRACE("blank line or EOF: %d", c);
  81. continue;
  82. } else if (c == '[') {
  83. TRACE("section");
  84. char * foo = tmp;
  85. int i;
  86. while ((i = fgetc(f)) >= 0) {
  87. if (i == ']') break;
  88. *foo = i;
  89. foo++;
  90. *foo = '\0';
  91. }
  92. while (!feof(f) && fgetc(f) != '\n');
  93. current_section = hashmap_create(10);
  94. TRACE("adding section %s", tmp);
  95. hashmap_set(out->sections, tmp, current_section);
  96. TRACE("section is over");
  97. } else {
  98. TRACE("value");
  99. char * foo = tmp;
  100. *foo = c;
  101. foo++;
  102. int i;
  103. while ((i = fgetc(f)) >= 0) {
  104. if (i == '=') break;
  105. *foo = i;
  106. foo++;
  107. *foo = '\0';
  108. }
  109. if (i != '=') {
  110. TRACE("no equals sign");
  111. while (!feof(f) && fgetc(f) != '\n');
  112. continue;
  113. }
  114. TRACE("=");
  115. foo = tmp2;
  116. while ((i = fgetc(f)) >= 0) {
  117. if (i == '\n') break;
  118. *foo = i;
  119. foo++;
  120. *foo = '\0';
  121. }
  122. TRACE("setting value %s to %s", tmp, tmp2);
  123. hashmap_set(current_section, tmp, strdup(tmp2));
  124. }
  125. }
  126. fclose(f);
  127. TRACE("done reading");
  128. return out;
  129. }
  130. void confreader_free(confreader_t * conf) {
  131. free_hashmap(conf->sections);
  132. free(conf);
  133. }
  134. char * confreader_get(confreader_t * ctx, char * section, char * value) {
  135. if (!ctx) return NULL;
  136. hashmap_t * s = hashmap_get(ctx->sections, section);
  137. if (!s) {
  138. TRACE("section doesn't exist: %s", section);
  139. return NULL;
  140. }
  141. return hashmap_get(s, value);
  142. }
  143. char * confreader_getd(confreader_t * ctx, char * section, char * value, char * def) {
  144. char * result = confreader_get(ctx, section, value);
  145. return result ? result : def;
  146. }
  147. int confreader_int(confreader_t * ctx, char * section, char * value) {
  148. char * result = confreader_get(ctx, section, value);
  149. if (!result) return 0;
  150. return atoi(result);
  151. }
  152. int confreader_intd(confreader_t * ctx, char * section, char * value, int def) {
  153. char * result = confreader_get(ctx, section, value);
  154. if (!result) return def;
  155. return atoi(result);
  156. }