summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
authorHaru <haru@dotalux.com>2014-11-09 02:07:09 +0100
committerHaru <haru@dotalux.com>2015-01-18 21:35:36 +0100
commitce08d6238d902590dbfb650f889a8ab8887356bf (patch)
tree218266957f961e71a51a307b432b02ed9647243a /src/common
parent0285ddf7cee2f6569a513fe6118c43f99fd71279 (diff)
downloadhercules-ce08d6238d902590dbfb650f889a8ab8887356bf.tar.gz
hercules-ce08d6238d902590dbfb650f889a8ab8887356bf.tar.bz2
hercules-ce08d6238d902590dbfb650f889a8ab8887356bf.tar.xz
hercules-ce08d6238d902590dbfb650f889a8ab8887356bf.zip
Command line arguments handling overhaul
- login_server, char_server, map_server as well as the tools (mapcache) now have a common command line arguments handling mechanism. - All of them now accept `--help` (`-h`), `--version` (`-v`) and `--load-plugin`. - login_server now accepts `--login-config` and `--lan-config` instead of relying on positional arguments to override those files. The old syntax will no longer work, please update your custom startup scripts. - char_server now accepts `--char-config`, `--inter-config`, `--lan-config` instead of relying on positional arguments. The old syntax will no longer work, please update your custom startup scripts. - mapcache now accepts `--grf-list`, `--map-list`, `--map-cache`, `--rebuild` in place of, respectively, `-grf`, `-list`, `-cache`, `-rebuild`. - A new macro `CMDLINEARG()` is provided, to help defining new command line argument handlers (i.e. in plugins). the `addArg()` call is still required, but its syntax has changed. The `help` argument is now of type `const char *` rather than a function pointer, and it is supposed to contain the message to show in the `--help` screen. Pass `NULL` if no help message is desired. Signed-off-by: Haru <haru@dotalux.com>
Diffstat (limited to 'src/common')
-rw-r--r--src/common/HPM.c104
-rw-r--r--src/common/HPM.h20
-rw-r--r--src/common/HPMi.h4
-rw-r--r--src/common/core.c207
-rw-r--r--src/common/core.h44
-rw-r--r--src/common/malloc.c36
-rw-r--r--src/common/malloc.h7
7 files changed, 331 insertions, 91 deletions
diff --git a/src/common/HPM.c b/src/common/HPM.c
index 6d9a2cb6b..10208cdad 100644
--- a/src/common/HPM.c
+++ b/src/common/HPM.c
@@ -293,7 +293,20 @@ void hplugin_unload(struct hplugin* plugin) {
}
}
-void hplugins_config_read(const char * const *extra_plugins, int extra_plugins_count) {
+/**
+ * Adds a plugin requested from the command line to the auto-load list.
+ */
+CMDLINEARG(loadplugin)
+{
+ RECREATE(HPM->cmdline_plugins, char *, ++HPM->cmdline_plugins_count);
+ HPM->cmdline_plugins[HPM->cmdline_plugins_count-1] = aStrdup(params);
+ return true;
+}
+
+/**
+ * Reads the plugin configuration and loads the plugins as necessary.
+ */
+void hplugins_config_read(void) {
config_t plugins_conf;
config_setting_t *plist = NULL;
const char *config_filename = "conf/plugins.conf"; // FIXME hardcoded name
@@ -313,9 +326,9 @@ void hplugins_config_read(const char * const *extra_plugins, int extra_plugins_c
HPM->symbol_defaults_sub();
plist = libconfig->lookup(&plugins_conf, "plugins_list");
- for (i = 0; i < extra_plugins_count; i++) {
+ for (i = 0; i < HPM->cmdline_plugins_count; i++) {
config_setting_t *entry = libconfig->setting_add(plist, NULL, CONFIG_TYPE_STRING);
- config_setting_set_string(entry, extra_plugins[i]);
+ config_setting_set_string(entry, HPM->cmdline_plugins[i]);
}
if (plist != NULL) {
@@ -562,6 +575,9 @@ unsigned char hplugins_parse_packets(int fd, enum HPluginPacketHookingPoints poi
char *hplugins_id2name (unsigned int pid) {
unsigned int i;
+ if (pid == HPM_PID_CORE)
+ return "core";
+
for( i = 0; i < HPM->plugin_count; i++ ) {
if( HPM->plugins[i]->idx == pid )
return HPM->plugins[i]->info->name;
@@ -624,50 +640,32 @@ void HPM_HookStop (const char *func, unsigned int pID) {
bool HPM_HookStopped (void) {
return HPM->force_return;
}
-/* command-line args */
-bool hpm_parse_arg(const char *arg, int *index, char *argv[], bool param) {
- struct HPMArgData *data;
-
- if( (data = strdb_get(HPM->arg_db,arg)) ) {
- data->func((data->has_param && param)?argv[(*index)+1]:NULL);
- if( data->has_param && param ) *index += 1;
- return true;
- }
-
- return false;
-}
-void hpm_arg_help(void) {
- DBIterator *iter = db_iterator(HPM->arg_db);
- struct HPMArgData *data = NULL;
-
- for( data = dbi_first(iter); dbi_exists(iter); data = dbi_next(iter) ) {
- if( data->help != NULL )
- data->help();
- else
- ShowInfo(" %s (%s)\t\t<no description provided>\n",data->name,HPM->pid2name(data->pluginID));
- }
-
- dbi_destroy(iter);
-}
-bool hpm_add_arg(unsigned int pluginID, char *name, bool has_param, void (*func) (char *param),void (*help) (void)) {
- struct HPMArgData *data = NULL;
+/**
+ * Adds a plugin-defined command-line argument.
+ *
+ * @param pluginID the current plugin's ID.
+ * @param name the command line argument's name, including the leading '--'.
+ * @param has_param whether the command line argument expects to be followed by a value.
+ * @param func the triggered function.
+ * @param help the help string to be displayed by '--help', if any.
+ * @return the success status.
+ */
+bool hpm_add_arg(unsigned int pluginID, char *name, bool has_param, CmdlineExecFunc func, const char *help) {
+ int i;
- if( strdb_exists(HPM->arg_db, name) ) {
- ShowError("HPM:add_arg:%s duplicate! (from %s)\n",name,HPM->pid2name(pluginID));
+ if (!name || strlen(name) < 3 || name[0] != '-' || name[1] != '-') {
+ ShowError("HPM:add_arg:%s invalid argument name: arguments must begin with '--' (from %s)\n", name, HPM->pid2name(pluginID));
return false;
}
- CREATE(data, struct HPMArgData, 1);
+ ARR_FIND(0, cmdline->args_data_count, i, strcmp(cmdline->args_data[i].name, name) == 0);
- data->pluginID = pluginID;
- data->name = aStrdup(name);
- data->func = func;
- data->help = help;
- data->has_param = has_param;
+ if (i < cmdline->args_data_count) {
+ ShowError("HPM:add_arg:%s duplicate! (from %s)\n",name,HPM->pid2name(pluginID));
+ return false;
+ }
- strdb_put(HPM->arg_db, data->name, data);
-
- return true;
+ return cmdline->arg_add(pluginID, name, '\0', func, help, has_param ? CMDLINE_OPT_PARAM : CMDLINE_OPT_NORMAL);
}
bool hplugins_addconf(unsigned int pluginID, enum HPluginConfType type, char *name, void (*func) (const char *val)) {
struct HPConfListenStorage *conf;
@@ -833,8 +831,6 @@ void hpm_init(void) {
HPM->packetsc[i] = 0;
}
- HPM->arg_db = strdb_alloc(DB_OPT_RELEASE_DATA, 0);
-
HPM->symbol_defaults();
#ifdef CONSOLE_INPUT
@@ -855,13 +851,6 @@ void hpm_memdown(void) {
free(HPM->fnames);
}
}
-int hpm_arg_db_clear_sub(DBKey key, DBData *data, va_list args) {
- struct HPMArgData *a = DB->data2ptr(data);
-
- aFree(a->name);
-
- return 0;
-}
void hpm_final(void) {
unsigned int i;
@@ -892,8 +881,13 @@ void hpm_final(void) {
if( HPM->confsc[i] )
aFree(HPM->confs[i]);
}
-
- HPM->arg_db->destroy(HPM->arg_db,HPM->arg_db_clear_sub);
+ if (HPM->cmdline_plugins) {
+ for (i = 0; i < HPM->cmdline_plugins_count; i++)
+ aFree(HPM->cmdline_plugins[i]);
+ aFree(HPM->cmdline_plugins);
+ HPM->cmdline_plugins = NULL;
+ HPM->cmdline_plugins_count = 0;
+ }
/* HPM->fnames is cleared after the memory manager goes down */
iMalloc->post_shutdown = hpm_memdown;
@@ -919,7 +913,8 @@ void hpm_defaults(void) {
HPM->confs[i] = NULL;
HPM->confsc[i] = 0;
}
- HPM->arg_db = NULL;
+ HPM->cmdline_plugins = NULL;
+ HPM->cmdline_plugins_count = 0;
/* */
HPM->init = hpm_init;
HPM->final = hpm_final;
@@ -940,9 +935,6 @@ void hpm_defaults(void) {
HPM->parse_packets = hplugins_parse_packets;
HPM->load_sub = NULL;
HPM->addhook_sub = NULL;
- HPM->arg_db_clear_sub = hpm_arg_db_clear_sub;
- HPM->parse_arg = hpm_parse_arg;
- HPM->arg_help = hpm_arg_help;
HPM->grabHPData = hplugins_grabHPData;
HPM->grabHPDataSub = NULL;
HPM->parseConf = hplugins_parse_conf;
diff --git a/src/common/HPM.h b/src/common/HPM.h
index 973bc6cca..e99b0f2ae 100644
--- a/src/common/HPM.h
+++ b/src/common/HPM.h
@@ -82,14 +82,6 @@ struct HPMFileNameCache {
char *name;
};
-struct HPMArgData {
- unsigned int pluginID;
- char *name;/* e.g. "--my-arg","-v","--whatever" */
- void (*help) (void);/* to display when --help is used */
- void (*func) (char *param);/* NULL when no param is available */
- bool has_param;/* because of the weird "--arg<space>param" instead of the "--arg=param" */
-};
-
struct HPDataOperationStorage {
void **HPDataSRCPtr;
unsigned int *hdatac;
@@ -123,8 +115,9 @@ struct HPM_interface {
/* config listen */
struct HPConfListenStorage *confs[HPCT_MAX];
unsigned int confsc[HPCT_MAX];
- /* --command-line */
- DBMap *arg_db;
+ /** Plugins requested through the command line */
+ char **cmdline_plugins;
+ int cmdline_plugins_count;
/* funcs */
void (*init) (void);
void (*final) (void);
@@ -137,16 +130,13 @@ struct HPM_interface {
void *(*import_symbol) (char *name, unsigned int pID);
void (*share) (void *, char *);
void (*symbol_defaults) (void);
- void (*config_read) (const char * const *extra_plugins, int extra_plugins_count);
+ void (*config_read) (void);
bool (*populate) (struct hplugin *plugin,const char *filename);
void (*symbol_defaults_sub) (void);//TODO drop
char *(*pid2name) (unsigned int pid);
unsigned char (*parse_packets) (int fd, enum HPluginPacketHookingPoints point);
void (*load_sub) (struct hplugin *plugin);
bool (*addhook_sub) (enum HPluginHookType type, const char *target, void *hook, unsigned int pID);
- bool (*parse_arg) (const char *arg, int* index, char *argv[], bool param);
- void (*arg_help) (void);
- int (*arg_db_clear_sub) (DBKey key, DBData *data, va_list args);
void (*grabHPData) (struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr);
/* for server-specific HPData e.g. map_session_data */
bool (*grabHPDataSub) (struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr);
@@ -158,6 +148,8 @@ struct HPM_interface {
void (*datacheck_final) (void);
};
+CMDLINEARG(loadplugin);
+
struct HPM_interface *HPM;
void hpm_defaults(void);
diff --git a/src/common/HPMi.h b/src/common/HPMi.h
index 47f4e6b8b..d4b2e323c 100644
--- a/src/common/HPMi.h
+++ b/src/common/HPMi.h
@@ -104,7 +104,7 @@ enum HPluginConfType {
#define hookStop() (HPMi->HookStop(__func__,HPMi->pid))
#define hookStopped() (HPMi->HookStopped())
-#define addArg(name,param,func,help) (HPMi->addArg(HPMi->pid,(name),(param),(func),(help)))
+#define addArg(name, param,func,help) (HPMi->addArg(HPMi->pid,(name),(param),(cmdline_arg_ ## func),(help)))
/* HPData handy redirects */
/* session[] */
#define addToSession(ptr,data,index,autofree) (HPMi->addToHPData(HPDT_SESSION,HPMi->pid,(ptr),(data),(index),(autofree)))
@@ -214,7 +214,7 @@ HPExport struct HPMi_interface {
void (*HookStop) (const char *func, unsigned int pID);
bool (*HookStopped) (void);
/* program --arg/-a */
- bool (*addArg) (unsigned int pluginID, char *name, bool has_param,void (*func) (char *param),void (*help) (void));
+ bool (*addArg) (unsigned int pluginID, char *name, bool has_param, CmdlineExecFunc func, const char *help);
/* battle-config recv param */
bool (*addConf) (unsigned int pluginID, enum HPluginConfType type, char *name, void (*func) (const char *val));
/* pc group permission */
diff --git a/src/common/core.c b/src/common/core.c
index e1bb9ed0b..6ad971c86 100644
--- a/src/common/core.c
+++ b/src/common/core.c
@@ -178,6 +178,7 @@ void core_defaults(void) {
console_defaults();
strlib_defaults();
malloc_defaults();
+ cmdline_defaults();
#ifndef MINICORE
libconfig_defaults();
sql_defaults();
@@ -186,6 +187,196 @@ void core_defaults(void) {
socket_defaults();
#endif
}
+/**
+ * Returns the source (core or plugin name) for the given command-line argument
+ */
+const char *cmdline_arg_source(struct CmdlineArgData *arg) {
+#ifdef MINICORE
+ return "core";
+#else // !MINICORE
+ return HPM->pid2name(arg->pluginID);
+#endif // MINICORE
+}
+/**
+ * Defines a command line argument.
+ *
+ * @param pluginID the source plugin ID (use HPM_PID_CORE if loading from the core).
+ * @param name the command line argument name, including the leading '--'.
+ * @param shortname an optional short form (single-character, it will be prefixed with '-'). Use '\0' to skip.
+ * @param func the triggered function.
+ * @param help the help string to be displayed by '--help', if any.
+ * @param options options associated to the command-line argument. @see enum cmdline_options.
+ * @return the success status.
+ */
+bool cmdline_arg_add(unsigned int pluginID, const char *name, char shortname, CmdlineExecFunc func, const char *help, unsigned int options) {
+ struct CmdlineArgData *data = NULL;
+
+ RECREATE(cmdline->args_data, struct CmdlineArgData, ++cmdline->args_data_count);
+ data = &cmdline->args_data[cmdline->args_data_count-1];
+ data->pluginID = pluginID;
+ data->name = aStrdup(name);
+ data->shortname = shortname;
+ data->func = func;
+ data->help = aStrdup(help);
+ data->options = options;
+
+ return true;
+}
+/**
+ * Help screen to be displayed by '--help'.
+ */
+static CMDLINEARG(help)
+{
+ int i;
+ ShowInfo("Usage: %s [options]\n", SERVER_NAME);
+ ShowInfo("\n");
+ ShowInfo("Options:\n");
+
+ for (i = 0; i < cmdline->args_data_count; i++) {
+ struct CmdlineArgData *data = &cmdline->args_data[i];
+ char altname[16], paramnames[256];
+ if (data->shortname) {
+ snprintf(altname, sizeof(altname), " [-%c]", data->shortname);
+ } else {
+ *altname = '\0';
+ }
+ snprintf(paramnames, sizeof(paramnames), "%s%s%s", data->name, altname, data->options&CMDLINE_OPT_PARAM ? " <name>" : "");
+ ShowInfo(" %-30s %s [%s]\n", paramnames, data->help ? data->help : "<no description provided>", cmdline->arg_source(data));
+ }
+ return false;
+}
+/**
+ * Info screen to be displayed by '--version'.
+ */
+static CMDLINEARG(version)
+{
+ ShowInfo(CL_GREEN"Website/Forum:"CL_RESET"\thttp://hercules.ws/\n");
+ ShowInfo(CL_GREEN"IRC Channel:"CL_RESET"\tirc://irc.rizon.net/#Hercules\n");
+ ShowInfo("Open "CL_WHITE"readme.txt"CL_RESET" for more information.\n");
+ return false;
+}
+/**
+ * Checks if there is a value available for the current argument
+ *
+ * @param name the current argument's name.
+ * @param current_arg the current argument's position.
+ * @param argc the program's argc.
+ * @return true if a value for the current argument is available on the command line.
+ */
+bool cmdline_arg_next_value(const char *name, int current_arg, int argc)
+{
+ if (current_arg >= argc-1) {
+ ShowError("Missing value for option '%s'.\n", name);
+ return false;
+ }
+
+ return true;
+}
+/**
+ * Executes the command line arguments handlers.
+ *
+ * @param argc the program's argc
+ * @param argv the program's argv
+ * @param options Execution options. Allowed values:
+ * - CMDLINE_OPT_SILENT: Scans the argv for a command line argument that
+ * requires the server's silent mode, and triggers it. Invalid command line
+ * arguments don't cause it to abort. No command handlers are executed.
+ * - CMDLINE_OPT_PREINIT: Scans the argv for command line arguments with the
+ * CMDLINE_OPT_PREINIT flag set and executes their handlers. Invalid command
+ * line arguments don't cause it to abort. Handler's failure causes the
+ * program to abort.
+ * - CMDLINE_OPT_NORMAL: Scans the argv for normal command line arguments,
+ * skipping the pre-init ones, and executes their handlers. Invalid command
+ * line arguments or handler's failure cause the program to abort.
+ * @return the amount of command line handlers successfully executed.
+ */
+int cmdline_exec(int argc, char **argv, unsigned int options)
+{
+ int count = 0, i, j;
+ for (i = 1; i < argc; i++) {
+ struct CmdlineArgData *data = NULL;
+ const char *arg = argv[i];
+ if (arg[0] != '-') { // All arguments must begin with '-'
+ ShowError("Invalid option '%s'.\n", argv[i]);
+ exit(EXIT_FAILURE);
+ }
+ if (arg[1] != '-' && strlen(arg) == 2) {
+ ARR_FIND(0, cmdline->args_data_count, j, cmdline->args_data[j].shortname == arg[1]);
+ } else {
+ ARR_FIND(0, cmdline->args_data_count, j, strcmpi(cmdline->args_data[j].name, arg) == 0);
+ }
+ if (j == cmdline->args_data_count) {
+ if (options&(CMDLINE_OPT_SILENT|CMDLINE_OPT_PREINIT))
+ continue;
+ ShowError("Unknown option '%s'.\n", arg);
+ exit(EXIT_FAILURE);
+ }
+ data = &cmdline->args_data[j];
+ if (data->options&CMDLINE_OPT_PARAM) {
+ if (!cmdline->arg_next_value(arg, i, argc))
+ exit(EXIT_FAILURE);
+ i++;
+ }
+ if (options&CMDLINE_OPT_SILENT) {
+ if (data->options&CMDLINE_OPT_SILENT) {
+ msg_silent = 0x7; // silence information and status messages
+ break;
+ }
+ } else if ((data->options&CMDLINE_OPT_PREINIT) == (options&CMDLINE_OPT_PREINIT)) {
+ const char *param = NULL;
+ if (data->options&CMDLINE_OPT_PARAM) {
+ param = argv[i]; // Already incremented above
+ }
+ if (!data->func(arg, param))
+ exit(EXIT_SUCCESS);
+ count++;
+ }
+ }
+ return count;
+}
+/**
+ * Defines the global command-line arguments.
+ */
+void cmdline_init(void)
+{
+#ifdef MINICORE
+ // Minicore has no HPM. This value isn't used, but the arg_add function requires it, so we're (re)defining it here
+#define HPM_PID_CORE ((unsigned int)-1)
+#endif
+ CMDLINEARG_DEF(help, 'h', "Displays this help screen", CMDLINE_OPT_NORMAL);
+ CMDLINEARG_DEF(version, 'v', "Displays the server's version.", CMDLINE_OPT_NORMAL);
+#ifndef MINICORE
+ CMDLINEARG_DEF2(load-plugin, loadplugin, "Loads an additional plugin (can be repeated).", CMDLINE_OPT_PARAM|CMDLINE_OPT_PREINIT);
+#endif // !MINICORE
+ cmdline_args_init_local();
+}
+void cmdline_final(void)
+{
+ int i;
+ for (i = 0; i < cmdline->args_data_count; i++) {
+ aFree(cmdline->args_data[i].name);
+ aFree(cmdline->args_data[i].help);
+ }
+ if (cmdline->args_data)
+ aFree(cmdline->args_data);
+}
+
+struct cmdline_interface cmdline_s;
+
+void cmdline_defaults(void)
+{
+ cmdline = &cmdline_s;
+
+ cmdline->args_data = NULL;
+ cmdline->args_data_count = 0;
+
+ cmdline->init = cmdline_init;
+ cmdline->final = cmdline_final;
+ cmdline->arg_add = cmdline_arg_add;
+ cmdline->exec = cmdline_exec;
+ cmdline->arg_next_value = cmdline_arg_next_value;
+ cmdline->arg_source = cmdline_arg_source;
+}
/*======================================
* CORE : MAINROUTINE
*--------------------------------------*/
@@ -203,17 +394,14 @@ int main (int argc, char **argv) {
}
core_defaults();
- {
- int i;
- for(i = 0; i < argc; i++) {
- if( strcmp(argv[i], "--script-check") == 0 ) {
- msg_silent = 0x7; // silence information and status messages
- }
- }
- }
-
iMalloc->init();// needed for Show* in display_title() [FlavioJS]
+ cmdline->init();
+
+ cmdline->exec(argc, argv, CMDLINE_OPT_SILENT);
+
+ iMalloc->init_messages(); // Initialization messages (after buying us some time to suppress them if needed)
+
sysinfo->init();
if (!(msg_silent&0x1))
@@ -269,6 +457,7 @@ int main (int argc, char **argv) {
rathread_final();
ers_final();
#endif
+ cmdline->final();
//sysinfo->final(); Called by iMalloc->final()
iMalloc->final();
diff --git a/src/common/core.h b/src/common/core.h
index 025f636e9..827d345ba 100644
--- a/src/common/core.h
+++ b/src/common/core.h
@@ -5,6 +5,7 @@
#ifndef COMMON_CORE_H
#define COMMON_CORE_H
+#include "../common/cbasetypes.h"
#include "../common/db.h"
#include "../common/mmo.h"
@@ -39,6 +40,7 @@ extern char *SERVER_NAME;
enum server_types SERVER_TYPE;
+extern void cmdline_args_init_local(void);
extern int do_init(int,char**);
extern void set_server_type(void);
extern void do_abort(void);
@@ -49,4 +51,46 @@ extern int do_final(void);
extern void (*shutdown_callback)(void);
#endif // HERCULES_CORE
+/// Options for command line argument handlers.
+enum cmdline_options {
+ CMDLINE_OPT_NORMAL = 0x0, ///< No special options.
+ CMDLINE_OPT_PARAM = 0x1, ///< An additional value parameter is expected.
+ CMDLINE_OPT_SILENT = 0x2, ///< If this command-line argument is passed, the server won't print any messages.
+ CMDLINE_OPT_PREINIT = 0x4, ///< This command-line argument is executed before initializing the HPM.
+};
+typedef bool (*CmdlineExecFunc)(const char *name, const char *params);
+struct CmdlineArgData {
+ unsigned int pluginID; ///< Plugin ID (HPM_PID_CORE if used by the core)
+ unsigned int options; ///< Command line argument options (@see enum cmdline_options)
+ char *name; ///< Command-line argument (i.e. "--my-arg", "--version", "--whatever")
+ char shortname; ///< Short form (i.e. "-v") - only store the 'v' part.
+ CmdlineExecFunc func; ///< Function to call
+ char *help; ///< Help message
+};
+
+struct cmdline_interface {
+ struct CmdlineArgData *args_data;
+ int args_data_count;
+
+ void (*init) (void);
+ void (*final) (void);
+ bool (*arg_add) (unsigned int pluginID, const char *name, char shortname, CmdlineExecFunc func, const char *help, unsigned int options);
+ int (*exec) (int argc, char **argv, unsigned int options);
+ bool (*arg_next_value) (const char *name, int current_arg, int argc);
+ const char *(*arg_source) (struct CmdlineArgData *arg);
+};
+
+struct cmdline_interface *cmdline;
+
+#define CMDLINEARG(x) bool cmdline_arg_ ## x (const char *name, const char *params)
+#ifdef HERCULES_CORE
+/// Special plugin ID assigned to the Hercules core
+#define HPM_PID_CORE ((unsigned int)-1)
+
+#define CMDLINEARG_DEF(name, shortname, help, options) cmdline->arg_add(HPM_PID_CORE, "--" EXPAND_AND_QUOTE(name), shortname, cmdline_arg_ ## name, help, options)
+#define CMDLINEARG_DEF2(name, funcname, help, options) cmdline->arg_add(HPM_PID_CORE, "--" EXPAND_AND_QUOTE(name), '\0', cmdline_arg_ ## funcname, help, options)
+
+void cmdline_defaults(void);
+#endif // HERCULES_CORE
+
#endif /* COMMON_CORE_H */
diff --git a/src/common/malloc.c b/src/common/malloc.c
index 244b1114c..43fbe4ea1 100644
--- a/src/common/malloc.c
+++ b/src/common/malloc.c
@@ -769,12 +769,24 @@ void memmgr_report (int extra) {
}
-static void memmgr_init (void)
+/**
+ * Initializes the Memory Manager.
+ */
+static void memmgr_init(void)
+{
+#ifdef LOG_MEMMGR
+ memset(hash_unfill, 0, sizeof(hash_unfill));
+#endif /* LOG_MEMMGR */
+}
+
+/**
+ * Prints initialization messages from the Memory Manager.
+ */
+static void memmgr_init_messages(void)
{
#ifdef LOG_MEMMGR
sprintf(memmer_logfile, "log/%s.leaks", SERVER_NAME);
ShowStatus("Memory manager initialized: "CL_WHITE"%s"CL_RESET"\n", memmer_logfile);
- memset(hash_unfill, 0, sizeof(hash_unfill));
#endif /* LOG_MEMMGR */
}
#endif /* USE_MEMMGR */
@@ -821,7 +833,22 @@ void malloc_final (void) {
iMalloc->post_shutdown();
}
-void malloc_init (void) {
+/**
+ * Prints initialization status messages.
+ *
+ * This is separated from malloc_init() in order to be run after giving the
+ * chance to other modules to initialize, in case they want to silence any
+ * status messages, but at the same time require malloc.
+ */
+void malloc_init_messages(void)
+{
+#ifdef USE_MEMMGR
+ memmgr_init_messages();
+#endif
+}
+
+void malloc_init(void)
+{
#ifdef USE_MEMMGR
memmgr_usage_bytes_t = 0;
memmgr_usage_bytes = 0;
@@ -836,7 +863,7 @@ void malloc_init (void) {
GC_INIT();
#endif
#ifdef USE_MEMMGR
- memmgr_init ();
+ memmgr_init();
#endif
}
@@ -865,4 +892,5 @@ void malloc_defaults(void) {
iMalloc->free = aFree_;
#endif
iMalloc->post_shutdown = NULL;
+ iMalloc->init_messages = malloc_init_messages;
}
diff --git a/src/common/malloc.h b/src/common/malloc.h
index bc79ac65a..7ed2fb19c 100644
--- a/src/common/malloc.h
+++ b/src/common/malloc.h
@@ -59,12 +59,6 @@
////////////////////////////////////////////////
-//void malloc_memory_check(void);
-//bool malloc_verify_ptr(void* ptr);
-//size_t malloc_usage (void);
-//void malloc_init (void);
-//void malloc_final (void);
-
#ifdef HERCULES_CORE
void malloc_defaults(void);
@@ -87,6 +81,7 @@ struct malloc_interface {
size_t (*usage) (void);
/* */
void (*post_shutdown) (void);
+ void (*init_messages) (void);
};
struct malloc_interface *iMalloc;