core.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. // Copyright (c) Athena Dev Teams - Licensed under GNU GPL
  2. // For more information, see LICENCE in the main folder
  3. #include "../common/mmo.h"
  4. #include "../common/version.h"
  5. #include "../common/showmsg.h"
  6. #include "../common/malloc.h"
  7. #include "core.h"
  8. #ifndef MINICORE
  9. #include "../common/db.h"
  10. #include "../common/socket.h"
  11. #include "../common/timer.h"
  12. #include "../common/plugins.h"
  13. #endif
  14. #ifndef _WIN32
  15. #include "svnversion.h"
  16. #endif
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <signal.h>
  20. #include <string.h>
  21. #ifndef _WIN32
  22. #include <unistd.h>
  23. #endif
  24. /// Called when a terminate signal is received.
  25. void (*shutdown_callback)(void) = NULL;
  26. int runflag = CORE_ST_RUN;
  27. int arg_c = 0;
  28. char **arg_v = NULL;
  29. char *SERVER_NAME = NULL;
  30. char SERVER_TYPE = ATHENA_SERVER_NONE;
  31. #ifndef SVNVERSION
  32. static char eA_svn_version[10] = "";
  33. #endif
  34. #ifndef MINICORE // minimalist Core
  35. // Added by Gabuzomeu
  36. //
  37. // This is an implementation of signal() using sigaction() for portability.
  38. // (sigaction() is POSIX; signal() is not.) Taken from Stevens' _Advanced
  39. // Programming in the UNIX Environment_.
  40. //
  41. #ifdef WIN32 // windows don't have SIGPIPE
  42. #define SIGPIPE SIGINT
  43. #endif
  44. #ifndef POSIX
  45. #define compat_signal(signo, func) signal(signo, func)
  46. #else
  47. sigfunc *compat_signal(int signo, sigfunc *func)
  48. {
  49. struct sigaction sact, oact;
  50. sact.sa_handler = func;
  51. sigemptyset(&sact.sa_mask);
  52. sact.sa_flags = 0;
  53. #ifdef SA_INTERRUPT
  54. sact.sa_flags |= SA_INTERRUPT; /* SunOS */
  55. #endif
  56. if (sigaction(signo, &sact, &oact) < 0)
  57. return (SIG_ERR);
  58. return (oact.sa_handler);
  59. }
  60. #endif
  61. /*======================================
  62. * CORE : Signal Sub Function
  63. *--------------------------------------*/
  64. static void sig_proc(int sn)
  65. {
  66. static int is_called = 0;
  67. switch (sn) {
  68. case SIGINT:
  69. case SIGTERM:
  70. if (++is_called > 3)
  71. exit(EXIT_SUCCESS);
  72. if( shutdown_callback != NULL )
  73. shutdown_callback();
  74. else
  75. runflag = CORE_ST_STOP;// auto-shutdown
  76. break;
  77. case SIGSEGV:
  78. case SIGFPE:
  79. do_abort();
  80. // Pass the signal to the system's default handler
  81. compat_signal(sn, SIG_DFL);
  82. raise(sn);
  83. break;
  84. #ifndef _WIN32
  85. case SIGXFSZ:
  86. // ignore and allow it to set errno to EFBIG
  87. ShowWarning ("Max file size reached!\n");
  88. //run_flag = 0; // should we quit?
  89. break;
  90. case SIGPIPE:
  91. //ShowInfo ("Broken pipe found... closing socket\n"); // set to eof in socket.c
  92. break; // does nothing here
  93. #endif
  94. }
  95. }
  96. void signals_init (void)
  97. {
  98. compat_signal(SIGTERM, sig_proc);
  99. compat_signal(SIGINT, sig_proc);
  100. #ifndef _DEBUG // need unhandled exceptions to debug on Windows
  101. compat_signal(SIGSEGV, sig_proc);
  102. compat_signal(SIGFPE, sig_proc);
  103. #endif
  104. #ifndef _WIN32
  105. compat_signal(SIGILL, SIG_DFL);
  106. compat_signal(SIGXFSZ, sig_proc);
  107. compat_signal(SIGPIPE, sig_proc);
  108. compat_signal(SIGBUS, SIG_DFL);
  109. compat_signal(SIGTRAP, SIG_DFL);
  110. #endif
  111. }
  112. #endif
  113. #ifdef SVNVERSION
  114. #define xstringify(x) stringify(x)
  115. #define stringify(x) #x
  116. const char *get_svn_revision(void)
  117. {
  118. return xstringify(SVNVERSION);
  119. }
  120. #else// not SVNVERSION
  121. const char* get_svn_revision(void)
  122. {
  123. FILE *fp;
  124. if(*eA_svn_version)
  125. return eA_svn_version;
  126. if ((fp = fopen(".svn/entries", "r")) != NULL)
  127. {
  128. char line[1024];
  129. int rev;
  130. // Check the version
  131. if (fgets(line, sizeof(line), fp))
  132. {
  133. if(!ISDIGIT(line[0]))
  134. {
  135. // XML File format
  136. while (fgets(line,sizeof(line),fp))
  137. if (strstr(line,"revision=")) break;
  138. if (sscanf(line," %*[^\"]\"%d%*[^\n]", &rev) == 1) {
  139. snprintf(eA_svn_version, sizeof(eA_svn_version), "%d", rev);
  140. }
  141. }
  142. else
  143. {
  144. // Bin File format
  145. fgets(line, sizeof(line), fp); // Get the name
  146. fgets(line, sizeof(line), fp); // Get the entries kind
  147. if(fgets(line, sizeof(line), fp)) // Get the rev numver
  148. {
  149. snprintf(eA_svn_version, sizeof(eA_svn_version), "%d", atoi(line));
  150. }
  151. }
  152. }
  153. fclose(fp);
  154. }
  155. if(!(*eA_svn_version))
  156. snprintf(eA_svn_version, sizeof(eA_svn_version), "Unknown");
  157. return eA_svn_version;
  158. }
  159. #endif
  160. /*======================================
  161. * CORE : Display title
  162. * ASCII By CalciumKid 1/12/2011
  163. *--------------------------------------*/
  164. static void display_title(void)
  165. {
  166. //ClearScreen(); // clear screen and go up/left (0, 0 position in text)
  167. ShowMessage("\n");
  168. ShowMessage(""CL_PASS" "CL_BOLD" "CL_PASS""CL_CLL""CL_NORMAL"\n");
  169. ShowMessage(""CL_PASS" "CL_BT_WHITE" RAthena Development Team presents "CL_PASS""CL_CLL""CL_NORMAL"\n");
  170. ShowMessage(""CL_PASS" "CL_BOLD" ____ ___ __ __ "CL_PASS""CL_CLL""CL_NORMAL"\n");
  171. ShowMessage(""CL_PASS" "CL_BOLD" / __ \\/ | / /_/ /_ ___ ____ ____ _ "CL_PASS""CL_CLL""CL_NORMAL"\n");
  172. ShowMessage(""CL_PASS" "CL_BOLD" / /_/ / /| |/ __/ __ \\/ _ \\/ __ \\/ __ `/ "CL_PASS""CL_CLL""CL_NORMAL"\n");
  173. ShowMessage(""CL_PASS" "CL_BOLD" / _, _/ ___ / /_/ / / / __/ / / / /_/ / "CL_PASS""CL_CLL""CL_NORMAL"\n");
  174. ShowMessage(""CL_PASS" "CL_BOLD" /_/ |_/_/ |_\\__/_/ /_/\\___/_/ /_/\\___,_/ "CL_PASS""CL_CLL""CL_NORMAL"\n");
  175. ShowMessage(""CL_PASS" "CL_BOLD" "CL_PASS""CL_CLL""CL_NORMAL"\n");
  176. ShowMessage(""CL_PASS" "CL_GREEN" http://rathena.org/board/ "CL_PASS""CL_CLL""CL_NORMAL"\n");
  177. ShowMessage(""CL_PASS" "CL_BOLD" "CL_PASS""CL_CLL""CL_NORMAL"\n");
  178. ShowInfo("SVN Revision: '"CL_WHITE"%s"CL_RESET"'.\n", get_svn_revision());
  179. }
  180. // Warning if logged in as superuser (root)
  181. void usercheck(void)
  182. {
  183. #ifndef _WIN32
  184. if ((getuid() == 0) && (getgid() == 0)) {
  185. ShowWarning ("You are running rAthena with root privileges, it is not necessary.\n");
  186. }
  187. #endif
  188. }
  189. /*======================================
  190. * CORE : MAINROUTINE
  191. *--------------------------------------*/
  192. int main (int argc, char **argv)
  193. {
  194. {// initialize program arguments
  195. char *p1 = SERVER_NAME = argv[0];
  196. char *p2 = p1;
  197. while ((p1 = strchr(p2, '/')) != NULL || (p1 = strchr(p2, '\\')) != NULL)
  198. {
  199. SERVER_NAME = ++p1;
  200. p2 = p1;
  201. }
  202. arg_c = argc;
  203. arg_v = argv;
  204. }
  205. malloc_init();// needed for Show* in display_title() [FlavioJS]
  206. #ifdef MINICORE // minimalist Core
  207. display_title();
  208. usercheck();
  209. do_init(argc,argv);
  210. do_final();
  211. #else// not MINICORE
  212. set_server_type();
  213. display_title();
  214. usercheck();
  215. db_init();
  216. signals_init();
  217. timer_init();
  218. socket_init();
  219. plugins_init();
  220. do_init(argc,argv);
  221. plugin_event_trigger(EVENT_ATHENA_INIT);
  222. {// Main runtime cycle
  223. int next;
  224. while (runflag != CORE_ST_STOP) {
  225. next = do_timer(gettick_nocache());
  226. do_sockets(next);
  227. }
  228. }
  229. plugin_event_trigger(EVENT_ATHENA_FINAL);
  230. do_final();
  231. timer_final();
  232. plugins_final();
  233. socket_final();
  234. db_final();
  235. #endif
  236. malloc_final();
  237. return 0;
  238. }