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	:  /cmds/std/_su.c
//	Creator	:  Sulam@TMI (1-21-92)
//	Updated	:  Huma@TMI (11-15-92) for conversion to mudlib 0.9
//	
//	Completely overhauled by Watcher@TMI (2-18-93) for new connection
//	login system, and to improve a few of the su processes.
//
//	Updated by Watcher@TMI (03/92) to accomodated body transfers
//	into monsters by users.
//
//	Updated by Watcher@TMI (04/04/93) stripping away multiple user
//	capabilities to avoid confusion and fix a few other things.
//
//	This command allows wizards to refresh their player object, or
//	change into another user, if the correct password is known.
//	Admins are not required to enter the password.

#include <uid.h>
#include <priv.h>
#include <config.h>
#include <logs.h>
#include <mudlib.h>
#include <daemons.h>
#include <channels.h>
#include <login.h>
#include <login_macros.h>

inherit DAEMON ;

// Local hack?
#undef CAP_NAME
#ifndef CAP_NAME_MASTER_ONLY
#define CAP_NAME(ob) capitalize((ob)->query("name"))
#else
#define CAP_NAME(ob) (ob)->query("name")
#endif

mapping active = ([]);
 
static int link_monster(string name);
static int get_password(string pass);
static void enter_world();
static int check_password(string pass);
static void try_again();
static void switch_player();
static void complete_entry(string str);

void create() {
	seteuid(getuid(this_object()));		//  Set daemons permissions
}

int cmd_su(string name) {
   object ob;
 
   //	Setup the euid of the command to ROOT
 
   seteuid( getuid(this_object()) );
 
   //	If no name is given assume user's real (non-monster) name
 
   if(!name)  name = (string)this_player()->link_data("name");
 
   //	Make sure user's name is lowercase
 
   name = lower_case(name);
 
   //	Check to see if anyone is using the su command.
 
   if(!undefinedp(active["new"])) {
   notify_fail("Su: The su command is presently in use. Please try again.\n");
   return 0; }
 
   //	Check to see if a monster matches the requested id

   if(wizardp(this_player()) && link_monster(name))  return 1;
 
   //	Create new connection object to link 
 
   ob = new(CONNECTION);
 
   //	Check to see if user actually exists in the database
 
   if(!file_exists(user_data_file(ob, name) + __SAVE_EXTENSION__)) {
 
      if(wizardp(this_player()))
	write("Su: No such user or monster exists.\n");
      else
	write("Su: No such user exists.\n");
 
   ob->remove();
   return 1; }
 
   // Add user and connection object to su storage array
 
   active["old"] = this_player();
   active["new"] = ob;
   active["who"] = name;
 
   //	Set and pass permissions
 
   seteuid( name );
   export_uid(ob);
   seteuid(getuid());
 
   //	Name connection object and attempt to restore user's data
 
   ob->SET_NAME(name);
 
   if(!ob->restore()) {
   write("Su: Could not restore requested user.\n");
   ob->remove();
   active = ([]);
   return 1; }
 
   if(!wizardp(this_player()) && !ob->query("wizard") &&
      name != (string)this_player()->link_data("name")) {
   write("Su: Players may only su to themselves or a wizard character.\n");
   ob->remove();
   active = ([]);
   return 1; }
 
   //	If user is an admin, and target isn't an admin
 
   if(adminp(this_player()->link_data("name")) &&
      !adminp(name)) {
   active["same"] = 0;
   switch_player();
   }
 
   //	Switching to a new user ... ask for password
 
   else if((string)this_player()->link_data("name") != name) {
   active["same"] = 0;
   input_to("get_password", 1);
   write("Password: ");
   }
 
   //	Same player ... so don't ask password
 
   else {
   active["same"] = 1;
   switch_player();
   }
 
return 1; }
 
static int get_password(string pass) {
 
   write("\n");
 
   //	Check to see if inputed password is correct
 
   if(!check_password(pass)) {
   write("Su: Incorrect password.\n");
   active = ([]);
   return 0; }
 
   //	If correct, change into the new shell
 
   switch_player();
 
return 1; }
 
static int check_password(string pass) {
   string password;
 
   //	Get stored character password from connection object
 
   password = (string)active["new"]->PASS;
 
   //	Compared inputed password with stored character password
 
   if(password != crypt(pass, password))  return 0;
 
return 1; }
 
static void switch_player() {
   int volume, capacity;
 
   //	Switch interactive between old and new shells
/*
  if(member_array("/std/body.c",deep_inherit_list(active["new"])) == -1){
	write("Security violation\n");
	return 1;
}
*/
   if( exec(active["new"], active["old"]) )
	enter_world();
 
   else {
   write("Su: Login attempt failed.\n");
   active["new"]->remove();
   active = ([]);
   return; }
 
}
 
static void enter_world() {
   object *inv;
    string *history;
    int cmd_num, ptr, max;
   int i, volume, capacity;
 
   //	Save present user configuration
 
   active["old"]->save_data();
 
   //	Setup new user object and move inventory to new host
 
   if(!active["new"]->restore_body() || !active["new"]->connect() ||
      !active["new"]->BODY_OB->query("name")) {
   write("Su: Could not restore new user body.\n");
   exec(active["old"], active["new"]);
   active["new"]->BODY_OB->remove();
   active["new"]->remove();
   active = ([]);
   return; }
 
   //	Get old user volume and capacity
 
   if(active["same"]) {
   volume = (int)active["old"]->query("volume");
   capacity = (int)active["old"]->query("capacity");
   }
 
    history = copy((string *)active["old"]->query_history());
    cmd_num = (int)active["old"]->query_cmd_num();
    max = (int)active["old"]->query_max();
    ptr = (int)active["old"]->query_ptr();
   //	Move the inventory..etc.. if old isn't a monster.
 
   if(!active["old"]->query("npc") && !active["new"]->query("npc")) {
 

   for(inv=all_inventory(active["old"]); i<sizeof(inv); i++) 
   if(!inv[i]->query_auto_load()) 
	inv[i]->move( active["new"]->BODY_OB );
 
   //	Reset previous volume and capacity in new user shell
   //   in users last, so the move always succeeds
    if(active["same"]) {
       active["new"]->set("volume", volume);
       active["new"]->set("capacity", capacity);
    }
 
   }
 
#ifdef SU_LOG
   log_file(SU_LOG, CAP_NAME(active["old"]) + ": sued into " +
           CAP_NAME(active["new"]) + " from " +
	   query_ip_name(this_player()) + " [" +
	   extract(ctime(time()), 4, 15) + "]\n");
#endif

   if(active["old"]->query("npc")) {
   write("Reappear in the same location? [y/n] ");
   input_to("complete_entry", 0);
   return; }
 
   complete_entry("yes");

return; }
 
static void complete_entry(string str) {
    string domain;
 
   if(!str || member_array(str, ({ "y", "yes", "n", "no" })) == -1) {
   write("Reappear in the same location? [y/n] ");
   input_to("complete_entry", 0);
   return; }
 
   if(str == "no" || str == "n")
   active["new"]->BODY_OB->move( START );

   else active["new"]->BODY_OB->move( environment(active["old"]) );
 
   if(active["old"]->query("npc")) {
	active["old"]->clear_monster();
 
         domain = master()->domain_file(file_name(active["old"]));
         switch (domain) {
             case ROOT_UID:
             case BACKBONE_UID:
             case "NONAME":
             case "User":
             case "Anonymous":
                 seteuid("Anonymous");
                 break;
             default:
                 seteuid(domain);
                 break;
         }
         export_uid(active["old"]);
         seteuid(getuid());
	active["old"]->reset_monster();
   }
 
   if(active["same"]) {
   write("Transfer complete.\n");
   if(!active["old"]->query("npc"))
        message("prompt", this_player()->write_prompt(1), this_player());
    active["new"]->BODY_OB->init_setup();
   }

   else {
   write("You polymorph into " + active["new"]->query("cap_name") + ".\n");
   say(active["old"]->query("cap_name") + " polymorphed into " +
       active["new"]->query("cap_name") + ".\n",
       ({ active["old"], active["new"] }));
   active["new"]->BODY_OB->init_setup();
   }
 
   //	Announce the departure of the old char if different from new
 
   if(!active["same"] && !active["old"]->query("npc"))
	ANNOUNCE->announce_user( active["old"], 1 );
 
   if(!active["old"]->query("npc")) {
   active["old"]->save_data();
   active["old"]->remove();
   }
 
   CHANNELS_D -> initialize_user();
   active = ([]);
}
 
//	This function handles the user transfers into monster shells

static int link_monster(string name) {
   object ob, old;
   int ret;
 
   old = this_player();
 
   ob = get_object( name );
 
   //   Check to see if a monster matches the requested id

   if(!ob || !ob->query("npc") || !environment(ob) || this_player() == ob)
	return 0;

   if(interactive(ob)) {
   write("Su: That monster body is presently inhabited.\n");
   return 1; }

   this_player()->query_link()->set("tmp_body", ob);
   ret = this_player()->query_link()->switch_body();

   if(!ret) {
   write("Su: Could not transfer into " + name + ".\n");
   return 1; }
 
   ob->clear_monster();
   seteuid( (string)this_player()->link_data("name") );
   export_uid(ob);
   seteuid(getuid());

   ob->init_setup();
   old->set_link(0);
   old->quit();

   write("Transfer complete.\n> ");

return 1; }
 
mapping query_active() {  return active;  }
 
int help() {
 
   write("Usage: su [user]\n\n" +
    "The su command allows a user to change from their present character\n" +
    "to another, either a fresh version of the present character or a new\n" +
    "version of another character (provided you know the password). It is\n" +
    "equivalent to logging out and back in again, but quicker. With an\n" +
    "argument, su prompts you for the requested user's password, and if\n" +
    "answered correctly, you will be polymorphed into that user. Without\n" +
    "an argument, or if you pass your own character's name as an argument,\n"+
    "you will be transfered into a new copy of your present character.\n");
 
return 1; }