dw_fluffos_v2/
dw_fluffos_v2/fluffos-2.9-ds2.05/
dw_fluffos_v2/fluffos-2.9-ds2.05/ChangeLog.old/
dw_fluffos_v2/fluffos-2.9-ds2.05/Win32/
dw_fluffos_v2/fluffos-2.9-ds2.05/compat/
dw_fluffos_v2/fluffos-2.9-ds2.05/compat/simuls/
dw_fluffos_v2/fluffos-2.9-ds2.05/include/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/clone/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/command/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/data/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/etc/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/include/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/inherit/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/inherit/master/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/log/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/single/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/single/tests/compiler/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/single/tests/efuns/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/single/tests/operators/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/u/
dw_fluffos_v2/fluffos-2.9-ds2.05/tmp/
dw_fluffos_v2/fluffos-2.9-ds2.05/windows/
dw_fluffos_v2/lib/
dw_fluffos_v2/lib/binaries/cmds/
dw_fluffos_v2/lib/binaries/cmds/creator/
dw_fluffos_v2/lib/binaries/cmds/living/
dw_fluffos_v2/lib/binaries/cmds/player/
dw_fluffos_v2/lib/binaries/d/admin/obj/
dw_fluffos_v2/lib/binaries/d/liaison/
dw_fluffos_v2/lib/binaries/global/virtual/
dw_fluffos_v2/lib/binaries/global/virtual/setup_compiler/
dw_fluffos_v2/lib/binaries/obj/handlers/autodoc/
dw_fluffos_v2/lib/binaries/obj/handlers/terrain_things/
dw_fluffos_v2/lib/binaries/obj/misc/
dw_fluffos_v2/lib/binaries/obj/misc/buckets/
dw_fluffos_v2/lib/binaries/obj/monster/
dw_fluffos_v2/lib/binaries/obj/reactions/
dw_fluffos_v2/lib/binaries/obj/reagents/
dw_fluffos_v2/lib/binaries/secure/cmds/creator/
dw_fluffos_v2/lib/binaries/secure/master/
dw_fluffos_v2/lib/binaries/std/
dw_fluffos_v2/lib/binaries/std/dom/
dw_fluffos_v2/lib/binaries/std/effects/object/
dw_fluffos_v2/lib/binaries/std/guilds/
dw_fluffos_v2/lib/binaries/std/languages/
dw_fluffos_v2/lib/binaries/std/races/
dw_fluffos_v2/lib/binaries/std/room/
dw_fluffos_v2/lib/binaries/std/room/basic/
dw_fluffos_v2/lib/binaries/std/shops/
dw_fluffos_v2/lib/binaries/std/shops/inherit/
dw_fluffos_v2/lib/binaries/www/
dw_fluffos_v2/lib/cmds/guild-race/
dw_fluffos_v2/lib/cmds/guild-race/crafts/
dw_fluffos_v2/lib/cmds/guild-race/other/
dw_fluffos_v2/lib/cmds/playtester/
dw_fluffos_v2/lib/cmds/playtester/senior/
dw_fluffos_v2/lib/d/admin/
dw_fluffos_v2/lib/d/admin/log/
dw_fluffos_v2/lib/d/admin/mapper/31-10-01/mapmaker/event/
dw_fluffos_v2/lib/d/admin/meetings/
dw_fluffos_v2/lib/d/admin/obj/
dw_fluffos_v2/lib/d/admin/room/we_care/
dw_fluffos_v2/lib/d/admin/save/
dw_fluffos_v2/lib/d/dist/
dw_fluffos_v2/lib/d/dist/mtf/
dw_fluffos_v2/lib/d/dist/pumpkin/
dw_fluffos_v2/lib/d/dist/pumpkin/chars/
dw_fluffos_v2/lib/d/dist/pumpkin/desert/
dw_fluffos_v2/lib/d/dist/pumpkin/gumboot/
dw_fluffos_v2/lib/d/dist/pumpkin/hospital/
dw_fluffos_v2/lib/d/dist/pumpkin/inherit/
dw_fluffos_v2/lib/d/dist/pumpkin/map/
dw_fluffos_v2/lib/d/dist/pumpkin/plain/
dw_fluffos_v2/lib/d/dist/pumpkin/pumpkin/
dw_fluffos_v2/lib/d/dist/pumpkin/save/
dw_fluffos_v2/lib/d/dist/pumpkin/squash/
dw_fluffos_v2/lib/d/dist/pumpkin/terrain/
dw_fluffos_v2/lib/d/dist/pumpkin/woods/
dw_fluffos_v2/lib/d/dist/start/
dw_fluffos_v2/lib/d/learning/TinyTown/buildings/
dw_fluffos_v2/lib/d/learning/TinyTown/map/
dw_fluffos_v2/lib/d/learning/TinyTown/roads/
dw_fluffos_v2/lib/d/learning/add_command/
dw_fluffos_v2/lib/d/learning/arms_and_weps/
dw_fluffos_v2/lib/d/learning/chars/
dw_fluffos_v2/lib/d/learning/cutnpaste/
dw_fluffos_v2/lib/d/learning/examples/npcs/
dw_fluffos_v2/lib/d/learning/examples/player_houses/npcs/
dw_fluffos_v2/lib/d/learning/examples/terrain_map/basic/
dw_fluffos_v2/lib/d/learning/functions/
dw_fluffos_v2/lib/d/learning/handlers/
dw_fluffos_v2/lib/d/learning/help_topics/npcs/
dw_fluffos_v2/lib/d/learning/help_topics/objects/
dw_fluffos_v2/lib/d/learning/help_topics/rcs_demo/
dw_fluffos_v2/lib/d/learning/help_topics/rooms/
dw_fluffos_v2/lib/d/learning/help_topics/rooms/crowd/
dw_fluffos_v2/lib/d/learning/help_topics/rooms/situations/
dw_fluffos_v2/lib/d/learning/items/
dw_fluffos_v2/lib/d/learning/save/
dw_fluffos_v2/lib/d/liaison/
dw_fluffos_v2/lib/d/liaison/NEWBIE/doc/
dw_fluffos_v2/lib/d/liaison/NEWBIE/save/oldlog/
dw_fluffos_v2/lib/db/
dw_fluffos_v2/lib/doc/
dw_fluffos_v2/lib/doc/creator/
dw_fluffos_v2/lib/doc/creator/autodoc/include/reaction/
dw_fluffos_v2/lib/doc/creator/autodoc/include/ritual_system/
dw_fluffos_v2/lib/doc/creator/autodoc/include/talker/
dw_fluffos_v2/lib/doc/creator/autodoc/include/terrain_map/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/baggage/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/clock/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/clothing/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/cont_save/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/corpse/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/money/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/monster/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/scabbard/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/service_provider/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/state_changer/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/wand/
dw_fluffos_v2/lib/doc/creator/autodoc/std/book_dir/
dw_fluffos_v2/lib/doc/creator/autodoc/std/key/
dw_fluffos_v2/lib/doc/creator/autodoc/std/learning/
dw_fluffos_v2/lib/doc/creator/autodoc/std/map/
dw_fluffos_v2/lib/doc/creator/autodoc/std/race/
dw_fluffos_v2/lib/doc/creator/autodoc/std/weapon_logic/
dw_fluffos_v2/lib/doc/creator/files/
dw_fluffos_v2/lib/doc/creator/policy/
dw_fluffos_v2/lib/doc/creator/room/
dw_fluffos_v2/lib/doc/effects/
dw_fluffos_v2/lib/doc/ideas/
dw_fluffos_v2/lib/doc/known_command/
dw_fluffos_v2/lib/doc/lpc/basic_manual/
dw_fluffos_v2/lib/doc/lpc/intermediate/
dw_fluffos_v2/lib/doc/new/add_command/
dw_fluffos_v2/lib/doc/new/handlers/
dw_fluffos_v2/lib/doc/new/living/
dw_fluffos_v2/lib/doc/new/living/race/
dw_fluffos_v2/lib/doc/new/living/spells/
dw_fluffos_v2/lib/doc/new/player/
dw_fluffos_v2/lib/doc/new/room/guild/
dw_fluffos_v2/lib/doc/new/room/outside/
dw_fluffos_v2/lib/doc/new/room/storeroom/
dw_fluffos_v2/lib/doc/object/
dw_fluffos_v2/lib/doc/playtesters/
dw_fluffos_v2/lib/doc/policy/
dw_fluffos_v2/lib/doc/weapons/
dw_fluffos_v2/lib/global/handlers/
dw_fluffos_v2/lib/global/virtual/setup_compiler/
dw_fluffos_v2/lib/include/
dw_fluffos_v2/lib/include/cmds/
dw_fluffos_v2/lib/include/effects/
dw_fluffos_v2/lib/include/npc/
dw_fluffos_v2/lib/include/shops/
dw_fluffos_v2/lib/net/daemon/chars/
dw_fluffos_v2/lib/net/inherit/
dw_fluffos_v2/lib/net/intermud3/
dw_fluffos_v2/lib/net/intermud3/services/
dw_fluffos_v2/lib/net/obj/
dw_fluffos_v2/lib/net/save/
dw_fluffos_v2/lib/net/smnmp/
dw_fluffos_v2/lib/net/snmp/
dw_fluffos_v2/lib/obj/amulets/
dw_fluffos_v2/lib/obj/b_day/
dw_fluffos_v2/lib/obj/examples/
dw_fluffos_v2/lib/obj/food/alcohol/
dw_fluffos_v2/lib/obj/food/chocolates/
dw_fluffos_v2/lib/obj/food/fruits/
dw_fluffos_v2/lib/obj/food/meat/
dw_fluffos_v2/lib/obj/food/nuts/
dw_fluffos_v2/lib/obj/food/seafood/
dw_fluffos_v2/lib/obj/food/vegetables/
dw_fluffos_v2/lib/obj/fungi/
dw_fluffos_v2/lib/obj/furnitures/artwork/
dw_fluffos_v2/lib/obj/furnitures/bathroom/
dw_fluffos_v2/lib/obj/furnitures/beds/
dw_fluffos_v2/lib/obj/furnitures/cabinets/
dw_fluffos_v2/lib/obj/furnitures/chairs/
dw_fluffos_v2/lib/obj/furnitures/chests/
dw_fluffos_v2/lib/obj/furnitures/clocks/
dw_fluffos_v2/lib/obj/furnitures/crockery/
dw_fluffos_v2/lib/obj/furnitures/cupboards/
dw_fluffos_v2/lib/obj/furnitures/cushions/
dw_fluffos_v2/lib/obj/furnitures/fake_plants/
dw_fluffos_v2/lib/obj/furnitures/lamps/
dw_fluffos_v2/lib/obj/furnitures/mirrors/
dw_fluffos_v2/lib/obj/furnitures/outdoor/
dw_fluffos_v2/lib/obj/furnitures/safes/
dw_fluffos_v2/lib/obj/furnitures/shelves/
dw_fluffos_v2/lib/obj/furnitures/sideboards/
dw_fluffos_v2/lib/obj/furnitures/sofas/
dw_fluffos_v2/lib/obj/furnitures/stoves/
dw_fluffos_v2/lib/obj/furnitures/tables/
dw_fluffos_v2/lib/obj/furnitures/wardrobes/
dw_fluffos_v2/lib/obj/handlers/
dw_fluffos_v2/lib/obj/handlers/autodoc/
dw_fluffos_v2/lib/obj/jewellery/anklets/
dw_fluffos_v2/lib/obj/jewellery/bracelets/
dw_fluffos_v2/lib/obj/jewellery/earrings/
dw_fluffos_v2/lib/obj/jewellery/misc/
dw_fluffos_v2/lib/obj/jewellery/necklaces/
dw_fluffos_v2/lib/obj/jewellery/rings/
dw_fluffos_v2/lib/obj/media/
dw_fluffos_v2/lib/obj/misc/buckets/
dw_fluffos_v2/lib/obj/misc/jars/
dw_fluffos_v2/lib/obj/misc/papers/
dw_fluffos_v2/lib/obj/misc/player_shop/
dw_fluffos_v2/lib/obj/misc/shops/
dw_fluffos_v2/lib/obj/misc/traps/
dw_fluffos_v2/lib/obj/monster/
dw_fluffos_v2/lib/obj/monster/godmother/
dw_fluffos_v2/lib/obj/monster/transport/
dw_fluffos_v2/lib/obj/plants/inherit/
dw_fluffos_v2/lib/obj/potions/
dw_fluffos_v2/lib/open/boards/
dw_fluffos_v2/lib/save/autodoc/
dw_fluffos_v2/lib/save/bank_accounts/
dw_fluffos_v2/lib/save/boards/frog/
dw_fluffos_v2/lib/save/books/bed_catalog/
dw_fluffos_v2/lib/save/creators/
dw_fluffos_v2/lib/save/mail/
dw_fluffos_v2/lib/save/mail/p/
dw_fluffos_v2/lib/save/soul/data/
dw_fluffos_v2/lib/save/tasks/
dw_fluffos_v2/lib/save/vaults/
dw_fluffos_v2/lib/secure/cmds/lord/
dw_fluffos_v2/lib/secure/config/
dw_fluffos_v2/lib/secure/items/
dw_fluffos_v2/lib/secure/player/
dw_fluffos_v2/lib/soul/
dw_fluffos_v2/lib/soul/i/
dw_fluffos_v2/lib/soul/j/
dw_fluffos_v2/lib/soul/k/
dw_fluffos_v2/lib/soul/o/
dw_fluffos_v2/lib/soul/q/
dw_fluffos_v2/lib/soul/to_approve/
dw_fluffos_v2/lib/soul/u/
dw_fluffos_v2/lib/soul/v/
dw_fluffos_v2/lib/soul/wish_list/
dw_fluffos_v2/lib/soul/y/
dw_fluffos_v2/lib/soul/z/
dw_fluffos_v2/lib/std/creator/
dw_fluffos_v2/lib/std/effects/
dw_fluffos_v2/lib/std/effects/attached/
dw_fluffos_v2/lib/std/effects/external/
dw_fluffos_v2/lib/std/effects/fighting/
dw_fluffos_v2/lib/std/effects/other/
dw_fluffos_v2/lib/std/environ/
dw_fluffos_v2/lib/std/guilds/
dw_fluffos_v2/lib/std/hospital/
dw_fluffos_v2/lib/std/house/
dw_fluffos_v2/lib/std/house/onebedhouse/
dw_fluffos_v2/lib/std/house/onebedhut/
dw_fluffos_v2/lib/std/house/tworoomflat/
dw_fluffos_v2/lib/std/languages/
dw_fluffos_v2/lib/std/liquids/
dw_fluffos_v2/lib/std/nationality/
dw_fluffos_v2/lib/std/nationality/accents/
dw_fluffos_v2/lib/std/nationality/accents/national/
dw_fluffos_v2/lib/std/nationality/accents/regional/
dw_fluffos_v2/lib/std/npc/goals/
dw_fluffos_v2/lib/std/npc/goals/basic/
dw_fluffos_v2/lib/std/npc/goals/misc/
dw_fluffos_v2/lib/std/npc/inherit/
dw_fluffos_v2/lib/std/npc/plans/
dw_fluffos_v2/lib/std/npc/plans/basic/
dw_fluffos_v2/lib/std/outsides/
dw_fluffos_v2/lib/std/races/shadows/
dw_fluffos_v2/lib/std/room/basic/topography/
dw_fluffos_v2/lib/std/room/controller/
dw_fluffos_v2/lib/std/room/controller/topography/
dw_fluffos_v2/lib/std/room/furniture/games/
dw_fluffos_v2/lib/std/room/furniture/inherit/
dw_fluffos_v2/lib/std/room/inherit/carriage/
dw_fluffos_v2/lib/std/room/inherit/topography/
dw_fluffos_v2/lib/std/room/punishments/
dw_fluffos_v2/lib/std/room/topography/area/
dw_fluffos_v2/lib/std/room/topography/iroom/
dw_fluffos_v2/lib/std/room/topography/milestone/
dw_fluffos_v2/lib/std/shadows/
dw_fluffos_v2/lib/std/shadows/attached/
dw_fluffos_v2/lib/std/shadows/curses/
dw_fluffos_v2/lib/std/shadows/disease/
dw_fluffos_v2/lib/std/shadows/fighting/
dw_fluffos_v2/lib/std/shadows/room/
dw_fluffos_v2/lib/std/shops/controllers/
dw_fluffos_v2/lib/std/shops/objs/
dw_fluffos_v2/lib/std/shops/player_shop/
dw_fluffos_v2/lib/std/shops/player_shop/office_code/
dw_fluffos_v2/lib/std/socket/
dw_fluffos_v2/lib/www/
dw_fluffos_v2/lib/www/external/autodoc/
dw_fluffos_v2/lib/www/external/java/telnet/Documentation/
dw_fluffos_v2/lib/www/external/java/telnet/Documentation/images/
dw_fluffos_v2/lib/www/external/java/telnet/examples/
dw_fluffos_v2/lib/www/external/java/telnet/tools/
dw_fluffos_v2/lib/www/pics/
dw_fluffos_v2/lib/www/secure/creator/
dw_fluffos_v2/lib/www/secure/editors/
dw_fluffos_v2/lib/www/secure/survey_results/
dw_fluffos_v2/win32/
/* 92/04/18 - cleaned up stylistically by Sulam@TMI */
#include "std.h"
#include "lpc_incl.h"
#include "backend.h"
#include "comm.h"
#include "replace_program.h"
#include "socket_efuns.h"
#include "call_out.h"
#include "port.h"
#include "lint.h"
#include "master.h"
#include "eval.h"

#ifdef PACKAGE_ASYNC
#include "packages/async.h"
#endif

#ifdef WIN32
#include <process.h>
void CDECL alarm_loop (void *);
#endif

error_context_t *current_error_context = 0;

/*
 * The 'current_time' is updated in the call_out cycles
 */
long current_time;

object_t *current_heart_beat;
static void look_for_objects_to_swap (void);
void call_heart_beat (void);

#if 0
static void report_holes (void);
#endif

/*
 * There are global variables that must be zeroed before any execution.
 * In case of errors, there will be a LONGJMP(), and the variables will
 * have to be cleared explicitely. They are normally maintained by the
 * code that use them.
 *
 * This routine must only be called from top level, not from inside
 * stack machine execution (as stack will be cleared).
 */
void clear_state()
{
    current_object = 0;
    set_command_giver(0);
    current_interactive = 0;
    previous_ob = 0;
    current_prog = 0;
    caller_type = 0;
    reset_machine(0);   /* Pop down the stack. */
}       /* clear_state() */

#if 0
static void report_holes() {
    if (current_object && current_object->name)
  debug_message("current_object is /%s\n", current_object->name);
    if (command_giver && command_giver->name)
  debug_message("command_giver is /%s\n", command_giver->name);
    if (current_interactive && current_interactive->name)
  debug_message("current_interactive is /%s\n", current_interactive->name);
    if (previous_ob && previous_ob->name)
  debug_message("previous_ob is /%s\n", previous_ob->name);
    if (current_prog && current_prog->name)
  debug_message("current_prog is /%s\n", current_prog->name);
    if (caller_type)
  debug_message("caller_type is %s\n", caller_type);
}
#endif

void logon (object_t * ob)
{
  if(ob->flags & O_DESTRUCTED){
    return;
  }
  /* current_object no longer set */
  apply(APPLY_LOGON, ob, 0, ORIGIN_DRIVER);
  /* function not existing is no longer fatal */
}

/*
 * This is the backend. We will stay here for ever (almost).
 */

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() */


/*
 * 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() */

/* Call all heart_beat() functions in all objects.  Also call the next reset,
 * and the call out.
 * We do heart beats by moving each object done to the end of the heart beat
 * list before we call its function, and always using the item at the head
 * of the list as our function to call.  We keep calling heart beats until
 * a timeout or we have done num_heart_objs calls.  It is done this way so
 * that objects can delete heart beating objects from the list from within
 * their heart beat without truncating the current round of heart beats.
 *
 * Set command_giver to current_object if it is a living object. If the object
 * is shadowed, check the shadowed object if living. There is no need to save
 * the value of the command_giver, as the caller resets it to 0 anyway.  */

typedef struct {
    object_t *ob;
    short heart_beat_ticks;
    short time_to_heart_beat;
} heart_beat_t;

static heart_beat_t *heart_beats = 0;
static int max_heart_beats = 0;
static int heart_beat_index = 0;
static int num_hb_objs = 0;
static int num_hb_to_do = 0;

static int num_hb_calls = 0;  /* starts */
static float perc_hb_probes = 100.0;  /* decaying avge of how many complete */

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() */

int
query_heart_beat (object_t * ob)
{
    int index;

    if (!(ob->flags & O_HEART_BEAT))  return 0;
    index = num_hb_objs;
    while (index--) {
  if (heart_beats[index].ob == ob)
      return heart_beats[index].time_to_heart_beat;
    }
    return 0;
}       /* query_heart_beat() */

/* add or remove an object from the heart beat list; does the major check...
 * If an object removes something from the list from within a heart beat,
 * various pointers in call_heart_beat could be stuffed, so we must
 * check current_heart_beat and adjust pointers.  */

int set_heart_beat (object_t * ob, int to)
{
    int index;

    if (ob->flags & O_DESTRUCTED) return 0;

    if (!to) {
  int num;

  index = num_hb_objs;
  while (index--) {
      if (heart_beats[index].ob == ob) break;
  }
  if (index < 0) return 0;

  if (num_hb_to_do) {
      if (index <= heart_beat_index)
    heart_beat_index--;
      if (index < num_hb_to_do)
    num_hb_to_do--;
  }

  if ((num = (num_hb_objs - (index + 1))))
      memmove(heart_beats + index, heart_beats + (index + 1), num * sizeof(heart_beat_t));

  num_hb_objs--;
  ob->flags &= ~O_HEART_BEAT;
  return 1;
    }

    if (ob->flags & O_HEART_BEAT) {
  if (to < 0) return 0;

  index = num_hb_objs;
  while (index--) {
      if (heart_beats[index].ob == ob) {
    heart_beats[index].time_to_heart_beat = heart_beats[index].heart_beat_ticks = to;
    break;
      }
  }
  DEBUG_CHECK(index < 0, "Couldn't find enabled object in heart_beat list!\n");
    } else {
  heart_beat_t *hb;

  if (!max_heart_beats)
      heart_beats = CALLOCATE(max_heart_beats = HEART_BEAT_CHUNK,
            heart_beat_t, TAG_HEART_BEAT,
            "set_heart_beat: 1");
  else if (num_hb_objs == max_heart_beats) {
      max_heart_beats += HEART_BEAT_CHUNK;
      heart_beats = RESIZE(heart_beats, max_heart_beats,
         heart_beat_t, TAG_HEART_BEAT,
         "set_heart_beat: 1");
  }

  hb = &heart_beats[num_hb_objs++];
  hb->ob = ob;
  if (to < 0) to = 1;
  hb->time_to_heart_beat = to;
  hb->heart_beat_ticks = to;
  ob->flags |= O_HEART_BEAT;
    }

    return 1;
}

int heart_beat_status (outbuffer_t * ob, int verbose)
{
    char buf[20];

    if (verbose == 1) {
  outbuf_add(ob, "Heart beat information:\n");
  outbuf_add(ob, "-----------------------\n");
  outbuf_addv(ob, "Number of objects with heart beat: %d, starts: %d\n",
        num_hb_objs, num_hb_calls);

  /* passing floats to varargs isn't highly portable so let sprintf
     handle it */
  sprintf(buf, "%.2f", perc_hb_probes);
  outbuf_addv(ob, "Percentage of HB calls completed last time: %s\n", buf);
    }
    return (0);
}       /* heart_beat_status() */

/* 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() */

/* All destructed objects are moved into a sperate linked list,
 * and deallocated after program execution.  */

INLINE void remove_destructed_objects()
{
    object_t *ob, *next;

    if (obj_list_replace)
        replace_programs();
    for (ob = obj_list_destruct; ob; ob = next) {
        next = ob->next_all;
        destruct2(ob);
    }
    obj_list_destruct = 0;
}       /* remove_destructed_objects() */

static double load_av = 0.0;

void update_load_av()
{
    static int last_time;
    int n;
    double c;
    static int acc = 0;

    acc++;
    if (current_time == last_time)
  return;
    n = current_time - last_time;
    if (n < NUM_CONSTS)
  c = consts[n];
    else
  c = exp(-n / 900.0);
    load_av = c * load_av + acc * (1 - c) / n;
    last_time = current_time;
    acc = 0;
}       /* update_load_av() */

static double compile_av = 0.0;

void
update_compile_av (int lines)
{
    static int last_time;
    int n;
    double c;
    static int acc = 0;

    acc += lines;
    if (current_time == last_time)
  return;
    n = current_time - last_time;
    if (n < NUM_CONSTS)
  c = consts[n];
    else
  c = exp(-n / 900.0);
    compile_av = c * compile_av + acc * (1 - c) / n;
    last_time = current_time;
    acc = 0;
}       /* update_compile_av() */

char *query_load_av()
{
    static char buff[100];

    sprintf(buff, "%.2f cmds/s, %.2f comp lines/s", load_av, compile_av);
    return (buff);
}       /* query_load_av() */

#ifdef F_HEART_BEATS
array_t *get_heart_beats() {
  int nob = 0, n = num_hb_objs;
  heart_beat_t *hb = heart_beats;
  object_t **obtab;
  array_t *arr;
#ifdef F_SET_HIDE
  int apply_valid_hide = 1, display_hidden = 0;
#endif

  obtab = CALLOCATE(n, object_t *, TAG_TEMPORARY, "heart_beats");
  while (n--) {
#ifdef F_SET_HIDE
    if (hb->ob->flags & O_HIDDEN) {
      if (apply_valid_hide) {
        apply_valid_hide = 0;
        display_hidden = valid_hide(current_object);
      }
      if (!display_hidden)
        continue;
    }
#endif
    obtab[nob++] = (hb++)->ob;
  }

  arr = allocate_empty_array(nob);
  while (nob--) {
    arr->item[nob].type = T_OBJECT;
    arr->item[nob].u.ob = obtab[nob];
    add_ref(arr->item[nob].u.ob, "get_heart_beats");
  }

  FREE(obtab);

  return arr;
}
#endif