#include "copyrite.h"
#include "config.h"
#ifdef I_STRING
#include <string.h>
#else
#include <strings.h>
#endif
#include "conf.h"
#include "dbdefs.h"
#include "externs.h"
#include "flags.h"
#include "intrface.h"
#include "match.h"
#include "parse.h"
#include "mushdb.h"
#ifdef MEM_CHECK
#include "memcheck.h"
#endif
#include "confmagic.h"
#ifdef WIN32
#pragma warning( disable : 4761) /* NJG: disable warning re conversion */
#endif
#ifdef CHAT_SYSTEM
#include "extchat.h"
extern CHAN *channels;
#endif
extern char ccom[BUFFER_LEN]; /* bsd.c */
char *do_get_attrib _((dbref executor, dbref thing, char *attrib));
dbref next_con _((dbref player, dbref this));
dbref next_exit _((dbref player, dbref this));
static lock_type get_locktype _((dbref obj, const char *str));
extern struct db_stat_info *get_stats _((dbref player, dbref owner));
extern ATTR *aname_hash_lookup _((const char *name));
static int lattr_helper _((dbref player, dbref thing, char const *pattern,
ATTR *atr, void *args));
char *
do_get_attrib(executor, thing, attrib)
dbref executor;
dbref thing;
char *attrib;
{
ATTR *a;
char const *value;
a = atr_get(thing, upcasestr(attrib));
if (a) {
if (Can_Read_Attr(executor, thing, a)) {
if (strlen(value = uncompress(a->value)) < BUFFER_LEN)
return (char *) value;
else
return (char *) "#-1 ATTRIBUTE LENGTH TOO LONG";
}
return (char *) "#-1 NO PERMISSION TO GET ATTRIBUTE";
}
a = atr_match(upcasestr(attrib));
if (a) {
if (Can_Read_Attr(executor, thing, a))
return (char *) "";
return (char *) "#-1 NO PERMISSION TO GET ATTRIBUTE";
}
if (!Can_Examine(executor, thing))
return (char *) "#-1 NO PERMISSION TO GET ATTRIBUTE";
return (char *) "";
}
/* this function produces a space-separated list of attributes that are
* on an object.
*/
struct lh_args {
int first;
char *buff;
char **bp;
};
/* ARGSUSED */
static int
lattr_helper(player, thing, pattern, atr, args)
dbref player;
dbref thing;
char const *pattern;
ATTR *atr;
void *args;
{
struct lh_args *lh = args;
if (lh->first)
lh->first = 0;
else
safe_chr(' ', lh->buff, lh->bp);
safe_str(AL_NAME(atr), lh->buff, lh->bp);
return 1;
}
/* ARGSUSED */
FUNCTION(fun_lattr)
{
dbref thing;
char *pattern;
struct lh_args lh;
pattern = (char *) index(args[0], '/');
if (pattern)
*pattern++ = '\0';
else
pattern = (char *) "*"; /* match anything */
thing = match_thing(executor, args[0]);
if (thing == NOTHING) {
safe_str("#-1 NO MATCH", buff, bp);
return;
}
if (!Can_Examine(executor, thing)) {
safe_str("#-1 PERMISSION DENIED", buff, bp);
return;
}
lh.first = 1;
lh.buff = buff;
lh.bp = bp;
(void) atr_iter_get(executor, thing, pattern, lattr_helper, &lh);
}
/* ARGSUSED */
FUNCTION(fun_hasattr)
{
dbref thing;
ATTR *a;
thing = match_thing(executor, args[0]);
if (thing == NOTHING) {
safe_str("#-1 NO SUCH OBJECT VISIBLE", buff, bp);
return;
}
if (strchr(called_as, 'P'))
a = atr_get(thing, upcasestr(args[1]));
else
a = atr_get_noparent(thing, upcasestr(args[1]));
if (a && Can_Read_Attr(executor, thing, a)) {
if (strchr(called_as, 'V'))
safe_chr(*AL_STR(a) ? '1' : '0', buff, bp);
else
safe_chr('1', buff, bp);
return;
} else if (a || !Can_Examine(executor, thing)) {
safe_str("#-1 PERMISSION DENIED", buff, bp);
return;
}
safe_chr('0', buff, bp);
}
/* ARGSUSED */
FUNCTION(fun_get)
{
dbref thing;
char *s;
s = strchr(args[0], '/');
if (!s) {
safe_str("#-1 BAD ARGUMENT FORMAT TO GET", buff, bp);
return;
}
*s++ = '\0';
thing = match_thing(executor, args[0]);
if (thing == NOTHING) {
safe_str("#-1 NO SUCH OBJECT VISIBLE", buff, bp);
return;
}
safe_str(do_get_attrib(executor, thing, s), buff, bp);
}
/* Functions like get, but uses the standard way of passing arguments */
/* to a function, and thus doesn't choke on nested functions within. */
/* ARGSUSED */
FUNCTION(fun_xget)
{
dbref thing;
thing = match_thing(executor, args[0]);
if (thing == NOTHING) {
safe_str("#-1 NO SUCH OBJECT VISIBLE", buff, bp);
return;
}
safe_str(do_get_attrib(executor, thing, args[1]), buff, bp);
}
/* Functions like get, but includes a default response if the
* attribute isn't present or is null
*/
/* ARGSUSED */
FUNCTION(fun_default)
{
dbref thing;
ATTR *attrib;
char *dp;
char const *sp;
char mstr[BUFFER_LEN];
/* find our object and attribute */
dp = mstr;
sp = args[0];
process_expression(mstr, &dp, &sp, executor, caller, enactor,
PE_DEFAULT, PT_DEFAULT, pe_info);
*dp = '\0';
parse_attrib(executor, mstr, &thing, &attrib);
if (GoodObject(thing) && attrib &&
Can_Read_Attr(executor, thing, attrib)) {
/* Ok, we've got it */
sp = safe_uncompress(attrib->value);
safe_str(sp, buff, bp);
free((Malloc_t) sp);
return;
}
/* We couldn't get it. Evaluate args[1] and return it */
sp = args[1];
process_expression(buff, bp, &sp, executor, caller, enactor,
PE_DEFAULT, PT_DEFAULT, pe_info);
return;
}
/* ARGSUSED */
FUNCTION(fun_eval)
{
/* like xget, except pronoun substitution is done */
dbref thing;
char *tbuf;
char const *tp;
ATTR *a;
thing = match_thing(executor, args[0]);
if (thing == NOTHING) {
safe_str("#-1 NO SUCH OBJECT VISIBLE", buff, bp);
return;
}
a = atr_get(thing, upcasestr(args[1]));
if (a && Can_Read_Attr(executor, thing, a)) {
tp = tbuf = safe_uncompress(a->value);
#ifdef MEM_CHECK
add_check("fun_eval.attr_value");
#endif
process_expression(buff, bp, &tp, thing, executor, executor,
PE_DEFAULT, PT_DEFAULT, pe_info);
mush_free((Malloc_t) tbuf, "fun_eval.attr_value");
return;
} else if (a || !Can_Examine(executor, thing)) {
safe_str("#-1 NO PERMISSION TO GET ATTRIBUTE", buff, bp);
return;
}
return;
}
/* ARGSUSED */
FUNCTION(fun_get_eval)
{
/* like eval, except uses obj/attr syntax. 2.x compatibility */
dbref thing;
char *tbuf, *s;
char const *tp;
ATTR *a;
s = strchr(args[0], '/');
if (!s) {
safe_str("#-1 BAD ARGUMENT FORMAT TO GET_EVAL", buff, bp);
return;
}
*s++ = '\0';
thing = match_thing(executor, args[0]);
if (thing == NOTHING) {
safe_str("#-1 NO SUCH OBJECT VISIBLE", buff, bp);
return;
}
a = atr_get(thing, upcasestr(s));
if (a && Can_Read_Attr(executor, thing, a)) {
tp = tbuf = safe_uncompress(a->value);
#ifdef MEM_CHECK
add_check("fun_eval.attr_value");
#endif
process_expression(buff, bp, &tp, thing, executor, executor,
PE_DEFAULT, PT_DEFAULT, pe_info);
mush_free((Malloc_t) tbuf, "fun_eval.attr_value");
return;
} else if (a || !Can_Examine(executor, thing)) {
safe_str("#-1 NO PERMISSION TO GET ATTRIBUTE", buff, bp);
return;
}
return;
}
/* Functions like eval, but includes a default response if the
* attribute isn't present or is null
*/
/* ARGSUSED */
FUNCTION(fun_edefault)
{
dbref thing;
ATTR *attrib;
char *dp, *sbuf;
char const *sp;
char mstr[BUFFER_LEN];
/* find our object and attribute */
dp = mstr;
sp = args[0];
process_expression(mstr, &dp, &sp, executor, caller, enactor,
PE_DEFAULT, PT_DEFAULT, pe_info);
*dp = '\0';
parse_attrib(executor, mstr, &thing, &attrib);
if (GoodObject(thing) && attrib &&
Can_Read_Attr(executor, thing, attrib)) {
/* Ok, we've got it */
sp = sbuf = safe_uncompress(attrib->value);
#ifdef MEM_CHECK
add_check("fun_edefault.attr_value");
#endif
process_expression(buff, bp, &sp, thing, executor, executor,
PE_DEFAULT, PT_DEFAULT, pe_info);
mush_free((Malloc_t) sbuf, "fun_edefault.attr_value");
return;
}
/* We couldn't get it. Evaluate args[1] and return it */
sp = args[1];
process_expression(buff, bp, &sp, executor, caller, enactor,
PE_DEFAULT, PT_DEFAULT, pe_info);
return;
}
/* ARGSUSED */
FUNCTION(fun_v)
{
/* handle 0-9, va-vz, n, l, # */
int c;
if (args[0][0] && !args[0][1]) {
switch (c = args[0][0]) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (wenv[c - '0'])
safe_str(wenv[c - '0'], buff, bp);
return;
case '#':
/* enactor dbref */
safe_str(unparse_dbref(enactor), buff, bp);
return;
case '@':
/* caller dbref */
safe_str(unparse_dbref(caller), buff, bp);
return;
case '!':
/* executor dbref */
safe_str(unparse_dbref(executor), buff, bp);
return;
case 'n':
case 'N':
/* enactor name */
safe_str(Name(enactor), buff, bp);
return;
case 'l':
case 'L':
/* giving the location does not violate security,
* since the object is the enactor. */
safe_str(unparse_dbref(Location(enactor)), buff, bp);
return;
case 'c':
case 'C':
safe_str(ccom, buff, bp);
return;
}
}
safe_str(do_get_attrib(executor, executor, args[0]), buff, bp);
}
/* ARGSUSED */
FUNCTION(fun_flags)
{
dbref thing;
thing = match_thing(executor, args[0]);
if (thing == NOTHING)
safe_str("#-1", buff, bp);
else
safe_str(unparse_flags(thing, executor), buff, bp);
}
/* ARGSUSED */
FUNCTION(fun_num)
{
safe_str(unparse_dbref(match_thing(executor, args[0])), buff, bp);
}
/* ARGSUSED */
FUNCTION(fun_rnum)
{
dbref place = match_thing(executor, args[0]);
char *name = args[1];
dbref thing;
if ((place != NOTHING) &&
(Can_Examine(executor, place) || (Location(executor) == place) ||
(enactor == place))) {
switch (thing = match_result(place, name, NOTYPE, MAT_REMOTE)) {
case NOTHING:
safe_str("#-1 NO MATCH", buff, bp);
break;
case AMBIGUOUS:
safe_str("#-1 AMBIGUOUS MATCH", buff, bp);
break;
default:
safe_str(unparse_dbref(thing), buff, bp);
}
} else
safe_str("#-1", buff, bp);
}
/*
* fun_lcon, fun_lexits, fun_con, fun_exit, fun_next, and next_exit were all
* re-coded by d'mike, 7/12/91. next_con was added at this time as well.
*
* The function behavior was changed by Amberyl, to remove what she saw
* as a security problem, since mortals could get the contents of rooms
* they didn't control, thus (if they were willing to go through the trouble)
* they could build a scanner to locate anything they wanted.
*
* You can get the contents of any room you control, regardless of whether
* or not the object is dark. You can get the contents of your current
* location, _except_ for dark objects (and DARK/OPAQUE rooms). You CANNOT
* get the contents of anything else, regardless of whether or not you have
* objects in it. This latter behavior is exhibited by 2.0.
*
* The same behavior is true for exits, except OPAQUE doesn't apply.
*/
/* ARGSUSED */
FUNCTION(fun_lcon)
{
dbref thing;
int first;
dbref it = match_thing(executor, args[0]);
if ((it != NOTHING) &&
(Can_Examine(executor, it) || (Location(executor) == it) ||
(enactor == it))) {
first = 1;
DOLIST_VISIBLE(thing, Contents(it), executor) {
if (first)
first = 0;
else
safe_chr(' ', buff, bp);
safe_str(unparse_dbref(thing), buff, bp);
}
} else
safe_str("#-1", buff, bp);
}
/* ARGSUSED */
FUNCTION(fun_con)
{
dbref it = match_thing(executor, args[0]);
if ((it != NOTHING) &&
(Can_Examine(executor, it) || (where_is(executor) == it) ||
(enactor == it))) {
it = first_visible(executor, it);
if (it == NOTHING)
safe_str("#-1", buff, bp);
else
safe_str(unparse_dbref(Contents(it)), buff, bp);
} else {
safe_str("#-1", buff, bp);
}
}
/* return next contents that is ok to see */
dbref
next_con(player, this)
dbref player;
dbref this;
{
dbref loc;
int sees_loc;
if ((this == NOTHING) || ((loc = Location(this)) == NOTHING))
return NOTHING;
sees_loc = Can_Examine(player, loc);
if (sees_loc || ((Location(player) == loc) && !Dark(loc) && !Opaque(loc))) {
this = first_visible(player, this);
}
return (this);
}
/* return next exit that is ok to see */
dbref
next_exit(player, this)
dbref player;
dbref this;
{
dbref loc;
int sees_loc;
if ((this == NOTHING) || ((loc = Home(this)) == NOTHING))
return NOTHING;
sees_loc = Can_Examine(player, loc);
if (sees_loc || ((Location(player) == loc) && !Dark(loc))) {
this = first_visible(player, this);
}
return (this);
}
/* ARGSUSED */
FUNCTION(fun_lexits)
{
dbref it = match_thing(executor, args[0]);
dbref thing;
int first;
int sees_loc;
sees_loc = Can_Examine(executor, it);
first = 1;
if (GoodObject(it) && (Typeof(it) == TYPE_ROOM)) {
if (sees_loc || (Location(executor) == it)) {
DOLIST_VISIBLE(thing, Exits(it), executor) {
if (first)
first = 0;
else
safe_chr(' ', buff, bp);
safe_str(unparse_dbref(thing), buff, bp);
}
}
} else
safe_str("#-1", buff, bp);
}
/* fun_exit is really just a wrapper for next_exit now... */
/* ARGSUSED */
FUNCTION(fun_exit)
{
dbref it = match_thing(executor, args[0]);
if (GoodObject(it) && (Typeof(it) == TYPE_ROOM))
safe_str(unparse_dbref(next_exit(executor, Exits(it))), buff, bp);
else
safe_str("#-1", buff, bp);
return;
}
/* ARGSUSED */
FUNCTION(fun_next)
{
dbref it = match_thing(executor, args[0]);
if (it != NOTHING)
safe_str(unparse_dbref(next_exit(executor, Next(it))), buff, bp);
else
safe_str("#-1", buff, bp);
}
/* ARGSUSED */
FUNCTION(fun_entrances)
{
/* All args are optional.
* The first argument is the dbref to check (default = this room)
* The second argument to this function is a set of characters:
* (a)ll (default), (e)xits, (t)hings, (p)layers, (r)ooms
* The third and fourth args limit the range of dbrefs (default=0,db_top)
*/
dbref where = Location(executor);
dbref low = 0;
dbref high = db_top - 1;
dbref counter;
dbref entrance;
int found;
int exd, td, pd, rd; /* what we're looking for */
char *p;
if (options.daytime) {
notify(executor, "Function disabled.");
safe_str("#-1", buff, bp);
return;
}
if (!payfor(executor, FIND_COST)) {
notify(executor, tprintf("You don't have %d %s to do that.",
FIND_COST,
((FIND_COST == 1) ? MONEY : MONIES)));
safe_str("#-1", buff, bp);
return;
}
if (nargs > 0)
where = match_result(executor, args[0], NOTYPE, MAT_EVERYTHING);
if (!GoodObject(where)) {
safe_str("#-1 INVALID LOCATION", buff, bp);
return;
}
exd = td = pd = rd = 0;
if (nargs > 1) {
if (!args[1] || !*args[1]) {
safe_str("#-1 INVALID SECOND ARGUMENT", buff, bp);
return;
}
p = args[1];
while (*p) {
switch (*p) {
case 'a':
case 'A':
exd = td = pd = rd = 1;
break;
case 'e':
case 'E':
exd = 1;
break;
case 't':
case 'T':
td = 1;
break;
case 'p':
case 'P':
pd = 1;
break;
case 'r':
case 'R':
rd = 1;
break;
default:
safe_str("#-1 INVALID SECOND ARGUMENT", buff, bp);
return;
}
p++;
}
}
if (!exd && !td && !pd && !rd) {
exd = td = pd = rd = 1;
}
if (nargs > 2) {
if (is_integer(args[2])) {
low = parse_integer(args[2]);
} else if (is_dbref(args[2])) {
low = parse_dbref(args[2]);
} else {
safe_str(e_ints, buff, bp);
return;
}
}
if (nargs > 3) {
if (is_integer(args[3])) {
high = parse_integer(args[3]);
} else if (is_dbref(args[3])) {
high = parse_dbref(args[3]);
} else {
safe_str(e_ints, buff, bp);
return;
}
}
if (!GoodObject(low))
low = 0;
if (!GoodObject(high))
high = db_top - 1;
if (!controls(executor, where) && !Search_All(executor)) {
safe_str("#-1 PERMISSION DENIED.", buff, bp);
return;
}
/* Ok, do the real work */
found = 0;
for (counter = low; counter <= high; counter++) {
if (controls(executor, where) || controls(executor, counter)) {
if ((exd && (Typeof(counter) == TYPE_EXIT)) ||
(td && (Typeof(counter) == TYPE_THING)) ||
(pd && (Typeof(counter) == TYPE_PLAYER)) ||
(rd && (Typeof(counter) == TYPE_ROOM))) {
if (Typeof(counter) == TYPE_PLAYER || Typeof(counter) == TYPE_THING)
entrance = Home(counter);
else
entrance = Location(counter);
if (entrance == where) {
if (!found)
found = 1;
else
safe_chr(' ', buff, bp);
safe_str(unparse_dbref(counter), buff, bp);
}
}
}
}
return;
}
/* ARGSUSED */
FUNCTION(fun_nearby)
{
dbref obj1 = match_thing(executor, args[0]);
dbref obj2 = match_thing(executor, args[1]);
if (!controls(executor, obj1) && !controls(executor, obj2)
&& !nearby(executor, obj1) && !nearby(executor, obj2)) {
safe_str("#-1 NO OBJECTS CONTROLLED", buff, bp);
return;
}
if (!GoodObject(obj1) || !GoodObject(obj2)) {
safe_str("#-1", buff, bp);
return;
}
safe_chr(nearby(obj1, obj2) ? '1' : '0', buff, bp);
}
/* ARGSUSED */
FUNCTION(fun_controls)
{
dbref it = match_thing(executor, args[0]);
dbref thing = match_thing(executor, args[1]);
if (it == NOTHING)
safe_str("#-1 ARG1 NOT FOUND", buff, bp);
else if (thing == NOTHING)
safe_str("#-1 ARG2 NOT FOUND", buff, bp);
else if (!(controls(executor, it) || See_All(executor)))
safe_str("#-1 PERMISSION DENIED", buff, bp);
else
safe_chr(controls(it, thing) ? '1' : '0', buff, bp);
}
/* ARGSUSED */
FUNCTION(fun_visible)
{
/* check to see if we have an object-attribute pair. If we don't,
* then we want to know about the whole object; otherwise, we're
* just interested in a single attribute.
* If we encounter an error, we return 0 rather than an error
* code, since if it doesn't exist, it obviously can't see
* anything or be seen.
*/
dbref it, thing;
char *name;
ATTR *a;
if ((it = match_thing(executor, args[0])) == NOTHING) {
safe_chr('0', buff, bp);
return;
}
if ((name = strchr(args[1], '/')))
*name++ = '\0';
if ((thing = match_thing(executor, args[1])) == NOTHING) {
safe_chr('0', buff, bp);
return;
}
if (name) {
a = atr_get(thing, upcasestr(name));
safe_chr((a && Can_Read_Attr(it, thing, a)) ? '1' : '0', buff, bp);
} else {
safe_chr(Can_Examine(it, thing) ? '1' : '0', buff, bp);
}
}
/* ARGSUSED */
FUNCTION(fun_type)
{
dbref it = match_thing(executor, args[0]);
if (it == NOTHING) {
safe_str("#-1", buff, bp);
return;
}
switch (Typeof(it)) {
case TYPE_PLAYER:
safe_str("PLAYER", buff, bp);
break;
case TYPE_THING:
safe_str("THING", buff, bp);
break;
case TYPE_EXIT:
safe_str("EXIT", buff, bp);
break;
case TYPE_ROOM:
safe_str("ROOM", buff, bp);
break;
default:
safe_str("WEIRD OBJECT", buff, bp);
do_rawlog(LT_ERR, "WARNING: Weird object #%d (type %d)\n", it, Typeof(it));
}
}
/* ARGSUSED */
FUNCTION(fun_hasflag)
{
dbref thing;
ATTR *attrib;
int f;
if (strchr(args[0], '/')) {
parse_attrib(executor, args[0], &thing, &attrib);
if (!attrib)
safe_str("#-1", buff, bp);
else if ((f = string_to_atrflag(executor, args[1])) < 0)
safe_str("#-1", buff, bp);
else
safe_chr((attrib->flags & f) ? '1' : '0', buff, bp);
} else {
thing = match_thing(executor, args[0]);
if (thing == NOTHING)
safe_str("#-1", buff, bp);
else
safe_chr(sees_flag(executor, thing, args[1]) ? '1' : '0', buff, bp);
}
}
/* ARGSUSED */
FUNCTION(fun_hastype)
{
dbref it = match_thing(executor, args[0]);
if (it == NOTHING) {
safe_str("#-1", buff, bp);
return;
}
switch (*args[1]) {
case 'r':
case 'R':
safe_chr((Typeof(it) == TYPE_ROOM) ? '1' : '0', buff, bp);
break;
case 'e':
case 'E':
safe_chr((Typeof(it) == TYPE_EXIT) ? '1' : '0', buff, bp);
break;
case 'p':
case 'P':
safe_chr((Typeof(it) == TYPE_PLAYER) ? '1' : '0', buff, bp);
break;
case 't':
case 'T':
safe_chr((Typeof(it) == TYPE_THING) ? '1' : '0', buff, bp);
break;
default:
safe_str("#-1 NO SUCH TYPE", buff, bp);
break;
};
}
/* ARGSUSED */
FUNCTION(fun_orflags)
{
safe_chr(handle_flaglists(executor, args[0], args[1], 0) ? '1' : '0',
buff, bp);
}
/* ARGSUSED */
FUNCTION(fun_andflags)
{
safe_chr(handle_flaglists(executor, args[0], args[1], 1) ? '1' : '0',
buff, bp);
}
static lock_type
get_locktype(obj, str)
dbref obj;
char const *str;
{
/* figure out a lock type */
if (!str || !*str)
return Basic_Lock;
return str;
}
/* ARGSUSED */
FUNCTION(fun_lock)
{
dbref it;
char *p;
lock_type ltype;
if ((p = strchr(args[0], '/')))
*p++ = '\0';
it = match_thing(executor, args[0]);
ltype = get_locktype(it, p);
if (nargs == 2) {
#ifdef FUNCTION_SIDE_EFFECTS
do_lock(executor, args[0], args[1], ltype);
#else
safe_str("#-1 FUNCTION DISABLED", buff, bp);
#endif
return;
}
if ((it != NOTHING) && (ltype != NULL) && Can_Read_Lock(executor, it, ltype)) {
safe_str(unparse_boolexp(executor, getlock(it, ltype), 1), buff, bp);
return;
}
safe_str("#-1", buff, bp);
}
/* ARGSUSED */
FUNCTION(fun_elock)
{
char *p;
lock_type ltype;
dbref it;
dbref victim = match_thing(executor, args[1]);
p = (char *) strchr(args[0], '/');
if (p)
*p++ = '\0';
it = match_thing(executor, args[0]);
ltype = get_locktype(it, p);
if ((it == NOTHING) ||
(ltype == NULL) ||
!Can_Run_Lock(executor, it, ltype)) {
safe_str("#-1", buff, bp);
return;
}
safe_chr(eval_lock(victim, it, ltype) ? '1' : '0', buff, bp);
return;
}
/* ARGSUSED */
FUNCTION(fun_findable)
{
dbref obj = match_thing(executor, args[0]);
dbref victim = match_thing(executor, args[1]);
if (obj == NOTHING)
safe_str("#-1 ARG1 NOT FOUND", buff, bp);
else if (victim == NOTHING)
safe_str("#-1 ARG2 NOT FOUND", buff, bp);
else
safe_chr(Can_Locate(obj, victim) ? '1' : '0', buff, bp);
}
/* ARGSUSED */
FUNCTION(fun_loc)
{
dbref it = match_thing(executor, args[0]);
if ((it != NOTHING) && Can_Locate(executor, it))
safe_str(unparse_dbref(Location(it)), buff, bp);
else
safe_str("#-1", buff, bp);
}
#ifdef CREATION_TIMES
/* ARGSUSED */
FUNCTION(fun_ctime)
{
dbref it = match_thing(executor, args[0]);
if ((it != NOTHING) && Can_Examine(executor, it)) {
safe_str(ctime(&CreTime(it)), buff, bp);
(*bp)--;
return;
}
safe_str("#-1", buff, bp);
}
/* ARGSUSED */
FUNCTION(fun_mtime)
{
dbref it = match_thing(executor, args[0]);
if ((it != NOTHING) && Can_Examine(executor, it) &&
(Typeof(it) != TYPE_PLAYER)) {
safe_str(ctime(&ModTime(it)), buff, bp);
(*bp)--;
return;
}
safe_str("#-1", buff, bp);
}
#endif
/* ARGSUSED */
FUNCTION(fun_where)
{
/* finds the "real" location of an object */
dbref it = match_thing(executor, args[0]);
if ((it != NOTHING) && Can_Locate(executor, it))
safe_str(unparse_dbref(where_is(it)), buff, bp);
else
safe_str("#-1", buff, bp);
}
/* ARGSUSED */
FUNCTION(fun_room)
{
dbref room;
int rec = 0;
dbref it = match_thing(executor, args[0]);
if ((it != NOTHING) && Can_Locate(executor, it)) {
room = Location(it);
if (!GoodObject(room)) {
safe_str("#-1", buff, bp);
return;
}
while (Typeof(room) != TYPE_ROOM) {
room = Location(room);
rec++;
if (rec > 20) {
notify(executor, "Too many containers.");
safe_str("#-1", buff, bp);
return;
}
}
safe_str(unparse_dbref(room), buff, bp);
} else {
notify(executor, "Permission denied.");
safe_str("#-1", buff, bp);
}
}
/* ARGSUSED */
FUNCTION(fun_rloc)
{
int i;
int deep = parse_integer(args[1]);
dbref it = match_thing(executor, args[0]);
if (deep > 20)
deep = 20;
if ((it != NOTHING) && Can_Locate(executor, it)) {
for (i = 0; i < deep; i++) {
if (!GoodObject(it) || (Typeof(it) == TYPE_ROOM))
break;
it = Location(it);
}
safe_str(unparse_dbref(it), buff, bp);
return;
}
safe_str("#-1", buff, bp);
}
/* ARGSUSED */
FUNCTION(fun_zone)
{
dbref it;
if (nargs == 2) {
#ifdef FUNCTION_SIDE_EFFECTS
do_chzone(executor, args[0], args[1]);
#else
safe_str("#-1 FUNCTION DISABLED", buff, bp);
return;
#endif
}
it = match_thing(executor, args[0]);
if (it == NOTHING || !Can_Examine(executor, it)) {
safe_str("#-1", buff, bp);
return;
}
safe_str(unparse_dbref(Zone(it)), buff, bp);
}
/* ARGSUSED */
FUNCTION(fun_parent)
{
dbref it;
if (nargs == 2) {
#ifdef FUNCTION_SIDE_EFFECTS
do_parent(executor, args[0], args[1]);
#else
safe_str("#-1 FUNCTION DISABLED", buff, bp);
return;
#endif
}
it = match_thing(executor, args[0]);
if ((it == NOTHING) || !Can_Examine(executor, it)) {
safe_str("#-1", buff, bp);
return;
}
safe_str(unparse_dbref(Parent(it)), buff, bp);
}
/* ARGSUSED */
FUNCTION(fun_lparent)
{
dbref it;
dbref par;
it = match_thing(executor, args[0]);
if (!GoodObject(it)) {
safe_str("#-1", buff, bp);
return;
}
safe_str(unparse_dbref(it), buff, bp);
par = Parent(it);
while (GoodObject(par) && Can_Examine(executor, it)) {
safe_chr(' ', buff, bp);
safe_str(unparse_dbref(par), buff, bp);
it = par;
par = Parent(par);
}
}
/* ARGSUSED */
FUNCTION(fun_home)
{
dbref it = match_thing(executor, args[0]);
if ((it == NOTHING) || !Can_Examine(executor, it) ||
(Typeof(it) == TYPE_ROOM)) {
safe_str("#-1", buff, bp);
return;
}
safe_str(unparse_dbref(Exits(it)), buff, bp);
}
/* ARGSUSED */
FUNCTION(fun_money)
{
dbref it = match_thing(executor, args[0]);
if (it == NOTHING) {
safe_str("#-1", buff, bp);
return;
}
safe_str(unparse_integer(Pennies(it)), buff, bp);
}
/* ARGSUSED */
FUNCTION(fun_owner)
{
dbref thing;
ATTR *attrib;
if (strchr(args[0], '/')) {
parse_attrib(executor, args[0], &thing, &attrib);
if (!attrib)
safe_str("#-1", buff, bp);
else
safe_str(unparse_dbref(attrib->creator), buff, bp);
} else {
thing = match_thing(executor, args[0]);
if (thing == NOTHING)
safe_str("#-1", buff, bp);
else
safe_str(unparse_dbref(Owner(thing)), buff, bp);
}
}
/* ARGSUSED */
FUNCTION(fun_name)
{
dbref it;
if (nargs == 2) {
#ifdef FUNCTION_SIDE_EFFECTS
do_name(executor, args[0], args[1]);
#else
safe_str("#-1 FUNCTION DISABLED", buff, bp);
return;
#endif
}
if ((it = match_thing(executor, args[0])) != NOTHING)
safe_str(shortname(it), buff, bp);
}
/* ARGSUSED */
FUNCTION(fun_fullname)
{
dbref it;
if ((it = match_thing(executor, args[0])) != NOTHING)
safe_str(Name(it), buff, bp);
}
/* ARGSUSED */
FUNCTION(fun_pmatch)
{
dbref target;
if (*args[0] == '*')
target = lookup_player(args[0] + 1);
else if (*args[0] == NUMBER_TOKEN) {
target = parse_dbref(args[0]);
if (!(GoodObject(target) && (Typeof(target) == TYPE_PLAYER))) {
notify(executor, "No match.");
safe_str("#-1", buff, bp);
return;
} else {
safe_str(unparse_dbref(target), buff, bp);
return;
}
} else
target = lookup_player(args[0]);
if (target == NOTHING) {
if (*args[0] == '*')
target = short_page(args[0] + 1);
else
target = short_page(args[0]);
if (hidden(target) && !Priv_Who(executor))
target = NOTHING;
}
switch (target) {
case NOTHING:
notify(executor, "No match.");
safe_str("#-1", buff, bp);
break;
case AMBIGUOUS:
notify(executor, "I'm not sure who you mean.");
safe_str("#-2", buff, bp);
break;
default:
safe_str(unparse_dbref(target), buff, bp);
}
}
/* ARGSUSED */
FUNCTION(fun_locate)
{
dbref looker;
object_flag_type pref_type;
dbref item;
char *p;
int keys = 0;
int done = 0;
int ambig_ok = 0;
long match_flags = 0;
/* find out what we're matching in relation to */
looker = match_thing(executor, args[0]);
if (looker == NOTHING) {
notify(executor, "I don't see that here.");
safe_str("#-1", buff, bp);
return;
}
if (!See_All(executor) && !controls(executor, looker)) {
notify(executor, "Permission denied.");
safe_str("#-1", buff, bp);
return;
}
/* find out our preferred match type */
pref_type = NOTYPE;
for (p = args[2]; *p; p++) {
switch (*p) {
case 'N':
pref_type = NOTYPE;
break;
case 'E':
pref_type = TYPE_EXIT;
break;
case 'P':
pref_type = TYPE_PLAYER;
break;
case 'R':
pref_type = TYPE_ROOM;
break;
case 'T':
pref_type = TYPE_THING;
break;
case 'L':
keys = 1;
break;
}
}
if (keys)
match_flags = MAT_CHECK_KEYS;
/* now figure out where what kinds of matches we want done */
for (p = args[2]; *p && !done; p++) {
switch (*p) {
case '*':
match_flags |= MAT_EVERYTHING;
done = 1;
break;
case 'a':
match_flags |= MAT_ABSOLUTE;
break;
case 'c':
match_flags |= MAT_CARRIED_EXIT;
break;
case 'e':
match_flags |= MAT_EXIT;
break;
case 'h':
match_flags |= MAT_HERE;
break;
case 'i':
match_flags |= MAT_POSSESSION;
break;
case 'l':
match_flags |= MAT_CONTAINER;
break;
case 'm':
match_flags |= MAT_ME;
break;
case 'n':
match_flags |= MAT_NEIGHBOR;
break;
case 'p':
match_flags |= MAT_PLAYER;
break;
case 'N':
case 'E':
case 'P':
case 'R':
case 'T':
case 'L':
/* these are from previous type switch check. ignore. */
break;
case 'X':
ambig_ok = 1; /* okay to pick last match */
default:
notify(executor, tprintf("I don't understand switch '%c'.", *p));
break;
}
}
/* report the results */
if (!ambig_ok)
item = match_result(looker, args[1], pref_type, match_flags);
else
item = last_match_result(looker, args[1], pref_type, match_flags);
if (item == NOTHING)
notify(executor, "Nothing found.");
else if (item == AMBIGUOUS)
notify(executor, "More than one match found.");
safe_str(tprintf("#%d", item), buff, bp);
}
#ifdef FUNCTION_SIDE_EFFECTS
/* --------------------------------------------------------------------------
* Creation functions: CREATE, OPEN, DIG
*/
/* ARGSUSED */
FUNCTION(fun_create)
{
int cost;
if (nargs == 2)
cost = parse_integer(args[1]);
else
cost = 10;
safe_str(unparse_dbref(do_create(executor, args[0], cost)), buff, bp);
}
/* ARGSUSED */
FUNCTION(fun_open)
{
safe_str(unparse_dbref(do_real_open(executor, args[0], args[1], NOTHING)),
buff, bp);
}
/* ARGSUSED */
FUNCTION(fun_dig)
{
safe_str(unparse_dbref(do_dig(executor, args[0], args, 0)), buff, bp);
}
/* ARGSUSED */
FUNCTION(fun_clone)
{
safe_str(unparse_dbref(do_clone(executor, args[0])), buff, bp);
}
/* --------------------------------------------------------------------------
* Attribute functions: LINK, SET
*/
/* ARGSUSED */
FUNCTION(fun_link)
{
do_link(executor, args[0], args[1]);
}
/* ARGSUSED */
FUNCTION(fun_set)
{
do_set(executor, args[0], args[1]);
}
/* ARGSUSED */
FUNCTION(fun_wipe)
{
do_wipe(executor, args[0]);
}
/* --------------------------------------------------------------------------
* Misc functions: TEL
*/
/* ARGSUSED */
FUNCTION(fun_tel)
{
do_teleport(executor, args[0], args[1]);
}
#else
/* ARGSUSED */
FUNCTION(fun_create)
{
safe_str("#-1 FUNCTION DISABLED", buff, bp);
}
/* ARGSUSED */
FUNCTION(fun_open)
{
safe_str("#-1 FUNCTION DISABLED", buff, bp);
}
/* ARGSUSED */
FUNCTION(fun_dig)
{
safe_str("#-1 FUNCTION DISABLED", buff, bp);
}
/* ARGSUSED */
FUNCTION(fun_clone)
{
safe_str("#-1 FUNCTION DISABLED", buff, bp);
}
/* ARGSUSED */
FUNCTION(fun_link)
{
safe_str("#-1 FUNCTION DISABLED", buff, bp);
}
/* ARGSUSED */
FUNCTION(fun_set)
{
safe_str("#-1 FUNCTION DISABLED", buff, bp);
}
/* ARGSUSED */
FUNCTION(fun_wipe)
{
safe_str("#-1 FUNCTION DISABLED", buff, bp);
}
/* ARGSUSED */
FUNCTION(fun_tel)
{
safe_str("#-1 FUNCTION DISABLED", buff, bp);
}
#endif /* FUNCTION_SIDE_EFFECTS */
/* ARGSUSED */
FUNCTION(fun_isdbref)
{
safe_chr((parse_dbref(args[0]) != NOTHING) ? '1' : '0', buff, bp);
}
/* ARGSUSED */
FUNCTION(fun_grep)
{
char *tp;
dbref it = match_thing(executor, args[0]);
if (it == NOTHING) {
safe_str("#-1 NO SUCH OBJECT VISIBLE", buff, bp);
return;
}
/* make sure there's an attribute and a pattern */
if (!*args[1]) {
safe_str("#-1 NO SUCH ATTRIBUTE", buff, bp);
return;
}
if (!*args[2]) {
safe_str("#-1 INVALID GREP PATTERN", buff, bp);
return;
}
tp = grep_util(executor, it, args[1], args[2], strlen(args[2]),
strcmp(called_as, "GREP"));
#ifdef MEM_CHECK
add_check("fun_grep.attr_list");
#endif
safe_str(tp, buff, bp);
mush_free((Malloc_t) tp, "fun_grep.attr_list");
}
/* Get database size statistics */
/* ARGSUSED */
FUNCTION(fun_lstats)
{
dbref who;
char tbuf1[BUFFER_LEN];
struct db_stat_info *si;
if ((!args[0]) || !*args[0] || !strcasecmp(args[0], "all")) {
who = ANY_OWNER;
} else if (!strcasecmp(args[0], "me")) {
who = executor;
} else {
who = lookup_player(args[0]);
if (who == NOTHING) {
safe_str("#-1 NOT FOUND", buff, bp);
return;
}
}
if (!Search_All(executor)) {
if (who != ANY_OWNER && who != executor) {
safe_str("#-1 PERMISSION DENIED", buff, bp);
return;
}
}
si = get_stats(executor, who);
if (who != ANY_OWNER) {
sprintf(tbuf1, "%d %d %d %d %d", si->total - si->garbage, si->rooms, si->exits, si->things, si->players);
} else {
sprintf(tbuf1, "%d %d %d %d %d %d", si->total, si->rooms, si->exits, si->things,
si->players, si->garbage);
}
safe_str(tbuf1, buff, bp);
}
/* ARGSUSED */
FUNCTION(fun_atrlock)
{
dbref thing;
char *p;
ALIST *ptr;
int status;
#ifdef FUNCTION_SIDE_EFFECTS
if (nargs == 1)
status = 0;
else {
if (!strcasecmp(args[1], "on")) {
status = 1;
} else if (!strcasecmp(args[1], "off")) {
status = 2;
} else
status = 0;
}
#else
status = 0;
#endif
if (!args[0] || !*args[0]) {
safe_str("#-1 ARGUMENT MUST BE OBJ/ATTR", buff, bp);
return;
}
if (!(p = (char *) index(args[0], '/')) || !(*(p + 1))) {
safe_str("#-1 ARGUMENT MUST BE OBJ/ATTR", buff, bp);
return;
}
*p++ = '\0';
if ((thing = noisy_match_result(executor, args[0], NOTYPE, MAT_EVERYTHING)) == NOTHING) {
safe_str("#-1", buff, bp);
return;
}
for (ptr = db[thing].list; ptr; ptr = AL_NEXT(ptr))
if (!strcasecmp(AL_NAME(ptr), p)
#ifndef VISIBLE_EMPTY_ATTRS
&& *AL_STR(ptr)
#endif
)
break;
if (!ptr) {
ptr = aname_hash_lookup(strupper(p));
if (!ptr || !strcmp(p, AL_NAME(ptr)))
ptr = NULL;
else {
p = (char *) AL_NAME(ptr);
for (ptr = db[thing].list; ptr; ptr = AL_NEXT(ptr))
if (!strcmp(AL_NAME(ptr), p)
#ifndef VISIBLE_EMPTY_ATTRS
&& *AL_STR(ptr)
#endif
)
break;
}
}
if (ptr) {
switch (status) {
case 0:
safe_str(unparse_integer(!!(AL_FLAGS(ptr) & AF_LOCKED)), buff, bp);
return;
case 1:
if (!Wizard(executor) &&
(Owner(AL_CREATOR(ptr)) != Owner(executor))) {
safe_str("#-1 PERMISSION DENIED", buff, bp);
return;
}
AL_FLAGS(ptr) |= AF_LOCKED;
return;
case 2:
if (!Wizard(executor) &&
(Owner(AL_CREATOR(ptr)) != Owner(executor))) {
safe_str("#-1 PERMISSION DENIED", buff, bp);
return;
}
AL_FLAGS(ptr) &= ~AF_LOCKED;
return;
default:
safe_str("#-1", buff, bp);
return;
}
} else
safe_str("#-1 NO SUCH ATTRIBUTE", buff, bp);
return;
}
#ifdef CHAT_SYSTEM
FUNCTION(fun_channels)
{
dbref it;
if (nargs == 1) {
CHANLIST *c;
/* Given an argument, return list of channels it's on */
it = match_thing(executor, args[0]);
if ((it == NOTHING) || !Can_Examine(executor, it)) {
safe_str("#-1", buff, bp);
return;
}
for (c = Chanlist(it); c; c = c->next) {
if (c != Chanlist(it))
safe_chr(' ', buff, bp);
safe_str(ChanName(c->chan), buff, bp);
}
} else {
CHAN *c;
/* No arguments - return list of all channels */
for (c = channels; c; c = c->next) {
if (Chan_Can_See(c, executor)) {
if (c != channels)
safe_chr(' ', buff, bp);
safe_str(ChanName(c), buff, bp);
}
}
}
return;
}
#endif