Exemple #1
0
/*
 * Check that a path to a file is valid for read or write.
 * This is done by functions in the master object.
 * The path is always treated as an absolute path, and is returned without
 * a leading '/'.
 * If the path was '/', then '.' is returned.
 * Otherwise, the returned path is temporarily allocated by apply(), which
 * means it will be deallocated at next apply().
 */
const char *check_valid_path (const char * path, object_t * call_object, const char * const  call_fun, int writeflg)
{
    svalue_t *v;

    if(!master_ob && !call_object){
    	//early startup, ignore security
    	extern svalue_t apply_ret_value;
        free_svalue(&apply_ret_value, "check_valid_path");
        apply_ret_value.type = T_STRING;
        apply_ret_value.subtype = STRING_MALLOC;
        path = apply_ret_value.u.string = string_copy(path, "check_valid_path");
    	return path;
    }

    if (call_object == 0 || call_object->flags & O_DESTRUCTED)
        return 0;

#ifdef WIN32
    {
        char *p;
        
        for(p=path; *p; p++) if (*p == '\\') *p='/';
    }
#endif

    copy_and_push_string(path);
    push_object(call_object);
    push_constant_string(call_fun);
    if (writeflg)
        v = apply_master_ob(APPLY_VALID_WRITE, 3);
    else
        v = apply_master_ob(APPLY_VALID_READ, 3);

    if (v == (svalue_t *)-1)
        v = 0;
    
    if (v && v->type == T_NUMBER && v->u.number == 0) return 0;
    if (v && v->type == T_STRING) {
        path = v->u.string;
    } else {
        extern svalue_t apply_ret_value;
        
        free_svalue(&apply_ret_value, "check_valid_path");
        apply_ret_value.type = T_STRING;
        apply_ret_value.subtype = STRING_MALLOC;
        path = apply_ret_value.u.string = string_copy(path, "check_valid_path");
    }
    
    if (path[0] == '/')
        path++;
    if (path[0] == '\0')
        path = ".";
    if (legal_path(path))
        return path;

    return 0;
}
Exemple #2
0
/* 将ob设置为master对象 */
void set_master(object_t *  ob) {
#if defined(PACKAGE_UIDS) || defined(PACKAGE_MUDLIB_STATS)
    int first_load = (!master_ob);
#endif
#ifdef PACKAGE_UIDS
    svalue_t *ret;
#endif

    get_master_applies(ob);			/* master load好之后,要apply一下? */
    master_ob = ob;
    /* Make sure master_ob is never made a dangling pointer. */
    add_ref(master_ob, "set_master");
#ifndef PACKAGE_UIDS
#  ifdef PACKAGE_MUDLIB_STATS
    if (first_load) {
        set_backbone_domain("BACKBONE");
        set_master_author("NONAME");
    }
#  endif
#else
    ret = apply_master_ob(APPLY_GET_ROOT_UID, 0);
    /* can't be -1 or we wouldn't be here */
    if (!ret) {
        debug_message("No function %s() in master object; possibly the mudlib doesn't want PACKAGE_UIDS to be defined.\n",
                      applies_table[APPLY_GET_ROOT_UID]);
        exit(-1);
    }
    if (ret->type != T_STRING) {
        debug_message("%s() in master object does not work.\n",
                      applies_table[APPLY_GET_ROOT_UID]);
        exit(-1);
    }
    if (first_load) {											/* 第一次load master? */
        master_ob->uid = set_root_uid(ret->u.string);
        master_ob->euid = master_ob->uid;
#  ifdef PACKAGE_MUDLIB_STATS
        set_master_author(ret->u.string);
#  endif
        ret = apply_master_ob(APPLY_GET_BACKBONE_UID, 0);
        if (ret == 0 || ret->type != T_STRING) {
            debug_message("%s() in the master file does not work\n",
                          applies_table[APPLY_GET_BACKBONE_UID]);		/* apply有多个,装table */
            exit(-1);
        }
        set_backbone_uid(ret->u.string);
#  ifdef PACKAGE_MUDLIB_STATS
        set_backbone_domain(ret->u.string);
#  endif
    } else {
        master_ob->uid = add_uid(ret->u.string);
        master_ob->euid = master_ob->uid;
    }
#endif
}
Exemple #3
0
static void
udpsvc_process(udpsvc_t *svc)
{
    int addrlen, cc;
    struct sockaddr_in addr;
    struct gdexception exception_frame;
    
    update_udp_av();

    exception_frame.e_exception = exception;
    exception_frame.e_catch = 0;

    exception = &exception_frame;

    
    if (setjmp(exception_frame.e_context) == 0)
    {
	push_string(inet_ntoa(addr.sin_addr), STRING_MSTRING);
	push_string((char *)nq_rptr(svc->nq), STRING_MSTRING);
	(void)apply_master_ob(M_INCOMING_UDP, 2);
    }
    exception = exception->e_exception;
    addrlen = sizeof (addr);

    if (!read_datagram(svc)) {
	nd_enable(svc->nd, ND_R);
	svc->task = 0;
	return;
    }
    reschedule_task(svc->task);
}
Exemple #4
0
static void 
slow_shut_down(void *v)
{
    shutdown_task = 0;
    push_number(slow_shut_down_to_do);
    slow_shut_down_to_do = 0;
    apply_master_ob(M_MEMORY_FAILURE, 1);
}
Exemple #5
0
static void PSIG(sig_usr1)
{
    push_string("Host machine shutting down", STRING_CONSTANT);
    push_undefined();
    push_undefined();
    apply_master_ob(APPLY_CRASH, 3);
    debug_message("Received SIGUSR1, calling exit(-1)\n");
    exit(-1);
}
Exemple #6
0
/* New version used when not in -o mode. The epilog() in master.c is
 * supposed to return an array of files (castles in 2.4.5) to load. The array
 * returned by apply() will be freed at next call of apply(), which means that
 * the ref count has to be incremented to protect against deallocation.
 *
 * The master object is asked to do the actual loading.
 */
void preload_objects (int eflag)
{
    VOLATILE array_t *prefiles;
    svalue_t *ret;
    VOLATILE int ix;
    error_context_t econ;

    save_context(&econ);
    if (SETJMP(econ.context)) {
        restore_context(&econ);
        pop_context(&econ);
        return;
    }
    push_number(eflag);
    ret = apply_master_ob(APPLY_EPILOG, 1);
    pop_context(&econ);
    if ((ret == 0) || (ret == (svalue_t *)-1) || (ret->type != T_ARRAY))
        return;
    else
        prefiles = ret->u.arr;
    if ((prefiles == 0) || (prefiles->size < 1))
        return;

    debug_message("\nLoading preloaded files ...\n");
    prefiles->ref++;
    ix = 0;
    /* in case of an error, effectively do a 'continue' */
    save_context(&econ);
    if (SETJMP(econ.context)) {
        restore_context(&econ);
        ix++;
    }
    for ( ; ix < prefiles->size; ix++) {
        if (prefiles->item[ix].type != T_STRING)
            continue;

        set_eval(max_cost);

        push_svalue(((array_t *)prefiles)->item + ix);
        (void) apply_master_ob(APPLY_PRELOAD, 1);
    }
    free_array((array_t *)prefiles);
    pop_context(&econ);
}       /* preload_objects() */
Exemple #7
0
static void init_domain_for_ob (object_t * ob)
{
    svalue_t *ret;
    const char *domain_name;

    if (!current_object
#ifdef PACKAGE_UIDS
	|| !current_object->uid
#endif
	) {
	/*
	 * Only for the master and void object. Note that you can't ask for
	 * the backbone or root domain here since we're in the process of
	 * loading the master object.
	 */
	ob->stats.domain = add_stat_entry("NONAME", &domains);
	return;
    }
    /*
     * Ask master object who the creator of this object is.
     */
    push_malloced_string(add_slash(ob->obname));

    if (master_ob)
	ret = apply_master_ob(APPLY_DOMAIN_FILE, 1);
    else
	ret = apply(applies_table[APPLY_DOMAIN_FILE], ob, 1, ORIGIN_DRIVER);

    if (IS_ZERO(ret)) {
	ob->stats.domain = current_object->stats.domain;
	return;
    }
    if (ret->type != T_STRING)
	error("'domain_file' in the master object must return a string!\n");
    domain_name = ret->u.string;
    if (strcmp(current_object->stats.domain->name, domain_name) == 0) {
	ob->stats.domain = current_object->stats.domain;
	return;
    }
    if (strcmp(backbone_domain->name, domain_name) == 0) {
	/*
	 * The object is loaded from backbone. We give domain ownership to
	 * the creator rather than backbone.
	 */
	ob->stats.domain = current_object->stats.domain;
	return;
    }
    /*
     * The object isn't loaded from backbone or from the same domain as the
     * creator, so we need to lookup the domain, and add it if it isnt
     * present.
     */
    ob->stats.domain = add_stat_entry(domain_name, &domains);
    return;
}
Exemple #8
0
/*
 * Argument is a file name, which we want to get the domain of.
 * Ask the master object.
 */
static const char *domain_for_file (const char * file)
{
    svalue_t *ret;
    static char buff[512];

    share_and_push_string(file);
    ret = apply_master_ob(APPLY_DOMAIN_FILE, 1);
    if (ret == 0 || ret == (svalue_t*)-1 || ret->type != T_STRING)
	return 0;
    strcpy(buff, ret->u.string);
    return buff;
}
INLINE int
valid_hide P1(struct object *, obj)
{
    struct svalue *ret;

    if (!obj) {
	return 0;
    }
    push_object(obj);
    ret = apply_master_ob(APPLY_VALID_HIDE, 1);
    return (!IS_ZERO(ret));
}
Exemple #10
0
static const char *author_for_file (const char * file)
{
    svalue_t *ret;
    static char buff[50];

    copy_and_push_string(file);
    ret = apply_master_ob(APPLY_AUTHOR_FILE, 1);
    if (ret == 0 || ret == (svalue_t*)-1 || ret->type != T_STRING)
	return 0;
    strcpy(buff, ret->u.string);
    return buff;
}
Exemple #11
0
static void init_author_for_ob (object_t * ob)
{
    svalue_t *ret;

    push_malloced_string(add_slash(ob->obname));
    ret = apply_master_ob(APPLY_AUTHOR_FILE, 1);
    if (ret == (svalue_t *)-1) {
	ob->stats.author = master_author;
    } else if (!ret || ret->type != T_STRING) {
	ob->stats.author = NULL;
    } else {
	ob->stats.author = add_stat_entry(ret->u.string, &authors);
    }
}
Exemple #12
0
/* valid_database
 *
 * Calls APPLY_VALID_DATABASE in the master object to provide some
 * security on which objects can tweak your database (we don't want
 * people doing "DELETE * FROM *" or equivalent for us)
 */
svalue_t *valid_database (const char * action, array_t * info)
{
	svalue_t *ret;

	/*
	 * Call valid_database(object ob, string action, mixed *info)
	 *
	 * Return: string - password for access
	 *         int    - 1 for no password, accept, 0 deny
	 */
	push_object(current_object);
	push_constant_string(action);
	push_refed_array(info);

	ret = apply_master_ob(APPLY_VALID_DATABASE, 3);
	if (ret && (ret == (svalue_t *)-1 || (ret->type == T_STRING || (ret->type == T_NUMBER && ret->u.number))))
		return ret;

	error("Database security violation attempted\n");
}
Exemple #13
0
/*
 * Read and process a UDP datagram.
 */
static void
udpsvc_read(ndesc_t *nd, nqueue_t *nq)
{
    int addrlen, cc;
    struct sockaddr_in addr;

    addrlen = sizeof (addr);

    cc = recvfrom(nd_fd(nd), nq_wptr(nq), nq_size(nq) - 1, 0,
	     (struct sockaddr *)&addr, &addrlen);

    if (cc == -1)
	return;

    nq_wptr(nq)[cc] = '\0';

    /* XXX We need a safe master apply XXX */
    push_string(inet_ntoa(addr.sin_addr), STRING_MSTRING);
    push_string((char *)nq_rptr(nq), STRING_MSTRING);
    (void)apply_master_ob(M_INCOMING_UDP, 2);
}
Exemple #14
0
static void
send_signals(void *x)
{
    int i;
    
    sigprocmask(SIG_BLOCK, &sigs_to_block, NULL);
    for (i = 0; i < MAX_SIGNALS; i++)
	if (pending_signals & (1 << i))
            break;

    pending_signals &= ~(1 << i);
    sigprocmask(SIG_UNBLOCK, &sigs_to_block, NULL);

    if (pending_signals)
        reschedule_task(signal_task);
    else
        signal_task = 0;
    if (i < MAX_SIGNALS)
        push_string(disp[i].name, STRING_CSTRING);
        (void)apply_master_ob(M_EXTERNAL_SIGNAL, 1);
}
Exemple #15
0
static void
handle_exception(int action, char *message)
{
    char buf[1024];

    (void)strcpy(buf, "\"");

    if (strlen(message) < 2)
	(void)strcat(buf, "Unspecified condition");
    else
	(void)strcat(buf, message);
    (void)strcat(buf, "\"");
    
    push_number(action);
    push_string(buf, STRING_MSTRING);
    push_number(current_line);
    push_string(current_file, STRING_MSTRING);
    (void)apply_master_ob(M_PARSE_EXCEPTION, 4);
    
    if (action == ERROR)
	lexerror("Parse aborted on #error statement,");
}
/*
 * check permission
 */
int check_valid_socket (const char * const what, int fd, object_t * owner,
        const char * const addr, int port)
{
    array_t *info;
    svalue_t *mret;

    info = allocate_empty_array(4);
    info->item[0].type = T_NUMBER;
    info->item[0].u.number = fd;
    assign_socket_owner(&info->item[1], owner);
    info->item[2].type = T_STRING;
    info->item[2].subtype = STRING_SHARED;
    info->item[2].u.string = make_shared_string(addr);
    info->item[3].type = T_NUMBER;
    info->item[3].u.number = port;

    push_object(current_object);
    push_constant_string(what);
    push_refed_array(info);

    mret = apply_master_ob(APPLY_VALID_SOCKET, 3);
    return MASTER_APPROVED(mret);
}
Exemple #17
0
/* Make sure the path does not have any ".." elements. */
char *
check_valid_compile_path(char *path, char *file_name, char *calling_function)
{
#if 0
    struct svalue *ret;
#endif
    char *p = path;
    
    while (*p)
    {
	if (p[0] == '.' && p[1] == '.')
	    return NULL;
	p++;
    }
#if 0
    push_string(path, STRING_MSTRING);
    push_string(file_name, STRING_MSTRING);
    push_string(calling_function, STRING_MSTRING);
    ret = apply_master_ob(M_VALID_COMPILE_PATH, 3);
    if (ret)
	path = tmpstring_copy(ret->u.string);
#endif
    return path;
}
Exemple #18
0
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 > 65535){
        fprintf(stderr, "Maximum array size can not exceed 65535");
        max_array_size = 65535;
    }
    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 */

    set_eval(max_cost);

    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();
    }
    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;
}
Exemple #19
0
int main P2(int, argc, char **, argv)
{
    time_t tm;
    int i, new_mudlib = 0, got_defaults = 0;
    int no_ip_demon = 0;
    char *p;
    char version_buf[80];
#if 0
    int dtablesize;
#endif
    error_context_t econ;

#if !defined(LATTICE) && !defined(OLD_ULTRIX) && !defined(sequent) && \
    !defined(sgi)
    void tzset();
#endif
    struct lpc_predef_s predefs;

#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
#if !defined(OLD_ULTRIX) && !defined(LATTICE) && !defined(sequent)
    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;

    /* const0n used by nullp() */
    const0n.type = T_NUMBER;
    const0n.subtype = T_NULLVALUE;
    const0n.u.number = 0;

    fake_prog.program_size = 0;

    /*
     * 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;
	}
    }
    if (!got_defaults) {
	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 */

/* disable this for now */
#if 0
    /*
     * We estimate that we will need MAX_USERS + MAX_EFUN_SOCKS + 10 file
     * descriptors if the maximum number of users were to log in and all LPC
     * sockets were in use.  This is a pretty close estimate.
     */
#ifndef LATTICE
    dtablesize = MAX_USERS + MAX_EFUN_SOCKS + 10;
#else
    /*
     * Amiga sockets separate from file descriptors
     */
    dtablesize = MAX_USERS + MAX_EFUN_SOCKS;
#endif

    /*
     * 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.
     */
    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;
    time_to_swap = TIME_TO_SWAP;
    max_cost = MAX_COST;
    reserved_size = RESERVED_SIZE;
    max_array_size = MAX_ARRAY_SIZE;
    max_buffer_size = MAX_BUFFER_SIZE;
    max_string_length = MAX_STRING_LENGTH;
    master_file_name = (char *) MASTER_FILE;
    /* fix the filename */
    while (*master_file_name == '/') master_file_name++;
    p = master_file_name;
    while (*p++);
    if (p[-2]=='c' && p[-3]=='.')
	p[-3]=0;
    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);
    init_num_args();
    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]) {	/* Amylaar : allow flags to be passed down to
				 * the LPC preprocessor */
		struct lpc_predef_s *tmp;

		tmp = &predefs;
		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 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);
    }
    get_version(version_buf);
    time(&tm);
    debug_message("----------------------------------------------------------------------------\n%s (%s) starting up on %s - %s\n\n", MUD_NAME, version_buf, ARCH, ctime(&tm));

#ifdef BINARIES
    init_binaries(argc, argv);
#endif
#ifdef LPC_TO_C
    init_lpc_to_c();
#endif
    add_predefines();

#ifndef NO_IP_DEMON
    if (!no_ip_demon && ADDR_SERVER_IP)
	init_addr_server(ADDR_SERVER_IP, ADDR_SERVER_PORT);
#endif				/* NO_IP_DEMON */

    eval_cost = max_cost;	/* needed for create() functions */

    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(MASTER_FILE);
    }
    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':
		continue;
	    case 'f':
		save_context(&econ);
		if (SETJMP(econ.context)) {
		    debug_message("Error while calling master::flag(\"%s\"), aborting ...", argv[i] + 2);
		    exit(-1);
		}
		push_constant_string(argv[i] + 2);
		(void) 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
                d_flag++;
#else
                debug_message("Driver must be compiled with DEBUG on to use -d.\n");
#endif
	    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 (strlen(DEFAULT_FAIL_MESSAGE))
	default_fail_message = DEFAULT_FAIL_MESSAGE;
    else
	default_fail_message = "What?";
#ifdef PACKAGE_MUDLIB_STATS
    restore_stat_files();
#endif
#ifdef PACKAGE_SOCKETS
    init_sockets();		/* initialize efun sockets           */
#endif
    preload_objects(e_flag);
#ifdef SIGFPE
    signal(SIGFPE, sig_fpe);
#endif
#ifdef TRAP_CRASHES
#ifdef SIGUSR1
    signal(SIGUSR1, sig_usr1);
#endif
    signal(SIGTERM, sig_term);
    signal(SIGINT, sig_int);
#ifndef DEBUG
#if defined(SIGABRT) && !defined(LATTICE)
    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
#ifndef LATTICE
    signal(SIGSEGV, sig_segv);
    signal(SIGILL, sig_ill);
#endif
#endif				/* DEBUG */
#endif
    backend();
    return 0;
}
Exemple #20
0
/*
 * The start_boot() in master.c is supposed to return an array of files to load.
 * The array returned by apply() will be freed at next call of apply(),
 * which means that the ref count has to be incremented to protect against
 * deallocation.
 *
 * The master object is asked to do the actual loading.
 */
void 
preload_objects(int eflag)
{
    struct gdexception exception_frame;
    struct vector *prefiles;
    struct svalue *ret = NULL;
    volatile int ix;

    set_current_time();


    if (setjmp(exception_frame.e_context)) 
    {
	clear_state();
	(void)add_message("Error in start_boot() in master_ob.\n");
	exception = NULL;
	return;
    }
    else
    {
	exception_frame.e_exception = NULL;
	exception_frame.e_catch = 0;
	exception = &exception_frame;
	push_number(eflag);
	ret = apply_master_ob(M_START_BOOT, 1);
    }

    if ((ret == 0) || (ret->type != T_POINTER))
	return;
    else
	prefiles = ret->u.vec;

    if ((prefiles == 0) || (prefiles->size < 1))
	return;

    INCREF(prefiles->ref); /* Otherwise it will be freed next sapply */

    ix = -1;
    if (setjmp(exception_frame.e_context)) 
    {
	clear_state();
	(void)add_message("Anomaly in the fabric of world space.\n");
    }

    while (++ix < prefiles->size) 
    {
        set_current_time();
	if (s_flag)
	    reset_mudstatus();
	eval_cost = 0;
	push_svalue(&(prefiles->item[ix]));
	(void)apply_master_ob(M_PRELOAD_BOOT, 1);
	if (s_flag)
	    print_mudstatus(prefiles->item[ix].u.string, eval_cost,
			    get_millitime(), get_processtime());
	tmpclean();
    }
    free_vector(prefiles);
    exception = NULL;
    set_current_time();
}
Exemple #21
0
int 
main(int argc, char **argv)
{
    extern int game_is_being_shut_down;
    char *p;
    int i = 0;
    struct svalue *ret;
    extern struct svalue catch_value;
    extern void init_cfuns(void);
    struct gdexception exception_frame;

    (void)setlinebuf(stdout);

    parse_args(argc, argv);
    
    const0.type = T_NUMBER; const0.u.number = 0;
    const1.type = T_NUMBER; const1.u.number = 1;
    constempty.type = T_FUNCTION; constempty.u.func = &funcempty;
    funcempty.funtype = FUN_EMPTY;
    catch_value = const0;
    
    /*
     * Check that the definition of EXTRACT_UCHAR() is correct.
     */
    p = (char *)&i;
    *p = -10;
    if (EXTRACT_UCHAR(p) != 0x100 - 10)
    {
	(void)fprintf(stderr, "Bad definition of EXTRACT_UCHAR() in config.h.\n");
	exit(1);
    }
    set_current_time();

#ifdef PROFILE_LPC
    set_profile_timebase(60.0); /* One minute */
#endif

#if RESERVED_SIZE > 0
    reserved_area = malloc(RESERVED_SIZE);
#endif

    init_random();
    init_tasks();
    query_load_av();
    init_num_args();
    init_machine();
    init_cfuns();
    init_hash();

    /*
     * Set up the signal handling.
     */
    init_signals();

    if (chdir(mudlib_path) == -1) {
        (void)fprintf(stderr, "Bad mudlib directory: %s\n", MUD_LIB);
	exit(1);
    }

    if (setjmp(exception_frame.e_context))
    {
	clear_state();
	add_message("Anomaly in the fabric of world space.\n");
    } 
    else
    {
	exception_frame.e_exception = NULL;
	exception_frame.e_catch = 0;
	exception = &exception_frame;
	auto_ob = 0;
	master_ob = 0;
	
	if ((auto_ob = load_object("secure/auto", 1, 0, 0)) != NULL)
	{
	    add_ref(auto_ob, "main");
	    auto_ob->prog->flags |= PRAGMA_RESIDENT;
	}

	get_simul_efun();
	master_ob = load_object("secure/master", 1, 0, 0);
	if (master_ob)
	{
	    /*
	     * Make sure master_ob is never made a dangling pointer.
	     * Look at apply_master_ob() for more details.
	     */
	    add_ref(master_ob, "main");
	    master_ob->prog->flags |= PRAGMA_RESIDENT;
            resolve_master_fkntab();
	    create_object(master_ob);
            load_parse_information();
	    clear_state();
	}
    }
    exception = NULL;
    if (auto_ob == 0) 
    {
	(void)fprintf(stderr, "The file secure/auto must be loadable.\n");
	exit(1);
    }
    if (master_ob == 0) 
    {
	(void)fprintf(stderr, "The file secure/master must be loadable.\n");
	exit(1);
    }
    set_inc_list(apply_master_ob(M_DEFINE_INCLUDE_DIRS, 0));
    
    {
	struct svalue* ret1;

	ret1 = apply_master_ob(M_PREDEF_DEFINES, 0);
	if (ret1 && ret1->type == T_POINTER)
	{
	    int ii;

	    for (ii = 0; ii < ret1->u.vec->size; ii++)
		if (ret1->u.vec->item[ii].type == T_STRING)
		{
                    add_pre_define(ret1->u.vec->item[ii].u.string);
		}
	}
    }

    if (flag != NULL)
    {
        printf("Applying driver flag: %s\n", flag);
        push_string(flag, STRING_MSTRING);
        (void)apply_master_ob(M_FLAG, 1);

        if (game_is_being_shut_down)
        {
            (void)fprintf(stderr, "Shutdown by master object.\n");
            exit(0);
        }
    }

    /*
     * See to it that the mud name is always defined in compiled files
     */
    ret = apply_master_ob(M_GET_MUD_NAME, 0);

    if (ret && ret->type == T_STRING)
    {
	struct lpc_predef_s *tmp;
		
	tmp = (struct lpc_predef_s *)
	    xalloc(sizeof(struct lpc_predef_s));
	if (!tmp) 
	    fatal("xalloc failed\n");
	tmp->flag = string_copy(ret->u.string);
	tmp->next = lpc_predefs;
	lpc_predefs = tmp;
    }

    ret = apply_master_ob(M_GET_VBFC_OBJECT, 0);
    if (ret && ret->type == T_OBJECT)
    {
	vbfc_object = ret->u.ob;
	INCREF(vbfc_object->ref);
    }
    else
	vbfc_object = 0;

    if (game_is_being_shut_down)
	exit(1);

    init_call_out();
    preload_objects(e_flag);
    (void)apply_master_ob(M_FINAL_BOOT, 0);
    
    mainloop();

    return 0;
}
Exemple #22
0
/*
 * Remove an interactive player immediately.
 */
void
remove_interactive(struct interactive *ip, int link_dead)
{
    struct object *save = command_giver;
    struct object *ob = ip->ob;
    int i;

    if (!ob || !(ob->interactive))
	return;
    for (i = 0; i < MAX_PLAYERS; i++)
    {
	if (all_players[i] != ob->interactive)
	    continue;
	if (ob->interactive->closing)
	    fatal("Double call to remove_interactive()\n");

	command_giver = ob;

	if (ob->interactive->ed_buffer)
	{
	    extern void save_ed_buffer(void);

	    /* This will call 'get_ed_buffer_save_file_name' in master_ob
             * If that fails(error in LPC) the closing IP will hang and
	     * on the next read a 'fatal read on closing socket will occur'
	     * unless we do this here before ip->closing = 1
	     */
	    (void)add_message("Saving editor buffer.\n");
	    save_ed_buffer();
	}
	if (ob->interactive == NULL)
	    return;
	ob->interactive->closing = 1;
	if (ob->interactive->snoop_by)
	{
	    ob->interactive->snoop_by->snoop_on = 0;
	    ob->interactive->snoop_by = 0;
	}
	if (ob->interactive->snoop_on)
	{
	    ob->interactive->snoop_on->snoop_by = 0;
	    ob->interactive->snoop_on = 0;
	}
	write_socket("Closing down.\n", ob);
	telnet_detach(ob->interactive->tp);
#ifdef SUPER_SNOOP
	if (ob->interactive->snoop_fd >= 0) {
	    (void)close(ob->interactive->snoop_fd);
	    ob->interactive->snoop_fd = -1;
	}
#endif
	num_player--;
	if (ob->interactive->input_to)
	{
	    free_sentence(ob->interactive->input_to);
	    ob->interactive->input_to = 0;
	}
	if(ob->interactive->rname)
	    free(ob->interactive->rname);
	if (current_interactive == ob)
	    current_interactive = 0;
	free((char *)ob->interactive);
	ob->interactive = 0;
	all_players[i] = 0;
	free_object(ob, "remove_interactive");

	push_object(ob);
	push_number(link_dead);
	(void)apply_master_ob(M_REMOVE_INTERACTIVE,2);
	
	command_giver = save;
	return;
    }
    fatal("Could not find and remove player %s\n", ob->name);
}
Exemple #23
0
int 
main(int argc, char **argv)
{
    extern int game_is_being_shut_down;
    int i, new_mudlib = 0;
    char *p;
    struct svalue *ret;
    extern struct svalue catch_value;
    extern void init_cfuns(void);
    struct gdexception exception_frame;

    (void)setlinebuf(stdout);

    const0.type = T_NUMBER; const0.u.number = 0;
    const1.type = T_NUMBER; const1.u.number = 1;
    constempty.type = T_FUNCTION; constempty.u.func = &funcempty;
    funcempty.funtype = FUN_EMPTY;
    catch_value = const0;
    
    /*
     * Check that the definition of EXTRACT_UCHAR() is correct.
     */
    p = (char *)&i;
    *p = -10;
    if (EXTRACT_UCHAR(p) != 0x100 - 10)
    {
	(void)fprintf(stderr, "Bad definition of EXTRACT_UCHAR() in config.h.\n");
	exit(1);
    }
    set_current_time();
#ifdef PROFILE_LPC
    set_profile_timebase(60.0); /* One minute */
#endif

#ifdef DRAND48
    srand48((long)current_time);
#else
#ifdef RANDOM
    srandom(current_time);
#else
#error No random generator specified!\n
#endif /* RANDOM */
#endif /* DRAND48 */

#if RESERVED_SIZE > 0
    reserved_area = malloc(RESERVED_SIZE);
#endif
    init_tasks();
    query_load_av();
    init_num_args();
    init_machine();
    init_cfuns();

    /*
     * Set up the signal handling.
     */
    init_signals();

    /*
     * 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 (atoi(argv[i]))
	    port_number = atoi(argv[i]);
	else if (argv[i][0] != '-')
	    continue;
	switch(argv[i][1])
	{
	case 'D':
	    if (argv[i][2]) { /* Amylaar : allow flags to be passed down to
				 the LPC preprocessor */
		struct lpc_predef_s *tmp;
		
		tmp = (struct lpc_predef_s *)
		    xalloc(sizeof(struct lpc_predef_s));
		if (!tmp)
		    fatal("xalloc failed\n");
		tmp->flag = string_copy(argv[i]+2);
		tmp->next = lpc_predefs;
		lpc_predefs = tmp;
		continue;
	    }
	    (void)fprintf(stderr, "Illegal flag syntax: %s\n", argv[i]);
	    exit(1);
	    /* NOTREACHED */
	case 'N':
	    no_ip_demon++; continue;
	case 'm':
	    if (chdir(argv[i]+2) == -1)
	    {
	        (void)fprintf(stderr, "Bad mudlib directory: %s\n", argv[i]+2);
		exit(1);
	    }
	    new_mudlib = 1;
	    break;
	}
    }

    if (!new_mudlib && chdir(MUD_LIB) == -1) {
        (void)fprintf(stderr, "Bad mudlib directory: %s\n", MUD_LIB);
	exit(1);
    }

    if (setjmp(exception_frame.e_context))
    {
	clear_state();
	add_message("Anomaly in the fabric of world space.\n");
    } 
    else
    {
	exception_frame.e_exception = NULL;
	exception_frame.e_catch = 0;
	exception = &exception_frame;
	auto_ob = 0;
	master_ob = 0;
	
	if ((auto_ob = load_object("secure/auto", 1, 0, 0)) != NULL)
	{
	    add_ref(auto_ob, "main");
	    auto_ob->prog->flags |= PRAGMA_RESIDENT;
	}

	get_simul_efun();
	master_ob = load_object("secure/master", 1, 0, 0);
	if (master_ob)
	{
	    /*
	     * Make sure master_ob is never made a dangling pointer.
	     * Look at apply_master_ob() for more details.
	     */
	    add_ref(master_ob, "main");
	    master_ob->prog->flags |= PRAGMA_RESIDENT;
            resolve_master_fkntab();
	    create_object(master_ob);
            load_parse_information();
	    clear_state();
	}
    }
    exception = NULL;
    if (auto_ob == 0) 
    {
	(void)fprintf(stderr, "The file secure/auto must be loadable.\n");
	exit(1);
    }
    if (master_ob == 0) 
    {
	(void)fprintf(stderr, "The file secure/master must be loadable.\n");
	exit(1);
    }
    set_inc_list(apply_master_ob(M_DEFINE_INCLUDE_DIRS, 0));
    {
	struct svalue* ret1;

	ret1 = apply_master_ob(M_PREDEF_DEFINES, 0);
	if (ret1 && ret1->type == T_POINTER)
	{
	    int ii;
	    struct lpc_predef_s *tmp;

	    for (ii = 0; ii < ret1->u.vec->size; ii++)
		if (ret1->u.vec->item[ii].type == T_STRING)
		{
		    tmp = (struct lpc_predef_s *)
			xalloc(sizeof(struct lpc_predef_s));
		    tmp->flag = string_copy(ret1->u.vec->item[ii].u.string);
		    tmp->next = lpc_predefs;
		    lpc_predefs = tmp;
		}
	}
    }
    for (i = 1; i < argc; i++)
    {
	if (atoi(argv[i]))
	    ;
	else if (argv[i][0] != '-')
	{
	    (void)fprintf(stderr, "Bad argument %s\n", argv[i]);
	    exit(1);
	}
	else 
	{
	    /*
	     * Look at flags. -m has already been tested.
	     */
	    switch(argv[i][1])
	    {
	    case 'f':
		push_string(argv[i]+2, STRING_MSTRING);
		(void)apply_master_ob(M_FLAG, 1);
		if (game_is_being_shut_down)
		{
		    (void)fprintf(stderr, "Shutdown by master object.\n");
		    exit(0);
		}
		continue;
	    case 'e':
		e_flag++; continue;
	    case 'O':
		warnobsoleteflag++; continue;
	    case 'D':
		continue;
	    case 'N':
		continue;
	    case 'm':
		continue;
	    case 'd':
		d_flag = atoi(argv[i] + 2);
		continue;
	    case 'c':
		comp_flag++; continue;
	    case 'l':
		unlimited++;
		continue;
	    case 't':
		t_flag++; continue;
	    case 'S':
		s_flag++; 
		mudstatus_set(1, -1, -1); /* Statistics, default limits */
		continue;
	    case 'u':
#ifdef CATCH_UDP_PORT
		udp_port = atoi (&argv[i][2]);
#endif
		continue;
	    case 'p':
#ifdef SERVICE_PORT
		service_port = atoi (&argv[i][2]);
#endif
		continue;
	    case 'y':
#ifdef YYDEBUG
		yydebug = 1;
#endif
		continue;
	    default:
		(void)fprintf(stderr, "Unknown flag: %s\n", argv[i]);
		exit(1);
	    }
	}
    }

    /*
     * See to it that the mud name is always defined in compiled files
     */
    ret = apply_master_ob(M_GET_MUD_NAME, 0);

    if (ret && ret->type == T_STRING)
    {
	struct lpc_predef_s *tmp;
		
	tmp = (struct lpc_predef_s *)
	    xalloc(sizeof(struct lpc_predef_s));
	if (!tmp) 
	    fatal("xalloc failed\n");
	tmp->flag = string_copy(ret->u.string);
	tmp->next = lpc_predefs;
	lpc_predefs = tmp;
    }

    ret = apply_master_ob(M_GET_VBFC_OBJECT, 0);
    if (ret && ret->type == T_OBJECT)
    {
	vbfc_object = ret->u.ob;
	INCREF(vbfc_object->ref);
    }
    else
	vbfc_object = 0;

    if (game_is_being_shut_down)
	exit(1);

    if (!t_flag)
	init_call_out();

    preload_objects(e_flag);
    (void)apply_master_ob(M_FINAL_BOOT, 0);
    

    mainloop();
    /* backend(); */

    return 0;
}