home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  


Writing Apache Modules with Perl and C
By:   Lincoln Stein and Doug MacEachern
Published:   O'Reilly & Associates, Inc.  - March 1999

Copyright © 1999 by O'Reilly & Associates, Inc.


 


   Show Contents   Previous Page   Next Page

Chapter 11 - C API Reference Guide, Part II / Implementing Configuration Directives in C
Constants for the args_how Field

Directives differ in their syntax: the number of arguments they take, the number of variable arguments, and the relationship of one argument to another. Apache can handle the common syntaxes, preparsing the directive and its arguments, then presenting the results to a directive handler of your own devising.

Eleven constants, all defined in http_config.h, specify various syntax parsing strategies. If none of these satisfies your needs, a twelfth constant, RAW_ARGS, gives you direct access to the text of the configuration file.

In the list that follows, we give the constant and the recommended function prototype for the directive handler callback. All callbacks take at least two arguments. parms is a pointer to a cmd_parms structure, from which various information about the server and the status of the configuration process can be extracted. More details on the cmd_parms structure are given in the next section.

mconfig is a generic pointer to the module-specific per-directory configuration data that your module created earlier with its create_dir_config() routine. Since most directive handlers work with pre-directory configuration records, this parameter is provided as a convenience. Your handler will typecast this to its specific type, and then set the appropriate fields. Directive handlers that operate on per-server configuration data must manually retrieve the record using ap_get_module_config() as described later.

On successful processing of the directive, the handler should return NULL. If an error occurred while processing the directive, the routine should return a string describing the source of the error. There is also a third possibility. The configuration directive handler can return DECLINE_CMD, a constant defined in http_config.h as the string \a\b. This is useful in the rare circumstance in which a module redeclares another module's directive in order to override it. The directive handler can then return DECLINE_CMD when it wishes the directive to fall through to the original module.

NO_ARGS

The directive takes no arguments at all, for example ClearModuleList.

Function prototype:

static const char *cmd_no_args
     (cmd_parms *parms, void *mconfig)

FLAG

The directive takes one of the string arguments On or Off. The parser converts this argument to an integer Boolean, which it passes to the directive handler. UseCanonicalName is one example of this type of directive.

Function prototype:

static const char *cmd_flag
     (cmd_parms *parms, void *mconfig, int flag)

TAKE1

The directive takes one argument only, e.g., Port.

Function prototype:

static const char *cmd_take1
     (cmd_parms *parms, void *mconfig, const char *arg)

Here is an example of a handler for a TrafficCopSpeedLimit directive that takes a single argument indicating the maximum speed at which clients are allowed to fetch documents:

static const char *traffic_speed_limit_cmd (cmd_parms *parms,
                           void *mconfig, const char *arg)
{
    traffic_dir_config *cfg = (traffic_dir_config *)mconfig;
    traffic_server_config *scfg = (traffic_server_config *)
       ap_get_module_config(parms->server->module_config, &traffic_module);
     long int speed = strtol(arg, (char**)NULL, 10);
     if (speed < 0) {
        return "Speed must be a positive number";
    }
    if (speed == LONG_MAX) {
        return "Integer overflow or invalid number";
    }
    scfg->speed_limit = speed;
    return NULL;
}

TAKE2

The directive takes exactly two arguments, e.g., SetEnv.

Function prototype:

static const char *cmd_take2
     (cmd_parms *parms, void *mconfig, const char *one, const char *two)

ITERATE

The directive takes a list of arguments, each of which has the same meaning, as in IndexIgnore . The callback is invoked repeatedly to process each argument.

Function prototype:

static const char *cmd_iterate
     (cmd_parms *parms, void *mconfig, const char *arg)

For example, a TrafficCopRightOfWay directive for the imaginary traffic cop module might take a list of domains and hostnames that are allowed to retrieve documents as fast as they wish. Assuming that the list of privileged hosts is maintained as the set of keys in an Apache table, here's one way to record the configuration information:

static const char *traffic_rt_of_way_cmd(cmd_parms *parms,
                           void *mconfig, const char *arg)
{
    traffic_dir_config *cfg = (traffic_dir_config *)mconfig;
    traffic_server_config *scfg = (traffic_server_config *)
        ap_get_module_config(parms->server->module_config, &traffic_module);
    ap_table_set(scfg->right_of_way, arg, "t");
   return NULL;
}

ITERATE2

The directive takes a mandatory first argument followed by a variable list of arguments to be applied to the first. A familiar example is the AddIcon directive. Apache will call the directive handler once for each member of the list, passing the handler the mandatory argument and the current list item.

Function prototype:

static const char *cmd_iterate2
     (cmd_parms *parms, void *mconfig, const char *one, const char *two)

TAKE12

The directive will accept one or two arguments, as in the AuthUserFile directive. If the optional second argument is absent, it will be passed as NULL to your handler.

Function prototype:

static const char *cmd_take12
     (cmd_parms *parms, void *mconfig, const char *one, const char *two)

TAKE3

The directive takes exactly three arguments.

Function prototype:

static const char *cmd_take3
     (cmd_parms *parms, void *mconfig,
      const char *one, const char *two, const char *three)

TAKE23

The directive takes two or three arguments, as in Redirect. Missing arguments are passed to the directive handler as NULL.

Function prototype:

static const char *cmd_take23
     (cmd_parms *parms, void *mconfig,
      const char *one, const char *two, const char *three)

TAKE123

The directive takes one, two, or three arguments. Missing arguments are passed to the directive handler as NULL.

Function prototype:

static const char *cmd_take123
     (cmd_parms *parms, void *mconfig,
      const char *one, const char *two, const char *three)

TAKE13

Continuing in the same vein, directives with this syntax take either one or three arguments, but not two. Any missing arguments are passed as NULL.

Function prototype:

static const char *cmd_take13
     (cmd_parms *parms, void *mconfig,
      const char *one, const char *two, const char *three)

RAW_ARGS

This last constant is used for complex directives that the server won't be able to parse on its own. Your module must implement the parsing itself. The corresponding directive handler will be passed everything to the right of the directive name as an unparsed string. It can then use ap_getword() to process the string a word at a time.

The function prototype for RAW_ARGS directive handlers looks like this:

const char *cmd_raw_args
     (cmd_parms *parms, void *mconfig, const char *args)

RAW_ARGS can also be used to implement new container-style directives like <Limit> and <Location> by reading directly from the configuration file using the config_file field of the parms argument. See "Customizing the Configuration Process" later in this chapter for details on reading from this field.

   Show Contents   Previous Page   Next Page
Copyright © 1999 by O'Reilly & Associates, Inc.