/* predicates.c */
#include "copyright.h"
#include <varargs.h>
#include <ctype.h>
#ifdef WANT_ANSI
#ifdef __STDC__
#include <stddef.h>
#include <stdlib.h>
#endif /* __STDC__ */
#endif /* WANT_ANSI */
#include "mudconf.h"
#include "config.h"
#include "db.h"
#include "interface.h"
#include "externs.h"
#include "match.h"
#include "command.h"
/* Wouldn't it be neat if this used varargs? */
#ifdef NEVER
char *tprintf(format, a, b, c, d, e, f)
char *format;
int a, b, c, d, e, f;
{
static char buff[10000];
sprintf(buff, format, a, b, c, d, e, f);
buff[9999] = 0;
return (buff);
}
#else
char *tprintf(va_alist)
va_dcl
{
static char buff[10000];
va_list ap;
char *format;
va_start(ap);
format = va_arg(ap, char *);
vsprintf(buff, format, ap);
va_end(ap);
buff[9999] = '\0';
return buff;
}
#endif
/* ---------------------------------------------------------------------------
* insert_first, remove_first: Insert or remove objects from lists.
*/
dbref insert_first (dbref head, dbref thing)
{
s_Next(thing, head);
return thing;
}
dbref remove_first (dbref head, dbref thing)
{
dbref prev;
if (head == thing)
return (Next(thing));
DOLIST(prev, head) {
if (Next(prev) == thing) {
s_Next(prev, Next(thing));
return head;
}
}
return head;
}
/* ---------------------------------------------------------------------------
* reverse_list: Reverse the order of members in a list.
*/
dbref reverse_list(dbref list)
{
dbref newlist, rest;
newlist = NOTHING;
while (list != NOTHING) {
rest = Next(list);
s_Next(list, newlist);
newlist = list;
list = rest;
}
return newlist;
}
/* ---------------------------------------------------------------------------
* member - indicate if thing is in list
*/
int member(dbref thing, dbref list)
{
DOLIST(list, list) {
if (list == thing)
return 1;
}
return 0;
}
/* ---------------------------------------------------------------------------
* is_number: see if string contains just a number.
*/
int is_number (char *str)
{
while (*str && isspace(*str)) str++; /* Leading spaces */
if (*str == '-') { /* Leading minus */
str++;
if (!*str) return 0; /* but not if just a minus */
}
while (*str && isdigit(*str)) str++; /* The number */
while (*str && isspace(*str)) str++; /* Leading spaces */
return (*str ? 0 : 1);
}
#ifndef STANDALONE
int could_doit(dbref player, dbref thing, int locknum)
{
char *key;
dbref aowner;
int aflags, doit;
/* no if puppet trys to get key */
if (Typeof(player) != TYPE_PLAYER) {
if (IS(thing, TYPE_THING, THING_KEY) ||
IS(thing, TYPE_EXIT, EXIT_KEY))
return 0;
}
if (Typeof(thing) != TYPE_ROOM && Location(thing) == NOTHING)
return 0;
key = atr_get(thing, locknum, &aowner, &aflags);
doit = eval_boolexp_atr(player, thing, key);
free_lbuf(key);
return doit;
}
int can_see(dbref player, dbref thing, int can_see_loc)
{
/* Sleeping players are invisible if configured */
if ((Typeof(thing) == TYPE_PLAYER) &&
!(Flags(thing) & (PLAYER_CONNECT|PUPPET)) &&
mudconf.dark_sleepers) {
return 0;
}
/* You don't see yourself or exits */
if ((player == thing) || (Typeof(thing) == TYPE_EXIT)) {
return 0;
}
/* If loc is not dark, you see it if it's not dark or you control it.
* If loc is dark, you see it if you control it. Seeing your own
* dark objects is controlled by mudconf.see_own_dark.
*/
if (can_see_loc) {
return (!Dark(thing) ||
(mudconf.see_own_dark && Examinable(player, thing)));
} else {
return (mudconf.see_own_dark && Examinable(player, thing));
}
}
static int pay_quota(dbref who, int cost)
{
dbref aowner;
int quota, aflags;
char buf[20], *quota_str;
/* determine quota */
quota = atoi(quota_str = atr_get(Owner(who), A_RQUOTA, &aowner, &aflags));
free_lbuf(quota_str);
/* enough to build? Wizards always have enough. */
quota -= cost;
if ((quota < 0) && !Wizard(who) && !Wizard(Owner(who)))
return 0;
/* dock the quota */
sprintf(buf, "%d", quota);
atr_add_raw(who, A_RQUOTA, buf);
return 1;
}
int canpayfees(dbref player, dbref who, int pennies, int quota)
{
if (!Wizard(who) && !Wizard(Owner(who)) &&
!Immortal(who) && !Immortal(Owner(who)) &&
(Pennies(Owner(who)) < pennies)) {
if (player == who) {
notify(player,
tprintf("Sorry, you don't have enough %s.",
mudconf.many_coins));
} else {
notify(player,
tprintf("Sorry, that player doesn't have enough %s."));
}
return 0;
}
if(mudconf.quotas) {
if (!pay_quota(who, quota)) {
if (player == who) {
notify(player,
"Sorry, your building contract has run out.");
} else {
notify(player,
"Sorry, that player's building contract has run out.");
}
return 0;
}
}
payfor(who, pennies);
return 1;
}
int payfor(dbref who, int cost)
{
dbref tmp;
if (Wizard(who) || Wizard(Owner(who)) ||
Immortal(who) || Immortal(Owner(who))) {
return 1;
}
who = Owner(who);
if ((tmp = Pennies(who)) >= cost) {
s_Pennies(who, tmp - cost);
return 1;
}
return 0;
}
#endif /* STANDALONE */
void add_quota(dbref who, int payment)
{
dbref aowner;
int aflags;
char buf[20], *quota;
quota = atr_get(who, A_RQUOTA, &aowner, &aflags);
sprintf(buf, "%d", atoi(quota) + payment);
free_lbuf(quota);
atr_add_raw(who, A_RQUOTA, buf);
}
void giveto(dbref who, int pennies)
{
if (Wizard(who) || Wizard(Owner(who)) ||
Immortal(who) || Immortal(Owner(who))) {
return;
}
who = Owner(who);
s_Pennies(who, Pennies(who) + pennies);
}
int ok_name(const char *name)
{
const char *cp;
for (cp=name; cp && *cp; cp++) if (!isprint(*cp)) return 0;
return (name &&
*name &&
*name != LOOKUP_TOKEN &&
*name != NUMBER_TOKEN &&
*name != NOT_TOKEN &&
!index(name, ARG_DELIMITER) &&
!index(name, AND_TOKEN) &&
!index(name, OR_TOKEN) &&
string_compare(name, "me") &&
string_compare(name, "home") &&
string_compare(name, "here"));
}
int ok_player_name(const char *name)
{
const char *cp;
if (!ok_name(name) || strlen(name) > PLAYER_NAME_LIMIT)
return 0;
for (cp=name; *cp; cp++) if (isspace(*cp)) return 0;
return 1;
}
int ok_attr_name(const char *attrname)
{
const char *scan;
if (!isalpha(*attrname)) return 0;
for (scan=attrname; *scan; scan++) {
if (isalnum(*scan)) continue;
if (!(index("-_.@#$^&~=+", *scan))) return 0;
}
return 1;
}
int ok_password(const char *password)
{
const char *scan;
if (*password == '\0')
return 0;
for (scan = password; *scan; scan++) {
if (!(isprint(*scan) && !isspace(*scan))) {
return 0;
}
}
/* Needed. Change it if you like, but be sure yours is the same. */
if ((strlen(password) == 13) &&
(password[0] == 'X') &&
(password[1] == 'X'))
return 0;
return 1;
}
#ifndef STANDALONE
/* ---------------------------------------------------------------------------
* handle_ears: Generate the 'grows ears' and 'loses ears' messages.
*/
void handle_ears (dbref thing, int could_hear, int can_hear)
{
char *buff, *bp;
if (!could_hear && can_hear) {
buff = alloc_lbuf("handle_ears.grow");
strcpy(buff, Name(thing));
if (Typeof(thing) == TYPE_EXIT) {
for (bp=buff; *bp && (*bp!=';'); bp++) ;
*bp = '\0';
}
if (Has_location(thing))
notify_all(Location(thing), thing,
tprintf("%s grows ears and can now hear.",
buff), 0);
if (Has_contents(thing))
notify_all(thing, thing,
tprintf("%s grows ears and can now hear.",
buff), 0);
free_lbuf(buff);
} else if (could_hear && !can_hear) {
buff = alloc_lbuf("handle_ears.lose");
strcpy(buff, Name(thing));
if (Typeof(thing) == TYPE_EXIT) {
for (bp=buff; *bp && (*bp!=';'); bp++) ;
*bp = '\0';
}
if (Has_location(thing))
notify_all(Location(thing), thing,
tprintf("%s loses its ears and becomes deaf.",
buff), 0);
if (Has_contents(thing))
notify_all(thing, thing,
tprintf("%s loses its ears and becomes deaf.",
buff), 0);
free_lbuf(buff);
}
}
/* for lack of better place the @switch code is here */
void do_switch (dbref player, dbref cause, int key, char *expr,
char *args[], int nargs, char *cargs[], int ncargs)
{
int any, a;
char *buff;
any = 0;
if (!expr || (nargs <= 0))
return;
if (key == SWITCH_DEFAULT) {
if (mudconf.switch_df_all)
key = SWITCH_ANY;
else
key = SWITCH_ONE;
}
/* now try a wild card match of buff with stuff in coms */
for (a=0; (a<(nargs-1)) && args[a] && args[a+1]; a+=2) {
buff = exec(player, cause, EV_STRIP|EV_FCHECK, args[a],
cargs, ncargs);
if (wild_match(buff, expr, (char **)NULL, 0)) {
if ((any == 0) || (key == SWITCH_ANY))
wait_que(player, cause, RU_ARG1_COPY,
0, NOTHING, args[a+1], cargs, ncargs);
any = 1;
}
free_lbuf(buff);
}
if ((a < nargs) && !any && args[a])
wait_que(player, cause, RU_ARG1_COPY, 0, NOTHING,
args[a], cargs, ncargs);
}
/* ---------------------------------------------------------------------------
* do_comment: Implement the @@ (comment) command. Very cpu-intensive :-)
*/
void do_comment (dbref player, dbref cause, int key)
{
}
dbref is_possess(dbref player, char *arg1)
{
dbref result1, result;
char *buff, *place, *temp, *s1, *d1;
/* If no space in the string, forget it */
place = (char *)index(arg1, ' ');
if (place == NULL)
return NOTHING;
/* Look for <name>' and <name>'s. Return failure if <name> is null. */
temp = place--;
temp++;
if (place == arg1)
return NOTHING;
if ((*place != 's') && (*place != 'S') && (*place != '\''))
return NOTHING;
if (*place != '\'') {
place--;
if ((place == arg1) || (*place != '\''))
return NOTHING;
}
/* Copy the container name to a new buffer so we can terminate it */
buff = alloc_lbuf("is_posess");
for (s1=arg1,d1=buff; *s1&&(s1<place); *d1++=(*s1++)) ;
*d1 = '\0';
/* Look for the container here and in our inventory */
init_match(player, buff, NOTYPE);
match_neighbor();
match_possession();
result1 = match_result();
free_lbuf(buff);
if (result1 == NOTHING || result1 == AMBIGUOUS)
return NOTHING;
/* If we don't control it and it is either dark or opaque, fail */
if ((Dark(result1) || (Flags(result1) & OPAQUE)) &&
!Controls(player, result1))
return NOTHING;
/* Look for the object in the container */
init_match(result1, temp, NOTYPE);
match_possession();
result = match_result();
if (result == AMBIGUOUS)
result = NOTHING;
return result;
}
#endif /* STANDALONE */
/* ---------------------------------------------------------------------------
* where_is: Returns place where obj is linked into a list.
* ie. location for players/things, source for exits, NOTHING for rooms.
*/
dbref where_is (dbref what)
{
dbref loc;
if (!Good_obj(what))
return NOTHING;
switch (Typeof(what)) {
case TYPE_PLAYER:
case TYPE_THING:
loc = Location(what);
break;
case TYPE_EXIT:
loc = Exits(what);
break;
default:
loc = NOTHING;
break;
}
return loc;
}
/* ---------------------------------------------------------------------------
* nearby: Check if thing is nearby player (in inventory, in same room, or
* IS the room.
*/
int nearby (dbref player, dbref thing)
{
int thing_loc, player_loc;
if (!Good_obj(player) || !Good_obj(thing))
return 0;
thing_loc = where_is(thing);
if (thing_loc == player)
return 1;
player_loc = where_is(player);
if ((thing_loc == player_loc) || (thing == player_loc))
return 1;
return 0;
}
/* ---------------------------------------------------------------------------
* next_exit: return next exit that is ok to see.
*/
dbref next_exit(dbref player, dbref this, int exam_here)
{
if (Typeof(this) == TYPE_ROOM)
return NOTHING;
if ((Typeof(this) != TYPE_EXIT) || exam_here)
return this;
while ((this != NOTHING) &&
(Flags(this) & DARK) &&
!Examinable(player, this))
this = Next(this);
return this;
}
#ifndef STANDALONE
/* ---------------------------------------------------------------------------
* did_it: Do something with an object
*/
void did_it(dbref player, dbref thing, int what, const char *def, int owhat,
const char *odef, int awhat, char *args[], int nargs)
{
char *d, *buff, *act, *charges;
dbref loc, aowner;
int num, aflags;
/* message to player */
if (what) {
if (*(d = atr_pget(thing, what, &aowner, &aflags))) {
buff = exec(thing, player, EV_FIGNORE, d, args, nargs);
notify(player, buff);
free_lbuf(buff);
} else if (def) {
notify(player, def);
}
free_lbuf(d);
}
/* message to neighbors */
if (owhat && Has_location(player) &&
Good_obj(loc = Location(player))) {
if (*(d = atr_pget(thing, owhat, &aowner, &aflags))) {
buff = exec(thing, player, EV_FIGNORE, d, args, nargs);
notify_except2(loc, player, player, thing,
tprintf("%s %s", Name(player), buff), 1);
free_lbuf(buff);
} else if (odef) {
notify_except2(loc, player, player, thing,
tprintf("%s %s", Name(player), odef), 1);
}
free_lbuf(d);
}
/* do the action attribute */
if (awhat) {
if (*(act = atr_pget(thing, awhat, &aowner, &aflags))) {
charges = atr_pget(thing, A_CHARGES, &aowner, &aflags);
if (*charges) {
num = atoi(charges);
if (num > 0) {
buff = alloc_sbuf("did_it.charges");
sprintf(buff, "%d", num - 1);
atr_add_raw(thing, A_CHARGES, buff);
free_sbuf(buff);
} else if (*(buff = atr_pget(thing, A_RUNOUT, &aowner, &aflags))) {
free_lbuf(act);
act = buff;
} else {
free_lbuf(act);
free_lbuf(buff);
free_lbuf(charges);
return;
}
}
free_lbuf(charges);
wait_que(thing, player, RU_ARG1_COPY, 0, NOTHING,
act, args, nargs);
}
free_lbuf(act);
}
}
/* ---------------------------------------------------------------------------
* do_verb: Command interface to did_it.
*/
void do_verb (dbref player, dbref cause, int key, char *actor_str,
char *args[], int nargs)
{
dbref actor;
int what, owhat, awhat, nxargs;
ATTR *ap;
const char *whatd, *owhatd;
char *xargs[10];
/* Look for the actor */
if (!actor_str || !*actor_str) {
notify(player, "Nothing to do.");
return;
}
actor = match_controlled(player, actor_str);
if (!Good_obj(actor))
return;
/* Get the invoker. Default to my invoker. Player must control. */
if ((nargs >= 1) && args[0] && *args[0]) {
cause = match_controlled(player, args[0]);
} else if (!Controls(player, cause)) {
notify(player, "Permission denied.");
return;
}
if (!Good_obj(cause))
return;
what = 0;
owhat = 0;
awhat = 0;
whatd = NULL;
owhatd = NULL;
nxargs = 0;
/* Get invoker message attribute */
if (nargs >= 2) {
ap = atr_str(args[1]);
if (ap)
what = ap->number;
}
/* Get invoker message default */
if ((nargs >= 3) && args[2] && *args[2]) {
whatd = args[2];
}
/* Get others message attribute */
if (nargs >= 4) {
ap = atr_str(args[3]);
if (ap)
owhat = ap->number;
}
/* Get others message default */
if ((nargs >= 5) && args[4] && *args[4]) {
owhatd = args[4];
}
/* Get action attribute */
if (nargs >= 6) {
ap = atr_str(args[5]);
if (ap)
awhat = ap->number;
}
/* Get arguments */
if (nargs >= 7) {
parse_arglist(actor, cause, args[6], '\0',
EV_STRIP_LS|EV_STRIP_TS, xargs, 10, (char **)NULL, 0);
for (nxargs=0; (nxargs<10) && xargs[nxargs]; nxargs++) ;
}
/* Go do it */
did_it(cause, actor, what, whatd, owhat, owhatd, awhat,
xargs, nxargs);
}
/* ---------------------------------------------------------------------------
* Buffer pool routines - faster allocate/free for fixed-size buffers
*/
#define POOL_MAGICNUM 0xdeadbeef
void pool_init(POOL *poolp, int poolsize)
{
poolp->pool_size = poolsize;
poolp->free_head = NULL;
poolp->chain_head = NULL;
poolp->tot_alloc = 0;
poolp->num_alloc = 0;
poolp->max_alloc = 0;
poolp->num_lost = 0;
return;
}
#ifdef PARANOID_ALLOC
static void pool_vfy (POOL *poolp, const char *tag)
{
POOLHDR *ph;
for (ph=poolp->chain_head; ph; ph=ph->next) {
if (ph->magicnum != POOL_MAGICNUM) {
if (mudstate.logging == 0) {
STARTLOG(LOG_ALWAYS,"BUG","ALLOC")
sprintf(mudstate.buffer,
"Buffer[%d] consistency check at %x, tag '%s'";
poolp->pool_size, ph, tag);
log_text(mudstate.buffer);
ENDLOG
else {
sprintf(mudstate.buffer,
"***< Buffer[%d] consistency check at %x, tag '%s' >***";
poolp->pool_size, ph, tag);
log_text(mudstate.buffer);
}
}
}
}
void pool_check(const char *tag)
{
pool_vfy(&mudstate.lbuf_pool, tag);
pool_vfy(&mudstate.mbuf_pool, tag);
pool_vfy(&mudstate.sbuf_pool, tag);
pool_vfy(&mudstate.bool_pool, tag);
pool_vfy(&mudstate.desc_pool, tag);
pool_vfy(&mudstate.qentry_pool, tag);
}
#endif
char *pool_alloc(POOL *poolp, const char *tag)
{
int *p;
char *h;
POOLHDR *ph;
#ifdef PARANOID_ALLOC
pool_check(tag);
#endif
do {
if (poolp->free_head == NULL) {
h = (char *)malloc(poolp->pool_size + sizeof(POOLHDR));
if (h == NULL) abort();
ph = (POOLHDR *)h;
ph->next = poolp->chain_head;
ph->nxtfree = NULL;
ph->magicnum = POOL_MAGICNUM;
poolp->chain_head = ph;
poolp->max_alloc++;
p = (int *)(h + sizeof(POOLHDR));
*p = POOL_MAGICNUM;
} else {
ph = (POOLHDR *)(poolp->free_head);
h = (char *)ph;
poolp->free_head = ph->nxtfree;
p = (int *)(h + sizeof(POOLHDR));
if (ph->magicnum != POOL_MAGICNUM) {
/* New buffer is corrupted. Log it always. */
if (!mudstate.logging) {
STARTLOG(LOG_ALWAYS,"BUG","ALLOC")
sprintf(mudstate.buffer,
"Alloc[%d] (tag %s) got corrupted buffer at %x, clearing freelist.",
poolp->pool_size,
tag, ph);
log_text(mudstate.buffer);
ENDLOG
} else {
sprintf(mudstate.buffer,
"***< Alloc[%d] (tag %s) got corrupted buffer at %x, clearing freelist. >***",
poolp->pool_size, tag, ph);
log_text(mudstate.buffer);
}
/* Start a new free list and record stats */
p = NULL;
poolp->free_head = NULL;
poolp->num_lost +=
(poolp->tot_alloc - poolp->num_alloc);
poolp->tot_alloc = poolp->num_alloc;
}
}
} while (p == NULL);
ph->buf_tag = (char *)tag;
poolp->tot_alloc++;
poolp->num_alloc++;
/* Log if requested. Only try to log if we are not logging, because
* there are often alloc/free pairs within a STARTLOG/ENDLOG pair,
* and attemting to log these would generate a recursive logging
* error. */
if (!mudstate.logging) {
STARTLOG(LOG_ALLOCATE,"DBG","ALLOC")
sprintf(mudstate.buffer, "Allocate[%d] at %x by %s",
poolp->pool_size, ph, tag);
log_text(mudstate.buffer);
ENDLOG
}
/* If the buffer was modified after it was last freed, log it. */
if ((*p != POOL_MAGICNUM) && (!mudstate.logging)) {
STARTLOG(LOG_PROBLEMS,"BUG","ALLOC")
sprintf(mudstate.buffer,
"Alloc[%d] (tag %s) buffer at %x modified after free.",
poolp->pool_size, tag, ph);
log_text(mudstate.buffer);
ENDLOG
}
return (char *)p;
}
void pool_free(POOL *poolp, char **buf)
{
int *ibuf;
char *h;
POOLHDR *ph;
ibuf = (int *)*buf;
h = (char *)ibuf;
h -= sizeof(POOLHDR);
ph = (POOLHDR *)h;
#ifdef PARANOID_ALLOC
pool_check(ph->buf_tag);
#endif
*ibuf = POOL_MAGICNUM;
/* Make sure the buffer header is good. If it isn't, log the error and
* throw away the buffer. */
if (ph->magicnum != POOL_MAGICNUM) {
if (!mudstate.logging) {
STARTLOG(LOG_ALWAYS,"BUG","ALLOC")
sprintf(mudstate.buffer,
"Free[%d] buffer header corrupted at %x.",
poolp->pool_size, ph);
log_text(mudstate.buffer);
ENDLOG
} else {
sprintf(mudstate.buffer,
"***< Free[%d] buffer header corrupted at %x. >***",
poolp->pool_size, ph);
log_text(mudstate.buffer);
}
poolp->num_lost++;
poolp->num_alloc--;
poolp->tot_alloc--;
return;
}
/* Log if requested. Only try to log if we are not logging, because
* there are often alloc/free pairs within a STARTLOG/ENDLOG pair,
* and attemting to log these would generate a recursive logging
* error. */
if (!mudstate.logging) {
STARTLOG(LOG_ALLOCATE,"DBG","ALLOC")
sprintf(mudstate.buffer, "Free[%d] at %x (alloc by %s)",
poolp->pool_size, ph, ph->buf_tag);
log_text(mudstate.buffer);
ENDLOG
}
/* Make sure we aren't freeing an already free buffer. If we are,
* log an error, otherwise update the pool header and stats
*/
if (ph->buf_tag == NULL) {
if (!mudstate.logging) {
STARTLOG(LOG_BUGS,"BUG","ALLOC")
sprintf(mudstate.buffer,
"Free[%d] of already free block at %x",
poolp->pool_size, ph);
log_text(mudstate.buffer);
ENDLOG
}
} else {
ph->nxtfree = poolp->free_head;
poolp->free_head = ph;
poolp->num_alloc--;
ph->buf_tag = NULL;
}
}
static char *pool_stats(POOL *poolp, const char *text)
{
char *buf;
buf = alloc_mbuf("pool_stats");
sprintf(buf, "%-15s %5d%9d%9d%9d%9d", text, poolp->pool_size,
poolp->num_alloc, poolp->max_alloc, poolp->tot_alloc,
poolp->num_lost);
return buf;
}
static void pool_trace(dbref player, POOL *poolp, const char *text)
{
POOLHDR *ph;
int numfree;
numfree = 0;
notify(player, tprintf("----- %s -----", text));
for (ph=poolp->chain_head; ph!=NULL; ph=ph->next) {
if (ph->magicnum != POOL_MAGICNUM) {
notify(player,"*** CORRUPTED BUFFER HEADER, ABORTING SCAN ***");
notify(player,
tprintf("%d free %s (before corruption)",
numfree, text));
return;
}
if (ph->buf_tag != NULL)
notify(player, ph->buf_tag);
else
numfree++;
}
notify(player, tprintf("%d free %s", numfree, text));
}
static void list_bufstat(dbref player, POOL *poolp, const char *pool_name)
{
char *buff;
buff = pool_stats(poolp, pool_name);
notify(player, buff);
free_mbuf(buff);
}
void list_bufstats(dbref player)
{
notify(player, "Buffer Stats Size InUse Total Allocs Lost");
list_bufstat(player, &mudstate.lbuf_pool, "Lbufs");
list_bufstat(player, &mudstate.mbuf_pool, "Mbufs");
list_bufstat(player, &mudstate.sbuf_pool, "Sbufs");
list_bufstat(player, &mudstate.bool_pool, "Bools");
list_bufstat(player, &mudstate.desc_pool, "Descs");
list_bufstat(player, &mudstate.qentry_pool, "Qentries");
}
void list_buftrace(dbref player)
{
pool_trace(player,&mudstate.lbuf_pool, "Lbufs");
pool_trace(player,&mudstate.mbuf_pool, "Mbufs");
pool_trace(player,&mudstate.sbuf_pool, "Sbufs");
pool_trace(player,&mudstate.bool_pool, "Bools");
pool_trace(player,&mudstate.desc_pool, "Descs");
pool_trace(player,&mudstate.qentry_pool, "Qentries");
}
#endif /* STANDALONE */