QNAP-TS419p system daemon
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

292 lines
7.5 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. /***************************************************************************
  2. * Copyright (C) 03/2010 by Olaf Rempel *
  3. * razzor@kopf-tisch.de *
  4. * *
  5. * This program is free software; you can redistribute it and/or modify *
  6. * it under the terms of the GNU General Public License as published by *
  7. * the Free Software Foundation; version 2 of the License *
  8. * *
  9. * This program is distributed in the hope that it will be useful, *
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  12. * GNU General Public License for more details. *
  13. * *
  14. * You should have received a copy of the GNU General Public License *
  15. * along with this program; if not, write to the *
  16. * Free Software Foundation, Inc., *
  17. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  18. ***************************************************************************/
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <unistd.h>
  23. #include <ctype.h>
  24. #include "configfile.h"
  25. #include "list.h"
  26. #include "logging.h"
  27. #define BUFSIZE 1024
  28. struct conf_section {
  29. struct list_head list;
  30. struct list_head tupel_list;
  31. const char *name;
  32. };
  33. struct conf_tupel {
  34. struct list_head list;
  35. const char *option;
  36. const char *parameter;
  37. };
  38. static LIST_HEAD(config_list);
  39. static struct conf_section * config_add_section(const char *name)
  40. {
  41. struct conf_section *section;
  42. section = malloc(sizeof(struct conf_section) + strlen(name));
  43. if (section == NULL)
  44. return NULL;
  45. INIT_LIST_HEAD(&section->list);
  46. INIT_LIST_HEAD(&section->tupel_list);
  47. section->name = strdup(name);
  48. if (section->name == NULL) {
  49. free(section);
  50. return NULL;
  51. }
  52. list_add_tail(&section->list, &config_list);
  53. return section;
  54. }
  55. static int config_add_tupel(struct conf_section *section, const char *option, const char *parameter)
  56. {
  57. struct conf_tupel *tupel = malloc(sizeof(struct conf_tupel));
  58. if (tupel == NULL)
  59. return -1;
  60. INIT_LIST_HEAD(&tupel->list);
  61. tupel->option = strdup(option);
  62. tupel->parameter = strdup(parameter);
  63. if (tupel->option == NULL || tupel->parameter == NULL) {
  64. free(tupel);
  65. return -1;
  66. }
  67. list_add_tail(&tupel->list, &section->tupel_list);
  68. return 0;
  69. }
  70. int config_parse(const char *config)
  71. {
  72. FILE *fz = fopen(config, "r");
  73. if (fz == NULL) {
  74. log_print(LOG_ERROR, "%s(): failed to open config '%s'", __FUNCTION__, config);
  75. return -1;
  76. }
  77. char *line = malloc(BUFSIZE);
  78. if (line == NULL) {
  79. log_print(LOG_ERROR, "%s(): out of memory", __FUNCTION__);
  80. fclose(fz);
  81. return -1;
  82. }
  83. int linenum = 0;
  84. struct conf_section *section = NULL;
  85. while (fgets(line, BUFSIZE, fz) != NULL) {
  86. linenum++;
  87. if (line[0] == '#' || line[0] <= ' ') {
  88. continue;
  89. } else if (line[0] == '[') {
  90. char *tok = strtok(line +1, " ]\n");
  91. if (tok == NULL || (section = config_add_section(tok)) == NULL) {
  92. log_print(LOG_WARN, "%s(): invalid section in row %d", __FUNCTION__, linenum);
  93. free(line);
  94. fclose(fz);
  95. return -1;
  96. }
  97. continue;
  98. } else if (section == NULL) {
  99. log_print(LOG_WARN, "%s(): missing section in row %d", __FUNCTION__, linenum);
  100. free(line);
  101. fclose(fz);
  102. return -1;
  103. }
  104. char *tmp, *tok = strtok_r(line, " \t\n", &tmp);
  105. if (tok != NULL) {
  106. char *tok2;
  107. while ((tok2 = strtok_r(NULL, " \n", &tmp))) {
  108. if (config_add_tupel(section, tok, tok2) != 0)
  109. log_print(LOG_WARN, "%s(): invalid row %d", __FUNCTION__, linenum);
  110. }
  111. }
  112. }
  113. fclose(fz);
  114. free(line);
  115. return 0;
  116. }
  117. void config_free(void)
  118. {
  119. struct conf_section *section, *section_tmp;
  120. struct conf_tupel *tupel, *tupel_tmp;
  121. list_for_each_entry_safe(section, section_tmp, &config_list, list) {
  122. list_for_each_entry_safe(tupel, tupel_tmp, &section->tupel_list, list) {
  123. list_del(&tupel->list);
  124. free((char *)tupel->option);
  125. free((char *)tupel->parameter);
  126. free(tupel);
  127. }
  128. list_del(&section->list);
  129. free(section);
  130. }
  131. }
  132. static struct conf_section * config_get_section(const char *name)
  133. {
  134. struct conf_section *section;
  135. list_for_each_entry(section, &config_list, list) {
  136. if (!strcmp(section->name, name))
  137. return section;
  138. }
  139. return NULL;
  140. }
  141. const char * config_get_string(const char *section_str, const char *option, const char *def)
  142. {
  143. struct conf_section *section = config_get_section(section_str);
  144. if (section != NULL) {
  145. struct conf_tupel *tupel;
  146. list_for_each_entry(tupel, &section->tupel_list, list) {
  147. if (!strcmp(tupel->option, option))
  148. return tupel->parameter;
  149. }
  150. }
  151. if (def != NULL)
  152. log_print(LOG_WARN, "config [%s:%s] not found, using default: '%s'",
  153. section_str, option, def);
  154. return def;
  155. }
  156. int config_get_int(const char *section, const char *option, int *value, int def)
  157. {
  158. const char *ret = config_get_string(section, option, NULL);
  159. if (ret == NULL) {
  160. log_print(LOG_WARN, "config [%s:%s] not found, using default: '%d'",
  161. section, option, def);
  162. *value = def;
  163. return -1;
  164. }
  165. char *tmp;
  166. *value = strtol(ret, &tmp, 0);
  167. if (*tmp != '\0' && !isspace(*tmp)) {
  168. log_print(LOG_WARN, "config [%s:%s] not an integer: '%s', using default '%d'",
  169. section, option, ret, def);
  170. *value = def;
  171. return -1;
  172. }
  173. return 0;
  174. }
  175. int config_get_strings(const char *section_str, const char *option,
  176. int (*callback)(const char *value, void *privdata),
  177. void *privdata)
  178. {
  179. struct conf_section *section = config_get_section(section_str);
  180. if (section == NULL)
  181. return -1;
  182. int cnt = 0;
  183. struct conf_tupel *tupel;
  184. list_for_each_entry(tupel, &section->tupel_list, list) {
  185. if (!strcmp(tupel->option, option))
  186. if (callback(tupel->parameter, privdata) == 0)
  187. cnt++;
  188. }
  189. return cnt;
  190. }
  191. struct strtoken * strtokenize(const char *input, const char *delim, int maxfields)
  192. {
  193. struct strtoken *tokens = malloc(sizeof(struct strtoken) +
  194. (maxfields +1) * sizeof(char *) +
  195. strlen(input));
  196. if (tokens == NULL)
  197. return NULL;
  198. char *ptr = (char *)&tokens->field[maxfields];
  199. strcpy(ptr, input);
  200. tokens->input = input;
  201. tokens->delim = delim;
  202. tokens->maxfields = maxfields;
  203. int i;
  204. char *tmp;
  205. tokens->count = 0;
  206. for (i = 0; i < maxfields; i++) {
  207. tokens->field[i] = strtok_r(ptr, delim, &tmp);
  208. ptr = NULL;
  209. if (tokens->field[i] != NULL)
  210. tokens->count++;
  211. }
  212. return tokens;
  213. }
  214. struct strtoken * config_get_strtoken(const char *section, const char *option, const char *delim, int maxfields)
  215. {
  216. const char *ret = config_get_string(section, option, NULL);
  217. if (ret == NULL) {
  218. log_print(LOG_WARN, "config [%s:%s] not found", section, option);
  219. return NULL;
  220. }
  221. return strtokenize(ret, delim, maxfields);
  222. }
  223. int config_get_strtokens(const char *section_str, const char *option, const char *delim, int maxfields,
  224. int (*callback)(struct strtoken *data, void *privdata),
  225. void *privdata)
  226. {
  227. struct conf_section *section = config_get_section(section_str);
  228. if (section == NULL)
  229. return -1;
  230. int cnt = 0;
  231. struct conf_tupel *tupel;
  232. list_for_each_entry(tupel, &section->tupel_list, list) {
  233. if (!strcmp(tupel->option, option)) {
  234. struct strtoken *tokens = strtokenize(tupel->parameter, delim, maxfields);
  235. if (tokens != NULL) {
  236. if (callback(tokens, privdata) == 0)
  237. cnt++;
  238. free(tokens);
  239. }
  240. }
  241. }
  242. return cnt;
  243. }