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.

cfg_utils.c 8.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. #include <sys/types.h>
  2. #include <sys/socket.h>
  3. #include <ctype.h>
  4. #include <errno.h>
  5. #include <stdarg.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <sys/un.h>
  10. #include <netinet/in.h>
  11. #include <arpa/inet.h>
  12. #include <syslog.h>
  13. #include <netdb.h>
  14. #include <math.h>
  15. #include <netinet/in.h>
  16. #include <arpa/inet.h>
  17. #include "config.h"
  18. #include "cfg_file.h"
  19. #include "main.h"
  20. #ifndef HAVE_OWN_QUEUE_H
  21. #include <sys/queue.h>
  22. #else
  23. #include "queue.h"
  24. #endif
  25. extern int yylineno;
  26. extern char *yytext;
  27. static void
  28. clean_hash_bucket (gpointer key, gpointer value, gpointer unused)
  29. {
  30. LIST_HEAD (moduleoptq, module_opt) *cur_module_opt = (struct moduleoptq *)value;
  31. struct module_opt *cur, *tmp;
  32. LIST_FOREACH_SAFE (cur, cur_module_opt, next, tmp) {
  33. if (cur->param) {
  34. free (cur->param);
  35. }
  36. if (cur->value) {
  37. free (cur->value);
  38. }
  39. LIST_REMOVE (cur, next);
  40. free (cur);
  41. }
  42. free (cur_module_opt);
  43. }
  44. int
  45. add_memcached_server (struct config_file *cf, char *str)
  46. {
  47. char *cur_tok, *err_str;
  48. struct memcached_server *mc;
  49. struct hostent *hent;
  50. uint16_t port;
  51. if (str == NULL) return 0;
  52. cur_tok = strsep (&str, ":");
  53. if (cur_tok == NULL || *cur_tok == '\0') return 0;
  54. if(cf->memcached_servers_num == MAX_MEMCACHED_SERVERS) {
  55. yywarn ("yyparse: maximum number of memcached servers is reached %d", MAX_MEMCACHED_SERVERS);
  56. }
  57. mc = &cf->memcached_servers[cf->memcached_servers_num];
  58. if (mc == NULL) return 0;
  59. /* cur_tok - server name, str - server port */
  60. if (str == NULL) {
  61. port = DEFAULT_MEMCACHED_PORT;
  62. }
  63. else {
  64. port = (uint16_t)strtoul (str, &err_str, 10);
  65. if (*err_str != '\0') {
  66. return 0;
  67. }
  68. }
  69. if (!inet_aton (cur_tok, &mc->addr)) {
  70. /* Try to call gethostbyname */
  71. hent = gethostbyname (cur_tok);
  72. if (hent == NULL) {
  73. return 0;
  74. }
  75. else {
  76. memcpy((char *)&mc->addr, hent->h_addr, sizeof(struct in_addr));
  77. }
  78. }
  79. mc->port = port;
  80. cf->memcached_servers_num++;
  81. return 1;
  82. }
  83. int
  84. parse_bind_line (struct config_file *cf, char *str)
  85. {
  86. char *cur_tok, *err_str;
  87. struct hostent *hent;
  88. size_t s;
  89. if (str == NULL) return 0;
  90. cur_tok = strsep (&str, ":");
  91. if (cur_tok[0] == '/' || cur_tok[0] == '.') {
  92. cf->bind_host = strdup (cur_tok);
  93. cf->bind_family = AF_UNIX;
  94. return 1;
  95. } else {
  96. if (str == '\0') {
  97. cf->bind_port = DEFAULT_BIND_PORT;
  98. }
  99. else {
  100. cf->bind_port = (uint16_t)strtoul (str, &err_str, 10);
  101. if (*err_str != '\0') {
  102. return 0;
  103. }
  104. }
  105. if (!inet_aton (cur_tok, &cf->bind_addr)) {
  106. /* Try to call gethostbyname */
  107. hent = gethostbyname (cur_tok);
  108. if (hent == NULL) {
  109. return 0;
  110. }
  111. else {
  112. cf->bind_host = strdup (cur_tok);
  113. memcpy((char *)&cf->bind_addr, hent->h_addr, sizeof(struct in_addr));
  114. s = strlen (cur_tok) + 1;
  115. }
  116. }
  117. cf->bind_family = AF_INET;
  118. return 1;
  119. }
  120. return 0;
  121. }
  122. void
  123. init_defaults (struct config_file *cfg)
  124. {
  125. cfg->memcached_error_time = DEFAULT_UPSTREAM_ERROR_TIME;
  126. cfg->memcached_dead_time = DEFAULT_UPSTREAM_DEAD_TIME;
  127. cfg->memcached_maxerrors = DEFAULT_UPSTREAM_MAXERRORS;
  128. cfg->memcached_protocol = TCP_TEXT;
  129. cfg->workers_number = DEFAULT_WORKERS_NUM;
  130. cfg->modules_opts = g_hash_table_new (g_str_hash, g_str_equal);
  131. cfg->variables = g_hash_table_new (g_str_hash, g_str_equal);
  132. LIST_INIT (&cfg->filters);
  133. LIST_INIT (&cfg->perl_modules);
  134. LIST_INIT (&cfg->c_modules);
  135. }
  136. void
  137. free_config (struct config_file *cfg)
  138. {
  139. struct filter_chain *chain, *tmp_chain;
  140. struct script_param *param, *tmp_param;
  141. struct perl_module *module, *tmp_module;
  142. struct c_module *cmodule, *tmp_cmodule;
  143. if (cfg->pid_file) {
  144. g_free (cfg->pid_file);
  145. }
  146. if (cfg->temp_dir) {
  147. g_free (cfg->temp_dir);
  148. }
  149. if (cfg->bind_host) {
  150. g_free (cfg->bind_host);
  151. }
  152. LIST_FOREACH_SAFE (chain, &cfg->filters, next, tmp_chain) {
  153. LIST_FOREACH_SAFE (param, chain->scripts, next, tmp_param) {
  154. if (param->symbol) {
  155. free (param->symbol);
  156. }
  157. if (param->function) {
  158. free (param->function);
  159. }
  160. LIST_REMOVE (param, next);
  161. free (param);
  162. }
  163. LIST_REMOVE (chain, next);
  164. free (chain);
  165. }
  166. LIST_FOREACH_SAFE (module, &cfg->perl_modules, next, tmp_module) {
  167. if (module->path) {
  168. free (module->path);
  169. }
  170. LIST_REMOVE (module, next);
  171. free (module);
  172. }
  173. LIST_FOREACH_SAFE (cmodule, &cfg->c_modules, next, tmp_cmodule) {
  174. if (cmodule->ctx) {
  175. free (cmodule->ctx);
  176. }
  177. free (cmodule);
  178. }
  179. g_hash_table_foreach (cfg->modules_opts, clean_hash_bucket, NULL);
  180. g_hash_table_remove_all (cfg->modules_opts);
  181. g_hash_table_unref (cfg->modules_opts);
  182. g_hash_table_remove_all (cfg->variables);
  183. g_hash_table_unref (cfg->variables);
  184. }
  185. int
  186. parse_script (char *str, struct script_param *param, enum script_type type)
  187. {
  188. char *cur_tok;
  189. bzero (param, sizeof (struct script_param));
  190. param->type = type;
  191. /* symbol:path:function -> cur_tok - symbol, str -> function */
  192. cur_tok = strsep (&str, ":");
  193. if (str == NULL || cur_tok == NULL || *cur_tok == '\0') return -1;
  194. param->symbol = strdup (cur_tok);
  195. param->function = strdup (str);
  196. return 0;
  197. }
  198. char*
  199. get_module_opt (struct config_file *cfg, char *module_name, char *opt_name)
  200. {
  201. LIST_HEAD (moduleoptq, module_opt) *cur_module_opt = NULL;
  202. struct module_opt *cur;
  203. cur_module_opt = g_hash_table_lookup (cfg->modules_opts, module_name);
  204. if (cur_module_opt == NULL) {
  205. return NULL;
  206. }
  207. LIST_FOREACH (cur, cur_module_opt, next) {
  208. if (strcmp (cur->param, opt_name) == 0) {
  209. return cur->value;
  210. }
  211. }
  212. return NULL;
  213. }
  214. size_t
  215. parse_limit (const char *limit)
  216. {
  217. size_t result = 0;
  218. char *err_str;
  219. if (!limit || *limit == '\0') return 0;
  220. result = strtoul (limit, &err_str, 10);
  221. if (*err_str != '\0') {
  222. /* Megabytes */
  223. if (*err_str == 'm' || *err_str == 'M') {
  224. result *= 1048576L;
  225. }
  226. /* Kilobytes */
  227. else if (*err_str == 'k' || *err_str == 'K') {
  228. result *= 1024;
  229. }
  230. /* Gigabytes */
  231. else if (*err_str == 'g' || *err_str == 'G') {
  232. result *= 1073741824L;
  233. }
  234. }
  235. return result;
  236. }
  237. unsigned int
  238. parse_seconds (const char *t)
  239. {
  240. unsigned int result = 0;
  241. char *err_str;
  242. if (!t || *t == '\0') return 0;
  243. result = strtoul (t, &err_str, 10);
  244. if (*err_str != '\0') {
  245. /* Seconds */
  246. if (*err_str == 's' || *err_str == 'S') {
  247. result *= 1000;
  248. }
  249. }
  250. return result;
  251. }
  252. char
  253. parse_flag (const char *str)
  254. {
  255. if (!str || !*str) return -1;
  256. if ((*str == 'Y' || *str == 'y') && *(str + 1) == '\0') {
  257. return 1;
  258. }
  259. if ((*str == 'Y' || *str == 'y') &&
  260. (*(str + 1) == 'E' || *(str + 1) == 'e') &&
  261. (*(str + 2) == 'S' || *(str + 2) == 's') &&
  262. *(str + 3) == '\0') {
  263. return 1;
  264. }
  265. if ((*str == 'N' || *str == 'n') && *(str + 1) == '\0') {
  266. return 0;
  267. }
  268. if ((*str == 'N' || *str == 'n') &&
  269. (*(str + 1) == 'O' || *(str + 1) == 'o') &&
  270. *(str + 2) == '\0') {
  271. return 0;
  272. }
  273. return -1;
  274. }
  275. /*
  276. * Try to substitute all variables in given string
  277. * Return: newly allocated string with substituted variables (original string may be freed if variables are found)
  278. */
  279. char *
  280. substitute_variable (struct config_file *cfg, char *str, u_char recursive)
  281. {
  282. char *var, *new, *v_begin, *v_end;
  283. size_t len;
  284. while ((v_begin = strstr (str, "${")) != NULL) {
  285. len = strlen (str);
  286. *v_begin = '\0';
  287. v_begin += 2;
  288. if ((v_end = strstr (v_begin, "}")) == NULL) {
  289. /* Not a variable, skip */
  290. continue;
  291. }
  292. *v_end = '\0';
  293. var = g_hash_table_lookup (cfg->variables, v_begin);
  294. if (var == NULL) {
  295. yywarn ("substitute_variable: variable %s is not defined", v_begin);
  296. /* Substitute unknown variables with empty string */
  297. var = "";
  298. }
  299. else if (recursive) {
  300. var = substitute_variable (cfg, var, recursive);
  301. }
  302. /* Allocate new string */
  303. new = g_malloc (len - strlen (v_begin) + strlen (var) + 1);
  304. snprintf (new, len - strlen (v_begin) + strlen (var) + 1, "%s%s%s",
  305. str, var, v_end + 1);
  306. g_free (str);
  307. str = new;
  308. }
  309. return str;
  310. }
  311. static void
  312. substitute_module_variables (gpointer key, gpointer value, gpointer data)
  313. {
  314. struct config_file *cfg = (struct config_file *)data;
  315. LIST_HEAD (moduleoptq, module_opt) *cur_module_opt = (struct moduleoptq *)value;
  316. struct module_opt *cur, *tmp;
  317. LIST_FOREACH_SAFE (cur, cur_module_opt, next, tmp) {
  318. if (cur->value) {
  319. cur->value = substitute_variable (cfg, cur->value, 0);
  320. }
  321. }
  322. }
  323. static void
  324. substitute_all_variables (gpointer key, gpointer value, gpointer data)
  325. {
  326. struct config_file *cfg = (struct config_file *)data;
  327. char *var;
  328. var = value;
  329. /* Do recursive substitution */
  330. var = substitute_variable (cfg, var, 1);
  331. }
  332. /*
  333. * Substitute all variables in strings
  334. */
  335. void
  336. post_load_config (struct config_file *cfg)
  337. {
  338. g_hash_table_foreach (cfg->variables, substitute_all_variables, cfg);
  339. g_hash_table_foreach (cfg->modules_opts, substitute_module_variables, cfg);
  340. }
  341. /*
  342. * vi:ts=4
  343. */