From e47778974acc39511f01ac89281bd32a759aab9f Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Wed, 7 Apr 2010 19:56:23 +0400 Subject: [PATCH] * Wellcome to the XML world --- src/cfg_file.h | 2 + src/cfg_file.y | 2 + src/cfg_utils.c | 2 +- src/cfg_xml.c | 268 ++++++++++++++++++++++++++++++++++++------------ src/cfg_xml.h | 1 + src/main.c | 140 ++++++++++++++++--------- 6 files changed, 303 insertions(+), 112 deletions(-) diff --git a/src/cfg_file.h b/src/cfg_file.h index 0cf70e8a0..fb220f486 100644 --- a/src/cfg_file.h +++ b/src/cfg_file.h @@ -290,6 +290,8 @@ struct config_file { GList *views; /**< views */ GHashTable* domain_settings; /**< settings per-domains */ GHashTable* user_settings; /**< settings per-user */ + gchar* domain_settings_str; /**< string representation of settings */ + gchar* user_settings_str; gchar* checksum; /**< real checksum of config file */ gchar* dump_checksum; /**< dump checksum of config file */ diff --git a/src/cfg_file.y b/src/cfg_file.y index 47d3a545c..58813ad6b 100644 --- a/src/cfg_file.y +++ b/src/cfg_file.y @@ -1140,6 +1140,7 @@ usersettings: yyerror ("yyparse: cannot read settings %s", $3); YYERROR; } + cfg->user_settings_str = memory_pool_strdup (cfg->cfg_pool, $3); } ; domainsettings: @@ -1148,6 +1149,7 @@ domainsettings: yyerror ("yyparse: cannot read settings %s", $3); YYERROR; } + cfg->domain_settings_str = memory_pool_strdup (cfg->cfg_pool, $3); } ; %% diff --git a/src/cfg_utils.c b/src/cfg_utils.c index 9047340fb..4450d6cad 100644 --- a/src/cfg_utils.c +++ b/src/cfg_utils.c @@ -862,7 +862,7 @@ read_xml_config (struct config_file *cfg, const gchar *filename) ud.cfg = cfg; ud.state = XML_READ_START; - ctx = g_markup_parse_context_new (&xml_parser, G_MARKUP_TREAT_CDATA_AS_TEXT, &ud, NULL); + ctx = g_markup_parse_context_new (&xml_parser, G_MARKUP_TREAT_CDATA_AS_TEXT | G_MARKUP_PREFIX_ERROR_POSITION, &ud, NULL); res = g_markup_parse_context_parse (ctx, data, st.st_size, &err); munmap (data, st.st_size); diff --git a/src/cfg_xml.c b/src/cfg_xml.c index c089bf7a0..5acba2d49 100644 --- a/src/cfg_xml.c +++ b/src/cfg_xml.c @@ -41,6 +41,8 @@ /* Maximum attributes for param */ #define MAX_PARAM 64 +#define EOL "\n" + #define NULL_ATTR \ { \ NULL, \ @@ -412,7 +414,7 @@ extract_attr (const gchar *attr, const gchar **attribute_names, const gchar **at cur_value = attribute_values; while (*cur_attr && *cur_value) { - if (g_ascii_strcasecmp (*cur_attr, attr)) { + if (g_ascii_strcasecmp (*cur_attr, attr) == 0) { *res = (gchar *) *cur_value; return TRUE; } @@ -700,7 +702,7 @@ handle_module_opt (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHa is_lua = TRUE; } } - cur_opt = g_hash_table_lookup (cfg->modules_opts, ctx->section_name); + cur_opt = g_hash_table_lookup (cfg->modules_opts, ctx->section_pointer); if (cur_opt == NULL) { /* Insert new option structure */ cur = memory_pool_alloc0 (cfg->cfg_pool, sizeof (struct module_opt)); @@ -708,7 +710,7 @@ handle_module_opt (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHa cur->value = data; cur->is_lua = is_lua; cur_opt = g_list_prepend (NULL, cur); - g_hash_table_insert (cfg->modules_opts, memory_pool_strdup (cfg->cfg_pool, ctx->section_name), cur_opt); + g_hash_table_insert (cfg->modules_opts, memory_pool_strdup (cfg->cfg_pool, ctx->section_pointer), cur_opt); } else { /* First try to find option with this name */ @@ -886,6 +888,7 @@ handle_view_symbols (struct config_file *cfg, struct rspamd_xml_userdata *ctx, G msg_err ("invalid symbols line in view definition: ip = '%s'", data); return FALSE; } + cfg->domain_settings_str = memory_pool_strdup (cfg->cfg_pool, data); return TRUE; } @@ -898,6 +901,7 @@ handle_user_settings (struct config_file *cfg, struct rspamd_xml_userdata *ctx, msg_err ("cannot read settings %s", data); return FALSE; } + cfg->user_settings_str = memory_pool_strdup (cfg->cfg_pool, data); return TRUE; } @@ -1134,7 +1138,8 @@ rspamd_xml_start_element (GMarkupParseContext *context, const gchar *element_nam const gchar **attribute_values, gpointer user_data, GError **error) { struct rspamd_xml_userdata *ud = user_data; - gchar *res; + struct classifier_config *ccf; + gchar *res; switch (ud->state) { case XML_READ_START: @@ -1152,7 +1157,7 @@ rspamd_xml_start_element (GMarkupParseContext *context, const gchar *element_nam if (g_ascii_strcasecmp (element_name, "module") == 0) { /* Read module data */ if (extract_attr ("name", attribute_names, attribute_values, &res)) { - g_strlcpy (ud->section_name, res, sizeof (ud->section_name)); + ud->section_pointer = res; ud->state = XML_READ_MODULE; } else { @@ -1180,10 +1185,16 @@ rspamd_xml_start_element (GMarkupParseContext *context, const gchar *element_nam } else if (g_ascii_strcasecmp (element_name, "classifier") == 0) { if (extract_attr ("type", attribute_names, attribute_values, &res)) { - g_strlcpy (ud->section_name, res, sizeof (ud->section_name)); ud->state = XML_READ_CLASSIFIER; /* Create object */ - ud->section_pointer = check_classifier_cfg (ud->cfg, NULL); + ccf = check_classifier_cfg (ud->cfg, NULL); + if ((ccf->classifier = get_classifier (res)) == NULL) { + *error = g_error_new (xml_error_quark (), XML_INVALID_ATTR, "invalid classifier type: %s", res); + ud->state = XML_ERROR; + } + else { + ud->section_pointer = ccf; + } } else { *error = g_error_new (xml_error_quark (), XML_PARAM_MISSING, "param 'type' is required for tag 'classifier'"); @@ -1203,6 +1214,7 @@ rspamd_xml_start_element (GMarkupParseContext *context, const gchar *element_nam else { /* Extract other tags */ g_strlcpy (ud->section_name, element_name, sizeof (ud->section_name)); + ud->cur_attrs = process_attrs (ud->cfg, attribute_names, attribute_values); ud->state = XML_READ_VALUE; } break; @@ -1214,12 +1226,18 @@ rspamd_xml_start_element (GMarkupParseContext *context, const gchar *element_nam ud->parent_pointer = ud->section_pointer; ud->section_pointer = memory_pool_alloc0 (ud->cfg->cfg_pool, sizeof (struct statfile)); } + else { + g_strlcpy (ud->section_name, element_name, sizeof (ud->section_name)); + /* Save attributes */ + ud->cur_attrs = process_attrs (ud->cfg, attribute_names, attribute_values); + } break; case XML_READ_MODULE: case XML_READ_FACTORS: case XML_READ_STATFILE: case XML_READ_WORKER: case XML_READ_LOGGING: + g_strlcpy (ud->section_name, element_name, sizeof (ud->section_name)); /* Save attributes */ ud->cur_attrs = process_attrs (ud->cfg, attribute_names, attribute_values); break; @@ -1269,6 +1287,7 @@ rspamd_xml_end_element (GMarkupParseContext *context, const gchar *element_name, if (st->path == NULL || st->size == 0 || st->symbol == NULL) { *error = g_error_new (xml_error_quark (), XML_PARAM_MISSING, "not enough arguments in statfile definition"); ud->state = XML_ERROR; + return; } ccf->statfiles = g_list_prepend (ccf->statfiles, st); ud->cfg->statfiles = g_list_prepend (ud->cfg->statfiles, st); @@ -1343,56 +1362,64 @@ rspamd_xml_text (GMarkupParseContext *context, const gchar *text, gsize text_len char *val; struct config_file *cfg = ud->cfg; + if (*text == '\n') { + return; + } + val = xml_asciiz_string (cfg->cfg_pool, text, text_len); switch (ud->state) { case XML_READ_MODULE: if (!call_param_handler (ud, ud->section_name, val, ud->section_pointer, XML_SECTION_MODULE)) { - *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "cannot parse tag's '%s' data: %s", ud->section_name, val); + *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "cannot parse tag '%s' data: %s", ud->section_name, val); ud->state = XML_ERROR; } break; case XML_READ_CLASSIFIER: if (!call_param_handler (ud, ud->section_name, val, ud->section_pointer, XML_SECTION_CLASSIFIER)) { - *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "cannot parse tag's '%s' data: %s", ud->section_name, val); + *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "cannot parse tag '%s' data: %s", ud->section_name, val); ud->state = XML_ERROR; } break; case XML_READ_STATFILE: + if (!call_param_handler (ud, ud->section_name, val, ud->section_pointer, XML_SECTION_STATFILE)) { + *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "cannot parse tag '%s' data: %s", ud->section_name, val); + ud->state = XML_ERROR; + } break; case XML_READ_FACTORS: if (!call_param_handler (ud, ud->section_name, val, cfg, XML_SECTION_CLASSIFIER)) { - *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "cannot parse tag's '%s' data: %s", ud->section_name, val); + *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "cannot parse tag '%s' data: %s", ud->section_name, val); ud->state = XML_ERROR; } break; case XML_READ_METRIC: if (!call_param_handler (ud, ud->section_name, val, ud->section_pointer, XML_SECTION_METRIC)) { - *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "cannot parse tag's '%s' data: %s", ud->section_name, val); + *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "cannot parse tag '%s' data: %s", ud->section_name, val); ud->state = XML_ERROR; } break; case XML_READ_WORKER: if (!call_param_handler (ud, ud->section_name, val, ud->section_pointer, XML_SECTION_WORKER)) { - *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "cannot parse tag's '%s' data: %s", ud->section_name, val); + *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "cannot parse tag '%s' data: %s", ud->section_name, val); ud->state = XML_ERROR; } break; case XML_READ_VIEW: if (!call_param_handler (ud, ud->section_name, val, ud->section_pointer, XML_SECTION_VIEW)) { - *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "cannot parse tag's '%s' data: %s", ud->section_name, val); + *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "cannot parse tag '%s' data: %s", ud->section_name, val); ud->state = XML_ERROR; } break; case XML_READ_VALUE: if (!call_param_handler (ud, ud->section_name, val, cfg, XML_SECTION_MAIN)) { - *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "cannot parse tag's '%s' data: %s", ud->section_name, val); + *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "cannot parse tag '%s' data: %s", ud->section_name, val); ud->state = XML_ERROR; } break; case XML_READ_LOGGING: if (!call_param_handler (ud, ud->section_name, val, cfg, XML_SECTION_LOGGING)) { - *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "cannot parse tag's '%s' data: %s", ud->section_name, val); + *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "cannot parse tag '%s' data: %s", ud->section_name, val); ud->state = XML_ERROR; } break; @@ -1423,30 +1450,42 @@ xml_dump_main (struct config_file *cfg, FILE *f) char *escaped_str; /* Print header comment */ - fprintf (f, "" CRLF); + fprintf (f, "" EOL); escaped_str = g_markup_escape_text (cfg->temp_dir, -1); - fprintf (f, "%s" CRLF, escaped_str); + fprintf (f, "%s" EOL, escaped_str); g_free (escaped_str); escaped_str = g_markup_escape_text (cfg->pid_file, -1); - fprintf (f, "%s" CRLF, escaped_str); + fprintf (f, "%s" EOL, escaped_str); g_free (escaped_str); escaped_str = g_markup_escape_text (cfg->filters_str, -1); - fprintf (f, "%s" CRLF, escaped_str); + fprintf (f, "%s" EOL, escaped_str); g_free (escaped_str); + + if (cfg->user_settings_str) { + escaped_str = g_markup_escape_text (cfg->user_settings_str, -1); + fprintf (f, "%s" EOL, escaped_str); + g_free (escaped_str); + } + if (cfg->domain_settings_str) { + escaped_str = g_markup_escape_text (cfg->domain_settings_str, -1); + fprintf (f, "%s" EOL, escaped_str); + g_free (escaped_str); + } + fprintf (f, "%llu" EOL, (long long unsigned)cfg->max_statfile_size); if (cfg->checksum) { escaped_str = g_markup_escape_text (cfg->checksum, -1); - fprintf (f, "%s" CRLF, escaped_str); + fprintf (f, "%s" EOL, escaped_str); g_free (escaped_str); } - fprintf (f, "%s" CRLF, cfg->raw_mode ? "yes" : "no"); + fprintf (f, "%s" EOL, cfg->raw_mode ? "yes" : "no"); /* Print footer comment */ - fprintf (f, "" CRLF); + fprintf (f, "" EOL EOL); return TRUE; } @@ -1460,7 +1499,7 @@ xml_variable_callback (gpointer key, gpointer value, gpointer user_data) escaped_key = g_markup_escape_text (key, -1); escaped_value = g_markup_escape_text (value, -1); - fprintf (f, "%s" CRLF, escaped_key, escaped_value); + fprintf (f, "%s" EOL, escaped_key, escaped_value); g_free (escaped_key); g_free (escaped_value); } @@ -1469,13 +1508,13 @@ static gboolean xml_dump_variables (struct config_file *cfg, FILE *f) { /* Print header comment */ - fprintf (f, "" CRLF); + fprintf (f, "" EOL); /* Iterate through variables */ g_hash_table_foreach (cfg->variables, xml_variable_callback, (gpointer)f); /* Print footer comment */ - fprintf (f, "" CRLF); + fprintf (f, "" EOL EOL); return TRUE; } @@ -1492,7 +1531,7 @@ xml_composite_callback (gpointer key, gpointer value, gpointer user_data) escaped_key = g_markup_escape_text (key, -1); escaped_value = g_markup_escape_text (expr->orig, -1); - fprintf (f, "%s" CRLF, escaped_key, escaped_value); + fprintf (f, "%s" EOL, escaped_key, escaped_value); g_free (escaped_key); g_free (escaped_value); } @@ -1501,13 +1540,13 @@ static gboolean xml_dump_composites (struct config_file *cfg, FILE *f) { /* Print header comment */ - fprintf (f, "" CRLF); + fprintf (f, "" EOL); /* Iterate through variables */ g_hash_table_foreach (cfg->composite_symbols, xml_composite_callback, (gpointer)f); /* Print footer comment */ - fprintf (f, "" CRLF); + fprintf (f, "" EOL EOL); return TRUE; } @@ -1521,7 +1560,7 @@ xml_worker_param_callback (gpointer key, gpointer value, gpointer user_data) escaped_key = g_markup_escape_text (key, -1); escaped_value = g_markup_escape_text (value, -1); - fprintf (f, " %s" CRLF, escaped_key, escaped_value); + fprintf (f, " %s" EOL, escaped_key, escaped_value); g_free (escaped_key); g_free (escaped_value); } @@ -1534,47 +1573,47 @@ xml_dump_workers (struct config_file *cfg, FILE *f) char *escaped_str; /* Print header comment */ - fprintf (f, "" CRLF); + fprintf (f, "" EOL); /* Iterate through list */ cur = g_list_first (cfg->workers); while (cur) { wrk = cur->data; - fprintf (f, "" CRLF); + fprintf (f, "" EOL); switch (wrk->type) { case TYPE_WORKER: - fprintf (f, " normal" CRLF); + fprintf (f, " normal" EOL); break; case TYPE_CONTROLLER: - fprintf (f, " controller" CRLF); + fprintf (f, " controller" EOL); break; case TYPE_FUZZY: - fprintf (f, " fuzzy" CRLF); + fprintf (f, " fuzzy" EOL); break; case TYPE_LMTP: - fprintf (f, " lmtp" CRLF); + fprintf (f, " lmtp" EOL); break; } escaped_str = g_markup_escape_text (wrk->bind_host, -1); - fprintf (f, " %s" CRLF, escaped_str); + fprintf (f, " %s" EOL, escaped_str); g_free (escaped_str); - fprintf (f, " %u" CRLF, wrk->count); - fprintf (f, " %u" CRLF, wrk->rlimit_nofile); - fprintf (f, " %u" CRLF, wrk->rlimit_maxcore); + fprintf (f, " %u" EOL, wrk->count); + fprintf (f, " %u" EOL, wrk->rlimit_nofile); + fprintf (f, " %u" EOL, wrk->rlimit_maxcore); /* Now dump other attrs */ - fprintf (f, "" CRLF); + fprintf (f, "" EOL); g_hash_table_foreach (wrk->params, xml_worker_param_callback, f); - fprintf (f, "" CRLF); + fprintf (f, "" EOL); cur = g_list_next (cur); } /* Print footer comment */ - fprintf (f, "" CRLF); + fprintf (f, "" EOL EOL); return TRUE; } @@ -1589,8 +1628,8 @@ xml_module_callback (gpointer key, gpointer value, gpointer user_data) struct module_opt *opt; escaped_key = g_markup_escape_text (key, -1); - fprintf (f, "" CRLF, escaped_key); - fprintf (f, "" CRLF, escaped_key); + fprintf (f, "" EOL, escaped_key); + fprintf (f, "" EOL, escaped_key); g_free (escaped_key); cur = g_list_first (value); @@ -1598,25 +1637,25 @@ xml_module_callback (gpointer key, gpointer value, gpointer user_data) opt = cur->data; escaped_key = g_markup_escape_text (opt->param, -1); escaped_value = g_markup_escape_text (opt->value, -1); - fprintf (f, " " CRLF, escaped_key, escaped_value); + fprintf (f, " " EOL, escaped_key, escaped_value); g_free (escaped_key); g_free (escaped_value); cur = g_list_next (cur); } - fprintf (f, "" CRLF); + fprintf (f, "" EOL EOL); } static gboolean xml_dump_modules (struct config_file *cfg, FILE *f) { /* Print header comment */ - fprintf (f, "" CRLF); + fprintf (f, "" EOL); /* Iterate through variables */ g_hash_table_foreach (cfg->modules_opts, xml_module_callback, (gpointer)f); /* Print footer comment */ - fprintf (f, "" CRLF); + fprintf (f, "" EOL EOL); return TRUE; } @@ -1630,7 +1669,7 @@ xml_classifier_callback (gpointer key, gpointer value, gpointer user_data) escaped_key = g_markup_escape_text (key, -1); escaped_value = g_markup_escape_text (value, -1); - fprintf (f, " %s" CRLF, escaped_key, escaped_value); + fprintf (f, " " EOL, escaped_key, escaped_value); g_free (escaped_key); g_free (escaped_value); } @@ -1643,51 +1682,148 @@ xml_dump_classifiers (struct config_file *cfg, FILE *f) struct statfile *st; /* Print header comment */ - fprintf (f, "" CRLF); + fprintf (f, "" EOL); /* Iterate through classifiers */ cur = g_list_first (cfg->classifiers); while (cur) { ccf = cur->data; - fprintf (f, "" CRLF, ccf->classifier->name); - fprintf (f, " %s" CRLF, ccf->tokenizer->name); - fprintf (f, " %s" CRLF, ccf->metric); + fprintf (f, "" EOL, ccf->classifier->name); + fprintf (f, " %s" EOL, ccf->tokenizer->name); + fprintf (f, " %s" EOL, ccf->metric); g_hash_table_foreach (ccf->opts, xml_classifier_callback, f); /* Statfiles */ cur_st = g_list_first (ccf->statfiles); while (cur_st) { st = cur_st->data; - fprintf (f, " " CRLF); - fprintf (f, " %s" CRLF " %lu" CRLF " %s" CRLF, + fprintf (f, " " EOL); + fprintf (f, " %s" EOL " %lu" EOL " %s" EOL, st->symbol, (long unsigned)st->size, st->path); - fprintf (f, " %s" CRLF, st->normalizer_str); + fprintf (f, " %s" EOL, st->normalizer_str); /* Binlog */ if (st->binlog) { if (st->binlog->affinity == AFFINITY_MASTER) { - fprintf (f, " master" CRLF); + fprintf (f, " master" EOL); } else if (st->binlog->affinity == AFFINITY_SLAVE) { - fprintf (f, " slave" CRLF); - fprintf (f, " %s:%d" CRLF, + fprintf (f, " slave" EOL); + fprintf (f, " %s:%d" EOL, inet_ntoa (st->binlog->master_addr), ntohs (st->binlog->master_port)); } - fprintf (f, " %lu" CRLF, (long unsigned)st->binlog->rotate_time); + fprintf (f, " %lu" EOL, (long unsigned)st->binlog->rotate_time); } - fprintf (f, " " CRLF); + fprintf (f, " " EOL); cur_st = g_list_next (cur_st); } - fprintf (f, "" CRLF); + fprintf (f, "" EOL); cur = g_list_next (cur); } /* Print footer comment */ - fprintf (f, "" CRLF); + fprintf (f, "" EOL EOL); return TRUE; } +/* Logging section */ +static gboolean +xml_dump_logging (struct config_file *cfg, FILE *f) +{ + gchar *escaped_value; + + /* Print header comment */ + fprintf (f, "" EOL); + fprintf (f, "" EOL); + + /* Level */ + if (cfg->log_level < G_LOG_LEVEL_WARNING) { + fprintf (f, " error" EOL); + } + else if (cfg->log_level < G_LOG_LEVEL_MESSAGE) { + fprintf (f, " warning" EOL); + } + else if (cfg->log_level < G_LOG_LEVEL_DEBUG) { + fprintf (f, " info" EOL); + } + else { + fprintf (f, " debug" EOL); + } + + /* Other options */ + fprintf (f, " %s" EOL, cfg->log_urls ? "yes" : "no"); + if (cfg->log_buf_size != 0) { + fprintf (f, " %u" EOL, (unsigned)cfg->log_buf_size); + } + if (cfg->debug_ip_map != NULL) { + escaped_value = g_markup_escape_text (cfg->debug_ip_map, -1); + fprintf (f, " %s" EOL, escaped_value); + g_free (escaped_value); + } + + /* Handle type */ + if (cfg->log_type == RSPAMD_LOG_FILE) { + escaped_value = g_markup_escape_text (cfg->log_file, -1); + fprintf (f, " file" EOL, escaped_value); + g_free (escaped_value); + } + else if (cfg->log_type == RSPAMD_LOG_CONSOLE) { + fprintf (f, " console" EOL); + } + else if (cfg->log_type == RSPAMD_LOG_SYSLOG) { + escaped_value = NULL; + switch (cfg->log_facility) { + case LOG_AUTH: + escaped_value = "LOG_AUTH"; + break; + case LOG_CRON: + escaped_value = "LOG_CRON"; + break; + case LOG_DAEMON: + escaped_value = "LOG_DAEMON"; + break; + case LOG_MAIL: + escaped_value = "LOG_MAIL"; + break; + case LOG_USER: + escaped_value = "LOG_USER"; + break; + case LOG_LOCAL0: + escaped_value = "LOG_LOCAL0"; + break; + case LOG_LOCAL1: + escaped_value = "LOG_LOCAL1"; + break; + case LOG_LOCAL2: + escaped_value = "LOG_LOCAL2"; + break; + case LOG_LOCAL3: + escaped_value = "LOG_LOCAL3"; + break; + case LOG_LOCAL4: + escaped_value = "LOG_LOCAL4"; + break; + case LOG_LOCAL5: + escaped_value = "LOG_LOCAL5"; + break; + case LOG_LOCAL6: + escaped_value = "LOG_LOCAL6"; + break; + case LOG_LOCAL7: + escaped_value = "LOG_LOCAL7"; + break; + } + fprintf (f, " syslog" EOL, escaped_value); + } + fprintf (f, "" EOL); + /* Print footer comment */ + fprintf (f, "" EOL EOL); + + return TRUE; +} + + #define CHECK_RES do { if (!res) { fclose (f); return FALSE; } } while (0) gboolean xml_dump_config (struct config_file *cfg, const char *filename) @@ -1702,10 +1838,12 @@ xml_dump_config (struct config_file *cfg, const char *filename) } /* Header */ - fprintf (f, "" CRLF "" CRLF); + fprintf (f, "" EOL "" EOL); /* Now dump all parts of config */ res = xml_dump_main (cfg, f); CHECK_RES; + res = xml_dump_logging (cfg, f); + CHECK_RES; res = xml_dump_variables (cfg, f); CHECK_RES; res = xml_dump_composites (cfg, f); @@ -1717,7 +1855,7 @@ xml_dump_config (struct config_file *cfg, const char *filename) res = xml_dump_classifiers (cfg, f); CHECK_RES; /* Footer */ - fprintf (f, "" CRLF); + fprintf (f, "" EOL); fclose (f); return TRUE; diff --git a/src/cfg_xml.h b/src/cfg_xml.h index d27f147ca..62e011fc6 100644 --- a/src/cfg_xml.h +++ b/src/cfg_xml.h @@ -10,6 +10,7 @@ #define XML_PARAM_MISSING 2 #define XML_EXTRA_ELEMENT 3 #define XML_UNMATCHED_TAG 4 +#define XML_INVALID_ATTR 5 enum xml_read_state { XML_READ_START, diff --git a/src/main.c b/src/main.c index 022773038..442e09de9 100644 --- a/src/main.c +++ b/src/main.c @@ -72,6 +72,7 @@ static gchar *cfg_name; static gchar *rspamd_user; static gchar *rspamd_group; static gchar *rspamd_pidfile; +static gchar *convert_config; static gboolean dump_vars; static gboolean dump_cache; @@ -94,6 +95,7 @@ static GOptionEntry entries[] = { "pid", 'p', 0, G_OPTION_ARG_STRING, &rspamd_pidfile, "Path to pidfile", NULL }, { "dump-vars", 'V', 0, G_OPTION_ARG_NONE, &dump_vars, "Print all rspamd variables and exit", NULL }, { "dump-cache", 'C', 0, G_OPTION_ARG_NONE, &dump_cache, "Dump symbols cache stats and exit", NULL }, + { "convert-config", 'X', 0, G_OPTION_ARG_STRING, &convert_config, "Convert old style of config to xml one", NULL }, { NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL } }; @@ -535,11 +537,95 @@ wait_for_workers (gpointer key, gpointer value, gpointer unused) return TRUE; } +static gboolean +convert_old_config (struct rspamd_main *rspamd) +{ + FILE *f; + + f = fopen (rspamd->cfg->cfg_name, "r"); + if (f == NULL) { + msg_err ("cannot open file: %s", rspamd->cfg->cfg_name); + return EBADF; + } + yyin = f; + + if (yyparse () != 0 || yynerrs > 0) { + msg_err ("cannot parse config file, %d errors", yynerrs); + return EBADF; + } + + /* Strictly set temp dir */ + if (!rspamd->cfg->temp_dir) { + msg_warn ("tempdir is not set, trying to use $TMPDIR"); + rspamd->cfg->temp_dir = memory_pool_strdup (rspamd->cfg->cfg_pool, getenv ("TMPDIR")); + + if (!rspamd->cfg->temp_dir) { + msg_warn ("$TMPDIR is empty too, using /tmp as default"); + rspamd->cfg->temp_dir = memory_pool_strdup (rspamd->cfg->cfg_pool, "/tmp"); + } + } + + + fclose (f); + /* Dump it to xml */ + if (get_config_checksum (rspamd->cfg)) { + if (xml_dump_config (rspamd->cfg, convert_config)) { + rspamd->cfg->cfg_name = convert_config; + return TRUE; + } + } + + return FALSE; +} + +static gboolean +load_rspamd_config (struct rspamd_main *rspamd) +{ + GList *l; + struct filter *filt; + struct module_ctx *cur_module = NULL; + + if (! read_xml_config (rspamd->cfg, rspamd->cfg->cfg_name)) { + return FALSE; + } + + /* Strictly set temp dir */ + if (!rspamd->cfg->temp_dir) { + msg_warn ("tempdir is not set, trying to use $TMPDIR"); + rspamd->cfg->temp_dir = memory_pool_strdup (rspamd->cfg->cfg_pool, getenv ("TMPDIR")); + + if (!rspamd->cfg->temp_dir) { + msg_warn ("$TMPDIR is empty too, using /tmp as default"); + rspamd->cfg->temp_dir = memory_pool_strdup (rspamd->cfg->cfg_pool, "/tmp"); + } + } + + /* Do post-load actions */ + post_load_config (rspamd->cfg); + /* Init counters */ + counters = rspamd_hash_new_shared (rspamd->server_pool, g_str_hash, g_str_equal, 64); + + /* Init C modules */ + l = g_list_first (rspamd->cfg->filters); + + while (l) { + filt = l->data; + if (filt->module) { + cur_module = memory_pool_alloc (rspamd->cfg->cfg_pool, sizeof (struct module_ctx)); + if (filt->module->module_init_func (cfg, &cur_module) == 0) { + g_hash_table_insert (cfg->c_modules, (gpointer) filt->module->name, cur_module); + } + } + l = g_list_next (l); + } + + return TRUE; +} + int main (int argc, char **argv, char **env) { struct rspamd_main *rspamd; - struct module_ctx *cur_module = NULL; int res = 0, i; struct sigaction signals; struct rspamd_worker *cur; @@ -547,7 +633,6 @@ main (int argc, char **argv, char **env) struct metric *metric; struct cache_item *item; struct filter *filt; - FILE *f; pid_t wrk; GList *l; #ifndef WITHOUT_PERL @@ -610,41 +695,15 @@ main (int argc, char **argv, char **env) init_title (argc, argv, environ); #endif init_lua (cfg); - - f = fopen (rspamd->cfg->cfg_name, "r"); - if (f == NULL) { - msg_err ("cannot open file: %s", rspamd->cfg->cfg_name); - return EBADF; - } - yyin = f; - - if (yyparse () != 0 || yynerrs > 0) { - msg_err ("cannot parse config file, %d errors", yynerrs); - return EBADF; - } - - fclose (f); - /* Dump it to xml */ - if (get_config_checksum (rspamd->cfg)) { - xml_dump_config (rspamd->cfg, "/tmp/rspamd.xml"); + + if (convert_config != NULL) { + if (! convert_old_config (rspamd)) { + exit (EXIT_FAILURE); + } } - /* Do post-load actions */ - post_load_config (rspamd->cfg); - /* Init counters */ - counters = rspamd_hash_new_shared (rspamd->server_pool, g_str_hash, g_str_equal, 64); - /* Init C modules */ - l = g_list_first (rspamd->cfg->filters); - - while (l) { - filt = l->data; - if (filt->module) { - cur_module = memory_pool_alloc (rspamd->cfg->cfg_pool, sizeof (struct module_ctx)); - if (filt->module->module_init_func (cfg, &cur_module) == 0) { - g_hash_table_insert (cfg->c_modules, (gpointer) filt->module->name, cur_module); - } - } - l = g_list_next (l); + if (! load_rspamd_config (rspamd)) { + exit (EXIT_FAILURE); } if (cfg->config_test || dump_vars || dump_cache) { @@ -704,17 +763,6 @@ main (int argc, char **argv, char **env) msg_info ("rspamd " RVERSION " is starting"); rspamd->cfg->cfg_name = memory_pool_strdup (rspamd->cfg->cfg_pool, rspamd->cfg->cfg_name); - /* Strictly set temp dir */ - if (!rspamd->cfg->temp_dir) { - msg_warn ("tempdir is not set, trying to use $TMPDIR"); - rspamd->cfg->temp_dir = memory_pool_strdup (rspamd->cfg->cfg_pool, getenv ("TMPDIR")); - - if (!rspamd->cfg->temp_dir) { - msg_warn ("$TMPDIR is empty too, using /tmp as default"); - rspamd->cfg->temp_dir = memory_pool_strdup (rspamd->cfg->cfg_pool, "/tmp"); - } - } - if (!rspamd->cfg->no_fork && daemon (0, 0) == -1) { fprintf (stderr, "Cannot daemonize\n"); exit (-errno); -- 2.39.5