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