/* walkdb.c */
#include "copyright.h"
/* Support for commands which trudge up 'n down the database like
@find, @fnd and @stat. */
#ifdef WANT_ANSI
#ifdef __STDC__
#include <stddef.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 "flags.h"
#include "misc.h"
/* Bind occurances of the universal var in ACTION to ARG, then run ACTION.
Cmds run in low-prio Q after a 1 sec delay for the first one. */
static void bind_and_queue (dbref player, dbref cause, char *action,
char *argstr, char *cargs[], int ncargs)
{
char *command; /* allocated by replace_string */
command = replace_string (BOUND_VAR, argstr, action),
wait_que (player, cause, RU_ARG1_TAKE, 0, NOTHING, command,
cargs, ncargs);
}
#ifdef notdef
/*************************************************************************/
/* Option-ish Schtuff */
/*************************************************************************/
#define FND_HELPFILE "@fnd_helpfile"
/* These two statements define the operator tokens. They MUST be sorted
longest first, so the longer ops will still match if they contain a
shorter op in their beginning. */
typedef enum
{
WILDNEQ, WILDEQ, STRNEQ, STREQ, ERR
} op_t;
static const char *Ops[] =
{
"!==", "==", "!=", "=", NULL
};
/* union of all op chars, above */
#define OP_CHARS "=!"
/*************************************************************************/
/* End of Option-ish Schtuff */
/*************************************************************************/
/* struct used to remember each word in query after parsing */
typedef struct
{
char *left, *right;
op_t op;
} findit;
extern void abort ();
extern int atoi ();
extern dbref match_thing (dbref player, const char *name);
extern char **string2list (char *str, const char sep);
static void fnd_parse_word (char *word, findit * out)
{
int where, len, wherelen, i;
if (!word || *word == '\0' || ((len = strlen (word))
== (where = strcspn (word, OP_CHARS))))
out->op = ERR;
else
{
wherelen = strspn (word + where, OP_CHARS);
for (i = 0; Ops[i]; i++)
if (!strncmp (Ops[i], word + where, strlen (Ops[i])))
break;
out->op = i;
if (i != ERR)
{
out->left = word;
*(word + where) = '\0';
out->right = word + where + wherelen;
}
}
}
/*
* Returns number of non-null ptrs in array thereof
*/
static int count_ptrs (const void **p)
{
int out = 0;
if (p)
while (*p++)
out++;
return out;
}
#define FNDUSAGE(x) if(1) { notify(player,x);\
spit_file(player, FND_HELPFILE);\
goto byebye; }
#define MALLOCTST(x) if(!x) { perror("Bad malloc in do_fnd. No mem?");\
return; }
#define FNDMALLOC(x,y,z) if(!((x) = XMALLOC (y, z)))\
{ perror("Bad malloc in do_fnd. No mem?");\
return; }
#define HELP " "
#define ATTRIB "Bad @fnd attribute/value syntax."
#define OPTION "Bad @fnd `-' option syntax."
#define CONFUSED "I don't think this does what you think it does."
/*#define FND_DEBUG*/
/* Command: @fnd - More like the unix find.
* Created: Tue Dec 18 20:33:20 1990 mitch@alpha.ces.cwru.edu
* Usage: @fnd
*/
/**** Trial new version (old one below) ****/
void do_fnd (dbref player, const char *in_cmd)
{
extern char *optarg;
extern int optind, opterr, getopt (int, char **, const char *);
int c, argc, nquery; /* argc:how many words */
char *command; /* my copy of in_cmd */
char **argv; /* pntrs to words in cmd */
char *buff; /* temporary buffer */
dbref i; /* for walking dbase */
findit *queries = NULL; /* array of attribute/operation structs */
/* Option vars and their defaults:: Set according to user input. */
int debug = 0; /* no debug mode by default */
int quiet = 0; /* print output by default */
char *execstr = NULL; /* execute this string on each hit */
opterr = 0; /* tell getopt: no error message */
optind = 1; /* tell getopt: start on second arg */
if (!in_cmd || *in_cmd == '\0')
{
notify (player, "Sorry, internal error.");
return;
}
if (!payfor (player, mudconf.searchcost))
{
notify (player, tprintf("You don't have enough %s.", mudconf.many_coins));
return;
}
/*
* Copy because s2l will modify it. This may not really be needed.
*/
FNDMALLOC (command, sizeof (char *) * strlen (in_cmd) +1, "do_fnd");
argv = string2list (strcpy (command, in_cmd), ' ');
argc = count_ptrs ((const void **) argv);
if (argc <= 1)
FNDUSAGE (CONFUSED);
#ifdef FND_DEBUG
for (i = 0; i < argc; i++)
{
buff=alloc_lbuf("do_fnd.debug.1");
sprintf (buff, "FND-DEBUG:arg %d=`%s'", i, argv[i]);
fputs (buff, stderr);
notify (player, buff);
free_lbuf(buff);
}
#endif
while ((c = getopt (argc, argv, "qhdx:")) != EOF)
switch (c)
{
case 'x':
execstr = optarg;
break;
case 'h': /* help */
FNDUSAGE (HELP);
case 'q': /* quiet */
quiet = 1;
break;
case 'd': /* debug */
debug = 1;
break;
case '?': /* huh? */
FNDUSAGE (OPTION);
}
/* Check the non-option parameters. If any have no '=' in them,
complain. Otherwise, treat as an ATTR=VALUE pair to look for */
FNDMALLOC (buff, sizeof (findit) * (argc - optind + 1), "do_fnd.2");
queries = (findit *)buff;
for (nquery = 0; optind < argc; optind++, nquery++)
{
fnd_parse_word (argv[optind], &queries[nquery]);
if (queries[nquery].op == ERR)
FNDUSAGE (ATTRIB);
}
if (debug)
{
buff=alloc_lbuf("do_fnd.debug.2");
sprintf (buff,
"fnd debug:quiet=%d execstr=`%s' nquery=%d", quiet, execstr, nquery);
notify (player, buff);
for (i = 0; i < nquery; i++)
{
sprintf (buff, "op=%d left=`%s' right=`%s'", queries[i].op,
queries[i].left, queries[i].right);
notify (player, buff);
}
free_lbuf(buff);
}
else
{
#if 0
/* We know the options, let's do the db walk */
DO_WHOLE_DB(i)
{
if (!controls (player, i))
continue;
if (!quiet) {
buff = unparse_object (player, i);
notify (player, buff);
free_lbuf(buff);
}
if (execstr && !(Flags (i) & GOING))
/* bind_and_queue (player, player, execstr, i, NULL, 0); */
/*2nd player==cause */
}
#endif
if (!quiet)
notify (player, "*** @fnd: End of List ***");
}
byebye:
XFREE (command, "do_fnd");
XFREE (queries, "do_fnd.2"); /* TO DO: walk this, to free each one. */
} /* end of do_fnd */
#endif /* notdef */
/* New @dolist. i.e.:
* @dolist #12 #34 #45 #123 #34644=@emit [name(##)]
*/
void do_dolist (dbref player, dbref cause, int key, char *list, char *command,
char *cargs[], int ncargs)
{
char *curr, *objstring;
if (!list || *list == '\0') {
notify (player, "That's terrific, but what should I do with the list?");
return;
}
curr = list;
while (curr && *curr) {
while (*curr==' ') curr++;
if (*curr) {
objstring = parse_to(&curr, ' ', EV_STRIP);
bind_and_queue (player, cause, command, objstring,
cargs, ncargs);
}
}
}
/* Regular @find command */
void do_find (dbref player, dbref cause, int key, char *name)
{
dbref i;
char *buff;
if (!payfor (player, mudconf.searchcost))
{
notify (player, tprintf("You don't have enough %s.",mudconf.many_coins));
}
else
{
DO_WHOLE_DB(i)
{
if ((i % 100) == 0)
{
tmp_sync();
cache_reset();
}
if (Typeof (i) != TYPE_EXIT
&& controls (player, i)
&& (!*name || string_match (Name (i), name)))
{
buff = unparse_object (player, i);
notify (player, buff);
free_lbuf(buff);
}
}
notify (player, "***End of List***");
}
}
/* ---------------------------------------------------------------------------
* get_stats, do_stats: Get counts of items in the db.
*/
int get_stats (dbref player, dbref who, STATS *info)
{
dbref i;
info->s_total = 0;
info->s_rooms = 0;
info->s_exits = 0;
info->s_things = 0;
info->s_players = 0;
info->s_garbage = 0;
/* Do we have permission? */
if (Good_obj(who) && !Controls(player, who)) {
notify(player, "Permission denied.");
return 0;
}
/* Can we afford it? */
if (!payfor (player, mudconf.searchcost)) {
notify (player, tprintf("You don't have enough %s.",
mudconf.many_coins));
return 0;
}
DO_WHOLE_DB(i) {
if ((who == NOTHING) || (who == Owner (i))) {
info->s_total++;
if ((Flags (i) & GOING) && (Typeof(i) != TYPE_ROOM)) {
info->s_garbage++;
continue;
}
switch (Typeof (i)) {
case TYPE_ROOM: info->s_rooms++; break;
case TYPE_EXIT: info->s_exits++; break;
case TYPE_THING: info->s_things++; break;
case TYPE_PLAYER: info->s_players++; break;
default: info->s_garbage++;
}
}
}
return 1;
}
void do_stats (dbref player, dbref cause, int key, char *name)
/* reworked by R'nice */
{
dbref owner;
STATS statinfo;
switch (key) {
case STAT_ALL:
owner = NOTHING;
break;
case STAT_ME:
owner = Owner(player);
break;
case STAT_PLAYER:
if (!(name && *name)) {
notify(player,
tprintf("The universe contains %d objects.",
mudstate.db_top));
return;
}
owner = lookup_player (player, name, 1);
if (owner == NOTHING) {
notify(player, "Not found.");
return;
}
break;
default:
notify(player, "Illegal combination of switches.");
return;
}
if (!get_stats(player, owner, &statinfo))
return;
notify (player,
tprintf ("%d objects = %d rooms, %d exits, %d things, %d players. (%d garbage)",
statinfo.s_total, statinfo.s_rooms, statinfo.s_exits,
statinfo.s_things, statinfo.s_players,
statinfo.s_garbage));
#ifdef TEST_MALLOC
if (Wizard (player))
notify (player, tprintf ("Malloc count = %d.", malloc_count));
#endif /* TEST_MALLOC */
#ifdef MSTATS
if(Wizard(player)) {
struct mstats_value mval;
int i;
extern unsigned int malloc_sbrk_used, malloc_sbrk_unused;
extern int nmal, nfre;
extern struct mstats_value malloc_stats();
extern int malloc_mem_used(), malloc_mem_free();
notify(player, tprintf("Sbrk Unused: %d -- Sbrk Used: %d",
malloc_sbrk_unused, malloc_sbrk_used));
notify(player, tprintf("Raw malloc cnt: %d -- Raw free cnt: %d",
nmal, nfre));
for(i = 0; i < 15; i++) {
mval = malloc_stats(i);
notify(player, tprintf("Blocksz: %d -- Free: %d -- Used: %d",
mval.blocksize, mval.nfree, mval.nused));
}
notify(player, tprintf("Mem used: %d -- Mem free: %d",
malloc_mem_used(), malloc_mem_free()));
}
#endif /* MSTATS */
}
int chown_all (dbref from_player, dbref to_player)
{
int i, count;
if (Typeof(from_player) != TYPE_PLAYER)
from_player = Owner(from_player);
if (Typeof(to_player) != TYPE_PLAYER)
to_player = Owner(to_player);
count = 0;
DO_WHOLE_DB(i) {
if ((Owner(i) == from_player) && (Owner(i) != i)) {
if (Typeof(i) == TYPE_PLAYER)
s_Owner(i, i);
else
s_Owner (i, to_player);
s_Flags(i, (Flags(i) & ~(CHOWN_OK|INHERIT)) | HALT);
count++;
}
}
return count;
}
void do_chownall (dbref player, dbref cause, int key, char *from, char *to)
{
int count;
dbref victim, recipient;
init_match (player, from, TYPE_PLAYER);
match_neighbor ();
match_absolute ();
match_player ();
if ((victim = noisy_match_result ()) == NOTHING)
return;
if ((to != NULL) && *to) {
init_match (player, to, TYPE_PLAYER);
match_neighbor ();
match_absolute ();
match_player ();
if ((recipient = noisy_match_result ()) == NOTHING)
return;
} else {
recipient = player;
}
count = chown_all(victim, recipient);
if (!Quiet(player)) {
notify(player, tprintf("%d objects @chowned.", count));
}
}
#define ANY_OWNER -2
/* ---------------------------------------------------------------------------
* convert_flags: convert a list of flag letters into its bit pattern.
* Also set the type qualifier if specified and not already set.
*/
FLAG convert_flags (dbref player, char *flaglist, FLAGSEL *selection,
FLAG *p_type)
{
int i, handled, handled_any, handled_real_flag;
char *s;
FLAG masks[8], type;
FLAGENT *fp;
for(i=0; i<8; i++)
masks[i] = 0;
handled_real_flag = 0;
type = *p_type;
for (s=flaglist; *s; s++) {
handled = 0;
/* Check for object type */
for (i=0; (i<=7) && !handled; i++) {
if ((object_types[i].lett == *s) &&
!(((object_types[i].perm & CA_WIZARD) &&
!Wizard(player)) ||
((object_types[i].perm & CA_GOD) &&
!God(player)))) {
if ((type != NOTYPE) && (type != i)) {
notify(player,
tprintf("%c: Conflicting type specifications.",
*s));
return 0;
}
type = i;
handled = 1;
}
}
/* Check generic flags */
if (handled)
continue;
for (fp=gen_flags; (fp->flagname) && !handled; fp++) {
if ((fp->flaglett == *s) &&
!(((fp->listperm & CA_WIZARD) &&
!Wizard(player)) ||
((fp->listperm & CA_GOD) &&
!God(player)))) {
for (i=0; i<8; i++)
masks[i] |= fp->flagvalue;
handled = 1;
handled_real_flag = 1;
}
}
/* Check type-specific flags */
if (handled)
continue;
handled_any = 0;
for (i=0; i<=7; i++) {
handled = 0;
if ((type != NOTYPE) && (type != i))
continue;
if (!(fp = object_types[i].flaglist))
continue;
for (; (fp->flagname) && !handled; fp++) {
if ((fp->flaglett == *s) &&
!(((fp->listperm & CA_WIZARD) &&
!Wizard(player)) ||
((fp->listperm & CA_GOD) &&
!God(player)))) {
masks[i] |= fp->flagvalue;
handled = 1;
handled_any = 1;
handled_real_flag = 1;
}
}
if (!handled)
masks[i] = -1;
}
if (handled_any)
handled = 1;
if (!handled) {
notify(player,
tprintf("%c: Flag unknown or not valid for specified object type",
*s));
return 0;
}
}
/* Exclude classes that match nothing by setting their mask to -1 */
if (handled_real_flag) {
for (i=0; i<8; i++) {
if (!masks[i]) masks[i] = -1;
}
}
/* return new mask and type */
selection->player_flags = masks[TYPE_PLAYER];
selection->room_flags = masks[TYPE_ROOM];
selection->thing_flags = masks[TYPE_THING];
selection->exit_flags = masks[TYPE_EXIT];
selection->player_eflags = 0;
*p_type = type;
return 1;
}
void er_mark_disabled (dbref player)
{
notify(player,
"The mark commands are not allowed while DB cleaning is enabled.");
notify(player,
"Use the '@disable cleaning' command to disable automatic cleaning.");
notify(player,
"Remember to '@unmark_all' before re-enabling automatic cleaning.");
}
/* ---------------------------------------------------------------------------
* do_search: Walk the db reporting various things (or setting/clearing
* mark bits)
*/
int search_setup (dbref player, char *searchfor, SEARCH *parm)
{
char *pname, *searchtype;
int err;
/* Crack arg into <pname> <type>=<targ> */
pname = parse_to(&searchfor, '=', EV_STRIP_TS);
if (!pname || !*pname)
pname = (char *) "me";
searchtype = strchr(pname, ' ');
if (searchtype) {
*searchtype++ = '\0';
} else {
if (!searchfor || !*searchfor) {
searchtype = (char *) "";
} else {
searchtype = pname;
pname = (char *) "";
}
}
parm->s_owner = Owner(player);
parm->s_wizard = Wizard(player);
/* set limits on who we search */
parm->s_rst_owner = NOTHING;
if (!*pname) {
parm->s_rst_owner = parm->s_wizard ? ANY_OWNER : player;
} else if (pname[0] == '#') {
parm->s_rst_owner = atoi (&pname[1]);
if (!Good_obj(parm->s_rst_owner))
parm->s_rst_owner = NOTHING;
else if (Typeof(parm->s_rst_owner) != TYPE_PLAYER)
parm->s_rst_owner = NOTHING;
} else if (strcmp (pname, "me") == 0) {
parm->s_rst_owner = player;
} else {
parm->s_rst_owner = lookup_player (player, pname, 1);
}
if (parm->s_rst_owner == NOTHING) {
notify (player, tprintf ("%s: No such player", pname));
return 0;
}
/* set limits on what we search for */
err = 0;
parm->s_rst_name = NULL;
parm->s_rst_eval = NULL;
parm->s_rst_type = NOTYPE;
parm->s_flagmasks.player_flags = 0;
parm->s_flagmasks.room_flags = 0;
parm->s_flagmasks.thing_flags = 0;
parm->s_flagmasks.exit_flags = 0;
parm->s_flagmasks.player_eflags = 0;
switch (searchtype[0]) {
case '\0': /* the no class requested class :) */
break;
case 'e':
if (string_prefix ("exits", searchtype)) {
parm->s_rst_name = searchfor;
parm->s_rst_type = TYPE_EXIT;
} else if (string_prefix ("evaluate", searchtype)) {
parm->s_rst_eval = searchfor;
} else if (string_prefix ("eplayer", searchtype)) {
parm->s_rst_type = TYPE_PLAYER;
parm->s_rst_eval = searchfor;
} else if (string_prefix ("eroom", searchtype)) {
parm->s_rst_type = TYPE_ROOM;
parm->s_rst_eval = searchfor;
} else if (string_prefix ("eobject", searchtype)) {
parm->s_rst_type = TYPE_THING;
parm->s_rst_eval = searchfor;
} else if (string_prefix ("eexit", searchtype)) {
parm->s_rst_type = TYPE_EXIT;
parm->s_rst_eval = searchfor;
} else {
err = 1;
}
break;
case 'f':
if (string_prefix ("flags", searchtype)) {
/* convert_flags ignores previous values of flag_mask
* and s_rst_type while setting them */
if (!convert_flags (player, searchfor,
&parm->s_flagmasks, &parm->s_rst_type))
return 0;
} else {
err = 1;
}
break;
case 'n':
if (string_prefix ("name", searchtype)) {
parm->s_rst_name = searchfor;
} else {
err = 1;
}
break;
case 'o':
if (string_prefix ("objects", searchtype)) {
parm->s_rst_name = searchfor;
parm->s_rst_type = TYPE_THING;
} else {
err = 1;
}
break;
case 'p':
if (string_prefix ("players", searchtype)) {
parm->s_rst_name = searchfor;
parm->s_rst_type = TYPE_PLAYER;
if (!*pname)
parm->s_rst_owner = ANY_OWNER;
} else {
err = 1;
}
break;
case 'r':
if (string_prefix ("rooms", searchtype)) {
parm->s_rst_name = searchfor;
parm->s_rst_type = TYPE_ROOM;
} else {
err = 1;
}
break;
case 't':
if (string_prefix ("type", searchtype)) {
if (searchfor[0] == '\0')
break;
if (string_prefix ("room", searchfor))
parm->s_rst_type = TYPE_ROOM;
else if (string_prefix ("exit", searchfor))
parm->s_rst_type = TYPE_EXIT;
else if (string_prefix ("object", searchfor))
parm->s_rst_type = TYPE_THING;
else if (string_prefix ("player", searchfor)) {
parm->s_rst_type = TYPE_PLAYER;
if (!*pname)
parm->s_rst_owner = ANY_OWNER;
} else {
notify(player,
tprintf("%s: unknown type",
searchfor));
return 0;
}
} else {
err = 1;
}
break;
default:
err = 1;
}
if (err) {
notify (player, tprintf ("%s: unknown class", searchtype));
return 0;
}
/* Make sure player is authorized to do the search */
if (!parm->s_wizard &&
(parm->s_rst_type != TYPE_PLAYER) &&
(parm->s_rst_owner != player)) {
notify (player, "You need a search warrant to do that!");
return 0;
}
/* make sure player has money to do the search */
if (!payfor(player, mudconf.searchcost)) {
notify(player,
tprintf("You don't have enough %s to search. (You need %d)",
mudconf.many_coins, mudconf.searchcost));
return 0;
}
return 1;
}
void search_perform (dbref player, dbref cause, SEARCH *parm)
{
FLAG thingflags, mask;
dbref thing;
char *buff, *buff2, *result;
int save_invk_ctr;
buff = alloc_sbuf("search_perform.num");
olist_init();
save_invk_ctr = mudstate.func_invk_ctr;
DO_WHOLE_DB(thing) {
if ((thing % 100) == 0) {
tmp_sync();
cache_reset();
}
mudstate.func_invk_ctr = save_invk_ctr;
/* Check for matching type */
if ((parm->s_rst_type != NOTYPE) &&
(parm->s_rst_type != Typeof(thing)))
continue;
/* Check for matching owner */
if ((parm->s_rst_owner != ANY_OWNER) &&
(parm->s_rst_owner != Owner(thing)))
continue;
/* Toss out destroyed things */
thingflags = Flags(thing);
if ((Typeof(thing) == TYPE_THING) && (thingflags & GOING))
continue;
/* Check for matching flags */
switch (Typeof(thing)) {
case TYPE_PLAYER:
mask = parm->s_flagmasks.player_flags;
break;
case TYPE_ROOM:
mask = parm->s_flagmasks.room_flags;
break;
case TYPE_THING:
mask = parm->s_flagmasks.thing_flags;
break;
case TYPE_EXIT:
mask = parm->s_flagmasks.exit_flags;
break;
default:
mask = 0;
}
if ((thingflags & mask) != mask)
continue;
/* Check for matching name */
if (parm->s_rst_name != NULL) {
if (!string_prefix(Name(thing), parm->s_rst_name))
continue;
}
/* Check for successful evaluation */
if (parm->s_rst_eval != NULL) {
sprintf(buff, "#%d", thing);
buff2 = replace_string(BOUND_VAR, buff,
parm->s_rst_eval);
result = exec(player, cause, EV_FCHECK, buff2,
(char **)NULL, 0);
free_lbuf(buff2);
if (!*result || !xlate(result)) {
free_lbuf(result);
continue;
}
free_lbuf(result);
}
/* It passed everything. Amazing. */
olist_add(thing);
}
free_sbuf(buff);
mudstate.func_invk_ctr = save_invk_ctr;
}
static void search_mark (dbref player, int key)
{
dbref thing;
int nchanged, is_marked;
nchanged = 0;
for (thing=olist_first(); thing!=NOTHING; thing=olist_next()) {
is_marked = Marked(thing);
/* Don't bother checking if marking and already marked
* (or if unmarking and not marked) */
if (((key == SRCH_MARK) && is_marked) ||
((key == SRCH_UNMARK) && !is_marked))
continue;
/* Toggle the mark bit and update the counters */
if (key == SRCH_MARK) {
Mark(thing);
nchanged++;
} else {
Unmark(thing);
nchanged++;
}
}
notify(player,
tprintf("%d objects %smarked",
nchanged, ((key==SRCH_MARK) ? "" : "un")));
return;
}
void do_search (dbref player, dbref cause, int key, char *arg)
{
int flag, destitute;
char *buff, *outbuf, *bp;
dbref thing, from, to;
SEARCH searchparm;
if ((key != SRCH_SEARCH) && (mudconf.control_flags & CF_DBCHECK)) {
er_mark_disabled(player);
return;
}
if (!search_setup (player, arg, &searchparm))
return;
search_perform (player, cause, &searchparm);
destitute = 1;
/* If we are doing a @mark command, handle that here. */
if (key != SRCH_SEARCH) {
search_mark(player, key);
return;
}
outbuf = alloc_lbuf("do_search.outbuf");
/* room search */
if (searchparm.s_rst_type == TYPE_ROOM ||
searchparm.s_rst_type == NOTYPE) {
flag = 1;
for (thing=olist_first(); thing!=NOTHING; thing=olist_next()) {
if (Typeof(thing) != TYPE_ROOM) continue;
if (flag) {
flag = 0;
destitute = 0;
notify (player, "\nROOMS:");
}
buff = unparse_object (player, thing);
notify (player, buff);
free_lbuf(buff);
}
}
/* exit search */
if (searchparm.s_rst_type == TYPE_EXIT ||
searchparm.s_rst_type == NOTYPE) {
flag = 1;
for (thing=olist_first(); thing!=NOTHING; thing=olist_next()) {
if (Typeof(thing) != TYPE_EXIT) continue;
if (flag) {
flag = 0;
destitute = 0;
notify (player, "\nEXITS:");
}
from = Exits (thing);
to = Location (thing);
bp = outbuf;
buff = unparse_object (player, thing);
safe_str(buff, outbuf, &bp);
free_lbuf(buff);
safe_str((char *)" [from ", outbuf, &bp);
buff = unparse_object (player, from);
safe_str(((from==NOTHING) ? "NOWHERE" : buff),
outbuf, &bp);
free_lbuf(buff);
safe_str((char *)" to ", outbuf, &bp);
buff = unparse_object (player, to);
safe_str(((to==NOTHING) ? "NOWHERE" : buff),
outbuf, &bp);
free_lbuf(buff);
safe_chr(']', outbuf, &bp);
*bp = '\0';
notify (player, outbuf);
}
}
/* object search */
if (searchparm.s_rst_type == TYPE_THING ||
searchparm.s_rst_type == NOTYPE) {
flag = 1;
for (thing=olist_first(); thing!=NOTHING; thing=olist_next()) {
if (Typeof(thing) != TYPE_THING) continue;
if (flag) {
flag = 0;
destitute = 0;
notify (player, "\nOBJECTS:");
}
bp = outbuf;
buff = unparse_object (player, thing);
safe_str(buff, outbuf, &bp);
free_lbuf(buff);
safe_str((char *)" [owner: ", outbuf, &bp);
buff = unparse_object (player, Owner (thing));
safe_str(buff, outbuf, &bp);
free_lbuf(buff);
safe_chr(']', outbuf, &bp);
*bp = '\0';
notify (player, outbuf);
}
}
/* player search */
if (searchparm.s_rst_type == TYPE_PLAYER ||
searchparm.s_rst_type == NOTYPE) {
flag = 1;
for (thing=olist_first(); thing!=NOTHING; thing=olist_next()) {
if (Typeof(thing) != TYPE_PLAYER) continue;
if (flag) {
flag = 0;
destitute = 0;
notify (player, "\nPLAYERS:");
}
bp = outbuf;
buff = unparse_object (player, thing);
safe_str(buff, outbuf, &bp);
free_lbuf(buff);
if (searchparm.s_wizard) {
safe_str((char *)" [location: ",
outbuf, &bp);
buff = unparse_object (player,
Location (thing));
safe_str(buff, outbuf, &bp);
free_lbuf(buff);
safe_chr(']', outbuf, &bp);
}
*bp = '\0';
notify (player, outbuf);
}
}
/* if nothing found matching search criteria */
if (destitute) {
notify (player, "Nothing found.");
}
free_lbuf(outbuf);
olist_init();
}
/* ---------------------------------------------------------------------------
* do_markall: set or clear the mark bits of all objects in the db.
*/
void do_markall (dbref player, dbref cause, int key)
{
int i;
if (mudconf.control_flags & CF_DBCHECK) {
er_mark_disabled(player);
return;
}
if (key == MARK_SET)
Mark_all(i);
else if (key == MARK_CLEAR)
Unmark_all(i);
if (!Quiet(player)) notify(player, "Done.");
}
/* ---------------------------------------------------------------------------
* do_apply_marked: Perform a command for each marked obj in the db.
*/
void do_apply_marked (dbref player, dbref cause, int key, char *command,
char *cargs[], int ncargs)
{
char *buff;
int i;
if (mudconf.control_flags & CF_DBCHECK) {
er_mark_disabled(player);
return;
}
buff = alloc_sbuf("do_apply_marked");
DO_WHOLE_DB(i) {
if (Marked(i)) {
sprintf(buff, "#%d", i);
bind_and_queue (player, cause, command, buff,
cargs, ncargs);
}
}
free_sbuf(buff);
if (!Quiet(player)) notify(player, "Done.");
}
/* ---------------------------------------------------------------------------
* olist_init, olist_add, olist_first, olist_next: Object list management
* routines.
*/
/* olist_init: Clear and initialize the object list */
void olist_init (void)
{
OBLOCK *op, *onext;
for (op=mudstate.olist_head; op!=NULL; op=onext) {
onext = op->next;
free_lbuf(op);
}
mudstate.olist_head = NULL;
mudstate.olist_tail = NULL;
mudstate.olist_cblock = NULL;
mudstate.olist_count = 0;
mudstate.olist_citm = 0;
}
/* olist_add: Add an entry to the object list */
void olist_add (dbref item)
{
OBLOCK *op;
if (!mudstate.olist_head) {
op = (OBLOCK *)alloc_lbuf("olist_add.first");
mudstate.olist_head = mudstate.olist_tail = op;
mudstate.olist_count = 0;
op->next = NULL;
} else if (mudstate.olist_count >= OBLOCK_SIZE) {
op = (OBLOCK *)alloc_lbuf("olist_add.next");
mudstate.olist_tail->next = op;
mudstate.olist_tail = op;
mudstate.olist_count = 0;
op->next = NULL;
} else {
op = mudstate.olist_tail;
}
op->data[mudstate.olist_count++] = item;
}
/* olist_first: Return the first entry in the object list */
dbref olist_first (void)
{
if (!mudstate.olist_head)
return NOTHING;
if ((mudstate.olist_head == mudstate.olist_tail) &&
(mudstate.olist_count == 0))
return NOTHING;
mudstate.olist_cblock = mudstate.olist_head;
mudstate.olist_citm = 0;
return mudstate.olist_cblock -> data[mudstate.olist_citm++];
}
dbref olist_next (void)
{
dbref thing;
if (!mudstate.olist_cblock)
return NOTHING;
if ((mudstate.olist_cblock == mudstate.olist_tail) &&
(mudstate.olist_citm >= mudstate.olist_count))
return NOTHING;
thing = mudstate.olist_cblock->data[mudstate.olist_citm++];
if (mudstate.olist_citm >= OBLOCK_SIZE) {
mudstate.olist_cblock = mudstate.olist_cblock->next;
mudstate.olist_citm = 0;
}
return thing;
}