/* conf.c - configuration functions and defaults */
/* $Id: conf.c,v 1.192 2004/10/09 23:17:03 tyrspace Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include "alloc.h" /* required by mudconf */
#include "flags.h" /* required by mudconf */
#include "htab.h" /* required by mudconf */
#include "mudconf.h" /* required by code */
#include "db.h" /* required by externs */
#include "externs.h" /* required by interface */
#include "interface.h" /* required by code */
#include "command.h" /* required by code */
#include "attrs.h" /* required by code */
#include "match.h" /* required by code */
#include "ansi.h" /* required by code */
/* 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
/*
* ---------------------------------------------------------------------------
* * External symbols.
*/
CONFDATA mudconf;
STATEDATA mudstate;
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[];
/* ---------------------------------------------------------------------------
* cf_init: Initialize mudconf to default values.
*/
void NDECL(cf_init)
{
char *s;
s = XMALLOC(MBUF_SIZE, "cf_init");
mudconf.status_file = XSTRDUP("shutdown.status", "cf_string");
mudstate.modules_list = NULL;
mudstate.modloaded[0] = '\0';
mudconf.port = 6250;
mudconf.conc_port = 6251;
mudconf.init_size = 1000;
mudconf.use_global_aconn = 1;
mudconf.global_aconn_uselocks = 0;
mudconf.guest_char = NOTHING;
mudconf.guest_nuker = GOD;
mudconf.number_guests = 30;
mudconf.guest_basename = XSTRDUP("Guest", "cf_string");
mudconf.guest_password = XSTRDUP("guest", "cf_string");
mudconf.guest_prefixes = XSTRDUP("", "cf_string");
mudconf.guest_suffixes = XSTRDUP("", "cf_string");
sprintf(s, "%s/guest.txt", mudconf.txthome);
mudconf.guest_file = XSTRDUP(s, "cf_string");
sprintf(s, "%s/connect.txt", mudconf.txthome);
mudconf.conn_file = XSTRDUP(s, "cf_string");
sprintf(s, "%s/register.txt", mudconf.txthome);
mudconf.creg_file = XSTRDUP(s, "cf_string");
sprintf(s, "%s/create_reg.txt", mudconf.txthome);
mudconf.regf_file = XSTRDUP(s, "cf_string");
sprintf(s, "%s/motd.txt", mudconf.txthome);
mudconf.motd_file = XSTRDUP(s, "cf_string");
sprintf(s, "%s/wizmotd.txt", mudconf.txthome);
mudconf.wizmotd_file = XSTRDUP(s, "cf_string");
sprintf(s, "%s/quit.txt", mudconf.txthome);
mudconf.quit_file = XSTRDUP(s, "cf_string");
sprintf(s, "%s/down.txt", mudconf.txthome);
mudconf.down_file = XSTRDUP(s, "cf_string");
sprintf(s, "%s/full.txt", mudconf.txthome);
mudconf.full_file = XSTRDUP(s, "cf_string");
sprintf(s, "%s/badsite.txt", mudconf.txthome);
mudconf.site_file = XSTRDUP(s, "cf_string");
sprintf(s, "%s/newuser.txt", mudconf.txthome);
mudconf.crea_file = XSTRDUP(s, "cf_string");
#ifdef PUEBLO_SUPPORT
sprintf(s, "%s/htmlconn.txt", mudconf.txthome);
mudconf.htmlconn_file = XSTRDUP(s, "cf_string");
#endif
mudconf.motd_msg = XSTRDUP("", "cf_string");
mudconf.wizmotd_msg = XSTRDUP("", "cf_string");
mudconf.downmotd_msg = XSTRDUP("", "cf_string");
mudconf.fullmotd_msg = XSTRDUP("", "cf_string");
mudconf.dump_msg = XSTRDUP("", "cf_string");
mudconf.postdump_msg = XSTRDUP("", "cf_string");
mudconf.fixed_home_msg = XSTRDUP("", "cf_string");
mudconf.fixed_tel_msg = XSTRDUP("", "cf_string");
mudconf.huh_msg = XSTRDUP("Huh? (Type \"help\" for help.)", "cf_string");
#ifdef PUEBLO_SUPPORT
mudconf.pueblo_msg = XSTRDUP("</xch_mudtext><img xch_mode=html><tt>", "cf_string");
#endif
mudconf.sql_host = XSTRDUP("127.0.0.1", "cf_string");
mudconf.sql_db = XSTRDUP("", "cf_string");
mudconf.sql_username = XSTRDUP("", "cf_string");
mudconf.sql_password = XSTRDUP("", "cf_string");
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 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.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.visible_wizzes = 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_objeval = 0;
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.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;
mudconf.page_req_equals = 0;
mudconf.comma_say = 0;
mudconf.you_say = 1;
mudconf.c_cmd_subst = 1;
mudconf.register_limit = 50;
/* -- ??? 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_proto = NOTHING;
mudconf.room_proto = NOTHING;
mudconf.exit_proto = NOTHING;
mudconf.thing_proto = NOTHING;
mudconf.player_defobj = NOTHING;
mudconf.room_defobj = NOTHING;
mudconf.thing_defobj = NOTHING;
mudconf.exit_defobj = 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 = 0;
mudconf.vattr_flag_list = NULL;
mudconf.mud_name = XSTRDUP("TinyMUSH", "cf_string");
mudconf.one_coin = XSTRDUP("penny", "cf_string");
mudconf.many_coins = XSTRDUP("pennies", "cf_string");
mudconf.struct_dstr = XSTRDUP("\r\n", "cf_string");
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 | LOG_LOCAL;
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.wild_times_lim = 25000;
mudconf.cmd_nest_lim = 50;
mudconf.cmd_invk_lim = 2500;
mudconf.func_nest_lim = 50;
mudconf.func_invk_lim = 2500;
mudconf.func_cpu_lim_secs = 60;
mudconf.func_cpu_lim = 60 * CLOCKS_PER_SEC;
mudconf.ntfy_nest_lim = 20;
mudconf.fwdlist_lim = 100;
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.max_player_aliases = 10;
mudconf.cache_width = CACHE_WIDTH;
mudconf.cache_size = CACHE_SIZE;
mudstate.initializing = 0;
mudstate.loading_db = 0;
mudstate.panicking = 0;
mudstate.standalone = 0;
mudstate.dumping = 0;
mudstate.dumper = 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.flatfile_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.moduletype_top = DBTYPE_RESERVED;
mudstate.freelist = NOTHING;
mudstate.markbits = NULL;
mudstate.sql_socket = -1;
mudstate.cmd_nest_lev = 0;
mudstate.cmd_invk_ctr = 0;
mudstate.func_nest_lev = 0;
mudstate.func_invk_ctr = 0;
mudstate.wild_times_lev = 0;
mudstate.cputime_base = clock();
mudstate.ntfy_nest_lev = 0;
mudstate.lock_nest_lev = 0;
mudstate.zone_nest_num = 0;
mudstate.in_loop = 0;
mudstate.loop_token[0] = NULL;
mudstate.loop_number[0] = 0;
mudstate.in_switch = 0;
mudstate.switch_token = NULL;
mudstate.inpipe = 0;
mudstate.pout = NULL;
mudstate.poutnew = NULL;
mudstate.poutbufc = NULL;
mudstate.poutobj = -1;
mudstate.dbm_fd = -1;
mudstate.rdata = NULL;
XFREE(s, "cf_init");
}
/* ---------------------------------------------------------------------------
* 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;
{
if (mudstate.initializing) {
STARTLOG(LOG_STARTUP, "CNF", "NFND")
log_printf("%s: %s %s not found", cmd, thingname, thing);
ENDLOG
} else {
notify(player, tprintf("%s %s not found", thingname, thing));
}
}
/* ---------------------------------------------------------------------------
* cf_log_syntax: Log a syntax error.
*/
#if defined(__STDC__) && defined(STDC_HEADERS)
void cf_log_syntax(dbref player, char *cmd, const char *template,...)
#else
void cf_log_syntax(va_alist)
va_dcl
#endif
{
va_list ap;
#if defined(__STDC__) && defined(STDC_HEADERS)
va_start(ap, template);
#else
dbref player;
char *cmd, *template;
player = va_arg(ap, dbref);
cmd = va_arg(ap, char *);
template = va_arg(ap, char *);
#endif
if (mudstate.initializing) {
STARTLOG(LOG_STARTUP, "CNF", "SYNTX")
log_printf("%s: ", cmd);
log_vprintf(template, ap);
ENDLOG
} else {
notify(player, tvprintf(template, ap));
}
va_end(ap);
}
/* ---------------------------------------------------------------------------
* 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;
{
/*
* 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")
log_printf("%s: Nothing to set", cmd);
ENDLOG
} else {
notify(player, "Nothing to set");
}
}
return -1;
}
/* ---------------------------------------------------------------------------
* cf_const: Read-only integer or boolean parameter.
*/
CF_HAND(cf_const)
{
/* Fail on any attempt to change the value */
return -1;
}
/* ---------------------------------------------------------------------------
* cf_int: Set integer parameter.
*/
CF_HAND(cf_int)
{
/* Copy the numeric value to the parameter */
if ((extra > 0) && (atoi(str) > extra)) {
cf_log_syntax(player, cmd, "Value exceeds limit of %d", extra);
return -1;
}
sscanf(str, "%d", vp);
return 0;
}
/* ---------------------------------------------------------------------------
* cf_int_factor: Set integer parameter that will be used as a factor
* (ie. cannot be set to 0)
*/
CF_HAND(cf_int_factor)
{
int num;
/* Copy the numeric value to the parameter */
num = atoi(str);
if ((extra > 0) && (num > extra)) {
cf_log_syntax(player, cmd, "Value exceeds limit of %d", extra);
return -1;
}
if (num == 0) {
cf_log_syntax(player, cmd, "Value cannot be 0. You may want a value of 1.");
return -1;
}
sscanf(str, "%d", vp);
return 0;
}
/* ---------------------------------------------------------------------------
* cf_dbref: Set dbref parameter.
*/
CF_HAND(cf_dbref)
{
int num;
/* No consistency check on initialization. */
if (mudstate.initializing) {
if (*str == '#') {
sscanf(str, "#%d", vp);
} else {
sscanf(str, "%d", vp);
}
return 0;
}
/* Otherwise we have to validate this. If 'extra' is non-zero, the
* dbref is allowed to be NOTHING.
*/
if (*str == '#')
num = atoi(str + 1);
else
num = atoi(str);
if (((extra == NOTHING) && (num == NOTHING)) ||
(Good_obj(num) && !Going(num))) {
if (*str == '#') {
sscanf(str, "#%d", vp);
} else {
sscanf(str, "%d", vp);
}
return 0;
}
if (extra == NOTHING) {
cf_log_syntax(player, cmd, "A valid dbref, or -1, is required.");
} else {
cf_log_syntax(player, cmd, "A valid dbref is required.");
}
return -1;
}
/* ---------------------------------------------------------------------------
* cf_module: Open a loadable module. Modules are initialized later in the
* startup.
*/
CF_HAND(cf_module)
{
lt_dlhandle handle;
void (*initptr)(void);
MODULE *mp;
handle = lt_dlopen(tprintf("%s.la", str));
if (!handle) {
STARTLOG(LOG_STARTUP, "CNF", "MOD")
log_printf("Loading of %s module failed: %s",
str, lt_dlerror());
ENDLOG
return -1;
}
mp = (MODULE *) XMALLOC(sizeof(MODULE), "cf_module.mp");
mp->modname = XSTRDUP(str, "cf_module.name");
mp->handle = handle;
mp->next = mudstate.modules_list;
mudstate.modules_list = mp;
/* Look up our symbols now, and cache the pointers. They're
* not going to change from here on out.
*/
mp->process_command = DLSYM_INT(handle, str, "process_command",
(dbref, dbref, int, char *,
char *[], int));
mp->process_no_match = DLSYM_INT(handle, str, "process_no_match",
(dbref, dbref, int, char *, char *,
char *[], int));
mp->did_it = DLSYM_INT(handle, str, "did_it",
(dbref, dbref, dbref,
int, const char *, int, const char *, int,
int, char *[], int, int));
mp->create_obj = DLSYM(handle, str, "create_obj", (dbref, dbref));
mp->destroy_obj = DLSYM(handle, str, "destroy_obj", (dbref, dbref));
mp->create_player = DLSYM(handle, str, "create_player",
(dbref, dbref, int, int));
mp->destroy_player = DLSYM(handle, str, "destroy_player",
(dbref, dbref));
mp->announce_connect = DLSYM(handle, str, "announce_connect",
(dbref, const char *, int));
mp->announce_disconnect = DLSYM(handle, str, "announce_disconnect",
(dbref, const char *, int));
mp->examine = DLSYM(handle, str, "examine",
(dbref, dbref, dbref, int, int));
mp->dump_database = DLSYM(handle, str, "dump_database", (FILE *));
mp->db_grow = DLSYM(handle, str, "db_grow", (int, int));
mp->db_write = DLSYM(handle, str, "db_write", (void));
mp->db_write_flatfile = DLSYM(handle, str, "db_write_flatfile", (FILE *));
mp->do_second = DLSYM(handle, str, "do_second", (void));
mp->cache_put_notify = DLSYM(handle, str, "cache_put_notify", (DBData, unsigned int));
mp->cache_del_notify = DLSYM(handle, str, "cache_del_notify", (DBData, unsigned int));
if (!mudstate.standalone) {
if ((initptr = DLSYM(handle, str, "init", (void))) != NULL)
(*initptr)();
}
STARTLOG(LOG_STARTUP, "CNF", "MOD")
log_printf("Loaded module: %s", str);
ENDLOG
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;
/*
* Make a copy of the string if it is not too big
*/
retval = 0;
if (strlen(str) >= (unsigned int)extra) {
str[extra - 1] = '\0';
if (mudstate.initializing) {
STARTLOG(LOG_STARTUP, "CNF", "NFND")
log_printf("%s: String truncated", cmd);
ENDLOG
} else {
notify(player, "String truncated");
}
retval = 1;
}
XFREE(*(char **)vp, "cf_string");
*(char **)vp = XSTRDUP(str, "cf_string");
return retval;
}
/* ---------------------------------------------------------------------------
* cf_alias: define a generic hash table alias.
*/
CF_HAND(cf_alias)
{
char *alias, *orig, *p, *tokst;
int *cp, upcase;
alias = strtok_r(str, " \t=,", &tokst);
orig = strtok_r(NULL, " \t=,", &tokst);
if (orig) {
upcase = 0;
for (p = orig; *p; p++)
*p = tolower(*p);
cp = hashfind(orig, (HASHTAB *) vp);
if (cp == NULL) {
upcase++;
for (p = orig; *p; p++)
*p = toupper(*p);
cp = hashfind(orig, (HASHTAB *) vp);
if (cp == NULL) {
cf_log_notfound(player, cmd,
(char *) extra, orig);
return -1;
}
}
if (upcase) {
for (p = alias; *p; p++)
*p = toupper(*p);
} else {
for (p = alias; *p; p++)
*p = tolower(*p);
}
if (((HASHTAB *)vp)->flags & HT_KEYREF) {
/* hashadd won't copy it, so we do that here */
p = alias;
alias = XSTRDUP(p, "cf_alias");
}
return hashadd(alias, cp, (HASHTAB *) vp, HASH_ALIAS);
} else {
cf_log_syntax(player, cmd, "Invalid original for alias %s",
alias);
return -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_printf("Log type %s already diverted: %s",
type_str, 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_printf("Cannot open logfile: %s", 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_printf("Cannot make nonblocking: %s", file_str);
ENDLOG
return -1;
}
#else
if (fcntl(fd, F_SETFL, O_NDELAY) == -1) {
STARTLOG(LOG_STARTUP, "CNF", "DIVT")
log_printf("Cannot make nonblocking: %s", file_str);
ENDLOG
return -1;
}
#endif
}
/* Indicate that this is being diverted. */
tp->fileptr = fptr;
tp->filename = XSTRDUP(file_str, "cf_divert_log");
*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);
}
/* ---------------------------------------------------------------------------
* modify_xfuncs: Helper function to change xfuncs.
*/
static NAMEDFUNC **all_named_funcs = NULL;
static int num_named_funcs = 0;
static int modify_xfuncs(fn_name, fn_ptr, xfuncs, negate)
char *fn_name;
int (*fn_ptr)(dbref);
EXTFUNCS **xfuncs;
int negate; /* 0 - normal, 1 - remove */
{
EXTFUNCS *xfp;
NAMEDFUNC *np, **tp;
int i;
xfp = *xfuncs;
/* If we're negating, just remove it from the list of functions. */
if (negate) {
if (!xfp)
return 0;
for (i = 0; i < xfp->num_funcs; i++) {
if (!strcmp(xfp->ext_funcs[i]->fn_name, fn_name)) {
xfp->ext_funcs[i] = NULL;
return 1;
}
}
return 0;
}
/* Have we encountered this function before? */
np = NULL;
for (i = 0; i < num_named_funcs; i++) {
if (!strcmp(all_named_funcs[i]->fn_name, fn_name)) {
np = all_named_funcs[i];
break;
}
}
/* If not, we need to allocate it. */
if (!np) {
np = (NAMEDFUNC *) XMALLOC(sizeof(NAMEDFUNC), "nfunc");
np->fn_name = (char *) strdup(fn_name);
np->handler = fn_ptr;
}
/* Add it to the ones we know about. */
if (num_named_funcs == 0) {
all_named_funcs = (NAMEDFUNC **) XMALLOC(sizeof(NAMEDFUNC *),
"all_named_funcs");
num_named_funcs = 1;
all_named_funcs[0] = np;
} else {
tp = (NAMEDFUNC **) XREALLOC(all_named_funcs,
(num_named_funcs + 1) * sizeof(NAMEDFUNC *),
"all_named_funcs");
tp[num_named_funcs] = np;
all_named_funcs = tp;
num_named_funcs++;
}
/* Do we have an existing list of functions? If not, this is easy. */
if (!xfp) {
xfp = (EXTFUNCS *) XMALLOC(sizeof(EXTFUNCS), "xfunc");
xfp->num_funcs = 1;
xfp->ext_funcs = (NAMEDFUNC **) XMALLOC(sizeof(NAMEDFUNC *), "nfuncs");
xfp->ext_funcs[0] = np;
*xfuncs = xfp;
return 1;
}
/* See if we have an empty slot to insert into. */
for (i = 0; i < xfp->num_funcs; i++) {
if (!xfp->ext_funcs[i]) {
xfp->ext_funcs[i] = np;
return 1;
}
}
/* Guess not. Tack it onto the end. */
tp = (NAMEDFUNC **) XREALLOC(xfp->ext_funcs,
(xfp->num_funcs + 1) * sizeof(NAMEDFUNC *),
"nfuncs");
tp[xfp->num_funcs] = np;
xfp->ext_funcs = tp;
xfp->num_funcs++;
return 1;
}
/* ---------------------------------------------------------------------------
* parse_ext_access: Parse an extended access list with module callouts.
*/
int parse_ext_access(perms, xperms, str, ntab, player, cmd)
int *perms;
EXTFUNCS **xperms;
char *str;
NAMETAB *ntab;
dbref player;
char *cmd;
{
char *sp, *tokst, *cp, *ostr;
int f, negate, success, failure, got_one;
MODULE *mp;
int (*hp)(dbref);
/* 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, ntab, sp);
if (f > 0) {
if (negate)
*perms &= ~f;
else
*perms |= f;
success++;
} else {
/* Is this a module callout? */
got_one = 0;
if (!strncmp(sp, "mod_", 4)) {
/* Split it apart, see if we have anything. */
ostr = (char *) strdup(sp);
if (*(sp + 4) != '\0') {
cp = strchr(sp + 4, '_');
if (cp) {
*cp++ = '\0';
WALK_ALL_MODULES(mp) {
got_one = 1;
if (!strcmp(sp + 4, mp->modname)) {
hp = DLSYM_INT(mp->handle, mp->modname, cp,
(dbref));
if (!hp) {
cf_log_notfound(player, cmd,
"Module function", ostr);
failure++;
} else {
if (modify_xfuncs(ostr, hp, xperms,
negate))
success++;
else
failure++;
}
break;
}
}
if (!got_one) {
cf_log_notfound(player, cmd, "Loaded module",
sp + 4);
got_one = 1;
}
}
}
free(ostr);
}
if (!got_one) {
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;
for (sp = str; *sp; sp++)
*sp = toupper(*sp);
/*
* 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 = strchr(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 = strchr(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) &&
strcmp(mask_txt, "255.255.255.255")) {
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.
*/
static int helper_cf_cf_access(tp, player, vp, ap, cmd, extra)
CONF *tp;
dbref player;
int *vp;
char *ap, *cmd;
long extra;
{
/* Cannot modify parameters set STATIC */
if (tp->flags & CA_STATIC) {
notify(player, NOPERM_MESSAGE);
STARTLOG(LOG_CONFIGMODS, "CFG", "PERM")
if (db)
log_name(player);
else
log_printf("System");
log_printf(" tried to change %s access to static param: %s",
(((long)vp) ? "read" : "write"),
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_HAND(cf_cf_access)
{
CONF *tp, *ctab;
char *ap;
MODULE *mp;
for (ap = str; *ap && !isspace(*ap); ap++) ;
if (*ap)
*ap++ = '\0';
for (tp = conftable; tp->pname; tp++) {
if (!strcmp(tp->pname, str)) {
return (helper_cf_cf_access(tp, player, vp, ap, cmd, extra));
}
}
WALK_ALL_MODULES(mp) {
if ((ctab = DLSYM_VAR(mp->handle, mp->modname, "conftable",
CONF *)) != NULL) {
for (tp = ctab; tp->pname; tp++) {
if (!strcmp(tp->pname, str)) {
return (helper_cf_cf_access(tp, player, vp, ap,
cmd, extra));
}
}
}
}
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, confcmd, str, is_raw)
dbref player;
char *confcmd, *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 (fpath == NULL) {
cf_log_syntax(player, confcmd, "Missing path for helpfile %s", fcmd);
free_mbuf(newstr);
return -1;
}
if (fcmd[0] == '_' && fcmd[1] == '_') {
cf_log_syntax(player, confcmd, "Helpfile %s would cause @addcommand conflict", fcmd);
free_mbuf(newstr);
return -1;
}
if (strlen(fpath) > SBUF_SIZE) {
cf_log_syntax(player, confcmd, "Helpfile %s filename too long", fcmd);
free_mbuf(newstr);
return -1;
}
cmdp = (CMDENT *) XMALLOC(sizeof(CMDENT), "add_helpfile.cmdp");
cmdp->cmdname = XSTRDUP(fcmd, "add_helpfile.cmd");
cmdp->switches = NULL;
cmdp->perms = 0;
cmdp->pre_hook = NULL;
cmdp->post_hook = NULL;
cmdp->userperms = NULL;
cmdp->callseq = CS_ONE_ARG;
cmdp->info.handler = do_help;
cmdp->extra = mudstate.helpfiles;
if (is_raw)
cmdp->extra |= HELP_RAWHELP;
hashdelete(cmdp->cmdname, &mudstate.command_htab);
hashadd(cmdp->cmdname, (int *) cmdp, &mudstate.command_htab, 0);
hashdelete(tprintf("__%s", cmdp->cmdname), &mudstate.command_htab);
hashadd(tprintf("__%s", cmdp->cmdname), (int *) cmdp, &mudstate.command_htab, HASH_ALIAS);
/* We may need to grow the helpfiles table, or create it. */
if (!mudstate.hfiletab) {
mudstate.hfiletab = (char **) XCALLOC(4, sizeof(char *), "helpfile.htab");
mudstate.hfile_hashes = (HASHTAB *) XCALLOC(4, sizeof(HASHTAB), "helpfile.hashes");
mudstate.hfiletab_size = 4;
} else if (mudstate.helpfiles >= mudstate.hfiletab_size) {
ftab = (char **) XREALLOC(mudstate.hfiletab,
(mudstate.hfiletab_size + 4) * sizeof(char *),
"helpfile.htab");
hashes = (HASHTAB *) XREALLOC(mudstate.hfile_hashes,
(mudstate.hfiletab_size + 4) *
sizeof(HASHTAB), "helpfile.hashes");
ftab[mudstate.hfiletab_size] = NULL;
ftab[mudstate.hfiletab_size + 1] = NULL;
ftab[mudstate.hfiletab_size + 2] = NULL;
ftab[mudstate.hfiletab_size + 3] = 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)
XFREE(mudstate.hfiletab[mudstate.helpfiles], "add_helpfile.fpath");
mudstate.hfiletab[mudstate.helpfiles] = XSTRDUP(fpath, "add_helpfile.fpath");
/* Initialize the associated hashtable. */
hashinit(&mudstate.hfile_hashes[mudstate.helpfiles], 30 * HASH_FACTOR,
HT_STR);
mudstate.helpfiles++;
free_mbuf(newstr);
return 0;
}
CF_HAND(cf_helpfile)
{
return add_helpfile(player, cmd, str, 0);
}
CF_HAND(cf_raw_helpfile)
{
return add_helpfile(player, cmd, 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 && !(isdigit(*(zp + 1)) && isspace(*(zp -1))))
*zp = '\0'; /*
* zap comment, but only if it's
* not sitting between whitespace
* and a digit, which traps a case
* like 'master_room #2'
*/
for (zp = zp - 1; zp >= ap && isspace(*zp); zp--)
*zp = '\0'; /*
* zap trailing spaces
*/
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_attr_type);
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 *)"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,(long)"Attribute"},
{(char *)"attr_cmd_access", cf_acmd_access, CA_GOD, CA_DISABLED, NULL, (long)access_nametab},
{(char *)"attr_type", cf_attr_type, CA_GOD, CA_DISABLED, NULL, (long)attraccess_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, MBUF_SIZE},
{(char *)"binary_home", cf_string, CA_STATIC, CA_GOD, (int *)&mudconf.binhome, MBUF_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 *)"c_is_command", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.c_cmd_subst, (long)"%c substitution is last command rather than ANSI"},
{(char *)"cache_size", cf_int, CA_GOD, CA_GOD, &mudconf.cache_size, 0},
{(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 *)"command_invocation_limit", cf_int, CA_GOD, CA_PUBLIC, &mudconf.cmd_invk_lim, 0},
{(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 *)"command_recursion_limit", cf_int, CA_GOD, CA_PUBLIC, &mudconf.cmd_nest_lim, 0},
{(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, MBUF_SIZE},
{(char *)"connect_reg_file", cf_string, CA_STATIC, CA_GOD, (int *)&mudconf.creg_file, MBUF_SIZE},
{(char *)"crash_database", cf_string, CA_STATIC, CA_GOD, (int *)&mudconf.crashdb, MBUF_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 *)"database_home", cf_string, CA_STATIC, CA_GOD, (int *)&mudconf.dbhome, MBUF_SIZE},
{(char *)"default_home", cf_dbref, CA_GOD, CA_PUBLIC, &mudconf.default_home, NOTHING},
{(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, MBUF_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, MBUF_SIZE},
{(char *)"postdump_message", cf_string, CA_GOD, CA_WIZARD, (int *)&mudconf.postdump_msg, MBUF_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_dbref, CA_GOD, CA_PUBLIC, &mudconf.exit_parent, NOTHING},
{(char *)"exit_proto", cf_dbref, CA_GOD, CA_PUBLIC, &mudconf.exit_proto, NOTHING},
{(char *)"exit_attr_defaults", cf_dbref, CA_GOD, CA_PUBLIC, &mudconf.exit_defobj, NOTHING},
{(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, MBUF_SIZE},
{(char *)"fixed_tel_message", cf_string, CA_STATIC, CA_PUBLIC, (int *)&mudconf.fixed_tel_msg, MBUF_SIZE},
{(char *)"find_money_chance", cf_int, CA_GOD, CA_WIZARD, &mudconf.payfind, 0},
{(char *)"flag_alias", cf_alias, CA_GOD, CA_DISABLED, (int *)&mudstate.flags_htab, (long)"Flag"},
{(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 *)"forwardlist_limit", cf_int, CA_GOD, CA_PUBLIC, &mudconf.fwdlist_lim, 0},
{(char *)"full_file", cf_string, CA_STATIC, CA_GOD, (int *)&mudconf.full_file, MBUF_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, (long)"Function"},
{(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 *)"function_cpu_limit", cf_int, CA_STATIC, CA_PUBLIC, &mudconf.func_cpu_lim_secs, 0},
{(char *)"gdbm_database", cf_string, CA_STATIC, CA_GOD, (int *)&mudconf.gdbm, MBUF_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_basename", cf_string, CA_STATIC, CA_PUBLIC, (int *)&mudconf.guest_basename, PLAYER_NAME_LIMIT},
{(char *)"guest_char_num", cf_dbref, CA_GOD, CA_WIZARD, &mudconf.guest_char, NOTHING},
{(char *)"guest_nuker", cf_dbref, CA_GOD, CA_WIZARD, &mudconf.guest_nuker, GOD},
{(char *)"guest_password", cf_string, CA_GOD, CA_GOD, (int *)&mudconf.guest_password, SBUF_SIZE},
{(char *)"guest_prefixes", cf_string, CA_GOD, CA_WIZARD, (int *)&mudconf.guest_prefixes, LBUF_SIZE},
{(char *)"guest_suffixes", cf_string, CA_GOD, CA_WIZARD, (int *)&mudconf.guest_suffixes, LBUF_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, MBUF_SIZE},
{(char *)"guest_site", cf_site, CA_GOD, CA_DISABLED, (int *)&mudstate.access_list, H_GUEST},
{(char *)"guest_starting_room", cf_dbref, CA_GOD, CA_WIZARD, &mudconf.guest_start_room, NOTHING},
{(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, MBUF_SIZE},
{(char *)"pueblo_message", cf_string, CA_GOD, CA_WIZARD, (int *)&mudconf.pueblo_msg, GBUF_SIZE},
#endif
{(char *)"huh_message", cf_string, CA_GOD, CA_PUBLIC, (int *)&mudconf.huh_msg, MBUF_SIZE},
{(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 *)"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_factor, 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,(long)"Logged-out command"},
{(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_factor, CA_GOD, CA_PUBLIC, &mudconf.machinecost, 0},
{(char *)"master_room", cf_dbref, CA_GOD, CA_WIZARD, &mudconf.master_room, NOTHING},
{(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 *)"module", cf_module, CA_STATIC, CA_WIZARD, NULL, 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, MBUF_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, MBUF_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 *)"objeval_requires_control", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.fascist_objeval, (long)"Control of victim required by objeval()"},
{(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_limit", cf_int, CA_GOD, CA_WIZARD, &mudconf.output_limit, 0},
{(char *)"page_cost", cf_int, CA_GOD, CA_PUBLIC, &mudconf.pagecost, 0},
{(char *)"page_requires_equals", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.page_req_equals, (long)"page command always requires an equals sign"},
{(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_aliases_limit", cf_int, CA_GOD, CA_PUBLIC, &mudconf.max_player_aliases, 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_dbref, CA_GOD, CA_PUBLIC, &mudconf.player_parent, NOTHING},
{(char *)"player_proto", cf_dbref, CA_GOD, CA_PUBLIC, &mudconf.player_proto, NOTHING},
{(char *)"player_attr_defaults", cf_dbref, CA_GOD, CA_PUBLIC, &mudconf.player_defobj, NOTHING},
{(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_dbref, CA_GOD, CA_PUBLIC, &mudconf.start_home, NOTHING},
{(char *)"player_starting_room", cf_dbref, CA_GOD, CA_PUBLIC, &mudconf.start_room, 0},
{(char *)"port", cf_int, CA_STATIC, CA_PUBLIC, &mudconf.port, 0},
{(char *)"power_access", cf_power_access,CA_GOD, CA_DISABLED, NULL, 0},
{(char *)"power_alias", cf_alias, CA_GOD, CA_DISABLED, (int *)&mudstate.powers_htab, (long)"Power"},
{(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, MBUF_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, MBUF_SIZE},
{(char *)"register_limit", cf_int, CA_GOD, CA_PUBLIC, &mudconf.register_limit, 0},
{(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_dbref, CA_GOD, CA_PUBLIC, &mudconf.room_parent, NOTHING},
{(char *)"room_proto", cf_dbref, CA_GOD, CA_PUBLIC, &mudconf.room_proto, NOTHING},
{(char *)"room_attr_defaults", cf_dbref, CA_GOD, CA_PUBLIC, &mudconf.room_defobj, NOTHING},
{(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_factor, 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 *)"say_uses_comma", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.comma_say, (long)"Say uses a grammatically-correct comma"},
{(char *)"say_uses_you", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.you_say, (long)"Say uses You rather than the player name"},
{(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, MBUF_SIZE - 2},
{(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, MBUF_SIZE},
{(char *)"stripped_flags", cf_set_flags, CA_GOD, CA_DISABLED, (int *)&mudconf.stripped_flags, 0},
{(char *)"structure_delimiter_string", cf_string, CA_GOD, CA_PUBLIC, (int *)&mudconf.struct_dstr, 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 *)"text_home", cf_string, CA_STATIC, CA_GOD, (int *)&mudconf.txthome, MBUF_SIZE},
{(char *)"thing_flags", cf_set_flags, CA_GOD, CA_DISABLED, (int *)&mudconf.thing_flags, 0},
{(char *)"thing_parent", cf_dbref, CA_GOD, CA_PUBLIC, &mudconf.thing_parent, NOTHING},
{(char *)"thing_proto", cf_dbref, CA_GOD, CA_PUBLIC, &mudconf.thing_proto, NOTHING},
{(char *)"thing_attr_defaults", cf_dbref, CA_GOD, CA_PUBLIC, &mudconf.thing_defobj, NOTHING},
{(char *)"thing_quota", cf_int, CA_GOD, CA_PUBLIC, &mudconf.thing_quota, 0},
{(char *)"timeslice", cf_int_factor, 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 *)"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 *)"visible_wizards", cf_bool, CA_GOD, CA_PUBLIC, &mudconf.visible_wizzes, (long)"DARK Wizards are hidden from WHO but not invisible"},
{(char *)"wait_cost", cf_int, CA_GOD, CA_PUBLIC, &mudconf.waitcost, 0},
{(char *)"wildcard_match_limit", cf_int, CA_GOD, CA_PUBLIC, &mudconf.wild_times_lim, 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, MBUF_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.
*/
static int helper_cf_set(cp, ap, player, tp)
char *cp, *ap;
dbref player;
CONF *tp;
{
int i;
char *buff;
if (!mudstate.standalone && !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_printf(" entered config directive: %s with args '%s'. Status: ", cp, strip_ansi(buff));
switch (i) {
case 0:
log_printf("Success.");
break;
case 1:
log_printf("Partial success.");
break;
case -1:
log_printf("Failure.");
break;
default:
log_printf("Strange.");
}
ENDLOG
free_lbuf(buff);
}
return i;
}
int cf_set(cp, ap, player)
char *cp, *ap;
dbref player;
{
CONF *tp, *ctab;
MODULE *mp;
/*
* Search the config parameter table for the command. If we find it,
* call the handler to parse the argument.
*/
/* Make sure that if we're standalone, the paramaters we need to
* load module flatfiles are loaded */
if (mudstate.standalone && strcmp(cp, "module") &&
strcmp(cp, "database_home")) {
return 0;
}
for (tp = conftable; tp->pname; tp++) {
if (!strcmp(tp->pname, cp)) {
return (helper_cf_set(cp, ap, player, tp));
}
}
WALK_ALL_MODULES(mp) {
if ((ctab = DLSYM_VAR(mp->handle, mp->modname, "conftable",
CONF *)) != NULL) {
for (tp = ctab; tp->pname; tp++) {
if (!strcmp(tp->pname, cp))
return (helper_cf_set(cp, ap, player, tp));
}
}
}
/* Config directive not found. Complain about it. */
if (!mudstate.standalone)
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;
char tmpfile[256], *c;
mudconf.config_file = XSTRDUP(fn, "cf_read.config_file");
mudstate.initializing = 1;
retval = cf_include(NULL, fn, 0, 0, (char *)"init");
mudstate.initializing = 0;
/* Fill in missing DB file names */
strcpy(tmpfile, mudconf.gdbm);
if ((c = strchr(tmpfile, '.')) != NULL)
*c = '\0';
if (!*mudconf.crashdb) {
XFREE(mudconf.crashdb, "cf_read_crashdb");
mudconf.crashdb = XSTRDUP(tprintf("%s.CRASH", tmpfile),
"cf_read_crashdb");
}
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, *ctab;
char *buff;
MODULE *mp;
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);
}
}
WALK_ALL_MODULES(mp) {
if ((ctab = DLSYM_VAR(mp->handle, mp->modname, "conftable",
CONF *)) != NULL) {
for (tp = ctab; 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, *ctab;
char *buff;
MODULE *mp;
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);
}
}
WALK_ALL_MODULES(mp) {
if ((ctab = DLSYM_VAR(mp->handle, mp->modname, "conftable",
CONF *)) != NULL) {
for (tp = ctab; 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_verify: Walk all configuration tables and validate any dbref values.
*/
#define Check_Conf_Dbref(x) \
if ((x)->interpreter == cf_dbref) { \
if (!((((x)->extra == NOTHING) && (*((x)->loc) == NOTHING)) || \
(Good_obj(*((x)->loc)) && !Going(*((x)->loc))))) { \
STARTLOG(LOG_ALWAYS, "CNF", "VRFY") \
log_printf("%s #%d is invalid. Reset to #%d.", \
(x)->pname, *((x)->loc), (x)->extra); \
ENDLOG \
*((x)->loc) = (dbref) (x)->extra; \
} \
}
void cf_verify()
{
CONF *tp, *ctab;
MODULE *mp;
for (tp = conftable; tp->pname; tp++) {
Check_Conf_Dbref(tp);
}
WALK_ALL_MODULES(mp) {
if ((ctab = DLSYM_VAR(mp->handle, mp->modname, "conftable",
CONF *)) != NULL) {
for (tp = ctab; tp->pname; tp++) {
Check_Conf_Dbref(tp);
}
}
}
}
/* ---------------------------------------------------------------------------
* cf_display: Given a config parameter by name, return its value in some
* sane fashion.
*/
static void helper_cf_display(player, buff, bufc, tp)
dbref player;
char *buff, **bufc;
CONF *tp;
{
NAMETAB *opt;
if (!check_access(player, tp->rperms)) {
safe_noperm(buff, bufc);
return;
}
if ((tp->interpreter == cf_bool) ||
(tp->interpreter == cf_int) ||
(tp->interpreter == cf_int_factor) ||
(tp->interpreter == cf_const)) {
safe_ltos(buff, bufc, *(tp->loc));
return;
}
if ((tp->interpreter == cf_string)) {
safe_str(*((char **)tp->loc), buff, bufc);
return;
}
if ((tp->interpreter == cf_dbref)) {
safe_dbref(buff, bufc, *(tp->loc));
return;
}
if ((tp->interpreter == cf_option)) {
opt = find_nametab_ent_flag(GOD, (NAMETAB *)tp->extra, *(tp->loc));
safe_str((opt ? opt->name : "*UNKNOWN*"), buff, bufc);
return;
}
safe_noperm(buff, bufc);
return;
}
void cf_display(player, param_name, buff, bufc)
dbref player;
char *param_name;
char *buff;
char **bufc;
{
CONF *tp, *ctab;
MODULE *mp;
for (tp = conftable; tp->pname; tp++) {
if (!strcasecmp(tp->pname, param_name)) {
helper_cf_display(player, buff, bufc, tp);
return;
}
}
WALK_ALL_MODULES(mp) {
if ((ctab = DLSYM_VAR(mp->handle, mp->modname, "conftable",
CONF *)) != NULL) {
for (tp = ctab; tp->pname; tp++) {
if (!strcasecmp(tp->pname, param_name)) {
helper_cf_display(player, buff, bufc, tp);
return;
}
}
}
}
safe_nomatch(buff, bufc);
}
void list_options(player)
dbref player;
{
CONF *tp, *ctab;
MODULE *mp;
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 : "")));
}
}
WALK_ALL_MODULES(mp) {
if ((ctab = DLSYM_VAR(mp->handle, mp->modname, "conftable",
CONF *)) != NULL) {
for (tp = ctab; 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 : "")));
}
}
}
}
}