/* wiz.c */
#include "copyright.h"
/* Wizard-only commands */
#ifdef WANT_ANSI
#ifdef __STDC__
#include <stddef.h>
#include <stdlib.h>
#endif /* __STDC__ */
#endif /* WANT_ANSI */
#include <ctype.h>
#include "mudconf.h"
#include "config.h"
#include "db.h"
#include "interface.h"
#include "match.h"
#include "externs.h"
#include "command.h"
#include "htab.h"
extern char *crypt();
void do_teleport(dbref player, dbref cause, int key, char *arg1, char *arg2)
{
dbref victim, destination;
char *to;
/* get victim */
if (*arg2 == '\0') {
victim = player;
to = arg1;
} else {
init_match(player, arg1, NOTYPE);
match_neighbor();
match_possession();
match_me();
match_absolute();
match_player();
victim = noisy_match_result();
if (victim == NOTHING)
return;
to = arg2;
}
/* Validate type of victim */
switch (Typeof(victim)) {
case TYPE_PLAYER:
case TYPE_THING:
break;
default:
notify(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))) {
notify(player, "Permission denied.");
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_here();
match_absolute();
match_neighbor();
match_me();
match_player();
match_exit();
destination = match_result();
switch (destination) {
case NOTHING:
notify(player, "No match.");
return;
case AMBIGUOUS:
notify(player, "I don't know which destination you mean!");
return;
default:
if (victim == destination) {
notify(player, "Bad destination.");
return;
}
}
switch (Typeof(destination)) {
case TYPE_ROOM:
case TYPE_PLAYER:
case TYPE_THING:
/* You must control the destination, or it must be a JUMP_OK
* room where you pass its TELEPORT lock.
*/
if (!Controls(player, destination) &&
!(IS(destination, TYPE_ROOM, ROOM_JUMP_OK) &&
could_doit(player, destination, A_LTPORT))) {
notify(player, "Permission denied.");
return;
}
if (move_via_teleport(victim, destination, cause, 0)) {
if (player != victim) {
if (!Quiet(player))
notify(player, "Teleported.");
if (!Quiet(victim))
notify(victim, "Teleported.");
}
}
break;
case TYPE_EXIT:
if (Exits(destination) == Location(victim)) {
move_exit(victim, destination, 0,
"You can't go that way.", 0);
} else {
notify(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 extra, char *command,
char *args[], int nargs)
{
char *cp;
cp=parse_to(&command, ' ', 0);
if (!command) return;
while (*command && isspace(*command)) command++;
if (*command)
do_force(player, cause, extra, cp, command, args, nargs);
}
/* ---------------------------------------------------------------------------
* do_force: Force an object to do something.
*/
void do_force(dbref player, dbref cause, int extra, 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, RU_ARG1_COPY, 0, NOTHING,
command, args, nargs);
}
/* ---------------------------------------------------------------------------
* 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 (Typeof(victim) != TYPE_PLAYER) {
notify(player, "Try @destroy instead.");
return;
}
if (Wizard(victim)) {
notify(player, "You can't toad a Wizard.");
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 {
recipient = player;
}
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 {
count = chown_all(victim, recipient);
s_Owner(victim, recipient); /* you get it */
}
s_Flags(victim, TYPE_THING|HALT);
s_Pennies(victim, 1);
/* notify people */
loc = Location(victim);
buf=alloc_mbuf("do_toad");
sprintf(buf, "%s has been turned into a slimy toad!", Name(victim));
notify_except2(loc, player, victim, player, buf, 1);
sprintf(buf, "You toaded %s! (%d objects @chowned)", Name(victim),
count + 1);
notify(player, buf);
/* Zap the name from the name hash table */
delete_player_name(victim, Name(victim));
sprintf(buf, "a slimy toad named %s", Name(victim));
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);
count = boot_off(victim,
(char *)"You have been turned into a slimy toad!");
notify(player, tprintf("%d connection%s closed.",
count, (count==1 ? "" : "s")));
}
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(player, "No such player.");
return;
}
if (*password != '\0' && !ok_password(password)) {
/* Can set null passwords, but not bad passwords */
notify(player, "Bad password");
return;
}
if (God(victim) && !God(player)) {
notify(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(password, "XX"));
buf=alloc_lbuf("do_newpassword");
notify(player, "Password changed.");
sprintf(buf, "Your password has been changed by %s.", Name(player));
notify(victim, buf);
free_lbuf(buf);
}
void do_boot(dbref player, dbref cause, int key, char *name)
{
dbref victim;
char *buf, *bp;
int count;
if (key & BOOT_PORT) {
if (is_number(name)) {
victim = atoi(name);
} else {
notify(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(player, "You cannot boot that player!");
return;
}
if ((Typeof(victim) != TYPE_PLAYER && !God(player)) ||
(player == victim)) {
notify(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(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);
notify(player, tprintf("%d connection%s closed.",
count, (count==1 ? "" : "s")));
if (buf)
free_lbuf(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 = atoi(arg1);
DO_WHOLE_DB(a) {
if (Typeof(a) == TYPE_PLAYER) {
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(player, "No match.");
break;
case AMBIGUOUS:
notify(player, "I don't know which one");
break;
default:
s_Next(object, NOTHING);
notify(player, "Cut.");
}
}
/* ---------------------------------------------------------------------------
* count_quota, mung_quota, show_quota, do_quota: Manage quotas.
*/
static int count_quota (dbref player)
{
int i, q;
player = Owner(player);
q = 0 - mudconf.player_quota;
DO_WHOLE_DB(i) {
if (Owner(i) != player)
continue;
if ((Flags(i) & GOING) && (Typeof(i) != TYPE_ROOM))
continue;
switch (Typeof(i)) {
case TYPE_EXIT: q += mudconf.exit_quota; break;
case TYPE_ROOM: q += mudconf.room_quota; break;
case TYPE_THING: q += mudconf.thing_quota; break;
case TYPE_PLAYER: q += mudconf.player_quota; break;
}
}
return q;
}
static void mung_quotas (dbref player, int key, int value)
{
dbref aowner;
int aq, rq, xq, aflags;
char *buff;
if (key & QUOTA_FIX) {
/* Get value of stuff owned and good value, set other value
* from that. */
xq = count_quota(player);
if (key & QUOTA_TOT) {
buff = atr_get(Owner(player), A_RQUOTA,
&aowner, &aflags);
aq = atoi(buff) + xq;
atr_add_raw(Owner(player), A_QUOTA, tprintf("%d", aq));
free_lbuf(buff);
} else {
buff = atr_get(Owner(player), A_QUOTA,
&aowner, &aflags);
rq = atoi(buff) - xq;
atr_add_raw(Owner(player), A_RQUOTA, tprintf("%d", rq));
free_lbuf(buff);
}
} else {
/* Obtain (or calculate) current relative and absolute quota */
buff = atr_get(Owner(player), A_QUOTA,
&aowner, &aflags);
if (!*buff) {
free_lbuf(buff);
buff = atr_get(Owner(player), A_RQUOTA,
&aowner, &aflags);
rq = atoi(buff);
free_lbuf(buff);
aq = rq + count_quota(player);
} else {
aq = atoi(buff);
free_lbuf(buff);
buff = atr_get(Owner(player), A_RQUOTA,
&aowner, &aflags);
rq = atoi(buff);
free_lbuf(buff);
}
/* Adjust values */
if (key & QUOTA_REM) {
aq += (value - rq);
rq = value;
} else {
rq += (value - aq);
aq = value;
}
/* Set both abs and relative quota */
atr_add_raw(Owner(player), A_QUOTA, tprintf("%d", aq));
atr_add_raw(Owner(player), A_RQUOTA, tprintf("%d", rq));
}
}
static void show_quota (dbref player, dbref victim)
{
dbref aowner;
int aq, rq, aflags;
char *buff;
player = Owner(player);
victim = Owner(victim);
buff = atr_get(victim, A_QUOTA, &aowner, &aflags);
aq = atoi(buff);
free_lbuf(buff);
buff = atr_get(victim, A_RQUOTA, &aowner, &aflags);
rq = aq - atoi(buff);
free_lbuf(buff);
if (!Wizard(victim))
notify(player, tprintf("%-16s Quota: %9d Used: %9d",
Name(victim), aq, rq));
else
notify(player, tprintf("%-16s Quota: UNLIMITED Used: %9d",
Name(victim), rq));
}
void do_quota (dbref player, dbref cause, int key, char *arg1, char *arg2)
{
dbref who;
int set, value, i;
if(!(mudconf.quotas | Wizard(player))) {
notify(player, "Quotas are not enabled.");
return;
}
if ((key & QUOTA_TOT) && (key & QUOTA_REM)) {
notify(player, "Illegal combination of switches.");
return;
}
value = 0;
set = 0;
if (key & QUOTA_ALL) {
if (arg1 && *arg1) {
value = atoi(arg1);
set = 1;
}
if (set) {
STARTLOG(LOG_WIZARD,"WIZ","QUOTA")
log_name(player);
log_text((char *)" changed everyone's quota");
ENDLOG
}
DO_WHOLE_DB(i) {
if (Typeof(i) == TYPE_PLAYER) {
if (set)
mung_quotas(i, key, value);
show_quota(player, i);
}
}
return;
}
if (!arg1 || *arg1 == '\0')
who = player;
else {
init_match(player, arg1, TYPE_PLAYER);
match_me();
match_player();
match_neighbor();
match_absolute();
if ((who = noisy_match_result()) == NOTHING)
return;
}
if (!Wizard(player)) {
if (arg2 && *arg2) {
notify(player, "Permission denied.");
return;
}
if (player != who) {
notify(player, "Permission denied.");
return;
}
}
if (arg2 && *arg2) {
set = 1;
value = atoi(arg2);
}
if (set) {
STARTLOG(LOG_WIZARD,"WIZ","QUOTA")
log_name(player);
log_text((char *)" changed the quota of ");
log_name(who);
ENDLOG
mung_quotas(who, key, value);
}
show_quota(player, who);
}
/* --------------------------------------------------------------------------
* do_motd: Wizard-settable message of the day (displayed on connect)
*/
void do_motd (dbref player, dbref cause, int key, char *message)
{
switch (key) {
case MOTD_ALL:
strcpy(mudconf.motd_msg, message);
if (!Quiet(player)) notify(player, "Set: MOTD.");
break;
case MOTD_WIZ:
strcpy(mudconf.wizmotd_msg, message);
if (!Quiet(player)) notify(player, "Set: Wizard MOTD.");
break;
case MOTD_DOWN:
strcpy(mudconf.downmotd_msg, message);
if (!Quiet(player)) notify(player, "Set: Down MOTD.");
break;
case MOTD_FULL:
strcpy(mudconf.fullmotd_msg, message);
if (!Quiet(player)) notify(player, "Set: Full MOTD.");
break;
case MOTD_LIST:
if (Wizard(player)) {
notify(player,
tprintf("MOTD: %s", mudconf.motd_msg));
notify(player,
tprintf("Wizard MOTD: %s", mudconf.wizmotd_msg));
notify(player,
tprintf("Down MOTD: %s", mudconf.downmotd_msg));
notify(player,
tprintf("Full MOTD: %s", mudconf.fullmotd_msg));
} else {
if (Guest(player))
fcache_send(player, mudstate.guest_fcache);
else
fcache_send(player, mudstate.motd_fcache);
notify(player, mudconf.motd_msg);
}
break;
default:
notify(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},
{(char *)"idlechecking", 2, CA_PUBLIC, CF_IDLECHECK},
{(char *)"interpret", 2, CA_PUBLIC, CF_INTERP},
{(char *)"local_rwho", 3, CA_PUBLIC, CF_ALLOW_RWHO},
{(char *)"logins", 3, CA_PUBLIC, CF_LOGIN},
{(char *)"transmit_rwho", 1, CA_PUBLIC, CF_RWHO_XMIT},
{ 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 == -1) {
notify(player, "I don't know about that flag.");
} else if (key == GLOB_ENABLE) {
mudconf.control_flags |= flagvalue;
if (!Quiet(player)) notify(player, "Enabled.");
} else if (key == GLOB_DISABLE) {
mudconf.control_flags &= ~flagvalue;
if (!Quiet(player)) notify(player, "Disabled.");
} else {
notify(player, "Illegal combination of switches.");
}
}