// wiz.c -- Wizard-only commands
//
// $Id: wiz.cpp,v 1.7 2000/08/28 07:52:08 sdennis Exp $
//
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include "externs.h"
#include "mudconf.h"
#include "file_c.h"
#include "db.h"
#include "interface.h"
#include "match.h"
#include "command.h"
#include "htab.h"
#include "alloc.h"
#include "attrs.h"
#include "powers.h"
extern char *FDECL(crypt, (const char *, const char *));
void do_teleport(dbref player, dbref cause, int key, char *arg1, char *arg2)
{
dbref victim, destination, loc;
char *to;
int hush = 0;
if ( ( Fixed(player)
|| Fixed(Owner(player))
)
&& !Tel_Anywhere(player)
)
{
notify(player, mudconf.fixed_tel_msg);
return;
}
// Get victim.
//
if (*arg2 == '\0')
{
victim = player;
to = arg1;
}
else
{
init_match(player, arg1, NOTYPE);
match_everything(MAT_NO_EXITS);
victim = noisy_match_result();
if (victim == NOTHING)
{
return;
}
to = arg2;
}
// Validate type of victim.
//
if (!Has_location(victim))
{
notify_quiet(player, "You can't teleport that.");
return;
}
// Fail if we don't control the victim or the victim's location.
//
if ( !Controls(player, victim)
&& !Controls(player, Location(victim))
&& !Tel_Anything(player))
{
notify_quiet(player, NOPERM_MESSAGE);
return;
}
// Check for teleporting home
//
if (!string_compare(to, "home"))
{
(void)move_via_teleport(victim, HOME, cause, 0);
return;
}
// Find out where to send the victim.
//
init_match(player, to, NOTYPE);
match_everything(0);
destination = match_result();
switch (destination)
{
case NOTHING:
notify_quiet(player, "No match.");
return;
case AMBIGUOUS:
notify_quiet(player, "I don't know which destination you mean!");
return;
default:
if (victim == destination)
{
notify_quiet(player, "Bad destination.");
return;
}
}
// If fascist teleport is on, you must control the victim's ultimate
// location (after LEAVEing any objects) or it must be JUMP_OK.
//
if (mudconf.fascist_tport)
{
loc = where_room(victim);
if ( !Good_obj(loc)
|| !isRoom(loc)
|| !( Controls(player, loc)
|| Jump_ok(loc)
|| Tel_Anywhere(player)
)
)
{
notify_quiet(player, NOPERM_MESSAGE);
return;
}
}
if (Has_contents(destination))
{
// You must control the destination, or it must be a JUMP_OK
// room where you pass its TELEPORT lock.
//
if ( !( Controls(player, destination)
|| Jump_ok(destination)
|| Tel_Anywhere(player)
)
|| !could_doit(player, destination, A_LTPORT)
)
{
// Nope, report failure.
//
if (player != victim)
{
notify_quiet(player, NOPERM_MESSAGE);
}
did_it(victim, destination,
A_TFAIL, "You can't teleport there!",
A_OTFAIL, 0, A_ATFAIL, (char **)NULL, 0);
return;
}
// We're OK, do the teleport.
//
if (key & TELEPORT_QUIET)
{
hush = HUSH_ENTER | HUSH_LEAVE;
}
if (move_via_teleport(victim, destination, cause, hush))
{
if (player != victim)
{
if (!Quiet(player))
{
notify_quiet(player, "Teleported.");
}
}
}
}
else if (isExit(destination))
{
if (Exits(destination) == Location(victim))
{
move_exit(victim, destination, 0, "You can't go that way.", 0);
}
else
{
notify_quiet(player, "I can't find that exit.");
}
}
}
// ---------------------------------------------------------------------------
// do_force_prefixed: Interlude to do_force for the # command
//
void do_force_prefixed( dbref player, dbref cause, int key, char *command,
char *args[], int nargs )
{
char *cp;
cp = parse_to(&command, ' ', 0);
if (!command)
{
return;
}
while (Tiny_IsSpace[(unsigned char)*command])
{
command++;
}
if (*command)
{
do_force(player, cause, key, cp, command, args, nargs);
}
}
// ---------------------------------------------------------------------------
// do_force: Force an object to do something.
//
void do_force( dbref player, dbref cause, int key, char *what, char *command,
char *args[], int nargs )
{
dbref victim;
if ((victim = match_controlled(player, what)) == NOTHING)
{
return;
}
// Force victim to do command.
//
wait_que( victim, player, 0, NOTHING, 0,
command, args, nargs, mudstate.global_regs);
}
// ---------------------------------------------------------------------------
// do_toad: Turn a player into an object.
//
void do_toad(dbref player, dbref cause, int key, char *toad, char *newowner)
{
dbref victim, recipient, loc, aowner;
char *buf;
int count, aflags;
init_match(player, toad, TYPE_PLAYER);
match_neighbor();
match_absolute();
match_player();
if ((victim = noisy_match_result()) == NOTHING)
{
return;
}
if (!isPlayer(victim))
{
notify_quiet(player, "Try @destroy instead.");
return;
}
if (No_Destroy(victim))
{
notify_quiet(player, "You can't toad that player.");
return;
}
if ((newowner != NULL) && *newowner)
{
init_match(player, newowner, TYPE_PLAYER);
match_neighbor();
match_absolute();
match_player();
if ((recipient = noisy_match_result()) == NOTHING)
{
return;
}
}
else
{
if (mudconf.toad_recipient == -1)
{
recipient = player;
}
else
{
recipient = mudconf.toad_recipient;
}
}
STARTLOG(LOG_WIZARD, "WIZ", "TOAD");
log_name_and_loc(victim);
log_text((char *)" was @toaded by ");
log_name(player);
ENDLOG;
// Clear everything out.
//
if (key & TOAD_NO_CHOWN)
{
count = -1;
}
else
{
// You get it.
//
count = chown_all(victim, recipient, player, CHOWN_NOZONE);
s_Owner(victim, recipient);
s_Zone(victim, NOTHING);
}
s_Flags(victim, TYPE_THING | HALT);
s_Flags2(victim, 0);
s_Flags3(victim, 0);
s_Pennies(victim, 1);
// Notify people.
//
loc = Location(victim);
buf = alloc_mbuf("do_toad");
char *pVictimName = Name(victim);
sprintf(buf, "%s has been turned into a slimy toad!", pVictimName);
notify_except2(loc, player, victim, player, buf);
sprintf(buf, "You toaded %s! (%d objects @chowned)", pVictimName, count+1);
notify_quiet(player, buf);
// Zap the name from the name hash table.
//
sprintf(buf, "a slimy toad named %s", pVictimName);
delete_player_name(victim, pVictimName);
s_Name(victim, buf);
free_mbuf(buf);
// Zap the alias, too.
//
buf = atr_pget(victim, A_ALIAS, &aowner, &aflags);
delete_player_name(victim, buf);
free_lbuf(buf);
// Boot off.
//
count = boot_off(victim, (char *)"You have been turned into a slimy toad!");
// Release comsys and @mail resources.
//
ReleaseAllResources(victim);
buf = tprintf("%d connection%s closed.", count, (count == 1 ? "" : "s"));
notify_quiet(player, buf);
}
void do_newpassword(dbref player, dbref cause, int key, char *name,
char *password)
{
dbref victim;
char *buf;
if ((victim = lookup_player(player, name, 0)) == NOTHING)
{
notify_quiet(player, "No such player.");
return;
}
if (*password != '\0' && !ok_password(password, player))
{
// Can set null passwords, but not bad passwords.
// Notification of reason done by ok_password().
//
return;
}
if (God(victim))
{
notify_quiet(player, "You cannot change that player's password.");
return;
}
STARTLOG(LOG_WIZARD, "WIZ", "PASS");
log_name(player);
log_text((char *)" changed the password of ");
log_name(victim);
ENDLOG;
// It's ok, do it.
//
s_Pass(victim, crypt((const char *)password, "XX"));
notify_quiet(player, "Password changed.");
buf = alloc_lbuf("do_newpassword");
char *bp = buf;
safe_tprintf_str(buf, &bp, "Your password has been changed by %s.", Name(player));
notify_quiet(victim, buf);
free_lbuf(buf);
}
void do_boot(dbref player, dbref cause, int key, char *name)
{
dbref victim;
char *buf, *bp;
int count;
if (!(Can_Boot(player)))
{
notify(player, NOPERM_MESSAGE);
return;
}
if (key & BOOT_PORT)
{
if (is_number(name))
{
victim = Tiny_atol(name);
}
else
{
notify_quiet(player, "That's not a number!");
return;
}
STARTLOG(LOG_WIZARD, "WIZ", "BOOT");
buf = alloc_sbuf("do_boot.port");
sprintf(buf, "Port %d", victim);
log_text(buf);
log_text((char *)" was @booted by ");
log_name(player);
free_sbuf(buf);
ENDLOG;
}
else
{
init_match(player, name, TYPE_PLAYER);
match_neighbor();
match_absolute();
match_player();
if ((victim = noisy_match_result()) == NOTHING)
{
return;
}
if (God(victim))
{
notify_quiet(player, "You cannot boot that player!");
return;
}
if ( ( !isPlayer(victim)
&& !God(player)
)
|| player == victim
)
{
notify_quiet(player, "You can only boot off other players!");
return;
}
STARTLOG(LOG_WIZARD, "WIZ", "BOOT");
log_name_and_loc(victim);
log_text((char *)" was @booted by ");
log_name(player);
ENDLOG;
notify_quiet(player, tprintf("You booted %s off!", Name(victim)));
}
if (key & BOOT_QUIET)
{
buf = NULL;
}
else
{
bp = buf = alloc_lbuf("do_boot.msg");
safe_str(Name(player), buf, &bp);
safe_str((char *)" gently shows you the door.", buf, &bp);
*bp = '\0';
}
if (key & BOOT_PORT)
{
count = boot_by_port(victim, !God(player), buf);
}
else
{
count = boot_off(victim, buf);
}
if (buf)
{
free_lbuf(buf);
}
buf = tprintf("%d connection%s closed.", count, (count == 1 ? "" : "s"));
notify_quiet(player, buf);
}
// ---------------------------------------------------------------------------
// do_poor: Reduce the wealth of anyone over a specified amount.
//
void do_poor(dbref player, dbref cause, int key, char *arg1)
{
dbref a;
int amt, curamt;
if (!is_number(arg1))
{
return;
}
amt = Tiny_atol(arg1);
DO_WHOLE_DB(a)
{
if (isPlayer(a))
{
curamt = Pennies(a);
if (amt < curamt)
{
s_Pennies(a, amt);
}
}
}
}
// ---------------------------------------------------------------------------
// do_cut: Chop off a contents or exits chain after the named item.
//
void do_cut(dbref player, dbref cause, int key, char *thing)
{
dbref object;
object = match_controlled(player, thing);
switch (object)
{
case NOTHING:
notify_quiet(player, "No match.");
break;
case AMBIGUOUS:
notify_quiet(player, "I don't know which one");
break;
default:
s_Next(object, NOTHING);
notify_quiet(player, "Cut.");
}
}
// --------------------------------------------------------------------------
// do_motd: Wizard-settable message of the day (displayed on connect)
//
void do_motd(dbref player, dbref cause, int key, char *message)
{
int is_brief;
is_brief = 0;
if (key & MOTD_BRIEF)
{
is_brief = 1;
key = key & ~MOTD_BRIEF;
if (key == MOTD_ALL)
key = MOTD_LIST;
else if (key != MOTD_LIST)
key |= MOTD_BRIEF;
}
switch (key)
{
case MOTD_ALL:
strncpy(mudconf.motd_msg, message, GBUF_SIZE-1);
mudconf.motd_msg[GBUF_SIZE-1] = '\0';
if (!Quiet(player))
{
notify_quiet(player, "Set: MOTD.");
}
break;
case MOTD_WIZ:
strncpy(mudconf.wizmotd_msg, message, GBUF_SIZE-1);
mudconf.wizmotd_msg[GBUF_SIZE-1] = '\0';
if (!Quiet(player))
{
notify_quiet(player, "Set: Wizard MOTD.");
}
break;
case MOTD_DOWN:
strncpy(mudconf.downmotd_msg, message, GBUF_SIZE-1);
mudconf.downmotd_msg[GBUF_SIZE-1] = '\0';
if (!Quiet(player))
{
notify_quiet(player, "Set: Down MOTD.");
}
break;
case MOTD_FULL:
strncpy(mudconf.fullmotd_msg, message, GBUF_SIZE-1);
mudconf.fullmotd_msg[GBUF_SIZE-1] = '\0';
if (!Quiet(player))
{
notify_quiet(player, "Set: Full MOTD.");
}
break;
case MOTD_LIST:
if (Wizard(player))
{
if (!is_brief)
{
notify_quiet(player, "----- motd file -----");
fcache_send(player, FC_MOTD);
notify_quiet(player, "----- wizmotd file -----");
fcache_send(player, FC_WIZMOTD);
notify_quiet(player, "----- motd messages -----");
}
notify_quiet(player, tprintf("MOTD: %s", mudconf.motd_msg));
notify_quiet( player,
tprintf("Wizard MOTD: %s", mudconf.wizmotd_msg) );
notify_quiet( player,
tprintf("Down MOTD: %s", mudconf.downmotd_msg) );
notify_quiet( player,
tprintf("Full MOTD: %s", mudconf.fullmotd_msg) );
}
else
{
if (Guest(player))
{
fcache_send(player, FC_CONN_GUEST);
}
else
{
fcache_send(player, FC_MOTD);
}
notify_quiet(player, mudconf.motd_msg);
}
break;
default:
notify_quiet(player, "Illegal combination of switches.");
}
}
// ---------------------------------------------------------------------------
// do_enable: enable or disable global control flags
//
NAMETAB enable_names[] =
{
{(char *)"building", 1, CA_PUBLIC, CF_BUILD},
{(char *)"checkpointing", 2, CA_PUBLIC, CF_CHECKPOINT},
{(char *)"cleaning", 2, CA_PUBLIC, CF_DBCHECK},
{(char *)"dequeueing", 1, CA_PUBLIC, CF_DEQUEUE},
#ifdef MUSH3
{(char *)"god_monitoring", 1, CA_PUBLIC, CF_GODMONITOR},
#endif
{(char *)"idlechecking", 2, CA_PUBLIC, CF_IDLECHECK},
{(char *)"interpret", 2, CA_PUBLIC, CF_INTERP},
{(char *)"logins", 3, CA_PUBLIC, CF_LOGIN},
{(char *)"eventchecking", 2, CA_PUBLIC, CF_EVENTCHECK},
{ NULL, 0, 0, 0}
};
void do_global(dbref player, dbref cause, int key, char *flag)
{
int flagvalue;
// Set or clear the indicated flag.
//
flagvalue = search_nametab(player, enable_names, flag);
if (flagvalue < 0)
{
notify_quiet(player, "I don't know about that flag.");
}
else if (key == GLOB_ENABLE)
{
// Check for CF_DEQUEUE
//
if (flagvalue == CF_DEQUEUE)
{
scheduler.SetMinPriority(PRIORITY_CF_DEQUEUE_ENABLED);
}
mudconf.control_flags |= flagvalue;
STARTLOG(LOG_CONFIGMODS, "CFG", "GLOBAL");
log_name(player);
log_text((char *)" enabled: ");
log_text(flag);
ENDLOG;
if (!Quiet(player))
{
notify_quiet(player, "Enabled.");
}
}
else if (key == GLOB_DISABLE)
{
if (flagvalue == CF_DEQUEUE)
{
scheduler.SetMinPriority(PRIORITY_CF_DEQUEUE_DISABLED);
}
mudconf.control_flags &= ~flagvalue;
STARTLOG(LOG_CONFIGMODS, "CFG", "GLOBAL");
log_name(player);
log_text((char *)" disabled: ");
log_text(flag);
ENDLOG;
if (!Quiet(player))
{
notify_quiet(player, "Disabled.");
}
}
else
{
notify_quiet(player, "Illegal combination of switches.");
}
}