summaryrefslogtreecommitdiff
path: root/src/common/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/core.c')
-rw-r--r--src/common/core.c202
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()