Name

Command Table

Synopsis

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_recs.

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 (ORed 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

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().