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