TinyMUSH 3.3
TinyMUSH Server
|
Command parser and support routines. More...
#include "config.h"
#include "constants.h"
#include "typedefs.h"
#include "macros.h"
#include "externs.h"
#include "prototypes.h"
#include <stdbool.h>
#include <ctype.h>
#include <string.h>
#include <pcre.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <dlfcn.h>
#include <unistd.h>
#include <libgen.h>
Functions | |
void | init_cmdtab (void) |
Initialize the command table. More... | |
void | reset_prefix_cmds (void) |
Reset prefix's commands. More... | |
bool | check_access (dbref player, int mask) |
Check if player has access to function. Note that the calling function may also give permission denied messages on failure. More... | |
bool | check_mod_access (dbref player, EXTFUNCS *xperms) |
Go through sequence of module call-outs, treating all of them like permission checks. More... | |
bool | check_userdef_access (dbref player, HOOKENT *hookp, char *cargs[], int ncargs) |
Check if user has access to command with user-def'd permissions. More... | |
void | process_hook (HOOKENT *hp, int save_globs, dbref player, dbref cause __attribute__((unused)), char *cargs[], int ncargs) |
Evaluate a hook. More... | |
void | call_move_hook (dbref player, dbref cause, bool state) |
Call the hooks before and after leaving a room. More... | |
bool | check_cmd_access (dbref player, CMDENT *cmdp, char *cargs[], int ncargs) |
Check if user has access to command. More... | |
void | process_cmdent (CMDENT *cmdp, char *switchp, dbref player, dbref cause, bool interactive, char *arg, char *unp_command, char *cargs[], int ncargs) |
Perform indicated command with passed args. More... | |
char * | process_command (dbref player, dbref cause, int interactive, char *command, char *args[], int nargs) |
Execute a command. More... | |
void | process_cmdline (dbref player, dbref cause, char *cmdline, char *args[], int nargs, BQUE *qent) |
Execute a semicolon/pipe-delimited series of commands. More... | |
void | list_cmdtable (dbref player) |
List internal commands. Note that user-defined command permissions are ignored in this context. More... | |
void | list_attrtable (dbref player) |
List available attributes. More... | |
void | helper_list_cmdaccess (dbref player, CMDENT *ctab) |
Helper for the list access commands. More... | |
void | list_cmdaccess (dbref player) |
List access commands. More... | |
void | list_cmdswitches (dbref player) |
List switches for commands. More... | |
void | list_attraccess (dbref player) |
List access to attributes. More... | |
void | list_attrtypes (dbref player) |
List attribute "types" (wildcards and permissions) More... | |
int | cf_access (int *vp __attribute__((unused)), char *str, long extra, dbref player, char *cmd) |
Change command or switch permissions. More... | |
int | cf_acmd_access (int *vp __attribute__((unused)), char *str, long extra, dbref player, char *cmd) |
Change command permissions for all attr-setting cmds. More... | |
int | cf_attr_access (int *vp __attribute__((unused)), char *str, long extra, dbref player, char *cmd) |
Change access on an attribute. More... | |
int | cf_attr_type (int *vp __attribute__((unused)), char *str, long extra, dbref player, char *cmd) |
Define attribute flags for new user-named attributes whose names match a certain pattern. More... | |
int | cf_cmd_alias (int *vp, char *str, long extra __attribute__((unused)), dbref player, char *cmd) |
Add a command alias. More... | |
void | list_df_flags (dbref player) |
List default flags at create time. More... | |
void | list_costs (dbref player) |
List the costs of things. More... | |
void | list_params (dbref player) |
List boolean game options from mushconf. list_config: List non-boolean game options. More... | |
void | list_vattrs (dbref player) |
List user-defined attributes. More... | |
void | list_hashstat (dbref player, const char *tab_name, HASHTAB *htab) |
Helper for listing information from an hash table. More... | |
void | list_nhashstat (dbref player, const char *tab_name, HASHTAB *htab) |
Helper for listing information from an nhash table. More... | |
void | list_hashstats (dbref player) |
List informations from Hash/NHash tables. More... | |
void | list_textfiles (dbref player) |
List textfiles. More... | |
void | list_db_stats (dbref player) |
Get useful info from the DB layer about hash stats, etc. More... | |
void | list_process (dbref player) |
List local resource usage stats of the MUSH process. Adapted from code by Claudius@PythonMUCK, posted to the net by Howard/Dark_Lord. More... | |
void | print_memory (dbref player, const char *item, size_t size) |
void | list_memory (dbref player) |
Breaks down memory usage of the process. More... | |
void | do_list (dbref player, dbref cause __attribute__((unused)), int extra __attribute__((unused)), char *arg) |
List information stored in internal structures. More... | |
Variables | |
void(* | handler_cs_no_args )(dbref, dbref, int) |
void(* | handler_cs_one_args )(dbref, dbref, int, char *) |
void(* | handler_cs_one_args_unparse )(dbref, char *) |
void(* | handler_cs_one_args_cmdargs )(dbref, dbref, int, char *, char *[], int) |
void(* | handler_cs_two_args )(dbref, dbref, int, char *, char *) |
void(* | handler_cs_two_args_cmdargs )(dbref, dbref, int, char *, char *, char *[], int) |
void(* | handler_cs_two_args_argv )(dbref, dbref, int, char *, char *[], int) |
void(* | handler_cs_two_args_cmdargs_argv )(dbref, dbref, int, char *, char *[], int, char *[], int) |
CMDENT * | prefix_cmds [256] |
CMDENT * | goto_cmdp |
CMDENT * | enter_cmdp |
CMDENT * | leave_cmdp |
CMDENT * | internalgoto_cmdp |
Command parser and support routines.
void call_move_hook | ( | dbref | player, |
dbref | cause, | ||
bool | state | ||
) |
Call the hooks before and after leaving a room.
player | DBref of Player leaving |
cause | DBref of what caused the action |
state | True: before, False: after |
int cf_access | ( | int *vp | __attribute__(unused), |
char * | str, | ||
long | extra, | ||
dbref | player, | ||
char * | cmd | ||
) |
Change command or switch permissions.
vp | |
str | |
extra | |
player | |
cmd |
int cf_acmd_access | ( | int *vp | __attribute__(unused), |
char * | str, | ||
long | extra, | ||
dbref | player, | ||
char * | cmd | ||
) |
Change command permissions for all attr-setting cmds.
vp | |
str | |
extra | |
player | |
cmd |
int cf_attr_access | ( | int *vp | __attribute__(unused), |
char * | str, | ||
long | extra, | ||
dbref | player, | ||
char * | cmd | ||
) |
Change access on an attribute.
vp | |
str | |
extra | |
player | |
cmd |
int cf_attr_type | ( | int *vp | __attribute__(unused), |
char * | str, | ||
long | extra, | ||
dbref | player, | ||
char * | cmd | ||
) |
Define attribute flags for new user-named attributes whose names match a certain pattern.
vp | |
str | |
extra | |
player | |
cmd |
Split our string into the attribute pattern and privileges. Also uppercase it, while we're at it. Make sure it's not longer than an attribute name can be.
Create our new data blob. Make sure that we're setting the privs to something reasonable before trying to link it in. (If we're not, an error will have been logged; we don't need to do it.)
int cf_cmd_alias | ( | int * | vp, |
char * | str, | ||
long extra | __attribute__(unused), | ||
dbref | player, | ||
char * | cmd | ||
) |
Add a command alias.
vp | |
str | |
extra | |
player | |
cmd |
we only got one argument to @alias. Bad.
Switch form of command aliasing: create an alias for a command + a switch
Look up the command
Look up the switch
Got it, create the new command table entry
KNOWN PROBLEM: We are not inheriting the hook that the 'original' command had – we will have to add it manually (whereas an alias of a non-switched command is just another hashtable entry for the same command pointer and therefore gets the hook). This is preferable to having to search the hashtable for hooks when a hook is deleted, though.
A normal (non-switch) alias
bool check_access | ( | dbref | player, |
int | mask | ||
) |
Check if player has access to function. Note that the calling function may also give permission denied messages on failure.
player | Player doing the command |
mask | Permission's mask |
Check if we have permission to execute
Check for bits that we have to have. Since we know that we're not God at this point, if it is God-only, it fails. (God in combination with other stuff is implicitly checked, since we return false if we don't find the other bits.)
Check the things that we can't be.
bool check_cmd_access | ( | dbref | player, |
CMDENT * | cmdp, | ||
char * | cargs[], | ||
int | ncargs | ||
) |
Check if user has access to command.
player | DBref of playuer |
cmdp | Command entry |
cargs | Command Arguments |
ncargs | Number of arguments |
bool check_mod_access | ( | dbref | player, |
EXTFUNCS * | xperms | ||
) |
Go through sequence of module call-outs, treating all of them like permission checks.
player | Player doing the command |
xperms | Extended functions list |
bool check_userdef_access | ( | dbref | player, |
HOOKENT * | hookp, | ||
char * | cargs[], | ||
int | ncargs | ||
) |
Check if user has access to command with user-def'd permissions.
player | Player doing the command |
hookp | Hook entry point |
cargs | Command argument list |
ncargs | Number of arguments |
We have user-defined command permissions. Go evaluate the obj/attr pair that we've been given. If that result is nonexistent, we consider it a failure. We use boolean truth here.
Note that unlike before and after hooks, we always preserve the registers. (When you get right down to it, this thing isn't really a hook. It's just convenient to re-use the same code that we use with hooks.)
void do_list | ( | dbref | player, |
dbref cause | __attribute__(unused), | ||
int extra | __attribute__(unused), | ||
char * | arg | ||
) |
List information stored in internal structures.
player | DBref of player |
cause | DBref of cause |
extra | Not used. |
arg | Arguments |
void helper_list_cmdaccess | ( | dbref | player, |
CMDENT * | ctab | ||
) |
Helper for the list access commands.
player | DBref of the player |
ctab | Command table |
buff | Buffer for the list |
void init_cmdtab | ( | void | ) |
Initialize the command table.
Load attribute-setting commands
also add the __ alias form
Load the builtin commands, plus __ aliases
Set the builtin prefix commands
void list_attraccess | ( | dbref | player | ) |
List access to attributes.
player | DBref of player |
void list_attrtable | ( | dbref | player | ) |
List available attributes.
player |
void list_attrtypes | ( | dbref | player | ) |
List attribute "types" (wildcards and permissions)
player | DBref of player |
void list_cmdaccess | ( | dbref | player | ) |
List access commands.
player | DBref of the player |
void list_cmdswitches | ( | dbref | player | ) |
List switches for commands.
player | DBref of the player |
void list_cmdtable | ( | dbref | player | ) |
List internal commands. Note that user-defined command permissions are ignored in this context.
player | DBref of the player |
Players get the list of logged-out cmds too
void list_costs | ( | dbref | player | ) |
List the costs of things.
player | DBref of player |
void list_db_stats | ( | dbref | player | ) |
Get useful info from the DB layer about hash stats, etc.
player | DBref of player |
void list_df_flags | ( | dbref | player | ) |
List default flags at create time.
player | DBref of player |
void list_hashstat | ( | dbref | player, |
const char * | tab_name, | ||
HASHTAB * | htab | ||
) |
Helper for listing information from an hash table.
player | DBref of player |
tab_name | Hash table name |
htab | Hash table |
void list_hashstats | ( | dbref | player | ) |
List informations from Hash/NHash tables.
player | DBref of player |
void list_memory | ( | dbref | player | ) |
Breaks down memory usage of the process.
player | DBref of player |
Calculate size of object structures
Calculate size of mushstate and mushconf structures
Calculate size of cache
Calculate size of object pipelines
Calculate size of name caches
Calculate size of Raw Memory allocations
Calculate size of command hashtable
Add up all the little bits in the CMDENT.
Calculate size of logged-out commands hashtable
Calculate size of functions hashtable
We don't count func->name because we already got it with htab->target.s
Calculate size of user-defined functions hashtable
Calculate size of flags hashtable
We don't count flag->flagname because we already got it with htab->target.s
Calculate size of powers hashtable
We don't count power->powername because we already got it with htab->target.s
Calculate size of helpfile hashtables
Calculate size of vattr name hashtable
Calculate size of attr name hashtable
Calculate the size of anum_table
After this point, we only report if it's non-zero.
Calculate size of object stacks
Calculate the size of grids
Calculate the size of xvars.
Calculate the size of overhead associated with structures.
Calculate the size of data associated with structures.
Report end total.
void list_nhashstat | ( | dbref | player, |
const char * | tab_name, | ||
HASHTAB * | htab | ||
) |
Helper for listing information from an nhash table.
player | DBref of player |
tab_name | NHash table name |
htab | NHash table |
void list_params | ( | dbref | player | ) |
List boolean game options from mushconf. list_config: List non-boolean game options.
player | DBref of player |
void list_process | ( | dbref | player | ) |
List local resource usage stats of the MUSH process. Adapted from code by Claudius@PythonMUCK, posted to the net by Howard/Dark_Lord.
player | DBref of player |
Go display everything
void list_textfiles | ( | dbref | player | ) |
List textfiles.
player | DBref of player |
void list_vattrs | ( | dbref | player | ) |
List user-defined attributes.
player | DBref of player |
void process_cmdent | ( | CMDENT * | cmdp, |
char * | switchp, | ||
dbref | player, | ||
dbref | cause, | ||
bool | interactive, | ||
char * | arg, | ||
char * | unp_command, | ||
char * | cargs[], | ||
int | ncargs | ||
) |
Perform indicated command with passed args.
cmdp | Command |
switchp | Switches |
player | DBref of player doing the command |
cause | DBref of what caused the action |
interactive | Is the command interractive? |
arg | Raw Arguments |
unp_command | Raw Commands |
cargs | Arguments |
ncargs | Number of arguments |
Perform object type checks.
Check if we have permission to execute the command
Check global flags
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.
At this point we're guaranteed we're going to execute something. Let's check to see if we have a pre-command hook.
If the command normally has interpreted args, but the user specified, /noeval, just do EV_STRIP.
If the command is interpreted, or we're interactive (and the command isn't specified CS_NOINTERP), eval the args.
The others are obvious.
< <cmd> (no args)
< <cmd> <arg>
If an unparsed command, just give it to the handler
Interpret if necessary, but not twice for CS_ADDED
Call the correct handler
Construct the matching buffer.
In the case of a single-letter prefix, we want to just skip past that first letter. want to just skip past that first letter. Otherwise we want to go past the first word.
No args
Now search against the attributes, unless we can't pass the uselock.
Skip the '$' character, and the next
The command the player typed didn't match any of the wildcard patterns we have for that addcommand. We should raise an error. We DO NOT go back into trying to match other stuff – this is a 'Huh?' situation.
Free the buffer if one was allocated
Interpret ARG1
Handle when no '=' was specified
Arg2 is ARGV style. Go get the args
Call the correct command handler
Free the argument buffers
Arg2 is normal style. Interpret if needed
Call the correct command handler
Free the buffer, if needed
Free the buffer obtained by evaluating Arg1
And now we go do the posthook, if we have one.
void process_cmdline | ( | dbref | player, |
dbref | cause, | ||
char * | cmdline, | ||
char * | args[], | ||
int | nargs, | ||
BQUE * | qent | ||
) |
Execute a semicolon/pipe-delimited series of commands.
player | DBref of the player |
cause | DBref of the cause |
cmdline | Command |
args | Arguments |
nargs | Number of arguments |
qent | Command queue. |
No lag check on piped commands
Is the queue still linked like we think it is?
Don't use msec_add(), this is more accurate
char * process_command | ( | dbref | player, |
dbref | cause, | ||
int | interactive, | ||
char * | command, | ||
char * | args[], | ||
int | nargs | ||
) |
Execute a command.
player | DBref of player doing the command |
cause | DBref of what caused the action |
interactive | Is the command interractive? |
command | Command |
args | Arguments |
nargs | Number of arguments |
Robustify player
Make sure player isn't going or halted
Reset recursion and other limits. Baseline the CPU counter.
We have no pointer, we should have no flags.
Eat leading whitespace, and space-compress if configured
Allow modules to intercept command strings.
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.
Check for the HOME command. You cannot do hooks on this because home is not part of the traditional command table.
Only check for exits if we may use the goto command
Check for an exit name
Exits literally call the 'move' command. Note that, later, when we go to matching master-room and other global-ish exits, that we also need to have move_match_more set to 'yes', or we'll match here only to encounter dead silence when we try to find the exit inside the move routine. We also need to directly find what the pointer for the move (goto) command is, since we could have @addcommand'd it (and probably did, if this conf option is on). Finally, we've got to make this look like we really did type 'goto <exit>', or the @addcommand will just skip over the string.
Execute the pre-hook for the goto command
Execute the post-hook for the goto command
Check for an exit in the master room
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 lcbuf after the lowercased command.
Removed copy of the rest of the command, since it's ok to allow it to be trashed. -dcm
Check for a builtin command (or an alias of a builtin command)
We handle this specially – there is no space compression involved, so we must go back to the preserved command.
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.
Idea for enter/leave aliases from R'nice@TinyTIM
Check for a leave alias, if we have permissions to use the 'leave' command.
Check for enter aliases, if we have permissions to use the 'enter' command.
At each of the following stages, we check to make sure that we haven't hit a match on a STOP-set object.
Check for $-command matches on me
Check for $-command matches on nearby things and on my room
Check for $-command matches in my inventory
If we didn't find anything, and we're checking local masters, do those checks. Do it for the zone of the player's location first, and then, if nothing is found, on the player's personal zone. Walking back through the parent tree stops when a match is found. Also note that these matches are done in the style of the master room: parents of the contents of the rooms aren't checked for commands. We try to maintain 2.2/MUX compatibility here, putting both sets of checks together.
2.2 style location
MUX style location
zone of player's location is a parent room
check parent room exits
try matching commands on area zone object
2.2 style player
MUX style player
if nothing matched with parent room/zone object, try matching zone commands on the player's personal zone
If we didn't find anything, try in the master room
Allow modules to intercept, if still no match. This time we pass both the lower-cased evaluated buffer and the preserved command.
If we still didn't find anything, tell how to get help.
void process_hook | ( | HOOKENT * | hp, |
int | save_globs, | ||
dbref | player, | ||
dbref cause | __attribute__(unused), | ||
char * | cargs[], | ||
int | ncargs | ||
) |
Evaluate a hook.
hp | Hook Entry |
save_globs | Save globals? |
player | Player being evaluated |
cause | Cause of the evaluation |
cargs | Command arguments |
ncargs | Number of arguments |
We know we have a non-null hook. We want to evaluate the obj/attr pair of that hook. We consider the enactor to be the player who executed the command that caused this hook to be called.
void reset_prefix_cmds | ( | void | ) |
Reset prefix's commands.