#include "os.h"
#include "config.h"
#include "db.h"
#include "externs.h"
#include "interface.h"
#include "match.h"
#include "attrib.h"
#include "oldattrib.h"
#ifdef MEM_CHECK
#include "mem_check.h"
#endif
/* attribute list */
ATTR attr[] = {
{(char *) "AAHEAR", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "ACLONE", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "ACONNECT", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "ADEATH", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "ADESCRIBE", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "ADISCONNECT", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "ADROP", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "AEFAIL", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "AENTER", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "AFAILURE", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "AHEAR", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "ALEAVE", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "AMHEAR", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "AMOVE", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "APAYMENT", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "ASUCCESS", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "AUSE", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "AWAY", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "CHARGES", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "CLASS", AF_NOPROG, NULL, 0},
{(char *) "COST", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "DEATH", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "DESCRIBE", AF_NOPROG, NULL, 0},
{(char *) "DOES", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "DROP", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "EALIAS", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "EFAIL", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "ENTER", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "FAILURE", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "HAVEN", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "IDESCRIBE", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "IDLE", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "LALIAS", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "LAST", AF_WIZARD | AF_LOCKED, NULL, 0},
{(char *) "LASTSITE", AF_LOCKED | AF_ODARK, NULL, 0},
{(char *) "LEAVE", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "LISTEN", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "MOVE", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "ODEATH", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "ODESCRIBE", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "ODROP", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "OEFAIL", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "OENTER", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "OFAILURE", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "OLEAVE", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "OMOVE", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "OPAYMENT", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "OSUCCESS", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "OUSE", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "OXENTER", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "OXLEAVE", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "PAYMENT", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "QUEUE", AF_ODARK | AF_WIZARD, NULL, 0},
{(char *) "RACE", AF_NOPROG | AF_WIZARD, NULL, 0},
{(char *) "RQUOTA", AF_DARK | AF_WIZARD, NULL, 0},
{(char *) "RUNOUT", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "SEX", AF_NOPROG, NULL, 0},
{(char *) "STARTUP", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "SUCCESS", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "USE", AF_ODARK | AF_NOPROG, NULL, 0},
{(char *) "VA", AF_ODARK, NULL, 0},
{(char *) "VB", AF_ODARK, NULL, 0},
{(char *) "VC", AF_ODARK, NULL, 0},
{(char *) "VD", AF_ODARK, NULL, 0},
{(char *) "VE", AF_ODARK, NULL, 0},
{(char *) "VF", AF_ODARK, NULL, 0},
{(char *) "VG", AF_ODARK, NULL, 0},
{(char *) "VH", AF_ODARK, NULL, 0},
{(char *) "VI", AF_ODARK, NULL, 0},
{(char *) "VJ", AF_ODARK, NULL, 0},
{(char *) "VK", AF_ODARK, NULL, 0},
{(char *) "VL", AF_ODARK, NULL, 0},
{(char *) "VM", AF_ODARK, NULL, 0},
{(char *) "VN", AF_ODARK, NULL, 0},
{(char *) "VO", AF_ODARK, NULL, 0},
{(char *) "VP", AF_ODARK, NULL, 0},
{(char *) "VQ", AF_ODARK, NULL, 0},
{(char *) "VR", AF_ODARK, NULL, 0},
{(char *) "VS", AF_ODARK, NULL, 0},
{(char *) "VT", AF_ODARK, NULL, 0},
{(char *) "VU", AF_ODARK, NULL, 0},
{(char *) "VV", AF_ODARK, NULL, 0},
{(char *) "VW", AF_ODARK, NULL, 0},
{(char *) "VX", AF_ODARK, NULL, 0},
{(char *) "VY", AF_ODARK, NULL, 0},
{(char *) "VZ", AF_ODARK, NULL, 0},
{(char *) "WA", AF_ODARK, NULL, 0},
{(char *) "WB", AF_ODARK, NULL, 0},
{(char *) "WC", AF_ODARK, NULL, 0},
{(char *) "WD", AF_ODARK, NULL, 0},
{(char *) "WE", AF_ODARK, NULL, 0},
{(char *) "WF", AF_ODARK, NULL, 0},
{(char *) "WG", AF_ODARK, NULL, 0},
{(char *) "WH", AF_ODARK, NULL, 0},
{(char *) "WI", AF_ODARK, NULL, 0},
{(char *) "WJ", AF_ODARK, NULL, 0},
{(char *) "WK", AF_ODARK, NULL, 0},
{(char *) "WL", AF_ODARK, NULL, 0},
{(char *) "WM", AF_ODARK, NULL, 0},
{(char *) "WN", AF_ODARK, NULL, 0},
{(char *) "WO", AF_ODARK, NULL, 0},
{(char *) "WP", AF_ODARK, NULL, 0},
{(char *) "WQ", AF_ODARK, NULL, 0},
{(char *) "WR", AF_ODARK, NULL, 0},
{(char *) "WS", AF_ODARK, NULL, 0},
{(char *) "WT", AF_ODARK, NULL, 0},
{(char *) "WU", AF_ODARK, NULL, 0},
{(char *) "WV", AF_ODARK, NULL, 0},
{(char *) "WW", AF_ODARK, NULL, 0},
{(char *) "WX", AF_ODARK, NULL, 0},
{(char *) "WY", AF_ODARK, NULL, 0},
{(char *) "WZ", AF_ODARK, NULL, 0},
{(char *) "XA", AF_ODARK, NULL, 0},
{(char *) "XB", AF_ODARK, NULL, 0},
{(char *) "XC", AF_ODARK, NULL, 0},
{(char *) "XD", AF_ODARK, NULL, 0},
{(char *) "XE", AF_ODARK, NULL, 0},
{(char *) "XF", AF_ODARK, NULL, 0},
{(char *) "XG", AF_ODARK, NULL, 0},
{(char *) "XH", AF_ODARK, NULL, 0},
{(char *) "XI", AF_ODARK, NULL, 0},
{(char *) "XJ", AF_ODARK, NULL, 0},
{(char *) "XK", AF_ODARK, NULL, 0},
{(char *) "XL", AF_ODARK, NULL, 0},
{(char *) "XM", AF_ODARK, NULL, 0},
{(char *) "XN", AF_ODARK, NULL, 0},
{(char *) "XO", AF_ODARK, NULL, 0},
{(char *) "XP", AF_ODARK, NULL, 0},
{(char *) "XQ", AF_ODARK, NULL, 0},
{(char *) "XR", AF_ODARK, NULL, 0},
{(char *) "XS", AF_ODARK, NULL, 0},
{(char *) "XT", AF_ODARK, NULL, 0},
{(char *) "XU", AF_ODARK, NULL, 0},
{(char *) "XV", AF_ODARK, NULL, 0},
{(char *) "XW", AF_ODARK, NULL, 0},
{(char *) "XX", AF_ODARK, NULL, 0},
{(char *) "XY", AF_ODARK, NULL, 0},
{(char *) "XZ", AF_ODARK, NULL, 0},
{(char *) "XYXXY", AF_DARK | AF_NOPROG | AF_LOCKED | AF_WIZARD,
NULL, 0},
{NULL, 0, NULL, 0}
};
static char *clean_atr_name (char *s)
{
static char buf[BUFFER_LEN];
char *q = buf;
char *a;
if (!*s || !s) {
sprintf (buf, "NULL");
return buf;
}
if (!string_compare ("KILL", s)) {
sprintf (buf, "DEATH");
return buf;
}
if (!string_compare ("KILL", s + 1) &&
(*s == 'o' || *s == 'O' || *s == 'a' || *s == 'A')) {
sprintf (buf, "%c%s", *s, s + 1);
return buf;
}
for (a = s; *a; a++)
if (isprint ((int)*a) && !isspace ((int)*a))
*q++ = *a;
*q = '\0';
return buf;
}
ATTR *atr_str (char *s)
{
ATTR *result;
ATTR *a = attr;
int done = 0;
char *q;
result = (ATTR *) malloc (sizeof (ATTR));
q = clean_atr_name (s);
result->name = (char *) malloc (strlen (q) + 1);
#ifdef MEM_CHECK
add_check ("attribute");
add_check ("attribute_name");
#endif
strcpy (result->name, strupper (q));
result->flags = AF_ODARK;
while (a->name && !done) {
if (!string_compare (result->name, a->name)) {
result->flags = a->flags;
done++;
}
a++;
}
return result;
}
struct boolatr *alloc_atr (char *name, char *s)
{
struct boolatr *a;
const char *p;
a = (struct boolatr *) malloc (sizeof (struct boolatr));
a->name = (char *) malloc (strlen (name) + 1);
strcpy (a->name, name);
p = compress (s);
a->text = (char *) malloc (strlen (p) + 1);
strcpy (a->text, p);
#ifdef MEM_CHECK
add_check ("bool_atr");
add_check ("bool_atr_name");
add_check ("bool_atr_val");
#endif
return a;
}
void atr_clr (dbref thing, char *atr)
{
ALIST *ptr = db[thing].list;
while (ptr) {
if (!string_compare (atr, AL_NAME (ptr))) {
AL_DISPOSE (ptr);
return;
}
ptr = AL_NEXT (ptr);
}
}
ALIST *AL_MAKE (char *type, ALIST * next, char *string, dbref owner,
dbref flags)
{
ALIST *ptr;
const char *p;
ptr = (ALIST *) malloc (sizeof (ALIST));
AL_ATTR (ptr) = atr_str (type);
AL_CREATOR (ptr) = owner;
p = compress (string);
AL_STR (ptr) = (char *) malloc (strlen (p) + 1);
#ifdef MEM_CHECK
add_check ("ALIST");
add_check ("attribute_value");
#endif
strcpy (AL_STR (ptr), p);
if (flags != NOTHING)
AL_FLAGS (ptr) |= flags;
AL_NEXT (ptr) = next;
return ptr;
}
void atr_new_add (dbref thing, char *atr, char *s, dbref player, dbref flags)
{
s = (char *) compress (s);
db[thing].list = AL_MAKE (atr, db[thing].list, s, player, flags);
}
int atr_add (dbref thing, char *atr, char *s, dbref player, dbref flags)
{
ALIST *ptr;
dbref privs;
if (thing == 0) {
privs = GOD; /* should only be hit by first couple objects */
db[player].owner = GOD;
} else
privs = db[player].owner;
if (!s)
s = (char *) "";
for (ptr = db[thing].list;
(ptr && string_compare (atr, AL_NAME (ptr))); ptr = AL_NEXT (ptr));
if (!*s) {
if (ptr)
if (!Wizard (privs) &&
((AL_FLAGS (ptr) & AF_WIZARD) ||
((privs != db[AL_CREATOR (ptr)].owner) &&
(AL_FLAGS (ptr) & AF_LOCKED)))) {
return -1;
} else {
AL_DISPOSE (ptr);
return 1;
} else
return 0;
}
s = (char *) compress (s);
if (!ptr) {
db[thing].list = AL_MAKE (atr, db[thing].list, s, privs, flags);
return 1;
} else {
if (!Wizard (privs) &&
((AL_FLAGS (ptr) & AF_WIZARD) ||
((privs != db[AL_CREATOR (ptr)].owner) &&
(AL_FLAGS (ptr) & AF_LOCKED)))) {
return -1;
} else {
const char *p;
free ((char *) AL_STR (ptr));
#ifdef MEM_CHECK
del_check ("attribute_value");
#endif
p = compress (s);
AL_STR (ptr) = (char *) malloc (strlen (p) + 1);
#ifdef MEM_CHECK
add_check ("attribute_value");
#endif
strcpy (AL_STR (ptr), p);
AL_CREATOR (ptr) = db[privs].owner;
if (flags != NOTHING)
AL_FLAGS (ptr) = flags;
if (AL_BAD (ptr))
AL_FLAGS (ptr) &= ~AF_NUKED;
return 1;
}
}
/*NOTREACHED*/ return 0;
}
ATTR *atr_get (dbref thing, char *atr)
{
ALIST *ptr;
if (thing == NOTHING || !atr)
return NULL;
for (ptr = db[thing].list; ptr; ptr = AL_NEXT (ptr)) {
if (!AL_BAD (ptr) && !string_compare (AL_NAME (ptr), atr)) {
return AL_ATTR (ptr);
}
}
for (ptr = db[thing].list; ptr; ptr = AL_NEXT (ptr)) {
if (!AL_BAD (ptr) && string_prefix (AL_NAME (ptr), atr)) {
return (AL_ATTR (ptr));
}
}
return (ATTR *) NULL;
}
void free_attrib (ATTR * thisattr)
{
if (thisattr) {
if (thisattr->name)
free ((char *) thisattr->name);
if (thisattr->value)
free ((char *) thisattr->value);
free ((char *) thisattr);
}
#ifdef MEM_CHECK
del_check ("attribute_name");
del_check ("attribute_value");
del_check ("attribute");
#endif
}
void atr_free (dbref thing)
{
ALIST *ptr, *next;
for (ptr = db[thing].list; ptr; ptr = next) {
next = AL_NEXT (ptr);
free_attrib (AL_ATTR (ptr));
free ((char *) ptr);
#ifdef MEM_CHECK
del_check ("ALIST");
#endif
}
db[thing].list = (ALIST *) NULL;
}
/* reconstruct an attribute list */
void atr_collect (dbref thing)
{
ALIST *ptr, *next;
ptr = db[thing].list;
db[thing].list = NULL;
while (ptr) {
if (!AL_BAD (ptr)) {
db[thing].list = AL_MAKE (AL_NAME (ptr), db[thing].list,
AL_STR (ptr), AL_CREATOR (ptr), AL_FLAGS (ptr));
}
next = AL_NEXT (ptr);
free_attrib (AL_ATTR (ptr));
free ((char *) ptr);
#ifdef MEM_CHECK
del_check ("ALIST");
#endif
ptr = next;
}
}
void atr_cpy (dbref dest, dbref source)
{
ALIST *ptr;
ptr = db[source].list;
db[dest].list = NULL;
while (ptr) {
if (!AL_BAD (ptr)) {
db[dest].list = AL_MAKE (AL_NAME (ptr), db[dest].list,
AL_STR (ptr), AL_CREATOR (ptr), AL_FLAGS (ptr));
}
ptr = AL_NEXT (ptr);
}
}
char *convert_atr (dbref oldatr)
{
static char result[MAX_COMMAND_LEN];
int factor = 0;
switch (oldatr) {
case A_OSUCC:
return "OSUCCESS";
case A_OFAIL:
return "OFAILURE";
case A_FAIL:
return "FAILURE";
case A_SUCC:
return "SUCCESS";
case A_PASS:
return "XYXXY";
case A_DESC:
return "DESCRIBE";
case A_SEX:
return "SEX";
case A_ODROP:
return "ODROP";
case A_DROP:
return "DROP";
case A_OKILL:
return "OKILL";
case A_KILL:
return "KILL";
case A_ASUCC:
return "ASUCCESS";
case A_AFAIL:
return "AFAILURE";
case A_ADROP:
return "ADROP";
case A_AKILL:
return "AKILL";
case A_USE:
return "DOES";
case A_CHARGES:
return "CHARGES";
case A_RUNOUT:
return "RUNOUT";
case A_STARTUP:
return "STARTUP";
case A_ACLONE:
return "ACLONE";
case A_APAY:
return "APAYMENT";
case A_OPAY:
return "OPAYMENT";
case A_PAY:
return "PAYMENT";
case A_COST:
return "COST";
case A_RAND:
return "RAND";
case A_LISTEN:
return "LISTEN";
case A_AAHEAR:
return "AAHEAR";
case A_AMHEAR:
return "AMHEAR";
case A_AHEAR:
return "AHEAR";
case A_LAST:
return "LAST";
case A_QUEUE:
return "QUEUE";
case A_IDESC:
return "IDESCRIBE";
case A_ENTER:
return "ENTER";
case A_OXENTER:
return "OXENTER";
case A_AENTER:
return "AENTER";
case A_ADESC:
return "ADESCRIBE";
case A_ODESC:
return "ODESCRIBE";
case A_RQUOTA:
return "RQUOTA";
case A_ACONNECT:
return "ACONNECT";
case A_ADISCONNECT:
return "ADISCONNECT";
case A_LEAVE:
return "LEAVE";
case A_ALEAVE:
return "ALEAVE";
case A_OLEAVE:
return "OLEAVE";
case A_OENTER:
return "OENTER";
case A_OXLEAVE:
return "OXLEAVE";
default:
if (oldatr >= 100 && oldatr < 126)
factor = 0;
else if (oldatr >= 126 && oldatr < 152)
factor = 1;
else if (oldatr >= 152 && oldatr < 178)
factor = 2;
else {
fprintf (stderr,
"ERROR: Invalid attribute number in convert_atr. aborting.\n");
fflush (stderr);
abort ();
}
sprintf ((char *) result, "%c%c",
'V' + factor, oldatr - (100 + (factor * 26)) + 'A');
return result;
}
/*NOTREACHED*/ return "";
}
ATTR *atr_match (char *string)
{
ATTR *a = attr;
while (a->name) {
if (!string_compare (string, a->name)) {
return a;
}
a++;
}
return (ATTR *) NULL;
}
int atr_comm_match (dbref thing, dbref player, int type, int end, char *str)
{
ALIST *ptr;
int match = 0;
char tbuf1[BUFFER_LEN];
char *s;
if (thing < 0 || thing >= db_top)
return 0;
for (ptr = db[thing].list; ptr; ptr = AL_NEXT (ptr)) {
if (!AL_BAD (ptr) && (*AL_STR (ptr) == type) &&
!(AL_FLAGS (ptr) & AF_NOPROG)) {
strcpy (tbuf1, uncompress (AL_STR (ptr)));
for (s = tbuf1 + 1; *s && (*s != end); s++);
if (!*s)
continue;
*s++ = '\0';
if (wild_match (tbuf1 + 1, str)) {
match = 1;
if ((type == '$') &&
(!eval_boolexp (player, db[thing].usekey, thing, 0, USELOCK)))
notify (player, "Permission denied.");
else
parse_que (thing, s, player);
}
}
}
return match;
}
void do_atrlock (dbref player, const char *arg1, const char *arg2)
{
dbref thing;
char *p;
ALIST *ptr;
int status;
if (!arg2 || !*arg2)
status = 0;
else {
if (!string_compare (arg2, "on")) {
status = 1;
} else if (!string_compare (arg2, "off")) {
status = 2;
} else
status = 0;
}
if (!arg1 || !*arg1) {
notify (player, "You need to give an object/attribute pair.");
return;
}
if (!(p = index (arg1, '/')) || !(*(p + 1))) {
notify (player, "You need to give an object/attribute pair.");
return;
}
*p++ = '\0';
init_match (player, arg1, NOTYPE);
match_everything ();
if ((thing = noisy_match_result ()) == NOTHING)
return;
for (ptr = db[thing].list; ptr; ptr = AL_NEXT (ptr))
if (!AL_BAD (ptr) && !string_compare (AL_NAME (ptr), p))
break;
if (!ptr)
for (ptr = db[thing].list; ptr; ptr = AL_NEXT (ptr))
if (!AL_BAD (ptr) && string_prefix (AL_NAME (ptr), p))
break;
if (ptr) {
if (!status) {
notify (player, tprintf ("That attribute is %slocked.",
(AL_FLAGS (ptr) & AF_LOCKED) ? "" : "un"));
return;
} else if (!Wizard (player) &&
(db[AL_CREATOR (ptr)].owner != db[player].owner)) {
notify (player, "You need to own the attribute to change its lock.");
return;
} else {
if (status == 1) {
AL_FLAGS (ptr) |= AF_LOCKED;
notify (player, "Attribute locked.");
return;
} else if (status == 2) {
AL_FLAGS (ptr) &= ~AF_LOCKED;
notify (player, "Attribute unlocked.");
return;
} else {
notify (player, "Invalid status on atrlock.. Notify god.");
return;
}
}
} else
notify (player, "No such attribute.");
return;
}
void do_atrchown (dbref player, const char *arg1, const char *arg2)
{
dbref thing, new_owner;
char *p;
ALIST *ptr;
if (!arg1 || !*arg1) {
notify (player, "You need to give an object/attribute pair.");
return;
}
if (!(p = index (arg1, '/')) || !(*(p + 1))) {
notify (player, "You need to give an object/attribute pair.");
return;
}
*p++ = '\0';
init_match (player, arg1, NOTYPE);
match_everything ();
if ((thing = noisy_match_result ()) == NOTHING)
return;
if ((!arg2 && !*arg2) || !string_compare (arg2, "me"))
new_owner = player;
else
new_owner = lookup_player (arg2);
if (new_owner == NOTHING) {
notify (player, "I can't find that player");
return;
}
for (ptr = db[thing].list; ptr; ptr = AL_NEXT (ptr))
if (!AL_BAD (ptr) && !string_compare (AL_NAME (ptr), p))
break;
if (!ptr)
for (ptr = db[thing].list; ptr; ptr = AL_NEXT (ptr))
if (!AL_BAD (ptr) && string_prefix (AL_NAME (ptr), p))
break;
if (ptr) {
if ((controls (player, thing) && !(AL_FLAGS (ptr) & AF_LOCKED)) ||
(db[player].owner == db[AL_CREATOR (ptr)].owner)) {
if (new_owner != db[thing].owner && !Wizard (player)) {
notify (player,
"You can only chown an attribute to the current owner of the object.");
return;
}
AL_CREATOR (ptr) = db[new_owner].owner;
notify (player, "Attribute owner changed.");
return;
} else {
notify (player, "You don't have the permission to chown that.");
return;
}
} else
notify (player, "No such attribute.");
}
ATTR *atr_complete_match (dbref player, char *atr, dbref privs)
{
ATTR *a;
char *s = atr;
dbref thing;
if (*s == '_')
s++;
if ((a = atr_get (player, s)) != NULL) {
if (!controls (privs, player) &&
db[privs].owner != db[a->creator].owner && (a->flags & AF_ODARK)) {
DOLIST (thing, db[player].contents) {
if ((a = atr_get (thing, s)) != NULL) {
if (!controls (privs, player) &&
db[privs].owner != db[a->creator].owner &&
(a->flags & AF_ODARK)) {
return NULL;
} else {
return a;
}
}
}
} else {
return a;
}
}
return NULL;
}