diff options
author | Haru <haru@dotalux.com> | 2014-11-09 02:07:09 +0100 |
---|---|---|
committer | Haru <haru@dotalux.com> | 2015-01-18 21:35:36 +0100 |
commit | ce08d6238d902590dbfb650f889a8ab8887356bf (patch) | |
tree | 218266957f961e71a51a307b432b02ed9647243a | |
parent | 0285ddf7cee2f6569a513fe6118c43f99fd71279 (diff) | |
download | hercules-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>
-rw-r--r-- | src/char/char.c | 90 | ||||
-rw-r--r-- | src/char/char.h | 5 | ||||
-rw-r--r-- | src/char/inter.h | 2 | ||||
-rw-r--r-- | src/common/HPM.c | 104 | ||||
-rw-r--r-- | src/common/HPM.h | 20 | ||||
-rw-r--r-- | src/common/HPMi.h | 4 | ||||
-rw-r--r-- | src/common/core.c | 207 | ||||
-rw-r--r-- | src/common/core.h | 44 | ||||
-rw-r--r-- | src/common/malloc.c | 36 | ||||
-rw-r--r-- | src/common/malloc.h | 7 | ||||
-rw-r--r-- | src/login/login.c | 68 | ||||
-rw-r--r-- | src/login/login.h | 5 | ||||
-rw-r--r-- | src/map/atcommand.c | 2 | ||||
-rw-r--r-- | src/map/map.c | 363 | ||||
-rw-r--r-- | src/map/map.h | 13 | ||||
-rw-r--r-- | src/plugins/db2sql.c | 6 | ||||
-rw-r--r-- | src/tool/mapcache.c | 102 |
17 files changed, 735 insertions, 343 deletions
diff --git a/src/char/char.c b/src/char/char.c index f29bf8cff..1301f2cc4 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -50,10 +50,6 @@ #endif // private declarations -#define CHAR_CONF_NAME "conf/char-server.conf" -#define LAN_CONF_NAME "conf/subnet.conf" -#define SQL_CONF_NAME "conf/inter-server.conf" - char char_db[256] = "char"; char scdata_db[256] = "sc_data"; char cart_db[256] = "cart_inventory"; @@ -5707,6 +5703,11 @@ int do_final(void) { if( chr->server[i].map ) aFree(chr->server[i].map); + aFree(chr->CHAR_CONF_NAME); + aFree(chr->LAN_CONF_NAME); + aFree(chr->SQL_CONF_NAME); + aFree(chr->INTER_CONF_NAME); + HPM->event(HPET_POST_FINAL); ShowStatus("Finished.\n"); @@ -5763,45 +5764,80 @@ void char_hp_symbols(void) { HPM->share(inter->sql_handle, "sql_handle"); } +/** + * --char-config handler + * + * Overrides the default char configuration file. + * @see cmdline->exec + */ +static CMDLINEARG(charconfig) +{ + aFree(chr->CHAR_CONF_NAME); + chr->CHAR_CONF_NAME = aStrdup(params); + return true; +} +/** + * --inter-config handler + * + * Overrides the default inter-server configuration file. + * @see cmdline->exec + */ +static CMDLINEARG(interconfig) +{ + aFree(chr->INTER_CONF_NAME); + chr->INTER_CONF_NAME = aStrdup(params); + return true; +} +/** + * --lan-config handler + * + * Overrides the default subnet configuration file. + * @see cmdline->exec + */ +static CMDLINEARG(lanconfig) +{ + aFree(chr->LAN_CONF_NAME); + chr->LAN_CONF_NAME = aStrdup(params); + return true; +} +/** + * Initializes the command line arguments handlers. + */ +void cmdline_args_init_local(void) +{ + CMDLINEARG_DEF2(char-config, charconfig, "Alternative char-server configuration.", CMDLINE_OPT_PARAM); + CMDLINEARG_DEF2(inter-config, interconfig, "Alternative inter-server configuration.", CMDLINE_OPT_PARAM); + CMDLINEARG_DEF2(lan-config, lanconfig, "Alternative subnet configuration.", CMDLINE_OPT_PARAM); +} + int do_init(int argc, char **argv) { int i; memset(&skillid2idx, 0, sizeof(skillid2idx)); char_load_defaults(); + chr->CHAR_CONF_NAME = aStrdup("conf/char-server.conf"); + chr->LAN_CONF_NAME = aStrdup("conf/subnet.conf"); + chr->SQL_CONF_NAME = aStrdup("conf/inter-server.conf"); + chr->INTER_CONF_NAME = aStrdup("conf/inter-server.conf"); + for(i = 0; i < MAX_MAP_SERVERS; i++ ) chr->server[i].map = NULL; HPM_char_do_init(); HPM->symbol_defaults_sub = char_hp_symbols; -#if 0 - /* TODO: Move to common code */ - for( i = 1; i < argc; i++ ) { - const char* arg = argv[i]; - if( strcmp(arg, "--load-plugin") == 0 ) { - if( map->arg_next_value(arg, i, argc, true) ) { - RECREATE(load_extras, char *, ++load_extras_count); - load_extras[load_extras_count-1] = argv[++i]; - } - } - } - HPM->config_read((const char * const *)load_extras, load_extras_count); - if (load_extras) { - aFree(load_extras); - load_extras = NULL; - load_extras_count = 0; - } -#endif - HPM->config_read(NULL, 0); + cmdline->exec(argc, argv, CMDLINE_OPT_PREINIT); + HPM->config_read(); HPM->event(HPET_PRE_INIT); //Read map indexes mapindex->init(); start_point.map = mapindex->name2id("new_zone01"); - chr->config_read((argc < 2) ? CHAR_CONF_NAME : argv[1]); - chr->lan_config_read((argc > 3) ? argv[3] : LAN_CONF_NAME); - chr->sql_config_read(SQL_CONF_NAME); + cmdline->exec(argc, argv, CMDLINE_OPT_NORMAL); + chr->config_read(chr->CHAR_CONF_NAME); + chr->lan_config_read(chr->LAN_CONF_NAME); + chr->sql_config_read(chr->SQL_CONF_NAME); if (strcmp(chr->userid, "s1")==0 && strcmp(chr->passwd, "p1")==0) { ShowWarning("Using the default user/password s1/p1 is NOT RECOMMENDED.\n"); @@ -5809,7 +5845,7 @@ int do_init(int argc, char **argv) { ShowNotice("And then change the user/password to use in conf/char-server.conf (or conf/import/char_conf.txt)\n"); } - inter->init_sql((argc > 2) ? argv[2] : inter_cfgName); // inter server configuration + inter->init_sql(chr->INTER_CONF_NAME); // inter server configuration auth_db = idb_alloc(DB_OPT_RELEASE_DATA); chr->online_char_db = idb_alloc(DB_OPT_RELEASE_DATA); diff --git a/src/char/char.h b/src/char/char.h index 4b68dc43c..e27aa0b44 100644 --- a/src/char/char.h +++ b/src/char/char.h @@ -144,6 +144,11 @@ struct char_interface { int server_type; int new_display; + char *CHAR_CONF_NAME; + char *LAN_CONF_NAME; + char *SQL_CONF_NAME; + char *INTER_CONF_NAME; + int (*waiting_disconnect) (int tid, int64 tick, int id, intptr_t data); int (*delete_char_sql) (int char_id); DBData (*create_online_char_data) (DBKey key, va_list args); diff --git a/src/char/inter.h b/src/char/inter.h index 7f5b5fc22..a58d3b3a9 100644 --- a/src/char/inter.h +++ b/src/char/inter.h @@ -11,8 +11,6 @@ struct accreg; -#define inter_cfgName "conf/inter-server.conf" - #ifdef HERCULES_CORE extern unsigned int party_share_level; 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; diff --git a/src/login/login.c b/src/login/login.c index ec5b2bb7c..036456a85 100644 --- a/src/login/login.c +++ b/src/login/login.c @@ -1899,6 +1899,9 @@ int do_final(void) { HPM_login_do_final(); + aFree(login->LOGIN_CONF_NAME); + aFree(login->LAN_CONF_NAME); + HPM->event(HPET_POST_FINAL); ShowStatus("Finished.\n"); @@ -1939,6 +1942,39 @@ void login_hp_symbols(void) { HPM->share(login,"login"); } +/** + * --login-config handler + * + * Overrides the default login configuration file. + * @see cmdline->exec + */ +static CMDLINEARG(loginconfig) +{ + aFree(login->LOGIN_CONF_NAME); + login->LOGIN_CONF_NAME = aStrdup(params); + return true; +} +/** + * --lan-config handler + * + * Overrides the default subnet configuration file. + * @see cmdline->exec + */ +static CMDLINEARG(lanconfig) +{ + aFree(login->LAN_CONF_NAME); + login->LAN_CONF_NAME = aStrdup(params); + return true; +} +/** + * Defines the local command line arguments + */ +void cmdline_args_init_local(void) +{ + CMDLINEARG_DEF2(login-config, loginconfig, "Alternative login-server configuration.", CMDLINE_OPT_PARAM); + CMDLINEARG_DEF2(lan-config, lanconfig, "Alternative subnet configuration.", CMDLINE_OPT_PARAM); +} + //------------------------------ // Login server initialization //------------------------------ @@ -1959,31 +1995,18 @@ int do_init(int argc, char** argv) // read login-server configuration login_set_defaults(); + login->LOGIN_CONF_NAME = aStrdup("conf/login-server.conf"); + login->LAN_CONF_NAME = aStrdup("conf/subnet.conf"); + HPM_login_do_init(); HPM->symbol_defaults_sub = login_hp_symbols; - HPM->config_read(NULL, 0); -#if 0 - /* TODO: Move to common code */ - for( i = 1; i < argc; i++ ) { - const char* arg = argv[i]; - if( strcmp(arg, "--load-plugin") == 0 ) { - if( map->arg_next_value(arg, i, argc, true) ) { - RECREATE(load_extras, char *, ++load_extras_count); - load_extras[load_extras_count-1] = argv[++i]; - } - } - } - HPM->config_read((const char * const *)load_extras, load_extras_count); - if (load_extras) { - aFree(load_extras); - load_extras = NULL; - load_extras_count = 0; - } -#endif + cmdline->exec(argc, argv, CMDLINE_OPT_PREINIT); + HPM->config_read(); HPM->event(HPET_PRE_INIT); - login_config_read((argc > 1) ? argv[1] : LOGIN_CONF_NAME); - login->lan_config_read((argc > 2) ? argv[2] : LAN_CONF_NAME); + cmdline->exec(argc, argv, CMDLINE_OPT_NORMAL); + login_config_read(login->LOGIN_CONF_NAME); + login->lan_config_read(login->LAN_CONF_NAME); for( i = 0; i < ARRAYLENGTH(server); ++i ) chrif_server_init(i); @@ -2105,4 +2128,7 @@ void login_defaults(void) { login->kick = login_kick; login->login_error = login_login_error; login->send_coding_key = login_send_coding_key; + + login->LOGIN_CONF_NAME = NULL; + login->LAN_CONF_NAME = NULL; } diff --git a/src/login/login.h b/src/login/login.h index 8a377927b..7254b5db2 100644 --- a/src/login/login.h +++ b/src/login/login.h @@ -18,9 +18,6 @@ enum E_LOGINSERVER_ST LOGINSERVER_ST_LAST }; -#define LOGIN_CONF_NAME "conf/login-server.conf" -#define LAN_CONF_NAME "conf/subnet.conf" - // supported encryption types: 1- passwordencrypt, 2- passwordencrypt2, 3- both #define PASSWORDENC 3 #define PASSWD_LEN (32+1) // 23+1 for plaintext, 32+1 for md5-ed passwords @@ -200,6 +197,8 @@ struct login_interface { void (*char_server_connection_status) (int fd, struct login_session_data* sd, uint8 status); void (*parse_request_connection) (int fd, struct login_session_data* sd, const char *ip); int (*parse_login) (int fd); + char *LOGIN_CONF_NAME; + char *LAN_CONF_NAME; }; struct login_interface *login; diff --git a/src/map/atcommand.c b/src/map/atcommand.c index f750b307a..000192b62 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -3628,7 +3628,7 @@ ACMD(reloadscript) { mapit->free(iter); flush_fifos(); - map->reloadnpc(true, NULL, 0); // reload config files seeking for npcs + map->reloadnpc(true); // reload config files seeking for npcs script->reload(); npc->reload(); diff --git a/src/map/map.c b/src/map/map.c index 640dd0ce1..e71085fda 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -3689,7 +3689,12 @@ void map_reloadnpc_sub(char *cfgName) { fclose(fp); } -void map_reloadnpc(bool clear, const char * const *extra_scripts, int extra_scripts_count) { +/** + * Reloads all the scripts. + * + * @param clear whether to clear the script list before reloading. + */ +void map_reloadnpc(bool clear) { int i; if (clear) npc->addsrcfile("clear"); // this will clear the current script list @@ -3701,8 +3706,8 @@ void map_reloadnpc(bool clear, const char * const *extra_scripts, int extra_scri #endif // Append extra scripts - for( i = 0; i < extra_scripts_count; i++ ) { - npc->addsrcfile(extra_scripts[i]); + for( i = 0; i < map->extra_scripts_count; i++ ) { + npc->addsrcfile(map->extra_scripts[i]); } } @@ -5381,6 +5386,14 @@ int do_final(void) { } ShowStatus("Cleaned up %d maps."CL_CLL"\n", map->count); + if (map->extra_scripts) { + for (i = 0; i < map->extra_scripts_count; i++) + aFree(map->extra_scripts[i]); + aFree(map->extra_scripts); + map->extra_scripts = NULL; + map->extra_scripts_count = 0; + } + map->id_db->foreach(map->id_db,map->cleanup_db_sub); chrif->char_reset_offline(); chrif->flush(); @@ -5444,8 +5457,17 @@ int do_final(void) { if( !map->enable_grf ) aFree(map->cache_buffer); - HPM->event(HPET_POST_FINAL); + aFree(map->MAP_CONF_NAME); + aFree(map->BATTLE_CONF_FILENAME); + aFree(map->ATCOMMAND_CONF_FILENAME); + aFree(map->SCRIPT_CONF_NAME); + aFree(map->MSG_CONF_NAME); + aFree(map->GRF_PATH_FILENAME); + aFree(map->INTER_CONF_NAME); + aFree(map->LOG_CONF_NAME); + HPM->event(HPET_POST_FINAL); + ShowStatus("Finished.\n"); return map->retval; } @@ -5480,45 +5502,6 @@ void do_abort(void) chrif->flush(); } -/*====================================================== -* Map-Server Version Screen [MC Cameri] -*------------------------------------------------------*/ -void map_helpscreen(bool do_exit) -{ - ShowInfo("Usage: %s [options]\n", SERVER_NAME); - ShowInfo("\n"); - ShowInfo("Options:\n"); - ShowInfo(" -?, -h [--help] Displays this help screen.\n"); - ShowInfo(" -v [--version] Displays the server's version.\n"); - ShowInfo(" --run-once Closes server after loading (testing).\n"); - ShowInfo(" --map-config <file> Alternative map-server configuration.\n"); - ShowInfo(" --battle-config <file> Alternative battle configuration.\n"); - ShowInfo(" --atcommand-config <file> Alternative atcommand configuration.\n"); - ShowInfo(" --script-config <file> Alternative script configuration.\n"); - ShowInfo(" --msg-config <file> Alternative message configuration.\n"); - ShowInfo(" --grf-path <file> Alternative GRF path configuration.\n"); - ShowInfo(" --inter-config <file> Alternative inter-server configuration.\n"); - ShowInfo(" --log-config <file> Alternative logging configuration.\n"); - ShowInfo(" --script-check Doesn't run the server, only tests the\n"); - ShowInfo(" scripts passed through --load-script.\n"); - ShowInfo(" --load-script <file> Loads an additional script (can be repeated).\n"); - ShowInfo(" --load-plugin <name> Loads an additional plugin (can be repeated).\n"); - HPM->arg_help(); /* display help for commands implemented through HPM */ - if( do_exit ) - exit(EXIT_SUCCESS); -} - -/*====================================================== - * Map-Server Version Screen [MC Cameri] - *------------------------------------------------------*/ -void map_versionscreen(bool do_exit) { - 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"); - if( do_exit ) - exit(EXIT_SUCCESS); -} - void set_server_type(void) { SERVER_TYPE = SERVER_TYPE_MAP; } @@ -5543,17 +5526,6 @@ void do_shutdown(void) } } -bool map_arg_next_value(const char* option, int i, int argc, bool must) -{ - if( i >= argc-1 ) { - if( must ) - ShowWarning("Missing value for option '%s'.\n", option); - return false; - } - - return true; -} - CPCMD(gm_position) { int x = 0, y = 0, m = 0; char map_name[25]; @@ -5706,12 +5678,160 @@ void map_load_defaults(void) { npc_chat_defaults(); #endif } +/** + * --run-once handler + * + * Causes the server to run its loop once, and shutdown. Useful for testing. + * @see cmdline->exec + */ +static CMDLINEARG(runonce) +{ + runflag = CORE_ST_STOP; + return true; +} +/** + * --map-config handler + * + * Overrides the default map-server configuration filename. + * @see cmdline->exec + */ +static CMDLINEARG(mapconfig) +{ + aFree(map->MAP_CONF_NAME); + map->MAP_CONF_NAME = aStrdup(params); + return true; +} +/** + * --battle-config handler + * + * Overrides the default battle configuration filename. + * @see cmdline->exec + */ +static CMDLINEARG(battleconfig) +{ + aFree(map->BATTLE_CONF_FILENAME); + map->BATTLE_CONF_FILENAME = aStrdup(params); + return true; +} +/** + * --atcommand-config handler + * + * Overrides the default atcommands configuration filename. + * @see cmdline->exec + */ +static CMDLINEARG(atcommandconfig) +{ + aFree(map->ATCOMMAND_CONF_FILENAME); + map->ATCOMMAND_CONF_FILENAME = aStrdup(params); + return true; +} +/** + * --script-config handler + * + * Overrides the default script configuration filename. + * @see cmdline->exec + */ +static CMDLINEARG(scriptconfig) +{ + aFree(map->SCRIPT_CONF_NAME); + map->SCRIPT_CONF_NAME = aStrdup(params); + return true; +} +/** + * --msg-config handler + * + * Overrides the default messages configuration filename. + * @see cmdline->exec + */ +static CMDLINEARG(msgconfig) +{ + aFree(map->MSG_CONF_NAME); + map->MSG_CONF_NAME = aStrdup(params); + return true; +} +/** + * --grf-path handler + * + * Overrides the default grf configuration filename. + * @see cmdline->exec + */ +static CMDLINEARG(grfpath) +{ + aFree(map->GRF_PATH_FILENAME); + map->GRF_PATH_FILENAME = aStrdup(params); + return true; +} +/** + * --inter-config handler + * + * Overrides the default inter-server configuration filename. + * @see cmdline->exec + */ +static CMDLINEARG(interconfig) +{ + aFree(map->INTER_CONF_NAME); + map->INTER_CONF_NAME = aStrdup(params); + return true; +} +/** + * --log-config handler + * + * Overrides the default log configuration filename. + * @see cmdline->exec + */ +static CMDLINEARG(logconfig) +{ + aFree(map->LOG_CONF_NAME); + map->LOG_CONF_NAME = aStrdup(params); + return true; +} +/** + * --script-check handler + * + * Enables script-check mode. Checks scripts and quits without running. + * @see cmdline->exec + */ +static CMDLINEARG(scriptcheck) +{ + map->minimal = true; + runflag = CORE_ST_STOP; + map->scriptcheck = true; + return true; +} +/** + * --load-script handler + * + * Adds a filename to the script auto-load list. + * @see cmdline->exec + */ +static CMDLINEARG(loadscript) +{ + RECREATE(map->extra_scripts, char *, ++map->extra_scripts_count); + map->extra_scripts[map->extra_scripts_count-1] = aStrdup(params); + return true; +} +/** + * Defines the local command line arguments + */ +void cmdline_args_init_local(void) +{ + CMDLINEARG_DEF2(run-once, runonce, "Closes server after loading (testing).", CMDLINE_OPT_NORMAL); + CMDLINEARG_DEF2(map-config, mapconfig, "Alternative map-server configuration.", CMDLINE_OPT_NORMAL|CMDLINE_OPT_PARAM); + CMDLINEARG_DEF2(battle-config, battleconfig, "Alternative battle configuration.", CMDLINE_OPT_NORMAL|CMDLINE_OPT_PARAM); + CMDLINEARG_DEF2(atcommand-config, atcommandconfig, "Alternative atcommand configuration.", CMDLINE_OPT_NORMAL|CMDLINE_OPT_PARAM); + CMDLINEARG_DEF2(script-config, scriptconfig, "Alternative script configuration.", CMDLINE_OPT_NORMAL|CMDLINE_OPT_PARAM); + CMDLINEARG_DEF2(msg-config, msgconfig, "Alternative message configuration.", CMDLINE_OPT_NORMAL|CMDLINE_OPT_PARAM); + CMDLINEARG_DEF2(grf-path, grfpath, "Alternative GRF path configuration.", CMDLINE_OPT_NORMAL|CMDLINE_OPT_PARAM); + CMDLINEARG_DEF2(inter-config, interconfig, "Alternative inter-server configuration.", CMDLINE_OPT_NORMAL|CMDLINE_OPT_PARAM); + CMDLINEARG_DEF2(log-config, logconfig, "Alternative logging configuration.", CMDLINE_OPT_NORMAL|CMDLINE_OPT_PARAM); + CMDLINEARG_DEF2(script-check, scriptcheck, "Doesn't run the server, only tests the scripts passed through --load-script.", CMDLINE_OPT_SILENT); + CMDLINEARG_DEF2(load-script, loadscript, "Loads an additional script (can be repeated).", CMDLINE_OPT_NORMAL|CMDLINE_OPT_PARAM); +} + int do_init(int argc, char *argv[]) { bool minimal = false; - bool scriptcheck = false; - int i, load_extras_count = 0; - char **load_extras = NULL; + int i; #ifdef GCOLLECT GC_enable_incremental(); @@ -5719,98 +5839,23 @@ int do_init(int argc, char *argv[]) map_load_defaults(); + map->INTER_CONF_NAME = aStrdup("conf/inter-server.conf"); + map->LOG_CONF_NAME = aStrdup("conf/logs.conf"); + map->MAP_CONF_NAME = aStrdup("conf/map-server.conf"); + map->BATTLE_CONF_FILENAME = aStrdup("conf/battle.conf"); + map->ATCOMMAND_CONF_FILENAME = aStrdup("conf/atcommand.conf"); + map->SCRIPT_CONF_NAME = aStrdup("conf/script.conf"); + map->MSG_CONF_NAME = aStrdup("conf/messages.conf"); + map->GRF_PATH_FILENAME = aStrdup("conf/grf-files.txt"); + HPM_map_do_init(); HPM->symbol_defaults_sub = map_hp_symbols; - for( i = 1; i < argc; i++ ) { - const char* arg = argv[i]; - if( strcmp(arg, "--load-plugin") == 0 ) { - if( map->arg_next_value(arg, i, argc, true) ) { - RECREATE(load_extras, char *, ++load_extras_count); - load_extras[load_extras_count-1] = argv[++i]; - } - } - } - HPM->config_read((const char * const *)load_extras, load_extras_count); - if (load_extras) { - aFree(load_extras); - load_extras = NULL; - load_extras_count = 0; - } + cmdline->exec(argc, argv, CMDLINE_OPT_PREINIT); + HPM->config_read(); HPM->event(HPET_PRE_INIT); - for( i = 1; i < argc ; i++ ) { - const char* arg = argv[i]; - - if( arg[0] != '-' && ( arg[0] != '/' || arg[1] == '-' ) ) {// -, -- and / - ShowError("Unknown option '%s'.\n", argv[i]); - exit(EXIT_FAILURE); - } else if ( HPM->parse_arg(arg,&i,argv,map->arg_next_value(arg, i, argc, false)) ) { - continue; /* HPM Triggered */ - } else if( (++arg)[0] == '-' ) {// long option - arg++; - - if( strcmp(arg, "help") == 0 ) { - map->helpscreen(true); - } else if( strcmp(arg, "version") == 0 ) { - map->versionscreen(true); - } else if( strcmp(arg, "map-config") == 0 ) { - if( map->arg_next_value(arg, i, argc, true) ) - map->MAP_CONF_NAME = argv[++i]; - } else if( strcmp(arg, "battle-config") == 0 ) { - if( map->arg_next_value(arg, i, argc, true) ) - map->BATTLE_CONF_FILENAME = argv[++i]; - } else if( strcmp(arg, "atcommand-config") == 0 ) { - if( map->arg_next_value(arg, i, argc, true) ) - map->ATCOMMAND_CONF_FILENAME = argv[++i]; - } else if( strcmp(arg, "script-config") == 0 ) { - if( map->arg_next_value(arg, i, argc, true) ) - map->SCRIPT_CONF_NAME = argv[++i]; - } else if( strcmp(arg, "msg-config") == 0 ) { - if( map->arg_next_value(arg, i, argc, true) ) - map->MSG_CONF_NAME = argv[++i]; - } else if( strcmp(arg, "grf-path-file") == 0 ) { - if( map->arg_next_value(arg, i, argc, true) ) - map->GRF_PATH_FILENAME = argv[++i]; - } else if( strcmp(arg, "inter-config") == 0 ) { - if( map->arg_next_value(arg, i, argc, true) ) - map->INTER_CONF_NAME = argv[++i]; - } else if( strcmp(arg, "log-config") == 0 ) { - if( map->arg_next_value(arg, i, argc, true) ) - map->LOG_CONF_NAME = argv[++i]; - } else if( strcmp(arg, "run-once") == 0 ) { // close the map-server as soon as its done.. for testing [Celest] - runflag = CORE_ST_STOP; - } else if( strcmp(arg, "script-check") == 0 ) { - map->minimal = true; - runflag = CORE_ST_STOP; - scriptcheck = true; - } else if( strcmp(arg, "load-plugin") == 0 ) { - if( map->arg_next_value(arg, i, argc, true) ) - i++; - } else if( strcmp(arg, "load-script") == 0 ) { - if( map->arg_next_value(arg, i, argc, true) ) { - RECREATE(load_extras, char *, ++load_extras_count); - load_extras[load_extras_count-1] = argv[++i]; - } - } else { - ShowError("Unknown option '%s'.\n", argv[i]); - exit(EXIT_FAILURE); - } - } else { - switch( arg[0] ) {// short option - case '?': - case 'h': - map->helpscreen(true); - break; - case 'v': - map->versionscreen(true); - break; - default: - ShowError("Unknown option '%s'.\n", argv[i]); - exit(EXIT_FAILURE); - } - } - } + cmdline->exec(argc, argv, CMDLINE_OPT_NORMAL); minimal = map->minimal;/* temp (perhaps make minimal a mask with options of what to load? e.g. plugin 1 does minimal |= mob_db; */ if (!minimal) { map->config_read(map->MAP_CONF_NAME); @@ -5819,7 +5864,7 @@ int do_init(int argc, char *argv[]) map->config_read_sub(map->MAP_CONF_NAME); // loads npcs - map->reloadnpc(false, (const char * const *)load_extras, load_extras_count); + map->reloadnpc(false); chrif->checkdefaultlogin(); @@ -5928,23 +5973,16 @@ int do_init(int argc, char *argv[]) duel->init(minimal); vending->init(minimal); - if (scriptcheck) { - if (load_extras) { - bool failed = load_extras_count > 0 ? false : true; - for (i = 0; i < load_extras_count; i++) { - if (npc->parsesrcfile(load_extras[i], false) != EXIT_SUCCESS) - failed = true; - } - if (failed) - exit(EXIT_FAILURE); + if (map->scriptcheck) { + bool failed = map->extra_scripts_count > 0 ? false : true; + for (i = 0; i < map->extra_scripts_count; i++) { + if (npc->parsesrcfile(map->extra_scripts[i], false) != EXIT_SUCCESS) + failed = true; } + if (failed) + exit(EXIT_FAILURE); exit(EXIT_SUCCESS); } - if (load_extras) { - aFree(load_extras); - load_extras = NULL; - //load_extras_count = 0; // Dead store. Uncomment if needed again. - } if( minimal ) { HPM->event(HPET_READY); @@ -5987,8 +6025,12 @@ void map_defaults(void) { /* */ map->minimal = false; + map->scriptcheck = false; map->count = 0; map->retval = EXIT_SUCCESS; + + map->extra_scripts = NULL; + map->extra_scripts_count = 0; sprintf(map->db_path ,"db"); sprintf(map->help_txt ,"conf/help.txt"); @@ -6242,9 +6284,6 @@ void map_defaults(void) { map->nick_db_final = nick_db_final; map->cleanup_db_sub = cleanup_db_sub; map->abort_sub = map_abort_sub; - map->helpscreen = map_helpscreen; - map->versionscreen = map_versionscreen; - map->arg_next_value = map_arg_next_value; map->update_cell_bl = map_update_cell_bl; diff --git a/src/map/map.h b/src/map/map.h index 9721b19f3..a1c6d2cde 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -812,7 +812,13 @@ struct map_cache_map_info { struct map_interface { /* vars */ - bool minimal; + bool minimal; ///< Starts the server in minimal initialization mode. + bool scriptcheck; ///< Starts the server in script-check mode. + + /** Additional scripts requested through the command-line */ + char **extra_scripts; + int extra_scripts_count; + int retval; int count; @@ -1005,7 +1011,7 @@ struct map_interface { struct mob_data * (*getmob_boss) (int16 m); struct mob_data * (*id2boss) (int id); // reload config file looking only for npcs - void (*reloadnpc) (bool clear, const char * const *extra_scripts, int extra_scripts_count); + void (*reloadnpc) (bool clear); int (*check_dir) (int s_dir,int t_dir); uint8 (*calc_dir) (struct block_list *src,int16 x,int16 y); @@ -1068,9 +1074,6 @@ struct map_interface { int (*nick_db_final) (DBKey key, DBData *data, va_list args); int (*cleanup_db_sub) (DBKey key, DBData *data, va_list va); int (*abort_sub) (struct map_session_data *sd, va_list ap); - void (*helpscreen) (bool do_exit); - void (*versionscreen) (bool do_exit); - bool (*arg_next_value) (const char *option, int i, int argc, bool must); void (*update_cell_bl) (struct block_list *bl, bool increase); int (*get_new_bonus_id) (void); void (*add_questinfo) (int m, struct questinfo *qi); diff --git a/src/plugins/db2sql.c b/src/plugins/db2sql.c index eda61d026..62ed80255 100644 --- a/src/plugins/db2sql.c +++ b/src/plugins/db2sql.c @@ -348,8 +348,10 @@ void do_db2sql(void) { CPCMD(db2sql) { do_db2sql(); } -void db2sql_arg(char *param) { +CMDLINEARG(db2sql) +{ map->minimal = torun = true; + return true; } HPExport void server_preinit (void) { SQL = GET_SYMBOL("SQL"); @@ -360,7 +362,7 @@ HPExport void server_preinit (void) { libconfig = GET_SYMBOL("libconfig"); StrBuf = GET_SYMBOL("StrBuf"); - addArg("--db2sql",false,db2sql_arg,NULL); + addArg("--db2sql",false,db2sql,NULL); } HPExport void plugin_init (void) { addCPCommand("server:tools:db2sql",db2sql); diff --git a/src/tool/mapcache.c b/src/tool/mapcache.c index 2cc70ebf3..5376458dc 100644 --- a/src/tool/mapcache.c +++ b/src/tool/mapcache.c @@ -10,6 +10,7 @@ #include <string.h> #include "../common/cbasetypes.h" +#include "../common/core.h" #include "../common/grfio.h" #include "../common/malloc.h" #include "../common/mmo.h" @@ -23,9 +24,9 @@ #define NO_WATER 1000000 -char grf_list_file[256] = "conf/grf-files.txt"; -char map_list_file[256] = "db/map_index.txt"; -char map_cache_file[256]; +char *grf_list_file; +char *map_list_file; +char *map_cache_file; int rebuild = 0; FILE *map_cache_fp; @@ -184,25 +185,67 @@ char *remove_extension(char *mapname) return mapname; } -// Processes command-line arguments -void process_args(int argc, char *argv[]) +/** + * --grf-list handler + * + * Overrides the default grf list filename. + * @see cmdline->exec + */ +static CMDLINEARG(grflist) { - int i; + aFree(grf_list_file); + grf_list_file = aStrdup(params); + return true; +} - for(i = 0; i < argc; i++) { - if(strcmp(argv[i], "-grf") == 0) { - if(++i < argc) - safestrncpy(grf_list_file, argv[i], sizeof(grf_list_file)); - } else if(strcmp(argv[i], "-list") == 0) { - if(++i < argc) - safestrncpy(map_list_file, argv[i], sizeof(map_list_file)); - } else if(strcmp(argv[i], "-cache") == 0) { - if(++i < argc) - safestrncpy(map_cache_file, argv[i], sizeof(map_cache_file)); - } else if(strcmp(argv[i], "-rebuild") == 0) - rebuild = 1; - } +/** + * --map-list handler + * + * Overrides the default map list filename. + * @see cmdline->exec + */ +static CMDLINEARG(maplist) +{ + aFree(map_list_file); + map_list_file = aStrdup(params); + return true; +} +/** + * --map-cache handler + * + * Overrides the default map cache filename. + * @see cmdline->exec + */ +static CMDLINEARG(mapcache) +{ + aFree(map_cache_file); + map_cache_file = aStrdup(params); + return true; +} + +/** + * --rebuild handler + * + * Forces a rebuild of the mapcache, rather than only adding missing maps. + * @see cmdline->exec + */ +static CMDLINEARG(rebuild) +{ + rebuild = 1; + return true; +} + +/** + * Defines the local command line arguments + */ +void cmdline_args_init_local(void) +{ + CMDLINEARG_DEF2(grf-list, grflist, "Alternative grf list file", CMDLINE_OPT_NORMAL|CMDLINE_OPT_PARAM); + CMDLINEARG_DEF2(map-list, maplist, "Alternative map list file", CMDLINE_OPT_NORMAL|CMDLINE_OPT_PARAM); + CMDLINEARG_DEF2(map-cache, mapcache, "Alternative map cache file", CMDLINE_OPT_NORMAL|CMDLINE_OPT_PARAM); + CMDLINEARG_DEF2(rebuild, rebuild, "Forces a rebuild of the map cache, rather than only adding missing maps", CMDLINE_OPT_NORMAL); + } int do_init(int argc, char** argv) @@ -212,17 +255,13 @@ int do_init(int argc, char** argv) struct map_data map; char name[MAP_NAME_LENGTH_EXT]; + grf_list_file = aStrdup("conf/grf-files.txt"); + map_list_file = aStrdup("db/map_index.txt"); /* setup pre-defined, #define-dependant */ - sprintf(map_cache_file,"db/%s/map_cache.dat", -#ifdef RENEWAL - "re" -#else - "pre-re" -#endif - ); + map_cache_file = aStrdup("db/"DBPATH"map_cache.dat"); - // Process the command-line arguments - process_args(argc, argv); + cmdline->exec(argc, argv, CMDLINE_OPT_PREINIT); + cmdline->exec(argc, argv, CMDLINE_OPT_NORMAL); ShowStatus("Initializing grfio with %s\n", grf_list_file); grfio_init(grf_list_file); @@ -302,9 +341,14 @@ int do_init(int argc, char** argv) ShowInfo("%d maps now in cache\n", header.map_count); + aFree(grf_list_file); + aFree(map_list_file); + aFree(map_cache_file); + return 0; } -void do_final(void) +int do_final(void) { + return EXIT_SUCCESS; } |