// command.cpp - command parser and support routines. // // $Id: command.cpp,v 1.20 2000/09/07 08:14:41 sdennis Exp $ // #include "copyright.h" #include "autoconf.h" #include "config.h" #include "externs.h" #include "db.h" #include "interface.h" #include "mudconf.h" #include "command.h" #include "functions.h" #include "match.h" #include "attrs.h" #include "flags.h" #include "powers.h" #include "alloc.h" #include "vattr.h" #include "mail.h" #include "comsys.h" extern void FDECL(list_cf_access, (dbref)); extern void FDECL(list_siteinfo, (dbref)); extern void logged_out0(dbref player, dbref cause, int key); extern void logged_out1(dbref player, dbref cause, int key, char *arg); extern void boot_slave(dbref, dbref, int); extern void NDECL(vattr_clean_db); #define SW_MULTIPLE 0x80000000 // This sw may be spec'd w/others. #define SW_GOT_UNIQUE 0x40000000 // Already have a unique option. #define SW_NOEVAL 0x20000000 // Don't parse args before calling // handler (typically controlled via // a switch). // Switch tables for the various commands. // NAMETAB attrib_sw[] = { {(char *)"access", 1, CA_GOD, ATTRIB_ACCESS}, {(char *)"delete", 1, CA_GOD, ATTRIB_DELETE}, {(char *)"rename", 1, CA_GOD, ATTRIB_RENAME}, { NULL, 0, 0, 0} }; NAMETAB boot_sw[] = { {(char *)"port", 1, CA_WIZARD, BOOT_PORT|SW_MULTIPLE}, {(char *)"quiet", 1, CA_WIZARD, BOOT_QUIET|SW_MULTIPLE}, { NULL, 0, 0, 0} }; NAMETAB cemit_sw[] = { {(char *)"noheader", 1, CA_PUBLIC, CEMIT_NOHEADER}, { NULL, 0, 0, 0} }; NAMETAB clone_sw[] = { {(char *)"cost", 1, CA_PUBLIC, CLONE_SET_COST}, {(char *)"inherit", 3, CA_PUBLIC, CLONE_INHERIT|SW_MULTIPLE}, {(char *)"inventory", 3, CA_PUBLIC, CLONE_INVENTORY}, {(char *)"location", 1, CA_PUBLIC, CLONE_LOCATION}, {(char *)"parent", 2, CA_PUBLIC, CLONE_PARENT|SW_MULTIPLE}, {(char *)"preserve", 2, CA_WIZARD, CLONE_PRESERVE|SW_MULTIPLE}, { NULL, 0, 0, 0} }; NAMETAB clist_sw[] = { {(char *)"full", 0, CA_PUBLIC, CLIST_FULL}, { NULL, 0, 0, 0} }; NAMETAB cset_sw[] = { {(char *)"anon", 1, CA_PUBLIC, CSET_SPOOF}, {(char *)"list", 2, CA_PUBLIC, CSET_LIST}, {(char *)"loud", 2, CA_PUBLIC, CSET_LOUD}, {(char *)"mute", 1, CA_PUBLIC, CSET_QUIET}, {(char *)"nospoof", 1, CA_PUBLIC, CSET_NOSPOOF}, {(char *)"object", 1, CA_PUBLIC, CSET_OBJECT}, {(char *)"private", 2, CA_PUBLIC, CSET_PRIVATE}, {(char *)"public", 2, CA_PUBLIC, CSET_PUBLIC}, {(char *)"quiet", 1, CA_PUBLIC, CSET_QUIET}, {(char *)"spoof", 1, CA_PUBLIC, CSET_SPOOF}, { NULL, 0, 0, 0} }; NAMETAB decomp_sw[] = { {(char *)"dbref", 1, CA_PUBLIC, DECOMP_DBREF}, { NULL, 0, 0, 0} }; NAMETAB destroy_sw[] = { {(char *)"override", 8, CA_PUBLIC, DEST_OVERRIDE}, { NULL, 0, 0, 0} }; NAMETAB dig_sw[] = { {(char *)"teleport", 1, CA_PUBLIC, DIG_TELEPORT}, { NULL, 0, 0, 0} }; NAMETAB doing_sw[] = { {(char *)"header", 1, CA_PUBLIC, DOING_HEADER}, {(char *)"message", 1, CA_PUBLIC, DOING_MESSAGE}, {(char *)"poll", 1, CA_PUBLIC, DOING_POLL}, { NULL, 0, 0, 0} }; NAMETAB dolist_sw[] = { {(char *)"delimit", 1, CA_PUBLIC, DOLIST_DELIMIT}, {(char *)"space", 1, CA_PUBLIC, DOLIST_SPACE}, { NULL, 0, 0, 0,} }; NAMETAB drop_sw[] = { {(char *)"quiet", 1, CA_PUBLIC, DROP_QUIET}, { NULL, 0, 0, 0} }; NAMETAB dump_sw[] = { {(char *)"structure", 1, CA_WIZARD, DUMP_STRUCT|SW_MULTIPLE}, {(char *)"text", 1, CA_WIZARD, DUMP_TEXT|SW_MULTIPLE}, {(char *)"flatfile", 1, CA_WIZARD, DUMP_FLATFILE|SW_MULTIPLE}, { NULL, 0, 0, 0} }; NAMETAB emit_sw[] = { {(char *)"here", 2, CA_PUBLIC, SAY_HERE|SW_MULTIPLE}, {(char *)"html", 2, CA_PUBLIC, SAY_HTML|SW_MULTIPLE}, {(char *)"room", 1, CA_PUBLIC, SAY_ROOM|SW_MULTIPLE}, { NULL, 0, 0, 0} }; NAMETAB enter_sw[] = { {(char *)"quiet", 1, CA_PUBLIC, MOVE_QUIET}, { NULL, 0, 0, 0} }; NAMETAB examine_sw[] = { {(char *)"brief", 1, CA_PUBLIC, EXAM_BRIEF}, {(char *)"debug", 1, CA_WIZARD, EXAM_DEBUG}, {(char *)"full", 1, CA_PUBLIC, EXAM_LONG}, {(char *)"parent", 1, CA_PUBLIC, EXAM_PARENT}, { NULL, 0, 0, 0} }; NAMETAB femit_sw[] = { {(char *)"here", 1, CA_PUBLIC, PEMIT_HERE|SW_MULTIPLE}, {(char *)"room", 1, CA_PUBLIC, PEMIT_ROOM|SW_MULTIPLE}, { NULL, 0, 0, 0} }; NAMETAB fixdb_sw[] = { // {(char *)"add_pname",1, CA_GOD, FIXDB_ADD_PN}, {(char *)"contents", 1, CA_GOD, FIXDB_CON}, {(char *)"exits", 1, CA_GOD, FIXDB_EXITS}, {(char *)"location", 1, CA_GOD, FIXDB_LOC}, {(char *)"next", 1, CA_GOD, FIXDB_NEXT}, {(char *)"owner", 1, CA_GOD, FIXDB_OWNER}, {(char *)"pennies", 1, CA_GOD, FIXDB_PENNIES}, {(char *)"rename", 1, CA_GOD, FIXDB_NAME}, // {(char *)"rm_pname", 1, CA_GOD, FIXDB_DEL_PN}, { NULL, 0, 0, 0} }; NAMETAB fpose_sw[] = { {(char *)"default", 1, CA_PUBLIC, 0}, {(char *)"nospace", 1, CA_PUBLIC, SAY_NOSPACE}, { NULL, 0, 0, 0} }; NAMETAB function_sw[] = { {(char *)"list", 1, CA_WIZARD, FN_LIST}, {(char *)"preserve", 3, CA_WIZARD, FN_PRES}, {(char *)"privileged", 3, CA_WIZARD, FN_PRIV}, { NULL, 0, 0, 0} }; NAMETAB get_sw[] = { {(char *)"quiet", 1, CA_PUBLIC, GET_QUIET}, { NULL, 0, 0, 0} }; NAMETAB give_sw[] = { {(char *)"quiet", 1, CA_WIZARD, GIVE_QUIET}, { NULL, 0, 0, 0} }; NAMETAB goto_sw[] = { {(char *)"quiet", 1, CA_PUBLIC, MOVE_QUIET}, { NULL, 0, 0, 0} }; NAMETAB halt_sw[] = { {(char *)"all", 1, CA_PUBLIC, HALT_ALL}, { NULL, 0, 0, 0} }; NAMETAB leave_sw[] = { {(char *)"quiet", 1, CA_PUBLIC, MOVE_QUIET}, { NULL, 0, 0, 0} }; NAMETAB listmotd_sw[] = { {(char *)"brief", 1, CA_WIZARD, MOTD_BRIEF}, { NULL, 0, 0, 0} }; NAMETAB lock_sw[] = { {(char *)"defaultlock", 1, CA_PUBLIC, A_LOCK}, {(char *)"droplock", 1, CA_PUBLIC, A_LDROP}, {(char *)"enterlock", 1, CA_PUBLIC, A_LENTER}, {(char *)"givelock", 1, CA_PUBLIC, A_LGIVE}, {(char *)"leavelock", 2, CA_PUBLIC, A_LLEAVE}, {(char *)"linklock", 2, CA_PUBLIC, A_LLINK}, {(char *)"pagelock", 3, CA_PUBLIC, A_LPAGE}, {(char *)"parentlock", 3, CA_PUBLIC, A_LPARENT}, {(char *)"receivelock", 1, CA_PUBLIC, A_LRECEIVE}, {(char *)"teloutlock", 2, CA_PUBLIC, A_LTELOUT}, {(char *)"tportlock", 2, CA_PUBLIC, A_LTPORT}, {(char *)"uselock", 1, CA_PUBLIC, A_LUSE}, {(char *)"userlock", 4, CA_PUBLIC, A_LUSER}, {(char *)"speechlock", 1, CA_PUBLIC, A_LSPEECH}, { NULL, 0, 0, 0} }; NAMETAB look_sw[] = { {(char *)"outside", 1, CA_PUBLIC, LOOK_OUTSIDE}, { NULL, 0, 0, 0} }; NAMETAB mail_sw[] = { {(char *)"abort", 0, CA_PUBLIC, MAIL_ABORT}, {(char *)"alias", 1, CA_PUBLIC, MAIL_ALIAS}, {(char *)"alist", 1, CA_PUBLIC, MAIL_ALIST}, {(char *)"cc", 2, CA_PUBLIC, MAIL_CC}, {(char *)"clear", 1, CA_PUBLIC, MAIL_CLEAR}, {(char *)"debug", 1, CA_PUBLIC, MAIL_DEBUG}, {(char *)"dstats", 1, CA_PUBLIC, MAIL_DSTATS}, {(char *)"edit", 2, CA_PUBLIC, MAIL_EDIT}, {(char *)"file", 1, CA_PUBLIC, MAIL_FILE}, {(char *)"folder", 1, CA_PUBLIC, MAIL_FOLDER}, {(char *)"forward", 2, CA_PUBLIC, MAIL_FORWARD}, {(char *)"fstats", 1, CA_PUBLIC, MAIL_FSTATS}, {(char *)"fwd", 2, CA_PUBLIC, MAIL_FORWARD}, {(char *)"list", 1, CA_PUBLIC, MAIL_LIST}, {(char *)"nuke", 1, CA_PUBLIC, MAIL_NUKE}, {(char *)"proof", 1, CA_PUBLIC, MAIL_PROOF}, {(char *)"purge", 1, CA_PUBLIC, MAIL_PURGE}, {(char *)"quick", 0, CA_PUBLIC, MAIL_QUICK}, {(char *)"quote", 3, CA_PUBLIC, MAIL_QUOTE|SW_MULTIPLE}, {(char *)"read", 1, CA_PUBLIC, MAIL_READ}, {(char *)"reply", 3, CA_PUBLIC, MAIL_REPLY}, {(char *)"replyall", 6, CA_PUBLIC, MAIL_REPLYALL}, {(char *)"retract", 2, CA_PUBLIC, MAIL_RETRACT}, {(char *)"review", 2, CA_PUBLIC, MAIL_REVIEW}, {(char *)"safe", 2, CA_PUBLIC, MAIL_SAFE}, {(char *)"send", 0, CA_PUBLIC, MAIL_SEND}, {(char *)"stats", 1, CA_PUBLIC, MAIL_STATS}, {(char *)"tag", 1, CA_PUBLIC, MAIL_TAG}, {(char *)"unclear", 1, CA_PUBLIC, MAIL_UNCLEAR}, {(char *)"untag", 1, CA_PUBLIC, MAIL_UNTAG}, {(char *)"urgent", 1, CA_PUBLIC, MAIL_URGENT}, { NULL, 0, 0, 0} }; NAMETAB malias_sw[] = { {(char *)"desc", 1, CA_PUBLIC, MALIAS_DESC}, {(char *)"chown", 1, CA_PUBLIC, MALIAS_CHOWN}, {(char *)"add", 1, CA_PUBLIC, MALIAS_ADD}, {(char *)"remove", 1, CA_PUBLIC, MALIAS_REMOVE}, {(char *)"delete", 1, CA_PUBLIC, MALIAS_DELETE}, {(char *)"rename", 1, CA_PUBLIC, MALIAS_RENAME}, {(char *)"list", 1, CA_PUBLIC, MALIAS_LIST}, {(char *)"status", 1, CA_PUBLIC, MALIAS_STATUS}, { NULL, 0, 0, 0} }; NAMETAB mark_sw[] = { {(char *)"set", 1, CA_PUBLIC, MARK_SET}, {(char *)"clear", 1, CA_PUBLIC, MARK_CLEAR}, { NULL, 0, 0, 0} }; NAMETAB markall_sw[] = { {(char *)"set", 1, CA_PUBLIC, MARK_SET}, {(char *)"clear", 1, CA_PUBLIC, MARK_CLEAR}, { NULL, 0, 0, 0} }; NAMETAB motd_sw[] = { {(char *)"brief", 1, CA_WIZARD, MOTD_BRIEF|SW_MULTIPLE}, {(char *)"connect", 1, CA_WIZARD, MOTD_ALL}, {(char *)"down", 1, CA_WIZARD, MOTD_DOWN}, {(char *)"full", 1, CA_WIZARD, MOTD_FULL}, {(char *)"list", 1, CA_PUBLIC, MOTD_LIST}, {(char *)"wizard", 1, CA_WIZARD, MOTD_WIZ}, { NULL, 0, 0, 0} }; NAMETAB notify_sw[] = { {(char *)"all", 1, CA_PUBLIC, NFY_NFYALL}, {(char *)"first", 1, CA_PUBLIC, NFY_NFY}, { NULL, 0, 0, 0} }; NAMETAB open_sw[] = { {(char *)"inventory", 1, CA_PUBLIC, OPEN_INVENTORY}, {(char *)"location", 1, CA_PUBLIC, OPEN_LOCATION}, { NULL, 0, 0, 0} }; NAMETAB pemit_sw[] = { {(char *)"contents", 1, CA_PUBLIC, PEMIT_CONTENTS|SW_MULTIPLE}, {(char *)"html", 1, CA_PUBLIC, PEMIT_HTML|SW_MULTIPLE}, {(char *)"list", 1, CA_PUBLIC, PEMIT_LIST|SW_MULTIPLE}, {(char *)"noeval", 1, CA_PUBLIC, SW_NOEVAL|SW_MULTIPLE}, {(char *)"object", 1, CA_PUBLIC, 0}, {(char *)"silent", 1, CA_PUBLIC, 0}, { NULL, 0, 0, 0} }; NAMETAB pose_sw[] = { {(char *)"default", 1, CA_PUBLIC, 0}, {(char *)"nospace", 1, CA_PUBLIC, SAY_NOSPACE}, { NULL, 0, 0, 0} }; NAMETAB ps_sw[] = { {(char *)"all", 1, CA_PUBLIC, PS_ALL|SW_MULTIPLE}, {(char *)"brief", 1, CA_PUBLIC, PS_BRIEF}, {(char *)"long", 1, CA_PUBLIC, PS_LONG}, {(char *)"summary", 1, CA_PUBLIC, PS_SUMM}, { NULL, 0, 0, 0} }; NAMETAB quota_sw[] = { {(char *)"all", 1, CA_GOD, QUOTA_ALL|SW_MULTIPLE}, {(char *)"fix", 1, CA_WIZARD, QUOTA_FIX}, {(char *)"remaining", 1, CA_WIZARD, QUOTA_REM|SW_MULTIPLE}, {(char *)"set", 1, CA_WIZARD, QUOTA_SET}, {(char *)"total", 1, CA_WIZARD, QUOTA_TOT|SW_MULTIPLE}, { NULL, 0, 0, 0} }; NAMETAB set_sw[] = { {(char *)"quiet", 1, CA_PUBLIC, SET_QUIET}, { NULL, 0, 0, 0} }; NAMETAB stats_sw[] = { {(char *)"all", 1, CA_PUBLIC, STAT_ALL}, {(char *)"me", 1, CA_PUBLIC, STAT_ME}, {(char *)"player", 1, CA_PUBLIC, STAT_PLAYER}, { NULL, 0, 0, 0} }; NAMETAB sweep_sw[] = { {(char *)"commands", 3, CA_PUBLIC, SWEEP_COMMANDS|SW_MULTIPLE}, {(char *)"connected", 3, CA_PUBLIC, SWEEP_CONNECT|SW_MULTIPLE}, {(char *)"exits", 1, CA_PUBLIC, SWEEP_EXITS|SW_MULTIPLE}, {(char *)"here", 1, CA_PUBLIC, SWEEP_HERE|SW_MULTIPLE}, {(char *)"inventory", 1, CA_PUBLIC, SWEEP_ME|SW_MULTIPLE}, {(char *)"listeners", 1, CA_PUBLIC, SWEEP_LISTEN|SW_MULTIPLE}, {(char *)"players", 1, CA_PUBLIC, SWEEP_PLAYER|SW_MULTIPLE}, { NULL, 0, 0, 0} }; NAMETAB switch_sw[] = { {(char *)"all", 1, CA_PUBLIC, SWITCH_ANY}, {(char *)"default", 1, CA_PUBLIC, SWITCH_DEFAULT}, {(char *)"first", 1, CA_PUBLIC, SWITCH_ONE}, { NULL, 0, 0, 0} }; NAMETAB teleport_sw[] = { {(char *)"loud", 1, CA_PUBLIC, TELEPORT_DEFAULT}, {(char *)"quiet", 1, CA_PUBLIC, TELEPORT_QUIET}, { NULL, 0, 0, 0} }; NAMETAB timecheck_sw[] = { {(char *)"log", 1, CA_WIZARD, TIMECHK_LOG | SW_MULTIPLE}, {(char *)"reset", 1, CA_WIZARD, TIMECHK_RESET | SW_MULTIPLE}, {(char *)"screen", 1, CA_WIZARD, TIMECHK_SCREEN | SW_MULTIPLE}, { NULL, 0, 0, 0} }; NAMETAB toad_sw[] = { {(char *)"no_chown", 1, CA_WIZARD, TOAD_NO_CHOWN|SW_MULTIPLE}, { NULL, 0, 0, 0} }; NAMETAB trig_sw[] = { {(char *)"quiet", 1, CA_PUBLIC, TRIG_QUIET}, { NULL, 0, 0, 0} }; NAMETAB wall_sw[] = { {(char *)"emit", 1, CA_ANNOUNCE, SAY_WALLEMIT}, {(char *)"no_prefix", 1, CA_ANNOUNCE, SAY_NOTAG|SW_MULTIPLE}, {(char *)"pose", 1, CA_ANNOUNCE, SAY_WALLPOSE}, {(char *)"wizard", 1, CA_ANNOUNCE, SAY_WIZSHOUT|SW_MULTIPLE}, {(char *)"admin", 1, CA_ADMIN, SAY_ADMINSHOUT}, { NULL, 0, 0, 0} }; NAMETAB warp_sw[] = { {(char *)"check", 1, CA_WIZARD, TWARP_CLEAN|SW_MULTIPLE}, {(char *)"dump", 1, CA_WIZARD, TWARP_DUMP|SW_MULTIPLE}, {(char *)"idle", 1, CA_WIZARD, TWARP_IDLE|SW_MULTIPLE}, {(char *)"queue", 1, CA_WIZARD, TWARP_QUEUE|SW_MULTIPLE}, {(char *)"events", 1, CA_WIZARD, TWARP_EVENTS|SW_MULTIPLE}, { NULL, 0, 0, 0} }; /* --------------------------------------------------------------------------- * Command table: Definitions for builtin commands, used to build the command * hash table. * * Format: Name Switches Permissions Needed * Key (if any) Calling Seq Handler */ CMDENT_NO_ARG command_table_no_arg[] = { {(char *)"@@", NULL, 0, 0, CS_NO_ARGS, do_comment}, {(char *)"@clist", clist_sw, CA_NO_SLAVE, 0, CS_NO_ARGS, do_chanlist}, {(char *)"@dbck", NULL, CA_WIZARD, 0, CS_NO_ARGS, do_dbck}, {(char *)"@dbclean", NULL, CA_GOD, 0, CS_NO_ARGS, do_dbclean}, {(char *)"@dump", dump_sw, CA_WIZARD, 0, CS_NO_ARGS, do_dump}, {(char *)"@mark_all", markall_sw, CA_WIZARD, MARK_SET, CS_NO_ARGS, do_markall}, {(char *)"@readcache", NULL, CA_WIZARD, 0, CS_NO_ARGS, do_readcache}, {(char *)"@restart", NULL, CA_WIZARD, 0, CS_NO_ARGS, do_restart}, #ifndef WIN32 {(char *)"@startslave", NULL, CA_WIZARD, 0, CS_NO_ARGS, boot_slave}, #endif {(char *)"@timecheck", timecheck_sw, CA_WIZARD, 0, CS_NO_ARGS, do_timecheck}, {(char *)"comlist", NULL, CA_NO_SLAVE, 0, CS_NO_ARGS, do_comlist}, {(char *)"clearcom", NULL, CA_NO_SLAVE, 0, CS_NO_ARGS, do_clearcom}, {(char *)"inventory", NULL, 0, LOOK_INVENTORY, CS_NO_ARGS, do_inventory}, {(char *)"leave", leave_sw, CA_LOCATION, 0, CS_NO_ARGS|CS_INTERP, do_leave}, {(char *)"score", NULL, 0, LOOK_SCORE, CS_NO_ARGS, do_score}, {(char *)"version", NULL, 0, 0, CS_NO_ARGS, do_version}, {(char *)"quit", NULL, CA_PUBLIC, CMD_QUIT, CS_NO_ARGS, logged_out0}, {(char *)"logout", NULL, CA_PUBLIC, CMD_LOGOUT, CS_NO_ARGS, logged_out0}, {(char *)"report", NULL, 0, 0, CS_NO_ARGS, do_report}, {(char *)NULL, NULL, 0, 0, 0, NULL} }; CMDENT_ONE_ARG command_table_one_arg[] = { {(char *)"+help", NULL, 0, HELP_PLUSHELP, CS_ONE_ARG, do_help}, {(char *)"+shelp", NULL, CA_STAFF, HELP_STAFFHELP, CS_ONE_ARG, do_help}, {(char *)"@boot", boot_sw, CA_NO_GUEST|CA_NO_SLAVE, 0, CS_ONE_ARG|CS_INTERP, do_boot}, {(char *)"@ccreate", NULL, CA_NO_SLAVE|CA_NO_GUEST, 0, CS_ONE_ARG, do_createchannel}, {(char *)"@cdestroy", NULL, CA_NO_SLAVE|CA_NO_GUEST, 0, CS_ONE_ARG, do_destroychannel}, {(char *)"@cut", NULL, CA_WIZARD|CA_LOCATION, 0, CS_ONE_ARG|CS_INTERP, do_cut}, {(char *)"@cwho", NULL, CA_NO_SLAVE, 0, CS_ONE_ARG, do_channelwho}, {(char *)"@destroy", destroy_sw, CA_NO_SLAVE|CA_NO_GUEST|CA_GBL_BUILD, DEST_ONE, CS_ONE_ARG|CS_INTERP, do_destroy}, //{(char *)"@destroyall", NULL, CA_WIZARD|CA_GBL_BUILD, DEST_ALL, CS_ONE_ARG, do_destroy}, {(char *)"@disable", NULL, CA_WIZARD, GLOB_DISABLE, CS_ONE_ARG, do_global}, {(char *)"@doing", doing_sw, CA_PUBLIC, 0, CS_ONE_ARG, do_doing}, {(char *)"@emit", emit_sw, CA_LOCATION|CA_NO_GUEST|CA_NO_SLAVE, SAY_EMIT, CS_ONE_ARG|CS_INTERP, do_say}, {(char *)"@enable", NULL, CA_WIZARD, GLOB_ENABLE, CS_ONE_ARG, do_global}, {(char *)"@entrances", NULL, CA_NO_GUEST, 0, CS_ONE_ARG|CS_INTERP, do_entrances}, {(char *)"@find", NULL, 0, 0, CS_ONE_ARG|CS_INTERP, do_find}, {(char *)"@halt", halt_sw, CA_NO_SLAVE, 0, CS_ONE_ARG|CS_INTERP, do_halt}, {(char *)"@kick", NULL, CA_WIZARD, QUEUE_KICK, CS_ONE_ARG|CS_INTERP, do_queue}, {(char *)"@last", NULL, CA_NO_GUEST, 0, CS_ONE_ARG|CS_INTERP, do_last}, {(char *)"@list", NULL, 0, 0, CS_ONE_ARG|CS_INTERP, do_list}, {(char *)"@listcommands", NULL, CA_GOD, 0, CS_ONE_ARG, do_listcommands}, {(char *)"@list_file", NULL, CA_WIZARD, 0, CS_ONE_ARG|CS_INTERP, do_list_file}, {(char *)"@listmotd", listmotd_sw,0, MOTD_LIST, CS_ONE_ARG, do_motd}, {(char *)"@mark", mark_sw, CA_WIZARD, SRCH_MARK, CS_ONE_ARG|CS_NOINTERP, do_search}, {(char *)"@motd", motd_sw, CA_WIZARD, 0, CS_ONE_ARG, do_motd}, {(char *)"@nemit", emit_sw, CA_LOCATION|CA_NO_GUEST|CA_NO_SLAVE, SAY_EMIT, CS_ONE_ARG|CS_UNPARSE|CS_NOSQUISH, do_say}, {(char *)"@poor", NULL, CA_GOD, 0, CS_ONE_ARG|CS_INTERP, do_poor}, {(char *)"@ps", ps_sw, 0, 0, CS_ONE_ARG|CS_INTERP, do_ps}, {(char *)"@quitprogram", NULL, CA_PUBLIC, 0, CS_ONE_ARG|CS_INTERP, do_quitprog}, {(char *)"@search", NULL, 0, SRCH_SEARCH, CS_ONE_ARG|CS_NOINTERP, do_search}, {(char *)"@shutdown", NULL, CA_WIZARD, 0, CS_ONE_ARG, do_shutdown}, {(char *)"@stats", stats_sw, 0, 0, CS_ONE_ARG|CS_INTERP, do_stats}, {(char *)"@sweep", sweep_sw, 0, 0, CS_ONE_ARG, do_sweep}, {(char *)"@timewarp", warp_sw, CA_WIZARD, 0, CS_ONE_ARG|CS_INTERP, do_timewarp}, {(char *)"@unlink", NULL, CA_NO_SLAVE|CA_GBL_BUILD, 0, CS_ONE_ARG|CS_INTERP, do_unlink}, {(char *)"@unlock", lock_sw, CA_NO_SLAVE, 0, CS_ONE_ARG|CS_INTERP, do_unlock}, {(char *)"@wall", wall_sw, CA_ANNOUNCE, SAY_SHOUT, CS_ONE_ARG|CS_INTERP, do_say}, {(char *)"@wipe", wall_sw, CA_NO_SLAVE|CA_NO_GUEST|CA_GBL_BUILD, 0, CS_ONE_ARG|CS_INTERP, do_wipe}, {(char *)"allcom", NULL, CA_NO_SLAVE, 0, CS_ONE_ARG, do_allcom}, {(char *)"delcom", NULL, CA_NO_SLAVE, 0, CS_ONE_ARG, do_delcom}, {(char *)"drop", drop_sw, CA_NO_SLAVE|CA_CONTENTS|CA_LOCATION|CA_NO_GUEST, 0, CS_ONE_ARG|CS_INTERP, do_drop}, {(char *)"enter", enter_sw, CA_LOCATION, 0, CS_ONE_ARG|CS_INTERP, do_enter}, {(char *)"examine", examine_sw, 0, 0, CS_ONE_ARG|CS_INTERP, do_examine}, {(char *)"get", get_sw, CA_LOCATION|CA_NO_GUEST, 0, CS_ONE_ARG|CS_INTERP, do_get}, {(char *)"goto", goto_sw, CA_LOCATION, 0, CS_ONE_ARG|CS_INTERP, do_move}, {(char *)"help", NULL, 0, HELP_HELP, CS_ONE_ARG, do_help}, {(char *)"look", look_sw, CA_LOCATION, LOOK_LOOK, CS_ONE_ARG|CS_INTERP, do_look}, {(char *)"news", NULL, 0, HELP_NEWS, CS_ONE_ARG, do_help}, {(char *)"outputprefix", NULL, CA_PUBLIC, CMD_PREFIX, CS_ONE_ARG, logged_out1}, {(char *)"outputsuffix", NULL, CA_PUBLIC, CMD_SUFFIX, CS_ONE_ARG, logged_out1}, {(char *)"pose", pose_sw, CA_LOCATION|CA_NO_SLAVE, SAY_POSE, CS_ONE_ARG|CS_INTERP, do_say}, {(char *)"say", NULL, CA_LOCATION|CA_NO_SLAVE, SAY_SAY, CS_ONE_ARG|CS_INTERP, do_say}, {(char *)"session", NULL, CA_PUBLIC, CMD_SESSION, CS_ONE_ARG, logged_out1}, {(char *)"think", NULL, CA_NO_SLAVE, 0, CS_ONE_ARG, do_think}, {(char *)"use", NULL, CA_NO_SLAVE|CA_GBL_INTERP, 0, CS_ONE_ARG|CS_INTERP, do_use}, {(char *)"wizhelp", NULL, CA_WIZARD, HELP_WIZHELP, CS_ONE_ARG, do_help}, {(char *)"wiznews", NULL, CA_WIZARD, HELP_WIZNEWS, CS_ONE_ARG, do_help}, {(char *)"doing", NULL, CA_PUBLIC, CMD_DOING, CS_ONE_ARG, logged_out1}, {(char *)"who", NULL, CA_PUBLIC, CMD_WHO, CS_ONE_ARG, logged_out1}, {(char *)"puebloclient", NULL, CA_PUBLIC, CMD_PUEBLOCLIENT,CS_ONE_ARG, logged_out1}, {(char *)"\\", NULL, CA_NO_GUEST|CA_LOCATION|CF_DARK|CA_NO_SLAVE, SAY_PREFIX, CS_ONE_ARG|CS_INTERP, do_say}, {(char *)":", NULL, CA_LOCATION|CF_DARK|CA_NO_SLAVE, SAY_PREFIX, CS_ONE_ARG|CS_INTERP|CS_LEADIN, do_say}, {(char *)";", NULL, CA_LOCATION|CF_DARK|CA_NO_SLAVE, SAY_PREFIX, CS_ONE_ARG|CS_INTERP|CS_LEADIN, do_say}, {(char *)"\"", NULL, CA_LOCATION|CF_DARK|CA_NO_SLAVE, SAY_PREFIX, CS_ONE_ARG|CS_INTERP|CS_LEADIN, do_say}, {(char *)"-", NULL, CA_NO_GUEST|CA_NO_SLAVE|CF_DARK, 0, CS_ONE_ARG|CS_LEADIN, do_postpend}, {(char *)"~", NULL, CA_NO_GUEST|CA_NO_SLAVE|CF_DARK, 0, CS_ONE_ARG|CS_LEADIN, do_prepend}, {(char *)NULL, NULL, 0, 0, 0, NULL} }; CMDENT_ONE_ARG_CMDARG command_table_one_arg_cmdarg[] = { {(char *)"@apply_marked", NULL, CA_WIZARD|CA_GBL_INTERP, 0, CS_ONE_ARG|CS_CMDARG|CS_NOINTERP|CS_STRIP_AROUND, do_apply_marked}, {(char *)"#", NULL, CA_NO_SLAVE|CA_GBL_INTERP|CF_DARK, 0, CS_ONE_ARG|CS_INTERP|CS_CMDARG, do_force_prefixed}, {(char *)NULL, NULL, 0, 0, 0, NULL} }; CMDENT_TWO_ARG command_table_two_arg[] = { {(char *)"@addcommand", NULL, CA_GOD, 0, CS_TWO_ARG, do_addcommand}, {(char *)"@admin", NULL, CA_WIZARD, 0, CS_TWO_ARG|CS_INTERP, do_admin}, {(char *)"@alias", NULL, CA_NO_GUEST|CA_NO_SLAVE, 0, CS_TWO_ARG, do_alias}, {(char *)"@attribute", attrib_sw, CA_GOD, 0, CS_TWO_ARG|CS_INTERP, do_attribute}, {(char *)"@cboot", NULL, CA_NO_SLAVE|CA_NO_GUEST, 0, CS_TWO_ARG, do_chboot}, {(char *)"@ccharge", NULL, CA_NO_SLAVE|CA_NO_GUEST, 1, CS_TWO_ARG, do_editchannel}, {(char *)"@cchown", NULL, CA_NO_SLAVE|CA_NO_GUEST, 0, CS_TWO_ARG, do_editchannel}, {(char *)"@cemit", cemit_sw, CA_NO_SLAVE|CA_NO_GUEST, 0, CS_TWO_ARG, do_cemit}, {(char *)"@chown", NULL, CA_NO_SLAVE|CA_NO_GUEST|CA_GBL_BUILD, CHOWN_ONE, CS_TWO_ARG|CS_INTERP, do_chown}, {(char *)"@chownall", NULL, CA_WIZARD|CA_GBL_BUILD, CHOWN_ALL, CS_TWO_ARG|CS_INTERP, do_chownall}, {(char *)"@chzone", NULL, CA_NO_SLAVE|CA_NO_GUEST|CA_GBL_BUILD, 0, CS_TWO_ARG|CS_INTERP, do_chzone}, {(char *)"@clone", clone_sw, CA_NO_SLAVE|CA_GBL_BUILD|CA_CONTENTS|CA_NO_GUEST, 0, CS_TWO_ARG|CS_INTERP, do_clone}, {(char *)"@coflags", NULL, CA_NO_SLAVE, 4, CS_TWO_ARG, do_editchannel}, {(char *)"@cpflags", NULL, CA_NO_SLAVE, 3, CS_TWO_ARG, do_editchannel}, {(char *)"@create", NULL, CA_NO_SLAVE|CA_GBL_BUILD|CA_CONTENTS|CA_NO_GUEST, 0, CS_TWO_ARG|CS_INTERP, do_create}, {(char *)"@cset", cset_sw, CA_NO_SLAVE, 0, CS_TWO_ARG|CS_INTERP, do_chopen}, {(char *)"@decompile", decomp_sw, 0, 0, CS_TWO_ARG|CS_INTERP, do_decomp}, {(char *)"@delcommand", NULL, CA_GOD, 0, CS_TWO_ARG, do_delcommand}, {(char *)"@drain", NULL, CA_GBL_INTERP|CA_NO_SLAVE|CA_NO_GUEST, NFY_DRAIN, CS_TWO_ARG, do_notify}, {(char *)"@femit", femit_sw, CA_LOCATION|CA_NO_GUEST|CA_NO_SLAVE, PEMIT_FEMIT, CS_TWO_ARG|CS_INTERP, do_pemit}, {(char *)"@fixdb", fixdb_sw, CA_GOD, 0, CS_TWO_ARG|CS_INTERP, do_fixdb}, {(char *)"@fpose", fpose_sw, CA_LOCATION|CA_NO_SLAVE, PEMIT_FPOSE, CS_TWO_ARG|CS_INTERP, do_pemit}, {(char *)"@fsay", NULL, CA_LOCATION|CA_NO_SLAVE, PEMIT_FSAY, CS_TWO_ARG|CS_INTERP, do_pemit}, {(char *)"@function", function_sw,CA_GOD, 0, CS_TWO_ARG|CS_INTERP, do_function}, {(char *)"@link", NULL, CA_NO_SLAVE|CA_GBL_BUILD|CA_NO_GUEST, 0, CS_TWO_ARG|CS_INTERP, do_link}, {(char *)"@lock", lock_sw, CA_NO_SLAVE, 0, CS_TWO_ARG|CS_INTERP, do_lock}, {(char *)"@log", NULL, CA_WIZARD, 0, CS_TWO_ARG, do_log}, {(char *)"@mail", mail_sw, CA_NO_SLAVE|CA_NO_GUEST|CA_PLAYER, 0, CS_TWO_ARG|CS_INTERP, do_mail}, {(char *)"@malias", malias_sw, CA_NO_SLAVE|CA_NO_GUEST, 0, CS_TWO_ARG|CS_INTERP, do_malias}, {(char *)"@name", NULL, CA_NO_SLAVE|CA_GBL_BUILD|CA_NO_GUEST, 0, CS_TWO_ARG|CS_INTERP, do_name}, {(char *)"@newpassword", NULL, CA_WIZARD, PASS_ANY, CS_TWO_ARG, do_newpassword}, {(char *)"@notify", notify_sw, CA_GBL_INTERP|CA_NO_SLAVE|CA_NO_GUEST, 0, CS_TWO_ARG, do_notify}, {(char *)"@oemit", NULL, CA_LOCATION|CA_NO_GUEST|CA_NO_SLAVE, PEMIT_OEMIT, CS_TWO_ARG|CS_INTERP, do_pemit}, {(char *)"@parent", NULL, CA_NO_SLAVE|CA_GBL_BUILD|CA_NO_GUEST, 0, CS_TWO_ARG, do_parent}, {(char *)"@password", NULL, CA_NO_GUEST, PASS_MINE, CS_TWO_ARG, do_password}, {(char *)"@pcreate", NULL, CA_WIZARD|CA_GBL_BUILD, PCRE_PLAYER, CS_TWO_ARG, do_pcreate}, {(char *)"@pemit", pemit_sw, CA_NO_GUEST|CA_NO_SLAVE, PEMIT_PEMIT, CS_TWO_ARG|CS_INTERP, do_pemit}, {(char *)"@npemit", pemit_sw, CA_NO_GUEST|CA_NO_SLAVE, PEMIT_PEMIT, CS_TWO_ARG|CS_UNPARSE|CS_NOSQUISH, do_pemit}, {(char *)"@power", NULL, 0, 0, CS_TWO_ARG, do_power}, {(char *)"@program", NULL, CA_PUBLIC, 0, CS_TWO_ARG|CS_INTERP, do_prog}, {(char *)"@quota", quota_sw, 0, 0, CS_TWO_ARG|CS_INTERP, do_quota}, {(char *)"@robot", NULL, CA_NO_SLAVE|CA_GBL_BUILD|CA_NO_GUEST|CA_PLAYER, PCRE_ROBOT, CS_TWO_ARG, do_pcreate}, {(char *)"@set", set_sw, CA_NO_SLAVE|CA_GBL_BUILD|CA_NO_GUEST, 0, CS_TWO_ARG, do_set}, {(char *)"@teleport", teleport_sw,CA_NO_GUEST, TELEPORT_DEFAULT, CS_TWO_ARG|CS_INTERP, do_teleport}, {(char *)"@toad", toad_sw, CA_WIZARD, 0, CS_TWO_ARG|CS_INTERP, do_toad}, {(char *)"addcom", NULL, CA_NO_SLAVE, 0, CS_TWO_ARG, do_addcom}, {(char *)"comtitle", NULL, CA_NO_SLAVE, 0, CS_TWO_ARG, do_comtitle}, {(char *)"give", give_sw, CA_LOCATION|CA_NO_GUEST, 0, CS_TWO_ARG|CS_INTERP, do_give}, {(char *)"kill", NULL, CA_NO_GUEST|CA_NO_SLAVE, KILL_KILL, CS_TWO_ARG|CS_INTERP, do_kill}, {(char *)"page", NULL, CA_NO_SLAVE, 0, CS_TWO_ARG|CS_INTERP, do_page}, {(char *)"slay", NULL, CA_WIZARD, KILL_SLAY, CS_TWO_ARG|CS_INTERP, do_kill}, {(char *)"whisper", NULL, CA_LOCATION|CA_NO_SLAVE, PEMIT_WHISPER, CS_TWO_ARG|CS_INTERP, do_pemit}, {(char *)"&", NULL, CA_NO_GUEST|CA_NO_SLAVE|CF_DARK, 0, CS_TWO_ARG|CS_LEADIN, do_setvattr}, {(char *)NULL, NULL, 0, 0, 0, NULL} }; CMDENT_TWO_ARG_ARGV command_table_two_arg_argv[] = { {(char *)"@cpattr", NULL, CA_NO_SLAVE|CA_NO_GUEST|CA_GBL_BUILD, 0, CS_TWO_ARG|CS_ARGV, do_cpattr}, {(char *)"@dig", dig_sw, CA_NO_SLAVE|CA_NO_GUEST|CA_GBL_BUILD, 0, CS_TWO_ARG|CS_ARGV|CS_INTERP, do_dig}, {(char *)"@edit", NULL, CA_NO_SLAVE|CA_NO_GUEST, 0, CS_TWO_ARG|CS_ARGV|CS_STRIP_AROUND, do_edit}, {(char *)"@mvattr", NULL, CA_NO_SLAVE|CA_NO_GUEST|CA_GBL_BUILD, 0, CS_TWO_ARG|CS_ARGV, do_mvattr}, {(char *)"@open", open_sw, CA_NO_SLAVE|CA_GBL_BUILD|CA_NO_GUEST, 0, CS_TWO_ARG|CS_ARGV|CS_INTERP, do_open}, {(char *)"@trigger", trig_sw, CA_GBL_INTERP, 0, CS_TWO_ARG|CS_ARGV, do_trigger}, {(char *)"@verb", NULL, CA_GBL_INTERP|CA_NO_SLAVE, 0, CS_TWO_ARG|CS_ARGV|CS_INTERP|CS_STRIP_AROUND, do_verb}, {(char *)NULL, NULL, 0, 0, 0, NULL} }; CMDENT_TWO_ARG_CMDARG command_table_two_arg_cmdarg[] = { {(char *)"@dolist", dolist_sw, CA_GBL_INTERP, 0, CS_TWO_ARG|CS_CMDARG|CS_NOINTERP|CS_STRIP_AROUND, do_dolist}, {(char *)"@force", NULL, CA_NO_SLAVE|CA_GBL_INTERP|CA_NO_GUEST, FRC_COMMAND, CS_TWO_ARG|CS_INTERP|CS_CMDARG, do_force}, {(char *)"@wait", NULL, CA_GBL_INTERP, 0, CS_TWO_ARG|CS_CMDARG|CS_NOINTERP|CS_STRIP_AROUND, do_wait}, {(char *)NULL, NULL, 0, 0, 0, NULL} }; CMDENT_TWO_ARG_ARGV_CMDARG command_table_two_arg_argv_cmdarg[] = { {(char *)"@switch", switch_sw, CA_GBL_INTERP, 0, CS_TWO_ARG|CS_ARGV|CS_CMDARG|CS_NOINTERP|CS_STRIP_AROUND, do_switch}, {(char *)NULL, NULL, 0, 0, 0, NULL} }; CMDENT *prefix_cmds[256]; CMDENT *goto_cmdp; void NDECL(init_cmdtab) { CMDENT_NO_ARG *cp0a; CMDENT_ONE_ARG *cp1a; CMDENT_ONE_ARG_CMDARG *cp1ac; CMDENT_TWO_ARG *cp2a; CMDENT_TWO_ARG_ARGV *cp2aa; CMDENT_TWO_ARG_CMDARG *cp2ac; CMDENT_TWO_ARG_ARGV_CMDARG *cp2aac; ATTR *ap; // Load attribute-setting commands. // for (ap = attr; ap->name; ap++) { if (ap->flags & AF_NOCMD) { continue; } int nBuffer; BOOL bValid; char *cbuff = MakeCanonicalAttributeCommand(ap->name, &nBuffer, &bValid); if (!bValid) { continue; } cp2a = (CMDENT_TWO_ARG *)MEMALLOC(sizeof(CMDENT_TWO_ARG)); ISOUTOFMEMORY(cp2a); cp2a->cmdname = (char *)StringClone(cbuff); cp2a->perms = CA_NO_GUEST | CA_NO_SLAVE; cp2a->switches = NULL; if (ap->flags & (AF_WIZARD | AF_MDARK)) { cp2a->perms |= CA_WIZARD; } cp2a->extra = ap->number; cp2a->callseq = CS_TWO_ARG; cp2a->handler = do_setattr; hashaddLEN(cp2a->cmdname, nBuffer, (int *)cp2a, &mudstate.command_htab); } /* * Load the builtin commands */ for (cp0a = command_table_no_arg; cp0a->cmdname; cp0a++) hashaddLEN(cp0a->cmdname, strlen(cp0a->cmdname), (int *)cp0a, &mudstate.command_htab); for (cp1a = command_table_one_arg; cp1a->cmdname; cp1a++) hashaddLEN(cp1a->cmdname, strlen(cp1a->cmdname), (int *)cp1a, &mudstate.command_htab); for (cp1ac = command_table_one_arg_cmdarg; cp1ac->cmdname; cp1ac++) hashaddLEN(cp1ac->cmdname, strlen(cp1ac->cmdname), (int *)cp1ac, &mudstate.command_htab); for (cp2a = command_table_two_arg; cp2a->cmdname; cp2a++) hashaddLEN(cp2a->cmdname, strlen(cp2a->cmdname), (int *)cp2a, &mudstate.command_htab); for (cp2aa = command_table_two_arg_argv; cp2aa->cmdname; cp2aa++) hashaddLEN(cp2aa->cmdname, strlen(cp2aa->cmdname), (int *)cp2aa, &mudstate.command_htab); for (cp2ac = command_table_two_arg_cmdarg; cp2ac->cmdname; cp2ac++) hashaddLEN(cp2ac->cmdname, strlen(cp2ac->cmdname), (int *)cp2ac, &mudstate.command_htab); for (cp2aac = command_table_two_arg_argv_cmdarg; cp2aac->cmdname; cp2aac++) hashaddLEN(cp2aac->cmdname, strlen(cp2aac->cmdname), (int *)cp2aac, &mudstate.command_htab); set_prefix_cmds(); goto_cmdp = (CMDENT *) hashfindLEN((char *)"goto", strlen("goto"), &mudstate.command_htab); } void set_prefix_cmds() { int i; // Load the command prefix table. Note - these commands can never // be typed in by a user because commands are lowercased before // the hash table is checked. The names are abbreviated to // minimise name checking time. // for (i = 0; i < 256; i++) { prefix_cmds[i] = NULL; } prefix_cmds['"'] = (CMDENT *) hashfindLEN((char *)"\"", 1, &mudstate.command_htab); prefix_cmds[':'] = (CMDENT *) hashfindLEN((char *)":", 1, &mudstate.command_htab); prefix_cmds[';'] = (CMDENT *) hashfindLEN((char *)";", 1, &mudstate.command_htab); prefix_cmds['\\'] = (CMDENT *) hashfindLEN((char *)"\\", 1, &mudstate.command_htab); prefix_cmds['#'] = (CMDENT *) hashfindLEN((char *)"#", 1, &mudstate.command_htab); prefix_cmds['&'] = (CMDENT *) hashfindLEN((char *)"&", 1, &mudstate.command_htab); prefix_cmds['-'] = (CMDENT *) hashfindLEN((char *)"-", 1, &mudstate.command_htab); prefix_cmds['~'] = (CMDENT *) hashfindLEN((char *)"~", 1, &mudstate.command_htab); } /* * --------------------------------------------------------------------------- * * check_access: Check if player has access to function. */ int check_access(dbref player, int mask) { int succ, fail; if (mask & CA_DISABLED) { return 0; } if (God(player) || mudstate.initializing) { return 1; } succ = fail = 0; if (mask & CA_GOD) fail++; if (mask & CA_WIZARD) { if (Wizard(player)) succ++; else fail++; } if ((succ == 0) && (mask & CA_ADMIN)) { if (WizRoy(player)) succ++; else fail++; } if ((succ == 0) && (mask & CA_BUILDER)) { if (Builder(player)) succ++; else fail++; } if ((succ == 0) && (mask & CA_STAFF)) { if (Staff(player)) succ++; else fail++; } if ((succ == 0) && (mask & CA_HEAD)) { if (Head(player)) succ++; else fail++; } if ((succ == 0) && (mask & CA_ANNOUNCE)) { if (Announce(player)) succ++; else fail++; } if ((succ == 0) && (mask & CA_IMMORTAL)) { if (Immortal(player)) succ++; else fail++; } if ((succ == 0) && (mask & CA_ROBOT)) { if (Robot(player)) succ++; else fail++; } if (succ > 0) fail = 0; if (fail > 0) return 0; // Check for forbidden flags. // if ( !Wizard(player) && ( ((mask & CA_NO_HAVEN) && Player_haven(player)) || ((mask & CA_NO_ROBOT) && Robot(player)) || ((mask & CA_NO_SLAVE) && Slave(player)) || ((mask & CA_NO_SUSPECT) && Suspect(player)) || ((mask & CA_NO_GUEST) && Guest(player)))) { return 0; } return 1; } /* * --------------------------------------------------------------------------- * * process_cmdent: Perform indicated command with passed args. */ void process_cmdent(CMDENT *cmdp, char *switchp, dbref player, dbref cause, int interactive, char *arg, char *unp_command, char *cargs[], int ncargs) { char *buf1, *buf2, tchar, *bp, *str, *buff, *s, *j, *new0; char *args[MAX_ARG]; int nargs, i, interp, key, xkey, aflags; int hasswitch = 0; dbref aowner; char *aargs[10]; ADDENT *add; // Perform object type checks. // if (Invalid_Objtype(player)) { notify(player, "Command incompatible with invoker type."); return; } // Check if we have permission to execute the command. // if (!check_access(player, cmdp->perms)) { notify(player, NOPERM_MESSAGE); return; } // Check global flags // if ( !Builder(player) && Protect(CA_GBL_BUILD) && !(mudconf.control_flags & CF_BUILD)) { notify(player, "Sorry, building is not allowed now."); return; } if (Protect(CA_GBL_INTERP) && !(mudconf.control_flags & CF_INTERP)) { notify(player, "Sorry, queueing and triggering are not allowed now."); return; } key = cmdp->extra & ~SW_MULTIPLE; if (key & SW_GOT_UNIQUE) { i = 1; key = key & ~SW_GOT_UNIQUE; } else { i = 0; } // Check command switches. Note that there may be more than one, // and that we OR all of them together along with the extra value // from the command table to produce the key value in the handler // call. // if (switchp && cmdp->switches) { do { buf1 = (char *)strchr(switchp, '/'); if (buf1) *buf1++ = '\0'; xkey = search_nametab(player, cmdp->switches, switchp); if (xkey == -1) { notify(player, tprintf("Unrecognized switch '%s' for command '%s'.", switchp, cmdp->cmdname)); return; } else if (xkey == -2) { notify(player, NOPERM_MESSAGE); return; } else if (!(xkey & SW_MULTIPLE)) { if (i == 1) { notify(player, "Illegal combination of switches."); return; } i = 1; } else { xkey &= ~SW_MULTIPLE; } key |= xkey; switchp = buf1; hasswitch = 1; } while (buf1); } else if (switchp && !(cmdp->callseq & CS_ADDED)) { notify(player, tprintf("Command %s does not take switches.", cmdp->cmdname)); return; } // We are allowed to run the command. Now, call the handler using // the appropriate calling sequence and arguments. // //if ((cmdp->callseq & CS_INTERP) && (key & SW_NOEVAL)) if (key & SW_NOEVAL) { // The user specified /noeval on a @pemit or a @npemit, // just do EV_STRIP_CURLY and remove the SW_NOEVAL from the // 'key'. // interp = EV_STRIP_CURLY; key &= ~SW_NOEVAL; } else if ( (cmdp->callseq & CS_INTERP) || !(interactive || (cmdp->callseq & CS_NOINTERP))) { // If the command is interpreted, or we're interactive (and // the command isn't specified CS_NOINTERP), eval the args. // interp = EV_EVAL | EV_STRIP_CURLY; } else if (cmdp->callseq & CS_STRIP) { interp = EV_STRIP_CURLY; } else if (cmdp->callseq & CS_STRIP_AROUND) { interp = EV_STRIP_AROUND; } else { interp = 0; } switch (cmdp->callseq & CS_NARG_MASK) { case CS_NO_ARGS: // <cmd> (no args) (*(((CMDENT_NO_ARG *)cmdp)->handler)) (player, cause, key); break; case CS_ONE_ARG: /* * <cmd> <arg> */ /* * If an unparsed command, just give it to the handler */ #if 0 // This never happens. if (cmdp->callseq & CS_UNPARSE) { (*(((CMDENT_ONE_ARG *)cmdp)->handler)) (player, unp_command); break; } #endif // Interpret if necessary, but not twice for CS_ADDED. // if ((interp & EV_EVAL) && !(cmdp->callseq & CS_ADDED)) { buf1 = bp = alloc_lbuf("process_cmdent"); str = arg; TinyExec(buf1, &bp, 0, player, cause, interp | EV_FCHECK | EV_TOP, &str, cargs, ncargs); *bp = '\0'; } else { buf1 = parse_to(&arg, '\0', interp | EV_TOP); } // Call the correct handler. // if (cmdp->callseq & CS_CMDARG) { (*(((CMDENT_ONE_ARG_CMDARG *)cmdp)->handler)) (player, cause, key, buf1, cargs, ncargs); } else { if (cmdp->callseq & CS_ADDED) { for (add = (ADDENT *)cmdp->handler; add != NULL; add = add->next) { buff = atr_get(add->thing, add->atr, &aowner, &aflags); // Skip the '$' character, and the next character. // for (s = buff + 2; *s && (*s != ':'); s++) { // nothing } if (!*s) { break; } *s++ = '\0'; if (!(cmdp->callseq & CS_LEADIN)) { for (j = unp_command; *j && (*j != ' '); j++) ; } else { for (j = unp_command; *j; j++) ; } new0 = alloc_lbuf("process_cmdent.soft"); bp = new0; if (!*j) { // No args. // if (!(cmdp->callseq & CS_LEADIN)) { safe_str(cmdp->cmdname, new0, &bp); } else { safe_str(unp_command, new0, &bp); } if (switchp) { safe_chr('/', new0, &bp); safe_str(switchp, new0, &bp); } *bp = '\0'; } else { j++; safe_str(cmdp->cmdname, new0, &bp); if (switchp) { safe_chr('/', new0, &bp); safe_str(switchp, new0, &bp); } safe_chr(' ', new0, &bp); safe_str(j, new0, &bp); *bp = '\0'; } if (wild(buff + 1, new0, aargs, 10)) { wait_que(add->thing, player, 0, NOTHING, 0, s, aargs, 10, mudstate.global_regs); for (i = 0; i < 10; i++) { if (aargs[i]) { free_lbuf(aargs[i]); } } } free_lbuf(new0); free_lbuf(buff); } } else { (*(((CMDENT_ONE_ARG *)cmdp)->handler)) (player, cause, key, buf1); } } // Free the buffer if one was allocated. // if ((interp & EV_EVAL) && !(cmdp->callseq & CS_ADDED)) { free_lbuf(buf1); } break; case CS_TWO_ARG: // <cmd> <arg1> = <arg2> // Interpret ARG1 // buf2 = parse_to(&arg, '=', EV_STRIP_TS); // Handle when no '=' was specified. // if (!arg || (arg && !*arg)) { arg = &tchar; *arg = '\0'; } buf1 = bp = alloc_lbuf("process_cmdent.2"); str = buf2; TinyExec(buf1, &bp, 0, player, cause, EV_STRIP_CURLY | EV_FCHECK | EV_EVAL | EV_TOP, &str, cargs, ncargs); *bp = '\0'; if (cmdp->callseq & CS_ARGV) { // Arg2 is ARGV style. Go get the args. // parse_arglist(player, cause, arg, '\0', interp | EV_STRIP_LS | EV_STRIP_TS, args, MAX_ARG, cargs, ncargs, &nargs); // Call the correct command handler. // if (cmdp->callseq & CS_CMDARG) { (*(((CMDENT_TWO_ARG_ARGV_CMDARG *)cmdp)->handler)) (player, cause, key, buf1, args, nargs, cargs, ncargs); } else { (*(((CMDENT_TWO_ARG_ARGV *)cmdp)->handler)) (player, cause, key, buf1, args, nargs); } // Free the argument buffers. // for (i = 0; i < nargs; i++) { free_lbuf(args[i]); } } else { // Arg2 is normal style. Interpret if needed. // if (interp & EV_EVAL) { buf2 = bp = alloc_lbuf("process_cmdent.3"); str = arg; TinyExec(buf2, &bp, 0, player, cause, interp | EV_FCHECK | EV_TOP, &str, cargs, ncargs); *bp = '\0'; } else if (cmdp->callseq & CS_UNPARSE) { buf2 = parse_to(&arg, '\0', interp | EV_TOP | EV_NO_COMPRESS); } else { buf2 = parse_to(&arg, '\0', interp | EV_STRIP_LS | EV_STRIP_TS | EV_TOP); } // Call the correct command handler. // if (cmdp->callseq & CS_CMDARG) { (*(((CMDENT_TWO_ARG_CMDARG *)cmdp)->handler)) (player, cause, key, buf1, buf2, cargs, ncargs); } else { (*(((CMDENT_TWO_ARG *)cmdp)->handler)) (player, cause, key, buf1, buf2); } // Free the buffer, if needed. // if (interp & EV_EVAL) { free_lbuf(buf2); } } // Free the buffer obtained by evaluating Arg1. // free_lbuf(buf1); break; } return; } /* * --------------------------------------------------------------------------- * * process_command: Execute a command. */ void process_command(dbref player, dbref cause, int interactive, char *arg_command, char *args[], int nargs) { char *pOriginalCommand = arg_command; static char SpaceCompressCommand[LBUF_SIZE]; static char LowerCaseCommand[LBUF_SIZE]; char *pCommand; char *p, *q, *arg, *pSlash, *cmdsave, *bp, *str; int succ, aflags, i; dbref exit, aowner; CMDENT *cmdp; // Robustify player. // cmdsave = mudstate.debug_cmd; mudstate.debug_cmd = (char *)"< process_command >"; Tiny_Assert(pOriginalCommand); if (!Good_obj(player)) { // We are using SpaceCompressCommand temporarily. // STARTLOG(LOG_BUGS, "CMD", "PLYR"); sprintf(SpaceCompressCommand, "Bad player in process_command: %d", player); log_text(SpaceCompressCommand); ENDLOG; mudstate.debug_cmd = cmdsave; return; } // Make sure player isn't going or halted. // if ( Going(player) || (Halted(player) && !((Typeof(player) == TYPE_PLAYER) && interactive))) { notify(Owner(player), tprintf("Attempt to execute command by halted object #%d", player)); mudstate.debug_cmd = cmdsave; return; } if (Suspect(player)) { STARTLOG(LOG_SUSPECTCMDS, "CMD", "SUSP"); log_name_and_loc(player); log_text(" entered: "); log_text(pOriginalCommand); ENDLOG; } else { STARTLOG(LOG_ALLCOMMANDS, "CMD", "ALL"); log_name_and_loc(player); log_text(" entered: "); log_text(pOriginalCommand); ENDLOG; } // Reset recursion limits. // mudstate.func_nest_lev = 0; mudstate.func_invk_ctr = 0; mudstate.ntfy_nest_lev = 0; mudstate.lock_nest_lev = 0; if (Verbose(player)) { notify(Owner(player), tprintf("%s] %s", Name(player), pOriginalCommand)); } // Eat leading whitespace, and space-compress if configured. // while (Tiny_IsSpace[(unsigned char)*pOriginalCommand]) { pOriginalCommand++; } mudstate.debug_cmd = pOriginalCommand; if (mudconf.space_compress) { // Compress out the spaces and use that as the command // pCommand = SpaceCompressCommand; p = pOriginalCommand; q = SpaceCompressCommand; while (*p) { while (*p && !Tiny_IsSpace[(unsigned char)*p]) { *q++ = *p++; } while (Tiny_IsSpace[(unsigned char)*p]) { p++; } if (*p) { *q++ = ' '; } } *q = '\0'; } else { // Don't compress the spaces. Use the original command // (without leading spaces) as the command to use. // pCommand = pOriginalCommand; } // Now comes the fun stuff. First check for single-letter leadins. // We check these before checking HOME because they are among the // most frequently executed commands, and they can never be the // HOME command. // i = pCommand[0] & 0xff; if (i && (prefix_cmds[i] != NULL)) { process_cmdent(prefix_cmds[i], NULL, player, cause, interactive, pCommand, pCommand, args, nargs); mudstate.debug_cmd = cmdsave; return; } if ( mudconf.have_comsys && !(Slave(player)) && !do_comsystem(player, pCommand)) { return; } // Check for the HOME command. // if (string_compare(pCommand, "home") == 0) { if (((Fixed(player)) || (Fixed(Owner(player)))) && !(WizRoy(player))) { notify(player, mudconf.fixed_home_msg); return; } do_move(player, cause, 0, "home"); mudstate.debug_cmd = cmdsave; return; } // Only check for exits if we may use the goto command. // if (check_access(player, goto_cmdp->perms)) { // Check for an exit name. // init_match_check_keys(player, pCommand, TYPE_EXIT); match_exit_with_parents(); exit = last_match_result(); if (exit != NOTHING) { move_exit(player, exit, 0, "You can't go that way.", 0); mudstate.debug_cmd = cmdsave; return; } // Check for an exit in the master room. // init_match_check_keys(player, pCommand, TYPE_EXIT); match_master_exit(); exit = last_match_result(); if (exit != NOTHING) { move_exit(player, exit, 1, NULL, 0); mudstate.debug_cmd = cmdsave; return; } } // Set up a lowercase command and an arg pointer for the hashed // command check. Since some types of argument processing destroy // the arguments, make a copy so that we keep the original command // line intact. Store the edible copy in LowerCaseCommand after // the lower-cased command. // // Make lowercase command // for (p = pCommand, q = LowerCaseCommand; *p && !Tiny_IsSpace[(unsigned char)*p]; p++, q++) { *q = Tiny_ToLower[(unsigned char)*p]; } *q = '\0'; int nLowerCaseCommand = q - LowerCaseCommand; // Skip spaces before arg // while (Tiny_IsSpace[(unsigned char)*p]) { p++; } // Remember where arg starts // arg = p; // Strip off any command switches and save them. // pSlash = (char *)strchr(LowerCaseCommand, '/'); if (pSlash) { nLowerCaseCommand = pSlash - LowerCaseCommand; *pSlash++ = '\0'; } // Check for a builtin command (or an alias of a builtin command) // cmdp = (CMDENT *)hashfindLEN(LowerCaseCommand, nLowerCaseCommand, &mudstate.command_htab); if (cmdp != NULL) { if (mudconf.space_compress && (cmdp->callseq & CS_NOSQUISH)) { // We handle this specially -- there is no space compression // involved, so we must go back to the original command. // We skip over the command and a single space to position // arg at the arguments. // arg = pCommand = pOriginalCommand; while (*arg && !Tiny_IsSpace[(unsigned char)*arg]) { arg++; } if (*arg) { // We stopped on the space, advance to next. // arg++; } } process_cmdent(cmdp, pSlash, player, cause, interactive, arg, pCommand, args, nargs); mudstate.debug_cmd = cmdsave; return; } // Check for enter and leave aliases, user-defined commands on the // player, other objects where the player is, on objects in the // player's inventory, and on the room that holds the player. We // evaluate the command line here to allow chains of $-commands // to work. // bp = LowerCaseCommand; str = pCommand; TinyExec(LowerCaseCommand, &bp, 0, player, cause, EV_EVAL | EV_FCHECK | EV_STRIP_CURLY | EV_TOP, &str, args, nargs); *bp = '\0'; succ = 0; // Idea for enter/leave aliases from R'nice@TinyTIM // if (Has_location(player) && Good_obj(Location(player))) { // Check for a leave alias. // p = atr_pget(Location(player), A_LALIAS, &aowner, &aflags); if (p && *p) { if (matches_exit_from_list(LowerCaseCommand, p)) { free_lbuf(p); do_leave(player, player, 0); return; } } free_lbuf(p); // Check for enter aliases. // DOLIST(exit, Contents(Location(player))) { p = atr_pget(exit, A_EALIAS, &aowner, &aflags); if (p && *p) { if (matches_exit_from_list(LowerCaseCommand, p)) { free_lbuf(p); do_enter_internal(player, exit, 0); return; } } free_lbuf(p); } } // Check for $-command matches on me. // if (mudconf.match_mine && (!(No_Command(player)))) { if (((Typeof(player) != TYPE_PLAYER) || mudconf.match_mine_pl) && (atr_match(player, player, AMATCH_CMD, LowerCaseCommand, 1) > 0)) { succ++; } } // Check for $-command matches on nearby things and on my room. // if (Has_location(player)) { succ += list_check(Contents(Location(player)), player, AMATCH_CMD, LowerCaseCommand, 1); if (!(No_Command(Location(player)))) { if (atr_match(Location(player), player, AMATCH_CMD, LowerCaseCommand, 1) > 0) { succ++; } } } // Check for $-command matches in my inventory. // if (Has_contents(player)) { succ += list_check(Contents(player), player, AMATCH_CMD, LowerCaseCommand, 1); } // now do check on zones. // if ((!succ) && mudconf.have_zones && (Zone(Location(player)) != NOTHING)) { if (Typeof(Zone(Location(player))) == TYPE_ROOM) { // zone of player's location is a parent room. // if (Location(player) != Zone(player)) { // check parent room exits. // init_match_check_keys(player, pCommand, TYPE_EXIT); match_zone_exit(); exit = last_match_result(); if (exit != NOTHING) { move_exit(player, exit, 1, NULL, 0); mudstate.debug_cmd = cmdsave; return; } succ += list_check(Contents(Zone(Location(player))), player, AMATCH_CMD, LowerCaseCommand, 1); // end of parent room checks. // } } else { // try matching commands on area zone object. // if ( (!succ) && mudconf.have_zones && (Zone(Location(player)) != NOTHING) && (!(No_Command(Zone(Location(player)))))) { succ += atr_match(Zone(Location(player)), player, AMATCH_CMD, LowerCaseCommand, 1); } } } // End of matching on zone of player's location. // // if nothing matched with parent room/zone object, try matching // zone commands on the player's personal zone. // if ( (!succ) && mudconf.have_zones && (Zone(player) != NOTHING) && (!(No_Command(Zone(player)))) && (Zone(Location(player)) != Zone(player))) { succ += atr_match(Zone(player), player, AMATCH_CMD, LowerCaseCommand, 1); } // If we didn't find anything, try in the master room. // if (!succ) { if ( Good_obj(mudconf.master_room) && Has_contents(mudconf.master_room)) { succ += list_check(Contents(mudconf.master_room), player, AMATCH_CMD, LowerCaseCommand, 0); if (!(No_Command(mudconf.master_room))) { if (atr_match(mudconf.master_room, player, AMATCH_CMD, LowerCaseCommand, 0) > 0) { succ++; } } } } // If we still didn't find anything, tell how to get help. // if (!succ) { // We use LowerCaseCommand for another purpose. // notify(player, "Huh? (Type \"help\" for help.)"); STARTLOG(LOG_BADCOMMANDS, "CMD", "BAD"); log_name_and_loc(player); log_text(" entered: "); log_text(pCommand); ENDLOG; } mudstate.debug_cmd = cmdsave; return; } /* * --------------------------------------------------------------------------- * * list_cmdtable: List internal commands. */ static void list_cmdtable(dbref player) { char *buf, *bp, *cp; buf = alloc_lbuf("list_cmdtable"); bp = buf; for (cp = (char *)"Commands:"; *cp; cp++) *bp++ = *cp; { CMDENT_NO_ARG *cmdp; for (cmdp = command_table_no_arg; cmdp->cmdname; cmdp++) { if (check_access(player, cmdp->perms)) { if (!(cmdp->perms & CF_DARK)) { *bp++ = ' '; for (cp = cmdp->cmdname; *cp; cp++) *bp++ = *cp; } } } } { CMDENT_ONE_ARG *cmdp; for (cmdp = command_table_one_arg; cmdp->cmdname; cmdp++) { if (check_access(player, cmdp->perms)) { if (!(cmdp->perms & CF_DARK)) { *bp++ = ' '; for (cp = cmdp->cmdname; *cp; cp++) *bp++ = *cp; } } } } { CMDENT_ONE_ARG_CMDARG *cmdp; for (cmdp = command_table_one_arg_cmdarg; cmdp->cmdname; cmdp++) { if (check_access(player, cmdp->perms)) { if (!(cmdp->perms & CF_DARK)) { *bp++ = ' '; for (cp = cmdp->cmdname; *cp; cp++) *bp++ = *cp; } } } } { CMDENT_TWO_ARG *cmdp; for (cmdp = command_table_two_arg; cmdp->cmdname; cmdp++) { if (check_access(player, cmdp->perms)) { if (!(cmdp->perms & CF_DARK)) { *bp++ = ' '; for (cp = cmdp->cmdname; *cp; cp++) *bp++ = *cp; } } } } { CMDENT_TWO_ARG_ARGV *cmdp; for (cmdp = command_table_two_arg_argv; cmdp->cmdname; cmdp++) { if (check_access(player, cmdp->perms)) { if (!(cmdp->perms & CF_DARK)) { *bp++ = ' '; for (cp = cmdp->cmdname; *cp; cp++) *bp++ = *cp; } } } } { CMDENT_TWO_ARG_CMDARG *cmdp; for (cmdp = command_table_two_arg_cmdarg; cmdp->cmdname; cmdp++) { if (check_access(player, cmdp->perms)) { if (!(cmdp->perms & CF_DARK)) { *bp++ = ' '; for (cp = cmdp->cmdname; *cp; cp++) *bp++ = *cp; } } } } { CMDENT_TWO_ARG_ARGV_CMDARG *cmdp; for (cmdp = command_table_two_arg_argv_cmdarg; cmdp->cmdname; cmdp++) { if (check_access(player, cmdp->perms)) { if (!(cmdp->perms & CF_DARK)) { *bp++ = ' '; for (cp = cmdp->cmdname; *cp; cp++) *bp++ = *cp; } } } } *bp = '\0'; /* * Players get the list of logged-out cmds too */ if (Typeof(player) == TYPE_PLAYER) display_nametab(player, logout_cmdtable, buf, 1); else notify(player, buf); free_lbuf(buf); } /* * --------------------------------------------------------------------------- * * list_attrtable: List available attributes. */ static void list_attrtable(dbref player) { ATTR *ap; char *buf, *bp, *cp; buf = alloc_lbuf("list_attrtable"); bp = buf; for (cp = (char *)"Attributes:"; *cp; cp++) *bp++ = *cp; for (ap = attr; ap->name; ap++) { if (See_attr(player, player, ap, player, 0)) { *bp++ = ' '; for (cp = (char *)(ap->name); *cp; cp++) *bp++ = *cp; } } *bp = '\0'; raw_notify(player, buf); free_lbuf(buf); } /* * --------------------------------------------------------------------------- * * list_cmdaccess: List access commands. */ NAMETAB access_nametab[] = { {(char *)"builder", 6, CA_WIZARD, CA_BUILDER}, {(char *)"dark", 4, CA_GOD, CF_DARK}, {(char *)"disabled", 4, CA_GOD, CA_DISABLED}, {(char *)"global_build", 8, CA_PUBLIC, CA_GBL_BUILD}, {(char *)"global_interp", 8, CA_PUBLIC, CA_GBL_INTERP}, {(char *)"god", 2, CA_GOD, CA_GOD}, {(char *)"head", 2, CA_WIZARD, CA_HEAD}, {(char *)"immortal", 3, CA_WIZARD, CA_IMMORTAL}, {(char *)"need_contents", 6, CA_PUBLIC, CA_CONTENTS}, {(char *)"need_location", 6, CA_PUBLIC, CA_LOCATION}, {(char *)"need_player", 6, CA_PUBLIC, CA_PLAYER}, {(char *)"no_haven", 4, CA_PUBLIC, CA_NO_HAVEN}, {(char *)"no_robot", 4, CA_WIZARD, CA_NO_ROBOT}, {(char *)"no_slave", 5, CA_PUBLIC, CA_NO_SLAVE}, {(char *)"no_suspect", 5, CA_WIZARD, CA_NO_SUSPECT}, {(char *)"no_guest", 5, CA_WIZARD, CA_NO_GUEST}, {(char *)"robot", 2, CA_WIZARD, CA_ROBOT}, {(char *)"wizard", 3, CA_WIZARD, CA_WIZARD}, {NULL, 0, 0, 0} }; static void list_cmdaccess(dbref player) { ATTR *ap; char *buff = alloc_sbuf("list_cmdaccess"); { CMDENT_NO_ARG *cmdp; for (cmdp = command_table_no_arg; cmdp->cmdname; cmdp++) { if (check_access(player, cmdp->perms)) { if (!(cmdp->perms & CF_DARK)) { sprintf(buff, "%.60s:", cmdp->cmdname); listset_nametab(player, access_nametab, cmdp->perms, buff, 1); } } } } { CMDENT_ONE_ARG *cmdp; for (cmdp = command_table_one_arg; cmdp->cmdname; cmdp++) { if (check_access(player, cmdp->perms)) { if (!(cmdp->perms & CF_DARK)) { sprintf(buff, "%.60s:", cmdp->cmdname); listset_nametab(player, access_nametab, cmdp->perms, buff, 1); } } } } { CMDENT_ONE_ARG_CMDARG *cmdp; for (cmdp = command_table_one_arg_cmdarg; cmdp->cmdname; cmdp++) { if (check_access(player, cmdp->perms)) { if (!(cmdp->perms & CF_DARK)) { sprintf(buff, "%.60s:", cmdp->cmdname); listset_nametab(player, access_nametab, cmdp->perms, buff, 1); } } } } { CMDENT_TWO_ARG *cmdp; for (cmdp = command_table_two_arg; cmdp->cmdname; cmdp++) { if (check_access(player, cmdp->perms)) { if (!(cmdp->perms & CF_DARK)) { sprintf(buff, "%.60s:", cmdp->cmdname); listset_nametab(player, access_nametab, cmdp->perms, buff, 1); } } } } { CMDENT_TWO_ARG_ARGV *cmdp; for (cmdp = command_table_two_arg_argv; cmdp->cmdname; cmdp++) { if (check_access(player, cmdp->perms)) { if (!(cmdp->perms & CF_DARK)) { sprintf(buff, "%.60s:", cmdp->cmdname); listset_nametab(player, access_nametab, cmdp->perms, buff, 1); } } } } { CMDENT_TWO_ARG_CMDARG *cmdp; for (cmdp = command_table_two_arg_cmdarg; cmdp->cmdname; cmdp++) { if (check_access(player, cmdp->perms)) { if (!(cmdp->perms & CF_DARK)) { sprintf(buff, "%.60s:", cmdp->cmdname); listset_nametab(player, access_nametab, cmdp->perms, buff, 1); } } } } { CMDENT_TWO_ARG_ARGV_CMDARG *cmdp; for (cmdp = command_table_two_arg_argv_cmdarg; cmdp->cmdname; cmdp++) { if (check_access(player, cmdp->perms)) { if (!(cmdp->perms & CF_DARK)) { sprintf(buff, "%.60s:", cmdp->cmdname); listset_nametab(player, access_nametab, cmdp->perms, buff, 1); } } } } free_sbuf(buff); for (ap = attr; ap->name; ap++) { if (ap->flags & AF_NOCMD) { continue; } int nBuffer; BOOL bValid; buff = MakeCanonicalAttributeCommand(ap->name, &nBuffer, &bValid); if (!bValid) { continue; } CMDENT *cmdp = (CMDENT *)hashfindLEN(buff, nBuffer, &mudstate.command_htab); if (cmdp == NULL) { continue; } if (!check_access(player, cmdp->perms)) { continue; } if (!(cmdp->perms & CF_DARK)) { sprintf(buff, "%.60s:", cmdp->cmdname); listset_nametab(player, access_nametab, cmdp->perms, buff, 1); } } } /* * --------------------------------------------------------------------------- * * list_cmdswitches: List switches for commands. */ static void list_cmdswitches(dbref player) { char *buff; buff = alloc_sbuf("list_cmdswitches"); { CMDENT_NO_ARG *cmdp; for (cmdp = command_table_no_arg; cmdp->cmdname; cmdp++) { if (cmdp->switches) { if (check_access(player, cmdp->perms)) { if (!(cmdp->perms & CF_DARK)) { sprintf(buff, "%.60s:", cmdp->cmdname); display_nametab(player, cmdp->switches, buff, 0); } } } } } { CMDENT_ONE_ARG *cmdp; for (cmdp = command_table_one_arg; cmdp->cmdname; cmdp++) { if (cmdp->switches) { if (check_access(player, cmdp->perms)) { if (!(cmdp->perms & CF_DARK)) { sprintf(buff, "%.60s:", cmdp->cmdname); display_nametab(player, cmdp->switches, buff, 0); } } } } } { CMDENT_ONE_ARG_CMDARG *cmdp; for (cmdp = command_table_one_arg_cmdarg; cmdp->cmdname; cmdp++) { if (cmdp->switches) { if (check_access(player, cmdp->perms)) { if (!(cmdp->perms & CF_DARK)) { sprintf(buff, "%.60s:", cmdp->cmdname); display_nametab(player, cmdp->switches, buff, 0); } } } } } { CMDENT_TWO_ARG *cmdp; for (cmdp = command_table_two_arg; cmdp->cmdname; cmdp++) { if (cmdp->switches) { if (check_access(player, cmdp->perms)) { if (!(cmdp->perms & CF_DARK)) { sprintf(buff, "%.60s:", cmdp->cmdname); display_nametab(player, cmdp->switches, buff, 0); } } } } } { CMDENT_TWO_ARG_ARGV *cmdp; for (cmdp = command_table_two_arg_argv; cmdp->cmdname; cmdp++) { if (cmdp->switches) { if (check_access(player, cmdp->perms)) { if (!(cmdp->perms & CF_DARK)) { sprintf(buff, "%.60s:", cmdp->cmdname); display_nametab(player, cmdp->switches, buff, 0); } } } } } { CMDENT_TWO_ARG_CMDARG *cmdp; for (cmdp = command_table_two_arg_cmdarg; cmdp->cmdname; cmdp++) { if (cmdp->switches) { if (check_access(player, cmdp->perms)) { if (!(cmdp->perms & CF_DARK)) { sprintf(buff, "%.60s:", cmdp->cmdname); display_nametab(player, cmdp->switches, buff, 0); } } } } } { CMDENT_TWO_ARG_ARGV_CMDARG *cmdp; for (cmdp = command_table_two_arg_argv_cmdarg; cmdp->cmdname; cmdp++) { if (cmdp->switches) { if (check_access(player, cmdp->perms)) { if (!(cmdp->perms & CF_DARK)) { sprintf(buff, "%.60s:", cmdp->cmdname); display_nametab(player, cmdp->switches, buff, 0); } } } } } free_sbuf(buff); } /* --------------------------------------------------------------------------- * list_attraccess: List access to attributes. */ NAMETAB attraccess_nametab[] = { {(char *)"dark", 2, CA_WIZARD, AF_DARK}, {(char *)"deleted", 2, CA_WIZARD, AF_DELETED}, {(char *)"god", 1, CA_PUBLIC, AF_GOD}, {(char *)"hidden", 1, CA_WIZARD, AF_MDARK}, {(char *)"ignore", 2, CA_WIZARD, AF_NOCMD}, {(char *)"internal", 2, CA_WIZARD, AF_INTERNAL}, {(char *)"is_lock", 4, CA_PUBLIC, AF_IS_LOCK}, {(char *)"locked", 1, CA_PUBLIC, AF_LOCK}, {(char *)"no_command", 4, CA_PUBLIC, AF_NOPROG}, {(char *)"no_inherit", 4, CA_PUBLIC, AF_PRIVATE}, {(char *)"private", 1, CA_PUBLIC, AF_ODARK}, {(char *)"regexp", 1, CA_PUBLIC, AF_REGEXP}, {(char *)"visual", 1, CA_PUBLIC, AF_VISUAL}, {(char *)"wizard", 1, CA_PUBLIC, AF_WIZARD}, { NULL, 0, 0, 0} }; NAMETAB indiv_attraccess_nametab[] = { {(char *)"hidden", 1, CA_WIZARD, AF_MDARK}, {(char *)"wizard", 1, CA_WIZARD, AF_WIZARD}, {(char *)"no_command", 4, CA_PUBLIC, AF_NOPROG}, {(char *)"no_inherit", 4, CA_PUBLIC, AF_PRIVATE}, {(char *)"visual", 1, CA_PUBLIC, AF_VISUAL}, {(char *)"regexp", 1, CA_PUBLIC, AF_REGEXP}, { NULL, 0, 0, 0} }; static void list_attraccess(dbref player) { char *buff; ATTR *ap; buff = alloc_sbuf("list_attraccess"); for (ap = attr; ap->name; ap++) { if (Read_attr(player, player, ap, player, 0)) { sprintf(buff, "%s:", ap->name); listset_nametab(player, attraccess_nametab, ap->flags, buff, 1); } } free_sbuf(buff); } /* * --------------------------------------------------------------------------- * * cf_access: Change command or switch permissions. */ extern void FDECL(cf_log_notfound, (dbref, char *, const char *, char *)); CF_HAND(cf_access) { CMDENT *cmdp; char *ap; int set_switch; for (ap = str; *ap && !Tiny_IsSpace[(unsigned char)*ap] && (*ap != '/'); ap++) ; if (*ap == '/') { set_switch = 1; *ap++ = '\0'; } else { set_switch = 0; if (*ap) *ap++ = '\0'; while (Tiny_IsSpace[(unsigned char)*ap]) ap++; } cmdp = (CMDENT *)hashfindLEN(str, strlen(str), &mudstate.command_htab); if (cmdp != NULL) { if (set_switch) return cf_ntab_access((int *)cmdp->switches, ap, extra, player, cmd); else return cf_modify_bits(&(cmdp->perms), ap, extra, player, cmd); } else { cf_log_notfound(player, cmd, "Command", str); return -1; } } /* * --------------------------------------------------------------------------- * * cf_acmd_access: Change command permissions for all attr-setting cmds. */ CF_HAND(cf_acmd_access) { ATTR *ap; for (ap = attr; ap->name; ap++) { int nBuffer; int bValid; char *buff = MakeCanonicalAttributeCommand(ap->name, &nBuffer, &bValid); if (!bValid) { continue; } CMDENT *cmdp = (CMDENT *)hashfindLEN(buff, nBuffer, &mudstate.command_htab); if (cmdp != NULL) { int save = cmdp->perms; int failure = cf_modify_bits(&(cmdp->perms), str, extra, player, cmd); if (failure != 0) { cmdp->perms = save; free_sbuf(buff); return -1; } } } return 0; } /* * --------------------------------------------------------------------------- * * cf_attr_access: Change access on an attribute. */ CF_HAND(cf_attr_access) { ATTR *ap; char *sp; for (sp = str; *sp && !Tiny_IsSpace[(unsigned char)*sp]; sp++) ; if (*sp) *sp++ = '\0'; while (Tiny_IsSpace[(unsigned char)*sp]) sp++; ap = atr_str(str); if (ap != NULL) return cf_modify_bits(&(ap->flags), sp, extra, player, cmd); else { cf_log_notfound(player, cmd, "Attribute", str); return -1; } } /* * --------------------------------------------------------------------------- * * cf_cmd_alias: Add a command alias. */ CF_HAND(cf_cmd_alias) { char *ap; CMDENT *cmdp, *cmd2; NAMETAB *nt; int *hp; TINY_STRTOK_STATE tts; Tiny_StrTokString(&tts, str); Tiny_StrTokControl(&tts, " \t=,"); char *alias = Tiny_StrTokParse(&tts); char *orig = Tiny_StrTokParse(&tts); if (!orig) { // We only got one argument to @alias. Bad. // return -1; } for (ap = orig; *ap && (*ap != '/'); ap++) ; if (*ap == '/') { /* * Switch form of command aliasing: create an alias for a * * * * * * * command + a switch */ *ap++ = '\0'; /* * Look up the command */ cmdp = (CMDENT *) hashfindLEN(orig, strlen(orig), (CHashTable *) vp); if (cmdp == NULL || cmdp->switches == NULL) { cf_log_notfound(player, cmd, "Command", orig); return -1; } /* * Look up the switch */ nt = find_nametab_ent(player, (NAMETAB *) cmdp->switches, ap); if (!nt) { cf_log_notfound(player, cmd, "Switch", ap); return -1; } // Got it, create the new command table entry. // cmd2 = (CMDENT *)MEMALLOC(sizeof(CMDENT)); ISOUTOFMEMORY(cmd2); cmd2->cmdname = StringClone(alias); cmd2->switches = cmdp->switches; cmd2->perms = cmdp->perms | nt->perm; cmd2->extra = (cmdp->extra | nt->flag) & ~SW_MULTIPLE; if (!(nt->flag & SW_MULTIPLE)) { cmd2->extra |= SW_GOT_UNIQUE; } cmd2->callseq = cmdp->callseq; cmd2->handler = cmdp->handler; if (hashaddLEN(cmd2->cmdname, strlen(cmd2->cmdname), (int *)cmd2, (CHashTable *) vp)) { MEMFREE(cmd2->cmdname); MEMFREE(cmd2); } } else { /* * A normal (non-switch) alias */ hp = hashfindLEN(orig, strlen(orig), (CHashTable *) vp); if (hp == NULL) { cf_log_notfound(player, cmd, "Entry", orig); return -1; } hashaddLEN(alias, strlen(alias), hp, (CHashTable *) vp); } return 0; } /* * --------------------------------------------------------------------------- * * list_df_flags: List default flags at create time. */ static void list_df_flags(dbref player) { char *playerb, *roomb, *thingb, *exitb, *robotb, *buff; playerb = decode_flags(player, (mudconf.player_flags.word1 | TYPE_PLAYER), mudconf.player_flags.word2, mudconf.player_flags.word3); roomb = decode_flags(player, (mudconf.room_flags.word1 | TYPE_ROOM), mudconf.room_flags.word2, mudconf.room_flags.word3); exitb = decode_flags(player, (mudconf.exit_flags.word1 | TYPE_EXIT), mudconf.exit_flags.word2, mudconf.exit_flags.word3); thingb = decode_flags(player, (mudconf.thing_flags.word1 | TYPE_THING), mudconf.thing_flags.word2, mudconf.thing_flags.word3); robotb = decode_flags(player, (mudconf.robot_flags.word1 | TYPE_PLAYER), mudconf.robot_flags.word2, mudconf.robot_flags.word3); buff = alloc_lbuf("list_df_flags"); sprintf(buff, "Default flags: Players...%s Rooms...%s Exits...%s Things...%s Robots...%s", playerb, roomb, exitb, thingb, robotb); raw_notify(player, buff); free_lbuf(buff); free_sbuf(playerb); free_sbuf(roomb); free_sbuf(exitb); free_sbuf(thingb); free_sbuf(robotb); } /* * --------------------------------------------------------------------------- * * list_costs: List the costs of things. */ #define coin_name(s) (((s)==1) ? mudconf.one_coin : mudconf.many_coins) static void list_costs(dbref player) { char *buff; buff = alloc_mbuf("list_costs"); *buff = '\0'; if (mudconf.quotas) sprintf(buff, " and %d quota", mudconf.room_quota); notify(player, tprintf("Digging a room costs %d %s%s.", mudconf.digcost, coin_name(mudconf.digcost), buff)); if (mudconf.quotas) sprintf(buff, " and %d quota", mudconf.exit_quota); notify(player, tprintf("Opening a new exit costs %d %s%s.", mudconf.opencost, coin_name(mudconf.opencost), buff)); notify(player, tprintf("Linking an exit, home, or dropto costs %d %s.", mudconf.linkcost, coin_name(mudconf.linkcost))); if (mudconf.quotas) sprintf(buff, " and %d quota", mudconf.thing_quota); if (mudconf.createmin == mudconf.createmax) raw_notify(player, tprintf("Creating a new thing costs %d %s%s.", mudconf.createmin, coin_name(mudconf.createmin), buff)); else raw_notify(player, tprintf("Creating a new thing costs between %d and %d %s%s.", mudconf.createmin, mudconf.createmax, mudconf.many_coins, buff)); if (mudconf.quotas) sprintf(buff, " and %d quota", mudconf.player_quota); notify(player, tprintf("Creating a robot costs %d %s%s.", mudconf.robotcost, coin_name(mudconf.robotcost), buff)); if (mudconf.killmin == mudconf.killmax) { raw_notify(player, tprintf("Killing costs %d %s, with a %d%% chance of success.", mudconf.killmin, coin_name(mudconf.digcost), (mudconf.killmin * 100) / mudconf.killguarantee)); } else { raw_notify(player, tprintf("Killing costs between %d and %d %s.", mudconf.killmin, mudconf.killmax, mudconf.many_coins)); raw_notify(player, tprintf("You must spend %d %s to guarantee success.", mudconf.killguarantee, coin_name(mudconf.killguarantee))); } raw_notify(player, tprintf("Computationally expensive commands and functions (ie: @entrances, @find, @search, @stats (with an argument or switch), search(), and stats()) cost %d %s.", mudconf.searchcost, coin_name(mudconf.searchcost))); if (mudconf.machinecost > 0) raw_notify(player, tprintf("Each command run from the queue costs 1/%d %s.", mudconf.machinecost, mudconf.one_coin)); if (mudconf.waitcost > 0) { raw_notify(player, tprintf("A %d %s deposit is charged for putting a command on the queue.", mudconf.waitcost, mudconf.one_coin)); raw_notify(player, "The deposit is refunded when the command is run or canceled."); } if (mudconf.sacfactor == 0) { Tiny_ltoa(mudconf.sacadjust, buff); } else if (mudconf.sacfactor == 1) { if (mudconf.sacadjust < 0) sprintf(buff, "<create cost> - %d", -mudconf.sacadjust); else if (mudconf.sacadjust > 0) sprintf(buff, "<create cost> + %d", mudconf.sacadjust); else sprintf(buff, "<create cost>"); } else { if (mudconf.sacadjust < 0) sprintf(buff, "(<create cost> / %d) - %d", mudconf.sacfactor, -mudconf.sacadjust); else if (mudconf.sacadjust > 0) sprintf(buff, "(<create cost> / %d) + %d", mudconf.sacfactor, mudconf.sacadjust); else sprintf(buff, "<create cost> / %d", mudconf.sacfactor); } raw_notify(player, tprintf("The value of an object is %s.", buff)); if (mudconf.clone_copy_cost) raw_notify(player, "The default value of cloned objects is the value of the original object."); else raw_notify(player, tprintf("The default value of cloned objects is %d %s.", mudconf.createmin, coin_name(mudconf.createmin))); free_mbuf(buff); } /* * --------------------------------------------------------------------------- * * list_options: List more game options from mudconf. */ static const char *switchd[] = {"/first", "/all"}; static const char *examd[] = {"/brief", "/full"}; static const char *ed[] = {"Disabled", "Enabled"}; static void list_options(dbref player) { char *buff; CLinearTimeAbsolute ltaNow; ltaNow.GetUTC(); if (mudconf.quotas) raw_notify(player, "Building quotas are enforced."); if (mudconf.name_spaces) raw_notify(player, "Player names may contain spaces."); else raw_notify(player, "Player names may not contain spaces."); if (!mudconf.robot_speak) raw_notify(player, "Robots are not allowed to speak in public areas."); if (mudconf.player_listen) raw_notify(player, "The @Listen/@Ahear attribute set works on player objects."); if (mudconf.ex_flags) raw_notify(player, "The 'examine' command lists the flag names for the object's flags."); if (!mudconf.quiet_look) raw_notify(player, "The 'look' command shows visible attributes in addition to the description."); if (mudconf.see_own_dark) raw_notify(player, "The 'look' command lists DARK objects owned by you."); if (!mudconf.dark_sleepers) raw_notify(player, "The 'look' command shows disconnected players."); if (mudconf.terse_look) raw_notify(player, "The 'look' command obeys the TERSE flag."); if (mudconf.trace_topdown) { raw_notify(player, "Trace output is presented top-down (whole expression first, then sub-exprs)."); raw_notify(player, tprintf("Only %d lines of trace output are displayed.", mudconf.trace_limit)); } else { raw_notify(player, "Trace output is presented bottom-up (subexpressions first)."); } if (!mudconf.quiet_whisper) raw_notify(player, "The 'whisper' command lets others in the room with you know you whispered."); if (mudconf.pemit_players) raw_notify(player, "The '@pemit' command may be used to emit to faraway players."); if (!mudconf.terse_contents) raw_notify(player, "The TERSE flag suppresses listing the contents of a location."); if (!mudconf.terse_exits) raw_notify(player, "The TERSE flag suppresses listing obvious exits in a location."); if (!mudconf.terse_movemsg) raw_notify(player, "The TERSE flag suppresses enter/leave/succ/drop messages generated by moving."); if (mudconf.pub_flags) raw_notify(player, "The 'flags()' function will return the flags of any object."); if (mudconf.read_rem_desc) raw_notify(player, "The 'get()' function will return the description of faraway objects,"); if (mudconf.read_rem_name) raw_notify(player, "The 'name()' function will return the name of faraway objects."); raw_notify(player, tprintf("The default switch for the '@switch' command is %s.", switchd[mudconf.switch_df_all])); raw_notify(player, tprintf("The default switch for the 'examine' command is %s.", examd[mudconf.exam_public])); if (mudconf.sweep_dark) raw_notify(player, "Players may @sweep dark locations."); if (mudconf.fascist_tport) raw_notify(player, "You may only @teleport out of locations that are JUMP_OK or that you control."); raw_notify(player, tprintf("Players may have at most %d commands in the queue at one time.", mudconf.queuemax)); if (mudconf.match_mine) { if (mudconf.match_mine_pl) raw_notify(player, "All objects search themselves for $-commands."); else raw_notify(player, "Objects other than players search themselves for $-commands."); } if (!Wizard(player)) return; buff = alloc_mbuf("list_options"); raw_notify(player, tprintf("%d commands are run from the queue when there is no net activity.", mudconf.queue_chunk)); raw_notify(player, tprintf("%d commands are run from the queue when there is net activity.", mudconf.active_q_chunk)); if (mudconf.idle_wiz_dark) raw_notify(player, "Wizards idle for longer than the default timeout are automatically set DARK."); if (mudconf.safe_unowned) raw_notify(player, "Objects not owned by you are automatically considered SAFE."); if (mudconf.paranoid_alloc) raw_notify(player, "The buffer pools are checked for consistency on each allocate or free."); if (mudconf.cache_names) raw_notify(player, "A seperate name cache is used."); #if !defined(VMS) && !defined(WIN32) if (mudconf.fork_dump) { raw_notify(player, "Database dumps are performed by a fork()ed process."); if (mudconf.fork_vfork) raw_notify(player, "The 'vfork()' call is used to perform the fork."); } #endif // WIN32 if (mudconf.max_players >= 0) raw_notify(player, tprintf("There may be at most %d players logged in at once.", mudconf.max_players)); if (mudconf.quotas) sprintf(buff, " and %d quota", mudconf.start_quota); else *buff = '\0'; raw_notify(player, tprintf("New players are given %d %s to start with.", mudconf.paystart, mudconf.many_coins)); raw_notify(player, tprintf("Players are given %d %s each day they connect.", mudconf.paycheck, mudconf.many_coins)); raw_notify(player, tprintf("Earning money is difficult if you have more than %d %s.", mudconf.paylimit, mudconf.many_coins)); if (mudconf.payfind > 0) raw_notify(player, tprintf("Players have a 1 in %d chance of finding a %s each time they move.", mudconf.payfind, mudconf.one_coin)); raw_notify(player, tprintf("The head of the object freelist is #%d.", mudstate.freelist)); sprintf(buff, "Intervals: Dump...%d Clean...%d Idlecheck...%d", mudconf.dump_interval, mudconf.check_interval, mudconf.idle_interval); raw_notify(player, buff); CLinearTimeDelta ltdDump = mudstate.dump_counter - ltaNow; CLinearTimeDelta ltdCheck = mudstate.check_counter - ltaNow; CLinearTimeDelta ltdIdle = mudstate.idle_counter - ltaNow; sprintf(buff, "Timers: Dump...%ld Clean...%ld Idlecheck...%ld", ltdDump.ReturnSeconds(), ltdCheck.ReturnSeconds(), ltdIdle.ReturnSeconds()); raw_notify(player, buff); sprintf(buff, "Timeouts: Idle...%d Connect...%d Tries...%d", mudconf.idle_timeout, mudconf.conn_timeout, mudconf.retry_limit); raw_notify(player, buff); sprintf(buff, "Scheduling: Timeslice...%d Max_Quota...%d Increment...%d", mudconf.timeslice, mudconf.cmd_quota_max, mudconf.cmd_quota_incr); raw_notify(player, buff); sprintf(buff, "Spaces...%s Savefiles...%s", ed[mudconf.space_compress], ed[mudconf.compress_db]); raw_notify(player, buff); sprintf(buff, "New characters: Room...#%d Home...#%d DefaultHome...#%d Quota...%d", mudconf.start_room, mudconf.start_home, mudconf.default_home, mudconf.start_quota); raw_notify(player, buff); sprintf(buff, "Misc: GuestChar...#%d IdleQueueChunk...%d ActiveQueueChunk...%d Master_room...#%d", mudconf.guest_char, mudconf.queue_chunk, mudconf.active_q_chunk, mudconf.master_room); raw_notify(player, buff); free_mbuf(buff); } /* * --------------------------------------------------------------------------- * * list_vattrs: List user-defined attributes */ static void list_vattrs(dbref player) { VATTR *va; int na; char *buff; buff = alloc_lbuf("list_vattrs"); raw_notify(player, "--- User-Defined Attributes ---"); for (va = vattr_first(), na = 0; va; va = vattr_next(va), na++) { if (!(va->flags & AF_DELETED)) { sprintf(buff, "%s(%d):", va->name, va->number); listset_nametab(player, attraccess_nametab, va->flags, buff, 1); } } raw_notify(player, tprintf("%d attributes, next=%d", na, mudstate.attr_next)); free_lbuf(buff); } /* * --------------------------------------------------------------------------- * * list_hashstats: List information from hash tables */ static void list_hashstat(dbref player, const char *tab_name, CHashTable *htab) { char *buff = hashinfo(tab_name, htab); raw_notify(player, buff); free_mbuf(buff); } static void list_hashstats(dbref player) { raw_notify(player, "Hash Stats Size Entries Deleted Lookups Hits Checks Longest"); list_hashstat(player, "Commands", &mudstate.command_htab); list_hashstat(player, "Logged-out Cmds", &mudstate.logout_cmd_htab); list_hashstat(player, "Functions", &mudstate.func_htab); list_hashstat(player, "Flags", &mudstate.flags_htab); list_hashstat(player, "Powers", &mudstate.powers_htab); list_hashstat(player, "Attr names", &mudstate.attr_name_htab); list_hashstat(player, "Vattr names", &mudstate.vattr_name_htab); list_hashstat(player, "Player Names", &mudstate.player_htab); list_hashstat(player, "Net Descriptors", &mudstate.desc_htab); list_hashstat(player, "Forwardlists", &mudstate.fwdlist_htab); list_hashstat(player, "Overlaid $-cmds", &mudstate.parent_htab); list_hashstat(player, "Mail messages", &mudstate.mail_htab); list_hashstat(player, "Channel names", &mudstate.channel_htab); list_hashstat(player, "News topics", &mudstate.news_htab); list_hashstat(player, "Help topics", &mudstate.help_htab); list_hashstat(player, "Wizhelp topics", &mudstate.wizhelp_htab); list_hashstat(player, "+Help topics", &mudstate.plushelp_htab); list_hashstat(player, "+Shelp topics", &mudstate.staffhelp_htab); list_hashstat(player, "Wiznews topics", &mudstate.wiznews_htab); list_hashstat(player, "Attribute Cache", &mudstate.acache_htab); } #ifndef MEMORY_BASED // // These are from 'svdhash.cpp'. // extern CLinearTimeAbsolute cs_ltime; extern int cs_writes; // total writes extern int cs_reads; // total reads extern int cs_dels; // total deletes extern int cs_fails; // attempts to grab nonexistent extern int cs_syncs; // total cache syncs extern int cs_dbreads; // total read-throughs extern int cs_dbwrites; // total write-throughs extern int cs_rhits; // total reads filled from cache extern int cs_whits; // total writes to dirty cache #endif // !MEMORY_BASED #ifdef RADIX_COMPRESSION extern unsigned int strings_compressed; // Total number of compressed strings extern unsigned int strings_decompressed; // Total number of decompressed strings extern unsigned int chars_in; // Total characters compressed extern unsigned int symbols_out; // Total symbols emitted #endif // RADIX_COMPRESSION /* * --------------------------------------------------------------------------- * * list_db_stats: Get useful info from the DB layer about hash stats, etc. */ static void list_db_stats(dbref player) { #ifdef MEMORY_BASED raw_notify(player, "Database is memory based."); #else CLinearTimeAbsolute lsaNow; lsaNow.GetUTC(); CLinearTimeDelta ltd = lsaNow - cs_ltime; raw_notify(player, tprintf("DB Cache Stats Writes Reads (over %d seconds)", ltd.ReturnSeconds())); raw_notify(player, tprintf("Calls %12d%12d", cs_writes, cs_reads)); raw_notify(player, tprintf("\nDeletes %12d", cs_dels)); raw_notify(player, tprintf("Syncs %12d", cs_syncs)); raw_notify(player, tprintf("I/O %12d%12d", cs_dbwrites, cs_dbreads)); raw_notify(player, tprintf("Cache Hits %12d%12d", cs_whits, cs_rhits)); #endif // !MEMORY_BASED #ifdef RADIX_COMPRESSION raw_notify(player, "Compression statistics:"); raw_notify(player, tprintf("Strings compressed %d", strings_compressed)); raw_notify(player, tprintf("Strings decompressed %d", strings_decompressed)); raw_notify(player, tprintf("Compression ratio %d:%d", chars_in, symbols_out + (symbols_out >> 1))); #endif // RADIX_COMPRESSION } /* * --------------------------------------------------------------------------- * * list_process: List local resource usage stats of the mux process. * * Adapted from code by Claudius@PythonMUCK, * * posted to the net by Howard/Dark_Lord. */ static void list_process(dbref player) { int maxfds; #ifdef HAVE_GETRUSAGE struct rusage usage; int ixrss, idrss, isrss, curr, last, dur; getrusage(RUSAGE_SELF, &usage); // Calculate memory use from the aggregate totals. // curr = mudstate.mstat_curr; last = 1 - curr; dur = mudstate.mstat_secs[curr] - mudstate.mstat_secs[last]; if (dur > 0) { ixrss = (mudstate.mstat_ixrss[curr] - mudstate.mstat_ixrss[last]) / dur; idrss = (mudstate.mstat_idrss[curr] - mudstate.mstat_idrss[last]) / dur; isrss = (mudstate.mstat_isrss[curr] - mudstate.mstat_isrss[last]) / dur; } else { ixrss = 0; idrss = 0; isrss = 0; } #endif #ifdef WIN32 maxfds = FD_SETSIZE; #else // WIN32 #ifdef HAVE_GETDTABLESIZE maxfds = getdtablesize(); #else maxfds = sysconf(_SC_OPEN_MAX); #endif int psize = getpagesize(); #endif // WIN32 /* * Go display everything */ #ifdef WIN32 raw_notify(player, tprintf("Process ID: %10d", game_pid)); #else // WIN32 raw_notify(player, tprintf("Process ID: %10d %10d bytes per page", game_pid, psize)); #endif // WIN32 #ifdef HAVE_GETRUSAGE raw_notify(player, tprintf("Time used: %10d user %10d sys", usage.ru_utime.tv_sec, usage.ru_stime.tv_sec)); /* * raw_notify(player, * * tprintf("Resident mem:%10d shared %10d private%10d stack", * * ixrss, idrss, isrss)); */ raw_notify(player, tprintf("Integral mem:%10d shared %10d private%10d stack", usage.ru_ixrss, usage.ru_idrss, usage.ru_isrss)); raw_notify(player, tprintf("Max res mem: %10d pages %10d bytes", usage.ru_maxrss, (usage.ru_maxrss * psize))); raw_notify(player, tprintf("Page faults: %10d hard %10d soft %10d swapouts", usage.ru_majflt, usage.ru_minflt, usage.ru_nswap)); raw_notify(player, tprintf("Disk I/O: %10d reads %10d writes", usage.ru_inblock, usage.ru_oublock)); raw_notify(player, tprintf("Network I/O: %10d in %10d out", usage.ru_msgrcv, usage.ru_msgsnd)); raw_notify(player, tprintf("Context swi: %10d vol %10d forced %10d sigs", usage.ru_nvcsw, usage.ru_nivcsw, usage.ru_nsignals)); raw_notify(player, tprintf("Descs avail: %10d", maxfds)); #endif } /* * --------------------------------------------------------------------------- * * do_list: List information stored in internal structures. */ #define LIST_ATTRIBUTES 1 #define LIST_COMMANDS 2 #define LIST_COSTS 3 #define LIST_FLAGS 4 #define LIST_FUNCTIONS 5 #define LIST_GLOBALS 6 #define LIST_ALLOCATOR 7 #define LIST_LOGGING 8 #define LIST_DF_FLAGS 9 #define LIST_PERMS 10 #define LIST_ATTRPERMS 11 #define LIST_OPTIONS 12 #define LIST_HASHSTATS 13 #define LIST_BUFTRACE 14 #define LIST_CONF_PERMS 15 #define LIST_SITEINFO 16 #define LIST_POWERS 17 #define LIST_SWITCHES 18 #define LIST_VATTRS 19 #define LIST_DB_STATS 20 #define LIST_PROCESS 21 #define LIST_BADNAMES 22 #define LIST_RESOURCES 23 NAMETAB list_names[] = { {(char *)"allocations", 2, CA_WIZARD, LIST_ALLOCATOR}, {(char *)"attr_permissions", 5, CA_WIZARD, LIST_ATTRPERMS}, {(char *)"attributes", 2, CA_PUBLIC, LIST_ATTRIBUTES}, {(char *)"bad_names", 2, CA_WIZARD, LIST_BADNAMES}, {(char *)"buffers", 2, CA_WIZARD, LIST_BUFTRACE}, {(char *)"commands", 3, CA_PUBLIC, LIST_COMMANDS}, {(char *)"config_permissions", 3, CA_GOD, LIST_CONF_PERMS}, {(char *)"costs", 3, CA_PUBLIC, LIST_COSTS}, {(char *)"db_stats", 2, CA_WIZARD, LIST_DB_STATS}, {(char *)"default_flags", 1, CA_PUBLIC, LIST_DF_FLAGS}, {(char *)"flags", 2, CA_PUBLIC, LIST_FLAGS}, {(char *)"functions", 2, CA_PUBLIC, LIST_FUNCTIONS}, {(char *)"globals", 1, CA_WIZARD, LIST_GLOBALS}, {(char *)"hashstats", 1, CA_WIZARD, LIST_HASHSTATS}, {(char *)"logging", 1, CA_GOD, LIST_LOGGING}, {(char *)"options", 1, CA_PUBLIC, LIST_OPTIONS}, {(char *)"permissions", 2, CA_WIZARD, LIST_PERMS}, {(char *)"powers", 2, CA_WIZARD, LIST_POWERS}, {(char *)"process", 2, CA_WIZARD, LIST_PROCESS}, {(char *)"resources", 1, CA_WIZARD, LIST_RESOURCES}, {(char *)"site_information", 2, CA_WIZARD, LIST_SITEINFO}, {(char *)"switches", 2, CA_PUBLIC, LIST_SWITCHES}, {(char *)"user_attributes", 1, CA_WIZARD, LIST_VATTRS}, { NULL, 0, 0, 0} }; extern NAMETAB enable_names[]; extern NAMETAB logoptions_nametab[]; extern NAMETAB logdata_nametab[]; void do_list(dbref player, dbref cause, int extra, char *arg) { int flagvalue; flagvalue = search_nametab(player, list_names, arg); switch (flagvalue) { case LIST_ALLOCATOR: list_bufstats(player); break; case LIST_BUFTRACE: list_buftrace(player); break; case LIST_ATTRIBUTES: list_attrtable(player); break; case LIST_COMMANDS: list_cmdtable(player); break; case LIST_SWITCHES: list_cmdswitches(player); break; case LIST_COSTS: list_costs(player); break; case LIST_OPTIONS: list_options(player); break; case LIST_HASHSTATS: list_hashstats(player); break; case LIST_SITEINFO: list_siteinfo(player); break; case LIST_FLAGS: display_flagtab(player); break; case LIST_FUNCTIONS: list_functable(player); break; case LIST_GLOBALS: interp_nametab(player, enable_names, mudconf.control_flags, (char *)"Global parameters:", (char *)"enabled", (char *)"disabled"); break; case LIST_DF_FLAGS: list_df_flags(player); break; case LIST_PERMS: list_cmdaccess(player); break; case LIST_CONF_PERMS: list_cf_access(player); break; case LIST_POWERS: display_powertab(player); break; case LIST_ATTRPERMS: list_attraccess(player); break; case LIST_VATTRS: list_vattrs(player); break; case LIST_LOGGING: interp_nametab(player, logoptions_nametab, mudconf.log_options, (char *)"Events Logged:", (char *)"enabled", (char *)"disabled"); interp_nametab(player, logdata_nametab, mudconf.log_info, (char *)"Information Logged:", (char *)"yes", (char *)"no"); break; case LIST_DB_STATS: list_db_stats(player); break; case LIST_PROCESS: list_process(player); break; case LIST_BADNAMES: badname_list(player, "Disallowed names:"); break; case LIST_RESOURCES: list_system_resources(player); break; default: display_nametab(player, list_names, (char *)"Unknown option. Use one of:", 1); } }