]> granicus.if.org Git - apache/blob - server/config.c
Don't allocation large buffers on the stack to avoid over-running a fixed length...
[apache] / server / config.c
1 /* Copyright 1999-2004 The Apache Software Foundation
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 /*
17  * http_config.c: once was auxillary functions for reading httpd's config
18  * file and converting filenames into a namespace
19  *
20  * Rob McCool
21  *
22  * Wall-to-wall rewrite for Apache... commands which are part of the
23  * server core can now be found next door in "http_core.c".  Now contains
24  * general command loop, and functions which do bookkeeping for the new
25  * Apache config stuff (modules and configuration vectors).
26  *
27  * rst
28  *
29  */
30
31 #include "apr.h"
32 #include "apr_strings.h"
33 #include "apr_portable.h"
34 #include "apr_file_io.h"
35 #include "apr_fnmatch.h"
36
37 #define APR_WANT_STDIO
38 #define APR_WANT_STRFUNC
39 #include "apr_want.h"
40
41 #define CORE_PRIVATE
42
43 #include "ap_config.h"
44 #include "httpd.h"
45 #include "http_config.h"
46 #include "http_protocol.h"
47 #include "http_core.h"
48 #include "http_log.h"           /* for errors in parse_htaccess */
49 #include "http_request.h"       /* for default_handler (see invoke_handler) */
50 #include "http_main.h"
51 #include "http_vhost.h"
52 #include "util_cfgtree.h"
53 #include "mpm.h"
54
55
56 AP_DECLARE_DATA const char *ap_server_argv0 = NULL;
57
58 AP_DECLARE_DATA const char *ap_server_root = NULL;
59
60 AP_DECLARE_DATA apr_array_header_t *ap_server_pre_read_config = NULL;
61 AP_DECLARE_DATA apr_array_header_t *ap_server_post_read_config = NULL;
62 AP_DECLARE_DATA apr_array_header_t *ap_server_config_defines = NULL;
63
64 AP_DECLARE_DATA ap_directive_t *ap_conftree = NULL;
65
66 APR_HOOK_STRUCT(
67            APR_HOOK_LINK(header_parser)
68            APR_HOOK_LINK(pre_config)
69            APR_HOOK_LINK(post_config)
70            APR_HOOK_LINK(open_logs)
71            APR_HOOK_LINK(child_init)
72            APR_HOOK_LINK(handler)
73            APR_HOOK_LINK(quick_handler)
74            APR_HOOK_LINK(optional_fn_retrieve)
75 )
76
77 AP_IMPLEMENT_HOOK_RUN_ALL(int, header_parser,
78                           (request_rec *r), (r), OK, DECLINED)
79
80 AP_IMPLEMENT_HOOK_RUN_ALL(int, pre_config,
81                           (apr_pool_t *pconf, apr_pool_t *plog,
82                            apr_pool_t *ptemp),
83                           (pconf, plog, ptemp), OK, DECLINED)
84
85 AP_IMPLEMENT_HOOK_RUN_ALL(int, post_config,
86                           (apr_pool_t *pconf, apr_pool_t *plog,
87                            apr_pool_t *ptemp, server_rec *s),
88                           (pconf, plog, ptemp, s), OK, DECLINED)
89
90 /* During the course of debugging I expanded this macro out, so
91  * rather than remove all the useful information there is in the
92  * following lines, I'm going to leave it here in case anyone
93  * else finds it useful.
94  *
95  * Ben has looked at it and thinks it correct :)
96  *
97 AP_DECLARE(int) ap_hook_post_config(ap_HOOK_post_config_t *pf,
98                                     const char * const *aszPre,
99                                     const char * const *aszSucc,
100                                     int nOrder)
101 {
102     ap_LINK_post_config_t *pHook;
103
104     if (!_hooks.link_post_config) {
105         _hooks.link_post_config = apr_array_make(apr_hook_global_pool, 1,
106                                                  sizeof(ap_LINK_post_config_t));
107         apr_hook_sort_register("post_config", &_hooks.link_post_config);
108     }
109
110     pHook = apr_array_push(_hooks.link_post_config);
111     pHook->pFunc = pf;
112     pHook->aszPredecessors = aszPre;
113     pHook->aszSuccessors = aszSucc;
114     pHook->nOrder = nOrder;
115     pHook->szName = apr_hook_debug_current;
116
117     if (apr_hook_debug_enabled)
118         apr_hook_debug_show("post_config", aszPre, aszSucc);
119 }
120
121 AP_DECLARE(apr_array_header_t *) ap_hook_get_post_config(void) {
122     return _hooks.link_post_config;
123 }
124
125 AP_DECLARE(int) ap_run_post_config(apr_pool_t *pconf,
126                                    apr_pool_t *plog,
127                                    apr_pool_t *ptemp,
128                                    server_rec *s)
129 {
130     ap_LINK_post_config_t *pHook;
131     int n;
132
133     if(!_hooks.link_post_config)
134         return;
135
136     pHook = (ap_LINK_post_config_t *)_hooks.link_post_config->elts;
137     for (n = 0; n < _hooks.link_post_config->nelts; ++n)
138         pHook[n].pFunc (pconf, plog, ptemp, s);
139 }
140  */
141
142 AP_IMPLEMENT_HOOK_RUN_ALL(int, open_logs,
143                           (apr_pool_t *pconf, apr_pool_t *plog,
144                            apr_pool_t *ptemp, server_rec *s),
145                           (pconf, plog, ptemp, s), OK, DECLINED)
146
147 AP_IMPLEMENT_HOOK_VOID(child_init,
148                        (apr_pool_t *pchild, server_rec *s),
149                        (pchild, s))
150
151 AP_IMPLEMENT_HOOK_RUN_FIRST(int, handler, (request_rec *r),
152                             (r), DECLINED)
153
154 AP_IMPLEMENT_HOOK_RUN_FIRST(int, quick_handler, (request_rec *r, int lookup),
155                             (r, lookup), DECLINED)
156
157 AP_IMPLEMENT_HOOK_VOID(optional_fn_retrieve, (void), ())
158
159 /****************************************************************
160  *
161  * We begin with the functions which deal with the linked list
162  * of modules which control just about all of the server operation.
163  */
164
165 /* total_modules is the number of modules that have been linked
166  * into the server.
167  */
168 static int total_modules = 0;
169
170 /* dynamic_modules is the number of modules that have been added
171  * after the pre-loaded ones have been set up. It shouldn't be larger
172  * than DYNAMIC_MODULE_LIMIT.
173  */
174 static int dynamic_modules = 0;
175
176 AP_DECLARE_DATA module *ap_top_module = NULL;
177 AP_DECLARE_DATA module **ap_loaded_modules=NULL;
178
179 typedef int (*handler_func)(request_rec *);
180 typedef void *(*dir_maker_func)(apr_pool_t *, char *);
181 typedef void *(*merger_func)(apr_pool_t *, void *, void *);
182
183 /* Dealing with config vectors.  These are associated with per-directory,
184  * per-server, and per-request configuration, and have a void* pointer for
185  * each modules.  The nature of the structure pointed to is private to the
186  * module in question... the core doesn't (and can't) know.  However, there
187  * are defined interfaces which allow it to create instances of its private
188  * per-directory and per-server structures, and to merge the per-directory
189  * structures of a directory and its subdirectory (producing a new one in
190  * which the defaults applying to the base directory have been properly
191  * overridden).
192  */
193
194 static ap_conf_vector_t *create_empty_config(apr_pool_t *p)
195 {
196     void *conf_vector = apr_pcalloc(p, sizeof(void *) *
197                                     (total_modules + DYNAMIC_MODULE_LIMIT));
198     return conf_vector;
199 }
200
201 static ap_conf_vector_t *create_default_per_dir_config(apr_pool_t *p)
202 {
203     void **conf_vector = apr_pcalloc(p, sizeof(void *) *
204                                      (total_modules + DYNAMIC_MODULE_LIMIT));
205     module *modp;
206
207     for (modp = ap_top_module; modp; modp = modp->next) {
208         dir_maker_func df = modp->create_dir_config;
209
210         if (df)
211             conf_vector[modp->module_index] = (*df)(p, NULL);
212     }
213
214     return (ap_conf_vector_t *)conf_vector;
215 }
216
217 AP_CORE_DECLARE(ap_conf_vector_t *) ap_merge_per_dir_configs(apr_pool_t *p,
218                                            ap_conf_vector_t *base,
219                                            ap_conf_vector_t *new_conf)
220 {
221     void **conf_vector = apr_palloc(p, sizeof(void *) * total_modules);
222     void **base_vector = (void **)base;
223     void **new_vector = (void **)new_conf;
224     module *modp;
225
226     for (modp = ap_top_module; modp; modp = modp->next) {
227         int i = modp->module_index;
228
229         if (!new_vector[i]) {
230             conf_vector[i] = base_vector[i];
231         }
232         else {
233             merger_func df = modp->merge_dir_config;
234             if (df && base_vector[i]) {
235                 conf_vector[i] = (*df)(p, base_vector[i], new_vector[i]);
236             }
237             else
238                 conf_vector[i] = new_vector[i];
239         }
240     }
241
242     return (ap_conf_vector_t *)conf_vector;
243 }
244
245 static ap_conf_vector_t *create_server_config(apr_pool_t *p, server_rec *s)
246 {
247     void **conf_vector = apr_pcalloc(p, sizeof(void *) *
248                                      (total_modules + DYNAMIC_MODULE_LIMIT));
249     module *modp;
250
251     for (modp = ap_top_module; modp; modp = modp->next) {
252         if (modp->create_server_config)
253             conf_vector[modp->module_index] = (*modp->create_server_config)(p, s);
254     }
255
256     return (ap_conf_vector_t *)conf_vector;
257 }
258
259 static void merge_server_configs(apr_pool_t *p, ap_conf_vector_t *base,
260                                  ap_conf_vector_t *virt)
261 {
262     /* Can reuse the 'virt' vector for the spine of it, since we don't
263      * have to deal with the moral equivalent of .htaccess files here...
264      */
265
266     void **base_vector = (void **)base;
267     void **virt_vector = (void **)virt;
268     module *modp;
269
270     for (modp = ap_top_module; modp; modp = modp->next) {
271         merger_func df = modp->merge_server_config;
272         int i = modp->module_index;
273
274         if (!virt_vector[i])
275             virt_vector[i] = base_vector[i];
276         else if (df)
277             virt_vector[i] = (*df)(p, base_vector[i], virt_vector[i]);
278     }
279 }
280
281 AP_CORE_DECLARE(ap_conf_vector_t *) ap_create_request_config(apr_pool_t *p)
282 {
283     return create_empty_config(p);
284 }
285
286 AP_CORE_DECLARE(ap_conf_vector_t *) ap_create_conn_config(apr_pool_t *p)
287 {
288     return create_empty_config(p);
289 }
290
291 AP_CORE_DECLARE(ap_conf_vector_t *) ap_create_per_dir_config(apr_pool_t *p)
292 {
293     return create_empty_config(p);
294 }
295
296 static int ap_invoke_filter_init(ap_filter_t *filters)
297 {
298     while (filters) {
299         if (filters->frec->filter_init_func) {
300             int result = filters->frec->filter_init_func(filters);
301             if (result != OK) {
302                 return result;
303             }
304         }
305         filters = filters->next;
306     } 
307     return OK;
308 }
309
310 AP_CORE_DECLARE(int) ap_invoke_handler(request_rec *r)
311 {
312     const char *handler;
313     const char *p;
314     int result;
315     const char *old_handler = r->handler;
316
317     /*
318      * The new insert_filter stage makes the most sense here.  We only use
319      * it when we are going to run the request, so we must insert filters
320      * if any are available.  Since the goal of this phase is to allow all
321      * modules to insert a filter if they want to, this filter returns
322      * void.  I just can't see any way that this filter can reasonably
323      * fail, either your modules inserts something or it doesn't.  rbb
324      */
325     ap_run_insert_filter(r);
326
327     /* Before continuing, allow each filter that is in the two chains to
328      * run their init function to let them do any magic before we could
329      * start generating data.
330      */
331     result = ap_invoke_filter_init(r->input_filters);
332     if (result != OK) {
333         return result;
334     }
335     result = ap_invoke_filter_init(r->output_filters);
336     if (result != OK) {
337         return result;
338     }
339
340     if (!r->handler) {
341         handler = r->content_type ? r->content_type : ap_default_type(r);
342         if ((p=ap_strchr_c(handler, ';')) != NULL) {
343             char *new_handler = (char *)apr_pmemdup(r->pool, handler,
344                                                     p - handler + 1);
345             char *p2 = new_handler + (p - handler);
346             handler = new_handler;
347
348             /* MIME type arguments */
349             while (p2 > handler && p2[-1] == ' ')
350                 --p2; /* strip trailing spaces */
351
352             *p2='\0';
353         }
354
355         r->handler = handler;
356     }
357
358     result = ap_run_handler(r);
359
360     r->handler = old_handler;
361
362     if (result == DECLINED && r->handler && r->filename) {
363         ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
364             "handler \"%s\" not found for: %s", r->handler, r->filename);
365     }
366
367     return result == DECLINED ? HTTP_INTERNAL_SERVER_ERROR : result;
368 }
369
370 AP_DECLARE(int) ap_method_is_limited(cmd_parms *cmd, const char *method)
371 {
372     int methnum;
373
374     methnum = ap_method_number_of(method);
375
376     /*
377      * A method number either hardcoded into apache or
378      * added by a module and registered.
379      */
380     if (methnum != M_INVALID) {
381         return (cmd->limited & (AP_METHOD_BIT << methnum)) ? 1 : 0;
382     }
383
384     return 0; /* not found */
385 }
386
387 AP_DECLARE(void) ap_register_hooks(module *m, apr_pool_t *p)
388 {
389     if (m->register_hooks) {
390         if (getenv("SHOW_HOOKS")) {
391             printf("Registering hooks for %s\n", m->name);
392             apr_hook_debug_enabled = 1;
393         }
394
395         apr_hook_debug_current = m->name;
396         m->register_hooks(p);
397     }
398 }
399
400 /* One-time setup for precompiled modules --- NOT to be done on restart */
401
402 AP_DECLARE(void) ap_add_module(module *m, apr_pool_t *p)
403 {
404     /* This could be called from a LoadModule httpd.conf command,
405      * after the file has been linked and the module structure within it
406      * teased out...
407      */
408
409     if (m->version != MODULE_MAGIC_NUMBER_MAJOR) {
410         ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
411                      "%s: module \"%s\" is not compatible with this "
412                      "version of Apache (found %d, need %d).",
413                      ap_server_argv0, m->name, m->version,
414                      MODULE_MAGIC_NUMBER_MAJOR);
415         ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
416                      "Please contact the vendor for the correct version.");
417         exit(1);
418     }
419
420     if (m->next == NULL) {
421         m->next = ap_top_module;
422         ap_top_module = m;
423     }
424
425     if (m->module_index == -1) {
426         m->module_index = total_modules++;
427         dynamic_modules++;
428
429         if (dynamic_modules > DYNAMIC_MODULE_LIMIT) {
430             ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
431                          "%s: module \"%s\" could not be loaded, because"
432                          " the dynamic", ap_server_argv0, m->name);
433             ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
434                          "module limit was reached. Please increase "
435                          "DYNAMIC_MODULE_LIMIT and recompile.");
436             exit(1);
437         }
438     }
439
440     /* Some C compilers put a complete path into __FILE__, but we want
441      * only the filename (e.g. mod_includes.c). So check for path
442      * components (Unix and DOS), and remove them.
443      */
444
445     if (ap_strrchr_c(m->name, '/'))
446         m->name = 1 + ap_strrchr_c(m->name, '/');
447
448     if (ap_strrchr_c(m->name, '\\'))
449         m->name = 1 + ap_strrchr_c(m->name, '\\');
450
451 #ifdef _OSD_POSIX
452     /* __FILE__ =
453      * "*POSIX(/home/martin/apache/src/modules/standard/mod_info.c)"
454      */
455
456     /* We cannot fix the string in-place, because it's const */
457     if (m->name[strlen(m->name)-1] == ')') {
458         char *tmp = strdup(m->name); /* FIXME: memory leak, albeit a small one */
459         tmp[strlen(tmp)-1] = '\0';
460         m->name = tmp;
461     }
462 #endif /*_OSD_POSIX*/
463
464     /*  FIXME: is this the right place to call this?
465      *  It doesn't appear to be
466      */
467     ap_register_hooks(m, p);
468 }
469
470 /*
471  * remove_module undoes what add_module did. There are some caveats:
472  * when the module is removed, its slot is lost so all the current
473  * per-dir and per-server configurations are invalid. So we should
474  * only ever call this function when you are invalidating almost
475  * all our current data. I.e. when doing a restart.
476  */
477
478 AP_DECLARE(void) ap_remove_module(module *m)
479 {
480     module *modp;
481
482     modp = ap_top_module;
483     if (modp == m) {
484         /* We are the top module, special case */
485         ap_top_module = modp->next;
486         m->next = NULL;
487     }
488     else {
489         /* Not the top module, find use. When found modp will
490          * point to the module _before_ us in the list
491          */
492
493         while (modp && modp->next != m) {
494             modp = modp->next;
495         }
496
497         if (!modp) {
498             /* Uh-oh, this module doesn't exist */
499             ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
500                          "Cannot remove module %s: not found in module list",
501                          m->name);
502             return;
503         }
504
505         /* Eliminate us from the module list */
506         modp->next = modp->next->next;
507     }
508
509     m->module_index = -1; /* simulate being unloaded, should
510                            * be unnecessary */
511     dynamic_modules--;
512     total_modules--;
513 }
514
515 AP_DECLARE(void) ap_add_loaded_module(module *mod, apr_pool_t *p)
516 {
517     module **m;
518
519     /*
520      *  Add module pointer to top of chained module list
521      */
522     ap_add_module(mod, p);
523
524     /*
525      *  And module pointer to list of loaded modules
526      *
527      *  Notes: 1. ap_add_module() would already complain if no more space
528      *            exists for adding a dynamically loaded module
529      *         2. ap_add_module() accepts double inclusion, so we have
530      *            to accept this, too.
531      */
532     for (m = ap_loaded_modules; *m != NULL; m++)
533         ;
534     *m++ = mod;
535     *m = NULL;
536 }
537
538 AP_DECLARE(void) ap_remove_loaded_module(module *mod)
539 {
540     module **m;
541     module **m2;
542     int done;
543
544     /*
545      *  Remove module pointer from chained module list
546      */
547     ap_remove_module(mod);
548
549     /*
550      *  Remove module pointer from list of loaded modules
551      *
552      *  Note: 1. We cannot determine if the module was successfully
553      *           removed by ap_remove_module().
554      *        2. We have not to complain explicity when the module
555      *           is not found because ap_remove_module() did it
556      *           for us already.
557      */
558     for (m = m2 = ap_loaded_modules, done = 0; *m2 != NULL; m2++) {
559         if (*m2 == mod && done == 0)
560             done = 1;
561         else
562             *m++ = *m2;
563     }
564
565     *m = NULL;
566 }
567
568 AP_DECLARE(void) ap_setup_prelinked_modules(process_rec *process)
569 {
570     module **m;
571     module **m2;
572
573     apr_hook_global_pool=process->pconf;
574
575     /*
576      *  Initialise total_modules variable and module indices
577      */
578     total_modules = 0;
579     for (m = ap_preloaded_modules; *m != NULL; m++)
580         (*m)->module_index = total_modules++;
581
582     /*
583      *  Initialise list of loaded modules
584      */
585     ap_loaded_modules = (module **)apr_palloc(process->pool,
586         sizeof(module *) * (total_modules + DYNAMIC_MODULE_LIMIT + 1));
587
588     if (ap_loaded_modules == NULL) {
589         ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
590                      "Ouch!  Out of memory in ap_setup_prelinked_modules()!");
591     }
592
593     for (m = ap_preloaded_modules, m2 = ap_loaded_modules; *m != NULL; )
594         *m2++ = *m++;
595
596     *m2 = NULL;
597
598     /*
599      *   Initialize chain of linked (=activate) modules
600      */
601     for (m = ap_prelinked_modules; *m != NULL; m++)
602         ap_add_module(*m, process->pconf);
603
604     apr_hook_sort_all();
605 }
606
607 AP_DECLARE(const char *) ap_find_module_name(module *m)
608 {
609     return m->name;
610 }
611
612 AP_DECLARE(module *) ap_find_linked_module(const char *name)
613 {
614     module *modp;
615
616     for (modp = ap_top_module; modp; modp = modp->next) {
617         if (strcmp(modp->name, name) == 0)
618             return modp;
619     }
620
621     return NULL;
622 }
623
624 /* Add a named module.  Returns 1 if module found, 0 otherwise.  */
625 AP_DECLARE(int) ap_add_named_module(const char *name, apr_pool_t *p)
626 {
627     module *modp;
628     int i = 0;
629
630     for (modp = ap_loaded_modules[i]; modp; modp = ap_loaded_modules[++i]) {
631         if (strcmp(modp->name, name) == 0) {
632             /* Only add modules that are not already enabled.  */
633             if (modp->next == NULL) {
634                 ap_add_module(modp, p);
635             }
636
637             return 1;
638         }
639     }
640
641     return 0;
642 }
643
644 /*****************************************************************
645  *
646  * Resource, access, and .htaccess config files now parsed by a common
647  * command loop.
648  *
649  * Let's begin with the basics; parsing the line and
650  * invoking the function...
651  */
652
653 static const char *invoke_cmd(const command_rec *cmd, cmd_parms *parms,
654                               void *mconfig, const char *args)
655 {
656     char *w, *w2, *w3;
657     const char *errmsg = NULL;
658
659     if ((parms->override & cmd->req_override) == 0)
660         return apr_pstrcat(parms->pool, cmd->name, " not allowed here", NULL);
661
662     parms->info = cmd->cmd_data;
663     parms->cmd = cmd;
664
665     switch (cmd->args_how) {
666     case RAW_ARGS:
667 #ifdef RESOLVE_ENV_PER_TOKEN
668         args = ap_resolve_env(parms->pool,args);
669 #endif
670         return cmd->AP_RAW_ARGS(parms, mconfig, args);
671
672     case NO_ARGS:
673         if (*args != 0)
674             return apr_pstrcat(parms->pool, cmd->name, " takes no arguments",
675                                NULL);
676
677         return cmd->AP_NO_ARGS(parms, mconfig);
678
679     case TAKE1:
680         w = ap_getword_conf(parms->pool, &args);
681
682         if (*w == '\0' || *args != 0)
683             return apr_pstrcat(parms->pool, cmd->name, " takes one argument",
684                                cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
685
686         return cmd->AP_TAKE1(parms, mconfig, w);
687
688     case TAKE2:
689         w = ap_getword_conf(parms->pool, &args);
690         w2 = ap_getword_conf(parms->pool, &args);
691
692         if (*w == '\0' || *w2 == '\0' || *args != 0)
693             return apr_pstrcat(parms->pool, cmd->name, " takes two arguments",
694                                cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
695
696         return cmd->AP_TAKE2(parms, mconfig, w, w2);
697
698     case TAKE12:
699         w = ap_getword_conf(parms->pool, &args);
700         w2 = ap_getword_conf(parms->pool, &args);
701
702         if (*w == '\0' || *args != 0)
703             return apr_pstrcat(parms->pool, cmd->name, " takes 1-2 arguments",
704                                cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
705
706         return cmd->AP_TAKE2(parms, mconfig, w, *w2 ? w2 : NULL);
707
708     case TAKE3:
709         w = ap_getword_conf(parms->pool, &args);
710         w2 = ap_getword_conf(parms->pool, &args);
711         w3 = ap_getword_conf(parms->pool, &args);
712
713         if (*w == '\0' || *w2 == '\0' || *w3 == '\0' || *args != 0)
714             return apr_pstrcat(parms->pool, cmd->name, " takes three arguments",
715                                cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
716
717         return cmd->AP_TAKE3(parms, mconfig, w, w2, w3);
718
719     case TAKE23:
720         w = ap_getword_conf(parms->pool, &args);
721         w2 = ap_getword_conf(parms->pool, &args);
722         w3 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
723
724         if (*w == '\0' || *w2 == '\0' || *args != 0)
725             return apr_pstrcat(parms->pool, cmd->name,
726                                " takes two or three arguments",
727                                cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
728
729         return cmd->AP_TAKE3(parms, mconfig, w, w2, w3);
730
731     case TAKE123:
732         w = ap_getword_conf(parms->pool, &args);
733         w2 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
734         w3 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
735
736         if (*w == '\0' || *args != 0)
737             return apr_pstrcat(parms->pool, cmd->name,
738                                " takes one, two or three arguments",
739                                cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
740
741         return cmd->AP_TAKE3(parms, mconfig, w, w2, w3);
742
743     case TAKE13:
744         w = ap_getword_conf(parms->pool, &args);
745         w2 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
746         w3 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
747
748         if (*w == '\0' || (w2 && *w2 && !w3) || *args != 0)
749             return apr_pstrcat(parms->pool, cmd->name,
750                                " takes one or three arguments",
751                                cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
752
753         return cmd->AP_TAKE3(parms, mconfig, w, w2, w3);
754
755     case ITERATE:
756         while (*(w = ap_getword_conf(parms->pool, &args)) != '\0') {
757
758             errmsg = cmd->AP_TAKE1(parms, mconfig, w);
759
760             if (errmsg && strcmp(errmsg, DECLINE_CMD) != 0)
761                 return errmsg;
762         }
763
764         return errmsg;
765
766     case ITERATE2:
767         w = ap_getword_conf(parms->pool, &args);
768
769         if (*w == '\0' || *args == 0)
770             return apr_pstrcat(parms->pool, cmd->name,
771                                " requires at least two arguments",
772                                cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
773
774         while (*(w2 = ap_getword_conf(parms->pool, &args)) != '\0') {
775
776             errmsg = cmd->AP_TAKE2(parms, mconfig, w, w2);
777
778             if (errmsg && strcmp(errmsg, DECLINE_CMD) != 0)
779                 return errmsg;
780         }
781
782         return errmsg;
783
784     case FLAG:
785         w = ap_getword_conf(parms->pool, &args);
786
787         if (*w == '\0' || (strcasecmp(w, "on") && strcasecmp(w, "off")))
788             return apr_pstrcat(parms->pool, cmd->name, " must be On or Off",
789                                NULL);
790
791         return cmd->AP_FLAG(parms, mconfig, strcasecmp(w, "off") != 0);
792
793     default:
794         return apr_pstrcat(parms->pool, cmd->name,
795                            " is improperly configured internally (server bug)",
796                            NULL);
797     }
798 }
799
800 AP_CORE_DECLARE(const command_rec *) ap_find_command(const char *name,
801                                                      const command_rec *cmds)
802 {
803     while (cmds->name) {
804         if (!strcasecmp(name, cmds->name))
805             return cmds;
806
807         ++cmds;
808     }
809
810     return NULL;
811 }
812
813 AP_CORE_DECLARE(const command_rec *) ap_find_command_in_modules(
814                                           const char *cmd_name, module **mod)
815 {
816     const command_rec *cmdp;
817     module *modp;
818
819     for (modp = *mod; modp; modp = modp->next) {
820         if (modp->cmds && (cmdp = ap_find_command(cmd_name, modp->cmds))) {
821             *mod = modp;
822             return cmdp;
823         }
824     }
825
826     return NULL;
827 }
828
829 AP_CORE_DECLARE(void *) ap_set_config_vectors(server_rec *server,
830                                               ap_conf_vector_t *section_vector,
831                                               const char *section,
832                                               module *mod, apr_pool_t *pconf)
833 {
834     void *section_config = ap_get_module_config(section_vector, mod);
835     void *server_config = ap_get_module_config(server->module_config, mod);
836
837     if (!section_config && mod->create_dir_config) {
838         /* ### need to fix the create_dir_config functions' prototype... */
839         section_config = (*mod->create_dir_config)(pconf, (char *)section);
840         ap_set_module_config(section_vector, mod, section_config);
841     }
842
843     if (!server_config && mod->create_server_config) {
844         server_config = (*mod->create_server_config)(pconf, server);
845         ap_set_module_config(server->module_config, mod, server_config);
846     }
847
848     return section_config;
849 }
850
851 static const char *execute_now(char *cmd_line, const char *args,
852                                cmd_parms *parms,
853                                apr_pool_t *p, apr_pool_t *ptemp,
854                                ap_directive_t **sub_tree,
855                                ap_directive_t *parent);
856
857 static const char *ap_build_config_sub(apr_pool_t *p, apr_pool_t *temp_pool,
858                                        const char *l, cmd_parms *parms,
859                                        ap_directive_t **current,
860                                        ap_directive_t **curr_parent,
861                                        ap_directive_t **conftree)
862 {
863     const char *retval = NULL;
864     const char *args;
865     char *cmd_name;
866     ap_directive_t *newdir;
867     module *mod = ap_top_module;
868     const command_rec *cmd;
869
870     if (*l == '#' || *l == '\0')
871         return NULL;
872
873 #if RESOLVE_ENV_PER_TOKEN
874     args = l;
875 #else
876     args = ap_resolve_env(temp_pool, l);
877 #endif
878
879     cmd_name = ap_getword_conf(p, &args);
880     if (*cmd_name == '\0') {
881         /* Note: this branch should not occur. An empty line should have
882          * triggered the exit further above.
883          */
884         return NULL;
885     }
886
887     if (cmd_name[1] != '/') {
888         char *lastc = cmd_name + strlen(cmd_name) - 1;
889         if (*lastc == '>') {
890             *lastc = '\0' ;
891         }
892         if (cmd_name[0] == '<' && *args == '\0') {
893             args = ">";
894         }
895     }
896
897     newdir = apr_pcalloc(p, sizeof(ap_directive_t));
898     newdir->filename = parms->config_file->name;
899     newdir->line_num = parms->config_file->line_number;
900     newdir->directive = cmd_name;
901     newdir->args = apr_pstrdup(p, args);
902
903     if ((cmd = ap_find_command_in_modules(cmd_name, &mod)) != NULL) {
904         if (cmd->req_override & EXEC_ON_READ) {
905             ap_directive_t *sub_tree = NULL;
906
907             parms->err_directive = newdir;
908             retval = execute_now(cmd_name, args, parms, p, temp_pool,
909                                  &sub_tree, *curr_parent);
910             if (*current) {
911                 (*current)->next = sub_tree;
912             }
913             else {
914                 *current = sub_tree;
915                 if (*curr_parent) {
916                     (*curr_parent)->first_child = (*current);
917                 }
918                 if (*current) {
919                     (*current)->parent = (*curr_parent);
920                 }
921             }
922             if (*current) {
923                 if (!*conftree) {
924                     /* Before walking *current to the end of the list,
925                      * set the head to *current.
926                      */
927                     *conftree = *current;
928                 }
929                 while ((*current)->next != NULL) {
930                     (*current) = (*current)->next;
931                     (*current)->parent = (*curr_parent);
932                 }
933             }
934             return retval;
935         }
936     }
937
938     if (cmd_name[0] == '<') {
939         if (cmd_name[1] != '/') {
940             (*current) = ap_add_node(curr_parent, *current, newdir, 1);
941         }
942         else if (*curr_parent == NULL) {
943             parms->err_directive = newdir;
944             return apr_pstrcat(p, cmd_name,
945                                " without matching <", cmd_name + 2,
946                                " section", NULL);
947         }
948         else {
949             char *bracket = cmd_name + strlen(cmd_name) - 1;
950
951             if (*bracket != '>') {
952                 parms->err_directive = newdir;
953                 return apr_pstrcat(p, cmd_name,
954                                    "> directive missing closing '>'", NULL);
955             }
956
957             *bracket = '\0';
958
959             if (strcasecmp(cmd_name + 2,
960                            (*curr_parent)->directive + 1) != 0) {
961                 parms->err_directive = newdir;
962                 return apr_pstrcat(p, "Expected </",
963                                    (*curr_parent)->directive + 1, "> but saw ",
964                                    cmd_name, ">", NULL);
965             }
966
967             *bracket = '>';
968
969             /* done with this section; move up a level */
970             *current = *curr_parent;
971             *curr_parent = (*current)->parent;
972         }
973     }
974     else {
975         *current = ap_add_node(curr_parent, *current, newdir, 0);
976     }
977
978     return retval;
979 }
980
981 AP_DECLARE(const char *) ap_build_cont_config(apr_pool_t *p,
982                                               apr_pool_t *temp_pool,
983                                               cmd_parms *parms,
984                                               ap_directive_t **current,
985                                               ap_directive_t **curr_parent,
986                                               char *orig_directive)
987 {
988     char *l;
989     char *bracket;
990     const char *retval;
991     ap_directive_t *sub_tree = NULL;
992
993     /* Since this function can be called recursively, allocate
994      * the temporary 8k string buffer from the temp_pool rather 
995      * than the stack to avoid over-running a fixed length stack.
996      */
997     l = apr_palloc(temp_pool, MAX_STRING_LEN);
998
999     bracket = apr_pstrcat(p, orig_directive + 1, ">", NULL);
1000     while (!(ap_cfg_getline(l, MAX_STRING_LEN, parms->config_file))) {
1001         if (!memcmp(l, "</", 2)
1002             && (strcasecmp(l + 2, bracket) == 0)
1003             && (*curr_parent == NULL)) {
1004             break;
1005         }
1006         retval = ap_build_config_sub(p, temp_pool, l, parms, current,
1007                                      curr_parent, &sub_tree);
1008         if (retval != NULL)
1009             return retval;
1010
1011         if (sub_tree == NULL && curr_parent != NULL) {
1012             sub_tree = *curr_parent;
1013         }
1014
1015         if (sub_tree == NULL && current != NULL) {
1016             sub_tree = *current;
1017         }
1018     }
1019
1020     *current = sub_tree;
1021     return NULL;
1022 }
1023
1024 static const char *ap_walk_config_sub(const ap_directive_t *current,
1025                                       cmd_parms *parms,
1026                                       ap_conf_vector_t *section_vector)
1027 {
1028     module *mod = ap_top_module;
1029
1030     while (1) {
1031         const command_rec *cmd;
1032
1033         if (!(cmd = ap_find_command_in_modules(current->directive, &mod))) {
1034             parms->err_directive = current;
1035             return apr_pstrcat(parms->pool, "Invalid command '",
1036                                current->directive,
1037                                "', perhaps mis-spelled or defined by a module "
1038                                "not included in the server configuration",
1039                                NULL);
1040         }
1041         else {
1042             void *dir_config = ap_set_config_vectors(parms->server,
1043                                                      section_vector,
1044                                                      parms->path,
1045                                                      mod,
1046                                                      parms->pool);
1047             const char *retval;
1048
1049             /* Once was enough? */
1050             if (cmd->req_override & EXEC_ON_READ) {
1051                 return NULL;
1052             }
1053
1054             retval = invoke_cmd(cmd, parms, dir_config, current->args);
1055             if (retval == NULL) {
1056                 return NULL;
1057             }
1058
1059             if (strcmp(retval, DECLINE_CMD) != 0) {
1060                 /* If the directive in error has already been set, don't
1061                  * replace it.  Otherwise, an error inside a container 
1062                  * will be reported as occuring on the first line of the
1063                  * container.
1064                  */
1065                 if (!parms->err_directive) {
1066                     parms->err_directive = current;
1067                 }
1068
1069                 return retval;
1070             }
1071
1072             mod = mod->next; /* Next time around, skip this one */
1073         }
1074     }
1075     /* NOTREACHED */
1076 }
1077
1078 AP_DECLARE(const char *) ap_walk_config(ap_directive_t *current,
1079                                         cmd_parms *parms,
1080                                         ap_conf_vector_t *section_vector)
1081 {
1082     ap_conf_vector_t *oldconfig = parms->context;
1083
1084     parms->context = section_vector;
1085
1086     /* scan through all directives, executing each one */
1087     for (; current != NULL; current = current->next) {
1088         const char *errmsg;
1089
1090         parms->directive = current;
1091
1092         /* actually parse the command and execute the correct function */
1093         errmsg = ap_walk_config_sub(current, parms, section_vector);
1094         if (errmsg != NULL) {
1095             /* restore the context (just in case) */
1096             parms->context = oldconfig;
1097             return errmsg;
1098         }
1099     }
1100
1101     parms->context = oldconfig;
1102     return NULL;
1103 }
1104
1105 AP_DECLARE(const char *) ap_build_config(cmd_parms *parms,
1106                                          apr_pool_t *p, apr_pool_t *temp_pool,
1107                                          ap_directive_t **conftree)
1108 {
1109     ap_directive_t *current = *conftree;
1110     ap_directive_t *curr_parent = NULL;
1111     char l[MAX_STRING_LEN];
1112     const char *errmsg;
1113
1114     if (current != NULL) {
1115         while (current->next) {
1116             current = current->next;
1117         }
1118     }
1119
1120     while (!(ap_cfg_getline(l, MAX_STRING_LEN, parms->config_file))) {
1121         errmsg = ap_build_config_sub(p, temp_pool, l, parms,
1122                                      &current, &curr_parent, conftree);
1123         if (errmsg != NULL)
1124             return errmsg;
1125
1126         if (*conftree == NULL && curr_parent != NULL) {
1127             *conftree = curr_parent;
1128         }
1129
1130         if (*conftree == NULL && current != NULL) {
1131             *conftree = current;
1132         }
1133     }
1134
1135     if (curr_parent != NULL) {
1136         errmsg = "";
1137
1138         while (curr_parent != NULL) {
1139             errmsg = apr_psprintf(p, "%s%s%s:%u: %s> was not closed.",
1140                                   errmsg,
1141                                   *errmsg == '\0' ? "" : APR_EOL_STR,
1142                                   curr_parent->filename,
1143                                   curr_parent->line_num,
1144                                   curr_parent->directive);
1145
1146             parms->err_directive = curr_parent;
1147             curr_parent = curr_parent->parent;
1148         }
1149
1150         return errmsg;
1151     }
1152
1153     return NULL;
1154 }
1155
1156 /*
1157  * Generic command functions...
1158  */
1159
1160 AP_DECLARE_NONSTD(const char *) ap_set_string_slot(cmd_parms *cmd,
1161                                                    void *struct_ptr,
1162                                                    const char *arg)
1163 {
1164     int offset = (int)(long)cmd->info;
1165
1166     *(const char **)((char *)struct_ptr + offset) = arg;
1167
1168     return NULL;
1169 }
1170
1171 AP_DECLARE_NONSTD(const char *) ap_set_int_slot(cmd_parms *cmd,
1172                                                 void *struct_ptr,
1173                                                 const char *arg)
1174 {
1175     char *endptr;
1176     char *error_str = NULL;
1177     int offset = (int)(long)cmd->info;
1178
1179     *(int *)((char*)struct_ptr + offset) = strtol(arg, &endptr, 10);
1180
1181     if ((*arg == '\0') || (*endptr != '\0')) {
1182         error_str = apr_psprintf(cmd->pool,
1183                      "Invalid value for directive %s, expected integer",
1184                      cmd->directive->directive);
1185     }
1186
1187     return error_str;
1188 }
1189
1190 AP_DECLARE_NONSTD(const char *) ap_set_string_slot_lower(cmd_parms *cmd,
1191                                                          void *struct_ptr,
1192                                                          const char *arg_)
1193 {
1194     char *arg = apr_pstrdup(cmd->pool,arg_);
1195     int offset = (int)(long)cmd->info;
1196
1197     ap_str_tolower(arg);
1198     *(char **)((char *)struct_ptr + offset) = arg;
1199
1200     return NULL;
1201 }
1202
1203 AP_DECLARE_NONSTD(const char *) ap_set_flag_slot(cmd_parms *cmd,
1204                                                  void *struct_ptr_v, int arg)
1205 {
1206     int offset = (int)(long)cmd->info;
1207     char *struct_ptr = (char *)struct_ptr_v;
1208
1209     *(int *)(struct_ptr + offset) = arg ? 1 : 0;
1210
1211     return NULL;
1212 }
1213
1214 AP_DECLARE_NONSTD(const char *) ap_set_file_slot(cmd_parms *cmd, void *struct_ptr,
1215                                                  const char *arg)
1216 {
1217     /* Prepend server_root to relative arg.
1218      * This allows most args to be independent of server_root,
1219      * so the server can be moved or mirrored with less pain.
1220      */
1221     const char *path;
1222     int offset = (int)(long)cmd->info;
1223
1224     path = ap_server_root_relative(cmd->pool, arg);
1225
1226     if (!path) {
1227         return apr_pstrcat(cmd->pool, "Invalid file path ",
1228                            arg, NULL);
1229     }
1230
1231     *(const char **) ((char*)struct_ptr + offset) = path;
1232
1233     return NULL;
1234 }
1235
1236 AP_DECLARE_NONSTD(const char *) ap_set_deprecated(cmd_parms *cmd,
1237                                                   void *struct_ptr,
1238                                                   const char *arg)
1239 {
1240     return cmd->cmd->errmsg;
1241 }
1242
1243 /*****************************************************************
1244  *
1245  * Reading whole config files...
1246  */
1247
1248 static cmd_parms default_parms =
1249 {NULL, 0, -1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
1250
1251 AP_DECLARE(char *) ap_server_root_relative(apr_pool_t *p, const char *file)
1252 {
1253     char *newpath = NULL;
1254     apr_status_t rv;
1255     rv = apr_filepath_merge(&newpath, ap_server_root, file,
1256                             APR_FILEPATH_TRUENAME, p);
1257     if (newpath && (rv == APR_SUCCESS || APR_STATUS_IS_EPATHWILD(rv) 
1258                                       || APR_STATUS_IS_ENOENT(rv)
1259                                       || APR_STATUS_IS_ENOTDIR(rv))) {
1260         return newpath;
1261     }
1262     else {
1263         return NULL;
1264     }
1265 }
1266
1267 AP_DECLARE(const char *) ap_soak_end_container(cmd_parms *cmd, char *directive)
1268 {
1269     char l[MAX_STRING_LEN];
1270     const char *args;
1271     char *cmd_name;
1272
1273     while(!(ap_cfg_getline(l, MAX_STRING_LEN, cmd->config_file))) {
1274 #if RESOLVE_ENV_PER_TOKEN
1275         args = l;
1276 #else
1277         args = ap_resolve_env(cmd->temp_pool, l);
1278 #endif
1279
1280         cmd_name = ap_getword_conf(cmd->pool, &args);
1281         if (cmd_name[0] == '<') {
1282             if (cmd_name[1] == '/') {
1283                 cmd_name[strlen(cmd_name) - 1] = '\0';
1284
1285                 if (strcasecmp(cmd_name + 2, directive + 1) != 0) {
1286                     return apr_pstrcat(cmd->pool, "Expected </",
1287                                        directive + 1, "> but saw ",
1288                                        cmd_name, ">", NULL);
1289                 }
1290
1291                 return NULL; /* found end of container */
1292             }
1293             else {
1294                 const char *msg;
1295
1296                 if (*args == '\0' && cmd_name[strlen(cmd_name) - 1] == '>') {
1297                     cmd_name[strlen(cmd_name) - 1] = '\0';
1298                 }
1299
1300                 if ((msg = ap_soak_end_container(cmd, cmd_name)) != NULL) {
1301                     return msg;
1302                 }
1303             }
1304         }
1305     }
1306
1307     return apr_pstrcat(cmd->pool, "Expected </",
1308                        directive + 1, "> before end of configuration",
1309                        NULL);
1310 }
1311
1312 static const char *execute_now(char *cmd_line, const char *args,
1313                                cmd_parms *parms,
1314                                apr_pool_t *p, apr_pool_t *ptemp,
1315                                ap_directive_t **sub_tree,
1316                                ap_directive_t *parent)
1317 {
1318     module *mod = ap_top_module;
1319     const command_rec *cmd;
1320
1321     if (!(cmd = ap_find_command_in_modules(cmd_line, &mod))) {
1322         return apr_pstrcat(parms->pool, "Invalid command '",
1323                            cmd_line,
1324                            "', perhaps mis-spelled or defined by a module "
1325                            "not included in the server configuration",
1326                            NULL);
1327     }
1328     else {
1329         return invoke_cmd(cmd, parms, sub_tree, args);
1330     }
1331 }
1332
1333 /* This structure and the following functions are needed for the
1334  * table-based config file reading. They are passed to the
1335  * cfg_open_custom() routine.
1336  */
1337
1338 /* Structure to be passed to cfg_open_custom(): it contains an
1339  * index which is incremented from 0 to nelts on each call to
1340  * cfg_getline() (which in turn calls arr_elts_getstr())
1341  * and an apr_array_header_t pointer for the string array.
1342  */
1343 typedef struct {
1344     apr_array_header_t *array;
1345     int curr_idx;
1346 } arr_elts_param_t;
1347
1348
1349 /* arr_elts_getstr() returns the next line from the string array. */
1350 static void *arr_elts_getstr(void *buf, size_t bufsiz, void *param)
1351 {
1352     arr_elts_param_t *arr_param = (arr_elts_param_t *)param;
1353
1354     /* End of array reached? */
1355     if (++arr_param->curr_idx > arr_param->array->nelts)
1356         return NULL;
1357
1358     /* return the line */
1359     apr_cpystrn(buf,
1360                 ((char **)arr_param->array->elts)[arr_param->curr_idx - 1],
1361                 bufsiz);
1362
1363     return buf;
1364 }
1365
1366
1367 /* arr_elts_close(): dummy close routine (makes sure no more lines can be read) */
1368 static int arr_elts_close(void *param)
1369 {
1370     arr_elts_param_t *arr_param = (arr_elts_param_t *)param;
1371
1372     arr_param->curr_idx = arr_param->array->nelts;
1373
1374     return 0;
1375 }
1376
1377 static void process_command_config(server_rec *s, apr_array_header_t *arr,
1378                                    ap_directive_t **conftree, apr_pool_t *p,
1379                                    apr_pool_t *ptemp)
1380 {
1381     const char *errmsg;
1382     cmd_parms parms;
1383     arr_elts_param_t arr_parms;
1384
1385     arr_parms.curr_idx = 0;
1386     arr_parms.array = arr;
1387
1388     parms = default_parms;
1389     parms.pool = p;
1390     parms.temp_pool = ptemp;
1391     parms.server = s;
1392     parms.override = (RSRC_CONF | OR_ALL) & ~(OR_AUTHCFG | OR_LIMIT);
1393
1394     parms.config_file = ap_pcfg_open_custom(p, "-c/-C directives",
1395                                             &arr_parms, NULL,
1396                                             arr_elts_getstr, arr_elts_close);
1397
1398     errmsg = ap_build_config(&parms, p, ptemp, conftree);
1399     if (errmsg) {
1400         ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
1401                      "Syntax error in -C/-c directive:" APR_EOL_STR "%s",
1402                      errmsg);
1403         exit(1);
1404     }
1405
1406     ap_cfg_closefile(parms.config_file);
1407 }
1408
1409 typedef struct {
1410     char *fname;
1411 } fnames;
1412
1413 static int fname_alphasort(const void *fn1, const void *fn2)
1414 {
1415     const fnames *f1 = fn1;
1416     const fnames *f2 = fn2;
1417
1418     return strcmp(f1->fname,f2->fname);
1419 }
1420
1421 static void process_resource_config_nofnmatch(server_rec *s, const char *fname,
1422                                               ap_directive_t **conftree,
1423                                               apr_pool_t *p,
1424                                               apr_pool_t *ptemp)
1425 {
1426     cmd_parms parms;
1427     ap_configfile_t *cfp;
1428     const char *errmsg;
1429
1430     if (ap_is_rdirectory(p, fname)) {
1431         apr_dir_t *dirp;
1432         apr_finfo_t dirent;
1433         int current;
1434         apr_array_header_t *candidates = NULL;
1435         fnames *fnew;
1436         apr_status_t rv;
1437         char errmsg[120], *path = apr_pstrdup(p, fname);
1438
1439         /*
1440          * first course of business is to grok all the directory
1441          * entries here and store 'em away. Recall we need full pathnames
1442          * for this.
1443          */
1444         rv = apr_dir_open(&dirp, path, p);
1445         if (rv != APR_SUCCESS) {
1446             fprintf(stderr, "%s: could not open config directory %s: %s\n",
1447                     ap_server_argv0, path,
1448                     apr_strerror(rv, errmsg, sizeof errmsg));
1449             exit(1);
1450         }
1451
1452         candidates = apr_array_make(p, 1, sizeof(fnames));
1453         while (apr_dir_read(&dirent, APR_FINFO_DIRENT, dirp) == APR_SUCCESS) {
1454             /* strip out '.' and '..' */
1455             if (strcmp(dirent.name, ".")
1456                 && strcmp(dirent.name, "..")) {
1457                 fnew = (fnames *) apr_array_push(candidates);
1458                 fnew->fname = ap_make_full_path(p, path, dirent.name);
1459             }
1460         }
1461
1462         apr_dir_close(dirp);
1463         if (candidates->nelts != 0) {
1464             qsort((void *) candidates->elts, candidates->nelts,
1465                   sizeof(fnames), fname_alphasort);
1466
1467             /*
1468              * Now recurse these... we handle errors and subdirectories
1469              * via the recursion, which is nice
1470              */
1471             for (current = 0; current < candidates->nelts; ++current) {
1472                 fnew = &((fnames *) candidates->elts)[current];
1473                 process_resource_config_nofnmatch(s, fnew->fname, conftree, p,
1474                                                   ptemp);
1475             }
1476         }
1477
1478         return;
1479     }
1480
1481     /* GCC's initialization extensions are soooo nice here... */
1482     parms = default_parms;
1483     parms.pool = p;
1484     parms.temp_pool = ptemp;
1485     parms.server = s;
1486     parms.override = (RSRC_CONF | OR_ALL) & ~(OR_AUTHCFG | OR_LIMIT);
1487
1488     if (ap_pcfg_openfile(&cfp, p, fname) != APR_SUCCESS) {
1489         ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
1490                      "%s: could not open document config file %s",
1491                      ap_server_argv0, fname);
1492         exit(1);
1493     }
1494
1495     parms.config_file = cfp;
1496
1497     errmsg = ap_build_config(&parms, p, ptemp, conftree);
1498
1499     if (errmsg != NULL) {
1500         ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
1501                      "Syntax error on line %d of %s:",
1502                      parms.err_directive->line_num,
1503                      parms.err_directive->filename);
1504         ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
1505                      "%s", errmsg);
1506         exit(1);
1507     }
1508
1509     ap_cfg_closefile(cfp);
1510
1511     return;
1512 }
1513
1514 AP_DECLARE(void) ap_process_resource_config(server_rec *s, const char *fname,
1515                                             ap_directive_t **conftree,
1516                                             apr_pool_t *p,
1517                                             apr_pool_t *ptemp)
1518 {
1519     /* XXX: lstat() won't work on the wildcard pattern...
1520      */
1521
1522     /* don't require conf/httpd.conf if we have a -C or -c switch */
1523     if ((ap_server_pre_read_config->nelts
1524         || ap_server_post_read_config->nelts)
1525         && !(strcmp(fname, ap_server_root_relative(p, SERVER_CONFIG_FILE)))) {
1526         apr_finfo_t finfo;
1527
1528         if (apr_stat(&finfo, fname, APR_FINFO_LINK | APR_FINFO_TYPE, p) != APR_SUCCESS)
1529             return;
1530     }
1531
1532     if (!apr_fnmatch_test(fname)) {
1533         process_resource_config_nofnmatch(s, fname, conftree, p, ptemp);
1534     }
1535     else {
1536         apr_dir_t *dirp;
1537         apr_finfo_t dirent;
1538         int current;
1539         apr_array_header_t *candidates = NULL;
1540         fnames *fnew;
1541         apr_status_t rv;
1542         char errmsg[120], *path = apr_pstrdup(p, fname), *pattern = NULL;
1543
1544         pattern = ap_strrchr(path, '/');
1545
1546         AP_DEBUG_ASSERT(pattern != NULL); /* path must be absolute. */
1547
1548         *pattern++ = '\0';
1549
1550         if (apr_fnmatch_test(path)) {
1551             fprintf(stderr, "%s: wildcard patterns not allowed in Include "
1552                     "%s\n", ap_server_argv0, fname);
1553             exit(1);
1554         }
1555
1556         if (!ap_is_rdirectory(p, path)){ 
1557             fprintf(stderr, "%s: Include directory '%s' not found",
1558                     ap_server_argv0, path);
1559             exit(1);
1560         }
1561
1562         if (!apr_fnmatch_test(pattern)) {
1563             fprintf(stderr, "%s: must include a wildcard pattern "
1564                     "for Include %s\n", ap_server_argv0, fname);
1565             exit(1);
1566         }
1567
1568         /*
1569          * first course of business is to grok all the directory
1570          * entries here and store 'em away. Recall we need full pathnames
1571          * for this.
1572          */
1573         rv = apr_dir_open(&dirp, path, p);
1574         if (rv != APR_SUCCESS) {
1575             fprintf(stderr, "%s: could not open config directory %s: %s\n",
1576                     ap_server_argv0, path,
1577                     apr_strerror(rv, errmsg, sizeof errmsg));
1578             exit(1);
1579         }
1580
1581         candidates = apr_array_make(p, 1, sizeof(fnames));
1582         while (apr_dir_read(&dirent, APR_FINFO_DIRENT, dirp) == APR_SUCCESS) {
1583             /* strip out '.' and '..' */
1584             if (strcmp(dirent.name, ".")
1585                 && strcmp(dirent.name, "..")
1586                 && (apr_fnmatch(pattern, dirent.name,
1587                                 APR_FNM_PERIOD) == APR_SUCCESS)) {
1588                 fnew = (fnames *) apr_array_push(candidates);
1589                 fnew->fname = ap_make_full_path(p, path, dirent.name);
1590             }
1591         }
1592
1593         apr_dir_close(dirp);
1594         if (candidates->nelts != 0) {
1595             qsort((void *) candidates->elts, candidates->nelts,
1596                   sizeof(fnames), fname_alphasort);
1597
1598             /*
1599              * Now recurse these... we handle errors and subdirectories
1600              * via the recursion, which is nice
1601              */
1602             for (current = 0; current < candidates->nelts; ++current) {
1603                 fnew = &((fnames *) candidates->elts)[current];
1604                 process_resource_config_nofnmatch(s, fnew->fname, conftree, p,
1605                                                   ptemp);
1606             }
1607         }
1608     }
1609
1610     return;
1611 }
1612
1613 AP_DECLARE(int) ap_process_config_tree(server_rec *s,
1614                                        ap_directive_t *conftree,
1615                                        apr_pool_t *p,
1616                                        apr_pool_t *ptemp)
1617 {
1618     const char *errmsg;
1619     cmd_parms parms;
1620
1621     parms = default_parms;
1622     parms.pool = p;
1623     parms.temp_pool = ptemp;
1624     parms.server = s;
1625     parms.override = (RSRC_CONF | OR_ALL) & ~(OR_AUTHCFG | OR_LIMIT);
1626     parms.limited = -1;
1627
1628     errmsg = ap_walk_config(conftree, &parms, s->lookup_defaults);
1629     if (errmsg) {
1630         ap_log_perror(APLOG_MARK, APLOG_STARTUP, 0, p,
1631                      "Syntax error on line %d of %s:",
1632                      parms.err_directive->line_num,
1633                      parms.err_directive->filename);
1634         ap_log_perror(APLOG_MARK, APLOG_STARTUP, 0, p,
1635                      "%s", errmsg);
1636         return HTTP_INTERNAL_SERVER_ERROR;
1637     }
1638
1639     return OK;
1640 }
1641
1642 AP_CORE_DECLARE(int) ap_parse_htaccess(ap_conf_vector_t **result,
1643                                        request_rec *r, int override,
1644                                        const char *d, const char *access_name)
1645 {
1646     ap_configfile_t *f = NULL;
1647     cmd_parms parms;
1648     char *filename = NULL;
1649     const struct htaccess_result *cache;
1650     struct htaccess_result *new;
1651     ap_conf_vector_t *dc = NULL;
1652     apr_status_t status;
1653
1654     /* firstly, search cache */
1655     for (cache = r->htaccess; cache != NULL; cache = cache->next) {
1656         if (cache->override == override && strcmp(cache->dir, d) == 0) {
1657             *result = cache->htaccess;
1658             return OK;
1659         }
1660     }
1661
1662     parms = default_parms;
1663     parms.override = override;
1664     parms.pool = r->pool;
1665     parms.temp_pool = r->pool;
1666     parms.server = r->server;
1667     parms.path = apr_pstrdup(r->pool, d);
1668
1669     /* loop through the access names and find the first one */
1670     while (access_name[0]) {
1671         /* AFAICT; there is no use of the actual 'filename' against
1672          * any canonicalization, so we will simply take the given
1673          * name, ignoring case sensitivity and aliases
1674          */
1675         filename = ap_make_full_path(r->pool, d,
1676                                      ap_getword_conf(r->pool, &access_name));
1677         status = ap_pcfg_openfile(&f, r->pool, filename);
1678
1679         if (status == APR_SUCCESS) {
1680             const char *errmsg;
1681             ap_directive_t *temptree = NULL;
1682
1683             dc = ap_create_per_dir_config(r->pool);
1684
1685             parms.config_file = f;
1686             errmsg = ap_build_config(&parms, r->pool, r->pool, &temptree);
1687             if (errmsg == NULL)
1688                 errmsg = ap_walk_config(temptree, &parms, dc);
1689
1690             ap_cfg_closefile(f);
1691
1692             if (errmsg) {
1693                 ap_log_rerror(APLOG_MARK, APLOG_ALERT, 0, r,
1694                               "%s: %s", filename, errmsg);
1695                 return HTTP_INTERNAL_SERVER_ERROR;
1696             }
1697
1698             *result = dc;
1699             break;
1700         }
1701         else {
1702             if (!APR_STATUS_IS_ENOENT(status)
1703                 && !APR_STATUS_IS_ENOTDIR(status)) {
1704                 ap_log_rerror(APLOG_MARK, APLOG_CRIT, status, r,
1705                               "%s pcfg_openfile: unable to check htaccess file, "
1706                               "ensure it is readable",
1707                               filename);
1708                 apr_table_setn(r->notes, "error-notes",
1709                                "Server unable to read htaccess file, denying "
1710                                "access to be safe");
1711                 return HTTP_FORBIDDEN;
1712             }
1713         }
1714     }
1715
1716     /* cache it */
1717     new = apr_palloc(r->pool, sizeof(struct htaccess_result));
1718     new->dir = parms.path;
1719     new->override = override;
1720     new->htaccess = dc;
1721
1722     /* add to head of list */
1723     new->next = r->htaccess;
1724     r->htaccess = new;
1725
1726     return OK;
1727 }
1728
1729 AP_CORE_DECLARE(const char *) ap_init_virtual_host(apr_pool_t *p,
1730                                                    const char *hostname,
1731                                                    server_rec *main_server,
1732                                                    server_rec **ps)
1733 {
1734     server_rec *s = (server_rec *) apr_pcalloc(p, sizeof(server_rec));
1735
1736     /* TODO: this crap belongs in http_core */
1737     s->process = main_server->process;
1738     s->server_admin = NULL;
1739     s->server_hostname = NULL;
1740     s->error_fname = NULL;
1741     s->timeout = 0;
1742     s->keep_alive_timeout = 0;
1743     s->keep_alive = -1;
1744     s->keep_alive_max = -1;
1745     s->error_log = main_server->error_log;
1746     s->loglevel = main_server->loglevel;
1747     /* useful default, otherwise we get a port of 0 on redirects */
1748     s->port = main_server->port;
1749     s->next = NULL;
1750
1751     s->is_virtual = 1;
1752     s->names = apr_array_make(p, 4, sizeof(char **));
1753     s->wild_names = apr_array_make(p, 4, sizeof(char **));
1754
1755     s->module_config = create_empty_config(p);
1756     s->lookup_defaults = ap_create_per_dir_config(p);
1757
1758     s->limit_req_line = main_server->limit_req_line;
1759     s->limit_req_fieldsize = main_server->limit_req_fieldsize;
1760     s->limit_req_fields = main_server->limit_req_fields;
1761
1762     *ps = s;
1763
1764     return ap_parse_vhost_addrs(p, hostname, s);
1765 }
1766
1767
1768 AP_DECLARE(void) ap_fixup_virtual_hosts(apr_pool_t *p, server_rec *main_server)
1769 {
1770     server_rec *virt;
1771
1772     for (virt = main_server->next; virt; virt = virt->next) {
1773         merge_server_configs(p, main_server->module_config,
1774                              virt->module_config);
1775
1776         virt->lookup_defaults =
1777             ap_merge_per_dir_configs(p, main_server->lookup_defaults,
1778                                      virt->lookup_defaults);
1779
1780         if (virt->server_admin == NULL)
1781             virt->server_admin = main_server->server_admin;
1782
1783         if (virt->timeout == 0)
1784             virt->timeout = main_server->timeout;
1785
1786         if (virt->keep_alive_timeout == 0)
1787             virt->keep_alive_timeout = main_server->keep_alive_timeout;
1788
1789         if (virt->keep_alive == -1)
1790             virt->keep_alive = main_server->keep_alive;
1791
1792         if (virt->keep_alive_max == -1)
1793             virt->keep_alive_max = main_server->keep_alive_max;
1794
1795         /* XXX: this is really something that should be dealt with by a
1796          * post-config api phase
1797          */
1798         ap_core_reorder_directories(p, virt);
1799     }
1800
1801     ap_core_reorder_directories(p, main_server);
1802 }
1803
1804 /*****************************************************************
1805  *
1806  * Getting *everything* configured...
1807  */
1808
1809 static void init_config_globals(apr_pool_t *p)
1810 {
1811     /* Global virtual host hash bucket pointers.  Init to null. */
1812     ap_init_vhost_config(p);
1813 }
1814
1815 static server_rec *init_server_config(process_rec *process, apr_pool_t *p)
1816 {
1817     apr_status_t rv;
1818     server_rec *s = (server_rec *) apr_pcalloc(p, sizeof(server_rec));
1819
1820     apr_file_open_stderr(&s->error_log, p);
1821     s->process = process;
1822     s->port = 0;
1823     s->server_admin = DEFAULT_ADMIN;
1824     s->server_hostname = NULL;
1825     s->error_fname = DEFAULT_ERRORLOG;
1826     s->loglevel = DEFAULT_LOGLEVEL;
1827     s->limit_req_line = DEFAULT_LIMIT_REQUEST_LINE;
1828     s->limit_req_fieldsize = DEFAULT_LIMIT_REQUEST_FIELDSIZE;
1829     s->limit_req_fields = DEFAULT_LIMIT_REQUEST_FIELDS;
1830     s->timeout = apr_time_from_sec(DEFAULT_TIMEOUT);
1831     s->keep_alive_timeout = apr_time_from_sec(DEFAULT_KEEPALIVE_TIMEOUT);
1832     s->keep_alive_max = DEFAULT_KEEPALIVE;
1833     s->keep_alive = 1;
1834     s->next = NULL;
1835     s->addrs = apr_pcalloc(p, sizeof(server_addr_rec));
1836
1837     /* NOT virtual host; don't match any real network interface */
1838     rv = apr_sockaddr_info_get(&s->addrs->host_addr,
1839                                NULL, APR_INET, 0, 0, p);
1840     ap_assert(rv == APR_SUCCESS); /* otherwise: bug or no storage */
1841
1842     s->addrs->host_port = 0; /* matches any port */
1843     s->addrs->virthost = ""; /* must be non-NULL */
1844     s->names = s->wild_names = NULL;
1845
1846     s->module_config = create_server_config(p, s);
1847     s->lookup_defaults = create_default_per_dir_config(p);
1848
1849     return s;
1850 }
1851
1852
1853 AP_DECLARE(server_rec*) ap_read_config(process_rec *process, apr_pool_t *ptemp,
1854                                        const char *filename,
1855                                        ap_directive_t **conftree)
1856 {
1857     const char *confname;
1858     apr_pool_t *p = process->pconf;
1859     server_rec *s = init_server_config(process, p);
1860
1861     init_config_globals(p);
1862
1863     /* All server-wide config files now have the SAME syntax... */
1864     process_command_config(s, ap_server_pre_read_config, conftree,
1865                            p, ptemp);
1866
1867     /* process_command_config may change the ServerRoot so
1868      * compute this config file name afterwards.
1869      */
1870     confname = ap_server_root_relative(p, filename);
1871
1872     if (!confname) {
1873         ap_log_error(APLOG_MARK, APLOG_STARTUP|APLOG_CRIT,
1874                      APR_EBADPATH, NULL, "Invalid config file path %s",
1875                      filename);
1876         exit(1);
1877     }
1878
1879     ap_process_resource_config(s, confname, conftree, p, ptemp);
1880
1881     process_command_config(s, ap_server_post_read_config, conftree,
1882                            p, ptemp);
1883
1884     return s;
1885 }
1886
1887 AP_DECLARE(void) ap_single_module_configure(apr_pool_t *p, server_rec *s,
1888                                             module *m)
1889 {
1890     if (m->create_server_config)
1891         ap_set_module_config(s->module_config, m,
1892                              (*m->create_server_config)(p, s));
1893
1894     if (m->create_dir_config)
1895         ap_set_module_config(s->lookup_defaults, m,
1896                              (*m->create_dir_config)(p, NULL));
1897 }
1898
1899 AP_DECLARE(void) ap_run_rewrite_args(process_rec *process)
1900 {
1901     module *m;
1902
1903     for (m = ap_top_module; m; m = m->next) {
1904         if (m->rewrite_args) {
1905             (*m->rewrite_args)(process);
1906         }
1907     }
1908 }
1909
1910 /********************************************************************
1911  * Configuration directives are restricted in terms of where they may
1912  * appear in the main configuration files and/or .htaccess files according
1913  * to the bitmask req_override in the command_rec structure.
1914  * If any of the overrides set in req_override are also allowed in the
1915  * context in which the command is read, then the command is allowed.
1916  * The context is determined as follows:
1917  *
1918  *    inside *.conf --> override = (RSRC_CONF|OR_ALL)&~(OR_AUTHCFG|OR_LIMIT);
1919  *    within <Directory> or <Location> --> override = OR_ALL|ACCESS_CONF;
1920  *    within .htaccess --> override = AllowOverride for current directory;
1921  *
1922  * the result is, well, a rather confusing set of possibilities for when
1923  * a particular directive is allowed to be used.  This procedure prints
1924  * in English where the given (pc) directive can be used.
1925  */
1926 static void show_overrides(const command_rec *pc, module *pm)
1927 {
1928     int n = 0;
1929
1930     printf("\tAllowed in *.conf ");
1931     if ((pc->req_override & (OR_OPTIONS | OR_FILEINFO | OR_INDEXES))
1932         || ((pc->req_override & RSRC_CONF)
1933         && ((pc->req_override & (ACCESS_CONF | OR_AUTHCFG | OR_LIMIT))))) {
1934         printf("anywhere");
1935     }
1936     else if (pc->req_override & RSRC_CONF) {
1937         printf("only outside <Directory>, <Files> or <Location>");
1938     }
1939     else {
1940         printf("only inside <Directory>, <Files> or <Location>");
1941     }
1942
1943     /* Warn if the directive is allowed inside <Directory> or .htaccess
1944      * but module doesn't support per-dir configuration
1945      */
1946     if ((pc->req_override & (OR_ALL | ACCESS_CONF)) && !pm->create_dir_config)
1947         printf(" [no per-dir config]");
1948
1949     if (pc->req_override & OR_ALL) {
1950         printf(" and in .htaccess\n\twhen AllowOverride");
1951
1952         if ((pc->req_override & OR_ALL) == OR_ALL) {
1953             printf(" isn't None");
1954         }
1955         else {
1956             printf(" includes ");
1957
1958             if (pc->req_override & OR_AUTHCFG) {
1959                 if (n++)
1960                     printf(" or ");
1961
1962                 printf("AuthConfig");
1963             }
1964
1965             if (pc->req_override & OR_LIMIT) {
1966                 if (n++)
1967                     printf(" or ");
1968
1969                 printf("Limit");
1970             }
1971
1972             if (pc->req_override & OR_OPTIONS) {
1973                 if (n++)
1974                     printf(" or ");
1975
1976                 printf("Options");
1977             }
1978
1979             if (pc->req_override & OR_FILEINFO) {
1980                 if (n++)
1981                     printf(" or ");
1982
1983                 printf("FileInfo");
1984             }
1985
1986             if (pc->req_override & OR_INDEXES) {
1987                 if (n++)
1988                     printf(" or ");
1989
1990                 printf("Indexes");
1991             }
1992         }
1993     }
1994
1995     printf("\n");
1996 }
1997
1998 /* Show the preloaded configuration directives, the help string explaining
1999  * the directive arguments, in what module they are handled, and in
2000  * what parts of the configuration they are allowed.  Used for httpd -L.
2001  */
2002 AP_DECLARE(void) ap_show_directives(void)
2003 {
2004     const command_rec *pc;
2005     int n;
2006
2007     for (n = 0; ap_loaded_modules[n]; ++n) {
2008         for (pc = ap_loaded_modules[n]->cmds; pc && pc->name; ++pc) {
2009             printf("%s (%s)\n", pc->name, ap_loaded_modules[n]->name);
2010
2011             if (pc->errmsg)
2012                 printf("\t%s\n", pc->errmsg);
2013
2014             show_overrides(pc, ap_loaded_modules[n]);
2015         }
2016     }
2017 }
2018
2019 /* Show the preloaded module names.  Used for httpd -l. */
2020 AP_DECLARE(void) ap_show_modules(void)
2021 {
2022     int n;
2023
2024     printf("Compiled in modules:\n");
2025     for (n = 0; ap_loaded_modules[n]; ++n)
2026         printf("  %s\n", ap_loaded_modules[n]->name);
2027 }
2028
2029 AP_DECLARE(const char *) ap_show_mpm(void)
2030 {
2031     return MPM_NAME;
2032 }