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