/* conf.c: set up configuration information and static data */
/* $Id: conf.c,v 1.75.4.4 2000/05/30 11:32:05 rmg Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "mudconf.h"
#include "db.h"
#include "externs.h"
#include "interface.h"
#include "command.h"
#include "htab.h"
#include "alloc.h"
#include "attrs.h"
#include "flags.h"
#include "powers.h"
#include "udb_defs.h"
#include "match.h"
/* Some systems are lame, and inet_addr() claims to return -1 on failure,
* despite the fact that it returns an unsigned long. (It's not really a -1,
* obviously.) Better-behaved systems use INADDR_NONE.
*/
#ifndef INADDR_NONE
#define INADDR_NONE -1
#endif
/* ---------------------------------------------------------------------------
* 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 rperms; /* read permission flags */
int *loc; /* where to store value */
long 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[];
extern LOGFILETAB logfds_table[];
#endif
/*
* ---------------------------------------------------------------------------
* * cf_init: Initialize mudconf to default values.
*/
void NDECL(cf_init)
{
#ifndef STANDALONE
int i;
StringCopy(mudconf.indb, "tinymush.db");
StringCopy(mudconf.outdb, "");
StringCopy(mudconf.crashdb, "");
StringCopy(mudconf.gdbm, "");
StringCopy(mudconf.mail_db, "mail.db");
StringCopy(mudconf.comsys_db, "comsys.db");
mudconf.compress_db = 0;
StringCopy(mudconf.compress, "gzip");
StringCopy(mudconf.uncompress, "gzip -d");
StringCopy(mudconf.status_file, "shutdown.status");
StringCopy(mudconf.mudlogname, "netmush.log");
mudconf.port = 6250;
mudconf.conc_port = 6251;
mudconf.init_size = 1000;
mudconf.use_global_aconn = 1;
mudconf.global_aconn_uselocks = 0;
mudconf.guest_char = -1;
mudconf.guest_nuker = 1;
mudconf.number_guests = 30;
StringCopy(mudconf.guest_prefix, "Guest");
StringCopy(mudconf.guest_file, "text/guest.txt");
StringCopy(mudconf.conn_file, "text/connect.txt");
StringCopy(mudconf.creg_file, "text/register.txt");
StringCopy(mudconf.regf_file, "text/create_reg.txt");
StringCopy(mudconf.motd_file, "text/motd.txt");
StringCopy(mudconf.wizmotd_file, "text/wizmotd.txt");
StringCopy(mudconf.quit_file, "text/quit.txt");
StringCopy(mudconf.down_file, "text/down.txt");
StringCopy(mudconf.full_file, "text/full.txt");
StringCopy(mudconf.site_file, "text/badsite.txt");
StringCopy(mudconf.crea_file, "text/newuser.txt");
#ifdef PUEBLO_SUPPORT
StringCopy(mudconf.htmlconn_file, "text/htmlconn.txt");
#endif
StringCopy(mudconf.motd_msg, "");
StringCopy(mudconf.wizmotd_msg, "");
StringCopy(mudconf.downmotd_msg, "");
StringCopy(mudconf.fullmotd_msg, "");
StringCopy(mudconf.dump_msg, "");
StringCopy(mudconf.postdump_msg, "");
StringCopy(mudconf.fixed_home_msg, "");
StringCopy(mudconf.fixed_tel_msg, "");
StringCopy(mudconf.public_channel, "Public");
StringCopy(mudconf.guests_channel, "Guests");
StringCopy(mudconf.public_calias, "pub");
StringCopy(mudconf.guests_calias, "g");
#ifdef PUEBLO_SUPPORT
StringCopy(mudconf.pueblo_msg, "</xch_mudtext><img xch_mode=html><tt>");
#endif
StringCopy(mudconf.sql_host, "127.0.0.1");
StringCopy(mudconf.sql_db, "");
StringCopy(mudconf.sql_username, "");
StringCopy(mudconf.sql_password, "");
mudconf.sql_reconnect = 0;
mudconf.indent_desc = 0;
mudconf.name_spaces = 1;
mudconf.fork_dump = 0;
mudconf.fork_vfork = 0;
mudconf.dbopt_interval = 0;
#ifdef USE_COMSYS
mudconf.have_comsys = 1;
#else
mudconf.have_comsys = 0;
#endif
#ifdef USE_MAIL
mudconf.have_mailer = 1;
#else
mudconf.have_mailer = 0;
#endif
#ifdef PUEBLO_SUPPORT
mudconf.have_pueblo = 1;
#else
mudconf.have_pueblo = 0;
#endif
mudconf.have_zones = 1;
mudconf.paranoid_alloc = 0;
mudconf.sig_action = SA_DFLT;
mudconf.max_players = -1;
mudconf.dump_interval = 3600;
mudconf.check_interval = 600;
mudconf.events_daily_hour = 7;
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.site_chars = 25;
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.mail_expiration = 14;
mudconf.queuemax = 100;
mudconf.queue_chunk = 10;
mudconf.active_q_chunk = 10;
mudconf.sacfactor = 5;
mudconf.sacadjust = -1;
mudconf.use_hostname = 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.addcmd_match_blindly = 1;
mudconf.addcmd_obey_stop = 0;
mudconf.addcmd_obey_uselocks = 0;
mudconf.lattr_oldstyle = 0;
mudconf.bools_oldstyle = 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.wiz_obey_linklock = 0;
mudconf.local_masters = 1;
mudconf.req_cmds_flag = 1;
mudconf.fmt_contents = 1;
mudconf.fmt_exits = 1;
mudconf.ansi_colors = 1;
mudconf.safer_passwords = 0;
mudconf.instant_recycle = 1;
mudconf.dark_actions = 0;
mudconf.no_ambiguous_match = 0;
mudconf.exit_calls_move = 0;
mudconf.move_match_more = 0;
mudconf.autozone = 1;
/* -- ??? Running SC on a non-SC DB may cause problems */
mudconf.space_compress = 1;
mudconf.start_room = 0;
mudconf.guest_start_room = NOTHING; /* default, use start_room */
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.player_flags.word3 = 0;
mudconf.room_flags.word1 = 0;
mudconf.room_flags.word2 = 0;
mudconf.room_flags.word3 = 0;
mudconf.exit_flags.word1 = 0;
mudconf.exit_flags.word2 = 0;
mudconf.exit_flags.word3 = 0;
mudconf.thing_flags.word1 = 0;
mudconf.thing_flags.word2 = 0;
mudconf.thing_flags.word3 = 0;
mudconf.robot_flags.word1 = ROBOT;
mudconf.robot_flags.word2 = 0;
mudconf.robot_flags.word3 = 0;
mudconf.stripped_flags.word1 = IMMORTAL | INHERIT | ROYALTY | WIZARD;
mudconf.stripped_flags.word2 = BLIND | CONNECTED | GAGGED |
HEAD_FLAG | SLAVE | STAFF | STOP_MATCH | SUSPECT | UNINSPECTED;
mudconf.stripped_flags.word3 = 0;
mudconf.vattr_flags = AF_ODARK;
StringCopy(mudconf.mud_name, "TinyMUSH");
StringCopy(mudconf.one_coin, "penny");
StringCopy(mudconf.many_coins, "pennies");
mudconf.timeslice = 1000;
mudconf.cmd_quota_max = 100;
mudconf.cmd_quota_incr = 1;
#ifdef NO_LAG_CHECK
mudconf.lag_check = 0;
#else
mudconf.lag_check = 1;
#endif
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.log_diversion = 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.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.zone_nest_lim = 20;
mudconf.numvars_lim = 50;
mudconf.stack_lim = 50;
mudconf.struct_lim = 100;
mudconf.instance_lim = 100;
mudconf.cache_trim = 0;
mudconf.cache_depth = CACHE_DEPTH;
mudconf.cache_width = CACHE_WIDTH;
mudconf.cache_names = 1;
mudstate.events_flag = 0;
mudstate.initializing = 0;
mudstate.loading_db = 0;
mudstate.panicking = 0;
mudstate.dumping = 0;
mudstate.logging = 0;
mudstate.epoch = 0;
mudstate.generation = 0;
mudstate.reboot_nums = 0;
mudstate.mudlognum = 0;
mudstate.helpfiles = 0;
mudstate.hfiletab = NULL;
mudstate.hfiletab_size = 0;
mudstate.hfile_hashes = NULL;
mudstate.curr_player = NOTHING;
mudstate.curr_enactor = NOTHING;
mudstate.curr_cmd = (char *) "< none >";
mudstate.shutdown_flag = 0;
mudstate.attr_next = A_USER_START;
mudstate.debug_cmd = (char *)"< init >";
StringCopy(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.mstat_ixrss[0] = 0;
mudstate.mstat_ixrss[1] = 0;
mudstate.mstat_idrss[0] = 0;
mudstate.mstat_idrss[1] = 0;
mudstate.mstat_isrss[0] = 0;
mudstate.mstat_isrss[1] = 0;
mudstate.mstat_secs[0] = 0;
mudstate.mstat_secs[1] = 0;
mudstate.mstat_curr = 0;
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 = NULL;
mudstate.min_size = 0;
mudstate.db_top = 0;
mudstate.db_size = 0;
mudstate.mail_db_top = 0;
mudstate.mail_db_size = 0;
mudstate.mail_freelist = 0;
mudstate.freelist = NOTHING;
mudstate.markbits = NULL;
mudstate.sql_socket = -1;
mudstate.func_nest_lev = 0;
mudstate.func_invk_ctr = 0;
mudstate.ntfy_nest_lev = 0;
mudstate.lock_nest_lev = 0;
mudstate.zone_nest_num = 0;
mudstate.in_loop = 0;
mudstate.loop_token = NULL;
mudstate.loop_number = 0;
mudstate.in_switch = 0;
mudstate.switch_token = NULL;
mudstate.inpipe = 0;
mudstate.pout = NULL;
mudstate.poutnew = NULL;
mudstate.poutbufc = NULL;
mudstate.poutobj = -1;
for (i = 0; i < MAX_GLOBAL_REGS; i++) {
mudstate.global_regs[i] = NULL;
mudstate.glob_reg_len[i] = 0;
}
#else
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.quotas = 0;
mudconf.start_room = 0;
mudconf.start_home = -1;
mudconf.default_home = -1;
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_trim = 0;
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[LBUF_SIZE * 2];
if (mudstate.initializing) {
STARTLOG(LOG_STARTUP, "CNF", "NFND")
sprintf(buff, "%s: %s %s not found",
cmd, thingname, thing);
log_text(buff);
ENDLOG
} else {
sprintf(buff, "%s %s not found", thingname, thing);
notify(player, tprintf("%s %s not found", thingname, thing));
}
}
/*
* ---------------------------------------------------------------------------
* * 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[LBUF_SIZE * 2];
if (mudstate.initializing) {
STARTLOG(LOG_STARTUP, "CNF", "SYNTX")
sprintf(buff, template, arg);
log_text(cmd);
log_text((char *)": ");
log_text(buff);
ENDLOG
} else {
sprintf(buff, template, arg);
notify(player, 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_const)
{
/*
* Ignore any attempt to change the value
*/
return 0;
}
/*
* ---------------------------------------------------------------------------
* * cf_int: Set integer parameter.
*/
CF_HAND(cf_int)
{
/*
* Copy the numeric value to the parameter
*/
sscanf(str, "%d", vp);
return 0;
}
/* *INDENT-OFF* */
/* ---------------------------------------------------------------------------
* 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}};
/* *INDENT-ON* */
CF_HAND(cf_bool)
{
*vp = (int) search_nametab(GOD, bool_names, str);
if (*vp < 0)
*vp = (long) 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 < 0) {
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) >= extra) {
str[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;
}
StringCopy((char *)vp, str);
return retval;
}
/*
* ---------------------------------------------------------------------------
* * cf_alias: define a generic hash table alias.
*/
CF_HAND(cf_alias)
{
char *alias, *orig, *p, *tokst;
int *cp;
alias = strtok_r(str, " \t=,", &tokst);
orig = strtok_r(NULL, " \t=,", &tokst);
if (orig) {
for (p = orig; *p; p++)
*p = ToLower(*p);
cp = hashfind(orig, (HASHTAB *) vp);
if (cp == NULL) {
for (p = orig; *p; p++)
*p = ToUpper(*p);
cp = hashfind(orig, (HASHTAB *) vp);
if (cp == NULL) {
cf_log_notfound(player, cmd, "Entry", orig);
return -1;
}
}
} else {
return -1;
}
hashadd(alias, cp, (HASHTAB *) vp);
return 0;
}
/*
* ---------------------------------------------------------------------------
* * cf_flagalias: define a flag alias.
*/
CF_HAND(cf_flagalias)
{
char *alias, *orig, *tokst;
int *cp, success;
success = 0;
alias = strtok_r(str, " \t=,", &tokst);
orig = strtok_r(NULL, " \t=,", &tokst);
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_divert_log: Redirect a log type.
*/
CF_HAND(cf_divert_log)
{
char *type_str, *file_str, *tokst;
int f, fd;
FILE *fptr;
LOGFILETAB *tp, *lp;
/* Two args, two args only */
type_str = strtok_r(str, " \t", &tokst);
file_str = strtok_r(NULL, " \t", &tokst);
if (!type_str || !file_str) {
cf_log_syntax(player, cmd, "Missing pathname to log to.", (char *) "");
return -1;
}
/* Find the log. */
f = search_nametab(GOD, (NAMETAB *) extra, type_str);
if (f <= 0) {
cf_log_notfound(player, cmd, "Log diversion", type_str);
return -1;
}
for (tp = logfds_table; tp->log_flag; tp++) {
if (tp->log_flag == f)
break;
}
if (tp == NULL) { /* This should never happen! */
cf_log_notfound(player, cmd, "Logfile table corruption", type_str);
return -1;
}
/* We shouldn't have a file open already. */
if (tp->filename != NULL) {
STARTLOG(LOG_STARTUP, "CNF", "DIVT")
log_text((char *) "Log type ");
log_text(type_str);
log_text((char *) " already diverted: ");
log_text(tp->filename);
ENDLOG
return -1;
}
/* Check to make sure that we don't have this filename open already. */
fptr = NULL;
for (lp = logfds_table; lp->log_flag; lp++) {
if (lp->filename && !strcmp(file_str, lp->filename)) {
fptr = lp->fileptr;
break;
}
}
/* We don't have this filename yet. Open the logfile. */
if (!fptr) {
fptr = fopen(file_str, "w");
if (!fptr) {
STARTLOG(LOG_STARTUP, "CNF", "DIVT")
log_text((char *) "Cannot open logfile: ");
log_text(file_str);
ENDLOG
return -1;
}
if ((fd = fileno(fptr)) == -1) {
return -1;
}
#ifdef FNDELAY
if (fcntl(fd, F_SETFL, FNDELAY) == -1) {
STARTLOG(LOG_STARTUP, "CNF", "DIVT")
log_text((char *) "Cannot make nonblocking: ");
log_text(file_str);
ENDLOG
return -1;
}
#else
if (fcntl(fd, F_SETFL, O_NDELAY) == -1) {
STARTLOG(LOG_STARTUP, "CNF", "DIVT")
log_text((char *) "Cannot make nonblocking: ");
log_text(file_str);
ENDLOG
return -1;
}
#endif
}
/* Indicate that this is being diverted. */
tp->fileptr = fptr;
tp->filename = (char *) strdup(file_str);
*vp |= f;
return 0;
}
/* ---------------------------------------------------------------------------
* cf_modify_bits: set or clear bits in a flag word from a namelist.
*/
CF_HAND(cf_modify_bits)
{
char *sp, *tokst;
int f, negate, success, failure;
/*
* Walk through the tokens
*/
success = failure = 0;
sp = strtok_r(str, " \t", &tokst);
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 > 0) {
if (negate)
*vp &= ~f;
else
*vp |= f;
success++;
} else {
cf_log_notfound(player, cmd, "Entry", sp);
failure++;
}
/*
* Get the next token
*/
sp = strtok_r(NULL, " \t", &tokst);
}
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, *tokst;
FLAGENT *fp;
FLAGSET *fset;
int success, failure;
/*
* Walk through the tokens
*/
success = failure = 0;
sp = strtok_r(str, " \t", &tokst);
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;
(*fset).word3 = 0;
}
if (fp->flagflag & FLAG_WORD3)
(*fset).word3 |= fp->flagvalue;
else if (fp->flagflag & FLAG_WORD2)
(*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_r(NULL, " \t", &tokst);
}
if ((success == 0) && (failure == 0)) {
(*fset).word1 = 0;
(*fset).word2 = 0;
(*fset).word3 = 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 (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 INADDR_NONE;
else
return inet_addr(str);
}
/*
* ---------------------------------------------------------------------------
* * cf_site: Update site information
*/
CF_AHAND(cf_site)
{
SITE *site, *last, *head;
char *addr_txt, *mask_txt, *tokst;
struct in_addr addr_num, mask_num;
int mask_bits;
if ((mask_txt = (char *) index(str, '/')) == NULL) {
/* Standard IP range and netmask notation. */
addr_txt = strtok_r(str, " \t=,", &tokst);
if (addr_txt)
mask_txt = strtok_r(NULL, " \t=,", &tokst);
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)) == INADDR_NONE) {
cf_log_syntax(player, cmd, "Malformed host address: %s", addr_txt);
return -1;
}
if ((mask_num.s_addr = sane_inet_addr(mask_txt)) == INADDR_NONE) {
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 if (mask_bits == 0) {
mask_num.s_addr = htonl(0); /* can't shift by 32 */
} else {
mask_num.s_addr = htonl(0xFFFFFFFFU << (32 - mask_bits));
}
if ((addr_num.s_addr = sane_inet_addr(addr_txt)) == INADDR_NONE) {
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 = (long *) site;
} else {
for (last = head; last->next; last = last->next)
;
last->next = site;
}
} else {
site->next = head;
*vp = (long *) site;
}
return 0;
}
/*
* ---------------------------------------------------------------------------
* * cf_cf_access: Set write or read access on config directives
* kludge: this cf handler uses vp as an extra extra field since the
* first extra field is taken up with the access nametab.
*/
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)) {
/* Cannot modify parameters set STATIC */
if (tp->flags & CA_STATIC) {
notify(player, NOPERM_MESSAGE);
STARTLOG(LOG_CONFIGMODS, "CFG", "PERM")
log_name(player);
log_text((char *) " tried to change ");
log_text((char *) (((long)vp) ? "read" : "write"));
log_text((char *) " access to static param: ");
log_text(tp->pname);
ENDLOG
return -1;
}
if ((long)vp) {
return (cf_modify_bits(&tp->rperms, ap, extra,
player, cmd));
} else {
return (cf_modify_bits(&tp->flags, ap, extra,
player, cmd));
}
}
}
cf_log_notfound(player, cmd, "Config directive", str);
return -1;
}
/* ---------------------------------------------------------------------------
* cf_helpfile: Add a help/news-style file. Only valid during startup.
*/
int add_helpfile(player, str, is_raw)
dbref player;
char *str;
int is_raw;
{
char *fcmd, *fpath, *newstr, *tokst;
CMDENT *cmdp;
char **ftab; /* pointer to an array of filepaths */
HASHTAB *hashes;
/* Make a new string so we won't SEGV if given a constant string */
newstr = alloc_mbuf("add_helpfile");
StringCopy(newstr, str);
fcmd = strtok_r(newstr, " \t=,", &tokst);
fpath = strtok_r(NULL, " \t=,", &tokst);
if (strlen(fpath) > SBUF_SIZE) {
free_mbuf(newstr);
return -1;
}
if ((cmdp = (CMDENT *) hashfind(fcmd, &mudstate.command_htab)) == NULL) {
/* We need to allocate a new command structure. */
cmdp = (CMDENT *) XMALLOC(sizeof(CMDENT), "add_helpfile");
cmdp->cmdname = (char *) strdup(fcmd);
cmdp->switches = NULL;
cmdp->perms = 0;
cmdp->pre_hook = NULL;
cmdp->post_hook = NULL;
cmdp->callseq = CS_ONE_ARG;
cmdp->info.handler = do_help;
cmdp->extra = mudstate.helpfiles;
if (is_raw)
cmdp->extra |= HELP_RAWHELP;
hashadd(fcmd, (int *) cmdp, &mudstate.command_htab);
} else {
/* Otherwise we just need to repoint things. */
cmdp->info.handler = do_help;
}
/* We may need to grow the helpfiles table, or create it. */
if (!mudstate.hfiletab) {
mudstate.hfiletab = (char **) calloc(4, sizeof(char *));
mudstate.hfile_hashes = (HASHTAB *) calloc(4, sizeof(HASHTAB));
mudstate.hfiletab_size = 4;
} else if (mudstate.helpfiles >= mudstate.hfiletab_size) {
ftab = (char **) realloc(mudstate.hfiletab,
(mudstate.hfiletab_size + 4) * sizeof(char *));
hashes = (HASHTAB *) realloc(mudstate.hfile_hashes,
(mudstate.hfiletab_size + 4) *
sizeof(HASHTAB));
ftab[mudstate.hfiletab_size + 1] = NULL;
ftab[mudstate.hfiletab_size + 2] = NULL;
ftab[mudstate.hfiletab_size + 3] = NULL;
ftab[mudstate.hfiletab_size + 4] = NULL;
mudstate.hfiletab_size += 4;
mudstate.hfiletab = ftab;
mudstate.hfile_hashes = hashes;
}
/* Add or replace the path to the file. */
if (mudstate.hfiletab[mudstate.helpfiles] != NULL)
free(mudstate.hfiletab[mudstate.helpfiles]);
mudstate.hfiletab[mudstate.helpfiles] = (char *) strdup(fpath);
/* Initialize the associated hashtable. */
hashinit(&mudstate.hfile_hashes[mudstate.helpfiles], 30 * HASH_FACTOR);
mudstate.helpfiles++;
free_mbuf(newstr);
return 0;
}
CF_HAND(cf_helpfile)
{
return add_helpfile(player, str, 0);
}
CF_HAND(cf_raw_helpfile)
{
return add_helpfile(player, str, 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;
}
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_func_access);
extern CF_HDCL(cf_flag_access);
extern CF_HDCL(cf_flag_name);
extern CF_HDCL(cf_power_access);
/* *INDENT-OFF* */
/* ---------------------------------------------------------------------------
* conftable: Table for parsing the configuration file.
*/
CONF conftable[] = {
{(char *)"abort_on_bug", cf_bool, CA_STATIC, CA_GOD, (int *)&mudconf.abort_on_bug, (long)"Dump core after logging a bug"},
{(char *)"access", cf_access, CA_GOD, CA_DISABLED, NULL, (long)access_nametab},
{(char *)"addcommands_match_blindly", cf_bool, CA_GOD, CA_WIZARD, &mudconf.addcmd_match_blindly, (long)"@addcommands don't error if no match is found"},
{(char *)"addcommands_obey_stop", cf_bool, CA_GOD, CA_WIZARD, &mudconf.addcmd_obey_stop, (long)"@addcommands obey STOP"},
{(char *)"addcommands_obey_uselocks", cf_bool, CA_GOD, CA_WIZARD, &mudconf.addcmd_obey_uselocks, (long)"@addcommands obey UseLocks"},
{(char *)"alias", cf_cmd_alias, CA_GOD, CA_DISABLED, (int *)&mudstate.command_htab, 0},
{(char *)"ansi_colors", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.ansi_colors, (long)"ANSI color codes enabled"},
{(char *)"attr_access", cf_attr_access, CA_GOD, CA_DISABLED, NULL, (long)attraccess_nametab},
{(char *)"attr_alias", cf_alias, CA_GOD, CA_DISABLED, (int *)&mudstate.attr_name_htab,0},
{(char *)"attr_cmd_access", cf_acmd_access, CA_GOD, CA_DISABLED, NULL, (long)access_nametab},
{(char *)"autozone", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.autozone, (long)"New objects are @chzoned to their creator's zone"},
{(char *)"bad_name", cf_badname, CA_GOD, CA_DISABLED, NULL, 0},
{(char *)"badsite_file", cf_string, CA_STATIC, CA_GOD, (int *)mudconf.site_file, SBUF_SIZE},
{(char *)"booleans_oldstyle", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.bools_oldstyle, (long)"Dbrefs #0 and #-1 are boolean false, all other\n\t\t\t\tdbrefs are boolean true"},
{(char *)"building_limit", cf_int, CA_GOD, CA_PUBLIC, (int *)&mudconf.building_limit, 0},
{(char *)"cache_depth", cf_int, CA_STATIC, CA_GOD, &mudconf.cache_depth, 0},
{(char *)"cache_names", cf_bool, CA_STATIC, CA_GOD, &mudconf.cache_names, (long)"Names are cached separately"},
{(char *)"cache_trim", cf_bool, CA_GOD, CA_GOD, &mudconf.cache_trim, (long)"Cache trimmed periodically"},
{(char *)"cache_width", cf_int, CA_STATIC, CA_GOD, &mudconf.cache_width, 0},
{(char *)"check_interval", cf_int, CA_GOD, CA_WIZARD, &mudconf.check_interval, 0},
{(char *)"check_offset", cf_int, CA_GOD, CA_WIZARD, &mudconf.check_offset, 0},
{(char *)"clone_copies_cost", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.clone_copy_cost, (long)"@clone copies object cost"},
{(char *)"comsys_database", cf_string, CA_STATIC, CA_GOD, (int *)mudconf.comsys_db, PBUF_SIZE},
{(char *)"command_quota_increment", cf_int, CA_GOD, CA_WIZARD, &mudconf.cmd_quota_incr, 0},
{(char *)"command_quota_max", cf_int, CA_GOD, CA_WIZARD, &mudconf.cmd_quota_max, 0},
{(char *)"compress_program", cf_string, CA_STATIC, CA_GOD, (int *)mudconf.compress, PBUF_SIZE},
{(char *)"compression", cf_bool, CA_GOD, CA_GOD, &mudconf.compress_db, (long)"Database files are compressed"},
{(char *)"concentrator_port", cf_int, CA_STATIC, CA_WIZARD, &mudconf.conc_port, 0},
{(char *)"config_access", cf_cf_access, CA_GOD, CA_DISABLED, NULL, (long)access_nametab},
{(char *)"config_read_access", cf_cf_access, CA_GOD, CA_DISABLED, (int *)1, (long)access_nametab},
{(char *)"conn_timeout", cf_int, CA_GOD, CA_WIZARD, &mudconf.conn_timeout, 0},
{(char *)"connect_file", cf_string, CA_STATIC, CA_GOD, (int *)mudconf.conn_file, SBUF_SIZE},
{(char *)"connect_reg_file", cf_string, CA_STATIC, CA_GOD, (int *)mudconf.creg_file, SBUF_SIZE},
{(char *)"crash_database", cf_string, CA_STATIC, CA_GOD, (int *)mudconf.crashdb, PBUF_SIZE},
{(char *)"create_max_cost", cf_int, CA_GOD, CA_PUBLIC, &mudconf.createmax, 0},
{(char *)"create_min_cost", cf_int, CA_GOD, CA_PUBLIC, &mudconf.createmin, 0},
{(char *)"dark_actions", cf_bool, CA_GOD, CA_WIZARD, &mudconf.dark_actions, (long)"Dark objects still trigger @a-actions when moving"},
{(char *)"dark_sleepers", cf_bool, CA_GOD, CA_WIZARD, &mudconf.dark_sleepers, (long)"Disconnected players not shown in room contents"},
{(char *)"default_home", cf_int, CA_GOD, CA_PUBLIC, &mudconf.default_home, 0},
{(char *)"dig_cost", cf_int, CA_GOD, CA_PUBLIC, &mudconf.digcost, 0},
{(char *)"divert_log", cf_divert_log, CA_STATIC, CA_DISABLED, &mudconf.log_diversion, (long) logoptions_nametab},
{(char *)"down_file", cf_string, CA_STATIC, CA_GOD, (int *)mudconf.down_file, SBUF_SIZE},
{(char *)"down_motd_message", cf_string, CA_GOD, CA_WIZARD, (int *)mudconf.downmotd_msg, GBUF_SIZE},
{(char *)"dump_interval", cf_int, CA_GOD, CA_WIZARD, &mudconf.dump_interval, 0},
{(char *)"dump_message", cf_string, CA_GOD, CA_WIZARD, (int *)mudconf.dump_msg, PBUF_SIZE},
{(char *)"postdump_message", cf_string, CA_GOD, CA_WIZARD, (int *)mudconf.postdump_msg, PBUF_SIZE},
{(char *)"dump_offset", cf_int, CA_GOD, CA_WIZARD, &mudconf.dump_offset, 0},
{(char *)"earn_limit", cf_int, CA_GOD, CA_PUBLIC, &mudconf.paylimit, 0},
{(char *)"examine_flags", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.ex_flags, (long)"examine shows names of flags"},
{(char *)"examine_public_attrs", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.exam_public, (long)"examine shows public attributes"},
{(char *)"exit_flags", cf_set_flags, CA_GOD, CA_DISABLED, (int *)&mudconf.exit_flags, 0},
{(char *)"exit_calls_move", cf_bool, CA_GOD, CA_WIZARD, &mudconf.exit_calls_move, (long)"Using an exit calls the move command"},
{(char *)"exit_parent", cf_int, CA_GOD, CA_PUBLIC, &mudconf.exit_parent, 0},
{(char *)"exit_quota", cf_int, CA_GOD, CA_PUBLIC, &mudconf.exit_quota, 0},
{(char *)"events_daily_hour", cf_int, CA_GOD, CA_PUBLIC, &mudconf.events_daily_hour, 0},
{(char *)"fascist_teleport", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.fascist_tport, (long)"@teleport source restricted to control or JUMP_OK"},
{(char *)"fixed_home_message", cf_string, CA_STATIC, CA_PUBLIC, (int *)mudconf.fixed_home_msg, PBUF_SIZE},
{(char *)"fixed_tel_message", cf_string, CA_STATIC, CA_PUBLIC, (int *)mudconf.fixed_tel_msg, PBUF_SIZE},
{(char *)"find_money_chance", cf_int, CA_GOD, CA_WIZARD, &mudconf.payfind, 0},
{(char *)"flag_alias", cf_flagalias, CA_GOD, CA_DISABLED, NULL, 0},
{(char *)"flag_access", cf_flag_access, CA_GOD, CA_DISABLED, NULL, 0},
{(char *)"flag_name", cf_flag_name, CA_GOD, CA_DISABLED, NULL, 0},
{(char *)"forbid_site", cf_site, CA_GOD, CA_DISABLED, (int *)&mudstate.access_list, H_FORBIDDEN},
{(char *)"fork_dump", cf_bool, CA_GOD, CA_WIZARD, &mudconf.fork_dump, (long)"Dumps are performed using a forked process"},
{(char *)"fork_vfork", cf_bool, CA_GOD, CA_WIZARD, &mudconf.fork_vfork, (long)"Forks are done using vfork()"},
{(char *)"format_contents", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.fmt_contents, (long)"@ConFormat is obeyed when displaying contents"},
{(char *)"format_exits", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.fmt_exits, (long)"@ExitFormat is obeyed when displaying exit lists"},
{(char *)"full_file", cf_string, CA_STATIC, CA_GOD, (int *)mudconf.full_file, SBUF_SIZE},
{(char *)"full_motd_message", cf_string, CA_GOD, CA_WIZARD, (int *)mudconf.fullmotd_msg, GBUF_SIZE},
{(char *)"function_access", cf_func_access, CA_GOD, CA_DISABLED, NULL, (long)access_nametab},
{(char *)"function_alias", cf_alias, CA_GOD, CA_DISABLED, (int *)&mudstate.func_htab, 0},
{(char *)"function_invocation_limit", cf_int, CA_GOD, CA_PUBLIC, &mudconf.func_invk_lim, 0},
{(char *)"function_recursion_limit", cf_int, CA_GOD, CA_PUBLIC, &mudconf.func_nest_lim, 0},
{(char *)"game_log", cf_string, CA_STATIC, CA_GOD, (int *)mudconf.mudlogname, PBUF_SIZE},
{(char *)"gdbm_database", cf_string, CA_STATIC, CA_GOD, (int *)mudconf.gdbm, PBUF_SIZE},
{(char *)"global_aconn_uselocks", cf_bool, CA_GOD, CA_WIZARD, &mudconf.global_aconn_uselocks, (long)"Obey UseLocks on global @aconnect and @adisconnect"},
{(char *)"good_name", cf_badname, CA_GOD, CA_DISABLED, NULL, 1},
{(char *)"guest_char_num", cf_int, CA_STATIC, CA_WIZARD, &mudconf.guest_char, 0},
{(char *)"guest_nuker", cf_int, CA_GOD, CA_WIZARD, &mudconf.guest_nuker, 0},
{(char *)"guest_prefix", cf_string, CA_STATIC, CA_PUBLIC, (int *)mudconf.guest_prefix, SBUF_SIZE},
{(char *)"number_guests", cf_int, CA_STATIC, CA_WIZARD, &mudconf.number_guests, 0},
{(char *)"guest_file", cf_string, CA_STATIC, CA_GOD, (int *)mudconf.guest_file, SBUF_SIZE},
{(char *)"guests_calias", cf_string, CA_STATIC, CA_PUBLIC, (int *)mudconf.guests_calias, SBUF_SIZE},
{(char *)"guests_channel", cf_string, CA_STATIC, CA_PUBLIC, (int *)mudconf.guests_channel, SBUF_SIZE},
{(char *)"guest_site", cf_site, CA_GOD, CA_DISABLED, (int *)&mudstate.access_list, H_GUEST},
{(char *)"guest_starting_room", cf_int, CA_GOD, CA_WIZARD, &mudconf.guest_start_room, 0},
#ifdef USE_COMSYS
{(char *)"have_comsys", cf_bool, CA_STATIC, CA_PUBLIC, &mudconf.have_comsys, (long)"Built-in comsys enabled"},
#else
{(char *)"have_comsys", cf_const, CA_STATIC, CA_PUBLIC, &mudconf.have_comsys, (long)"Built-in comsys enabled"},
#endif
#ifdef USE_MAIL
{(char *)"have_mailer", cf_bool, CA_STATIC, CA_PUBLIC, &mudconf.have_mailer, (long)"Built-in @mail system enabled"},
#else
{(char *)"have_mailer", cf_const, CA_STATIC, CA_PUBLIC, &mudconf.have_mailer, (long)"Built-in @mail system enabled"},
#endif
{(char *)"have_pueblo", cf_const, CA_STATIC, CA_PUBLIC, &mudconf.have_pueblo, (long)"Pueblo client extensions are supported"},
{(char *)"have_zones", cf_bool, CA_STATIC, CA_PUBLIC, &mudconf.have_zones, (long)"Multiple control via ControlLocks is permitted"},
{(char *)"helpfile", cf_helpfile, CA_STATIC, CA_DISABLED, NULL, 0},
{(char *)"hostnames", cf_bool, CA_GOD, CA_WIZARD, &mudconf.use_hostname, (long)"DNS lookups are done on hostnames"},
#ifdef PUEBLO_SUPPORT
{(char *)"html_connect_file", cf_string, CA_STATIC, CA_GOD, (int *) mudconf.htmlconn_file, SBUF_SIZE},
{(char *)"pueblo_message", cf_string, CA_GOD, CA_WIZARD, (int *) mudconf.pueblo_msg, GBUF_SIZE},
#endif
{(char *)"idle_wiz_dark", cf_bool, CA_GOD, CA_WIZARD, &mudconf.idle_wiz_dark, (long)"Wizards who idle are set DARK"},
{(char *)"idle_interval", cf_int, CA_GOD, CA_WIZARD, &mudconf.idle_interval, 0},
{(char *)"idle_timeout", cf_int, CA_GOD, CA_PUBLIC, &mudconf.idle_timeout, 0},
{(char *)"include", cf_include, CA_STATIC, CA_DISABLED, NULL, 0},
{(char *)"indent_desc", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.indent_desc, (long)"Descriptions are indented"},
{(char *)"initial_size", cf_int, CA_STATIC, CA_WIZARD, &mudconf.init_size, 0},
{(char *)"input_database", cf_string, CA_STATIC, CA_GOD, (int *)mudconf.indb, PBUF_SIZE},
{(char *)"instance_limit", cf_int, CA_GOD, CA_PUBLIC, &mudconf.instance_lim, 0},
{(char *)"instant_recycle", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.instant_recycle, (long)"@destroy instantly recycles objects set DESTROY_OK"},
{(char *)"kill_guarantee_cost", cf_int, CA_GOD, CA_PUBLIC, &mudconf.killguarantee, 0},
{(char *)"kill_max_cost", cf_int, CA_GOD, CA_PUBLIC, &mudconf.killmax, 0},
{(char *)"kill_min_cost", cf_int, CA_GOD, CA_PUBLIC, &mudconf.killmin, 0},
{(char *)"lag_check", cf_const, CA_STATIC, CA_PUBLIC, &mudconf.lag_check, (long)"CPU usage warnings are enabled"},
{(char *)"lag_maximum", cf_int, CA_GOD, CA_WIZARD, &mudconf.max_cmdsecs, 0},
{(char *)"lattr_default_oldstyle", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.lattr_oldstyle, (long)"Empty lattr() returns blank, not #-1 NO MATCH"},
{(char *)"link_cost", cf_int, CA_GOD, CA_PUBLIC, &mudconf.linkcost, 0},
{(char *)"list_access", cf_ntab_access, CA_GOD, CA_DISABLED, (int *)list_names, (long)access_nametab},
{(char *)"local_master_rooms", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.local_masters, (long)"Objects set ZONE act as local master rooms"},
{(char *)"lock_recursion_limit", cf_int, CA_WIZARD, CA_PUBLIC, &mudconf.lock_nest_lim, 0},
{(char *)"log", cf_modify_bits, CA_GOD, CA_DISABLED, &mudconf.log_options, (long)logoptions_nametab},
{(char *)"log_options", cf_modify_bits, CA_GOD, CA_DISABLED, &mudconf.log_info, (long)logdata_nametab},
{(char *)"logout_cmd_access", cf_ntab_access, CA_GOD, CA_DISABLED, (int *)logout_cmdtable, (long)access_nametab},
{(char *)"logout_cmd_alias", cf_alias, CA_GOD, CA_DISABLED, (int *)&mudstate.logout_cmd_htab,0},
{(char *)"look_obey_terse", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.terse_look, (long)"look obeys the TERSE flag"},
{(char *)"machine_command_cost", cf_int, CA_GOD, CA_PUBLIC, &mudconf.machinecost, 0},
{(char *)"mail_database", cf_string, CA_STATIC, CA_GOD, (int *)mudconf.mail_db, PBUF_SIZE},
{(char *)"mail_expiration", cf_int, CA_GOD, CA_PUBLIC, &mudconf.mail_expiration, 0},
{(char *)"master_room", cf_int, CA_GOD, CA_WIZARD, &mudconf.master_room, 0},
{(char *)"match_own_commands", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.match_mine, (long)"Non-players can match $-commands on themselves"},
{(char *)"max_players", cf_int, CA_GOD, CA_WIZARD, &mudconf.max_players, 0},
{(char *)"money_name_plural", cf_string, CA_GOD, CA_PUBLIC, (int *)mudconf.many_coins, SBUF_SIZE},
{(char *)"money_name_singular", cf_string, CA_GOD, CA_PUBLIC, (int *)mudconf.one_coin, SBUF_SIZE},
{(char *)"motd_file", cf_string, CA_STATIC, CA_GOD, (int *)mudconf.motd_file, SBUF_SIZE},
{(char *)"motd_message", cf_string, CA_GOD, CA_WIZARD, (int *)mudconf.motd_msg, GBUF_SIZE},
{(char *)"move_match_more", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.move_match_more, (long)"Move command checks for global and zone exits,\n\t\t\t\tresolves ambiguity"},
{(char *)"mud_name", cf_string, CA_GOD, CA_PUBLIC, (int *)mudconf.mud_name, SBUF_SIZE},
{(char *)"newuser_file", cf_string, CA_STATIC, CA_GOD, (int *)mudconf.crea_file, SBUF_SIZE},
{(char *)"no_ambiguous_match", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.no_ambiguous_match, (long)"Ambiguous matches resolve to the last match"},
{(char *)"notify_recursion_limit", cf_int, CA_GOD, CA_PUBLIC, &mudconf.ntfy_nest_lim, 0},
{(char *)"open_cost", cf_int, CA_GOD, CA_PUBLIC, &mudconf.opencost, 0},
{(char *)"opt_frequency", cf_int, CA_GOD, CA_WIZARD, &mudconf.dbopt_interval, 0},
{(char *)"output_database", cf_string, CA_STATIC, CA_GOD, (int *)mudconf.outdb, PBUF_SIZE},
{(char *)"output_limit", cf_int, CA_GOD, CA_WIZARD, &mudconf.output_limit, 0},
{(char *)"page_cost", cf_int, CA_GOD, CA_PUBLIC, &mudconf.pagecost, 0},
{(char *)"paranoid_allocate", cf_bool, CA_GOD, CA_WIZARD, &mudconf.paranoid_alloc, (long)"Buffer pools sanity-checked on alloc/free"},
{(char *)"parent_recursion_limit", cf_int, CA_GOD, CA_PUBLIC, &mudconf.parent_nest_lim, 0},
{(char *)"paycheck", cf_int, CA_GOD, CA_PUBLIC, &mudconf.paycheck, 0},
{(char *)"pemit_far_players", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.pemit_players, (long)"@pemit targets can be players in other locations"},
{(char *)"pemit_any_object", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.pemit_any, (long)"@pemit targets can be objects in other locations"},
{(char *)"permit_site", cf_site, CA_GOD, CA_DISABLED, (int *)&mudstate.access_list, 0},
{(char *)"player_flags", cf_set_flags, CA_GOD, CA_DISABLED, (int *)&mudconf.player_flags, 0},
{(char *)"player_listen", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.player_listen, (long)"@listen and ^-monitors are checked on players"},
{(char *)"player_match_own_commands", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.match_mine_pl, (long)"Players can match $-commands on themselves"},
{(char *)"player_name_spaces", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.name_spaces, (long)"Player names can contain spaces"},
{(char *)"player_parent", cf_int, CA_GOD, CA_PUBLIC, &mudconf.player_parent, 0},
{(char *)"player_queue_limit", cf_int, CA_GOD, CA_PUBLIC, &mudconf.queuemax, 0},
{(char *)"player_quota", cf_int, CA_GOD, CA_PUBLIC, &mudconf.player_quota, 0},
{(char *)"player_starting_home", cf_int, CA_GOD, CA_PUBLIC, &mudconf.start_home, 0},
{(char *)"player_starting_room", cf_int, CA_GOD, CA_PUBLIC, &mudconf.start_room, 0},
{(char *)"public_calias", cf_string, CA_STATIC, CA_PUBLIC, (int *)mudconf.public_calias, SBUF_SIZE},
{(char *)"public_channel", cf_string, CA_STATIC, CA_PUBLIC, (int *)mudconf.public_channel, SBUF_SIZE},
{(char *)"port", cf_int, CA_STATIC, CA_PUBLIC, &mudconf.port, 0},
{(char *)"power_access", cf_power_access,CA_GOD, CA_DISABLED, NULL, 0},
{(char *)"public_flags", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.pub_flags, (long)"Flag information is public"},
{(char *)"queue_active_chunk", cf_int, CA_GOD, CA_PUBLIC, &mudconf.active_q_chunk, 0},
{(char *)"queue_idle_chunk", cf_int, CA_GOD, CA_PUBLIC, &mudconf.queue_chunk, 0},
{(char *)"quiet_look", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.quiet_look, (long)"look shows public attributes in addition to @Desc"},
{(char *)"quiet_whisper", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.quiet_whisper, (long)"whisper is quiet"},
{(char *)"quit_file", cf_string, CA_STATIC, CA_GOD, (int *)mudconf.quit_file, SBUF_SIZE},
{(char *)"quotas", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.quotas, (long)"Quotas are enforced"},
{(char *)"raw_helpfile", cf_raw_helpfile,CA_STATIC, CA_DISABLED, NULL, 0},
{(char *)"read_remote_desc", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.read_rem_desc, (long)"@Desc is public, even to players not nearby"},
{(char *)"read_remote_name", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.read_rem_name, (long)"Names are public, even to players not nearby"},
{(char *)"register_create_file", cf_string, CA_STATIC, CA_GOD, (int *)mudconf.regf_file, SBUF_SIZE},
{(char *)"register_site", cf_site, CA_GOD, CA_DISABLED, (int *)&mudstate.access_list, H_REGISTRATION},
{(char *)"require_cmds_flag", cf_bool, CA_GOD, CA_PUBLIC, (int *)&mudconf.req_cmds_flag, (long)"Only objects with COMMANDS flag are searched\n\t\t\t\tfor $-commands"},
{(char *)"retry_limit", cf_int, CA_GOD, CA_WIZARD, &mudconf.retry_limit, 0},
{(char *)"robot_cost", cf_int, CA_GOD, CA_PUBLIC, &mudconf.robotcost, 0},
{(char *)"robot_flags", cf_set_flags, CA_GOD, CA_DISABLED, (int *)&mudconf.robot_flags, 0},
{(char *)"robot_speech", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.robot_speak, (long)"Robots can speak in locations their owners do not\n\t\t\t\tcontrol"},
{(char *)"room_flags", cf_set_flags, CA_GOD, CA_DISABLED, (int *)&mudconf.room_flags, 0},
{(char *)"room_parent", cf_int, CA_GOD, CA_PUBLIC, &mudconf.room_parent, 0},
{(char *)"room_quota", cf_int, CA_GOD, CA_PUBLIC, &mudconf.room_quota, 0},
{(char *)"sacrifice_adjust", cf_int, CA_GOD, CA_PUBLIC, &mudconf.sacadjust, 0},
{(char *)"sacrifice_factor", cf_int, CA_GOD, CA_PUBLIC, &mudconf.sacfactor, 0},
{(char *)"safer_passwords", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.safer_passwords, (long)"Passwords must satisfy minimum security standards"},
{(char *)"search_cost", cf_int, CA_GOD, CA_PUBLIC, &mudconf.searchcost, 0},
{(char *)"see_owned_dark", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.see_own_dark, (long)"look shows DARK objects owned by you"},
{(char *)"signal_action", cf_option, CA_STATIC, CA_GOD, &mudconf.sig_action, (long)sigactions_nametab},
{(char *)"site_chars", cf_int, CA_GOD, CA_WIZARD, &mudconf.site_chars, 0},
{(char *)"space_compress", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.space_compress, (long)"Multiple spaces are compressed to a single space"},
{(char *)"sql_database", cf_string, CA_STATIC, CA_GOD, (int *)mudconf.sql_db, MBUF_SIZE},
{(char *)"sql_host", cf_string, CA_STATIC, CA_GOD, (int *)mudconf.sql_host, MBUF_SIZE},
{(char *)"sql_username", cf_string, CA_STATIC, CA_GOD, (int *)mudconf.sql_username, MBUF_SIZE},
{(char *)"sql_password", cf_string, CA_STATIC, CA_GOD, (int *)mudconf.sql_password, MBUF_SIZE},
{(char *)"sql_reconnect", cf_bool, CA_GOD, CA_WIZARD, &mudconf.sql_reconnect, (long)"SQL queries re-initiate dropped connections"},
{(char *)"stack_limit", cf_int, CA_GOD, CA_PUBLIC, &mudconf.stack_lim, 0},
{(char *)"starting_money", cf_int, CA_GOD, CA_PUBLIC, &mudconf.paystart, 0},
{(char *)"starting_quota", cf_int, CA_GOD, CA_PUBLIC, &mudconf.start_quota, 0},
{(char *)"starting_exit_quota", cf_int, CA_GOD, CA_PUBLIC, &mudconf.start_exit_quota, 0},
{(char *)"starting_player_quota", cf_int, CA_GOD, CA_PUBLIC, &mudconf.start_player_quota, 0},
{(char *)"starting_room_quota", cf_int, CA_GOD, CA_PUBLIC, &mudconf.start_room_quota, 0},
{(char *)"starting_thing_quota", cf_int, CA_GOD, CA_PUBLIC, &mudconf.start_thing_quota, 0},
{(char *)"status_file", cf_string, CA_STATIC, CA_GOD, (int *)mudconf.status_file, PBUF_SIZE},
{(char *)"stripped_flags", cf_set_flags, CA_GOD, CA_DISABLED, (int *)&mudconf.stripped_flags, 0},
{(char *)"structure_limit", cf_int, CA_GOD, CA_PUBLIC, &mudconf.struct_lim, 0},
{(char *)"suspect_site", cf_site, CA_GOD, CA_DISABLED, (int *)&mudstate.suspect_list, H_SUSPECT},
{(char *)"sweep_dark", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.sweep_dark, (long)"@sweep works on Dark locations"},
{(char *)"switch_default_all", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.switch_df_all, (long)"@switch default is /all, not /first"},
{(char *)"terse_shows_contents", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.terse_contents, (long)"TERSE suppresses the contents list of a location"},
{(char *)"terse_shows_exits", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.terse_exits, (long)"TERSE suppresses the exit list of a location"},
{(char *)"terse_shows_move_messages", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.terse_movemsg, (long)"TERSE suppresses movement messages"},
{(char *)"thing_flags", cf_set_flags, CA_GOD, CA_DISABLED, (int *)&mudconf.thing_flags, 0},
{(char *)"thing_parent", cf_int, CA_GOD, CA_PUBLIC, &mudconf.thing_parent, 0},
{(char *)"thing_quota", cf_int, CA_GOD, CA_PUBLIC, &mudconf.thing_quota, 0},
{(char *)"timeslice", cf_int, CA_GOD, CA_PUBLIC, &mudconf.timeslice, 0},
{(char *)"trace_output_limit", cf_int, CA_GOD, CA_PUBLIC, &mudconf.trace_limit, 0},
{(char *)"trace_topdown", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.trace_topdown, (long)"Trace output is top-down"},
{(char *)"trust_site", cf_site, CA_GOD, CA_DISABLED, (int *)&mudstate.suspect_list, 0},
{(char *)"typed_quotas", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.typed_quotas, (long)"Quotas are enforced per object type"},
{(char *)"uncompress_program", cf_string, CA_STATIC, CA_GOD, (int *)mudconf.uncompress, PBUF_SIZE},
{(char *)"unowned_safe", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.safe_unowned, (long)"Objects not owned by you are considered SAFE"},
{(char *)"user_attr_access", cf_modify_bits, CA_GOD, CA_DISABLED, &mudconf.vattr_flags, (long)attraccess_nametab},
{(char *)"use_global_aconn", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.use_global_aconn, (long)"Global @aconnects and @adisconnects are used"},
{(char *)"variables_limit", cf_int, CA_GOD, CA_PUBLIC, &mudconf.numvars_lim, 0},
{(char *)"wait_cost", cf_int, CA_GOD, CA_PUBLIC, &mudconf.waitcost, 0},
{(char *)"wizard_obeys_linklock", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.wiz_obey_linklock, (long)"Check LinkLock even if player can link to anything"},
{(char *)"wizard_motd_file", cf_string, CA_STATIC, CA_GOD, (int *)mudconf.wizmotd_file, SBUF_SIZE},
{(char *)"wizard_motd_message", cf_string, CA_GOD, CA_WIZARD, (int *)mudconf.wizmotd_msg, GBUF_SIZE},
{(char *)"zone_recursion_limit", cf_int, CA_GOD, CA_PUBLIC, &mudconf.zone_nest_lim, 0},
{ NULL, NULL, 0, 0, NULL, 0}};
/* *INDENT-ON* */
/* ---------------------------------------------------------------------------
* 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, NOPERM_MESSAGE);
return (-1);
}
if (!mudstate.initializing) {
buff = alloc_lbuf("cf_set");
StringCopy(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) {
StringCopy(mudconf.outdb, mudconf.indb);
strcat(mudconf.outdb, ".out");
}
if (!*mudconf.crashdb) {
StringCopy(mudconf.crashdb, mudconf.indb);
strcat(mudconf.crashdb, ".CRASH");
}
if (!*mudconf.gdbm) {
StringCopy(mudconf.gdbm, mudconf.indb);
strcat(mudconf.gdbm, ".gdbm");
}
return retval;
}
/*
* ---------------------------------------------------------------------------
* * list_cf_access, list_cf_read_access: List write or read 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);
}
void list_cf_read_access(player)
dbref player;
{
CONF *tp;
char *buff;
buff = alloc_mbuf("list_cf_read_access");
for (tp = conftable; tp->pname; tp++) {
if (God(player) || check_access(player, tp->rperms)) {
sprintf(buff, "%s:", tp->pname);
listset_nametab(player, access_nametab, tp->rperms,
buff, 1);
}
}
free_mbuf(buff);
}
/* ---------------------------------------------------------------------------
* cf_display: Given a config parameter by name, return its value in some
* sane fashion.
*/
void cf_display(player, param_name, buff, bufc)
dbref player;
char *param_name;
char *buff;
char **bufc;
{
CONF *tp;
for (tp = conftable; tp->pname; tp++) {
if (!strcasecmp(tp->pname, param_name)) {
if (!check_access(player, tp->rperms)) {
safe_noperm(buff, bufc);
return;
}
if ((tp->interpreter == cf_int) ||
(tp->interpreter == cf_bool) ||
(tp->interpreter == cf_const)) {
safe_ltos(buff, bufc, *(tp->loc));
return;
}
if ((tp->interpreter == cf_string)) {
safe_str((char *) tp->loc, buff, bufc);
return;
}
safe_noperm(buff, bufc);
return;
}
}
safe_nomatch(buff, bufc);
}
void list_options(player)
dbref player;
{
CONF *tp;
for (tp = conftable; tp->pname; tp++) {
if (((tp->interpreter == cf_const) ||
(tp->interpreter == cf_bool)) &&
(check_access(player, tp->rperms))) {
raw_notify(player, tprintf("%-25s %c %s?",
tp->pname,
(*(tp->loc) ? 'Y' : 'N'),
(tp->extra ? (char *)tp->extra : "")));
}
}
}
#endif /*
* * STANDALONE
*/