TinyMAZE/
TinyMAZE/config/
TinyMAZE/doc/
TinyMAZE/run/msgs/
TinyMAZE/src/
TinyMAZE/src/db/
TinyMAZE/src/ident/
TinyMAZE/src/io/
TinyMAZE/src/prog/
TinyMAZE/src/softcode/
TinyMAZE/src/util/
#include <stdio.h>
#include <ctype.h>
#include <fcntl.h>
#include <signal.h>
#include "db.h"
#include "config.h"
#include "externs.h"
#include "mail.h"
#include "gametime.h"

time_t next_dbck;
time_t game_time = 0;

static int alarm_triggered = 0;

static signal_type alarm_handler(int i)
{
  alarm_triggered = 1;
  signal(SIGALRM, alarm_handler);
#ifdef void_signal_type
  return;
#else
  return 0;
#endif
}

void init_timer()
{
  signal(SIGALRM, alarm_handler);
  signal(SIGHUP, alarm_handler);
  alarm(1);
}

static void trig_idle_boot()
{
  DDATA *d, *dnext;

  if(!config.idle_boot_time)
    return;

  for(d = descriptor_list;d;d = dnext)
  {
    dnext = d->next;
 
    if(!check_state(d, STATE_CONNECTED))
    {
      if(now-d->last_time > config.idle_boot_time)
      {
        queue_string(d, "You have been idle for too long. Sorry.", 1);
        process_output(d);
        log_io(tprintf("Descriptor %d, host %s@%s, was idle booted.",
          d->descriptor, d->user, d->addr));
        shutdownsock(d);
      }
      continue;
    }

/* Make sure this part of the loop is here or it will crash because */
/* of d->player */
    if(Guest(d->player))
    {
      if(now-d->last_time > config.idle_boot_time)
      {
        notify(d->player, "You have been idle for too long. Sorry.");
        process_output(d);
        log_io(tprintf("Descriptor %d (%s) was idle booted.",
          d->descriptor, name(d->player)));
        shutdownsock(d);
      }
    }
  }
}

static time_t get_next_midnight()
{
  struct tm *t;
  unsigned long num_seconds = 0;

  t = localtime(&now);

  num_seconds += t->tm_sec;
  num_seconds += t->tm_min*SEC_PER_MINUTE;
  num_seconds += t->tm_hour*SEC_PER_HOUR;

  return((time_t)(now+(SEC_PER_DAY-num_seconds)));
}

static int check_new_day()
{
  static time_t next_midnight = 0;

  if(!next_midnight)
  {
    next_midnight = get_next_midnight();
    return(0);
  }

  if(now < next_midnight)
    return(0);

  next_midnight = get_next_midnight();
  return(1);
}

static void do_new_day()
{
}

void dispatch()
{
  extern struct timed_reboot_struct timed_reboot;
  extern time_t next_dump;

  now = time(NULL);

  if(!alarm_triggered)
    return;
  alarm_triggered = 0;

/* Check for timed reboot */
  if(timed_reboot.when)
    if(now >= timed_reboot.when)
    {
      if(timed_reboot.reboot)
        do_reboot(root_obj, timed_reboot.arg, "");
      else
        do_shutdown(root_obj, config.maze_name, "");
    }

  if(now >= next_dbck)
  {
    log_command("dbcking started...");

    next_dbck = now+config.dbck_interval;
    do_dbck(root_obj);

    log_command("dbcking done");
  }

/* Database dump routines */
  if(now >= next_dump)
  {
    log_command("Dumping db");
    notify_except_flag("|+W|** Saving **", NULL, QUIET);
    flush_all_output();
    fork_and_dump();
    next_dump = now+config.dump_interval;
  }

/* Stale mail deletion. */
  if(now >= next_mail_clear)
  {
    log_command("Deleting old mail.\n");
    clear_old_mail();
    next_mail_clear = now+config.old_mail_interval;
  }

/* Boot unidle guests and unconnected descriptors */
  trig_idle_boot();

  chk_hostname_update();
  poll_pending_email();

  if(check_new_day())
    do_new_day();

  plugin_timed();

/* We have to unallocate the stack here, because if everyone in the game
   is idle, all these timed processes will continuously make the stack
   grow */
  stack_unalloc();

  alarm(1);
}