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
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 Page

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