Name

Per-Directory Merger

Example

As you can see, this merges the configuration from the base conditionally, depending on whether the new configuration specified an INHERIT option.

Once more, the only change in 2.0 is that pool has become apr_pool_t. See Example 21-6 for an excerpt from mod_env.c.

This function creates a new configuration into which it then copies the base vars table (a table of environment variable names and values). It then runs through the individual entries of the addv vars table, setting them in the new table. It does this rather than use overlay_tables() because overlay_tables() does not deal with duplicated keys. Then the addv configuration’s unsetenv (which is a space-separated list of environment variables to unset) unsets any variables specified to be unset for addv ’s server.

The 2.0 version of this function has a number of alterations, but on close inspection is actually very much the same, allowing for differences in function names and some rather radical restructuring:

static void *merge_env_dir_configs(apr_pool_t *p, void *basev, void *addv)
{
    env_dir_config_rec *base = basev;
    env_dir_config_rec *add = addv;
    env_dir_config_rec *res = apr_palloc(p, sizeof(*res));
    const apr_table_entry_t *elts;
    const apr_array_header_t *arr;
    int i;

    res->vars = apr_table_copy(p, base->vars);
    res->unsetenv = NULL;

    arr = apr_table_elts(add->unsetenv);
    elts = (const apr_table_entry_t *)arr->elts;

    for (i = 0; i < arr->nelts; ++i) {
        apr_table_unset(res->vars, elts[i].key);
    }

    arr = apr_table_elts(add->vars);
    elts = (const apr_table_entry_t *)arr->elts;

    for (i = 0; i < arr->nelts; ++i) {
        apr_table_setn(res->vars, elts[i].key, elts[i].val);
    }

    return res;
}