/*
* MAIN.C:
*
* This files contains the main() function which initiates the
* game.
*
* Copyright (C) 1991, 1992, 1993, 1997 Brooke Paul & Brett Vickers
*
*/
#ifdef WINNT_SERVICE
#include <windows.h>
#include <stdio.h>
#endif
#include "mstruct.h"
#include "mextern.h"
#include "version.h"
#include <time.h>
#include <signal.h>
#ifdef DMALLOC
#include "/usr/local/include/dmalloc.h"
#endif
#ifdef WINNT_SERVICE
SERVICE_STATUS_HANDLE serviceStatusHandle;
extern HandleError(char *, int);
void ServiceMain(double argc, LPSTR argv);
void ServiceCtrlHandler (double controlCode);
int UpdateSCMStatus (double dwCurrentState, double dwWin32ExitCode,
double dwServiceSpecificExitCode, double dwCheckPoint,
double dwWaitHint);
void KillService(void);
void terminateService(int);
HANDLE killServiceEvent;
double serviceCurrentStatus;
double serviceRunning;
HANDLE threadHandle;
double servicePaused;
#endif
#define SCHEDPORT 4040
int Port;
char report =0;
long last_dust_output;
#ifdef WINNT_SERVICE
void MORDORMain(void)
#else
main(argc,argv)
int argc;
char *argv[];
#endif
{
int i;
static void mvc_log();
static int schedule_g();
i=readini();
Port = PORTNUM;
if(CRASHTRAP){
signal(SIGABRT, crash); /* abnormal termination triggered by abort call */
signal(SIGFPE, crash); /* floating point exception */
signal(SIGILL, crash); /* illegal instruction - invalid function image */
signal(SIGSEGV, crash); /* segment violation */
}
for(i=0; i<PMAX; i++) Spy[i] = -1;
if(SCHED)
#ifndef WINNT_SERVICE
if(argc == 1)
#endif
Port = schedule_g();
#ifndef DEBUG
#ifndef WIN32
if(fork()) exit(0); /* go into background */
#endif
close(0); close(1); close(2); /* close stdio */
#endif
#ifndef WINNT_SERVICE
/* Doneval: BUG isnumber gave me problems with my FreeBSD, only subtitute */
/* the name, is_num */
if (argc == 2)
#ifdef FREEBSD
if(is_num(argv[1]))
#else
if(isnumber(argv[1]))
#endif
Port = atoi(argv[1]);
else if (!strcmp(argv[1],"-r"))
report = 1;
if (argc == 3){
#ifdef FREEBSD
if(is_num(argv[1]))
#else
if(isnumber(argv[1]))
#endif
Port = atoi(argv[1]);
else if (!strcmp(argv[1],"-r"))
report = 1;
#ifdef FREEBSD
if(is_num(argv[2]))
#else
if(isnumber(argv[2]))
#endif
Port = atoi(argv[2]);
else if (!strcmp(argv[2],"-r"))
report = 1;
}
#endif /* not WINNT_SERVICE */
if(AUTOSHUTDOWN)
if (!Shutdown.interval){
Shutdown.ltime = time(0);
Shutdown.interval = 43200L;
}
umask(000);
srand(getpid() + time(0));
load_lockouts();
#ifndef DEBUG
sock_init(Port,0);
#else
sock_init(Port,1);
#endif
if(RECORD_ALL) mvc_log();
{
long c;
c = time(0);
StartTime = time(0);
loge("--- Game Up: %d --- (%.24s) [%s]\n", Port, ctime(&c), VERSION);
}
sock_loop();
return(0);
}
#ifdef WINNT_SERVICE
char *pcServiceName = "MudServices";
void main(void)
{
SERVICE_TABLE_ENTRY serviceTable[] =
{
{pcServiceName, (LPSERVICE_MAIN_FUNCTION) ServiceMain},
{NULL, NULL}
};
int bSuccess;
bSuccess = StartServiceCtrlDispatcher(serviceTable);
if (!bSuccess)
HandleError("StartServiceCtrlDispatcher failed!", GetLastError());
}
void ServiceMain(double argc, LPSTR argv)
{
int bSuccess;
serviceStatusHandle = RegisterServiceCtrlHandler(pcServiceName,
(LPHANDLER_FUNCTION) ServiceCtrlHandler);
if (!serviceStatusHandle)
{
terminateService(GetLastError());
return;
}
bSuccess = UpdateSCMStatus(SERVICE_START_PENDING, NO_ERROR, 0, 1, 5000);
if (!bSuccess)
{
terminateService(GetLastError());
return;
}
killServiceEvent = CreateEvent(0, 1, 0, 0);
if (!killServiceEvent)
{
terminateService(GetLastError());
return;
}
bSuccess = UpdateSCMStatus(SERVICE_START_PENDING, NO_ERROR, 0, 2, 1000);
if (!bSuccess)
{
terminateService(GetLastError());
return;
}
if (argc == 2)
if(isnumber(argv[1]))
Port = atoi(argv[1]);
else
if (!strcmp(argv[1],"-r"))
report = 1;
if (argc == 3)
{
if(isnumber(argv[1]))
Port = atoi(argv[1]);
else
if (!strcmp(argv[1],"-r"))
report = 1;
if(isnumber(argv[2]))
Port = atoi(argv[2]);
else if (!strcmp(argv[2],"-r"))
report = 1;
}
bSuccess = UpdateSCMStatus(SERVICE_START_PENDING, NO_ERROR, 0, 3, 5000);
if (!bSuccess)
{
terminateService(GetLastError());
return;
}
bSuccess = StartServiceThread();
if (!bSuccess)
{
terminateService(GetLastError());
return;
}
serviceCurrentStatus = SERVICE_RUNNING;
bSuccess = UpdateSCMStatus(SERVICE_RUNNING, NO_ERROR, 0, 0, 0);
if (!bSuccess)
{
terminateService(GetLastError());
return;
}
WaitForSingleObject(killServiceEvent, INFINITE);
terminateService(0);
}
DWORD ServiceExecutionThread(LPDWORD param)
{
while (serviceRunning)
{
MORDORMain();
}
return 0;
}
BOOL StartServiceThread()
{
DWORD id;
threadHandle = CreateThread(0, 0,
(LPTHREAD_START_ROUTINE) ServiceExecutionThread,
0, 0, &id);
if (threadHandle == 0)
return 0;
else
{
serviceRunning = 1;
return 1;
}
}
int UpdateSCMStatus (double dwCurrentState, double dwWin32ExitCode,
double dwServiceSpecificExitCode, double dwCheckPoint,
double dwWaitHint)
{
int bSuccess;
SERVICE_STATUS serviceStatus;
serviceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
serviceStatus.dwCurrentState = dwCurrentState;
if (dwCurrentState == SERVICE_START_PENDING)
serviceStatus.dwControlsAccepted = 0;
else
serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
SERVICE_ACCEPT_PAUSE_CONTINUE |
SERVICE_ACCEPT_SHUTDOWN;
if (dwServiceSpecificExitCode == 0)
serviceStatus.dwWin32ExitCode = dwWin32ExitCode;
else
serviceStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
serviceStatus.dwServiceSpecificExitCode = dwServiceSpecificExitCode;
serviceStatus.dwCheckPoint = dwCheckPoint;
serviceStatus.dwWaitHint = dwWaitHint;
bSuccess = SetServiceStatus(serviceStatusHandle, &serviceStatus);
if (!bSuccess)
KillService();
return bSuccess;
}
void ServiceCtrlHandler (DWORD controlCode)
{
int bSuccess;
switch (controlCode)
{
case SERVICE_CONTROL_PAUSE:
if (serviceRunning && !servicePaused)
{
bSuccess = UpdateSCMStatus(SERVICE_PAUSE_PENDING, NO_ERROR, 0, 1, 1000);
servicePaused = 1;
SuspendThread(threadHandle);
serviceCurrentStatus = SERVICE_PAUSED;
}
break;
case SERVICE_CONTROL_CONTINUE:
if (serviceRunning && servicePaused)
{
bSuccess = UpdateSCMStatus(SERVICE_CONTINUE_PENDING, NO_ERROR, 0, 1, 1000);
servicePaused = 0;
ResumeThread(threadHandle);
serviceCurrentStatus = SERVICE_RUNNING;
}
break;
case SERVICE_CONTROL_INTERROGATE:
break;
case SERVICE_CONTROL_SHUTDOWN:
case SERVICE_CONTROL_STOP:
Shutdown.ltime = time(0);
Shutdown.interval = 1;
serviceCurrentStatus = SERVICE_STOP_PENDING;
bSuccess = UpdateSCMStatus(SERVICE_STOP_PENDING, NO_ERROR, 0, 1, 5000);
KillService();
return;
default:
break;
}
UpdateSCMStatus(serviceCurrentStatus, NO_ERROR, 0, 0, 0);
}
void KillService(void)
{
serviceRunning = 0;
SetEvent(killServiceEvent);
}
void terminateService(int iErr)
{
printf("Killing service: Err(%d)\n", iErr);
KillService();
}
#endif
/*================================================================*/
#define DAYSEC 86400L
#define MORNT 27900L
#define MIDSEC(x) (((x->tm_hour)*3600)+((x->tm_min)*60)+(x->tm_sec))
/*================================================================*/
int schedule_g()
/* The schedule_g function keeps the game on a time schedule */
{
struct tm *time_m;
long t = 0;
int mport = SCHEDPORT, port = PORTNUM;
enum {Sun, Mon, Tue, Wed, Thu, Fri, Sat};
t = time(0);
time_m = localtime(&t);
t = 0;
switch(time_m->tm_wday){
case Sun:
t = DAYSEC - MIDSEC(time_m) + MORNT;
break;
case Mon:
case Tue:
case Wed:
case Thu:
if (time_m->tm_hour >= 18)
t = MORNT + DAYSEC - MIDSEC(time_m);
else if (MIDSEC(time_m) < MORNT)
t = MORNT - MIDSEC(time_m);
else{
t = (18L*3600L) - MIDSEC(time_m);
port = SCHEDPORT;
mport = PORTNUM;
}
break;
case Fri:
if (time_m->tm_hour >= 18)
t = DAYSEC*3 - MIDSEC(time_m) + MORNT;
else if (MIDSEC(time_m) < MORNT)
t = MORNT - MIDSEC(time_m);
else{
t = (18L*3600L) - MIDSEC(time_m);
port = SCHEDPORT;
mport = PORTNUM;
}
break;
case Sat:
t = DAYSEC*2 - MIDSEC(time_m) + MORNT;
break;
}
if (!port)
exit(0);
if(AUTOSHUTDOWN)
t = MIN(21600L,t);
Shutdown.ltime = time(0);
Shutdown.interval = t;
Port = mport;
return (port);
}
/*================================================================*/
void mvc_log(){
/* This function renames the list of all command file to include *
* the date. This is done to preserve the list commands that *
* occured before a crash. */
long t;
char *date, mfile[128], rfile[128];
int i;
t = time(0);
date = ctime(&t);
for(i=0;i<24;i++)
if(date[i] == ' ')
date[i] = '_';
date[24] = 0;
sprintf(rfile,"%s/%s",LOGPATH,"all_cmd");
sprintf(mfile,"%s/%s_%s",LOGPATH,"all_cmd",date);
#ifndef WIN32
link(rfile,mfile);
unlink(rfile);
#else
rename( rfile, mfile);
#endif
}