Command Table
command_rec aCommands[]
This structure points to an array of
directives that configure the module. Each entry names a directive,
specifies a function that will handle the command, and specifies
which AllowOverride
directives must be in force
for the command to be permitted. Each entry then specifies how the
directive’s arguments are to be parsed and supplies
an error message in case of syntax errors (such as the wrong number
of arguments, or a directive used where it shouldn’t
be).
The definition of
command_rec
can be found in
http_config.h:
typedef struct command_struct { const char *name; /* Name of this command */ const char *(*func)(); /* Function invoked */ void *cmd_data; /* Extra data, for functions that * implement multiple commands... */ int req_override; /* What overrides need to be allowed to * enable this command */ enum cmd_how args_how; /* What the command expects as arguments */ const char *errmsg; /* 'usage' message, in case of syntax errors */ } command_rec;
Note that in 2.0 this definition is still broadly correct, but
there’s also a variant for compilers that allow
designated initializers to permit the type-safe initialization of
command_rec
s.
cmd_how
is defined as
follows:
enum cmd_how { RAW_ARGS, /* cmd_func parses command line itself */ TAKE1, /* one argument only */ TAKE2, /* two arguments only */ ITERATE, /* one argument, occurring multiple times * (e.g., IndexIgnore) */ ITERATE2, /* two arguments, 2nd occurs multiple times * (e.g., AddIcon) */ FLAG, /* One of 'On' or 'Off' */ NO_ARGS, /* No args at all, e.g. </Directory> */ TAKE12, /* one or two arguments */ TAKE3, /* three arguments only */ TAKE23, /* two or three arguments */ TAKE123, /* one, two, or three arguments */ TAKE13 /* one or three arguments */ };
These options determine how the function func
is
called when the matching directive is found in a Config file, but
first we must look at one more structure,
cmd_parms
:
typedef struct { void *info; /* Argument to command from cmd_table */ int override; /* Which allow-override bits are set */ int limited; /* Which methods are <Limit>ed */ configfile_t *config_file; /* Config file structure from pcfg_openfile() */ ap_pool *pool; /* Pool to allocate new storage in */ struct pool *temp_pool; /* Pool for scratch memory; persists during * configuration, but wiped before the first * request is served... */ server_rec *server; /* Server_rec being configured for */ char *path; /* If configuring for a directory, * pathname of that directory. * NOPE! That's what it meant previous to the * existance of <Files>, <Location> and regex * matching. Now the only usefulness that can * be derived from this field is whether a command * is being called in a server context (path == NULL) * or being called in a dir context (path != NULL). */ const command_rec *cmd; /* configuration command */ const char *end_token; /* end token required to end a nested section */ void *context; /* per_dir_config vector passed * to handle_command */ } cmd_parms;
This structure is filled in and passed to the function associated
with each directive. Note that cmd_parms.info
is
filled in with the value of command_rec.cmd_data
,
allowing arbitrary extra information to be passed to the function.
The function is also passed its per-directory configuration
structure, if there is one, shown in the following function
definitions as mconfig
. The per-server
configuration can be accessed by a call similar to:
ap_get_module_config(parms->server->module_config, &module_struct)
replacing module_struct
with your own
module’s module
structure. Extra
information may also be passed, depending on the value of
args_how
:
RAW_ARGS
func(cmd_parms *parms, void *mconfig, char *args)
args
is simply the rest of the line (that is,
excluding the directive).
NO_ARGS
func(cmd_parms *parms, void *mconfig)
TAKE1
func(cmd_parms *parms, void *mconfig, char *w)
w
is the single argument to the directive.
TAKE2
, TAKE12
func(cmd_parms *parms, void *mconfig, char *w1, char
*w2)
w1
and w2
are the two arguments
to the directive. TAKE12
means the second argument
is optional. If absent, w2
is
NULL
.
TAKE3
, TAKE13
, TAKE23
, TAKE123
func(cmd_parms *parms, void *mconfig, char *w1, char *w2,
char *w3)
w1
, w2
, and
w3
are the three arguments to the directive.
TAKE13
, TAKE23
, and
TAKE123
mean that the directive takes one or
three, two or three, and one, two, or three arguments, respectively.
Missing arguments are NULL
.
ITERATE
func(cmd_parms *parms, void *mconfig, char *w)
func
is called repeatedly, once for each argument
following the directive.
ITERATE2
func(cmd_parms *parms, void *mconfig, char *w1, char
*w2)
There must be at least two arguments. func
is
called once for each argument, starting with the second. The first is
passed to func
every time.
FLAG
func(cmd_parms *parms, void *mconfig, int f)
The argument must be either On
or
Off
. If On
, then
f
is nonzero; if Off
,
f
is zero.
In 2.0 each of the previous has its own macro to define it, to allow
for type-safe initialization where supported by the compiler entries.
So instead of directly using the flag ITERATE
, for
example, you would instead use the macro
AP_INIT_ITERATE
to fill in the
command_rec
structure.
req_override
can be any combination of the
following (OR
ed together):
#define OR_NONE 0 #define OR_LIMIT 1 #define OR_OPTIONS 2 #define OR_FILEINFO 4 #define OR_AUTHCFG 8 #define OR_INDEXES 16 #define OR_UNSET 32 #define ACCESS_CONF 64 #define RSRC_CONF 128 #define OR_ALL (OR_LIMIT|OR_OPTIONS|OR_FILEINFO|OR_AUTHCFG|OR_INDEXES)
2.0 adds one extra option:
#define EXEC_ON_READ 256 /**< force directive to execute a command which would modify the configuration (like including another file, or IFModule */
This flag defines the circumstances under which a directive is
permitted. The logical AND
of this field and the
current override state must be nonzero for the directive to be
allowed. In configuration files, the current override state is:
RSRC_CONF|OR_OPTIONS|OR_FILEINFO|OR_INDEXES
when outside a <Directory>
section, and it
is:
ACCESS_CONF|OR_LIMIT|OR_OPTIONS|OR_FILEINFO|OR_AUTHCFG|OR_INDEXES
when inside a <Directory>
section.
In .htaccess files, the state is determined by
the AllowOverride
directive. See Example 21-7 (1.3) for an excerpt from
mod_mime.c.
Example 21-7. mod_mime.c
static const command_rec mime_cmds[] = { {"AddType", add_type, NULL, OR_FILEINFO, ITERATE2, "a mime type followed by one or more file extensions"}, {"AddEncoding", add_encoding, NULL, OR_FILEINFO, ITERATE2, "an encoding (e.g., gzip), followed by one or more file extensions"}, {"AddCharset", add_charset, NULL, OR_FILEINFO, ITERATE2, "a charset (e.g., iso-2022-jp), followed by one or more file extensions"}, {"AddLanguage", add_language, NULL, OR_FILEINFO, ITERATE2, "a language (e.g., fr), followed by one or more file extensions"}, {"AddHandler", add_handler, NULL, OR_FILEINFO, ITERATE2, "a handler name followed by one or more file extensions"}, {"ForceType", ap_set_string_slot_lower, (void *)XtOffsetOf(mime_dir_config, type), OR_FILEINFO, TAKE1, "a media type"}, {"RemoveHandler", remove_handler, NULL, OR_FILEINFO, ITERATE, "one or more file extensions"}, {"RemoveEncoding", remove_encoding, NULL, OR_FILEINFO, ITERATE, "one or more file extensions"}, {"RemoveType", remove_type, NULL, OR_FILEINFO, ITERATE, "one or more file extensions"}, {"SetHandler", ap_set_string_slot_lower, (void *)XtOffsetOf(mime_dir_config, handler), OR_FILEINFO, TAKE1, "a handler name"}, {"TypesConfig", set_types_config, NULL, RSRC_CONF, TAKE1, "the MIME types config file"}, {"DefaultLanguage", ap_set_string_slot, (void*)XtOffsetOf(mime_dir_config, default_language), OR_FILEINFO, TAKE1, "language to use for documents with no other language file extension" }, {NULL} };
Note the use of set_string_slot()
. This
standard function uses the offset defined in
cmd_data
, using XtOffsetOf
to
set a char*
in the per-directory configuration of
the module. See Example 21-8 (2.0)
for an excerpt from mod_mime.c.
Example 21-8. mod_mime.c
static const command_rec mime_cmds[] = { AP_INIT_ITERATE2("AddCharset", add_extension_info, (void *)APR_XtOffsetOf(extension_info, charset_type), OR_FILEINFO, "a charset (e.g., iso-2022-jp), followed by one or more file extensions"), AP_INIT_ITERATE2("AddEncoding", add_extension_info, (void *)APR_XtOffsetOf(extension_info, encoding_type), OR_FILEINFO, "an encoding (e.g., gzip), followed by one or more file extensions"), AP_INIT_ITERATE2("AddHandler", add_extension_info, (void *)APR_XtOffsetOf(extension_info, handler), OR_FILEINFO, "a handler name followed by one or more file extensions"), AP_INIT_ITERATE2("AddInputFilter", add_extension_info, (void *)APR_XtOffsetOf(extension_info, input_filters), OR_FILEINFO, "input filter name (or ; delimited names) followed by one or more file extensions"), AP_INIT_ITERATE2("AddLanguage", add_extension_info, (void *)APR_XtOffsetOf(extension_info, language_type), OR_FILEINFO, "a language (e.g., fr), followed by one or more file extensions"), AP_INIT_ITERATE2("AddOutputFilter", add_extension_info, (void *)APR_XtOffsetOf(extension_info, output_filters), OR_FILEINFO, "output filter name (or ; delimited names) followed by one or more file extensions"), AP_INIT_ITERATE2("AddType", add_extension_info, (void *)APR_XtOffsetOf(extension_info, forced_type), OR_FILEINFO, "a mime type followed by one or more file extensions"), AP_INIT_TAKE1("DefaultLanguage", ap_set_string_slot, (void*)APR_XtOffsetOf(mime_dir_config, default_language), OR_FILEINFO, "language to use for documents with no other language file extension"), AP_INIT_ITERATE("MultiviewsMatch", multiviews_match, NULL, OR_FILEINFO, "NegotiatedOnly (default), Handlers and/or Filters, or Any"), AP_INIT_ITERATE("RemoveCharset", remove_extension_info, (void *)APR_XtOffsetOf(extension_info, charset_type), OR_FILEINFO, "one or more file extensions"), AP_INIT_ITERATE("RemoveEncoding", remove_extension_info, (void *)APR_XtOffsetOf(extension_info, encoding_type), OR_FILEINFO, "one or more file extensions"), AP_INIT_ITERATE("RemoveHandler", remove_extension_info, (void *)APR_XtOffsetOf(extension_info, handler), OR_FILEINFO, "one or more file extensions"), AP_INIT_ITERATE("RemoveInputFilter", remove_extension_info, (void *)APR_XtOffsetOf(extension_info, input_filters), OR_FILEINFO, "one or more file extensions"), AP_INIT_ITERATE("RemoveLanguage", remove_extension_info, (void *)APR_XtOffsetOf(extension_info, language_type), OR_FILEINFO, "one or more file extensions"), AP_INIT_ITERATE("RemoveOutputFilter", remove_extension_info, (void *)APR_XtOffsetOf(extension_info, output_filters), OR_FILEINFO, "one or more file extensions"), AP_INIT_ITERATE("RemoveType", remove_extension_info, (void *)APR_XtOffsetOf(extension_info, forced_type), OR_FILEINFO, "one or more file extensions"), AP_INIT_TAKE1("TypesConfig", set_types_config, NULL, RSRC_CONF, "the MIME types config file"), {NULL} };
As you can see, this uses the macros to initialize the structure.
Also note that set_string_slot()
has become
ap_set_string_slot()
.