mud/fluffos-2.23-ds03/main.c
2020-09-06 05:43:07 -07:00

688 lines
16 KiB
C

#define SUPPRESS_COMPILER_INLINES
#include "std.h"
#include "file_incl.h"
#include "lpc_incl.h"
#include "backend.h"
#include "simul_efun.h"
#include "main.h"
#include "otable.h"
#include "comm.h"
#include "compiler.h"
#include "port.h"
#include "md.h"
#include "main.h"
#include "socket_efuns.h"
#include "master.h"
#include "eval.h"
port_def_t external_port[5];
static int e_flag = 0; /* Load empty, without preloads. */
int t_flag = 0; /* Disable heart beat and reset */
int comp_flag = 0; /* Trace compilations */
int max_cost;
int time_to_clean_up;
const char *default_fail_message;
time_t boot_time;
int max_array_size;
int max_buffer_size;
int max_string_length;
static int reserved_size;
char *reserved_area; /* reserved for MALLOC() */
static char *mud_lib;
double consts[NUM_CONSTS];
#ifndef NO_IP_DEMON
int no_ip_demon = 0;
void init_addr_server();
#endif /* NO_IP_DEMON */
#ifdef SIGNAL_FUNC_TAKES_INT
#define SIGPROT (int)
#define PSIG(z) z (int sig)
#else
#define SIGPROT (void)
#define PSIG(z) z()
#endif
static void CDECL sig_fpe SIGPROT;
static void CDECL sig_cld SIGPROT;
#ifdef HAS_CONSOLE
static void CDECL sig_ttin SIGPROT;
#endif
#ifdef TRAP_CRASHES
static void CDECL sig_usr1 SIGPROT;
static void CDECL sig_usr2 SIGPROT;
static void CDECL sig_term SIGPROT;
static void CDECL sig_int SIGPROT;
#ifndef DEBUG
static void CDECL sig_hup SIGPROT,
CDECL sig_abrt SIGPROT,
CDECL sig_segv SIGPROT,
CDECL sig_ill SIGPROT,
CDECL sig_bus SIGPROT,
CDECL sig_iot SIGPROT;
#endif
#endif
#ifdef DEBUG_MACRO
/* used by debug.h: please leave this in here -- Tru (you can change its
value if you like).
*/
int debug_level = 0;
#endif
int main (int argc, char ** argv)
{
time_t tm;
int i, new_mudlib = 0, got_defaults = 0;
char *p;
char version_buf[80];
#if 0
int dtablesize;
#endif
error_context_t econ;
#ifdef PROTO_TZSET
void tzset();
#endif
#ifdef INCL_LOCALE_H
setlocale(LC_ALL, "C");
#endif
#if !defined(__SASC) && (defined(AMITCP) || defined(AS225))
amiga_sockinit();
atexit(amiga_sockexit);
#endif
#ifdef WRAPPEDMALLOC
wrappedmalloc_init();
#endif /* WRAPPEDMALLOC */
#ifdef DEBUGMALLOC
MDinit();
#endif
#if (defined(PROFILING) && !defined(PROFILE_ON) && defined(HAS_MONCONTROL))
moncontrol(0);
#endif
#ifdef USE_TZSET
tzset();
#endif
boot_time = get_current_time();
const0.type = T_NUMBER;
const0.u.number = 0;
const1.type = T_NUMBER;
const1.u.number = 1;
/* const0u used by undefinedp() */
const0u.type = T_NUMBER;
const0u.subtype = T_UNDEFINED;
const0u.u.number = 0;
//fake_prog.program_size = 0; //0 anyway
/*
* Check that the definition of EXTRACT_UCHAR() is correct.
*/
p = (char *) &i;
*p = -10;
if (EXTRACT_UCHAR(p) != 0x100 - 10) {
fprintf(stderr, "Bad definition of EXTRACT_UCHAR() in interpret.h.\n");
exit(-1);
}
/*
* An added test: can we do EXTRACT_UCHAR(x++)?
* (read_number, etc uses it)
*/
p = (char *) &i;
(void) EXTRACT_UCHAR(p++);
if ((p - (char *) &i) != 1) {
fprintf(stderr, "EXTRACT_UCHAR() in interpret.h evaluates its argument more than once.\n");
exit(-1);
}
/*
* Check the living hash table size
*/
if (CFG_LIVING_HASH_SIZE != 4 && CFG_LIVING_HASH_SIZE != 16 &&
CFG_LIVING_HASH_SIZE != 64 && CFG_LIVING_HASH_SIZE != 256 &&
CFG_LIVING_HASH_SIZE != 1024 && CFG_LIVING_HASH_SIZE != 4096) {
fprintf(stderr, "CFG_LIVING_HASH_SIZE in options.h must be one of 4, 16, 64, 256, 1024, 4096, ...\n");
exit(-1);
}
#ifdef RAND
srand(get_current_time());
#else
# ifdef DRAND48
srand48(get_current_time());
# else
# ifdef RANDOM
srandom(get_current_time());
# else
fprintf(stderr, "Warning: no random number generator specified!\n");
# endif
# endif
#endif
current_time = get_current_time();
/*
* Initialize the microsecond clock.
*/
init_usec_clock();
/* read in the configuration file */
got_defaults = 0;
for (i = 1; (i < argc) && !got_defaults; i++) {
if (argv[i][0] != '-') {
set_defaults(argv[i]);
got_defaults = 1;
}
}
get_version(version_buf);
if (!got_defaults) {
fprintf(stderr, "%s for %s.\n", version_buf, ARCH);
fprintf(stderr, "You must specify the configuration filename as an argument.\n");
exit(-1);
}
printf("Initializing internal tables....\n");
init_strings(); /* in stralloc.c */
init_otable(); /* in otable.c */
init_identifiers(); /* in lex.c */
init_locals(); /* in compiler.c */
/*
* If our estimate is larger than FD_SETSIZE, then we need more file
* descriptors than the operating system can handle. This is a problem
* that can be resolved by decreasing MAX_USERS, MAX_EFUN_SOCKS, or both.
*
* Unfortunately, since neither MAX_USERS or MAX_EFUN_SOCKS exist any more,
* we have no clue how many we will need. This code really should be
* moved to places where ENFILE/EMFILE is returned.
*/
#if 0
if (dtablesize > FD_SETSIZE) {
fprintf(stderr, "Warning: File descriptor requirements exceed system capacity!\n");
fprintf(stderr, " Configuration exceeds system capacity by %d descriptor(s).\n",
dtablesize - FD_SETSIZE);
}
#ifdef HAS_SETDTABLESIZE
/*
* If the operating system supports setdtablesize() then we can request
* the number of file descriptors we really need. First check to see if
* wee already have enough. If so dont bother the OS. If not, attempt to
* allocate the number we estimated above. There are system imposed
* limits on file descriptors, so we may not get as many as we asked for.
* Check to make sure we get enough.
*/
if (getdtablesize() < dtablesize)
if (setdtablesize(dtablesize) < dtablesize) {
fprintf(stderr, "Warning: Could not allocate enough file descriptors!\n");
fprintf(stderr, " setdtablesize() could not allocate %d descriptor(s).\n",
getdtablesize() - dtablesize);
}
/*
* Just be polite and tell the administrator how many he has.
*/
fprintf(stderr, "%d file descriptors were allocated, (%d were requested).\n",
getdtablesize(), dtablesize);
#endif
#endif
time_to_clean_up = TIME_TO_CLEAN_UP;
max_cost = MAX_COST;
reserved_size = RESERVED_SIZE;
max_array_size = MAX_ARRAY_SIZE;
if(max_array_size > 2147483647){
fprintf(stderr, "Maximum array size can not exceed 65535");
max_array_size = 2147483647;
}
max_buffer_size = MAX_BUFFER_SIZE;
max_string_length = MAX_STRING_LENGTH;
mud_lib = (char *) MUD_LIB;
set_inc_list(INCLUDE_DIRS);
if (reserved_size > 0)
reserved_area = (char *) DMALLOC(reserved_size, TAG_RESERVED, "main.c: reserved_area");
for (i = 0; i < sizeof consts / sizeof consts[0]; i++)
consts[i] = exp(-i / 900.0);
reset_machine(1);
/*
* The flags are parsed twice ! The first time, we only search for the -m
* flag, which specifies another mudlib, and the D-flags, so that they
* will be available when compiling master.c.
*/
for (i = 1; i < argc; i++) {
if (argv[i][0] != '-')
continue;
switch (argv[i][1]) {
case 'D':
if (argv[i][2]) {
lpc_predef_t *tmp = ALLOCATE(lpc_predef_t, TAG_PREDEFINES,
"predef");
tmp->flag = argv[i] + 2;
tmp->next = lpc_predefs;
lpc_predefs = tmp;
continue;
}
fprintf(stderr, "Illegal flag syntax: %s\n", argv[i]);
exit(-1);
case 'N':
no_ip_demon++;
continue;
#ifdef HAS_CONSOLE
case 'C':
has_console = 1;
continue;
#endif
#ifdef YYDEBUG
case 'y':
yydebug = 1;
continue;
#endif /* YYDEBUG */
case 'm':
mud_lib = alloc_cstring(argv[i] + 2, "mudlib dir");
if (chdir(mud_lib) == -1) {
fprintf(stderr, "Bad mudlib directory: %s\n", mud_lib);
exit(-1);
}
new_mudlib = 1;
break;
}
}
if (!new_mudlib && chdir(mud_lib) == -1) {
fprintf(stderr, "Bad mudlib directory: %s\n", mud_lib);
exit(-1);
}
time(&tm);
debug_message("----------------------------------------------------------------------------\n%s (%s) starting up on %s - %s\n\n", MUD_NAME, version_buf, ARCH, ctime(&tm));
add_predefines();
#ifdef WIN32
_tzset();
#endif
#ifndef NO_IP_DEMON
if (!no_ip_demon && ADDR_SERVER_IP)
init_addr_server(ADDR_SERVER_IP, ADDR_SERVER_PORT);
#endif /* NO_IP_DEMON */
save_context(&econ);
if (SETJMP(econ.context)) {
debug_message("The simul_efun (%s) and master (%s) objects must be loadable.\n",
SIMUL_EFUN, MASTER_FILE);
exit(-1);
} else {
init_simul_efun(SIMUL_EFUN);
init_master();
}
set_eval(max_cost);
pop_context(&econ);
for (i = 1; i < argc; i++) {
if (argv[i][0] != '-') {
continue;
} else {
/*
* Look at flags. -m and -o has already been tested.
*/
switch (argv[i][1]) {
case 'D':
case 'N':
case 'm':
case 'y':
case 'C':
continue;
case 'f':
save_context(&econ);
if (SETJMP(econ.context)) {
debug_message("Error while calling master::flag(\"%s\"), aborting ...\n", argv[i] + 2);
exit(-1);
}
push_constant_string(argv[i] + 2);
apply_master_ob(APPLY_FLAG, 1);
if (MudOS_is_being_shut_down) {
debug_message("Shutdown by master object.\n");
exit(0);
}
pop_context(&econ);
continue;
case 'e':
e_flag++;
continue;
case 'p':
external_port[0].port = atoi(argv[i] + 2);
continue;
case 'd':
#ifdef DEBUG_MACRO
if (argv[i][2])
debug_level_set(&argv[i][2]);
else
debug_level |= DBG_d_flag;
#else
debug_message("Driver must be compiled with DEBUG_MACRO on to use -d.\n");
#endif
break;
case 'c':
comp_flag++;
continue;
case 't':
t_flag++;
continue;
default:
debug_message("Unknown flag: %s\n", argv[i]);
exit(-1);
}
}
}
if (MudOS_is_being_shut_down)
exit(1);
if (*(DEFAULT_FAIL_MESSAGE)) {
char buf[8192];
strcpy(buf, DEFAULT_FAIL_MESSAGE);
strcat(buf, "\n");
default_fail_message = make_shared_string(buf);
} else
default_fail_message = "What?\n";
#ifdef PACKAGE_MUDLIB_STATS
restore_stat_files();
#endif
preload_objects(e_flag);
#ifdef SIGFPE
signal(SIGFPE, sig_fpe);
#endif
#ifdef TRAP_CRASHES
#ifdef SIGUSR1
signal(SIGUSR1, sig_usr1);
#endif
#ifdef SIGUSR2
signal(SIGUSR2, sig_usr2);
#endif
signal(SIGTERM, sig_term);
signal(SIGINT, sig_int);
#ifndef DEBUG
#if defined(SIGABRT)
signal(SIGABRT, sig_abrt);
#endif
#ifdef SIGIOT
signal(SIGIOT, sig_iot);
#endif
#ifdef SIGHUP
signal(SIGHUP, sig_hup);
#endif
#ifdef SIGBUS
signal(SIGBUS, sig_bus);
#endif
signal(SIGSEGV, sig_segv);
signal(SIGILL, sig_ill);
#endif /* DEBUG */
#endif
#ifndef WIN32
#ifdef USE_BSD_SIGNALS
signal(SIGCHLD, sig_cld);
#else
signal(SIGCLD, sig_cld);
#endif
#endif
#ifdef HAS_CONSOLE
if(has_console >= 0)
signal(SIGTTIN, sig_ttin);
signal(SIGTTOU, SIG_IGN);
#endif
backend();
return 0;
}
#ifdef DEBUGMALLOC
char *int_string_copy (const char * const str, char * desc)
#else
char *int_string_copy (const char * const str)
#endif
{
char *p;
int len;
DEBUG_CHECK(!str, "Null string passed to string_copy.\n");
len = strlen(str);
if (len > max_string_length) {
len = max_string_length;
p = new_string(len, desc);
(void) strncpy(p, str, len);
p[len] = '\0';
} else {
p = new_string(len, desc);
(void) strncpy(p, str, len + 1);
}
return p;
}
#ifdef DEBUGMALLOC
char *int_string_unlink (const char * str, char * desc)
#else
char *int_string_unlink (const char * str)
#endif
{
malloc_block_t *mbt, *newmbt;
mbt = ((malloc_block_t *)str) - 1;
mbt->ref--;
if (mbt->size == USHRT_MAX) {
int l = strlen(str + USHRT_MAX) + USHRT_MAX; /* ouch */
newmbt = (malloc_block_t *)DXALLOC(l + sizeof(malloc_block_t) + 1, TAG_MALLOC_STRING, desc);
memcpy((char *)(newmbt + 1), (char *)(mbt + 1), l+1);
newmbt->size = USHRT_MAX;
ADD_NEW_STRING(USHRT_MAX, sizeof(malloc_block_t));
} else {
newmbt = (malloc_block_t *)DXALLOC(mbt->size + sizeof(malloc_block_t) + 1, TAG_MALLOC_STRING, desc);
memcpy((char *)(newmbt + 1), (char *)(mbt + 1), mbt->size+1);
newmbt->size = mbt->size;
ADD_NEW_STRING(mbt->size, sizeof(malloc_block_t));
}
newmbt->ref = 1;
CHECK_STRING_STATS;
return (char *)(newmbt + 1);
}
static FILE *debug_message_fp = 0;
void debug_message (const char *fmt, ...)
{
static char deb_buf[1024];
static char *deb = deb_buf;
va_list args;
if (!debug_message_fp) {
/*
* check whether config file specified this option
*/
if (strlen(DEBUG_LOG_FILE))
snprintf(deb, 1023, "%s/%s", LOG_DIR, DEBUG_LOG_FILE);
else
snprintf(deb, 1023, "%s/debug.log", LOG_DIR);
deb[1023] = 0;
while (*deb == '/')
deb++;
debug_message_fp = fopen(deb, "w");
if (!debug_message_fp) {
/* darn. We're in trouble */
perror(deb);
abort();
}
}
V_START(args, fmt);
V_VAR(char *, fmt, args);
vfprintf(debug_message_fp, fmt, args);
fflush(debug_message_fp);
va_end(args);
V_START(args, fmt);
V_VAR(char *, fmt, args);
vfprintf(stderr, fmt, args);
fflush(stderr);
va_end(args);
}
int slow_shut_down_to_do = 0;
char *xalloc (int size)
{
char *p;
const char *t;
static int going_to_exit;
if (going_to_exit)
exit(3);
#ifdef DEBUG
if (size == 0)
fatal("Tried to allocate 0 bytes.\n");
#endif
p = (char *) DMALLOC(size, TAG_MISC, "main.c: xalloc");
if (p == 0) {
if (reserved_area) {
FREE(reserved_area);
t = "Temporarily out of MEMORY. Freeing reserve.\n";
write(1, t, strlen(t));
reserved_area = 0;
slow_shut_down_to_do = 6;
return xalloc(size);/* Try again */
}
going_to_exit = 1;
fatal("Totally out of MEMORY.\n");
}
return p;
}
static void CDECL PSIG(sig_cld)
{
#ifndef WIN32
int status;
#ifdef USE_BSD_SIGNALS
while (wait3(&status, WNOHANG, NULL) > 0)
;
#else
wait(&status);
signal(SIGCLD, sig_cld);
#endif
#endif
}
static void CDECL PSIG(sig_fpe)
{
signal(SIGFPE, sig_fpe);
}
#ifdef HAS_CONSOLE
void restore_sigttin(void) {
if(has_console >= 0)
signal(SIGTTIN, sig_ttin);
}
/* The console goes to sleep when backgrounded and can
* be woken back up with kill -SIGTTIN <pid>
*/
static void CDECL PSIG(sig_ttin)
{ char junk[1024];
int fl;
has_console = !has_console;
signal(SIGTTIN, SIG_IGN);
if(has_console) {
/* now eat all the gibberish they typed in the console when it was dead */
fl = fcntl(STDIN_FILENO, F_GETFL);
fcntl(STDIN_FILENO, F_SETFL, fl | O_NONBLOCK);
while(read(STDIN_FILENO, junk, 1023) > 0); /* ; */
/* leaving the output nonblocking is a bad idea. large outputs tend
to get truncated.
*/
fcntl(STDIN_FILENO, F_SETFL, fl);
}
}
#endif
#ifdef TRAP_CRASHES
/* send this signal when the machine is about to reboot. The script
which restarts the MUD should take an exit code of 1 to mean don't
restart
*/
static void CDECL PSIG(sig_usr1)
{
push_constant_string("Host machine shutting down");
push_undefined();
push_undefined();
apply_master_ob(APPLY_CRASH, 3);
debug_message("Received SIGUSR1, calling exit(-1)\n");
exit(-1);
}
/* Abort evaluation */
static void CDECL PSIG(sig_usr2)
{
outoftime = 1;
}
/*
* Actually, doing all this stuff from a signal is probably illegal
* -Beek
*/
static void CDECL PSIG(sig_term)
{
fatal("Process terminated");
}
static void CDECL PSIG(sig_int)
{
fatal("Process interrupted");
}
#ifndef DEBUG
static void CDECL PSIG(sig_segv)
{
fatal("Segmentation fault");
}
static void CDECL PSIG(sig_bus)
{
fatal("Bus error");
}
static void CDECL PSIG(sig_ill)
{
fatal("Illegal instruction");
}
static void CDECL PSIG(sig_hup)
{
fatal("Hangup!");
}
static void CDECL PSIG(sig_abrt)
{
fatal("Aborted");
}
static void CDECL PSIG(sig_iot)
{
fatal("Aborted(IOT)");
}
#endif /* !DEBUG */
#endif /* TRAP_CRASHES */