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