]> granicus.if.org Git - apache/blob - server/config.c
Use the new command-handler initializer macros in mod_auth;
[apache] / server / config.c
1 /* ====================================================================
2  * The Apache Software License, Version 1.1
3  *
4  * Copyright (c) 2000 The Apache Software Foundation.  All rights
5  * reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in
16  *    the documentation and/or other materials provided with the
17  *    distribution.
18  *
19  * 3. The end-user documentation included with the redistribution,
20  *    if any, must include the following acknowledgment:
21  *       "This product includes software developed by the
22  *        Apache Software Foundation (http://www.apache.org/)."
23  *    Alternately, this acknowledgment may appear in the software itself,
24  *    if and wherever such third-party acknowledgments normally appear.
25  *
26  * 4. The names "Apache" and "Apache Software Foundation" must
27  *    not be used to endorse or promote products derived from this
28  *    software without prior written permission. For written
29  *    permission, please contact apache@apache.org.
30  *
31  * 5. Products derived from this software may not be called "Apache",
32  *    nor may "Apache" appear in their name, without prior written
33  *    permission of the Apache Software Foundation.
34  *
35  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46  * SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Apache Software Foundation.  For more
51  * information on the Apache Software Foundation, please see
52  * <http://www.apache.org/>.
53  *
54  * Portions of this software are based upon public domain software
55  * originally written at the National Center for Supercomputing Applications,
56  * University of Illinois, Urbana-Champaign.
57  */
58
59 /*
60  * http_config.c: once was auxillary functions for reading httpd's config
61  * file and converting filenames into a namespace
62  *
63  * Rob McCool 
64  * 
65  * Wall-to-wall rewrite for Apache... commands which are part of the
66  * server core can now be found next door in "http_core.c".  Now contains
67  * general command loop, and functions which do bookkeeping for the new
68  * Apache config stuff (modules and configuration vectors).
69  *
70  * rst
71  *
72  */
73
74 #define CORE_PRIVATE
75
76 #include "ap_config.h"
77 #include "apr_portable.h"
78 #include "apr_file_io.h"
79 #include "httpd.h"
80 #include "http_config.h"
81 #include "http_core.h"
82 #include "http_log.h"           /* for errors in parse_htaccess */
83 #include "http_request.h"       /* for default_handler (see invoke_handler) */
84 #include "http_main.h"
85 #include "http_vhost.h"
86 #include "util_cfgtree.h"
87
88 API_VAR_EXPORT const char *ap_server_argv0;
89
90 API_VAR_EXPORT const char *ap_server_root;
91
92 API_VAR_EXPORT ap_array_header_t *ap_server_pre_read_config;
93 API_VAR_EXPORT ap_array_header_t *ap_server_post_read_config;
94 API_VAR_EXPORT ap_array_header_t *ap_server_config_defines;
95
96 AP_HOOK_STRUCT(
97             AP_HOOK_LINK(header_parser)
98             AP_HOOK_LINK(pre_config)
99             AP_HOOK_LINK(post_config)
100             AP_HOOK_LINK(open_logs)
101             AP_HOOK_LINK(child_init)
102 )
103
104 AP_IMPLEMENT_HOOK_RUN_ALL(int,header_parser,
105                           (request_rec *r),(r),OK,DECLINED)
106 AP_IMPLEMENT_HOOK_VOID(pre_config,
107                        (ap_pool_t *pconf, ap_pool_t *plog, ap_pool_t *ptemp),
108                        (pconf,plog,ptemp))
109 AP_IMPLEMENT_HOOK_VOID(post_config,
110                        (ap_pool_t *pconf, ap_pool_t *plog, ap_pool_t *ptemp,
111                         server_rec *s),(pconf,plog,ptemp,s))
112 AP_IMPLEMENT_HOOK_VOID(open_logs,
113                        (ap_pool_t *pconf, ap_pool_t *plog, ap_pool_t *ptemp, 
114                         server_rec *s),(pconf,plog,ptemp,s))
115 AP_IMPLEMENT_HOOK_VOID(child_init,
116                        (ap_pool_t *pchild, server_rec *s),(pchild,s))
117
118 /****************************************************************
119  *
120  * We begin with the functions which deal with the linked list
121  * of modules which control just about all of the server operation.
122  */
123
124 /* total_modules is the number of modules that have been linked
125  * into the server.
126  */
127 static int total_modules = 0;
128 /* dynamic_modules is the number of modules that have been added
129  * after the pre-loaded ones have been set up. It shouldn't be larger
130  * than DYNAMIC_MODULE_LIMIT.
131  */
132 static int dynamic_modules = 0;
133 API_VAR_EXPORT module *top_module = NULL;
134 API_VAR_EXPORT module **ap_loaded_modules=NULL;
135
136 typedef int (*handler_func) (request_rec *);
137 typedef void *(*dir_maker_func) (ap_pool_t *, char *);
138 typedef void *(*merger_func) (ap_pool_t *, void *, void *);
139
140 /* Dealing with config vectors.  These are associated with per-directory,
141  * per-server, and per-request configuration, and have a void* pointer for
142  * each modules.  The nature of the structure pointed to is private to the
143  * module in question... the core doesn't (and can't) know.  However, there
144  * are defined interfaces which allow it to create instances of its private
145  * per-directory and per-server structures, and to merge the per-directory
146  * structures of a directory and its subdirectory (producing a new one in
147  * which the defaults applying to the base directory have been properly
148  * overridden).
149  */
150
151 #ifndef ap_get_module_config
152 API_EXPORT(void *) ap_get_module_config(void *conf_vector, module *m)
153 {
154     void **confv = (void **) conf_vector;
155     return confv[m->module_index];
156 }
157 #endif
158
159 #ifndef ap_set_module_config
160 API_EXPORT(void) ap_set_module_config(void *conf_vector, module *m, void *val)
161 {
162     void **confv = (void **) conf_vector;
163     confv[m->module_index] = val;
164 }
165 #endif
166
167 static void *create_empty_config(ap_pool_t *p)
168 {
169     void **conf_vector = (void **) ap_pcalloc(p, sizeof(void *) *
170                                     (total_modules + DYNAMIC_MODULE_LIMIT));
171     return (void *) conf_vector;
172 }
173
174 static void *create_default_per_dir_config(ap_pool_t *p)
175 {
176     void **conf_vector = (void **) ap_pcalloc(p, sizeof(void *) * (total_modules + DYNAMIC_MODULE_LIMIT));
177     module *modp;
178
179     for (modp = top_module; modp; modp = modp->next) {
180         dir_maker_func df = modp->create_dir_config;
181
182         if (df)
183             conf_vector[modp->module_index] = (*df) (p, NULL);
184     }
185
186     return (void *) conf_vector;
187 }
188
189 void *
190      ap_merge_per_dir_configs(ap_pool_t *p, void *base, void *new)
191 {
192     void **conf_vector = (void **) ap_palloc(p, sizeof(void *) * total_modules);
193     void **base_vector = (void **) base;
194     void **new_vector = (void **) new;
195     module *modp;
196
197     for (modp = top_module; modp; modp = modp->next) {
198         merger_func df = modp->merge_dir_config;
199         int i = modp->module_index;
200
201         if (df && new_vector[i])
202             conf_vector[i] = (*df) (p, base_vector[i], new_vector[i]);
203         else
204             conf_vector[i] = new_vector[i] ? new_vector[i] : base_vector[i];
205     }
206
207     return (void *) conf_vector;
208 }
209
210 static void *create_server_config(ap_pool_t *p, server_rec *s)
211 {
212     void **conf_vector = (void **) ap_pcalloc(p, sizeof(void *) * (total_modules + DYNAMIC_MODULE_LIMIT));
213     module *modp;
214
215     for (modp = top_module; modp; modp = modp->next) {
216         if (modp->create_server_config)
217             conf_vector[modp->module_index] = (*modp->create_server_config) (p, s);
218     }
219
220     return (void *) conf_vector;
221 }
222
223 static void merge_server_configs(ap_pool_t *p, void *base, void *virt)
224 {
225     /* Can reuse the 'virt' vector for the spine of it, since we don't
226      * have to deal with the moral equivalent of .htaccess files here...
227      */
228
229     void **base_vector = (void **) base;
230     void **virt_vector = (void **) virt;
231     module *modp;
232
233     for (modp = top_module; modp; modp = modp->next) {
234         merger_func df = modp->merge_server_config;
235         int i = modp->module_index;
236
237         if (!virt_vector[i])
238             virt_vector[i] = base_vector[i];
239         else if (df)
240             virt_vector[i] = (*df) (p, base_vector[i], virt_vector[i]);
241     }
242 }
243
244 void *ap_create_request_config(ap_pool_t *p)
245 {
246     return create_empty_config(p);
247 }
248
249 void *ap_create_conn_config(ap_pool_t *p)
250 {
251     return create_empty_config(p);
252 }
253
254 CORE_EXPORT(void *) ap_create_per_dir_config(ap_pool_t *p)
255 {
256     return create_empty_config(p);
257 }
258
259 /*
260  * For speed/efficiency we generate a compact list of all the handlers
261  * and wildcard handlers.  This means we won't have to scan the entire
262  * module list looking for handlers... where we'll find a whole whack
263  * of NULLs.
264  */
265 typedef struct {
266     handler_rec hr;
267     size_t len;
268 } fast_handler_rec;
269
270 static fast_handler_rec *handlers;
271 static fast_handler_rec *wildhandlers;
272
273 static void init_handlers(ap_pool_t *p)
274 {
275     module *modp;
276     int nhandlers = 0;
277     int nwildhandlers = 0;
278     const handler_rec *handp;
279     fast_handler_rec *ph, *pw;
280     const char *starp;
281
282     for (modp = top_module; modp; modp = modp->next) {
283         if (!modp->handlers)
284             continue;
285         for (handp = modp->handlers; handp->content_type; ++handp) {
286             if (ap_strchr_c(handp->content_type, '*')) {
287                 nwildhandlers ++;
288             } else {
289                 nhandlers ++;
290             }
291         }
292     }
293     ph = handlers = ap_palloc(p, sizeof(*ph)*(nhandlers + 1));
294     pw = wildhandlers = ap_palloc(p, sizeof(*pw)*(nwildhandlers + 1));
295     for (modp = top_module; modp; modp = modp->next) {
296         if (!modp->handlers)
297             continue;
298         for (handp = modp->handlers; handp->content_type; ++handp) {
299             if ((starp = ap_strchr_c(handp->content_type, '*'))) {
300                 pw->hr.content_type = handp->content_type;
301                 pw->hr.handler = handp->handler;
302                 pw->len = starp - handp->content_type;
303                 pw ++;
304             } else {
305                 ph->hr.content_type = handp->content_type;
306                 ph->hr.handler = handp->handler;
307                 ph->len = strlen(handp->content_type);
308                 ph ++;
309             }
310         }
311     }
312     pw->hr.content_type = NULL;
313     pw->hr.handler = NULL;
314     ph->hr.content_type = NULL;
315     ph->hr.handler = NULL;
316 }
317
318 int ap_invoke_handler(request_rec *r)
319 {
320     fast_handler_rec *handp;
321     const char *handler;
322     const char *p;
323     size_t handler_len;
324     int result = HTTP_INTERNAL_SERVER_ERROR;
325
326     if (r->handler) {
327         handler = r->handler;
328         handler_len = strlen(handler);
329     }
330     else {
331         handler = r->content_type ? r->content_type : ap_default_type(r);
332         if ((p = ap_strchr_c(handler, ';')) != NULL) {
333             /* MIME type arguments */
334             while (p > handler && p[-1] == ' ')
335                 --p;            /* strip trailing spaces */
336             handler_len = p - handler;
337         }
338         else {
339             handler_len = strlen(handler);
340         }
341     }
342
343     /* Pass one --- direct matches */
344
345     for (handp = handlers; handp->hr.content_type; ++handp) {
346         if (handler_len == handp->len
347             && !strncmp(handler, handp->hr.content_type, handler_len)) {
348             result = (*handp->hr.handler) (r);
349
350             if (result != DECLINED)
351                 return result;
352         }
353     }
354
355     /* Pass two --- wildcard matches */
356
357     for (handp = wildhandlers; handp->hr.content_type; ++handp) {
358         if (handler_len >= handp->len
359             && !strncmp(handler, handp->hr.content_type, handp->len)) {
360             result = (*handp->hr.handler) (r);
361
362             if (result != DECLINED)
363                 return result;
364          }
365     }
366
367     if (result == HTTP_INTERNAL_SERVER_ERROR && r->handler && r->filename) {
368         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
369             "handler \"%s\" not found for: %s", r->handler, r->filename);
370     }
371     return HTTP_INTERNAL_SERVER_ERROR;
372 }
373
374 API_EXPORT(void) ap_register_hooks(module *m)
375     {
376     if(m->register_hooks)
377         {
378         if(getenv("SHOW_HOOKS"))
379             {
380             printf("Registering hooks for %s\n",m->name);
381             ap_debug_module_hooks=1;
382             }
383         ap_debug_module_name=m->name;
384         m->register_hooks();
385         }
386     }
387
388 /* One-time setup for precompiled modules --- NOT to be done on restart */
389
390 API_EXPORT(void) ap_add_module(module *m)
391 {
392     /* This could be called from an AddModule httpd.conf command,
393      * after the file has been linked and the module structure within it
394      * teased out...
395      */
396
397     if (m->version != MODULE_MAGIC_NUMBER_MAJOR) {
398         ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
399                      "%s: module \"%s\" is not compatible with this "
400                      "version of Apache.", ap_server_argv0, m->name);
401         ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "Please contact the vendor for the correct version.");
402         exit(1);
403     }
404
405     if (m->next == NULL) {
406         m->next = top_module;
407         top_module = m;
408     }
409     if (m->module_index == -1) {
410         m->module_index = total_modules++;
411         dynamic_modules++;
412
413         if (dynamic_modules > DYNAMIC_MODULE_LIMIT) {
414             ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
415                          "%s: module \"%s\" could not be loaded, because"
416                          " the dynamic", ap_server_argv0, m->name);
417             ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
418                          "module limit was reached. Please increase "
419                          "DYNAMIC_MODULE_LIMIT and recompile.");
420             exit(1);
421         }
422     }
423
424     /* Some C compilers put a complete path into __FILE__, but we want
425      * only the filename (e.g. mod_includes.c). So check for path
426      * components (Unix and DOS), and remove them.
427      */
428
429     if (ap_strrchr_c(m->name, '/'))
430         m->name = 1 + ap_strrchr_c(m->name, '/');
431     if (ap_strrchr_c(m->name, '\\'))
432         m->name = 1 + ap_strrchr_c(m->name, '\\');
433
434 #ifdef _OSD_POSIX /* __FILE__="*POSIX(/home/martin/apache/src/modules/standard/mod_info.c)" */
435     /* We cannot fix the string in-place, because it's const */
436     if (m->name[strlen(m->name)-1]==')') {
437         char *tmp = strdup(m->name);    /* FIXME:memory leak, albeit a small one */
438         tmp[strlen(tmp)-1] = '\0';
439         m->name = tmp;
440     }
441 #endif /*_OSD_POSIX*/
442
443     /* FIXME: is this the right place to call this? */
444     ap_register_hooks(m);
445 }
446
447 /* 
448  * remove_module undoes what add_module did. There are some caveats:
449  * when the module is removed, its slot is lost so all the current
450  * per-dir and per-server configurations are invalid. So we should
451  * only ever call this function when you are invalidating almost
452  * all our current data. I.e. when doing a restart.
453  */
454
455 API_EXPORT(void) ap_remove_module(module *m)
456 {
457     module *modp;
458
459     modp = top_module;
460     if (modp == m) {
461         /* We are the top module, special case */
462         top_module = modp->next;
463         m->next = NULL;
464     }
465     else {
466         /* Not the top module, find use. When found modp will
467          * point to the module _before_ us in the list
468          */
469
470         while (modp && modp->next != m) {
471             modp = modp->next;
472         }
473         if (!modp) {
474             /* Uh-oh, this module doesn't exist */
475             ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, NULL,
476                 "Cannot remove module %s: not found in module list",
477                 m->name);
478             return;
479         }
480         /* Eliminate us from the module list */
481         modp->next = modp->next->next;
482     }
483
484     m->module_index = -1;       /* simulate being unloaded, should
485                                  * be unnecessary */
486     dynamic_modules--;
487     total_modules--;
488 }
489
490 API_EXPORT(void) ap_add_loaded_module(module *mod)
491 {
492     module **m;
493
494     /* 
495      *  Add module pointer to top of chained module list 
496      */
497     ap_add_module(mod);
498
499     /* 
500      *  And module pointer to list of loaded modules 
501      *
502      *  Notes: 1. ap_add_module() would already complain if no more space
503      *            exists for adding a dynamically loaded module
504      *         2. ap_add_module() accepts double inclusion, so we have
505      *            to accept this, too.
506      */
507     for (m = ap_loaded_modules; *m != NULL; m++)
508         ;
509     *m++ = mod;
510     *m = NULL;
511 }
512
513 API_EXPORT(void) ap_remove_loaded_module(module *mod)
514 {
515     module **m;
516     module **m2;
517     int done;
518
519     /* 
520      *  Remove module pointer from chained module list 
521      */
522     ap_remove_module(mod);
523
524     /* 
525      *  Remove module pointer from list of loaded modules
526      *
527      *  Note: 1. We cannot determine if the module was successfully
528      *           removed by ap_remove_module().
529      *        2. We have not to complain explicity when the module
530      *           is not found because ap_remove_module() did it
531      *           for us already.
532      */
533     for (m = m2 = ap_loaded_modules, done = 0; *m2 != NULL; m2++) {
534         if (*m2 == mod && done == 0)
535             done = 1;
536         else
537             *m++ = *m2;
538     }
539     *m = NULL;
540 }
541
542 API_EXPORT(void) ap_setup_prelinked_modules(process_rec *process)
543 {
544     module **m;
545     module **m2;
546
547     ap_global_hook_pool=process->pconf;
548
549     /*
550      *  Initialise total_modules variable and module indices
551      */
552     total_modules = 0;
553     for (m = ap_preloaded_modules; *m != NULL; m++)
554         (*m)->module_index = total_modules++;
555
556     /* 
557      *  Initialise list of loaded modules
558      */
559     ap_loaded_modules = (module **)ap_palloc(process->pool,
560         sizeof(module *)*(total_modules+DYNAMIC_MODULE_LIMIT+1));
561     if (ap_loaded_modules == NULL) {
562         ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
563                      "Ouch!  Out of memory in ap_setup_prelinked_modules()!");
564     }
565     for (m = ap_preloaded_modules, m2 = ap_loaded_modules; *m != NULL; )
566         *m2++ = *m++;
567     *m2 = NULL;
568
569     /*
570      *   Initialize chain of linked (=activate) modules
571      */
572     for (m = ap_prelinked_modules; *m != NULL; m++)
573         ap_add_module(*m);
574
575     ap_sort_hooks();
576 }
577
578 API_EXPORT(const char *) ap_find_module_name(module *m)
579 {
580     return m->name;
581 }
582
583 API_EXPORT(module *) ap_find_linked_module(const char *name)
584 {
585     module *modp;
586
587     for (modp = top_module; modp; modp = modp->next) {
588         if (strcmp(modp->name, name) == 0)
589             return modp;
590     }
591     return NULL;
592 }
593
594 /* Add a named module.  Returns 1 if module found, 0 otherwise.  */
595 API_EXPORT(int) ap_add_named_module(const char *name)
596 {
597     module *modp;
598     int i = 0;
599
600     for (modp = ap_loaded_modules[i]; modp; modp = ap_loaded_modules[++i]) {
601         if (strcmp(modp->name, name) == 0) {
602             /* Only add modules that are not already enabled.  */
603             if (modp->next == NULL) {
604                 ap_add_module(modp);
605             }
606             return 1;
607         }
608     }
609
610     return 0;
611 }
612
613 /* Clear the internal list of modules, in preparation for starting over. */
614 API_EXPORT(void) ap_clear_module_list()
615 {
616     module **m = &top_module;
617     module **next_m;
618
619     while (*m) {
620         next_m = &((*m)->next);
621         *m = NULL;
622         m = next_m;
623     }
624
625     /* This is required; so we add it always.  */
626     ap_add_named_module("http_core.c");
627 }
628
629 /*****************************************************************
630  *
631  * Resource, access, and .htaccess config files now parsed by a common
632  * command loop.
633  *
634  * Let's begin with the basics; parsing the line and
635  * invoking the function...
636  */
637
638 static const char *invoke_cmd(const command_rec *cmd, cmd_parms *parms,
639                               void *mconfig, const char *args)
640 {
641     char *w, *w2, *w3;
642     const char *errmsg;
643
644     if ((parms->override & cmd->req_override) == 0)
645         return ap_pstrcat(parms->pool, cmd->name, " not allowed here", NULL);
646
647     parms->info = cmd->cmd_data;
648     parms->cmd = cmd;
649
650     switch (cmd->args_how) {
651     case RAW_ARGS:
652 #ifdef RESOLVE_ENV_PER_TOKEN
653         args = ap_resolve_env(parms->pool,args);
654 #endif
655         return cmd->AP_RAW_ARGS(parms, mconfig, args);
656
657     case NO_ARGS:
658         if (*args != 0)
659             return ap_pstrcat(parms->pool, cmd->name, " takes no arguments",
660                            NULL);
661
662         return cmd->AP_NO_ARGS(parms, mconfig);
663
664     case TAKE1:
665         w = ap_getword_conf(parms->pool, &args);
666
667         if (*w == '\0' || *args != 0)
668             return ap_pstrcat(parms->pool, cmd->name, " takes one argument",
669                             cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
670
671         return cmd->AP_TAKE1(parms, mconfig, w);
672
673     case TAKE2:
674         w = ap_getword_conf(parms->pool, &args);
675         w2 = ap_getword_conf(parms->pool, &args);
676
677         if (*w == '\0' || *w2 == '\0' || *args != 0)
678             return ap_pstrcat(parms->pool, cmd->name, " takes two arguments",
679                             cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
680
681         return cmd->AP_TAKE2(parms, mconfig, w, w2);
682
683     case TAKE12:
684
685         w = ap_getword_conf(parms->pool, &args);
686         w2 = ap_getword_conf(parms->pool, &args);
687
688         if (*w == '\0' || *args != 0)
689             return ap_pstrcat(parms->pool, cmd->name, " takes 1-2 arguments",
690                             cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
691
692         return cmd->AP_TAKE2(parms, mconfig, w, *w2 ? w2 : NULL);
693
694     case TAKE3:
695
696         w = ap_getword_conf(parms->pool, &args);
697         w2 = ap_getword_conf(parms->pool, &args);
698         w3 = ap_getword_conf(parms->pool, &args);
699
700         if (*w == '\0' || *w2 == '\0' || *w3 == '\0' || *args != 0)
701             return ap_pstrcat(parms->pool, cmd->name, " takes three arguments",
702                             cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
703
704         return cmd->AP_TAKE3(parms, mconfig, w, w2, w3);
705
706     case TAKE23:
707
708         w = ap_getword_conf(parms->pool, &args);
709         w2 = ap_getword_conf(parms->pool, &args);
710         w3 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
711
712         if (*w == '\0' || *w2 == '\0' || *args != 0)
713             return ap_pstrcat(parms->pool, cmd->name,
714                             " takes two or three arguments",
715                             cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
716
717         return cmd->AP_TAKE3(parms, mconfig, w, w2, w3);
718
719     case TAKE123:
720
721         w = ap_getword_conf(parms->pool, &args);
722         w2 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
723         w3 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
724
725         if (*w == '\0' || *args != 0)
726             return ap_pstrcat(parms->pool, cmd->name,
727                             " takes one, two or three arguments",
728                             cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
729
730         return cmd->AP_TAKE3(parms, mconfig, w, w2, w3);
731
732     case TAKE13:
733
734         w = ap_getword_conf(parms->pool, &args);
735         w2 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
736         w3 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
737
738         if (*w == '\0' || (w2 && *w2 && !w3) || *args != 0)
739             return ap_pstrcat(parms->pool, cmd->name,
740                             " takes one or three arguments",
741                             cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
742
743         return cmd->AP_TAKE3(parms, mconfig, w, w2, w3);
744
745     case ITERATE:
746
747         while (*(w = ap_getword_conf(parms->pool, &args)) != '\0')
748             {
749             if ((errmsg = cmd->AP_TAKE1(parms, mconfig, w)))
750                 return errmsg;
751             }
752
753         return NULL;
754
755     case ITERATE2:
756
757         w = ap_getword_conf(parms->pool, &args);
758
759         if (*w == '\0' || *args == 0)
760             return ap_pstrcat(parms->pool, cmd->name,
761                             " requires at least two arguments",
762                             cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
763
764         while (*(w2 = ap_getword_conf(parms->pool, &args)) != '\0')
765             {
766             if ((errmsg = cmd->AP_TAKE2(parms, mconfig, w, w2)))
767                 return errmsg;
768             }
769
770         return NULL;
771
772     case FLAG:
773
774         w = ap_getword_conf(parms->pool, &args);
775
776         if (*w == '\0' || (strcasecmp(w, "on") && strcasecmp(w, "off")))
777             return ap_pstrcat(parms->pool, cmd->name, " must be On or Off",
778                             NULL);
779
780         return cmd->AP_FLAG(parms, mconfig, strcasecmp(w, "off") != 0);
781
782     default:
783
784         return ap_pstrcat(parms->pool, cmd->name,
785                     " is improperly configured internally (server bug)",
786                         NULL);
787     }
788 }
789
790 CORE_EXPORT(const command_rec *) ap_find_command(const char *name, const command_rec *cmds)
791 {
792     while (cmds->name)
793         if (!strcasecmp(name, cmds->name))
794             return cmds;
795         else
796             ++cmds;
797
798     return NULL;
799 }
800
801 CORE_EXPORT(const command_rec *) ap_find_command_in_modules(const char *cmd_name, module **mod)
802 {
803     const command_rec *cmdp;
804     module *modp;
805
806     for (modp = *mod; modp; modp = modp->next)
807         if (modp->cmds && (cmdp = ap_find_command(cmd_name, modp->cmds))) {
808             *mod = modp;
809             return cmdp;
810         }
811
812     return NULL;
813 }
814
815 CORE_EXPORT(void *) ap_set_config_vectors(cmd_parms *parms, void *config, module *mod)
816 {
817     void *mconfig = ap_get_module_config(config, mod);
818     void *sconfig = ap_get_module_config(parms->server->module_config, mod);
819
820     if (!mconfig && mod->create_dir_config) {
821         mconfig = (*mod->create_dir_config) (parms->pool, parms->path);
822         ap_set_module_config(config, mod, mconfig);
823     }
824
825     if (!sconfig && mod->create_server_config) {
826         sconfig = (*mod->create_server_config) (parms->pool, parms->server);
827         ap_set_module_config(parms->server->module_config, mod, sconfig);
828     }
829     return mconfig;
830 }
831
832 static const char *execute_now(char *cmd_line, const char *args, cmd_parms *parms, 
833                          ap_pool_t *p, ap_pool_t *ptemp,
834                          ap_directive_t **sub_tree, ap_directive_t *parent);
835
836 static const char * ap_build_config_sub(ap_pool_t *p, ap_pool_t *temp_pool,
837                                         const char *l, cmd_parms *parms,
838                                         ap_directive_t **current,
839                                         ap_directive_t **curr_parent)
840 {
841     const char *args;
842     char *cmd_name;
843     ap_directive_t *newdir;
844     module *mod = top_module;
845     const command_rec *cmd;
846
847     if (*l == '#' || *l == '\0')
848         return NULL;
849
850 #if RESOLVE_ENV_PER_TOKEN
851     args = l;
852 #else
853     args = ap_resolve_env(temp_pool, l); 
854 #endif
855     cmd_name = ap_getword_conf(p, &args);
856     if (*cmd_name == '\0') {
857         /* Note: this branch should not occur. An empty line should have
858          * triggered the exit further above.
859          */
860         return NULL;
861     }
862
863     if ((cmd = ap_find_command_in_modules(cmd_name, &mod)) != NULL) {
864         if (cmd->req_override & EXEC_ON_READ) {
865             const char *retval;
866             ap_directive_t *sub_tree = NULL;
867
868             retval = execute_now(cmd_name, args, parms, p, temp_pool, 
869                                  &sub_tree, *curr_parent);
870             if (*current) {
871                 (*current)->next = sub_tree;
872             }
873             else {
874                 (*current) = sub_tree;
875                 if (*curr_parent) {
876                     (*curr_parent)->first_child = (*current);
877                 }
878                 if (*current) {
879                     (*current)->parent = (*curr_parent);
880                 }
881             }
882             if (*current) {
883                 while ((*current)->next != NULL) {
884                     (*current) = (*current)->next;
885                     (*current)->parent = (*curr_parent);
886                 }
887             }
888             return retval;
889         }
890     }
891
892     newdir = ap_pcalloc(p, sizeof(ap_directive_t));
893     newdir->filename = parms->config_file->name;
894     newdir->line_num = parms->config_file->line_number;
895     newdir->directive = cmd_name;
896     newdir->args = ap_pstrdup(p, args);
897
898     if (cmd_name[0] == '<') {
899         if (cmd_name[1] != '/') {
900             (*current) = ap_add_node(curr_parent, *current, newdir, 1);
901         }
902         else if (*curr_parent == NULL) {
903             parms->err_directive = newdir;
904             return ap_pstrcat(p, cmd_name,
905                               " without matching <", cmd_name + 2,
906                               " section", NULL);
907         }
908         else {
909             char *bracket = cmd_name + strlen(cmd_name) - 1;
910
911             if (*bracket != '>') {
912                 return ap_pstrcat(p, cmd_name,
913                                   "> directive missing closing '>'", NULL);
914             }
915             *bracket = '\0';
916             if (strcasecmp(cmd_name + 2,
917                             (*curr_parent)->directive + 1) != 0) {
918                 return ap_pstrcat(p, "Expected </",
919                                   (*curr_parent)->directive + 1, "> but saw ",
920                                   cmd_name, ">", NULL);
921             }
922             *bracket = '>';
923
924             /* done with this section; move up a level */
925             *current = *curr_parent;
926             *curr_parent = (*current)->parent;
927         }
928     }
929     else {
930         *current = ap_add_node(curr_parent, *current, newdir, 0);
931     }
932
933     return NULL;
934 }
935
936 const char * ap_build_cont_config(ap_pool_t *p, ap_pool_t *temp_pool,
937                                         cmd_parms *parms,
938                                         ap_directive_t **current,
939                                         ap_directive_t **curr_parent,
940                                         char *orig_directive)
941 {
942     char l[MAX_STRING_LEN];
943     char *bracket;
944     const char *retval;
945     ap_directive_t *conftree = NULL;
946
947     bracket = ap_pstrcat(p, orig_directive + 1, ">", NULL);
948     while(!(ap_cfg_getline(l, MAX_STRING_LEN, parms->config_file))) {
949         if ((strcasecmp(l + 2, bracket) == 0) &&
950             (*curr_parent == NULL)) {
951             break;
952         } 
953         retval = ap_build_config_sub(p, temp_pool, l, parms, current, 
954                                      curr_parent);
955         if (retval != NULL)
956             return retval;
957         if (conftree == NULL && curr_parent != NULL) { 
958             conftree = *curr_parent;
959         }
960         if (conftree == NULL && current != NULL) {
961             conftree = *current;
962         }
963     }
964     *current = conftree;
965     return NULL;
966 }
967
968 static const char *ap_walk_config_sub(const ap_directive_t *current,
969                                       cmd_parms *parms, void *config)
970 {
971     module *mod = top_module;
972
973     while (1) {
974         const command_rec *cmd;
975
976         if (!(cmd = ap_find_command_in_modules(current->directive, &mod))) {
977             parms->err_directive = current;
978             return ap_pstrcat(parms->pool, "Invalid command '", 
979                               current->directive,
980                               "', perhaps mis-spelled or defined by a module "
981                               "not included in the server configuration",
982                               NULL);
983         }
984         else {
985             void *mconfig = ap_set_config_vectors(parms,config, mod);
986             const char *retval;
987
988             retval = invoke_cmd(cmd, parms, mconfig, current->args);
989             if (retval == NULL) {
990                 return NULL;
991             }
992             if (strcmp(retval, DECLINE_CMD) != 0) {
993                 /* If the directive in error has already been set, don't
994                  * replace it.  Otherwise, an error inside a container 
995                  * will be reported as occuring on the first line of the
996                  * container.
997                  */
998                 if (!parms->err_directive) {
999                     parms->err_directive = current;
1000                 }
1001                 return retval;
1002             }
1003
1004             mod = mod->next;    /* Next time around, skip this one */
1005         }
1006     }
1007     /* NOTREACHED */
1008 }
1009
1010 API_EXPORT(const char *) ap_walk_config(ap_directive_t *current,
1011                                         cmd_parms *parms, void *config)
1012 {
1013     void *oldconfig = parms->context;
1014
1015     parms->context = config;
1016
1017     /* scan through all directives, executing each one */
1018     for (; current != NULL; current = current->next) {
1019         const char *errmsg;
1020
1021         parms->directive = current;
1022
1023         /* actually parse the command and execute the correct function */
1024         errmsg = ap_walk_config_sub(current, parms, config);
1025         if (errmsg != NULL) {
1026             /* restore the context (just in case) */
1027             parms->context = oldconfig;
1028             return errmsg;
1029         }
1030     }
1031
1032     parms->context = oldconfig;
1033     return NULL;
1034 }
1035
1036
1037 API_EXPORT(const char *) ap_build_config(cmd_parms *parms,
1038                                          ap_pool_t *p, ap_pool_t *temp_pool,
1039                                          ap_directive_t **conftree)
1040 {
1041     ap_directive_t *current = *conftree;
1042     ap_directive_t *curr_parent = NULL;
1043     char l[MAX_STRING_LEN];
1044     const char *errmsg;
1045
1046     if (current != NULL) {
1047         while (current->next) {
1048             current = current->next;
1049         }
1050     }
1051
1052     while (!(ap_cfg_getline(l, MAX_STRING_LEN, parms->config_file))) {
1053
1054         errmsg = ap_build_config_sub(p, temp_pool, l, parms,
1055                                      &current, &curr_parent);
1056         if (errmsg != NULL)
1057             return errmsg;
1058
1059         if (*conftree == NULL && curr_parent != NULL) { 
1060             *conftree = curr_parent;
1061         }
1062         if (*conftree == NULL && current != NULL) {
1063             *conftree = current;
1064         }
1065     }
1066
1067     if (curr_parent != NULL) {
1068         errmsg = "";
1069         while (curr_parent != NULL) {
1070             errmsg = ap_psprintf(p, "%s%s%s:%u: %s> was not closed.",
1071                                  errmsg,
1072                                  *errmsg == '\0' ? "" : "\n",
1073                                  curr_parent->filename,
1074                                  curr_parent->line_num,
1075                                  curr_parent->directive);
1076             curr_parent = curr_parent->parent;
1077         }
1078         return errmsg;
1079     }
1080
1081     return NULL;
1082 }
1083
1084 /*
1085  * Generic command functions...
1086  */
1087
1088 API_EXPORT_NONSTD(const char *) ap_set_string_slot(cmd_parms *cmd,
1089                                                    void *struct_ptr,
1090                                                    const char *arg)
1091 {
1092     /* This one's pretty generic... */
1093
1094     int offset = (int) (long) cmd->info;
1095     *(const char **) ((char *)struct_ptr + offset) = arg;
1096     return NULL;
1097 }
1098
1099 API_EXPORT_NONSTD(const char *) ap_set_string_slot_lower(cmd_parms *cmd,
1100                                                          void *struct_ptr,
1101                                                          const char *arg_)
1102 {
1103     /* This one's pretty generic... */
1104     char *arg=ap_pstrdup(cmd->pool,arg_);
1105
1106     int offset = (int) (long) cmd->info;
1107     ap_str_tolower(arg);
1108     *(char **) ((char *)struct_ptr + offset) = arg;
1109     return NULL;
1110 }
1111
1112 API_EXPORT_NONSTD(const char *) ap_set_flag_slot(cmd_parms *cmd,
1113                                                  void *struct_ptr_v, int arg)
1114 {
1115     /* This one's pretty generic too... */
1116
1117     int offset = (int) (long) cmd->info;
1118     char *struct_ptr = (char *)struct_ptr_v;
1119     *(int *) (struct_ptr + offset) = arg ? 1 : 0;
1120     return NULL;
1121 }
1122
1123 API_EXPORT_NONSTD(const char *) ap_set_file_slot(cmd_parms *cmd, char *struct_ptr, 
1124                                                  const char *arg)
1125 {
1126     /* Prepend server_root to relative arg.
1127        This allows .htaccess to be independent of server_root,
1128        so the server can be moved or mirrored with less pain.  */
1129     char *p;
1130     int offset = (int) (long) cmd->info;
1131     if (ap_os_is_path_absolute(arg))
1132         p = ap_pstrdup(cmd->pool, arg);
1133     else
1134         p = ap_make_full_path(cmd->pool, ap_server_root, arg);
1135     *(char **) (struct_ptr + offset) = p;
1136     return NULL;
1137 }
1138
1139 /*****************************************************************
1140  *
1141  * Reading whole config files...
1142  */
1143
1144 static cmd_parms default_parms =
1145 {NULL, 0, -1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
1146
1147 API_EXPORT(const char *) ap_server_root_relative(ap_pool_t *p, const char *file)
1148 {
1149     if(ap_os_is_path_absolute(file))
1150         return file;
1151     return ap_make_full_path(p, ap_server_root, file);
1152 }
1153
1154 API_EXPORT(const char *) ap_soak_end_container(cmd_parms *cmd, char *directive)
1155 {
1156     char l[MAX_STRING_LEN];
1157     const char *args;
1158     char *cmd_name;
1159
1160     while(!(ap_cfg_getline(l, MAX_STRING_LEN, cmd->config_file))) {
1161 #if RESOLVE_ENV_PER_TOKEN
1162         args = l;
1163 #else
1164         args = ap_resolve_env(cmd->temp_pool, l);
1165 #endif
1166         cmd_name = ap_getword_conf(cmd->pool, &args);
1167         if (cmd_name[0] == '<') {
1168             if (cmd_name[1] == '/') {
1169                 cmd_name[strlen(cmd_name) - 1] = '\0';
1170                 if (strcasecmp(cmd_name + 2, directive + 1) != 0) {
1171                     return ap_pstrcat(cmd->pool, "Expected </",
1172                                       directive + 1, "> but saw ",
1173                                       cmd_name, ">", NULL);
1174                 }
1175                 break;
1176             }
1177             else {
1178                 ap_soak_end_container(cmd, cmd_name);
1179             }
1180         }
1181     }
1182     return NULL;
1183 }
1184
1185 static const char *execute_now(char *cmd_line, const char *args, cmd_parms *parms, 
1186                          ap_pool_t *p, ap_pool_t *ptemp, 
1187                          ap_directive_t **sub_tree, ap_directive_t *parent)
1188 {
1189     module *mod = top_module;
1190     const command_rec *cmd;
1191
1192     if (!(cmd = ap_find_command_in_modules(cmd_line, &mod))) {
1193         return ap_pstrcat(parms->pool, "Invalid command '", 
1194                           cmd_line,
1195                           "', perhaps mis-spelled or defined by a module "
1196                           "not included in the server configuration",
1197                           NULL);
1198     }
1199     else {
1200         return invoke_cmd(cmd, parms, sub_tree, args);
1201     }
1202 }
1203
1204 /* This structure and the following functions are needed for the
1205  * table-based config file reading. They are passed to the
1206  * cfg_open_custom() routine.
1207  */
1208
1209 /* Structure to be passed to cfg_open_custom(): it contains an
1210  * index which is incremented from 0 to nelts on each call to
1211  * cfg_getline() (which in turn calls arr_elts_getstr())
1212  * and an ap_array_header_t pointer for the string array.
1213  */
1214 typedef struct {
1215     ap_array_header_t *array;
1216     int curr_idx;
1217 } arr_elts_param_t;
1218
1219
1220 /* arr_elts_getstr() returns the next line from the string array. */
1221 static void *arr_elts_getstr(void *buf, size_t bufsiz, void *param)
1222 {
1223     arr_elts_param_t *arr_param = (arr_elts_param_t *) param;
1224
1225     /* End of array reached? */
1226     if (++arr_param->curr_idx > arr_param->array->nelts)
1227         return NULL;
1228
1229     /* return the line */
1230     ap_cpystrn(buf, ((char **) arr_param->array->elts)[arr_param->curr_idx - 1], bufsiz);
1231
1232     return buf;
1233 }
1234
1235
1236 /* arr_elts_close(): dummy close routine (makes sure no more lines can be read) */
1237 static int arr_elts_close(void *param)
1238 {
1239     arr_elts_param_t *arr_param = (arr_elts_param_t *) param;
1240     arr_param->curr_idx = arr_param->array->nelts;
1241     return 0;
1242 }
1243
1244 static void process_command_config(server_rec *s, ap_array_header_t *arr, 
1245                               ap_directive_t **conftree, ap_pool_t *p,
1246                               ap_pool_t *ptemp)
1247 {
1248     const char *errmsg;
1249     cmd_parms parms;
1250     arr_elts_param_t arr_parms;
1251
1252     arr_parms.curr_idx = 0;
1253     arr_parms.array = arr;
1254
1255     parms = default_parms;
1256     parms.pool = p;
1257     parms.temp_pool = ptemp;
1258     parms.server = s;
1259     parms.override = (RSRC_CONF | OR_ALL) & ~(OR_AUTHCFG | OR_LIMIT);
1260
1261     parms.config_file = ap_pcfg_open_custom(p, "-c/-C directives",
1262                               &arr_parms, NULL,
1263                               arr_elts_getstr, arr_elts_close);
1264
1265     errmsg = ap_build_config(&parms, p, ptemp, conftree);
1266     if (errmsg) {
1267         ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
1268                      "Syntax error in -C/-c directive:\n%s", errmsg);
1269         exit(1);
1270     }
1271
1272     ap_cfg_closefile(parms.config_file);
1273 }
1274
1275 void ap_process_resource_config(server_rec *s, const char *fname, 
1276                                 ap_directive_t **conftree, ap_pool_t *p, 
1277                                 ap_pool_t *ptemp)
1278 {
1279     cmd_parms parms;
1280     ap_finfo_t finfo;
1281     const char *errmsg;
1282     configfile_t *cfp;
1283
1284     fname = ap_server_root_relative(p, fname);
1285
1286     /* don't require conf/httpd.conf if we have a -C or -c switch */
1287     if((ap_server_pre_read_config->nelts || ap_server_post_read_config->nelts) &&
1288        !(strcmp(fname, ap_server_root_relative(p, SERVER_CONFIG_FILE)))) {
1289         if (ap_stat(&finfo, fname, p) != APR_SUCCESS)     
1290             return;
1291     }
1292
1293     /* GCC's initialization extensions are soooo nice here... */
1294
1295     parms = default_parms;
1296     parms.pool = p;
1297     parms.temp_pool = ptemp;
1298     parms.server = s;
1299     parms.override = (RSRC_CONF | OR_ALL) & ~(OR_AUTHCFG | OR_LIMIT);
1300
1301     if (ap_pcfg_openfile(&cfp, p, fname) != APR_SUCCESS) {
1302         ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
1303                      "%s: could not open document config file %s",
1304                      ap_server_argv0, fname);
1305         exit(1);
1306     }
1307
1308     parms.config_file = cfp;
1309
1310     errmsg = ap_build_config(&parms, p, ptemp, conftree);
1311
1312     if (errmsg != NULL) {
1313         ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
1314                      "Syntax error on line %d of %s:",
1315                      parms.err_directive->line_num, 
1316                      parms.err_directive->filename);
1317         ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1318                      "%s", errmsg);
1319         exit(1);
1320     }
1321
1322     ap_cfg_closefile(cfp);
1323 }
1324
1325 API_EXPORT(void)ap_process_config_tree(server_rec *s, ap_directive_t *conftree,
1326                                        ap_pool_t *p, ap_pool_t *ptemp)
1327 {
1328     const char *errmsg;
1329     cmd_parms parms;
1330
1331     parms = default_parms;
1332     parms.pool = p;
1333     parms.temp_pool = ptemp;
1334     parms.server = s;
1335     parms.override = (RSRC_CONF | OR_ALL) & ~(OR_AUTHCFG | OR_LIMIT);
1336
1337     errmsg = ap_walk_config(conftree, &parms, s->lookup_defaults);
1338     if (errmsg) {
1339         ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
1340                      "Syntax error on line %d of %s:",
1341                      parms.err_directive->line_num,
1342                      parms.err_directive->filename);
1343         ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1344                      "%s", errmsg);
1345         exit(1);
1346     }
1347 }
1348
1349 int ap_parse_htaccess(void **result, request_rec *r, int override,
1350                    const char *d, const char *access_name)
1351 {
1352     configfile_t *f = NULL;
1353     cmd_parms parms;
1354     char *filename = NULL;
1355     const struct htaccess_result *cache;
1356     struct htaccess_result *new;
1357     void *dc = NULL;
1358     ap_status_t status;
1359
1360 /* firstly, search cache */
1361     for (cache = r->htaccess; cache != NULL; cache = cache->next)
1362         if (cache->override == override && strcmp(cache->dir, d) == 0) {
1363             if (cache->htaccess != NULL)
1364                 *result = cache->htaccess;
1365             return OK;
1366         }
1367
1368     parms = default_parms;
1369     parms.override = override;
1370     parms.pool = r->pool;
1371     parms.temp_pool = r->pool;
1372     parms.server = r->server;
1373     parms.path = ap_pstrdup(r->pool, d);
1374
1375     /* loop through the access names and find the first one */
1376
1377     while (access_name[0]) {
1378         filename = ap_make_full_path(r->pool, d,
1379                                      ap_getword_conf(r->pool, &access_name));
1380         status = ap_pcfg_openfile(&f, r->pool, filename);
1381
1382         if (status == APR_SUCCESS) {
1383             const char *errmsg;
1384             ap_directive_t *conftree;
1385
1386             dc = ap_create_per_dir_config(r->pool);
1387
1388             parms.config_file = f;
1389             errmsg = ap_build_config(&parms, r->pool, r->pool, &conftree);
1390             if (errmsg == NULL)
1391                 errmsg = ap_walk_config(conftree, &parms, dc);
1392
1393             ap_cfg_closefile(f);
1394
1395             if (errmsg) {
1396                 ap_log_rerror(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, 0, r,
1397                               "%s: %s", filename, errmsg);
1398                 return HTTP_INTERNAL_SERVER_ERROR;
1399             }
1400             *result = dc;
1401             break;
1402         } else {
1403             ap_status_t cerr = ap_canonical_error(status);
1404
1405             if (cerr != APR_ENOENT && cerr != APR_ENOTDIR) {
1406                 ap_log_rerror(APLOG_MARK, APLOG_CRIT, status, r,
1407                               "%s pcfg_openfile: unable to check htaccess file, "
1408                               "ensure it is readable",
1409                               filename);
1410                 ap_table_setn(r->notes, "error-notes",
1411                               "Server unable to read htaccess file, denying "
1412                               "access to be safe");
1413                 return HTTP_FORBIDDEN;
1414             }
1415         }
1416     }
1417
1418 /* cache it */
1419     new = ap_palloc(r->pool, sizeof(struct htaccess_result));
1420     new->dir = parms.path;
1421     new->override = override;
1422     new->htaccess = dc;
1423 /* add to head of list */
1424     new->next = r->htaccess;
1425     r->htaccess = new;
1426
1427     return OK;
1428 }
1429
1430
1431 CORE_EXPORT(const char *) ap_init_virtual_host(ap_pool_t *p, const char *hostname,
1432                               server_rec *main_server, server_rec **ps)
1433 {
1434     server_rec *s = (server_rec *) ap_pcalloc(p, sizeof(server_rec));
1435
1436     /* TODO: this crap belongs in http_core */
1437     s->process = main_server->process;
1438     s->server_admin = NULL;
1439     s->server_hostname = NULL;
1440     s->error_fname = NULL;
1441     s->timeout = 0;
1442     s->keep_alive_timeout = 0;
1443     s->keep_alive = -1;
1444     s->keep_alive_max = -1;
1445     s->error_log = main_server->error_log;
1446     s->loglevel = main_server->loglevel;
1447     /* useful default, otherwise we get a port of 0 on redirects */
1448     s->port = main_server->port;
1449     s->next = NULL;
1450
1451     s->is_virtual = 1;
1452     s->names = ap_make_array(p, 4, sizeof(char **));
1453     s->wild_names = ap_make_array(p, 4, sizeof(char **));
1454
1455     s->module_config = create_empty_config(p);
1456     s->lookup_defaults = ap_create_per_dir_config(p);
1457
1458 #if 0
1459     s->server_uid = ap_user_id;
1460     s->server_gid = ap_group_id;
1461 #endif
1462
1463     s->limit_req_line = main_server->limit_req_line;
1464     s->limit_req_fieldsize = main_server->limit_req_fieldsize;
1465     s->limit_req_fields = main_server->limit_req_fields;
1466
1467     *ps = s;
1468
1469     return ap_parse_vhost_addrs(p, hostname, s);
1470 }
1471
1472
1473 API_EXPORT(void) ap_fixup_virtual_hosts(ap_pool_t *p, server_rec *main_server)
1474 {
1475     server_rec *virt;
1476
1477     for (virt = main_server->next; virt; virt = virt->next) {
1478         merge_server_configs(p, main_server->module_config,
1479                              virt->module_config);
1480
1481         virt->lookup_defaults =
1482             ap_merge_per_dir_configs(p, main_server->lookup_defaults,
1483                                   virt->lookup_defaults);
1484
1485         if (virt->server_admin == NULL)
1486             virt->server_admin = main_server->server_admin;
1487
1488         if (virt->timeout == 0)
1489             virt->timeout = main_server->timeout;
1490
1491         if (virt->keep_alive_timeout == 0)
1492             virt->keep_alive_timeout = main_server->keep_alive_timeout;
1493
1494         if (virt->keep_alive == -1)
1495             virt->keep_alive = main_server->keep_alive;
1496
1497         if (virt->keep_alive_max == -1)
1498             virt->keep_alive_max = main_server->keep_alive_max;
1499
1500         /* XXX: this is really something that should be dealt with by a
1501          * post-config api phase */
1502         ap_core_reorder_directories(p, virt);
1503     }
1504     ap_core_reorder_directories(p, main_server);
1505 }
1506
1507 /*****************************************************************
1508  *
1509  * Getting *everything* configured... 
1510  */
1511
1512 static void init_config_globals(ap_pool_t *p)
1513 {
1514     /* Global virtual host hash bucket pointers.  Init to null. */
1515     ap_init_vhost_config(p);
1516 }
1517
1518 static server_rec *init_server_config(process_rec *process, ap_pool_t *p)
1519 {
1520     server_rec *s = (server_rec *) ap_pcalloc(p, sizeof(server_rec));
1521
1522     ap_open_stderr(&s->error_log, p);
1523     s->process = process;
1524     s->port = 0;
1525     s->server_admin = DEFAULT_ADMIN;
1526     s->server_hostname = NULL;
1527     s->error_fname = DEFAULT_ERRORLOG;
1528     s->loglevel = DEFAULT_LOGLEVEL;
1529     s->limit_req_line = DEFAULT_LIMIT_REQUEST_LINE;
1530     s->limit_req_fieldsize = DEFAULT_LIMIT_REQUEST_FIELDSIZE;
1531     s->limit_req_fields = DEFAULT_LIMIT_REQUEST_FIELDS;
1532     s->timeout = DEFAULT_TIMEOUT;     
1533     s->keep_alive_timeout = DEFAULT_KEEPALIVE_TIMEOUT;
1534     s->keep_alive_max = DEFAULT_KEEPALIVE;
1535     s->keep_alive = 1;
1536     s->next = NULL;
1537     s->addrs = ap_pcalloc(p, sizeof(server_addr_rec));
1538     /* NOT virtual host; don't match any real network interface */
1539     s->addrs->host_addr.s_addr = htonl(INADDR_ANY);
1540     s->addrs->host_port = 0;    /* matches any port */
1541     s->addrs->virthost = "";    /* must be non-NULL */
1542     s->names = s->wild_names = NULL;
1543
1544     s->module_config = create_server_config(p, s);
1545     s->lookup_defaults = create_default_per_dir_config(p);
1546
1547     return s;
1548 }
1549
1550
1551 API_EXPORT(server_rec*) ap_read_config(process_rec *process, ap_pool_t *ptemp,
1552                                        const char *confname, 
1553                                        ap_directive_t **conftree)
1554 {
1555     ap_pool_t *p = process->pconf;
1556     server_rec *s = init_server_config(process, p);
1557
1558     init_config_globals(p);
1559
1560     /* All server-wide config files now have the SAME syntax... */
1561
1562     process_command_config(s, ap_server_pre_read_config, conftree,
1563                                       p, ptemp);
1564
1565     ap_process_resource_config(s, confname, conftree, p, ptemp);
1566
1567     process_command_config(s, ap_server_post_read_config, conftree,
1568                                       p, ptemp);
1569
1570     return s;
1571 }
1572
1573 void ap_single_module_configure(ap_pool_t *p, server_rec *s, module *m)
1574 {
1575     if (m->create_server_config)
1576         ap_set_module_config(s->module_config, m,
1577                              (*m->create_server_config)(p, s));
1578     if (m->create_dir_config)
1579         ap_set_module_config(s->lookup_defaults, m,
1580                              (*m->create_dir_config)(p, NULL));
1581 }
1582
1583 API_EXPORT(void) ap_run_rewrite_args(process_rec *process)
1584 {
1585     module *m;
1586
1587     for (m = top_module; m; m = m->next)
1588         if (m->rewrite_args)
1589             (*m->rewrite_args) (process);
1590 }
1591
1592 API_EXPORT(void) ap_post_config_hook(ap_pool_t *pconf, ap_pool_t *plog, ap_pool_t *ptemp, server_rec *s)
1593 {
1594     ap_run_post_config(pconf,plog,ptemp,s); 
1595     init_handlers(pconf);
1596 }
1597
1598 void ap_child_init_hook(ap_pool_t *pchild, server_rec *s)
1599 {
1600     /* TODO: uh this seems ugly, is there a better way? */
1601     /*ap_child_init_alloc();    PUT THIS BACK IN XXXXX */
1602
1603     ap_run_child_init(pchild,s);
1604 }
1605
1606 /********************************************************************
1607  * Configuration directives are restricted in terms of where they may
1608  * appear in the main configuration files and/or .htaccess files according
1609  * to the bitmask req_override in the command_rec structure.
1610  * If any of the overrides set in req_override are also allowed in the
1611  * context in which the command is read, then the command is allowed.
1612  * The context is determined as follows:
1613  *
1614  *    inside *.conf --> override = (RSRC_CONF|OR_ALL)&~(OR_AUTHCFG|OR_LIMIT);
1615  *    within <Directory> or <Location> --> override = OR_ALL|ACCESS_CONF;
1616  *    within .htaccess --> override = AllowOverride for current directory;
1617  *
1618  * the result is, well, a rather confusing set of possibilities for when
1619  * a particular directive is allowed to be used.  This procedure prints
1620  * in English where the given (pc) directive can be used.
1621  */
1622 static void show_overrides(const command_rec *pc, module *pm)
1623 {
1624     int n = 0;
1625
1626     printf("\tAllowed in *.conf ");
1627     if ((pc->req_override & (OR_OPTIONS | OR_FILEINFO | OR_INDEXES)) ||
1628         ((pc->req_override & RSRC_CONF) &&
1629          ((pc->req_override & (ACCESS_CONF | OR_AUTHCFG | OR_LIMIT)))))
1630         printf("anywhere");
1631     else if (pc->req_override & RSRC_CONF)
1632         printf("only outside <Directory>, <Files> or <Location>");
1633     else
1634         printf("only inside <Directory>, <Files> or <Location>");
1635
1636     /* Warn if the directive is allowed inside <Directory> or .htaccess
1637      * but module doesn't support per-dir configuration */
1638
1639     if ((pc->req_override & (OR_ALL | ACCESS_CONF)) && !pm->create_dir_config)
1640         printf(" [no per-dir config]");
1641
1642     if (pc->req_override & OR_ALL) {
1643         printf(" and in .htaccess\n\twhen AllowOverride");
1644
1645         if ((pc->req_override & OR_ALL) == OR_ALL)
1646             printf(" isn't None");
1647         else {
1648             printf(" includes ");
1649
1650             if (pc->req_override & OR_AUTHCFG) {
1651                 if (n++)
1652                     printf(" or ");
1653                 printf("AuthConfig");
1654             }
1655             if (pc->req_override & OR_LIMIT) {
1656                 if (n++)
1657                     printf(" or ");
1658                 printf("Limit");
1659             }
1660             if (pc->req_override & OR_OPTIONS) {
1661                 if (n++)
1662                     printf(" or ");
1663                 printf("Options");
1664             }
1665             if (pc->req_override & OR_FILEINFO) {
1666                 if (n++)
1667                     printf(" or ");
1668                 printf("FileInfo");
1669             }
1670             if (pc->req_override & OR_INDEXES) {
1671                 if (n++)
1672                     printf(" or ");
1673                 printf("Indexes");
1674             }
1675         }
1676     }
1677     printf("\n");
1678 }
1679
1680 /* Show the preloaded configuration directives, the help string explaining
1681  * the directive arguments, in what module they are handled, and in
1682  * what parts of the configuration they are allowed.  Used for httpd -h.
1683  */
1684 API_EXPORT(void) ap_show_directives()
1685 {
1686     const command_rec *pc;
1687     int n;
1688
1689     for (n = 0; ap_loaded_modules[n]; ++n)
1690         for (pc = ap_loaded_modules[n]->cmds; pc && pc->name; ++pc) {
1691             printf("%s (%s)\n", pc->name, ap_loaded_modules[n]->name);
1692             if (pc->errmsg)
1693                 printf("\t%s\n", pc->errmsg);
1694             show_overrides(pc, ap_loaded_modules[n]);
1695         }
1696 }
1697
1698 /* Show the preloaded module names.  Used for httpd -l. */
1699 API_EXPORT(void) ap_show_modules()
1700 {
1701     int n;
1702
1703     printf("Compiled in modules:\n");
1704     for (n = 0; ap_loaded_modules[n]; ++n)
1705         printf("  %s\n", ap_loaded_modules[n]->name);
1706 }
1707