// conf.cpp: set up configuration information and static data. // // $Id: conf.cpp,v 1.23 2000/09/26 06:27:41 sdennis Exp $ // #include "copyright.h" #include "autoconf.h" #include "config.h" #include "externs.h" #include "mudconf.h" #include "db.h" #include "interface.h" #include "command.h" #include "htab.h" #include "alloc.h" #include "attrs.h" #include "flags.h" #include "powers.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 { char *pname; // parm name int (*interpreter)(int *vp, char *str, unsigned int extra, dbref player, char *cmd); // routine to interp parameter int flags; // control flags int *loc; // where to store value long extra; // extra data for interpreter } CONF; /* * --------------------------------------------------------------------------- * * External symbols. */ CONFDATA mudconf; STATEDATA mudstate; #ifndef STANDALONE extern NAMETAB logdata_nametab[]; extern NAMETAB logoptions_nametab[]; extern NAMETAB access_nametab[]; extern NAMETAB attraccess_nametab[]; extern NAMETAB list_names[]; extern NAMETAB sigactions_nametab[]; extern CONF conftable[]; #endif /* * --------------------------------------------------------------------------- * * cf_init: Initialize mudconf to default values. */ void NDECL(cf_init) { #ifndef STANDALONE int i; mudconf.indb = StringClone("netmux.db"); mudconf.outdb = StringClone(""); mudconf.crashdb = StringClone(""); mudconf.game_dir = StringClone(""); mudconf.game_pag = StringClone(""); mudconf.mail_db = StringClone("mail.db"); mudconf.comsys_db = StringClone("comsys.db"); mudconf.compress_db = 0; mudconf.compress = StringClone("gzip"); mudconf.uncompress = StringClone("gzip -d"); mudconf.status_file = StringClone("shutdown.status"); mudconf.max_cache_size = 1*1024*1024; mudconf.port = 2860; mudconf.conc_port = 2861; mudconf.init_size = 1000; mudconf.guest_char = -1; mudconf.guest_nuker = 1; mudconf.number_guests = 30; strcpy(mudconf.guest_prefix, "Guest"); mudconf.guest_file = StringClone("text/guest.txt"); mudconf.conn_file = StringClone("text/connect.txt"); mudconf.creg_file = StringClone("text/register.txt"); mudconf.regf_file = StringClone("text/create_reg.txt"); mudconf.motd_file = StringClone("text/motd.txt"); mudconf.wizmotd_file = StringClone("text/wizmotd.txt"); mudconf.quit_file = StringClone("text/quit.txt"); mudconf.down_file = StringClone("text/down.txt"); mudconf.full_file = StringClone("text/full.txt"); mudconf.site_file = StringClone("text/badsite.txt"); mudconf.crea_file = StringClone("text/newuser.txt"); mudconf.help_file = StringClone("text/help.txt"); mudconf.help_indx = StringClone("text/help.indx"); mudconf.news_file = StringClone("text/news.txt"); mudconf.news_indx = StringClone("text/news.indx"); mudconf.whelp_file = StringClone("text/wizhelp.txt"); mudconf.whelp_indx = StringClone("text/wizhelp.indx"); mudconf.plushelp_file = StringClone("text/plushelp.txt"); mudconf.plushelp_indx = StringClone("text/plushelp.indx"); mudconf.staffhelp_file = StringClone("text/staffhelp.txt"); mudconf.staffhelp_indx = StringClone("text/staffhelp.indx"); mudconf.wiznews_file = StringClone("text/wiznews.txt"); mudconf.wiznews_indx = StringClone("text/wiznews.indx"); mudconf.motd_msg[0] = '\0'; mudconf.wizmotd_msg[0] = '\0'; mudconf.downmotd_msg[0] = '\0'; mudconf.fullmotd_msg[0] = '\0'; mudconf.dump_msg[0] = '\0'; mudconf.postdump_msg[0] = '\0'; mudconf.fixed_home_msg[0] = '\0'; mudconf.fixed_tel_msg[0] = '\0'; strcpy(mudconf.public_channel, "Public"); strcpy(mudconf.guests_channel, "Guests"); strcpy(mudconf.pueblo_msg, "</xch_mudtext><img xch_mode=html>"); mudconf.indent_desc = 0; mudconf.name_spaces = 1; #if !defined(VMS) && !defined(WIN32) mudconf.fork_dump = 1; mudconf.fork_vfork = 0; mudstate.dumping = 0; #endif // WIN32 mudconf.have_comsys = 1; mudconf.have_mailer = 1; 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 = 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.exit_quota = 1; mudconf.player_quota = 1; mudconf.room_quota = 1; mudconf.thing_quota = 1; mudconf.mail_expiration = 14; mudconf.use_http = 0; 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.ex_flags = 1; mudconf.robot_speak = 1; mudconf.clone_copy_cost = 0; mudconf.pub_flags = 1; mudconf.quiet_look = 1; mudconf.exam_public = 1; mudconf.read_rem_desc = 0; mudconf.read_rem_name = 0; mudconf.sweep_dark = 0; mudconf.player_listen = 0; mudconf.quiet_whisper = 1; mudconf.dark_sleepers = 1; mudconf.see_own_dark = 1; mudconf.idle_wiz_dark = 0; mudconf.pemit_players = 0; mudconf.pemit_any = 0; mudconf.match_mine = 1; mudconf.match_mine_pl = 1; 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.safer_passwords = 0; // -- ??? Running SC on a non-SC DB may cause problems. // mudconf.space_compress = 1; mudconf.allow_guest_from_registered_site = 1; mudconf.start_room = 0; mudconf.start_home = NOTHING; mudconf.default_home = NOTHING; mudconf.master_room = 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.vattr_flags = AF_ODARK; strcpy(mudconf.mud_name, "MUX"); strcpy(mudconf.one_coin, "penny"); strcpy(mudconf.many_coins, "pennies"); mudconf.timeslice = 1000; mudconf.cmd_quota_max = 100; mudconf.cmd_quota_incr = 1; mudconf.max_cmdsecs = 120; mudconf.control_flags = 0xffffffff; // Everything for now... mudconf.log_options = LOG_ALWAYS | LOG_BUGS | LOG_SECURITY | LOG_NET | LOG_LOGIN | LOG_DBSAVES | LOG_CONFIGMODS | LOG_SHOUTS | LOG_STARTUP | LOG_WIZARD | LOG_PROBLEMS | LOG_PCREATES | LOG_TIMEUSE; mudconf.log_info = LOGOPT_TIMESTAMP | LOGOPT_LOC; mudconf.markdata[0] = 0x01; mudconf.markdata[1] = 0x02; mudconf.markdata[2] = 0x04; mudconf.markdata[3] = 0x08; mudconf.markdata[4] = 0x10; mudconf.markdata[5] = 0x20; mudconf.markdata[6] = 0x40; mudconf.markdata[7] = 0x80; mudconf.func_nest_lim = 50; mudconf.func_invk_lim = 2500; mudconf.ntfy_nest_lim = 20; mudconf.lock_nest_lim = 20; mudconf.parent_nest_lim = 10; mudconf.zone_nest_lim = 20; mudconf.stack_limit = 50; mudconf.cache_names = 1; mudconf.toad_recipient = -1; mudstate.events_flag = 0; mudstate.initializing = 0; mudstate.panicking = 0; mudstate.logging = 0; mudstate.epoch = 0; mudstate.generation = 0; mudstate.curr_player = NOTHING; mudstate.curr_enactor = NOTHING; mudstate.shutdown_flag = 0; mudstate.attr_next = A_USER_START; mudstate.debug_cmd = (char *)"< init >"; strcpy(mudstate.doing_hdr, "Doing"); mudstate.access_list = NULL; mudstate.suspect_list = NULL; mudstate.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_alist_len = 0; 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.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.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; } mudstate.nObjEvalNest = 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 = NOTHING; mudconf.default_home = NOTHING; mudconf.vattr_flags = AF_ODARK; mudconf.log_options = 0xffffffff; mudconf.log_info = 0; mudconf.markdata[0] = 0x01; mudconf.markdata[1] = 0x02; mudconf.markdata[2] = 0x04; mudconf.markdata[3] = 0x08; mudconf.markdata[4] = 0x10; mudconf.markdata[5] = 0x20; mudconf.markdata[6] = 0x40; mudconf.markdata[7] = 0x80; mudconf.ntfy_nest_lim = 20; 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_alist_len = 0; 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(dbref player, char *cmd, const char *thingname, char *thing) { 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, buff); } } /* * --------------------------------------------------------------------------- * * cf_log_syntax: Log a syntax error. */ void DCL_CDECL cf_log_syntax(dbref player, char *cmd, const char *fmt, ...) { va_list ap; va_start(ap, fmt); char *buf = alloc_lbuf("cf_log_syntax"); Tiny_vsnprintf(buf, LBUF_SIZE, fmt, ap); if (mudstate.initializing) { STARTLOG(LOG_STARTUP, "CNF", "SYNTX") log_text(cmd); log_text((char *)": "); log_text(buf); ENDLOG; } else { notify(player, buf); } free_lbuf(buf); va_end(ap); } /* * --------------------------------------------------------------------------- * * cf_status_from_succfail: Return command status from succ and fail info */ int cf_status_from_succfail(dbref player, char *cmd, int success, int failure) { char *buff; /* * If any successes, return SUCCESS(0) if no failures or * * * * * * PARTIAL_SUCCESS(1) if any failures. */ if (success > 0) return ((failure == 0) ? 0 : 1); /* * No successes. If no failures indicate nothing done. Always return * * * * * * * * * * * FAILURE(-1) */ if (failure == 0) { if (mudstate.initializing) { STARTLOG(LOG_STARTUP, "CNF", "NDATA") buff = alloc_lbuf("cf_status_from_succfail.LOG"); sprintf(buff, "%s: Nothing to set", cmd); log_text(buff); free_lbuf(buff); ENDLOG } else { notify(player, "Nothing to set"); } } return -1; } /* * --------------------------------------------------------------------------- * * cf_int: Set integer parameter. */ CF_HAND(cf_int) { // Copy the numeric value to the parameter. // *vp = Tiny_atol(str); return 0; } /* --------------------------------------------------------------------------- * cf_bool: Set boolean parameter. */ NAMETAB bool_names[] = { {(char *)"true", 1, 0, 1}, {(char *)"false", 1, 0, 0}, {(char *)"yes", 1, 0, 1}, {(char *)"no", 1, 0, 0}, {(char *)"1", 1, 0, 1}, {(char *)"0", 1, 0, 0}, {NULL, 0, 0, 0} }; CF_HAND(cf_bool) { *vp = (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) { char *pc = (char *)vp; // The following should never happen because extra is always a non-zero // constant in the config table. // if (extra <= 0) return 1; // Copy the string to the buffer if it is not too big. // int retval = 0; unsigned int nStr = strlen(str); if (nStr >= extra) { nStr = extra - 1; if (mudstate.initializing) { STARTLOG(LOG_STARTUP, "CNF", "NFND"); char *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; } memcpy(pc, str, nStr+1); pc[nStr] = '\0'; #ifdef WIN32 if (pc == mudconf.mud_name) { // We are changing the name of the MUD. Let the logger know. // Log.ChangePrefix(mudconf.mud_name); } #endif // WIN32 return retval; } /* * --------------------------------------------------------------------------- * * cf_string_dyn: Set string parameter using dynamically allocated memory. */ CF_HAND(cf_string_dyn) { char **ppc = (char **)vp; // Allocate memory for buffer and copy string to it. If extra is non-zero, // then there is a size limitation as well. // int retval = 0; unsigned int nStr = strlen(str); if (extra && nStr >= extra) { nStr = extra - 1; if (mudstate.initializing) { STARTLOG(LOG_STARTUP, "CNF", "NFND"); char *logbuff = alloc_lbuf("cf_string.LOG"); sprintf(logbuff, "%s: String truncated", cmd); log_text(logbuff); free_lbuf(logbuff); ENDLOG; } else { notify(player, "String truncated"); } retval = 1; } char *confbuff = StringCloneLen(str, nStr); // Free previous memory for buffer. // if (*ppc != NULL) { MEMFREE(*ppc); } *ppc = confbuff; return retval; } /* * --------------------------------------------------------------------------- * * cf_alias: define a generic hash table alias. */ CF_HAND(cf_alias) { TINY_STRTOK_STATE tts; Tiny_StrTokString(&tts, str); Tiny_StrTokControl(&tts, " \t=,"); char *alias = Tiny_StrTokParse(&tts); char *orig = Tiny_StrTokParse(&tts); if (orig) { _strlwr(orig); int *cp = hashfindLEN(orig, strlen(orig), (CHashTable *) vp); if (cp == NULL) { _strupr(orig); cp = hashfindLEN(orig, strlen(orig), (CHashTable *) vp); if (cp == NULL) { cf_log_notfound(player, cmd, "Entry", orig); return -1; } } hashaddLEN(alias, strlen(alias), cp, (CHashTable *) vp); return 0; } return -1; } /* * --------------------------------------------------------------------------- * * cf_flagalias: define a flag alias. */ CF_HAND(cf_flagalias) { TINY_STRTOK_STATE tts; Tiny_StrTokString(&tts, str); Tiny_StrTokControl(&tts, " \t=,"); char *alias = Tiny_StrTokParse(&tts); char *orig = Tiny_StrTokParse(&tts); int success = 0; int nName; BOOL bValid; int *cp; char *pName = MakeCanonicalFlagName(orig, &nName, &bValid); if ( bValid && (cp = hashfindLEN(pName, nName, &mudstate.flags_htab))) { char *pName = MakeCanonicalFlagName(alias, &nName, &bValid); if (bValid) { hashaddLEN(pName, nName, cp, &mudstate.flags_htab); success++; } } if (!success) { cf_log_notfound(player, cmd, "Flag", orig); } return ((success > 0) ? 0 : -1); } /* * --------------------------------------------------------------------------- * * cf_or_in_bits: OR in bits from namelist to a word. */ CF_HAND(cf_or_in_bits) { int f, success, failure; // Walk through the tokens. // success = failure = 0; TINY_STRTOK_STATE tts; Tiny_StrTokString(&tts, str); Tiny_StrTokControl(&tts, " \t"); char *sp = Tiny_StrTokParse(&tts); while (sp != NULL) { // Set the appropriate bit. // f = search_nametab(GOD, (NAMETAB *) extra, sp); if (f > 0) { *vp |= f; success++; } else { cf_log_notfound(player, cmd, "Entry", sp); failure++; } // Get the next token. // sp = Tiny_StrTokParse(&tts); } return cf_status_from_succfail(player, cmd, success, failure); } /* * --------------------------------------------------------------------------- * * cf_modify_bits: set or clear bits in a flag word from a namelist. */ CF_HAND(cf_modify_bits) { int f, negate, success, failure; // Walk through the tokens. // success = failure = 0; TINY_STRTOK_STATE tts; Tiny_StrTokString(&tts, str); Tiny_StrTokControl(&tts, " \t"); char *sp = Tiny_StrTokParse(&tts); 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 = Tiny_StrTokParse(&tts); } return cf_status_from_succfail(player, cmd, success, failure); } /* * --------------------------------------------------------------------------- * * cf_set_bits: Clear flag word and then set specified bits from namelist. */ CF_HAND(cf_set_bits) { int f, success, failure; /* * Walk through the tokens */ success = failure = 0; *vp = 0; TINY_STRTOK_STATE tts; Tiny_StrTokString(&tts, str); Tiny_StrTokControl(&tts, " \t"); char *sp = Tiny_StrTokParse(&tts); while (sp != NULL) { // Set the appropriate bit. // f = search_nametab(GOD, (NAMETAB *) extra, sp); if (f > 0) { *vp |= f; success++; } else { cf_log_notfound(player, cmd, "Entry", sp); failure++; } // Get the next token. // sp = Tiny_StrTokParse(&tts); } 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) { FLAGENT *fp; FLAGSET *fset; int success, failure; // Walk through the tokens. // success = failure = 0; TINY_STRTOK_STATE tts; Tiny_StrTokString(&tts, str); Tiny_StrTokControl(&tts, " \t"); char *sp = Tiny_StrTokParse(&tts); fset = (FLAGSET *) vp; while (sp != NULL) { // Set the appropriate bit. // fp = (FLAGENT *) hashfindLEN(sp, strlen(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 = Tiny_StrTokParse(&tts); } 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. * * This approach specifically disallows the Berkeley-only IP formats: * * a.b.c (e.g., Class B 128.net.host) * a.b (e.g., class A: net.host) * a (single 32-bit number) * * Avoiding a SIGSEGV on certain operating systems is better than supporting * niche formats that are only available on Berkeley Unix. */ static unsigned long sane_inet_addr(char *str) { int i; char *p = str; for (i = 1; (p = (char *) strchr(p, '.')) != NULL; i++, p++) { // Nothing } if (i < 4) { return (unsigned long)INADDR_NONE; } else { return inet_addr(str); } } // Given a host-ordered mask, this function will determine whether it is a // valid one. Valid masks consist of a N-bit sequence of '1' bits followed by // a (32-N)-bit sequence of '0' bits, where N is 0 to 32. // BOOL isValidSubnetMask(unsigned long ulMask) { unsigned long ulTest = 0xFFFFFFFFUL; for (int i = 0; i <= 32; i++) { if (ulMask == ulTest) { return TRUE; } ulTest <<= 1; } return FALSE; } /* * --------------------------------------------------------------------------- * * cf_site: Update site information */ CF_HAND(cf_site) { struct in_addr addr_num, mask_num; unsigned long ulMask; char *addr_txt; char *mask_txt = strchr(str, '/'); if (!mask_txt) { // Standard IP range and netmask notation. // TINY_STRTOK_STATE tts; Tiny_StrTokString(&tts, str); Tiny_StrTokControl(&tts, " \t=,"); addr_txt = Tiny_StrTokParse(&tts); mask_txt = NULL; if (addr_txt) { mask_txt = Tiny_StrTokParse(&tts); } if (!addr_txt || !*addr_txt || !mask_txt || !*mask_txt) { cf_log_syntax(player, cmd, "Missing host address or mask.", (char *)""); return -1; } mask_num.s_addr = sane_inet_addr(mask_txt); if ( mask_num.s_addr == INADDR_NONE || !isValidSubnetMask(ulMask = ntohl(mask_num.s_addr))) { 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'; int mask_bits = Tiny_atol(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 { // << [0,31] works. << 32 is problematic on some systems. // ulMask = 0; if (mask_bits > 0) { ulMask = 0xFFFFFFFFUL << (32 - mask_bits); } mask_num.s_addr = htonl(ulMask); } } addr_num.s_addr = sane_inet_addr(addr_txt); if (addr_num.s_addr == INADDR_NONE) { cf_log_syntax(player, cmd, "Malformed host address: %s", addr_txt); return -1; } unsigned long ulAddr = ntohl(addr_num.s_addr); if (ulAddr & ~ulMask) { // The given subnet address contains 'one' bits which are outside // the given subnet mask. If we don't clear these bits, they will // interfere with the subnet tests in site_check. The subnet spec // would be defunct and useless. // cf_log_syntax(player, cmd, "Non-zero host address bits outside the subnet mask (fixed): %s %s", addr_txt, mask_txt); ulAddr &= ulMask; addr_num.s_addr = htonl(ulAddr); } SITE *head = (SITE *) * vp; // Parse the access entry and allocate space for it. // SITE *site = (SITE *)MEMALLOC(sizeof(SITE)); ISOUTOFMEMORY(site); // Initialize the site entry. // site->address.s_addr = addr_num.s_addr; site->mask.s_addr = mask_num.s_addr; site->flag = extra; site->next = NULL; // Link in the entry. Link it at the start if not initializing, at the // end if initializing. This is so that entries in the config file are // processed as you would think they would be, while entries made while // running are processed first. // if (mudstate.initializing) { if (head == NULL) { *vp = (int) site; } else { SITE *last; for (last = head; last->next; last = last->next) { // Nothing } last->next = site; } } else { site->next = head; *vp = (int) site; } return 0; } /* * --------------------------------------------------------------------------- * * cf_cf_access: Set access on config directives */ CF_HAND(cf_cf_access) { CONF *tp; char *ap; for (ap = str; *ap && !Tiny_IsSpace[(unsigned char)*ap]; ap++) { ; // Nothing } if (*ap) { *ap++ = '\0'; } for (tp = conftable; tp->pname; tp++) { if (!strcmp(tp->pname, str)) { // Cannot modify parameters set CA_STATIC. // if (tp->flags & CA_STATIC) { notify(player, NOPERM_MESSAGE); STARTLOG(LOG_CONFIGMODS, "CFG", "PERM"); log_name(player); log_text((char *) " tried to change access to static param: "); log_text(tp->pname); ENDLOG; return -1; } return cf_modify_bits(&tp->flags, ap, extra, player, cmd); } } cf_log_notfound(player, cmd, "Config directive", str); return -1; } /* * --------------------------------------------------------------------------- * * cf_include: Read another config file. Only valid during startup. */ CF_HAND(cf_include) { FILE *fp; char *cp, *ap, *zp, *buf; extern int FDECL(cf_set, (char *, char *, dbref)); if (!mudstate.initializing) return -1; fp = fopen(str, "rb"); if (fp == NULL) { cf_log_notfound(player, cmd, "Config file", str); return -1; } DebugTotalFiles++; 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++) ; // Strip '\n' // *cp = '\0'; // Strip spaces. // for (cp = buf; Tiny_IsSpace[(unsigned char)*cp]; cp++) ; // Skip over command. // for (ap = cp; *ap && !Tiny_IsSpace[(unsigned char)*ap]; ap++) ; // Trim command. // if (*ap) *ap++ = '\0'; // Skip Spaces. // for (; Tiny_IsSpace[(unsigned char)*ap]; ap++) ; // Find comment. // for (zp = ap; *zp && (*zp != '#'); zp++) ; // Zap comment. // if (*zp) *zp = '\0'; // Zap trailing spaces. // for (zp = zp - 1; zp >= ap && Tiny_IsSpace[(unsigned char)*zp]; zp--) *zp = '\0'; cf_set(cp, ap, player); fgets(buf, LBUF_SIZE, fp); } free_lbuf(buf); if (fclose(fp) == 0) { DebugTotalFiles--; } return 0; } extern CF_HAND(cf_access); extern CF_HAND(cf_cmd_alias); extern CF_HAND(cf_acmd_access); extern CF_HAND(cf_attr_access); extern CF_HAND(cf_func_access); extern CF_HAND(cf_flag_access); /* --------------------------------------------------------------------------- * conftable: Table for parsing the configuration file. */ CONF conftable[] = { {(char *)"access", cf_access, CA_GOD, NULL, (long)access_nametab}, {(char *)"alias", cf_cmd_alias, CA_GOD, (int *)&mudstate.command_htab, 0}, {(char *)"attr_access", cf_attr_access, CA_GOD, NULL, (long)attraccess_nametab}, {(char *)"attr_alias", cf_alias, CA_GOD, (int *)&mudstate.attr_name_htab,0}, {(char *)"attr_cmd_access", cf_acmd_access, CA_GOD, NULL, (long)access_nametab}, {(char *)"bad_name", cf_badname, CA_GOD, NULL, 0}, {(char *)"badsite_file", cf_string_dyn, CA_STATIC, (int *)&mudconf.site_file, SIZEOF_PATHNAME}, {(char *)"cache_names", cf_bool, CA_STATIC, &mudconf.cache_names, 0}, {(char *)"check_interval", cf_int, CA_GOD, &mudconf.check_interval, 0}, {(char *)"check_offset", cf_int, CA_GOD, &mudconf.check_offset, 0}, {(char *)"clone_copies_cost", cf_bool, CA_GOD, &mudconf.clone_copy_cost, 0}, {(char *)"comsys_database", cf_string_dyn, CA_STATIC, (int *)&mudconf.comsys_db, SIZEOF_PATHNAME}, {(char *)"command_quota_increment", cf_int, CA_GOD, &mudconf.cmd_quota_incr, 0}, {(char *)"command_quota_max", cf_int, CA_GOD, &mudconf.cmd_quota_max, 0}, {(char *)"compress_program", cf_string_dyn, CA_STATIC, (int *)&mudconf.compress, SIZEOF_PATHNAME}, {(char *)"compression", cf_bool, CA_GOD, &mudconf.compress_db, 0}, {(char *)"concentrator_port", cf_int, CA_STATIC, &mudconf.conc_port, 0}, {(char *)"config_access", cf_cf_access, CA_GOD, NULL, (long)access_nametab}, {(char *)"conn_timeout", cf_int, CA_GOD, &mudconf.conn_timeout, 0}, {(char *)"connect_file", cf_string_dyn, CA_STATIC, (int *)&mudconf.conn_file, SIZEOF_PATHNAME}, {(char *)"connect_reg_file", cf_string_dyn, CA_STATIC, (int *)&mudconf.creg_file, SIZEOF_PATHNAME}, {(char *)"crash_database", cf_string_dyn, CA_STATIC, (int *)&mudconf.crashdb, SIZEOF_PATHNAME}, {(char *)"create_max_cost", cf_int, CA_GOD, &mudconf.createmax, 0}, {(char *)"create_min_cost", cf_int, CA_GOD, &mudconf.createmin, 0}, {(char *)"dark_sleepers", cf_bool, CA_GOD, &mudconf.dark_sleepers, 0}, {(char *)"default_home", cf_int, CA_GOD, &mudconf.default_home, 0}, {(char *)"dig_cost", cf_int, CA_GOD, &mudconf.digcost, 0}, {(char *)"down_file", cf_string_dyn, CA_STATIC, (int *)&mudconf.down_file, SIZEOF_PATHNAME}, {(char *)"down_motd_message", cf_string, CA_GOD, (int *)mudconf.downmotd_msg, GBUF_SIZE}, {(char *)"dump_interval", cf_int, CA_GOD, &mudconf.dump_interval, 0}, {(char *)"dump_message", cf_string, CA_GOD, (int *)mudconf.dump_msg, 128}, {(char *)"postdump_message", cf_string, CA_GOD, (int *)mudconf.postdump_msg, 128}, {(char *)"pueblo_message", cf_string, CA_GOD, (int *) mudconf.pueblo_msg, GBUF_SIZE}, {(char *)"dump_offset", cf_int, CA_GOD, &mudconf.dump_offset, 0}, {(char *)"earn_limit", cf_int, CA_GOD, &mudconf.paylimit, 0}, {(char *)"examine_flags", cf_bool, CA_GOD, &mudconf.ex_flags, 0}, {(char *)"examine_public_attrs", cf_bool, CA_GOD, &mudconf.exam_public, 0}, {(char *)"exit_flags", cf_set_flags, CA_GOD, (int *)&mudconf.exit_flags, 0}, {(char *)"exit_quota", cf_int, CA_GOD, &mudconf.exit_quota, 0}, {(char *)"events_daily_hour", cf_int, CA_GOD, &mudconf.events_daily_hour, 0}, {(char *)"fascist_teleport", cf_bool, CA_GOD, &mudconf.fascist_tport, 0}, {(char *)"fixed_home_message", cf_string, CA_STATIC, (int *)mudconf.fixed_home_msg, 128}, {(char *)"fixed_tel_message", cf_string, CA_STATIC, (int *)mudconf.fixed_tel_msg, 128}, {(char *)"find_money_chance", cf_int, CA_GOD, &mudconf.payfind, 0}, {(char *)"flag_access", cf_flag_access, CA_GOD, NULL, 0}, {(char *)"flag_alias", cf_flagalias, CA_GOD, NULL, 0}, {(char *)"forbid_site", cf_site, CA_GOD, (int *)&mudstate.access_list, H_FORBIDDEN}, #if !defined(VMS) && !defined(WIN32) {(char *)"fork_dump", cf_bool, CA_GOD, &mudconf.fork_dump, 0}, {(char *)"fork_vfork", cf_bool, CA_GOD, &mudconf.fork_vfork, 0}, #endif // WIN32 {(char *)"full_file", cf_string_dyn, CA_STATIC, (int *)&mudconf.full_file, SIZEOF_PATHNAME}, {(char *)"full_motd_message", cf_string, CA_GOD, (int *)mudconf.fullmotd_msg, GBUF_SIZE}, {(char *)"function_access", cf_func_access, CA_GOD, NULL, (long)access_nametab}, {(char *)"function_alias", cf_alias, CA_GOD, (int *)&mudstate.func_htab, 0}, {(char *)"function_invocation_limit", cf_int, CA_GOD, &mudconf.func_invk_lim, 0}, {(char *)"function_recursion_limit", cf_int, CA_GOD, &mudconf.func_nest_lim, 0}, {(char *)"game_dir_file", cf_string_dyn, CA_STATIC, (int *)&mudconf.game_dir, SIZEOF_PATHNAME}, {(char *)"game_pag_file", cf_string_dyn, CA_STATIC, (int *)&mudconf.game_pag, SIZEOF_PATHNAME}, {(char *)"good_name", cf_badname, CA_GOD, NULL, 1}, {(char *)"guest_char_num", cf_int, CA_STATIC, &mudconf.guest_char, 0}, {(char *)"guest_nuker", cf_int, CA_GOD, &mudconf.guest_nuker, 0}, {(char *)"guest_prefix", cf_string, CA_STATIC, (int *)mudconf.guest_prefix, 32}, {(char *)"guest_file", cf_string_dyn, CA_STATIC, (int *)&mudconf.guest_file, SIZEOF_PATHNAME}, {(char *)"number_guests", cf_int, CA_STATIC, &mudconf.number_guests, 0}, {(char *)"guests_channel", cf_string, CA_STATIC, (int *)mudconf.guests_channel, 32}, {(char *)"guest_site", cf_site, CA_GOD, (int *)&mudstate.access_list, H_GUEST}, {(char *)"have_comsys", cf_bool, CA_STATIC, &mudconf.have_comsys, 0}, {(char *)"have_mailer", cf_bool, CA_STATIC, &mudconf.have_mailer, 0}, {(char *)"have_zones", cf_bool, CA_STATIC, &mudconf.have_zones, 0}, {(char *)"help_file", cf_string_dyn, CA_STATIC, (int *)&mudconf.help_file, SIZEOF_PATHNAME}, {(char *)"help_index", cf_string_dyn, CA_STATIC, (int *)&mudconf.help_indx, SIZEOF_PATHNAME}, {(char *)"hostnames", cf_bool, CA_GOD, &mudconf.use_hostname, 0}, {(char *)"use_http", cf_bool, CA_STATIC, &mudconf.use_http, 0}, {(char *)"idle_wiz_dark", cf_bool, CA_GOD, &mudconf.idle_wiz_dark, 0}, {(char *)"idle_interval", cf_int, CA_GOD, &mudconf.idle_interval, 0}, {(char *)"idle_timeout", cf_int, CA_GOD, &mudconf.idle_timeout, 0}, {(char *)"include", cf_include, CA_STATIC, NULL, 0}, {(char *)"indent_desc", cf_bool, CA_GOD, &mudconf.indent_desc, 0}, {(char *)"initial_size", cf_int, CA_STATIC, &mudconf.init_size, 0}, {(char *)"input_database", cf_string_dyn, CA_STATIC, (int *)&mudconf.indb, SIZEOF_PATHNAME}, {(char *)"kill_guarantee_cost", cf_int, CA_GOD, &mudconf.killguarantee, 0}, {(char *)"kill_max_cost", cf_int, CA_GOD, &mudconf.killmax, 0}, {(char *)"kill_min_cost", cf_int, CA_GOD, &mudconf.killmin, 0}, {(char *)"lag_maximum", cf_int, CA_GOD, &mudconf.max_cmdsecs, 0}, {(char *)"link_cost", cf_int, CA_GOD, &mudconf.linkcost, 0}, {(char *)"list_access", cf_ntab_access, CA_GOD, (int *)list_names, (long)access_nametab}, {(char *)"lock_recursion_limit", cf_int, CA_WIZARD, &mudconf.lock_nest_lim, 0}, {(char *)"log", cf_modify_bits, CA_GOD, &mudconf.log_options, (long)logoptions_nametab}, {(char *)"log_options", cf_modify_bits, CA_GOD, &mudconf.log_info, (long)logdata_nametab}, {(char *)"logout_cmd_access", cf_ntab_access, CA_GOD, (int *)logout_cmdtable, (long)access_nametab}, {(char *)"logout_cmd_alias", cf_alias, CA_GOD, (int *)&mudstate.logout_cmd_htab,0}, {(char *)"look_obey_terse", cf_bool, CA_GOD, &mudconf.terse_look, 0}, {(char *)"machine_command_cost", cf_int, CA_GOD, &mudconf.machinecost, 0}, {(char *)"mail_database", cf_string_dyn, CA_GOD, (int *)&mudconf.mail_db, SIZEOF_PATHNAME}, {(char *)"mail_expiration", cf_int, CA_GOD, &mudconf.mail_expiration, 0}, {(char *)"master_room", cf_int, CA_GOD, &mudconf.master_room, 0}, {(char *)"match_own_commands", cf_bool, CA_GOD, &mudconf.match_mine, 0}, {(char *)"max_players", cf_int, CA_GOD, &mudconf.max_players, 0}, {(char *)"max_cache_size", cf_int, CA_GOD, (int *)&mudconf.max_cache_size, 0}, {(char *)"money_name_plural", cf_string, CA_GOD, (int *)mudconf.many_coins, 32}, {(char *)"money_name_singular", cf_string, CA_GOD, (int *)mudconf.one_coin, 32}, {(char *)"motd_file", cf_string_dyn, CA_STATIC, (int *)&mudconf.motd_file, SIZEOF_PATHNAME}, {(char *)"motd_message", cf_string, CA_GOD, (int *)mudconf.motd_msg, GBUF_SIZE}, {(char *)"mud_name", cf_string, CA_GOD, (int *)mudconf.mud_name, 32}, {(char *)"news_file", cf_string_dyn, CA_STATIC, (int *)&mudconf.news_file, SIZEOF_PATHNAME}, {(char *)"news_index", cf_string_dyn, CA_STATIC, (int *)&mudconf.news_indx, SIZEOF_PATHNAME}, {(char *)"newuser_file", cf_string_dyn, CA_STATIC, (int *)&mudconf.crea_file, SIZEOF_PATHNAME}, {(char *)"notify_recursion_limit", cf_int, CA_GOD, &mudconf.ntfy_nest_lim, 0}, {(char *)"open_cost", cf_int, CA_GOD, &mudconf.opencost, 0}, {(char *)"output_database", cf_string_dyn, CA_STATIC, (int *)&mudconf.outdb, SIZEOF_PATHNAME}, {(char *)"output_limit", cf_int, CA_GOD, &mudconf.output_limit, 0}, {(char *)"page_cost", cf_int, CA_GOD, &mudconf.pagecost, 0}, {(char *)"paranoid_allocate", cf_bool, CA_GOD, &mudconf.paranoid_alloc, 0}, {(char *)"parent_recursion_limit", cf_int, CA_GOD, &mudconf.parent_nest_lim, 0}, {(char *)"paycheck", cf_int, CA_GOD, &mudconf.paycheck, 0}, {(char *)"pemit_far_players", cf_bool, CA_GOD, &mudconf.pemit_players, 0}, {(char *)"pemit_any_object", cf_bool, CA_GOD, &mudconf.pemit_any, 0}, {(char *)"permit_site", cf_site, CA_GOD, (int *)&mudstate.access_list, 0}, {(char *)"player_flags", cf_set_flags, CA_GOD, (int *)&mudconf.player_flags, 0}, {(char *)"player_listen", cf_bool, CA_GOD, &mudconf.player_listen, 0}, {(char *)"player_match_own_commands", cf_bool, CA_GOD, &mudconf.match_mine_pl, 0}, {(char *)"player_name_spaces", cf_bool, CA_GOD, &mudconf.name_spaces, 0}, {(char *)"player_queue_limit", cf_int, CA_GOD, &mudconf.queuemax, 0}, {(char *)"player_quota", cf_int, CA_GOD, &mudconf.player_quota, 0}, {(char *)"player_starting_home", cf_int, CA_GOD, &mudconf.start_home, 0}, {(char *)"player_starting_room", cf_int, CA_GOD, &mudconf.start_room, 0}, {(char *)"plushelp_file", cf_string_dyn, CA_STATIC, (int *)&mudconf.plushelp_file, SIZEOF_PATHNAME}, {(char *)"plushelp_index", cf_string_dyn, CA_STATIC, (int *)&mudconf.plushelp_indx, SIZEOF_PATHNAME}, {(char *)"staffhelp_file", cf_string_dyn, CA_STATIC, (int *)&mudconf.staffhelp_file, SIZEOF_PATHNAME}, {(char *)"staffhelp_index", cf_string_dyn, CA_STATIC, (int *)&mudconf.staffhelp_indx, SIZEOF_PATHNAME}, {(char *)"public_channel", cf_string, CA_STATIC, (int *)mudconf.public_channel, 32}, {(char *)"wiznews_file", cf_string_dyn, CA_STATIC, (int *)&mudconf.wiznews_file, SIZEOF_PATHNAME}, {(char *)"wiznews_index", cf_string_dyn, CA_STATIC, (int *)&mudconf.wiznews_indx, SIZEOF_PATHNAME}, {(char *)"port", cf_int, CA_STATIC, &mudconf.port, 0}, {(char *)"public_flags", cf_bool, CA_GOD, &mudconf.pub_flags, 0}, {(char *)"queue_active_chunk", cf_int, CA_GOD, &mudconf.active_q_chunk, 0}, {(char *)"queue_idle_chunk", cf_int, CA_GOD, &mudconf.queue_chunk, 0}, {(char *)"quiet_look", cf_bool, CA_GOD, &mudconf.quiet_look, 0}, {(char *)"quiet_whisper", cf_bool, CA_GOD, &mudconf.quiet_whisper, 0}, {(char *)"quit_file", cf_string_dyn, CA_STATIC, (int *)&mudconf.quit_file, SIZEOF_PATHNAME}, {(char *)"quotas", cf_bool, CA_GOD, &mudconf.quotas, 0}, {(char *)"read_remote_desc", cf_bool, CA_GOD, &mudconf.read_rem_desc, 0}, {(char *)"read_remote_name", cf_bool, CA_GOD, &mudconf.read_rem_name, 0}, {(char *)"register_create_file", cf_string_dyn, CA_STATIC, (int *)&mudconf.regf_file, SIZEOF_PATHNAME}, {(char *)"register_site", cf_site, CA_GOD, (int *)&mudstate.access_list, H_REGISTRATION}, {(char *)"allow_guest_from_registered_site", cf_bool, CA_GOD, &mudconf.allow_guest_from_registered_site, 1}, {(char *)"retry_limit", cf_int, CA_GOD, &mudconf.retry_limit, 0}, {(char *)"robot_cost", cf_int, CA_GOD, &mudconf.robotcost, 0}, {(char *)"robot_flags", cf_set_flags, CA_GOD, (int *)&mudconf.robot_flags, 0}, {(char *)"robot_speech", cf_bool, CA_GOD, &mudconf.robot_speak, 0}, {(char *)"room_flags", cf_set_flags, CA_GOD, (int *)&mudconf.room_flags, 0}, {(char *)"room_quota", cf_int, CA_GOD, &mudconf.room_quota, 0}, {(char *)"sacrifice_adjust", cf_int, CA_GOD, &mudconf.sacadjust, 0}, {(char *)"sacrifice_factor", cf_int, CA_GOD, &mudconf.sacfactor, 0}, {(char *)"safer_passwords", cf_bool, CA_GOD, &mudconf.safer_passwords, 0}, {(char *)"search_cost", cf_int, CA_GOD, &mudconf.searchcost, 0}, {(char *)"see_owned_dark", cf_bool, CA_GOD, &mudconf.see_own_dark, 0}, {(char *)"signal_action", cf_option, CA_STATIC, &mudconf.sig_action, (long)sigactions_nametab}, {(char *)"site_chars", cf_int, CA_GOD, (int *)&mudconf.site_chars, 0}, {(char *)"space_compress", cf_bool, CA_GOD, &mudconf.space_compress, 0}, {(char *)"stack_limit", cf_int, CA_GOD, &mudconf.stack_limit, 0}, {(char *)"starting_money", cf_int, CA_GOD, &mudconf.paystart, 0}, {(char *)"starting_quota", cf_int, CA_GOD, &mudconf.start_quota, 0}, {(char *)"status_file", cf_string_dyn, CA_STATIC, (int *)&mudconf.status_file, SIZEOF_PATHNAME}, {(char *)"suspect_site", cf_site, CA_GOD, (int *)&mudstate.suspect_list, H_SUSPECT}, {(char *)"sweep_dark", cf_bool, CA_GOD, &mudconf.sweep_dark, 0}, {(char *)"switch_default_all", cf_bool, CA_GOD, &mudconf.switch_df_all, 0}, {(char *)"terse_shows_contents", cf_bool, CA_GOD, &mudconf.terse_contents, 0}, {(char *)"terse_shows_exits", cf_bool, CA_GOD, &mudconf.terse_exits, 0}, {(char *)"terse_shows_move_messages", cf_bool, CA_GOD, &mudconf.terse_movemsg, 0}, {(char *)"thing_flags", cf_set_flags, CA_GOD, (int *)&mudconf.thing_flags, 0}, {(char *)"thing_quota", cf_int, CA_GOD, &mudconf.thing_quota, 0}, {(char *)"timeslice", cf_int, CA_GOD, &mudconf.timeslice, 0}, {(char *)"toad_recipient", cf_int, CA_GOD, &mudconf.toad_recipient, 0}, {(char *)"trace_output_limit", cf_int, CA_GOD, &mudconf.trace_limit, 0}, {(char *)"trace_topdown", cf_bool, CA_GOD, &mudconf.trace_topdown, 0}, {(char *)"trust_site", cf_site, CA_GOD, (int *)&mudstate.suspect_list, 0}, {(char *)"uncompress_program", cf_string_dyn, CA_STATIC, (int *)&mudconf.uncompress, SIZEOF_PATHNAME}, {(char *)"unowned_safe", cf_bool, CA_GOD, &mudconf.safe_unowned, 0}, {(char *)"user_attr_access", cf_modify_bits, CA_GOD, &mudconf.vattr_flags, (long)attraccess_nametab}, {(char *)"wait_cost", cf_int, CA_GOD, &mudconf.waitcost, 0}, {(char *)"wizard_help_file", cf_string_dyn, CA_STATIC, (int *)&mudconf.whelp_file, SIZEOF_PATHNAME}, {(char *)"wizard_help_index", cf_string_dyn, CA_STATIC, (int *)&mudconf.whelp_indx, SIZEOF_PATHNAME}, {(char *)"wizard_motd_file", cf_string_dyn, CA_STATIC, (int *)&mudconf.wizmotd_file, SIZEOF_PATHNAME}, {(char *)"wizard_motd_message", cf_string, CA_GOD, (int *)mudconf.wizmotd_msg, GBUF_SIZE}, {(char *)"zone_recursion_limit", cf_int, CA_GOD, &mudconf.zone_nest_lim, 0}, { NULL, NULL, 0, NULL, 0} }; /* * --------------------------------------------------------------------------- * * cf_set: Set config parameter. */ int cf_set(char *cp, char *ap, dbref player) { CONF *tp; int i; char *buff = 0; // 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"); strcpy(buff, ap); } i = tp->interpreter(tp->loc, ap, tp->extra, player, cp); if (!mudstate.initializing) { STARTLOG(LOG_CONFIGMODS, "CFG", "UPDAT"); log_name(player); log_text((char *)" entered config directive: "); log_text(cp); log_text((char *)" with args '"); log_text(buff); log_text((char *)"'. Status: "); switch (i) { case 0: log_text((char *)"Success."); break; case 1: log_text((char *)"Partial success."); break; case -1: log_text((char *)"Failure."); break; default: log_text((char *)"Strange."); } ENDLOG; free_lbuf(buff); } return i; } } // Config directive not found. Complain about it. // cf_log_notfound(player, (char *)"Set", "Config directive", cp); return -1; } /* * --------------------------------------------------------------------------- * * do_admin: Command handler to set config params at runtime */ void do_admin(dbref player, dbref cause, int extra, char *kw, char *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 */ struct { char **pFilename; char *pSuffix; } DefaultSuffixes[] = { { &mudconf.outdb, ".out" }, { &mudconf.crashdb, ".CRASH" }, { &mudconf.game_dir, ".dir" }, { &mudconf.game_pag, ".pag" }, { 0, 0 } }; int cf_read(void) { int retval; mudstate.initializing = 1; retval = cf_include(NULL, mudconf.config_file, 0, 0, (char *)"init"); mudstate.initializing = 0; // Fill in missing DB file names. // unsigned int nInDB = strlen(mudconf.indb); for (int i = 0; DefaultSuffixes[i].pFilename; i++) { char **p = DefaultSuffixes[i].pFilename; if (**p == '\0') { // The filename is an empty string so we should construct // a default filename. // char *pSuffix = DefaultSuffixes[i].pSuffix; int nSuffix = strlen(pSuffix); char *buff = (char *)MEMALLOC(nInDB + nSuffix + 1); ISOUTOFMEMORY(buff); memcpy(buff, mudconf.indb, nInDB); memcpy(buff + nInDB, pSuffix, nSuffix+1); MEMFREE(*p); *p = buff; } } return retval; } /* * --------------------------------------------------------------------------- * * list_cf_access: List access to config directives. */ void list_cf_access(dbref player) { CONF *tp; char *buff; buff = alloc_mbuf("list_cf_access"); for (tp = conftable; tp->pname; tp++) { if (God(player) || check_access(player, tp->flags)) { sprintf(buff, "%s:", tp->pname); listset_nametab(player, access_nametab, tp->flags, buff, 1); } } free_mbuf(buff); } #endif /* * * STANDALONE */