#define OR_UNSET 32
#define ACCESS_CONF 64
#define RSRC_CONF 128
+#define EXEC_ON_READ 256
#define OR_ALL (OR_LIMIT|OR_OPTIONS|OR_FILEINFO|OR_AUTHCFG|OR_INDEXES)
/* This can be returned by a function if they don't wish to handle
#define DECLINE_CMD "\a\b"
+/* Common structure for reading of config files / passwd files etc. */
+typedef struct {
+ int (*getch) (void *param); /* a getc()-like function */
+ void *(*getstr) (void *buf, size_t bufsiz, void *param); /* a fgets()-like function */
+ int (*close) (void *param); /* a close hander function */
+ void *param; /* the argument passed to getch/getstr/close */
+ const char *name; /* the filename / description */
+ unsigned line_number; /* current line number, starting at 1 */
+} configfile_t;
+
/*
* This structure is passed to a command which is being invoked,
* to carry a large variety of miscellaneous data which is all of
int override; /* Which allow-override bits are set */
int limited; /* Which methods are <Limit>ed */
+ configfile_t *config_file; /* Config file structure. */
ap_directive_t *directive; /* the directive specifying this command */
ap_pool_t *pool; /* Pool to allocate new storage in */
API_EXPORT(const char *) ap_find_module_name(module *m);
API_EXPORT(module *) ap_find_linked_module(const char *name);
-/* Common structure for reading of config files / passwd files etc. */
-typedef struct {
- int (*getch) (void *param); /* a getc()-like function */
- void *(*getstr) (void *buf, size_t bufsiz, void *param); /* a fgets()-like function */
- int (*close) (void *param); /* a close hander function */
- void *param; /* the argument passed to getch/getstr/close */
- const char *name; /* the filename / description */
- unsigned line_number; /* current line number, starting at 1 */
-} configfile_t;
-
/* Open a configfile_t as FILE, return open configfile_t struct pointer */
API_EXPORT(ap_status_t) ap_pcfg_openfile(configfile_t **, ap_pool_t *p, const char *name);
API_EXPORT(int) ap_cfg_closefile(configfile_t *cfp);
/* for implementing subconfigs and customized config files */
-API_EXPORT(const char *) ap_build_config(configfile_t *cfp,
+API_EXPORT(const char *) ap_soak_end_container(cmd_parms *cmd, char *directive);
+const char * ap_build_cont_config(ap_pool_t *p, ap_pool_t *temp_pool,
+ cmd_parms *parms,
+ ap_directive_t **current,
+ ap_directive_t **curr_parent,
+ char *orig_directive);
+API_EXPORT(const char *) ap_build_config(cmd_parms *parms,
ap_pool_t *conf_pool,
ap_pool_t *temp_pool,
ap_directive_t **conftree);
found = ap_find_linked_module(arg);
if ((!not && found) || (not && !found)) {
- return ap_walk_config(cmd->directive->first_child, cmd, cmd->context);
- }
+ ap_directive_t *parent = NULL;
+ ap_directive_t *current = NULL;
+ const char *retval;
- return NULL;
+ retval = ap_build_cont_config(cmd->pool, cmd->temp_pool, cmd,
+ ¤t, &parent, "<IfModule");
+ *(ap_directive_t **)dummy = current;
+ return retval;
+ }
+ else {
+ *(ap_directive_t **)dummy = NULL;
+ return ap_soak_end_container(cmd, "<IfModule");
+ }
}
API_EXPORT(int) ap_exists_config_define(char *name)
}
defined = ap_exists_config_define(arg);
-
if ((!not && defined) || (not && !defined)) {
- return ap_walk_config(cmd->directive->first_child, cmd, cmd->context);
- }
+ ap_directive_t *parent = NULL;
+ ap_directive_t *current = NULL;
+ const char *retval;
- return NULL;
+ retval = ap_build_cont_config(cmd->pool, cmd->temp_pool, cmd,
+ ¤t, &parent, "<IfDefine");
+ *(ap_directive_t **)dummy = current;
+ return retval;
+ }
+ else {
+ *(ap_directive_t **)dummy = NULL;
+ return ap_soak_end_container(cmd, "<IfDefine");
+ }
}
/* httpd.conf commands... beginning with the <VirtualHost> business */
return ap_pstrcat(cmd->pool, "Cannot add module via name '", arg,
"': not in list of loaded modules", NULL);
}
+ *(ap_directive_t **)dummy = NULL;
return NULL;
}
}
ap_clear_module_list();
+ *(ap_directive_t **)dummy = NULL;
return NULL;
}
{ "<LimitExcept", ap_limit_section, (void*)1, OR_ALL, RAW_ARGS,
"Container for authentication directives to be applied when any HTTP "
"method other than those specified is used to access the resource" },
-{ "<IfModule", start_ifmod, NULL, OR_ALL, TAKE1,
+{ "<IfModule", start_ifmod, NULL, EXEC_ON_READ | OR_ALL, TAKE1,
"Container for directives based on existance of specified modules" },
-{ "<IfDefine", start_ifdefine, NULL, OR_ALL, TAKE1,
+{ "<IfDefine", start_ifdefine, NULL, EXEC_ON_READ | OR_ALL, TAKE1,
"Container for directives based on existance of command line defines" },
{ "<DirectoryMatch", dirsection, (void*)1, RSRC_CONF, RAW_ARGS,
"Container for directives affecting resources located in the "
RSRC_CONF|ACCESS_CONF, TAKE1,
"How to work out the ServerName : Port when constructing URLs" },
/* TODO: RlimitFoo should all be part of mod_cgi, not in the core */
-{ "AddModule", add_module_command, NULL, RSRC_CONF, ITERATE,
+{ "AddModule", add_module_command, NULL, RSRC_CONF | EXEC_ON_READ, ITERATE,
"The name of a module" },
-{ "ClearModuleList", clear_module_list_command, NULL, RSRC_CONF, NO_ARGS,
- NULL },
+{ "ClearModuleList", clear_module_list_command, NULL, RSRC_CONF | EXEC_ON_READ,
+ NO_ARGS, NULL },
/* TODO: ListenBacklog in MPM */
{ "Include", include_config, NULL, (RSRC_CONF | ACCESS_CONF), TAKE1,
"Name of the config file to be included" },
moduleinfo *modie;
int i;
+ /* we need to setup this value for dummy to make sure that we don't try
+ * to add a non-existant tree into the build when we return to
+ * execute_now.
+ */
+ *(ap_directive_t **)dummy = NULL;
+
/*
* check for already existing module
* If it already exists, we have nothing to do
#endif /* NO_DLOPEN */
static const command_rec so_cmds[] = {
- { "LoadModule", load_module, NULL, RSRC_CONF, TAKE2,
+ { "LoadModule", load_module, NULL, RSRC_CONF | EXEC_ON_READ, TAKE2,
"a module name and the name of a shared object file to load it from"},
{ "LoadFile", load_file, NULL, RSRC_CONF, ITERATE,
"shared object file or library to load into the server at runtime"},
return mconfig;
}
+static const char *execute_now(char *cmd_line, const char *args, cmd_parms *parms,
+ ap_pool_t *p, ap_pool_t *ptemp,
+ ap_directive_t **sub_tree, ap_directive_t *parent);
+
static const char * ap_build_config_sub(ap_pool_t *p, ap_pool_t *temp_pool,
- const configfile_t *cfp,
- const char *l,
+ const char *l, cmd_parms *parms,
ap_directive_t **current,
ap_directive_t **curr_parent)
{
const char *args;
char *cmd_name;
ap_directive_t *newdir;
+ module *mod = top_module;
+ const command_rec *cmd;
if (*l == '#' || *l == '\0')
return NULL;
return NULL;
}
+ if ((cmd = ap_find_command_in_modules(cmd_name, &mod)) != NULL) {
+ if (cmd->req_override & EXEC_ON_READ) {
+ const char *retval;
+ ap_directive_t *sub_tree = NULL;
+
+ retval = execute_now(cmd_name, args, parms, p, temp_pool,
+ &sub_tree, *curr_parent);
+ (*current)->next = sub_tree;
+ while ((*current)->next != NULL) {
+ (*current) = (*current)->next;
+ }
+ return retval;
+ }
+ }
+
newdir = ap_pcalloc(p, sizeof(ap_directive_t));
- newdir->filename = cfp->name;
- newdir->line_num = cfp->line_number;
+ newdir->filename = parms->config_file->name;
+ newdir->line_num = parms->config_file->line_number;
newdir->directive = cmd_name;
newdir->args = ap_pstrdup(p, args);
return NULL;
}
+const char * ap_build_cont_config(ap_pool_t *p, ap_pool_t *temp_pool,
+ cmd_parms *parms,
+ ap_directive_t **current,
+ ap_directive_t **curr_parent,
+ char *orig_directive)
+{
+ char l[MAX_STRING_LEN];
+ char *bracket;
+ const char *retval;
+ ap_directive_t *conftree = NULL;
+
+ bracket = ap_pstrcat(p, orig_directive + 1, ">", NULL);
+ while(!(ap_cfg_getline(l, MAX_STRING_LEN, parms->config_file))) {
+ if ((strcasecmp(l + 2, bracket) == 0) &&
+ (*curr_parent == NULL)) {
+ break;
+ }
+ retval = ap_build_config_sub(p, temp_pool, l, parms, current,
+ curr_parent);
+ if (retval != NULL)
+ return retval;
+ if (conftree == NULL && curr_parent != NULL) {
+ conftree = *curr_parent;
+ }
+ if (conftree == NULL && current != NULL) {
+ conftree = *current;
+ }
+ }
+ *current = conftree;
+ return NULL;
+}
+
static const char *ap_walk_config_sub(const ap_directive_t *current,
cmd_parms *parms, void *config)
{
}
-API_EXPORT(const char *) ap_build_config(configfile_t *cfp,
+API_EXPORT(const char *) ap_build_config(cmd_parms *parms,
ap_pool_t *p, ap_pool_t *temp_pool,
ap_directive_t **conftree)
{
*conftree = NULL;
- while (!(ap_cfg_getline(l, MAX_STRING_LEN, cfp))) {
+ while (!(ap_cfg_getline(l, MAX_STRING_LEN, parms->config_file))) {
- errmsg = ap_build_config_sub(p, temp_pool, cfp, l,
+ errmsg = ap_build_config_sub(p, temp_pool, l, parms,
¤t, &curr_parent);
if (errmsg != NULL)
return errmsg;
return ap_make_full_path(p, ap_server_root, file);
}
+API_EXPORT(const char *) ap_soak_end_container(cmd_parms *cmd, char *directive)
+{
+ char l[MAX_STRING_LEN];
+ const char *args;
+ char *cmd_name;
+
+ while(!(ap_cfg_getline(l, MAX_STRING_LEN, cmd->config_file))) {
+#if RESOLVE_ENV_PER_TOKEN
+ args = l;
+#else
+ args = ap_resolve_env(cmd->temp_pool, l);
+#endif
+ cmd_name = ap_getword_conf(cmd->pool, &args);
+ if (cmd_name[0] == '<') {
+ if (cmd_name[1] == '/') {
+ cmd_name[strlen(cmd_name) - 1] = '\0';
+ if (strcasecmp(cmd_name + 2, directive + 1) != 0) {
+ return ap_pstrcat(cmd->pool, "Expected </",
+ directive + 1, "> but saw ",
+ cmd_name, ">", NULL);
+ }
+ break;
+ }
+ else {
+ ap_soak_end_container(cmd, cmd_name);
+ }
+ }
+ }
+ return NULL;
+}
+
+static const char *execute_now(char *cmd_line, const char *args, cmd_parms *parms,
+ ap_pool_t *p, ap_pool_t *ptemp,
+ ap_directive_t **sub_tree, ap_directive_t *parent)
+{
+ module *mod = top_module;
+ const command_rec *cmd;
+
+ if (!(cmd = ap_find_command_in_modules(cmd_line, &mod))) {
+ return ap_pstrcat(parms->pool, "Invalid command '",
+ cmd_line,
+ "', perhaps mis-spelled or defined by a module "
+ "not included in the server configuration",
+ NULL);
+ }
+ else {
+ return invoke_cmd(cmd, parms, sub_tree, args);
+ }
+}
/* This structure and the following functions are needed for the
* table-based config file reading. They are passed to the
cmd_parms parms;
arr_elts_param_t arr_parms;
ap_directive_t *conftree;
- configfile_t *cfp;
arr_parms.curr_idx = 0;
arr_parms.array = arr;
parms.server = s;
parms.override = (RSRC_CONF | OR_ALL) & ~(OR_AUTHCFG | OR_LIMIT);
- cfp = ap_pcfg_open_custom(p, "-c/-C directives",
+ parms.config_file = ap_pcfg_open_custom(p, "-c/-C directives",
&arr_parms, NULL,
arr_elts_getstr, arr_elts_close);
- errmsg = ap_build_config(cfp, p, ptemp, &conftree);
+ errmsg = ap_build_config(&parms, p, ptemp, &conftree);
if (errmsg == NULL)
errmsg = ap_walk_config(conftree, &parms, s->lookup_defaults);
if (errmsg) {
exit(1);
}
- ap_cfg_closefile(cfp);
+ ap_cfg_closefile(parms.config_file);
}
void ap_process_resource_config(server_rec *s, const char *fname, ap_pool_t *p, ap_pool_t *ptemp)
exit(1);
}
- errmsg = ap_build_config(cfp, p, ptemp, &conftree);
+ parms.config_file = cfp;
+ errmsg = ap_build_config(&parms, p, ptemp, &conftree);
if (errmsg == NULL)
errmsg = ap_walk_config(conftree, &parms, s->lookup_defaults);
dc = ap_create_per_dir_config(r->pool);
- errmsg = ap_build_config(f, r->pool, r->pool, &conftree);
+ parms.config_file = f;
+ errmsg = ap_build_config(&parms, r->pool, r->pool, &conftree);
if (errmsg == NULL)
errmsg = ap_walk_config(conftree, &parms, dc);