httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From r..@covalent.net
Subject Re: Add hook to get server read.
Date Fri, 12 May 2000 13:38:35 GMT

Okay, this patch is a bit smaller and it should be much easier to
understand.  A lot of it is the same as the original patch, and the
concept and reason for this patch are the same.  The basic flow for this
code is:  (Use ifmodule as an example, most others will follow this style)

    A directive is read from the file and located in a module
    if found and EXEC_ON_READ is set
        execute_now is called, which calls invoke_cmd which in turn calls
        start_ifmod
            If the expression evaluates to TRUE
                call ap_build_cont_config to build a config tree for this
	        container    
                    in ap_build_cont_config, ap_build_config_sub is used
                    unti either an error occurs or we hit the end of the
                    current container.
                Set *(ap_directive_t **)dummy to the new sub_tree, return
                NULL
                if there has been an error we return the error and 
                sub_tree is set to NULL
            If the expression evaluates to FALSE
                call ap_soak_end_container to read in the config file to
                the end of the current container
                set *(ap_directive_t **)dummy to NULL
                return NULL
                if there is an error in the soak_container stuff it will
                return and error, and we return that error.
         When we return to execute_now, we add the sub_tree to the current
         tree, and move to the end of the resulting tree.    
    If EXEC_ON_READ is not set, execution continues the way it always has.

Hopefully this makes it very clea how this stuff works.  If not, please
let me know.  The code is much cleaner now than it was yesterday.  :-)

Ryan


? src/build.log
? src/build.err
Index: src/CHANGES
===================================================================
RCS file: /home/cvs/apache-2.0/src/CHANGES,v
retrieving revision 1.109
diff -u -d -b -w -u -r1.109 CHANGES
--- src/CHANGES	2000/05/11 20:25:38	1.109
+++ src/CHANGES	2000/05/12 16:33:31
@@ -1,4 +1,12 @@
 Changes with Apache 2.0a4
+  *) Add the ability to hook into the config file reading phase.  Basically
+     if a directive is specified EXEC_ON_READ, then when that directive is
+     read from the config file, the assocaited function is executed.  This
+     should only be used for those directives that must muck with HOW the
+     server INTERPRETS the config.  This should not be used for directives
+     that re-order or replace items in the config tree.  Those changes should
+     be made in the pre-config step.
+     [Ryan Bloom]
 
   *) Add mod_example to the build system.
      [Tony Finch]
Index: src/include/http_config.h
===================================================================
RCS file: /home/cvs/apache-2.0/src/include/http_config.h,v
retrieving revision 1.18
diff -u -d -b -w -u -r1.18 http_config.h
--- src/include/http_config.h	2000/04/26 07:14:30	1.18
+++ src/include/http_config.h	2000/05/12 16:33:32
@@ -135,6 +135,7 @@
 #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
@@ -144,6 +145,16 @@
 
 #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
@@ -155,6 +166,7 @@
     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 */
@@ -304,16 +316,6 @@
 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);
 
@@ -334,7 +336,13 @@
 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);
Index: src/main/http_config.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/main/http_config.c,v
retrieving revision 1.45
diff -u -d -b -w -u -r1.45 http_config.c
--- src/main/http_config.c	2000/05/09 22:46:03	1.45
+++ src/main/http_config.c	2000/05/12 16:33:39
@@ -831,15 +831,20 @@
     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;
@@ -857,9 +862,24 @@
 	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);
 
@@ -900,6 +920,38 @@
     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)
 {
@@ -956,7 +1008,7 @@
 }
 
 
-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)
 {
@@ -967,9 +1019,9 @@
 
     *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,
 				     &current, &curr_parent);
 	if (errmsg != NULL)
 	    return errmsg;
@@ -1064,6 +1116,55 @@
     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
@@ -1112,7 +1213,6 @@
     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;
@@ -1123,11 +1223,11 @@
     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) {
@@ -1136,7 +1236,7 @@
         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)
@@ -1171,7 +1271,8 @@
 	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);
 
@@ -1228,7 +1329,8 @@
 
             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);
 
Index: src/main/http_core.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/main/http_core.c,v
retrieving revision 1.56
diff -u -d -b -w -u -r1.56 http_core.c
--- src/main/http_core.c	2000/05/11 02:32:05	1.56
+++ src/main/http_core.c	2000/05/12 16:33:39
@@ -1554,11 +1554,20 @@
     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, 
+                                      &current, &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)
 {
@@ -1593,13 +1602,21 @@
     }
 
     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, 
+                                      &current, &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 */
 
@@ -1681,6 +1698,7 @@
 	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;
 }
 
@@ -1692,6 +1710,7 @@
     }
 
     ap_clear_module_list();
+    *(ap_directive_t **)dummy = NULL;
     return NULL;
 }
 
@@ -2162,9 +2181,9 @@
 { "<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 "
@@ -2245,10 +2264,10 @@
   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" },
Index: src/modules/standard/mod_so.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/modules/standard/mod_so.c,v
retrieving revision 1.14
diff -u -d -b -w -u -r1.14 mod_so.c
--- src/modules/standard/mod_so.c	2000/04/27 04:15:48	1.14
+++ src/modules/standard/mod_so.c	2000/05/12 16:33:40
@@ -230,6 +230,12 @@
     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 
@@ -349,7 +355,7 @@
 #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"},



Mime
View raw message