
git-svn-id: https://svn.code.sf.net/p/rathena/svn/branches/stable@1308 54d463be-8e91-2dee-dedb-b68131a5f0ec
324 lines
9.1 KiB
C
324 lines
9.1 KiB
C
// $Id: core.c,v 1.1.1.1 2004/09/10 17:44:49 MagicalTux Exp $
|
||
// original : core.c 2003/02/26 18:03:12 Rev 1.7
|
||
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#ifndef _WIN32
|
||
#include <unistd.h>
|
||
#endif
|
||
#include <signal.h>
|
||
#include <string.h>
|
||
#ifdef DUMPSTACK
|
||
#ifndef CYGWIN // HAVE_EXECINFO_H
|
||
#include <execinfo.h>
|
||
#endif
|
||
#endif
|
||
|
||
#include "../common/mmo.h"
|
||
#include "malloc.h"
|
||
#include "core.h"
|
||
#include "socket.h"
|
||
#include "timer.h"
|
||
#include "version.h"
|
||
#include "showmsg.h"
|
||
|
||
#ifdef MEMWATCH
|
||
#include "memwatch.h"
|
||
#endif
|
||
|
||
char server_type[24];
|
||
int runflag = 1;
|
||
unsigned long ticks = 0; // by MC Cameri
|
||
char pid_file[256];
|
||
static void (*term_func)(void)=NULL;
|
||
|
||
/*======================================
|
||
* CORE : Set function
|
||
*--------------------------------------
|
||
*/
|
||
void set_termfunc(void (*termfunc)(void))
|
||
{
|
||
term_func = termfunc;
|
||
}
|
||
|
||
// Added by Gabuzomeu
|
||
//
|
||
// This is an implementation of signal() using sigaction() for portability.
|
||
// (sigaction() is POSIX; signal() is not.) Taken from Stevens' _Advanced
|
||
// Programming in the UNIX Environment_.
|
||
//
|
||
#ifndef SIGPIPE
|
||
#define SIGPIPE SIGINT
|
||
#endif
|
||
|
||
#ifndef POSIX
|
||
#define compat_signal(signo, func) signal(signo, func)
|
||
#else
|
||
sigfunc *compat_signal(int signo, sigfunc *func)
|
||
{
|
||
struct sigaction sact, oact;
|
||
|
||
sact.sa_handler = func;
|
||
sigemptyset(&sact.sa_mask);
|
||
sact.sa_flags = 0;
|
||
#ifdef SA_INTERRUPT
|
||
sact.sa_flags |= SA_INTERRUPT; /* SunOS */
|
||
#endif
|
||
|
||
if (sigaction(signo, &sact, &oact) < 0)
|
||
return (SIG_ERR);
|
||
|
||
return (oact.sa_handler);
|
||
}
|
||
#endif
|
||
|
||
/*======================================
|
||
* CORE : Signal Sub Function
|
||
*--------------------------------------
|
||
*/
|
||
// for handling certain signals ourselves, like SIGPIPE
|
||
static void sig_ignore(int sn) {
|
||
printf ("Broken pipe found... closing socket\n"); // set to eof in socket.c
|
||
return; // does nothing here
|
||
}
|
||
static void sig_proc(int sn)
|
||
{
|
||
int i;
|
||
static int is_called = 0;
|
||
|
||
if(is_called++)
|
||
return;
|
||
|
||
switch(sn){
|
||
case SIGINT:
|
||
case SIGTERM:
|
||
if(term_func)
|
||
term_func();
|
||
for(i=0;i<fd_max;i++){
|
||
if(!session[i])
|
||
continue;
|
||
close(i);
|
||
}
|
||
exit(0);
|
||
break;
|
||
}
|
||
}
|
||
|
||
/*=========================================
|
||
* Dumps the stack using glibc's backtrace
|
||
*-----------------------------------------
|
||
*/
|
||
#ifndef DUMPSTACK
|
||
#define sig_dump SIG_DFL
|
||
#else
|
||
#ifdef CYGWIN
|
||
#define FOPEN_ freopen
|
||
extern void cygwin_stackdump();
|
||
#else
|
||
#define FOPEN_(fn,m,s) fopen(fn,m)
|
||
#endif
|
||
extern const char *strsignal(int);
|
||
void sig_dump(int sn)
|
||
{
|
||
FILE *fp;
|
||
char file[256];
|
||
int no = 0;
|
||
|
||
#ifndef CYGWIN
|
||
void* array[20];
|
||
char **stack;
|
||
size_t size;
|
||
#endif
|
||
|
||
// search for a usable filename
|
||
do {
|
||
sprintf (file, "log/%s%04d.stackdump", server_type, ++no);
|
||
} while((fp = fopen(file,"r")) && (fclose(fp), no < 9999));
|
||
// dump the trace into the file
|
||
|
||
if ((fp = FOPEN_(file, "w", stderr)) != NULL) {
|
||
printf ("Dumping stack... ");
|
||
fprintf(fp, "Exception: %s \n", strsignal(sn));
|
||
fflush (fp);
|
||
|
||
#ifdef CYGWIN
|
||
cygwin_stackdump ();
|
||
#else
|
||
fprintf(fp, "Stack trace:\n");
|
||
size = backtrace (array, 20);
|
||
stack = backtrace_symbols (array, size);
|
||
for (no = 0; no < size; no++) {
|
||
fprintf(fp, "%s\n", stack[no]);
|
||
}
|
||
fprintf(fp,"End of stack trace\n");
|
||
aFree(stack);
|
||
#endif
|
||
|
||
printf ("Done.\n");
|
||
fflush(stdout);
|
||
fclose(fp);
|
||
}
|
||
// Pass the signal to the system's default handler
|
||
compat_signal(sn, SIG_DFL);
|
||
raise(sn);
|
||
}
|
||
#endif
|
||
|
||
int get_svn_revision(char *svnentry) { // Warning: minor syntax checking
|
||
char line[1024];
|
||
int rev = 0;
|
||
FILE *fp;
|
||
if ((fp = fopen(svnentry, "r")) == NULL) {
|
||
return 0;
|
||
} else {
|
||
while (fgets(line,1023,fp)) if (strstr(line,"revision=")) break;
|
||
fclose(fp);
|
||
if (sscanf(line," %*[^\"]\"%d%*[^\n]",&rev)==1)
|
||
return rev;
|
||
else
|
||
return 0;
|
||
}
|
||
// return 0;
|
||
}
|
||
|
||
/*======================================
|
||
* CORE : Display title
|
||
*--------------------------------------
|
||
*/
|
||
|
||
static void display_title(void)
|
||
{
|
||
int revision;
|
||
// for help with the console colors look here:
|
||
// http://www.edoceo.com/liberum/?doc=printf-with-color
|
||
// some code explanation (used here):
|
||
// \033[2J : clear screen and go up/left (0, 0 position)
|
||
// \033[K : clear line from actual position to end of the line
|
||
// \033[0m : reset color parameter
|
||
// \033[1m : use bold for font
|
||
printf("\033[2J"); // clear screen and go up/left (0, 0 position in text)
|
||
printf("\033[37;44m (=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=)\033[K\033[0m\n"); // white writing (37) on blue background (44), \033[K clean until end of file
|
||
printf("\033[0;44m (\033[1;33m (c)2005 eAthena Development Team presents \033[0;44m)\033[K\033[0m\n"); // yellow writing (33)
|
||
printf("\033[0;44m (\033[1m ______ __ __ \033[0;44m)\033[K\033[0m\n"); // 1: bold char, 0: normal char
|
||
printf("\033[0;44m (\033[1m /\\ _ \\/\\ \\__/\\ \\ v%2d.%02d.%02d \033[0;44m)\033[K\033[0m\n", ATHENA_MAJOR_VERSION, ATHENA_MINOR_VERSION, ATHENA_REVISION); // 1: bold char, 0: normal char
|
||
printf("\033[0;44m (\033[1m __\\ \\ \\_\\ \\ \\ ,_\\ \\ \\___ __ ___ __ \033[0;44m)\033[K\033[0m\n"); // 1: bold char, 0: normal char
|
||
printf("\033[0;44m (\033[1m /'__`\\ \\ __ \\ \\ \\/\\ \\ _ `\\ /'__`\\/' _ `\\ /'__`\\ \033[0;44m)\033[K\033[0m\n"); // 1: bold char, 0: normal char
|
||
printf("\033[0;44m (\033[1m /\\ __/\\ \\ \\/\\ \\ \\ \\_\\ \\ \\ \\ \\/\\ __//\\ \\/\\ \\/\\ \\_\\.\\_ \033[0;44m)\033[K\033[0m\n"); // 1: bold char, 0: normal char
|
||
printf("\033[0;44m (\033[1m \\ \\____\\\\ \\_\\ \\_\\ \\__\\\\ \\_\\ \\_\\ \\____\\ \\_\\ \\_\\ \\__/.\\_\\ \033[0;44m)\033[K\033[0m\n"); // 1: bold char, 0: normal char
|
||
printf("\033[0;44m (\033[1m \\/____/ \\/_/\\/_/\\/__/ \\/_/\\/_/\\/____/\\/_/\\/_/\\/__/\\/_/ \033[0;44m)\033[K\033[0m\n"); // 1: bold char, 0: normal char
|
||
printf("\033[0;44m (\033[1m _ _ _ _ _ _ _ _ _ _ _ _ _ \033[0;44m)\033[K\033[0m\n"); // 1: bold char, 0: normal char
|
||
printf("\033[0;44m (\033[1m / \\ / \\ / \\ / \\ / \\ / \\ / \\ / \\ / \\ / \\ / \\ / \\ / \\ \033[0;44m)\033[K\033[0m\n"); // 1: bold char, 0: normal char
|
||
printf("\033[0;44m (\033[1m ( e | n | g | l | i | s | h ) ( A | t | h | e | n | a ) \033[0;44m)\033[K\033[0m\n"); // 1: bold char, 0: normal char
|
||
printf("\033[0;44m (\033[1m \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \033[0;44m)\033[K\033[0m\n"); // 1: bold char, 0: normal char
|
||
printf("\033[0;44m (\033[1m \033[0;44m)\033[K\033[0m\n"); // yellow writing (33)
|
||
printf("\033[0;44m (\033[1;33m Advanced Fusion Maps (c) 2003-2005 The Fusion Project \033[0;44m)\033[K\033[0m\n"); // yellow writing (33)
|
||
printf("\033[37;44m (=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=)\033[K\033[0m\n\n"); // reset color
|
||
|
||
if ((revision = get_svn_revision(".svn\\entries"))>0) {
|
||
snprintf(tmp_output,sizeof(tmp_output),"SVN Revision: '"CL_WHITE"%d"CL_RESET"'.\n",revision);
|
||
ShowInfo(tmp_output);
|
||
}
|
||
}
|
||
|
||
/*======================================
|
||
* CORE : MAINROUTINE
|
||
*--------------------------------------
|
||
*/
|
||
|
||
void pid_delete(void) {
|
||
unlink(pid_file);
|
||
}
|
||
|
||
void pid_create(const char* file) {
|
||
FILE *fp;
|
||
int len = strlen(file);
|
||
strcpy(pid_file,file);
|
||
if(len > 4 && pid_file[len - 4] == '.') {
|
||
pid_file[len - 4] = 0;
|
||
}
|
||
strcat(pid_file,".pid");
|
||
fp = fopen(pid_file,"w");
|
||
if(fp) {
|
||
#ifdef _WIN32
|
||
fprintf(fp,"%d",GetCurrentProcessId());
|
||
#else
|
||
fprintf(fp,"%d",getpid());
|
||
#endif
|
||
fclose(fp);
|
||
atexit(pid_delete);
|
||
}
|
||
}
|
||
|
||
#define LOG_UPTIME 0
|
||
void log_uptime()
|
||
{
|
||
#if LOG_UPTIME
|
||
time_t curtime;
|
||
char curtime2[24];
|
||
FILE *fp;
|
||
long seconds = 0, day = 24*60*60, hour = 60*60,
|
||
minute = 60, days = 0, hours = 0, minutes = 0;
|
||
|
||
fp = fopen("log/uptime.log","a");
|
||
if (fp) {
|
||
time(&curtime);
|
||
strftime(curtime2, 24, "%m/%d/%Y %H:%M:%S", localtime(&curtime));
|
||
|
||
seconds = (gettick()-ticks)/CLOCKS_PER_SEC;
|
||
days = seconds/day;
|
||
seconds -= (seconds/day>0)?(seconds/day)*day:0;
|
||
hours = seconds/hour;
|
||
seconds -= (seconds/hour>0)?(seconds/hour)*hour:0;
|
||
minutes = seconds/minute;
|
||
seconds -= (seconds/minute>0)?(seconds/minute)*minute:0;
|
||
|
||
fprintf(fp, "%s: %s uptime - %ld days, %ld hours, %ld minutes, %ld seconds.\n",
|
||
curtime2, server_type, days, hours, minutes, seconds);
|
||
fclose(fp);
|
||
}
|
||
|
||
return;
|
||
#endif
|
||
}
|
||
|
||
int main(int argc,char **argv)
|
||
{
|
||
int next;
|
||
|
||
display_title();
|
||
// call this first so it'll be finalised last
|
||
do_init_memmgr(argv[0]); // <20><><EFBFBD>ԍŏ<D48D><C58F>Ɏ<EFBFBD><C98E>s<EFBFBD><73><EFBFBD><EFBFBD><EFBFBD>K<EFBFBD>v<EFBFBD><76><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
|
||
sscanf(argv[0], "./%24[^\n]", server_type); // map/char/login?
|
||
atexit(log_uptime);
|
||
pid_create(argv[0]);
|
||
|
||
Net_Init();
|
||
do_socket();
|
||
|
||
compat_signal(SIGPIPE, sig_ignore);
|
||
compat_signal(SIGTERM,sig_proc);
|
||
compat_signal(SIGINT,sig_proc);
|
||
|
||
// Signal to create coredumps by system when necessary (crash)
|
||
compat_signal(SIGSEGV, sig_dump);
|
||
compat_signal(SIGFPE, sig_dump);
|
||
compat_signal(SIGILL, sig_dump);
|
||
#ifndef _WIN32
|
||
compat_signal(SIGBUS, sig_dump);
|
||
compat_signal(SIGTRAP, SIG_DFL);
|
||
#endif
|
||
|
||
tick_ = time(0);
|
||
ticks = gettick();
|
||
|
||
do_init(argc,argv);
|
||
while(runflag){
|
||
next=do_timer(gettick_nocache());
|
||
do_sendrecv(next);
|
||
do_parsepacket();
|
||
}
|
||
|
||
return 0;
|
||
}
|