Show Contents Previous Page Next Page
Chapter 11 - C API Reference Guide, Part II / Implementing Configuration Directives in C Handy Built-in Directive Handlers
It is often the case that a configuration directive will end up simply setting the value of a structure field without doing any additional work. There are a few directive handlers built into the Apache API to handle such common cases.
Since it isn't possible for a built-in function to know anything about the
structure of a module-specific data type, these functions work by writing directly
into the module's configuration data using pointer arithmetic. You calculate
the correct offset into the structure using the XtOffsetOf() macro1
and place this offset into the command table's cmd_data field.
For example, in Example 11-3 the HelloTo
directive simply sets a string pointer in the to field of the hello_dir_config
struct. Instead of writing our own handler to accomplish this task, we can use
the generic ap_set_string_slot() call, providing the handler with the
offset of the field:
static command_rec hello_cmds[] =
{
{
"HelloTo",
ap_set_string_slot,
(void *)XtOffsetOf(hello_dir_config, to),
OR_ALL,
TAKE1,
"Who we say hello to, default is 'world'"
},
{NULL}
};
The generic directive handlers and the XtOffsetOf() macro are declared in ap_config.h. The following generic directive handlers are available:
const char *ap_set_string_slot (cmd_parms *parms, char *ptr, char *arg)
This handler is used with the TAKE1 prototype to set a string in a configuration structure.
The provided offset must point to a char* field. See the previous code snippet for
an example of its usage.
const char *ap_set_string_slot_lower (cmd_parms *parms, char *ptr,
char *arg)
This function works just the same as ap_set_string_slot() but changes the value of the
directive's argument to lowercase before setting the configuration field.
const char *ap_set_flag_slot (cmd_parms *parms, char *ptr, int flag)
This function is intended to be used with a FLAG prototype. The structure offset
should point to an integer field. For example, if we wanted the ability to turn off our
"Hello world" message entirely, we could add a new int helloOn field to the hello_dir_
config struct and toggle it on and off with a SayHello directive. An appropriate slot in the
command table would then look like this:
{
"SayHello",
ap_set_flag_slot,
(void *)XtOffsetOf(hello_dir_config, helloOn),
OR_ALL,
FLAG,
"Should we say Hello, On or Off",
},
The content handler could now test cfg->helloOn to determine whether to print out that annoyingly repetitive message or not.
const char *ap_set_file_slot (cmd_parms *parms, char *ptr, char *file)
The last goodie is a built-in handler that works much like ap_set_string_slot() but assumes
the argument is a filename. If the filename is not absolute, it is first resolved relative to
the configured ServerRoot directory. For example, let's say we wanted to read our "Hello" message from a file stored on disk.
We could add a char* to_file field to the configuration struct and set it using a HelloToFile
directive described by this table entry:
{
"HelloToFile",
ap_set_file_slot,
(void *)XtOffsetOf(hello_dir_config, to_file),
OR_ALL,
TAKE1,
"File containing hello message, absolute or server root relative."
},
With this setup, both HelloToFile /etc/motd and HelloToFile conf/hello.conf would work in a manner consistent with other Apache directives.
Accessing Other Modules' Configuration Information Show Contents Go to Top Previous Page Next PageAlthough it violates the principles of code encapsulation, there's no reason that one module can't access another module's configuration information. The module simply calls ap_get_module_config() with the address of the other module's module table in order to obtain the desired configuration information. You'll need to know the correct data type for the configuration data in order to do anything useful with it, of course.
If you happen to have a C module that needs to tap into the PerlSetVar configuration, you can do so by following this example:
#include "modules/perl/mod_perl.h"
perl_dir_config *c = (perl_dir_config *)
ap_get_module_config(r->per_dir_config, &perl_module);
table *perl_vars = c->vars;
mod_perl 's per-directory configuration data is simply an Apache
table. You can access the PerlSetVar keys and values with ap_table_get():
char *value = ap_table_get(perl_vars, "GuestbookFile");
Before interacting with another module, it is wise to determine if the module has been configured with the server. There are a few functions that can be used to find out if a module is accessible:
module *ap_find_linked_module (const char *name)
This function will walk the internal list of loaded modules, comparing name
with the name field of each module structure. If
a match is found, a pointer to the module structure is returned,
NULL otherwise. The IfModule configuration directive
is implemented using this function. Example:
if(ap_find_linked_module("mod_proxy.c")) {
/* mod_proxy is loaded */
}
int ap_exists_config_define (char *name)
Apache Version 1.3.1 added a -D command line switch that can be
used to pass the server parameter names for conditional configuration with
the If-Define directive. These names exist for the lifetime of the
server and can be accessed at any time using the ap_ exists_config_define()
function. For example, both Stronghold and mod_ssl's module
structures are defined in a file named mod_ssl.c, so ap_find_linked_module()
cannot be used to differentiate between the two. However, mod_ssl
passes a -DSSL parameter to the server which can be tested instead:
if(ap_exists_config_define("SSL")) {
/* mod_ssl started the server with -DSSL */
}
else {
...
}
Footnotes 1 The name XtOffsetOf() betrays this macro's origins.
It was cut and pasted from the X Windows source code! Show Contents Go to Top Previous Page Next Page Copyright © 1999 by O'Reilly & Associates, Inc. |