/* conf.c: set up configuration information and static data */
#include <math.h>
#include "autoconf.h"
#include "copyright.h"
#ifndef lint
static char RCSid[] = "$Id: conf.c,v 1.10 1995/03/20 23:59:54 ambar Exp $";
USE(RCSid);
#endif
#include "externs.h"
#include "interface.h"
#include "command.h"
#include "htab.h"
#include "alloc.h"
#include "attrs.h"
#include "flags.h"
#include "udb_defs.h"
/* ---------------------------------------------------------------------------
* CONFPARM: Data used to find fields in CONFDATA.
*/
typedef struct confparm CONF;
struct confparm {
char *pname; /* parm name */
int (*interpreter) (); /* routine to interp parameter */
int flags; /* control flags */
int *loc; /* where to store value */
void *extra; /* extra data for interpreter */
};
/* ---------------------------------------------------------------------------
* External symbols.
*/
CONFDATA mudconf;
STATEDATA mudstate;
#ifndef STANDALONE
extern NAMETAB logdata_nametab[];
extern NAMETAB logoptions_nametab[];
extern NAMETAB access_nametab[];
extern NAMETAB attraccess_nametab[];
extern NAMETAB list_names[];
extern NAMETAB sigactions_nametab[];
extern CONF conftable[];
#endif
/* ---------------------------------------------------------------------------
* cf_init: Initialize mudconf to default values.
*/
void
NDECL(cf_init)
{
#ifndef STANDALONE
int i;
strcpy(mudconf.indb, "tinymush.db");
strcpy(mudconf.outdb, "");
strcpy(mudconf.crashdb, "");
strcpy(mudconf.gdbm, "");
strcpy(mudconf.status_file, "shutdown.status");
mudconf.port = 6250;
mudconf.init_size = 1000;
mudconf.use_global_aconn = 1;
mudconf.num_guests = -1;
for (i = 0; i < MAX_GUESTS; i++)
mudconf.guest_chars[i] = -1;
strcpy(mudconf.guest_file, "guest.txt");
strcpy(mudconf.conn_file, "connect.txt");
strcpy(mudconf.creg_file, "register.txt");
strcpy(mudconf.regf_file, "create_reg.txt");
strcpy(mudconf.motd_file, "motd.txt");
strcpy(mudconf.wizmotd_file, "wizmotd.txt");
strcpy(mudconf.quit_file, "quit.txt");
strcpy(mudconf.down_file, "down.txt");
strcpy(mudconf.full_file, "full.txt");
strcpy(mudconf.site_file, "badsite.txt");
strcpy(mudconf.crea_file, "newuser.txt");
#ifdef PUEBLO_SUPPORT
strcpy(mudconf.htmlconn_file, "htmlconn.txt");
#endif /* PUEBLO_SUPPORT */
strcpy(mudconf.help_file, "help.txt");
strcpy(mudconf.help_indx, "help.indx");
strcpy(mudconf.news_file, "news.txt");
strcpy(mudconf.news_indx, "news.indx");
strcpy(mudconf.whelp_file, "wizhelp.txt");
strcpy(mudconf.whelp_indx, "wizhelp.indx");
strcpy(mudconf.motd_msg, "");
strcpy(mudconf.wizmotd_msg, "");
strcpy(mudconf.downmotd_msg, "");
strcpy(mudconf.fullmotd_msg, "");
strcpy(mudconf.dump_msg, "");
strcpy(mudconf.postdump_msg, "");
#ifdef PUEBLO_SUPPORT
strcpy(mudconf.pueblo_msg, "</xch_mudtext><img xch_mode=html><tt>");
#endif /* PUEBLO_SUPPORT */
mudconf.name_spaces = 1;
mudconf.fork_dump = 1;
mudconf.fork_vfork = 0;
mudconf.sig_action = SA_DFLT;
mudconf.paranoid_alloc = 0;
mudconf.max_players = -1;
mudconf.garbage_chunk = 3;
mudconf.dump_interval = 3600;
mudconf.check_interval = 600;
mudconf.dump_offset = 0;
mudconf.check_offset = 300;
mudconf.idle_timeout = 3600;
mudconf.conn_timeout = 120;
mudconf.idle_interval = 60;
mudconf.retry_limit = 3;
mudconf.output_limit = 16384;
mudconf.paycheck = 0;
mudconf.paystart = 0;
mudconf.paylimit = 10000;
mudconf.start_quota = mudconf.start_room_quota = mudconf.start_exit_quota
= mudconf.start_thing_quota = mudconf.start_player_quota = 20;
mudconf.payfind = 0;
mudconf.digcost = 10;
mudconf.linkcost = 1;
mudconf.opencost = 1;
mudconf.createmin = 10;
mudconf.createmax = 505;
mudconf.killmin = 10;
mudconf.killmax = 100;
mudconf.killguarantee = 100;
mudconf.robotcost = 1000;
mudconf.pagecost = 10;
mudconf.searchcost = 100;
mudconf.waitcost = 10;
mudconf.machinecost = 64;
mudconf.building_limit = 50000;
mudconf.exit_quota = 1;
mudconf.player_quota = 1;
mudconf.room_quota = 1;
mudconf.thing_quota = 1;
mudconf.queuemax = 100;
mudconf.queue_chunk = 10;
mudconf.active_q_chunk = 10;
mudconf.sacfactor = 5;
mudconf.sacadjust = -1;
mudconf.use_hostname = 1;
mudconf.recycle = 1;
mudconf.quotas = 0;
mudconf.typed_quotas = 0;
mudconf.ex_flags = 1;
mudconf.robot_speak = 1;
mudconf.clone_copy_cost = 0;
mudconf.pub_flags = 1;
mudconf.quiet_look = 1;
mudconf.exam_public = 1;
mudconf.read_rem_desc = 0;
mudconf.read_rem_name = 0;
mudconf.sweep_dark = 0;
mudconf.player_listen = 0;
mudconf.quiet_whisper = 1;
mudconf.dark_sleepers = 1;
mudconf.see_own_dark = 1;
mudconf.idle_wiz_dark = 0;
mudconf.pemit_players = 0;
mudconf.pemit_any = 0;
mudconf.match_mine = 0;
mudconf.match_mine_pl = 0;
mudconf.switch_df_all = 1;
mudconf.fascist_tport = 0;
mudconf.terse_look = 1;
mudconf.terse_contents = 1;
mudconf.terse_exits = 1;
mudconf.terse_movemsg = 1;
mudconf.trace_topdown = 1;
mudconf.trace_limit = 200;
mudconf.safe_unowned = 0;
mudconf.parent_control = 0;
mudconf.wiz_obey_linklock = 0;
mudconf.local_masters = 1;
mudconf.req_cmds_flag = 1;
mudconf.parent_zones = 1;
mudconf.fmt_contents = 1;
mudconf.fmt_exits = 1;
mudconf.ansi_colors = 0;
mudconf.safer_passwords = 0;
/* -- ??? Running SC on a non-SC DB may cause problems */
mudconf.space_compress = 1;
mudconf.start_room = 0;
mudconf.start_home = NOTHING;
mudconf.default_home = NOTHING;
mudconf.master_room = NOTHING;
mudconf.player_parent = NOTHING;
mudconf.room_parent = NOTHING;
mudconf.exit_parent = NOTHING;
mudconf.thing_parent = NOTHING;
mudconf.player_flags.word1 = 0;
mudconf.player_flags.word2 = 0;
mudconf.room_flags.word1 = 0;
mudconf.room_flags.word2 = 0;
mudconf.exit_flags.word1 = 0;
mudconf.exit_flags.word2 = 0;
mudconf.thing_flags.word1 = 0;
mudconf.thing_flags.word2 = 0;
mudconf.robot_flags.word1 = ROBOT;
mudconf.robot_flags.word2 = 0;
mudconf.vattr_flags = AF_ODARK;
mudconf.abort_on_bug = 0;
mudconf.rwho_transmit = 0;
strcpy(mudconf.mud_name, "TinyMUSH");
strcpy(mudconf.rwho_host, "139.78.1.15"); /* riemann.math.okstate.edu */
strcpy(mudconf.rwho_pass, "get_your_own");
mudconf.rwho_info_port = 6888;
mudconf.rwho_data_port = 6889;
mudconf.rwho_interval = 241;
strcpy(mudconf.one_coin, "penny");
strcpy(mudconf.many_coins, "pennies");
mudconf.timeslice = 1000;
mudconf.cmd_quota_max = 100;
mudconf.cmd_quota_incr = 1;
mudconf.max_cmdsecs = 120;
mudconf.control_flags = 0xffffffff; /* Everything for now... */
mudconf.control_flags &= ~CF_GODMONITOR; /* Except for monitoring... */
mudconf.log_options = LOG_ALWAYS | LOG_BUGS | LOG_SECURITY |
LOG_NET | LOG_LOGIN | LOG_DBSAVES | LOG_CONFIGMODS |
LOG_SHOUTS | LOG_STARTUP | LOG_WIZARD |
LOG_PROBLEMS | LOG_PCREATES | LOG_TIMEUSE;
mudconf.log_info = LOGOPT_TIMESTAMP | LOGOPT_LOC;
mudconf.markdata[0] = 0x01;
mudconf.markdata[1] = 0x02;
mudconf.markdata[2] = 0x04;
mudconf.markdata[3] = 0x08;
mudconf.markdata[4] = 0x10;
mudconf.markdata[5] = 0x20;
mudconf.markdata[6] = 0x40;
mudconf.markdata[7] = 0x80;
mudconf.func_nest_lim = 50;
mudconf.func_invk_lim = 2500;
mudconf.ntfy_nest_lim = 20;
mudconf.lock_nest_lim = 20;
mudconf.parent_nest_lim = 10;
mudconf.cache_depth = CACHE_DEPTH;
mudconf.cache_width = CACHE_WIDTH;
mudconf.cache_names = 1;
mudconf.cache_steal_dirty = 0;
mudstate.initializing = 0;
mudstate.panicking = 0;
mudstate.dumping = 0;
mudstate.logging = 0;
mudstate.epoch = 0;
mudstate.generation = 0;
mudstate.reboot_nums = 0;
mudstate.curr_player = NOTHING;
mudstate.curr_enactor = NOTHING;
mudstate.curr_cmd = (char *) "< none >";
mudstate.shutdown_flag = 0;
mudstate.rwho_on = 0;
mudstate.attr_next = A_USER_START;
mudstate.debug_cmd = (char *) "< init >";
strcpy(mudstate.doing_hdr, "Doing");
mudstate.access_list = NULL;
mudstate.suspect_list = NULL;
mudstate.qfirst = NULL;
mudstate.qlast = NULL;
mudstate.qlfirst = NULL;
mudstate.qllast = NULL;
mudstate.qwait = NULL;
mudstate.qsemfirst = NULL;
mudstate.qsemlast = NULL;
mudstate.badname_head = NULL;
mudstate.iter_alist.data = NULL;
mudstate.iter_alist.len = 0;
mudstate.iter_alist.next = NULL;
mudstate.mod_alist = NULL;
mudstate.mod_size = 0;
mudstate.mod_al_id = NOTHING;
mudstate.olist_head = NULL;
mudstate.olist_tail = NULL;
mudstate.olist_cblock = NULL;
mudstate.olist_count = 0;
mudstate.olist_citm = 0;
mudstate.min_size = 0;
mudstate.db_top = 0;
mudstate.db_size = 0;
mudstate.freelist = NOTHING;
mudstate.markbits = NULL;
mudstate.func_nest_lev = 0;
mudstate.func_invk_ctr = 0;
mudstate.ntfy_nest_lev = 0;
mudstate.lock_nest_lev = 0;
mudstate.inpipe = 0;
mudstate.pout = NULL;
mudstate.poutnew = NULL;
mudstate.poutbufc = NULL;
mudstate.poutobj = NOTHING;
for (i = 0; i < MAX_GLOBAL_REGS; i++)
mudstate.global_regs[i] = NULL;
#else /* match for #ifndef STANDALONE */
mudconf.paylimit = 10000;
mudconf.digcost = 10;
mudconf.opencost = 1;
mudconf.robotcost = 1000;
mudconf.createmin = 5;
mudconf.createmax = 505;
mudconf.sacfactor = 5;
mudconf.sacadjust = -1;
mudconf.room_quota = 1;
mudconf.exit_quota = 1;
mudconf.thing_quota = 1;
mudconf.player_quota = 1;
mudconf.start_room = 0;
mudconf.start_home = NOTHING;
mudconf.default_home = NOTHING;
mudconf.vattr_flags = AF_ODARK;
mudconf.log_options = 0xffffffff;
mudconf.log_info = 0;
mudconf.markdata[0] = 0x01;
mudconf.markdata[1] = 0x02;
mudconf.markdata[2] = 0x04;
mudconf.markdata[3] = 0x08;
mudconf.markdata[4] = 0x10;
mudconf.markdata[5] = 0x20;
mudconf.markdata[6] = 0x40;
mudconf.markdata[7] = 0x80;
mudconf.ntfy_nest_lim = 20;
mudconf.cache_steal_dirty = 1;
mudstate.logging = 0;
mudstate.attr_next = A_USER_START;
mudstate.iter_alist.data = NULL;
mudstate.iter_alist.len = 0;
mudstate.iter_alist.next = NULL;
mudstate.mod_alist = NULL;
mudstate.mod_size = 0;
mudstate.mod_al_id = NOTHING;
mudstate.min_size = 0;
mudstate.db_top = 0;
mudstate.db_size = 0;
mudstate.freelist = NOTHING;
mudstate.markbits = NULL;
#endif /* STANDALONE */
}
#ifndef STANDALONE
/* ---------------------------------------------------------------------------
* cf_log_notfound: Log a 'parameter not found' error.
*/
void
cf_log_notfound(player, cmd, thingname, thing)
dbref player;
char *cmd, *thing;
const char *thingname;
{
char *buff;
if (mudstate.initializing) {
STARTLOG(LOG_STARTUP, "CNF", "NFND")
buff = alloc_lbuf("cf_log_notfound.LOG");
sprintf(buff, "%s: %s %s not found",
cmd, thingname, thing);
log_text(buff);
free_lbuf(buff);
ENDLOG
} else {
buff = alloc_lbuf("cf_log_notfound");
sprintf(buff, "%s %s not found", thingname, thing);
notify(player, buff);
free_lbuf(buff);
}
}
/* ---------------------------------------------------------------------------
* cf_log_syntax: Log a syntax error.
*/
void
cf_log_syntax(player, cmd, template, arg)
dbref player;
char *cmd, *arg;
const char *template;
{
char *buff;
if (mudstate.initializing) {
STARTLOG(LOG_STARTUP, "CNF", "SYNTX")
buff = alloc_lbuf("cf_log_syntax.LOG");
sprintf(buff, template, arg);
log_text(cmd);
log_text((char *) ": ");
log_text(buff);
free_lbuf(buff);
ENDLOG
} else {
buff = alloc_lbuf("cf_log_syntax");
sprintf(buff, template, arg);
notify(player, buff);
free_lbuf(buff);
}
}
/* ---------------------------------------------------------------------------
* cf_status_from_succfail: Return command status from succ and fail info
*/
int
cf_status_from_succfail(player, cmd, success, failure)
dbref player;
char *cmd;
int success, failure;
{
char *buff;
/* If any successes, return SUCCESS(0) if no failures or
PARTIAL_SUCCESS(1) if any failures. */
if (success > 0)
return ((failure == 0) ? 0 : 1);
/* No successes. If no failures indicate nothing done.
Always return FAILURE(-1) */
if (failure == 0) {
if (mudstate.initializing) {
STARTLOG(LOG_STARTUP, "CNF", "NDATA")
buff = alloc_lbuf("cf_status_from_succfail.LOG");
sprintf(buff, "%s: Nothing to set", cmd);
log_text(buff);
free_lbuf(buff);
ENDLOG
} else {
notify(player, "Nothing to set");
}
}
return -1;
}
/* ---------------------------------------------------------------------------
* cf_int: Set integer parameter.
*/
CF_HAND(cf_int)
{
/* Copy the numeric value to the parameter */
sscanf(str, "%d", vp);
return 0;
}
/* ---------------------------------------------------------------------------
* cf_bool: Set boolean parameter.
*/
NAMETAB bool_names[] =
{
{(char *) "true", 1, 0, 1},
{(char *) "false", 1, 0, 0},
{(char *) "yes", 1, 0, 1},
{(char *) "no", 1, 0, 0},
{(char *) "1", 1, 0, 1},
{(char *) "0", 1, 0, 0},
{NULL, 0, 0, 0}};
CF_HAND(cf_bool)
{
*vp = search_nametab(GOD, bool_names, str);
if (*vp == -1)
*vp = 0;
return 0;
}
/* ---------------------------------------------------------------------------
* cf_option: Select one option from many choices.
*/
CF_HAND(cf_option)
{
int i;
i = search_nametab(GOD, (NAMETAB *) extra, str);
if (i == -1) {
cf_log_notfound(player, cmd, "Value", str);
return -1;
}
*vp = i;
return 0;
}
/* ---------------------------------------------------------------------------
* cf_string: Set string parameter.
*/
CF_HAND(cf_string)
{
int retval;
char *buff;
/* Copy the string to the buffer if it is not too big */
retval = 0;
if (strlen(str) >= (long) extra) {
str[(long) extra - 1] = '\0';
if (mudstate.initializing) {
STARTLOG(LOG_STARTUP, "CNF", "NFND")
buff = alloc_lbuf("cf_string.LOG");
sprintf(buff, "%s: String truncated", cmd);
log_text(buff);
free_lbuf(buff);
ENDLOG
} else {
notify(player, "String truncated");
}
retval = 1;
}
strcpy((char *) vp, str);
return retval;
}
/* ---------------------------------------------------------------------------
* cf_alias: define a generic hash table alias.
*/
CF_HAND(cf_alias)
{
char *alias, *orig;
int *cp;
alias = strtok(str, " \t=,");
orig = strtok(NULL, " \t=,");
cp = hashfind(orig, (HASHTAB *) vp);
if (cp == NULL) {
cf_log_notfound(player, cmd, "Entry", orig);
return -1;
}
hashadd(alias, cp, (HASHTAB *) vp);
return 0;
}
/* ---------------------------------------------------------------------------
* cf_flagalias: define a flag alias.
*/
CF_HAND(cf_flagalias)
{
char *alias, *orig;
int *cp, success;
success = 0;
alias = strtok(str, " \t=,");
orig = strtok(NULL, " \t=,");
cp = hashfind(orig, &mudstate.flags_htab);
if (cp != NULL) {
hashadd(alias, cp, &mudstate.flags_htab);
success++;
}
if (!success)
cf_log_notfound(player, cmd, "Flag", orig);
return ((success > 0) ? 0 : -1);
}
/* ---------------------------------------------------------------------------
* cf_or_in_bits: OR in bits from namelist to a word.
*/
CF_HAND(cf_or_in_bits)
{
char *sp;
int f, success, failure;
/* Walk through the tokens */
success = failure = 0;
sp = strtok(str, " \t");
while (sp != NULL) {
/* Set the appropriate bit */
f = search_nametab(GOD, (NAMETAB *) extra, sp);
if (f != -1) {
*vp |= f;
success++;
} else {
cf_log_notfound(player, cmd, "Entry", sp);
failure++;
}
/* Get the next token */
sp = strtok(NULL, " \t");
}
return cf_status_from_succfail(player, cmd, success, failure);
}
/* ---------------------------------------------------------------------------
* cf_modify_bits: set or clear bits in a flag word from a namelist.
*/
CF_HAND(cf_modify_bits)
{
char *sp;
int f, negate, success, failure;
/* Walk through the tokens */
success = failure = 0;
sp = strtok(str, " \t");
while (sp != NULL) {
/* Check for negation */
negate = 0;
if (*sp == '!') {
negate = 1;
sp++;
}
/* Set or clear the appropriate bit */
f = search_nametab(GOD, (NAMETAB *) extra, sp);
if (f != -1) {
if (negate)
*vp &= ~f;
else
*vp |= f;
success++;
} else {
cf_log_notfound(player, cmd, "Entry", sp);
failure++;
}
/* Get the next token */
sp = strtok(NULL, " \t");
}
return cf_status_from_succfail(player, cmd, success, failure);
}
/* ---------------------------------------------------------------------------
* cf_set_bits: Clear flag word and then set specified bits from namelist.
*/
CF_HAND(cf_set_bits)
{
char *sp;
int f, success, failure;
/* Walk through the tokens */
success = failure = 0;
*vp = 0;
sp = strtok(str, " \t");
while (sp != NULL) {
/* Set the appropriate bit */
f = search_nametab(GOD, (NAMETAB *) extra, sp);
if (f != -1) {
*vp |= f;
success++;
} else {
cf_log_notfound(player, cmd, "Entry", sp);
failure++;
}
/* Get the next token */
sp = strtok(NULL, " \t");
}
return cf_status_from_succfail(player, cmd, success, failure);
}
/* ---------------------------------------------------------------------------
* cf_set_flags: Clear flag word and then set from a flags htab.
*/
CF_HAND(cf_set_flags)
{
char *sp;
FLAGENT *fp;
FLAGSET *fset;
int success, failure;
/* Walk through the tokens */
success = failure = 0;
sp = strtok(str, " \t");
fset = (FLAGSET *) vp;
while (sp != NULL) {
/* Set the appropriate bit */
fp = (FLAGENT *) hashfind(sp, &mudstate.flags_htab);
if (fp != NULL) {
if (success == 0) {
(*fset).word1 = 0;
(*fset).word2 = 0;
}
if (fp->flagflag & FLAG_EXT)
(*fset).word2 |= fp->flagvalue;
else
(*fset).word1 |= fp->flagvalue;
success++;
} else {
cf_log_notfound(player, cmd, "Entry", sp);
failure++;
}
/* Get the next token */
sp = strtok(NULL, " \t");
}
if ((success == 0) && (failure == 0)) {
(*fset).word1 = 0;
(*fset).word2 = 0;
return 0;
}
if (success > 0)
return ((failure == 0) ? 0 : 1);
return -1;
}
/* ---------------------------------------------------------------------------
* cf_badname: Disallow use of player name/alias.
*/
CF_HAND(cf_badname)
{
if ((long) extra)
badname_remove(str);
else
badname_add(str);
return 0;
}
/* ---------------------------------------------------------------------------
* sane_inet_addr: inet_addr() does not necessarily do reasonable checking
* for sane syntax. On certain operating systems, if passed less than four
* octets, it will cause a segmentation violation. This is unfriendly.
* We take steps here to deal with it.
*/
static unsigned long sane_inet_addr(str)
char *str;
{
int i;
char *p;
p = str;
for (i = 1; (p = (char *) index(p, '.')) != NULL; i++, p++)
;
if (i < 4)
return -1;
else
return inet_addr(str);
}
/* ---------------------------------------------------------------------------
* cf_site: Update site information
*/
CF_HANDP(cf_site)
{
SITE *site, *last, *head;
char *addr_txt, *mask_txt, *p;
struct in_addr addr_num, mask_num;
int i, mask_bits;
if ((mask_txt = (char *) index(str, '/')) == NULL) {
/* Standard IP range and netmask notation. */
addr_txt = strtok(str, " \t=,");
if (addr_txt)
mask_txt = strtok(NULL, " \t=,");
if (!addr_txt || !*addr_txt || !mask_txt || !*mask_txt) {
cf_log_syntax(player, cmd, "Missing host address or mask.",
(char *) "");
return -1;
}
if ((addr_num.s_addr = sane_inet_addr(addr_txt)) == -1) {
cf_log_syntax(player, cmd, "Malformed host address: %s", addr_txt);
return -1;
}
if ((mask_num.s_addr = sane_inet_addr(mask_txt)) == -1) {
cf_log_syntax(player, cmd, "Malformed mask address: %s", mask_txt);
return -1;
}
} else {
/* RFC 1517, 1518, 1519, 1520: CIDR IP prefix notation */
addr_txt = str;
*mask_txt++ = '\0';
mask_bits = atoi(mask_txt);
if ((mask_bits > 32) || (mask_bits < 0)) {
cf_log_syntax(player, cmd,
"Mask bits (%d) in CIDR IP prefix out of range.",
mask_bits);
return -1;
} else {
mask_num.s_addr = pow(2, 32) - pow(2, 32 - mask_bits);
}
if ((addr_num.s_addr = sane_inet_addr(addr_txt)) == -1) {
cf_log_syntax(player, cmd, "Malformed host address: %s", addr_txt);
return -1;
}
}
head = (SITE *) * vp;
/* Parse the access entry and allocate space for it */
if (!(site = (SITE *) XMALLOC(sizeof(SITE), "cf_site")))
return -1;
/* Initialize the site entry */
site->address.s_addr = addr_num.s_addr;
site->mask.s_addr = mask_num.s_addr;
site->flag = (long) extra;
site->next = NULL;
/* Link in the entry. Link it at the start if not initializing, at
* the end if initializing. This is so that entries in the config
* file are processed as you would think they would be, while entries
* made while running are processed first.
*/
if (mudstate.initializing) {
if (head == NULL) {
*vp = (int *) site;
} else {
for (last = head; last->next; last = last->next);
last->next = site;
}
} else {
site->next = head;
*vp = (int *) site;
}
return 0;
}
/* ---------------------------------------------------------------------------
* cf_cf_access: Set access on config directives
*/
CF_HAND(cf_cf_access)
{
CONF *tp;
char *ap;
for (ap = str; *ap && !isspace(*ap); ap++);
if (*ap)
*ap++ = '\0';
for (tp = conftable; tp->pname; tp++) {
if (!strcmp(tp->pname, str)) {
return (cf_modify_bits(&tp->flags, ap, extra,
player, cmd));
}
}
cf_log_notfound(player, cmd, "Config directive", str);
return -1;
}
/* ---------------------------------------------------------------------------
* cf_include: Read another config file. Only valid during startup.
*/
CF_HAND(cf_include)
{
FILE *fp;
char *cp, *ap, *zp, *buf;
extern int FDECL(cf_set, (char *, char *, dbref));
if (!mudstate.initializing)
return -1;
fp = fopen(str, "r");
if (fp == NULL) {
cf_log_notfound(player, cmd, "Config file", str);
return -1;
}
buf = alloc_lbuf("cf_include");
fgets(buf, LBUF_SIZE, fp);
while (!feof(fp)) {
cp = buf;
if (*cp == '#') {
fgets(buf, LBUF_SIZE, fp);
continue;
}
/* Not a comment line. Strip off the NL and any characters
* following it. Then, split the line into the command and
* argument portions (separated by a space). Also, trim off
* the trailing comment, if any (delimited by #)
*/
for (cp = buf; *cp && *cp != '\n'; cp++);
*cp = '\0'; /* strip \n */
for (cp = buf; *cp && isspace(*cp); cp++); /* strip spaces */
for (ap = cp; *ap && !isspace(*ap); ap++); /* skip over command */
if (*ap)
*ap++ = '\0'; /* trim command */
for (; *ap && isspace(*ap); ap++); /* skip spaces */
for (zp = ap; *zp && (*zp != '#'); zp++); /* find comment */
if (*zp)
*zp = '\0'; /* zap comment */
for (zp = zp - 1; zp >= ap && isspace(*zp); zp--)
*zp = '\0'; /* zap trailing spcs */
cf_set(cp, ap, player);
fgets(buf, LBUF_SIZE, fp);
}
free_lbuf(buf);
fclose(fp);
return 0;
}
/* ---------------------------------------------------------------------------
* cf_dbref_list: Set a list of dbref values. extra is a pointer
* to an "int" which will contain the number of dbrefs found.
*/
CF_HAND(cf_dbref_list)
{
char *tmp = strtok(str, " \t");
int *num = (int *) extra;
*num = 0;
while (tmp) {
vp[*num] = atoi(tmp);
(*num)++;
tmp = strtok(NULL, " \t");
}
return 0;
}
extern CF_HDCL(cf_access);
extern CF_HDCL(cf_cmd_alias);
extern CF_HDCL(cf_acmd_access);
extern CF_HDCL(cf_attr_access);
extern CF_HDCL(cf_ntab_access);
extern CF_HDCL(cf_func_access);
/* ---------------------------------------------------------------------------
* conftable: Table for parsing the configuration file.
*/
CONF conftable[] =
{
{"abort_on_bug", cf_bool, CA_DISABLED,
&mudconf.abort_on_bug, 0},
{"access", cf_access, CA_GOD,
NULL, access_nametab},
{"alias", cf_cmd_alias, CA_GOD,
(int *) &mudstate.command_htab, 0},
{"ansi_colors", cf_bool, CA_GOD,
&mudconf.ansi_colors, 0},
{"attr_access", cf_attr_access, CA_GOD,
NULL, attraccess_nametab},
{"attr_alias", cf_alias, CA_GOD,
(int *) &mudstate.attr_name_htab, 0},
{"attr_cmd_access", cf_acmd_access, CA_GOD,
NULL, access_nametab},
{"bad_name", cf_badname, CA_GOD,
NULL, 0},
{"badsite_file", cf_string, CA_DISABLED,
(int *) mudconf.site_file, (void *) SBUF_SIZE},
{"building_limit", cf_int, CA_GOD,
&mudconf.building_limit, 0},
{"cache_depth", cf_int, CA_DISABLED,
&mudconf.cache_depth, 0},
{"cache_names", cf_bool, CA_DISABLED,
&mudconf.cache_names, 0},
{"cache_steal_dirty", cf_bool, CA_GOD,
&mudconf.cache_steal_dirty, 0},
{"cache_width", cf_int, CA_DISABLED,
&mudconf.cache_width, 0},
{"check_interval", cf_int, CA_GOD,
&mudconf.check_interval, 0},
{"check_offset", cf_int, CA_GOD,
&mudconf.check_offset, 0},
{"clone_copies_cost", cf_bool, CA_GOD,
&mudconf.clone_copy_cost, 0},
{"command_quota_increment", cf_int, CA_GOD,
&mudconf.cmd_quota_incr, 0},
{"command_quota_max", cf_int, CA_GOD,
&mudconf.cmd_quota_max, 0},
{"config_access", cf_cf_access, CA_GOD,
NULL, access_nametab},
{"conn_timeout", cf_int, CA_GOD,
&mudconf.conn_timeout, 0},
{"connect_file", cf_string, CA_DISABLED,
(int *) mudconf.conn_file, (void *) SBUF_SIZE},
{"connect_reg_file", cf_string, CA_DISABLED,
(int *) mudconf.creg_file, (void *) SBUF_SIZE},
{"crash_database", cf_string, CA_DISABLED,
(int *) mudconf.crashdb, (void *) PBUF_SIZE},
{"create_max_cost", cf_int, CA_GOD,
&mudconf.createmax, 0},
{"create_min_cost", cf_int, CA_GOD,
&mudconf.createmin, 0},
{"dark_sleepers", cf_bool, CA_GOD,
&mudconf.dark_sleepers, 0},
{"default_home", cf_int, CA_GOD,
&mudconf.default_home, 0},
{"dig_cost", cf_int, CA_GOD,
&mudconf.digcost, 0},
{"down_file", cf_string, CA_DISABLED,
(int *) mudconf.down_file, (void *) SBUF_SIZE},
{"down_motd_message", cf_string, CA_GOD,
(int *) mudconf.downmotd_msg, (void *) GBUF_SIZE},
{"dump_interval", cf_int, CA_GOD,
&mudconf.dump_interval, 0},
{"dump_message", cf_string, CA_GOD,
(int *) mudconf.dump_msg, (void *) PBUF_SIZE},
{"postdump_message", cf_string, CA_GOD,
(int *) mudconf.postdump_msg, (void *) PBUF_SIZE},
#ifdef PUEBLO_SUPPORT
{"html_connect_file", cf_string, CA_DISABLED,
(int *) mudconf.htmlconn_file, (void *) SBUF_SIZE},
{"pueblo_message", cf_string, CA_GOD,
(int *) mudconf.pueblo_msg, (void *) GBUF_SIZE},
#endif /* PUEBLO_SUPPORT */
{"dump_offset", cf_int, CA_GOD,
&mudconf.dump_offset, 0},
{"earn_limit", cf_int, CA_GOD,
&mudconf.paylimit, 0},
{"examine_flags", cf_bool, CA_GOD,
&mudconf.ex_flags, 0},
{"examine_public_attrs", cf_bool, CA_GOD,
&mudconf.exam_public, 0},
{"exit_flags", cf_set_flags, CA_GOD,
(int *) &mudconf.exit_flags, 0},
{"exit_parent", cf_int, CA_GOD,
&mudconf.exit_parent, 0},
{"exit_quota", cf_int, CA_GOD,
&mudconf.exit_quota, 0},
{"fascist_teleport", cf_bool, CA_GOD,
&mudconf.fascist_tport, 0},
{"find_money_chance", cf_int, CA_GOD,
&mudconf.payfind, 0},
{"flag_alias", cf_flagalias, CA_GOD,
NULL, 0},
{"forbid_site", cf_site, CA_GOD,
(int *) &mudstate.access_list, (void *) H_FORBIDDEN},
{"fork_dump", cf_bool, CA_GOD,
&mudconf.fork_dump, 0},
{"fork_vfork", cf_bool, CA_GOD,
&mudconf.fork_vfork, 0},
{"format_contents", cf_bool, CA_GOD,
&mudconf.fmt_contents, 0},
{"format_exits", cf_bool, CA_GOD,
&mudconf.fmt_exits, 0},
{"full_file", cf_string, CA_DISABLED,
(int *) mudconf.full_file, (void *) SBUF_SIZE},
{"full_motd_message", cf_string, CA_GOD,
(int *) mudconf.fullmotd_msg, (void *) GBUF_SIZE},
{"function_access", cf_func_access, CA_GOD,
NULL, access_nametab},
{"function_alias", cf_alias, CA_GOD,
(int *) &mudstate.func_htab, 0},
{"function_invocation_limit", cf_int, CA_GOD,
&mudconf.func_invk_lim, 0},
{"function_recursion_limit", cf_int, CA_GOD,
&mudconf.func_nest_lim, 0},
{"garbage_chunk", cf_int, CA_GOD,
&mudconf.garbage_chunk, 0},
{"gdbm_database", cf_string, CA_DISABLED,
(int *) mudconf.gdbm, (void *) PBUF_SIZE},
{"good_name", cf_badname, CA_GOD,
NULL, (void *) 1},
{"guests", cf_dbref_list, CA_GOD,
mudconf.guest_chars, &mudconf.num_guests},
{"guest_file", cf_string, CA_DISABLED,
(int *) mudconf.guest_file, (void *) SBUF_SIZE},
{"guest_site", cf_site, CA_GOD,
(int *) &mudstate.access_list, (void *) H_GUEST},
{"help_file", cf_string, CA_DISABLED,
(int *) mudconf.help_file, (void *) SBUF_SIZE},
{"help_index", cf_string, CA_DISABLED,
(int *) mudconf.help_indx, (void *) SBUF_SIZE},
{"hostnames", cf_bool, CA_GOD,
&mudconf.use_hostname, 0},
{"idle_wiz_dark", cf_bool, CA_GOD,
&mudconf.idle_wiz_dark, 0},
{"idle_interval", cf_int, CA_GOD,
&mudconf.idle_interval, 0},
{"idle_timeout", cf_int, CA_GOD,
&mudconf.idle_timeout, 0},
{"include", cf_include, CA_DISABLED,
NULL, 0},
{"initial_size", cf_int, CA_DISABLED,
&mudconf.init_size, 0},
{"input_database", cf_string, CA_DISABLED,
(int *) mudconf.indb, (void *) PBUF_SIZE},
{"kill_guarantee_cost", cf_int, CA_GOD,
&mudconf.killguarantee, 0},
{"kill_max_cost", cf_int, CA_GOD,
&mudconf.killmax, 0},
{"kill_min_cost", cf_int, CA_GOD,
&mudconf.killmin, 0},
{"lag_maximum", cf_int, CA_GOD,
&mudconf.max_cmdsecs, 0},
{"link_cost", cf_int, CA_GOD,
&mudconf.linkcost, 0},
{"list_access", cf_ntab_access, CA_GOD,
(int *) list_names, access_nametab},
{"local_master_rooms", cf_bool, CA_GOD,
&mudconf.local_masters, 0},
{"lock_recursion_limit", cf_int, CA_GOD,
&mudconf.lock_nest_lim, 0},
{"log", cf_modify_bits, CA_GOD,
&mudconf.log_options, logoptions_nametab},
{"log_options", cf_modify_bits, CA_GOD,
&mudconf.log_info, logdata_nametab},
{"logout_cmd_access", cf_ntab_access, CA_GOD,
(int *) logout_cmdtable, access_nametab},
{"logout_cmd_alias", cf_alias, CA_GOD,
(int *) &mudstate.logout_cmd_htab, 0},
{"look_obey_terse", cf_bool, CA_GOD,
&mudconf.terse_look, 0},
{"machine_command_cost", cf_int, CA_GOD,
&mudconf.machinecost, 0},
{"master_room", cf_int, CA_GOD,
&mudconf.master_room, 0},
{"match_own_commands", cf_bool, CA_GOD,
&mudconf.match_mine, 0},
{"max_players", cf_int, CA_GOD,
&mudconf.max_players, 0},
{"money_name_plural", cf_string, CA_GOD,
(int *) mudconf.many_coins, (void *) SBUF_SIZE},
{"money_name_singular", cf_string, CA_GOD,
(int *) mudconf.one_coin, (void *) SBUF_SIZE},
{"motd_file", cf_string, CA_DISABLED,
(int *) mudconf.motd_file, (void *) SBUF_SIZE},
{"motd_message", cf_string, CA_GOD,
(int *) mudconf.motd_msg, (void *) GBUF_SIZE},
{"mud_name", cf_string, CA_GOD,
(int *) mudconf.mud_name, (void *) SBUF_SIZE},
{"news_file", cf_string, CA_DISABLED,
(int *) mudconf.news_file, (void *) SBUF_SIZE},
{"news_index", cf_string, CA_DISABLED,
(int *) mudconf.news_indx, (void *) SBUF_SIZE},
{"newuser_file", cf_string, CA_DISABLED,
(int *) mudconf.crea_file, (void *) SBUF_SIZE},
{"notify_recursion_limit", cf_int, CA_GOD,
&mudconf.ntfy_nest_lim, 0},
{"open_cost", cf_int, CA_GOD,
&mudconf.opencost, 0},
{"output_database", cf_string, CA_DISABLED,
(int *) mudconf.outdb, (void *) PBUF_SIZE},
{"output_limit", cf_int, CA_GOD,
&mudconf.output_limit, 0},
{"page_cost", cf_int, CA_GOD,
&mudconf.pagecost, 0},
{"paranoid_allocate", cf_bool, CA_GOD,
&mudconf.paranoid_alloc, 0},
{"parentable_control_lock", cf_bool, CA_DISABLED,
&mudconf.parent_control, 0},
{"parent_zones", cf_bool, CA_GOD,
&mudconf.parent_zones, 0},
{"paycheck", cf_int, CA_GOD,
&mudconf.paycheck, 0},
{"pemit_far_players", cf_bool, CA_GOD,
&mudconf.pemit_players, 0},
{"pemit_any_object", cf_bool, CA_GOD,
&mudconf.pemit_any, 0},
{"permit_site", cf_site, CA_GOD,
(int *) &mudstate.access_list, 0},
{"player_flags", cf_set_flags, CA_GOD,
(int *) &mudconf.player_flags, 0},
{"player_listen", cf_bool, CA_GOD,
&mudconf.player_listen, 0},
{"player_match_own_commands", cf_bool, CA_GOD,
&mudconf.match_mine_pl, 0},
{"player_name_spaces", cf_bool, CA_GOD,
&mudconf.name_spaces, 0},
{"player_parent", cf_int, CA_GOD,
&mudconf.player_parent, 0},
{"player_queue_limit", cf_int, CA_GOD,
&mudconf.queuemax, 0},
{"player_quota", cf_int, CA_GOD,
&mudconf.player_quota, 0},
{"player_starting_home", cf_int, CA_GOD,
&mudconf.start_home, 0},
{"player_starting_room", cf_int, CA_GOD,
&mudconf.start_room, 0},
{"port", cf_int, CA_DISABLED,
&mudconf.port, 0},
{"power_access", cf_ntab_access, CA_GOD,
(int *) powers_nametab, access_nametab},
{"public_flags", cf_bool, CA_GOD,
&mudconf.pub_flags, 0},
{"queue_active_chunk", cf_int, CA_GOD,
&mudconf.active_q_chunk, 0},
{"queue_idle_chunk", cf_int, CA_GOD,
&mudconf.queue_chunk, 0},
{"quiet_look", cf_bool, CA_GOD,
&mudconf.quiet_look, 0},
{"quiet_whisper", cf_bool, CA_GOD,
&mudconf.quiet_whisper, 0},
{"quit_file", cf_string, CA_DISABLED,
(int *) mudconf.quit_file, (void *) SBUF_SIZE},
{"quotas", cf_bool, CA_GOD,
&mudconf.quotas, 0},
{"read_remote_desc", cf_bool, CA_GOD,
&mudconf.read_rem_desc, 0},
{"read_remote_name", cf_bool, CA_GOD,
&mudconf.read_rem_name, 0},
{"recycling", cf_bool, CA_GOD,
&mudconf.recycle, 0},
{"register_create_file", cf_string, CA_DISABLED,
(int *) mudconf.regf_file, (void *) SBUF_SIZE},
{"register_site", cf_site, CA_GOD,
(int *) &mudstate.access_list, (void *) H_REGISTRATION},
{"require_cmds_flag", cf_bool, CA_GOD,
&mudconf.req_cmds_flag, 0},
{"retry_limit", cf_int, CA_GOD,
&mudconf.retry_limit, 0},
{"robot_cost", cf_int, CA_GOD,
&mudconf.robotcost, 0},
{"robot_flags", cf_set_flags, CA_GOD,
(int *) &mudconf.robot_flags, 0},
{"robot_speech", cf_bool, CA_GOD,
&mudconf.robot_speak, 0},
{"room_flags", cf_set_flags, CA_GOD,
(int *) &mudconf.room_flags, 0},
{"room_parent", cf_int, CA_GOD,
&mudconf.room_parent, 0},
{"room_quota", cf_int, CA_GOD,
&mudconf.room_quota, 0},
{"rwho_data_port", cf_int, CA_GOD,
&mudconf.rwho_data_port, 0},
{"rwho_dump_interval", cf_int, CA_GOD,
&mudconf.rwho_interval, 0},
{"rwho_host", cf_string, CA_GOD,
(int *) mudconf.rwho_host, (void *) 64},
{"rwho_info_port", cf_int, CA_GOD,
&mudconf.rwho_info_port, 0},
{"rwho_password", cf_string, CA_GOD,
(int *) mudconf.rwho_pass, (void *) SBUF_SIZE},
{"rwho_transmit", cf_bool, CA_GOD,
&mudconf.rwho_transmit, 0},
{"sacrifice_adjust", cf_int, CA_GOD,
&mudconf.sacadjust, 0},
{"sacrifice_factor", cf_int, CA_GOD,
&mudconf.sacfactor, 0},
{"safer_passwords", cf_bool, CA_GOD,
&mudconf.safer_passwords, 0},
{"search_cost", cf_int, CA_GOD,
&mudconf.searchcost, 0},
{"see_owned_dark", cf_bool, CA_GOD,
&mudconf.see_own_dark, 0},
{"signal_action", cf_option, CA_DISABLED,
&mudconf.sig_action, sigactions_nametab},
{"space_compress", cf_bool, CA_GOD,
&mudconf.space_compress, 0},
{"starting_money", cf_int, CA_GOD,
&mudconf.paystart, 0},
{"starting_quota", cf_int, CA_GOD,
&mudconf.start_quota, 0},
{"starting_exit_quota", cf_int, CA_GOD,
&mudconf.start_exit_quota, 0},
{"starting_player_quota", cf_int, CA_GOD,
&mudconf.start_player_quota, 0},
{"starting_room_quota", cf_int, CA_GOD,
&mudconf.start_room_quota, 0},
{"starting_thing_quota", cf_int, CA_GOD,
&mudconf.start_thing_quota, 0},
{"status_file", cf_string, CA_DISABLED,
(int *) mudconf.status_file, (void *) PBUF_SIZE},
{"suspect_site", cf_site, CA_GOD,
(int *) &mudstate.suspect_list, (void *) H_SUSPECT},
{"sweep_dark", cf_bool, CA_GOD,
&mudconf.sweep_dark, 0},
{"switch_default_all", cf_bool, CA_GOD,
&mudconf.switch_df_all, 0},
{"terse_shows_contents", cf_bool, CA_GOD,
&mudconf.terse_contents, 0},
{"terse_shows_exits", cf_bool, CA_GOD,
&mudconf.terse_exits, 0},
{"terse_shows_move_messages", cf_bool, CA_GOD,
&mudconf.terse_movemsg, 0},
{"thing_flags", cf_set_flags, CA_GOD,
(int *) &mudconf.thing_flags, 0},
{"thing_parent", cf_int, CA_GOD,
&mudconf.thing_parent, 0},
{"thing_quota", cf_int, CA_GOD,
&mudconf.thing_quota, 0},
{"timeslice", cf_int, CA_GOD,
&mudconf.timeslice, 0},
{"trace_output_limit", cf_int, CA_GOD,
&mudconf.trace_limit, 0},
{"trace_topdown", cf_bool, CA_GOD,
&mudconf.trace_topdown, 0},
{"trust_site", cf_site, CA_GOD,
(int *) &mudstate.suspect_list, 0},
{"typed_quotas", cf_bool, CA_GOD,
&mudconf.typed_quotas, 0},
{"unowned_safe", cf_bool, CA_GOD,
&mudconf.safe_unowned, 0},
{"user_attr_access", cf_modify_bits, CA_GOD,
&mudconf.vattr_flags, attraccess_nametab},
{"use_global_aconn", cf_bool, CA_GOD,
&mudconf.use_global_aconn, 0},
{"wait_cost", cf_int, CA_GOD,
&mudconf.waitcost, 0},
{"wizard_obeys_linklock", cf_bool, CA_GOD,
&mudconf.wiz_obey_linklock, 0},
{"wizard_help_file", cf_string, CA_DISABLED,
(int *) mudconf.whelp_file, (void *) SBUF_SIZE},
{"wizard_help_index", cf_string, CA_DISABLED,
(int *) mudconf.whelp_indx, (void *) SBUF_SIZE},
{"wizard_motd_file", cf_string, CA_DISABLED,
(int *) mudconf.wizmotd_file, (void *) SBUF_SIZE},
{"wizard_motd_message", cf_string, CA_GOD,
(int *) mudconf.wizmotd_msg, (void *) GBUF_SIZE},
{NULL, NULL, 0,
NULL, 0}};
/* ---------------------------------------------------------------------------
* cf_set: Set config parameter.
*/
int
cf_set(cp, ap, player)
char *cp, *ap;
dbref player;
{
CONF *tp;
int i;
char *buff;
/* Search the config parameter table for the command.
If we find it, call the handler to parse the argument. */
for (tp = conftable; tp->pname; tp++) {
if (!strcmp(tp->pname, cp)) {
if (!mudstate.initializing &&
!check_access(player, tp->flags)) {
notify(player,
"Permission denied.");
return (-1);
}
if (!mudstate.initializing) {
buff = alloc_lbuf("cf_set");
strcpy(buff, ap);
}
i = tp->interpreter(tp->loc, ap, tp->extra, player, cp);
if (!mudstate.initializing) {
STARTLOG(LOG_CONFIGMODS, "CFG", "UPDAT")
log_name(player);
log_text((char *) " entered config directive: ");
log_text(cp);
log_text((char *) " with args '");
log_text(buff);
log_text((char *) "'. Status: ");
switch (i) {
case 0:
log_text((char *) "Success.");
break;
case 1:
log_text((char *) "Partial success.");
break;
case -1:
log_text((char *) "Failure.");
break;
default:
log_text((char *) "Strange.");
}
ENDLOG
free_lbuf(buff);
}
return i;
}
}
/* Config directive not found. Complain about it. */
cf_log_notfound(player, (char *) "Set", "Config directive", cp);
return (-1);
}
/* ---------------------------------------------------------------------------
* do_admin: Command handler to set config params at runtime */
void
do_admin(player, cause, extra, kw, value)
dbref player, cause;
int extra;
char *kw, *value;
{
int i;
i = cf_set(kw, value, player);
if ((i >= 0) && !Quiet(player))
notify(player, "Set.");
return;
}
/* ---------------------------------------------------------------------------
* cf_read: Read in config parameters from named file
*/
int
cf_read(fn)
char *fn;
{
int retval;
strncpy(mudconf.config_file, fn, PBUF_SIZE - 1);
mudconf.config_file[PBUF_SIZE - 1] = '\0';
mudstate.initializing = 1;
retval = cf_include(NULL, fn, 0, 0, (char *) "init");
mudstate.initializing = 0;
/* Fill in missing DB file names */
if (!*mudconf.outdb) {
strcpy(mudconf.outdb, mudconf.indb);
strcat(mudconf.outdb, ".out");
}
if (!*mudconf.crashdb) {
strcpy(mudconf.crashdb, mudconf.indb);
strcat(mudconf.crashdb, ".CRASH");
}
if (!*mudconf.gdbm) {
strcpy(mudconf.gdbm, mudconf.indb);
strcat(mudconf.gdbm, ".gdbm");
}
return retval;
}
/* ---------------------------------------------------------------------------
* list_cf_access: List access to config directives.
*/
void
list_cf_access(player)
dbref player;
{
CONF *tp;
char *buff;
buff = alloc_mbuf("list_cf_access");
for (tp = conftable; tp->pname; tp++) {
if (God(player) || check_access(player, tp->flags)) {
sprintf(buff, "%s:", tp->pname);
listset_nametab(player, access_nametab, tp->flags,
buff, 1);
}
}
free_mbuf(buff);
}
#endif /* STANDALONE */