#include "config.h" #include "params.h" #include "db.h" #include "defaults.h" #include "externs.h" #include "array.h" #include "interp.h" const char *tp_dumpwarn_mesg = DUMPWARN_MESG; const char *tp_deltawarn_mesg = DELTAWARN_MESG; const char *tp_dumpdeltas_mesg = DUMPDELTAS_MESG; const char *tp_dumping_mesg = DUMPING_MESG; const char *tp_dumpdone_mesg = DUMPDONE_MESG; const char *tp_penny = PENNY; const char *tp_pennies = PENNIES; const char *tp_cpenny = CPENNY; const char *tp_cpennies = CPENNIES; const char *tp_muckname = MUCKNAME; const char *tp_rwho_passwd = RWHO_PASSWD; const char *tp_rwho_server = RWHO_SERVER; const char *tp_huh_mesg = HUH_MESSAGE; const char *tp_leave_mesg = LEAVE_MESSAGE; const char *tp_idle_mesg = IDLEBOOT_MESSAGE; const char *tp_register_mesg = REG_MSG; const char *tp_playermax_warnmesg = PLAYERMAX_WARNMESG; const char *tp_playermax_bootmesg = PLAYERMAX_BOOTMESG; const char *tp_autolook_cmd = AUTOLOOK_CMD; const char *tp_proplist_counter_fmt = PROPLIST_COUNTER_FORMAT; const char *tp_proplist_entry_fmt = PROPLIST_ENTRY_FORMAT; const char *tp_ssl_keyfile_passwd = SSL_KEYFILE_PASSWD; const char *tp_pcreate_flags = PCREATE_FLAGS; const char *tp_reserved_names = RESERVED_NAMES; const char *tp_reserved_player_names = RESERVED_PLAYER_NAMES; struct tune_str_entry { const char *group; const char *name; const char **str; int security; int isdefault; const char *label; }; struct tune_str_entry tune_str_list[] = { {"Commands", "autolook_cmd", &tp_autolook_cmd, 0, 1, "Room entry look command"}, {"Currency", "penny", &tp_penny, 0, 1, "Currency name"}, {"Currency", "pennies", &tp_pennies, 0, 1, "Currency name, plural"}, {"Currency", "cpenny", &tp_cpenny, 0, 1, "Currency name, capitalized"}, {"Currency", "cpennies", &tp_cpennies, 0, 1, "Currency name, capitalized, plural"}, {"DB Dumps", "dumpwarn_mesg", &tp_dumpwarn_mesg, 0, 1, "Full dump warning mesg"}, {"DB Dumps", "deltawarn_mesg", &tp_deltawarn_mesg, 0, 1, "Delta dump warning mesg"}, {"DB Dumps", "dumping_mesg", &tp_dumping_mesg, 0, 1, "Full dump start mesg"}, {"DB Dumps", "dumpdeltas_mesg", &tp_dumpdeltas_mesg, 0, 1, "Delta dump start mesg"}, {"DB Dumps", "dumpdone_mesg", &tp_dumpdone_mesg, 0, 1, "Dump completion message"}, {"Idle Boot", "idle_boot_mesg", &tp_idle_mesg, 0, 1, "Boot message for idling out"}, {"Player Max", "playermax_warnmesg", &tp_playermax_warnmesg, 0, 1, "Max. players login warning"}, {"Player Max", "playermax_bootmesg", &tp_playermax_bootmesg, 0, 1, "Max. players boot message"}, {"Properties", "proplist_counter_fmt", &tp_proplist_counter_fmt, 0, 1, "Proplist counter name format"}, {"Properties", "proplist_entry_fmt", &tp_proplist_entry_fmt, 0, 1, "Proplist entry name format"}, {"Registration", "register_mesg", &tp_register_mesg, 0, 1, "Login registration mesg"}, {"RWHO", "rwho_passwd", &tp_rwho_passwd, 4, 1, "RWHO server entry password"}, {"RWHO", "rwho_server", &tp_rwho_server, 4, 1, "RWHO server hostname"}, {"Misc", "muckname", &tp_muckname, 0, 1, "Muck name"}, {"Misc", "leave_mesg", &tp_leave_mesg, 0, 1, "Logoff message"}, {"Misc", "huh_mesg", &tp_huh_mesg, 0, 1, "Command unrecognized warning"}, {"SSL", "ssl_keyfile_passwd", &tp_ssl_keyfile_passwd, 4, 1, "Password for SSL keyfile"}, {"Database", "pcreate_flags", &tp_pcreate_flags, 0, 1, "Initial Player Flags"}, {"Database", "reserved_names", &tp_reserved_names, 0, 1, "Reserved names smatch"}, {"Database", "reserved_player_names", &tp_reserved_player_names, 0, 1, "Reserved player names smatch"}, {NULL, NULL, NULL, 0, 0} }; /* times */ int tp_rwho_interval = RWHO_INTERVAL; int tp_dump_interval = DUMP_INTERVAL; int tp_dump_warntime = DUMP_WARNTIME; int tp_monolithic_interval = MONOLITHIC_INTERVAL; int tp_clean_interval = CLEAN_INTERVAL; int tp_aging_time = AGING_TIME; int tp_maxidle = MAXIDLE; struct tune_time_entry { const char *group; const char *name; int *tim; int security; const char *label; }; struct tune_time_entry tune_time_list[] = { {"Database", "aging_time", &tp_aging_time, 0, "When to considered an object old and unused"}, {"DB Dumps", "dump_interval", &tp_dump_interval, 0, "Interval between delta dumps"}, {"DB Dumps", "dump_warntime", &tp_dump_warntime, 0, "Interval between warning and dump"}, {"DB Dumps", "monolithic_interval", &tp_monolithic_interval, 0, "Interval between full dumps"}, {"Idle Boot", "maxidle", &tp_maxidle, 0, "Maximum idle time before booting"}, {"RWHO", "rwho_interval", &tp_rwho_interval, 0, "Interval between RWHO server updates."}, {"Tuning", "clean_interval", &tp_clean_interval, 0, "Interval between memory cleanups."}, {NULL, NULL, NULL, 0} }; /* integers */ int tp_max_object_endowment = MAX_OBJECT_ENDOWMENT; int tp_object_cost = OBJECT_COST; int tp_exit_cost = EXIT_COST; int tp_link_cost = LINK_COST; int tp_room_cost = ROOM_COST; int tp_lookup_cost = LOOKUP_COST; int tp_max_pennies = MAX_PENNIES; int tp_penny_rate = PENNY_RATE; int tp_start_pennies = START_PENNIES; int tp_kill_base_cost = KILL_BASE_COST; int tp_kill_min_cost = KILL_MIN_COST; int tp_kill_bonus = KILL_BONUS; int tp_command_burst_size = COMMAND_BURST_SIZE; int tp_commands_per_time = COMMANDS_PER_TIME; int tp_command_time_msec = COMMAND_TIME_MSEC; int tp_max_output = MAX_OUTPUT; int tp_max_delta_objs = MAX_DELTA_OBJS; int tp_max_loaded_objs = MAX_LOADED_OBJS; int tp_max_process_limit = MAX_PROCESS_LIMIT; int tp_max_plyr_processes = MAX_PLYR_PROCESSES; int tp_max_instr_count = MAX_INSTR_COUNT; int tp_max_ml4_preempt_count = MAX_ML4_PREEMPT_COUNT; int tp_instr_slice = INSTR_SLICE; int tp_mpi_max_commands = MPI_MAX_COMMANDS; int tp_pause_min = PAUSE_MIN; int tp_free_frames_pool = FREE_FRAMES_POOL; int tp_listen_mlev = LISTEN_MLEV; int tp_playermax_limit = PLAYERMAX_LIMIT; int tp_process_timer_limit = PROCESS_TIMER_LIMIT; int tp_cmd_log_threshold_msec = CMD_LOG_THRESHOLD_MSEC; int tp_userlog_mlev = USERLOG_MLEV; int tp_mcp_muf_mlev = MCP_MUF_MLEV; struct tune_val_entry { const char *group; const char *name; int *val; int security; const char *label; }; struct tune_val_entry tune_val_list[] = { {"Costs", "max_object_endowment", &tp_max_object_endowment, 0, "Max value of object"}, {"Costs", "object_cost", &tp_object_cost, 0, "Cost to create thing"}, {"Costs", "exit_cost", &tp_exit_cost, 0, "Cost to create exit"}, {"Costs", "link_cost", &tp_link_cost, 0, "Cost to link exit"}, {"Costs", "room_cost", &tp_room_cost, 0, "Cost to create room"}, {"Costs", "lookup_cost", &tp_lookup_cost, 0, "Cost to lookup playername"}, {"Currency", "max_pennies", &tp_max_pennies, 0, "Player currency cap"}, {"Currency", "penny_rate", &tp_penny_rate, 0, "Moves between finding currency, avg"}, {"Currency", "start_pennies", &tp_start_pennies, 0, "Player starting currency count"}, {"Killing", "kill_base_cost", &tp_kill_base_cost, 0, "Cost to guarentee kill"}, {"Killing", "kill_min_cost", &tp_kill_min_cost, 0, "Min cost to kill"}, {"Killing", "kill_bonus", &tp_kill_bonus, 0, "Bonus to killed player"}, {"Listeners", "listen_mlev", &tp_listen_mlev, 0, "Mucker Level required for Listener progs"}, {"Logging", "cmd_log_threshold_msec", &tp_cmd_log_threshold_msec, 0, "Log commands that take longer than X millisecs"}, {"MUF", "max_process_limit", &tp_max_process_limit, 0, "Max concurrent processes on system"}, {"MUF", "max_plyr_processes", &tp_max_plyr_processes, 0, "Max concurrent processes per player"}, {"MUF", "max_instr_count", &tp_max_instr_count, 0, "Max MUF instruction run length for ML1"}, {"MUF", "max_ml4_preempt_count", &tp_max_ml4_preempt_count, 0, "Max MUF preempt instruction run length for ML4, (0 = no limit)"}, {"MUF", "instr_slice", &tp_instr_slice, 0, "Instructions run per timeslice"}, {"MUF", "process_timer_limit", &tp_process_timer_limit, 0, "Max timers per process"}, {"MUF", "mcp_muf_mlev", &tp_mcp_muf_mlev, 0, "Mucker Level required to use MCP"}, {"MUF", "userlog_mlev", &tp_userlog_mlev, 0, "Mucker Level required to write to userlog"}, {"MPI", "mpi_max_commands", &tp_mpi_max_commands, 0, "Max MPI instruction run length"}, {"Player Max", "playermax_limit", &tp_playermax_limit, 0, "Max player connections allowed"}, {"Spam Limits", "command_burst_size", &tp_command_burst_size, 0, "Commands before limiter engages"}, {"Spam Limits", "commands_per_time", &tp_commands_per_time, 0, "Commands allowed per time period"}, {"Spam Limits", "command_time_msec", &tp_command_time_msec, 0, "Millisecs per spam limiter time period"}, {"Spam Limits", "max_output", &tp_max_output, 0, "Max output buffer size"}, {"Tuning", "pause_min", &tp_pause_min, 0, "Min ms to pause between MUF timeslices"}, {"Tuning", "free_frames_pool", &tp_free_frames_pool, 0, "Size of MUF process frame pool"}, {"Tuning", "max_delta_objs", &tp_max_delta_objs, 0, "Percentage changed objects to force full dump"}, {"Tuning", "max_loaded_objs", &tp_max_loaded_objs, 0, "Max proploaded object percentage"}, {NULL, NULL, NULL, 0} }; /* dbrefs */ dbref tp_player_start = PLAYER_START; dbref tp_default_room_parent = GLOBAL_ENVIRONMENT; struct tune_ref_entry { const char *group; const char *name; int typ; dbref *ref; int security; const char *label; }; struct tune_ref_entry tune_ref_list[] = { {"Database", "default_room_parent", TYPE_ROOM, &tp_default_room_parent, 0, "Place to parent new rooms to"}, {"Database", "player_start", TYPE_ROOM, &tp_player_start, 0, "Place where new players start"}, {NULL, NULL, 0, NULL, 0} }; /* booleans */ int tp_hostnames = HOSTNAMES; int tp_log_commands = LOG_COMMANDS; int tp_log_failed_commands = LOG_FAILED_COMMANDS; int tp_log_programs = LOG_PROGRAMS; int tp_dbdump_warning = DBDUMP_WARNING; int tp_deltadump_warning = DELTADUMP_WARNING; int tp_dumpdone_warning = DUMPDONE_WARNING; int tp_periodic_program_purge = PERIODIC_PROGRAM_PURGE; int tp_rwho = RWHO; int tp_secure_who = SECURE_WHO; int tp_who_doing = WHO_DOING; int tp_realms_control = REALMS_CONTROL; int tp_listeners = LISTENERS; int tp_listeners_obj = LISTENERS_OBJ; int tp_listeners_env = LISTENERS_ENV; int tp_zombies = ZOMBIES; int tp_wiz_vehicles = WIZ_VEHICLES; int tp_force_mlev1_name_notify = FORCE_MLEV1_NAME_NOTIFY; int tp_restrict_kill = RESTRICT_KILL; int tp_registration = REGISTRATION; int tp_teleport_to_player = TELEPORT_TO_PLAYER; int tp_secure_teleport = SECURE_TELEPORT; int tp_exit_darking = EXIT_DARKING; int tp_thing_darking = THING_DARKING; int tp_dark_sleepers = DARK_SLEEPERS; int tp_who_hides_dark = WHO_HIDES_DARK; int tp_compatible_priorities = COMPATIBLE_PRIORITIES; int tp_do_mpi_parsing = DO_MPI_PARSING; int tp_look_propqueues = LOOK_PROPQUEUES; int tp_lock_envcheck = LOCK_ENVCHECK; int tp_diskbase_propvals = DISKBASE_PROPVALS; int tp_idleboot = IDLEBOOT; int tp_playermax = PLAYERMAX; int tp_allow_home = ALLOW_HOME; int tp_enable_prefix = ENABLE_PREFIX; int tp_thing_movement = SECURE_THING_MOVEMENT; int tp_expanded_debug = EXPANDED_DEBUG_TRACE; int tp_proplist_int_counter = PROPLIST_INT_COUNTER; int tp_log_interactive = LOG_INTERACTIVE; int tp_lazy_mpi_istype_perm = LAZY_MPI_ISTYPE_PERM; int tp_optimize_muf = OPTIMIZE_MUF; int tp_ignore_support = IGNORE_SUPPORT; int tp_ignore_bidirectional = IGNORE_BIDIRECTIONAL; int tp_verbose_clone = VERBOSE_CLONE; int tp_muf_comments_strict = MUF_COMMENTS_STRICT; struct tune_bool_entry { const char *group; const char *name; int *bool; int security; const char *label; }; struct tune_bool_entry tune_bool_list[] = { {"Commands", "enable_home", &tp_allow_home, 4, "Enable 'home' command"}, {"Commands", "enable_prefix", &tp_enable_prefix, 4, "Enable prefix actions"}, {"Commands", "verbose_clone", &tp_verbose_clone, 4, "Verbose @clone command"}, {"Dark", "exit_darking", &tp_exit_darking, 0, "Allow setting exits dark"}, {"Dark", "thing_darking", &tp_thing_darking, 0, "Allow setting things dark"}, {"Dark", "dark_sleepers", &tp_dark_sleepers, 0, "Make sleeping players dark"}, {"Dark", "who_hides_dark", &tp_who_hides_dark, 4, "Hide dark players from WHO list"}, {"Database", "realms_control", &tp_realms_control, 0, "Enable Realms control"}, {"Database", "compatible_priorities", &tp_compatible_priorities, 0, "Use legacy exit priority levels on things"}, {"DB Dumps", "diskbase_propvals", &tp_diskbase_propvals, 0, "Enable property value diskbasing (req. restart)"}, {"DB Dumps", "dbdump_warning", &tp_dbdump_warning, 0, "Enable warning messages for full DB dumps"}, {"DB Dumps", "deltadump_warning", &tp_deltadump_warning, 0, "Enable warning messages for delta DB dumps"}, {"DB Dumps", "dumpdone_warning", &tp_dumpdone_warning, 0, "Enable notification of DB dump completion"}, {"Idle Boot", "idleboot", &tp_idleboot, 0, "Enable booting of idle players"}, {"Killing", "restrict_kill", &tp_restrict_kill, 0, "Restrict kill command to players set Kill_OK"}, {"Listeners", "allow_listeners", &tp_listeners, 0, "Enable programs to listen to player output"}, {"Listeners", "allow_listeners_obj", &tp_listeners_obj, 0, "Allow listeners on things"}, {"Listeners", "allow_listeners_env", &tp_listeners_env, 0, "Allow listeners down environment"}, {"Logging", "log_commands", &tp_log_commands, 4, "Enable logging of player commands"}, {"Logging", "log_failed_commands", &tp_log_failed_commands, 4, "Enable logging of unrecognized commands"}, {"Logging", "log_interactive", &tp_log_interactive, 4, "Enable logging of text sent to MUF"}, {"Logging", "log_programs", &tp_log_programs, 4, "Log programs every time they are saved"}, {"Movement", "teleport_to_player", &tp_teleport_to_player, 0, "Allow teleporting to a player"}, {"Movement", "secure_teleport", &tp_secure_teleport, 0, "Restrict actions to Jump_OK or controlled rooms"}, {"Movement", "secure_thing_movement", &tp_thing_movement, 4, "Moving things act like player"}, {"MPI", "do_mpi_parsing", &tp_do_mpi_parsing, 0, "Enable parsing of mesgs for MPI"}, {"MPI", "lazy_mpi_istype_perm", &tp_lazy_mpi_istype_perm, 0, "Enable looser legacy perms for MPI {istype}"}, {"MUF", "optimize_muf", &tp_optimize_muf, 0, "Enable MUF bytecode optimizer"}, {"MUF", "expanded_debug_trace", &tp_expanded_debug, 0, "MUF debug trace shows array contents"}, {"MUF", "force_mlev1_name_notify", &tp_force_mlev1_name_notify, 0, "MUF notify prepends username at ML1"}, {"MUF", "muf_comments_strict", &tp_muf_comments_strict, 0, "MUF comments are strict and not recursive"}, {"Player Max", "playermax", &tp_playermax, 0, "Limit number of concurrent players allowed"}, {"Properties", "look_propqueues", &tp_look_propqueues, 0, "When a player looks, trigger _look/ propqueues"}, {"Properties", "lock_envcheck", &tp_lock_envcheck, 0, "Locks check environment for properties"}, {"Properties", "proplist_int_counter", &tp_proplist_int_counter, 0, "Proplist counter uses an integer property"}, {"Registration", "registration", &tp_registration, 0, "Require new players to register manually"}, {"RWHO", "support_rwho", &tp_rwho, 0, "Enable RWHO server support"}, {"Tuning", "periodic_program_purge", &tp_periodic_program_purge, 0, "Periodically free unused MUF programs"}, {"WHO", "use_hostnames", &tp_hostnames, 0, "Resolve IP addresses into hostnames"}, {"WHO", "secure_who", &tp_secure_who, 0, "Disallow WHO command from login screen and programs"}, {"WHO", "who_doing", &tp_who_doing, 0, "Show '_/do' property value in WHO lists"}, {"Misc", "allow_zombies", &tp_zombies, 0, "Enable Zombie things to relay what they hear"}, {"Misc", "wiz_vehicles", &tp_wiz_vehicles, 0, "Only let Wizards set vehicle bits"}, {"Misc", "ignore_support", &tp_ignore_support, 3, "Enable support for @ignoring players"}, {"Misc", "ignore_bidirectional", &tp_ignore_bidirectional, 3, "Enable bidirectional @ignore"}, {NULL, NULL, NULL, 0} }; static const char * timestr_full(long dtime) { static char buf[32]; int days, hours, minutes, seconds; days = dtime / 86400; dtime %= 86400; hours = dtime / 3600; dtime %= 3600; minutes = dtime / 60; seconds = dtime % 60; snprintf(buf, sizeof(buf), "%3dd %2d:%02d:%02d", days, hours, minutes, seconds); return buf; } int tune_count_parms(void) { int total = 0; struct tune_str_entry *tstr = tune_str_list; struct tune_time_entry *ttim = tune_time_list; struct tune_val_entry *tval = tune_val_list; struct tune_ref_entry *tref = tune_ref_list; struct tune_bool_entry *tbool = tune_bool_list; while ((tstr++)->name) total++; while ((ttim++)->name) total++; while ((tval++)->name) total++; while ((tref++)->name) total++; while ((tbool++)->name) total++; return total; } void tune_display_parms(dbref player, char *name) { char buf[BUFFER_LEN + 50]; struct tune_str_entry *tstr = tune_str_list; struct tune_time_entry *ttim = tune_time_list; struct tune_val_entry *tval = tune_val_list; struct tune_ref_entry *tref = tune_ref_list; struct tune_bool_entry *tbool = tune_bool_list; while (tstr->name) { strcpy(buf, tstr->name); if (!*name || equalstr(name, buf)) { snprintf(buf, sizeof(buf), "(str) %-20s = %.4096s", tstr->name, *tstr->str); notify(player, buf); } tstr++; } while (ttim->name) { strcpy(buf, ttim->name); if (!*name || equalstr(name, buf)) { snprintf(buf, sizeof(buf), "(time) %-20s = %s", ttim->name, timestr_full(*ttim->tim)); notify(player, buf); } ttim++; } while (tval->name) { strcpy(buf, tval->name); if (!*name || equalstr(name, buf)) { snprintf(buf, sizeof(buf), "(int) %-20s = %d", tval->name, *tval->val); notify(player, buf); } tval++; } while (tref->name) { strcpy(buf, tref->name); if (!*name || equalstr(name, buf)) { snprintf(buf, sizeof(buf), "(ref) %-20s = %s", tref->name, unparse_object(player, *tref->ref)); notify(player, buf); } tref++; } while (tbool->name) { strcpy(buf, tbool->name); if (!*name || equalstr(name, buf)) { snprintf(buf, sizeof(buf), "(bool) %-20s = %s", tbool->name, ((*tbool->bool) ? "yes" : "no")); notify(player, buf); } tbool++; } notify(player, "*done*"); } void tune_save_parms_to_file(FILE * f) { struct tune_str_entry *tstr = tune_str_list; struct tune_time_entry *ttim = tune_time_list; struct tune_val_entry *tval = tune_val_list; struct tune_ref_entry *tref = tune_ref_list; struct tune_bool_entry *tbool = tune_bool_list; while (tstr->name) { fprintf(f, "%s=%.4096s\n", tstr->name, *tstr->str); tstr++; } while (ttim->name) { fprintf(f, "%s=%s\n", ttim->name, timestr_full(*ttim->tim)); ttim++; } while (tval->name) { fprintf(f, "%s=%d\n", tval->name, *tval->val); tval++; } while (tref->name) { fprintf(f, "%s=#%d\n", tref->name, *tref->ref); tref++; } while (tbool->name) { fprintf(f, "%s=%s\n", tbool->name, (*tbool->bool) ? "yes" : "no"); tbool++; } } stk_array* tune_parms_array(const char* pattern, int mlev) { struct tune_str_entry *tstr = tune_str_list; struct tune_time_entry *ttim = tune_time_list; struct tune_val_entry *tval = tune_val_list; struct tune_ref_entry *tref = tune_ref_list; struct tune_bool_entry *tbool = tune_bool_list; stk_array *nu = new_array_packed(0); struct inst temp1; char pat[BUFFER_LEN]; char buf[BUFFER_LEN]; int i = 0; strcpy(pat, pattern); while (tbool->name) { if (tbool->security <= mlev) { strcpy(buf, tbool->name); if (!*pattern || equalstr(pat, buf)) { stk_array *item = new_array_dictionary(); array_set_strkey_strval(&item, "type", "boolean"); array_set_strkey_strval(&item, "group", tbool->group); array_set_strkey_strval(&item, "name", tbool->name); array_set_strkey_intval(&item, "value", *tbool->bool? 1 : 0); array_set_strkey_intval(&item, "mlev", tbool->security); array_set_strkey_strval(&item, "label", tbool->label); temp1.type = PROG_ARRAY; temp1.data.array = item; array_set_intkey(&nu, i++, &temp1); CLEAR(&temp1); } } tbool++; } while (ttim->name) { if (ttim->security <= mlev) { strcpy(buf, ttim->name); if (!*pattern || equalstr(pat, buf)) { stk_array *item = new_array_dictionary(); array_set_strkey_strval(&item, "type", "timespan"); array_set_strkey_strval(&item, "group", ttim->group); array_set_strkey_strval(&item, "name", ttim->name); array_set_strkey_intval(&item, "value", *ttim->tim); array_set_strkey_intval(&item, "mlev", ttim->security); array_set_strkey_strval(&item, "label", ttim->label); temp1.type = PROG_ARRAY; temp1.data.array = item; array_set_intkey(&nu, i++, &temp1); CLEAR(&temp1); } } ttim++; } while (tval->name) { if (tval->security <= mlev) { strcpy(buf, tval->name); if (!*pattern || equalstr(pat, buf)) { stk_array *item = new_array_dictionary(); array_set_strkey_strval(&item, "type", "integer"); array_set_strkey_strval(&item, "group", tval->group); array_set_strkey_strval(&item, "name", tval->name); array_set_strkey_intval(&item, "value", *tval->val); array_set_strkey_intval(&item, "mlev", tval->security); array_set_strkey_strval(&item, "label", tval->label); temp1.type = PROG_ARRAY; temp1.data.array = item; array_set_intkey(&nu, i++, &temp1); CLEAR(&temp1); } } tval++; } while (tref->name) { if (tref->security <= mlev) { strcpy(buf, tref->name); if (!*pattern || equalstr(pat, buf)) { stk_array *item = new_array_dictionary(); array_set_strkey_strval(&item, "type", "dbref"); array_set_strkey_strval(&item, "group", tref->group); array_set_strkey_strval(&item, "name", tref->name); array_set_strkey_refval(&item, "value", *tref->ref); array_set_strkey_intval(&item, "mlev", tref->security); array_set_strkey_strval(&item, "label", tref->label); switch (tref->typ) { case NOTYPE: array_set_strkey_strval(&item, "objtype", "any"); break; case TYPE_PLAYER: array_set_strkey_strval(&item, "objtype", "player"); break; case TYPE_THING: array_set_strkey_strval(&item, "objtype", "thing"); break; case TYPE_ROOM: array_set_strkey_strval(&item, "objtype", "room"); break; case TYPE_EXIT: array_set_strkey_strval(&item, "objtype", "exit"); break; case TYPE_PROGRAM: array_set_strkey_strval(&item, "objtype", "program"); break; case TYPE_GARBAGE: array_set_strkey_strval(&item, "objtype", "garbage"); break; default: array_set_strkey_strval(&item, "objtype", "unknown"); break; } temp1.type = PROG_ARRAY; temp1.data.array = item; array_set_intkey(&nu, i++, &temp1); CLEAR(&temp1); } } tref++; } while (tstr->name) { if (tstr->security <= mlev) { strcpy(buf, tstr->name); if (!*pattern || equalstr(pat, buf)) { stk_array *item = new_array_dictionary(); array_set_strkey_strval(&item, "type", "string"); array_set_strkey_strval(&item, "group", tstr->group); array_set_strkey_strval(&item, "name", tstr->name); array_set_strkey_strval(&item, "value", *tstr->str); array_set_strkey_intval(&item, "mlev", tstr->security); array_set_strkey_strval(&item, "label", tstr->label); temp1.type = PROG_ARRAY; temp1.data.array = item; array_set_intkey(&nu, i++, &temp1); CLEAR(&temp1); } } tstr++; } return nu; } void tune_save_parmsfile(void) { FILE *f; f = fopen(PARMFILE_NAME, "w"); if (!f) { log_status("Couldn't open file %s!\n", PARMFILE_NAME); return; } tune_save_parms_to_file(f); fclose(f); } const char * tune_get_parmstring(const char *name, int mlev) { static char buf[BUFFER_LEN + 50]; struct tune_str_entry *tstr = tune_str_list; struct tune_time_entry *ttim = tune_time_list; struct tune_val_entry *tval = tune_val_list; struct tune_ref_entry *tref = tune_ref_list; struct tune_bool_entry *tbool = tune_bool_list; while (tstr->name) { if (!string_compare(name, tstr->name)) { if (tstr->security > mlev) return ""; return (*tstr->str); } tstr++; } while (ttim->name) { if (!string_compare(name, ttim->name)) { if (ttim->security > mlev) return ""; snprintf(buf, sizeof(buf), "%d", *ttim->tim); return (buf); } ttim++; } while (tval->name) { if (!string_compare(name, tval->name)) { if (tval->security > mlev) return ""; snprintf(buf, sizeof(buf), "%d", *tval->val); return (buf); } tval++; } while (tref->name) { if (!string_compare(name, tref->name)) { if (tref->security > mlev) return ""; snprintf(buf, sizeof(buf), "#%d", *tref->ref); return (buf); } tref++; } while (tbool->name) { if (!string_compare(name, tbool->name)) { if (tbool->security > mlev) return ""; snprintf(buf, sizeof(buf), "%s", ((*tbool->bool) ? "yes" : "no")); return (buf); } tbool++; } /* Parameter was not found. Return null string. */ strcpy(buf, ""); return (buf); } /* return values: * 0 for success. * 1 for unrecognized parameter name. * 2 for bad parameter value syntax. * 3 for bad parameter value. */ #define TUNESET_SUCCESS 0 #define TUNESET_UNKNOWN 1 #define TUNESET_SYNTAX 2 #define TUNESET_BADVAL 3 void tune_freeparms() { struct tune_str_entry *tstr = tune_str_list; while (tstr->name) { if (!tstr->isdefault) { free((char *) *tstr->str); } tstr++; } } int tune_setparm(const char *parmname, const char *val) { struct tune_str_entry *tstr = tune_str_list; struct tune_time_entry *ttim = tune_time_list; struct tune_val_entry *tval = tune_val_list; struct tune_ref_entry *tref = tune_ref_list; struct tune_bool_entry *tbool = tune_bool_list; char buf[BUFFER_LEN]; char *parmval; strcpy(buf, val); parmval = buf; while (tstr->name) { if (!string_compare(parmname, tstr->name)) { if (!tstr->isdefault) free((char *) *tstr->str); if (*parmval == '-') parmval++; *tstr->str = string_dup(parmval); tstr->isdefault = 0; return 0; } tstr++; } while (ttim->name) { if (!string_compare(parmname, ttim->name)) { int days, hrs, mins, secs, result; char *end; days = hrs = mins = secs = 0; end = parmval + strlen(parmval) - 1; switch (*end) { case 's': case 'S': *end = '\0'; if (!number(parmval)) return 2; secs = atoi(parmval); break; case 'm': case 'M': *end = '\0'; if (!number(parmval)) return 2; mins = atoi(parmval); break; case 'h': case 'H': *end = '\0'; if (!number(parmval)) return 2; hrs = atoi(parmval); break; case 'd': case 'D': *end = '\0'; if (!number(parmval)) return 2; days = atoi(parmval); break; default: result = sscanf(parmval, "%dd %2d:%2d:%2d", &days, &hrs, &mins, &secs); if (result != 4) return 2; break; } *ttim->tim = (days * 86400) + (3600 * hrs) + (60 * mins) + secs; return 0; } ttim++; } while (tval->name) { if (!string_compare(parmname, tval->name)) { if (!number(parmval)) return 2; *tval->val = atoi(parmval); return 0; } tval++; } while (tref->name) { if (!string_compare(parmname, tref->name)) { dbref obj; if (*parmval != NUMBER_TOKEN) return 2; if (!number(parmval + 1)) return 2; obj = (dbref) atoi(parmval + 1); if (obj < 0 || obj >= db_top) return 2; if (tref->typ != NOTYPE && Typeof(obj) != tref->typ) return 3; *tref->ref = obj; return 0; } tref++; } while (tbool->name) { if (!string_compare(parmname, tbool->name)) { if (*parmval == 'y' || *parmval == 'Y') { *tbool->bool = 1; } else if (*parmval == 'n' || *parmval == 'N') { *tbool->bool = 0; } else { return 2; } return 0; } tbool++; } return 1; } void tune_load_parms_from_file(FILE * f, dbref player, int cnt) { char buf[BUFFER_LEN]; char *c, *p; int result=0; while (!feof(f) && (cnt < 0 || cnt--)) { fgets(buf, sizeof(buf), f); if (*buf != '#') { p = c = index(buf, '='); if (c) { *c++ = '\0'; while (p > buf && isspace(*(--p))) *p = '\0'; while (isspace(*c)) c++; for (p = c; *p && *p != '\n' && *p != '\r'; p++) ; *p = '\0'; for (p = buf; isspace(*p); p++) ; if (*p) { result = tune_setparm(p, c); } switch (result) { case TUNESET_SUCCESS: strcatn(buf, sizeof(buf), ": Parameter set."); break; case TUNESET_UNKNOWN: strcatn(buf, sizeof(buf), ": Unknown parameter."); break; case TUNESET_SYNTAX: strcatn(buf, sizeof(buf), ": Bad parameter syntax."); break; case TUNESET_BADVAL: strcatn(buf, sizeof(buf), ": Bad parameter value."); break; } if (result && player != NOTHING) notify(player, p); } } } } void tune_load_parmsfile(dbref player) { FILE *f; f = fopen(PARMFILE_NAME, "r"); if (!f) { log_status("Couldn't open file %s!\n", PARMFILE_NAME); return; } tune_load_parms_from_file(f, player, -1); fclose(f); } void do_tune(dbref player, char *parmname, char *parmval) { int result; if (!Wizard(player)) { notify(player, "You pull out a harmonica and play a short tune."); return; } if (*parmname && *parmval) { result = tune_setparm(parmname, parmval); switch (result) { case TUNESET_SUCCESS: log_status("TUNED: %s(%d) tuned %s to %s\n", NAME(player), player, parmname, parmval); notify(player, "Parameter set."); tune_display_parms(player, parmname); break; case TUNESET_UNKNOWN: notify(player, "Unknown parameter."); break; case TUNESET_SYNTAX: notify(player, "Bad parameter syntax."); break; case TUNESET_BADVAL: notify(player, "Bad parameter value."); break; } return; } else if (*parmname) { if (!string_compare(parmname, "save")) { tune_save_parmsfile(); notify(player, "Saved parameters to configuration file."); } else if (!string_compare(parmname, "load")) { tune_load_parmsfile(player); notify(player, "Restored parameters from configuration file."); } else { tune_display_parms(player, parmname); } return; } else if (!*parmval && !*parmname) { tune_display_parms(player, parmname); } else { notify(player, "But what do you want to tune?"); return; } }