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