From 92aff95471b2d258d9fc4852d0b14ab9855cd447 Mon Sep 17 00:00:00 2001 From: pk910 Date: Sun, 12 Feb 2012 19:30:52 +0100 Subject: [PATCH] added module management commands --- Makefile.am | 1 + src/main.c | 2 + src/module_commands.c | 86 +++++++++++++++++++++++++++++++++++++++++++ src/module_commands.h | 24 ++++++++++++ src/modules.c | 64 ++++++++++++++++++++++---------- src/modules.h | 25 ++++++++++++- 6 files changed, 181 insertions(+), 21 deletions(-) create mode 100644 src/module_commands.c create mode 100644 src/module_commands.h diff --git a/Makefile.am b/Makefile.am index f63733a..9a64dcd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -163,6 +163,7 @@ neonserv_SOURCES = src/version.c \ src/ConfigParser.c \ src/QServer.c \ src/modules.c \ + src/module_commands.c \ src/memoryDebug.c neonserv_LDADD = $(MYSQL_LIBS) $(WINSOCK_LIBS) -ldl diff --git a/src/main.c b/src/main.c index 74fd93c..8262b4b 100644 --- a/src/main.c +++ b/src/main.c @@ -39,6 +39,7 @@ #include "QServer.h" #include "version.h" #include "modules.h" +#include "module_commands.h" time_t start_time; static int running, hard_restart; @@ -280,6 +281,7 @@ main: init_ModeNode(); init_bind(); init_modcmd(); + register_module_commands(); init_handleinfohandler(); init_tools(); loadModules(); diff --git a/src/module_commands.c b/src/module_commands.c new file mode 100644 index 0000000..2927de2 --- /dev/null +++ b/src/module_commands.c @@ -0,0 +1,86 @@ +/* module_commands.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "modcmd.h" +#include "IRCParser.h" +#include "modules.h" +#include "tools.h" +#include "lang.h" + +static const struct default_language_entry msgtab[] = { + {"MODULE_LOADED", "Module %s loaded."}, /* {ARGS: "NeonServ"} */ + {"MODULE_UNLOADED", "Module %s unloaded."}, /* {ARGS: "NeonServ"} */ + {"MODULE_RELOADED", "Module %s reloaded."}, /* {ARGS: "NeonServ"} */ + {"MODULE_ERROR", "An error occured when performing this module operation. View error log for more information."}, + {"MODULE_LIST", "Loaded Modules: %s"}, + {NULL, NULL} +}; + +static CMD_BIND(module_cmd_load); +static CMD_BIND(module_cmd_unload); +static CMD_BIND(module_cmd_reload); +static CMD_BIND(module_cmd_modules); + +void register_module_commands() { + //Module Commands + #define OPER_COMMAND(NAME,FUNCTION,PARAMCOUNT,GACCESS,FLAGS) register_command(0, NAME, 0, FUNCTION, PARAMCOUNT, NULL, GACCESS, FLAGS) + // NAME FUNCTION PARAMS ACCS FLAGS + OPER_COMMAND("loadmod", module_cmd_load, 1, 1000, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); + OPER_COMMAND("unloadmod", module_cmd_unload, 1, 1000, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); + OPER_COMMAND("reloadmod", module_cmd_reload, 1, 1000, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); + OPER_COMMAND("modules", module_cmd_modules, 0, 1000, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); + #undef OPER_COMMAND + + register_default_language_table(msgtab); +} + +static CMD_BIND(module_cmd_load) { + if(ext_load_module(argv[0])) + reply(getTextBot(), user, "MODULE_LOADED", argv[0]); + else + reply(getTextBot(), user, "MODULE_ERROR"); +} + +static CMD_BIND(module_cmd_unload) { + if(ext_unload_module(argv[0])) + reply(getTextBot(), user, "MODULE_UNLOADED", argv[0]); + else + reply(getTextBot(), user, "MODULE_ERROR"); +} + +static CMD_BIND(module_cmd_reload) { + if(ext_reload_module(argv[0])) + reply(getTextBot(), user, "MODULE_RELOADED", argv[0]); + else + reply(getTextBot(), user, "MODULE_ERROR"); +} + +static CMD_BIND(module_cmd_modules) { + char modules[MAXLEN]; + int modpos = 0; + int modcount = 0; + struct ModuleInfo *modinfo; + for(modinfo = ext_get_modules(NULL); modinfo; modinfo = ext_get_modules(modinfo)) { + if(modpos + strlen(modinfo->name) > 450) { + reply(getTextBot(), user, "MODULE_LIST", modules); + modpos = 0; + } + modcount++; + modpos += sprintf(modules + modpos, (modpos ? ", %s" : "%s"), modinfo->name); + } + if(!modcount || modpos) + reply(getTextBot(), user, "MODULE_LIST", (modpos ? modules : "none")); +} diff --git a/src/module_commands.h b/src/module_commands.h new file mode 100644 index 0000000..bd46c47 --- /dev/null +++ b/src/module_commands.h @@ -0,0 +1,24 @@ +/* module_commands.h - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef _module_commands_h +#define _module_commands_h +#ifndef DND_FUNCTIONS + +void register_module_commands(); + +#endif +#endif diff --git a/src/modules.c b/src/modules.c index dc3f598..53ff4af 100644 --- a/src/modules.c +++ b/src/modules.c @@ -248,23 +248,6 @@ void *global_functions[] = { /* 188 */ (Function) get_patchlevel }; -#define MODINFO_STATE_STARTED 0x01 - -struct ModuleInfo { - char *name; - int module_id; - #ifndef WIN32 - void *module; - #else - HMODULE module; - #endif - int state; - void *startfunc; - void *loopfunc; - void *stopfunc; - struct ModuleInfo *next; -}; - static int module_id_counter = 1; static struct ModuleInfo *modules = NULL; @@ -281,6 +264,10 @@ void loadModules() { } int loadModule(char *name) { + struct ModuleInfo *modinfo; + for(modinfo = modules; modinfo; modinfo = modinfo->next) { + if(!stricmp(modinfo->name, name)) return 0; + } char fname[256]; #ifndef WIN32 sprintf(fname, "%s.so", name); @@ -327,7 +314,7 @@ int loadModule(char *name) { putlog(LOGLEVEL_ERROR, "Error loading module '%s': module reported error (errid: %d)\n", name, errid); return 0; } - struct ModuleInfo *modinfo = malloc(sizeof(*modinfo)); + modinfo = malloc(sizeof(*modinfo)); if(!modinfo) { unregister_module_hooks(module_id); return 0; @@ -353,7 +340,40 @@ static void closemodule(HMODULE module) { } #endif -int reload_module(char *name) { +int ext_load_module(char *name) { + if(!loadModule(name)) return 0; + struct ModuleInfo *modinfo; + for(modinfo = modules; modinfo; modinfo = modinfo->next) { + if(!(modinfo->state & MODINFO_STATE_STARTED)) { + modinfo->state |= MODINFO_STATE_STARTED; + ((void (*)(int)) modinfo->startfunc)(MODSTATE_STARTSTOP); + } else + ((void (*)(int)) modinfo->startfunc)(MODSTATE_REBIND); + } + return 1; +} + +int ext_unload_module(char *name) { + struct ModuleInfo *old_modinfo, *old_prev = NULL; + for(old_modinfo = modules; old_modinfo; old_modinfo = old_modinfo->next) { + if(!stricmp(old_modinfo->name, name)) { + if(old_prev) + old_prev->next = old_modinfo->next; + else + modules = old_modinfo->next; + unregister_module_hooks(old_modinfo->module_id); + ((void (*)(int)) old_modinfo->stopfunc)(MODSTATE_STARTSTOP); + closemodule(old_modinfo->module); + free(old_modinfo->name); + free(old_modinfo); + return 1; + } else + old_prev = old_modinfo; + } + return 0; +} + +int ext_reload_module(char *name) { struct ModuleInfo *old_modinfo, *old_prev = NULL; for(old_modinfo = modules; old_modinfo; old_modinfo = old_modinfo->next) { if(!stricmp(old_modinfo->name, name)) { @@ -375,13 +395,17 @@ int reload_module(char *name) { for(modinfo = modules; modinfo; modinfo = modinfo->next) { if(!(modinfo->state & MODINFO_STATE_STARTED)) { modinfo->state |= MODINFO_STATE_STARTED; - ((void (*)(int)) modinfo->startfunc)(MODSTATE_STARTSTOP); + ((void (*)(int)) modinfo->startfunc)(MODSTATE_RELOAD); } else ((void (*)(int)) modinfo->startfunc)(MODSTATE_REBIND); } return 1; } +struct ModuleInfo *ext_get_modules(struct ModuleInfo *last) { + return (last ? last->next : modules); +} + void start_modules() { struct ModuleInfo *modinfo; for(modinfo = modules; modinfo; modinfo = modinfo->next) { diff --git a/src/modules.h b/src/modules.h index 8e326ea..e729c2e 100644 --- a/src/modules.h +++ b/src/modules.h @@ -17,6 +17,24 @@ #ifndef _modules_h #define _modules_h +#define MODINFO_STATE_STARTED 0x01 + +struct ModuleInfo { + char *name; + int module_id; + #ifndef WIN32 + void *module; + #else + HMODULE module; + #endif + int state; + void *startfunc; + void *loopfunc; + void *stopfunc; + struct ModuleInfo *next; +}; + +#ifndef DND_FUNCTIONS void loadModules(); int loadModule(char *name); void start_modules(); @@ -24,4 +42,9 @@ void loop_modules(); void stop_modules(); int module_loaded(int module_id); -#endif \ No newline at end of file +int ext_load_module(char *name); +int ext_unload_module(char *name); +int ext_reload_module(char *name); +struct ModuleInfo *ext_get_modules(struct ModuleInfo *last); +#endif +#endif -- 2.20.1