Ejemplo n.º 1
0
void handle_read(struct request *req, int val){
    aiob *aio = req->aio;
    close(aio->aio_fildes);
    if(val){
        FREE(aio->aio_buf);
        push_number(val);
        set_eval(max_cost);
        safe_call_efun_callback(req->fun, 1);
        return;
    }
    val = aio_return(aio);
    if(val < 0){
        FREE(aio->aio_buf);
        push_number(val);
        set_eval(max_cost);
        safe_call_efun_callback(req->fun, 1);
        return;
    }
    char *file = new_string(val, "read_file_async: str");
    memcpy(file, (char *)(aio->aio_buf), val);
    file[val]=0;
    push_malloced_string(file);
    FREE(aio->aio_buf);
    set_eval(max_cost);
    safe_call_efun_callback(req->fun, 1);
}
Ejemplo n.º 2
0
Archivo: async.c Proyecto: Elohim/FGmud
void handle_write(struct request *req){
	free_svalue(&req->tmp, "handle_write");
	int val = req->ret;
	if(val < 0){
		push_number(val);
		set_eval(max_cost);
		safe_call_efun_callback(req->fun, 1);
		return;
	}
	push_undefined();
	set_eval(max_cost);
	safe_call_efun_callback(req->fun, 1);
}
Ejemplo n.º 3
0
void handle_getdir(struct request *req, int val){
    aiob *aio = req->aio;
    close(aio->aio_fildes);
    val = aio_return(aio);
    array_t *ret = allocate_empty_array(val);
    int i;
    if(val > -1)
    {
        struct linux_dirent *de = (struct linux_dirent *)aio->aio_buf;
        for(i=0; ((char *)de) - (char *)(aio->aio_buf) < val; i++)
        {
            svalue_t *vp = &(ret->item[i]);
            vp->type = T_STRING;
            vp->subtype = STRING_MALLOC;
            //printf("%s ", de->d_name);
            vp->u.string = string_copy(de->d_name, "encode_stat");
            de = (struct linux_dirent *)(((char *)de) + de->d_reclen);
        }
    }
    ret = RESIZE_ARRAY(ret, i);
    ret->size = i;
    push_refed_array(ret);
    set_eval(max_cost);
    safe_call_efun_callback(req->fun, 1);
}
Ejemplo n.º 4
0
Archivo: async.c Proyecto: Elohim/FGmud
void handle_getdir(struct request *req){
	int val = req->ret;
	if(val>MAX_ARRAY_SIZE)
		val = MAX_ARRAY_SIZE;
	array_t *ret = allocate_empty_array(val);
	int i=0;
	if(val > 0)
	{
		struct linux_dirent *de = (struct linux_dirent *)req->buf;
		for(i=0; i<MAX_ARRAY_SIZE && ((char *)de) - (char *)(req->buf) < val; i++)
		{
			svalue_t *vp = &(ret->item[i]);
			vp->type = T_STRING;
			vp->subtype = STRING_MALLOC;
			vp->u.string = string_copy(de->d_name, "encode_stat");
			de = (struct linux_dirent *)(((char *)de) + de->d_reclen);
		}
	}
	ret = resize_array(ret, i);
	ret->size = i;
	push_refed_array(ret);
	FREE((void *)req->buf);
	set_eval(max_cost);
	safe_call_efun_callback(req->fun, 1);
}
Ejemplo n.º 5
0
Archivo: async.c Proyecto: Elohim/FGmud
void handle_read(struct request *req){
	int val = req->ret;
	if(val < 0){
		FREE((void *)req->buf);
		push_number(val);
		set_eval(max_cost);
		safe_call_efun_callback(req->fun, 1);
		return;
	}
	char *file = new_string(val, "read_file_async: str");
	memcpy(file, (char *)(req->buf), val);
	file[val]=0;
	push_malloced_string(file);
	FREE((void *)req->buf);
	set_eval(max_cost);
	safe_call_efun_callback(req->fun, 1);
}
Ejemplo n.º 6
0
orcaData parserParser::eval(orcaVM* vm, const string& src)/*{{{*/
{
	set_eval(true);

	//printf(">>> eval: %s\n", src.c_str());
	curr_fp = fmemopen((void*)src.c_str(), src.size(), "r");

	// init
	parserCode::init();
	parserCode::push_code_stack((char*)"eval", NULL);
	code_top->init_current();  

	// parse
	int rv;
	try {
		init();
		try {
			rv = yyparse();
		}
		catch(const char* cp) {
			printf("%s\n", cp);
			rv = -1;
		}

		if (rv == 0) {
			code_top->push_char(OP_RETURN);
			code_top->eval(vm);
		}

		if (!is<TYPE_NIL>(g_last_pop_stack)) {
			parserCode::init();
			set_eval(false);
			return g_last_pop_stack;
		}
	}
	catch(orcaException& e) {
		printf("uncaugted exception: %s %s\n", e.who(), e.what());
		cout << e.m_stack_trace << endl;
	}

	parserCode::init();
	set_eval(false);
	return NIL;
}
Ejemplo n.º 7
0
Archivo: async.c Proyecto: Elohim/FGmud
void handle_db_exec(struct request *req){
	free_svalue(&req->tmp, "handle_db_exec");
	int val = req->ret;
	if(val == -1){
		copy_and_push_string(req->path);
	}
	else
		push_number(val);
	set_eval(max_cost);
	safe_call_efun_callback(req->fun, 1);
}
Ejemplo n.º 8
0
void handle_write(struct request *req, int val){
    aiob *aio = req->aio;
    close(aio->aio_fildes);
    free_svalue(&req->tmp, "handle_write");
    if(val){
        push_number(val);
        set_eval(max_cost);
        safe_call_efun_callback(req->fun, 1);
        return;
    }
    val = aio_return(aio);
    if(val < 0){
        push_number(val);
        set_eval(max_cost);
        safe_call_efun_callback(req->fun, 1);
        return;
    }
    push_undefined();
    set_eval(max_cost);
    safe_call_efun_callback(req->fun, 1);
}
Ejemplo n.º 9
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() */
Ejemplo n.º 10
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;
}
Ejemplo n.º 11
0
void backend()
{
    struct timeval timeout;
    int i, nb;
    volatile int first_call = 1;
    int there_is_a_port = 0;
    error_context_t econ;

    debug_message("Initializations complete.\n\n");
    for (i = 0; i < 5; i++) {
        if (external_port[i].port) {
            debug_message("Accepting connections on port %d.\n",
                    external_port[i].port);
            there_is_a_port = 1;
        }
    }

    if (!there_is_a_port)
        debug_message("No external ports specified.\n");

    init_user_conn();   /* initialize user connection socket */
#ifdef SIGHUP
    signal(SIGHUP, startshutdownMudOS);
#endif
    clear_state();
    save_context(&econ);
    if (SETJMP(econ.context))
        restore_context(&econ);
    if (!t_flag && first_call) {
        first_call = 0;
        call_heart_beat();
    }

    while (1) {
        /* Has to be cleared if we jumped out of process_user_command() */
        current_interactive = 0;
        set_eval(max_cost);

        if (obj_list_replace || obj_list_destruct)
            remove_destructed_objects();

        /*
         * shut down MudOS if MudOS_is_being_shut_down is set.
         */
        if (MudOS_is_being_shut_down)
            shutdownMudOS(0);
        if (slow_shut_down_to_do) {
            int tmp = slow_shut_down_to_do;

            slow_shut_down_to_do = 0;
            slow_shut_down(tmp);
        }
        /*
         * select
         */
        make_selectmasks();
        timeout.tv_sec = 1;
        timeout.tv_usec = 0;
#ifndef hpux
        nb = select(FD_SETSIZE, &readmask, &writemask, (fd_set *) 0, &timeout);
#else
        nb = select(FD_SETSIZE, (int *) &readmask, (int *) &writemask,
                (int *) 0, &timeout);
#endif
        /*
         * process I/O if necessary.
         */
        if (nb > 0) {
            process_io();
        }
        /*
         * process user commands.
         */
        for (i = 0; process_user_command() && i < max_users; i++)
            ;

        /*
         * call outs
         */
        call_out();
#ifdef PACKAGE_ASYNC
        check_reqs();
#endif
    }
}       /* backend() */
Ejemplo n.º 12
0
void call_heart_beat()
{
    object_t *ob;
    heart_beat_t *curr_hb;
    error_context_t econ;

    current_interactive = 0;

    if ((num_hb_to_do = num_hb_objs)) {
        num_hb_calls++;
        heart_beat_index = 0;
        save_context(&econ);
        while (1) {
            ob = (curr_hb = &heart_beats[heart_beat_index])->ob;
            DEBUG_CHECK(!(ob->flags & O_HEART_BEAT),
                    "Heartbeat not set in object on heartbeat list!");
            /* is it time to do a heart beat ? */
            curr_hb->heart_beat_ticks--;

            if (ob->prog->heart_beat != 0) {
                if (curr_hb->heart_beat_ticks < 1) {
                    object_t *new_command_giver;
                    curr_hb->heart_beat_ticks = curr_hb->time_to_heart_beat;
                    current_heart_beat = ob;
                    new_command_giver = ob;
#ifndef NO_SHADOWS
                    while (new_command_giver->shadowing)
                        new_command_giver = new_command_giver->shadowing;
#endif
#ifndef NO_ADD_ACTION
                    if (!(new_command_giver->flags & O_ENABLE_COMMANDS))
                        new_command_giver = 0;
#endif
#ifdef PACKAGE_MUDLIB_STATS
                    add_heart_beats(&ob->stats, 1);
#endif
                    set_eval(max_cost);

                    if (SETJMP(econ.context)) {
                        restore_context(&econ);
                    } else {
                        save_command_giver(new_command_giver);
                        call_direct(ob, ob->prog->heart_beat - 1,
                                ORIGIN_DRIVER, 0);
                        pop_stack(); /* pop the return value */
                        restore_command_giver();
                    }

                    current_object = 0;
                }
            }
            if (++heart_beat_index == num_hb_to_do)
                break;
        }
        pop_context(&econ);
        if (heart_beat_index < num_hb_to_do)
            perc_hb_probes = 100 * (float) heart_beat_index / num_hb_to_do;
        else
            perc_hb_probes = 100.0;
        heart_beat_index = num_hb_to_do = 0;
    }
    current_prog = 0;
    current_heart_beat = 0;
    look_for_objects_to_swap();
#ifdef PACKAGE_MUDLIB_STATS
    mudlib_stats_decay();
#endif
}       /* call_heart_beat() */
Ejemplo n.º 13
0
/*
 * Despite the name, this routine takes care of several things.
 * It will run once every 15 minutes.
 *
 * . It will attempt to reconnect to the address server if the connection has
 *   been lost.
 * . It will loop through all objects.
 *
 *   . If an object is found in a state of not having done reset, and the
 *     delay to next reset has passed, then reset() will be done.
 *
 *   . If the object has a existed more than the time limit given for swapping,
 *     then 'clean_up' will first be called in the object
 *
 * There are some problems if the object self-destructs in clean_up, so
 * special care has to be taken of how the linked list is used.
 */
static void look_for_objects_to_swap()
{
    static int next_time;
#ifndef NO_IP_DEMON
    extern int no_ip_demon;
    static int next_server_time;
#endif
    object_t *ob;
    VOLATILE object_t *next_ob;
    error_context_t econ;

#ifndef NO_IP_DEMON
    if (current_time >= next_server_time) {
        /* initialize the address server.  if it is already initialized, then
         * this is a nop.  this will cause the driver to reattempt connecting
         * to the address server once every 15 minutes in the event that it
         * has gone down.
         */
        if (!no_ip_demon && next_server_time)
            init_addr_server(ADDR_SERVER_IP, ADDR_SERVER_PORT);
        next_server_time = current_time + 15 * 60;
    }
#endif

    if (current_time < next_time)
        return;     /* Not time to look yet */
    next_time = current_time + 5 * 60; /* Next time is in 5 minutes */

    /*
     * Objects object can be destructed, which means that next object to
     * investigate is saved in next_ob. If very unlucky, that object can be
     * destructed too. In that case, the loop is simply restarted.
     */
    next_ob = obj_list;
    save_context(&econ);
    if (SETJMP(econ.context))
        restore_context(&econ);

    while ((ob = (object_t *)next_ob)) {
        int ready_for_clean_up = 0;

        if (ob->flags & O_DESTRUCTED)
            ob = obj_list;  /* restart */
        next_ob = ob->next_all;

        /*
         * Check reference time before reset() is called.
         */
        if (current_time - ob->time_of_ref > time_to_clean_up)
            ready_for_clean_up = 1;
#if !defined(NO_RESETS) && !defined(LAZY_RESETS)
        /*
         * Should this object have reset(1) called ?
         */
        if ((ob->flags & O_WILL_RESET) && (ob->next_reset < current_time)
                && !(ob->flags & O_RESET_STATE)) {
            debug(d_flag, ("RESET /%s\n", ob->obname));
            set_eval(max_cost);
            reset_object(ob);
            if(ob->flags & O_DESTRUCTED)
                continue;
        }
#endif
        if (time_to_clean_up > 0) {
            /*
             * Has enough time passed, to give the object a chance to
             * self-destruct ? Save the O_RESET_STATE, which will be cleared.
             *
             * Only call clean_up in objects that has defined such a function.
             *
             * Only if the clean_up returns a non-zero value, will it be called
             * again.
             */

            if (ready_for_clean_up && (ob->flags & O_WILL_CLEAN_UP)) {
                int save_reset_state = ob->flags & O_RESET_STATE;
                svalue_t *svp;

                debug(d_flag, ("clean up /%s\n", ob->obname));

                /*
                 * Supply a flag to the object that says if this program is
                 * inherited by other objects. Cloned objects might as well
                 * believe they are not inherited. Swapped objects will not
                 * have a ref count > 1 (and will have an invalid ob->prog
                 * pointer).
                 *
                 * Note that if it is in the apply_low cache, it will also
                 * get a flag of 1, which may cause the mudlib not to clean
                 * up the object.  This isn't bad because:
                 * (1) one expects it is rare for objects that have untouched
                 * long enough to clean_up to still be in the cache, especially
                 * on busy MUDs.
                 * (2) the ones that are are the more heavily used ones, so
                 * keeping them around seems justified.
                 */

                push_number(ob->flags & (O_CLONE) ? 0 : ob->prog->ref);
                set_eval(max_cost);
                svp = apply(APPLY_CLEAN_UP, ob, 1, ORIGIN_DRIVER);
                if (ob->flags & O_DESTRUCTED)
                    continue;
                if (!svp || (svp->type == T_NUMBER && svp->u.number == 0))
                    ob->flags &= ~O_WILL_CLEAN_UP;
                ob->flags |= save_reset_state;
            }
        }
    }
    pop_context(&econ);
}       /* look_for_objects_to_swap() */