]> granicus.if.org Git - apache/blob - server/config.c
Another one in the department of fairly useless patches which
[apache] / server / config.c
1 /* ====================================================================
2  * Copyright (c) 1995-2000 The Apache Software Foundation.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer. 
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in
13  *    the documentation and/or other materials provided with the
14  *    distribution.
15  *
16  * 3. All advertising materials mentioning features or use of this
17  *    software must display the following acknowledgment:
18  *    "This product includes software developed by the Apache Software Foundation
19  *    for use in the Apache HTTP server project (http://www.apache.org/)."
20  *
21  * 4. The names "Apache Server" and "Apache Software Foundation" must not be used to
22  *    endorse or promote products derived from this software without
23  *    prior written permission. For written permission, please contact
24  *    apache@apache.org.
25  *
26  * 5. Products derived from this software may not be called "Apache"
27  *    nor may "Apache" appear in their names without prior written
28  *    permission of the Apache Software Foundation.
29  *
30  * 6. Redistributions of any form whatsoever must retain the following
31  *    acknowledgment:
32  *    "This product includes software developed by the Apache Software Foundation
33  *    for use in the Apache HTTP server project (http://www.apache.org/)."
34  *
35  * THIS SOFTWARE IS PROVIDED BY THE Apache Software Foundation ``AS IS'' AND ANY
36  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
38  * PURPOSE ARE 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
41  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
42  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
44  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
46  * OF THE POSSIBILITY OF SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Apache Software Foundation and was originally based
51  * on public domain software written at the National Center for
52  * Supercomputing Applications, University of Illinois, Urbana-Champaign.
53  * For more information on the Apache Software Foundation and the Apache HTTP server
54  * project, please see <http://www.apache.org/>.
55  *
56  */
57
58 /*
59  * http_config.c: once was auxillary functions for reading httpd's config
60  * file and converting filenames into a namespace
61  *
62  * Rob McCool 
63  * 
64  * Wall-to-wall rewrite for Apache... commands which are part of the
65  * server core can now be found next door in "http_core.c".  Now contains
66  * general command loop, and functions which do bookkeeping for the new
67  * Apache config stuff (modules and configuration vectors).
68  *
69  * rst
70  *
71  */
72
73 #define CORE_PRIVATE
74
75 #include "ap_config.h"
76 #include "apr_portable.h"
77 #include "apr_file_io.h"
78 #include "httpd.h"
79 #include "http_config.h"
80 #include "http_core.h"
81 #include "http_log.h"           /* for errors in parse_htaccess */
82 #include "http_request.h"       /* for default_handler (see invoke_handler) */
83 #include "http_main.h"
84 #include "http_vhost.h"
85
86 HOOK_STRUCT(
87             HOOK_LINK(header_parser)
88             HOOK_LINK(pre_config)
89             HOOK_LINK(post_config)
90             HOOK_LINK(open_logs)
91             HOOK_LINK(child_init)
92 )
93
94 IMPLEMENT_HOOK_RUN_ALL(int,header_parser,(request_rec *r),(r),OK,DECLINED)
95 IMPLEMENT_HOOK_VOID(pre_config,(ap_context_t *pconf,ap_context_t *plog,ap_context_t *ptemp),
96                     (pconf,plog,ptemp))
97 IMPLEMENT_HOOK_VOID(post_config,
98                     (ap_context_t *pconf, ap_context_t *plog, ap_context_t *ptemp, server_rec *s),
99                     (pconf,plog,ptemp,s))
100 IMPLEMENT_HOOK_VOID(open_logs,
101                     (ap_context_t *pconf, ap_context_t *plog, ap_context_t *ptemp, server_rec *s),
102                     (pconf,plog,ptemp,s))
103 IMPLEMENT_HOOK_VOID(child_init,(ap_context_t *pchild, server_rec *s),(pchild,s))
104
105 /****************************************************************
106  *
107  * We begin with the functions which deal with the linked list
108  * of modules which control just about all of the server operation.
109  */
110
111 /* total_modules is the number of modules that have been linked
112  * into the server.
113  */
114 static int total_modules = 0;
115 /* dynamic_modules is the number of modules that have been added
116  * after the pre-loaded ones have been set up. It shouldn't be larger
117  * than DYNAMIC_MODULE_LIMIT.
118  */
119 static int dynamic_modules = 0;
120 API_VAR_EXPORT module *top_module = NULL;
121 API_VAR_EXPORT module **ap_loaded_modules=NULL;
122
123 typedef int (*handler_func) (request_rec *);
124 typedef void *(*dir_maker_func) (ap_context_t *, char *);
125 typedef void *(*merger_func) (ap_context_t *, void *, void *);
126
127 /* Dealing with config vectors.  These are associated with per-directory,
128  * per-server, and per-request configuration, and have a void* pointer for
129  * each modules.  The nature of the structure pointed to is private to the
130  * module in question... the core doesn't (and can't) know.  However, there
131  * are defined interfaces which allow it to create instances of its private
132  * per-directory and per-server structures, and to merge the per-directory
133  * structures of a directory and its subdirectory (producing a new one in
134  * which the defaults applying to the base directory have been properly
135  * overridden).
136  */
137
138 #ifndef ap_get_module_config
139 API_EXPORT(void *) ap_get_module_config(void *conf_vector, module *m)
140 {
141     void **confv = (void **) conf_vector;
142     return confv[m->module_index];
143 }
144 #endif
145
146 #ifndef ap_set_module_config
147 API_EXPORT(void) ap_set_module_config(void *conf_vector, module *m, void *val)
148 {
149     void **confv = (void **) conf_vector;
150     confv[m->module_index] = val;
151 }
152 #endif
153
154 static void *create_empty_config(ap_context_t *p)
155 {
156     void **conf_vector = (void **) ap_pcalloc(p, sizeof(void *) *
157                                     (total_modules + DYNAMIC_MODULE_LIMIT));
158     return (void *) conf_vector;
159 }
160
161 static void *create_default_per_dir_config(ap_context_t *p)
162 {
163     void **conf_vector = (void **) ap_pcalloc(p, sizeof(void *) * (total_modules + DYNAMIC_MODULE_LIMIT));
164     module *modp;
165
166     for (modp = top_module; modp; modp = modp->next) {
167         dir_maker_func df = modp->create_dir_config;
168
169         if (df)
170             conf_vector[modp->module_index] = (*df) (p, NULL);
171     }
172
173     return (void *) conf_vector;
174 }
175
176 void *
177      ap_merge_per_dir_configs(ap_context_t *p, void *base, void *new)
178 {
179     void **conf_vector = (void **) ap_palloc(p, sizeof(void *) * total_modules);
180     void **base_vector = (void **) base;
181     void **new_vector = (void **) new;
182     module *modp;
183
184     for (modp = top_module; modp; modp = modp->next) {
185         merger_func df = modp->merge_dir_config;
186         int i = modp->module_index;
187
188         if (df && new_vector[i])
189             conf_vector[i] = (*df) (p, base_vector[i], new_vector[i]);
190         else
191             conf_vector[i] = new_vector[i] ? new_vector[i] : base_vector[i];
192     }
193
194     return (void *) conf_vector;
195 }
196
197 static void *create_server_config(ap_context_t *p, server_rec *s)
198 {
199     void **conf_vector = (void **) ap_pcalloc(p, sizeof(void *) * (total_modules + DYNAMIC_MODULE_LIMIT));
200     module *modp;
201
202     for (modp = top_module; modp; modp = modp->next) {
203         if (modp->create_server_config)
204             conf_vector[modp->module_index] = (*modp->create_server_config) (p, s);
205     }
206
207     return (void *) conf_vector;
208 }
209
210 static void merge_server_configs(ap_context_t *p, void *base, void *virt)
211 {
212     /* Can reuse the 'virt' vector for the spine of it, since we don't
213      * have to deal with the moral equivalent of .htaccess files here...
214      */
215
216     void **base_vector = (void **) base;
217     void **virt_vector = (void **) virt;
218     module *modp;
219
220     for (modp = top_module; modp; modp = modp->next) {
221         merger_func df = modp->merge_server_config;
222         int i = modp->module_index;
223
224         if (!virt_vector[i])
225             virt_vector[i] = base_vector[i];
226         else if (df)
227             virt_vector[i] = (*df) (p, base_vector[i], virt_vector[i]);
228     }
229 }
230
231 void *ap_create_request_config(ap_context_t *p)
232 {
233     return create_empty_config(p);
234 }
235
236 void *ap_create_conn_config(ap_context_t *p)
237 {
238     return create_empty_config(p);
239 }
240
241 CORE_EXPORT(void *) ap_create_per_dir_config(ap_context_t *p)
242 {
243     return create_empty_config(p);
244 }
245
246 /*
247  * For speed/efficiency we generate a compact list of all the handlers
248  * and wildcard handlers.  This means we won't have to scan the entire
249  * module list looking for handlers... where we'll find a whole whack
250  * of NULLs.
251  */
252 typedef struct {
253     handler_rec hr;
254     size_t len;
255 } fast_handler_rec;
256
257 static fast_handler_rec *handlers;
258 static fast_handler_rec *wildhandlers;
259
260 static void init_handlers(ap_context_t *p)
261 {
262     module *modp;
263     int nhandlers = 0;
264     int nwildhandlers = 0;
265     const handler_rec *handp;
266     fast_handler_rec *ph, *pw;
267     char *starp;
268
269     for (modp = top_module; modp; modp = modp->next) {
270         if (!modp->handlers)
271             continue;
272         for (handp = modp->handlers; handp->content_type; ++handp) {
273             if (strchr(handp->content_type, '*')) {
274                 nwildhandlers ++;
275             } else {
276                 nhandlers ++;
277             }
278         }
279     }
280     ph = handlers = ap_palloc(p, sizeof(*ph)*(nhandlers + 1));
281     pw = wildhandlers = ap_palloc(p, sizeof(*pw)*(nwildhandlers + 1));
282     for (modp = top_module; modp; modp = modp->next) {
283         if (!modp->handlers)
284             continue;
285         for (handp = modp->handlers; handp->content_type; ++handp) {
286             if ((starp = strchr(handp->content_type, '*'))) {
287                 pw->hr.content_type = handp->content_type;
288                 pw->hr.handler = handp->handler;
289                 pw->len = starp - handp->content_type;
290                 pw ++;
291             } else {
292                 ph->hr.content_type = handp->content_type;
293                 ph->hr.handler = handp->handler;
294                 ph->len = strlen(handp->content_type);
295                 ph ++;
296             }
297         }
298     }
299     pw->hr.content_type = NULL;
300     pw->hr.handler = NULL;
301     ph->hr.content_type = NULL;
302     ph->hr.handler = NULL;
303 }
304
305 int ap_invoke_handler(request_rec *r)
306 {
307     fast_handler_rec *handp;
308     const char *handler;
309     char *p;
310     size_t handler_len;
311     int result = HTTP_INTERNAL_SERVER_ERROR;
312
313     if (r->handler) {
314         handler = r->handler;
315         handler_len = strlen(handler);
316     }
317     else {
318         handler = r->content_type ? r->content_type : ap_default_type(r);
319         if ((p = strchr(handler, ';')) != NULL) { /* MIME type arguments */
320             while (p > handler && p[-1] == ' ')
321                 --p;            /* strip trailing spaces */
322             handler_len = p - handler;
323         }
324         else {
325             handler_len = strlen(handler);
326         }
327     }
328
329     /* Pass one --- direct matches */
330
331     for (handp = handlers; handp->hr.content_type; ++handp) {
332         if (handler_len == handp->len
333             && !strncmp(handler, handp->hr.content_type, handler_len)) {
334             result = (*handp->hr.handler) (r);
335
336             if (result != DECLINED)
337                 return result;
338         }
339     }
340
341     /* Pass two --- wildcard matches */
342
343     for (handp = wildhandlers; handp->hr.content_type; ++handp) {
344         if (handler_len >= handp->len
345             && !strncmp(handler, handp->hr.content_type, handp->len)) {
346              result = (*handp->hr.handler) (r);
347
348              if (result != DECLINED)
349                  return result;
350          }
351     }
352
353     if (result == HTTP_INTERNAL_SERVER_ERROR && r->handler && r->filename) {
354         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
355             "handler \"%s\" not found for: %s", r->handler, r->filename);
356     }
357     return HTTP_INTERNAL_SERVER_ERROR;
358 }
359
360 int g_bDebugHooks;
361 const char *g_szCurrentHookName;
362
363 static void register_hooks(module *m)
364     {
365     if(m->register_hooks)
366         {
367         if(getenv("SHOW_HOOKS"))
368             {
369             printf("Registering hooks for %s\n",m->name);
370             g_bDebugHooks=1;
371             }
372         g_szCurrentHookName=m->name;
373         m->register_hooks();
374         }
375     }
376
377 /* One-time setup for precompiled modules --- NOT to be done on restart */
378
379 API_EXPORT(void) ap_add_module(module *m)
380 {
381     /* This could be called from an AddModule httpd.conf command,
382      * after the file has been linked and the module structure within it
383      * teased out...
384      */
385
386     if (m->version != MODULE_MAGIC_NUMBER_MAJOR) {
387         ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
388                      "%s: module \"%s\" is not compatible with this "
389                      "version of Apache.", ap_server_argv0, m->name);
390         ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "Please contact the vendor for the correct version.");
391         exit(1);
392     }
393
394     if (m->next == NULL) {
395         m->next = top_module;
396         top_module = m;
397     }
398     if (m->module_index == -1) {
399         m->module_index = total_modules++;
400         dynamic_modules++;
401
402         if (dynamic_modules > DYNAMIC_MODULE_LIMIT) {
403             ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
404                          "%s: module \"%s\" could not be loaded, because"
405                          " the dynamic", ap_server_argv0, m->name);
406             ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
407                          "module limit was reached. Please increase "
408                          "DYNAMIC_MODULE_LIMIT and recompile.");
409             exit(1);
410         }
411     }
412
413     /* Some C compilers put a complete path into __FILE__, but we want
414      * only the filename (e.g. mod_includes.c). So check for path
415      * components (Unix and DOS), and remove them.
416      */
417
418     if (strrchr(m->name, '/'))
419         m->name = 1 + strrchr(m->name, '/');
420     if (strrchr(m->name, '\\'))
421         m->name = 1 + strrchr(m->name, '\\');
422
423 #ifdef _OSD_POSIX /* __FILE__="*POSIX(/home/martin/apache/src/modules/standard/mod_info.c)" */
424     /* We cannot fix the string in-place, because it's const */
425     if (m->name[strlen(m->name)-1]==')') {
426         char *tmp = strdup(m->name);    /* FIXME:memory leak, albeit a small one */
427         tmp[strlen(tmp)-1] = '\0';
428         m->name = tmp;
429     }
430 #endif /*_OSD_POSIX*/
431
432     /* FIXME: is this the right place to call this? */
433     register_hooks(m);
434 }
435
436 /* 
437  * remove_module undoes what add_module did. There are some caveats:
438  * when the module is removed, its slot is lost so all the current
439  * per-dir and per-server configurations are invalid. So we should
440  * only ever call this function when you are invalidating almost
441  * all our current data. I.e. when doing a restart.
442  */
443
444 API_EXPORT(void) ap_remove_module(module *m)
445 {
446     module *modp;
447
448     modp = top_module;
449     if (modp == m) {
450         /* We are the top module, special case */
451         top_module = modp->next;
452         m->next = NULL;
453     }
454     else {
455         /* Not the top module, find use. When found modp will
456          * point to the module _before_ us in the list
457          */
458
459         while (modp && modp->next != m) {
460             modp = modp->next;
461         }
462         if (!modp) {
463             /* Uh-oh, this module doesn't exist */
464             ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, NULL,
465                 "Cannot remove module %s: not found in module list",
466                 m->name);
467             return;
468         }
469         /* Eliminate us from the module list */
470         modp->next = modp->next->next;
471     }
472
473     m->module_index = -1;       /* simulate being unloaded, should
474                                  * be unnecessary */
475     dynamic_modules--;
476     total_modules--;
477 }
478
479 API_EXPORT(void) ap_add_loaded_module(module *mod)
480 {
481     module **m;
482
483     /* 
484      *  Add module pointer to top of chained module list 
485      */
486     ap_add_module(mod);
487
488     /* 
489      *  And module pointer to list of loaded modules 
490      *
491      *  Notes: 1. ap_add_module() would already complain if no more space
492      *            exists for adding a dynamically loaded module
493      *         2. ap_add_module() accepts double inclusion, so we have
494      *            to accept this, too.
495      */
496     for (m = ap_loaded_modules; *m != NULL; m++)
497         ;
498     *m++ = mod;
499     *m = NULL;
500 }
501
502 API_EXPORT(void) ap_remove_loaded_module(module *mod)
503 {
504     module **m;
505     module **m2;
506     int done;
507
508     /* 
509      *  Remove module pointer from chained module list 
510      */
511     ap_remove_module(mod);
512
513     /* 
514      *  Remove module pointer from list of loaded modules
515      *
516      *  Note: 1. We cannot determine if the module was successfully
517      *           removed by ap_remove_module().
518      *        2. We have not to complain explicity when the module
519      *           is not found because ap_remove_module() did it
520      *           for us already.
521      */
522     for (m = m2 = ap_loaded_modules, done = 0; *m2 != NULL; m2++) {
523         if (*m2 == mod && done == 0)
524             done = 1;
525         else
526             *m++ = *m2;
527     }
528     *m = NULL;
529 }
530
531 void ap_setup_prelinked_modules(process_rec *process)
532 {
533     module **m;
534     module **m2;
535
536     /*
537      *  Initialise total_modules variable and module indices
538      */
539     total_modules = 0;
540     for (m = ap_preloaded_modules; *m != NULL; m++)
541         (*m)->module_index = total_modules++;
542
543     /* 
544      *  Initialise list of loaded modules
545      */
546     ap_loaded_modules = (module **)ap_palloc(process->pool,
547         sizeof(module *)*(total_modules+DYNAMIC_MODULE_LIMIT+1));
548     if (ap_loaded_modules == NULL) {
549         ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
550                      "Ouch!  Out of memory in ap_setup_prelinked_modules()!");
551     }
552     for (m = ap_preloaded_modules, m2 = ap_loaded_modules; *m != NULL; )
553         *m2++ = *m++;
554     *m2 = NULL;
555
556     /*
557      *   Initialize chain of linked (=activate) modules
558      */
559     for (m = ap_prelinked_modules; *m != NULL; m++)
560         ap_add_module(*m);
561
562     ap_sort_hooks();
563 }
564
565 API_EXPORT(const char *) ap_find_module_name(module *m)
566 {
567     return m->name;
568 }
569
570 API_EXPORT(module *) ap_find_linked_module(const char *name)
571 {
572     module *modp;
573
574     for (modp = top_module; modp; modp = modp->next) {
575         if (strcmp(modp->name, name) == 0)
576             return modp;
577     }
578     return NULL;
579 }
580
581 /* Add a named module.  Returns 1 if module found, 0 otherwise.  */
582 API_EXPORT(int) ap_add_named_module(const char *name)
583 {
584     module *modp;
585     int i = 0;
586
587     for (modp = ap_loaded_modules[i]; modp; modp = ap_loaded_modules[++i]) {
588         if (strcmp(modp->name, name) == 0) {
589             /* Only add modules that are not already enabled.  */
590             if (modp->next == NULL) {
591                 ap_add_module(modp);
592             }
593             return 1;
594         }
595     }
596
597     return 0;
598 }
599
600 /* Clear the internal list of modules, in preparation for starting over. */
601 API_EXPORT(void) ap_clear_module_list()
602 {
603     module **m = &top_module;
604     module **next_m;
605
606     while (*m) {
607         next_m = &((*m)->next);
608         *m = NULL;
609         m = next_m;
610     }
611
612     /* This is required; so we add it always.  */
613     ap_add_named_module("http_core.c");
614 }
615
616 /*****************************************************************
617  *
618  * Resource, access, and .htaccess config files now parsed by a common
619  * command loop.
620  *
621  * Let's begin with the basics; parsing the line and
622  * invoking the function...
623  */
624
625 static const char *invoke_cmd(const command_rec *cmd, cmd_parms *parms,
626                             void *mconfig, const char *args)
627 {
628     char *w, *w2, *w3;
629     const char *errmsg;
630
631     if ((parms->override & cmd->req_override) == 0)
632         return ap_pstrcat(parms->pool, cmd->name, " not allowed here", NULL);
633
634     parms->info = cmd->cmd_data;
635     parms->cmd = cmd;
636
637     switch (cmd->args_how) {
638     case RAW_ARGS:
639 #ifdef RESOLVE_ENV_PER_TOKEN
640         args = ap_resolve_env(parms->pool,args);
641 #endif
642         return ((const char *(*)(cmd_parms *, void *, const char *))
643                 (cmd->func)) (parms, mconfig, args);
644
645     case NO_ARGS:
646         if (*args != 0)
647             return ap_pstrcat(parms->pool, cmd->name, " takes no arguments",
648                            NULL);
649
650         return ((const char *(*)(cmd_parms *, void *))
651                 (cmd->func)) (parms, mconfig);
652
653     case TAKE1:
654         w = ap_getword_conf(parms->pool, &args);
655
656         if (*w == '\0' || *args != 0)
657             return ap_pstrcat(parms->pool, cmd->name, " takes one argument",
658                             cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
659
660         return ((const char *(*)(cmd_parms *, void *, const char *))
661                 (cmd->func)) (parms, mconfig, w);
662
663     case TAKE2:
664
665         w = ap_getword_conf(parms->pool, &args);
666         w2 = ap_getword_conf(parms->pool, &args);
667
668         if (*w == '\0' || *w2 == '\0' || *args != 0)
669             return ap_pstrcat(parms->pool, cmd->name, " takes two arguments",
670                             cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
671
672         return ((const char *(*)(cmd_parms *, void *, const char *,
673                         const char *)) (cmd->func)) (parms, mconfig, w, w2);
674
675     case TAKE12:
676
677         w = ap_getword_conf(parms->pool, &args);
678         w2 = ap_getword_conf(parms->pool, &args);
679
680         if (*w == '\0' || *args != 0)
681             return ap_pstrcat(parms->pool, cmd->name, " takes 1-2 arguments",
682                             cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
683
684         return ((const char *(*)(cmd_parms *, void *, const char *,
685                             const char *)) (cmd->func)) (parms, mconfig, w,
686                                                             *w2 ? w2 : NULL);
687
688     case TAKE3:
689
690         w = ap_getword_conf(parms->pool, &args);
691         w2 = ap_getword_conf(parms->pool, &args);
692         w3 = ap_getword_conf(parms->pool, &args);
693
694         if (*w == '\0' || *w2 == '\0' || *w3 == '\0' || *args != 0)
695             return ap_pstrcat(parms->pool, cmd->name, " takes three arguments",
696                             cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
697
698         return ((const char *(*)(cmd_parms *, void *, const char *,
699                             const char *, const char *)) (cmd->func)) (parms,
700                                                         mconfig, w, w2, w3);
701
702     case TAKE23:
703
704         w = ap_getword_conf(parms->pool, &args);
705         w2 = ap_getword_conf(parms->pool, &args);
706         w3 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
707
708         if (*w == '\0' || *w2 == '\0' || *args != 0)
709             return ap_pstrcat(parms->pool, cmd->name,
710                             " takes two or three arguments",
711                             cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
712
713         return ((const char *(*)(cmd_parms *, void *, const char *,
714                             const char *, const char *)) (cmd->func)) (parms,
715                                                         mconfig, w, w2, w3);
716
717     case TAKE123:
718
719         w = ap_getword_conf(parms->pool, &args);
720         w2 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
721         w3 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
722
723         if (*w == '\0' || *args != 0)
724             return ap_pstrcat(parms->pool, cmd->name,
725                             " takes one, two or three arguments",
726                             cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
727
728         return ((const char *(*)(cmd_parms *, void *, const char *,
729                             const char *, const char *)) (cmd->func)) (parms,
730                                                         mconfig, w, w2, w3);
731
732     case TAKE13:
733
734         w = ap_getword_conf(parms->pool, &args);
735         w2 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
736         w3 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
737
738         if (*w == '\0' || (*w2 && !w3) || *args != 0)
739             return ap_pstrcat(parms->pool, cmd->name,
740                             " takes one or three arguments",
741                             cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
742
743         return ((const char *(*)(cmd_parms *, void *, const char *,
744                             const char *, const char *)) (cmd->func)) (parms,
745                                                         mconfig, w, w2, w3);
746
747     case ITERATE:
748
749         while (*(w = ap_getword_conf(parms->pool, &args)) != '\0')
750         if   ((errmsg = ((const char *(*)(cmd_parms *, void *,
751                         const char *)) (cmd->func)) (parms, mconfig, w)))
752                     return errmsg;
753
754         return NULL;
755
756     case ITERATE2:
757
758         w = ap_getword_conf(parms->pool, &args);
759
760         if (*w == '\0' || *args == 0)
761             return ap_pstrcat(parms->pool, cmd->name,
762                             " requires at least two arguments",
763                             cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
764
765
766         while (*(w2 = ap_getword_conf(parms->pool, &args)) != '\0')
767             if   ((errmsg = ((const char *(*)(cmd_parms *, void *,
768                             const char *, const char *)) (cmd->func)) (parms,
769                                                             mconfig, w, w2)))
770                         return errmsg;
771
772         return NULL;
773
774     case FLAG:
775
776         w = ap_getword_conf(parms->pool, &args);
777
778         if (*w == '\0' || (strcasecmp(w, "on") && strcasecmp(w, "off")))
779             return ap_pstrcat(parms->pool, cmd->name, " must be On or Off",
780                             NULL);
781
782         return ((const char *(*)(cmd_parms *, void *, int))
783                 (cmd->func)) (parms, mconfig, strcasecmp(w, "off") != 0);
784
785     default:
786
787         return ap_pstrcat(parms->pool, cmd->name,
788                     " is improperly configured internally (server bug)",
789                         NULL);
790     }
791 }
792
793 CORE_EXPORT(const command_rec *) ap_find_command(const char *name, const command_rec *cmds)
794 {
795     while (cmds->name)
796         if (!strcasecmp(name, cmds->name))
797             return cmds;
798         else
799             ++cmds;
800
801     return NULL;
802 }
803
804 CORE_EXPORT(const command_rec *) ap_find_command_in_modules(const char *cmd_name, module **mod)
805 {
806     const command_rec *cmdp;
807     module *modp;
808
809     for (modp = *mod; modp; modp = modp->next)
810         if (modp->cmds && (cmdp = ap_find_command(cmd_name, modp->cmds))) {
811             *mod = modp;
812             return cmdp;
813         }
814
815     return NULL;
816 }
817
818 CORE_EXPORT(void *) ap_set_config_vectors(cmd_parms *parms, void *config, module *mod)
819 {
820     void *mconfig = ap_get_module_config(config, mod);
821     void *sconfig = ap_get_module_config(parms->server->module_config, mod);
822
823     if (!mconfig && mod->create_dir_config) {
824         mconfig = (*mod->create_dir_config) (parms->pool, parms->path);
825         ap_set_module_config(config, mod, mconfig);
826     }
827
828     if (!sconfig && mod->create_server_config) {
829         sconfig = (*mod->create_server_config) (parms->pool, parms->server);
830         ap_set_module_config(parms->server->module_config, mod, sconfig);
831     }
832     return mconfig;
833 }
834
835
836 CORE_EXPORT(const char *) ap_handle_command(cmd_parms *parms, void *config, const char *l)
837 {
838     void *oldconfig;
839     const char *args, *cmd_name, *retval;
840     const command_rec *cmd;
841     module *mod = top_module;
842
843     if ((l[0] == '#') || (!l[0]))
844         return NULL;
845
846 #if RESOLVE_ENV_PER_TOKEN
847     args = l;
848 #else
849     args = ap_resolve_env(parms->temp_pool,l); 
850 #endif
851     cmd_name = ap_getword_conf(parms->temp_pool, &args);
852     if (*cmd_name == '\0')
853         return NULL;
854
855     oldconfig = parms->context;
856     parms->context = config;
857     do {
858         if (!(cmd = ap_find_command_in_modules(cmd_name, &mod))) {
859             errno = EINVAL;
860             return ap_pstrcat(parms->pool, "Invalid command '", cmd_name,
861                            "', perhaps mis-spelled or defined by a module "
862                            "not included in the server configuration", NULL);
863         }
864         else {
865             void *mconfig = ap_set_config_vectors(parms,config, mod);
866
867             retval = invoke_cmd(cmd, parms, mconfig, args);
868             mod = mod->next;    /* Next time around, skip this one */
869         }
870     } while (retval && !strcmp(retval, DECLINE_CMD));
871     parms->context = oldconfig;
872
873     return retval;
874 }
875
876 API_EXPORT(const char *) ap_srm_command_loop(cmd_parms *parms, void *config)
877 {
878     char l[MAX_STRING_LEN];
879
880     while (!(ap_cfg_getline(l, MAX_STRING_LEN, parms->config_file))) {
881         const char *errmsg = ap_handle_command(parms, config, l);
882         if (errmsg) {
883             return errmsg;
884         }
885     }
886
887     return NULL;
888 }
889
890 /*
891  * Generic command functions...
892  */
893
894 API_EXPORT_NONSTD(const char *) ap_set_string_slot(cmd_parms *cmd,
895                                                 char *struct_ptr, char *arg)
896 {
897     /* This one's pretty generic... */
898
899     int offset = (int) (long) cmd->info;
900     *(char **) (struct_ptr + offset) = arg;
901     return NULL;
902 }
903
904 API_EXPORT_NONSTD(const char *) ap_set_string_slot_lower(cmd_parms *cmd,
905                                                 char *struct_ptr, char *arg)
906 {
907     /* This one's pretty generic... */
908
909     int offset = (int) (long) cmd->info;
910     ap_str_tolower(arg);
911     *(char **) (struct_ptr + offset) = arg;
912     return NULL;
913 }
914
915 API_EXPORT_NONSTD(const char *) ap_set_flag_slot(cmd_parms *cmd,
916                                               char *struct_ptr, int arg)
917 {
918     /* This one's pretty generic too... */
919
920     int offset = (int) (long) cmd->info;
921     *(int *) (struct_ptr + offset) = arg ? 1 : 0;
922     return NULL;
923 }
924
925 API_EXPORT_NONSTD(const char *) ap_set_file_slot(cmd_parms *cmd, char *struct_ptr, char *arg)
926 {
927     /* Prepend server_root to relative arg.
928        This allows .htaccess to be independent of server_root,
929        so the server can be moved or mirrored with less pain.  */
930     char *p;
931     int offset = (int) (long) cmd->info;
932     if (ap_os_is_path_absolute(arg))
933         p = arg;
934     else
935         p = ap_make_full_path(cmd->pool, ap_server_root, arg);
936     *(char **) (struct_ptr + offset) = p;
937     return NULL;
938 }
939
940 /*****************************************************************
941  *
942  * Reading whole config files...
943  */
944
945 static cmd_parms default_parms =
946 {NULL, 0, -1, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
947
948 API_EXPORT(const char *) ap_server_root_relative(ap_context_t *p, const char *file)
949 {
950     if(ap_os_is_path_absolute(file))
951         return file;
952     return ap_make_full_path(p, ap_server_root, file);
953 }
954
955
956 /* This structure and the following functions are needed for the
957  * table-based config file reading. They are passed to the
958  * cfg_open_custom() routine.
959  */
960
961 /* Structure to be passed to cfg_open_custom(): it contains an
962  * index which is incremented from 0 to nelts on each call to
963  * cfg_getline() (which in turn calls arr_elts_getstr())
964  * and an ap_array_header_t pointer for the string array.
965  */
966 typedef struct {
967     ap_array_header_t *array;
968     int curr_idx;
969 } arr_elts_param_t;
970
971
972 /* arr_elts_getstr() returns the next line from the string array. */
973 static void *arr_elts_getstr(void *buf, size_t bufsiz, void *param)
974 {
975     arr_elts_param_t *arr_param = (arr_elts_param_t *) param;
976
977     /* End of array reached? */
978     if (++arr_param->curr_idx > arr_param->array->nelts)
979         return NULL;
980
981     /* return the line */
982     ap_cpystrn(buf, ((char **) arr_param->array->elts)[arr_param->curr_idx - 1], bufsiz);
983
984     return buf;
985 }
986
987
988 /* arr_elts_close(): dummy close routine (makes sure no more lines can be read) */
989 static int arr_elts_close(void *param)
990 {
991     arr_elts_param_t *arr_param = (arr_elts_param_t *) param;
992     arr_param->curr_idx = arr_param->array->nelts;
993     return 0;
994 }
995
996 static void process_command_config(server_rec *s, ap_array_header_t *arr, ap_context_t *p,
997                                     ap_context_t *ptemp)
998 {
999     const char *errmsg;
1000     cmd_parms parms;
1001     arr_elts_param_t arr_parms;
1002
1003     arr_parms.curr_idx = 0;
1004     arr_parms.array = arr;
1005
1006     parms = default_parms;
1007     parms.pool = p;
1008     parms.temp_pool = ptemp;
1009     parms.server = s;
1010     parms.override = (RSRC_CONF | OR_ALL) & ~(OR_AUTHCFG | OR_LIMIT);
1011     parms.config_file = ap_pcfg_open_custom(p, "-c/-C directives",
1012                                          &arr_parms, NULL,
1013                                          arr_elts_getstr, arr_elts_close);
1014
1015     errmsg = ap_srm_command_loop(&parms, s->lookup_defaults);
1016
1017     if (errmsg) {
1018         ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
1019                      "Syntax error in -C/-c directive:\n%s", errmsg);
1020         exit(1);
1021     }
1022
1023     ap_cfg_closefile(parms.config_file);
1024 }
1025
1026 void ap_process_resource_config(server_rec *s, const char *fname, ap_context_t *p, ap_context_t *ptemp)
1027 {
1028     const char *errmsg;
1029     cmd_parms parms;
1030     ap_finfo_t finfo;
1031
1032     fname = ap_server_root_relative(p, fname);
1033
1034     if (!(strcmp(fname, ap_server_root_relative(p, RESOURCE_CONFIG_FILE))) ||
1035         !(strcmp(fname, ap_server_root_relative(p, ACCESS_CONFIG_FILE)))) {
1036         if (ap_stat(&finfo, fname, p) != APR_SUCCESS)   
1037             return;
1038     }
1039
1040     /* don't require conf/httpd.conf if we have a -C or -c switch */
1041     if((ap_server_pre_read_config->nelts || ap_server_post_read_config->nelts) &&
1042        !(strcmp(fname, ap_server_root_relative(p, SERVER_CONFIG_FILE)))) {
1043         if (ap_stat(&finfo, fname, p) != APR_SUCCESS)     
1044             return;
1045     }
1046
1047     /* GCC's initialization extensions are soooo nice here... */
1048
1049     parms = default_parms;
1050     parms.pool = p;
1051     parms.temp_pool = ptemp;
1052     parms.server = s;
1053     parms.override = (RSRC_CONF | OR_ALL) & ~(OR_AUTHCFG | OR_LIMIT);
1054
1055     if (ap_pcfg_openfile(&parms.config_file, p, fname) != APR_SUCCESS) {
1056         ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
1057                      "%s: could not open document config file %s",
1058                      ap_server_argv0, fname);
1059         exit(1);
1060     }
1061
1062     errmsg = ap_srm_command_loop(&parms, s->lookup_defaults);
1063
1064     if (errmsg) {
1065         ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
1066                      "Syntax error on line %d of %s:",
1067                      parms.config_file->line_number, parms.config_file->name);
1068         ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1069                      "%s", errmsg);
1070         exit(1);
1071     }
1072
1073     ap_cfg_closefile(parms.config_file);
1074 }
1075
1076
1077 int ap_parse_htaccess(void **result, request_rec *r, int override,
1078                    const char *d, const char *access_name)
1079 {
1080     configfile_t *f = NULL;
1081     cmd_parms parms;
1082     const char *errmsg;
1083     char *filename = NULL;
1084     const struct htaccess_result *cache;
1085     struct htaccess_result *new;
1086     void *dc = NULL;
1087     ap_status_t status;
1088
1089 /* firstly, search cache */
1090     for (cache = r->htaccess; cache != NULL; cache = cache->next)
1091         if (cache->override == override && strcmp(cache->dir, d) == 0) {
1092             if (cache->htaccess != NULL)
1093                 *result = cache->htaccess;
1094             return OK;
1095         }
1096
1097     parms = default_parms;
1098     parms.override = override;
1099     parms.pool = r->pool;
1100     parms.temp_pool = r->pool;
1101     parms.server = r->server;
1102     parms.path = ap_pstrdup(r->pool, d);
1103
1104     /* loop through the access names and find the first one */
1105
1106     while (access_name[0]) {
1107         filename = ap_make_full_path(r->pool, d,
1108                                      ap_getword_conf(r->pool, &access_name));
1109         status = ap_pcfg_openfile(&f, r->pool, filename);
1110
1111         if (status == APR_SUCCESS) {
1112
1113             dc = ap_create_per_dir_config(r->pool);
1114
1115             parms.config_file = f;
1116
1117             errmsg = ap_srm_command_loop(&parms, dc);
1118
1119             ap_cfg_closefile(f);
1120
1121             if (errmsg) {
1122                 ap_log_rerror(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, 0, r,
1123                               "%s: %s", filename, errmsg);
1124                 return HTTP_INTERNAL_SERVER_ERROR;
1125             }
1126             *result = dc;
1127             break;
1128         }
1129         else if (status != APR_ENOENT && status != APR_ENOTDIR) {
1130             ap_log_rerror(APLOG_MARK, APLOG_CRIT, errno, r,
1131                           "%s pcfg_openfile: unable to check htaccess file, "
1132                           "ensure it is readable",
1133                           filename);
1134             ap_table_setn(r->notes, "error-notes",
1135                           "Server unable to read htaccess file, denying "
1136                           "access to be safe");
1137             return HTTP_FORBIDDEN;
1138         }
1139     }
1140
1141 /* cache it */
1142     new = ap_palloc(r->pool, sizeof(struct htaccess_result));
1143     new->dir = parms.path;
1144     new->override = override;
1145     new->htaccess = dc;
1146 /* add to head of list */
1147     new->next = r->htaccess;
1148     r->htaccess = new;
1149
1150     return OK;
1151 }
1152
1153
1154 CORE_EXPORT(const char *) ap_init_virtual_host(ap_context_t *p, const char *hostname,
1155                               server_rec *main_server, server_rec **ps)
1156 {
1157     server_rec *s = (server_rec *) ap_pcalloc(p, sizeof(server_rec));
1158
1159 #ifdef RLIMIT_NOFILE
1160     struct rlimit limits;
1161
1162     getrlimit(RLIMIT_NOFILE, &limits);
1163     if (limits.rlim_cur < limits.rlim_max) {
1164         limits.rlim_cur += 2;
1165         if (setrlimit(RLIMIT_NOFILE, &limits) < 0) {
1166             perror("setrlimit(RLIMIT_NOFILE)");
1167             ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1168                          "Cannot exceed hard limit for open files");
1169         }
1170     }
1171 #endif
1172
1173     /* TODO: this crap belongs in http_core */
1174     s->process = main_server->process;
1175     s->server_admin = NULL;
1176     s->server_hostname = NULL;
1177     s->error_fname = NULL;
1178     s->srm_confname = NULL;
1179     s->access_confname = NULL;
1180     s->timeout = 0;
1181     s->keep_alive_timeout = 0;
1182     s->keep_alive = -1;
1183     s->keep_alive_max = -1;
1184     s->error_log = main_server->error_log;
1185     s->loglevel = main_server->loglevel;
1186     /* useful default, otherwise we get a port of 0 on redirects */
1187     s->port = main_server->port;
1188     s->next = NULL;
1189
1190     s->is_virtual = 1;
1191     s->names = ap_make_array(p, 4, sizeof(char **));
1192     s->wild_names = ap_make_array(p, 4, sizeof(char **));
1193
1194     s->module_config = create_empty_config(p);
1195     s->lookup_defaults = ap_create_per_dir_config(p);
1196
1197 #if 0
1198     s->server_uid = ap_user_id;
1199     s->server_gid = ap_group_id;
1200 #endif
1201
1202     s->limit_req_line = main_server->limit_req_line;
1203     s->limit_req_fieldsize = main_server->limit_req_fieldsize;
1204     s->limit_req_fields = main_server->limit_req_fields;
1205
1206     *ps = s;
1207
1208     return ap_parse_vhost_addrs(p, hostname, s);
1209 }
1210
1211
1212 static void fixup_virtual_hosts(ap_context_t *p, server_rec *main_server)
1213 {
1214     server_rec *virt;
1215
1216     for (virt = main_server->next; virt; virt = virt->next) {
1217         merge_server_configs(p, main_server->module_config,
1218                              virt->module_config);
1219
1220         virt->lookup_defaults =
1221             ap_merge_per_dir_configs(p, main_server->lookup_defaults,
1222                                   virt->lookup_defaults);
1223
1224         if (virt->server_admin == NULL)
1225             virt->server_admin = main_server->server_admin;
1226
1227         if (virt->srm_confname == NULL)
1228             virt->srm_confname = main_server->srm_confname;
1229
1230         if (virt->access_confname == NULL)
1231             virt->access_confname = main_server->access_confname;
1232
1233         if (virt->timeout == 0)
1234             virt->timeout = main_server->timeout;
1235
1236         if (virt->keep_alive_timeout == 0)
1237             virt->keep_alive_timeout = main_server->keep_alive_timeout;
1238
1239         if (virt->keep_alive == -1)
1240             virt->keep_alive = main_server->keep_alive;
1241
1242         if (virt->keep_alive_max == -1)
1243             virt->keep_alive_max = main_server->keep_alive_max;
1244
1245         /* XXX: this is really something that should be dealt with by a
1246          * post-config api phase */
1247         ap_core_reorder_directories(p, virt);
1248     }
1249     ap_core_reorder_directories(p, main_server);
1250 }
1251
1252 /*****************************************************************
1253  *
1254  * Getting *everything* configured... 
1255  */
1256
1257 static void init_config_globals(ap_context_t *p)
1258 {
1259     /* Global virtual host hash bucket pointers.  Init to null. */
1260     ap_init_vhost_config(p);
1261 }
1262
1263 static server_rec *init_server_config(process_rec *process, ap_context_t *p)
1264 {
1265     server_rec *s = (server_rec *) ap_pcalloc(p, sizeof(server_rec));
1266
1267     ap_open_stderr(&s->error_log, p);
1268     s->process = process;
1269     s->port = 0;
1270     s->server_admin = DEFAULT_ADMIN;
1271     s->server_hostname = NULL;
1272     s->error_fname = DEFAULT_ERRORLOG;
1273     s->loglevel = DEFAULT_LOGLEVEL;
1274     s->srm_confname = RESOURCE_CONFIG_FILE;
1275     s->access_confname = ACCESS_CONFIG_FILE;
1276     s->limit_req_line = DEFAULT_LIMIT_REQUEST_LINE;
1277     s->limit_req_fieldsize = DEFAULT_LIMIT_REQUEST_FIELDSIZE;
1278     s->limit_req_fields = DEFAULT_LIMIT_REQUEST_FIELDS;
1279     s->timeout = DEFAULT_TIMEOUT;     
1280     s->keep_alive_timeout = DEFAULT_KEEPALIVE_TIMEOUT;
1281     s->keep_alive_max = DEFAULT_KEEPALIVE;
1282     s->keep_alive = 1;
1283     s->next = NULL;
1284     s->addrs = ap_pcalloc(p, sizeof(server_addr_rec));
1285     /* NOT virtual host; don't match any real network interface */
1286     s->addrs->host_addr.s_addr = htonl(INADDR_ANY);
1287     s->addrs->host_port = 0;    /* matches any port */
1288     s->addrs->virthost = "";    /* must be non-NULL */
1289     s->names = s->wild_names = NULL;
1290
1291     s->module_config = create_server_config(p, s);
1292     s->lookup_defaults = create_default_per_dir_config(p);
1293
1294     return s;
1295 }
1296
1297
1298 server_rec *ap_read_config(process_rec *process, ap_context_t *ptemp, const char *confname)
1299 {
1300     ap_context_t *p = process->pconf;
1301     server_rec *s = init_server_config(process, p);
1302
1303     init_config_globals(p);
1304
1305     /* All server-wide config files now have the SAME syntax... */
1306
1307     process_command_config(s, ap_server_pre_read_config, p, ptemp);
1308
1309     ap_process_resource_config(s, confname, p, ptemp);
1310     ap_process_resource_config(s, s->srm_confname, p, ptemp);
1311     ap_process_resource_config(s, s->access_confname, p, ptemp);
1312
1313     process_command_config(s, ap_server_post_read_config, p, ptemp);
1314
1315     fixup_virtual_hosts(p, s);
1316     ap_fini_vhost_config(p, s);
1317     ap_sort_hooks();
1318
1319     return s;
1320 }
1321
1322 void ap_single_module_configure(ap_context_t *p, server_rec *s, module *m)
1323 {
1324     if (m->create_server_config)
1325         ap_set_module_config(s->module_config, m,
1326                              (*m->create_server_config)(p, s));
1327     if (m->create_dir_config)
1328         ap_set_module_config(s->lookup_defaults, m,
1329                              (*m->create_dir_config)(p, NULL));
1330 }
1331
1332 void ap_post_config_hook(ap_context_t *pconf, ap_context_t *plog, ap_context_t *ptemp, server_rec *s)
1333 {
1334     ap_run_post_config(pconf,plog,ptemp,s); 
1335     init_handlers(pconf);
1336 }
1337
1338 void ap_child_init_hook(ap_context_t *pchild, server_rec *s)
1339 {
1340     /* TODO: uh this seems ugly, is there a better way? */
1341     /*ap_child_init_alloc();    PUT THIS BACK IN XXXXX */
1342
1343     ap_run_child_init(pchild,s);
1344 }
1345
1346 /********************************************************************
1347  * Configuration directives are restricted in terms of where they may
1348  * appear in the main configuration files and/or .htaccess files according
1349  * to the bitmask req_override in the command_rec structure.
1350  * If any of the overrides set in req_override are also allowed in the
1351  * context in which the command is read, then the command is allowed.
1352  * The context is determined as follows:
1353  *
1354  *    inside *.conf --> override = (RSRC_CONF|OR_ALL)&~(OR_AUTHCFG|OR_LIMIT);
1355  *    within <Directory> or <Location> --> override = OR_ALL|ACCESS_CONF;
1356  *    within .htaccess --> override = AllowOverride for current directory;
1357  *
1358  * the result is, well, a rather confusing set of possibilities for when
1359  * a particular directive is allowed to be used.  This procedure prints
1360  * in English where the given (pc) directive can be used.
1361  */
1362 static void show_overrides(const command_rec *pc, module *pm)
1363 {
1364     int n = 0;
1365
1366     printf("\tAllowed in *.conf ");
1367     if ((pc->req_override & (OR_OPTIONS | OR_FILEINFO | OR_INDEXES)) ||
1368         ((pc->req_override & RSRC_CONF) &&
1369          ((pc->req_override & (ACCESS_CONF | OR_AUTHCFG | OR_LIMIT)))))
1370         printf("anywhere");
1371     else if (pc->req_override & RSRC_CONF)
1372         printf("only outside <Directory>, <Files> or <Location>");
1373     else
1374         printf("only inside <Directory>, <Files> or <Location>");
1375
1376     /* Warn if the directive is allowed inside <Directory> or .htaccess
1377      * but module doesn't support per-dir configuration */
1378
1379     if ((pc->req_override & (OR_ALL | ACCESS_CONF)) && !pm->create_dir_config)
1380         printf(" [no per-dir config]");
1381
1382     if (pc->req_override & OR_ALL) {
1383         printf(" and in .htaccess\n\twhen AllowOverride");
1384
1385         if ((pc->req_override & OR_ALL) == OR_ALL)
1386             printf(" isn't None");
1387         else {
1388             printf(" includes ");
1389
1390             if (pc->req_override & OR_AUTHCFG) {
1391                 if (n++)
1392                     printf(" or ");
1393                 printf("AuthConfig");
1394             }
1395             if (pc->req_override & OR_LIMIT) {
1396                 if (n++)
1397                     printf(" or ");
1398                 printf("Limit");
1399             }
1400             if (pc->req_override & OR_OPTIONS) {
1401                 if (n++)
1402                     printf(" or ");
1403                 printf("Options");
1404             }
1405             if (pc->req_override & OR_FILEINFO) {
1406                 if (n++)
1407                     printf(" or ");
1408                 printf("FileInfo");
1409             }
1410             if (pc->req_override & OR_INDEXES) {
1411                 if (n++)
1412                     printf(" or ");
1413                 printf("Indexes");
1414             }
1415         }
1416     }
1417     printf("\n");
1418 }
1419
1420 /* Show the preloaded configuration directives, the help string explaining
1421  * the directive arguments, in what module they are handled, and in
1422  * what parts of the configuration they are allowed.  Used for httpd -h.
1423  */
1424 void ap_show_directives()
1425 {
1426     const command_rec *pc;
1427     int n;
1428
1429     for (n = 0; ap_loaded_modules[n]; ++n)
1430         for (pc = ap_loaded_modules[n]->cmds; pc && pc->name; ++pc) {
1431             printf("%s (%s)\n", pc->name, ap_loaded_modules[n]->name);
1432             if (pc->errmsg)
1433                 printf("\t%s\n", pc->errmsg);
1434             show_overrides(pc, ap_loaded_modules[n]);
1435         }
1436 }
1437
1438 /* Show the preloaded module names.  Used for httpd -l. */
1439 void ap_show_modules()
1440 {
1441     int n;
1442
1443     printf("Compiled in modules:\n");
1444     for (n = 0; ap_loaded_modules[n]; ++n)
1445         printf("  %s\n", ap_loaded_modules[n]->name);
1446 }
1447