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