From f267ddb5a7f2f2556b7a0c0751161f2f97bcae67 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Thu, 24 Sep 2015 17:09:35 +0100 Subject: [PATCH] Add rspamadm routine. --- src/CMakeLists.txt | 1 + src/rspamadm/CMakeLists.txt | 13 ++ src/rspamadm/commands.c | 52 +++++++ src/rspamadm/rspamadm.c | 290 ++++++++++++++++++++++++++++++++++++ src/rspamadm/rspamadm.h | 51 +++++++ 5 files changed, 407 insertions(+) create mode 100644 src/rspamadm/CMakeLists.txt create mode 100644 src/rspamadm/commands.c create mode 100644 src/rspamadm/rspamadm.c create mode 100644 src/rspamadm/rspamadm.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f86c45b40..3d3d887e4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -70,6 +70,7 @@ ADD_SUBDIRECTORY(libserver) ADD_SUBDIRECTORY(libmime) ADD_SUBDIRECTORY(libstat) ADD_SUBDIRECTORY(client) +ADD_SUBDIRECTORY(rspamadm) SET(RSPAMDSRC controller.c fuzzy_storage.c diff --git a/src/rspamadm/CMakeLists.txt b/src/rspamadm/CMakeLists.txt new file mode 100644 index 000000000..ba9814f8d --- /dev/null +++ b/src/rspamadm/CMakeLists.txt @@ -0,0 +1,13 @@ +SET(RSPAMADMSRC rspamadm.c commands.c) + +ADD_EXECUTABLE(rspamadm ${RSPAMADMSRC}) +TARGET_LINK_LIBRARIES(rspamadm rspamd-server) +TARGET_LINK_LIBRARIES(rspamadm ${RSPAMD_REQUIRED_LIBRARIES}) +TARGET_LINK_LIBRARIES(rspamadm stemmer) +TARGET_LINK_LIBRARIES(rspamadm rspamd-actrie) + +IF (NOT DEBIAN_BUILD) + SET_TARGET_PROPERTIES(rspamadm PROPERTIES VERSION ${RSPAMD_VERSION}) +ENDIF (NOT DEBIAN_BUILD) + +INSTALL(TARGETS rspamadm RUNTIME DESTINATION bin) \ No newline at end of file diff --git a/src/rspamadm/commands.c b/src/rspamadm/commands.c new file mode 100644 index 000000000..26f6b02b8 --- /dev/null +++ b/src/rspamadm/commands.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2015, Vsevolod Stakhov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "rspamadm.h" + +const struct rspamadm_command *commands[] = { + &help_command, + NULL +}; + + +const struct rspamadm_command * +rspamadm_search_command (const gchar *name) +{ + const struct rspamadm_command *ret = NULL; + guint i; + + if (name == NULL) { + name = "help"; + } + + for (i = 0; i < G_N_ELEMENTS (commands); i ++) { + if (commands[i] != NULL) { + if (strcmp (name, commands[i]->name) == 0) { + ret = commands[i]; + break; + } + } + } + + return ret; +} \ No newline at end of file diff --git a/src/rspamadm/rspamadm.c b/src/rspamadm/rspamadm.c new file mode 100644 index 000000000..0a6ecc7d7 --- /dev/null +++ b/src/rspamadm/rspamadm.c @@ -0,0 +1,290 @@ +/* + * Copyright (c) 2015, Vsevolod Stakhov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "rspamadm.h" +#include "rspamd.h" +#include "ottery.h" + +static gboolean verbose = FALSE; +static gboolean list_commands = FALSE; +static gboolean show_help = FALSE; +static gboolean show_version = FALSE; +GHashTable *ucl_vars = NULL; + +static void rspamadm_help (gint argc, gchar **argv); +static const char* rspamadm_help_help (gboolean full_help); + +struct rspamadm_command help_command = { + .name = "help", + .flags = RSPAMADM_FLAG_NOHELP, + .help = rspamadm_help_help, + .run = rspamadm_help +}; + +static gboolean rspamadm_parse_ucl_var (const gchar *option_name, + const gchar *value, gpointer data, + GError **error); + +static GOptionEntry entries[] = { + {"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, + "Enable verbose logging", NULL}, + {"list-commands", 'l', 0, G_OPTION_ARG_NONE, &list_commands, + "List available commands", NULL}, + {"var", 0, 0, G_OPTION_ARG_CALLBACK, rspamadm_parse_ucl_var, + "Redefine UCL variable", NULL}, + {"help", 'h', 0, G_OPTION_ARG_NONE, &show_help, + "Show help", NULL}, + {"version", 'h', 0, G_OPTION_ARG_NONE, &show_version, + "Show version", NULL}, + {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL} +}; + +GQuark +rspamadm_error (void) +{ + return g_quark_from_static_string ("rspamadm"); +} + +static void +rspamadm_version (void) +{ + printf ("Rspamadm %s\n", RVERSION); + exit (EXIT_SUCCESS); +} + +static void +rspamadm_usage (GOptionContext *context) +{ + gchar *help_str; + + help_str = g_option_context_get_help (context, TRUE, NULL); + printf ("%s", help_str); + + exit (EXIT_SUCCESS); +} + +static void +rspamadm_commands (GOptionContext *context) +{ + gchar *help_str; + const struct rspamadm_command **cmd; + + printf ("Rspamadm %s\n", RVERSION); + printf ("Usage: rspamadm [global_options] command [command_options]\n"); + printf ("\nAvailable commands:\n"); + + cmd = commands; + + while (*cmd) { + printf (" %-18s %-60s\n", (*cmd)->name, (*cmd)->help (FALSE)); + cmd ++; + } + + exit (EXIT_SUCCESS); +} + +static const char * +rspamadm_help_help (gboolean full_help) +{ + const char *help_str; + + if (full_help) { + help_str = "Shows help for a specified command\n" + "Usage: rspamadm help "; + } + else { + help_str = "Shows help for a specified command"; + } + + return help_str; +} + +static void +rspamadm_help (gint argc, gchar **argv) +{ + const gchar *cmd_name; + const struct rspamadm_command *cmd; + + if (argc == 0) { + cmd_name = "help"; + } + else { + cmd_name = argv[1]; + } + + cmd = rspamadm_search_command (cmd_name); + + if (cmd == NULL) { + fprintf (stderr, "Invalid command name: %s\n", cmd_name); + exit (EXIT_FAILURE); + } + + printf ("%s\n", cmd->help (TRUE)); +} + +static gboolean +rspamadm_parse_ucl_var (const gchar *option_name, + const gchar *value, gpointer data, + GError **error) +{ + gchar *k, *v, *t; + + t = strchr (value, '='); + + if (t != NULL) { + k = g_strdup (value); + t = k + (t - value); + v = g_strdup (t + 1); + *t = '\0'; + + g_hash_table_insert (ucl_vars, k, v); + } + else { + g_set_error (error, rspamadm_error (), EINVAL, + "Bad variable format: %s", value); + return FALSE; + } + + return TRUE; +} + +gint +main (gint argc, gchar **argv, gchar **env) +{ + GError *error = NULL; + GOptionContext *context; + GOptionGroup *og; + struct rspamd_config *cfg; + struct rspamd_main *rspamd_main; + GQuark process_quark; + gchar **nargv; + const gchar *cmd_name; + const struct rspamadm_command *cmd; + gint i, nargc; + + ucl_vars = g_hash_table_new_full (rspamd_strcase_hash, + rspamd_strcase_equal, g_free, g_free); + ottery_init (NULL); + process_quark = g_quark_from_static_string ("rspamadm"); + cfg = g_slice_alloc0 (sizeof (*cfg)); + rspamd_main = g_slice_alloc0 (sizeof (*rspamd_main)); + rspamd_init_libs (); + rspamd_init_cfg (cfg, TRUE); + rspamd_main->cfg = cfg; + rspamd_main->pid = getpid (); + rspamd_main->type = process_quark; + rspamd_main->server_pool = rspamd_mempool_new (rspamd_mempool_suggest_size (), + "rspamadm"); + + /* Setup logger */ + if (verbose) { + cfg->log_level = G_LOG_LEVEL_DEBUG; + } + else { + cfg->log_level = G_LOG_LEVEL_INFO; + } + + cfg->log_type = RSPAMD_LOG_CONSOLE; + rspamd_set_logger (cfg, process_quark, rspamd_main); + (void) rspamd_log_open (rspamd_main->logger); + g_log_set_default_handler (rspamd_glib_log_function, rspamd_main->logger); + g_set_printerr_handler (rspamd_glib_printerr_function); + + gperf_profiler_init (cfg, "rspamadm"); + setproctitle ("rspamdadm"); + + /* Now read options and store everything till the first non-dash argument */ + nargv = g_slice_alloc0 (sizeof (gchar *) * (argc + 1)); + nargv[0] = g_strdup (argv[0]); + + for (i = 1, nargc = 1; i < argc; i ++) { + if (argv[i] && argv[i][0] == '-') { + /* Copy to nargv */ + nargv[nargc] = g_strdup (argv[i]); + nargc ++; + } + else { + break; + } + } + + context = g_option_context_new ("command - rspamd administration utility"); + og = g_option_group_new ("global", "global options", "global options", + NULL, NULL); + g_option_context_set_help_enabled (context, FALSE); + g_option_group_add_entries (og, entries); + g_option_context_set_summary (context, + "Summary:\n Rspamd administration utility version " + RVERSION + "\n Release id: " + RID); + g_option_context_set_main_group (context, og); + + if (!g_option_context_parse (context, &nargc, &nargv, &error)) { + fprintf (stderr, "option parsing failed: %s\n", error->message); + g_error_free (error); + exit (1); + } + + if (show_version) { + rspamadm_version (); + } + if (show_help) { + rspamadm_usage (context); + } + if (list_commands) { + rspamadm_commands (context); + } + + cmd_name = argv[nargc]; + + if (cmd_name == NULL) { + cmd_name = "help"; + } + + cmd = rspamadm_search_command (cmd_name); + + if (cmd == NULL) { + fprintf (stderr, "Invalid command name: %s\n", cmd_name); + exit (EXIT_FAILURE); + } + + if (nargc < argc) { + cmd->run (argc - nargc - 1, &argv[nargc]); + } + else { + cmd->run (0, NULL); + } + + rspamd_log_close (rspamd_main->logger); + rspamd_config_free (rspamd_main->cfg); + g_free (rspamd_main->cfg); + g_free (rspamd_main); + + g_mime_shutdown (); + + return 0; +} + diff --git a/src/rspamadm/rspamadm.h b/src/rspamadm/rspamadm.h new file mode 100644 index 000000000..e7a90b5bb --- /dev/null +++ b/src/rspamadm/rspamadm.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2015, Vsevolod Stakhov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef RSPAMD_RSPAMDADM_H +#define RSPAMD_RSPAMDADM_H + +#include "config.h" + +extern GHashTable *ucl_vars; + +GQuark rspamadm_error (void); + +typedef const gchar* (*rspamadm_help_func) (gboolean full_help); +typedef void (*rspamadm_run_func) (gint argc, gchar **argv); + +#define RSPAMADM_FLAG_NOHELP (1 << 0) + +struct rspamadm_command { + const gchar *name; + guint flags; + rspamadm_help_func help; + rspamadm_run_func run; +}; + +extern const struct rspamadm_command *commands[]; +extern struct rspamadm_command help_command; + +const struct rspamadm_command *rspamadm_search_command (const gchar *name); + +#endif -- 2.39.5