/* set.c */
#include "os.h"
#include "copyright.h"
/* commands which set parameters */
#include "config.h"
#include "db.h"
#include "match.h"
#include "interface.h"
#include "externs.h"
#ifdef NOCRYPT
char *crypt (s, t)
char *s, *t;
{
return (s);
}
#endif
void do_name (dbref player, const char *name, char *newname)
{
dbref thing;
char *password;
ATTR *a;
const char *d;
#ifdef RWHO_SEND
char tbuf1[BUFFER_LEN];
#endif
if ((thing = match_controlled (player, name)) != NOTHING) {
/* check for bad name */
if (*newname == '\0') {
notify (player, "Give it what new name?");
return;
}
/* check for renaming a player */
if (Typeof (thing) == TYPE_PLAYER) {
#ifdef GUEST_RESTRICT
if (Guest (player)) {
notify (player, "Guests may not rename themselves.");
return;
}
#endif
/* split off password */
for (password = newname; *password && !isspace ((int)*password); password++);
/* eat whitespace */
if (*password) {
*password++ = '\0'; /* terminate name */
while (*password && isspace ((int)*password))
password++;
}
/* check for null password */
if (!*password) {
notify (player,
"You must specify a password to change a player name.");
notify (player, "E.g.: name player = newname password");
return;
} else if ((a = atr_get (player, "XYXXY")) &&
*(d = uncompress (a->value)) &&
strcmp (d, password) && strcmp (crypt (password, "XX"), d)) {
notify (player, "Incorrect password.");
return;
} else if (string_compare (newname, db[player].name)
&& !ok_player_name (newname)) {
/* string_compare allows changing foo to Foo, etc. */
notify (player, "You can't give a player that name.");
return;
}
/* everything ok, notify */
fprintf (stderr, "NAME CHANGE: %s(#%d) to %s\n",
db[thing].name, thing, newname);
if (db[thing].flags & PLAYER_SUSPECT)
raw_broadcast (WIZARD, "Broadcast: Suspect %s changed name to %s.",
db[thing].name, newname);
#ifdef RWHO_SEND
sprintf (tbuf1, "%d@%s", thing, MUDNAME);
rwhocli_userlogout (tbuf1);
#endif
delete_player (thing);
SET (db[thing].name, newname);
add_player (thing);
#ifdef RWHO_SEND
rwhocli_userlogin (tbuf1, newname, time ((time_t *) 0));
#endif
notify (player, "Name set.");
return;
} else {
if (!ok_name (newname)) {
notify (player, "That is not a reasonable name.");
return;
}
}
/* everything ok, change the name */
SET (db[thing].name, newname);
notify (player, "Name set.");
}
}
void
do_lock (dbref player, const char *name, const char *keyname, int locktype)
{
dbref thing;
struct boolexp *key;
init_match (player, name, NOTYPE);
match_everything ();
switch (thing = match_result ()) {
case NOTHING:
notify (player, "I don't see what you want to lock!");
return;
case AMBIGUOUS:
notify (player, "I don't know which one you want to lock!");
return;
default:
if (!controls (player, thing)) {
notify (player, "You can't lock that!");
return;
}
break;
}
key = parse_boolexp (player, keyname);
if (key == TRUE_BOOLEXP) {
notify (player, "I don't understand that key.");
} else {
/* everything ok, do it */
switch (locktype) {
case BASICLOCK:
free_boolexp (db[thing].key);
db[thing].key = key;
break;
case USELOCK:
free_boolexp (db[thing].usekey);
db[thing].usekey = key;
break;
case ENTERLOCK:
free_boolexp (db[thing].enterkey);
db[thing].enterkey = key;
break;
}
notify (player, "Locked.");
}
}
void do_unlock (dbref player, const char *name, int locktype)
{
dbref thing;
if ((thing = match_controlled (player, name)) != NOTHING) {
switch (locktype) {
case BASICLOCK:
free_boolexp (db[thing].key);
db[thing].key = TRUE_BOOLEXP;
break;
case USELOCK:
free_boolexp (db[thing].usekey);
db[thing].usekey = TRUE_BOOLEXP;
break;
case ENTERLOCK:
free_boolexp (db[thing].enterkey);
db[thing].enterkey = TRUE_BOOLEXP;
break;
}
notify (player, "Unlocked.");
}
}
void do_unlink (dbref player, const char *name)
{
dbref exit;
init_match (player, name, TYPE_EXIT);
match_exit ();
match_here ();
if (Wizard (player)) {
match_absolute ();
}
switch (exit = match_result ()) {
case NOTHING:
notify (player, "Unlink what?");
break;
case AMBIGUOUS:
notify (player, "I don't know which one you mean!");
break;
default:
if (!controls (player, exit)) {
notify (player, "Permission denied.");
} else {
switch (Typeof (exit)) {
case TYPE_EXIT:
db[exit].location = NOTHING;
notify (player, "Unlinked.");
break;
case TYPE_ROOM:
db[exit].location = NOTHING;
notify (player, "Dropto removed.");
break;
default:
notify (player, "You can't unlink that!");
break;
}
}
}
}
void do_chown (dbref player, const char *name, const char *newobj)
{
dbref thing;
dbref owner = NOTHING;
init_match (player, name, TYPE_THING);
match_possession ();
match_here ();
match_exit ();
if (Wizard (player)) {
match_player ();
match_absolute ();
}
switch (thing = match_result ()) {
case NOTHING:
notify (player, "You don't have that!");
return;
case AMBIGUOUS:
notify (player, "I don't know which you mean!");
return;
default:
if (!*newobj || !string_compare (newobj, "me")) {
owner = player;
} else {
if ((owner = lookup_player (newobj)) == NOTHING) {
notify (player, "I couldn't find that player.");
return;
}
}
if (Typeof (thing) == TYPE_PLAYER && !God (player)) {
notify (player, "Players always own themselves.");
return;
} else if (!controls (player, thing) &&
(!(db[thing].flags & CHOWN_OK) ||
((Typeof (thing) == TYPE_THING) &&
(db[thing].location != player) &&
!Wizard (player))) || !controls (player, owner)) {
notify (player, "Permission denied.");
} else if (!payfor (player, OBJECT_COST)) {
notify (player, "You don't have enough money.");
} else {
giveto (db[thing].owner, OBJECT_COST);
if (God (player)) {
db[thing].owner = owner;
} else {
db[thing].owner = db[owner].owner;
}
db[thing].zone = db[owner].zone;
db[thing].flags &= ~CHOWN_OK;
db[thing].flags &= ~WIZARD;
#ifdef ROYALTY_FLAG
db[thing].flags &= ~ROYALTY;
#endif
db[thing].flags &= ~INHERIT;
db[thing].flags |= HALT;
notify (player, "Owner changed.");
}
}
}
void do_chzone (dbref player, const char *name, const char *newobj)
{
dbref thing;
dbref zone;
if (!Wizard (player)) {
notify (player, "Only wizards may change the zone of an object.");
return;
}
init_match (player, name, NOTYPE);
match_neighbor ();
match_possession ();
match_here ();
match_exit ();
match_me ();
if (Wizard (player)) {
match_player ();
match_absolute ();
}
switch (thing = match_result ()) {
case NOTHING:
notify (player, "I can't seem to find that.");
return;
case AMBIGUOUS:
notify (player, "I don't know which one you mean!");
return;
}
if (Typeof (thing) == TYPE_PLAYER && !God (player)) {
notify (player, "Only God may change a player's zone.");
return;
}
if (!string_compare (newobj, "none"))
zone = NOTHING;
else {
init_match (player, newobj, TYPE_THING);
match_neighbor ();
match_possession ();
match_absolute ();
switch (zone = match_result ()) {
case NOTHING:
notify (player, "I can't seem to find that.");
return;
case AMBIGUOUS:
notify (player, "I don't know which one you mean!");
return;
}
if (Typeof (zone) != TYPE_THING) {
notify (player, "Zones may only be defined by objects.");
return;
}
}
db[thing].zone = zone;
db[thing].flags &= ~WIZARD;
#ifdef ROYALTY_FLAG
db[thing].flags &= ~ROYALTY;
#endif
db[thing].flags &= ~INHERIT;
notify (player, "Zone changed.");
}
void do_set (dbref player, const char *name, char *flag)
{
dbref thing;
int res;
char *p;
char tbuf1[BUFFER_LEN];
object_flag_type f;
int her;
/* find thing */
if ((thing = match_controlled (player, name)) == NOTHING)
return;
if (God (thing) && !God (player)) {
notify (player, "Only God can set himself!");
return;
}
#ifdef INHERIT_FLAG
if (!Inherit (player) && Inherit (thing)) {
notify (player, "Authorization failed.");
return;
}
#endif
#ifdef DESTROY
/*
* The GOING flag can only be affected by set in one special case--A
* room that is set to be destroy may be saved.
*/
if (string_prefix ("!GOING", flag) &&
(Typeof (thing) == TYPE_ROOM) && (db[thing].flags & GOING)) {
db[thing].flags ^= GOING;
if (db[thing].owner > 0)
notify (db[thing].owner, "Your room has been spared from destruction.");
return;
}
#endif /* DESTROY */
her = Hearer (thing);
/* check for attribute set first */
p = index (flag, ':');
if (p) {
ATTR *attrb = NULL;
ATTR *a = NULL;
*p++ = '\0';
/* check for predefined attribute match */
attrb = atr_match (flag);
/* check for _ */
if (*p == '_') {
dbref thing1;
char *q;
q = index (p, '/');
if (!(q && *q)) {
notify (player, "I need an object and an attribute.");
return;
}
*q++ = '\0';
init_match (player, p, NOTYPE);
match_everything ();
thing1 = noisy_match_result ();
if (thing1 == NOTHING)
return;
a = atr_get (thing1, q);
if (!a) {
notify (player, "No such attribute.");
return;
}
strcpy (tbuf1, uncompress (a->value));
} else {
strcpy (tbuf1, p);
}
if (attrb) {
if ((attrb->flags & AF_WIZARD) && !Wizard (player)) {
notify (player, "Sorry, only wizards can modify that.");
return;
}
res = atr_add (thing, attrb->name, tbuf1, player, NOTHING);
if (!res) {
notify (player, "No such attribute to reset.");
return;
}
if (res == -1) {
notify (player, "That attribute cannot be changed by you.");
return;
}
} else {
res = atr_add (thing, flag, tbuf1, player, NOTHING);
if (!res) {
notify (player, "No such attribute to reset.");
return;
}
if (res == -1) {
notify (player, "That attribute cannot be changed by you.");
return;
}
}
/* one special case for listen */
if (attrb && !string_compare (attrb->name, "LISTEN") && !her)
notify_except (db[getloc (thing)].contents, thing,
tprintf ("%s grows ears and can now hear.", db[thing].name));
if (!Quiet (player) && !Quiet (thing))
notify (player, tprintf ("%s - Set.", db[thing].name));
return;
}
/* move p past NOT_TOKEN if present */
for (p = (char *) flag; *p && (*p == NOT_TOKEN || isspace ((int)*p)); p++);
/* identify flag */
if (*p == '\0') {
notify (player, "You must specify a flag to set.");
return;
}
f = find_flag (p, thing);
if (f == 0) {
notify (player, "I don't recognize that flag.");
return;
}
if (f == -1) {
notify (player, "Broken function. Notify god.");
return;
}
/* check unsettable flags */
#ifdef DESTROY
if (f == GOING) {
notify (player,
"The GOING flag may only be used to stop the destruction of rooms.");
return;
}
#endif
if ((f == TYPE_EXIT) || (f == TYPE_PLAYER) || (f == TYPE_ROOM)) {
notify (player, "You cannot set that flag.");
return;
}
/* check for restricted flag */
if (!Wizard (player)) {
switch (Typeof (thing)) {
case TYPE_ROOM:
if (f == ROOM_TEMPLE) {
notify (player, "Permission denied.");
return;
}
break;
case TYPE_PLAYER:
#ifdef RESTRICTED_BUILDING
if (f == PLAYER_BUILD) {
notify (player, "Permission denied.");
return;
}
#endif /* RESTRICTED_BUILDING */
if (f == PLAYER_CONNECT) {
notify (player, "You cannot set that flag.");
return;
}
if (f == DARK) {
notify (player, "Permission denied.");
notify (player, "Use UNFINDABLE to hide from whereis command.");
return;
}
if (f == PLAYER_SUSPECT) {
notify (player, "Permission denied.");
return;
}
break;
case TYPE_THING:
if (f == THING_IMMORTAL) {
notify (player, "Permission denied.");
return;
}
break;
}
}
#ifdef ROYALTY_FLAG
if ((f == ROYALTY) && !((Royalty (player) && Typeof (thing) != TYPE_PLAYER)
|| Wizard (player) || God (player))) {
notify (player, "Permission denied.");
return;
}
#endif
if ((f == WIZARD) &&
!((Wizard (player) && db[thing].owner == player) || God (player))) {
notify (player, "Permission denied.");
return;
}
if ((Typeof (thing) == TYPE_PLAYER) && (db[thing].owner == thing) &&
(f == PLAYER_GAGGED) && (!Wizard (player) || Wizard (thing))) {
notify (player, "You cannot gag that!");
return;
}
/* else everything is ok, do the set */
if (*flag == NOT_TOKEN) {
/* reset the flag */
db[thing].flags &= ~f;
if (f == WIZARD)
fprintf (stderr, "** WIZFLAG RESET ** %s(#%d) --> %s(#%d)\n",
db[player].name, player, db[thing].name, thing);
#ifdef ROYALTY_FLAG
if (f == ROYALTY)
fprintf (stderr, "** ROYAL FLAG RESET ** %s(#%d) --> %s(#%d)\n",
db[player].name, player, db[thing].name, thing);
#endif
#ifdef RWHO_SEND
if (f == DARK && Typeof (thing) == TYPE_PLAYER) {
sprintf (tbuf1, "%d@%s", thing, MUDNAME);
rwhocli_userlogin (tbuf1, db[thing].name, time ((time_t *) 0));
}
#endif
if ((f == QUIET) || (!Quiet (player) && !Quiet (thing)))
notify (player, "Flag reset.");
} else {
/* set the flag */
db[thing].flags |= f;
if (f == WIZARD)
fprintf (stderr, "** WIZFLAG SET ** %s(#%d) --> %s(#%d)\n",
db[player].name, player, db[thing].name, thing);
#ifdef ROYALTY_FLAG
if (f == ROYALTY)
fprintf (stderr, "** ROYAL FLAG SET ** %s(#%d) --> %s(#%d)\n",
db[player].name, player, db[thing].name, thing);
#endif
#ifdef RWHO_SEND
if (f == DARK && Typeof (thing) == TYPE_PLAYER) {
sprintf (tbuf1, "%d@%s", thing, MUDNAME);
rwhocli_userlogout (tbuf1);
}
#endif
if ((Typeof (thing) == TYPE_THING) && (f == THING_PUPPET) && !her) {
sprintf (tbuf1, "%s grows ears and can now hear.", db[thing].name);
notify_except (db[db[thing].location].contents, 0, tbuf1);
}
if ((f == QUIET) || (!Quiet (player) && !Quiet (thing)))
notify (player, "Flag set.");
}
}
/* check for abbreviated set command */
int test_set (dbref player, char *command, char *arg1, char *arg2)
{
int a;
char tbuf1[BUFFER_LEN];
if (command[0] != '@' && command[0] != '&')
return (0);
/* added to make this 2.0 compatible. with '&' equivalent to '@_' */
if (command[0] == '&') {
sprintf (tbuf1, "%s:%s", command + 1, arg2);
do_set (player, arg1, tbuf1);
return (1);
}
/* first character is '@' */
/* check if it's a regular attribute */
for (a = 0; attr[a].name; a++)
if (string_prefix (attr[a].name, command + 1)) {
sprintf (tbuf1, "%s:%s", attr[a].name, arg2);
do_set (player, arg1, tbuf1);
return (1);
}
/* else treat it as a user-defined one */
if (command[1] != '_')
return (0);
sprintf (tbuf1, "%s:%s", command + 2, arg2);
do_set (player, arg1, tbuf1);
return (1);
}
void do_gedit (dbref player, char *it, char *argv[])
{
ALIST *a;
dbref thing;
char tbuf1[BUFFER_LEN], tbuf2[BUFFER_LEN];
char *q;
if (!(it && *it)) {
notify (player, "I need to know what you want to edit.");
return;
}
strcpy (tbuf1, it);
q = index (tbuf1, '/');
if (!(q && *q)) {
notify (player, "I need to know what you want to edit.");
return;
}
*q++ = '\0';
init_match (player, tbuf1, NOTYPE);
match_everything ();
thing = noisy_match_result ();
if (thing == NOTHING || !controls (player, thing)) {
notify (player, "Permission denied.");
return;
}
if (*q == '_')
q++;
for (a = db[thing].list; a; a = AL_NEXT (a)) {
strcpy (tbuf2, q);
if (!AL_BAD (a) && wild_match (tbuf2, AL_NAME (a))) {
sprintf (tbuf2, "%s/%s", tbuf1, AL_NAME (a));
do_edit (player, tbuf2, argv);
}
}
}
void do_edit (dbref player, char *it, char *argv[])
{
dbref thing;
int d, len, res;
ATTR *a;
char tbuf1[BUFFER_LEN], tbuf2[BUFFER_LEN];
char *r, *q, *s, *val;
if (!(it && *it)) {
notify (player, "I need to know what you want to edit.");
return;
}
strcpy (tbuf1, it);
q = index (tbuf1, '/');
if (!(q && *q)) {
notify (player, "I need to know what you want to edit.");
return;
}
*q++ = '\0';
init_match (player, tbuf1, NOTYPE);
match_everything ();
thing = noisy_match_result ();
if (thing == NOTHING || !controls (player, thing)) {
notify (player, "Permission denied.");
return;
}
if (!argv[1] || !*argv[1]) {
notify (player, "Nothing to do.");
return;
}
val = argv[1];
r = (argv[2]) ? argv[2] : (char *) "";
if (*q == '_')
q++;
a = atr_get (thing, q);
if (!a) {
notify (player, "No such attribute, try set instead.");
return;
}
if ((a->flags & AF_LOCKED) && db[player].owner != db[a->creator].owner) {
notify (player, "You need to control an attribute to edit it.");
return;
}
s = (char *) uncompress (a->value);
len = strlen (val);
for (d = 0; (d < BUFFER_LEN) && *s;)
if (strncmp (val, s, len) == 0) {
if ((d + strlen (r)) < BUFFER_LEN) {
strcpy (tbuf2 + d, r);
d += strlen (r);
s += len;
} else
tbuf2[d++] = *s++;
} else
tbuf2[d++] = *s++;
tbuf2[d++] = 0;
res = atr_add (thing, a->name, tbuf2, player, NOTHING);
if (!res) {
notify (player, "That attribute seems to have vanished!");
return;
}
if (res == -1) {
notify (player, "You don't have the power to change that.");
return;
}
if (!Quiet (player) && !Quiet (thing))
notify (player, tprintf ("%s - Set: %s", a->name, tbuf2));
}
void do_trigger (dbref player, char *object, char *argv[])
{
dbref thing;
int a;
char *s;
char tbuf1[BUFFER_LEN];
strcpy (tbuf1, object);
for (s = tbuf1; *s && (*s != '/'); s++);
if (!*s) {
notify (player, "I need to know what attribute to trigger.");
return;
}
*s++ = '\0';
init_match (player, tbuf1, NOTYPE);
match_everything ();
thing = noisy_match_result ();
if (thing == NOTHING)
return;
if (!controls (player, thing) && string_compare (s, "DOES")) {
notify (player, "Permission denied.");
return;
}
if (God (thing) && !God (player)) {
notify (player, "You can't trigger God!");
return;
}
#ifdef INHERIT_FLAG
if (!Inherit (player) && Inherit (thing)) {
notify (player, "Authorization failed.");
return;
}
#endif
for (a = 0; a < 10; a++)
wptr[a] = argv[a + 1];
did_it (player, thing, NULL, NULL, NULL, NULL, s, NOTHING);
if (!Quiet (player) && !Quiet (thing))
notify (player, tprintf ("%s - Triggered.", db[thing].name));
}
/* for lack of a better place, the use code is here */
void do_use (dbref player, const char *what)
{
dbref thing;
init_match (player, what, TYPE_THING);
match_neighbor ();
match_possession ();
match_absolute ();
if ((thing = noisy_match_result ()) != NOTHING) {
if (!eval_boolexp (player, db[thing].usekey, thing, 0, USELOCK)) {
notify (player, "Permission denied.");
return;
} else
did_it (player, thing, "USE", "Used.", "OUSE", NULL, "AUSE", NOTHING);
}
}