Return-Path: Delivered-To: apmail-new-httpd-archive@apache.org Received: (qmail 98659 invoked by uid 500); 11 May 2000 20:52:26 -0000 Mailing-List: contact new-httpd-help@apache.org; run by ezmlm Precedence: bulk X-No-Archive: yes Reply-To: new-httpd@apache.org list-help: list-unsubscribe: list-post: Delivered-To: mailing list new-httpd@apache.org Received: (qmail 98648 invoked from network); 11 May 2000 20:52:25 -0000 X-Authentication-Warning: koj.rkbloom.net: rbb owned process doing -bs Date: Thu, 11 May 2000 13:54:10 -0400 (EDT) From: rbb@covalent.net X-Sender: rbb@koj.rkbloom.net To: new-httpd@apache.org Subject: Add hook to get server read. Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII X-Spam-Rating: locus.apache.org 1.6.2 0/1000/N Okay, so I am posting this because it is a relatively large patch. I would like to commit this ASAP before too much other stuff changes. Basically, this patch allows module authors to hook into the config file read stage. Module authors declare that their variables should be EXEC_ON_READ, and when that directive is read, the associated function is called. This should only be done for directives that modify how the server interprets the config, not for modifying the tree itself. For example, in this patch, I have got LoadModule, AddModule, ClearModuleList, IfModule and IfDefine as EXEC_ON_READ. The Load/Add/Clear Module stuff should just make sense. If the modules aren't included in the server, the server doesn't understand all of the directives. The IfModule and IfDefine are EXEC_ON_READ because We really don't want the things inside those containers in the config if the statement is false. This is also how mod_perl will hook things for the directive. Basically, will be EXEC_ON_READ, so when this is hit, mod_perl takes over and reads from the config file until , and this whole section of the file _should_ be put into the tree as raw text. Then, during the walk phase, mod_perl converts the perl code into actual Apache directives. If you want external config parsers, then your whole config becomes: ReadExternalConfig "foobar" And the ReadExternalConfig directive would be EXEC_ON_READ. This directive is not implemented anywhere, but it is allowed for since some people seem to like this approach. Please, make comments quickly, because I am likely to commit quickly if too many other changes start going into the tree. Ryan ? src/main/.http_core.c.swp 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/11 20:46:36 @@ -1,8 +1,21 @@ +<<<<<<< CHANGES +Changes with Apache 2.0a4-dev + *) 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] + +======= Changes with Apache 2.0a4 *) Add mod_example to the build system. [Tony Finch] +>>>>>>> 1.109 *) APR: Add ap_xlate_conv_byte() to convert one char between single- byte character sets. [Jeff Trawick] 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/11 20:46:36 @@ -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 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,7 @@ 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_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/11 20:46:41 @@ -831,15 +831,80 @@ return mconfig; } +static const char *execute_now(char *cmd_line, const char *args, cmd_parms *parms, + ap_pool_t *p, ap_pool_t *ptempi, + ap_directive_t **sub_tree, ap_directive_t *parent); + +static 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) +{ + const char *args; + char l[MAX_STRING_LEN]; + char *cmd_name; + ap_directive_t *newdir; + + while(!(ap_cfg_getline(l, MAX_STRING_LEN, parms->config_file))) { +#if RESOLVE_ENV_PER_TOKEN + args = l; +#else + args = ap_resolve_env(parms->temp_pool, l); +#endif + cmd_name = ap_getword_conf(parms->pool, &args); + if (cmd_name[0] == '<') { + if (cmd_name[1] != '/') { + (*current) = ap_add_node(curr_parent, *current, newdir, 1); + } + else { + char *bracket = ap_pstrcat(p, orig_directive + 1, ">", NULL); + + if (cmd_name[strlen(cmd_name) - 1] != '>') { + return ap_pstrcat(p, cmd_name, + "> directive missing closing '>'", NULL); + } + + if (strcasecmp(cmd_name + 2, + bracket) != 0) { + return ap_pstrcat(p, "Expected but saw ", + cmd_name, NULL); + } + + /* done with this section; move up a level */ + if (*curr_parent == NULL) { + /* We are just building a sub tree, so once we hit this + * we should return. + */ + return NULL; + } + *current = *curr_parent; + *curr_parent = (*current)->parent; + } + } + else { + newdir = ap_pcalloc(p, sizeof(ap_directive_t)); + newdir->filename = parms->config_file->name; + newdir->line_num = parms->config_file->line_number; + newdir->directive = cmd_name; + newdir->args = ap_pstrdup(p, args); + + *current = ap_add_node(curr_parent, *current, newdir, 0); + } + } +} + 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 +922,24 @@ return NULL; } + if (cmd = ap_find_command_in_modules(cmd_name, &mod)) { + 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); @@ -956,7 +1036,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 +1047,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, ¤t, &curr_parent); if (errmsg != NULL) return errmsg; @@ -1064,6 +1144,71 @@ 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] == '/') { + char *bracket = '\0'; + if (strcasecmp(cmd_name + 2, + directive + 1) != 0) { + return ap_pstrcat(cmd->pool, "Expected but saw ", + cmd_name, ">", NULL); + } + break; + } + else { + ap_soak_end_container(cmd, cmd_name); + } + } + } +} + +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 { + void *mconfig = ap_set_config_vectors(parms, + parms->server->lookup_defaults, mod); + const char *retval; + + retval = invoke_cmd(cmd, parms, mconfig, args); + if (retval == NULL) { + int one = 1; + if (*(int *)mconfig == 1) { + return ap_build_cont_config(p, ptemp, parms, sub_tree, &parent, cmd_line); + } + else { + ap_soak_end_container(parms, cmd_line); + return retval; + } + } + if (strcmp(retval, DECLINE_CMD) != 0) + return retval; + } +} /* This structure and the following functions are needed for the * table-based config file reading. They are passed to the @@ -1112,7 +1257,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 +1267,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 +1280,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 +1315,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 +1373,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/11 20:46:41 @@ -1539,6 +1539,7 @@ { char *endp = strrchr(arg, '>'); int not = (arg[0] == '!'); + int one = 1; module *found; if (endp == NULL) { @@ -1554,8 +1555,14 @@ found = ap_find_linked_module(arg); if ((!not && found) || (not && !found)) { - return ap_walk_config(cmd->directive->first_child, cmd, cmd->context); + *(int *)dummy = one; + return NULL; } + else { + one = 0; + *(int *)dummy = one; + return NULL; + } return NULL; } @@ -1578,6 +1585,7 @@ { char *endp; int defined; + int one = 1; int not = 0; endp = strrchr(arg, '>'); @@ -1593,10 +1601,15 @@ } defined = ap_exists_config_define(arg); - if ((!not && defined) || (not && !defined)) { - return ap_walk_config(cmd->directive->first_child, cmd, cmd->context); + *(int *)dummy = one; + return NULL; } + else { + one = 0; + *(int *)dummy = one; + return NULL; + } return NULL; } @@ -2162,9 +2175,9 @@ { "