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