tmi2_fluffos_v2/
tmi2_fluffos_v2/bin/
tmi2_fluffos_v2/etc/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/ChangeLog.old/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/Win32/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/compat/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/compat/simuls/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/include/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/clone/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/command/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/data/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/etc/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/include/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/inherit/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/inherit/master/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/log/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/tests/compiler/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/tests/efuns/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/tests/operators/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/u/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/tmp/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/windows/
tmi2_fluffos_v2/lib/
tmi2_fluffos_v2/lib/adm/
tmi2_fluffos_v2/lib/adm/daemons/languages/
tmi2_fluffos_v2/lib/adm/daemons/network/I3/
tmi2_fluffos_v2/lib/adm/daemons/virtual/
tmi2_fluffos_v2/lib/adm/daemons/virtual/template/
tmi2_fluffos_v2/lib/adm/news/
tmi2_fluffos_v2/lib/adm/obj/
tmi2_fluffos_v2/lib/adm/obj/master/
tmi2_fluffos_v2/lib/adm/priv/
tmi2_fluffos_v2/lib/adm/shell/
tmi2_fluffos_v2/lib/adm/tmp/
tmi2_fluffos_v2/lib/cmds/
tmi2_fluffos_v2/lib/d/
tmi2_fluffos_v2/lib/d/Conf/
tmi2_fluffos_v2/lib/d/Conf/adm/
tmi2_fluffos_v2/lib/d/Conf/boards/
tmi2_fluffos_v2/lib/d/Conf/cmds/
tmi2_fluffos_v2/lib/d/Conf/data/
tmi2_fluffos_v2/lib/d/Conf/logs/
tmi2_fluffos_v2/lib/d/Conf/obj/
tmi2_fluffos_v2/lib/d/Conf/text/help/
tmi2_fluffos_v2/lib/d/Fooland/adm/
tmi2_fluffos_v2/lib/d/Fooland/data/
tmi2_fluffos_v2/lib/d/Fooland/data/attic/
tmi2_fluffos_v2/lib/d/Fooland/items/
tmi2_fluffos_v2/lib/d/TMI/
tmi2_fluffos_v2/lib/d/TMI/adm/
tmi2_fluffos_v2/lib/d/TMI/boards/
tmi2_fluffos_v2/lib/d/TMI/data/
tmi2_fluffos_v2/lib/d/TMI/rooms/
tmi2_fluffos_v2/lib/d/grid/
tmi2_fluffos_v2/lib/d/grid/adm/
tmi2_fluffos_v2/lib/d/grid/data/
tmi2_fluffos_v2/lib/d/std/
tmi2_fluffos_v2/lib/d/std/adm/
tmi2_fluffos_v2/lib/data/adm/
tmi2_fluffos_v2/lib/data/adm/daemons/
tmi2_fluffos_v2/lib/data/adm/daemons/doc_d/
tmi2_fluffos_v2/lib/data/adm/daemons/emoted/
tmi2_fluffos_v2/lib/data/adm/daemons/network/http/
tmi2_fluffos_v2/lib/data/adm/daemons/network/services/mail_q/
tmi2_fluffos_v2/lib/data/adm/daemons/network/smtp/
tmi2_fluffos_v2/lib/data/adm/daemons/news/archives/
tmi2_fluffos_v2/lib/data/attic/connection/
tmi2_fluffos_v2/lib/data/attic/user/
tmi2_fluffos_v2/lib/data/std/connection/b/
tmi2_fluffos_v2/lib/data/std/connection/l/
tmi2_fluffos_v2/lib/data/std/user/a/
tmi2_fluffos_v2/lib/data/std/user/b/
tmi2_fluffos_v2/lib/data/std/user/d/
tmi2_fluffos_v2/lib/data/std/user/f/
tmi2_fluffos_v2/lib/data/std/user/l/
tmi2_fluffos_v2/lib/data/std/user/x/
tmi2_fluffos_v2/lib/data/u/d/dm/working/doc_d/
tmi2_fluffos_v2/lib/data/u/l/leto/doc_d/
tmi2_fluffos_v2/lib/data/u/l/leto/smtp/
tmi2_fluffos_v2/lib/doc/
tmi2_fluffos_v2/lib/doc/driverdoc/applies/
tmi2_fluffos_v2/lib/doc/driverdoc/applies/interactive/
tmi2_fluffos_v2/lib/doc/driverdoc/concepts/
tmi2_fluffos_v2/lib/doc/driverdoc/driver/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/arrays/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/buffers/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/compile/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/ed/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/filesystem/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/floats/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/functions/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/general/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/mappings/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/numbers/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/parsing/
tmi2_fluffos_v2/lib/doc/driverdoc/lpc/constructs/
tmi2_fluffos_v2/lib/doc/driverdoc/lpc/preprocessor/
tmi2_fluffos_v2/lib/doc/driverdoc/lpc/types/
tmi2_fluffos_v2/lib/doc/driverdoc/platforms/
tmi2_fluffos_v2/lib/doc/mudlib/
tmi2_fluffos_v2/lib/ftp/
tmi2_fluffos_v2/lib/include/driver/
tmi2_fluffos_v2/lib/log/
tmi2_fluffos_v2/lib/log/driver/
tmi2_fluffos_v2/lib/obj/net/
tmi2_fluffos_v2/lib/obj/shells/
tmi2_fluffos_v2/lib/obj/tools/
tmi2_fluffos_v2/lib/std/adt/
tmi2_fluffos_v2/lib/std/board/
tmi2_fluffos_v2/lib/std/body/
tmi2_fluffos_v2/lib/std/fun/
tmi2_fluffos_v2/lib/std/living/
tmi2_fluffos_v2/lib/std/object/
tmi2_fluffos_v2/lib/std/shop/
tmi2_fluffos_v2/lib/std/socket/
tmi2_fluffos_v2/lib/std/user/
tmi2_fluffos_v2/lib/std/virtual/
tmi2_fluffos_v2/lib/student/
tmi2_fluffos_v2/lib/student/kalypso/
tmi2_fluffos_v2/lib/student/kalypso/armor/
tmi2_fluffos_v2/lib/student/kalypso/rooms/
tmi2_fluffos_v2/lib/student/kalypso/weapons/
tmi2_fluffos_v2/lib/u/l/leto/
tmi2_fluffos_v2/lib/u/l/leto/cmds/
tmi2_fluffos_v2/lib/www/errors/
tmi2_fluffos_v2/lib/www/gateways/
tmi2_fluffos_v2/lib/www/images/
tmi2_fluffos_v2/old/
tmi2_fluffos_v2/win32/
/*
// File:     shutdownd.c
// Purpose:  Does mudlibby things before calling the shutdown() efun.
// Credits:
// 92-09-26  Truilkan @ Basis wrote the original version.
// 93-01-04  Pallando @ TMI-2 added in the delay option and Apocalypse bits.
// 93-01-14  Pallando moved the emotes to a seperate file
// Comments: (makes it easier for other muds to create their own emote files)
// 93-04-02  Pallando added stop_shutdown()
// 93-05-22  Watcher @ TMI-2 Changed shout()s to message()s
// Comments: ensures the emotes are labeled and this_player() get them.
// 93-07-08  Pallando ensured delay to shutdown isn't messaged twice.
// 93-07-08  Grendel@tmi-2 stoped two shutdowns happening at once
// 93-10-30  Inspiral@TMI-2 added the DNS_MASTER call in save_daemons().
// 94-04-30  Robocoder added query_reason(), and PRUNE_LOGDIR to save_daemons()
// 94-07-26  Blue streamlined the get_emote() function, and made the
//           function select a random file, instead of a #defined one.
//           Also added some comments to the functions.
// 94-12-04  Blue fixed the count_down() function for the new driver,
//           cause previous_object() wasn't defined any more.
*/

#include <config.h>
#include <uid.h>
#include <daemons.h>
#include <net/daemons.h>
#include <driver/origin.h>

#define log( x )
// #define EMOTE_FILE "/adm/daemons/sh_apocalypse.t"
#define EMOTE_DIR "/adm/daemons/"
// Note the trailing slash.  Saves a bit of bother.
#define EMOTE_WILD "sh_*.t"
// The format of the filenames in EMOTE_DIR with the shutdown
// sequences in them.

string *emotes;
int num_emot; // the number of emotes
int s_sec; //   The time() the shutdown is due at, in seconds.
string reason;

string query_reason() { return reason; }
int query_shutdown() { return s_sec; }
mixed query_emotes() { return copy(emotes); }

void
save_daemons()
{
// Someone commented this check below, and i enabled it again.
// It's there so that no sneaky wiz can send UDP shutdowns
// to all muds by calling this. Leto
if (previous_object()) {
   if (getuid(previous_object()) != ROOT_UID) return; // Leto
 }
   PRUNE_LOGDIR_D->backup_debug_log();
   EMOTE_D->save_data();
#ifdef INTERMUD
// Commentd out because wmhod is obsolete and the existing
// Server at Actlab is gone anyways.
// CMWHO_D->halt();
   DNS_MASTER->send_shutdown();
#endif
   users()->save_data();
}

void init_emotes() {
  // Chooses a random emote file, if it can find any.  If so,
  // loads the contents into the *emotes array.  If not, sets
  // the *emotes array to be empty.
    string *emotefiles;
    emotefiles = get_dir( EMOTE_DIR + EMOTE_WILD );
    if (!sizeof( emotefiles )) {
        emotes = ({ });
        num_emot = -1;
    }
    else {
        emotes = explode( read_file(EMOTE_DIR + emotefiles[random(sizeof(emotefiles))]), "###\n");
        num_emot = sizeof(emotes) - 1;
#ifdef DEBUG
write ("NE="+num_emot) ;
#endif
    }
}

void
do_shutdown(int how) {
  // Performs the actual shutting down, right at the end.
   if ((previous_object() && geteuid( previous_object() ) != ROOT_UID) ||
	(!previous_object() && origin()==ORIGIN_CALL_OTHER) ) return ;
   save_daemons();
   shutdown(how);
}

void count_down(int how);

varargs
int start_shutdown( int how, int delay, string reasoning ) {
  // Called by the shutdown command to start the process off.
  if( geteuid( previous_object() ) != ROOT_UID ) return s_sec;
  if( delay < 0 ) return s_sec;
  if( this_player() )
   message("shutdown", (string)this_player()->query("cap_name") +
           " cackles: The end of the world is nigh. Prepare to meet thy " +
           "DOOM!\n", users());
  reason = reasoning;
  if( !delay )
  {
    do_shutdown( how );
    return time();
  }
  // if there is another shutdown on the way then cancel it
  if(s_sec)
    remove_call_out("count_down");

  s_sec = time() + ( delay * 60 );
    init_emotes();
  count_down( how );
  return s_sec;
}

string get_emote( int delay )
{
  // Returns the appropriate emote to the number of minutes left.
  if( delay < num_emot ) return emotes[(num_emot-delay)];
  return 0; // No message except the time until shutdown, done by count_down()
}

void count_down( int how )
{
  // A rather foolishly written function (sorry :) that is
  // called every minute once the shutdown has started.
  // It calculates the remaining time to shutdown, and
  // broadcasts the appropriate messages.
  int delay;
  string msg;

  if ( (origin() != ORIGIN_LOCAL) && (origin() != ORIGIN_CALL_OUT) )
    return;
  delay = ( s_sec + 30 - time() ) / 60;
// If s_sec - time() is a multiple of 60, as it's supposed to be,
// this won't make any difference.  However, it seems that the
// call_outs are getting delayed at some point by a couple of
// seconds, so this is needed to get the number of minutes right.
  if( msg = get_emote( delay ) )
    message( "shutdown", msg, users() );

  if( delay ) message( "shutdown",
    "The mud will shut down in " + delay + " minutes.\n", users() );
  if( delay < 1 )
  {
    do_shutdown( how );
    return;
  }
  call_out( "count_down", 60, how );
}

int stop_shutdown()
{
  // Self-explanatory, I suppose.  Stops everything.
  if( geteuid( previous_object() ) != ROOT_UID ) return 0;
  s_sec = 0;
  reason = 0;
  remove_call_out( "count_down" );
  if( this_player() )
    message("shutdown", "The Mighty " + this_player()->query("cap_name") +
            " intervenes to save the world.\n", users());
// Blessed are the peacemakers, for they shall save your hard won kit.
  return 1;
}