src/ConfigParser.c \
src/QServer.c \
src/modules.c \
+ src/module_commands.c \
src/memoryDebug.c
neonserv_LDADD = $(MYSQL_LIBS) $(WINSOCK_LIBS) -ldl
#include "QServer.h"
#include "version.h"
#include "modules.h"
+#include "module_commands.h"
time_t start_time;
static int running, hard_restart;
init_ModeNode();
init_bind();
init_modcmd();
+ register_module_commands();
init_handleinfohandler();
init_tools();
loadModules();
--- /dev/null
+/* 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 <http://www.gnu.org/licenses/>.
+ */
+#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"));
+}
--- /dev/null
+/* 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 <http://www.gnu.org/licenses/>.
+ */
+#ifndef _module_commands_h
+#define _module_commands_h
+#ifndef DND_FUNCTIONS
+
+void register_module_commands();
+
+#endif
+#endif
/* 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;
}
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);
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;
}
#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)) {
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) {
#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();
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