diff options
Diffstat (limited to 'src/common/core.c')
-rw-r--r-- | src/common/core.c | 202 |
1 files changed, 139 insertions, 63 deletions
diff --git a/src/common/core.c b/src/common/core.c index ccd80c44b..5be90a411 100644 --- a/src/common/core.c +++ b/src/common/core.c @@ -2,8 +2,8 @@ * This file is part of Hercules. * http://herc.ws - http://github.com/HerculesWS/Hercules * - * Copyright (C) 2012-2015 Hercules Dev Team - * Copyright (C) Athena Dev Teams + * Copyright (C) 2012-2020 Hercules Dev Team + * Copyright (C) Athena Dev Teams * * Hercules is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,27 +23,29 @@ #include "config/core.h" #include "core.h" +#include "common/HPM.h" #include "common/cbasetypes.h" +#include "common/conf.h" #include "common/console.h" #include "common/db.h" +#include "common/des.h" +#include "common/ers.h" +#include "common/grfio.h" +#include "common/md5calc.h" #include "common/memmgr.h" #include "common/mmo.h" +#include "common/mutex.h" +#include "common/nullpo.h" +#include "common/packets.h" #include "common/random.h" #include "common/showmsg.h" +#include "common/socket.h" +#include "common/sql.h" #include "common/strlib.h" #include "common/sysinfo.h" -#include "common/nullpo.h" - -#ifndef MINICORE -# include "common/HPM.h" -# include "common/conf.h" -# include "common/ers.h" -# include "common/socket.h" -# include "common/sql.h" -# include "common/thread.h" -# include "common/timer.h" -# include "common/utils.h" -#endif +#include "common/thread.h" +#include "common/timer.h" +#include "common/utils.h" #ifndef _WIN32 # include <unistd.h> @@ -54,13 +56,31 @@ #include <stdio.h> #include <stdlib.h> -/// Called when a terminate signal is received. -void (*shutdown_callback)(void) = NULL; +/* + * Uncomment the line below if you want to silence the root warning on startup + * (not recommended, as it opens the machine to security risks. You should + * never ever run software as root unless it requires the extra privileges + * (which Hercules does not.) + * More info: + * http://www.tldp.org/HOWTO/Security-HOWTO/local-security.html + * http://www.gentoo.org/doc/en/security/security-handbook.xml?style=printable&part=1&chap=1#doc_chap4 + * http://wiki.centos.org/TipsAndTricks/BecomingRoot + * http://fedoraproject.org/wiki/Configuring_Sudo + * https://help.ubuntu.com/community/RootSudo + * http://www.freebsdwiki.net/index.php/Root + * + * If your service provider forces (or encourages) you to run server software + * as root, please complain to them before and after uncommenting this line, + * since it is a very bad idea. + * Please note that NO SUPPORT will be given if you uncomment the following line. + */ +//#define I_AM_AWARE_OF_THE_RISK_AND_STILL_WANT_TO_RUN_HERCULES_AS_ROOT +// And don't complain to us if the XYZ plugin you installed wiped your hard disk, or worse. +// Note: This feature is deprecated, and should not be used. -struct core_interface core_s; +static struct core_interface core_s; struct core_interface *core = &core_s; -#ifndef MINICORE // minimalist Core // Added by Gabuzomeu // // This is an implementation of signal() using sigaction() for portability. @@ -74,7 +94,8 @@ struct core_interface *core = &core_s; #ifndef POSIX #define compat_signal(signo, func) signal((signo), (func)) #else -sigfunc *compat_signal(int signo, sigfunc *func) { +static sigfunc *compat_signal(int signo, sigfunc *func) +{ struct sigaction sact, oact; sact.sa_handler = func; @@ -95,13 +116,14 @@ sigfunc *compat_signal(int signo, sigfunc *func) { * CORE : Console events for Windows *--------------------------------------*/ #ifdef _WIN32 -static BOOL WINAPI console_handler(DWORD c_event) { +static BOOL WINAPI console_handler(DWORD c_event) +{ switch(c_event) { case CTRL_CLOSE_EVENT: case CTRL_LOGOFF_EVENT: case CTRL_SHUTDOWN_EVENT: - if( shutdown_callback != NULL ) - shutdown_callback(); + if (core->shutdown_callback != NULL) + core->shutdown_callback(); else core->runflag = CORE_ST_STOP;// auto-shutdown break; @@ -111,7 +133,8 @@ static BOOL WINAPI console_handler(DWORD c_event) { return TRUE; } -static void cevents_init(void) { +static void cevents_init(void) +{ if (SetConsoleCtrlHandler(console_handler,TRUE)==FALSE) ShowWarning ("Unable to install the console handler!\n"); } @@ -120,7 +143,8 @@ static void cevents_init(void) { /*====================================== * CORE : Signal Sub Function *--------------------------------------*/ -static void sig_proc(int sn) { +static void sig_proc(int sn) +{ static int is_called = 0; switch (sn) { @@ -128,8 +152,8 @@ static void sig_proc(int sn) { case SIGTERM: if (++is_called > 3) exit(EXIT_SUCCESS); - if( shutdown_callback != NULL ) - shutdown_callback(); + if (core->shutdown_callback != NULL) + core->shutdown_callback(); else core->runflag = CORE_ST_STOP;// auto-shutdown break; @@ -153,7 +177,8 @@ static void sig_proc(int sn) { } } -void signals_init (void) { +static void signals_init(void) +{ compat_signal(SIGTERM, sig_proc); compat_signal(SIGINT, sig_proc); #ifndef _DEBUG // need unhandled exceptions to debug on Windows @@ -168,47 +193,90 @@ void signals_init (void) { compat_signal(SIGTRAP, SIG_DFL); #endif } -#endif /** * Warns the user if executed as superuser (root) + * + * @retval false if the check didn't pass and the program should be terminated. */ -void usercheck(void) { +static bool usercheck(void) +{ +#ifndef _WIN32 if (sysinfo->is_superuser()) { - ShowWarning("You are running Hercules with root privileges, it is not necessary.\n"); + if (!isatty(fileno(stdin))) { +#ifdef BUILDBOT + return true; +#else // BUILDBOT + ShowFatalError("You are running Hercules with root privileges, it is not necessary, nor recommended. " + "Aborting.\n"); + return false; // Don't allow noninteractive execution regardless. +#endif // BUILDBOT + } + ShowError("You are running Hercules with root privileges, it is not necessary, nor recommended.\n"); +#ifdef I_AM_AWARE_OF_THE_RISK_AND_STILL_WANT_TO_RUN_HERCULES_AS_ROOT +#ifndef BUILDBOT +#warning This Hercules build is not eligible to obtain support by the developers. +#warning The setting I_AM_AWARE_OF_THE_RISK_AND_STILL_WANT_TO_RUN_HERCULES_AS_ROOT is deprecated and should not be used. +#endif // BUILDBOT +#else // not I_AM_AWARE_OF_THE_RISK_AND_STILL_WANT_TO_RUN_HERCULES_AS_ROOT + ShowNotice("Execution will be paused for 60 seconds. Press Ctrl-C if you wish to quit.\n"); + ShowNotice("If you want to get rid of this message, please open %s and uncomment, near the top, the line saying:\n" + "\t\"//#define I_AM_AWARE_OF_THE_RISK_AND_STILL_WANT_TO_RUN_HERCULES_AS_ROOT\"\n", __FILE__); + ShowNotice("Note: In a near future, this courtesy notice will go away. " + "Please update your infrastructure not to require root privileges before then.\n"); + ShowWarning("It's recommended that you " CL_WHITE "press CTRL-C now!" CL_RESET "\n"); + { + int i; + for (i = 0; i < 60; i++) { + ShowMessage("\a *"); + HSleep(1); + } + } + ShowMessage("\n"); + ShowNotice("Resuming operations with root privileges. " + CL_RED "If anything breaks, you get to keep the pieces, " + "and the Hercules developers won't be able to help you." + CL_RESET "\n"); +#endif // I_AM_AWARE_OF_THE_RISK_AND_STILL_WANT_TO_RUN_HERCULES_AS_ROOT } +#endif // not _WIN32 + return true; } -void core_defaults(void) { +static void core_defaults(void) +{ nullpo_defaults(); -#ifndef MINICORE hpm_defaults(); HCache_defaults(); -#endif sysinfo_defaults(); console_defaults(); strlib_defaults(); malloc_defaults(); showmsg_defaults(); cmdline_defaults(); -#ifndef MINICORE + des_defaults(); + grfio_defaults(); // Note: grfio is lazily loaded. grfio->init() and grfio->final() are not automatically called. + mutex_defaults(); libconfig_defaults(); sql_defaults(); timer_defaults(); db_defaults(); socket_defaults(); -#endif + packets_defaults(); + rnd_defaults(); + md5_defaults(); + thread_defaults(); } + /** * 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 +static const char *cmdline_arg_source(struct CmdlineArgData *arg) +{ + nullpo_retr(NULL, arg); return HPM->pid2name(arg->pluginID); -#endif // MINICORE } + /** * Defines a command line argument. * @@ -220,9 +288,11 @@ const char *cmdline_arg_source(struct CmdlineArgData *arg) { * @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) { +static bool cmdline_arg_add(unsigned int pluginID, const char *name, char shortname, CmdlineExecFunc func, const char *help, unsigned int options) +{ struct CmdlineArgData *data = NULL; + nullpo_retr(false, name); VECTOR_ENSURE(cmdline->args_data, 1, 1); VECTOR_PUSHZEROED(cmdline->args_data); data = &VECTOR_LAST(cmdline->args_data); @@ -238,6 +308,7 @@ bool cmdline_arg_add(unsigned int pluginID, const char *name, char shortname, Cm return true; } + /** * Help screen to be displayed by '--help'. */ @@ -261,6 +332,7 @@ static CMDLINEARG(help) } return false; } + /** * Info screen to be displayed by '--version'. */ @@ -271,6 +343,7 @@ static CMDLINEARG(version) 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 * @@ -279,7 +352,7 @@ static CMDLINEARG(version) * @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) +static 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); @@ -288,6 +361,7 @@ bool cmdline_arg_next_value(const char *name, int current_arg, int argc) return true; } + /** * Executes the command line arguments handlers. * @@ -306,14 +380,18 @@ bool cmdline_arg_next_value(const char *name, int current_arg, int argc) * 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) +static int cmdline_exec(int argc, char **argv, unsigned int options) { int count = 0, i; + + nullpo_ret(argv); for (i = 1; i < argc; i++) { int j; struct CmdlineArgData *data = NULL; const char *arg = argv[i]; if (arg[0] != '-') { // All arguments must begin with '-' + if ((options&(CMDLINE_OPT_SILENT|CMDLINE_OPT_PREINIT)) != 0) + continue; ShowError("Invalid option '%s'.\n", argv[i]); exit(EXIT_FAILURE); } @@ -351,24 +429,19 @@ int cmdline_exec(int argc, char **argv, unsigned int options) } return count; } + /** * Defines the global command-line arguments. */ -void cmdline_init(void) +static 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) +static void cmdline_final(void) { while (VECTOR_LENGTH(cmdline->args_data) > 0) { struct CmdlineArgData *data = &VECTOR_POP(cmdline->args_data); @@ -378,7 +451,7 @@ void cmdline_final(void) VECTOR_CLEAR(cmdline->args_data); } -struct cmdline_interface cmdline_s; +static struct cmdline_interface cmdline_s; struct cmdline_interface *cmdline; void cmdline_defaults(void) @@ -394,10 +467,12 @@ void cmdline_defaults(void) cmdline->arg_next_value = cmdline_arg_next_value; cmdline->arg_source = cmdline_arg_source; } + /*====================================== * CORE : MAINROUTINE *--------------------------------------*/ -int main (int argc, char **argv) { +int main(int argc, char **argv) +{ int retval = EXIT_SUCCESS; {// initialize program arguments char *p1 = SERVER_NAME = argv[0]; @@ -414,6 +489,7 @@ int main (int argc, char **argv) { iMalloc->init();// needed for Show* in display_title() [FlavioJS] showmsg->init(); + nullpo->init(); cmdline->init(); @@ -426,16 +502,13 @@ int main (int argc, char **argv) { if (!(showmsg->silent&0x1)) console->display_title(); - usercheck(); + if (!usercheck()) + return EXIT_FAILURE; -#ifdef MINICORE // minimalist Core - do_init(argc,argv); - do_final(); -#else// not MINICORE set_server_type(); Sql_Init(); - rathread_init(); + thread->init(); DB->init(); signals_init(); @@ -446,8 +519,7 @@ int main (int argc, char **argv) { timer->init(); /* timer first */ - rnd_init(); - srand((unsigned int)timer->gettick()); + rnd->init(); console->init(); @@ -457,6 +529,8 @@ int main (int argc, char **argv) { sockt->init(); + packets->init(); + do_init(argc,argv); // Main runtime cycle @@ -470,14 +544,16 @@ int main (int argc, char **argv) { retval = do_final(); HPM->final(); timer->final(); + packets->final(); sockt->final(); DB->final(); - rathread_final(); + thread->final(); ers_final(); -#endif + rnd->final(); cmdline->final(); //sysinfo->final(); Called by iMalloc->final() + nullpo->final(); iMalloc->final(); showmsg->final(); // Should be after iMalloc->final() |