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 9.3KB

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